create-agdf 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +30 -22
  2. package/bin/agdf-validator.js +11 -0
  3. package/generated/.agdf/control/README.md +3 -3
  4. package/generated/.github/skills/agdf-brownfield-analysis/SKILL.md +1 -1
  5. package/generated/.github/skills/agdf-delivery-path-search/SKILL.md +7 -6
  6. package/generated/.github/skills/agdf-gate-check/SKILL.md +28 -91
  7. package/generated/.github/skills/agdf-interaction-locales.json +2 -0
  8. package/generated/.github/skills/contracts/gate-transition.md +4 -2
  9. package/generated/.github/skills/contracts/modes.md +12 -1
  10. package/generated/.opencode/README.md +6 -8
  11. package/generated/.opencode/agdf-interaction-locales.json +2 -0
  12. package/generated/.opencode/contracts/gate-transition.md +4 -2
  13. package/generated/.opencode/contracts/modes.md +12 -1
  14. package/generated/.opencode/skills/agdf-brownfield-analysis/SKILL.md +1 -1
  15. package/generated/.opencode/skills/agdf-delivery-path-search/SKILL.md +7 -6
  16. package/generated/.opencode/skills/agdf-gate-check/SKILL.md +28 -91
  17. package/generated/plugins/agdf/.claude-plugin/plugin.json +19 -0
  18. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  19. package/generated/plugins/agdf/control/README.md +3 -3
  20. package/generated/plugins/agdf/hooks/session-start.sh +1 -1
  21. package/generated/plugins/agdf/meta/agdf-interaction-locales.json +2 -0
  22. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  23. package/generated/plugins/agdf/meta/contracts/gate-transition.md +4 -2
  24. package/generated/plugins/agdf/meta/contracts/modes.md +12 -1
  25. package/generated/plugins/agdf/runtime/agdf-local.js +11 -0
  26. package/generated/plugins/agdf/runtime/create-agdf/NOTICE +10 -0
  27. package/generated/plugins/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
  28. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +418 -0
  29. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +220 -0
  30. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +136 -0
  31. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +75 -0
  32. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +156 -0
  33. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
  34. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +45 -0
  35. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +291 -0
  36. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +265 -0
  37. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +459 -0
  38. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +283 -0
  39. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
  40. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
  41. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +344 -0
  42. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
  43. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
  44. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
  45. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
  46. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
  47. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +227 -0
  48. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
  49. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
  50. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
  51. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
  52. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
  53. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +44 -0
  54. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +53 -0
  55. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
  56. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
  57. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
  58. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
  59. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
  60. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
  61. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +154 -0
  62. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
  63. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +14 -0
  64. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
  65. package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +590 -0
  66. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +142 -0
  67. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
  68. package/generated/plugins/agdf/runtime/create-agdf/package.json +66 -0
  69. package/generated/plugins/agdf/runtime/runtime-manifest.json +8 -0
  70. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +1040 -0
  71. package/generated/plugins/agdf/skills/brownfield-analysis/SKILL.md +1 -1
  72. package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +7 -6
  73. package/generated/plugins/agdf/skills/gate-check/SKILL.md +28 -91
  74. package/lib/cli/application.js +21 -59
  75. package/lib/cli/command-registry.js +9 -11
  76. package/lib/cli/validation-handlers.js +45 -0
  77. package/lib/control-evaluation/doctor.js +1 -1
  78. package/lib/control-evaluation/gate-check.js +7 -7
  79. package/lib/control-evaluation/required-files.js +9 -0
  80. package/lib/installers/local-marketplace.js +322 -0
  81. package/lib/installers/opencode-activation.js +43 -0
  82. package/lib/installers/opencode.js +60 -18
  83. package/lib/installers/plugin-installers.js +102 -26
  84. package/lib/runtime/local-validator.js +142 -0
  85. package/lib/runtime/validator-application.js +40 -0
  86. package/lib/scaffold/plan.js +1 -30
  87. package/lib/scaffold/presentation.js +9 -14
  88. package/opencode-plugin.js +32 -24
  89. package/package.json +6 -2
@@ -37,7 +37,7 @@ Do not mix both modes silently. Name the active mode in the output.
37
37
 
38
38
  ## Rules
39
39
  1. Brownfield first: understand the existing codebase before PRD/SD decisions when existing-system impact is possible, and again before implementation.
40
- 2. Brownfield Review after `Approval: UR` is a sizing and routing step. It must visibly decide `quick_task`, `verified_change`, `structured_slice`, `structured_delivery`, or `block` before PRD depth or implementation is chosen.
40
+ 2. Brownfield Review after `Approval: UR` is a sizing and routing step. It must visibly decide `quick_task`, `verified_change`, `structured_slice`, `structured_delivery`, or `block` before PRD depth or implementation is chosen. Persist the completed review and its decision, scope reason, evidence and required next gate in the same internal operation; mark the review `done` only after both the artefact and canonical run projection are complete. An interrupted, incomplete or legacy record stays at fail-closed `Mode/Slice Decision` recovery without another user approval.
41
41
  3. Reuse-before-create: prefer existing modules, services, components, tables, endpoints, tests, and configuration.
42
42
  4. Minimal clean slice: choose the smallest durable intervention, not merely the smallest technical diff.
43
43
  5. No silent parallel structures.
@@ -35,16 +35,17 @@ Skip for routine questions, obvious local fixes and approved implementation with
35
35
  1. Run AGDF gate-check and inspect durable control state.
36
36
  2. Confirm that search is allowed and implementation is not occurring during exploration.
37
37
  3. Declare the active surface and its enforcement level.
38
- 4. Invoke the shared CLI runtime:
38
+ 4. Resolve the exact-version surface-local validator using the same ownership rules as `gate-check`. Do not search `PATH`, query a registry, install a package or invoke `npx ...@latest` during routine planning. If no owned or explicitly configured exact-version validator is available, report `machine_validation: unavailable` or `machine_validation: external_required` and stop the machine-evaluated search.
39
+ 5. Invoke the shared CLI runtime:
39
40
 
40
41
  ```bash
41
- npx --yes @agdf/cli@latest delivery-path-search --surface <surface> --json
42
+ node <surface-local-agdf> delivery-path-search --surface <surface> --json
42
43
  ```
43
44
 
44
45
  Optional AI-native candidate generation is explicit:
45
46
 
46
47
  ```bash
47
- npx --yes @agdf/cli@latest delivery-path-search \
48
+ node <surface-local-agdf> delivery-path-search \
48
49
  --surface codex \
49
50
  --generate-candidates \
50
51
  --json
@@ -52,9 +53,9 @@ npx --yes @agdf/cli@latest delivery-path-search \
52
53
 
53
54
  It supplements the deterministic baseline with at most one bounded generator call. Treat proposals as untrusted until the canonical core validates schema, gate action, scope, duplicates and material diversity. Report generation provenance, budgets, rejections and failure. Never hide deterministic fallback or switch providers automatically.
54
55
 
55
- 5. Treat facts, repository evidence, assumptions and model judgements separately.
56
- 6. Return exactly one recommendation or `no_safe_recommendation`.
57
- 7. Run canonical AGDF gate-check after search. Never translate a recommendation into permission.
56
+ 6. Treat facts, repository evidence, assumptions and model judgements separately.
57
+ 7. Return exactly one recommendation or `no_safe_recommendation`.
58
+ 8. Run canonical AGDF gate-check after search. Never translate a recommendation into permission.
58
59
 
59
60
  ## Enforcement
60
61
 
@@ -44,17 +44,23 @@ If required control files are missing, do not automatically create a full `.agdf
44
44
  The default first action is to draft the minimal UR in the response and request `Approval: UR`.
45
45
  Use `init` only when the user explicitly asks for durable AGDF control state, the repository already uses `.agdf/control/` as its live working state, or a deterministic CLI/CI setup path is being executed.
46
46
 
47
- Use the executable control path when a machine-readable check is requested, when the gate state is ambiguous, when CI or PR evidence is needed, when deterministic ready-gate rendering is required, or when a repository-local automation needs JSON output. Prefer an already installed `agdf` executable; use registry-resolved `npx ...@latest` only for bootstrap, installation, explicit refresh or when no local executable exists:
47
+ Use the executable control path when a machine-readable check is requested, when the gate state is ambiguous, when CI or PR evidence is needed, when deterministic ready-gate rendering is required, or when a repository-local automation needs JSON output. Resolve the version-matched validator owned by the active surface first: `<plugin-root>/runtime/agdf-local.js` for Codex or Claude, or `<opencode-config>/agdf/bin/agdf-local.js` for OpenCode. Run its `--resolve-only --json` probe before treating its output as machine evidence. An explicitly configured absolute `AGDF_VALIDATOR_PATH` is the only secondary local candidate and must match the active AGDF version.
48
+
49
+ Routine validation uses that resolved local entrypoint:
48
50
 
49
51
  ```bash
50
- npx --yes @agdf/cli@latest init
51
- npx --yes @agdf/cli@latest doctor --json
52
- npx --yes @agdf/cli@latest gate-check --json
53
- npx --yes @agdf/cli@latest delivery-map --json
52
+ node <surface-local-agdf> doctor --json
53
+ node <surface-local-agdf> gate-check --json
54
+ node <surface-local-agdf> delivery-map --json
54
55
  ```
55
56
 
56
- For repeated local checks, use `agdf doctor --json`, `agdf gate-check --json` or
57
- `agdf gate-check --approval-envelope`. The last command prints the validated
57
+ If no exact-version local validator exists, continue through agent-native inspection where permitted
58
+ and state `machine_validation: unavailable` or `external_required`; do not automatically invoke
59
+ `npx`, install a package or contact the registry. Registry-resolved commands are reserved for an
60
+ explicit bootstrap, installation, repair or refresh requested as a lifecycle action.
61
+
62
+ For repeated local checks, use the resolved entrypoint with `doctor --json`, `gate-check --json` or
63
+ `gate-check --approval-envelope`. The last command prints the validated
58
64
  two-card exact-text interaction; JSON exposes the same `approval_presentation`
59
65
  for a native-capable adapter.
60
66
 
@@ -65,93 +71,24 @@ The CLI reports are validators and JSON evidence, not the primary user experienc
65
71
 
66
72
  ## Native Interaction Path
67
73
 
68
- Use the Runtime Contract's Native Interaction Contract to classify every candidate interaction as `clarification`, `tool_permission`, `gate_approval`, `blocked` or `status` before selecting a host control.
69
-
70
- Prefer inspection over asking. Do not invoke a structured question for status reporting, facts available in the repository, routine read-only work or a gate that is not ready. Do not repeatedly prompt for the same non-ready gate.
71
-
72
- For a fresh request classified as read-only with no required run decision, emit the locale pack's
73
- `primary.readOnlyOrientationDescription` sentence once before the findings. This path creates no run, persists
74
- nothing, requests no approval and reuses the existing status projection. Do not repeat the sentence
75
- during the same request.
76
-
77
- For a ready `gate_approval`:
78
-
79
- 1. Resolve exactly one selected run and evaluate the current gate.
80
- 2. Confirm the required durable artefact is present and ready before presenting a question.
81
- 3. Consume the validated canonical `approval_presentation` for the same selected run, gate and revision. Do not compose or rewrite headings, fields, card order, locale copy or Markdown in the model.
82
- 4. Emit its complete `run_status_card` block first and `gate_transition_card` block second in one immediately preceding assistant message. The first heading is neutral; the five status fields are selected run, readiness, current gate, human-readable required decision and a neutral approve/revise/decline instruction. The exact approval value appears only in the transition card across these two blocks.
83
- 5. Never put either card only into the question, button description or hidden tool context. Do not invoke a native question until both rendered blocks are visible.
84
- 6. If the projection is absent or invalid, render no partial card and invoke no native control. Re-evaluate the gate. Use only the exact-text request when the same gate is still ready and its canonical value is independently valid; otherwise report the non-ready reason and request no decision.
85
- 7. Distinguish internal process steps from user decisions in natural language. For example, after `Approval: TP`, say that pre-implementation Brownfield Analysis runs next and that no further user action is required now; do not expose `next_user_gate: none` or `user_action_required: no`, and do not ask for a second approval for Brownfield Analysis.
86
- 8. Ask exactly one question that names the selected `run_id` and `current_gate`.
87
- 9. Offer options in stable order: exact `Approval: <GateName>`, localized revise and localized decline. Add explicit cancel only where supported after decline; otherwise host dismissal maps to cancel. Never preselect, skip, auto-submit or reorder an option.
88
- 10. Use the surface adapter declared in the canonical plugin definition only when it can wait for deliberate input without auto-resolution and can transport `exact_option_value` or `separate_label_and_value`; never invoke a `decorated_label_only` adapter. Otherwise request the same exact approval in concise text.
89
- 11. Render both supplied cards once in that single complete assistant message. Never merge, reverse, omit, duplicate or reconstruct them; the decision heading does not replace either card. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
90
- 12. Re-run gate evaluation for the same run and expected gate after the response and immediately before persistence.
91
- 13. Reject a missing artefact, ambiguous or wrong run, wrong gate, stale expected gate, timeout/default, hook-supplied answer, agent message, technical permission outcome or plan approval.
92
- 14. Persist accepted input only through the existing control-state workflow.
93
-
94
- Before projecting a ready gate, evaluate adapter callability, deliberate wait safety and canonical
95
- approval-value transport. Expose `native_attempt_required: true` only when that preflight proves
96
- `exact_option_value` or `separate_label_and_value` transport with safe deliberate waiting. Decorated-only,
97
- missing, conflicting or unknown capability exposes false and `unavailable_before_invocation`; unsafe
98
- waiting exposes false and `unsafe_to_wait`. In both cases use exact text without invoking the adapter.
99
- A hook, permission result or session context message cannot replace an eligible attempt or supply its answer.
100
-
101
- Before composing the question, resolve the configured chat locale from `.agdf/control/config.json` through `plugin/meta/agdf-interaction-locales.json`: exact complete pack, language subtag, then English fallback. German and English are initial packs, not a closed language list. Keep `Approval: <GateName>` exactly unchanged in every language, and do not mix presentation languages within one interaction. Labels and descriptions use the same resolved locale; host-owned UI chrome remains host-owned and may use a different language.
102
-
103
- The canonical renderer resolves the complete locale pack. The initial German pack includes `Bereit für deine Entscheidung`, `Jetzt freigeben` and `Danach`; the initial English pack includes `Ready for your decision`, `Approve now` and `Next`. Verify that the supplied blocks use one locale and a neutral decision heading while leaving the exact gate identifier and approval value unchanged. Do not model-edit the supplied Markdown.
104
-
105
- The primary option is derived exactly as `Approval: <GateName>` from the evaluated current gate; only explanatory copy and non-authoritative outcome labels are localized. Concrete localized copy belongs to the user-facing interaction layer or the approved delivery artefact, not to English runtime rules.
106
-
107
- Make exactly one native-attempt for the eligible ready gate. If the host does not render,
108
- apply or safely return the native question on that attempt, switch immediately
109
- to the exact textual approval. Do not ask the user to request the buttons again
110
- and do not create a retry loop or simulated control.
111
-
112
- State the outcome visibly: `presented`, `unavailable_before_invocation`,
113
- `attempted_not_applied` or `unsafe_to_wait`. For every fallback, say in the
114
- configured locale why a native control was not usable, show the exact approval
115
- value and confirm that authority is unchanged. This transient outcome is not
116
- approval evidence. A new explicit user request may reopen the unchanged decision
117
- only after fresh run/gate/artefact revalidation; never retry automatically.
118
-
119
- Surface behavior:
120
-
121
- - Codex: invoke the native short-question/request-user-input control only when preflight proves `exact_option_value` or `separate_label_and_value`, and omit auto-resolution. The canonical `decorated_label_only` capability must use exact text without invoking the adapter. `Approval: <GateName> (Recommended)` is never a valid option or approval.
122
- - Claude Code: invoke `AskUserQuestion` on the first eligible attempt only when no timeout can auto-continue and no hook supplies `answers` or `updatedInput`; if it is not rendered or applied, use exact text immediately. Claude permissions and `ExitPlanMode` remain separate.
123
- - OpenCode: use built-in `question` when permitted. Preserve explicit `permission.question` denial and use exact text in that case. `once`, `always`, `reject` and auto mode never become gate input.
124
- - GitHub Copilot: the current repository-instruction surface has no conforming native approval adapter. Transmit the canonical rendered cards followed by the exact-text request; never claim or simulate a native control. Copilot tool confirmations, plan interactions and repository permissions remain separate.
125
- - Other, unavailable or non-interactive surfaces: use exact textual approval and wait for a new explicit user response.
126
-
127
- Localized labels such as `Überarbeiten`/`Revise`, `Ablehnen`/`Decline` and `Abbrechen`/`Cancel` are presentation mappings to stable non-approval outcomes only. A label, description, option position or recommendation never authorizes a gate. Host-provided free-text or `Überspringen`/`Skip` actions never advance an AGDF gate.
128
-
129
- A free-form response must still exactly match the current gate's approval formula after revalidation. Keep `decline`, `cancel`, `no_response`, `timeout`, `empty`, `invalid` and `stale` distinct; none advances the gate. Native presentation, host permission and plan approval are inputs or separate authority domains, never durable AGDF authority.
130
-
131
- Every primary chat card shows the selected run's `UR`, `PRD`, `SD` and `TP` in that order. Render an existing canonical path as a readable link and a missing artefact as localized non-link text; never guess paths. Resolve the human run title from current artefact heading, approved UR heading, Objective, then normalized `run_id`. Status, blocked, clarification and internal-step interactions use the same locale and artefact projection but do not show approval buttons. Keep raw process keys and machine status values in JSON or audit detail.
132
-
133
- ### Breadcrumb Rendering
134
-
135
- The compact human Run Status Card includes a single-line path-derived breadcrumb showing the user's position in the delivery journey. Derive it from the Mode/Slice Decision and the Approvals table — not a fixed template. Use `✓` for fulfilled, `●` for current, `○` for open, separated by ` · `. Non-applicable gates are absent. See the Runtime Contract §Breadcrumb for the path templates and the derived `breadcrumb` array.
136
-
137
- ### Post-Acceptance Transition Narration
138
-
139
- After each accepted gate approval is persisted, emit exactly one narration line using the template `<what was satisfied> → <what the agent does next internally> → <user action: yes/no>`. This generalizes the existing TP pattern (step 7 above) to every gate advancement. The narration is post-acceptance only: it never appears in the same message as the Gate Transition Card, never contains the `Approval:` value, and never repeats the decision's effect. For internal steps (Brownfield Review, Brownfield Analysis), state what the agent does next and that no user action is required, without exposing `next_user_gate: none` or asking for a second approval. See the Runtime Contract §Post-Acceptance Transition Narration for the full contract.
140
-
141
- ### Internal-State Collapse in the Human Card
142
-
143
- When rendering the compact human Run Status Card, collapse internal sub-states (`verified_change` sub-states, `context_graph_required_action`, `multi_scope_state`) to stable human labels. `escalated`, `open_gap` and `blocked` remain explicitly visible. The full machine/audit projection retains all raw values unchanged. See the Runtime Contract §Internal-State Collapse for the complete mapping table.
144
-
145
- ### On-Demand "Why?" Response
74
+ `../../meta/contracts/interaction.md` is the complete normative owner for interaction kinds, locale,
75
+ canonical values, presentation order, adapter capability, deliberate waiting, native/fallback
76
+ behavior, transient outcomes, permissions and post-response validation. Load and apply that contract;
77
+ do not restate or infer a surface matrix in this skill.
146
78
 
147
- When the user asks "why?" or "Warum?" at any gate or internal step, respond with a `status` interaction (not `gate_approval`):
79
+ This skill owns only these operational responsibilities:
148
80
 
149
- 1. Pull the curated rationale from `gateRationale()` in the resolved locale.
150
- 2. Compose one fulfilled line from the selected run's Approvals table and artefact status.
151
- 3. Compose one protects-against line from the gate's rationale and the existing `primary.actions` copy.
152
- 4. Do not show approval controls. Do not advance any gate. Do not merge with the approval envelope.
81
+ 1. Select exactly one run and evaluate its current gate.
82
+ 2. Confirm that the required durable artefact is present and ready.
83
+ 3. Consume the canonical `approval_presentation` verbatim for the selected run, gate and revision.
84
+ 4. Present that projection and obtain deliberate input through the contract-selected native or exact-text path.
85
+ 5. Revalidate the same run, gate and revision immediately after the response and before persistence.
86
+ 6. Persist only a currently valid exact approval through the existing control-state workflow.
153
87
 
154
- The response is deterministic: same gate, same question, same answer. The `gate_approval` options remain exactly `approve | revise | decline | cancel`; no "why" option is added. See the Runtime Contract §Gate-Rationale-Registry and §On-Demand "Why?" Interaction for the full contract.
88
+ For status, blocked, read-only or rationale interactions, consume the same canonical projection and
89
+ locale contract without asking for approval. Internal process steps remain distinct from user
90
+ decisions. If the projection, adapter evidence or revalidation is missing, follow the contract's
91
+ fail-closed outcome and leave authority unchanged.
155
92
 
156
93
  ## Rules
157
94
  1. Fail closed when a required approval or artefact status is missing.
@@ -6,18 +6,6 @@ import {
6
6
  resolveRuns,
7
7
  writeLegacyProjection,
8
8
  } from "../control-state/index.js";
9
- import {
10
- buildStatusCard,
11
- evaluateGateCheck,
12
- printApprovalEnvelope,
13
- postApprovalTransition,
14
- printGateCheckReport,
15
- } from "../control-evaluation/gate-check.js";
16
- import {
17
- evaluateDeliveryMap,
18
- printDeliveryMapReport,
19
- } from "../control-evaluation/delivery-map.js";
20
- import { evaluateDoctor, printDoctorReport } from "../control-evaluation/doctor.js";
21
9
  import {
22
10
  defaultOpenCodeConfigDir,
23
11
  evaluateOpenCodeStatus,
@@ -39,23 +27,23 @@ import {
39
27
  import { printGeneralStatus, printLifecycleResult } from "../lifecycle/presentation.js";
40
28
  import { createLifecycleResult, globalInstallRestartAction, lifecycleFailure } from "../lifecycle/result.js";
41
29
  import { evaluateGeneralStatus } from "../lifecycle/status.js";
42
- import { agdfFragmentPath, generatedFilesForTarget, openCodeConfigFragmentPath } from "../scaffold/plan.js";
30
+ import { agdfFragmentPath, generatedFilesForTarget } from "../scaffold/plan.js";
43
31
  import { printNextSteps } from "../scaffold/presentation.js";
44
- import { assertGeneratedWritePlan, removeOwnedLegacyOpenCodeAgents, writeGeneratedFile } from "../scaffold/write.js";
32
+ import { assertGeneratedWritePlan, writeGeneratedFile } from "../scaffold/write.js";
45
33
  import { renderUsage, resolveCommand, validateCommandOptions } from "./command-registry.js";
46
- import { executeDeliveryPathSearch } from "./delivery-path-search-command.js";
47
34
  import { CliUsageError, parseArgs } from "./parse-args.js";
35
+ import { pluginDefinition } from "./runtime-context.js";
36
+ import { createValidationHandlers } from "./validation-handlers.js";
48
37
 
49
- const deliveryMapDependencies = Object.freeze({
50
- evaluateDoctor,
51
- buildStatusCard,
52
- postApprovalTransition,
53
- });
54
-
55
- function createHandlers({ io, env, exec }) {
56
- const installerAdapters = exec ? { exec, io } : { io };
38
+ function createHandlers({ io, env, exec, prepare }) {
39
+ const installerAdapters = {
40
+ ...(exec ? { exec } : {}),
41
+ ...(prepare ? { prepare } : {}),
42
+ ...(env.AGDF_DATA_DIR ? { dataRoot: env.AGDF_DATA_DIR } : {}),
43
+ };
57
44
  const scaffoldHandler = (options) => runScaffold(options, io);
58
45
  return new Map([
46
+ ...createValidationHandlers(io),
59
47
  ["codex-repo", scaffoldHandler],
60
48
  ["copilot", scaffoldHandler],
61
49
  ["opencode-repo", scaffoldHandler],
@@ -77,37 +65,6 @@ function createHandlers({ io, env, exec }) {
77
65
  io.log(output);
78
66
  return 0;
79
67
  }],
80
- ["doctor", (options) => {
81
- const report = evaluateDoctor(options.dir, options);
82
- printDoctorReport(report, options.json, io);
83
- return report.status === "block" ? 2 : 0;
84
- }],
85
- ["gate-check", (options) => {
86
- const report = evaluateGateCheck(options.dir, options);
87
- if (options.approvalEnvelope) {
88
- const output = printApprovalEnvelope(report, {
89
- io,
90
- reEvaluate: () => evaluateGateCheck(options.dir, options),
91
- });
92
- return output.status === "blocked" ? 2 : 0;
93
- }
94
- printGateCheckReport(report, options.json, options.statusCard, io);
95
- return report.status === "blocked" ? 2 : 0;
96
- }],
97
- ["delivery-map", (options) => {
98
- const report = evaluateDeliveryMap(options.dir, options, deliveryMapDependencies);
99
- printDeliveryMapReport(report, options.json, io);
100
- return report.status === "block" ? 2 : 0;
101
- }],
102
- ["delivery-path-search", async (options) => {
103
- try {
104
- const result = await executeDeliveryPathSearch(options, io);
105
- return result.status === "recommendation" ? 0 : 2;
106
- } catch (error) {
107
- io.error(`Delivery Path Search failed: ${error.message}`);
108
- return 2;
109
- }
110
- }],
111
68
  ["opencode-status", (options) => {
112
69
  const configDir = env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir();
113
70
  const report = evaluateOpenCodeStatus(options.dir, configDir);
@@ -198,7 +155,7 @@ function runLifecyclePhase(phase, operation) {
198
155
 
199
156
  function installResult(installed, { restartRequired, nextAction }) {
200
157
  return createLifecycleResult({
201
- operation: "install",
158
+ operation: installed.operation ?? "install",
202
159
  result: "success",
203
160
  surface: installed.surface,
204
161
  scope: "global",
@@ -308,7 +265,6 @@ function runUninstall(options, { io, env, exec }) {
308
265
  function runScaffold(options, io) {
309
266
  const files = generatedFilesForTarget(options.target, options.dir, options.force, options.language);
310
267
  const wroteAgentsFragment = files.some((file) => file.path === agdfFragmentPath);
311
- const wroteOpenCodeConfigFragment = files.some((file) => file.path === openCodeConfigFragmentPath);
312
268
  let removedOpenCodeAgents = [];
313
269
 
314
270
  try {
@@ -316,19 +272,25 @@ function runScaffold(options, io) {
316
272
  for (const file of files) {
317
273
  writeGeneratedFile(options.dir, file.path, file.content, options.force, file.allowOverwrite);
318
274
  }
319
- if (options.target === "opencode-repo") removedOpenCodeAgents = removeOwnedLegacyOpenCodeAgents(options.dir);
275
+ // Legacy OpenCode assets are intentionally preserved. A future explicit migration command
276
+ // may remove only ownership-proven files after its precedence behavior is verified.
320
277
  } catch (error) {
321
278
  io.error(error.message);
322
279
  return 1;
323
280
  }
324
281
 
325
- printNextSteps(options.target, options.dir, files, wroteAgentsFragment, wroteOpenCodeConfigFragment, removedOpenCodeAgents, { verbose: options.verbose, json: options.json, io });
282
+ printNextSteps(options.target, options.dir, files, wroteAgentsFragment, removedOpenCodeAgents, { verbose: options.verbose, json: options.json, io });
326
283
  return 0;
327
284
  }
328
285
 
329
286
  export async function runCli(argv = process.argv.slice(2), adapters = {}) {
330
287
  const io = adapters.io ?? console;
331
288
  const env = adapters.env ?? process.env;
289
+ if (argv.includes("--version")) {
290
+ const output = { name: "create-agdf", version: pluginDefinition.version };
291
+ io.log(argv.includes("--json") ? JSON.stringify(output) : output.version);
292
+ return 0;
293
+ }
332
294
  let parsed;
333
295
  try {
334
296
  parsed = parseArgs(argv, adapters.parser);
@@ -353,7 +315,7 @@ export async function runCli(argv = process.argv.slice(2), adapters = {}) {
353
315
  }
354
316
  const command = resolveCommand(options.target);
355
317
  if (!command) throw new Error(`No handler is registered for ${options.target}.`);
356
- const handler = createHandlers({ io, env, exec: adapters.exec }).get(command.handler);
318
+ const handler = createHandlers({ io, env, exec: adapters.exec, prepare: adapters.prepare }).get(command.handler);
357
319
  if (!handler) throw new Error(`No implementation is registered for ${command.name}.`);
358
320
  return await handler(options);
359
321
  }
@@ -23,16 +23,16 @@ export const commandRegistry = Object.freeze([
23
23
  command("both", { scaffold: [""] }),
24
24
  command("init", { preferred: [""], scaffold: [""] }),
25
25
  command("config", { scaffold: [" --language de"] }),
26
- command("doctor", { preferred: [""], scaffold: [""], legacy: [" --json"] }),
27
- command("gate-check", { preferred: [" --approval-envelope", " --json"], scaffold: [""], legacy: [" --json"] }),
28
- command("delivery-map", { scaffold: [""] }),
26
+ command("doctor", { local: [""], scaffold: [""], legacy: [" --json"] }),
27
+ command("gate-check", { local: [" --approval-envelope", " --json"], scaffold: [""], legacy: [" --json"] }),
28
+ command("delivery-map", { local: [" --json"], scaffold: [""] }),
29
29
  command("delivery-path-search", {
30
- preferred: [" --surface codex --json", " --surface claude --json"],
30
+ local: [" --surface codex --json", " --surface claude --json"],
31
31
  scaffold: [" --surface codex", " --surface claude"],
32
32
  }),
33
- command("run-create", { preferred: [" --run <run_id>"] }),
34
- command("run-migrate", { preferred: [" [--run <run_id>]"] }),
35
- command("run-render-legacy", { preferred: [" --run <run_id>"] }),
33
+ command("run-create", { local: [" --run <run_id>"] }),
34
+ command("run-migrate", { local: [" [--run <run_id>]"] }),
35
+ command("run-render-legacy", { local: [" --run <run_id>"] }),
36
36
  ]);
37
37
 
38
38
  const commandByName = new Map(commandRegistry.map((entry) => [entry.name, entry]));
@@ -87,13 +87,11 @@ Operating model:
87
87
  The CLI validates, renders deterministic gate output and supports automation.
88
88
 
89
89
  Repeated local validation (after global installation):
90
- agdf doctor
91
- agdf gate-check --approval-envelope
92
- agdf gate-check --json
90
+ ${usageLines("local", "agdf ")}
93
91
 
94
92
  Bootstrap, installation and explicit refresh:
95
93
 
96
- Primary commands:
94
+ Bootstrap and lifecycle commands:
97
95
  ${usageLines("preferred", "npx --yes @agdf/cli@latest ")}
98
96
 
99
97
  Advanced / Compatibility
@@ -0,0 +1,45 @@
1
+ import {
2
+ buildStatusCard,
3
+ evaluateGateCheck,
4
+ printApprovalEnvelope,
5
+ postApprovalTransition,
6
+ printGateCheckReport,
7
+ } from "../control-evaluation/gate-check.js";
8
+ import { evaluateDeliveryMap, printDeliveryMapReport } from "../control-evaluation/delivery-map.js";
9
+ import { evaluateDoctor, printDoctorReport } from "../control-evaluation/doctor.js";
10
+ import { executeDeliveryPathSearch } from "./delivery-path-search-command.js";
11
+
12
+ const deliveryMapDependencies = Object.freeze({ evaluateDoctor, buildStatusCard, postApprovalTransition });
13
+
14
+ export function createValidationHandlers(io = console) {
15
+ return new Map([
16
+ ["doctor", (options) => {
17
+ const report = evaluateDoctor(options.dir, options);
18
+ printDoctorReport(report, options.json, io);
19
+ return report.status === "block" ? 2 : 0;
20
+ }],
21
+ ["gate-check", (options) => {
22
+ const report = evaluateGateCheck(options.dir, options);
23
+ if (options.approvalEnvelope) {
24
+ const output = printApprovalEnvelope(report, { io, reEvaluate: () => evaluateGateCheck(options.dir, options) });
25
+ return output.status === "blocked" ? 2 : 0;
26
+ }
27
+ printGateCheckReport(report, options.json, options.statusCard, io);
28
+ return report.status === "blocked" ? 2 : 0;
29
+ }],
30
+ ["delivery-map", (options) => {
31
+ const report = evaluateDeliveryMap(options.dir, options, deliveryMapDependencies);
32
+ printDeliveryMapReport(report, options.json, io);
33
+ return report.status === "block" ? 2 : 0;
34
+ }],
35
+ ["delivery-path-search", async (options) => {
36
+ try {
37
+ const result = await executeDeliveryPathSearch(options, io);
38
+ return result.status === "recommendation" ? 0 : 2;
39
+ } catch (error) {
40
+ io.error(`Delivery Path Search failed: ${error.message}`);
41
+ return 2;
42
+ }
43
+ }],
44
+ ]);
45
+ }
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { aggregate, resolveRuns, verifyLegacyProjection } from '../control-state/index.js';
4
- import { doctorRequiredFiles } from '../scaffold/plan.js';
4
+ import { doctorRequiredFiles } from './required-files.js';
5
5
  import { analyzeDeliveryMap } from './delivery-map.js';
6
6
  import { evaluateVerifiedChange } from './verified-change.js';
7
7
  import { analyzeArtefactRoleConsistency, analyzeDurableGateArtefactConsistency, modeSliceDecision, readRunState } from './run-state.js';
@@ -28,10 +28,10 @@ export function postApprovalTransition(missingApproval) {
28
28
  const transitions = new Map([
29
29
  ["Approval: UR", {
30
30
  next_gate_after_approval: "Brownfield Review",
31
- allowed_after_approval: "Run Brownfield Review and record Mode/Slice Decision before PRD or implementation.",
32
- internal_next_step: "Brownfield Review and Mode/Slice Decision",
33
- next_user_gate: "PRD",
34
- user_action_required: "yes",
31
+ allowed_after_approval: "Run Brownfield Review and proportional routing as one internal operation; no user action is required now.",
32
+ internal_next_step: "Brownfield Review and proportional routing",
33
+ next_user_gate: "none",
34
+ user_action_required: "no",
35
35
  }],
36
36
  ["Approval: PRD", {
37
37
  next_gate_after_approval: "SD",
@@ -80,7 +80,7 @@ const BREADCRUMB_PATH_TEMPLATES = {
80
80
  structured_delivery: ["UR", "PRD", "SD", "TP", "QA", "UAT"],
81
81
  structured_slice: ["UR", "PRD", "SD", "TP", "QA", "UAT"],
82
82
  verified_change: ["UR", "Verified Change", "OR"],
83
- quick_task: ["UR", "Quick Task"],
83
+ quick_task: ["UR", "Compact Delivery"],
84
84
  block: ["UR", "Block"],
85
85
  undecided: ["UR"],
86
86
  };
@@ -102,11 +102,11 @@ function buildBreadcrumbPath(modeSliceDecision, currentGate, runState) {
102
102
  return { gate, status: "open" };
103
103
  }
104
104
  if (gate === currentGate) return { gate, status: "current" };
105
- if ((gate === "Verified Change" || gate === "Quick Task") && currentGate === "OR")
105
+ if ((gate === "Verified Change" || gate === "Compact Delivery") && currentGate === "OR")
106
106
  return { gate, status: "fulfilled" };
107
107
  if (gate === "Verified Change" && modeSliceDecision === "verified_change")
108
108
  return { gate, status: "current" };
109
- if (gate === "Quick Task" && modeSliceDecision === "quick_task")
109
+ if (gate === "Compact Delivery" && modeSliceDecision === "quick_task")
110
110
  return { gate, status: "current" };
111
111
  if (gate === "Block" && modeSliceDecision === "block")
112
112
  return { gate, status: "current" };
@@ -0,0 +1,9 @@
1
+ import { join } from "node:path";
2
+
3
+ export const doctorRequiredFiles = Object.freeze([
4
+ join(".agdf", "control", "AGDF_RUN.md"),
5
+ join(".agdf", "control", "MASTER_BACKLOG.md"),
6
+ join(".agdf", "control", "SOT_REGISTRY.md"),
7
+ join(".agdf", "control", "CONTEXT_GRAPH.md"),
8
+ join(".agdf", "control", "AGENT_QUALITY_CONTRACTS.json"),
9
+ ]);