create-agdf 0.8.3 → 0.8.5

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.
@@ -2259,10 +2259,14 @@ function buildStatusCard({
2259
2259
  const qualityOutlook = deriveQualityOutlook(runState, findings);
2260
2260
  const postApproval = postApprovalTransition(missingApproval);
2261
2261
  const isUserGateApproval = missingApproval !== "none";
2262
+ const lifecycle = extractField(runState.content ?? "", "lifecycle") || "unknown";
2263
+ const nativeAttemptRequired = status === "open" && isUserGateApproval;
2262
2264
  return {
2263
2265
  run_id: extractField(runState.content ?? "", "run_id") || "unknown",
2264
2266
  presentation_language: chatLanguage,
2265
2267
  mode: extractField(runState.content ?? "", "mode") || "unknown",
2268
+ lifecycle,
2269
+ delivery_state: lifecycle === "completed" && currentGate === "OR" ? "completed_closeout_pending" : lifecycle,
2266
2270
  status,
2267
2271
  current_gate: currentGate,
2268
2272
  mode_slice_decision: runState.mode_slice_decision?.decision || "undecided",
@@ -2280,6 +2284,8 @@ function buildStatusCard({
2280
2284
  next_skill: nextSkillByGate[currentGate] ?? "gate-check",
2281
2285
  next_step: nextAllowedAction,
2282
2286
  quality_outlook: qualityOutlook,
2287
+ interaction_kind: nativeAttemptRequired ? "gate_approval" : status === "blocked" ? "blocked" : "status",
2288
+ native_attempt_required: nativeAttemptRequired,
2283
2289
  };
2284
2290
  }
2285
2291
 
@@ -2736,6 +2742,8 @@ function evaluateGateCheck(targetDir, selection = {}) {
2736
2742
  doctor_summary: doctorReport.summary,
2737
2743
  evidence_refs: runState.evidence_refs,
2738
2744
  quality_outlook: deriveQualityOutlook(runState, deliveryMap.findings),
2745
+ interaction_kind: statusCard.interaction_kind,
2746
+ native_attempt_required: statusCard.native_attempt_required,
2739
2747
  candidate_runs: runState.candidate_runs ?? [],
2740
2748
  status_card: statusCard,
2741
2749
  delivery_map: {
@@ -2764,6 +2772,7 @@ function printGateCheckStatusCard(report) {
2764
2772
  console.log(`${labels.run}: ${card.run_id}`);
2765
2773
  console.log(`${labels.humanTitle}: ${presentation.runTitle}`);
2766
2774
  console.log(`${labels.gate}: ${card.current_gate} — ${presentation.gateTitle}`);
2775
+ console.log(`${labels.lifecycle}: ${primary.lifecycle[card.delivery_state] ?? primary.lifecycle.unknown}`);
2767
2776
  console.log(`${labels.artefacts}: ${formatArtefactRefs(presentation.artefactRefs)}`);
2768
2777
  console.log(`${labels.blocked}: ${card.blocking_condition === "none" ? primary.none : primary.blocked}`);
2769
2778
  console.log(`${labels.missing}: ${card.missing_approval === "none" ? primary.none : card.missing_approval}`);
@@ -63,18 +63,24 @@ For a ready `gate_approval`:
63
63
  1. Resolve exactly one selected run and evaluate the current gate.
64
64
  2. Confirm the required durable artefact is present and ready before presenting a question.
65
65
  3. Build one immutable, non-authorizing presentation snapshot from the selected evaluated run and current revision identity.
66
- 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
66
+ 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. Its first visible line is the localized action-oriented gate title as a level-two Markdown heading or equivalent accessible host heading; generic AGDF/card labels and raw gate IDs cannot be the primary heading. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
67
67
  5. In the same assistant message, render a separate localized Gate Transition Card second, immediately before any native question or exact-text fallback. It includes the deterministic human run title and `UR · PRD · SD · TP` links from the selected run. Never put either card only into the question, button description or hidden tool context. Do not invoke the native question tool until the complete two-card envelope is visible.
68
68
  6. Compose the transition card as one human-readable gate title with `run_id`, one ready-for-decision line, one short approval-effect block and one short next-transition block. It must answer only: where am I, what does this decision do, and what happens next. Run and gate identity may anchor both cards; do not duplicate status rows, action inventories or the native question.
69
69
  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.
70
70
  8. Ask exactly one question that names the selected `run_id` and `current_gate`.
71
71
  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.
72
72
  10. Use the surface adapter declared in the canonical plugin definition only when it can wait for deliberate input without auto-resolution; otherwise request the same exact approval in concise text.
73
- 11. Render both cards once in that single complete assistant message. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
73
+ 11. Render both cards once in that single complete assistant message. Never merge, reverse, omit or duplicate them; the action heading does not replace either card. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
74
74
  12. Re-run gate evaluation for the same run and expected gate after the response and immediately before persistence.
75
75
  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.
76
76
  14. Persist accepted input only through the existing control-state workflow.
77
77
 
78
+ The ready-gate projection must expose `native_attempt_required: true`. Treat this as a mandatory
79
+ orchestration instruction: after rendering the two cards, invoke the configured native question
80
+ adapter exactly once before using the exact-text fallback. A hook, permission result or session
81
+ context message cannot replace that attempt or supply its answer. For every non-ready interaction,
82
+ the signal is absent or false and no approval control may be shown.
83
+
78
84
  Before composing the question, resolve the configured chat locale from `.agdf/control/config.json` through `../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.
79
85
 
80
86
  For the transition card, use the complete resolved 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`. Keep each card in one locale. Use a localized human-readable gate title rather than an internal status label, while leaving the exact gate identifier and approval value unchanged. Do not render a Markdown table, dashboard rows, raw control-state keys, diagnostic codes, evidence lists, a duplicated gate question or a false user gate in the approval-time card.
@@ -25,6 +25,7 @@
25
25
  "skill": "Next skill",
26
26
  "step": "Next step",
27
27
  "quality": "Quality outlook",
28
+ "lifecycle": "Delivery status",
28
29
  "allowed": "Allowed now",
29
30
  "forbidden": "Forbidden now",
30
31
  "artefacts": "Artefacts"
@@ -64,6 +65,14 @@
64
65
  "CR": "Code review",
65
66
  "OR": "Delivery report"
66
67
  },
68
+ "gateActionTitles": {
69
+ "UR": "Approve user requirements",
70
+ "PRD": "Approve product requirements",
71
+ "SD": "Approve solution design",
72
+ "TP": "Approve task and test plan",
73
+ "QA": "Approve quality decision",
74
+ "UAT": "Accept delivery result"
75
+ },
67
76
  "interaction": {
68
77
  "ready": "Ready for your decision",
69
78
  "approveHeading": "Approve now",
@@ -91,6 +100,13 @@
91
100
  "none": "none",
92
101
  "blocked": "current gate prerequisites",
93
102
  "quality": "Keep the presentation contract, evidence and gate authority aligned.",
103
+ "lifecycle": {
104
+ "active": "in progress",
105
+ "completed_closeout_pending": "completed — delivery closeout pending",
106
+ "completed": "completed",
107
+ "blocked": "blocked",
108
+ "unknown": "status not available"
109
+ },
94
110
  "actions": {
95
111
  "UR": "Clarify and approve the user requirements.",
96
112
  "Brownfield Review": "Review existing owners and choose the smallest safe delivery path.",
@@ -132,6 +148,7 @@
132
148
  "skill": "Nächster Skill",
133
149
  "step": "Nächster Schritt",
134
150
  "quality": "Qualitätsausblick",
151
+ "lifecycle": "Lieferstatus",
135
152
  "allowed": "Jetzt erlaubt",
136
153
  "forbidden": "Aktuell verboten",
137
154
  "artefacts": "Artefakte"
@@ -171,6 +188,14 @@
171
188
  "CR": "Code-Review",
172
189
  "OR": "Lieferbericht"
173
190
  },
191
+ "gateActionTitles": {
192
+ "UR": "Nutzeranforderung freigeben",
193
+ "PRD": "Produktanforderungen freigeben",
194
+ "SD": "Lösungsdesign freigeben",
195
+ "TP": "Umsetzungsplan freigeben",
196
+ "QA": "Qualitätsentscheidung freigeben",
197
+ "UAT": "Ergebnis abnehmen"
198
+ },
174
199
  "interaction": {
175
200
  "ready": "Bereit für deine Entscheidung",
176
201
  "approveHeading": "Jetzt freigeben",
@@ -198,6 +223,13 @@
198
223
  "none": "keine",
199
224
  "blocked": "Voraussetzungen des aktuellen Gates",
200
225
  "quality": "Präsentationsvertrag, Nachweise und Gate-Berechtigung konsistent halten.",
226
+ "lifecycle": {
227
+ "active": "in Arbeit",
228
+ "completed_closeout_pending": "abgeschlossen — Abschluss offen",
229
+ "completed": "abgeschlossen",
230
+ "blocked": "blockiert",
231
+ "unknown": "Status nicht verfügbar"
232
+ },
201
233
  "actions": {
202
234
  "UR": "Nutzeranforderungen klären und freigeben.",
203
235
  "Brownfield Review": "Bestehende Owner prüfen und den kleinsten sicheren Lieferweg wählen.",
@@ -181,6 +181,14 @@ before invoking any native question tool or emitting an exact-text approval
181
181
  request. Splitting the cards across separate assistant turns or invoking the
182
182
  tool after only one card is a failed interaction, not a valid presentation.
183
183
 
184
+ The first visible line of that envelope is the localized action-oriented title
185
+ of the current user gate, rendered as a level-two Markdown heading or equivalent
186
+ accessible host heading inside the compact approval-time Run Status Card.
187
+ `AGDF Status`, `Run Status Card`, `Gate Transition Card`, raw gate identifiers
188
+ and machine values are semantic or diagnostic labels only and must not become
189
+ the primary heading. The action title appears exactly once and does not replace,
190
+ merge or reorder either required card block.
191
+
184
192
  The compact approval-time Run Status Card contains exactly six operational
185
193
  fields: selected run, readiness status, current gate, missing exact approval,
186
194
  one next action and quality outlook. It uses localized human-readable labels
@@ -390,6 +398,7 @@ interaction_kind: clarification | tool_permission | gate_approval | blocked | st
390
398
  surface: codex | claude | opencode | fallback
391
399
  run_id: required for gate_approval
392
400
  current_gate: required for gate_approval
401
+ native_attempt_required: true only for an eligible gate_approval before the first adapter attempt
393
402
  prompt: required
394
403
  options: required for a structured question
395
404
  effects: required when the interaction can cause side effects
@@ -420,6 +429,12 @@ Before presenting `gate_approval`, the agent must:
420
429
  6. reject missing evidence, ambiguous or wrong run, wrong gate, stale state and any response that is no longer valid;
421
430
  7. persist an accepted approval only through the existing control-state workflow.
422
431
 
432
+ For an eligible `gate_approval`, `native_attempt_required` is a mandatory orchestration signal. The
433
+ agent must make exactly one configured native adapter attempt after the two orientation cards and
434
+ before any exact-text fallback. Hooks may prepare context but must not answer, approve or replace
435
+ the adapter attempt. The signal is absent or false for clarification, blocked, status-only,
436
+ internal-step and non-ready interactions.
437
+
423
438
  The first eligible native-attempt has a single bounded outcome: the declared
424
439
  host control is presented, or the agent immediately uses the exact-text
425
440
  fallback. A host that does not apply the control does not trigger a second
@@ -25,6 +25,7 @@
25
25
  "skill": "Next skill",
26
26
  "step": "Next step",
27
27
  "quality": "Quality outlook",
28
+ "lifecycle": "Delivery status",
28
29
  "allowed": "Allowed now",
29
30
  "forbidden": "Forbidden now",
30
31
  "artefacts": "Artefacts"
@@ -64,6 +65,14 @@
64
65
  "CR": "Code review",
65
66
  "OR": "Delivery report"
66
67
  },
68
+ "gateActionTitles": {
69
+ "UR": "Approve user requirements",
70
+ "PRD": "Approve product requirements",
71
+ "SD": "Approve solution design",
72
+ "TP": "Approve task and test plan",
73
+ "QA": "Approve quality decision",
74
+ "UAT": "Accept delivery result"
75
+ },
67
76
  "interaction": {
68
77
  "ready": "Ready for your decision",
69
78
  "approveHeading": "Approve now",
@@ -91,6 +100,13 @@
91
100
  "none": "none",
92
101
  "blocked": "current gate prerequisites",
93
102
  "quality": "Keep the presentation contract, evidence and gate authority aligned.",
103
+ "lifecycle": {
104
+ "active": "in progress",
105
+ "completed_closeout_pending": "completed — delivery closeout pending",
106
+ "completed": "completed",
107
+ "blocked": "blocked",
108
+ "unknown": "status not available"
109
+ },
94
110
  "actions": {
95
111
  "UR": "Clarify and approve the user requirements.",
96
112
  "Brownfield Review": "Review existing owners and choose the smallest safe delivery path.",
@@ -132,6 +148,7 @@
132
148
  "skill": "Nächster Skill",
133
149
  "step": "Nächster Schritt",
134
150
  "quality": "Qualitätsausblick",
151
+ "lifecycle": "Lieferstatus",
135
152
  "allowed": "Jetzt erlaubt",
136
153
  "forbidden": "Aktuell verboten",
137
154
  "artefacts": "Artefakte"
@@ -171,6 +188,14 @@
171
188
  "CR": "Code-Review",
172
189
  "OR": "Lieferbericht"
173
190
  },
191
+ "gateActionTitles": {
192
+ "UR": "Nutzeranforderung freigeben",
193
+ "PRD": "Produktanforderungen freigeben",
194
+ "SD": "Lösungsdesign freigeben",
195
+ "TP": "Umsetzungsplan freigeben",
196
+ "QA": "Qualitätsentscheidung freigeben",
197
+ "UAT": "Ergebnis abnehmen"
198
+ },
174
199
  "interaction": {
175
200
  "ready": "Bereit für deine Entscheidung",
176
201
  "approveHeading": "Jetzt freigeben",
@@ -198,6 +223,13 @@
198
223
  "none": "keine",
199
224
  "blocked": "Voraussetzungen des aktuellen Gates",
200
225
  "quality": "Präsentationsvertrag, Nachweise und Gate-Berechtigung konsistent halten.",
226
+ "lifecycle": {
227
+ "active": "in Arbeit",
228
+ "completed_closeout_pending": "abgeschlossen — Abschluss offen",
229
+ "completed": "abgeschlossen",
230
+ "blocked": "blockiert",
231
+ "unknown": "Status nicht verfügbar"
232
+ },
201
233
  "actions": {
202
234
  "UR": "Nutzeranforderungen klären und freigeben.",
203
235
  "Brownfield Review": "Bestehende Owner prüfen und den kleinsten sicheren Lieferweg wählen.",
@@ -181,6 +181,14 @@ before invoking any native question tool or emitting an exact-text approval
181
181
  request. Splitting the cards across separate assistant turns or invoking the
182
182
  tool after only one card is a failed interaction, not a valid presentation.
183
183
 
184
+ The first visible line of that envelope is the localized action-oriented title
185
+ of the current user gate, rendered as a level-two Markdown heading or equivalent
186
+ accessible host heading inside the compact approval-time Run Status Card.
187
+ `AGDF Status`, `Run Status Card`, `Gate Transition Card`, raw gate identifiers
188
+ and machine values are semantic or diagnostic labels only and must not become
189
+ the primary heading. The action title appears exactly once and does not replace,
190
+ merge or reorder either required card block.
191
+
184
192
  The compact approval-time Run Status Card contains exactly six operational
185
193
  fields: selected run, readiness status, current gate, missing exact approval,
186
194
  one next action and quality outlook. It uses localized human-readable labels
@@ -390,6 +398,7 @@ interaction_kind: clarification | tool_permission | gate_approval | blocked | st
390
398
  surface: codex | claude | opencode | fallback
391
399
  run_id: required for gate_approval
392
400
  current_gate: required for gate_approval
401
+ native_attempt_required: true only for an eligible gate_approval before the first adapter attempt
393
402
  prompt: required
394
403
  options: required for a structured question
395
404
  effects: required when the interaction can cause side effects
@@ -420,6 +429,12 @@ Before presenting `gate_approval`, the agent must:
420
429
  6. reject missing evidence, ambiguous or wrong run, wrong gate, stale state and any response that is no longer valid;
421
430
  7. persist an accepted approval only through the existing control-state workflow.
422
431
 
432
+ For an eligible `gate_approval`, `native_attempt_required` is a mandatory orchestration signal. The
433
+ agent must make exactly one configured native adapter attempt after the two orientation cards and
434
+ before any exact-text fallback. Hooks may prepare context but must not answer, approve or replace
435
+ the adapter attempt. The signal is absent or false for clarification, blocked, status-only,
436
+ internal-step and non-ready interactions.
437
+
423
438
  The first eligible native-attempt has a single bounded outcome: the declared
424
439
  host control is presented, or the agent immediately uses the exact-text
425
440
  fallback. A host that does not apply the control does not trigger a second
@@ -63,18 +63,24 @@ For a ready `gate_approval`:
63
63
  1. Resolve exactly one selected run and evaluate the current gate.
64
64
  2. Confirm the required durable artefact is present and ready before presenting a question.
65
65
  3. Build one immutable, non-authorizing presentation snapshot from the selected evaluated run and current revision identity.
66
- 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
66
+ 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. Its first visible line is the localized action-oriented gate title as a level-two Markdown heading or equivalent accessible host heading; generic AGDF/card labels and raw gate IDs cannot be the primary heading. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
67
67
  5. In the same assistant message, render a separate localized Gate Transition Card second, immediately before any native question or exact-text fallback. It includes the deterministic human run title and `UR · PRD · SD · TP` links from the selected run. Never put either card only into the question, button description or hidden tool context. Do not invoke the native question tool until the complete two-card envelope is visible.
68
68
  6. Compose the transition card as one human-readable gate title with `run_id`, one ready-for-decision line, one short approval-effect block and one short next-transition block. It must answer only: where am I, what does this decision do, and what happens next. Run and gate identity may anchor both cards; do not duplicate status rows, action inventories or the native question.
69
69
  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.
70
70
  8. Ask exactly one question that names the selected `run_id` and `current_gate`.
71
71
  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.
72
72
  10. Use the surface adapter declared in the canonical plugin definition only when it can wait for deliberate input without auto-resolution; otherwise request the same exact approval in concise text.
73
- 11. Render both cards once in that single complete assistant message. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
73
+ 11. Render both cards once in that single complete assistant message. Never merge, reverse, omit or duplicate them; the action heading does not replace either card. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
74
74
  12. Re-run gate evaluation for the same run and expected gate after the response and immediately before persistence.
75
75
  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.
76
76
  14. Persist accepted input only through the existing control-state workflow.
77
77
 
78
+ The ready-gate projection must expose `native_attempt_required: true`. Treat this as a mandatory
79
+ orchestration instruction: after rendering the two cards, invoke the configured native question
80
+ adapter exactly once before using the exact-text fallback. A hook, permission result or session
81
+ context message cannot replace that attempt or supply its answer. For every non-ready interaction,
82
+ the signal is absent or false and no approval control may be shown.
83
+
78
84
  Before composing the question, resolve the configured chat locale from `.agdf/control/config.json` through `../../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.
79
85
 
80
86
  For the transition card, use the complete resolved 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`. Keep each card in one locale. Use a localized human-readable gate title rather than an internal status label, while leaving the exact gate identifier and approval value unchanged. Do not render a Markdown table, dashboard rows, raw control-state keys, diagnostic codes, evidence lists, a duplicated gate question or a false user gate in the approval-time card.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Codex-first operating system for governed AI-assisted delivery.",
5
5
  "author": {
6
6
  "name": "Arndt Gold",
@@ -25,6 +25,7 @@
25
25
  "skill": "Next skill",
26
26
  "step": "Next step",
27
27
  "quality": "Quality outlook",
28
+ "lifecycle": "Delivery status",
28
29
  "allowed": "Allowed now",
29
30
  "forbidden": "Forbidden now",
30
31
  "artefacts": "Artefacts"
@@ -64,6 +65,14 @@
64
65
  "CR": "Code review",
65
66
  "OR": "Delivery report"
66
67
  },
68
+ "gateActionTitles": {
69
+ "UR": "Approve user requirements",
70
+ "PRD": "Approve product requirements",
71
+ "SD": "Approve solution design",
72
+ "TP": "Approve task and test plan",
73
+ "QA": "Approve quality decision",
74
+ "UAT": "Accept delivery result"
75
+ },
67
76
  "interaction": {
68
77
  "ready": "Ready for your decision",
69
78
  "approveHeading": "Approve now",
@@ -91,6 +100,13 @@
91
100
  "none": "none",
92
101
  "blocked": "current gate prerequisites",
93
102
  "quality": "Keep the presentation contract, evidence and gate authority aligned.",
103
+ "lifecycle": {
104
+ "active": "in progress",
105
+ "completed_closeout_pending": "completed — delivery closeout pending",
106
+ "completed": "completed",
107
+ "blocked": "blocked",
108
+ "unknown": "status not available"
109
+ },
94
110
  "actions": {
95
111
  "UR": "Clarify and approve the user requirements.",
96
112
  "Brownfield Review": "Review existing owners and choose the smallest safe delivery path.",
@@ -132,6 +148,7 @@
132
148
  "skill": "Nächster Skill",
133
149
  "step": "Nächster Schritt",
134
150
  "quality": "Qualitätsausblick",
151
+ "lifecycle": "Lieferstatus",
135
152
  "allowed": "Jetzt erlaubt",
136
153
  "forbidden": "Aktuell verboten",
137
154
  "artefacts": "Artefakte"
@@ -171,6 +188,14 @@
171
188
  "CR": "Code-Review",
172
189
  "OR": "Lieferbericht"
173
190
  },
191
+ "gateActionTitles": {
192
+ "UR": "Nutzeranforderung freigeben",
193
+ "PRD": "Produktanforderungen freigeben",
194
+ "SD": "Lösungsdesign freigeben",
195
+ "TP": "Umsetzungsplan freigeben",
196
+ "QA": "Qualitätsentscheidung freigeben",
197
+ "UAT": "Ergebnis abnehmen"
198
+ },
174
199
  "interaction": {
175
200
  "ready": "Bereit für deine Entscheidung",
176
201
  "approveHeading": "Jetzt freigeben",
@@ -198,6 +223,13 @@
198
223
  "none": "keine",
199
224
  "blocked": "Voraussetzungen des aktuellen Gates",
200
225
  "quality": "Präsentationsvertrag, Nachweise und Gate-Berechtigung konsistent halten.",
226
+ "lifecycle": {
227
+ "active": "in Arbeit",
228
+ "completed_closeout_pending": "abgeschlossen — Abschluss offen",
229
+ "completed": "abgeschlossen",
230
+ "blocked": "blockiert",
231
+ "unknown": "Status nicht verfügbar"
232
+ },
201
233
  "actions": {
202
234
  "UR": "Nutzeranforderungen klären und freigeben.",
203
235
  "Brownfield Review": "Bestehende Owner prüfen und den kleinsten sicheren Lieferweg wählen.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "agdf",
4
- "version": "0.8.3",
4
+ "version": "0.8.5",
5
5
  "displayName": "AI Governance & Delivery Framework",
6
6
  "developerName": "Arndt Gold",
7
7
  "description": "Codex-first operating system for governed AI-assisted delivery.",
@@ -97,6 +97,8 @@
97
97
  "decline"
98
98
  ],
99
99
  "dismissOutcome": "cancel",
100
+ "canonicalValueTransport": false,
101
+ "authorizationPath": "exact_text",
100
102
  "technicalPermissionOwner": "codex_host"
101
103
  },
102
104
  "claude": {
@@ -109,6 +111,8 @@
109
111
  "decline"
110
112
  ],
111
113
  "dismissOutcome": "cancel",
114
+ "canonicalValueTransport": false,
115
+ "authorizationPath": "exact_text",
112
116
  "technicalPermissionOwner": "claude_host"
113
117
  },
114
118
  "opencode": {
@@ -121,6 +125,8 @@
121
125
  "decline"
122
126
  ],
123
127
  "dismissOutcome": "cancel",
128
+ "canonicalValueTransport": false,
129
+ "authorizationPath": "exact_text",
124
130
  "technicalPermissionOwner": "opencode_host"
125
131
  },
126
132
  "fallback": {
@@ -133,6 +139,8 @@
133
139
  "decline",
134
140
  "cancel"
135
141
  ],
142
+ "canonicalValueTransport": true,
143
+ "authorizationPath": "exact_text",
136
144
  "technicalPermissionOwner": "host_specific"
137
145
  }
138
146
  }
@@ -181,6 +181,14 @@ before invoking any native question tool or emitting an exact-text approval
181
181
  request. Splitting the cards across separate assistant turns or invoking the
182
182
  tool after only one card is a failed interaction, not a valid presentation.
183
183
 
184
+ The first visible line of that envelope is the localized action-oriented title
185
+ of the current user gate, rendered as a level-two Markdown heading or equivalent
186
+ accessible host heading inside the compact approval-time Run Status Card.
187
+ `AGDF Status`, `Run Status Card`, `Gate Transition Card`, raw gate identifiers
188
+ and machine values are semantic or diagnostic labels only and must not become
189
+ the primary heading. The action title appears exactly once and does not replace,
190
+ merge or reorder either required card block.
191
+
184
192
  The compact approval-time Run Status Card contains exactly six operational
185
193
  fields: selected run, readiness status, current gate, missing exact approval,
186
194
  one next action and quality outlook. It uses localized human-readable labels
@@ -390,6 +398,7 @@ interaction_kind: clarification | tool_permission | gate_approval | blocked | st
390
398
  surface: codex | claude | opencode | fallback
391
399
  run_id: required for gate_approval
392
400
  current_gate: required for gate_approval
401
+ native_attempt_required: true only for an eligible gate_approval before the first adapter attempt
393
402
  prompt: required
394
403
  options: required for a structured question
395
404
  effects: required when the interaction can cause side effects
@@ -420,6 +429,12 @@ Before presenting `gate_approval`, the agent must:
420
429
  6. reject missing evidence, ambiguous or wrong run, wrong gate, stale state and any response that is no longer valid;
421
430
  7. persist an accepted approval only through the existing control-state workflow.
422
431
 
432
+ For an eligible `gate_approval`, `native_attempt_required` is a mandatory orchestration signal. The
433
+ agent must make exactly one configured native adapter attempt after the two orientation cards and
434
+ before any exact-text fallback. Hooks may prepare context but must not answer, approve or replace
435
+ the adapter attempt. The signal is absent or false for clarification, blocked, status-only,
436
+ internal-step and non-ready interactions.
437
+
423
438
  The first eligible native-attempt has a single bounded outcome: the declared
424
439
  host control is presented, or the agent immediately uses the exact-text
425
440
  fallback. A host that does not apply the control does not trigger a second
@@ -63,18 +63,24 @@ For a ready `gate_approval`:
63
63
  1. Resolve exactly one selected run and evaluate the current gate.
64
64
  2. Confirm the required durable artefact is present and ready before presenting a question.
65
65
  3. Build one immutable, non-authorizing presentation snapshot from the selected evaluated run and current revision identity.
66
- 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
66
+ 4. Compose one Approval Orientation Envelope as one immediately preceding assistant message containing two distinct blocks. Render the compact localized approval-time Run Status Card first. Its first visible line is the localized action-oriented gate title as a level-two Markdown heading or equivalent accessible host heading; generic AGDF/card labels and raw gate IDs cannot be the primary heading. It contains exactly selected run, readiness status, current gate, missing exact approval, one next action and quality outlook; omit raw keys, machine statuses, evidence, diagnostics and allowed/forbidden inventories.
67
67
  5. In the same assistant message, render a separate localized Gate Transition Card second, immediately before any native question or exact-text fallback. It includes the deterministic human run title and `UR · PRD · SD · TP` links from the selected run. Never put either card only into the question, button description or hidden tool context. Do not invoke the native question tool until the complete two-card envelope is visible.
68
68
  6. Compose the transition card as one human-readable gate title with `run_id`, one ready-for-decision line, one short approval-effect block and one short next-transition block. It must answer only: where am I, what does this decision do, and what happens next. Run and gate identity may anchor both cards; do not duplicate status rows, action inventories or the native question.
69
69
  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.
70
70
  8. Ask exactly one question that names the selected `run_id` and `current_gate`.
71
71
  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.
72
72
  10. Use the surface adapter declared in the canonical plugin definition only when it can wait for deliberate input without auto-resolution; otherwise request the same exact approval in concise text.
73
- 11. Render both cards once in that single complete assistant message. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
73
+ 11. Render both cards once in that single complete assistant message. Never merge, reverse, omit or duplicate them; the action heading does not replace either card. If the native attempt is unavailable or not applied, continue to exact text without repeating either card.
74
74
  12. Re-run gate evaluation for the same run and expected gate after the response and immediately before persistence.
75
75
  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.
76
76
  14. Persist accepted input only through the existing control-state workflow.
77
77
 
78
+ The ready-gate projection must expose `native_attempt_required: true`. Treat this as a mandatory
79
+ orchestration instruction: after rendering the two cards, invoke the configured native question
80
+ adapter exactly once before using the exact-text fallback. A hook, permission result or session
81
+ context message cannot replace that attempt or supply its answer. For every non-ready interaction,
82
+ the signal is absent or false and no approval control may be shown.
83
+
78
84
  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.
79
85
 
80
86
  For the transition card, use the complete resolved 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`. Keep each card in one locale. Use a localized human-readable gate title rather than an internal status label, while leaving the exact gate identifier and approval value unchanged. Do not render a Markdown table, dashboard rows, raw control-state keys, diagnostic codes, evidence lists, a duplicated gate question or a false user gate in the approval-time card.
@@ -70,6 +70,7 @@ export function validateLocaleRegistry(registry) {
70
70
  }
71
71
  for (const key of REQUIRED_GATES) {
72
72
  if (typeof pack.gateTitles?.[key] !== "string" || !pack.gateTitles[key].trim()) errors.push(`missing_gate_title:${locale}:${key}`);
73
+ if (typeof pack.gateActionTitles?.[key] !== "string" || !pack.gateActionTitles[key].trim()) errors.push(`missing_gate_action_title:${locale}:${key}`);
73
74
  }
74
75
  }
75
76
  if (JSON.stringify(registry?.optionOrder) !== JSON.stringify(["approve", "revise", "decline", "cancel"])) errors.push("option_order");
@@ -147,6 +148,59 @@ export function buildRunCandidates(runs) {
147
148
  .sort((left, right) => left.display_title.localeCompare(right.display_title) || left.run_id.localeCompare(right.run_id));
148
149
  }
149
150
 
151
+ export function normalizeReconciliationText(value) {
152
+ return String(value ?? "")
153
+ .normalize("NFKC")
154
+ .toLowerCase()
155
+ .replace(/[._:/\\-]+/g, " ")
156
+ .replace(/[^\p{L}\p{N}\s]+/gu, " ")
157
+ .replace(/\s+/g, " ")
158
+ .trim();
159
+ }
160
+
161
+ export function reconcileRunScope({ requestText = "", scopeKey = "", runs = [] } = {}) {
162
+ const requested = normalizeReconciliationText(scopeKey || requestText);
163
+ if (!requested) return Object.freeze({ outcome: "match_uncertain", matches: [], reason: "scope_input_missing" });
164
+ const matches = [...(runs ?? [])]
165
+ .filter((run) => run?.valid && ["active", "completed"].includes(run?.meta?.lifecycle) && typeof run.run_id === "string")
166
+ .filter((run) => {
167
+ const keys = [run.scope_key, run.display_title, run.current_artefact_heading, run.ur_heading]
168
+ .map(normalizeReconciliationText)
169
+ .filter(Boolean);
170
+ return keys.includes(requested);
171
+ })
172
+ .map((run) => Object.freeze({
173
+ run_id: run.run_id,
174
+ lifecycle: run.meta.lifecycle,
175
+ display_title: displaySafeTitle(run.display_title || run.ur_heading || run.run_id, normalizedRunTitle(run.run_id)),
176
+ current_gate: run.control_state?.current_gate || run.meta?.current_gate || "unknown",
177
+ }))
178
+ .sort((left, right) => left.run_id.localeCompare(right.run_id));
179
+ if (matches.length !== 1) return Object.freeze({ outcome: matches.length ? "match_uncertain" : "no_match", matches, reason: matches.length > 1 ? "multiple_exact_matches" : "no_exact_match" });
180
+ return Object.freeze({ outcome: matches[0].lifecycle === "active" ? "active_match" : "completed_match", matches, reason: "exact_match" });
181
+ }
182
+
183
+ export function executeNativeApprovalAttempt({ ready = false, orientationSnapshot, invokeNative, fallback } = {}) {
184
+ if (!ready) return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "gate_not_ready", authorizes: false });
185
+ const preflight = validateApprovalOrientationSnapshot(orientationSnapshot);
186
+ if (!preflight.valid) return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "orientation_preflight_failed", authorizes: false });
187
+ if (typeof invokeNative !== "function") return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "adapter_unavailable", authorizes: false });
188
+ let adapterResult;
189
+ try {
190
+ adapterResult = invokeNative();
191
+ } catch (error) {
192
+ adapterResult = { outcome: "attempted_not_applied", reason: String(error?.message || "adapter_error") };
193
+ }
194
+ const outcome = ATTEMPT_OUTCOMES.has(adapterResult?.outcome)
195
+ ? adapterResult.outcome
196
+ : adapterResult?.presented === true || adapterResult?.applied === true
197
+ ? "presented"
198
+ : "attempted_not_applied";
199
+ const reason = String(adapterResult?.reason || "").trim();
200
+ if (outcome !== "presented" && typeof fallback === "function") fallback({ outcome, reason });
201
+ return Object.freeze({ attempted: true, outcome, reason, authorizes: false });
202
+ }
203
+
150
204
  export function buildInteractionAttempt({ interactionId, runId, currentGate, surface, attemptOutcome, expectedApproval, fallbackReason = "" }) {
151
205
  if (!ATTEMPT_OUTCOMES.has(attemptOutcome)) throw new Error("invalid interaction attempt outcome");
152
206
  if (!String(interactionId ?? "").trim() || !String(runId ?? "").trim() || !String(currentGate ?? "").trim())
@@ -229,6 +283,7 @@ export function buildApprovalOrientationSnapshot({
229
283
  const pack = localePack(registry, locale);
230
284
  const runTitle = String(humanPresentation.runTitle ?? "").trim() || normalizedRunTitle(runId);
231
285
  const currentGateTitle = String(humanPresentation.gateTitle ?? "").trim() || gateTitle(registry, locale, gate);
286
+ const primaryHeading = String(pack.gateActionTitles?.[gate] ?? "").trim();
232
287
  const artefactRefs = Object.freeze([...(humanPresentation.artefactRefs ?? [])].map((ref) => Object.freeze({ ...ref })));
233
288
  const statusFields = Object.freeze([
234
289
  Object.freeze({ id: "selected_run", label: pack.statusCard.run, value: `${runTitle} · ${runId}` }),
@@ -247,8 +302,15 @@ export function buildApprovalOrientationSnapshot({
247
302
  current_gate: gate,
248
303
  presentation_language: locale,
249
304
  sequence: APPROVAL_SEQUENCE,
250
- compact_status_card: Object.freeze({ title: pack.statusCard.title, fields: statusFields }),
305
+ compact_status_card: Object.freeze({
306
+ semantic_block: "run_status_card",
307
+ title: primaryHeading,
308
+ primary_heading: primaryHeading,
309
+ primary_heading_level: 2,
310
+ fields: statusFields,
311
+ }),
251
312
  gate_transition_card: Object.freeze({
313
+ semantic_block: "gate_transition_card",
252
314
  title: `${currentGateTitle} · ${runTitle} · ${runId}`,
253
315
  artefact_refs: artefactRefs,
254
316
  ready: pack.interaction.ready,
@@ -258,11 +320,32 @@ export function buildApprovalOrientationSnapshot({
258
320
  next_heading: pack.interaction.nextHeading,
259
321
  next_gate: String(statusCard.next_gate_after_approval ?? "none"),
260
322
  }),
261
- approval_interaction: Object.freeze({ expected_approval: expectedApproval, options, authorizes: false }),
323
+ approval_interaction: Object.freeze({ semantic_block: "approval_interaction", expected_approval: expectedApproval, options, authorizes: false }),
262
324
  authorizes: false,
263
325
  });
264
326
  }
265
327
 
328
+ export function validateApprovalOrientationSnapshot(snapshot) {
329
+ const errors = [];
330
+ if (!plainObject(snapshot)) return Object.freeze({ valid: false, errors: Object.freeze(["snapshot_missing"]) });
331
+ if (JSON.stringify(snapshot.sequence) !== JSON.stringify(APPROVAL_SEQUENCE)) errors.push("sequence");
332
+ if (snapshot.compact_status_card?.semantic_block !== "run_status_card") errors.push("run_status_card");
333
+ if (snapshot.gate_transition_card?.semantic_block !== "gate_transition_card") errors.push("gate_transition_card");
334
+ if (snapshot.approval_interaction?.semantic_block !== "approval_interaction") errors.push("approval_interaction");
335
+ const heading = String(snapshot.compact_status_card?.primary_heading ?? "").trim();
336
+ if (!heading || snapshot.compact_status_card?.primary_heading_level !== 2) errors.push("primary_heading");
337
+ if (String(snapshot.compact_status_card?.title ?? "").trim() !== heading) errors.push("primary_heading_owner");
338
+ if (/^(?:(?:agdf[- ]?status(?: card|karte)?|run status card|gate transition card)(?:\b|\s*[-:—·])|(?:UR|PRD|SD|TP|QA|UAT)(?:\s*[-:—·]|$))/i.test(heading)) errors.push("generic_primary_heading");
339
+ const fieldIds = snapshot.compact_status_card?.fields?.map((field) => field?.id);
340
+ if (JSON.stringify(fieldIds) !== JSON.stringify(["selected_run", "readiness_status", "current_gate", "missing_approval", "next_action", "quality_outlook"])) errors.push("status_fields");
341
+ const expectedApproval = `Approval: ${String(snapshot.current_gate ?? "").trim()}`;
342
+ if (!REQUIRED_GATES.includes(snapshot.current_gate)
343
+ || snapshot.gate_transition_card?.exact_approval !== expectedApproval
344
+ || snapshot.approval_interaction?.expected_approval !== expectedApproval
345
+ || snapshot.approval_interaction?.options?.[0]?.value !== expectedApproval) errors.push("canonical_approval");
346
+ return Object.freeze({ valid: errors.length === 0, errors: Object.freeze(errors) });
347
+ }
348
+
266
349
  export function attachApprovalOrientationSnapshot(statusCard, options = {}) {
267
350
  if (!plainObject(statusCard)) throw new Error("approval orientation status card missing");
268
351
  const snapshot = buildApprovalOrientationSnapshot({ ...options, statusCard });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
5
5
  "type": "module",
6
6
  "files": [