@timurproko/a1 0.2.7-dev.792 → 0.2.7-dev.801

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.
Files changed (120) hide show
  1. package/dist/app/session-shell/clipboard-diagnostics.js +1 -1
  2. package/dist/app/session-shell/response-copy-helper.js +21 -6
  3. package/dist/app/session-shell/response-copy-protocol.d.ts +1 -1
  4. package/dist/app/session-shell/response-copy-transport.d.ts +3 -6
  5. package/dist/app/session-shell/response-copy-transport.js +60 -17
  6. package/dist/app/session-shell/session-shell-root.d.ts +2 -0
  7. package/dist/app/session-shell/session-shell-root.js +6 -1
  8. package/dist/app/session-shell/session-shell.d.ts +1 -0
  9. package/dist/app/session-shell/session-shell.js +22 -19
  10. package/dist/app/session-shell/shell-host.js +11 -0
  11. package/dist/cli/tabs.js +1 -1
  12. package/dist/composition/owned-ui.d.ts +1 -0
  13. package/dist/composition/owned-ui.js +16 -3
  14. package/dist/features/resident-tab/shortcut-declarations.d.ts +1 -1
  15. package/dist/features/resident-tab/shortcut-declarations.js +1 -0
  16. package/dist/foundation/launch-guardian/exit-watcher.d.ts +14 -0
  17. package/dist/foundation/launch-guardian/exit-watcher.js +94 -0
  18. package/dist/foundation/launch-guardian/main.d.ts +2 -1
  19. package/dist/foundation/launch-guardian/main.js +58 -6
  20. package/dist/foundation/process-containment/{native-guardian-containment.d.ts → addon-containment.d.ts} +7 -5
  21. package/dist/foundation/process-containment/addon-containment.js +139 -0
  22. package/dist/foundation/process-containment/addon-process-inspector.d.ts +11 -0
  23. package/dist/foundation/process-containment/addon-process-inspector.js +36 -0
  24. package/dist/foundation/process-containment/addon.d.ts +42 -0
  25. package/dist/foundation/process-containment/addon.js +57 -0
  26. package/dist/foundation/process-containment/artifact.d.ts +1 -1
  27. package/dist/foundation/process-containment/artifact.js +6 -5
  28. package/dist/foundation/process-containment/contracts.d.ts +2 -0
  29. package/dist/foundation/process-containment/index.d.ts +4 -4
  30. package/dist/foundation/process-containment/index.js +3 -3
  31. package/dist/foundation/process-containment/native-process-inspector.d.ts +2 -1
  32. package/dist/foundation/process-containment/native-process-inspector.js +10 -10
  33. package/dist/foundation/release/bootstrap.js +53 -16
  34. package/dist/foundation/release/index.d.ts +1 -1
  35. package/dist/foundation/release/index.js +1 -1
  36. package/dist/foundation/release/release-store.d.ts +12 -0
  37. package/dist/foundation/release/release-store.js +124 -2
  38. package/dist/foundation/resident-tabs/bounded-host-command.d.ts +3 -1
  39. package/dist/foundation/resident-tabs/bounded-host-command.js +6 -2
  40. package/dist/foundation/resident-tabs/bridge-client.d.ts +2 -0
  41. package/dist/foundation/resident-tabs/bridge-client.js +13 -0
  42. package/dist/foundation/resident-tabs/doctor.d.ts +0 -1
  43. package/dist/foundation/resident-tabs/doctor.js +4 -4
  44. package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +7 -2
  45. package/dist/foundation/resident-tabs/ensure-terminal-host.js +15 -11
  46. package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
  47. package/dist/foundation/resident-tabs/fixture-control.js +35 -0
  48. package/dist/foundation/resident-tabs/host-entry.d.ts +1 -0
  49. package/dist/foundation/resident-tabs/host-entry.js +17 -0
  50. package/dist/foundation/resident-tabs/index.d.ts +2 -2
  51. package/dist/foundation/resident-tabs/index.js +1 -1
  52. package/dist/foundation/resident-tabs/maintenance.d.ts +5 -4
  53. package/dist/foundation/resident-tabs/maintenance.js +32 -17
  54. package/dist/foundation/resident-tabs/progress-observation.d.ts +7 -0
  55. package/dist/foundation/resident-tabs/progress-observation.js +119 -0
  56. package/dist/foundation/resident-tabs/release-holds.d.ts +3 -2
  57. package/dist/foundation/resident-tabs/release-holds.js +16 -7
  58. package/dist/foundation/resident-tabs/settings.d.ts +0 -1
  59. package/dist/foundation/resident-tabs/settings.js +1 -7
  60. package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +11 -15
  61. package/dist/foundation/resident-tabs/terminal-host-artifact.js +57 -32
  62. package/dist/foundation/session-writer-lock/index.d.ts +1 -3
  63. package/dist/foundation/session-writer-lock/index.js +8 -6
  64. package/dist/integrations/pi/components/shell-editor-autocomplete.js +2 -1
  65. package/dist/integrations/pi/components/shell-shared-facade.d.ts +2 -0
  66. package/dist/integrations/pi/engine/session-runtime.js +5 -2
  67. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +11 -0
  68. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +30 -1
  69. package/dist/native/darwin-arm64/manifest.json +8 -6
  70. package/dist/native/darwin-arm64/process-guardian.node +0 -0
  71. package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +1 -1
  72. package/dist/native/darwin-arm64/terminal-host.manifest.json +14 -13
  73. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  74. package/dist/native/darwin-x64/manifest.json +9 -7
  75. package/dist/native/darwin-x64/process-guardian.node +0 -0
  76. package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +1 -1
  77. package/dist/native/darwin-x64/terminal-host.manifest.json +15 -14
  78. package/dist/native/darwin-x64/terminal-host.node +0 -0
  79. package/dist/native/linux-x64/manifest.json +8 -6
  80. package/dist/native/linux-x64/process-guardian.node +0 -0
  81. package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +1 -1
  82. package/dist/native/linux-x64/terminal-host.manifest.json +14 -13
  83. package/dist/native/linux-x64/terminal-host.node +0 -0
  84. package/dist/native/win32-x64/manifest.json +8 -6
  85. package/dist/native/win32-x64/process-guardian.node +0 -0
  86. package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +1 -1
  87. package/dist/native/win32-x64/terminal-host.manifest.json +14 -13
  88. package/dist/native/win32-x64/terminal-host.node +0 -0
  89. package/dist/product-identity.d.ts +3 -3
  90. package/dist/product-identity.js +3 -3
  91. package/dist/product-identity.json +9 -2
  92. package/dist/runtime-payload-inventory.json +1 -0
  93. package/dist/ui/settings/declarations.d.ts +0 -12
  94. package/dist/ui/settings/declarations.js +0 -10
  95. package/docs/architecture/boundaries.md +10 -9
  96. package/docs/architecture/process-guardian-provenance.md +17 -11
  97. package/docs/architecture/resident-tabs.md +46 -40
  98. package/docs/architecture/terminal-host-provenance.md +5 -3
  99. package/docs/architecture/toolchain.md +8 -6
  100. package/docs/ci-release-runbook.md +1 -1
  101. package/docs/openspec-archive-automation.md +23 -9
  102. package/docs/validation.md +6 -2
  103. package/package.json +6 -3
  104. package/dist/foundation/process-containment/darwin-process-inspector.d.ts +0 -5
  105. package/dist/foundation/process-containment/darwin-process-inspector.js +0 -7
  106. package/dist/foundation/process-containment/native-guardian-containment.js +0 -152
  107. package/dist/foundation/process-containment/windows-process-inspector.d.ts +0 -19
  108. package/dist/foundation/process-containment/windows-process-inspector.js +0 -56
  109. package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
  110. package/dist/native/darwin-arm64/process-guardian +0 -0
  111. package/dist/native/darwin-arm64/terminal-host +0 -0
  112. package/dist/native/darwin-x64/a1_session_lock.node +0 -0
  113. package/dist/native/darwin-x64/process-guardian +0 -0
  114. package/dist/native/darwin-x64/terminal-host +0 -0
  115. package/dist/native/linux-x64/a1_session_lock.node +0 -0
  116. package/dist/native/linux-x64/process-guardian +0 -0
  117. package/dist/native/linux-x64/terminal-host +0 -0
  118. package/dist/native/win32-x64/a1_session_lock.node +0 -0
  119. package/dist/native/win32-x64/process-guardian.exe +0 -0
  120. package/dist/native/win32-x64/terminal-host.exe +0 -0
@@ -1,6 +1,6 @@
1
1
  # Atomic OpenSpec delivery and legacy archival
2
2
 
3
- New OpenSpec deliveries use one ordinary development pull request from draft planning through implementation, validation, acceptance, specification synchronization, and archival. An authorized maintainer chooses integration by manually merging the exact validated head or personally enabling GitHub native auto-merge for that unchanged head. Agents, Apps, bots, merge queue, and repository automation never arm or invoke implementation integration and never create a version-3 acceptance or archive follow-up PR.
3
+ New OpenSpec deliveries use one ordinary development pull request from draft planning through implementation, validation, acceptance, specification synchronization, and archival. An authorized maintainer chooses integration by manually merging the exact validated head, personally enabling GitHub native auto-merge for that unchanged head, or explicitly asking the active agent to merge the identified currently eligible head. Agents never infer or independently choose integration; Apps, bots, merge queue, workflows, and repository automation receive no implementation authority, and no version-3 acceptance or archive follow-up PR is created.
4
4
 
5
5
  Unrelated standalone documentation remains separate: a non-draft unassociated PR changing only `openspec/**`, `docs/**`, and/or root `README.md` retains the existing CI-gated automatic route. A new active change, implementation association, malformed lifecycle data, or mixed path remains outside documentation-owned integration. Before finalization or without valid human provenance, any arm is disabled; a finalized version-3 human arm remains a separate maintainer-owned route.
6
6
 
@@ -8,15 +8,29 @@ Version-1 and version-2 deliveries and their existing comments, acceptance PRs,
8
8
 
9
9
  ## Version-3 lifecycle
10
10
 
11
- 1. **Draft plan:** create one normally named branch/PR such as `feature/...`, `fix/...`, or `chore/...`. Start the body with `## Proposal`, use it for one or two sentences of intent, and follow it with two to ten unchecked, outcome-sized task items under `## Implementation`. Each item names a delivered code outcome. Omit generic process tasks; run, verify, validate, evidence, or manual-test items; quoted phase lines; and routine validation command lists, and keep machine linkage under final collapsed `Automation`. Keep it draft and include only planning artifacts until the maintainer approves the plan and explicitly requests implementation.
11
+ 1. **Draft plan:** create one normally named branch/PR such as `feature/...`, `fix/...`, or `chore/...`. Start the body with `## Proposal`, use it for one or two sentences of intent, and follow it with one or more unchecked, outcome-sized task items under `## Implementation`, with no fixed maximum. Each item names a delivered code outcome. Omit generic process tasks; run, verify, validate, evidence, or manual-test items; quoted phase lines; and routine validation command lists, and keep machine linkage under final collapsed `Automation`. Keep it draft and include only planning artifacts until the maintainer approves the plan and explicitly requests implementation.
12
12
  2. **Same-PR implementation:** continue after explicit approval in the same worktree, branch, history, draft PR, and phase-free body. Check an Implementation item as soon as its associated code and tests are written and its detailed task bookkeeping is complete; an ordinary progress edit changes only `[ ]` to `[x]` and is not deferred until handoff. Adding, removing, reordering, or rewriting an item is a scope refinement requiring explicit approval and coherent planning updates, with affected scope left unchecked. Reconcile approved refinements before corresponding code edits.
13
13
  3. **Complete implementation:** finish the code and its tests, substantive tasks, and explicit known-gap disposition. CI runs those tests after readiness; its success is objective evidence, not acceptance, and GitHub check counts are not Implementation task progress. Manual validation is the maintainer's optional choice before integrating and never blocks a checkbox, finalization, or merge.
14
14
  4. **Plain acceptance list:** before checking the final item, keep the body phase-free and add final `## Acceptance` with one to ten concise implementation-specific behavior-and-result bullets. Do not use checkboxes, generic review/CI/approval/archive statements, angle-bracket placeholders or HTML, URLs, mentions, or automated-test inventory.
15
15
  5. **Automatic readiness and finalization:** reconcile and push current `origin/develop`, run the [delivery body check](#delivery-body-check) on the intended final body, then check the final item. That checkbox update completes the agent-owned implementation job; agents never mark implementation PRs ready themselves. Trusted automation revalidates the exact fully complete version-3 task-list snapshot and all pre-finalization inputs, marks the PR ready, and then conservatively synchronizes all deltas, moves the active change into its dated archive, stages the conditional acceptance manifest, commits that to the same branch with the archive App identity, and writes the emitted paths into the body's implementation fence. It never checks tasks or infers completion. Running the [finalization command](#finalization-command) locally first is optional and yields the same bytes.
16
16
  6. **Validate:** one normal exact-head workflow validates the finalized head: implementation, synchronized specs, archive, manifest, tasks/evidence, exact PR-body list, and every selected product/governance scope before emitting the stable protected aggregate. A new commit or acceptance-list change re-finalizes automatically when needed and requires full renewed validation; no lifecycle body edit or second workflow run is required.
17
- 7. **Maintainer integration accepts:** after reviewing the finalized candidate, an authorized human either manually merges the exact validated head after the stable protected aggregate succeeds or personally enables GitHub native auto-merge for that unchanged head so protected integration waits for the aggregate. That human action means the listed scenarios are accepted. Agents, Apps, bots, merge queue, automation-owned implementation arms, and documentation integration remain forbidden. A changed head, acceptance list, or finalization invalidates the earlier arm and requires the maintainer to choose again.
17
+ 7. **Maintainer integration accepts:** after reviewing the finalized candidate, an authorized human manually merges the exact validated head, personally enables GitHub native auto-merge for that unchanged head, or explicitly asks the active agent to merge that identified head while it is currently eligible. The agent route re-reads authoritative state, requires the exact finalized head and acceptance list, current `develop`, successful `Development validation required`, positive mergeability, and the maintainer's authenticated human `User`, then issues one protected squash merge with expected-head enforcement. It never waits, arms auto-merge, retries later, uses automation credentials or merge queue, or bypasses protection. Each route means the listed scenarios are accepted. A candidate change invalidates the decision and requires the maintainer to choose again.
18
18
  8. **Verify and clean:** trusted post-merge policy derives `Archived` and reports `accepted-and-archived` from committed bytes and immutable GitHub provenance without editing the accepted PR body. It publishes no lifecycle branch or PR. Shared exact-head remote cleanup may delete the unchanged topic ref; local cleanup remains separately ownership-controlled: the agent parks the worktree with `handoff` at step 7, and the next session's `sweep` removes it once the merge, archive, and remote-ref evidence verify (see [local cleanup](local-worktree-cleanup.md)).
19
19
 
20
+ ### Maintainer-requested agent merge
21
+
22
+ The permission is one-shot and candidate-bound. A same-session instruction such as “merge it” is sufficient only when the conversation identifies one handed-off PR and head unambiguously; implementation approval, green CI, an earlier request, or a standing preference is not merge authority. If the PR is not currently eligible, report the blocker and stop. Do not poll, watch, arm native auto-merge, or retain the instruction for later.
23
+
24
+ Immediately before mutation, refresh the PR and authenticated principal. Require an open non-draft same-repository PR into `develop`, the requested exact finalized head and acceptance list, `MERGEABLE`/`CLEAN` state, successful `Development validation required` for that head, and a human `User` with write, maintain, or admin repository permission. Then use the ordinary protected route with no `--admin` or `--auto`:
25
+
26
+ ```bash
27
+ gh pr merge <pr> --repo <owner>/<repository> --squash --match-head-commit <exact-head-sha>
28
+ ```
29
+
30
+ GitHub branch protection remains authoritative. A refusal, changed head, advanced target, stale finalization, failed or pending check, ambiguous identity, or unavailable read ends the attempt and needs a fresh maintainer request. After success, use the ordinary read-only accepted/archive verification and cleanup path.
31
+
32
+ The policy PR introducing this route must integrate through the previously deployed maintainer-owned route. Only a later candidate may use a requested agent merge after this policy is present on `develop`.
33
+
20
34
  ### Complete-regression evidence ordering
21
35
 
22
36
  PR-attached Full regression is selected only for a repair that the trusted triage created from a failed Full regression: base policy verifies the immutable `openspec-ci` App author, generated candidate identity, and `regression-provenance.json`. Human-authored lookalikes, publishing or validation-authority changes, labels, Publish-only repairs, and successful-run persistent-overrun candidates retain bounded ordinary validation. Generated repair drafts run no Development test suites, including after implementation begins. Finish substantive implementation tasks, focused local evidence, pre-finalization observations, and known-gap disposition before checking the final Implementation item. The ready active head defers testing while trusted finalization publishes the candidate; the finalized head then receives all four native lanes as new full evidence, required by `Development validation required` alongside the existing gates.
@@ -27,7 +41,7 @@ The implementation, synchronized canonical specs, conditional acceptance record,
27
41
 
28
42
  ## Draft PR body
29
43
 
30
- The first screen should separate purpose from delivery detail, not foreground CI mechanics. Distill `Proposal` into one or two sentences answering why the PR exists, then put two to ten unchecked, implementation-specific outcomes under `Implementation`. They are a coarse progress summary, not a copy of the detailed OpenSpec task ledger:
44
+ The first screen should separate purpose from delivery detail, not foreground CI mechanics. Distill `Proposal` into one or two sentences answering why the PR exists, then put one or more unchecked, implementation-specific outcomes under `Implementation`, with no fixed maximum. They are a coarse progress summary, not a copy of the detailed OpenSpec task ledger:
31
45
 
32
46
  ```markdown
33
47
  ## Proposal
@@ -153,13 +167,13 @@ node scripts/governance/check-delivery-body.mjs --body-file .artifacts/agent/pr-
153
167
 
154
168
  `--final` validates the body as if every Implementation item were checked, so it can run before the last marker changes. `--pr <n>` reads the current pull request body instead. A defect exits 1 and prints the same `draft-<code>` reason the finalization run would report. The check covers association, Implementation, layout, and Acceptance only; detailed tasks, evidence, and target state remain covered by the [finalization command](#finalization-command) inspection mode.
155
169
 
156
- The committed conditional manifest contains the same ordered text. Trusted policy validates membership but never checks or edits it and never claims that the scenarios passed. The authorized maintainer's manual merge or personal native auto-merge arm for the unchanged exact head is the acceptance decision; no acceptance comment, checkbox edit, review-approval requirement, JSON edit, acceptance PR, archive PR, or later command is needed.
170
+ The committed conditional manifest contains the same ordered text. Trusted policy validates membership but never checks or edits it and never claims that the scenarios passed. The authorized maintainer's direct merge, personal native auto-merge arm, or explicit request for the active agent to merge the unchanged currently eligible exact head is the acceptance decision; no acceptance comment, checkbox edit, review-approval requirement, JSON edit, acceptance PR, archive PR, or later command is needed.
157
171
 
158
172
  If the body list changes, candidate validation reruns and compares it with the committed manifest. If the head changes, all prior exact-head CI is stale. If only the body changes to disagree with the manifest, integration remains blocked until the list and committed candidate agree again. No lifecycle body edit is needed after green CI.
159
173
 
160
174
  ## Automated finalization
161
175
 
162
- The `OpenSpec finalization` workflow (`.github/workflows/openspec-finalization.yml`) runs on `pull_request_target` for `opened`, `synchronize`, `ready_for_review`, `reopened`, and `edited` events targeting `develop`, one event at a time per PR. It checks out default-branch policy, installs the pinned tooling without hooks, and runs `scripts/governance/publish-openspec-finalization.mjs --pr <n>`; the PR head enters that process only as the `openspec/` tree the pinned OpenSpec engine reads. An all-checked version-3 task-list draft with valid Acceptance and complete detailed pre-finalization inputs is re-read as one exact snapshot and marked ready; no content is changed, and incomplete, malformed, legacy, unassociated, forked, or raced drafts remain draft with a stable reason. A draft with any unchecked item is skipped quietly. A draft whose every task-list item is checked but whose promotion is refused for a body, task, evidence, or other content defect fails the run with an `OpenSpec finalization` error annotation naming the `draft-<code>` reason, so the stall shows as a red check instead of a green skip. Closed PRs are skipped. For a ready version-3 candidate the workflow reconciles the head to its finalized form:
176
+ The `OpenSpec finalization` workflow (`.github/workflows/openspec-finalization.yml`) runs on `pull_request_target` for `opened`, `synchronize`, `ready_for_review`, `converted_to_draft`, `reopened`, and `edited` events targeting `develop`, one event at a time per PR. It checks out default-branch policy, installs the pinned tooling without hooks, and runs `scripts/governance/publish-openspec-finalization.mjs --pr <n>`; the PR head enters that process only as the `openspec/` tree the pinned OpenSpec engine reads. An all-checked version-3 task-list draft with valid Acceptance and complete detailed pre-finalization inputs is re-read as one exact snapshot and marked ready; no content is changed, and incomplete, malformed, legacy, unassociated, forked, or raced drafts remain draft with a stable reason. A draft with any unchecked item is skipped quietly. A finalized PR returned to draft is promoted again when its body still has every item checked, its fence names the exact head as finalized, and the tree holds exactly that archive with no active change; otherwise it stays draft with `draft-finalization-redraft-form`. A draft whose every task-list item is checked but whose promotion is refused for a body, task, evidence, or other content defect fails the run with an `OpenSpec finalization` error annotation naming the `draft-<code>` reason, so the stall shows as a red check instead of a green skip. Closed PRs are skipped. For a ready version-3 candidate the workflow reconciles the head to its finalized form:
163
177
 
164
178
  - **Active and current:** ordinary finalization with today's UTC date; one `docs(openspec): finalize <change>` commit.
165
179
  - **Finalized, valid, and current:** nothing is pushed; the run reports `already-finalized`.
@@ -214,7 +228,7 @@ Before a first finalization, canonical specs must still equal the selected targe
214
228
 
215
229
  ## Conditional acceptance and derived receipt
216
230
 
217
- `acceptance.md` truthfully says its verdict activates only when an authorized human manually merges the containing exact head after required current-head checks or personally arms native auto-merge for that unchanged head and GitHub integrates it after those checks. Its `openspec-delivery` block records stable pre-merge facts:
231
+ `acceptance.md` truthfully says its verdict activates only when an authorized human directly merges the containing exact head after required current-head checks, explicitly asks the active agent to execute that protected exact-head merge while it is eligible, or personally arms native auto-merge for the unchanged head and GitHub integrates it after those checks. Its `openspec-delivery` block records stable pre-merge facts:
218
232
 
219
233
  - schema version, repository, change, and source PR;
220
234
  - archive and manifest paths and finalization date;
@@ -223,7 +237,7 @@ Before a first finalization, canonical specs must still equal the selected targe
223
237
  - archive, canonical-spec, task, and evidence digests; and
224
238
  - explicit known-gap dispositions.
225
239
 
226
- It does not predict source head, merge commit, merger, or merge time. The PR head contains the manifest, so required CI binds those bytes without a recursive self-hash. After merge, the shared reader combines the manifest with immutable GitHub source head, successful required run, authorized human actor and permission, integration route, merge commit/time, and `develop` ancestry. Direct manual integration requires no active automatic authority. Human-enabled native auto-merge additionally requires a matching final-head enable event and `auto_merge.enabled_by`, with no later candidate commit or disable event. Queue, App/Bot, automation-owned, stale, malformed, or differently authored authority remains invalid. A human enable followed by disable before a valid manual merge is an abandoned attempt, not contradictory provenance. That shared result is the durable version-3 receipt used by audit and cleanup.
240
+ It does not predict source head, merge commit, merger, or merge time. The PR head contains the manifest, so required CI binds those bytes without a recursive self-hash. After merge, the shared reader combines the manifest with immutable GitHub source head, successful required run, authorized human actor and permission, integration route, merge commit/time, and `develop` ancestry. Direct integration, including an explicitly requested agent invocation through the maintainer's credential, requires no active automatic authority and retains the same authenticated-human merge provenance. Human-enabled native auto-merge additionally requires a matching final-head enable event and `auto_merge.enabled_by`, with no later candidate commit or disable event. Queue, App/Bot, automation-owned, stale, malformed, or differently authored authority remains invalid. A human enable followed by disable before a valid direct merge is an abandoned attempt, not contradictory provenance. That shared result is the durable version-3 receipt used by audit and cleanup.
227
241
 
228
242
  Unavailable, stale, automatic, unauthorized, conflicting, or contradictory provenance produces `invalid-provenance`/`blocked`, not acceptance. Post-merge code does not repair it by pushing `develop` or publishing another PR.
229
243
 
@@ -277,7 +291,7 @@ This bootstrap policy itself finishes under deployed version-2 authority. The fi
277
291
  - draft planning remaining unmerged;
278
292
  - explicit plan approval and same-PR implementation;
279
293
  - automated current-target finalization and exact-head CI;
280
- - authorized human integration, including manual merge and personally enabled exact-head native auto-merge, with plain acceptance scenarios;
294
+ - authorized human integration, including direct merge, an explicit exact-head agent-merge request, and personally enabled exact-head native auto-merge, with plain acceptance scenarios;
281
295
  - integrated canonical specs/archive and no generated acceptance/archive PR;
282
296
  - read-only `accepted-and-archived` verification and exact-head branch cleanup;
283
297
  - stale head/body/base/arm, incomplete tasks/evidence, malformed manifest, and automated or unauthorized auto-merge refusal fixtures; and
@@ -48,7 +48,11 @@ Conservative Development retains every pull-request owner but does not schedule
48
48
  node scripts/release/generate-validation-ownership-ledger.mjs --output .artifacts/validation/ownership-ledger.json
49
49
  ```
50
50
 
51
- The `terminal-host` owner is CI-only. A change under `native/terminal-host/` or to its run scripts selects, per platform (Windows x64, Linux x64, macOS arm64), one **Native terminal host** job and three **Native terminal host tests** partition jobs. The partition jobs each build the test profile and run one third of the serialized `role_integration` suite (`run-terminal-host-probe.mjs --partition <i>/3`, partitioned by sorted test name read from the suite's source); the build-and-probe job runs `npm run test:terminal-host` with the role suite skipped (`TERMINAL_HOST_PARTITION=none`), building the binary and Node-API lock artifact with Rust and Zig 0.15.2 for the lane's exact target and baseline CPU model and uploading the debug artifacts and frozen protocol manifest; Linux also runs bounded decoder fuzzing. The protected aggregate requires every partition of every selected platform, keyed by `partition` in the outcome authority and job envelope. Because the role suite no longer warms the resident launch paths in the build-and-probe job, its certification step runs one unmeasured `measure-resident-tabs.mjs` pass before the measured pass whose budgets are unchanged. Locally, `npm run test:terminal-host` without a partition is unchanged and runs everything in one process. Local Windows builds fail in `build.rs` unless `TERMINAL_HOST_LOCAL_BUILD=1` is set, because Zig's package fetch unpacks test data that workstation antivirus quarantines along with the installed process guardian. Native lanes also publish the terminal library they linked; a local build can link it instead of running Zig (see Local native iteration in [`architecture/resident-tabs.md`](architecture/resident-tabs.md)), which is development evidence only and never replaces selected CI. `TERMINAL_HOST_CONTRACTS_ONLY=1` is a library-only diagnostic and cannot substitute for selected CI. See [`native/terminal-host/README.md`](../native/terminal-host/README.md).
51
+ Containment-selected modular jobs build and test the debug `process-guardian.node` addon for their exact platform, export `A1_PROCESS_GUARDIAN_PATH` to that file, and run the launch-owner integration fixtures as Node processes. The tests exercise the real addon-held Windows job or Unix process group, addon-backed identity and terminal operations, and the Node exit watcher; no fixture invokes a process-guardian executable. The Windows startup lane keeps Defender real-time protection enabled while packaged startup loads the release addon.
52
+
53
+ The `terminal-host` owner is CI-only. A change under `native/terminal-host/` or to its run scripts selects, per platform (Windows x64, Linux x64, macOS arm64), one **Native terminal host** job and three **Native terminal host tests** partition jobs. The partition jobs each build the test profile and run one third of the serialized `role_integration` suite (`run-terminal-host-probe.mjs --partition <i>/3`, partitioned by sorted test name read from the suite's source); the feature-gated `role-host` binary stands in only for the fixed role grammar inside Rust integration tests and is never packaged. The build-and-probe job runs `npm run test:terminal-host` with the role suite skipped (`TERMINAL_HOST_PARTITION=none`), building `terminal-host.node` with Rust, Node-API 9, and Zig 0.15.2 for the lane's exact target and baseline CPU model. It loads the addon for its version and non-interactive probes, verifies the shared session-writer lock export, and uploads the debug addon and frozen protocol manifest; Linux also runs bounded decoder fuzzing.
54
+
55
+ The protected aggregate requires every partition of every selected platform, keyed by `partition` in the outcome authority and job envelope. Because the role suite no longer warms the resident launch paths in the build-and-probe job, its certification step runs one unmeasured `measure-resident-tabs.mjs` pass before the measured pass whose budgets are unchanged. Fidelity, latency, chaos, and certification start roles as `process.execPath dist/foundation/resident-tabs/host-entry.js` with `A1_TERMINAL_HOST_PATH` naming the addon. Windows cleanup identifies those Node-hosted residents by command line; it never kills every `node.exe` by image name. Locally, `npm run test:terminal-host` without a partition is unchanged and runs everything in one process. Local Windows builds fail in `build.rs` unless `TERMINAL_HOST_LOCAL_BUILD=1` is set, because Zig's package fetch unpacks test data that workstation antivirus quarantines. Native lanes also publish the terminal library they linked; a local build can link it instead of running Zig (see Local native iteration in [`architecture/resident-tabs.md`](architecture/resident-tabs.md)), which is development evidence only and never replaces selected CI. `TERMINAL_HOST_CONTRACTS_ONLY=1` is a library-only diagnostic and cannot substitute for selected CI. See [`native/terminal-host/README.md`](../native/terminal-host/README.md).
52
56
 
53
57
  ## Windows Full regression shards
54
58
 
@@ -122,7 +126,7 @@ Download these artifacts from the exact workflow run:
122
126
 
123
127
  For selected implementation candidates, record focused and pre-finalization full observations before finalization. Keep final head/run/selection identity in Actions and handoff rather than adding a post-success commit that invalidates that evidence. A successful selected PR run replaces an additional mandatory dispatch; standalone runs remain diagnostic, and numbered-package nightly recovery remains independent.
124
128
 
125
- Draft pull requests run no Development test suites. A ready version-3 PR whose body still identifies an active change defers testing and emits no protected aggregate while `OpenSpec finalization` publishes the candidate. A ready unassociated PR also fails closed when immutable base/head evidence shows that it introduces or restores active delivery content, or combines active-change edits with code or operational paths; it does not fall through to ordinary validation merely because its body fence is absent. Existing active-change documentation-only revisions and ordinary code PRs without active delivery paths retain their established routes. After finalization records the archive and acceptance manifest, the ordinary exact-head workflow runs selected product/governance lanes and `Finalized delivery validation` in parallel, then emits the stable protected `Development validation required` aggregate only when both authorities succeed. Green CI enables maintainer review and manual merge but does not claim human acceptance or merge automatically. The finalization fence update is the validation trigger, so no pre-finalization test run or later lifecycle body edit is required. Any subsequent eligible implementation commit changes the head and reruns applicable validation; any body change reruns readiness and finalized-record validation and must continue to match the committed manifest. Legacy acceptance-record-only PRs retain their separate trusted `Acceptance record validation` route. Queue availability remains explicitly unavailable inside a runner and is calculated from the Actions API during final run analysis rather than guessed.
129
+ Draft pull requests run no Development test suites. A ready version-3 PR whose body still identifies an active change defers testing and emits no protected aggregate while `OpenSpec finalization` publishes the candidate. A ready unassociated PR also fails closed when immutable base/head evidence shows that it introduces or restores active delivery content, or combines active-change edits with code or operational paths; it does not fall through to ordinary validation merely because its body fence is absent. Existing active-change documentation-only revisions and ordinary code PRs without active delivery paths retain their established routes. After finalization records the archive and acceptance manifest, the ordinary exact-head workflow runs selected product/governance lanes and `Finalized delivery validation` in parallel, then emits the stable protected `Development validation required` aggregate only when both authorities succeed. Green CI enables maintainer review and an explicit integration decision but does not claim human acceptance or merge automatically. After green exact-head validation, the maintainer may directly merge, personally arm native auto-merge, or explicitly ask the active agent to perform one expected-head protected squash merge for that currently eligible candidate. The finalization fence update is the validation trigger, so no pre-finalization test run or later lifecycle body edit is required. Any subsequent eligible implementation commit changes the head and reruns applicable validation; any body change reruns readiness and finalized-record validation and must continue to match the committed manifest. Legacy acceptance-record-only PRs retain their separate trusted `Acceptance record validation` route. Queue availability remains explicitly unavailable inside a runner and is calculated from the Actions API during final run analysis rather than guessed.
126
130
 
127
131
  ## Rollback
128
132
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1",
3
- "version": "0.2.7-dev.792",
3
+ "version": "0.2.7-dev.801",
4
4
  "description": "Standalone terminal workspace for supervised native and managed agents",
5
5
  "type": "module",
6
6
  "privateLaunchContract": "neutral-launch-v1",
@@ -23,7 +23,9 @@
23
23
  },
24
24
  "scripts": {
25
25
  "clean": "node scripts/clean.mjs",
26
- "build": "node scripts/development/check-environment.mjs && npm run clean && tsc -p tsconfig.build.json && node scripts/release/generate-release-notes-resource.mjs && node scripts/pi/build-pi-settings-metadata.mjs && node scripts/pi/build-startup-public.mjs && node scripts/development/build-process-guardian.mjs && node scripts/release/generate-runtime-payload-inventory.mjs",
26
+ "build": "node scripts/development/check-environment.mjs && npm run build:managed && node scripts/development/prepare-local-terminal-host.mjs && node scripts/release/generate-runtime-payload-inventory.mjs",
27
+ "build:core": "node scripts/development/check-environment.mjs && npm run build:managed && node scripts/release/generate-runtime-payload-inventory.mjs",
28
+ "build:managed": "npm run clean && tsc -p tsconfig.build.json && node scripts/release/generate-release-notes-resource.mjs && node scripts/pi/build-pi-settings-metadata.mjs && node scripts/pi/build-startup-public.mjs && node scripts/development/build-process-guardian.mjs",
27
29
  "build:process-guardian": "node scripts/development/build-process-guardian.mjs",
28
30
  "build:terminal-host": "node scripts/development/build-terminal-host.mjs",
29
31
  "typecheck": "tsgo -p tsconfig.json --noEmit && tsgo -p tsconfig.bin.json",
@@ -51,6 +53,7 @@
51
53
  "test:full": "node scripts/release/run-validation-tier.mjs full-release",
52
54
  "test:release": "node scripts/release/run-release-gates.mjs",
53
55
  "test:terminal-host": "node scripts/development/run-terminal-host-probe.mjs",
56
+ "test:resident-parallel-progress": "node scripts/development/verify-resident-parallel-progress.mjs",
54
57
  "test:resident-chaos": "node scripts/development/run-resident-chaos.mjs --build",
55
58
  "test:pi-engine-conformance": "vitest run test/integrations/pi/engine/conformance.test.ts test/integrations/pi/engine/runtime-integration.test.ts test/integrations/pi/engine/session-integration.test.ts",
56
59
  "report:pi-engine-conformance": "npm run build --silent && node scripts/pi/run-pi-engine-conformance.mjs",
@@ -65,7 +68,7 @@
65
68
  "start:pi": "npm run build && node scripts/development/dev-launch.mjs pi",
66
69
  "prepack": "node scripts/release/validate-packaged-release-note.mjs && node scripts/release/prepack-gate.mjs",
67
70
  "prepublishOnly": "npm run test:release",
68
- "prepare": "npm run build",
71
+ "prepare": "npm run build:core",
69
72
  "typecheck:bin": "tsgo -p tsconfig.bin.json"
70
73
  },
71
74
  "dependencies": {
@@ -1,5 +0,0 @@
1
- import { WindowsNativeProcessInspector, type InspectorCommandRunner } from "./windows-process-inspector.js";
2
- /** Verifies Darwin process identity through the bounded native guardian inspection command. */
3
- export declare class DarwinNativeProcessInspector extends WindowsNativeProcessInspector {
4
- constructor(helperPath: string, runner?: InspectorCommandRunner);
5
- }
@@ -1,7 +0,0 @@
1
- import { WindowsNativeProcessInspector } from "./windows-process-inspector.js";
2
- /** Verifies Darwin process identity through the bounded native guardian inspection command. */
3
- export class DarwinNativeProcessInspector extends WindowsNativeProcessInspector {
4
- constructor(helperPath, runner) {
5
- super(helperPath, runner, "darwin-proc-start:");
6
- }
7
- }
@@ -1,152 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdir, readFile, rm } from "node:fs/promises";
3
- import { dirname, resolve } from "node:path";
4
- import { PRODUCT_IDENTITY } from "../../product-identity.js";
5
- /** Delegates one root runtime to the native guardian and exposes its verified containment identity. */
6
- export class NativeGuardianContainment {
7
- #identity;
8
- #helper = null;
9
- #rootIdentity = null;
10
- #outcome = null;
11
- instanceId;
12
- helperPath;
13
- statusPath;
14
- exitNoticePath;
15
- constructor(instanceId, helperPath, statusPath, exitNoticePath = null) {
16
- this.instanceId = instanceId;
17
- this.helperPath = helperPath;
18
- this.statusPath = statusPath;
19
- this.exitNoticePath = exitNoticePath;
20
- this.#identity = { provider: "native-guardian-pending", token: instanceId };
21
- }
22
- get identity() {
23
- return this.#identity;
24
- }
25
- async spawn(executable, arguments_, options) {
26
- if (this.#helper)
27
- throw new Error("process containment already has a root runtime");
28
- await mkdir(dirname(this.statusPath), { recursive: true, mode: 0o700 });
29
- await rm(this.statusPath, { force: true });
30
- if (this.exitNoticePath)
31
- await rm(this.exitNoticePath, { force: true });
32
- const helper = spawn(this.helperPath, [
33
- "--parent-pid", String(process.pid),
34
- "--instance", this.instanceId,
35
- "--status-file", this.statusPath,
36
- ...(this.exitNoticePath ? ["--exit-notice", this.exitNoticePath] : []),
37
- "--", executable, ...arguments_,
38
- ], {
39
- cwd: options.cwd,
40
- env: {
41
- ...options.environment,
42
- ...(options.terminalType ? { TERM: options.terminalType } : {}),
43
- // Protocol: the runtime arms this notice and the guardian prints it if the runtime dies unclean.
44
- ...(this.exitNoticePath ? { [PRODUCT_IDENTITY.environment.exitNoticePath]: this.exitNoticePath } : {}),
45
- },
46
- shell: false,
47
- stdio: "inherit",
48
- windowsHide: false,
49
- });
50
- this.#helper = helper;
51
- this.#outcome = helperOutcome(helper);
52
- const status = await waitForReadyStatus(this.statusPath, this.#outcome, 5_000);
53
- this.#rootIdentity = { pid: status.pid, startIdentity: status.startIdentity };
54
- this.#identity = { provider: status.containmentProvider, token: status.containmentToken };
55
- return { identity: this.#rootIdentity, outcome: this.#outcome };
56
- }
57
- async contains(identity) {
58
- return this.#rootIdentity !== null
59
- && identity.pid === this.#rootIdentity.pid
60
- && identity.startIdentity === this.#rootIdentity.startIdentity;
61
- }
62
- async stop(force) {
63
- const root = this.#rootIdentity;
64
- if (!root)
65
- return;
66
- try {
67
- process.kill(root.pid, force ? "SIGKILL" : "SIGTERM");
68
- }
69
- catch { }
70
- }
71
- async waitForEmpty(timeoutMs) {
72
- if (!this.#helper || this.#helper.exitCode !== null || this.#helper.signalCode !== null)
73
- return true;
74
- return await new Promise(resolvePromise => {
75
- const timer = setTimeout(() => finish(false), timeoutMs);
76
- timer.unref();
77
- const finish = (empty) => {
78
- clearTimeout(timer);
79
- this.#helper?.off("close", onClose);
80
- resolvePromise(empty);
81
- };
82
- const onClose = () => finish(true);
83
- this.#helper?.once("close", onClose);
84
- });
85
- }
86
- async close() {
87
- const helper = this.#helper;
88
- if (helper && helper.exitCode === null && helper.signalCode === null)
89
- helper.kill("SIGKILL");
90
- await this.waitForEmpty(1_500);
91
- await rm(this.statusPath, { force: true });
92
- if (this.exitNoticePath)
93
- await rm(this.exitNoticePath, { force: true });
94
- }
95
- }
96
- export function resolveProcessGuardianPath(releaseRoot, environment = process.env, platform = process.platform, architecture = process.arch) {
97
- const override = environment[PRODUCT_IDENTITY.environment.processGuardianPath]?.trim();
98
- if (override)
99
- return resolve(override);
100
- const executable = platform === "win32"
101
- ? `${PRODUCT_IDENTITY.artifacts.processGuardianExecutable}.exe`
102
- : PRODUCT_IDENTITY.artifacts.processGuardianExecutable;
103
- return resolve(releaseRoot, "dist", "native", `${platform}-${architecture}`, executable);
104
- }
105
- function helperOutcome(helper) {
106
- return new Promise(resolvePromise => {
107
- let settled = false;
108
- const settle = (outcome) => {
109
- if (settled)
110
- return;
111
- settled = true;
112
- resolvePromise(outcome);
113
- };
114
- helper.once("error", error => settle({ kind: "guardian-error", message: error.message, code: errorCode(error) }));
115
- helper.once("close", (code, signal) => {
116
- if (signal)
117
- settle({ kind: "signaled", signal });
118
- else
119
- settle({ kind: "exited", exitCode: code ?? 1 });
120
- });
121
- });
122
- }
123
- async function waitForReadyStatus(path, outcome, timeoutMs) {
124
- const deadline = Date.now() + timeoutMs;
125
- let terminalOutcome = null;
126
- void outcome.then(value => { terminalOutcome = value; });
127
- while (Date.now() < deadline) {
128
- try {
129
- const value = JSON.parse(await readFile(path, "utf8"));
130
- if (isReadyStatus(value))
131
- return value;
132
- throw new Error("process guardian published invalid ready status");
133
- }
134
- catch (error) {
135
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
136
- throw error;
137
- }
138
- if (terminalOutcome)
139
- throw new Error(`process guardian exited before readiness: ${JSON.stringify(terminalOutcome)}`);
140
- await new Promise(resolvePromise => setTimeout(resolvePromise, 20));
141
- }
142
- throw new Error(`process guardian did not publish readiness within ${timeoutMs}ms`);
143
- }
144
- function isReadyStatus(value) {
145
- return Number.isSafeInteger(value.pid) && Number(value.pid) > 0
146
- && typeof value.startIdentity === "string" && value.startIdentity.length > 0
147
- && typeof value.containmentProvider === "string" && value.containmentProvider.length > 0
148
- && typeof value.containmentToken === "string" && value.containmentToken.length > 0;
149
- }
150
- function errorCode(error) {
151
- return "code" in error && typeof error.code === "string" ? error.code : null;
152
- }
@@ -1,19 +0,0 @@
1
- import type { NativeProcessIdentity } from "../lifecycle/index.js";
2
- import type { NativeProcessInspector } from "./contracts.js";
3
- export interface InspectorCommandResult {
4
- readonly exitCode: number;
5
- readonly stdout: string;
6
- readonly stderr: string;
7
- }
8
- export interface InspectorCommandRunner {
9
- run(executable: string, arguments_: readonly string[]): Promise<InspectorCommandResult>;
10
- }
11
- /** Verifies Windows process identity through the bounded process-guardian inspection command. */
12
- export declare class WindowsNativeProcessInspector implements NativeProcessInspector {
13
- readonly helperPath: string;
14
- private readonly runner;
15
- private readonly identityPrefix;
16
- constructor(helperPath: string, runner?: InspectorCommandRunner, identityPrefix?: string);
17
- observe(pid: number): Promise<NativeProcessIdentity | null>;
18
- matches(identity: NativeProcessIdentity): Promise<boolean>;
19
- }
@@ -1,56 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- /** Verifies Windows process identity through the bounded process-guardian inspection command. */
3
- export class WindowsNativeProcessInspector {
4
- helperPath;
5
- runner;
6
- identityPrefix;
7
- constructor(helperPath, runner = defaultRunner, identityPrefix = "windows-filetime:") {
8
- this.helperPath = helperPath;
9
- this.runner = runner;
10
- this.identityPrefix = identityPrefix;
11
- if (!helperPath || helperPath.includes("\0"))
12
- throw new TypeError("process guardian helper path is invalid");
13
- }
14
- async observe(pid) {
15
- if (!Number.isSafeInteger(pid) || pid <= 0)
16
- throw new TypeError("inspected PID must be a positive safe integer");
17
- const result = await this.runner.run(this.helperPath, ["--inspect-pid", String(pid)]);
18
- if (result.exitCode === 3)
19
- return null;
20
- if (result.exitCode !== 0) {
21
- const detail = result.stderr.trim() || `helper exited ${result.exitCode}`;
22
- throw Object.assign(new Error(`cannot inspect native process identity: ${detail}`), { code: "PROCESS_INSPECTION_FAILED" });
23
- }
24
- let value;
25
- try {
26
- value = JSON.parse(result.stdout);
27
- }
28
- catch {
29
- throw Object.assign(new Error("process guardian returned malformed identity data"), { code: "PROCESS_INSPECTION_INVALID" });
30
- }
31
- if (!isIdentity(value) || value.pid !== pid || !value.startIdentity.startsWith(this.identityPrefix)) {
32
- throw Object.assign(new Error("process guardian returned mismatched identity data"), { code: "PROCESS_INSPECTION_INVALID" });
33
- }
34
- return value;
35
- }
36
- async matches(identity) {
37
- const observed = await this.observe(identity.pid);
38
- return observed !== null && observed.startIdentity === identity.startIdentity;
39
- }
40
- }
41
- const defaultRunner = {
42
- async run(executable, arguments_) {
43
- return await new Promise(resolvePromise => {
44
- execFile(executable, [...arguments_], { windowsHide: true, timeout: 2_000, maxBuffer: 8 * 1_024 }, (error, stdout, stderr) => {
45
- const exitCode = error && "code" in error && typeof error.code === "number" ? error.code : error ? 1 : 0;
46
- resolvePromise({ exitCode, stdout, stderr });
47
- });
48
- });
49
- },
50
- };
51
- function isIdentity(value) {
52
- return typeof value === "object" && value !== null
53
- && "pid" in value && Number.isSafeInteger(value.pid) && Number(value.pid) > 0
54
- && "startIdentity" in value && typeof value.startIdentity === "string"
55
- && value.startIdentity.length > 0 && value.startIdentity.length <= 512 && !value.startIdentity.includes("\0");
56
- }
Binary file