codex-workflow-v2 2.0.0-beta.12.5 → 2.0.0-beta.12.7

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 (39) hide show
  1. package/README.md +29 -3
  2. package/dist/src/alpha6/downstream-proof.d.ts +41 -2
  3. package/dist/src/alpha6/downstream-proof.js +360 -5
  4. package/dist/src/alpha6/downstream-proof.js.map +1 -1
  5. package/dist/src/alpha6/plan-risk.js +2 -2
  6. package/dist/src/alpha6/plan-risk.js.map +1 -1
  7. package/dist/src/cli.js +57 -1
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/contracts.d.ts +44 -1
  10. package/dist/src/dependency-provenance.d.ts +9 -2
  11. package/dist/src/dependency-provenance.js +49 -5
  12. package/dist/src/dependency-provenance.js.map +1 -1
  13. package/dist/src/git.d.ts +1 -1
  14. package/dist/src/git.js +4 -2
  15. package/dist/src/git.js.map +1 -1
  16. package/dist/src/version.d.ts +1 -1
  17. package/dist/src/version.js +1 -1
  18. package/dist/src/workflow.d.ts +11 -1
  19. package/dist/src/workflow.js +434 -28
  20. package/dist/src/workflow.js.map +1 -1
  21. package/docs/autonomy-guardrails.md +7 -0
  22. package/docs/development-flow.md +16 -0
  23. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  24. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  25. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  26. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +26 -6
  27. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +27 -7
  28. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +34 -12
  29. package/docs/release.md +11 -1
  30. package/docs/updating-existing-project.md +61 -2
  31. package/docs/validation-report.md +92 -83
  32. package/package.json +2 -1
  33. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +1 -1
  34. package/plugins/codex-workflow-gateway/references/protocol.md +12 -1
  35. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +33 -1
  36. package/schemas/downstream-proof-invalidation-event.schema.json +1 -0
  37. package/schemas/downstream-proof-replan-recovery-event.schema.json +61 -0
  38. package/schemas/task.schema.json +56 -0
  39. package/scripts/generate-pdf-docs.py +13 -2
@@ -1,101 +1,110 @@
1
- # V2 beta.12.5 Validation Report
1
+ # V2 beta.12.7 Validation Report
2
2
 
3
- Release candidate `2.0.0-beta.12.5` was validated on 2026-08-29 (Europe/Moscow) with
3
+ Release candidate `2.0.0-beta.12.7` was validated on 2026-08-29 (Europe/Moscow) with
4
4
  Node.js 24.17.0.
5
5
 
6
6
  ## Automated release evidence
7
7
 
8
- - The pre-install `npm run validate` passed typecheck and `332/332` sequential tests with no
9
- failures, skips, cancellations, or todos in 1,313,147.293583 ms.
10
- - `npm ci` then completed from the lockfile with 0 reported vulnerabilities. The clean-install
11
- `npm run validate` independently passed the same `332/332` tests in 1,312,649.239333 ms.
12
- - A final credential-recovery review then added one mapping and one regression test for an eligible
13
- claimed C1 recovery whose writer lease is absent. Post-change typecheck and the focused
14
- downstream-proof, CLI-help, and lifecycle-model suite passed `15/15`; the final full
15
- `npm run validate` passed `333/333` tests with no failures, skips, cancellations, or todos in
16
- 1,321,160.33825 ms.
17
- - The suite covers the beta.12.5 downstream-proof recovery, exact lifecycle inventory, C1 yield,
18
- one-writer concurrency, transaction crash boundaries, tampered sidecars, unrelated dirty files,
19
- ordinary active-Step completion, existing Signal T04 recovery, dependency DAG, observer purity,
20
- credential secrecy, corrective replay, and Milestone validation/acceptance.
21
- - `npm run pack:check` built the exact beta.12.5 package: 274 files, 995.1 kB packed and 3.9 MB
22
- unpacked. The first sandboxed attempt could not write the user npm cache (`EPERM`); the exact
23
- authorized retry passed and included the new runtime module and public schema.
8
+ - `npm ci` completed from the lockfile with 0 reported vulnerabilities.
9
+ - The final post-fix `npm run validate` passed typecheck and `338/338` sequential tests with no
10
+ failures, skips, cancellations, or todos in 1,641,977.92675 ms. The same suite also passed after
11
+ the clean install (`338/338` in 1,661,195.192667 ms) and before it (`338/338` in
12
+ 1,347,257.496667 ms).
13
+ - `npm run test:signal-t03-replan-e2e` independently passed the full Signal-shaped compatibility
14
+ scenario. The focused dependency-provenance, downstream-proof, and lifecycle-model suite passed
15
+ `23/23`.
16
+ - The Signal-shaped E2E starts with the exact six-path ownership split and the beta.12.6 accidental
17
+ post-invalidation Knowledge rebind. It then proves: read-only source eligibility, two
18
+ dependency-only transport commits, `HEAD^`/`HEAD` provenance validation, bounded dependency
19
+ registration, atomic replan recovery, required Project Knowledge refresh, mandatory replacement
20
+ `plan-set`, one-Step dirty carryover admission, hostile concurrency and rollback/restart checks,
21
+ Core-owned Step commit, passed strict Step Review, and fresh navigation to `task submit`.
22
+ - Negative regressions reject stale Plan rebind, unrelated dirty files, changed content hash,
23
+ unknown history, a wider dependency candidate, current legacy-Plan audit/authorization, extra Task
24
+ revisions, active lease, pending transaction, corrupted invalidation/recovery sidecars, and a
25
+ replacement Plan that does not give one Step authority over the complete dirty set.
26
+ - `npm run pack:check` built the exact beta.12.7 package: 275 files, 1.0 MB packed and 4.1 MB
27
+ unpacked. The sandboxed attempt
28
+ could not write the user npm cache (`EPERM`); the exact authorized retry passed.
24
29
  - `npm run smoke:downstream` packed and installed the tarball in a disposable consumer project and
25
30
  returned `ok=true`. The sandboxed attempt could not resolve the npm registry (`ENOTFOUND`); the
26
31
  exact network-authorized retry passed.
27
- - `npm run plugin:check`, `npm run docs:pdf:check`, exact
28
- `RELEASE_TAG=v2.0.0-beta.12.5 npm run release:check`, and `git diff --check` passed. The bundled
29
- gateway cachebuster remains `0.1.0+codex.20260828064343`.
32
+ - `npm run plugin:check`, `npm run docs:pdf:check`, and exact
33
+ `RELEASE_TAG=v2.0.0-beta.12.7 npm run release:check` passed after the final source changes. The
34
+ bundled gateway cachebuster is `0.1.0+codex.20260829143747`.
30
35
 
31
- ## Root cause and bounded correction
36
+ ## Root causes corrected by beta.12.7
32
37
 
33
- - A downstream executable proof can demonstrate that a completed predecessor Step must change.
34
- The existing navigation still advertised `task step-complete`, but that command correctly
35
- rejected predecessor-owned dirty files. Repeating the command or increasing remediation attempts
36
- could not solve the authority contradiction: predecessor completion evidence remained canonical
37
- while the proof required changing its output.
38
- - beta.12.5 adds `task downstream-proof-recover`. It is advertised only when every dirty file
39
- outside the active Step belongs to a completed transitive predecessor, Task branch/Plan/history
40
- bindings are exact, the active Step has no completion evidence, and the Task uses a local
41
- workspace. Unrelated files, damaged history, a branch mismatch, a malformed audit journal, or an
42
- unregistered commit fail closed to `doctor`.
43
- - One crash-recoverable project transaction preserves worktree bytes and HEAD, append-only records
44
- `downstream-proof-invalidations.jsonl`, moves invalidated product commits to historical
45
- `invalidatedStepCommits`, clears stale Step/review/execution authority, yields claimed C1, removes
46
- the writer lease, and returns the same Task to ordinary `task plan-set`.
47
- - No completed-Step adoption or synthetic replacement Task is performed. The replacement Plan must
48
- re-cover the unfinished proof and invalidated predecessor work, then pass normal audit,
49
- authorization, execution, and review again.
38
+ - beta.12.6 correctly invalidated the completed migration predecessor and required a replacement
39
+ Plan. A later Project Knowledge approval nevertheless mechanically rebound the rejected two-Step
40
+ Plan and returned the Task to `awaiting_execution_authorization`. The required `plan-set` boundary
41
+ was therefore lost.
42
+ - The stranded state could not be fixed by another review attempt: no Step was runnable and the
43
+ current Plan was the artifact whose authority had already been rejected. The defect was routing
44
+ and recovery authority, not insufficient implementation effort.
45
+ - A one-transition repair was also insufficient. The full E2E exposed two additional dead ends:
46
+ the exact dependency-only update makes Project Knowledge stale before repair, and the ordinary
47
+ `task run` clean-checkout precondition rejected the deliberately preserved dirty bytes even after
48
+ a correct replacement Plan.
49
+ - beta.12.7 adds a closed compatibility sequence. The external source preflight recognizes only the
50
+ exact beta.12.6 stranded shape. Dependency registration binds the update commit to the original
51
+ invalidation, rebound Plan, preserved HEAD, dirty paths, and content hash. Replan recovery returns
52
+ the same Task to `needs_fix` without requiring the now-stale live Knowledge Map to be active.
53
+ - Project Knowledge can then be reconciled and approved, but refresh/rebind routing cannot replace
54
+ the mandatory `task plan-set`. The old Plan receives no execution authority.
55
+ - Dirty bytes are not adopted as completed evidence. After a fresh Plan Risk Audit and execution
56
+ authorization, `task run` permits carryover only when one planned Step owns every bound path and
57
+ current HEAD/path/content hashes exactly match the recovery event. All ordinary checks, Core Git
58
+ ownership, and strict-review requirements remain in force.
50
59
 
51
- ## Exact Signal read-only proof
60
+ ## Exact Signal project evidence
52
61
 
53
- - The final built beta.12.5 classifier inspected Signal repository
54
- `/Users/home-pc/htdocs/projects/signal_v4`, project
55
- `b06d0f18f790f4521a23c770`, and Task
56
- `TASK-01M0WXJAD4GZGVNRJ284ND95C6` without mutating repository or Workflow state.
57
- - Persisted Task revision is 103 on branch
58
- `codex/task-01m0wxjad4-processing-persistence-schema`; active Step is
59
- `STEP-002-REAL-POSTGRES-PROOF`. HEAD is
60
- `88f8bf70d1591852ad90c976625430d4f20585ac`.
61
- - The classifier observed six dirty files. Five are outside the active Step and are owned by the
62
- completed transitive predecessor `STEP-001-PROCESSING-MIGRATIONS`; the sixth,
63
- `tools/postgres/run-processing-integration.ts`, belongs to the active proof Step. The predecessor
64
- evidence commit equals the preserved HEAD.
65
- - The result was `applicable=true`, `eligible=true`, with no blockers. This proves that the exact
66
- current Signal boundary has a bounded beta.12.5 transition. It does not prove that the replacement
67
- Plan, product checks, strict review, or the remainder of Milestone 3 will pass.
62
+ - The Signal repository `/Users/home-pc/htdocs/projects/signal_v4` was inspected and exercised on
63
+ branch `codex/task-01m0wxjad4-processing-persistence-schema` at
64
+ `4606eaf98f3c5f1f0dec4c361f34e2abe9aefa66`.
65
+ - Its Workflow remains on exact `2.0.0-beta.12.6`. Task
66
+ `TASK-01M0WXJAD4GZGVNRJ284ND95C6` remains revision 106 and
67
+ `awaiting_execution_authorization`; live Workflow state was not mutated by beta.12.7 validation.
68
+ - The dirty set remains exactly six paths: five modified processing-migration files and untracked
69
+ `tools/postgres/run-processing-integration.ts`. After temporary hostile-test additions were
70
+ removed, the beta.12.7 source preflight returned `eligible=true`, empty blockers, the preserved
71
+ HEAD above, and dirty-worktree SHA-256
72
+ `1cbeb0ccb4883ade6f2ea751423385cf504f5c18e45473f40cb9a39ca850ece1`.
73
+ - The real Signal PostgreSQL harness was temporarily extended with two concurrent migrators and a
74
+ forced mid-migration conflict followed by restart. `npm run processing:postgres:test` passed clean
75
+ bootstrap/repeat, advisory-lock serialization, transaction rollback with no partial ledger/schema,
76
+ unchanged restart convergence, tamper/order denial, catalog fingerprint, immutable evidence, and
77
+ least-privilege checks against the pinned PostgreSQL image.
78
+ - Those temporary product changes were then removed exactly and the original runner bytes were
79
+ verified against a parallel Signal checkout before the recovery fingerprint was re-read. This
80
+ proves product feasibility without falsely presenting pre-authorized test bytes to Workflow.
81
+ - This is strong live read-only entry evidence plus real product proof. It is not a claim that the
82
+ unpublished beta.12.7 package has already updated Signal or mutated its Task. Final live continuation
83
+ still requires release publication, exact dependency-only transport, and following fresh
84
+ project-local `next` through the tested sequence.
68
85
 
69
- ## Sandbox-boundary prevention
86
+ ## PDF release documentation evidence
70
87
 
71
- - The bundled gateway now classifies Docker socket/CLI `EPERM`, `operation not permitted`, and
72
- `permission denied` from a sandbox as an execution-boundary failure, not evidence that the daemon,
73
- image, or product infrastructure is broken.
74
- - It permits one exact escalated read-only probe or Plan check without consuming a remediation or
75
- infrastructure retry. Docker Desktop restart, daemon mutation, or image substitution still
76
- requires separate authority and an actual escalated daemon failure.
77
- - Plugin validation pins this guidance. The release gates exercised analogous npm cache/network
78
- sandbox boundaries, but no live Docker daemon failure was synthesized; Docker runtime behavior is
79
- therefore documentation/gateway-contract evidence, not an end-to-end Docker test claim.
80
-
81
- ## beta.12.5 PDF release documentation evidence
82
-
83
- - Three tracked Russian PDFs were regenerated from Markdown sources; `npm run docs:pdf:check`
84
- reported an empty stale set.
85
- - All 27 pages were rendered and visually inspected: architecture is 7 pages, the delegated
86
- chat-only guide is 9 pages, and the technical reference is 11 pages. The changed recovery,
87
- Docker-boundary, command-surface, and release pages have no visible clipping, overlap, or
88
- unreadable content.
89
- - Visible titles, headers, commands, capabilities, and release gates identify beta.12.5.
88
+ - Three tracked Russian PDFs were regenerated from current Markdown sources;
89
+ `npm run docs:pdf:check` reported an empty stale set.
90
+ - All 28 pages were rendered and visually inspected: architecture is 8 pages, the delegated
91
+ chat-only guide is 9 pages, and the technical reference is 11 pages.
92
+ - Titles, beta.12.7 version headers, Cyrillic glyphs, tables, code blocks, new recovery commands,
93
+ page edges, and footers show no visible clipping, overlap, or unreadable content.
90
94
 
91
95
  ## Existing boundaries and non-claims
92
96
 
93
- - Structural replacement remains intentionally disabled. beta.12.5 does not implement P04-B,
97
+ - Structural replacement remains intentionally disabled. beta.12.7 does not implement P04-B,
94
98
  topology rewiring, completed-Step adoption, or a wider delegation surface.
95
- - Recovery requires exact one-writer/C1 authority and a fresh `next`; it does not authorize manual
96
- state edits, arbitrary Git history, unrelated dirty files, or automatic approval.
97
- - Validation performed no Signal mutation, npm publication, Git commit, tag, remote push, or local
98
- plugin reinstall. Those remain separate release actions.
99
- - A consumer must install the published exact beta.12.5 package, reinstall the bundled gateway, and
100
- follow fresh project-local `handshake -> doctor -> status -> next` navigation before invoking the
101
- advertised recovery.
99
+ - The new bridge is limited to the proven beta.12.6 invalidation-plus-accidental-rebind sequence.
100
+ It is not a general permission for dirty update, arbitrary Plan rollback, or manual state repair.
101
+ - A negative Plan Risk Audit decision may truthfully return the same Task to planning, but no
102
+ automatic component decides product semantics or widens Task objective, requirements, acceptance,
103
+ or Milestone topology.
104
+ - Git transport commits remain agent-executed operations on exact advertised boundaries. Runtime
105
+ does not create, amend, merge, reset, publish, tag, or push release history.
106
+ - Validation performed no npm publication, Git commit, tag, remote push, Signal dependency update,
107
+ or local plugin reinstall. Those remain separate release/deployment actions.
108
+ - Confidence is high for the implementation, package artifact, synthetic Workflow E2E, and real
109
+ PostgreSQL proof. Confidence in final live Signal continuation remains conditional on installing
110
+ the published exact package and observing the same project-local recovery sequence.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-workflow-v2",
3
- "version": "2.0.0-beta.12.5",
3
+ "version": "2.0.0-beta.12.7",
4
4
  "description": "Requirements-first Codex development workflow with local state and explicit Git ownership.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -44,6 +44,7 @@
44
44
  "typecheck": "tsc -p tsconfig.json --noEmit",
45
45
  "test": "node scripts/with-validation-lock.mjs test",
46
46
  "test:signal-t04-recovery": "node scripts/with-validation-lock.mjs test-signal-t04",
47
+ "test:signal-t03-replan-e2e": "node scripts/with-validation-lock.mjs test-signal-t03-replan",
47
48
  "validate": "npm run typecheck && npm test",
48
49
  "pack:check": "npm run build && npm pack --dry-run",
49
50
  "smoke:downstream": "npm run build && node scripts/downstream-smoke.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-workflow-gateway",
3
- "version": "0.1.0+codex.20260828064343",
3
+ "version": "0.1.0+codex.20260829143747",
4
4
  "description": "Thin personal Codex gateway for exact project-local Codex Workflow V2 packages and codebase-memory-mcp.",
5
5
  "author": {
6
6
  "name": "Codex Workflow Maintainers"
@@ -1,6 +1,6 @@
1
1
  # Gateway Protocol V2
2
2
 
3
- ## beta.12.5 compatibility transitions and continuable remediation
3
+ ## beta.12.6 compatibility transitions and continuable remediation
4
4
 
5
5
  - When fresh `next` advertises `task plan-integrity-recover`, consume its exact Task revision,
6
6
  Step, actor, and writer-token contract. This route is valid only for the Core-derived
@@ -15,6 +15,16 @@
15
15
  and routes the same Task to ordinary `task plan-set`. The replacement Plan, risk audit, and
16
16
  execution authorization are fresh authority; no Task or Milestone recreation is involved.
17
17
 
18
+ - When an older installed package cannot reach that recovery because its normal update preflight
19
+ requires a clean checkout, beta.12.6 permits one bounded dependency transport. The active
20
+ Milestone base and Task branch must first receive separate exact commits changing only
21
+ `package.json` and `package-lock.json`; product work remains dirty and uncommitted. Fresh beta.12.6
22
+ `next` must then advertise `update downstream-proof-dependency-recover`. Its preflight proves the
23
+ Task history at `HEAD^`, the dependency candidate at `HEAD`, aligned version surfaces, no lease or
24
+ transaction, exact predecessor ownership, and a content hash of the dirty set. Recovery registers
25
+ only the dependency commit. It does not mutate product files or Step state; fresh `next` must
26
+ proceed to `task downstream-proof-recover`, which outranks manifest-induced Knowledge staleness.
27
+
18
28
  - `update dependency-provenance-preflight --id <TASK-ID>` is read-only. The matching
19
29
  `update dependency-provenance-recover --id <TASK-ID> --expected-revision <N> --actor <ACTOR>
20
30
  --reason <TEXT>` is valid only when preflight and fresh `next` both advertise it. Historical
@@ -108,6 +118,7 @@ Current capability set:
108
118
  - `plan-proof-obligations-v1`
109
119
  - `bounded-plan-integrity-recovery-v1`
110
120
  - `downstream-proof-predecessor-recovery-v1`
121
+ - `active-downstream-proof-dependency-recovery-v1`
111
122
  - `corrective-yield-journal-v1`
112
123
  - `corrective-replan-journal-v1`
113
124
  - `corrective-replan-human-gate-v1`
@@ -123,7 +123,7 @@ command shape or consuming a replacement Discovery. Never rebind, refresh, repla
123
123
  resume, cancel, or manually replace the historical Task. Continue only after a later P04-B/P05
124
124
  package explicitly advertises a topology-preserving replacement capability.
125
125
 
126
- When beta.12.5 `next` advertises `task stop-override-prepare`, the route is limited to the exact
126
+ When beta.12.6 `next` advertises `task stop-override-prepare`, the route is limited to the exact
127
127
  beta.11 attempt-four policy stop: two ordinary failures, one corrective failure, a matching
128
128
  attempt-3 `continue-fix`, and a matching attempt-4 `stop-escalate` under the unchanged Plan. Invoke
129
129
  prepare with the exact Task/Step/revision, explicit human actor, and user-supplied reason. It is
@@ -149,6 +149,38 @@ Core may account for exactly one Task revision per ordered verified recovery. Ne
149
149
  compatibility from revision arithmetic alone: continue only when fresh `next` returns the validated
150
150
  `task run` route. An unrelated extra revision remains a hard stop.
151
151
 
152
+ For the exact beta.12.6 active-downstream-proof update deadlock, do not apply the ordinary
153
+ clean-boundary update recipe and do not stash/reset/commit product work. This exception is available
154
+ only when a completed transitive predecessor and the active proof Step already own the complete dirty
155
+ set, no writer lease/transaction/Core operation exists, and the active Milestone base can be updated
156
+ in a separate worktree. Commit only exact `package.json`/`package-lock.json` dependency changes on
157
+ that base, then commit only the same dependency files on the current Task branch while leaving all
158
+ product bytes untouched. Install the exact beta.12.6 package and use only a fresh advertised
159
+ `update downstream-proof-dependency-recover`. Run its read-only preflight first and require
160
+ `eligible=true`, empty blockers, exact Task revision and non-null `activeDownstreamProof` binding.
161
+ Require recorded Task history to validate at `HEAD^` and the exact dependency-only candidate to be
162
+ `HEAD`; neither boundary may contain an unrelated or unregistered commit. The mutation registers
163
+ only the dependency HEAD. Immediately run sequential `status` then `next`;
164
+ continue only to the returned `task downstream-proof-recover` (including advertised writer-credential
165
+ recovery when required). Any unrelated dirty path, unknown history, wider candidate commit, stale
166
+ base, version mismatch, lease, transaction, or different route is a hard stop and never authorizes
167
+ manual external-state edits.
168
+
169
+ For the exact beta.12.6 post-recovery knowledge-rebind deadlock, an exact beta.12.7 external runner
170
+ may execute only the read-only `update downstream-proof-replan-update-preflight` before dependency
171
+ transport. Require `eligible=true`, source version beta.12.6 on declared/locked/installed/current/base
172
+ surfaces, the exact Task revision/HEAD/dirty hash, no current audit for the rebound Plan, and no lease,
173
+ transaction, or Core operation. Commit only `package.json` and `package-lock.json` on the active
174
+ Milestone base, then only the same dependency files on the Task branch without touching product
175
+ bytes. Install beta.12.7 and follow fresh `next` only through
176
+ `update downstream-proof-replan-dependency-recover`, then
177
+ `task downstream-proof-replan-recover`, and finally ordinary `task plan-set`. The recovery keeps the
178
+ same Task, history, Knowledge binding, invalidated predecessor evidence, and dirty worktree. After
179
+ the replacement Plan is audited and authorized, `task run` is valid only when fresh `next` reports
180
+ `downstreamProofCarryover.state=validated` for one Step owning the complete hash-bound dirty set.
181
+ Any wider dependency commit, dirty-byte change, current audit, extra Task revision, missing binding,
182
+ or alternate route is a hard stop.
183
+
152
184
  When `next` returns `milestone initial-assembly`, execution is unavailable. Follow only the
153
185
  advertised `linked-task-assembly.commands` (`discovery start` and `discovery materialize`) until all
154
186
  intended linked Tasks exist. The closing `milestone plan-set` option appears only after at least one
@@ -52,6 +52,7 @@
52
52
  "uniqueItems": true,
53
53
  "items": { "type": "string", "minLength": 1 }
54
54
  },
55
+ "dirtyWorktreeHash": { "$ref": "#/$defs/hash64" },
55
56
  "preservedHeadCommit": { "$ref": "#/$defs/gitHash" },
56
57
  "actor": { "type": "string", "minLength": 1 },
57
58
  "reason": { "type": "string", "minLength": 1 },
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://codex-workflow.local/schemas/downstream-proof-replan-recovery-event.schema.json",
4
+ "title": "Codex Workflow V2 Downstream Proof Replan Recovery Event",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "eventId",
9
+ "taskId",
10
+ "previousTaskRevision",
11
+ "resultTaskRevision",
12
+ "invalidationEventId",
13
+ "invalidationPlanHash",
14
+ "reboundPlanHash",
15
+ "knowledgeRebindRecordedAt",
16
+ "dirtyFiles",
17
+ "dirtyWorktreeHash",
18
+ "preservedHeadCommit",
19
+ "dependencyRecoveryCommit",
20
+ "actor",
21
+ "reason",
22
+ "packageVersion",
23
+ "previousEventHash",
24
+ "recordedAt",
25
+ "eventHash"
26
+ ],
27
+ "properties": {
28
+ "eventId": { "type": "string", "pattern": "^DPR-[0-9A-HJKMNP-TV-Z]{26}$" },
29
+ "taskId": { "type": "string", "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
30
+ "previousTaskRevision": { "type": "integer", "minimum": 1 },
31
+ "resultTaskRevision": { "type": "integer", "minimum": 2 },
32
+ "invalidationEventId": { "type": "string", "pattern": "^DPI-[0-9A-HJKMNP-TV-Z]{26}$" },
33
+ "invalidationPlanHash": { "$ref": "#/$defs/hash64" },
34
+ "reboundPlanHash": { "$ref": "#/$defs/hash64" },
35
+ "knowledgeRebindRecordedAt": { "type": "string", "format": "date-time" },
36
+ "dirtyFiles": {
37
+ "type": "array",
38
+ "minItems": 1,
39
+ "uniqueItems": true,
40
+ "items": { "type": "string", "minLength": 1 }
41
+ },
42
+ "dirtyWorktreeHash": { "$ref": "#/$defs/hash64" },
43
+ "preservedHeadCommit": { "$ref": "#/$defs/gitHash" },
44
+ "dependencyRecoveryCommit": {
45
+ "anyOf": [
46
+ { "$ref": "#/$defs/gitHash" },
47
+ { "type": "null" }
48
+ ]
49
+ },
50
+ "actor": { "type": "string", "minLength": 1 },
51
+ "reason": { "type": "string", "minLength": 1 },
52
+ "packageVersion": { "type": "string", "minLength": 1 },
53
+ "previousEventHash": { "anyOf": [{ "$ref": "#/$defs/hash64" }, { "type": "null" }] },
54
+ "recordedAt": { "type": "string", "format": "date-time" },
55
+ "eventHash": { "$ref": "#/$defs/hash64" }
56
+ },
57
+ "$defs": {
58
+ "gitHash": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
59
+ "hash64": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
60
+ }
61
+ }
@@ -78,6 +78,62 @@
78
78
  "type": "array",
79
79
  "uniqueItems": true,
80
80
  "items": { "type": "string", "pattern": "^[a-f0-9]{40}$" }
81
+ },
82
+ "activeDownstreamProof": {
83
+ "type": "object",
84
+ "required": ["activeStepId", "planHash", "dirtyFiles", "dirtyWorktreeHash", "invalidatedStepIds"],
85
+ "properties": {
86
+ "activeStepId": { "type": "string", "pattern": "^STEP-[A-Z0-9][A-Z0-9-]{2,63}$" },
87
+ "planHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
88
+ "dirtyFiles": {
89
+ "type": "array",
90
+ "minItems": 1,
91
+ "uniqueItems": true,
92
+ "items": { "type": "string", "minLength": 1 }
93
+ },
94
+ "dirtyWorktreeHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
95
+ "invalidatedStepIds": {
96
+ "type": "array",
97
+ "minItems": 1,
98
+ "uniqueItems": true,
99
+ "items": { "type": "string", "pattern": "^STEP-[A-Z0-9][A-Z0-9-]{2,63}$" }
100
+ }
101
+ },
102
+ "additionalProperties": false
103
+ },
104
+ "downstreamProofReplan": {
105
+ "type": "object",
106
+ "required": [
107
+ "invalidationEventId",
108
+ "activeStepId",
109
+ "sourcePlanHash",
110
+ "reboundPlanHash",
111
+ "knowledgeRebindRecordedAt",
112
+ "dirtyFiles",
113
+ "dirtyWorktreeHash",
114
+ "invalidatedStepIds"
115
+ ],
116
+ "properties": {
117
+ "invalidationEventId": { "type": "string", "pattern": "^DPI-[0-9A-HJKMNP-TV-Z]{26}$" },
118
+ "activeStepId": { "type": "string", "pattern": "^STEP-[A-Z0-9][A-Z0-9-]{2,63}$" },
119
+ "sourcePlanHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
120
+ "reboundPlanHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
121
+ "knowledgeRebindRecordedAt": { "type": "string", "format": "date-time" },
122
+ "dirtyFiles": {
123
+ "type": "array",
124
+ "minItems": 1,
125
+ "uniqueItems": true,
126
+ "items": { "type": "string", "minLength": 1 }
127
+ },
128
+ "dirtyWorktreeHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
129
+ "invalidatedStepIds": {
130
+ "type": "array",
131
+ "minItems": 1,
132
+ "uniqueItems": true,
133
+ "items": { "type": "string", "pattern": "^STEP-[A-Z0-9][A-Z0-9-]{2,63}$" }
134
+ }
135
+ },
136
+ "additionalProperties": false
81
137
  }
82
138
  },
83
139
  "additionalProperties": false
@@ -200,6 +200,14 @@ def styles() -> dict[str, ParagraphStyle]:
200
200
  leading=10.3,
201
201
  textColor=TEXT,
202
202
  ),
203
+ "table_header": ParagraphStyle(
204
+ "TableHeader",
205
+ parent=base["BodyText"],
206
+ fontName="WorkflowBold",
207
+ fontSize=7.7,
208
+ leading=10.3,
209
+ textColor=colors.white,
210
+ ),
203
211
  "code": ParagraphStyle(
204
212
  "Code",
205
213
  parent=base["BodyText"],
@@ -316,8 +324,11 @@ def markdown_story(lines: list[str], style: dict[str, ParagraphStyle]) -> list:
316
324
  column_count = max(len(row) for row in rows)
317
325
  normalized = [row + [""] * (column_count - len(row)) for row in rows]
318
326
  rendered = [
319
- [Paragraph(inline_markup(cell), style["small"]) for cell in row]
320
- for row in normalized
327
+ [
328
+ Paragraph(inline_markup(cell), style["table_header"] if row_index == 0 else style["small"])
329
+ for cell in row
330
+ ]
331
+ for row_index, row in enumerate(normalized)
321
332
  ]
322
333
  table = LongTable(rendered, colWidths=table_widths(column_count), repeatRows=1)
323
334
  table.setStyle(TableStyle([