Repository navigation
feat(widgets): let the person choose a project folder for widget dev sessions - #612
Merged
Merged
Conversation
…sessions /develop (or /develop <folder>, or asking Clark) answers with a host-owned develop card. Its rows start a session through the person-only POST /widget-dev/sessions route: the desktop app opens the OS folder dialog, and a browser, a node on another machine or a dialog that does not open asks for the path and says why. A person's start marks the stored session as chosen by the person; Clark may then develop that folder, and folders inside it, and keeps the mark when it picks the session up. When Clark asks for any other folder the tool starts nothing and returns the same card offering the folder. Fixes #538
This was referenced Oct 7, 2026
This was referenced Oct 7, 2026
Merged
…aw, and let them forget it A chosen folder is compared as stored, so a link swapped in at its path widens nothing. The folder card names and starts the folder a path resolves to, says when that differs from the path given, and says the choice covers every folder inside it. A whole drive or the home folder may run a session but is never kept as chosen. The person takes a choice back with the person-only POST /widget-dev/chosen-folders/forget, the Forget button on the card /develop forget answers with, or the card Clark shows through develop_widget's new folders action; choose shows the folder card when asked in words. Focus returns to "Choose folder" when the path field closes, and a row's old badge gives way to the status of a settled press.
…older itself A start marks its folder as the person's choice only when the pressed path is the folder as it resolves now, so a link swapped in after the card was drawn, or made at a path that was missing, starts that session but grants nothing. The card offers no button for a path that is not found, not absolute, or a network share or device path, and the press outcome says when a folder was not kept and why. develop_widget choose runs only in a turn the person sent. Forget answers stillCoveredBy when another folder Clark may use still holds the forgotten one, and a chosen folder that is not found at its path now is listed as such, so the person can still forget it.
Contributor
Author
|
Review attestation: ready to merge at A push to this PR makes this attestation stale; the new head needs its own review. |
mrgoonie
enabled auto-merge (squash)
October 7, 2026 22:02
# Conflicts: # docs/manifest.json
Contributor
Author
|
Review attestation: ready to merge at A push to this PR makes this attestation stale; the new head needs its own review. |
# Conflicts: # docs/manifest.json
Contributor
Author
|
Review attestation: ready to merge at A push to this PR makes this attestation stale; the new head needs its own review. |
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.
Summary
The person can now choose the project folder a widget dev session watches, from the conversation, and Clark can then work in it until the person takes that back.
/developand/develop <folder>(or asking Clark, through the newdevelop_widgetactionchoose) answer with a host-owneddevelopcommand card. It has a row for the proposed folder (Develop this folder), a row to Choose folder…, the folders already chosen, and the node's recent sessions. A stopped session can be developed again.{ kind: "develop-folder", root? }. A press in the person's own client calls the existing person-onlyPOST /widget-dev/sessions, so no agent, widget or machine surface picks a host path for itself...) before the card is built; the row's label and its press use the resolved folder, and the note shows the given path when it differs. The card says the choice covers every folder inside the folder. A press is kept as a choice only when the pressed path is still the folder itself when pressed, so a link swapped in after the card was drawn starts that session but grants nothing; the outcome line says the folder was not kept, and why. A path that is missing, relative, or a network share or device path gets no Develop button, only a note.desktop:pickDirectorybridge, but only when the gateway is loopback.--node-url);chosenByPerson: true. A whole drive (filesystem or drive root) or the home folder itself is never marked: a session may run there, but Clark keeps no access.checkRootlets a session Clark starts use a chosen folder or anything inside it, in addition to the widget workspace and the person's ownworkspace.roots.workspace.rootsstays unregistered, so no surface can write it.POST /widget-dev/chosen-folders/forget{ root }→{ root, forgotten }, idempotent. It is refused for machine surfaces inisPersonOnlyRoute(WebSocket relay,clarkcant api, MCP) and by the route itself for a request marked with a machine-surface header./develop forget(or thedevelop_widgetactionfolderswhen asked in words or by voice) shows the folders Clark may use, each with a Forget button (new closed action{ kind: "develop-folder-forget", root }). A chosen folder that is not found at its path now is listed as "not found now", still with Forget.stillCoveredBywhen another chosen folder or a configured project root still holds the forgotten one, and the message says Clark may still develop there through it.develop_widget chooseruns only in a turn the person sent, likestart,rebuildandplace.foldersonly narrows access and stays open.develop_widget startstill returns403 ROOT_NOT_OWNEDand starts nothing. Its answer carries the same card as a host block, so the person can start that folder with one press. The refusal text (VI/EN) points to the card and/develop.docs/open-interfaces*.mdanddocs/widget-development*.md. The official site is updated in docs(widgets): choose a project folder for widget dev sessions with /develop clarkcant-web#134.Fixes #538
Review follow-up, round 2 (CHANGES_REQUIRED at 356bdc5)
startsetschosenByPersononly when the pressed path is canonical (sameRoot(resolve(pressed), root)). The session view now carrieschosenByPerson, and the client says when a press was not kept. A missing proposed path gets no button. Tests cover a swap before the press and a missing path made into a junction later.chooseis refused frommcp,relay,cli-api,automation,peerandchannelturns, with and withoutroot;foldersstill works. A test covers each origin.stillCoveredBy, and the done message and docs say so.marked()lists every mark, withfound; the card lists missing ones with a "not found now" badge and Forget.realpathSync.native), so the suites hold on macOS, where the temp folder is reached through a link.Review follow-up, round 1 (CHANGES_REQUIRED at e17c9ea)
/develop forget, with tests for the grant being removed and for machine surfaces being refused.develop_widgetchoose/folders.Notes, not changed here:
chosenByPersonin the session store, so Clark would lose access to chosen folders (it fails closed). Rolling forward again restores them.api.tsrecords it.Verification
At the pushed head:
corepack pnpm verify(invariants, typecheck, lint, all vitest suites): passed, 571 test files passed and 1 skipped, 7696 tests passed.corepack pnpm exec playwright test apps/web/e2e/slash-commands.spec.ts: 5 passed. The/developjourney now also checks that focus returns after Escape, and that/develop forget→ Forget takes the choice back.apps/runtime/test/widget-dev-sessions.spec.ts:mcp,relayandcli-api;chooseandfoldersactions;chooserefused for every non-person origin,foldersstill shown;stillCoveredBy;apps/runtime/test/open-interfaces.spec.ts: the WebSocket relay refuses the forget route.apps/runtime/test/slash-commands.spec.ts:/developwith and without dev sessions, with an argument, and/develop forget.packages/conversation-client/test/desktop-compact.spec.ts: the folder dialog bridge, which treats the shell's answer as untrusted.packages/conversation-client/test/develop-folder-card.spec.ts: path entry with a reason per case, a record view with no controls, outcome messages, the Forget row with its badge after a press, the not-kept outcome line, and the still-covered forget message.Not exercised here: the native OS dialog on macOS and Linux. The bridge already existed; this PR only calls it and falls back to typed entry when it fails.
Overlap
This branch is rebased on #609 and #610, which both touch
widget-dev-sessions.ts, its spec anddocs/open-interfaces*.md. It is also rebased on #530 (/report);SLASH_COMMANDS,BlockActionsand the shell messages were merged so both commands are kept.origin/mainwas merged in afterwards, up to 0677965.