ultra-builder-pro-cli 0.26.1 → 3.0.2

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 (75) hide show
  1. package/.ultra-template/contexts/TEMPLATE.md +64 -29
  2. package/.ultra-template/north-star.md +36 -30
  3. package/.ultra-template/project-brief.md +28 -0
  4. package/.ultra-template/specs/product.md +4 -0
  5. package/.ultra-template/specs/research-distillate.md +8 -0
  6. package/.ultra-template/tasks.json +1 -0
  7. package/.ultra-template/test-report.json +18 -1
  8. package/CHANGELOG.md +227 -1
  9. package/README.md +161 -59
  10. package/adapters/_shared/host-profile.cjs +68 -12
  11. package/adapters/_shared/plugin-core.cjs +4 -5
  12. package/adapters/_shared/runtime-assets.cjs +11 -2
  13. package/adapters/zcode.js +375 -0
  14. package/bin/delegate-worker.cjs +20 -0
  15. package/bin/delegate.cjs +94 -25
  16. package/bin/install.js +11 -6
  17. package/docs/ARCHITECTURE.md +109 -25
  18. package/docs/ARTIFACT-AUTHORITY.md +204 -30
  19. package/docs/DECISIONS.md +141 -10
  20. package/docs/PHILOSOPHY.md +61 -8
  21. package/docs/PLUGIN-ISOLATION-CONTRACT.md +6 -0
  22. package/docs/RUNTIME-COMPAT-MATRIX.md +106 -13
  23. package/docs/SKILL-AUTHORING.md +14 -9
  24. package/docs/WORKFLOW-LIFECYCLE.md +211 -53
  25. package/docs/evals/adversarial-review-2026-08-14.md +84 -0
  26. package/docs/evals/zcode-automation-2026-08-14.md +103 -0
  27. package/hooks/README.md +31 -3
  28. package/hooks/_common.py +1699 -33
  29. package/hooks/adapters/zcode.py +227 -0
  30. package/hooks/compact_context.py +176 -17
  31. package/hooks/mid_workflow_recall.py +27 -5
  32. package/hooks/post_edit_guard.py +133 -23
  33. package/hooks/session_context.py +722 -11
  34. package/package.json +6 -3
  35. package/skills/ultra-change/SKILL.md +84 -64
  36. package/skills/ultra-change/references/change-contract.md +130 -32
  37. package/skills/ultra-change/references/execution-grant.md +109 -0
  38. package/skills/ultra-change/references/primary-transfer.md +273 -0
  39. package/skills/ultra-change/scripts/validate_primary_transfer.cjs +1928 -0
  40. package/skills/ultra-delegate/SKILL.md +38 -5
  41. package/skills/ultra-delegate/references/delegation-contract.md +21 -1
  42. package/skills/ultra-deliver/SKILL.md +123 -44
  43. package/skills/ultra-deliver/references/baseline-reconciliation.md +5 -3
  44. package/skills/ultra-dev/SKILL.md +173 -43
  45. package/skills/ultra-grilling/SKILL.md +19 -16
  46. package/skills/ultra-grilling/references/reframing.md +7 -3
  47. package/skills/ultra-init/SKILL.md +99 -87
  48. package/skills/ultra-init/references/brownfield-adoption.md +23 -40
  49. package/skills/ultra-init/scripts/init_project.cjs +968 -21
  50. package/skills/ultra-plan/SKILL.md +83 -46
  51. package/skills/ultra-plan/references/task-evidence-v2.md +300 -0
  52. package/skills/ultra-plan/scripts/validate_task_evidence.cjs +859 -0
  53. package/skills/ultra-research/SKILL.md +119 -68
  54. package/skills/ultra-research/references/{03-competitive-landscape.md → 03-alternatives.md} +6 -6
  55. package/skills/ultra-research/references/04-product-strategy.md +11 -2
  56. package/skills/ultra-research/references/21-features-scope.md +8 -0
  57. package/skills/ultra-research/references/22-success-metrics.md +9 -4
  58. package/skills/ultra-research/references/99-synthesis.md +25 -1
  59. package/skills/ultra-research/references/north-star-v2.md +168 -0
  60. package/skills/ultra-research/references/wayfinding.md +50 -0
  61. package/skills/ultra-research/scripts/validate_north_star.cjs +1174 -0
  62. package/skills/ultra-review/SKILL.md +201 -24
  63. package/skills/ultra-review/references/adversarial-evaluation.md +31 -0
  64. package/skills/ultra-review/references/spec.md +5 -0
  65. package/skills/ultra-review/references/unified-schema.md +146 -11
  66. package/skills/ultra-review/references/worker-packet.md +151 -8
  67. package/skills/ultra-review/scripts/review_wait.py +2653 -63
  68. package/skills/ultra-status/SKILL.md +146 -32
  69. package/skills/ultra-tdd/SKILL.md +14 -4
  70. package/skills/ultra-tdd/references/test-execution.md +6 -1
  71. package/skills/ultra-test/SKILL.md +157 -15
  72. package/skills/ultra-test/scripts/validate_review_transport.cjs +549 -0
  73. package/skills/ultra-test/scripts/worktree_digest.cjs +551 -29
  74. package/skills/ultra-think/SKILL.md +5 -10
  75. package/skills/ultra-think/references/interaction-boundary.md +2 -1
@@ -5,41 +5,50 @@ description: Turn an evidenced Change intent into a dependency-valid task ledger
5
5
 
6
6
  # Turn one Change into executable tracer bullets
7
7
 
8
- Planning owns decomposition and technical design. Files carry the result across
9
- sessions and hosts; no runtime state decides whether the plan is meaningful.
8
+ Planning owns decomposition and technical design; files carry it across sessions and hosts.
10
9
 
11
10
  ## Before you start
12
11
 
13
- 1. Read `.ultra/tasks.json`; if a task is unfinished, read its `context_file` and
14
- closing `## Resume Note` before replacing or extending anything.
15
- 2. Read `CONTEXT.md` for vocabulary and the relevant `.ultra/decisions/` entries.
16
- 3. Read the active Change intent, its `trace_to` specification anchors, and the
12
+ 1. If model-selected, verify the live execution grant in `../ultra-change/references/execution-grant.md` — a current session-local activation or a stably verified durable work-package grant; without either, stop.
13
+ 2. Read `../ultra-change/references/change-contract.md` and apply its **Active Change
14
+ authority resolution** before reading any active `intent.md` or resolving a current
15
+ `change_id`. This workflow requires its one valid active authority; any zero result
16
+ or typed diagnostic stops before decomposition until the stated repair or retry
17
+ succeeds. The intent must be `accepted`, every blocking decision resolved, its
18
+ `## Research Disposition` exit evidence satisfied, and its `## North Star Trace`
19
+ current before decomposition.
20
+ 3. Read `.ultra/tasks.json`; select matching tasks and read each unfinished context and
21
+ Resume Note. Preserve all historical tasks in the append-only ledger.
22
+ 4. Read `CONTEXT.md` for vocabulary and the relevant `.ultra/decisions/` entries.
23
+ 5. Read the active Change intent, its `trace_to` specification anchors, and the
17
24
  source, tests, consumers and recovery paths those anchors describe.
18
25
 
19
26
  ## Definition of done
20
27
 
21
- - `.ultra/tasks.json` and one `.ultra/contexts/task-<id>.md` per task agree on
22
- identifiers, status, dependencies and trace anchors.
23
- - The owner confirmed the scope posture and the seam list.
24
- - Every feature task is a tracer bullet touching at least two layers, unless the
25
- Change itself demonstrably touches only one layer.
26
- - Every context names the north-star hard constraints its work could violate, and
27
- each `HC-<n>` it names resolves to a real entry in `.ultra/north-star.md`.
28
+ - `.ultra/tasks.json` uses `$schema: "ultra-task-ledger-v2"` and is the sole
29
+ task-status authority. Every current-Change row resolves one context whose stable
30
+ identifiers, dependencies and trace anchors agree with the ledger.
31
+ - The owner confirmed any material posture. Seams resolve to code; technical selection
32
+ stays model-owned unless it changes public contract, accepted risk, or material trade-off.
33
+ - Every feature task is a tracer bullet crossing the real boundaries needed to make its
34
+ observable behavior work; a genuinely local Change does not invent extra layers.
35
+ - Every task context records resolving `FP-<n>` premises, `NS-<n>` outcomes, and
36
+ `HC-<n>` constraints as IDs only. It explains the task-local causal contribution and
37
+ potential constraint breach without mirroring North Star prose.
28
38
  - Every Change acceptance id maps to at least one task context, and every context id
29
39
  resolves back to the active Change.
30
- - Coverage, dependency, trace, scope and context-budget checks have concrete results.
40
+ - Coverage, dependency, trace, scope and context-pressure checks have concrete results.
31
41
 
32
42
  ## Fix the planning posture
33
43
 
34
- Choose `EXPAND`, `SELECTIVE`, `HOLD` or `REDUCE`; default to `SELECTIVE`. Once
35
- chosen, keep that posture visible in the active Change intent rather than silently drifting.
36
- Write it to the active Change `intent.md` under `## Planning Posture`; there is no
37
- separate `plan.md` authority.
44
+ Choose `EXPAND`, `SELECTIVE`, `HOLD` or `REDUCE`; default to `SELECTIVE`. Write it under
45
+ `## Planning Posture` in active `intent.md`; there is no separate `plan.md` authority.
46
+ Keep the posture visible rather than silently drifting.
38
47
  Use `../ultra-grilling/SKILL.md` through the host-native question surface when the
39
48
  choice remains material, one question with a recommendation at a time.
40
49
 
41
- If the work cannot fit in one session *and* the path itself is still unclear, use
42
- `../ultra-think/SKILL.md` to resolve decision tickets before decomposing tasks.
50
+ When the whole path is still unclear, recommend `ultra-research`; the Change is not yet
51
+ evidenced enough to decompose. For one consequential trade-off, use `../ultra-think/SKILL.md`.
43
52
 
44
53
  ## Choose the plan shape
45
54
 
@@ -50,28 +59,44 @@ expand with old and new forms, migrate bounded batches, then contract the old fo
50
59
 
51
60
  Build the graph with these structural defences:
52
61
 
53
- - **Walking Skeleton**: Task 1 traverses every layer this Change touches through one
54
- real request and real data. A genuinely one-layer Change does not invent one.
55
- - **Contract task**: create it before both implementations when targets cross two top-
56
- level source directories or two processes/services.
57
- - **Integration Checkpoint**: insert one after every three or four feature tasks.
62
+ - **Walking Skeleton**: the earliest executable tracer bullet traverses the real
63
+ boundaries this Change touches with real data. A genuinely one-layer Change does not
64
+ invent extra layers.
65
+ - **Contract task**: create one before dependent implementations when a shared contract
66
+ must remain valid while independently changed boundaries coexist.
67
+ - **Integration Checkpoint**: insert one where independently developed slices first
68
+ compose, or where the observed coupling or recovery risk makes an intermediate
69
+ whole-path check useful.
58
70
  - A feature task that touches only one of several affected layers is merged or split
59
71
  into a tracer bullet; moving a whole layer into one task is horizontal slicing.
60
72
 
61
- Confirm the seam list before tests are written. Reuse an existing public seam and use
62
- the highest seam that observes the behavior; one seam is ideal when it covers the path.
73
+ Record seams before tests. The model chooses the technical seam: prefer an existing,
74
+ highest observable public seam, ideally one. Ask the owner only when it changes the
75
+ public contract or another material product, risk, or recovery trade-off.
63
76
 
64
77
  ## Write the files
65
78
 
66
- Each task records `id`, `title`, `type`, `priority`, `complexity`, `status`,
67
- `dependencies`, `context_file`, `trace_to` and `change_ref`. Complexity is only a
68
- splitting and context signal: 1–2 is local, 3–5 is bounded, 6–7 crosses a boundary,
69
- and complexity > 7 must split.
70
-
71
- Each context records Change Acceptance IDs, task-local Acceptance, confirmed seams,
72
- layers touched, target files, Implementation, verification commands, the hard
73
- constraints the work could violate, Definition of Drift, Change Log, Completion and
74
- Resume Note. Read every file back; task count and context count must match.
79
+ The ledger root records `$schema: "ultra-task-ledger-v2"` and `tasks`. Each new task
80
+ records `id`, `title`, `type`, `priority`, `status`, `dependencies`, `context_file`,
81
+ `trace_to` and `change_id`. Task ids are globally unique, and every dependency must name
82
+ a task with the same `change_id`; an archived Change must never become an implicit
83
+ prerequisite of current work. A legacy `complexity` field remains readable only as a
84
+ migration diagnostic. It is not copied into new rows and never decides splitting,
85
+ priority, scope, context, or completion.
86
+
87
+ Append new tasks or repair matching current-Change tasks in place; never replace the
88
+ ledger with only the latest graph. Every active Change receives the smallest graph that
89
+ covers its real seams, evidence, review, and recovery needs. A profile does not decide
90
+ the number of tasks or contexts.
91
+
92
+ Each context records Change Acceptance IDs, a task-local Acceptance table with `ID`,
93
+ `Criterion`, `Verification type`, and `Required evidence`, confirmed seams, layers
94
+ touched, target files, Implementation, verification commands, the hard constraints the
95
+ work could violate, a Trace containing `FP-<n>`, `NS-<n>`, and `HC-<n>` IDs, Definition
96
+ of Drift, Change Log, Completion, Task Review, and Resume Note. A v2 context does not
97
+ repeat task status. If a legacy context contains a Status or Complexity header, preserve
98
+ it as a migration diagnostic and use the ledger value. Read every file back and verify
99
+ that every row resolves its named context and every current context resolves one row.
75
100
 
76
101
  Name a hard constraint whenever the task could plausibly breach it, not only when you
77
102
  expect it to. The entry costs one line and is what makes a later breach a checkable
@@ -84,22 +109,34 @@ touches nothing constrained.
84
109
  context IDs. Map every in-scope user story or specification anchor to at least one task.
85
110
  2. Walk dependencies and repair every cycle with the exact cycle chain visible.
86
111
  3. Resolve every `trace_to` path and heading against a real file.
87
- 4. Resolve every `HC-<n>` against `.ultra/north-star.md`. A dangling constraint id is
88
- the same defect as a dangling `trace_to`: it reads as checked and never was.
89
- 5. Surface complexity, more than eight target files, or more than twenty tasks as
90
- scope warnings; they are observations, not semantic verdicts.
91
- 6. Estimate context at roughly `complexity × 5%`; surface anything above 40%.
112
+ 4. Resolve the Change and task `North Star Trace` `FP-<n>`/`NS-<n>`/`HC-<n>` ids
113
+ against `.ultra/north-star.md`. A revision mismatch is a stale observation that
114
+ returns to Change reconciliation, not a semantic verdict about alignment.
115
+ 5. Surface concrete scope pressure: unresolved dependencies, duplicated ownership,
116
+ boundaries that cannot be tested independently, evidence that cannot fit the named
117
+ seam, or a context that no longer supports a reliable resume. File, task, line, and
118
+ context counts do not decide plan quality.
119
+ 6. Validate exact ledger fields, ids, dependency edges, paths and typed acceptance
120
+ shapes. A validator reports structural diagnostics only; it never decides whether
121
+ the decomposition, criterion, evidence, or plan is semantically sufficient.
122
+ Follow `../ultra-review/SKILL.md` in plan mode. Require a validated current
123
+ `SUMMARY.json`; resolve every blocking finding and refresh affected evidence before
124
+ handoff. If further repair is not justified or an authorized resource ceiling is
125
+ reached, preserve the findings and return the evidence to the responsible model or
126
+ owner. Attempt and finding counts never manufacture convergence or failure.
92
127
 
93
128
  Report the graph, frontier, seams, warnings and first task. Recommend the next explicit
94
129
  capability from the files; do not invoke it.
95
130
 
96
131
  ## When the owner decides
97
132
 
98
- The owner chooses the posture, confirms seams, resolves reductions and accepts material
99
- omissions. Mechanical cycles and broken paths are repaired before handoff because they
100
- make the written graph impossible to execute.
101
-
133
+ The owner chooses material posture, reductions, omissions, and any seam changing public
134
+ contract or material trade-off. The model owns decomposition and repairs broken paths.
102
135
  ## References
103
136
 
137
+ - `../ultra-change/references/change-contract.md` — canonical Active Change authority resolution.
104
138
  - `../ultra-grilling/SKILL.md` — read before a material posture or seam question.
105
- - `../ultra-think/SKILL.md` — read when fog of war requires decision tickets.
139
+ - `../ultra-think/SKILL.md` — read when one evidenced decision blocks decomposition.
140
+ - `../ultra-review/SKILL.md` — read after plan files pass mechanical verification.
141
+ - `../ultra-change/references/execution-grant.md` — read only for grant-activated continuation.
142
+ - `references/task-evidence-v2.md` — canonical typed task evidence and task-review contract.
@@ -0,0 +1,300 @@
1
+ # Task ledger, context, and evidence v2
2
+
3
+ Use this contract when Plan creates a task or when Dev refreshes completion evidence.
4
+ The ledger owns mechanical task status. A task context contains meaning and resume
5
+ information but does not repeat `status`, `priority`, or `complexity` in a metadata
6
+ header. A legacy header is readable only as an observation; the ledger wins and the
7
+ reader reports a migration diagnostic.
8
+
9
+ ## Ledger and context
10
+
11
+ The ledger root is exactly `$schema` plus `tasks`, with `$schema` set to
12
+ `ultra-task-ledger-v2`. A current task row has these fields:
13
+
14
+ ```text
15
+ id, title, type, priority, status, dependencies, context_file, trace_to, change_id
16
+ ```
17
+
18
+ Legacy rows may retain `complexity`; do not use it to decide task, file, question,
19
+ finding, repair-round, or quality limits. The Acceptance section in every current
20
+ context starts with the Change Acceptance IDs and this exact table:
21
+
22
+ ```markdown
23
+ | ID | Criterion | Verification type | Required evidence |
24
+ |---|---|---|---|
25
+ ```
26
+
27
+ Criterion IDs are unique inside one task. Verification type is exactly `command`,
28
+ `inspection`, `owner-judgment`, or `external-observation`. The required-evidence cell
29
+ names evidence that can actually establish the criterion; it is not a second status.
30
+
31
+ ## Evidence root
32
+
33
+ `.ultra/evidence/<task-id>/evidence.json` is the one final completion record. It uses
34
+ `ultra-task-evidence-v2` and the exact ordered root fields below:
35
+
36
+ The product-worktree digest has one fixed boundary: it excludes `.ultra/evidence/**`,
37
+ whose command and external-observation entries bind raw bytes as
38
+ `raw_evidence_sha256` before stable exact record bytes are bound as `evidence_digest` by
39
+ aggregate Test. This makes evidence publication and refresh non-self-referential without
40
+ hiding provenance. No workflow supplies an additional exclusion.
41
+
42
+ ```text
43
+ $schema, task_id, change_id, context, subject, acceptance, dimensions,
44
+ task_review, artifacts, limitations, timestamp
45
+ ```
46
+
47
+ `context` is exactly `{path, acceptance_sha256}`. Hash the UTF-8 bytes beginning with
48
+ the `## Acceptance Criteria` heading and ending immediately before the next level-two
49
+ heading. Do not bind the whole mutable task context. `subject` is exactly
50
+ `{git_head, worktree_digest, observed_at}`. The `subject` is an independently captured
51
+ completion-snapshot freshness observation: capture it after the final strict task Review
52
+ validates and immediately before evidence publication. `task_review` separately binds
53
+ the retained strict summary. Worker Packet v1 carries no worktree digest and its
54
+ `SUMMARY.json` records `worktree_digest: null`, so neither review artifact proves or
55
+ cryptographically binds `subject.worktree_digest`. The subject is not rebound to a later
56
+ aggregate Change worktree.
57
+
58
+ Each acceptance item is exactly:
59
+
60
+ ```json
61
+ {
62
+ "criterion_id": "A-01",
63
+ "verification_type": "inspection",
64
+ "evidence": {
65
+ "source": "path/to/source",
66
+ "observation": "The observable fact.",
67
+ "revision": "the observed revision"
68
+ },
69
+ "disposition": {
70
+ "authority": "model",
71
+ "result": "satisfied",
72
+ "rationale": "Why the evidence supports this disposition."
73
+ }
74
+ }
75
+ ```
76
+
77
+ `result` is `satisfied`, `gap`, or `not_applicable`. The validator checks the record's
78
+ shape and authority token. It never infers the result from an exit code, digest,
79
+ counter, validator success, or model assertion.
80
+
81
+ ## Typed evidence
82
+
83
+ Use exactly one evidence object for each criterion:
84
+
85
+ - `command`: `{command, cwd, exit_code, raw_evidence_ref, raw_evidence_sha256,
86
+ freshness_identity}`, where freshness identity is
87
+ `{git_head, worktree_digest, observed_at}`.
88
+ - `inspection`: `{source, observation, revision}`.
89
+ - `owner-judgment`: `{owner_record_ref, owner_statement_or_disposition}`. Its
90
+ disposition authority must be `owner`; the model and validator cannot satisfy it.
91
+ - `external-observation`: `{provider, run_id, observed_at, raw_evidence_ref,
92
+ raw_evidence_sha256, observation}`.
93
+
94
+ `raw_evidence_sha256` is the lowercase SHA-256 of the exact bytes named by
95
+ `raw_evidence_ref`. The structural validator requires a normalized, mechanically safe
96
+ repository-relative ref and an exact 64-hex digest; structural mode does not dereference
97
+ the ref. Dev, Test, Status, and Deliver resolve it below the real repository root, require
98
+ every parent and the final file to remain repository-contained and non-symlink, open the
99
+ final ordinary regular file nonblocking and no-follow, cap the snapshot at 8 MiB, and
100
+ compare path and descriptor identity before and after reading. They hash only that one
101
+ bounded stable byte snapshot. A missing, special, symlinked, escaped, oversized, or
102
+ replaced ref is a typed evidence gap with retry or owning-task repair, never accepted
103
+ provenance.
104
+
105
+ `dimensions` contains exactly `tests_written`, `tests_passed`, `persistence_real`,
106
+ `feature_flags_audit`, `vertical_slice`, and `spec_trace`. Each dimension is an explicit
107
+ `{status, evidence_refs, rationale}` observation; its status uses the same three result
108
+ tokens and is not a semantic score.
109
+
110
+ ## Task review
111
+
112
+ First-review admission does not consume this final record. It consumes the ledger's
113
+ `in_progress` row, the task context and acceptance bytes, the immutable review packet,
114
+ and actual pre-review evidence already observed at the four typed authorities. Raw
115
+ outputs and citations may exist before review, but they do not form another evidence
116
+ schema, completion record, or task-status authority. Do not write `evidence.json` before the task's validated final `SUMMARY.json` exists.
117
+
118
+ `task_review` is exactly:
119
+
120
+ ```json
121
+ {
122
+ "execution_packet": {
123
+ "state": "available",
124
+ "digest": "<sha256>",
125
+ "limitation": null
126
+ },
127
+ "session_id": "<review-session>",
128
+ "summary_ref": ".ultra/reviews/<review-session>/SUMMARY.json",
129
+ "summary_digest": "<sha256>",
130
+ "blocking_findings": [
131
+ {
132
+ "id": "<finding-id>",
133
+ "resolution": "<what changed>",
134
+ "disposition": "<resolved, accepted risk, or still a gap>",
135
+ "evidence_refresh_refs": ["<fresh evidence>"]
136
+ }
137
+ ],
138
+ "retention": "<when the derived review may be removed>"
139
+ }
140
+ ```
141
+
142
+ For work that predates Execution Packet v1, use `state: pre-v1-unavailable`, a null
143
+ digest, and a non-empty limitation. Never manufacture a bootstrap digest. Keep the task
144
+ `in_progress` through implementation and blocking review repair. If a repair changes
145
+ implementation or evidence in review scope, create and validate a new immutable review
146
+ session before closeout; do not claim that Worker Packet v1 binds the resulting worktree.
147
+
148
+ ### Task-review provenance branches
149
+
150
+ `task_review` carries exactly one of two discriminated provenance branches. Records
151
+ with no `review_mode` field remain the strict-v4 branch, so every existing v2 record
152
+ and aggregate projection stays valid without migration.
153
+
154
+ The **strict-v4 branch** (`review_mode: "strict-v4"` or absent) is exactly the shape
155
+ above: a real retained `.ultra/reviews/<session>/SUMMARY.json` identity consumed by
156
+ the review waiter and the transport validator.
157
+
158
+ The **external-manual branch** (`review_mode: "external-manual"`) binds one real
159
+ repository-relative JSON receipt published by the owner-designated external reviewer
160
+ under `.ultra/evidence/<task-id>/`, never under `.ultra/reviews/`:
161
+
162
+ ```json
163
+ {
164
+ "review_mode": "external-manual",
165
+ "execution_packet": { "state": "pre-v1-unavailable", "digest": null, "limitation": "..." },
166
+ "receipt_ref": ".ultra/evidence/<task-id>/external-review.json",
167
+ "receipt_sha256": "<sha256-of-exact-receipt-bytes>",
168
+ "blocking_findings": [],
169
+ "retention": "Retain the exact external receipt bytes; it is a reconstructable observation, never semantic authority."
170
+ }
171
+ ```
172
+
173
+ The receipt itself uses `$schema: ultra-external-review-receipt-v1` with exactly
174
+ `reviewer` (identity), `reviewer_role: "read-only"`, `task_id`, `change_id`,
175
+ `reviewer_authority` (`ref` + `sha256` of the owner record authorizing the external
176
+ review mode/reviewer), `reviewed_contract` (`ref` + `sha256` of the reviewed
177
+ contract bytes), `subject` (`git_head` 40-hex + `worktree_digest` 64-hex of the
178
+ reviewed product worktree), `verdict` (`approve | request_changes`), `findings` (an
179
+ exact array of `{id, severity, title}` with severity P0–P3 and unique ids), and an
180
+ RFC 3339 `timestamp`. It is a reconstructable observation of who reviewed what bytes
181
+ with what result — it is not semantic authority, not owner acceptance, and never a
182
+ fabricated strict SUMMARY/ADMISSION/session. Only current P0/P1 (or owner-promoted)
183
+ receipt findings may appear in `blocking_findings`, and the blocking disposition id
184
+ set must equal exactly the receipt's P0/P1 id set: `approve` is rejected with any
185
+ unresolved P0/P1, `request_changes` with none, and P2/P3 stay recorded and
186
+ non-blocking.
187
+
188
+ Receipt verification is mandatory: the normal canonical sensor invocation below
189
+ verifies an external-manual record's receipt automatically, and
190
+ `--verify-external-receipt` remains a compatible alias:
191
+
192
+ ```bash
193
+ node skills/ultra-plan/scripts/validate_task_evidence.cjs \
194
+ .ultra/evidence/<task-id>/evidence.json
195
+ ```
196
+
197
+ The sensor reuses one canonical stable bounded no-follow repository-chain snapshot
198
+ for the receipt, the reviewed contract, and the reviewer-authority record: the real
199
+ repository root and every managed parent must stay ordinary non-symlink directories
200
+ (identities rechecked after reading), and the final entry must be an ordinary
201
+ regular file. It checks only authority/provenance facts: safe normalized receipt
202
+ location inside the task's evidence directory and outside `.ultra/reviews/`, exact
203
+ stable bytes against `receipt_sha256`, the exact receipt schema, task/change
204
+ identity equality with the evidence, reviewed HEAD and product-worktree digest
205
+ equality with the completion subject, exact stable bytes and digests for the
206
+ reviewed contract and the reviewer-authority record, well-formed severities, the
207
+ exact blocker/verdict set, and that every blocking disposition binds a P0/P1
208
+ finding that actually exists in the receipt. A missing, malformed, symlinked,
209
+ special, escaped, oversized, replaced, digest-mismatched, identity- or
210
+ subject-mismatched, unbound-contract, unbound-authority, or substituted receipt
211
+ returns typed reachable repair and is never treated as accepted. It never infers
212
+ semantic acceptance: an `approve` verdict is a recorded observation, and owner
213
+ acceptance remains a separate owner-judgment.
214
+
215
+ The same invocation with `--projection` emits, after successful verification, the
216
+ exact branch-specific aggregate Test projection item for the record. A strict-v4
217
+ record keeps the byte-compatible
218
+ `{task_id, schema, evidence_ref, evidence_digest, task_review_session,
219
+ task_review_summary_digest}` shape; an external-manual record carries
220
+ `{task_id, schema, evidence_ref, evidence_digest, task_review_mode:
221
+ "external-manual", task_review_receipt_ref, task_review_receipt_digest}` instead.
222
+ Test, Status, and Deliver consume that mechanical result verbatim; a strict session
223
+ identity can never substitute for the receipt fields and neither branch's
224
+ projection is rewritten into the other's. The projection is withheld whenever any
225
+ diagnostic is present.
226
+
227
+ Aggregate Test, Status, and Deliver preserve and recheck the declared branch: strict
228
+ items replay the retained strict summary through the existing waiter and transport
229
+ consumers; external-manual items take the bounded stable receipt bytes, recompute
230
+ `receipt_sha256`, and rerun the sensor's verify mode instead. An aggregate
231
+ projection item for an external-manual task substitutes
232
+ `task_review_mode: "external-manual"` plus `task_review_receipt_ref` and
233
+ `task_review_receipt_digest` for the strict `task_review_session` and
234
+ `task_review_summary_digest` fields; strict items keep their existing exact shape.
235
+ No consumer may rewrite one branch into the other or accept a strict SUMMARY where
236
+ the branch declares an external receipt.
237
+ When the newest current-subject summary returns `REQUEST_CHANGES`, consume its exact
238
+ validated `findings` array rather than a count or list copied from any historical summary.
239
+ Preserve every finding id, resolve or authoritatively disposition every current P0/P1,
240
+ and refresh each affected evidence reference before creating one fresh subject and
241
+ review. The blocking disposition set binds only current P0/P1 findings (or a P2 the
242
+ owner promoted after the current review reclassified it as P1 on evidence); P2 and P3
243
+ findings stay recorded in the retained summary as non-blocking backlog and never block
244
+ closeout, and no consumer may implicitly promote them to blockers inside the same task.
245
+ A later summary may contain a different set; that current exact set controls
246
+ recovery.
247
+ After the final validated `SUMMARY.json`, independently capture the completion subject and immediately write one canonical `ultra-task-evidence-v2` record with its separate exact task-review binding.
248
+ Write `completed` to the ledger only after every blocking finding has a disposition,
249
+ relevant evidence is refreshed, the canonical record and context review facts are
250
+ durable, and both are read back.
251
+
252
+ If later work invalidates a completed task, reopening is an explicit recovery action.
253
+ A reopen changes the ledger-authoritative row from `completed` to `in_progress`; there
254
+ is no silent demotion. Before the transition, record the affected criterion IDs and reason in both the context Change Log and Resume Note. Preserve the prior frozen review
255
+ as historical evidence, read the ledger write back, refresh only the affected evidence,
256
+ obtain a new final review, then capture and publish a new completion subject.
257
+
258
+ ## Aggregate Test projection
259
+
260
+ The v2 Test template carries ordered `task_evidence` immediately after `task_ids`.
261
+ Every item is exactly:
262
+
263
+ ```json
264
+ {
265
+ "task_id": "<task-id>",
266
+ "schema": "ultra-task-evidence-v2",
267
+ "evidence_ref": ".ultra/evidence/<task-id>/evidence.json",
268
+ "evidence_digest": "<sha256>",
269
+ "task_review_session": "<review-session>",
270
+ "task_review_summary_digest": "<sha256>"
271
+ }
272
+ ```
273
+
274
+ The evidence digest already binds `context.acceptance_sha256`; do not copy that field
275
+ into the Test projection. Historical `ultra-task-evidence-v1` remains readable and is
276
+ classified `legacy-v1`, but it cannot support a new v2 completion claim without an
277
+ honest migration.
278
+
279
+ The projection preserves each task's independently captured completion-snapshot
280
+ freshness observation and its separate task-review provenance. Aggregate Test binds its
281
+ report subject independently to the current whole Change; it never requires an earlier
282
+ task `subject.worktree_digest` to equal that aggregate digest and never treats the
283
+ retained task-review summary as proof of the completion subject. Instead it independently
284
+ rechecks the current Acceptance bytes, typed criterion IDs and verification types,
285
+ retained strict task-review summary, durable owner records, and every cited affected
286
+ artifact. An invalidated item uses the explicit reopen path above.
287
+
288
+ Run the structural sensor with:
289
+
290
+ ```bash
291
+ node skills/ultra-plan/scripts/validate_task_evidence.cjs \
292
+ .ultra/evidence/<task-id>/evidence.json
293
+ ```
294
+
295
+ The sensor resolves one input path and captures at most 8 MiB from a regular,
296
+ non-symlink file opened nonblocking and no-follow where the platform supports it. It
297
+ compares path and descriptor identity before and after the read, decodes the captured
298
+ bytes as strict UTF-8, and parses JSON from that same snapshot. Typed `input_*`
299
+ diagnostics return control for retry when the path is missing, replaced, oversized,
300
+ non-regular, a symlink, invalid UTF-8, or invalid JSON.