Migrate to neuron kernel and redesign the project workspace - #88
Merged
Conversation
…nds. Typed commands on the neuron's own grain interface plus synapse-routed signals; durable pending queue with Busy/Duplicate admission; synchronous local commands with an append-only command journal and bounded dedup; recovery fence with reconciliation; descriptor-driven describe/call for agents. Input for the neurons-only migration plan. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…ate; delete applications and scripting The old kernel (owner/principal partitioning, entities, webhooks, the scripting and application-authoring subsystem, the SDK and the standalone MCP host) is gone. In its place is the neuron substrate proven in digitalbraincore at 6479251: INeuron, Neuron, Neuron<TState>, PlainNeuron, NeuronRuntime, IModule, ModuleManifest, BrainOperations, BrainTools and BrainSimulation, copied verbatim together with tests/DigitalBrain.Tests and its eight feature files. The silo is reduced to Orleans plus /mcp, /health and /orleans. Modules and the product contracts do not compile against the new substrate and are commented out of the solution, the silo and the AppHost with a Phase B marker until their own tasks land. Aspire keeps this repo's Azure clustering wiring and loses the owner client wiring the neuron layer has no place for. Adapted from the donor: Orleans 10.3.1 types Serializer<T>.Deserialize as nullable where 10.2.2 did not, so JournalWindow decodes through one helper that asserts what Append guarantees. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Review round 1 on task A1. The silo lost its Basic auth gate along with the application surface, which left a deployed kernel serving /mcp and the Orleans dashboard to anyone. BasicAuthGate is back from b225d08 with only its namespace changed, and Program.cs runs it after CORS and before the dashboard and MCP maps, so DigitalBrain:Auth:Username and :Password gate everything again while /health and /alive stay open for probes. Fire awaiting Deliver while a reaction awaited Deliver back was a mutual deadlock between two non-reentrant neurons, broken only by the five-minute response timeout; react.feature "Reactions run in journal order" failed about half its runs on it. Per the amended spec, Deliver now carries [AlwaysInterleave] and NeuronConcurrency admits it as a kernel exception beside the Read* methods. Deliver stages the journal append and the latest-per-type update synchronously and awaits only its own state write, so interleaving it cannot reorder a journal or run a reaction early. Five consecutive suite runs are green at 46/46. Each Phase B marker now names b225d08 as the place to restore from, and the solution keeps one commented block per /Modules/<X>/ folder so a phase task can uncomment only its own. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…on and retry Deliver now reports DeliveryAdmission (Accepted / Duplicate / Busy) into a bounded durable pending queue: PendingWork owns the queue, the cancelled set and the reacted ring, and the incoming journal goes back to being history rather than the schedule. The drain peeks, reacts on a per-entry token linked to the activation, then completes and persists; a failed head arms the one retry timer the base class owns (1s to 60s, non-interleaving, keep-alive) so retries need no new traffic, and CancelReaction reaches a neuron mid-reaction. Fire reports Busy per target, and the MCP surface gains a cancel tool. ReadPendingCount is a tenth kernel read, added so a Busy emitter can see the backlog behind it; see task-A2-report.md for that and for the cold-restart reactivation gap the harness currently stands in for. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…eness Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…eminder While the head of Pending has failed the neuron now also holds one Orleans reminder named "retry"; Neuron implements IRemindable and ReceiveReminder only re-arms the drain. Deactivation suspends the timer but keeps the reminder, because the reminder is the only thing that brings a cold neuron back with no traffic. The test silo gains a file-backed IReminderTable so reminders survive RestartSiloAsync, and the restart step no longer touches the neuron. The period is NeuronOptions.RetryReminderPeriod, one minute by default - Orleans' floor - because a tick missed while the cluster is down is skipped rather than fired late; the test silo shrinks it so a cold restart is provable inside a scenario's patience. Also clears nine A2 review findings: deactivation is no longer logged as a reaction failure, cancellation has its own telemetry and resets the backoff, the post-admission staging is shared by Deliver and Schedule, PendingWork verifies the head before completing it, waiting moved out of a Then, and the slow fixture blocks on its token alone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
The reminder was registered on the first failure, so work accepted and then lost to a cold restart before its first reaction attempt was never resumed without traffic. It is now held from admission until Pending drains: Deliver registers after its persist, the drain registers on every non-empty peek, activation re-registers, and the four places where a head leaves the queue unregister only when nothing is left - the success path used to disarm even with work still queued. RetryTimer becomes RetryScheduler and splits into EnsureReminderAsync, ArmTimer and SettleAsync, so the reminder's lifetime (any pending work) and the timer's (one failed head) stop being conflated. A new admit scenario proves it: a slow neuron whose reaction never completes and never fails before the restart, observed afterwards through the Pong on the firing neuron's journal, so nothing in the test touches the neuron the reminder has to revive. Also: a host with no reminder service now fails at silo start naming the fix, ReceiveReminder ignores foreign reminder names, the cancelled paths complete and persist before they settle, and BrainSimulation configures one branch per storage mode. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…ded dedup Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…se mismatch Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…t, caller lineage Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…rage wiring Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…nal reads with gaps Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…commit journal floors Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…neage from the envelope Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Only the five kernel operations the spec names interleave; ReadState and ReadSynapses are serialized turns again and the concurrency validator holds a literal allow-list. A completed write advances the committed cursors only to the boundary it captured, so an interleaving Deliver's staging is no longer promoted by someone else's write. Reminder registration and removal are serialized, so an accepted delivery can no longer lose its durable wake-up to a concurrent removal. A failed reaction discards its staged effects before the retry is armed, and an incoming call filter enforces the recovery fence for every method on a neuron: a failed write refuses callers, a failed reaction's rollback only delays them. A repeated rejection replays the stored one instead of appending a second Rejected record, MCP reads surface a retention gap instead of polling a stale cursor, and Schedule stamps the sequence it is really appended at. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Command execution counters live in the simulation's silo services instead of a process-wide static, so parallel scenarios driving a counter named "c" no longer accumulate each other's counts (the reported 70/71 flake). The Sleepy and Throwing fixtures become one FailingNeuron behind one switch. recovery's first scenario no longer asserts a disjunction: one scenario proves an interleaving read is refused while the neuron recovers, driven by holding the revert's storage reload open, and one proves the failed write left no synapse. Four scenarios were added, one each for invariants 14, 13's Attempted arm, 12 and 9; invariant 14 needed the wrapper to check pending capacity at admission, as spec section 4 step 1 says, so a command that would schedule into a full queue records nothing but Rejected. Waits that already prove a pending count no longer restate it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
An MCP journal read no longer costs a second grain call: JournalRead carries the running total. The caller scope that pushes db.caller onto RequestContext is one struct both the edge and the outgoing filter use. Duplicate Neuron/Query accessors, three copies of Flatten and the unused correlated-fire step are gone, the peeked pending head is a token the drain hands back, and the file holding FileGrainStorage is finally named after it. DescriptorTable builds one grain type per method instead of one four-deep loop, the command wrapper's stored-outcome replay is its own decision, and an MCP read parses the requested view once. The gap scenario moved to the journal feature, where the header already promises it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Every derived index now rides the NoteReloaded seam, which fires exactly where live state and storage agree again: activation and a completed revert. Deliver's duplicate check reads a set of queued ids instead of walking up to 256 durable entries behind a fresh closure, an append adds to a running byte total instead of re-summing the window, dedup keeps its resolved and unresolved counts instead of sorting the dictionary on every resolution and scanning it on every command, reconciliation deserializes the command window once rather than once per unresolved outcome, and the neuron resolves its logger at activation. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
… worktrees Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…ive interleaving uses in constraints Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…ent refusals A reaction now buffers what it Schedules exactly as a command does, and the turn admits it only on success, immediately before its final persist. Until now a reaction staged its scheduled work at once, an interleaving Deliver's write flushed it to storage before the reaction threw, and the retry scheduled it a second time; a new react scenario fails with two Pongs against the old code. Transient capacity refusals — Pending full, Dedup full of unresolved — now throw NeuronBusyException before admission and write nothing, so Rejected is left to the permanent reasons and a retry against a saturated neuron no longer grows the command journal. Commit boundaries carry a reload generation, so a write captured before a revert cannot push the committed cursor past the reloaded state; two facts over JournalWindow pin that down. Also: the reminder gate follows the activation and is disposed with it, the guard filter skips the two requests that handle the fence themselves, the flush-time Busy names the race it is, and Neuron.cs is clean UTF-8 again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Delete src/Product/DigitalBrain.Product.Contracts: CommandId is superseded by the kernel's DigitalBrain.Abstractions.Identity.CommandId; UserMessaged, AgentTurnContext, ITrustedUserCommandHandler, IUserActionContinuation, IUserActionSource, SetupContinuation, SpecialistContinuation, UserActionRequest and NeuronPresentation are applications-era product contracts and are deleted outright. IUntrustedContentScreen is the one survivor: moved unchanged to src/Modules/AI/Contracts/Interactions (AI is the natural owner and already the implementer; every module that resolves it already references AI or AI.Contracts, so no reference cycle). Removed the Product.Contracts ProjectReference from every module csproj that carried it (AI, AI.Contracts, Excel, Google, Memory.Contracts, Salesforce, Time, Time.Contracts, UI, UI.Contracts) and cleaned the corresponding `using DigitalBrain.Product...` lines across their C# sources, either repointing to DigitalBrain.AI.Interactions / DigitalBrain.Abstractions.Identity or dropping the now-dangling using. Execution's two csproj/cs files are left untouched: Execution is deleted whole in task B6. Removed the commented Phase B Product block from DigitalBrain.slnx. Modules under src/Modules/** remain commented out of the slnx and are not expected to compile yet; later tasks port them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…expired tokens An OAuth token in a command argument is a token in the command journal, and a scheduled DTO carrying one is a token in the incoming journal. TokenHandoff is an in-memory, one-use, two-minute nonce store beside BrowserLogins: the callback deposits the bundle, Connect carries Subject/Email/GrantedScopes/lifetime and the nonce, and the reaction redeems it. Scopes and lifetime stay on the command on purpose, so a bad grant is refused synchronously instead of poisoning a reaction the kernel would retry forever; a missing nonce fires GmailConnectionRejected rather than throwing. Refresh(RefreshGmailConnection) exchanges the refresh token in its reaction behind IGmailTokenExchange, and GmailNativeTools retries a read exactly once after a refresh lands. Published facts now carry identifiers only: GmailDraftPrepared and GmailDraftCreated no longer copy the draft into the outgoing journal. Scheduled work has its own vocabulary (GmailConnectionRequested, GmailRefreshRequested, GmailDisconnectionRequested) so a to-do item and a published fact never share a signal type. Token expiry is driven by the injected TimeProvider everywhere, so the new refresh scenario advances a FakeTimeProvider instead of sleeping. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
… test consolidation Salesforce follows Google: ConnectSalesforceAccount carries the instance URL, the lifetime and a one-use TokenHandoff nonce, never a token, and the connect reaction redeems it. Refresh(RefreshSalesforceConnection) exchanges the refresh token in its reaction behind ISalesforceTokenExchange, and SalesforceNativeTools retries a read once after the refresh lands. SalesforceWriteConfirmed carries the preview id and schema hash only. Provider results from Salesforce and Aspire are marked untrustedData like Gmail's, each with the marker comment naming where the AI module screens them. The MCP transport-and-catalog block both providers duplicated moves to McpHttpSession in the kernel Http area; each provider keeps its own tool list, catalog validation, budget and projection. Microsoft: GitHubSetupService again turns a refused or unavailable required-check read into a readiness state instead of throwing at its caller; the two command-body gates say in one line that they are fast-fails the reaction re-validates; the 220-to-770-character lines in the bindings reader and the setup service are wrapped, the reader now having a body a person can check against the configuration keys. Tests consolidate to the one integrations.feature with seven scenarios - connect, confirmation and refresh per module plus the GitHub webhook. The second feature file and both per-module facts classes are deleted; token expiry runs on a FakeTimeProvider so nothing waits on a wall clock, and one shared helper owns the reaction wait. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
CRITICAL: the chat saved a terminal turn and then fired Responded or TurnFailed. A reaction that failed between the two lost the signal, because the Running guards made the kernel's retry a no-op. ChatTurnRecord now carries SettlementFired: a terminal turn whose announcement never went out re-enters the fire path on the retry, and only a fire that was accepted saves the marker. IChatSettlementCrashPoint (optional, absent in production, the ICommandCrashPoint pattern) lets uichat.feature lose an announcement and prove exactly one Responded arrives after the retry. Spec section 10 context, finished: a ContextRef naming an earlier turn imports that turn's slots under the existing last-write-wins precedence before the current turn's own message slot is appended, and ITurnContextBlobStore spills aged-out payloads instead of dropping them (Azure Blob when the grain-state client is registered, in memory otherwise). A slot resolves through the store when the responder's preamble is built, so an inherited spilled payload still reaches the model. ChatTurnSnapshot.Context exposes the slot digests. SurfaceNeuron computed its additions and fingerprint in the command, against a snapshot two queued opens both saw; the reaction now recomputes both and the command receipt is advisory. ComponentAdded event ids fold the fingerprint rather than the command id, so identical queued scenes cannot double-add. ActivityState.Apply returns a new instance and the reaction saves a new dictionary instead of mutating the live snapshot. Minors: ContextSlot.Ordinal removed (list position is the ordinal), UIVocabulary.DefaultSurfaceName deleted, generate_image reports failures to the model like its siblings, ChatState.TurnByCommand (1024) backstops the kernel dedup bound, and the surface steps name their command ids and say "refused" instead of "the fire was rejected". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
The chat restart flake had two causes, both of them "the state says done, so skip". A transient failure is no longer answered as advice. Fire collects a delivery that could not be made into an AggregateException, and a silo going down makes every delivery fail; both neurons caught that, answered the asker and let the drain complete the head, so the retry that would have worked never happened. Orleans messaging and availability failures and the kernel's busy, recovering and persistence exceptions now escape the reaction, which is exactly what the at-least-once drain is for. ChatNeuron is idempotent against its own snapshot. A snapshot save is not atomic with the pending queue, so a redelivered Said can meet a run it already advanced: the chat now decides from the transcript rather than the snapshot and re-fires the Turn the pending participant still owes, instead of returning in silence. CloseAsync fires the Reply before forgetting the run and skips the fire when the outgoing journal already holds one, so a lost activation can neither swallow the answer nor duplicate it. AgentNeuron skips a turn it already answered by causation, not correlation: a second Ask on the same correlation is a new question. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…model Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…he neuron model Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…n the neuron model Merge resolution: UIModule registers its kit tools through the AI module's contributor seam; the scripted client registration folds into ScriptedAi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
A journal keeps 512 entries and then reads back gapped and empty, which both AI neurons took for "not yet": past that a chat would answer twice and an agent would re-run its model on every retry. The question is a durability question, so the snapshot answers it. ChatRun carries ReplyFired, shaped like the UI chat's SettlementFired: the Reply fires, the marker is saved, and only then is the run forgotten, so a retry can tell "already answered" from "answered but never forgotten". A run whose reply is out is no longer re-invited. AgentState carries the last 64 delivery ids it has answered — causation, not correlation, because a second Ask on the same correlation is a new question — so the hot path reads no journal. The session write moved to after the answer and now carries the marker with it: recording "answered" before the fire would make a lost fire look done on the retry, which is the silence round 2 removed. DescriptorTable resolves a command DTO's Id property when it builds the descriptor rather than on every typed-function build, so a DTO that derives from Command without a serializable Id fails at silo start naming the interface and the method, next to every other descriptor rule. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…s escape reactions Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…; container module list Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…e in Contracts Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…e step Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
…n unsaved announce Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
Fix-list section C. C1: NativeTools, AddNativeTool and INativeToolContributor now live in AI.Contracts; the UI module dropped its reference to the AI implementation. C2: Gmail, Salesforce, GitHub, Aspire and a new Excel show_spreadsheet register through AddNativeTool, so Instruct.tools reaches them by name; the five "lands after the AI module merge" placeholders are gone. C3: NativeTools.Resolve wraps every contributor in ScreenedFunction, which passes the result through IUntrustedContentScreen before the model sees it. Brain operations and typed neuron functions stay unscreened. C4: Signal.FromJson<T> and delivery.Body<T> live in Contracts; the six module copies are deleted; a reaction body that will not parse logs a warning and returns instead of throwing on `!`; self-scheduled signal names carry their module prefix (TimerScheduling, SheetApplying, MemoryRemembering, SurfaceOpening, SurfaceActivating). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DR6TLP1Y48E1neXaZvmdRz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This branch migrates DigitalBrain to the neuron-based kernel and delivers the redesigned project workspace. Projects open directly into chat and a workspace with movable, resizable, snapping windows and a minimized-item dock.
Validation performed during implementation:
This PR includes the full refactor/neurons-only branch, not only the latest table component change. Untracked local design mockups are excluded.