Skip to content

Commit 25a8583

Browse files
committed
Order saved-repository writes across navigation and session changes
1 parent f7b61cb commit 25a8583

10 files changed

Lines changed: 166 additions & 36 deletions

File tree

‎DESIGN.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ in-flight step and stops future scheduling, while the current transaction can
9292
finish. A changing Play/Pause/New run action label uses an ordinary button,
9393
without a contradictory toggle pressed state. Respect another chosen control.
9494

95+
Repository saves expose a busy button and pending status. Their current-session
96+
writes run in order even when the user opens another repository; a changed
97+
repository gets its own form state. Completing a save restores its control only
98+
on the same route/account and without stealing another chosen input.
99+
95100
## Motion
96101

97102
No authored animation or transition in the workspace, including modal scale/fade, progress interpolation, hover motion and smooth route scrolling. Update status immediately without recreating the page. Native dialog handles focus and Escape; returning focus must not move the document. Game canvas motion belongs to gameplay and remains independent of workspace chrome.

‎docs/CONTEXT.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ and external AI CLIs require a direct user request. Never merge old work implici
8282
- Existing Commons run 49092854-f9bd-4b7a-8d12-4ac5ea0e5f70 retains the approved,
8383
unmerged safe-timer change from job 811bdb98-bcbb-4b65-80b9-f19693aef6b4.
8484
Preserve it. 29 earlier lab experiments were verified before this release work.
85-
- Public source: antropos17/commit-zero at 5392fc0; all three CI jobs passed with local dfa9ecb's identical tree. Preserve separate histories.
85+
- Public source: antropos17/commit-zero at f7b61cb; all three CI jobs passed with local 21c0ab1's identical tree. Preserve separate histories.
8686
README GIF is a 15.8s condensed walkthrough of retained Sequence Kit work,
8787
not a continuous live recording. Static fallback included; desktop/mobile and all
8888
three CI jobs passed. Evidence: runtime/verification/github-readme-gif-2026-10-19.json.

‎docs/DEVELOPMENT.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ output under `.cache/tmp`. Child processes receive TEMP/TMP/TMPDIR explicitly.
100100
On Windows, a local Chrome installation can be used without downloading a
101101
Playwright browser by setting `CZ_BROWSER_EXECUTABLE` to its absolute executable
102102
path. `CZ_CAPTURE_BROWSER=1` saves catalog desktop/narrow captures under
103-
`runtime/verification`. `npm run test:ui` runs four serial groups with fresh
103+
`runtime/verification`. `npm run test:ui` runs the configured serial groups with fresh
104104
disposable in-memory services to preserve scenario independence and keep the
105105
normal 180-request/minute API limiter active. `scripts/test-ui.mjs`
106106
checks that each browser spec is listed exactly once. Playwright global setup

‎docs/FIRST-RUN.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ do not establish runtime correctness. [Complete workflow](COMMONS.md).
6363
| Project address is already in use | The form retains its name and description; choose another address and submit again. No duplicate project is created. |
6464
| Saving a scenario repository is rate limited | The repository shows a persistent message beside **Save**. Wait briefly and select **Save** again; a failed request does not add a bookmark. |
6565
| Saved repositories are unavailable after sign-in | Your sign-in succeeded. Restore the service and select **Refresh saved repositories** on **My profile**. An unknown list is not shown as empty; a previously loaded list remains visible if refresh fails. |
66+
| Saving several repositories while navigating | Saves from this page session finish in order. The busy button and Saving status persist until that repository's action finishes. A failed save is not retried automatically; another explicitly requested save can proceed. Signing out cancels saves that have not yet been sent. Use **Refresh saved repositories** to reconcile changes from another tab. |
6667
| Task fails or is cancelled | Inspect its retained timeline and raw receipt. Retry by explicitly starting a new task; a restarted server does not silently retry jobs. |
6768
| Provider setup is unavailable | Continue exploring the deterministic example and model-free Commons forms. Do not interpret these as actual model contributions. |
6869

‎docs/HANDOFF-2026-10-19.md‎

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ tracks dated decisions and receipts; this file is the operational entry point.
88
## Repositories and state
99

1010
- Working repository: `X:\ai-github`, branch `codex/development-foundation`,
11-
latest fully checked local commit `dfa9ecb` at this checkpoint. The local data and model
11+
latest fully checked local commit `21c0ab1` at this checkpoint. The local data and model
1212
installation are here. Recheck status before acting; this file can age.
1313
- Public repository: [antropos17/commit-zero](https://github.com/antropos17/commit-zero),
14-
`main` at `5392fc00b2ac2f8faedc507acc63311705a93dcc` after a normal push.
14+
`main` at `f7b61cb854c4cd8df1d31f04d631568afedd8188` after a normal push.
1515
Its separate checkout is `.cache/publication`. The histories are unrelated;
16-
the public tree matches local `dfa9ecb` (`ceec86201675ecda32f8c844123f5994c1b8ac28`).
17-
Keyboard scenario-control changes are awaiting final gates.
16+
the public tree matches local `21c0ab1` (`a7e8072ee4235ae533b03ea92ad3cf5b665095ad`).
17+
Ordered bookmark-write and save-focus changes are awaiting final gates.
1818
Do not merge histories, reset the local branch or force push. Recheck remote
1919
before publishing anything else.
20-
- Public CI [run 39233009471](https://github.com/antropos17/commit-zero/actions/runs/39233009471)
21-
passed full gate, Chromium and runtime dependency audit for `5392fc0`. Local
20+
- Public CI [run 39234149501](https://github.com/antropos17/commit-zero/actions/runs/39234149501)
21+
passed full gate, Chromium and runtime dependency audit for `f7b61cb`. Local
2222
`evidence:status` confirmed equal trees and current full/browser receipts. The
2323
preceding retry-fixture failure at `5f9f88e` is preserved in the mission log.
2424
- This mission has not run local or hosted model inference, spawned product
@@ -125,16 +125,20 @@ The scenario assertion follows the actual returned step and forbids reset/advanc
125125
requests. [Desktop error](media/service-health-unavailable-2026-10-19.png) and
126126
[narrow dark retained state](media/service-health-last-known-2026-10-19.png)
127127
are real disposable-service captures. Full 81/81 and Chrome 18/18 passed on the
128-
same frozen source before commit/publication. The next keyboard unit preserves
128+
same frozen source before commit/publication. The completed keyboard unit preserves
129129
manual step focus and keeps Pause usable during the current transaction; its
130-
four focused Chrome tests passed, with full gates pending.
130+
four focused Chrome tests passed, then all 22 browser journeys, full gate and
131+
public CI passed. The pending bookmark unit serializes explicit session writes,
132+
continues after a failed write, and drops unsent work after identity changes.
133+
Repository form state is scoped to run/repository; save completion respects focus.
134+
Other tabs are reconciled by explicit saved-list refresh, not cross-tab locking.
131135

132-
- Latest local frozen full gate at `dfa9ecb`: 81/81 Node tests, compiled DOM/axe
136+
- Latest local frozen full gate at `21c0ab1`: 81/81 Node tests, compiled DOM/axe
133137
2/2, build and static serving passed. Stable source hash
134-
`b68e7f8a312d9ac724e2e845eb690f0db19313e4badf3e96fb5c6590398d9360`;
135-
receipts `runtime/verification/health-recovery-{full,browser}-2026-10-19.json`
138+
`64ac75502a7c3c75e7141067b6701859a4f43de08c1c3546c6c92a07f0c94b8f`;
139+
receipts `runtime/verification/scenario-keyboard-{full,browser}-2026-10-19.json`
136140
(ignored by Git).
137-
- Installed Chrome browser suite passed 18/18 at desktop and 390px. Real captures
141+
- Installed Chrome browser suite passed 22/22 at desktop and 390px. Real captures
138142
are `runtime/verification/commons-first-run-{desktop,narrow}-2026-10-19.png`,
139143
`commons-provider-offline-desktop-2026-10-19.png` and catalog captures. Tests
140144
used in-memory services; provider-health responses were controlled in the
@@ -203,7 +207,7 @@ four focused Chrome tests passed, with full gates pending.
203207

204208
## Next work, in order
205209

206-
1. Complete keyboard scenario controls: run grouped Chrome and `npm run check` on frozen source,
210+
1. Complete ordered bookmark writes: run grouped Chrome and `npm run check` on frozen source,
207211
commit it, copy the unpublished local commit into the separate public
208212
checkout, compare Git trees, push without force and inspect public CI.
209213
Record exact SHA and receipt.

‎docs/MISSION-2026-10-19.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Start: 03:46:17 UTC. Deadline: 15:46:17 UTC. Final integration reserve begins 14
1212

1313
## Current action
1414

15-
Finish keyboard scenario controls after two preserved Chrome failures. Next step now retains entry, terminal/error steps fall back to content, and Pause remains available during a transaction without cancelling its committed work. Verify current-step completion, no future scheduling, chosen-input focus and preserved exports; then frozen full gates and publication. Keep all new profiles disabled. The final integration reserve still begins at 14:16:17 UTC.
15+
Finish ordered account bookmark writes after a preserved delayed-response race. Explicit saves queue within one identity, failed writes do not poison the queue, and identity changes discard unsent earlier requests. Add visible pending/focus recovery and verify direct repository navigation, error continuation and account switching; then frozen full gates and publication. Keep all new profiles disabled. The final integration reserve still begins at 14:16:17 UTC.
1616

1717
## Decisions and limits
1818

@@ -93,4 +93,7 @@ Finish keyboard scenario controls after two preserved Chrome failures. Next step
9393
- 09:50 UTC: health/manual-refresh recovery committed locally as `dfa9ecb16afea0c7d5e31ff6bc029a9483fef1ac` after full 81/81 and Chrome 18/18 on the same frozen hash `b68e7f8a312d9ac724e2e845eb690f0db19313e4badf3e96fb5c6590398d9360`. Receipts: `runtime/verification/health-recovery-{full,browser}-2026-10-19.json`. Normal publication produced `5392fc00b2ac2f8faedc507acc63311705a93dcc`, identical tree `ceec86201675ecda32f8c844123f5994c1b8ac28`. CI39233009471 passed all three jobs. Local preflight confirmed current full/browser receipts and both clean equal trees.
9494
- Chrome then reproduced Next step losing focus after a successful transaction and Pause being disabled while a cycle request was pending. Both traces are retained under `runtime/verification/scenario-keyboard-baseline-2026-10-19`. An initial three-test focused correction passed; the strengthened pause cases also distinguish restoring the control from respecting another chosen input. No model calls or retained-store writes.
9595

96-
Run focused UI, freeze complete source for all browser groups and full gate, then commit/publish the keyboard unit. Next inspect competing bookmark writes and remaining release acceptance gaps. Keep the final 90-minute reserve from 14:16:17 UTC.
96+
- 10:00 UTC: keyboard scenario controls committed locally as `21c0ab140fb94dae5c030f37688c0cfeadb006f1` after full 81/81 and Chrome 22/22 on frozen hash `64ac75502a7c3c75e7141067b6701859a4f43de08c1c3546c6c92a07f0c94b8f`. Receipts: `runtime/verification/scenario-keyboard-{full,browser,evidence}-2026-10-19.json`. Normal push produced `f7b61cb854c4cd8df1d31f04d631568afedd8188`, identical tree `a7e8072ee4235ae533b03ea92ad3cf5b665095ad`. CI39234149501 passed all three jobs. Diagnostics reported 74 GB free; retained database, identity, backups and model sizes remained unchanged.
97+
- Chrome reproduced two successful bookmark writes followed by a delayed first response removing the second saved label. Baseline: `runtime/verification/bookmark-write-baseline-2026-10-19`. A separate actual focus failure is retained under `bookmark-focus-baseline-2026-10-19`. Six focused account tests passed the queue/error/session contracts before the final pending/focus refinement. The queue has no automatic write retry, provider execution or database migration.
98+
99+
Complete focused account/UI checks, then freeze all source for the full 25-test browser suite and `npm run check`; commit/publish and inspect CI. Next inspect release acceptance gaps and generic resource failure states. Keep the final 90-minute reserve from 14:16:17 UTC.

‎prototype/app/App.jsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ function Page({ route, preview, notify }) {
126126
case "repo":
127127
return (
128128
<Repository
129+
key={`${data.runId}/${id}`}
129130
id={id}
130131
tab={tab}
131132
file={file}

‎prototype/app/pages/workspace.jsx‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,16 @@ export function Repository({ id, tab = "code", file, preview, notify }) {
530530
const account = useAccount();
531531
const [saving, setSaving] = useState(false);
532532
const [saveError, setSaveError] = useState("");
533+
const saveOrigin = useRef(null);
534+
useLayoutEffect(() => {
535+
if (saving) return;
536+
const pending = saveOrigin.current;
537+
saveOrigin.current = null;
538+
if (pending && pending.owner === account.user?.id &&
539+
pending.hash === location.hash && pending.node.isConnected &&
540+
(document.activeElement === document.body || document.activeElement === pending.node))
541+
pending.node.focus({ preventScroll: true });
542+
}, [saving, account.user?.id]);
533543
const r = data.repos.find((x) => x.id === id);
534544
if (!r) return <NotFound />;
535545
const prs = data.prs.filter((p) => p.repo === id),
@@ -545,7 +555,8 @@ export function Repository({ id, tab = "code", file, preview, notify }) {
545555
notify("Copy unavailable. Select the code and copy it manually.");
546556
}
547557
}
548-
async function save() {
558+
async function save(event) {
559+
saveOrigin.current = { node: event.currentTarget, hash: location.hash, owner: account.user?.id };
549560
setSaving(true);
550561
setSaveError("");
551562
try {
@@ -692,7 +703,7 @@ export function Repository({ id, tab = "code", file, preview, notify }) {
692703
</button>
693704
)}
694705
{account.user ? (
695-
<button className="btn" disabled={saving} onClick={save}>
706+
<button className="btn" disabled={saving} aria-busy={saving} onClick={save}>
696707
{account.bookmarks.includes(id) ? "Saved" : "Save"}
697708
</button>
698709
) : (
@@ -711,6 +722,7 @@ export function Repository({ id, tab = "code", file, preview, notify }) {
711722
<span className="count">{r.stars.length}</span>
712723
</a>
713724
</div>
725+
{saving && <p className="field-help" role="status">Saving repository…</p>}
714726
{saveError && <p className="repo-save-error" role="alert">{saveError}</p>}
715727
</div>
716728
<Tabs

‎prototype/app/state.jsx‎

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,12 @@ export function AccountProvider({ children }) {
145145
[checked, setChecked] = useState(false);
146146
const currentUser = useRef(null),
147147
identityVersion = useRef(0),
148-
bookmarkVersion = useRef(0);
148+
bookmarkVersion = useRef(0),
149+
bookmarkQueue = useRef(Promise.resolve());
149150
const installIdentity = useCallback((next) => {
150151
identityVersion.current++;
151152
bookmarkVersion.current++;
153+
bookmarkQueue.current = Promise.resolve();
152154
currentUser.current = next;
153155
setUser(next);
154156
setBookmarks([]);
@@ -222,24 +224,31 @@ export function AccountProvider({ children }) {
222224
currentUser.current = result.user;
223225
setUser(result.user);
224226
};
225-
const bookmark = async (repo, saved) => {
227+
const bookmark = (repo, saved) => {
226228
const identity = identityVersion.current,
227229
owner = currentUser.current?.id;
228-
const result = await request(
229-
`account/bookmarks/${encodeURIComponent(repo)}`,
230-
{ method: "PUT", body: { saved } },
231-
);
232-
if (
233-
identityVersion.current !== identity ||
234-
currentUser.current?.id !== owner
235-
)
236-
return;
237-
// A read captured before this completed write must never replace its result.
238-
bookmarkVersion.current++;
239-
setBookmarks(result.bookmarks);
240-
setBookmarksKnown(true);
241-
setBookmarksLoading(false);
242-
setBookmarksError("");
230+
const isCurrent = () => owner && identityVersion.current === identity &&
231+
currentUser.current?.id === owner;
232+
// Responses contain full lists without revisions. Serialize this session's
233+
// explicit writes so a delayed earlier response cannot undo a later list.
234+
const operation = bookmarkQueue.current.then(async () => {
235+
if (!isCurrent()) return { applied: false };
236+
const result = await request(
237+
`account/bookmarks/${encodeURIComponent(repo)}`,
238+
{ method: "PUT", body: { saved } },
239+
);
240+
if (!isCurrent()) return { applied: false };
241+
// A read captured before this completed write must never replace its result.
242+
bookmarkVersion.current++;
243+
setBookmarks(result.bookmarks);
244+
setBookmarksKnown(true);
245+
setBookmarksLoading(false);
246+
setBookmarksError("");
247+
return { applied: true };
248+
});
249+
// Keep the caller's error, while allowing the next explicit save to proceed.
250+
bookmarkQueue.current = operation.catch(() => {});
251+
return operation;
243252
};
244253
return (
245254
<Account.Provider

0 commit comments

Comments
 (0)