codex-workflow-v2 2.0.0-beta.12.4 → 2.0.0-beta.12.6

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 (36) hide show
  1. package/README.md +31 -4
  2. package/dist/src/alpha6/downstream-proof.d.ts +34 -0
  3. package/dist/src/alpha6/downstream-proof.js +296 -0
  4. package/dist/src/alpha6/downstream-proof.js.map +1 -0
  5. package/dist/src/cli.js +32 -1
  6. package/dist/src/cli.js.map +1 -1
  7. package/dist/src/contracts.d.ts +34 -1
  8. package/dist/src/dependency-provenance.d.ts +8 -1
  9. package/dist/src/dependency-provenance.js +36 -5
  10. package/dist/src/dependency-provenance.js.map +1 -1
  11. package/dist/src/git.d.ts +1 -1
  12. package/dist/src/git.js +5 -2
  13. package/dist/src/git.js.map +1 -1
  14. package/dist/src/version.d.ts +1 -1
  15. package/dist/src/version.js +1 -1
  16. package/dist/src/workflow.d.ts +8 -0
  17. package/dist/src/workflow.js +224 -8
  18. package/dist/src/workflow.js.map +1 -1
  19. package/docs/autonomy-guardrails.md +16 -0
  20. package/docs/development-flow.md +19 -0
  21. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  22. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  23. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  24. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +27 -6
  25. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +28 -8
  26. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +42 -14
  27. package/docs/release.md +11 -1
  28. package/docs/updating-existing-project.md +37 -2
  29. package/docs/validation-report.md +95 -82
  30. package/package.json +1 -1
  31. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +1 -1
  32. package/plugins/codex-workflow-gateway/references/protocol.md +27 -1
  33. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +43 -1
  34. package/schemas/downstream-proof-invalidation-event.schema.json +70 -0
  35. package/schemas/task.schema.json +27 -0
  36. package/scripts/generate-pdf-docs.py +13 -2
@@ -1,98 +1,111 @@
1
- # V2 beta.12.4 Validation Report
1
+ # V2 beta.12.6 Validation Report
2
2
 
3
- Release candidate `2.0.0-beta.12.4` was validated on 2026-08-28 (Europe/Moscow) with
3
+ Release candidate `2.0.0-beta.12.6` 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
- - `npm ci` completed from the lockfile with 0 reported vulnerabilities.
9
- - The final `npm run validate` passed typecheck and `328/328` sequential tests with no failures,
10
- skips, cancellations, or todos in 1,348,269.052041 ms.
11
- - The suite includes the beta.12.4 real-order replay (`stop override -> context refresh -> base
12
- transport -> dependency provenance recovery -> task run`) and two fail-closed controls: an
13
- unexplained Task revision and damaged post-audit dependency provenance. Existing beta.12.3
14
- chained rebind, Signal T04, five-cycle remediation, transaction, credential, observer-purity,
15
- dependency DAG, transition-catalog, and lifecycle transcript tests also remained green.
16
- - `npm run pack:check` built the exact beta.12.4 package and reported a 270-file tarball. The first
17
- sandboxed attempt could not write the existing npm cache (`EPERM`); the authorized retry using
18
- the same source passed.
19
- - `npm run smoke:downstream` packed and installed the tarball in a clean temporary project and
20
- passed its packaged handshake. The sandboxed attempt could not resolve the npm registry for AJV;
21
- the authorized network retry using the same source passed.
22
- - `npm run plugin:check`, the official Codex plugin validator, the gateway skill validator,
23
- `npm run docs:pdf:check`, exact `RELEASE_TAG=v2.0.0-beta.12.4 npm run release:check`, and
24
- `git diff --check` passed. The bundled gateway cachebuster is
25
- `0.1.0+codex.20260828064343`.
8
+ - The first full `npm run validate` passed typecheck and `335/335` sequential tests with no
9
+ failures, skips, cancellations, or todos in 1,461,147.464875 ms.
10
+ - `npm ci` then completed from the lockfile with 0 reported vulnerabilities. The clean-install
11
+ `npm run validate` independently passed the same `335/335` tests with no failures, skips,
12
+ cancellations, or todos in 1,461,906.892 ms.
13
+ - The exact Signal T04/downstream recovery gate passed `8/8`. The targeted dependency-provenance,
14
+ downstream-proof, CLI-help, and lifecycle-model suite passed `23/23`.
15
+ - The positive beta.12.6 fixture proves the complete compatibility sequence: exact active-base and
16
+ Task dependency commits, history validation at `HEAD^`, candidate validation at `HEAD`, dirty
17
+ content binding, dependency registration, fresh navigation to `task downstream-proof-recover`,
18
+ unchanged product bytes, and valid recorded Task history. Negative cases cover unrelated dirty
19
+ files, unregistered history, and an active writer lease. Existing Signal T04 tests remain intact.
20
+ - `npm run pack:check` built the exact beta.12.6 package: 274 files, 1.0 MB packed and 4.0 MB
21
+ unpacked. The first attempt could not write the user npm cache (`EPERM`); the exact retry used an
22
+ isolated temporary cache and passed without changing global cache ownership.
23
+ - `npm run smoke:downstream` packed and installed the tarball in a disposable consumer project and
24
+ returned `ok=true`. The sandboxed attempt could not resolve the npm registry (`ENOTFOUND`); the
25
+ exact network-authorized retry passed.
26
+ - `npm run plugin:check`, `npm run docs:pdf:check`, and exact
27
+ `RELEASE_TAG=v2.0.0-beta.12.6 npm run release:check` passed. The plugin gate caught one missing
28
+ `HEAD^` boundary in the human-facing gateway instructions; that boundary was added and the gate
29
+ then passed. The bundled gateway cachebuster is `0.1.0+codex.20260829120000`.
26
30
 
27
- ## Root cause and bounded correction
31
+ ## Root cause corrected by beta.12.6
28
32
 
29
- - beta.12.3 validated the chained Knowledge-only Plan rebind and the exact Git
30
- dependency-provenance chain, but retained the older Task-revision predicate
31
- `reboundAudit.taskRevision + 1 === task.revision` for a failed Step.
32
- - Signal's actual install flow created the last mechanical Plan Risk Audit at Task revision 22,
33
- wrote the atomic context-refresh result at revision 23, then registered one advertised
34
- dependency-provenance recovery at revision 24. The old predicate therefore rejected valid,
35
- already-verified administrative evidence at the next navigation step.
36
- - beta.12.4 derives the exact authorization boundary as
37
- `reboundAudit.taskRevision + 1 + verifiedPostAuditRecoveries.length`. Only recovery records from
38
- the already validated stop-override-to-authorization Git chain count. Each record must remain
39
- ordered, single-parent, present in `systemCommits`, and an exact `package.json` plus
40
- `package-lock.json` Workflow dependency commit.
41
- - This is not a permissive `revision >=` rule. An unrelated state write, duplicate or malformed
42
- recovery, wrong parent, product-file change, semantic Plan drift, or broken chronology still
43
- routes to diagnostics.
33
+ - beta.12.5 correctly classified the current Signal downstream-proof conflict as recoverable, but
34
+ that did not make the release installable. Signal still runs beta.12.4, whose ordinary update
35
+ preflight rejects the running Step and dirty product work. Installing beta.12.5 would also advance
36
+ dependency manifests/HEAD before that new runtime could register the commit. The advertised
37
+ beta.12.5 recovery was therefore unreachable from the actual starting version.
38
+ - This is an update authority deadlock, not a need for more review attempts: the old runtime cannot
39
+ authorize the dirty update, while the new runtime cannot be reached without an exact update.
40
+ - beta.12.6 adds one bounded bridge rather than general dirty-update permission. The active
41
+ Milestone base and Task branch must each receive a separate dependency-only commit changing
42
+ exactly `package.json` and `package-lock.json`. A fresh beta.12.6 runtime then advertises
43
+ `update downstream-proof-dependency-recover` only for the active downstream-proof shape.
44
+ - Preflight verifies recorded Task history at `HEAD^`, the exact candidate at `HEAD`, aligned
45
+ runtime/declared/locked/installed/current-branch/base versions, one active Step, completed
46
+ transitive-predecessor ownership, branch and Plan bindings, no lease, no pending/corrupt
47
+ transaction or Core operation, and every dirty path plus SHA-256 content.
48
+ - Recovery registers only the dependency candidate in `systemCommits` and records the bound proof
49
+ in `dependencyProvenanceRecoveries.activeDownstreamProof`. It does not edit, stash, reset, commit,
50
+ or discard product work and does not change Step state. Fresh `next` then prioritizes
51
+ `task downstream-proof-recover` over manifest-induced Knowledge refresh.
52
+ - The ordinary downstream recovery remains responsible for invalidating stale predecessor
53
+ completion authority and returning the same Task to a new Plan, Risk Audit, authorization,
54
+ execution, and strict-review cycle. beta.12.6 does not bypass that lifecycle.
44
55
 
45
- ## Exact Signal read-only proof
56
+ ## Exact Signal read-only evidence
46
57
 
47
- - The final built beta.12.4 validator inspected Signal repository
48
- `/Users/home-pc/htdocs/projects/signal_v4`, Task
49
- `TASK-01M0WXJAD4GZGVNRJ284ND95C6`, and failed Step
50
- `STEP-001-PROCESSING-MIGRATIONS` without mutating the repository or Workflow state.
51
- - The persisted state has Task revision 24, current Plan hash
52
- `6a0c9b7a2a2ec11c9d6a9a24137dc17be1ecd18be42cf0188200942313776a50`, four Knowledge rebinds,
53
- three dependency-provenance recoveries, applied override
54
- `SOO-01M127VPRC5M5F3E3K7PS4MFJY`, and final rebound audit revision 22. Exactly one verified
55
- recovery was recorded after that audit, so `22 + 1 + 1 = 24`.
56
- - A direct final-build `next --repo /Users/home-pc/htdocs/projects/signal_v4 --json` returned
57
- `action=task run`, revision 24, the expected Step, and
58
- `stopOverrideContextRebind.state=validated`. It also preserved the exact claimed C1 actor and
59
- writer-credential recovery contract.
60
- - This proves compatibility with the currently persisted Signal M3 boundary. It does not prove
61
- that future product implementation or strict reviews will pass.
58
+ - The Signal repository `/Users/home-pc/htdocs/projects/signal_v4` was re-observed read-only after
59
+ implementation. It remains on branch
60
+ `codex/task-01m0wxjad4-processing-persistence-schema` at
61
+ `88f8bf70d1591852ad90c976625430d4f20585ac`.
62
+ - Its dirty set remains exactly six paths: five modified processing-migration files and one
63
+ untracked `tools/postgres/run-processing-integration.ts`. No Signal repository or Workflow state
64
+ was mutated during beta.12.6 implementation.
65
+ - Prior read-only state inspection identified Task
66
+ `TASK-01M0WXJAD4GZGVNRJ284ND95C6`, revision 103, active Step
67
+ `STEP-002-REAL-POSTGRES-PROOF`, five files owned by completed transitive predecessor
68
+ `STEP-001-PROCESSING-MIGRATIONS`, and one file owned by the active proof Step. The predecessor
69
+ evidence commit equals the preserved HEAD.
70
+ - The installed beta.12.4 ordinary update preflight returned `safe=false` for the running Step and
71
+ dirty checkout. The external beta.12.5 classifier returned `applicable=true`, `eligible=true`, and
72
+ no recovery blockers, proving that the product boundary itself is supported but not that the old
73
+ update path can reach it.
74
+ - The beta.12.6 regression fixture mirrors all six Signal paths and the same predecessor/active-Step
75
+ ownership split. It proves the new update bridge and subsequent downstream recovery route under
76
+ controlled Git/state mutations.
77
+ - This is strong structural and synthetic evidence, not a claim that the published package has
78
+ already updated live Signal. The final operational proof still requires the released exact
79
+ package, two exact dependency-only transport commits, the advertised preflight/recover, and a
80
+ fresh Signal `status -> next` readback.
62
81
 
63
- ## Packaged, plugin, and transcript evidence
82
+ ## PDF release documentation evidence
64
83
 
65
- - Downstream smoke validated exact package resolution and the packaged beta.12.4 handshake in a
66
- disposable installation.
67
- - The bundled gateway handshake reports package beta.12.4, protocol 2, state schema 2, and the new
68
- `stop-override-post-audit-dependency-revision-v1` capability.
69
- - A temporary trusted-harness transcript recorded the final built `gateway handshake` invocation
70
- and terminal result. `node scripts/validate-lifecycle-transcript.mjs` accepted both
71
- post-provenance events. The log SHA-256 is
72
- `4ec7d8cb105d901e82d1049c273c4f2ec8d22ea12e0116ed70cfa8ab703ea2eb`; the temporary log remains
73
- outside the repository.
74
-
75
- The transcript proves release-time invocation/result discipline for the final CLI. It does not
76
- claim a product Milestone replay or lifecycle mutation. Compatibility is covered by the exact
77
- Signal read-only proof and deterministic integration tests above.
78
-
79
- ## beta.12.4 PDF release documentation evidence
80
-
81
- - Three tracked Russian PDFs were deterministically regenerated from reviewable Markdown sources
82
- under `docs/pdf/sources`; `npm run docs:pdf:check` reported an empty stale set.
83
- - All 26 pages were rendered and visually inspected: architecture is 7 pages, the delegated
84
- chat-only guide is 8 pages, and the technical reference is 11 pages. Full-size inspection of the
85
- three changed compatibility pages found no clipped, overlapping, or unreadable content.
86
- - Visible titles, headers, package commands, capabilities, and release gates identify beta.12.4.
87
- The documents state the exact evidence-bound revision formula and its fail-closed boundary.
84
+ - Three tracked Russian PDFs were regenerated from Markdown sources; `npm run docs:pdf:check`
85
+ reported an empty stale set.
86
+ - All 27 pages were rendered and visually inspected: architecture is 7 pages (101,761 bytes), the
87
+ delegated chat-only guide is 9 pages (107,066 bytes), and the technical reference is 11 pages
88
+ (112,132 bytes).
89
+ - Visual inspection found table headers rendered dark-on-dark. The shared generator now uses an
90
+ explicit white bold header Paragraph style; all documents were regenerated and re-inspected.
91
+ Titles, version headers, Cyrillic glyphs, tables, code blocks, recovery instructions, page edges,
92
+ and footers have no visible clipping, overlap, or unreadable content.
88
93
 
89
94
  ## Existing boundaries and non-claims
90
95
 
91
- - The generic stale `continue-fix` recovery predicate is unchanged. The compatibility route does
92
- not reverse a semantic stop or authorize arbitrary Git/state history.
93
- - Structural replacement remains intentionally disabled. beta.12.4 does not implement P04-B,
96
+ - Structural replacement remains intentionally disabled. beta.12.6 does not implement P04-B,
94
97
  topology rewiring, completed-Step adoption, or a wider delegation surface.
98
+ - The compatibility bridge is limited to the proven active-downstream-proof shape. Unrelated dirty
99
+ paths, non-predecessor ownership, unknown history, a wider dependency commit, stale base/version
100
+ divergence, branch/Plan/Step mismatch, lease, transaction, or damaged sidecar fails closed.
101
+ - Read-only preflight is an observation, not an authorization token. Recover recomputes the current
102
+ binding. The stored hash proves which bytes the bridge preserved; subsequent downstream recovery
103
+ revalidates paths, ownership, and history, while the replacement Plan and review cover current
104
+ content.
105
+ - Git transport commits remain agent-executed operations on exact advertised boundaries. The
106
+ runtime does not create, amend, merge, reset, or push Git history.
95
107
  - Validation performed no Signal mutation, npm publication, Git commit, tag, remote push, or local
96
- plugin reinstall. Those are separate release actions after these gates.
97
- - A consumer must install the published exact beta.12.4 package, update/reinstall the bundled
98
- gateway, and use fresh project-local `handshake -> doctor -> status -> next` navigation.
108
+ plugin reinstall. Those are separate release/deployment actions.
109
+ - Confidence is high for the implemented source and tested Signal-shaped transition. Confidence in
110
+ the final live Signal update remains pending until the published package is installed and the
111
+ project-local runtime returns the expected 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.4",
3
+ "version": "2.0.0-beta.12.6",
4
4
  "description": "Requirements-first Codex development workflow with local state and explicit Git ownership.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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.20260829120000",
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.4 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
@@ -8,6 +8,23 @@
8
8
  It records a replan posture without changing Plan or product files; corrective yield and the
9
9
  existing state-bound corrective-replan Human gate remain mandatory.
10
10
 
11
+ - When fresh `next` advertises `task downstream-proof-recover`, Core has proved that every dirty
12
+ file outside the active Step belongs to a completed transitive predecessor and that recorded Git
13
+ history is intact. Invoke the exact lease-bound transition once. It preserves product files and
14
+ HEAD, invalidates stale predecessor completion authority with an append-only event, yields C1,
15
+ and routes the same Task to ordinary `task plan-set`. The replacement Plan, risk audit, and
16
+ execution authorization are fresh authority; no Task or Milestone recreation is involved.
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
+
11
28
  - `update dependency-provenance-preflight --id <TASK-ID>` is read-only. The matching
12
29
  `update dependency-provenance-recover --id <TASK-ID> --expected-revision <N> --actor <ACTOR>
13
30
  --reason <TEXT>` is valid only when preflight and fresh `next` both advertise it. Historical
@@ -100,6 +117,8 @@ Current capability set:
100
117
  - `remediation-mode-recovery-v1`
101
118
  - `plan-proof-obligations-v1`
102
119
  - `bounded-plan-integrity-recovery-v1`
120
+ - `downstream-proof-predecessor-recovery-v1`
121
+ - `active-downstream-proof-dependency-recovery-v1`
103
122
  - `corrective-yield-journal-v1`
104
123
  - `corrective-replan-journal-v1`
105
124
  - `corrective-replan-human-gate-v1`
@@ -175,6 +194,13 @@ actor through `--actor`; reviewer identity remains internal to the route.
175
194
  An unrecorded commit is Git history drift. Stop instead of adding another commit or editing
176
195
  workflow state manually; recovery remains coordinator-controlled.
177
196
 
197
+ If a Docker proof fails with `EPERM`, `operation not permitted`, or `permission denied` at the
198
+ Docker socket/CLI boundary, classify it as sandbox access, not daemon failure. Re-run the exact
199
+ read-only health probe or Plan command once with sandbox escalation; do not charge an infrastructure
200
+ retry. Restarting Docker Desktop or pulling another image is forbidden on this evidence alone. A
201
+ Docker infrastructure failure exists only when an escalated call reaches Docker and independently
202
+ proves the daemon unavailable.
203
+
178
204
  ## Plan Risk Audit and remediation breaker
179
205
 
180
206
  Before `task authorize`, every new alpha.7 Task requires:
@@ -67,6 +67,20 @@ active writer token when the C1 contract requires it. The recovery records only
67
67
  `task run` merely to manufacture the second failure, and never invoke this recovery for a generic
68
68
  test failure, a writable manifest, or unconfined changes.
69
69
 
70
+ When fresh `next` advertises `task downstream-proof-recover`, the active proof Step has produced
71
+ uncommitted files inside its own `allowedWrites` and has also exposed required changes owned by one
72
+ or more completed transitive predecessor Steps. Do not invoke `task step-complete`: its scope is
73
+ known to be stale. Use only the exact returned Task revision, claimant/lease actor, writer-token
74
+ contract, and a substantive reason. The atomic recovery preserves the worktree and HEAD, moves the
75
+ predecessor completion commits into historical `invalidatedStepCommits`, clears only the invalidated
76
+ completion evidence, blocks the active proof Step, supersedes execution authorization, appends
77
+ `downstream-proof-invalidations.jsonl`, releases C1/lease authority, and returns the same Task to
78
+ ordinary `task plan-set`. Build the replacement Plan from the full unfinished remainder, attach a
79
+ fresh Plan Risk Audit, then obtain fresh execution authorization. Never use this route for an
80
+ unrelated dirty file, a non-predecessor file, unregistered Git history, strict-review evidence, or
81
+ without explicit fresh `next` eligibility. Do not reset, stash, commit, or recreate the Task or
82
+ Milestone around this transition.
83
+
70
84
  If any step fails, report the concrete diagnostic. Do not load workflow
71
85
  semantics from this skill.
72
86
 
@@ -109,7 +123,7 @@ command shape or consuming a replacement Discovery. Never rebind, refresh, repla
109
123
  resume, cancel, or manually replace the historical Task. Continue only after a later P04-B/P05
110
124
  package explicitly advertises a topology-preserving replacement capability.
111
125
 
112
- When beta.12.4 `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
113
127
  beta.11 attempt-four policy stop: two ordinary failures, one corrective failure, a matching
114
128
  attempt-3 `continue-fix`, and a matching attempt-4 `stop-escalate` under the unchanged Plan. Invoke
115
129
  prepare with the exact Task/Step/revision, explicit human actor, and user-supplied reason. It is
@@ -135,6 +149,23 @@ Core may account for exactly one Task revision per ordered verified recovery. Ne
135
149
  compatibility from revision arithmetic alone: continue only when fresh `next` returns the validated
136
150
  `task run` route. An unrelated extra revision remains a hard stop.
137
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
+
138
169
  When `next` returns `milestone initial-assembly`, execution is unavailable. Follow only the
139
170
  advertised `linked-task-assembly.commands` (`discovery start` and `discovery materialize`) until all
140
171
  intended linked Tasks exist. The closing `milestone plan-set` option appears only after at least one
@@ -155,6 +186,17 @@ For `task start`, the policy applies only when choosing `--workspace-owner local
155
186
  `task step-complete`, `task merge`, and `task sync-base`, the advertised transition itself
156
187
  writes Git metadata.
157
188
 
189
+ Treat Docker access diagnostics before classifying an infrastructure failure. `EPERM`,
190
+ `operation not permitted`, or `permission denied` while opening the Docker socket or invoking the
191
+ Docker CLI from a sandbox means the proof is unavailable at the current execution boundary; it is
192
+ not evidence that the daemon or image is broken. Re-run the exact read-only health probe or exact
193
+ Plan check once with the required sandbox escalation. This escalation rerun does not consume a
194
+ Workflow remediation attempt or a local infrastructure retry. Only an escalated probe that reaches
195
+ Docker and reports an unavailable daemon may be classified as a Docker infrastructure failure.
196
+ Never start, stop, or restart Docker Desktop, pull a substitute image, or mutate Docker state merely
197
+ because the sandboxed call returned a permission error; those actions require their own explicit
198
+ authorization and evidence.
199
+
158
200
  When `next` includes `writerTokenContract`, treat it as an exact first-call precondition. Retain
159
201
  the active writer lease from the first-field `writerLeaseReceipt` returned by `task run` and pass it using the advertised `option` for that
160
202
  transition. The token is sensitive: never print, summarize, persist, or substitute a redacted
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://codex-workflow.local/schemas/downstream-proof-invalidation-event.schema.json",
4
+ "title": "Codex Workflow V2 Downstream Proof Invalidation Event",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "eventId",
9
+ "taskId",
10
+ "previousTaskRevision",
11
+ "resultTaskRevision",
12
+ "planHash",
13
+ "activeStepId",
14
+ "invalidatedSteps",
15
+ "dirtyFiles",
16
+ "preservedHeadCommit",
17
+ "actor",
18
+ "reason",
19
+ "packageVersion",
20
+ "previousEventHash",
21
+ "recordedAt",
22
+ "eventHash"
23
+ ],
24
+ "properties": {
25
+ "eventId": { "type": "string", "pattern": "^DPI-[0-9A-HJKMNP-TV-Z]{26}$" },
26
+ "taskId": { "$ref": "#/$defs/taskId" },
27
+ "previousTaskRevision": { "type": "integer", "minimum": 1 },
28
+ "resultTaskRevision": { "type": "integer", "minimum": 2 },
29
+ "planHash": { "$ref": "#/$defs/hash64" },
30
+ "activeStepId": { "$ref": "#/$defs/stepId" },
31
+ "invalidatedSteps": {
32
+ "type": "array",
33
+ "minItems": 1,
34
+ "items": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["stepId", "evidenceCommit", "triggerFiles"],
38
+ "properties": {
39
+ "stepId": { "$ref": "#/$defs/stepId" },
40
+ "evidenceCommit": { "$ref": "#/$defs/gitHash" },
41
+ "triggerFiles": {
42
+ "type": "array",
43
+ "uniqueItems": true,
44
+ "items": { "type": "string", "minLength": 1 }
45
+ }
46
+ }
47
+ }
48
+ },
49
+ "dirtyFiles": {
50
+ "type": "array",
51
+ "minItems": 1,
52
+ "uniqueItems": true,
53
+ "items": { "type": "string", "minLength": 1 }
54
+ },
55
+ "preservedHeadCommit": { "$ref": "#/$defs/gitHash" },
56
+ "actor": { "type": "string", "minLength": 1 },
57
+ "reason": { "type": "string", "minLength": 1 },
58
+ "packageVersion": { "type": "string", "minLength": 1 },
59
+ "previousEventHash": { "$ref": "#/$defs/nullableHash64" },
60
+ "recordedAt": { "type": "string", "format": "date-time" },
61
+ "eventHash": { "$ref": "#/$defs/hash64" }
62
+ },
63
+ "$defs": {
64
+ "taskId": { "type": "string", "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
65
+ "stepId": { "type": "string", "pattern": "^STEP-[0-9]{3}(?:-[A-Z0-9-]+)?$" },
66
+ "gitHash": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
67
+ "hash64": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
68
+ "nullableHash64": { "type": ["string", "null"], "pattern": "^[a-f0-9]{64}$" }
69
+ }
70
+ }
@@ -55,6 +55,11 @@
55
55
  },
56
56
  "replacementForTaskId": { "type": ["string", "null"], "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
57
57
  "replacedByTaskId": { "type": ["string", "null"], "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
58
+ "invalidatedStepCommits": {
59
+ "type": "array",
60
+ "uniqueItems": true,
61
+ "items": { "type": "string", "pattern": "^[a-f0-9]{40}$" }
62
+ },
58
63
  "dependencyProvenanceRecoveries": {
59
64
  "type": "array",
60
65
  "items": {
@@ -73,6 +78,28 @@
73
78
  "type": "array",
74
79
  "uniqueItems": true,
75
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
76
103
  }
77
104
  },
78
105
  "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([