-
Notifications
You must be signed in to change notification settings - Fork 2
Design Workspace: local-first projects and dedicated Design mode #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sambitcreate
wants to merge
68
commits into
main
Choose a base branch
from
feature/design-workspace
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
48bcb0c
feat(design): add secure spatial context pipeline
sambitcreate 940cd38
feat(design): ship the full spatial canvas workspace
sambitcreate 483d2e8
docs(design): unify the workspace roadmap
sambitcreate 19b87f0
feat(design): add source-backed designer runtime
sambitcreate c54bf6d
feat(design): complete point-to-review workflow
sambitcreate c660c24
docs(design): archive the completed MVP roadmap
sambitcreate 6990065
test(design): cover source context and overlay invariants
sambitcreate da1104b
perf(design): index canvas selection context
sambitcreate b465668
feat(design): add durable project storage and exports
sambitcreate 1c0abdf
feat(design): add recoverable workspace handoff
sambitcreate 8259645
feat(design): add local design system context
sambitcreate ad56d35
feat(design): add comments and bounded direct edits
sambitcreate 9010e54
feat(design): add durable multifile source actions
sambitcreate 7ac323f
feat(design): contain Vite and Next preview transport
sambitcreate ff1c776
feat(design): add crash-safe project lifecycle
sambitcreate e29c534
feat(design): bind project services to the main process
sambitcreate 9a53cb3
feat(design): add project library and inspector UI
sambitcreate f7646eb
feat(design): wire durable workspace IPC and context
sambitcreate d83f28f
feat(design): integrate the durable project workspace
sambitcreate d4704d3
feat(design): update onboarding for durable projects
sambitcreate 7bbd334
test(design): verify offline project exports
sambitcreate 50e16e8
docs(design): archive the completed alignment plan
sambitcreate 9f338f1
Merge origin/main into feature/design-workspace
sambitcreate 54737a6
fix(workspaces): defer cyclic llm dependency
sambitcreate 1c24fd1
fix(updater): preserve checked handler boundary
sambitcreate d0b2731
test(subagents): follow routed chat deletion
sambitcreate 56ba7f7
test(design): await preview source updates
sambitcreate 7c64b62
feat(design): explain canvas tools on hover
sambitcreate 06c4dfc
fix(design): separate prototype storage from workspace authority
sambitcreate 8c21a7a
fix(design): bind app previews and edits to projects
sambitcreate 7f4dfb4
feat(design): add reconnect flow and atomic prompt preflight
sambitcreate 4d3f2bf
docs: record alternate-port dev launch papercut
sambitcreate 52f948e
Merge origin/main into feature/design-workspace
sambitcreate 5d7e56f
test(design): align generation authority contracts
sambitcreate b6fbecd
feat(design): split Agent and Design workspaces
sambitcreate 77e1b28
feat(design): dock composer in project conversation
sambitcreate cc89706
docs(design): record workspace mode decisions
sambitcreate 4b3796d
fix(design): simplify scoped composer controls
sambitcreate 7732a4c
fix(design): close compact sidebar on mode switch
sambitcreate dc25aee
test(design): stabilize source preview revisions
sambitcreate 6a0e806
test(design): retry revision preview readiness
sambitcreate c06b1cc
fix(design): make startup recovery dependency-safe
sambitcreate 9d8a057
fix(design): preserve route and composer state
sambitcreate 156cda2
fix(design): preserve migrated project authority
sambitcreate 2d0bd3d
fix(design): close migration and route authority races
sambitcreate 06dc03e
fix(design): persist model revision lineage
sambitcreate b412d73
test(design): make preview revision checks exact
sambitcreate dfdf882
fix(design): contain source preview navigation
sambitcreate 39e631e
fix(design): keep rejected mode switches in place
sambitcreate 747e9fc
test(design): cover accepted mode switching
sambitcreate 3af236f
fix(design): keep action controls in conversation rail
sambitcreate 9d23587
test(bots): settle skill watchers before edits
sambitcreate 23277ec
fix(design): hide migrated projects from Agent lists
sambitcreate 529b789
docs: clarify machine-local papercuts policy
sambitcreate 47b7549
fix(design): resolve conversation rail review gaps
sambitcreate 104886d
fix(design): unlock stale todo conversations
sambitcreate f6b84fd
test(subagents): make grace timing deterministic
sambitcreate 68f9161
fix(sidebar): simplify mode picker contrast
sambitcreate a314fdc
fix(sidebar): align mode menu corners
sambitcreate 7cb5ab4
test(design): allow source preview integration startup
sambitcreate 8d518ce
fix(sidebar): soften mode menu shell
sambitcreate 136ac57
fix(sidebar): enforce matching mode menu radius
sambitcreate 162b62b
fix(design): make artifact publication durable
sambitcreate 80827f4
fix(design): reconcile canvas recovery state
sambitcreate 5c003d0
fix(design): make cancelled drafts recoverable
sambitcreate ec62962
test(design): pin durable route recovery
sambitcreate 8735cfc
fix(design): surface terminal publication conflicts
sambitcreate 4bda677
fix(design): clarify recovery guidance
sambitcreate File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
This file was deleted.
Oops, something went wrong.
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Design comments and bounded direct edits | ||
|
|
||
| Status: Implemented. Comments, direct-edit IPC, pointer/keyboard controls, durable connected review, | ||
| prototype revision creation, and exact immutable undo are wired. | ||
|
|
||
| ## Authority boundary | ||
|
|
||
| Comments and direct-manipulation gestures are context. They never grant repository, command, | ||
| network, Git, preview-session, or artifact-write authority. | ||
|
|
||
| A comment target is durable only when all of these identities are present: | ||
|
|
||
| - Design Project ID; | ||
| - artboard lineage ID; | ||
| - immutable revision media ID; | ||
| - an exact, single-match selector identity; and | ||
| - either the generated artifact content hash or a relative, source-version/range/preimage-hash | ||
| connected-source identity. | ||
|
|
||
| An ephemeral React Grab selection or preview capability is insufficient and is never persisted. | ||
| When the current immutable revision or full source binding changes, the store marks the older | ||
| comment stale. Stale comments remain visible and can be resolved or reopened, but are never | ||
| silently retargeted. | ||
|
|
||
| The comment store is main-owned, atomic, schema- and byte-bounded, and written with mode `0600`. | ||
| All writes use both database revision CAS and, for existing comments, comment revision CAS. | ||
| Corrupt or unsupported on-disk data makes the store unavailable rather than allowing a later | ||
| write to replace it. | ||
|
|
||
| ## Literal edit matrix | ||
|
|
||
| The direct-edit core accepts only: | ||
|
|
||
| - margin, padding, and gap spacing literals; | ||
| - width and height literals; | ||
| - enumerated alignment values; | ||
| - semantic CSS custom-property token names for color roles; | ||
| - border-radius literals; and | ||
| - bounded static plain text. | ||
|
|
||
| CSS expressions, URLs, raw colors, arbitrary properties, negative values, markup-like text, | ||
| localized or dynamic text, rich text, computed classes, ambiguous selector/component matches, | ||
| and repeated literal-definition matches fail closed. Proof facts must report exactly one selector, | ||
| component, and literal definition match. | ||
|
|
||
| Within one accepted gesture envelope, the proposal and undo identities are deterministic. That | ||
| gives the integration coordinator one idempotency key and one future undo record. A renderer IPC | ||
| retry is a new attended gesture with a newly minted gesture ID; it is not deduplicated against a | ||
| previous ambiguous request. | ||
|
|
||
| ## Origin-specific output | ||
|
|
||
| Prototype edits produce a `prototype-revision-request` pinned to the base media ID and artifact | ||
| hash. The request instructs an artifact adapter to create a new immutable revision; the core never | ||
| overwrites artifact bytes. | ||
|
|
||
| The main adapter re-reads the committed source, verifies its SHA-256 identity, proves one exact | ||
| `data-aiden-id` target and one literal inline definition, and derives a deterministic new media ID | ||
| from the proposal. It stages the new bytes, CAS-appends the lineage in the Design Project, appends | ||
| the chat artifact idempotently, and only then commits the staged bytes. A pre-CAS failure discards | ||
| only the exact pending row. A post-CAS interruption deliberately leaves the pending row for the | ||
| existing startup recovery path, so retries and restarts converge on one immutable revision. | ||
|
|
||
| Connected-app edits produce a `designer-action-request` carrying the relative path, full source | ||
| version, exact range, preimage, and independently verified preimage hash. The core never writes | ||
| source. An integration adapter must turn that semantic literal edit into one exact replacement, | ||
| then submit it through the existing Designer Action review/apply/undo transaction. Full permission | ||
| must not bypass that review. | ||
|
|
||
| The connected adapter resolves the live source-selection capability again, compares every path, | ||
| version, range, preimage, hash, and selector fact with the proposal, and parses the canonical TSX. | ||
| Only a single literal inline JSX style property or a single plain JSX text node is rewritten. The | ||
| caller must also provide a trusted source-graph proof that the enclosing component has one use; | ||
| missing or ambiguous graph evidence fails closed. The result is submitted to | ||
| `SourceDesignerActionService.propose`, so apply and undo retain the same review transaction as | ||
| every other Designer Action. | ||
|
|
||
| ## Intentional limitations | ||
|
|
||
| The | ||
| prototype adapter intentionally supports only literal inline HTML style declarations and plain | ||
| text nodes. The connected adapter intentionally supports only literal inline JSX style objects and | ||
| plain JSX text nodes. Stylesheets, classes, spreads, expressions, component indirection, localized | ||
| text, rich children, ambiguous selectors, and repeated definitions fail closed instead of being | ||
| guessed. Color changes additionally require the main caller to resolve the token from the current | ||
| trusted design-system snapshot; renderer-reported token names are never sufficient authority. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # Design handoff architecture | ||
|
|
||
| Status: Implemented. Coordinator, production effects, startup recovery, IPC, chat/model context, | ||
| renderer confirmation, cancellation, recovery, and project linkage are connected. | ||
|
|
||
| ## Boundary | ||
|
|
||
| **Continue in workspace** graduates one immutable Prototype revision into an ordinary workspace task. It does not turn the Design Project into a source-writing authority. The handoff coordinator has no filesystem, Git, command, model, provider, staging, commit, push, pull-request, deployment, or application-source write API. | ||
|
|
||
| The only content crossing the boundary is a parsed `DesignHandoffPacketV1`: | ||
|
|
||
| - Design Project ID and compare-and-swap revision; | ||
| - immutable source bundle, lineage, and revision IDs plus its SHA-256 and byte size; | ||
| - content-addressed reference asset IDs; | ||
| - bounded, normalized design-decision summaries; and | ||
| - bounded desktop, tablet, and phone dimensions. | ||
|
|
||
| The exact-key parser rejects unknown fields. In particular, there is no field for a prompt, transcript, internal project JSON, provider/model credentials, absolute path, arbitrary source bytes, tool authority, or source-write instruction. Decision text is conservatively rejected when it resembles a credential, absolute path, or serialized internal JSON. The installed packet is explicitly untrusted design context; subsequent implementation uses normal workspace chat permissions, file-tool approval, and Review. | ||
|
|
||
| ## Target confirmation | ||
|
|
||
| The durable journal is path-free. Both target variants contain a renderer-safe four-label preview (`workspaceId`, workspace label, repository label, and branch label) and a SHA-256 digest of that exact preview. A production `verifyTarget` port must re-resolve authoritative main-process state immediately before any effect and return the same parsed target. | ||
|
|
||
| The default target is an Aiden-managed worktree. The confirmation records committed `HEAD`, whether the source checkout was dirty, and the exact disclosure acknowledgment when dirty: uncommitted source-checkout changes are not included. `prepareWorkspace` must use the existing managed-worktree application service, create from that committed `HEAD`, and return matching `createdFromHead` evidence. | ||
|
|
||
| An existing authorized workspace is accepted only with the exact strong-warning acknowledgment and target-preview digest. Main revalidates the workspace ID and the preview before use. This path reuses the existing workspace; it does not create or remove a worktree. | ||
|
|
||
| ## Journal and publication boundary | ||
|
|
||
| `DesignHandoffJournalStore` owns `design-handoffs.json` under Electron `userData`. It uses `DataStore` atomic replacement, mode `0600`, a 2 MiB read ceiling, strict versioned parsing, a maximum of 128 records, compare-and-swap revisions, external reload before writes, and fail-closed corrupt/unsafe-file handling. It retains active and recoverable records; the oldest terminal record may be evicted only when the bound is reached. | ||
|
|
||
| The coordinator advances these durable stages: | ||
|
|
||
| ```text | ||
| prepared | ||
| -> workspace-ready | ||
| -> chat-ready | ||
| -> context-ready | ||
| -> published | ||
| ``` | ||
|
|
||
| Every effect receives the stable operation ID and must be idempotent by that ID. A crash after an effect but before its journal checkpoint therefore repeats discovery of the same worktree, chat, context installation, or project link rather than creating another one. Illegal stage skips, identity replacement, cancellation clearing, and stale revisions are rejected. | ||
|
|
||
| Project-link publication is the visible commit boundary. A publication call with an unknown outcome is reconciled with `inspectPublication(operationId)` before retry or rollback. The published linkage records the project, workspace, chat, task, and branch display identity. Publication does not grant the Prototype future workspace authority. | ||
|
|
||
| ## Cancellation and recovery | ||
|
|
||
| Before publication, cancellation is journaled and rollback is attempted in reverse order: | ||
|
|
||
| 1. remove the installed handoff context; | ||
| 2. remove the new chat/task; and | ||
| 3. roll back the new managed workspace. | ||
|
|
||
| Rollback ports also discover effects solely by operation ID. This covers cancellation or a crash between an external effect and its journal checkpoint. Each rollback returns a proof result. If any result is unknown or false, the coordinator stops destructive rollback, preserves the remaining workspace, and records a renderer-safe `recoverable` reason. It never reports the repository unchanged without proof. | ||
|
|
||
| If publication is observed—or cancellation arrives after the published checkpoint—the coordinator preserves the linked workspace and records `recoverable`. Startup can call `resumeRecoverable()` to resume nonterminal records idempotently. Terminal `published` and `rolled-back` entries are not replayed. | ||
|
|
||
| ## Production port mapping | ||
|
|
||
| The core deliberately defines injected ports. Production integration should map them as follows: | ||
|
|
||
| - `verifyTarget`: authoritative config/workspace/Git-state resolution, including dirty state and committed HEAD; | ||
| - `prepareWorkspace`: existing `workspaceWorktreeApplicationService.create` for managed targets, or authoritative lookup for the explicitly acknowledged existing workspace; | ||
| - `createChat`: existing chat application service, tagged durably by handoff operation ID; | ||
| - `installUntrustedContext`: a bounded main-owned task-context record, not a hidden user prompt or source write; | ||
| - `publishProjectLink`: one compare-and-swap Design Project update that makes the task linkage visible; | ||
| - `inspectPublication`: authoritative Design Project lookup by operation ID; | ||
| - rollback ports: existing chat/worktree cleanup services plus durable proof that the operation-owned effect is absent. | ||
|
|
||
| The production adapters must preserve the operation ID in their own effect records so “idempotent” is a verified property, not a coordinator assumption. They must not shell out directly; Git and worktree work stays behind existing application services. | ||
|
|
||
| ## Production effect integration | ||
|
|
||
| `DesignHandoffEffectStore` owns a second owner-only, bounded ledger, `design-handoff-effects.json`. The coordinator journal records the cross-store state machine; this effect ledger records the operation-keyed identities needed to rediscover effects after a crash. It stores only workspace/chat/task IDs, renderer-safe labels, the parsed handoff packet, and the published linkage. It does not store repository paths, source bytes, prompts, credentials, Git capabilities, or tool authority. | ||
|
|
||
| The existing managed-worktree and chat application services do not accept a caller-owned effect ID. The production adapter therefore derives a deterministic `feature/design-handoff-<digest>` branch and a visible `Design handoff · <digest>` chat title from the operation ID. Before creating either effect it searches authoritative main-owned records for that tag. The effect ledger then binds the discovered/generated workspace and chat identities to the operation. An ambiguous discovery fails closed. | ||
|
|
||
| Managed target inspection pairs the current Review snapshot with the cohesive committed Git `HEAD`. `verifyTarget` repeats that inspection immediately before any effect and requires the exact preview, dirty state, and commit the person confirmed. Worktree creation remains behind `workspaceWorktreeApplicationService.create`; its returned `createdFromHead` must equal the confirmation. A new managed handoff workspace is changed to `ask` permission before chat creation, so ordinary source writes and shell work retain Aiden's approval gates. An existing workspace retains its already-authorized permission and is never deleted by handoff rollback. | ||
|
|
||
| The workspace chat is an ordinary non-Bot chat. Aiden currently has no separate durable Task entity, so the published `taskId` is the chat ID; both identities remain explicit in the linkage. The packet is installed in the main-owned effect ledger as untrusted task context, not appended as a hidden system/user prompt. `contextForChat(chatId)` adds that bounded context to the visible task and accepted model turn. | ||
|
|
||
| Before context installation and again at publication, the production binding verifies the Design Project CAS revision, generated-artifact lineage/revision membership, committed source byte length and SHA-256, and the existence and project ownership of each content-addressed reference asset. Publication writes a separate project-indexed linkage in the effect ledger; it does not grant workspace authority back to the prototype or modify the project snapshot. | ||
|
|
||
| `designHandoffApplicationService.initialize()` initializes the effect ledger. `reconcileAtStartup()` is an explicit startup hook that resumes every nonterminal journal independently, returning renderer-safe failures while logging private diagnostics. The service also exposes target previews, begin/cancel/resume, project links, and chat context for the main handler layer. | ||
|
|
||
| ## Current limitations | ||
|
|
||
| Handoff creates or reuses a local workspace and an ordinary Aiden chat/task. It does not implement | ||
| hosted collaboration, deployment, pull-request creation, or automatic source writes. Recoverable | ||
| records remain explicit and can be resumed or cancelled from the owning project. |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.