Repository navigation
fix(widgets): hold a chosen folder's mark to the folder the person chose - #641
Merged
Merged
Conversation
A chosen folder was matched by path alone, so after it was moved away any real folder later made at that path counted as the person's choice again. The person's start now stores the chosen folder's device and file id (chosenFolderId) beside the mark, read right after the root is resolved. A mark counts only while its path resolves to itself and the folder there has that id, so a folder made in its place stays "not found now" and can be forgotten, while the chosen folder moved back counts again. A mark stored before ids were kept has none. It takes the id of the folder found at its path the first time one is, and is held to that folder from then on. The session store stays at version 1: the field is optional. Refs #628
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 8, 2026 02:56
…-identity # 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 was referenced Oct 8, 2026
Closed
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.
Fixes #628. Refs #538, #612, #610, #546.
What was wrong
A folder the person chose for widget development (#538, #612) was matched by path alone. After the chosen folder was moved away, its mark was listed as "not found now". But if any real folder was later made at the same path, the mark counted again, even though it was not the folder the person chose (finding N4 in the #612 review).
What changes
This takes option 1 from the issue: each mark is held to the folder's file identity.
chosenByPerson), it also stores that folder's device and file id aschosenFolderId: { dev, ino }, in decimal strings, in the node's widget dev session store.lstatright aftercheckRootresolved the root.foundonly when both hold:devRootState, the identity check dev sessions already use (fix(widgets): detect a replaced dev folder and ignore transient stat errors #546, fix(widgets): detect a replaced dev folder and ignore transient stat errors #610).Marks stored before this change
Older stores have marks with no
chosenFolderId. Such a mark takes the id of the folder found at its path the first time one is found there. That happens on the firstchosen(),marked(), card or Clark start check after the upgrade. From then on it is held to that folder.If the folder is missing at that first look, no id is taken. The mark stays "not found now" until a folder is there. There is no record of which folder was chosen before this change, so that first folder is the one adopted.
Store schema
The session store is the JSON file
widget-dev/sessions.json, not a SQL table, so no migration is involved. The new field is optional and the store stays atversion: 1, so existing files parse unchanged. No SQL migration was added or edited.Caveat: an older build reading a store written by this one rejects the unknown field, because the schema is strict. It sets the file aside, as it does for any unreadable store. Any new optional field on this strict schema has the same downgrade behaviour.
Residuals (not widened by this PR)
statxis missing, and that would break the mark on any edit.rm -rf dir && build) loses its mark, and the person chooses it again. A running session there keeps running: the engine still follows the folder (fix(widgets): detect a replaced dev folder and ignore transient stat errors #610). Only a new start by Clark needs the mark.Overlap
packages/core/src/widget-dev-engine.ts, where Quiet the builds around a dev folder that is deleted and recreated #638 is working. This reuses the exporteddevRootStatefor the comparison. The engine's privatedevRootIdentityOfis mirrored by a 7-linefolderIdOfin the runtime, which useslstatso that a link at the path gives no id. I mirrored it instead of exporting it to avoid conflicting with Quiet the builds around a dev folder that is deleted and recreated #638.Tests
New in
apps/runtime/test/widget-dev-sessions.spec.ts, using real folders and Windows junctions and run on Windows 11. The temp folder is realpath'd, which covers macOS/private/var.chosen()is[],marked()isfound: false, and the card shows "not found now";found: true, and Clark's start runs.Both fail on
mainsource:expected [ Array(1) ] to deeply equal []andexpected undefined to be defined.Verification (this tree)
widget-dev-sessions,slash-commands,open-interfacesanddevelop-folder-card: 123/123 passed.pnpm typecheckpassed.pnpm invariants: 15/15 passed.docs/manifest.jsonwas refreshed for the two edited docs.pnpm verify: 575 files passed (1 skipped), 7856 tests passed.Docs
docs/open-interfaces{,.vi}.mdanddocs/widget-development{,.vi}.mdare updated in pairs.