Skip to content

Commit e98812f

Browse files
committed
fix(commons): preserve saved author identity during read recovery
1 parent 9a8dde0 commit e98812f

12 files changed

Lines changed: 477 additions & 32 deletions

‎DESIGN.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ scrolling to fresh events is an explicit reader action.
245245

246246
## Compact working surfaces
247247

248+
Saved-author discovery preserves the selected ID while loading or unavailable.
249+
It never silently substitutes Workspace Builder. Explicit read recovery retains
250+
the task draft, qualifies last-available configurations and restores keyboard
251+
entry without overriding another chosen input. Unknown configurations cannot
252+
be submitted as the selected author.
253+
248254
Mobile navigation retains every labeled destination in three parallel groups.
249255
Tabs wrap rather than placing sections outside the visible strip. Primary preview,
250256
experiment launch and refresh controls belong in the page heading; PR status

‎docs/CONTEXT.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ and external AI CLIs require a direct user request. Never merge old work implici
2727
and previous PRs. Merging closes a linked issue transactionally. PRs support
2828
discussion, close/reopen and revision tasks; duplicate retained code is rejected.
2929
- Saved local agents can author proposals through owner-checked profile lookup.
30-
Configuration/version/instructions are frozen per task. Project scope, local
30+
Read-only discovery preserves selected IDs and offers explicit retry. Project scope, local
3131
provider/model, propose/discuss/star capabilities and duration are enforced.
3232
Reviewer is host-controlled; merge remains explicit. Instructions are not secrets.
3333
- Source changes modify or add one bounded JavaScript file; parser checks never

‎docs/ECOSYSTEM-DECISIONS.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,18 @@ without automatic write retry, and pause with/without another focus choice.
189189
| Browser startup and temporary files | Reuse installed Playwright 1.64.1, apply workspace temporary variables before import/spawn, and inspect/remove a fresh Chrome profile in a separate readiness probe. [Primary launch reference, baseline and actual receipt](WORKFLOW-MEASUREMENTS.md#browser-temporary-paths-and-readiness). No new dependency or sandbox is introduced. |
190190
| Source-bound release evidence | Use the existing Playwright JSON reporter and Git tree comparison to correlate full local/browser receipts without merging histories. [Primary reporter reference, observed manual friction and rejection fixtures](WORKFLOW-MEASUREMENTS.md#earlier-feedback-measurements). The preflight never publishes or claims provider/sandbox qualification. |
191191
| Open-source distribution | Prepare real captures and channel-specific material, respect channel restrictions, and publish only source/docs. [Rules, drafts and assets](DISTRIBUTION.md). |
192+
193+
### Saved-author recovery (accessed 2026-10-19)
194+
195+
The existing [React effect cleanup guidance](https://react.dev/reference/react/useEffect#fetching-data-with-effects)
196+
also applies to owner-scoped configuration reads. An actual Chrome baseline
197+
showed a false sign-in instruction and a native select visually falling back to
198+
Workspace Builder after HTTP 503. Decision: keep owner-scoped read state, validate
199+
rendered fields and IDs, cancel replaced reads, retain the intended selection
200+
with an unavailable option, and offer explicit read-only refresh. Last-available
201+
choices stay qualified and cannot authorize a submission until refreshed.
202+
Expected benefit: a failed discovery read cannot silently change task attribution.
203+
Four browser cases exercise actual disposable account/configuration endpoints,
204+
failed and malformed reads, recovery, missing selection, focus and narrow axe.
205+
Configuration creation is explicitly non-executable; no job is submitted and no
206+
model or catalog role is activated. No dependency or third-party code is added.

‎docs/FIRST-RUN.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,12 @@ uses malformed read-only metadata in disposable services; the subsequent retry
141141
reaches the real handler. Run agents is never pressed in those fixtures.
142142
A successful health check alone does not qualify inference, tool access, model
143143
quality or any of the disabled Proposed roles.
144+
145+
For a saved task author, **Refresh saved agents** retries the signed-in account's
146+
configuration list. A failed read preserves the selected ID and task draft;
147+
it does not silently choose Workspace Builder or ask an already signed-in owner
148+
to sign in again. Last-available configurations remain visible but cannot be
149+
used until refreshed successfully. A confirmed missing author requires an
150+
explicit author choice. [Actual narrow failure capture](media/commons-saved-agents-unavailable-2026-10-19.png)
151+
uses a configuration-only fixture and a routed HTTP 503. Recovery reads the
152+
actual owner endpoint; no task, agent or model is started.

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

Lines changed: 23 additions & 11 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 `4d236f3` at this checkpoint. The local data and model
11+
latest fully checked local commit `7ed1ea0` 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 `38c63799d41af4f4265870d5afb7801721acc33a` after a normal push.
14+
`main` at `9a8dde0de8cf7076f3f46b1e539e68ee9cfc0e9f` after a normal push.
1515
Its separate checkout is `.cache/publication`. The histories are unrelated;
16-
the public tree matches local `4d236f3` (`19906b17ac7eabb737a2c4b154da2d9637ef7c61`).
17-
Commons readiness recovery is the next bounded unit.
16+
the public tree matches local `7ed1ea0` (`5b4fdf3ef9a4233552c2a97b8b550894acaf7863`).
17+
Saved-author read recovery is the next bounded unit.
1818
Do not merge histories, reset the local branch or force push. Recheck remote
1919
before publishing anything else.
20-
- Public CI [run 39252943247](https://github.com/antropos17/commit-zero/actions/runs/39252943247)
21-
passed full gate, Chromium and runtime dependency audit for `38c6379`. Local
20+
- Public CI [run 39255670021](https://github.com/antropos17/commit-zero/actions/runs/39255670021)
21+
passed all three jobs for `9a8dde0`. 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
@@ -216,12 +216,24 @@ task submissions. [Actual unknown-readiness capture](media/commons-readiness-unk
216216
has SHA-256 `46437ce7afba4bede8e5014d1aa3636d6bb07560808a9862be2ad394bd3a6d3d`.
217217
It uses deliberately malformed fixture metadata; health checks do not establish
218218
actual inference or qualify a catalog role. Full 51-case Chrome and frozen full
219-
gates remain required for this unit.
219+
gates passed for the published unit.
220220

221-
- Latest local frozen full gate at `4d236f3`: 102/102 Node tests, compiled DOM/axe
221+
Saved-author discovery now lives in `prototype/app/pages/commons-agents.mjs`.
222+
It validates the list, scopes it by account, cancels replaced reads, preserves
223+
the selected ID and exposes read-only refresh with pending/error/last-available
224+
states. Missing or stale configurations cannot submit as an author; selecting
225+
Workspace Builder must be explicit. Five focused Chrome cases passed using
226+
actual disposable configuration-only account records, without task submission.
227+
The inspected [failure capture](media/commons-saved-agents-unavailable-2026-10-19.png)
228+
has SHA-256 `6da3987dac09f4723413bb50bb721dc90a39ce0251df34eaa7a5621180a79811`.
229+
The anonymous-session regression caught by the first full run is fixed; the
230+
signed-out selected-author case now passes in the isolated five-case group.
231+
Full 56-case Chrome and frozen full gates remain required for this new unit.
232+
233+
- Latest local frozen full gate at `7ed1ea0`: 102/102 Node tests, compiled DOM/axe
222234
2/2, build and static serving passed. Stable source hash
223-
`b5d53159f6c587d68f881f480f1f4ade365b9a78618e06b9ad24ec54241ed552`;
224-
receipts `runtime/verification/timeline-recovery-{full,browser}-2026-10-19.json`
235+
`fee9f65a04891d506c54db9a953cabeeb4d018ee1cf1dcc1a5745c9a979fc95a`;
236+
receipts `runtime/verification/commons-readiness-{full,browser}-2026-10-19.json`
225237
(ignored by Git).
226238
- Installed Chrome browser suite passed 47/47 at desktop and 390px. Real captures
227239
are `runtime/verification/commons-first-run-{desktop,narrow}-2026-10-19.png`,
@@ -292,7 +304,7 @@ gates remain required for this unit.
292304

293305
## Next work, in order
294306

295-
1. Complete Commons readiness: run grouped Chrome and `npm run check` on frozen source,
307+
1. Complete saved-author recovery: run grouped Chrome and `npm run check` on frozen source,
296308
commit it, use `publication:prepare` dry run/explicit staging in the separate
297309
checkout, compare Git trees, commit/push without force and inspect public CI.
298310
Record exact SHA and receipt.

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,13 @@ Complete Commons model-readiness recovery after five related Chrome cases passed
134134

135135
- A separate saved-author baseline created only an explicitly configuration-only author in disposable identity services, then routed the owner-list read to HTTP 503. It exposed a false sign-in instruction, native select falling back visually to Workspace Builder despite the retained selected ID, and no explicit list retry. Trace/context: `runtime/verification/saved-author-baseline-2026-10-19`. No author launch or task submission occurred. Repair this as the next bounded unit after readiness publication, keeping the selected identity explicit and recovery read-only.
136136

137-
Freeze source for the 51-test browser suite and full 102-test Node gate. Commit, prepare/publish and inspect exact CI. Preserve the final 90-minute reserve from 14:16:17 UTC.
137+
- 12:54 UTC: Commons readiness committed locally as `7ed1ea0df32c3ec942313bd10b1004dbadb03f8f` after full 102/102 Node, 2/2 DOM and Chrome 51/51 gates on frozen source-index v2 hash `fee9f65a04891d506c54db9a953cabeeb4d018ee1cf1dcc1a5745c9a979fc95a`, unchanged after commit. Fresh fetch and qualified preparation transferred a 172,922-byte patch, SHA-256 `cef8d1e63ece47e4aabd82f8468f0f97238d0372d6fe9c0d6c7860aaa7dc3f53`. Ordinary public commit/push produced `9a8dde0de8cf7076f3f46b1e539e68ee9cfc0e9f`, identical tree `5b4fdf3ef9a4233552c2a97b8b550894acaf7863`. CI39255670021 subsequently passed all three jobs. Receipts: `runtime/verification/commons-readiness-{full,browser,evidence}-2026-10-19.json` and `commons-readiness-preparation-{ready,staged}-2026-10-19.json`.
138+
- Saved-author recovery now retains explicit selected identity through failed/malformed reads, scopes configurations by owner, cancels replaced reads and exposes a read-only refresh with pending and last-available states. A stale selected configuration cannot authorize submission; native selection never silently falls back to Workspace Builder. Four focused Chrome cases passed against actual disposable account/configuration endpoints, including strict read fields, duplicate IDs, absent selected author, both manual focus outcomes and 390px light/dark axe. Initial fixture creation asserts configuration-only status and unavailable standalone execution. Subsequent checks assert no non-GET request or scenario/Commons revision, event or job change; no task or model is started. The inspected narrow capture `docs/media/commons-saved-agents-unavailable-2026-10-19.png` has SHA-256 `6da3987d`. `check:fast` passed 9/9 focused tests; full acceptance remains separate.
139+
140+
- The first saved-author focused UI gate passed its lint/build/two DOM/serving stages but correctly failed source stability because handoff/mission documentation was edited during the run. Receipt and raw log `runtime/verification/commons-saved-agents-ui-2026-10-19` are retained as failed evidence, not acceptance. Freeze all indexed source and documentation for the complete browser and full gate below; no stage is waived.
141+
142+
- The first full browser group then exposed an anonymous-session focus regression in the new hook (`entry` was null while both owner IDs were undefined). Its stable failed receipt is `commons-saved-agents-browser-2026-10-19.json`; no full gate or publication followed. Add an explicit non-null guard and a signed-out selected-author journey. An initial focused rebuild inadvertently still used the uncorrected source after a patch-context failure; its four failures remain under `commons-saved-agents-corrected-focused-2026-10-19`. The corrected built source passed all three first-run cases plus four author cases, then hit the unchanged 180/minute limiter when combined in one service cluster. Preserve that result under `commons-saved-agents-corrected-built-2026-10-19`; run the five author cases in their own fresh group, as the complete suite already does. No limiter, retry or assertion was weakened.
143+
144+
- The rebuilt anonymous fix and all five author cases then passed together in a fresh isolated cluster: `runtime/verification/commons-saved-agents-corrected-isolated-2026-10-19.log`. The existing full-run first-entry assertions remain unchanged. Freeze all source/docs for complete acceptance next.
145+
146+
Freeze source for the 56-test browser suite and full 102-test Node gate. Commit, prepare/publish and inspect exact CI. Preserve the final 90-minute reserve from 14:16:17 UTC.
124 KB
Loading
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import {
2+
useCallback,
3+
useEffect,
4+
useLayoutEffect,
5+
useRef,
6+
useState,
7+
} from "react";
8+
import { request } from "../api.mjs";
9+
10+
// Saved configuration discovery never starts an author or submits a task.
11+
export function useCommonsAgents(owner) {
12+
const [state, setState] = useState({
13+
owner: null,
14+
items: [],
15+
known: false,
16+
loading: false,
17+
error: "",
18+
});
19+
const [revision, setRevision] = useState(0);
20+
const origin = useRef(null);
21+
const scoped = state.owner === owner;
22+
const loading = Boolean(owner && (!scoped || state.loading));
23+
const refresh = useCallback(
24+
(trigger) => {
25+
origin.current = { trigger, hash: location.hash, owner };
26+
setState((old) => ({ ...old, loading: true, error: "" }));
27+
setRevision((value) => value + 1);
28+
},
29+
[owner],
30+
);
31+
useEffect(() => {
32+
if (!owner) {
33+
setState({ owner, items: [], known: false, loading: false, error: "" });
34+
return;
35+
}
36+
const controller = new AbortController();
37+
setState((old) => ({
38+
owner,
39+
items: old.owner === owner ? old.items : [],
40+
known: old.owner === owner && old.known,
41+
loading: true,
42+
error: "",
43+
}));
44+
void request("account/agents", { signal: controller.signal })
45+
.then((value) => {
46+
if (
47+
!Array.isArray(value?.agents) ||
48+
value.agents.some(
49+
(agent) =>
50+
!agent ||
51+
["id", "name", "provider", "model"].some(
52+
(field) =>
53+
typeof agent[field] !== "string" || !agent[field].trim(),
54+
) ||
55+
!Number.isSafeInteger(agent.version) ||
56+
agent.version < 1,
57+
) ||
58+
new Set(value.agents.map((agent) => agent.id)).size !==
59+
value.agents.length
60+
)
61+
throw new Error(
62+
"The service returned invalid saved agents. Refresh saved agents to try again.",
63+
);
64+
if (!controller.signal.aborted)
65+
setState({
66+
owner,
67+
items: value.agents,
68+
known: true,
69+
loading: false,
70+
error: "",
71+
});
72+
})
73+
.catch((error) => {
74+
if (!controller.signal.aborted)
75+
setState((old) => ({ ...old, loading: false, error: error.message }));
76+
});
77+
return () => controller.abort();
78+
}, [owner, revision]);
79+
useLayoutEffect(() => {
80+
if (loading) return;
81+
const entry = origin.current;
82+
origin.current = null;
83+
if (
84+
entry &&
85+
entry.owner === owner &&
86+
entry.hash === location.hash &&
87+
entry.trigger?.isConnected &&
88+
(document.activeElement === document.body ||
89+
document.activeElement === entry.trigger)
90+
)
91+
entry.trigger.focus({ preventScroll: true });
92+
}, [loading, state, owner]);
93+
return {
94+
agents: scoped ? state.items : [],
95+
known: Boolean(owner && scoped && state.known),
96+
loading,
97+
error: scoped ? state.error : "",
98+
refresh,
99+
};
100+
}

0 commit comments

Comments
 (0)