@timurproko/a1 0.2.6-dev.717 → 0.2.6-dev.727
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +13 -2
- package/bin/ui.js +13 -0
- package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
- package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
- package/dist/app/session-shell/session-shell-root.d.ts +2 -1
- package/dist/app/session-shell/session-shell-root.js +13 -6
- package/dist/app/session-shell/session-shell.js +45 -3
- package/dist/app/session-shell/session-viewport-controller.js +33 -21
- package/dist/cli/dispatch.js +5 -3
- package/dist/cli/session-context.d.ts +5 -1
- package/dist/cli/session-context.js +25 -8
- package/dist/composition/owned-ui.d.ts +3 -0
- package/dist/composition/owned-ui.js +66 -6
- package/dist/composition/settings-route-host.js +2 -1
- package/dist/contracts/owned-ui/index.d.ts +4 -2
- package/dist/contracts/owned-ui/index.js +1 -1
- package/dist/contracts/owned-ui/model.d.ts +4 -0
- package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
- package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
- package/dist/contracts/owned-ui/validation.js +7 -0
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/session-context.d.ts +17 -2
- package/dist/features/launch/session-context.js +9 -5
- package/dist/features/owned-ui/settings-app.js +21 -39
- package/dist/features/prompt-suggestions/diagnostics.js +4 -1
- package/dist/foundation/lifecycle/index.d.ts +2 -2
- package/dist/foundation/lifecycle/index.js +1 -1
- package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
- package/dist/foundation/lifecycle/session-repository-context.js +434 -66
- package/dist/foundation/process-containment/index.d.ts +1 -0
- package/dist/foundation/process-containment/index.js +1 -0
- package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
- package/dist/foundation/process-containment/native-process-inspector.js +21 -0
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/components.js +2 -2
- package/dist/integrations/pi/components/index.d.ts +2 -2
- package/dist/integrations/pi/components/index.js +1 -1
- package/dist/integrations/pi/components/modal-frame.js +3 -4
- package/dist/integrations/pi/components/models-dialog.js +5 -5
- package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/share-operation-dialog.js +3 -3
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +8 -7
- package/dist/integrations/pi/components/shell-extension-ui.d.ts +2 -0
- package/dist/integrations/pi/components/shell-extension-ui.js +20 -10
- package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
- package/dist/integrations/pi/components/shell-presenters-transcript.js +10 -10
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/components/skills-dialog.js +3 -3
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
- package/dist/integrations/pi/components/theme.d.ts +9 -0
- package/dist/integrations/pi/components/theme.js +30 -0
- package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +6 -6
- package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +3 -3
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +9 -9
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +2 -2
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +4 -4
- package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +31 -0
- package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
- package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/system-theme.js +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +18 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +207 -10
- package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/session-events.js +10 -2
- package/dist/integrations/pi/engine/transcript-projection.js +2 -1
- package/dist/integrations/pi/startup-public.js +306 -290
- package/dist/integrations/pi/startup-public.manifest.json +289 -265
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -1
- package/dist/integrations/pi/tui-runtime/adapter.js +7 -0
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/product-identity.d.ts +2 -2
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +3 -1
- package/dist/runtime-payload-inventory.json +3092 -2878
- package/dist/ui/components/prompt-input.d.ts +2 -0
- package/dist/ui/components/prompt-input.js +5 -1
- package/dist/ui/components/text-selection.d.ts +1 -1
- package/dist/ui/components/text-selection.js +3 -1
- package/dist/ui/components/theme.d.ts +2 -0
- package/dist/ui/components/transcript-viewport.d.ts +6 -4
- package/dist/ui/components/transcript-viewport.js +94 -16
- package/dist/ui/components/value-menu.d.ts +2 -0
- package/dist/ui/components/value-menu.js +13 -8
- package/dist/ui/settings/declarations.d.ts +26 -14
- package/dist/ui/settings/declarations.js +24 -11
- package/dist/ui/settings/migrations.js +16 -0
- package/docs/architecture/project-structure.md +4 -3
- package/docs/architecture/prompt-suggestions.md +14 -10
- package/docs/local-worktree-cleanup.md +11 -5
- package/docs/openspec-archive-automation.md +6 -5
- package/package.json +3 -3
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Prompt suggestion reliability
|
|
2
2
|
|
|
3
|
-
Bare A1 predicts a short next user input with
|
|
3
|
+
Bare A1 predicts a short next user input with an isolated request using the selected model. A successful eligible response normally starts one pre-settlement request. If that prefetch was missed, settlement starts it; if the first current attempt produces no candidate, one sequential recovery request is allowed. A clear offered action consistent with recent user intent, such as `archive it` after accepted merged work, is preferred over abstaining merely because optional testing was also offered. Required validation, conflicting intent, unresolved choices, and exhausted recovery still allow no suggestion. There is no quoted-text extraction fallback.
|
|
4
4
|
|
|
5
5
|
## Request and editor boundaries
|
|
6
6
|
|
|
7
|
-
The adapter
|
|
7
|
+
The adapter preserves the selected session model's current reasoning level and request options without changing the main thinking setting. Non-reasoning models omit reasoning controls; supported `off` also omits the optional reasoning argument, matching the model runtime's ordinary completion contract. Missing capabilities produce `unavailable`, not a guessed provider option. Provider mapping/clamping remains owned by the pinned model runtime; the diagnostic policy describes the applied request option, not inferred server-side computation.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Each attempt retains the 15-second deadline and uses the same transformed conversation, tools, model, reasoning, budgets, session identity, transport, and payload hook. The controller never overlaps attempts or switches models. `empty`, `rejected`, `provider-failure`, `unavailable`, or timeout can start one retry after settlement; cancellation and stale identity cannot. A provider that ignores abort cannot revive its retired attempt.
|
|
10
|
+
|
|
11
|
+
A timely candidate remains private until matching settlement. A candidate blocked only by temporary readiness, focus, autocomplete, or prompt mode is retained and presented when the same editor becomes eligible. Ghost text is not editor content, approval, or a submission: Tab accepts it into the editor, and Enter must be pressed separately to submit it. Typing aborts pending generation but keeps a delivered suggestion: the ghost text is hidden while the editor holds a draft and reappears when the draft is cleared. Submission, session/model replacement, continuation, interruption, or disabling suggestions invalidates unaccepted work. `a1 pi` does not install this feature.
|
|
10
12
|
|
|
11
13
|
## Opt-in local diagnostics
|
|
12
14
|
|
|
@@ -26,12 +28,12 @@ While that session is running, inspect the selected JSON file using a local edit
|
|
|
26
28
|
node -e 'const fs=require("node:fs"); console.table(JSON.parse(fs.readFileSync(process.argv[1],"utf8")).records)' .artifacts/suggestion-diagnostics.json
|
|
27
29
|
```
|
|
28
30
|
|
|
29
|
-
The `prompt-suggestion-diagnostics-v1` snapshot contains at most 128 metadata records and 64 KiB. Capture is off by default. Records include process-local session/run/response/request numbers, bounded provider/model identifiers, applied reasoning policy, elapsed milliseconds, event, and optional reason. They exclude conversation/candidate text, tool data, raw errors, credentials, and session/worktree paths. There is no upload. Older records are evicted, so a retained terminal event can outlive its evicted start event. `request: 0` means no request was started for that decision.
|
|
31
|
+
The `prompt-suggestion-diagnostics-v1` snapshot contains at most 128 metadata records and 64 KiB. Capture is off by default. Records include process-local session/run/response/request numbers, bounded attempt number and trigger (`prefetch`, `settlement`, or `retry`), provider/model identifiers, applied reasoning policy, elapsed milliseconds, event, and optional reason. They exclude conversation/candidate text, tool data, raw errors, credentials, and session/worktree paths. There is no upload. Older records are evicted, so a retained terminal event can outlive its evicted start event. `request: 0` means no request was started for that decision.
|
|
30
32
|
|
|
31
33
|
| Event | Meaning |
|
|
32
34
|
| --- | --- |
|
|
33
35
|
| `skipped` | No request started; inspect `reason`. |
|
|
34
|
-
| `started` | One generator request was initiated;
|
|
36
|
+
| `started` | One generator request was initiated; inspect `attempt` and `trigger`. Reasoning may be `unavailable` for an injected generator without policy metadata. |
|
|
35
37
|
| `displayed` | A current candidate was shown after settlement. |
|
|
36
38
|
| `empty` | The provider returned no text; this does not reveal the model's private reason for abstaining. |
|
|
37
39
|
| `rejected` | Returned content violated the candidate contract, contained tool calls, was truncated, or had invalid formatting/voice. |
|
|
@@ -40,7 +42,9 @@ The `prompt-suggestion-diagnostics-v1` snapshot contains at most 128 metadata re
|
|
|
40
42
|
| `timeout` | The controller's 15-second deadline expired. |
|
|
41
43
|
| `cancelled` | Work was invalidated or aborted, including typing or continuation. |
|
|
42
44
|
| `stale-result` | A result or settlement identity did not match its request. |
|
|
43
|
-
| `presentation-blocked` | A valid candidate
|
|
45
|
+
| `presentation-blocked` | A valid candidate met a permanent presentation blocker; inspect `reason`. |
|
|
46
|
+
| `presentation-deferred` | A valid candidate is retained behind temporary readiness, focus, autocomplete, or prompt-mode state. |
|
|
47
|
+
| `retry-exhausted` | Both bounded attempts ended without a candidate. |
|
|
44
48
|
| `late-result-discarded` | A retired request eventually resolved/rejected; this is not a second terminal outcome or request. |
|
|
45
49
|
|
|
46
50
|
Eligibility/presentation reasons include `disabled`, `disposed`, `early-conversation`, `no-model`, `failed-response`, `incomplete-response`, `tool-continuation`, `replacement-input`, `modal`, `draft`, `not-ready`, `not-focused`, `autocomplete`, `prompt-mode`, and `stale-identity`. `ineligible` and `presentation-unavailable` cover injected ports without finer metadata. A missing suggestion alone is never evidence of timeout or intentional model abstention.
|
|
@@ -51,10 +55,10 @@ To disable capture, omit/unset `A1_SUGGESTION_DIAGNOSTICS` before the next launc
|
|
|
51
55
|
|
|
52
56
|
## Verification and evidence limits
|
|
53
57
|
|
|
54
|
-
The focused tests cover
|
|
58
|
+
The focused tests cover settlement fallback, one-request success, bounded retry/exhaustion, timeout and late-result races, deferred presentation, request parity, editor acceptance, and local privacy/bounds:
|
|
55
59
|
|
|
56
60
|
```sh
|
|
57
|
-
npx vitest run test/app/session-shell/prompt-suggestion-controller.test.ts test/integrations/pi/engine/adapter.test.ts test/features/prompt-suggestions/diagnostics.test.ts test/contracts/owned-ui/contracts.test.ts test/app/session-shell/session-shell.test.ts
|
|
61
|
+
npx vitest run test/app/session-shell/prompt-suggestion-controller.test.ts test/app/session-shell/session-shell-suggestions.test.ts test/integrations/pi/engine/adapter.test.ts test/integrations/pi/engine/session-events.test.ts test/features/prompt-suggestions/diagnostics.test.ts test/contracts/owned-ui/contracts.test.ts test/app/session-shell/session-shell.test.ts
|
|
58
62
|
```
|
|
59
63
|
|
|
60
64
|
A separate opt-in probe uses the profile's saved model/authentication with a scratch cwd, in-memory sessions/settings, disabled extensions/skills/prompts, and no tools. It performs five original-policy predictions, five revised-policy predictions, and one required-testing counterexample. This makes **11 provider requests** and can consume quota. Run only with explicit authorization:
|
|
@@ -63,6 +67,6 @@ A separate opt-in probe uses the profile's saved model/authentication with a scr
|
|
|
63
67
|
RUN_PROMPT_SUGGESTION_PROVIDER_TEST=1 PROMPT_SUGGESTION_AGENT_DIR="C:/path/to/agent-profile" npx vitest run test/integrations/pi/engine/prompt-suggestion-provider.integration.test.ts
|
|
64
68
|
```
|
|
65
69
|
|
|
66
|
-
The probe reports outcome/latency summaries and archival-candidate counts, not raw text. It requires at least one revised archival continuation and rejects an archival continuation in the required-testing case. Five samples are a smoke comparison, not a statistical reliability guarantee.
|
|
70
|
+
The probe reports outcome/latency summaries and archival-candidate counts, not raw text. It requires at least one revised archival continuation and rejects an archival continuation in the required-testing case. Five samples are a smoke comparison, not a statistical reliability guarantee. It tests prompt quality, not settlement/retry lifecycle correctness; deterministic fault injection owns recovery acceptance. Missing credentials or model availability therefore do not block lifecycle evidence.
|
|
67
71
|
|
|
68
|
-
For manual review,
|
|
72
|
+
For manual review, repeat ordinary completed-work conversations with the editor untouched and diagnostics enabled. A normal candidate should show one `prefetch` request. A recovered miss should show either a first `settlement` request or a second `retry` request, followed by `displayed`; two failed attempts should end with `retry-exhausted`. Check that temporary focus/autocomplete blocking records `presentation-deferred` and reveals the same candidate after eligibility returns. Check Tab/Enter separately, then repeat with typing cancellation and suggestions disabled. Real latency, model abstention, and existing context-reconstruction limitations can still exhaust both attempts and leave the editor empty.
|
|
@@ -22,7 +22,13 @@ Every delivery session then starts, before it creates a worktree, with one bound
|
|
|
22
22
|
node scripts/governance/local-worktree-cleanup.mjs sweep --repo D:/Git/a1
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
`sweep` evaluates every released registration in one pass under the queue limits (100 registrations, 500 remote requests, a durable round-robin cursor) with a 180-second elapsed budget, since each merged candidate costs three evidence loads, and completes each candidate whose PR is verified merged using exactly the `complete` safeguards. It needs no `enable` and starts no process: its authority is each candidate's release. A candidate whose PR is open, draft, or not yet finalized reports `pending`; a candidate whose PR closed without merge reports `awaiting-discard` and is never touched; blockers report their exact reason. An old stop sentinel does not prevent a sweep, but `disable` run while a sweep is executing stops it before its next destructive step. If another session
|
|
25
|
+
`sweep` evaluates every released registration in one pass under the queue limits (100 registrations, 500 remote requests, a durable round-robin cursor) with a 180-second elapsed budget, since each merged candidate costs three evidence loads, and completes each candidate whose PR is verified merged using exactly the `complete` safeguards. It needs no `enable` and starts no process: its authority is each candidate's release. A candidate whose PR is open, draft, or not yet finalized reports `pending`; a candidate whose PR closed without merge reports `awaiting-discard` and is never touched; blockers report their exact reason. An old stop sentinel does not prevent a sweep, but `disable` run while a sweep is executing stops it before its next destructive step. If another session is cleaning the same path or ref, sweep reports that candidate `deferred (resource-busy)` and continues with disjoint registrations. The JSON report carries a `lines` array with one relayable line per candidate and pruned branch, for example `#458 close-absent-and-skewed-cleanup: removed [worktree-removed, local-ref-removed]`. Pending, deferred, or blocked results never delay another candidate or the new delivery.
|
|
26
|
+
|
|
27
|
+
### Concurrent cleanup scopes
|
|
28
|
+
|
|
29
|
+
Independent `complete`, `discard`, `retire-redundant`, sweep, and enabled queue operations may run at the same time when their canonical worktree paths and topic refs are disjoint. Long remote evidence reads, content traversal, Windows retry waits, generated-content purge, and non-force removal hold only the exact path/ref resource locks. The same candidate remains exclusive across ownership, hand-off, cleanup, empty-directory recovery, and branch pruning; a competing command receives `resource-busy` rather than racing the journal.
|
|
30
|
+
|
|
31
|
+
The existing `mutation.lock` now protects only brief atomic `state.json` transactions and remains at the same path so an older cleanup process already running during an upgrade is still honored. State-lock overlap is retried for a bounded interval. Fetches that update `refs/remotes/origin/develop` and exact local-ref changes coordinate only that shared ref operation; they do not serialize the surrounding candidate work. Every destructive boundary still repeats its existing evidence, identity, content, and compare-and-delete checks.
|
|
26
32
|
|
|
27
33
|
### Standalone documentation evidence
|
|
28
34
|
|
|
@@ -104,7 +110,7 @@ node scripts/governance/local-worktree-cleanup.mjs retire-redundant \
|
|
|
104
110
|
--confirm-redundant
|
|
105
111
|
```
|
|
106
112
|
|
|
107
|
-
The command requires an exact canonical, unlocked, non-current Git worktree on a normal topic branch; no cleanup registration; no pull request in any state for that branch; no remote topic ref; no unique commit beyond freshly fetched `origin/develop`; and no staged, unstaged, untracked, hidden-index, unknown ignored, nested-repository, submodule, or other protected content. Central-policy generated content is inspected and purged normally. Under
|
|
113
|
+
The command requires an exact canonical, unlocked, non-current Git worktree on a normal topic branch; no cleanup registration; no pull request in any state for that branch; no remote topic ref; no unique commit beyond freshly fetched `origin/develop`; and no staged, unstaged, untracked, hidden-index, unknown ignored, nested-repository, submodule, or other protected content. Central-policy generated content is inspected and purged normally. Under its exact path/ref resource locks, with brief atomic state transactions, the command revalidates every gate, journals the captured filesystem/HEAD/ref identity, removes the checkout non-forcibly, and compare-and-deletes only the unchanged local ref. It never removes a remote ref or enables broad cleanup authority.
|
|
108
114
|
|
|
109
115
|
A repeated exact confirmed invocation resumes a partial journal or reports `already-retired`. A branch with any pull request remains owned by `complete`/sweep or explicit closed-unmerged `discard`; an open, dirty, remote-backed, locally advanced, registered, locked, detached, protected, replaced, or ambiguous checkout remains retained. Agents never substitute manual deletion when this command blocks.
|
|
110
116
|
|
|
@@ -184,7 +190,7 @@ Before resuming a released worktree, acquire it:
|
|
|
184
190
|
node scripts/governance/local-worktree-cleanup.mjs claim --repo D:/Git/a1 --id REGISTRATION_ID --generation CURRENT_GENERATION
|
|
185
191
|
```
|
|
186
192
|
|
|
187
|
-
Use a private token for the new session. Claim, release, and cleanup share
|
|
193
|
+
Use a private token for the new session. Claim, release, hand-off, and cleanup share the candidate's exact path/ref resource locks and commit their state changes through brief repository-state transactions. A successful claim prevents deletion until the new owner releases it. A deleting or completed candidate cannot be claimed. A path reused after completed cleanup requires a new explicit `register` operation.
|
|
188
194
|
|
|
189
195
|
A session crash does not release ownership. After separately confirming that the owner and all related processes have stopped, an explicit recovery claims it for review:
|
|
190
196
|
|
|
@@ -192,7 +198,7 @@ A session crash does not release ownership. After separately confirming that the
|
|
|
192
198
|
node scripts/governance/local-worktree-cleanup.mjs recover --repo D:/Git/a1 --id REGISTRATION_ID --generation CURRENT_GENERATION --confirm-stopped
|
|
193
199
|
```
|
|
194
200
|
|
|
195
|
-
Recovery never releases or deletes. The generation must still match. A Git worktree lock remains a veto. A leftover
|
|
201
|
+
Recovery never releases or deletes. The generation must still match. A Git worktree lock remains a veto. A leftover repository-state or scoped resource lock from a killed cleanup process is evicted only on proof: the holder writes its PID and refreshes a heartbeat in the lock every five seconds, and a later operation needing that scope evicts the lock only when that heartbeat (or, for an old lock without one, the file's modification time) is more than two minutes old and the PID no longer exists. A live, unprobeable, or own PID keeps the lock, as does a fresh or unreadable-but-fresh file, and the affected operation reports `mutation-busy` for legacy/state contention or `resource-busy` for a candidate/ref scope. Each eviction is journaled as `lock-evicted-<time>-<id>.json` beside `state.json` with the evicted record; it releases no ownership and advances no journal step. A live scoped holder delays only commands needing that same path or ref.
|
|
196
202
|
|
|
197
203
|
## Outcomes and interruption handling
|
|
198
204
|
|
|
@@ -230,7 +236,7 @@ Stop watch with Ctrl+C, or request immediate stop authority from another termina
|
|
|
230
236
|
node scripts/governance/local-worktree-cleanup.mjs disable --repo D:/Git/a1
|
|
231
237
|
```
|
|
232
238
|
|
|
233
|
-
Disable writes a stop sentinel without waiting for a busy
|
|
239
|
+
Disable writes a stop sentinel without waiting for a busy state or resource lock. The worker checks it before each destructive step; an already executing Git operation cannot be undone. No later deletion starts while disabled. State and partial journals remain available for review and future explicit enablement.
|
|
234
240
|
|
|
235
241
|
Dependency-free focused fixtures (temporary repositories only, no live PR mutation or watcher activation):
|
|
236
242
|
|
|
@@ -118,14 +118,15 @@ After finalization, replace it with the exact emitted paths:
|
|
|
118
118
|
"version": 3,
|
|
119
119
|
"change": "example-change",
|
|
120
120
|
"archive": "openspec/changes/archive/2026-09-15-example-change/",
|
|
121
|
-
"acceptanceManifest": "openspec/changes/archive/2026-09-15-example-change/acceptance.md"
|
|
121
|
+
"acceptanceManifest": "openspec/changes/archive/2026-09-15-example-change/acceptance.md",
|
|
122
|
+
"finalizedHead": "0123456789abcdef0123456789abcdef01234567"
|
|
122
123
|
}
|
|
123
124
|
```
|
|
124
125
|
|
|
125
126
|
</details>
|
|
126
127
|
````
|
|
127
128
|
|
|
128
|
-
Version 3 forbids `specificationPr` and `archivePreparationTasks`.
|
|
129
|
+
Version 3 forbids `specificationPr` and `archivePreparationTasks`. The archive path, acceptance-manifest path, and exact `finalizedHead` binding must be absent for a draft or mutually consistent for a finalized candidate. Existing finalized records without the head binding are readable only for trusted normalization and cannot satisfy current-head validation. Unknown fields, duplicate fences/JSON keys, unsafe paths, mismatched dates/change identities, malformed SHAs, and partial finalization fail closed.
|
|
129
130
|
|
|
130
131
|
## Acceptance list
|
|
131
132
|
|
|
@@ -152,7 +153,7 @@ The `OpenSpec finalization` workflow (`.github/workflows/openspec-finalization.y
|
|
|
152
153
|
- **Finalized but drifted:** a later commit edited the archived tasks, evidence, design, or deltas, or the acceptance list changed. Finalization reruns from the archived form under the same archive date; one `docs(openspec): refinalize <change>` commit replaces the manifest and resynchronized specs.
|
|
153
154
|
- **Behind `develop`:** a restore commit returns the archive to its active form with the merge-base's spec bytes, a merge of `develop` follows, and finalization runs against the new tip. A merge conflict outside `openspec/` stops the run with `finalization-merge-conflict`; rebase or merge `develop` yourself and push.
|
|
154
155
|
|
|
155
|
-
The commit is pushed with a lease on the head the run read, so a developer push in between makes the run report `retry` and the next event finishes the work. Only after the push does the workflow `PATCH` the body fence, and only when the body
|
|
156
|
+
The commit is pushed with a lease on the head the run read, so a developer push in between makes the run report `retry` and the next event finishes the work. Only after the push does the workflow `PATCH` the body fence with `finalizedHead` equal to that exact commit, and only when both the body and PR head still match the operation's expected values. The guaranteed head-binding change triggers native `pull_request: edited` validation even when a re-finalization reuses the same archive paths. The workflow's own body edit triggers further runs that report `already-finalized`; an intermediate run with a missing or stale binding defers before product suites and emits no protected aggregate. Every pushed commit is either a merge of the exact `develop` tip or confined to the change's active path, its archive path, and its declared canonical specs.
|
|
156
157
|
|
|
157
158
|
Because the branch gains commits from the archive App, pull before pushing. A rebase that drops them is harmless: the next push is reconciled from whatever the head contains. Do not revert a finalization commit to make a fix; push the fix and let the workflow re-finalize. When the workflow fails, its summary names the finalization code (`tasks-incomplete`, `acceptance-*`, `delivery-known-gaps`, `openspec-operation`, `finalization-merge-conflict`, ...), nothing is pushed, and `Finalized delivery validation` on the unfinalized head reports that automated finalization is pending.
|
|
158
159
|
|
|
@@ -194,7 +195,7 @@ gh pr edit <pr> --body-file .artifacts/agent/openspec-pr-body.md
|
|
|
194
195
|
|
|
195
196
|
Use repeated `--known-gap "exact disposition"` only for an actually reviewed explicit gap. Gaps remain visible in the committed manifest and do not become test results. Missing or ambiguous disposition blocks finalization.
|
|
196
197
|
|
|
197
|
-
The operation validates the active change strictly, requires complete substantive tasks, runs the pinned OpenSpec archive/synchronization engine in isolation, verifies the resulting canonical specs, retains every archive artifact, computes deterministic content digests, writes `acceptance.md`, and applies only the allowed OpenSpec diff. Repeating
|
|
198
|
+
The operation validates the active change strictly, requires complete substantive tasks, runs the pinned OpenSpec archive/synchronization engine in isolation, verifies the resulting canonical specs, retains every archive artifact, computes deterministic content digests, writes `acceptance.md`, and applies only the allowed OpenSpec diff. Local preparation cannot know the eventual commit SHA, so trusted finalization normalizes the body with `finalizedHead` after the commit is present on the branch. Repeating the trusted operation against identical finalized inputs and a matching head binding is verification-only and byte-stable.
|
|
198
199
|
|
|
199
200
|
Before a first finalization, canonical specs must still equal the selected target. On an already finalized head the command re-finalizes from the archived form: it resets the synchronized specs to the target's bytes, reapplies the deltas, and rewrites the manifest under the same archive path, reporting `refinalized` (or `would-refinalize` without `--write`). If `develop` advances, merge or rebase onto it and rerun; the archive engine, not a hand edit, must produce the synchronized spec and archive copy.
|
|
200
201
|
|
|
@@ -217,7 +218,7 @@ Unavailable, stale, automatic, unauthorized, conflicting, or contradictory prove
|
|
|
217
218
|
|
|
218
219
|
Normal Development CI remains complete for the implementation once its reviewable candidate exists. An archive-shaped final diff does not select documentation-only validation because the authoritative version-3 association remains implementation-bound. Base-controlled readiness defers a ready head that still holds the active change without running test suites or emitting `Development validation required`. The finalization workflow pushes the finalized head and updates its implementation fence; that update starts one complete selected validation, while PR-level concurrency cancels any superseded eligible run.
|
|
219
220
|
|
|
220
|
-
`
|
|
221
|
+
The trusted post-push `finalizedHead` body edit reruns required CI as a native pull-request event. The ordinary finalized phase-free run exposes every selected lane and the stable protected aggregate on the PR checks page. Manual `workflow_dispatch` remains branch diagnostic evidence: it lacks authoritative PR payload and cannot replace finalized-delivery, acceptance, selection, visibility, or protected aggregate evidence. Documentation auto-merge's trusted owner also reevaluates lifecycle association. It preserves only an authorized human arm for the exact finalized version-3 head, never creates or exercises that arm, and disables stale, automated, malformed, draft, edited, or otherwise ineligible arms. Every publication entry point explicitly refuses version 3.
|
|
221
222
|
|
|
222
223
|
The OpenSpec archive workflow remains default-branch trusted. For version 3 it uses read-only contents, PR, and Actions access to report the integrated result; App credentials are unnecessary and are not minted for post-merge verification. For legacy candidates it retains its existing scoped App publication behavior. The OpenSpec finalization workflow is the one version-3 user of the archive App: it mints a short-lived installation token with `contents: write` and `pull_requests: write`, pushes only to the candidate's own branch under a lease, edits only the body fence, and revokes the token when the run ends.
|
|
223
224
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurproko/a1",
|
|
3
|
-
"version": "0.2.6-dev.
|
|
3
|
+
"version": "0.2.6-dev.727",
|
|
4
4
|
"description": "Standalone terminal workspace for supervised native and managed agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"privateLaunchContract": "neutral-launch-v1",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"typecheck:bin": "tsgo -p tsconfig.bin.json"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@earendil-works/pi-coding-agent": "1.0
|
|
69
|
-
"@earendil-works/pi-tui": "1.0
|
|
68
|
+
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
69
|
+
"@earendil-works/pi-tui": "1.1.0",
|
|
70
70
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
71
71
|
"chalk": "5.6.2",
|
|
72
72
|
"cross-spawn": "7.0.6",
|