create-agdf 0.4.0 → 0.4.1
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 +16 -0
- package/bin/create-agdf.js +162 -5
- package/generated/.github/copilot-instructions.md +1 -0
- package/generated/.opencode/AGDF.md +1 -0
- package/generated/.opencode/README.md +2 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/opencode-plugin.js +17 -5
- package/package.json +1 -1
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,8 @@ 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
|
+
|
|
136
152
|
`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
153
|
|
|
138
154
|
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
|
@@ -13,7 +13,9 @@ const generatedRoot = join(packageRoot, "generated");
|
|
|
13
13
|
const pluginDefinitionPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-plugin.definition.json");
|
|
14
14
|
const pluginDefinition = JSON.parse(readFileSync(pluginDefinitionPath, "utf8"));
|
|
15
15
|
const pluginInstallCommand = "npx --yes @agdf/cli@latest claude";
|
|
16
|
-
const
|
|
16
|
+
const npmCommand = process.platform === "win32" ? process.execPath : "npm";
|
|
17
|
+
const npmPrefixArgs = process.platform === "win32" ? [join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js")] : [];
|
|
18
|
+
const allowedTargets = new Set(["codex", "codex-repo", "claude", "copilot", "opencode", "opencode-status", "opencode-repo", "both", "init", "config", "doctor", "gate-check", "delivery-map"]);
|
|
17
19
|
const agdfFragmentPath = "AGENTS.agdf.md";
|
|
18
20
|
const openCodeConfigFragmentPath = "opencode.agdf.json";
|
|
19
21
|
const userGateOrder = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
|
|
@@ -161,6 +163,7 @@ Preferred AGDF CLI:
|
|
|
161
163
|
npx --yes @agdf/cli@latest codex-repo
|
|
162
164
|
npx --yes @agdf/cli@latest claude
|
|
163
165
|
npx --yes @agdf/cli@latest opencode
|
|
166
|
+
npx --yes @agdf/cli@latest opencode-status
|
|
164
167
|
npx --yes @agdf/cli@latest opencode-repo
|
|
165
168
|
npx --yes @agdf/cli@latest init
|
|
166
169
|
npx --yes @agdf/cli@latest doctor
|
|
@@ -172,6 +175,7 @@ Scaffold-compatible npm create usage:
|
|
|
172
175
|
npm create agdf@latest -- claude
|
|
173
176
|
npm create agdf@latest -- copilot
|
|
174
177
|
npm create agdf@latest -- opencode
|
|
178
|
+
npm create agdf@latest -- opencode-status
|
|
175
179
|
npm create agdf@latest -- opencode-repo
|
|
176
180
|
npm create agdf@latest -- both
|
|
177
181
|
npm create agdf@latest -- init
|
|
@@ -191,6 +195,7 @@ Options:
|
|
|
191
195
|
Set AGDF chat and artefact language. Defaults to detected system locale.
|
|
192
196
|
--lang <de|en> Alias for --language
|
|
193
197
|
--json Print doctor, gate-check or delivery-map output as JSON
|
|
198
|
+
--status-card Print compact gate-check status-card output for interactive use
|
|
194
199
|
--help Show this help
|
|
195
200
|
`);
|
|
196
201
|
}
|
|
@@ -252,6 +257,7 @@ function parseArgs(argv) {
|
|
|
252
257
|
let dir = ".";
|
|
253
258
|
let force = false;
|
|
254
259
|
let json = false;
|
|
260
|
+
let statusCard = false;
|
|
255
261
|
let language;
|
|
256
262
|
let dirExplicit = false;
|
|
257
263
|
|
|
@@ -274,6 +280,11 @@ function parseArgs(argv) {
|
|
|
274
280
|
continue;
|
|
275
281
|
}
|
|
276
282
|
|
|
283
|
+
if (arg === "--status-card") {
|
|
284
|
+
statusCard = true;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
|
|
277
288
|
if (arg === "--language" || arg === "--lang") {
|
|
278
289
|
const next = args[i + 1];
|
|
279
290
|
if (!next) {
|
|
@@ -323,7 +334,7 @@ function parseArgs(argv) {
|
|
|
323
334
|
}
|
|
324
335
|
|
|
325
336
|
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-map.");
|
|
337
|
+
console.error("Please choose one target: codex, codex-repo, claude, copilot, opencode, opencode-status, opencode-repo, both, init, config, doctor, gate-check or delivery-map.");
|
|
327
338
|
printUsage();
|
|
328
339
|
process.exit(1);
|
|
329
340
|
}
|
|
@@ -333,6 +344,7 @@ function parseArgs(argv) {
|
|
|
333
344
|
dir: resolve(process.cwd(), dir),
|
|
334
345
|
force,
|
|
335
346
|
json,
|
|
347
|
+
statusCard,
|
|
336
348
|
dirExplicit,
|
|
337
349
|
language: resolveLanguagePreference(language),
|
|
338
350
|
};
|
|
@@ -371,6 +383,11 @@ function installOpenCodeGlobalPlugin(configDir) {
|
|
|
371
383
|
};
|
|
372
384
|
|
|
373
385
|
mkdirSync(configDir, { recursive: true });
|
|
386
|
+
try {
|
|
387
|
+
execFileSync(npmCommand, [...npmPrefixArgs, "install", "--silent", "--save-prod", "--prefix", configDir, packageRoot], { stdio: "pipe" });
|
|
388
|
+
} catch (error) {
|
|
389
|
+
throw new Error(`Failed to install ${pluginDefinition.opencode.npmPackage} into the OpenCode config directory: ${(error.stderr || error.message).toString().trim()}`);
|
|
390
|
+
}
|
|
374
391
|
writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
|
|
375
392
|
|
|
376
393
|
return {
|
|
@@ -379,6 +396,119 @@ function installOpenCodeGlobalPlugin(configDir) {
|
|
|
379
396
|
};
|
|
380
397
|
}
|
|
381
398
|
|
|
399
|
+
function readOpenCodeConfig(configPath) {
|
|
400
|
+
if (!existsSync(configPath)) return { exists: false, parseError: "", config: {} };
|
|
401
|
+
try {
|
|
402
|
+
return { exists: true, parseError: "", config: JSON.parse(readFileSync(configPath, "utf8")) };
|
|
403
|
+
} catch (error) {
|
|
404
|
+
return { exists: true, parseError: error.message, config: {} };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function isOpenCodeRepositorySurfacePresent(targetDir) {
|
|
409
|
+
return existsSync(join(targetDir, ".opencode", pluginDefinition.opencode.instructionsFileName))
|
|
410
|
+
&& existsSync(join(targetDir, ".opencode", "agents", `${pluginDefinition.opencode.skillPrefix}gate-check.md`));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function resolveOpenCodePackage(configDir) {
|
|
414
|
+
const packageName = pluginDefinition.opencode.npmPackage;
|
|
415
|
+
try {
|
|
416
|
+
return {
|
|
417
|
+
loadable: true,
|
|
418
|
+
path: execFileSync(process.execPath, ["-e", `process.stdout.write(require.resolve(${JSON.stringify(packageName)}))`], {
|
|
419
|
+
cwd: configDir,
|
|
420
|
+
encoding: "utf8",
|
|
421
|
+
stdio: "pipe",
|
|
422
|
+
}),
|
|
423
|
+
error: "",
|
|
424
|
+
};
|
|
425
|
+
} catch (error) {
|
|
426
|
+
return {
|
|
427
|
+
loadable: false,
|
|
428
|
+
path: "",
|
|
429
|
+
error: (error.stderr || error.message || "package not resolvable").toString().trim(),
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir()) {
|
|
435
|
+
const configPath = join(configDir, "opencode.json");
|
|
436
|
+
const configState = readOpenCodeConfig(configPath);
|
|
437
|
+
const plugins = Array.isArray(configState.config.plugin) ? configState.config.plugin : [];
|
|
438
|
+
const globalConfigured = plugins.includes(pluginDefinition.opencode.npmPackage);
|
|
439
|
+
const packageState = resolveOpenCodePackage(configDir);
|
|
440
|
+
const sessionSignals = {
|
|
441
|
+
active: process.env.AGDF_PLUGIN_ACTIVE === "1",
|
|
442
|
+
version: process.env.AGDF_PLUGIN_VERSION || "",
|
|
443
|
+
control_dir: process.env.AGDF_CONTROL_DIR || "",
|
|
444
|
+
repository_surface: process.env.AGDF_OPENCODE_REPOSITORY_SURFACE === "1",
|
|
445
|
+
};
|
|
446
|
+
const repositorySurface = isOpenCodeRepositorySurfacePresent(targetDir);
|
|
447
|
+
|
|
448
|
+
const findings = [];
|
|
449
|
+
if (!configState.exists) findings.push("OpenCode global config not found.");
|
|
450
|
+
if (configState.parseError) findings.push(`OpenCode global config is not valid JSON: ${configState.parseError}`);
|
|
451
|
+
if (!globalConfigured) findings.push(`OpenCode global config does not include ${pluginDefinition.opencode.npmPackage}.`);
|
|
452
|
+
if (!packageState.loadable) findings.push(`${pluginDefinition.opencode.npmPackage} is not loadable from the OpenCode config directory.`);
|
|
453
|
+
if (!sessionSignals.active) findings.push("No active AGDF OpenCode session signal is visible in this process.");
|
|
454
|
+
if (!repositorySurface) findings.push("Current repository does not contain the AGDF OpenCode surface.");
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
schema_version: "1",
|
|
458
|
+
status: globalConfigured && packageState.loadable ? "configured" : "not_configured",
|
|
459
|
+
global_config: {
|
|
460
|
+
path: configPath,
|
|
461
|
+
exists: configState.exists,
|
|
462
|
+
parse_error: configState.parseError,
|
|
463
|
+
plugin_configured: globalConfigured,
|
|
464
|
+
},
|
|
465
|
+
package: {
|
|
466
|
+
name: pluginDefinition.opencode.npmPackage,
|
|
467
|
+
loadable: packageState.loadable,
|
|
468
|
+
resolved_path: packageState.path,
|
|
469
|
+
error: packageState.error,
|
|
470
|
+
},
|
|
471
|
+
session: sessionSignals,
|
|
472
|
+
repository_surface: {
|
|
473
|
+
path: targetDir,
|
|
474
|
+
present: repositorySurface,
|
|
475
|
+
instructions: join(targetDir, ".opencode", pluginDefinition.opencode.instructionsFileName),
|
|
476
|
+
gate_check_agent: join(targetDir, ".opencode", "agents", `${pluginDefinition.opencode.skillPrefix}gate-check.md`),
|
|
477
|
+
},
|
|
478
|
+
visible_entrypoint: repositorySurface ? `@${pluginDefinition.opencode.skillPrefix}gate-check` : "none until opencode-repo is installed for this repository",
|
|
479
|
+
findings,
|
|
480
|
+
next_step: repositorySurface
|
|
481
|
+
? `Restart OpenCode if needed, then use @${pluginDefinition.opencode.skillPrefix}gate-check for new build/change intent.`
|
|
482
|
+
: "Run npx --yes @agdf/cli@latest opencode-repo in repositories where AGDF governance should be active and reviewable.",
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function printOpenCodeStatus(report, json) {
|
|
487
|
+
if (json) {
|
|
488
|
+
console.log(JSON.stringify(report, null, 2));
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
console.log("AGDF OpenCode status");
|
|
493
|
+
console.log(`Status: ${report.status}`);
|
|
494
|
+
console.log(`Global config: ${report.global_config.plugin_configured ? "configured" : "missing"} (${report.global_config.path})`);
|
|
495
|
+
if (report.global_config.parse_error) console.log(`Config parse error: ${report.global_config.parse_error}`);
|
|
496
|
+
console.log(`Package loadable: ${report.package.loadable ? "yes" : "no"}`);
|
|
497
|
+
if (report.package.resolved_path) console.log(`Package path: ${report.package.resolved_path}`);
|
|
498
|
+
console.log(`Session active signal: ${report.session.active ? "yes" : "no"}`);
|
|
499
|
+
if (report.session.version) console.log(`Session plugin version: ${report.session.version}`);
|
|
500
|
+
if (report.session.control_dir) console.log(`Session control dir: ${report.session.control_dir}`);
|
|
501
|
+
console.log(`Repository surface: ${report.repository_surface.present ? "present" : "missing"}`);
|
|
502
|
+
console.log(`Visible entrypoint: ${report.visible_entrypoint}`);
|
|
503
|
+
console.log(`Next step: ${report.next_step}`);
|
|
504
|
+
|
|
505
|
+
if (report.findings.length > 0) {
|
|
506
|
+
console.log("");
|
|
507
|
+
console.log("Findings:");
|
|
508
|
+
for (const finding of report.findings) console.log(`- ${finding}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
382
512
|
function installCodexGlobalPlugin() {
|
|
383
513
|
try {
|
|
384
514
|
execFileSync("codex", ["plugin", "marketplace", "add", "arndtgold/ai-native-governance-delivery-framework"], { stdio: "inherit" });
|
|
@@ -1703,12 +1833,30 @@ function evaluateGateCheck(targetDir) {
|
|
|
1703
1833
|
};
|
|
1704
1834
|
}
|
|
1705
1835
|
|
|
1706
|
-
function
|
|
1836
|
+
function printGateCheckStatusCard(report) {
|
|
1837
|
+
const card = report.status_card;
|
|
1838
|
+
console.log(`AGDF status-card: ${card.status}`);
|
|
1839
|
+
console.log(`Current gate: ${card.current_gate}`);
|
|
1840
|
+
console.log(`Blocked by: ${card.blocking_condition}`);
|
|
1841
|
+
console.log(`Missing approval: ${card.missing_approval}`);
|
|
1842
|
+
console.log(`Next skill: ${card.next_skill}`);
|
|
1843
|
+
console.log(`Next step: ${card.next_step}`);
|
|
1844
|
+
console.log(`Quality outlook: ${card.quality_outlook}`);
|
|
1845
|
+
if (card.allowed_now.length > 0) console.log(`Allowed now: ${card.allowed_now.join("; ")}`);
|
|
1846
|
+
if (card.forbidden_now.length > 0) console.log(`Forbidden now: ${card.forbidden_now.join("; ")}`);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
function printGateCheckReport(report, json, statusCard = false) {
|
|
1707
1850
|
if (json) {
|
|
1708
1851
|
console.log(JSON.stringify(report, null, 2));
|
|
1709
1852
|
return;
|
|
1710
1853
|
}
|
|
1711
1854
|
|
|
1855
|
+
if (statusCard) {
|
|
1856
|
+
printGateCheckStatusCard(report);
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1712
1860
|
console.log(`AGDF gate-check: ${report.status}`);
|
|
1713
1861
|
console.log(`Current gate: ${report.current_gate}`);
|
|
1714
1862
|
console.log(`Blocking reason: ${report.blocking_reason}`);
|
|
@@ -1819,7 +1967,7 @@ function main() {
|
|
|
1819
1967
|
|
|
1820
1968
|
if (options.target === "gate-check") {
|
|
1821
1969
|
const report = evaluateGateCheck(options.dir);
|
|
1822
|
-
printGateCheckReport(report, options.json);
|
|
1970
|
+
printGateCheckReport(report, options.json, options.statusCard);
|
|
1823
1971
|
process.exit(report.status === "blocked" ? 2 : 0);
|
|
1824
1972
|
}
|
|
1825
1973
|
|
|
@@ -1829,6 +1977,13 @@ function main() {
|
|
|
1829
1977
|
process.exit(report.status === "block" ? 2 : 0);
|
|
1830
1978
|
}
|
|
1831
1979
|
|
|
1980
|
+
if (options.target === "opencode-status") {
|
|
1981
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir();
|
|
1982
|
+
const report = evaluateOpenCodeStatus(options.dir, configDir);
|
|
1983
|
+
printOpenCodeStatus(report, options.json);
|
|
1984
|
+
process.exit(report.status === "configured" ? 0 : 1);
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1832
1987
|
if (options.target === "codex") {
|
|
1833
1988
|
try {
|
|
1834
1989
|
installCodexGlobalPlugin();
|
|
@@ -1857,7 +2012,9 @@ function main() {
|
|
|
1857
2012
|
try {
|
|
1858
2013
|
const result = installOpenCodeGlobalPlugin(configDir);
|
|
1859
2014
|
console.log(`AGDF OpenCode global plugin ${result.added ? "installed" : "already present"}: ${result.configPath}`);
|
|
1860
|
-
|
|
2015
|
+
const report = evaluateOpenCodeStatus(options.dir, configDir);
|
|
2016
|
+
printOpenCodeStatus(report, false);
|
|
2017
|
+
console.log("Restart OpenCode so it loads the updated global plugin config.");
|
|
1861
2018
|
} catch (error) {
|
|
1862
2019
|
console.error(error.message);
|
|
1863
2020
|
process.exit(1);
|
|
@@ -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.
|
|
@@ -105,6 +105,7 @@ For relevant runs that change durable state, code, artefacts or gate status:
|
|
|
105
105
|
- The generated AGDF agents are `mode: subagent` workflow controls for internal routing. They are not OpenCode Skills under `.opencode/skills/` and are not intended to appear as primary menu agents.
|
|
106
106
|
- The visible user entry point is repository instruction loading plus direct subagent handoff, for example `@agdf-gate-check` for new build/change intent or unclear approval.
|
|
107
107
|
- The AGDF OpenCode plugin is loaded from npm through `opencode.json` `plugin: ["create-agdf"]`.
|
|
108
|
+
- Use `npx --yes @agdf/cli@latest opencode-status --json` to verify global config, package loadability, active session signals and repository surface presence separately.
|
|
108
109
|
- OpenCode permissions keep `edit` and `bash` on explicit approval by default.
|
|
109
110
|
- Shared output and gate rules live in `.opencode/agdf-runtime-contract.md`.
|
|
110
111
|
- 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.
|
|
@@ -9,6 +9,8 @@ These files were generated from the AGDF source repository for OpenCode.
|
|
|
9
9
|
- `.opencode/agents/` contains AGDF subagents generated from the canonical AGDF skills.
|
|
10
10
|
- These files intentionally do not install OpenCode Skills under `.opencode/skills/`; the AGDF agents are background workflow controls, not primary menu agents.
|
|
11
11
|
- Use `@agdf-gate-check` as the visible entry point for new build/change intent or unclear approval.
|
|
12
|
+
- Use `npx --yes @agdf/cli@latest opencode-status --json` to distinguish global hook configuration, package loadability, session activity and this repository surface.
|
|
13
|
+
- Use `npx --yes @agdf/cli@latest gate-check --status-card` for compact interactive gate state; reserve full `--json` output for automation or audit evidence.
|
|
12
14
|
- `.opencode/agdf-runtime-contract.md` is the shared gate and output contract.
|
|
13
15
|
|
|
14
16
|
## Agents
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.1",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "AI-native Governance & Delivery Framework",
|
|
7
7
|
"description": "Codex-first workflow skills for gated, auditable AI-assisted software delivery.",
|
package/opencode-plugin.js
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
const packageJson = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
|
|
2
4
|
|
|
3
5
|
export const AGDFPlugin = async ({ directory, client }) => {
|
|
4
6
|
const controlDir = `${directory}/.agdf/control`;
|
|
5
7
|
const hasRepositorySurface = () => existsSync(`${directory}/.opencode/AGDF.md`) && existsSync(`${directory}/.opencode/agents`);
|
|
8
|
+
const status = () => ({
|
|
9
|
+
active: true,
|
|
10
|
+
version: packageJson.version,
|
|
11
|
+
controlDir,
|
|
12
|
+
repositorySurface: hasRepositorySurface(),
|
|
13
|
+
});
|
|
6
14
|
|
|
7
15
|
return {
|
|
8
16
|
event: async ({ event }) => {
|
|
9
17
|
if (event?.type === "session.created") {
|
|
10
|
-
const
|
|
18
|
+
const currentStatus = status();
|
|
11
19
|
await client.app.log({
|
|
12
20
|
body: {
|
|
13
21
|
service: "agdf",
|
|
14
22
|
level: "info",
|
|
15
|
-
message: repositorySurface ? "AGDF OpenCode
|
|
16
|
-
extra:
|
|
23
|
+
message: currentStatus.repositorySurface ? "AGDF OpenCode active" : "AGDF OpenCode global hook active without repository surface",
|
|
24
|
+
extra: currentStatus,
|
|
17
25
|
},
|
|
18
26
|
});
|
|
19
27
|
}
|
|
20
28
|
},
|
|
21
29
|
|
|
22
30
|
"shell.env": async (_input, output) => {
|
|
31
|
+
const currentStatus = status();
|
|
32
|
+
output.env.AGDF_PLUGIN_ACTIVE = "1";
|
|
33
|
+
output.env.AGDF_PLUGIN_VERSION = currentStatus.version;
|
|
23
34
|
output.env.AGDF_CONTROL_DIR = controlDir;
|
|
35
|
+
output.env.AGDF_OPENCODE_REPOSITORY_SURFACE = currentStatus.repositorySurface ? "1" : "0";
|
|
24
36
|
},
|
|
25
37
|
|
|
26
38
|
"experimental.session.compacting": async (_input, output) => {
|
|
@@ -38,7 +50,7 @@ export const AGDFPlugin = async ({ directory, client }) => {
|
|
|
38
50
|
"## AGDF Runtime Reminder",
|
|
39
51
|
"Use `.opencode/AGDF.md`, `.opencode/agents/` and `.agdf/control/` as the AGDF source for this OpenCode session.",
|
|
40
52
|
"For new build/change intent or unclear approval, route first to `agdf-gate-check` before later artefacts or implementation.",
|
|
41
|
-
"Use `npx --yes @agdf/cli@latest gate-check --json` only as deterministic proof,
|
|
53
|
+
"Use `npx --yes @agdf/cli@latest gate-check --status-card` for compact interactive status. Use `--json` only as deterministic proof for automation or audit evidence, and summarize it instead of mirroring full JSON into chat.",
|
|
42
54
|
].join("\n"));
|
|
43
55
|
},
|
|
44
56
|
};
|
package/package.json
CHANGED