create-agdf 0.11.3 → 0.12.0
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 +5 -4
- package/generated/.agdf/control/templates/MASTER_BACKLOG.md +1 -1
- package/generated/.agdf/control/templates/artefacts/BROWNFIELD_REVIEW.md +25 -0
- package/generated/.github/skills/agdf-brownfield-analysis/SKILL.md +26 -0
- package/generated/.github/skills/agdf-gate-check/SKILL.md +40 -18
- package/generated/.github/skills/agdf-interaction-locales.json +50 -0
- package/generated/.github/skills/agdf-runtime-contract.md +1 -0
- package/generated/.github/skills/contracts/control-scaffold.md +2 -0
- package/generated/.github/skills/contracts/gate-transition.md +7 -3
- package/generated/.github/skills/contracts/interaction.md +22 -0
- package/generated/.github/skills/contracts/modes.md +81 -0
- package/generated/.github/skills/contracts/task-target-resolution.md +102 -0
- package/generated/.opencode/AGDF.md +2 -0
- package/generated/.opencode/agdf-interaction-locales.json +50 -0
- package/generated/.opencode/agdf-runtime-contract.md +1 -0
- package/generated/.opencode/contracts/control-scaffold.md +2 -0
- package/generated/.opencode/contracts/gate-transition.md +7 -3
- package/generated/.opencode/contracts/interaction.md +22 -0
- package/generated/.opencode/contracts/modes.md +81 -0
- package/generated/.opencode/contracts/task-target-resolution.md +102 -0
- package/generated/.opencode/skills/agdf-brownfield-analysis/SKILL.md +26 -0
- package/generated/.opencode/skills/agdf-gate-check/SKILL.md +40 -18
- package/generated/AGENTS.md +1 -0
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/control/templates/MASTER_BACKLOG.md +1 -1
- package/generated/plugins/agdf/control/templates/artefacts/BROWNFIELD_REVIEW.md +25 -0
- package/generated/plugins/agdf/meta/agdf-agent-router.md +16 -0
- package/generated/plugins/agdf/meta/agdf-interaction-locales.json +50 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -1
- package/generated/plugins/agdf/meta/agdf-runtime-contract.md +1 -0
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +2 -0
- package/generated/plugins/agdf/meta/contracts/gate-transition.md +7 -3
- package/generated/plugins/agdf/meta/contracts/interaction.md +22 -0
- package/generated/plugins/agdf/meta/contracts/modes.md +81 -0
- package/generated/plugins/agdf/meta/contracts/task-target-resolution.md +102 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +50 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +78 -14
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +14 -7
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +1 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +2 -11
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +2 -11
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +1 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +15 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +85 -0
- package/generated/plugins/agdf/runtime/create-agdf/package.json +6 -2
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +119 -3
- package/generated/plugins/agdf/skills/brownfield-analysis/SKILL.md +26 -0
- package/generated/plugins/agdf/skills/gate-check/SKILL.md +40 -18
- package/lib/cli/application.js +29 -3
- package/lib/cli/command-registry.js +2 -2
- package/lib/cli/delivery-path-search-command.js +78 -14
- package/lib/control-evaluation/gate-policy.js +14 -7
- package/lib/control-evaluation/shared.js +1 -0
- package/lib/delivery-path-search/evaluators/claude.js +2 -11
- package/lib/delivery-path-search/evaluators/codex.js +2 -11
- package/lib/delivery-path-search/evaluators/opencode.js +234 -0
- package/lib/delivery-path-search/evaluators/prompt.js +13 -0
- package/lib/delivery-path-search/search-engine.js +1 -0
- package/lib/delivery-path-search/surfaces/capabilities.js +15 -2
- package/lib/installers/opencode.js +341 -10
- package/lib/interaction-presentation.js +85 -0
- package/lib/lifecycle/operations.js +4 -0
- package/lib/live-agent/read-only-structured.js +43 -0
- package/lib/proportionality-benchmark/blind-prompt.js +37 -0
- package/lib/proportionality-benchmark/contracts.js +120 -0
- package/lib/proportionality-benchmark/corpus-loader.js +110 -0
- package/lib/proportionality-benchmark/evaluator.js +250 -0
- package/lib/proportionality-benchmark/index.js +7 -0
- package/lib/proportionality-benchmark/live-recorder.js +100 -0
- package/lib/proportionality-benchmark/report.js +51 -0
- package/lib/proportionality-benchmark/source-fingerprint.js +30 -0
- package/lib/skill-evals/live-recorder.js +3 -26
- package/opencode-plugin.js +59 -3
- package/package.json +6 -2
package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { validateEvaluation } from "../contracts.js";
|
|
4
|
+
import { guardedExecFileSync } from "../transports/read-only-guard.js";
|
|
5
|
+
import { buildEvaluatorPrompt } from "./prompt.js";
|
|
6
|
+
|
|
7
|
+
export const OPENCODE_EVALUATOR_AGENT = "agdf-evaluator";
|
|
8
|
+
|
|
9
|
+
export const OPENCODE_DENY_PERMISSIONS = Object.freeze({
|
|
10
|
+
"*": "deny",
|
|
11
|
+
read: "deny",
|
|
12
|
+
edit: "deny",
|
|
13
|
+
bash: "deny",
|
|
14
|
+
task: "deny",
|
|
15
|
+
webfetch: "deny",
|
|
16
|
+
websearch: "deny",
|
|
17
|
+
skill: "deny",
|
|
18
|
+
lsp: "deny",
|
|
19
|
+
todowrite: "deny",
|
|
20
|
+
question: "deny",
|
|
21
|
+
external_directory: "deny",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const executablePermissions = Object.freeze([
|
|
25
|
+
"edit", "bash", "task", "webfetch", "websearch", "skill", "lsp", "todowrite", "question",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export function openCodePermissionEnvironment(env = process.env) {
|
|
29
|
+
return {
|
|
30
|
+
...env,
|
|
31
|
+
OPENCODE_PERMISSION: JSON.stringify(OPENCODE_DENY_PERMISSIONS),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function preflightFailure(code, detail, evidence = []) {
|
|
36
|
+
return {
|
|
37
|
+
surface: "opencode",
|
|
38
|
+
status: "failed",
|
|
39
|
+
code,
|
|
40
|
+
detail,
|
|
41
|
+
evidence,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function extractAgentPermissions(output, agentName) {
|
|
46
|
+
const marker = `${agentName} (`;
|
|
47
|
+
const lines = output.split(/\r?\n/);
|
|
48
|
+
const start = lines.findIndex((line) => line.startsWith(marker));
|
|
49
|
+
if (start < 0) return null;
|
|
50
|
+
const mode = lines[start].slice(marker.length).split(")")[0];
|
|
51
|
+
let jsonStart = -1;
|
|
52
|
+
let depth = 0;
|
|
53
|
+
for (let index = start + 1; index < lines.length; index += 1) {
|
|
54
|
+
const line = lines[index].trim();
|
|
55
|
+
if (jsonStart < 0 && line === "[") {
|
|
56
|
+
jsonStart = index;
|
|
57
|
+
depth = 1;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (jsonStart >= 0) {
|
|
61
|
+
for (const character of line) {
|
|
62
|
+
if (character === "[") depth += 1;
|
|
63
|
+
if (character === "]") depth -= 1;
|
|
64
|
+
}
|
|
65
|
+
if (depth === 0) return { mode, permissions: JSON.parse(lines.slice(jsonStart, index + 1).join("\n")) };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function terminalPermissionDecision(permissions, permissionName) {
|
|
72
|
+
let decision = null;
|
|
73
|
+
for (const entry of permissions) {
|
|
74
|
+
if (entry?.pattern === "*" && (entry.permission === "*" || entry.permission === permissionName)) {
|
|
75
|
+
decision = entry.action;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return decision;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function preflightOpenCodeEvaluator(options = {}) {
|
|
82
|
+
const executable = options.openCodeBin ?? process.env.AGDF_OPENCODE_BIN ?? "opencode";
|
|
83
|
+
const run = options.execFileSync ?? execFileSync;
|
|
84
|
+
const cwd = options.cwd ?? process.cwd();
|
|
85
|
+
const agentName = options.agentName ?? OPENCODE_EVALUATOR_AGENT;
|
|
86
|
+
const env = openCodePermissionEnvironment(options.env ?? process.env);
|
|
87
|
+
let runtime;
|
|
88
|
+
let help;
|
|
89
|
+
let agents;
|
|
90
|
+
try {
|
|
91
|
+
runtime = run(executable, ["--version"], {
|
|
92
|
+
cwd, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 5000,
|
|
93
|
+
}).trim();
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return preflightFailure("opencode_host_unavailable", (error.stderr || error.message).toString().trim());
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
if (options.execFileSync) {
|
|
99
|
+
help = run(executable, ["run", "--help"], {
|
|
100
|
+
cwd, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 5000,
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
const helpProbe = (options.spawnSync ?? spawnSync)(executable, ["run", "--help"], {
|
|
104
|
+
cwd, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 5000,
|
|
105
|
+
});
|
|
106
|
+
if (helpProbe.error || helpProbe.status !== 0) throw helpProbe.error ?? new Error(helpProbe.stderr || "OpenCode run help failed.");
|
|
107
|
+
help = `${helpProbe.stdout ?? ""}\n${helpProbe.stderr ?? ""}`;
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return preflightFailure("opencode_run_unavailable", (error.stderr || error.message).toString().trim(), [`opencode ${runtime}`]);
|
|
111
|
+
}
|
|
112
|
+
const requiredFlags = ["--pure", "--agent", "--format", "--dir"];
|
|
113
|
+
const missingFlags = requiredFlags.filter((flag) => !help.includes(flag));
|
|
114
|
+
if (missingFlags.length) {
|
|
115
|
+
return preflightFailure("opencode_run_capability_missing", `Missing required flags: ${missingFlags.join(", ")}`, [`opencode ${runtime}`]);
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
agents = run(executable, ["agent", "list", "--pure"], {
|
|
119
|
+
cwd, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 10000,
|
|
120
|
+
});
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return preflightFailure("opencode_agent_probe_failed", (error.stderr || error.message).toString().trim(), [`opencode ${runtime}`]);
|
|
123
|
+
}
|
|
124
|
+
let projection;
|
|
125
|
+
try {
|
|
126
|
+
projection = extractAgentPermissions(agents, agentName);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return preflightFailure("opencode_agent_permissions_unparseable", error.message, [`opencode ${runtime}`]);
|
|
129
|
+
}
|
|
130
|
+
if (!projection) {
|
|
131
|
+
return preflightFailure("opencode_evaluator_agent_missing", `OpenCode agent ${agentName} is not available.`, [`opencode ${runtime}`]);
|
|
132
|
+
}
|
|
133
|
+
if (projection.mode !== "primary") {
|
|
134
|
+
return preflightFailure("opencode_evaluator_agent_incompatible", `OpenCode agent ${agentName} must be primary for opencode run --agent; observed ${projection.mode || "unknown"}.`, [
|
|
135
|
+
`opencode ${runtime}`,
|
|
136
|
+
`agent:${agentName}`,
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
const unsafe = executablePermissions.filter((permission) => terminalPermissionDecision(projection.permissions, permission) !== "deny");
|
|
140
|
+
if (unsafe.length) {
|
|
141
|
+
return preflightFailure("opencode_evaluator_permissions_unsafe", `Terminal deny is not effective for: ${unsafe.join(", ")}`, [
|
|
142
|
+
`opencode ${runtime}`,
|
|
143
|
+
`agent:${agentName}`,
|
|
144
|
+
]);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
surface: "opencode",
|
|
148
|
+
status: "passed",
|
|
149
|
+
code: "opencode_evaluator_ready",
|
|
150
|
+
invocation_id: `${process.pid}-${Date.now()}`,
|
|
151
|
+
runtime,
|
|
152
|
+
agent: agentName,
|
|
153
|
+
evidence: [
|
|
154
|
+
`opencode ${runtime}`,
|
|
155
|
+
"opencode run --pure --agent agdf-evaluator --format json",
|
|
156
|
+
"effective executable permissions terminal-deny",
|
|
157
|
+
],
|
|
158
|
+
env,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function parseOpenCodeEvaluatorOutput(raw) {
|
|
163
|
+
const text = [];
|
|
164
|
+
for (const line of raw.split(/\r?\n/).filter(Boolean)) {
|
|
165
|
+
const event = JSON.parse(line);
|
|
166
|
+
if (event?.type === "error") {
|
|
167
|
+
const status = event.error?.data?.statusCode;
|
|
168
|
+
const detail = event.error?.data?.message || event.error?.message || "unknown OpenCode evaluator error";
|
|
169
|
+
const error = new Error(`OpenCode evaluator error${status ? ` (${status})` : ""}: ${detail}`);
|
|
170
|
+
error.code = status === 401 || /auth|credential|provider available/i.test(detail)
|
|
171
|
+
? "OPENCODE_EVALUATOR_AUTHENTICATION_FAILED"
|
|
172
|
+
: "OPENCODE_EVALUATOR_UNAVAILABLE";
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
if (event?.part?.type === "text" && typeof event.part.text === "string") text.push(event.part.text);
|
|
176
|
+
else if (event?.type === "text" && typeof event.text === "string") text.push(event.text);
|
|
177
|
+
}
|
|
178
|
+
if (!text.length) throw new Error("OpenCode evaluator returned no text event.");
|
|
179
|
+
if (text.length !== 1) throw new Error(`OpenCode evaluator returned ${text.length} text events; exactly one final payload is required.`);
|
|
180
|
+
return JSON.parse(text[0]);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function fatalEvaluatorError(error) {
|
|
184
|
+
const wrapped = new Error(error.message);
|
|
185
|
+
wrapped.code = typeof error.code === "string" && error.code.startsWith("OPENCODE_EVALUATOR_")
|
|
186
|
+
? error.code
|
|
187
|
+
: error.code === "GENERATOR_MUTATION_DETECTED"
|
|
188
|
+
? "OPENCODE_EVALUATOR_MUTATION_DETECTED"
|
|
189
|
+
: error.code === "GENERATOR_TIMEOUT"
|
|
190
|
+
? "OPENCODE_EVALUATOR_TIMEOUT"
|
|
191
|
+
: error.code === "ENOENT"
|
|
192
|
+
? "OPENCODE_EVALUATOR_UNAVAILABLE"
|
|
193
|
+
: /auth|unauthorized|credential/i.test(`${error.message}\n${error.stderr ?? ""}`)
|
|
194
|
+
? "OPENCODE_EVALUATOR_AUTHENTICATION_FAILED"
|
|
195
|
+
: "OPENCODE_EVALUATOR_OUTPUT_INVALID";
|
|
196
|
+
wrapped.fatalEvaluator = true;
|
|
197
|
+
return wrapped;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function openCodeEvaluator(options = {}) {
|
|
201
|
+
if (options.preflight?.status !== "passed" || options.preflight.surface !== "opencode") {
|
|
202
|
+
throw new Error("OpenCode evaluator requires a successful current-invocation preflight.");
|
|
203
|
+
}
|
|
204
|
+
const executable = options.openCodeBin ?? process.env.AGDF_OPENCODE_BIN ?? "opencode";
|
|
205
|
+
const agentName = options.preflight.agent ?? OPENCODE_EVALUATOR_AGENT;
|
|
206
|
+
return {
|
|
207
|
+
name: "opencode",
|
|
208
|
+
metadata: {
|
|
209
|
+
name: "opencode",
|
|
210
|
+
runtime: options.preflight.runtime,
|
|
211
|
+
agent: agentName,
|
|
212
|
+
preflight: options.preflight.code,
|
|
213
|
+
},
|
|
214
|
+
async evaluate(input, candidate) {
|
|
215
|
+
const args = [
|
|
216
|
+
"run", "--pure", "--agent", agentName, "--format", "json", "--dir", options.cwd,
|
|
217
|
+
];
|
|
218
|
+
if (options.model) args.push("--model", options.model);
|
|
219
|
+
args.push(buildEvaluatorPrompt(input, candidate));
|
|
220
|
+
try {
|
|
221
|
+
const raw = guardedExecFileSync(executable, args, {
|
|
222
|
+
cwd: options.cwd,
|
|
223
|
+
env: options.preflight.env,
|
|
224
|
+
encoding: "utf8",
|
|
225
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
226
|
+
timeout: options.timeoutMs ?? 120000,
|
|
227
|
+
});
|
|
228
|
+
return validateEvaluation(parseOpenCodeEvaluatorOutput(raw), candidate.id);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
throw fatalEvaluatorError(error);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function buildEvaluatorPrompt(input, candidate) {
|
|
2
|
+
return [
|
|
3
|
+
"You are an evaluation-only component. Do not use tools, execute commands, inspect files, delegate work or modify state.",
|
|
4
|
+
`Return only one JSON object matching contract version ${input.contract_version}.`,
|
|
5
|
+
`Objective: ${input.objective}`,
|
|
6
|
+
`Current gate: ${input.current_gate}`,
|
|
7
|
+
`Candidate id: ${candidate.id}`,
|
|
8
|
+
`Candidate action: ${candidate.action}`,
|
|
9
|
+
"Score scope_fit, gate_readiness, risk_reduction, evidence_gain, testability, reversibility and cost from 0 to 5.",
|
|
10
|
+
"Cost 0 is low and 5 is high. uncertainty is 0 low to 5 high.",
|
|
11
|
+
"Keep rationale concise. child_actions must only contain actions permitted by the current gate.",
|
|
12
|
+
].join("\n");
|
|
13
|
+
}
|
package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js
CHANGED
|
@@ -114,6 +114,7 @@ export async function runDeliveryPathSearch(inputValue, evaluator, options = {})
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
} catch (error) {
|
|
117
|
+
if (error?.fatalEvaluator === true) throw error;
|
|
117
118
|
rejected.push({ candidate_id: candidate.id, action: candidate.action, reason: `invalid_evaluation: ${error.message}` });
|
|
118
119
|
}
|
|
119
120
|
}
|
package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { validateEnforcement } from "../contracts.js";
|
|
2
2
|
|
|
3
|
-
export function enforcementForSurface(surface, evidence = []) {
|
|
3
|
+
export function enforcementForSurface(surface, evidence = [], context = {}) {
|
|
4
4
|
const defaults = {
|
|
5
5
|
codex: { level: "tool_enforced", evidence: ["codex exec --sandbox read-only --ephemeral"] },
|
|
6
6
|
claude: { level: "tool_enforced", evidence: ["claude -p --disallowedTools Edit,Write,Bash"] },
|
|
@@ -9,6 +9,19 @@ export function enforcementForSurface(surface, evidence = []) {
|
|
|
9
9
|
generic: { level: "instruction_only", evidence: [] },
|
|
10
10
|
};
|
|
11
11
|
const selected = structuredClone(defaults[surface] ?? defaults.generic);
|
|
12
|
-
if (
|
|
12
|
+
if (surface === "opencode") {
|
|
13
|
+
const preflight = context.preflight;
|
|
14
|
+
if (preflight?.surface === "opencode"
|
|
15
|
+
&& preflight.status === "passed"
|
|
16
|
+
&& typeof preflight.invocation_id === "string"
|
|
17
|
+
&& preflight.invocation_id
|
|
18
|
+
&& Array.isArray(preflight.evidence)
|
|
19
|
+
&& preflight.evidence === evidence) {
|
|
20
|
+
selected.level = "tool_enforced";
|
|
21
|
+
selected.evidence = [...evidence];
|
|
22
|
+
}
|
|
23
|
+
} else if (evidence.length) {
|
|
24
|
+
selected.evidence = evidence;
|
|
25
|
+
}
|
|
13
26
|
return validateEnforcement(selected);
|
|
14
27
|
}
|
|
@@ -349,6 +349,91 @@ export function renderOperationalStatusCard(statusCard, {
|
|
|
349
349
|
});
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
+
export function renderTaskTargetOrientation(resolution, {
|
|
353
|
+
registry,
|
|
354
|
+
requestedLocale,
|
|
355
|
+
} = {}) {
|
|
356
|
+
if (!plainObject(resolution)) return null;
|
|
357
|
+
|
|
358
|
+
const resolutionState = String(resolution.resolution_state ?? "").trim();
|
|
359
|
+
const reasonCode = String(resolution.reason_code ?? "").trim();
|
|
360
|
+
const primaryTarget = String(resolution.primary_target ?? "").trim();
|
|
361
|
+
const governanceTarget = String(resolution.governance_target ?? "").trim();
|
|
362
|
+
const workingDirectory = String(resolution.working_directory ?? "").trim();
|
|
363
|
+
const nextAction = String(resolution.next_action ?? "").trim();
|
|
364
|
+
if (typeof resolution.target_changed !== "boolean") return null;
|
|
365
|
+
const targetChanged = resolution.target_changed === true;
|
|
366
|
+
const evidenceSources = Array.isArray(resolution.evidence_sources)
|
|
367
|
+
? resolution.evidence_sources.map((item) => String(item ?? "").trim()).filter(Boolean)
|
|
368
|
+
: null;
|
|
369
|
+
|
|
370
|
+
const resolvedReasons = new Set(["explicit_target", "continued_target"]);
|
|
371
|
+
const unresolvedReasons = new Set([
|
|
372
|
+
"multiple_plausible_targets",
|
|
373
|
+
"target_content_mismatch",
|
|
374
|
+
"target_unavailable",
|
|
375
|
+
"no_reliable_target",
|
|
376
|
+
]);
|
|
377
|
+
|
|
378
|
+
if (!["resolved", "unresolved"].includes(resolutionState)) return null;
|
|
379
|
+
if (!workingDirectory || evidenceSources === null) return null;
|
|
380
|
+
if (resolutionState === "resolved") {
|
|
381
|
+
if (!resolvedReasons.has(reasonCode) || !primaryTarget || nextAction) return null;
|
|
382
|
+
} else if (!unresolvedReasons.has(reasonCode) || primaryTarget || governanceTarget || !nextAction || targetChanged) {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
let locale;
|
|
387
|
+
try {
|
|
388
|
+
locale = resolvePresentationLocale(registry, requestedLocale);
|
|
389
|
+
} catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
if (!locale) return null;
|
|
393
|
+
|
|
394
|
+
const pack = localePack(registry, locale);
|
|
395
|
+
const labels = pack?.taskTargetResolution;
|
|
396
|
+
if (!plainObject(labels) || !plainObject(labels.reasonCodes)) return null;
|
|
397
|
+
const reason = labels.reasonCodes[reasonCode];
|
|
398
|
+
if (!reason) return null;
|
|
399
|
+
|
|
400
|
+
const rows = resolutionState === "resolved"
|
|
401
|
+
? [
|
|
402
|
+
[labels.state, labels.resolved],
|
|
403
|
+
[labels.primaryTarget, primaryTarget],
|
|
404
|
+
[labels.governanceTarget, governanceTarget || labels.none],
|
|
405
|
+
[labels.evidenceSources, evidenceSources.join("; ") || labels.none],
|
|
406
|
+
[labels.workingDirectory, workingDirectory],
|
|
407
|
+
[labels.reason, reason],
|
|
408
|
+
...(targetChanged ? [[labels.targetChanged, labels.yes]] : []),
|
|
409
|
+
]
|
|
410
|
+
: [
|
|
411
|
+
[labels.state, labels.unresolved],
|
|
412
|
+
[labels.reason, reason],
|
|
413
|
+
[labels.evidenceSources, evidenceSources.join("; ") || labels.none],
|
|
414
|
+
[labels.workingDirectory, workingDirectory],
|
|
415
|
+
[labels.nextAction, nextAction],
|
|
416
|
+
];
|
|
417
|
+
|
|
418
|
+
const markdown = [
|
|
419
|
+
`## ${labels.title}`,
|
|
420
|
+
"",
|
|
421
|
+
`| ${labels.field} | ${labels.value} |`,
|
|
422
|
+
"|---|---|",
|
|
423
|
+
...rows.map(([label, value]) => `| ${markdownCell(label)} | ${markdownCell(value)} |`),
|
|
424
|
+
].join("\n");
|
|
425
|
+
|
|
426
|
+
return Object.freeze({
|
|
427
|
+
schema_version: "1",
|
|
428
|
+
semantic_block: "task_target_orientation",
|
|
429
|
+
presentation_language: locale,
|
|
430
|
+
resolution_state: resolutionState,
|
|
431
|
+
reason_code: reasonCode,
|
|
432
|
+
markdown,
|
|
433
|
+
authorizes: false,
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
352
437
|
export function renderScopeClassificationCard(classification, {
|
|
353
438
|
registry,
|
|
354
439
|
requestedLocale,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
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": [
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test:delivery-path-search": "node ./scripts/delivery-path-search-test.js",
|
|
25
25
|
"test:delivery-path-search-unit": "node ./scripts/delivery-path-search-unit-test.js",
|
|
26
26
|
"test:delivery-path-search-generator": "node ./scripts/delivery-path-search-generator-test.js",
|
|
27
|
+
"test:opencode-hardening": "node ./scripts/opencode-hardening-test.js",
|
|
27
28
|
"test:cli-modularization": "node ./scripts/cli-modularization-test.js",
|
|
28
29
|
"test:local-validator": "node ./scripts/local-validator-test.js",
|
|
29
30
|
"test:local-marketplace": "node ./scripts/local-marketplace-test.js",
|
|
@@ -38,9 +39,12 @@
|
|
|
38
39
|
"test:skill-evals": "node ./scripts/skill-evals-test.js",
|
|
39
40
|
"eval:skills": "node ./scripts/run-skill-evals.js",
|
|
40
41
|
"eval:skills:record": "node ./scripts/record-skill-evals.js",
|
|
42
|
+
"eval:proportionality:record": "node ./scripts/record-proportionality-benchmark.js",
|
|
43
|
+
"eval:proportionality": "node ./scripts/run-proportionality-benchmark.js",
|
|
44
|
+
"test:proportionality": "node ./scripts/proportionality-benchmark-test.js",
|
|
41
45
|
"test:release-bootstrap": "node ./scripts/release-bootstrap-smoke-test.js",
|
|
42
46
|
"test:routing": "npm run sync-package-assets && node ./scripts/test-routing.js",
|
|
43
|
-
"smoke-test": "npm run sync-package-assets && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:skill-evals && npm run eval:skills && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
47
|
+
"smoke-test": "npm run sync-package-assets && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:skill-evals && npm run eval:skills && npm run test:proportionality && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
44
48
|
"prepack": "npm run sync-package-assets"
|
|
45
49
|
},
|
|
46
50
|
"keywords": [
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema_version": "1",
|
|
3
3
|
"generated": true,
|
|
4
4
|
"source": "create-agdf/cli",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.12.0",
|
|
6
6
|
"entrypoint": "create-agdf/bin/agdf-validator.js",
|
|
7
|
-
"digest": "
|
|
7
|
+
"digest": "a869279122dd6a2a7de6a5c719e41eedea5e89b7a2ee32012f7d74ce778ff24e"
|
|
8
8
|
}
|
|
@@ -92,6 +92,7 @@ const agentRouterPath = join(pluginRoot, "meta", "agdf-agent-router.md");
|
|
|
92
92
|
const runtimeContractPath = join(pluginRoot, "meta", "agdf-runtime-contract.md");
|
|
93
93
|
const contractsDir = join(pluginRoot, "meta", "contracts");
|
|
94
94
|
const contractModules = [
|
|
95
|
+
"task-target-resolution.md",
|
|
95
96
|
"gate-transition.md",
|
|
96
97
|
"interaction.md",
|
|
97
98
|
"modes.md",
|
|
@@ -331,12 +332,66 @@ if (!sourceMode && isFile(localRuntimeEntrypointPath)) {
|
|
|
331
332
|
}
|
|
332
333
|
}
|
|
333
334
|
const runtimeContract = readAllContracts();
|
|
335
|
+
const modesContract = isFile(join(contractsDir, "modes.md")) ? read(join(contractsDir, "modes.md")) : "";
|
|
336
|
+
const gateTransitionContract = isFile(join(contractsDir, "gate-transition.md")) ? read(join(contractsDir, "gate-transition.md")) : "";
|
|
337
|
+
const agentRouterContent = isFile(agentRouterPath) ? read(agentRouterPath) : "";
|
|
334
338
|
const interactionLocales = isFile(interactionLocalesPath) ? readJson(interactionLocalesPath, "interaction locale registry") : null;
|
|
335
339
|
const gateCheckSkill = isFile(gateCheckSkillPath) ? read(gateCheckSkillPath) : "";
|
|
336
340
|
const brownfieldSkill = isFile(brownfieldSkillPath) ? read(brownfieldSkillPath) : "";
|
|
337
341
|
if (!brownfieldSkill.includes("Persist the completed review and its decision, scope reason, evidence and required next gate in the same internal operation")) {
|
|
338
342
|
failures.push("brownfield-analysis must own atomic post-UR review and routing persistence");
|
|
339
343
|
}
|
|
344
|
+
for (const required of [
|
|
345
|
+
"### Structured Depth Decision",
|
|
346
|
+
"depth_unresolved",
|
|
347
|
+
"depth_facts_status",
|
|
348
|
+
"bounded_structured_slice",
|
|
349
|
+
"authority_policy_security_depth",
|
|
350
|
+
"architecture_runtime_depth",
|
|
351
|
+
"persistence_migration_depth",
|
|
352
|
+
"external_contract_depth",
|
|
353
|
+
"release_cross_host_depth",
|
|
354
|
+
"unbounded_consumer_coordination",
|
|
355
|
+
"depth_facts_missing",
|
|
356
|
+
"depth_facts_conflicting",
|
|
357
|
+
"coherent_outcome",
|
|
358
|
+
"authority_boundary",
|
|
359
|
+
"owner_consumer_coordination",
|
|
360
|
+
"full_depth_impacts_absent",
|
|
361
|
+
"migration_propagation_bounded",
|
|
362
|
+
"failure_recovery_local",
|
|
363
|
+
"independently_acceptable",
|
|
364
|
+
]) {
|
|
365
|
+
if (!modesContract.includes(required)) failures.push(`modes contract Structured Depth Decision missing: ${required}`);
|
|
366
|
+
}
|
|
367
|
+
if (!modesContract.includes("counts are not a decision proxy")
|
|
368
|
+
|| !modesContract.includes("threshold for either structured mode")) {
|
|
369
|
+
failures.push("modes contract must reject numeric structured-depth proxies");
|
|
370
|
+
}
|
|
371
|
+
if (!modesContract.includes("Structured Slice and Structured Delivery use the same existing gate and approval sequence")) {
|
|
372
|
+
failures.push("modes contract must preserve structured-depth gate parity");
|
|
373
|
+
}
|
|
374
|
+
if (!gateTransitionContract.includes("sole normative `Structured Depth Decision`")
|
|
375
|
+
|| !gateTransitionContract.includes("does not duplicate its")
|
|
376
|
+
|| !gateTransitionContract.includes("trigger or bounded-slice matrix")) {
|
|
377
|
+
failures.push("gate-transition contract must reference the Modes-owned Structured Depth Decision without duplicating it");
|
|
378
|
+
}
|
|
379
|
+
if (!gateTransitionContract.includes("`depth_unresolved` product result is persisted through this existing value")
|
|
380
|
+
|| !gateTransitionContract.includes("`depth_facts_missing | depth_facts_conflicting`")) {
|
|
381
|
+
failures.push("gate-transition contract must route unresolved structured depth through the existing block value");
|
|
382
|
+
}
|
|
383
|
+
for (const required of [
|
|
384
|
+
"../../meta/contracts/modes.md",
|
|
385
|
+
"depth_policy_version: 1",
|
|
386
|
+
"depth_facts_status: complete",
|
|
387
|
+
"rejected_alternative",
|
|
388
|
+
"missing_or_conflicting_facts",
|
|
389
|
+
"all seven bounded-slice",
|
|
390
|
+
"the existing `block` decision",
|
|
391
|
+
"Brownfield/Mode-Slice re-evaluation",
|
|
392
|
+
]) {
|
|
393
|
+
if (!brownfieldSkill.includes(required)) failures.push(`brownfield-analysis structured-depth guidance missing: ${required}`);
|
|
394
|
+
}
|
|
340
395
|
const codexPlugin = isFile(codexPluginPath) ? readJson(codexPluginPath, "Codex plugin manifest") : null;
|
|
341
396
|
const claudePlugin = isFile(claudePluginPath) ? readJson(claudePluginPath, "Claude plugin manifest") : null;
|
|
342
397
|
const agdfPackage = isFile(agdfPackagePath) ? readJson(agdfPackagePath, "agdf CLI package manifest") : null;
|
|
@@ -354,13 +409,18 @@ if (!runtimeContract.includes("### Interaction Locale Contract") || !runtimeCont
|
|
|
354
409
|
}
|
|
355
410
|
|
|
356
411
|
const gateCheckOperationalBoundaries = [
|
|
412
|
+
"Resolve or revalidate the primary task target before selecting repository control state.",
|
|
413
|
+
"Derive repository activation only from the resolved governance target",
|
|
357
414
|
"Select exactly one run and evaluate its current gate.",
|
|
358
415
|
"Confirm that the required durable artefact is present and ready.",
|
|
359
416
|
"Consume the canonical `approval_presentation` verbatim",
|
|
360
417
|
"obtain deliberate input through the contract-selected native or exact-text path",
|
|
361
|
-
"Revalidate the same run, gate and revision immediately after the response and before persistence.",
|
|
418
|
+
"Revalidate the same target, run, gate and revision immediately after the response and before persistence.",
|
|
362
419
|
"Persist only a currently valid exact approval through the existing control-state workflow.",
|
|
363
420
|
];
|
|
421
|
+
if (!gateCheckSkill.includes("../../meta/contracts/task-target-resolution.md")) {
|
|
422
|
+
failures.push("gate-check must load the focused task-target-resolution contract");
|
|
423
|
+
}
|
|
364
424
|
if (!gateCheckSkill.includes("../../meta/contracts/interaction.md")) {
|
|
365
425
|
failures.push("gate-check must load the focused interaction contract");
|
|
366
426
|
}
|
|
@@ -403,6 +463,26 @@ if (!runtimeContract.includes("### Repository Activation Diagnosis Boundary")) {
|
|
|
403
463
|
if (!runtimeContract.includes("### Scope Classification Card")) {
|
|
404
464
|
failures.push("interaction contract must own the scope classification card section");
|
|
405
465
|
}
|
|
466
|
+
if (!runtimeContract.includes("## Purpose And Ordering")
|
|
467
|
+
|| !runtimeContract.includes("## Target Authority Precedence")
|
|
468
|
+
|| !runtimeContract.includes("## Evidence And Mutation Boundary")
|
|
469
|
+
|| !runtimeContract.includes("## Fail-Closed States")) {
|
|
470
|
+
failures.push("task-target-resolution contract must own target precedence, evidence boundaries and fail-closed states");
|
|
471
|
+
}
|
|
472
|
+
if (!runtimeContract.includes("### Task Target Orientation")) {
|
|
473
|
+
failures.push("interaction contract must own the task target orientation section");
|
|
474
|
+
}
|
|
475
|
+
if (!agentRouterContent.includes("## Task Target Resolution")
|
|
476
|
+
|| agentRouterContent.indexOf("## Task Target Resolution") > agentRouterContent.indexOf("## Mode Selection")) {
|
|
477
|
+
failures.push("agent router must resolve the task target before Mode Selection");
|
|
478
|
+
}
|
|
479
|
+
if (!gateCheckSkill.includes("task_target_orientation.markdown` verbatim")) {
|
|
480
|
+
failures.push("gate-check must consume the canonical task target orientation verbatim");
|
|
481
|
+
}
|
|
482
|
+
if (gateCheckSkill.includes("## Task Target Orientation Template")
|
|
483
|
+
|| gateCheckSkill.includes("| Primary target | Governance target | Evidence sources |")) {
|
|
484
|
+
failures.push("gate-check must not maintain a skill-local task target orientation template");
|
|
485
|
+
}
|
|
406
486
|
if (!gateCheckSkill.includes("scope_classification.markdown` verbatim")) {
|
|
407
487
|
failures.push("gate-check must consume the canonical scope classification projection verbatim");
|
|
408
488
|
}
|
|
@@ -415,12 +495,21 @@ if (sourceMode && isFile(interactionPresentationPath)) {
|
|
|
415
495
|
if (!interactionPresentation.includes("export function renderScopeClassificationCard")) {
|
|
416
496
|
failures.push("interaction-presentation.js must export renderScopeClassificationCard");
|
|
417
497
|
}
|
|
498
|
+
if (!interactionPresentation.includes("export function renderTaskTargetOrientation")) {
|
|
499
|
+
failures.push("interaction-presentation.js must export renderTaskTargetOrientation");
|
|
500
|
+
}
|
|
418
501
|
}
|
|
419
502
|
for (const locale of ["en", "de"]) {
|
|
420
503
|
const pack = interactionLocales?.locales?.[locale];
|
|
421
504
|
if (!pack?.scopeClassification?.title || !pack?.scopeClassification?.mode?.quick_task || !pack?.scopeClassification?.challenge) {
|
|
422
505
|
failures.push(`Interaction locale ${locale} missing scopeClassification section keys`);
|
|
423
506
|
}
|
|
507
|
+
if (!pack?.taskTargetResolution?.title
|
|
508
|
+
|| !pack?.taskTargetResolution?.primaryTarget
|
|
509
|
+
|| !pack?.taskTargetResolution?.reasonCodes?.target_content_mismatch
|
|
510
|
+
|| !pack?.taskTargetResolution?.nextAction) {
|
|
511
|
+
failures.push(`Interaction locale ${locale} missing taskTargetResolution section keys`);
|
|
512
|
+
}
|
|
424
513
|
}
|
|
425
514
|
if (!runtimeContract.includes("not an agent-facing diagnosis proof")) {
|
|
426
515
|
failures.push("control-scaffold contract must classify AGDF_* env vars as non-agent-facing diagnosis");
|
|
@@ -902,9 +991,10 @@ for (const skill of expectedSkills) {
|
|
|
902
991
|
for (const required of [
|
|
903
992
|
"## Native Interaction Path",
|
|
904
993
|
"complete normative owner for interaction kinds, locale",
|
|
994
|
+
"Resolve or revalidate the primary task target before selecting repository control state",
|
|
905
995
|
"Select exactly one run and evaluate its current gate",
|
|
906
996
|
"Confirm that the required durable artefact is present and ready",
|
|
907
|
-
"Revalidate the same run, gate and revision immediately after the response and before persistence",
|
|
997
|
+
"Revalidate the same target, run, gate and revision immediately after the response and before persistence",
|
|
908
998
|
"Persist only a currently valid exact approval",
|
|
909
999
|
]) {
|
|
910
1000
|
if (!skillMd.includes(required)) failures.push(`gate-check native interaction guidance missing: ${required}`);
|
|
@@ -1066,7 +1156,33 @@ if (isFile(sotRegistryTemplatePath)) {
|
|
|
1066
1156
|
|
|
1067
1157
|
if (isFile(brownfieldReviewTemplatePath)) {
|
|
1068
1158
|
const brownfieldReviewTemplate = read(brownfieldReviewTemplatePath);
|
|
1069
|
-
for (const required of [
|
|
1159
|
+
for (const required of [
|
|
1160
|
+
"Existing-System View",
|
|
1161
|
+
"Reuse And Parallel-Structure Risk",
|
|
1162
|
+
"Mode / Slice Decision",
|
|
1163
|
+
"transparency_note",
|
|
1164
|
+
"Next Permissible Step",
|
|
1165
|
+
"delivery_context",
|
|
1166
|
+
"ui_ux_impact",
|
|
1167
|
+
"ui_ux_impact_reason",
|
|
1168
|
+
"ux_intent_definition_required",
|
|
1169
|
+
"ux_intent_definition_result",
|
|
1170
|
+
"Structured Depth Evidence",
|
|
1171
|
+
"depth_policy_version",
|
|
1172
|
+
"depth_facts_status",
|
|
1173
|
+
"primary_reason_code",
|
|
1174
|
+
"decisive_full_depth_triggers",
|
|
1175
|
+
"rejected_alternative",
|
|
1176
|
+
"missing_or_conflicting_facts",
|
|
1177
|
+
"depth_evidence_refs",
|
|
1178
|
+
"coherent_outcome",
|
|
1179
|
+
"authority_boundary",
|
|
1180
|
+
"owner_consumer_coordination",
|
|
1181
|
+
"full_depth_impacts_absent",
|
|
1182
|
+
"migration_propagation_bounded",
|
|
1183
|
+
"failure_recovery_local",
|
|
1184
|
+
"independently_acceptable",
|
|
1185
|
+
]) {
|
|
1070
1186
|
if (!brownfieldReviewTemplate.includes(required)) failures.push(`BROWNFIELD_REVIEW.md missing control field: ${required}`);
|
|
1071
1187
|
}
|
|
1072
1188
|
}
|
|
@@ -22,6 +22,7 @@ The skill answers:
|
|
|
22
22
|
Use these focused runtime-contract modules:
|
|
23
23
|
|
|
24
24
|
- `../../meta/contracts/gate-transition.md`
|
|
25
|
+
- `../../meta/contracts/modes.md`
|
|
25
26
|
- `../../meta/contracts/context-graph.md`
|
|
26
27
|
- `../../meta/contracts/quality.md`
|
|
27
28
|
|
|
@@ -54,6 +55,19 @@ not applicable; Brownfield records cite repository evidence. Do not create a sec
|
|
|
54
55
|
11. Large UI surfaces and state hooks must be checked for mixed render, view-model, derived state, orchestration, persistence, and recovery ownership.
|
|
55
56
|
12. Context Graph impact must be curated; it is not a review log or version index.
|
|
56
57
|
13. Specification archive migrations must follow the archive index if present.
|
|
58
|
+
14. In `post_ur_review`, evaluate unchanged compact paths first. For a structured candidate, apply
|
|
59
|
+
only the `Structured Depth Decision` in `modes.md`; do not recreate its trigger/check matrix in
|
|
60
|
+
this skill.
|
|
61
|
+
15. A positive structured decision requires `depth_policy_version: 1`,
|
|
62
|
+
`depth_facts_status: complete`, complete evidence for all seven bounded-slice checks, a primary
|
|
63
|
+
reason code, rejected alternative and evidence references. A decisive full-depth trigger may
|
|
64
|
+
support `structured_delivery`; `structured_slice` requires every bounded-slice check to pass.
|
|
65
|
+
16. Missing or conflicting decisive facts without an already-evidenced full-depth trigger persist
|
|
66
|
+
the existing `block` decision with `depth_facts_missing | depth_facts_conflicting`, named facts,
|
|
67
|
+
their evidence owner where known, a Brownfield Review link and a precise next action for evidence
|
|
68
|
+
completion and Brownfield/Mode-Slice re-evaluation.
|
|
69
|
+
17. Owner, file, consumer, task or derived-path counts must never select a structured depth by
|
|
70
|
+
themselves.
|
|
57
71
|
|
|
58
72
|
## When To Use
|
|
59
73
|
- after `gate-check` permits `Brownfield Review` or the selected canonical run record names Brownfield Review as the next allowed action
|
|
@@ -107,6 +121,11 @@ When used as Brownfield Review after `Approval: UR`, do not recommend PRD, SD, T
|
|
|
107
121
|
9. Check UI monolith risk for large surfaces or central hooks.
|
|
108
122
|
10. Check Context Graph impact according to `../../meta/contracts/context-graph.md`.
|
|
109
123
|
11. Recommend the minimal clean implementation path.
|
|
124
|
+
12. In `post_ur_review`, record `depth_policy_version`, `depth_facts_status`,
|
|
125
|
+
`primary_reason_code`, `decisive_full_depth_triggers`, `rejected_alternative`,
|
|
126
|
+
`missing_or_conflicting_facts`, `depth_evidence_refs` and evidence for all seven bounded-slice
|
|
127
|
+
check IDs in the Brownfield Review. Then persist the completed review and the existing
|
|
128
|
+
Mode/Slice Decision atomically.
|
|
110
129
|
|
|
111
130
|
## Output
|
|
112
131
|
Use a concise structure:
|
|
@@ -133,6 +152,13 @@ For `post_ur_review`, include the four UI/UX routing fields immediately after `s
|
|
|
133
152
|
definition is required, its `ready | blocked | not_applicable` result must be visible before PRD
|
|
134
153
|
readiness. A required `blocked` result is at least `revise` for this routing step.
|
|
135
154
|
|
|
155
|
+
For a structured `post_ur_review` candidate, also include the complete `Structured Depth Evidence`
|
|
156
|
+
section from `BROWNFIELD_REVIEW.md`. The decision projection must show the primary reason, decisive
|
|
157
|
+
dimensions, bounded-slice result, rejected alternative, evidence and required next gate. For
|
|
158
|
+
missing/conflicting facts, show product-language `depth_unresolved` while persisting `block`; name
|
|
159
|
+
the gap and exact recovery action. Structural instruction checks can detect missing contract
|
|
160
|
+
elements but do not prove semantic model compliance or live-host behavior.
|
|
161
|
+
|
|
136
162
|
## Pass / Revise / Block Guidance
|
|
137
163
|
- `pass`: existing owners are understood, reuse path is clear, and no blocking drift or parallel structure risk remains.
|
|
138
164
|
- `revise`: relevant evidence, tests, ownership, or reuse path is incomplete.
|