codex-workflow-v2 2.0.0-beta.13.13 → 2.0.0-beta.13.15

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 +17 -0
  2. package/dist/reviewer-runtime-build.json +19 -7
  3. package/dist/src/alpha6/captured-check-evidence.d.ts +49 -0
  4. package/dist/src/alpha6/captured-check-evidence.js +146 -0
  5. package/dist/src/alpha6/captured-check-evidence.js.map +1 -0
  6. package/dist/src/alpha6/corrective-decision-boundary.d.ts +4 -0
  7. package/dist/src/alpha6/corrective-decision-boundary.js +47 -0
  8. package/dist/src/alpha6/corrective-decision-boundary.js.map +1 -0
  9. package/dist/src/alpha6/root-cause-replan-carryover.d.ts +3 -1
  10. package/dist/src/alpha6/root-cause-replan-carryover.js +4 -0
  11. package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -1
  12. package/dist/src/contracts.d.ts +5 -1
  13. package/dist/src/dependency-provenance.js +10 -0
  14. package/dist/src/dependency-provenance.js.map +1 -1
  15. package/dist/src/version.d.ts +1 -1
  16. package/dist/src/version.js +1 -1
  17. package/dist/src/workflow-blocker-route.d.ts +8 -0
  18. package/dist/src/workflow-blocker-route.js +106 -0
  19. package/dist/src/workflow-blocker-route.js.map +1 -0
  20. package/dist/src/workflow.d.ts +1 -0
  21. package/dist/src/workflow.js +140 -18
  22. package/dist/src/workflow.js.map +1 -1
  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 +11 -1
  27. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +12 -2
  28. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +12 -2
  29. package/docs/release.md +63 -0
  30. package/docs/stable-release-defect-register.md +16 -0
  31. package/docs/updating-existing-project.md +9 -0
  32. package/package.json +1 -1
  33. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +1 -1
  34. package/plugins/codex-workflow-gateway/references/chat-dispatch.md +40 -11
  35. package/plugins/codex-workflow-gateway/references/codebase-memory-routing.md +52 -0
  36. package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +7 -1
  37. package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +10 -8
  38. package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +23 -5
  39. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +84 -13
@@ -463,7 +463,7 @@ Restart Docker Desktop требует отдельного разрешения
463
463
  # 10. Operational checklist
464
464
 
465
465
  - exact package version установлен, bundled gateway соответствует release и переустановлен;
466
- - handshake подтверждает `packageVersion=2.0.0-beta.13.13`, protocol 2, state schema 2 и beta.13
466
+ - handshake подтверждает `packageVersion=2.0.0-beta.13.15`, protocol 2, state schema 2 и beta.13
467
467
  capabilities;
468
468
  - routine observation начинается с компактного `status`; `status --full` запрашивается только для
469
469
  расследования, которому действительно нужна полная historical projection;
@@ -512,3 +512,13 @@ scope, с действующим делегированным маршрутом
512
512
  Обновление пакета само по себе не одобряет проектные источники. Проверка релиза
513
513
  включает четыре уже изменённых источника, перенос пакета и продолжение до checks
514
514
  и sealed review packet; фактическая готовность Signal проверяется отдельно.
515
+
516
+
517
+ ## beta.13.14: перенос проверяется в своей фазе
518
+
519
+ Исторический перенос незавершённой работы проверяется только для planned Step,
520
+ как и при исполнении. Для уже упавшего Step он не перекрывает актуальный маршрут
521
+ восстановления scope. До обновления нужна проверка навигации на остановленном
522
+ состоянии без мутаций, а после — свежие status и next. Атомарный context-refresh
523
+ не выдаёт writer credential: продолжает прежний C1 исполнитель с действующими
524
+ полномочиями.
@@ -57,7 +57,7 @@ AGENTS.md
57
57
  -> doctor только как дополнительная диагностика
58
58
  ```
59
59
 
60
- Handshake beta.13.13 должен сообщать `packageVersion=2.0.0-beta.13.13`, `protocolVersion=2`,
60
+ Handshake beta.13.15 должен сообщать `packageVersion=2.0.0-beta.13.15`, `protocolVersion=2`,
61
61
  `stateSchemaVersion=2`, dependency DAG, initial Plan transaction, mechanical feasibility,
62
62
  Milestone autonomy, host-safe credential reference, failed-Step continuation transaction,
63
63
  cause-bound rolling refinement, structural production edge, compact status, reviewer runtime preflight,
@@ -480,7 +480,7 @@ Task/project DGR. `dependencyBinding` для standalone handoff равен null.
480
480
  # 14. Итоговый checklist пользователя
481
481
 
482
482
  - beta.13.10 exact package и новый bundled gateway установлены; handshake показывает
483
- `packageVersion=2.0.0-beta.13.13`, protocol/state schema `2/2` и beta.13 capabilities;
483
+ `packageVersion=2.0.0-beta.13.15`, protocol/state schema `2/2` и beta.13 capabilities;
484
484
  - новый Coordinator chat не является fork старого Milestone;
485
485
  - bootstrap DGR, если нужен, выдан отдельным exact human confirmation;
486
486
  - Discovery не materialized при blocking unknowns;
@@ -538,3 +538,13 @@ scope, с действующим делегированным маршрутом
538
538
  Обновление пакета само по себе не одобряет проектные источники. Проверка релиза
539
539
  включает четыре уже изменённых источника, перенос пакета и продолжение до checks
540
540
  и sealed review packet; фактическая готовность Signal проверяется отдельно.
541
+
542
+
543
+ ## beta.13.14: перенос проверяется в своей фазе
544
+
545
+ Исторический перенос незавершённой работы проверяется только для planned Step,
546
+ как и при исполнении. Для уже упавшего Step он не перекрывает актуальный маршрут
547
+ восстановления scope. До обновления нужна проверка навигации на остановленном
548
+ состоянии без мутаций, а после — свежие status и next. Атомарный context-refresh
549
+ не выдаёт writer credential: продолжает прежний C1 исполнитель с действующими
550
+ полномочиями.
@@ -15,7 +15,7 @@ authority сами: mutating permission определяется runtime state
15
15
 
16
16
  | Параметр beta.13 | Значение |
17
17
  |---|---|
18
- | npm package | `codex-workflow-v2@2.0.0-beta.13.13` |
18
+ | npm package | `codex-workflow-v2@2.0.0-beta.13.15` |
19
19
  | protocolVersion | 2 |
20
20
  | stateSchemaVersion | 2 |
21
21
  | lifecycle epoch | 2 |
@@ -775,7 +775,7 @@ dirty update.
775
775
  observed-route matrix/compact-status/reviewer-runtime tests, legacy compatibility regressions,
776
776
  `npm run test:signal-t10-check-support-e2e`, `npm run test:signal-remediation-e2e`,
777
777
  `npm run pack:check`, `npm run smoke:downstream`, `npm run plugin:check`, official plugin/skill validators,
778
- `npm run docs:pdf:check` и `npm run release:check` с exact `v2.0.0-beta.13.13` tag binding и append-only
778
+ `npm run docs:pdf:check` и `npm run release:check` с exact `v2.0.0-beta.13.15` tag binding и append-only
779
779
  real-agent lifecycle log. Candidate проверяется из clean source checkout; missing built module не должен
780
780
  превращаться в stack trace, а обязан быть детерминированно собран или диагностирован release gate.
781
781
 
@@ -820,3 +820,13 @@ scope, с действующим делегированным маршрутом
820
820
  Обновление пакета само по себе не одобряет проектные источники. Проверка релиза
821
821
  включает четыре уже изменённых источника, перенос пакета и продолжение до checks
822
822
  и sealed review packet; фактическая готовность Signal проверяется отдельно.
823
+
824
+
825
+ ## beta.13.14: перенос проверяется в своей фазе
826
+
827
+ Исторический перенос незавершённой работы проверяется только для planned Step,
828
+ как и при исполнении. Для уже упавшего Step он не перекрывает актуальный маршрут
829
+ восстановления scope. До обновления нужна проверка навигации на остановленном
830
+ состоянии без мутаций, а после — свежие status и next. Атомарный context-refresh
831
+ не выдаёт writer credential: продолжает прежний C1 исполнитель с действующими
832
+ полномочиями.
package/docs/release.md CHANGED
@@ -1,5 +1,68 @@
1
1
  # Release Policy
2
2
 
3
+ ## beta.13.15: retained failed checks and consistent corrective navigation
4
+
5
+ Root-cause dirty carryover now requires one exact terminal corrective-yield witness and assesses
6
+ only that terminal failed-check head. Older failed attempts can no longer turn a later review or
7
+ corrective continuation into an unwitnessed `doctor` route. The regression includes the stopped
8
+ Signal topology: multiple historical failures, no terminal corrective-yield witness, and ordinary
9
+ writer recovery remaining visible.
10
+
11
+ Core now emits a declarative `workflowBlockerRoute` only for a confirmed navigation dead end. The
12
+ descriptor grants no effects. The originating Coordinator confirms the dead end and uses the
13
+ packaged gateway to idempotently dispatch an exact-version patch chat in `codex-workflow-v2`.
14
+ That patch chat owns diagnosis, implementation, verification, and publication; the Coordinator
15
+ owns callback handling, the downstream update, and resuming the stopped product chat. Chat policy
16
+ v2 selects only Mini, Luna, or Terra with low/medium effort; Sol, Astra, and high effort are
17
+ excluded from automatic creation.
18
+
19
+ The gateway now distinguishes approved Knowledge Map sources from codebase-memory indexes. Agents
20
+ must route code discovery through the MCP project whose normalized root exactly matches the fresh
21
+ Core graph request. The intent table separates product source, the exact installed workflow package,
22
+ and a workflow-development checkout; stale/missing indexes are refreshed and direct code search
23
+ requires a recorded MCP fallback. Workflow source support uses full indexing so plugin scripts and
24
+ tests are not silently excluded.
25
+
26
+ Captured check results are persisted in the existing failed-Step transaction with
27
+ separate capture/check hashes and exact readback. Rollback covers the new artifact;
28
+ legacy failures remain explicitly uncaptured. Private output can contain process
29
+ secrets. The opt-in excerpt is best-effort redacted and never used as authority or
30
+ published automatically in status. This release does not alter v1 cause semantics.
31
+
32
+ Optional independent corrective decisions accept a clean checkout or an exact current
33
+ failed-checkpoint file set and byte hash, bound to the verified remediation event,
34
+ Task HEAD/history and effective allowed/forbidden scope. Navigation and executor share
35
+ that boundary. C1 actor/credential, transaction, independent review and human corrective
36
+ Plan gates remain mandatory. This is not scope-amendment authority or a generic dirty
37
+ update transport. Required regressions cover distinct mechanical failures, dirty C1
38
+ wrong/missing credentials, changed bytes, outside paths and altered immutable history.
39
+
40
+ Previously unreleased dispatch changes distinguish sealed review roles from product
41
+ writers without granting repository writes. Explicit zero-write reviews must avoid
42
+ runtime-preflight APIs that create temporary caches. The shared carryover phase
43
+ predicate retains planned-Step safety checks and avoids masking failed successors;
44
+ both successful and failed replacement successor regressions remain required.
45
+
46
+ The existing source13.6 consumed-carryover profile remains source-pinned; its exact
47
+ current target and transcript validator additionally recognize beta13.15. No historical
48
+ receipt or source-version predicate is rewritten. Full candidate CI, ordinary release
49
+ checks and the documented real App boundary remain required before publication.
50
+
51
+
52
+ ## beta.13.14: keep carryover navigation in its execution phase
53
+
54
+ A retained root-cause carryover belongs to the start of a planned replacement
55
+ Step. After that Step runs and fails, its historical carryover must not overwrite
56
+ fresh failed-Step recovery navigation. Navigation must apply the same planned-Step
57
+ condition as execution; all carryover checks remain enforced for planned Steps.
58
+
59
+ The regression gate must cover an eligible support amendment with stale carryover
60
+ history, content-only Knowledge drift and retained C1 identity. Follow advertised
61
+ actions through scope recovery, delegated context refresh and the same Worker's
62
+ run. Context refresh does not supply a writer credential. Before transport, inspect
63
+ the patched navigation against the actual stopped state without mutating it;
64
+ transport eligibility alone does not prove successor navigation.
65
+
3
66
  ## beta.13.13: assess dirty Knowledge before dependency transport
4
67
 
5
68
  A failed Step can leave content changes in already approved Knowledge sources. The
@@ -16,6 +16,22 @@ Last reviewed: 2026-09-08.
16
16
 
17
17
  ## Active Milestone update findings
18
18
 
19
+ ### WF-M04-CARRYOVER-PHASE — historical carryover masks failed-Step recovery
20
+
21
+ - Status: Implemented in beta.13.14 with regression coverage; downstream
22
+ continuation still requires post-install verification.
23
+ - Severity: High
24
+ - Evidence: a current failed Step can have eligible check-support recovery while
25
+ task navigation returns a stale root-cause carryover blocker. Global navigation
26
+ then advertises Knowledge refresh before the support amendment.
27
+ - Cause: execution assesses carryover only for a planned Step, but navigation
28
+ also assessed it for a failed retry. The earlier combined fixture did not retain
29
+ this historical carryover, so its successful route did not cover the overlap.
30
+ - Required fix: use the same phase condition in navigation and execution without
31
+ relaxing planned-Step carryover, dirty-byte, scope or writer checks.
32
+ - Required evidence: exact stopped-state read-only navigation, regression for the
33
+ overlapping routes and same-Worker continuation through the advertised successor.
34
+
19
35
  ### WF-M04-KNOWLEDGE-TRANSPORT — preflight omits post-update Knowledge readiness
20
36
 
21
37
  - Status: Implemented in beta.13.13; full-route regression is part of the release gate.
@@ -22,6 +22,15 @@ state schema. Совпадение `stateSchemaVersion` до и после об
22
22
  нужна. Для alpha.6 при `stateSchemaVersion: 2` применяется не migration, а sidecar-only
23
23
  adoption posture.
24
24
 
25
+ ### beta.13.14: история переноса не перекрывает восстановление failed Step
26
+
27
+ Проверка переноса незавершённой работы относится только к planned Step. После его
28
+ запуска и отказа она не должна перекрывать актуальное восстановление scope. Перед
29
+ обновлением проверяйте также навигацию исправленного runtime на остановленном
30
+ состоянии без мутаций: одного transport preflight недостаточно. После обновления
31
+ выполняйте только свежий объявленный маршрут. Атомарный refresh не выдаёт writer
32
+ credential и не заменяет прежнего исполнителя.
33
+
25
34
  ### beta.13.13: изменённые product-файлы Knowledge до обновления
26
35
 
27
36
  Перед transport проверяйте не только версии и failed-Step scope, но и Knowledge.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-workflow-v2",
3
- "version": "2.0.0-beta.13.13",
3
+ "version": "2.0.0-beta.13.15",
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.20260830183000",
3
+ "version": "0.1.0+codex.20260909112043",
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"
@@ -31,7 +31,8 @@ those using real App/source evidence before using the new dispatch flow.
31
31
  "highRisk": false,
32
32
  "rationale": "New multi-file implementation plan with established requirements.",
33
33
  "availableModels": [
34
- {"id": "gpt-5.6-sol", "reasoningEfforts": ["low", "medium", "high", "xhigh", "max", "ultra"]}
34
+ {"id": "gpt-5.6-terra", "reasoningEfforts": ["low", "medium", "high", "xhigh", "max", "ultra"]},
35
+ {"id": "gpt-5.6-luna", "reasoningEfforts": ["low", "medium", "high", "xhigh", "max"]}
35
36
  ]
36
37
  }
37
38
  }
@@ -98,12 +99,12 @@ cost/latency preference, not measured savings or guaranteed account availability
98
99
  | Work | Preferred model | App thinking | Compatible fallback |
99
100
  | --- | --- | --- | --- |
100
101
  | Routine mechanical transitions, formatting, retrieval | gpt-5.4-mini | low | gpt-5.6-luna / low |
101
- | Coordinator supervision; small implementation | gpt-5.6-luna | medium | gpt-5.6-terra / medium |
102
- | Standard implementation | gpt-5.6-terra | medium | gpt-5.6-sol / medium |
103
- | Task planning | gpt-5.6-sol | medium | gpt-6-astra / medium |
104
- | Routine Step review | gpt-5.6-terra | medium | gpt-5.6-sol / medium |
105
- | Standard Step review, final review, plan/corrective audit | gpt-5.6-sol | high | gpt-6-astra / high |
106
- | Complex work or high risk, any role | gpt-6-astra | high | gpt-5.6-sol / high |
102
+ | Coordinator supervision; small implementation | gpt-5.6-luna | low | gpt-5.4-mini / medium |
103
+ | Standard implementation | gpt-5.6-terra | low | gpt-5.6-luna / medium |
104
+ | Task planning | gpt-5.6-terra | low | gpt-5.6-luna / medium |
105
+ | Routine Step review | gpt-5.6-luna | low | gpt-5.4-mini / medium |
106
+ | Standard Step review, final review, plan/corrective audit | gpt-5.6-terra | low | gpt-5.6-luna / medium |
107
+ | Complex work or high risk, any role | gpt-5.6-terra | medium | gpt-5.6-luna / medium |
107
108
 
108
109
  `routine` means a small, well-specified change or mechanical action with an existing check;
109
110
  `standard` is ordinary multi-file work; `complex` covers new architecture, unresolved concurrency,
@@ -111,7 +112,9 @@ recovery/provenance or distributed state. Mark `highRisk` for authorization, sec
111
112
  paths, data-loss exposure or irreversible migrations. The coordinator records the concrete
112
113
  rationale; classification is a human/agent judgment, not an automatic risk detector. Unknown
113
114
  complexity is not routine. Review/audit role floors override a falsely mechanical phase. No
114
- automatic xhigh/max/ultra, and no escalation merely because a review failed or a tool timed out.
115
+ automatic high/xhigh/max/ultra, and no escalation merely because a review failed or a tool timed out.
116
+ The policy never selects `gpt-5.6-sol` or `gpt-6-astra`. A caller cannot bypass that ceiling by
117
+ including either model or `high` effort in the destination catalog.
115
118
 
116
119
  The policy chooses only a listed supported pair. If neither preferred nor fallback pair is
117
120
  available, stop selection rather than silently inheriting the coordinator or lowering the review
@@ -121,8 +124,9 @@ https://developers.openai.com/api/docs/guides/latest-model
121
124
 
122
125
  For a phase change in an existing bound chat, call `model-select` with its same `threadId` and
123
126
  fresh `modelRequest`; copy the returned `followUpArgs` into `send_message_to_thread` with the
124
- closed follow-up prompt. For example, planning uses Sol/medium, implementation Terra/medium,
125
- then mechanical lifecycle work Mini/low. Do not create another Task just to switch model.
127
+ closed follow-up prompt. For example, planning uses Terra/low, a complex implementation uses
128
+ Terra/medium, then mechanical lifecycle work uses Mini/low. Do not create another Task just to
129
+ switch model.
126
130
  Keep the previous selection unless the phase/risk/scope changes materially. The journal records
127
131
  requested settings; tool acceptance/runtime readback, when available, is required to claim the
128
132
  actual model used. A model change never changes role, scope, credentials or approval authority.
@@ -134,12 +138,37 @@ Choose local only for an explicit user request to execute in the saved checkout.
134
138
  child checkout, not an absolute path copied from the parent's prompt, is the write destination.
135
139
  `dispatch-observe` records it and refuses silent movement of a bound child.
136
140
 
137
- Before the first write, and after any branch/cwd change, use read-only `dispatch-context-check`
141
+ For `task` and `coordinator` product/repository writes, before the first write and after any
142
+ branch/cwd change, use read-only `dispatch-context-check`
138
143
  with a fresh App observation, `writeRoot`, and `expectedBranch` from the current Core Task.
139
144
  Require `matched=true`, then refresh Core next and writer authority. Mismatch means reconcile the
140
145
  same Worker context; it never permits another create, an indirect write or an automatic handoff.
141
146
  A matched context does not authorize external operations. See packaged `docs/change-model.md`.
142
147
 
148
+ The explicit `step-review`, `final-review`, `corrective-audit`, and `plan-audit` roles instead
149
+ receive a read-only review boundary. They verify the canonical repository and immutable commit,
150
+ packet/seal or audit-request bindings, including before returning their result. A detached or
151
+ differently branched App checkout does not require Task-branch reconciliation for reading that
152
+ evidence. Reviewers must not modify product files, Git history, Workflow state, or invoke lifecycle
153
+ mutations. A requested result artifact may be saved only outside all repository checkouts and under
154
+ actual filesystem permissions. The prompt does not grant access. Model phase and prompt prose do
155
+ not confer this role; unknown registry types remain rejected. Existing writer context checks and
156
+ Core authority guards are unchanged.
157
+
158
+ “Read-only” Workflow diagnostics mean no product or Core transitions, not necessarily zero
159
+ filesystem writes. For example, `next` can invoke `prepareReviewerRuntimePreflight`, which creates
160
+ an external runtime-cache directory and writes/removes `.write-probe`. In a normal review, inspect
161
+ actual permissions before invoking diagnostics that use this cache; cache access grants no product
162
+ write authority.
163
+
164
+ An explicit user instruction prohibiting all writes takes precedence. For that review, reuse
165
+ current, unchanged bound receipts and the prior successful handshake from the same session;
166
+ inspect immutable files directly and avoid runtime-preflight APIs or other diagnostics with write
167
+ side effects. Do not rerun `next` solely to obtain a fresh receipt under a zero-write instruction.
168
+ If the available bindings cannot establish the required current evidence without writing, report
169
+ the precise unverified boundary instead of claiming a write-free verification. Saving a report is
170
+ also a write and requires explicit permission when all writes are prohibited.
171
+
143
172
  ### Existing legacy bindings
144
173
 
145
174
  `dispatch-context-check` also accepts an already bound legacy entry with no dispatch marker.
@@ -0,0 +1,52 @@
1
+ # Codebase-memory routing
2
+
3
+ Knowledge Map and `codebase-memory-mcp` answer different questions. Knowledge Map records approved
4
+ project knowledge sources and authority. The MCP graph indexes code structure for discovery,
5
+ call/dependency tracing, and impact analysis. An approved Knowledge Map entry does not prove that
6
+ an MCP project exists or is current.
7
+
8
+ ## Select by exact source root
9
+
10
+ Obtain a fresh Core `graph status` request before choosing an MCP project. Match the request's
11
+ absolute `sourceRoot` against `list_projects[].root_path` after path normalization. Names, basename
12
+ similarity, an older repository generation, and a Knowledge Map path are not valid matches. Zero
13
+ matches requires `index_repository` for that exact source root. More than one exact match is an
14
+ integrity blocker until the duplicate is resolved. Call `index_status` on the selected project and
15
+ refresh it when Core reports the binding missing/stale or its indexed HEAD/package manifest differs.
16
+
17
+ Use this intent table:
18
+
19
+ | Work being investigated | Active repository | Core graph kind | Expected source root |
20
+ | --- | --- | --- | --- |
21
+ | Product implementation | product repository | `product` | active product Git root |
22
+ | Installed workflow behavior blocking a product | product repository | `workflow` | exact installed package graph view returned by Core |
23
+ | Workflow source implementation or release | `codex-workflow-v2` checkout/worktree | `product` | that exact workflow source Git root |
24
+
25
+ The third row is intentionally `product`: Core uses that word for the active repository's own
26
+ source. The repository happens to be the workflow package. Never select Signal's product graph to
27
+ explain package internals, and never select an installed package graph to inspect Signal product
28
+ code.
29
+
30
+ For workflow implementation/support, request `full` indexing so plugin scripts, tests, and docs are
31
+ present. For a product repository, use the Plan's graph mode; raise it to `full` when required code
32
+ is in a directory excluded by moderate indexing. Bind the resulting evidence through Core before
33
+ relying on it as current workflow evidence.
34
+
35
+ ## Discovery policy
36
+
37
+ Use `get_architecture`, `search_graph`, `trace_path`, `query_graph`, and `get_code_snippet` for code
38
+ discovery. Search the graph first and fetch only the selected symbols. Do not repeatedly scan or
39
+ read whole source trees after an exact ready graph is available.
40
+
41
+ Direct filesystem search is a recorded fallback, allowed only when:
42
+
43
+ - MCP is unavailable after its normal retry boundary;
44
+ - the exact source root cannot be indexed;
45
+ - Core reports a stale/mismatched graph and refresh cannot complete; or
46
+ - the target is a newly created, generated, ignored, or exact non-code artifact absent from the
47
+ graph.
48
+
49
+ Record the failed MCP operation, selected source root, and fallback reason. A convenience preference
50
+ or an overly broad graph result is not a fallback reason: narrow the graph query first. Git status,
51
+ exact package resolution, and reading a specifically named authority artifact remain filesystem
52
+ operations rather than code discovery.
@@ -64,7 +64,13 @@ export function dispatchAction(action, entry, input = {}) {
64
64
  const selection = selectChatModel(entry.type, input.modelRequest);
65
65
  const id = randomUUID();
66
66
  const marker = `[workflow-dispatch:${id}:${hash(prompt)}]`;
67
- const dispatchedPrompt = `${marker}\n${prompt}\nExecution boundary: use the actual child checkout returned by App readback. Before any write, reconcile it with the exact Task branch and run dispatch-context-check. A repository path in this packet is identity context, not authorization to write outside that checkout.`;
67
+ // Only the registry's explicit review/audit roles receive a read-only boundary.
68
+ // A model phase or packet prose cannot turn a product Worker into a reviewer.
69
+ const reviewRole = ['step-review', 'final-review', 'corrective-audit', 'plan-audit'].includes(entry.type);
70
+ const boundary = reviewRole
71
+ ? 'Review boundary: use the exact canonical repository and immutable commit, packet/seal or audit-request bindings supplied for this independent review. Verify those bindings before reading evidence and before returning the result; stop if they change. The App checkout may be detached or on another branch: do not switch it or require Task-branch dispatch-context-check for read-only inspection. Do not modify product files, Git history, or Workflow state, and do not invoke lifecycle mutations. Save the review result only to an explicitly requested artifact path outside all repository checkouts, under actual filesystem permissions; this instruction grants no filesystem access. A repository path identifies read evidence, never write authority.'
72
+ : 'Execution boundary: use the actual child checkout returned by App readback. Before any product or repository write, reconcile it with the exact Task branch and run dispatch-context-check. A repository path in this packet is identity context, not authorization to write outside that checkout.';
73
+ const dispatchedPrompt = `${marker}\n${prompt}\n${boundary}`;
68
74
  entry.dispatch = {
69
75
  version: 1, id, state: 'creating', appProjectId, hostId, repositoryRoot, gitDir, executionMode,
70
76
  promptPath, promptHash: hash(prompt), dispatchedPromptHash: hash(dispatchedPrompt), marker,
@@ -1,15 +1,17 @@
1
1
  // Relative cost/latency policy, not a price list or an availability oracle.
2
- export const MODEL_POLICY_VERSION = 'chat-model-policy-v1';
2
+ export const MODEL_POLICY_VERSION = 'chat-model-policy-v2';
3
3
  const PROFILES = {
4
4
  mechanical: [['gpt-5.4-mini', 'low'], ['gpt-5.6-luna', 'low']],
5
- scoped: [['gpt-5.6-luna', 'medium'], ['gpt-5.6-terra', 'medium']],
6
- implementation: [['gpt-5.6-terra', 'medium'], ['gpt-5.6-sol', 'medium']],
7
- planning: [['gpt-5.6-sol', 'medium'], ['gpt-6-astra', 'medium']],
8
- review: [['gpt-5.6-sol', 'high'], ['gpt-6-astra', 'high']],
9
- 'scoped-review': [['gpt-5.6-terra', 'medium'], ['gpt-5.6-sol', 'medium']],
10
- complex: [['gpt-6-astra', 'high'], ['gpt-5.6-sol', 'high']],
5
+ scoped: [['gpt-5.6-luna', 'low'], ['gpt-5.4-mini', 'medium']],
6
+ implementation: [['gpt-5.6-terra', 'low'], ['gpt-5.6-luna', 'medium']],
7
+ planning: [['gpt-5.6-terra', 'low'], ['gpt-5.6-luna', 'medium']],
8
+ review: [['gpt-5.6-terra', 'low'], ['gpt-5.6-luna', 'medium']],
9
+ 'scoped-review': [['gpt-5.6-luna', 'low'], ['gpt-5.4-mini', 'medium']],
10
+ complex: [['gpt-5.6-terra', 'medium'], ['gpt-5.6-luna', 'medium']],
11
11
  };
12
- const TYPES = ['coordinator', 'task', 'step-review', 'final-review', 'corrective-audit', 'plan-audit'];
12
+ const TYPES = [
13
+ 'coordinator', 'task', 'step-review', 'final-review', 'corrective-audit', 'plan-audit', 'workflow-blocker',
14
+ ];
13
15
  export function selectChatModel(type, request) {
14
16
  if (!TYPES.includes(type)) throw new Error('Unknown chat type.');
15
17
  if (!request || !['routine', 'standard', 'complex'].includes(request.complexity)
@@ -14,7 +14,9 @@ import process from 'node:process';
14
14
  import { randomUUID } from 'node:crypto';
15
15
  import { dispatchAction, dispatchInput } from './chat-dispatch.mjs';
16
16
 
17
- const TYPES = new Set(['coordinator', 'task', 'step-review', 'final-review', 'corrective-audit', 'plan-audit']);
17
+ const TYPES = new Set([
18
+ 'coordinator', 'task', 'step-review', 'final-review', 'corrective-audit', 'plan-audit', 'workflow-blocker',
19
+ ]);
18
20
  const LOCK_STALE_MS = 30_000;
19
21
  const LOCK_WAIT_MS = 2_000;
20
22
 
@@ -26,9 +28,12 @@ export function allocateChat(options) {
26
28
  const sequence = registry.nextSequence;
27
29
  const reservationId = randomUUID();
28
30
  const candidates = buildTitleCandidates({ ...options, sequence });
31
+ const milestoneOrdinal = options.type === 'workflow-blocker'
32
+ ? null
33
+ : requiredOrdinal(options.milestoneOrdinal, 'M');
29
34
  const existing = registry.entries.find(entry => entry.status !== 'abandoned'
30
35
  && entry.type === options.type && entry.entityId === options.entityId
31
- && entry.milestoneOrdinal === requiredOrdinal(options.milestoneOrdinal, 'M')
36
+ && entry.milestoneOrdinal === milestoneOrdinal
32
37
  && entry.taskOrdinal === optionalOrdinal(options.taskOrdinal, 'T')
33
38
  && entry.stepOrdinal === optionalOrdinal(options.stepOrdinal, 'S')
34
39
  && (['task', 'coordinator'].includes(options.type)
@@ -38,7 +43,7 @@ export function allocateChat(options) {
38
43
  sequence,
39
44
  reservationId,
40
45
  type: options.type,
41
- milestoneOrdinal: requiredOrdinal(options.milestoneOrdinal, 'M'),
46
+ milestoneOrdinal,
42
47
  taskOrdinal: optionalOrdinal(options.taskOrdinal, 'T'),
43
48
  stepOrdinal: optionalOrdinal(options.stepOrdinal, 'S'),
44
49
  entityId: requiredText(options.entityId, 'entityId'),
@@ -191,6 +196,15 @@ export function showRegistry(options) {
191
196
  }
192
197
 
193
198
  export function buildTitleCandidates(options) {
199
+ if (options.type === 'workflow-blocker') {
200
+ const entityId = requiredText(options.entityId, 'entityId');
201
+ const semantic = compactWhitespace(requiredText(options.semanticTitle, 'semanticTitle'));
202
+ validateTypeBindings(options.type, null, null, entityId);
203
+ if (!/^\d+\.\d+\.\d+-beta(?:\.\d+)+$/u.test(semantic)) {
204
+ throw new Error('workflow-blocker title must be the exact target beta patch version.');
205
+ }
206
+ return [semantic];
207
+ }
194
208
  const prefix = `#${String(positiveInteger(options.sequence, 'sequence')).padStart(3, '0')}`;
195
209
  const milestone = requiredOrdinal(options.milestoneOrdinal, 'M');
196
210
  const task = optionalOrdinal(options.taskOrdinal, 'T');
@@ -331,11 +345,15 @@ function validateProjectId(projectId) {
331
345
 
332
346
  function validateTypeBindings(type, taskOrdinal, stepOrdinal, entityId) {
333
347
  if (!TYPES.has(type)) throw new Error(`Unsupported chat type: ${type}`);
334
- if (type !== 'coordinator' && !taskOrdinal) throw new Error(`${type} requires a Task membership ordinal.`);
348
+ if (!['coordinator', 'workflow-blocker'].includes(type) && !taskOrdinal) {
349
+ throw new Error(`${type} requires a Task membership ordinal.`);
350
+ }
335
351
  if ((type === 'step-review' || type === 'corrective-audit') && !stepOrdinal) {
336
352
  throw new Error(`${type} requires a Step membership ordinal.`);
337
353
  }
338
- const validEntity = type === 'coordinator'
354
+ const validEntity = type === 'workflow-blocker'
355
+ ? /^[a-f0-9]{64}$/u.test(entityId)
356
+ : type === 'coordinator'
339
357
  ? entityId === 'DISCOVERY' || /^MS-[0-9A-HJKMNP-TV-Z]{26}$/.test(entityId)
340
358
  : /^TASK-[0-9A-HJKMNP-TV-Z]{26}$/.test(entityId);
341
359
  if (!validEntity) throw new Error(`${type} requires its full authoritative entity ID.`);