CodeNomad/dev-docs/SESSION_RECOVERY.md
Pascal André 7a1fc90310
docs(agents): keep AGENTS.md to universal rules and agent docs to the current state (#1082)
AGENTS.md loaded about 33,000 tokens into every agent session, subagent and reviewer, mostly per-feature contracts, and the agent documentation around it had accumulated duplicates, dated logs and history of removed designs. This PR makes AGENTS.md a short set of rules that apply everywhere plus an index of area documents, and leaves AGENTS.md, dev-docs and the repository skills describing only the current state.

Three commits, reviewable separately:

1. **Move (lossless).** Every per-area rule moved verbatim from AGENTS.md into its area document (existing ones, or six new ones: UI_CONVENTIONS, UI_SHELL, COMPOSER, TRANSCRIPT, SETTINGS, PROJECTS). A script split the old file into 208 units, required one destination for each and checked all 199 content units verbatim at their destination. AGENTS.md went from 134,000 to 16,000 characters.
2. **Trim.** A per-area ponytail review removed rules stated two or three times (keeping the more precise copy), dated validation logs, per-version qualification sections below the current minimum, abandoned designs and self-references; seven documents whose surviving rules live elsewhere were deleted. It also fixed statements the code contradicts (locale registration, the Mission play/recovery condition, plugin package updates, cleanup progress UI, timeline index persistence, automation restart/targets, stale pins and minimums).
3. **Current state only.** The new AGENTS.md rule: no history (removed features and their names, former behavior, provenance, dated logs) and no denials; correct a contradicted statement at its source. DEVELOPER_MODE.md is merged into BROWSER_AUTOMATION.md and every Developer Mode mention is gone (including the README and the browser help page in ten locales). Names that only made sense against older designs are renamed with every reference updated, MISSIONS_ENVIRONMENT_ADMISSION is folded into SESSION_ENVIRONMENT, and INDEX lists every document. The server npm README now states the real OpenCode minimum (2.1.2).

AGENTS.md is now about 14,000 characters (roughly 3,500 tokens); AGENTS.md, dev-docs and the vendor README went from about 11,200 lines to under 4,700.

Validation: every relative Markdown link and every cited dev-docs path resolves; no reference to a renamed or deleted document remains; `npm run test:help` passes for all ten locales.

Review: three independent GPT-6.1 Sol (high) reviews by area found binding rules lost in the trim and current-state passes; 25 were restored as present-tense facts or prohibitions and four contradicting statements corrected, each checked against code. A Fable 5.1 gatekeeper review of the whole PR passed; its follow-up routes session recovery from the index, points to dev-docs/INDEX.md and documents the family identity read.
2026-10-21 16:59:43 +02:00

3.8 KiB

Authoritative session recovery

Contract

scripts/test-missions-native.mjs also runs this reconciliation against a private native session: succeeded clears a saved working marker; a queued resume:false synthetic keeps the historical outcome and does not resolve pending admission; resuming it yields a newer time.idle boundary that does.

Never infer interruption from a saved working marker plus idle activity (work can finish while the desktop is absent); saved interrupted markers are revalidated against native state. Native outcome records the last finished turn only.

Recovery reconciles these separate facts:

Current native activity Native last outcome Projection
Active / compacting Any previous outcome Active, no recovery marker; old outcome cleared
Idle succeeded Normal completion, no Interrupted marker
Idle failed Session.outcome=failed, no Interrupted marker
Idle interrupted Native Interrupted marker retained
Idle, saved work Missing / unproven pending
Activity unavailable Last outcome alone Existing activity/recovery retained

session-generation-recovery.ts owns the projection and merge policy; session-api.ts preserves native outcomes and wires it into list/runtime reads. The activity read occurs after the list/inventory outcome reads, without blocking publication of the root directory page. Active-only liveness refresh reads native session info only for inactive rows with outstanding work/recovery, then rechecks activity so unseen restarted work supersedes the last outcome.

session-state.ts passes outcome to saved-marker hydration and clears the old outcome when native activity is observed or new input is admitted (rollback restores the original outcome). An in-memory admission epoch survives acknowledgement, fencing fetches even if recovery/status values return to identical values. Queued/admitted idle input completes only on observed active work or a newer native time.idle boundary; missing boundary evidence leaves it pending. The admission captures that baseline separately as generationAdmissionIdleBoundary. Non-blocking metadata publication can advance time.idle while activity is unavailable without consuming the captured boundary. Later authoritative list or liveness reads can therefore recognize the newer completion; rollback restores the prior epoch/boundary as well as outcome.

The merge preserves activity/recovery/admission/outcome as an authority group when newer SSE/local authority supersedes the captured baseline. Deletion, instance/client-generation and abort fences apply. Recovery never prompts, interrupts, updates a session or replays anything automatically.

Validation

Store regressions use isolated in-memory clients and the real stores; mutation stubs fail on any prompt/interrupt/update. Run (the browser condition is required by Solid imports; --test-force-exit only ends test workers):

node --conditions=browser --import tsx --test --test-force-exit packages/ui/src/stores/session-generation-recovery.test.ts packages/ui/src/stores/session-generation-recovery-integration.test.ts packages/ui/src/stores/session-generation-admission.test.ts packages/ui/src/stores/session-native-events.test.ts packages/ui/src/stores/app-session-workspace-hydration.test.ts packages/ui/src/stores/session-request-authority.test.ts

Limits

  • failed is a distinct native outcome; a missing outcome is unknown.
  • Native interruption events set their proven marker. Only authoritative outcome reads settle pending work; an idle event alone never does.
  • The admission epoch lives in window memory, because native outcomes carry no execution ID. Qualify queued-input time.idle behavior with scripts/test-missions-native.mjs; absent a newer boundary, recovery stays pending.