create-agdf 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/bin/create-agdf.js +249 -8
- package/generated/.agdf/control/templates/AGDF_RUN.md +1 -0
- package/generated/.agdf/control/templates/artefacts/OR.md +1 -0
- package/generated/.github/copilot-instructions.md +1 -0
- package/generated/.github/skills/README.md +1 -0
- package/generated/.github/skills/agdf-delivery-closeout/SKILL.md +9 -4
- package/generated/.github/skills/agdf-delivery-path-search/SKILL.md +75 -0
- package/generated/.github/skills/agdf-release-or/SKILL.md +8 -4
- package/generated/.github/skills/agdf-runtime-contract.md +24 -0
- package/generated/.opencode/AGDF.md +3 -0
- package/generated/.opencode/README.md +3 -0
- package/generated/.opencode/agdf-runtime-contract.md +24 -0
- package/generated/.opencode/agents/agdf-delivery-closeout.md +9 -4
- package/generated/.opencode/agents/agdf-delivery-path-search.md +76 -0
- package/generated/.opencode/agents/agdf-release-or.md +8 -4
- package/generated/AGENTS.md +2 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/control/templates/AGDF_RUN.md +1 -0
- package/generated/plugins/agdf/control/templates/artefacts/OR.md +1 -0
- package/generated/plugins/agdf/meta/agdf-agent-router.md +2 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
- package/generated/plugins/agdf/meta/agdf-runtime-contract.md +24 -0
- package/generated/plugins/agdf/skills/delivery-closeout/SKILL.md +9 -4
- package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +75 -0
- package/generated/plugins/agdf/skills/delivery-path-search/help.md +5 -0
- package/generated/plugins/agdf/skills/release-or/SKILL.md +8 -4
- package/lib/delivery-path-search/candidate-policy.js +34 -0
- package/lib/delivery-path-search/contracts.js +110 -0
- package/lib/delivery-path-search/evaluators/codex.js +67 -0
- package/lib/delivery-path-search/evaluators/protocol.js +13 -0
- package/lib/delivery-path-search/persistence.js +34 -0
- package/lib/delivery-path-search/scoring.js +21 -0
- package/lib/delivery-path-search/search-engine.js +92 -0
- package/lib/delivery-path-search/state-adapter.js +58 -0
- package/lib/delivery-path-search/surfaces/capabilities.js +14 -0
- package/opencode-plugin.js +17 -5
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -10,10 +10,13 @@ Preferred long-term CLI shape:
|
|
|
10
10
|
npx --yes @agdf/cli@latest codex
|
|
11
11
|
npx --yes @agdf/cli@latest codex-repo
|
|
12
12
|
npx --yes @agdf/cli@latest claude
|
|
13
|
+
npx --yes @agdf/cli@latest opencode
|
|
14
|
+
npx --yes @agdf/cli@latest opencode-status
|
|
13
15
|
npx --yes @agdf/cli@latest opencode-repo
|
|
14
16
|
npx --yes @agdf/cli@latest init
|
|
15
17
|
npx --yes @agdf/cli@latest config --language en
|
|
16
18
|
npx --yes @agdf/cli@latest doctor
|
|
19
|
+
npx --yes @agdf/cli@latest gate-check --status-card
|
|
17
20
|
npx --yes @agdf/cli@latest gate-check --json
|
|
18
21
|
```
|
|
19
22
|
|
|
@@ -24,6 +27,8 @@ npm create agdf@latest -- codex
|
|
|
24
27
|
npm create agdf@latest -- codex-repo
|
|
25
28
|
npm create agdf@latest -- claude
|
|
26
29
|
npm create agdf@latest -- copilot
|
|
30
|
+
npm create agdf@latest -- opencode
|
|
31
|
+
npm create agdf@latest -- opencode-status
|
|
27
32
|
npm create agdf@latest -- opencode-repo
|
|
28
33
|
npm create agdf@latest -- both
|
|
29
34
|
npm create agdf@latest -- init
|
|
@@ -47,6 +52,7 @@ If no language is provided, `create-agdf` derives the preference from the local
|
|
|
47
52
|
- `claude` installs the AGDF plugin globally for Claude Code
|
|
48
53
|
- `copilot` writes `AGENTS.md`, Copilot custom instructions under `.github/`, visible repository skills under `.github/skills/`, and AGDF control templates under `.agdf/control/`
|
|
49
54
|
- `opencode` installs the AGDF npm plugin as a user-wide OpenCode hook
|
|
55
|
+
- `opencode-status` reports OpenCode global config, package loadability, session signals and repository surface presence
|
|
50
56
|
- `opencode-repo` writes `opencode.json`, `.opencode/AGDF.md`, prefixed OpenCode agents under `.opencode/agents/`, explicit edit/bash permissions, and AGDF control templates under `.agdf/control/`
|
|
51
57
|
- `both` writes the Codex repository-local marketplace plus the Copilot-facing repository files
|
|
52
58
|
- `config` writes or updates only `.agdf/control/config.json` for an already installed plugin or an existing repository
|
|
@@ -63,6 +69,14 @@ Use the `opencode` target to install the AGDF npm plugin as a user-wide OpenCode
|
|
|
63
69
|
npx --yes @agdf/cli@latest opencode
|
|
64
70
|
```
|
|
65
71
|
|
|
72
|
+
Then verify the visible installation state:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx --yes @agdf/cli@latest opencode-status --json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The status command reports global configuration, whether `create-agdf` is loadable from the OpenCode config directory, whether the current process exposes AGDF session signals, and whether the current repository has `.opencode/AGDF.md` plus the `agdf-gate-check` surface. It does not infer an active OpenCode session from config alone.
|
|
79
|
+
|
|
66
80
|
Use the `opencode-repo` target when AGDF should be available to OpenCode from repository files:
|
|
67
81
|
|
|
68
82
|
```bash
|
|
@@ -133,6 +147,29 @@ npx --yes create-agdf@latest gate-check --json
|
|
|
133
147
|
|
|
134
148
|
The gate check reports `open | blocked`, the current gate, blocking reason, missing exact approval, allowed outputs, forbidden outputs, next allowed action, evidence references and the embedded doctor report.
|
|
135
149
|
|
|
150
|
+
Use `gate-check --status-card` for compact interactive output, especially in OpenCode where shell output is highly visible. Keep `gate-check --json` for automation, CI, regression evidence and audit trails.
|
|
151
|
+
|
|
152
|
+
Use `delivery-path-search` only for high-impact planning decisions with several materially different next steps:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx --yes @agdf/cli@latest delivery-path-search --surface codex --json
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The first release uses bounded best-first Delivery Path Search, not MCTS. It is read-only and advisory: the result must be checked by canonical `gate-check`. Codex is the executable reference adapter; Claude Code, Copilot and OpenCode reuse the same skill and contracts while declaring whether enforcement is full, tool-enforced or instruction-only.
|
|
159
|
+
|
|
160
|
+
Requirements and boundaries:
|
|
161
|
+
|
|
162
|
+
- run it only in a repository with live `.agdf/control/AGDF_RUN.md` state
|
|
163
|
+
- the current control state must expose legal next actions
|
|
164
|
+
- Codex CLI must be installed and authenticated for `--surface codex`
|
|
165
|
+
- `--model <id>` optionally selects the Codex evaluator model
|
|
166
|
+
- `--persist` writes redacted `DELIVERY_PATH_SEARCH.json` and `.md` evidence under the current scope
|
|
167
|
+
- `--fixture <path>` is for deterministic contract tests, not a production evaluator
|
|
168
|
+
- Claude Code, Copilot and OpenCode have shared workflow mappings but no executable native evaluator in this release
|
|
169
|
+
- cost units are rubric values used for bounded comparison, not measured provider currency
|
|
170
|
+
|
|
171
|
+
The result is either one recommendation or `no_safe_recommendation`. In both cases run canonical `gate-check` afterwards.
|
|
172
|
+
|
|
136
173
|
`gate-check --json` and `delivery-map --json` also expose a `status_card` object. It is a compact projection of the current control state: current gate, allowed and forbidden actions, blocker, next skill, next permissible step and `quality_outlook`. `next_step` is process permission; `quality_outlook` is the next meaningful quality-improvement focus and does not unlock gates.
|
|
137
174
|
|
|
138
175
|
Together, `init`, `doctor` and `gate-check --json` turn AGDF from an instruction layer into a repository control system when durable control state is needed. For normal fresh requests, keep the path lighter: draft the minimal UR in the response, request `Approval: UR`, and use CLI validators only when machine-readable proof is useful.
|
package/bin/create-agdf.js
CHANGED
|
@@ -6,6 +6,12 @@ import { homedir } from "node:os";
|
|
|
6
6
|
import { dirname, join, posix, resolve } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import process from "node:process";
|
|
9
|
+
import { searchInputFromControl } from "../lib/delivery-path-search/state-adapter.js";
|
|
10
|
+
import { runDeliveryPathSearch } from "../lib/delivery-path-search/search-engine.js";
|
|
11
|
+
import { codexEvaluator } from "../lib/delivery-path-search/evaluators/codex.js";
|
|
12
|
+
import { fixtureEvaluator } from "../lib/delivery-path-search/evaluators/protocol.js";
|
|
13
|
+
import { enforcementForSurface } from "../lib/delivery-path-search/surfaces/capabilities.js";
|
|
14
|
+
import { persistSearchResult } from "../lib/delivery-path-search/persistence.js";
|
|
9
15
|
|
|
10
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
17
|
const packageRoot = resolve(__dirname, "..");
|
|
@@ -13,7 +19,9 @@ const generatedRoot = join(packageRoot, "generated");
|
|
|
13
19
|
const pluginDefinitionPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-plugin.definition.json");
|
|
14
20
|
const pluginDefinition = JSON.parse(readFileSync(pluginDefinitionPath, "utf8"));
|
|
15
21
|
const pluginInstallCommand = "npx --yes @agdf/cli@latest claude";
|
|
16
|
-
const
|
|
22
|
+
const npmCommand = process.platform === "win32" ? process.execPath : "npm";
|
|
23
|
+
const npmPrefixArgs = process.platform === "win32" ? [join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js")] : [];
|
|
24
|
+
const allowedTargets = new Set(["codex", "codex-repo", "claude", "copilot", "opencode", "opencode-status", "opencode-repo", "both", "init", "config", "doctor", "gate-check", "delivery-map", "delivery-path-search"]);
|
|
17
25
|
const agdfFragmentPath = "AGENTS.agdf.md";
|
|
18
26
|
const openCodeConfigFragmentPath = "opencode.agdf.json";
|
|
19
27
|
const userGateOrder = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
|
|
@@ -161,10 +169,12 @@ Preferred AGDF CLI:
|
|
|
161
169
|
npx --yes @agdf/cli@latest codex-repo
|
|
162
170
|
npx --yes @agdf/cli@latest claude
|
|
163
171
|
npx --yes @agdf/cli@latest opencode
|
|
172
|
+
npx --yes @agdf/cli@latest opencode-status
|
|
164
173
|
npx --yes @agdf/cli@latest opencode-repo
|
|
165
174
|
npx --yes @agdf/cli@latest init
|
|
166
175
|
npx --yes @agdf/cli@latest doctor
|
|
167
176
|
npx --yes @agdf/cli@latest gate-check --json
|
|
177
|
+
npx --yes @agdf/cli@latest delivery-path-search --surface codex --json
|
|
168
178
|
|
|
169
179
|
Scaffold-compatible npm create usage:
|
|
170
180
|
npm create agdf@latest -- codex
|
|
@@ -172,6 +182,7 @@ Scaffold-compatible npm create usage:
|
|
|
172
182
|
npm create agdf@latest -- claude
|
|
173
183
|
npm create agdf@latest -- copilot
|
|
174
184
|
npm create agdf@latest -- opencode
|
|
185
|
+
npm create agdf@latest -- opencode-status
|
|
175
186
|
npm create agdf@latest -- opencode-repo
|
|
176
187
|
npm create agdf@latest -- both
|
|
177
188
|
npm create agdf@latest -- init
|
|
@@ -179,6 +190,7 @@ Scaffold-compatible npm create usage:
|
|
|
179
190
|
npm create agdf@latest -- doctor
|
|
180
191
|
npm create agdf@latest -- gate-check
|
|
181
192
|
npm create agdf@latest -- delivery-map
|
|
193
|
+
npm create agdf@latest -- delivery-path-search --surface codex
|
|
182
194
|
|
|
183
195
|
Backward-compatible create-agdf usage:
|
|
184
196
|
npx --yes create-agdf@latest doctor --json
|
|
@@ -190,7 +202,14 @@ Options:
|
|
|
190
202
|
--language <de|en>
|
|
191
203
|
Set AGDF chat and artefact language. Defaults to detected system locale.
|
|
192
204
|
--lang <de|en> Alias for --language
|
|
193
|
-
--json Print
|
|
205
|
+
--json Print machine-readable command output as JSON
|
|
206
|
+
--status-card Print compact gate-check status-card output for interactive use
|
|
207
|
+
--surface <codex|claude|copilot|opencode|generic>
|
|
208
|
+
Declare the active Delivery Path Search surface
|
|
209
|
+
--fixture <path>
|
|
210
|
+
Use deterministic evaluator/candidate fixtures instead of a live evaluator
|
|
211
|
+
--persist Persist the redacted Delivery Path Search result under the current scope
|
|
212
|
+
--model <id> Optional Codex evaluator model
|
|
194
213
|
--help Show this help
|
|
195
214
|
`);
|
|
196
215
|
}
|
|
@@ -252,8 +271,13 @@ function parseArgs(argv) {
|
|
|
252
271
|
let dir = ".";
|
|
253
272
|
let force = false;
|
|
254
273
|
let json = false;
|
|
274
|
+
let statusCard = false;
|
|
255
275
|
let language;
|
|
256
276
|
let dirExplicit = false;
|
|
277
|
+
let surface = "generic";
|
|
278
|
+
let fixture;
|
|
279
|
+
let persist = false;
|
|
280
|
+
let model;
|
|
257
281
|
|
|
258
282
|
for (let i = 0; i < args.length; i += 1) {
|
|
259
283
|
const arg = args[i];
|
|
@@ -274,6 +298,34 @@ function parseArgs(argv) {
|
|
|
274
298
|
continue;
|
|
275
299
|
}
|
|
276
300
|
|
|
301
|
+
if (arg === "--status-card") {
|
|
302
|
+
statusCard = true;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (arg === "--persist") {
|
|
307
|
+
persist = true;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (["--surface", "--fixture", "--model"].includes(arg)) {
|
|
312
|
+
const next = args[i + 1];
|
|
313
|
+
if (!next) {
|
|
314
|
+
console.error(`Missing value for ${arg}`);
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
if (arg === "--surface") {
|
|
318
|
+
if (!["codex", "claude", "copilot", "opencode", "generic"].includes(next)) {
|
|
319
|
+
console.error("Unsupported surface. Use codex, claude, copilot, opencode or generic.");
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
surface = next;
|
|
323
|
+
} else if (arg === "--fixture") fixture = next;
|
|
324
|
+
else model = next;
|
|
325
|
+
i += 1;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
277
329
|
if (arg === "--language" || arg === "--lang") {
|
|
278
330
|
const next = args[i + 1];
|
|
279
331
|
if (!next) {
|
|
@@ -323,7 +375,7 @@ function parseArgs(argv) {
|
|
|
323
375
|
}
|
|
324
376
|
|
|
325
377
|
if (!target || !allowedTargets.has(target)) {
|
|
326
|
-
console.error("Please choose one target: codex, codex-repo, claude, copilot, opencode, opencode-repo, both, init, config, doctor, gate-check or delivery-
|
|
378
|
+
console.error("Please choose one target: codex, codex-repo, claude, copilot, opencode, opencode-status, opencode-repo, both, init, config, doctor, gate-check, delivery-map or delivery-path-search.");
|
|
327
379
|
printUsage();
|
|
328
380
|
process.exit(1);
|
|
329
381
|
}
|
|
@@ -333,8 +385,13 @@ function parseArgs(argv) {
|
|
|
333
385
|
dir: resolve(process.cwd(), dir),
|
|
334
386
|
force,
|
|
335
387
|
json,
|
|
388
|
+
statusCard,
|
|
336
389
|
dirExplicit,
|
|
337
390
|
language: resolveLanguagePreference(language),
|
|
391
|
+
surface,
|
|
392
|
+
fixture: fixture ? resolve(process.cwd(), fixture) : null,
|
|
393
|
+
persist,
|
|
394
|
+
model,
|
|
338
395
|
};
|
|
339
396
|
}
|
|
340
397
|
|
|
@@ -371,6 +428,11 @@ function installOpenCodeGlobalPlugin(configDir) {
|
|
|
371
428
|
};
|
|
372
429
|
|
|
373
430
|
mkdirSync(configDir, { recursive: true });
|
|
431
|
+
try {
|
|
432
|
+
execFileSync(npmCommand, [...npmPrefixArgs, "install", "--silent", "--save-prod", "--prefix", configDir, packageRoot], { stdio: "pipe" });
|
|
433
|
+
} catch (error) {
|
|
434
|
+
throw new Error(`Failed to install ${pluginDefinition.opencode.npmPackage} into the OpenCode config directory: ${(error.stderr || error.message).toString().trim()}`);
|
|
435
|
+
}
|
|
374
436
|
writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
|
|
375
437
|
|
|
376
438
|
return {
|
|
@@ -379,6 +441,119 @@ function installOpenCodeGlobalPlugin(configDir) {
|
|
|
379
441
|
};
|
|
380
442
|
}
|
|
381
443
|
|
|
444
|
+
function readOpenCodeConfig(configPath) {
|
|
445
|
+
if (!existsSync(configPath)) return { exists: false, parseError: "", config: {} };
|
|
446
|
+
try {
|
|
447
|
+
return { exists: true, parseError: "", config: JSON.parse(readFileSync(configPath, "utf8")) };
|
|
448
|
+
} catch (error) {
|
|
449
|
+
return { exists: true, parseError: error.message, config: {} };
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function isOpenCodeRepositorySurfacePresent(targetDir) {
|
|
454
|
+
return existsSync(join(targetDir, ".opencode", pluginDefinition.opencode.instructionsFileName))
|
|
455
|
+
&& existsSync(join(targetDir, ".opencode", "agents", `${pluginDefinition.opencode.skillPrefix}gate-check.md`));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function resolveOpenCodePackage(configDir) {
|
|
459
|
+
const packageName = pluginDefinition.opencode.npmPackage;
|
|
460
|
+
try {
|
|
461
|
+
return {
|
|
462
|
+
loadable: true,
|
|
463
|
+
path: execFileSync(process.execPath, ["-e", `process.stdout.write(require.resolve(${JSON.stringify(packageName)}))`], {
|
|
464
|
+
cwd: configDir,
|
|
465
|
+
encoding: "utf8",
|
|
466
|
+
stdio: "pipe",
|
|
467
|
+
}),
|
|
468
|
+
error: "",
|
|
469
|
+
};
|
|
470
|
+
} catch (error) {
|
|
471
|
+
return {
|
|
472
|
+
loadable: false,
|
|
473
|
+
path: "",
|
|
474
|
+
error: (error.stderr || error.message || "package not resolvable").toString().trim(),
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir()) {
|
|
480
|
+
const configPath = join(configDir, "opencode.json");
|
|
481
|
+
const configState = readOpenCodeConfig(configPath);
|
|
482
|
+
const plugins = Array.isArray(configState.config.plugin) ? configState.config.plugin : [];
|
|
483
|
+
const globalConfigured = plugins.includes(pluginDefinition.opencode.npmPackage);
|
|
484
|
+
const packageState = resolveOpenCodePackage(configDir);
|
|
485
|
+
const sessionSignals = {
|
|
486
|
+
active: process.env.AGDF_PLUGIN_ACTIVE === "1",
|
|
487
|
+
version: process.env.AGDF_PLUGIN_VERSION || "",
|
|
488
|
+
control_dir: process.env.AGDF_CONTROL_DIR || "",
|
|
489
|
+
repository_surface: process.env.AGDF_OPENCODE_REPOSITORY_SURFACE === "1",
|
|
490
|
+
};
|
|
491
|
+
const repositorySurface = isOpenCodeRepositorySurfacePresent(targetDir);
|
|
492
|
+
|
|
493
|
+
const findings = [];
|
|
494
|
+
if (!configState.exists) findings.push("OpenCode global config not found.");
|
|
495
|
+
if (configState.parseError) findings.push(`OpenCode global config is not valid JSON: ${configState.parseError}`);
|
|
496
|
+
if (!globalConfigured) findings.push(`OpenCode global config does not include ${pluginDefinition.opencode.npmPackage}.`);
|
|
497
|
+
if (!packageState.loadable) findings.push(`${pluginDefinition.opencode.npmPackage} is not loadable from the OpenCode config directory.`);
|
|
498
|
+
if (!sessionSignals.active) findings.push("No active AGDF OpenCode session signal is visible in this process.");
|
|
499
|
+
if (!repositorySurface) findings.push("Current repository does not contain the AGDF OpenCode surface.");
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
schema_version: "1",
|
|
503
|
+
status: globalConfigured && packageState.loadable ? "configured" : "not_configured",
|
|
504
|
+
global_config: {
|
|
505
|
+
path: configPath,
|
|
506
|
+
exists: configState.exists,
|
|
507
|
+
parse_error: configState.parseError,
|
|
508
|
+
plugin_configured: globalConfigured,
|
|
509
|
+
},
|
|
510
|
+
package: {
|
|
511
|
+
name: pluginDefinition.opencode.npmPackage,
|
|
512
|
+
loadable: packageState.loadable,
|
|
513
|
+
resolved_path: packageState.path,
|
|
514
|
+
error: packageState.error,
|
|
515
|
+
},
|
|
516
|
+
session: sessionSignals,
|
|
517
|
+
repository_surface: {
|
|
518
|
+
path: targetDir,
|
|
519
|
+
present: repositorySurface,
|
|
520
|
+
instructions: join(targetDir, ".opencode", pluginDefinition.opencode.instructionsFileName),
|
|
521
|
+
gate_check_agent: join(targetDir, ".opencode", "agents", `${pluginDefinition.opencode.skillPrefix}gate-check.md`),
|
|
522
|
+
},
|
|
523
|
+
visible_entrypoint: repositorySurface ? `@${pluginDefinition.opencode.skillPrefix}gate-check` : "none until opencode-repo is installed for this repository",
|
|
524
|
+
findings,
|
|
525
|
+
next_step: repositorySurface
|
|
526
|
+
? `Restart OpenCode if needed, then use @${pluginDefinition.opencode.skillPrefix}gate-check for new build/change intent.`
|
|
527
|
+
: "Run npx --yes @agdf/cli@latest opencode-repo in repositories where AGDF governance should be active and reviewable.",
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function printOpenCodeStatus(report, json) {
|
|
532
|
+
if (json) {
|
|
533
|
+
console.log(JSON.stringify(report, null, 2));
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
console.log("AGDF OpenCode status");
|
|
538
|
+
console.log(`Status: ${report.status}`);
|
|
539
|
+
console.log(`Global config: ${report.global_config.plugin_configured ? "configured" : "missing"} (${report.global_config.path})`);
|
|
540
|
+
if (report.global_config.parse_error) console.log(`Config parse error: ${report.global_config.parse_error}`);
|
|
541
|
+
console.log(`Package loadable: ${report.package.loadable ? "yes" : "no"}`);
|
|
542
|
+
if (report.package.resolved_path) console.log(`Package path: ${report.package.resolved_path}`);
|
|
543
|
+
console.log(`Session active signal: ${report.session.active ? "yes" : "no"}`);
|
|
544
|
+
if (report.session.version) console.log(`Session plugin version: ${report.session.version}`);
|
|
545
|
+
if (report.session.control_dir) console.log(`Session control dir: ${report.session.control_dir}`);
|
|
546
|
+
console.log(`Repository surface: ${report.repository_surface.present ? "present" : "missing"}`);
|
|
547
|
+
console.log(`Visible entrypoint: ${report.visible_entrypoint}`);
|
|
548
|
+
console.log(`Next step: ${report.next_step}`);
|
|
549
|
+
|
|
550
|
+
if (report.findings.length > 0) {
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log("Findings:");
|
|
553
|
+
for (const finding of report.findings) console.log(`- ${finding}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
382
557
|
function installCodexGlobalPlugin() {
|
|
383
558
|
try {
|
|
384
559
|
execFileSync("codex", ["plugin", "marketplace", "add", "arndtgold/ai-native-governance-delivery-framework"], { stdio: "inherit" });
|
|
@@ -1703,12 +1878,30 @@ function evaluateGateCheck(targetDir) {
|
|
|
1703
1878
|
};
|
|
1704
1879
|
}
|
|
1705
1880
|
|
|
1706
|
-
function
|
|
1881
|
+
function printGateCheckStatusCard(report) {
|
|
1882
|
+
const card = report.status_card;
|
|
1883
|
+
console.log(`AGDF status-card: ${card.status}`);
|
|
1884
|
+
console.log(`Current gate: ${card.current_gate}`);
|
|
1885
|
+
console.log(`Blocked by: ${card.blocking_condition}`);
|
|
1886
|
+
console.log(`Missing approval: ${card.missing_approval}`);
|
|
1887
|
+
console.log(`Next skill: ${card.next_skill}`);
|
|
1888
|
+
console.log(`Next step: ${card.next_step}`);
|
|
1889
|
+
console.log(`Quality outlook: ${card.quality_outlook}`);
|
|
1890
|
+
if (card.allowed_now.length > 0) console.log(`Allowed now: ${card.allowed_now.join("; ")}`);
|
|
1891
|
+
if (card.forbidden_now.length > 0) console.log(`Forbidden now: ${card.forbidden_now.join("; ")}`);
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
function printGateCheckReport(report, json, statusCard = false) {
|
|
1707
1895
|
if (json) {
|
|
1708
1896
|
console.log(JSON.stringify(report, null, 2));
|
|
1709
1897
|
return;
|
|
1710
1898
|
}
|
|
1711
1899
|
|
|
1900
|
+
if (statusCard) {
|
|
1901
|
+
printGateCheckStatusCard(report);
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1712
1905
|
console.log(`AGDF gate-check: ${report.status}`);
|
|
1713
1906
|
console.log(`Current gate: ${report.current_gate}`);
|
|
1714
1907
|
console.log(`Blocking reason: ${report.blocking_reason}`);
|
|
@@ -1808,7 +2001,35 @@ function printDeliveryMapReport(report, json) {
|
|
|
1808
2001
|
}
|
|
1809
2002
|
}
|
|
1810
2003
|
|
|
1811
|
-
function
|
|
2004
|
+
async function executeDeliveryPathSearch(options) {
|
|
2005
|
+
const fixture = options.fixture ? JSON.parse(readFileSync(options.fixture, "utf8")) : null;
|
|
2006
|
+
const enforcement = fixture?.input?.enforcement ?? enforcementForSurface(options.surface);
|
|
2007
|
+
const input = fixture?.input ?? searchInputFromControl(options.dir, { enforcement });
|
|
2008
|
+
const evaluator = fixture
|
|
2009
|
+
? fixtureEvaluator(fixture.evaluations ?? {})
|
|
2010
|
+
: options.surface === "codex"
|
|
2011
|
+
? codexEvaluator({ cwd: options.dir, model: options.model })
|
|
2012
|
+
: null;
|
|
2013
|
+
if (!evaluator) {
|
|
2014
|
+
throw new Error(`${options.surface} has no executable evaluator in this release. Codex is the reference adapter; --fixture is available for deterministic contract testing.`);
|
|
2015
|
+
}
|
|
2016
|
+
const result = await runDeliveryPathSearch(input, evaluator, { candidates: fixture?.candidates });
|
|
2017
|
+
if (options.persist) result.persistence = persistSearchResult(options.dir, result);
|
|
2018
|
+
if (options.json) {
|
|
2019
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2020
|
+
return result;
|
|
2021
|
+
}
|
|
2022
|
+
console.log(`AGDF Delivery Path Search: ${result.status}`);
|
|
2023
|
+
console.log(`Current gate: ${result.current_gate}`);
|
|
2024
|
+
console.log(`Enforcement: ${result.enforcement.level}`);
|
|
2025
|
+
console.log(`Recommendation: ${result.recommendation?.action ?? "none"}`);
|
|
2026
|
+
console.log(`Evaluations: ${result.budgets.evaluations}`);
|
|
2027
|
+
console.log(`Stopping reason: ${result.stopping_reason}`);
|
|
2028
|
+
console.log(result.next_gate_action);
|
|
2029
|
+
return result;
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
async function main() {
|
|
1812
2033
|
const options = parseArgs(process.argv.slice(2));
|
|
1813
2034
|
|
|
1814
2035
|
if (options.target === "doctor") {
|
|
@@ -1819,7 +2040,7 @@ function main() {
|
|
|
1819
2040
|
|
|
1820
2041
|
if (options.target === "gate-check") {
|
|
1821
2042
|
const report = evaluateGateCheck(options.dir);
|
|
1822
|
-
printGateCheckReport(report, options.json);
|
|
2043
|
+
printGateCheckReport(report, options.json, options.statusCard);
|
|
1823
2044
|
process.exit(report.status === "blocked" ? 2 : 0);
|
|
1824
2045
|
}
|
|
1825
2046
|
|
|
@@ -1829,6 +2050,24 @@ function main() {
|
|
|
1829
2050
|
process.exit(report.status === "block" ? 2 : 0);
|
|
1830
2051
|
}
|
|
1831
2052
|
|
|
2053
|
+
if (options.target === "delivery-path-search") {
|
|
2054
|
+
try {
|
|
2055
|
+
const result = await executeDeliveryPathSearch(options);
|
|
2056
|
+
process.exitCode = result.status === "recommendation" ? 0 : 2;
|
|
2057
|
+
} catch (error) {
|
|
2058
|
+
console.error(`Delivery Path Search failed: ${error.message}`);
|
|
2059
|
+
process.exitCode = 2;
|
|
2060
|
+
}
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
if (options.target === "opencode-status") {
|
|
2065
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir();
|
|
2066
|
+
const report = evaluateOpenCodeStatus(options.dir, configDir);
|
|
2067
|
+
printOpenCodeStatus(report, options.json);
|
|
2068
|
+
process.exit(report.status === "configured" ? 0 : 1);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
1832
2071
|
if (options.target === "codex") {
|
|
1833
2072
|
try {
|
|
1834
2073
|
installCodexGlobalPlugin();
|
|
@@ -1857,7 +2096,9 @@ function main() {
|
|
|
1857
2096
|
try {
|
|
1858
2097
|
const result = installOpenCodeGlobalPlugin(configDir);
|
|
1859
2098
|
console.log(`AGDF OpenCode global plugin ${result.added ? "installed" : "already present"}: ${result.configPath}`);
|
|
1860
|
-
|
|
2099
|
+
const report = evaluateOpenCodeStatus(options.dir, configDir);
|
|
2100
|
+
printOpenCodeStatus(report, false);
|
|
2101
|
+
console.log("Restart OpenCode so it loads the updated global plugin config.");
|
|
1861
2102
|
} catch (error) {
|
|
1862
2103
|
console.error(error.message);
|
|
1863
2104
|
process.exit(1);
|
|
@@ -1881,4 +2122,4 @@ function main() {
|
|
|
1881
2122
|
printNextSteps(options.target, options.dir, files, wroteAgentsFragment, wroteOpenCodeConfigFragment);
|
|
1882
2123
|
}
|
|
1883
2124
|
|
|
1884
|
-
main();
|
|
2125
|
+
await main();
|
|
@@ -117,6 +117,7 @@ Keep the active work item traceable. A gate may open only when the previous gate
|
|
|
117
117
|
|
|
118
118
|
- context_graph_impact: `none | link_only | update_existing_node | new_node_required | sot_drift`
|
|
119
119
|
- context_graph_refs:
|
|
120
|
+
- context_graph_reconciliation: `resolved | not_applicable | open_gap`
|
|
120
121
|
- context_graph_required_action: `none | link | update | create | resolve_drift`
|
|
121
122
|
- context_graph_gate_effect: `none | warning | revise | block`
|
|
122
123
|
- context_graph_evidence:
|
|
@@ -81,6 +81,7 @@ This is a compact projection of the control state. It does not replace gate-chec
|
|
|
81
81
|
|
|
82
82
|
- context_graph_impact: `none | link_only | update_existing_node | new_node_required | sot_drift`
|
|
83
83
|
- context_graph_refs:
|
|
84
|
+
- context_graph_reconciliation: `resolved | not_applicable | open_gap`
|
|
84
85
|
- context_graph_required_action: `none | link | update | create | resolve_drift`
|
|
85
86
|
- context_graph_gate_effect: `none | warning | revise | block`
|
|
86
87
|
- context_graph_evidence:
|
|
@@ -13,3 +13,4 @@ AGDF is active in this repository.
|
|
|
13
13
|
- Do not infer gate approval from generic consent such as "ok", "go ahead", "do it", "continue", "leg los" or "approved".
|
|
14
14
|
- Do not treat chat history as the source of truth for gate state, approvals, evidence or delivery status.
|
|
15
15
|
- Do not paste full control files, templates or artefact bodies into chat unless the user explicitly asks for the full content; summarize and link paths instead.
|
|
16
|
+
- For interactive checks, prefer `npx --yes @agdf/cli@latest gate-check --status-card`. Use `gate-check --json` for automation or audit evidence and summarize the status card instead of mirroring full JSON into chat.
|
|
@@ -8,6 +8,7 @@ These repository skills were generated from the AGDF source repository and are i
|
|
|
8
8
|
- `agdf-clean-implementation-review`
|
|
9
9
|
- `agdf-code-review`
|
|
10
10
|
- `agdf-delivery-closeout`
|
|
11
|
+
- `agdf-delivery-path-search`
|
|
11
12
|
- `agdf-gate-check`
|
|
12
13
|
- `agdf-qa-gate`
|
|
13
14
|
- `agdf-release-or`
|
|
@@ -32,6 +32,7 @@ Use `../agdf-runtime-contract.md` for closeout discipline, gate terms, Context G
|
|
|
32
32
|
4. `Approval: UAT` unlocks an active commit offer when code changes exist.
|
|
33
33
|
5. No commit handoff for runs without code changes.
|
|
34
34
|
6. Always include exactly one next step and one quality outlook.
|
|
35
|
+
7. If OR, QA or current run state reports `context_graph_reconciliation: open_gap`, do not provide a clean commit-ready handoff; set the next step to resolve or explicitly retain the Context Graph gap.
|
|
35
36
|
|
|
36
37
|
## When To Use
|
|
37
38
|
- after `QA pass` with code changes
|
|
@@ -62,8 +63,10 @@ If code-change status is unclear, do not claim a commit handoff.
|
|
|
62
63
|
- `uat_approved_with_code`
|
|
63
64
|
- `uat_approved_without_code`
|
|
64
65
|
- `non_delivery_closeout`
|
|
65
|
-
2.
|
|
66
|
-
3.
|
|
66
|
+
2. Check Context Graph reconciliation from OR, QA, review and current run state.
|
|
67
|
+
3. If reconciliation is `open_gap`, report the delivery status as not cleanly handoff-ready and do not derive commit-ready Git text.
|
|
68
|
+
4. Derive Git handoff only when code changes exist and no unresolved Context Graph gap remains.
|
|
69
|
+
5. Set exactly one next delivery step:
|
|
67
70
|
- offer commit
|
|
68
71
|
- offer push
|
|
69
72
|
- offer PR
|
|
@@ -71,13 +74,15 @@ If code-change status is unclear, do not claim a commit handoff.
|
|
|
71
74
|
- run QA/review
|
|
72
75
|
- obtain UAT/approval
|
|
73
76
|
- perform documentation follow-up
|
|
74
|
-
|
|
77
|
+
- resolve Context Graph gap
|
|
78
|
+
6. Set quality outlook:
|
|
75
79
|
- no further technical follow-up
|
|
76
80
|
- more tests
|
|
77
81
|
- refactoring
|
|
78
82
|
- documentation sharpening
|
|
79
83
|
- monitoring/runtime verification
|
|
80
|
-
|
|
84
|
+
- Context Graph reconciliation
|
|
85
|
+
7. If `Approval: UAT` exists, code changes were delivered, and no Context Graph gap remains, actively offer the commit but do not run it.
|
|
81
86
|
|
|
82
87
|
## Output
|
|
83
88
|
For code-changing runs:
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agdf-delivery-path-search
|
|
3
|
+
description: Use this skill for high-impact planning decisions when several materially different next delivery steps are plausible and comparing scope, risk, evidence, tests, cost and gate readiness would reduce expensive rework. Do not use for routine tasks, during implementation, or as gate permission.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Delivery Path Search
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
Search a bounded set of possible delivery paths before implementation and return one safest evidence-backed next step.
|
|
11
|
+
|
|
12
|
+
The search is advisory and read-only. Canonical AGDF `agdf-gate-check` remains the only authority for whether the recommended step may proceed.
|
|
13
|
+
|
|
14
|
+
## Runtime Contract
|
|
15
|
+
|
|
16
|
+
Use `../agdf-runtime-contract.md` for canonical gate state, output discipline and Delivery Path Search boundaries. This skill must not maintain a second gate or scoring model.
|
|
17
|
+
|
|
18
|
+
## Trigger
|
|
19
|
+
|
|
20
|
+
Use only when at least one applies:
|
|
21
|
+
|
|
22
|
+
- high product, architecture, security, policy, persistence or release impact
|
|
23
|
+
- several materially different next actions are plausible
|
|
24
|
+
- a wrong decision would cause expensive rework
|
|
25
|
+
- the best evidence-gathering or test action is unclear
|
|
26
|
+
|
|
27
|
+
Skip for routine questions, obvious local fixes and approved implementation with one clear next action.
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
1. Run AGDF gate-check and inspect durable control state.
|
|
32
|
+
2. Confirm that search is allowed and implementation is not occurring during exploration.
|
|
33
|
+
3. Declare the active surface and its enforcement level.
|
|
34
|
+
4. Invoke the shared CLI runtime:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx --yes @agdf/cli@latest delivery-path-search --surface <surface> --json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
5. Treat facts, repository evidence, assumptions and model judgements separately.
|
|
41
|
+
6. Return exactly one recommendation or `no_safe_recommendation`.
|
|
42
|
+
7. Run canonical AGDF gate-check after search. Never translate a recommendation into permission.
|
|
43
|
+
|
|
44
|
+
## Enforcement
|
|
45
|
+
|
|
46
|
+
Report exactly one:
|
|
47
|
+
|
|
48
|
+
- `full`: trusted lifecycle controls prevent writes
|
|
49
|
+
- `tool_enforced`: the evaluator receives read/evaluation tools only
|
|
50
|
+
- `instruction_only`: write prevention is instructional and not technically proven
|
|
51
|
+
|
|
52
|
+
Do not overstate the surface's guarantee.
|
|
53
|
+
|
|
54
|
+
## Output
|
|
55
|
+
|
|
56
|
+
Keep chat output compact:
|
|
57
|
+
|
|
58
|
+
- recommendation or `no_safe_recommendation`
|
|
59
|
+
- current gate
|
|
60
|
+
- enforcement level
|
|
61
|
+
- decisive evidence and assumptions
|
|
62
|
+
- rejected alternatives and reasons
|
|
63
|
+
- budgets and stopping reason
|
|
64
|
+
- next AGDF gate action
|
|
65
|
+
|
|
66
|
+
Persist only the redacted decision summary when durable evidence is required. Do not persist raw prompts, hidden reasoning, secrets or source snapshots.
|
|
67
|
+
|
|
68
|
+
## Boundaries
|
|
69
|
+
|
|
70
|
+
- This is bounded Delivery Path Search, not MCTS.
|
|
71
|
+
- Do not modify repository files during search.
|
|
72
|
+
- Do not execute evaluator-returned commands.
|
|
73
|
+
- Do not invent default scores for invalid evaluator output.
|
|
74
|
+
- Do not implement, approve or release based on search output.
|
|
75
|
+
- Do not create agent-specific scoring, gate logic or skill copies.
|
|
@@ -44,6 +44,8 @@ Use the Runtime Contract definition of `Relevant Run` to decide whether OR is ma
|
|
|
44
44
|
10. `CD+Tests` is not completion.
|
|
45
45
|
11. When moving a backlog item to Completed or Superseded, use the canonical human-readable table and link the final OR with a document-relative Markdown link.
|
|
46
46
|
12. Keep machine status normalization in the CLI; do not write internal snake_case status values into the human-facing backlog.
|
|
47
|
+
13. Reconcile Context Graph impact before clean closeout: report `context_graph_reconciliation: resolved | not_applicable | open_gap`.
|
|
48
|
+
14. If Context Graph work remains unresolved, report it as an explicit open gap and do not describe the run as cleanly handoff-ready.
|
|
47
49
|
|
|
48
50
|
## When To Use
|
|
49
51
|
- at the end of every relevant run
|
|
@@ -89,10 +91,11 @@ If information is missing, state the gap instead of guessing.
|
|
|
89
91
|
6. Summarize Brownfield fit and solution integrity if reviewed.
|
|
90
92
|
7. Summarize tests and verification.
|
|
91
93
|
8. Summarize documentation and Context Graph impact if relevant.
|
|
92
|
-
9.
|
|
93
|
-
10.
|
|
94
|
-
11. Set exactly one
|
|
95
|
-
12.
|
|
94
|
+
9. Record Context Graph reconciliation as `resolved`, `not_applicable`, or `open_gap`.
|
|
95
|
+
10. Name retained fallbacks and exit criteria.
|
|
96
|
+
11. Set exactly one next permissible step.
|
|
97
|
+
12. Set exactly one quality outlook.
|
|
98
|
+
13. State whether `agdf-delivery-closeout` is the next operational handoff step when code changes exist and the delivery state allows it.
|
|
96
99
|
|
|
97
100
|
## Output
|
|
98
101
|
Use a compact structure:
|
|
@@ -114,6 +117,7 @@ Use a compact structure:
|
|
|
114
117
|
```
|
|
115
118
|
|
|
116
119
|
When Context Graph impact is relevant, include the fields from `../agdf-runtime-contract.md`.
|
|
120
|
+
Include `context_graph_reconciliation` whenever Context Graph impact is present. If the value is `open_gap`, required next step must resolve or explicitly retain that gap before commit-ready or release-ready handoff.
|
|
117
121
|
|
|
118
122
|
## Forbidden
|
|
119
123
|
This skill must not:
|