create-agdf 0.14.2 → 0.14.4
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.
- package/README.md +39 -3
- package/generated/.opencode/contracts/control-scaffold.md +17 -2
- package/generated/.opencode/contracts/interaction.md +2 -2
- package/generated/.opencode/skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/.opencode/skills/agdf-gate-check/SKILL.md +6 -4
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/plugins/agdf/meta/contracts/interaction.md +2 -2
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/plugins/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -0
- package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/agdf/skills/gate-check/SKILL.md +6 -4
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +7 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +71 -51
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-gate-check/SKILL.md +6 -4
- package/generated/plugins/copilot/agdf/copilot-skills/contracts/control-scaffold.md +17 -2
- package/generated/plugins/copilot/agdf/copilot-skills/contracts/interaction.md +2 -2
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/plugins/copilot/agdf/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/submissions/openai/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/submissions/openai/agdf/meta/contracts/interaction.md +2 -2
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/submissions/openai/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/submissions/openai/agdf/skills/gate-check/SKILL.md +6 -4
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +18 -14
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +7 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/cli/application.js +24 -6
- package/lib/cli/command-registry.js +8 -1
- package/lib/cli/delivery-path-search-command.js +51 -19
- package/lib/cli/parse-args.js +3 -0
- package/lib/control-evaluation/doctor.js +13 -0
- package/lib/control-evaluation/gate-check.js +64 -13
- package/lib/control-evaluation/run-state.js +6 -0
- package/lib/control-state/run-identity.js +9 -0
- package/lib/control-state/run-state-parser.js +4 -2
- package/lib/delivery-path-search/contracts.js +37 -0
- package/lib/delivery-path-search/persistence.js +14 -2
- package/lib/delivery-path-search/search-engine.js +126 -36
- package/lib/delivery-path-search/state-adapter.js +40 -92
- package/lib/installers/claude-cache-recovery.js +76 -0
- package/lib/installers/copilot-settings.js +146 -16
- package/lib/installers/local-marketplace.js +169 -14
- package/lib/installers/plugin-installers.js +96 -9
- package/lib/interaction-presentation.js +57 -7
- package/lib/lifecycle/operations.js +28 -4
- package/lib/lifecycle/result.js +4 -4
- package/lib/release/profile-history.js +222 -0
- package/lib/release/version-bump.js +527 -0
- package/lib/release/version-coherence.js +92 -38
- package/lib/runtime/distribution-profile-history.js +173 -0
- package/lib/runtime/plugin-provenance.js +46 -3
- package/package.json +7 -3
package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONTRACT_VERSION, SCORING_POLICY_VERSION, validateEvaluation, validateSearchInput } from "./contracts.js";
|
|
1
|
+
import { CONTRACT_VERSION, SCORING_POLICY_VERSION, validateEvaluation, validateSearchInput, validateSearchResult } from "./contracts.js";
|
|
2
2
|
import { candidateLegality, candidatesFromInput, generatedCandidatesFromResponse } from "./candidate-policy.js";
|
|
3
3
|
import { scoreEvaluation } from "./scoring.js";
|
|
4
4
|
import { generatorRequestFromInput } from "./state-adapter.js";
|
|
@@ -14,6 +14,30 @@ function generatorFailureCode(error) {
|
|
|
14
14
|
return "generator_schema_invalid";
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function evaluatorFailureCode(error) {
|
|
18
|
+
if (error?.code === "ENOENT") return "evaluator_unavailable";
|
|
19
|
+
if (/auth/i.test(error?.message ?? "")) return "evaluator_authentication_failed";
|
|
20
|
+
if (/unavailable|not found|not configured/i.test(error?.message ?? "")) return "evaluator_unavailable";
|
|
21
|
+
return "evaluator_output_invalid";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function classifyTerminalOutcome({
|
|
25
|
+
inputUnavailable = false,
|
|
26
|
+
legalCandidates = 0,
|
|
27
|
+
evaluationAttempts = 0,
|
|
28
|
+
validEvaluations = 0,
|
|
29
|
+
invalidEvaluations = 0,
|
|
30
|
+
evaluatorUnavailable = false,
|
|
31
|
+
leader = null,
|
|
32
|
+
}) {
|
|
33
|
+
if (inputUnavailable) return { status: "input_unavailable", outcome_phase: "input" };
|
|
34
|
+
if (legalCandidates === 0) return { status: "no_legal_candidates", outcome_phase: "candidate" };
|
|
35
|
+
if (validEvaluations === 0 && evaluatorUnavailable) return { status: "evaluator_unavailable", outcome_phase: "evaluation" };
|
|
36
|
+
if (validEvaluations === 0 && legalCandidates > 0) return { status: "evaluator_error", outcome_phase: "evaluation" };
|
|
37
|
+
if (leader) return { status: "recommendation", outcome_phase: "search" };
|
|
38
|
+
return { status: "no_safe_recommendation", outcome_phase: "search" };
|
|
39
|
+
}
|
|
40
|
+
|
|
17
41
|
export async function runDeliveryPathSearch(inputValue, evaluator, options = {}) {
|
|
18
42
|
const input = validateSearchInput(inputValue);
|
|
19
43
|
const startedAt = Date.now();
|
|
@@ -22,12 +46,18 @@ export async function runDeliveryPathSearch(inputValue, evaluator, options = {})
|
|
|
22
46
|
const rejected = [];
|
|
23
47
|
const evaluated = [];
|
|
24
48
|
let evaluations = 0;
|
|
49
|
+
let evaluationAttempts = 0;
|
|
50
|
+
let invalidEvaluations = 0;
|
|
51
|
+
let legalCandidates = 0;
|
|
52
|
+
let rejectedCandidates = 0;
|
|
53
|
+
let evaluatorUnavailable = false;
|
|
54
|
+
let evaluationFailureCode = null;
|
|
25
55
|
let costUnits = 0;
|
|
26
56
|
let lastLeaderId = null;
|
|
27
57
|
let stableComparisons = 0;
|
|
28
58
|
let stoppingReason = "candidate_queue_exhausted";
|
|
29
59
|
const generation = {
|
|
30
|
-
status: input.generation?.enabled ? "
|
|
60
|
+
status: input.generation?.enabled ? "not_run" : "disabled",
|
|
31
61
|
adapter: options.generator?.metadata ?? null,
|
|
32
62
|
budgets: input.generation ?? null,
|
|
33
63
|
returned: 0,
|
|
@@ -38,7 +68,66 @@ export async function runDeliveryPathSearch(inputValue, evaluator, options = {})
|
|
|
38
68
|
failure_code: null,
|
|
39
69
|
};
|
|
40
70
|
|
|
71
|
+
const finish = ({ leader = null, outcome, failureCode = null, recoveryAction = null }) => {
|
|
72
|
+
evaluated.sort((a, b) => b.score - a.score || a.candidate.id.localeCompare(b.candidate.id));
|
|
73
|
+
const result = {
|
|
74
|
+
contract_version: CONTRACT_VERSION,
|
|
75
|
+
scoring_policy_version: SCORING_POLICY_VERSION,
|
|
76
|
+
scope_key: input.scope_key,
|
|
77
|
+
scope_revision: input.scope_revision ?? "unversioned",
|
|
78
|
+
objective: input.objective,
|
|
79
|
+
current_gate: input.current_gate,
|
|
80
|
+
outcome_phase: outcome.outcome_phase,
|
|
81
|
+
status: outcome.status,
|
|
82
|
+
recommendation: outcome.status === "recommendation" && leader ? {
|
|
83
|
+
candidate_id: leader.candidate.id,
|
|
84
|
+
action: leader.candidate.action,
|
|
85
|
+
score: leader.score,
|
|
86
|
+
rationale: leader.evaluation.rationale,
|
|
87
|
+
expected_evidence: leader.candidate.expected_evidence,
|
|
88
|
+
tests: leader.candidate.tests,
|
|
89
|
+
risks: leader.evaluation.risks,
|
|
90
|
+
assumptions: leader.evaluation.assumptions,
|
|
91
|
+
} : null,
|
|
92
|
+
alternatives: outcome.outcome_phase === "search" ? evaluated.slice(1).map((item) => ({
|
|
93
|
+
candidate_id: item.candidate.id,
|
|
94
|
+
action: item.candidate.action,
|
|
95
|
+
score: item.score,
|
|
96
|
+
rejection_reason: `ranked_below_${leader?.candidate.id ?? "search_policy"}`,
|
|
97
|
+
})) : [],
|
|
98
|
+
rejected,
|
|
99
|
+
provenance: {
|
|
100
|
+
baseline_candidates: baseline.length,
|
|
101
|
+
generated_candidates: generation.accepted,
|
|
102
|
+
legal_candidates: legalCandidates,
|
|
103
|
+
rejected_candidates: rejectedCandidates + generation.rejected.length,
|
|
104
|
+
evaluation_attempts: evaluationAttempts,
|
|
105
|
+
valid_evaluations: evaluations,
|
|
106
|
+
invalid_evaluations: invalidEvaluations,
|
|
107
|
+
},
|
|
108
|
+
enforcement: input.enforcement,
|
|
109
|
+
evaluator: evaluator?.metadata ?? { name: evaluator?.name ?? "unknown" },
|
|
110
|
+
generation,
|
|
111
|
+
budgets: { configured: input.budgets, evaluations, cost_units: costUnits, stable_comparisons: stableComparisons, duration_ms: Date.now() - startedAt },
|
|
112
|
+
stopping_reason: stoppingReason,
|
|
113
|
+
failure_code: failureCode,
|
|
114
|
+
next_action: recoveryAction ?? "Run canonical AGDF gate-check; search does not grant permission.",
|
|
115
|
+
next_gate_action: recoveryAction ?? "Run canonical AGDF gate-check; search does not grant permission.",
|
|
116
|
+
};
|
|
117
|
+
return validateSearchResult(result);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (input.input_failure_code || input.allowed_actions.length === 0) {
|
|
121
|
+
stoppingReason = input.input_failure_code || "canonical_actions_unavailable";
|
|
122
|
+
return finish({
|
|
123
|
+
outcome: classifyTerminalOutcome({ inputUnavailable: true }),
|
|
124
|
+
failureCode: input.input_failure_code || "canonical_actions_unavailable",
|
|
125
|
+
recoveryAction: input.input_recovery_action || "Run canonical AGDF gate-check and repair the selected control state.",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
41
129
|
if (input.generation?.enabled) {
|
|
130
|
+
generation.status = "failed";
|
|
42
131
|
if (!options.generator) {
|
|
43
132
|
generation.failure_code = "generator_unavailable";
|
|
44
133
|
} else {
|
|
@@ -75,17 +164,20 @@ export async function runDeliveryPathSearch(inputValue, evaluator, options = {})
|
|
|
75
164
|
}
|
|
76
165
|
|
|
77
166
|
while (queue.length > 0) {
|
|
78
|
-
if (evaluations >= input.budgets.max_evaluations) { stoppingReason = "evaluation_budget_exhausted"; break; }
|
|
79
|
-
if (costUnits >= input.budgets.max_cost_units) { stoppingReason = "cost_budget_exhausted"; break; }
|
|
80
|
-
if (Date.now() - startedAt >= input.budgets.max_duration_ms) { stoppingReason = "duration_budget_exhausted"; break; }
|
|
81
167
|
const candidate = queue.shift();
|
|
82
168
|
const legality = candidateLegality(candidate, input);
|
|
83
169
|
if (!legality.legal) {
|
|
170
|
+
rejectedCandidates += 1;
|
|
84
171
|
rejected.push({ candidate_id: candidate.id, action: candidate.action, reason: legality.reason });
|
|
85
172
|
continue;
|
|
86
173
|
}
|
|
174
|
+
legalCandidates += 1;
|
|
175
|
+
if (evaluations >= input.budgets.max_evaluations) { stoppingReason = "evaluation_budget_exhausted"; evaluationFailureCode = stoppingReason; break; }
|
|
176
|
+
if (costUnits >= input.budgets.max_cost_units) { stoppingReason = "cost_budget_exhausted"; evaluationFailureCode = stoppingReason; break; }
|
|
177
|
+
if (Date.now() - startedAt >= input.budgets.max_duration_ms) { stoppingReason = "duration_budget_exhausted"; evaluationFailureCode = stoppingReason; break; }
|
|
87
178
|
|
|
88
179
|
try {
|
|
180
|
+
evaluationAttempts += 1;
|
|
89
181
|
const evaluation = validateEvaluation(await evaluator.evaluate(input, candidate), candidate.id);
|
|
90
182
|
evaluations += 1;
|
|
91
183
|
costUnits += evaluation.cost;
|
|
@@ -115,41 +207,39 @@ export async function runDeliveryPathSearch(inputValue, evaluator, options = {})
|
|
|
115
207
|
}
|
|
116
208
|
} catch (error) {
|
|
117
209
|
if (error?.fatalEvaluator === true) throw error;
|
|
210
|
+
invalidEvaluations += 1;
|
|
211
|
+
evaluationFailureCode = evaluatorFailureCode(error);
|
|
212
|
+
evaluatorUnavailable ||= evaluationFailureCode === "evaluator_unavailable" || evaluationFailureCode === "evaluator_authentication_failed";
|
|
118
213
|
rejected.push({ candidate_id: candidate.id, action: candidate.action, reason: `invalid_evaluation: ${error.message}` });
|
|
214
|
+
if (evaluatorUnavailable) break;
|
|
119
215
|
}
|
|
120
216
|
}
|
|
121
217
|
|
|
122
218
|
evaluated.sort((a, b) => b.score - a.score || a.candidate.id.localeCompare(b.candidate.id));
|
|
123
219
|
const leader = evaluated[0];
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
evaluator: evaluator.metadata ?? { name: evaluator.name ?? "unknown" },
|
|
150
|
-
generation,
|
|
151
|
-
budgets: { configured: input.budgets, evaluations, cost_units: costUnits, stable_comparisons: stableComparisons, duration_ms: Date.now() - startedAt },
|
|
152
|
-
stopping_reason: stoppingReason,
|
|
153
|
-
next_gate_action: "Run canonical AGDF gate-check; search does not grant permission.",
|
|
154
|
-
};
|
|
220
|
+
const outcome = classifyTerminalOutcome({
|
|
221
|
+
legalCandidates,
|
|
222
|
+
evaluationAttempts,
|
|
223
|
+
validEvaluations: evaluations,
|
|
224
|
+
invalidEvaluations,
|
|
225
|
+
evaluatorUnavailable,
|
|
226
|
+
leader,
|
|
227
|
+
});
|
|
228
|
+
if (!leader) {
|
|
229
|
+
stoppingReason = outcome.status === "no_legal_candidates"
|
|
230
|
+
? "no_legal_candidates"
|
|
231
|
+
: outcome.status === "evaluator_unavailable"
|
|
232
|
+
? "evaluator_unavailable"
|
|
233
|
+
: outcome.status === "evaluator_error"
|
|
234
|
+
? "evaluator_error"
|
|
235
|
+
: stoppingReason;
|
|
236
|
+
}
|
|
237
|
+
return finish({
|
|
238
|
+
leader,
|
|
239
|
+
outcome,
|
|
240
|
+
failureCode: outcome.outcome_phase === "evaluation" ? evaluationFailureCode : null,
|
|
241
|
+
recoveryAction: outcome.outcome_phase === "evaluation"
|
|
242
|
+
? "Repair the declared evaluator capability and retry from a fresh canonical control snapshot."
|
|
243
|
+
: null,
|
|
244
|
+
});
|
|
155
245
|
}
|
package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
1
|
import {
|
|
4
2
|
CONTRACT_VERSION,
|
|
5
3
|
GENERATOR_CONTRACT_VERSION,
|
|
6
4
|
validateGeneratorRequest,
|
|
7
5
|
} from "./contracts.js";
|
|
8
|
-
import {
|
|
6
|
+
import { evaluateGateCheck } from "../control-evaluation/gate-check.js";
|
|
7
|
+
import { readRunState } from "../control-evaluation/run-state.js";
|
|
9
8
|
|
|
10
9
|
function section(content, heading) {
|
|
11
10
|
return (
|
|
@@ -15,100 +14,44 @@ function section(content, heading) {
|
|
|
15
14
|
);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.split("|")
|
|
23
|
-
.slice(1, -1)
|
|
24
|
-
.map((cell) => cell.trim());
|
|
25
|
-
if (
|
|
26
|
-
cells.length >= 2 &&
|
|
27
|
-
cells[0] &&
|
|
28
|
-
!cells[0].startsWith("---") &&
|
|
29
|
-
cells[0] !== "Question"
|
|
30
|
-
)
|
|
31
|
-
answers[cells[0]] = cells[1];
|
|
32
|
-
}
|
|
33
|
-
return answers;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function statusCard(content) {
|
|
37
|
-
const card = {};
|
|
38
|
-
for (const line of section(content, "Run Status Card").split(/\r?\n/)) {
|
|
39
|
-
const cells = line
|
|
40
|
-
.split("|")
|
|
41
|
-
.slice(1, -1)
|
|
42
|
-
.map((cell) => cell.trim().replace(/^`|`$/g, ""));
|
|
43
|
-
if (
|
|
44
|
-
cells.length >= 2 &&
|
|
45
|
-
cells[0] &&
|
|
46
|
-
!cells[0].startsWith("---") &&
|
|
47
|
-
cells[0] !== "Run status"
|
|
48
|
-
)
|
|
49
|
-
card[cells[0]] = cells[1];
|
|
50
|
-
}
|
|
51
|
-
return card;
|
|
17
|
+
function metaField(content, name) {
|
|
18
|
+
return content.match(new RegExp(`^- ${name}:\\s*(.+)$`, "m"))?.[1]
|
|
19
|
+
?.replace(/^`|`$/g, "")
|
|
20
|
+
.trim() ?? "";
|
|
52
21
|
}
|
|
53
22
|
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
23
|
+
export function searchInputFromControl(targetDir, options = {}, dependencies = {}) {
|
|
24
|
+
const evaluate = dependencies.evaluateGateCheck ?? evaluateGateCheck;
|
|
25
|
+
const readRun = dependencies.readRunState ?? readRunState;
|
|
26
|
+
const selection = options.scopeKey ? { runId: options.scopeKey } : {};
|
|
27
|
+
const gate = evaluate(targetDir, selection);
|
|
28
|
+
const run = readRun(targetDir, selection);
|
|
29
|
+
const content = run.content ?? "";
|
|
30
|
+
const evaluatedRunId = gate.status_card?.run_id ?? "";
|
|
31
|
+
const evaluatedRevision = gate.status_presentation?.revision_id ?? "";
|
|
32
|
+
const runId = metaField(content, "run_id");
|
|
33
|
+
const runRevision = metaField(content, "revision_id");
|
|
34
|
+
const runGate = metaField(content, "current_gate");
|
|
35
|
+
let inputFailureCode = "";
|
|
36
|
+
if (!content || run.resolution_error) inputFailureCode = "canonical_control_unavailable";
|
|
37
|
+
else if (!evaluatedRunId || !evaluatedRevision) inputFailureCode = "canonical_snapshot_identity_missing";
|
|
38
|
+
else if (evaluatedRunId !== runId || evaluatedRevision !== runRevision || gate.current_gate !== runGate) {
|
|
39
|
+
inputFailureCode = "stale_control_snapshot";
|
|
40
|
+
} else if (!Array.isArray(gate.allowed) || gate.allowed.length === 0) {
|
|
41
|
+
inputFailureCode = "canonical_actions_unavailable";
|
|
68
42
|
}
|
|
69
|
-
const resolved = existsSync(canonicalRoot)
|
|
70
|
-
? resolveRuns(targetDir, {
|
|
71
|
-
runIdArg: options.scopeKey,
|
|
72
|
-
runIdEnv: process.env.AGDF_RUN_ID,
|
|
73
|
-
})
|
|
74
|
-
: null;
|
|
75
|
-
const runPath =
|
|
76
|
-
resolved?.run.path ?? join(targetDir, ".agdf", "control", "AGDF_RUN.md");
|
|
77
|
-
if (!existsSync(runPath)) throw new Error("missing AGDF run state");
|
|
78
|
-
const content = readFileSync(runPath, "utf8");
|
|
79
|
-
const meta = Object.fromEntries(
|
|
80
|
-
[...content.matchAll(/^- ([a-z_]+):\s*(.+)$/gm)].map((match) => [
|
|
81
|
-
match[1],
|
|
82
|
-
match[2].replace(/^`|`$/g, "").trim(),
|
|
83
|
-
]),
|
|
84
|
-
);
|
|
85
|
-
const answers = tableAnswers(content);
|
|
86
|
-
const card = statusCard(content);
|
|
87
43
|
const result = {
|
|
88
44
|
contract_version: CONTRACT_VERSION,
|
|
89
|
-
scope_key: options.scopeKey
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
),
|
|
100
|
-
]
|
|
101
|
-
.slice(1)
|
|
102
|
-
.map((match) => `${match[1].trim()}: ${match[2].trim()}`),
|
|
103
|
-
risks: section(content, "Risks")
|
|
104
|
-
.split(/\r?\n/)
|
|
105
|
-
.filter(
|
|
106
|
-
(line) =>
|
|
107
|
-
line.startsWith("|") &&
|
|
108
|
-
!line.includes("---") &&
|
|
109
|
-
!line.includes("| Risk |"),
|
|
110
|
-
)
|
|
111
|
-
.map((line) => line.split("|")[1].trim()),
|
|
45
|
+
scope_key: evaluatedRunId || runId || options.scopeKey || "unknown-scope",
|
|
46
|
+
scope_revision: evaluatedRevision || runRevision || "unversioned",
|
|
47
|
+
objective: section(content, "Objective").trim() || "Canonical Delivery Path Search input unavailable",
|
|
48
|
+
current_gate: gate.current_gate || runGate || "unknown",
|
|
49
|
+
allowed_actions: inputFailureCode ? [] : [...gate.allowed],
|
|
50
|
+
forbidden_actions: Array.isArray(gate.forbidden) ? [...gate.forbidden] : [],
|
|
51
|
+
evidence_refs: Array.isArray(gate.evidence_refs)
|
|
52
|
+
? gate.evidence_refs.map((item) => `${item.evidence}: ${item.source}`)
|
|
53
|
+
: [],
|
|
54
|
+
risks: Array.isArray(run.risks) ? run.risks.map((item) => item.risk).filter(Boolean) : [],
|
|
112
55
|
enforcement: options.enforcement ?? {
|
|
113
56
|
level: "instruction_only",
|
|
114
57
|
evidence: ["surface instruction prohibits implementation during search"],
|
|
@@ -122,6 +65,11 @@ export function searchInputFromControl(targetDir, options = {}) {
|
|
|
122
65
|
stability_window: options.stabilityWindow ?? 3,
|
|
123
66
|
},
|
|
124
67
|
};
|
|
68
|
+
if (inputFailureCode) {
|
|
69
|
+
result.input_failure_code = inputFailureCode;
|
|
70
|
+
result.input_failure_detail = run.resolution_error || (gate.blocking_reason !== "none" ? gate.blocking_reason : "") || "canonical input is not ready";
|
|
71
|
+
result.input_recovery_action = gate.next_allowed_action || "Run canonical AGDF gate-check and repair the selected control state.";
|
|
72
|
+
}
|
|
125
73
|
if (options.generation?.enabled)
|
|
126
74
|
result.generation = {
|
|
127
75
|
enabled: true,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RUN_ID_PATTERN } from "./control-state/run-identity.js";
|
|
2
|
+
|
|
1
3
|
const REQUIRED_GATES = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
|
|
2
4
|
const ARTEFACT_ORDER = ["UR", "PRD", "SD", "TP"];
|
|
3
5
|
const OUTCOMES = new Set(["approve", "revise", "decline", "cancel", "no_response", "timeout", "empty", "invalid", "stale"]);
|
|
@@ -313,17 +315,37 @@ function operationalBreadcrumb(value, labels) {
|
|
|
313
315
|
.join(labels.breadcrumbSeparator);
|
|
314
316
|
}
|
|
315
317
|
|
|
318
|
+
export function validateOperationalStatusCardPreconditions(statusCard, {
|
|
319
|
+
registry,
|
|
320
|
+
humanPresentation,
|
|
321
|
+
} = {}) {
|
|
322
|
+
const errors = [];
|
|
323
|
+
if (!plainObject(statusCard)) errors.push("status_card_missing");
|
|
324
|
+
if (humanPresentation !== undefined && !plainObject(humanPresentation)) errors.push("human_presentation_missing");
|
|
325
|
+
if (plainObject(statusCard)) {
|
|
326
|
+
if (!String(statusCard.run_id ?? "").trim()) errors.push("run_id_missing");
|
|
327
|
+
if (!String(statusCard.current_gate ?? "").trim()) errors.push("current_gate_missing");
|
|
328
|
+
let locale = "";
|
|
329
|
+
try {
|
|
330
|
+
locale = resolvePresentationLocale(registry, statusCard.presentation_language);
|
|
331
|
+
} catch {
|
|
332
|
+
locale = "";
|
|
333
|
+
}
|
|
334
|
+
if (!locale) errors.push("locale_unresolved");
|
|
335
|
+
}
|
|
336
|
+
return Object.freeze({ valid: errors.length === 0, errors: Object.freeze(errors) });
|
|
337
|
+
}
|
|
338
|
+
|
|
316
339
|
export function renderOperationalStatusCard(statusCard, {
|
|
317
340
|
registry,
|
|
318
341
|
humanPresentation,
|
|
319
342
|
revisionId = "",
|
|
320
343
|
} = {}) {
|
|
321
|
-
if (!
|
|
344
|
+
if (!validateOperationalStatusCardPreconditions(statusCard, { registry, humanPresentation: humanPresentation ?? null }).valid) return null;
|
|
322
345
|
const runId = String(statusCard.run_id ?? "").trim();
|
|
323
346
|
const currentGate = String(statusCard.current_gate ?? "").trim();
|
|
324
347
|
const revision = String(revisionId ?? "").trim() || "unversioned";
|
|
325
348
|
const locale = resolvePresentationLocale(registry, statusCard.presentation_language);
|
|
326
|
-
if (!runId || !currentGate || !locale) return null;
|
|
327
349
|
|
|
328
350
|
const pack = localePack(registry, locale);
|
|
329
351
|
const labels = pack.statusCard;
|
|
@@ -537,6 +559,37 @@ export function normalizeInteractionOutcome(value, { expectedApproval, stale = f
|
|
|
537
559
|
return "invalid";
|
|
538
560
|
}
|
|
539
561
|
|
|
562
|
+
export function validateApprovalOrientationPreconditions({
|
|
563
|
+
statusCard,
|
|
564
|
+
humanPresentation,
|
|
565
|
+
registry,
|
|
566
|
+
requestedLocale,
|
|
567
|
+
} = {}) {
|
|
568
|
+
const errors = [];
|
|
569
|
+
if (!plainObject(statusCard)) return Object.freeze({ valid: false, errors: Object.freeze(["status_card_missing"]) });
|
|
570
|
+
if (humanPresentation !== undefined && !plainObject(humanPresentation)) errors.push("human_presentation_missing");
|
|
571
|
+
const gate = String(statusCard.current_gate ?? "").trim();
|
|
572
|
+
const runId = String(statusCard.run_id ?? "").trim();
|
|
573
|
+
if (!REQUIRED_GATES.includes(gate)) errors.push("gate_not_user_gate");
|
|
574
|
+
if (!RUN_ID_PATTERN.test(runId)) errors.push("run_id_invalid");
|
|
575
|
+
if (statusCard.status !== "open") errors.push("status_not_open");
|
|
576
|
+
if (statusCard.missing_approval !== `Approval: ${gate}`) errors.push("missing_approval_mismatch");
|
|
577
|
+
const nextGate = String(statusCard.next_gate_after_approval ?? "none");
|
|
578
|
+
const nextUserGate = String(statusCard.next_user_gate ?? "").trim();
|
|
579
|
+
const userActionRequired = String(statusCard.user_action_required ?? "").trim();
|
|
580
|
+
const userActionSemanticsValid = (userActionRequired === "no" && nextUserGate === "none")
|
|
581
|
+
|| (userActionRequired === "yes" && REQUIRED_GATES.includes(nextUserGate) && nextGate === nextUserGate);
|
|
582
|
+
if (!userActionSemanticsValid) errors.push("user_action_semantics_invalid");
|
|
583
|
+
let locale = "";
|
|
584
|
+
try {
|
|
585
|
+
locale = resolvePresentationLocale(registry, requestedLocale);
|
|
586
|
+
} catch {
|
|
587
|
+
locale = "";
|
|
588
|
+
}
|
|
589
|
+
if (!locale) errors.push("locale_unresolved");
|
|
590
|
+
return Object.freeze({ valid: errors.length === 0, errors: Object.freeze(errors) });
|
|
591
|
+
}
|
|
592
|
+
|
|
540
593
|
export function buildApprovalOrientationSnapshot({
|
|
541
594
|
ready = false,
|
|
542
595
|
statusCard,
|
|
@@ -545,11 +598,11 @@ export function buildApprovalOrientationSnapshot({
|
|
|
545
598
|
registry,
|
|
546
599
|
requestedLocale,
|
|
547
600
|
} = {}) {
|
|
548
|
-
if (!ready
|
|
601
|
+
if (!ready) return null;
|
|
602
|
+
if (!validateApprovalOrientationPreconditions({ statusCard, humanPresentation: humanPresentation ?? null, registry, requestedLocale }).valid) return null;
|
|
549
603
|
const gate = String(statusCard.current_gate ?? "").trim();
|
|
550
604
|
const runId = String(statusCard.run_id ?? "").trim();
|
|
551
605
|
const expectedApproval = `Approval: ${gate}`;
|
|
552
|
-
if (!REQUIRED_GATES.includes(gate) || !/^[A-Za-z0-9._-]+$/.test(runId) || statusCard.status !== "open" || statusCard.missing_approval !== expectedApproval) return null;
|
|
553
606
|
|
|
554
607
|
const locale = resolvePresentationLocale(registry, requestedLocale);
|
|
555
608
|
const pack = localePack(registry, locale);
|
|
@@ -560,9 +613,6 @@ export function buildApprovalOrientationSnapshot({
|
|
|
560
613
|
const nextGate = String(statusCard.next_gate_after_approval ?? "none");
|
|
561
614
|
const nextUserGate = String(statusCard.next_user_gate ?? "").trim();
|
|
562
615
|
const userActionRequired = String(statusCard.user_action_required ?? "").trim();
|
|
563
|
-
const userActionSemanticsValid = (userActionRequired === "no" && nextUserGate === "none")
|
|
564
|
-
|| (userActionRequired === "yes" && REQUIRED_GATES.includes(nextUserGate) && nextGate === nextUserGate);
|
|
565
|
-
if (!userActionSemanticsValid) return null;
|
|
566
616
|
const narration = pack.primary.narration.gates[gate] ?? {};
|
|
567
617
|
const nextDecision = userActionRequired === "no"
|
|
568
618
|
? pack.primary.narration.noAction
|
|
@@ -137,6 +137,22 @@ export function validateDistributionProfiles(definition) {
|
|
|
137
137
|
return { status: "matched", contract };
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
function classifyInstalledHistoricalProfile(catalogue, definition, classifyHistoricalProfile) {
|
|
141
|
+
if (typeof classifyHistoricalProfile !== "function") {
|
|
142
|
+
return { status: "invalid", reason: "profile_history_invalid" };
|
|
143
|
+
}
|
|
144
|
+
const result = classifyHistoricalProfile({
|
|
145
|
+
catalogue,
|
|
146
|
+
version: definition?.version,
|
|
147
|
+
distributionProfiles: definition?.distributionProfiles,
|
|
148
|
+
});
|
|
149
|
+
if (result.status !== "matched") return result;
|
|
150
|
+
return {
|
|
151
|
+
...result,
|
|
152
|
+
contract: catalogue.contracts[result.contract_id].distribution_profiles,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
140
156
|
export function inspectGeneratedRepositoryMarketplace(targetDir) {
|
|
141
157
|
const marketplacePath = join(targetDir, ".agents", "plugins", "marketplace.json");
|
|
142
158
|
if (!existsSync(marketplacePath)) return { status: "absent", marketplacePath };
|
|
@@ -196,11 +212,23 @@ export function inspectInstallationProvenance(pluginRoot, {
|
|
|
196
212
|
allowLegacy = false,
|
|
197
213
|
profileId = "runtime-plugin",
|
|
198
214
|
inventoryDigest = null,
|
|
215
|
+
allowHistoricalProfilesForMigration = false,
|
|
216
|
+
distributionProfileHistory = null,
|
|
217
|
+
classifyHistoricalProfile = null,
|
|
199
218
|
} = {}) {
|
|
200
219
|
const markerPath = join(pluginRoot, INSTALLATION_PROVENANCE_FILE);
|
|
201
220
|
const legacyPath = join(pluginRoot, LEGACY_LOCAL_INSTALL_FILE);
|
|
202
221
|
if (!existsSync(markerPath)) {
|
|
203
222
|
if (allowLegacy && existsSync(legacyPath)) {
|
|
223
|
+
const currentProfile = validateDistributionProfiles(definition);
|
|
224
|
+
if (Object.hasOwn(definition ?? {}, "distributionProfiles")
|
|
225
|
+
&& currentProfile.status !== "matched") {
|
|
226
|
+
return allowHistoricalProfilesForMigration
|
|
227
|
+
? classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile).status === "matched"
|
|
228
|
+
? { status: "invalid", reason: "installation_provenance_invalid" }
|
|
229
|
+
: classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile)
|
|
230
|
+
: currentProfile;
|
|
231
|
+
}
|
|
204
232
|
const marker = readJson(legacyPath);
|
|
205
233
|
if (!marker
|
|
206
234
|
|| marker.schema_version !== 1
|
|
@@ -223,8 +251,14 @@ export function inspectInstallationProvenance(pluginRoot, {
|
|
|
223
251
|
if (profile.status !== "matched") return profile;
|
|
224
252
|
return { status: "missing", reason: "installation_provenance_missing" };
|
|
225
253
|
}
|
|
226
|
-
const
|
|
227
|
-
|
|
254
|
+
const currentProfile = validateDistributionProfiles(definition);
|
|
255
|
+
const historicalProfile = currentProfile.status !== "matched" && allowHistoricalProfilesForMigration
|
|
256
|
+
? classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile)
|
|
257
|
+
: null;
|
|
258
|
+
if (currentProfile.status !== "matched" && historicalProfile?.status !== "matched") {
|
|
259
|
+
return historicalProfile ?? currentProfile;
|
|
260
|
+
}
|
|
261
|
+
const profile = currentProfile.status === "matched" ? currentProfile : historicalProfile;
|
|
228
262
|
const marker = readJson(markerPath);
|
|
229
263
|
if (!marker
|
|
230
264
|
|| marker.schema_version !== 1
|
|
@@ -247,7 +281,16 @@ export function inspectInstallationProvenance(pluginRoot, {
|
|
|
247
281
|
if (observedSourceDigest !== marker.source_digest) {
|
|
248
282
|
return { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
|
|
249
283
|
}
|
|
250
|
-
return {
|
|
284
|
+
return {
|
|
285
|
+
status: "matched",
|
|
286
|
+
marker,
|
|
287
|
+
observedSourceDigest,
|
|
288
|
+
profileClassification: historicalProfile ? "supported_historical" : "current",
|
|
289
|
+
historicalReleaseVersion: historicalProfile?.release_version ?? null,
|
|
290
|
+
historicalContractId: historicalProfile?.contract_id ?? null,
|
|
291
|
+
historicalContractDigest: historicalProfile?.contract_digest ?? null,
|
|
292
|
+
historicalEntryDigest: historicalProfile?.entry_digest ?? null,
|
|
293
|
+
};
|
|
251
294
|
}
|
|
252
295
|
|
|
253
296
|
export const distributionProfileContract = Object.freeze({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema_version": "1",
|
|
3
3
|
"generated": true,
|
|
4
4
|
"source": "create-agdf/cli",
|
|
5
|
-
"version": "0.14.
|
|
5
|
+
"version": "0.14.4",
|
|
6
6
|
"entrypoint": "create-agdf/bin/agdf-validator.js",
|
|
7
|
-
"digest": "
|
|
7
|
+
"digest": "68b83a6721a799c34067cdbcc0ed6664f7fbf89bce186a3d8de284b0959deac7"
|
|
8
8
|
}
|
|
@@ -4,11 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
Delivery Path Search is an optional read-only planning step for high-impact decisions with several materially different next actions.
|
|
6
6
|
|
|
7
|
-
- It consumes
|
|
8
|
-
|
|
7
|
+
- It consumes the canonical selected-run `gate-check` evaluation for run, revision, current gate and
|
|
8
|
+
legal actions. Persisted presentation Markdown such as the Run Status Card is never policy input.
|
|
9
|
+
- It binds the selected `scope_key`, `scope_revision` and objective to one control snapshot. A stale
|
|
10
|
+
or incomplete snapshot fails before candidate generation or evaluation.
|
|
11
|
+
- It reports the phase that actually ran: `input | candidate | evaluation | search`. A phase that
|
|
12
|
+
did not run cannot produce a later-phase conclusion.
|
|
13
|
+
- Terminal status is `input_unavailable | no_legal_candidates | evaluator_unavailable |
|
|
14
|
+
evaluator_error | recommendation | no_safe_recommendation`. Recommendation-facing statuses
|
|
15
|
+
require at least one contract-valid evaluation. `candidate_queue_exhausted` is a stopping reason,
|
|
16
|
+
not recommendation evidence.
|
|
17
|
+
- It reports baseline/generated/legal/rejected candidate counts and attempted/valid/invalid
|
|
18
|
+
evaluation counts. Zero valid evaluations must never be presented or persisted as an evaluated
|
|
19
|
+
recommendation conclusion.
|
|
9
20
|
- It must report budgets, stopping reason and `full | tool_enforced | instruction_only` enforcement.
|
|
10
21
|
- Model scores are judgements, not measurements.
|
|
11
22
|
- Search output is evidence only. Canonical `gate-check` independently decides what may proceed.
|
|
23
|
+
- Search applies only to the selected run objective. An unrelated decision needs the correct
|
|
24
|
+
governed scope; Delivery Path Search is not a second task-target resolver.
|
|
12
25
|
- The bounded first-release algorithm must not be labelled MCTS.
|
|
13
26
|
- Surface adapters may translate transport and presentation, but must not fork scoring, search or gate semantics.
|
|
14
27
|
- Optional AI-native candidate generation supplements the deterministic candidate baseline; it never replaces it.
|
|
@@ -19,6 +32,8 @@ Delivery Path Search is an optional read-only planning step for high-impact deci
|
|
|
19
32
|
- Codex and Claude Code may provide tool-enforced generator transports. Copilot, OpenCode and generic surfaces remain instruction-only without conforming evidence.
|
|
20
33
|
- OpenCode may provide a tool-enforced evaluator only for an invocation whose capability preflight proves `opencode run --pure --agent`, the owned evaluator agent and effective executable-tool denies. Preflight or transport failure must return `evaluator_unavailable` with `instruction_only` enforcement and point to the existing instruction-only workflow; it must not continue through a weaker subprocess.
|
|
21
34
|
- OpenCode candidate generation remains unavailable.
|
|
35
|
+
- Persistence accepts only contract-valid `recommendation` or `no_safe_recommendation` results with
|
|
36
|
+
at least one valid evaluation. Input, candidate and evaluator failure results remain transient.
|
|
22
37
|
|
|
23
38
|
The field names above are the stable machine-readable contract used by JSON
|
|
24
39
|
reports and automation. Human-facing Markdown must present the same projection
|
|
@@ -154,8 +154,8 @@ required decision and one neutral instruction to choose approve, request revisio
|
|
|
154
154
|
or decline. It does not contain the exact approval value or quality outlook. It uses localized human-readable labels
|
|
155
155
|
and must not contain evidence, diagnostic codes, raw control-state keys,
|
|
156
156
|
allowed/forbidden inventories or machine values. The complete Run Status Card remains the operational,
|
|
157
|
-
CLI and audit projection
|
|
158
|
-
approval-
|
|
157
|
+
CLI and audit projection. Every ready-gate presentation renders the complete operational Run Status Card exactly once, between the compact approval-time Run Status Card and the Gate Transition Card, consumed verbatim from the code-owned status presentation; when it is undeliverable, the localized status-presentation failure line with its concrete diagnostic codes takes its place and the decision is still requested.
|
|
158
|
+
The exact-approval once-only requirement applies to the compact approval-time Run Status Card and the Gate Transition Card only; the complete Run Status Card may carry the missing approval as audit data.
|
|
159
159
|
|
|
160
160
|
The first scan across both cards reveals the requested decision, readiness,
|
|
161
161
|
required approval, approval effect, remaining boundary and next transition.
|