create-agdf 0.3.5 → 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 CHANGED
@@ -8,10 +8,15 @@ Preferred long-term CLI shape:
8
8
 
9
9
  ```bash
10
10
  npx --yes @agdf/cli@latest codex
11
+ npx --yes @agdf/cli@latest codex-repo
12
+ npx --yes @agdf/cli@latest claude
11
13
  npx --yes @agdf/cli@latest opencode
14
+ npx --yes @agdf/cli@latest opencode-status
15
+ npx --yes @agdf/cli@latest opencode-repo
12
16
  npx --yes @agdf/cli@latest init
13
17
  npx --yes @agdf/cli@latest config --language en
14
18
  npx --yes @agdf/cli@latest doctor
19
+ npx --yes @agdf/cli@latest gate-check --status-card
15
20
  npx --yes @agdf/cli@latest gate-check --json
16
21
  ```
17
22
 
@@ -19,8 +24,12 @@ Backward-compatible scaffold usage:
19
24
 
20
25
  ```bash
21
26
  npm create agdf@latest -- codex
27
+ npm create agdf@latest -- codex-repo
28
+ npm create agdf@latest -- claude
22
29
  npm create agdf@latest -- copilot
23
30
  npm create agdf@latest -- opencode
31
+ npm create agdf@latest -- opencode-status
32
+ npm create agdf@latest -- opencode-repo
24
33
  npm create agdf@latest -- both
25
34
  npm create agdf@latest -- init
26
35
  npm create agdf@latest -- config --language en
@@ -38,27 +47,46 @@ If no language is provided, `create-agdf` derives the preference from the local
38
47
 
39
48
  ## Targets and existing AGENTS.md
40
49
 
41
- - `codex` writes a repository-local Codex marketplace under `.agents/plugins/` and a local AGDF plugin copy under `plugins/agdf/`
50
+ - `codex` installs the AGDF plugin globally for Codex
51
+ - `codex-repo` writes a repository-local Codex marketplace under `.agents/plugins/` and a local AGDF plugin copy under `plugins/agdf/`
52
+ - `claude` installs the AGDF plugin globally for Claude Code
42
53
  - `copilot` writes `AGENTS.md`, Copilot custom instructions under `.github/`, visible repository skills under `.github/skills/`, and AGDF control templates under `.agdf/control/`
43
- - `opencode` writes `opencode.json`, `.opencode/AGDF.md`, prefixed OpenCode agents under `.opencode/agents/`, explicit edit/bash permissions, and AGDF control templates under `.agdf/control/`
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
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/`
44
57
  - `both` writes the Codex repository-local marketplace plus the Copilot-facing repository files
45
58
  - `config` writes or updates only `.agdf/control/config.json` for an already installed plugin or an existing repository
46
59
 
47
60
  If the target repository already has an `AGENTS.md`, `create-agdf` preserves it and writes `AGENTS.agdf.md` instead of replacing your existing instructions. Merge the AGDF fragment into your current `AGENTS.md` when you want Copilot to load both instruction sets. The generated `.github/copilot-instructions.md` keeps Copilot pointed at `AGENTS.md`, `.github/skills/` and `.agdf/control/` without duplicating the full AGDF rule model. Use `--force` only when you explicitly want to overwrite generated files.
48
61
 
49
- Use the `codex` target when AGDF should be available only inside one repository instead of being installed as a personal/global Codex plugin.
62
+ Use the `codex-repo` target when AGDF should be available only inside one repository instead of being installed as a personal/global Codex plugin.
50
63
 
51
- After `npm create agdf@latest -- codex`, restart Codex in that repository, open `/plugins`, select `This repository` and install `agdf`.
64
+ After `npm create agdf@latest -- codex-repo`, restart Codex in that repository, open `/plugins`, select `This repository` and install `agdf`.
52
65
 
53
- Use the `opencode` target when AGDF should be available to OpenCode from repository files:
66
+ Use the `opencode` target to install the AGDF npm plugin as a user-wide OpenCode hook:
54
67
 
55
68
  ```bash
56
- npm create agdf@latest -- opencode
69
+ npx --yes @agdf/cli@latest opencode
57
70
  ```
58
71
 
59
- OpenCode loads the AGDF npm plugin from `opencode.json`, AGENTS-style rules from `.opencode/AGDF.md`, explicit `edit`/`bash` permissions and the `agdf-` prefixed agents under `.opencode/agents/`.
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
+
80
+ Use the `opencode-repo` target when AGDF should be available to OpenCode from repository files:
81
+
82
+ ```bash
83
+ npm create agdf@latest -- opencode-repo
84
+ ```
85
+
86
+ OpenCode loads the AGDF npm plugin from global OpenCode config or repository `opencode.json`, AGENTS-style rules from `.opencode/AGDF.md`, explicit `edit`/`bash` permissions and the `agdf-` prefixed agents under `.opencode/agents/`. AGDF for OpenCode has two layers: a global npm plugin hook installed with `npx --yes @agdf/cli@latest opencode` and a repository-local governance surface generated by the `opencode-repo` target.
87
+ Those generated agents use `mode: subagent` intentionally: they are internal governance-routing controls, not OpenCode Skills under `.opencode/skills/` and not primary menu agents. Use `@agdf-gate-check` as the visible entry point for new build/change intent or unclear approval.
60
88
  If `opencode.json` already exists, AGDF keeps it unchanged and writes `opencode.agdf.json` as a merge fragment.
61
- Using OpenCode's plugin installer for `create-agdf` can add the npm plugin entry, but AGDF still needs the repository instructions and agents. The `opencode` target writes the npm plugin entry and the repository files together.
89
+ Using OpenCode's plugin installer or global config for `create-agdf` can add the npm plugin hook, but AGDF still needs the repository instructions and agents. The `opencode-repo` target writes the repository files together.
62
90
 
63
91
  ## Control scaffold
64
92
 
@@ -93,6 +121,8 @@ This writes:
93
121
 
94
122
  `config.json` stores `artifact_language` and `chat_language` for governed work in the target repository. Runtime rules stay English so all AGDF surfaces share the same control contract.
95
123
 
124
+ For a normal fresh request, `init` is not the required first move. The agent-native path can draft the minimal UR in the response and ask for the exact approval text `Approval: UR`. Write or initialize `.agdf/control` only when durable repository-owned control state is explicitly wanted, already in use, or needed for deterministic setup/CI evidence. Before Brownfield Review, later gates or implementation, AGDF still requires the persisted or linked artefacts named by the Runtime Contract.
125
+
96
126
  For an existing repository where the plugin is already installed and only the language preference is missing or wrong, use the lighter config target:
97
127
 
98
128
  ```bash
@@ -117,9 +147,11 @@ npx --yes create-agdf@latest gate-check --json
117
147
 
118
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.
119
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
+
120
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.
121
153
 
122
- 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, the agent-native path can stay lighter: draft the minimal UR in the response, request `Approval: UR`, and use CLI validators only when machine-readable proof is useful.
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.
123
155
 
124
156
  ## Single source of truth
125
157
 
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { execFileSync } from "node:child_process";
5
+ import { homedir } from "node:os";
4
6
  import { dirname, join, posix, resolve } from "node:path";
5
7
  import { fileURLToPath } from "node:url";
6
8
  import process from "node:process";
@@ -10,8 +12,10 @@ const packageRoot = resolve(__dirname, "..");
10
12
  const generatedRoot = join(packageRoot, "generated");
11
13
  const pluginDefinitionPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-plugin.definition.json");
12
14
  const pluginDefinition = JSON.parse(readFileSync(pluginDefinitionPath, "utf8"));
13
- const pluginInstallCommand = "claude plugin add arndtgold/ai-native-governance-delivery-framework";
14
- const allowedTargets = new Set(["codex", "copilot", "opencode", "both", "init", "config", "doctor", "gate-check", "delivery-map"]);
15
+ const pluginInstallCommand = "npx --yes @agdf/cli@latest claude";
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"]);
15
19
  const agdfFragmentPath = "AGENTS.agdf.md";
16
20
  const openCodeConfigFragmentPath = "opencode.agdf.json";
17
21
  const userGateOrder = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
@@ -156,15 +160,23 @@ function printUsage() {
156
160
 
157
161
  Preferred AGDF CLI:
158
162
  npx --yes @agdf/cli@latest codex
163
+ npx --yes @agdf/cli@latest codex-repo
164
+ npx --yes @agdf/cli@latest claude
159
165
  npx --yes @agdf/cli@latest opencode
166
+ npx --yes @agdf/cli@latest opencode-status
167
+ npx --yes @agdf/cli@latest opencode-repo
160
168
  npx --yes @agdf/cli@latest init
161
169
  npx --yes @agdf/cli@latest doctor
162
170
  npx --yes @agdf/cli@latest gate-check --json
163
171
 
164
172
  Scaffold-compatible npm create usage:
165
173
  npm create agdf@latest -- codex
174
+ npm create agdf@latest -- codex-repo
175
+ npm create agdf@latest -- claude
166
176
  npm create agdf@latest -- copilot
167
177
  npm create agdf@latest -- opencode
178
+ npm create agdf@latest -- opencode-status
179
+ npm create agdf@latest -- opencode-repo
168
180
  npm create agdf@latest -- both
169
181
  npm create agdf@latest -- init
170
182
  npm create agdf@latest -- config --language de
@@ -177,12 +189,13 @@ Backward-compatible create-agdf usage:
177
189
  npx --yes create-agdf@latest gate-check --json
178
190
 
179
191
  Options:
180
- --dir <path> Write files into a specific directory
192
+ --dir <path> Write files into a specific directory. With opencode, use this as the OpenCode config directory.
181
193
  --force Overwrite existing generated files
182
194
  --language <de|en>
183
195
  Set AGDF chat and artefact language. Defaults to detected system locale.
184
196
  --lang <de|en> Alias for --language
185
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
186
199
  --help Show this help
187
200
  `);
188
201
  }
@@ -244,7 +257,9 @@ function parseArgs(argv) {
244
257
  let dir = ".";
245
258
  let force = false;
246
259
  let json = false;
260
+ let statusCard = false;
247
261
  let language;
262
+ let dirExplicit = false;
248
263
 
249
264
  for (let i = 0; i < args.length; i += 1) {
250
265
  const arg = args[i];
@@ -265,6 +280,11 @@ function parseArgs(argv) {
265
280
  continue;
266
281
  }
267
282
 
283
+ if (arg === "--status-card") {
284
+ statusCard = true;
285
+ continue;
286
+ }
287
+
268
288
  if (arg === "--language" || arg === "--lang") {
269
289
  const next = args[i + 1];
270
290
  if (!next) {
@@ -288,6 +308,7 @@ function parseArgs(argv) {
288
308
  process.exit(1);
289
309
  }
290
310
  dir = next;
311
+ dirExplicit = true;
291
312
  i += 1;
292
313
  continue;
293
314
  }
@@ -313,7 +334,7 @@ function parseArgs(argv) {
313
334
  }
314
335
 
315
336
  if (!target || !allowedTargets.has(target)) {
316
- console.error("Please choose one target: codex, copilot, opencode, 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.");
317
338
  printUsage();
318
339
  process.exit(1);
319
340
  }
@@ -323,10 +344,188 @@ function parseArgs(argv) {
323
344
  dir: resolve(process.cwd(), dir),
324
345
  force,
325
346
  json,
347
+ statusCard,
348
+ dirExplicit,
326
349
  language: resolveLanguagePreference(language),
327
350
  };
328
351
  }
329
352
 
353
+ function defaultOpenCodeConfigDir() {
354
+ return process.env.OPENCODE_CONFIG_DIR || join(homedir(), ".config", "opencode");
355
+ }
356
+
357
+ function installOpenCodeGlobalPlugin(configDir) {
358
+ const configPath = join(configDir, "opencode.json");
359
+ let config = {};
360
+
361
+ if (existsSync(configPath)) {
362
+ try {
363
+ config = JSON.parse(readFileSync(configPath, "utf8"));
364
+ } catch {
365
+ throw new Error(`Refusing to update unreadable OpenCode config: ${configPath}`);
366
+ }
367
+ }
368
+
369
+ if (config.plugin !== undefined && !Array.isArray(config.plugin)) {
370
+ throw new Error(`Refusing to update OpenCode config with non-array plugin field: ${configPath}`);
371
+ }
372
+
373
+ const plugins = [...(config.plugin ?? [])];
374
+ const alreadyInstalled = plugins.includes(pluginDefinition.opencode.npmPackage);
375
+ if (!alreadyInstalled) {
376
+ plugins.push(pluginDefinition.opencode.npmPackage);
377
+ }
378
+
379
+ const nextConfig = {
380
+ "$schema": config.$schema ?? "https://opencode.ai/config.json",
381
+ ...config,
382
+ plugin: plugins,
383
+ };
384
+
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
+ }
391
+ writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
392
+
393
+ return {
394
+ configPath,
395
+ added: !alreadyInstalled,
396
+ };
397
+ }
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
+
512
+ function installCodexGlobalPlugin() {
513
+ try {
514
+ execFileSync("codex", ["plugin", "marketplace", "add", "arndtgold/ai-native-governance-delivery-framework"], { stdio: "inherit" });
515
+ execFileSync("codex", ["plugin", "add", "agdf", "--marketplace", "agdf"], { stdio: "inherit" });
516
+ } catch (error) {
517
+ throw new Error("Failed to install the AGDF Codex plugin. Make sure the Codex CLI is installed and available on PATH, then rerun this command.");
518
+ }
519
+ }
520
+
521
+ function installClaudeGlobalPlugin() {
522
+ try {
523
+ execFileSync("claude", ["plugin", "add", "arndtgold/ai-native-governance-delivery-framework"], { stdio: "inherit" });
524
+ } catch {
525
+ throw new Error("Failed to install the AGDF Claude Code plugin. Make sure the Claude Code CLI is installed and available on PATH, then rerun this command.");
526
+ }
527
+ }
528
+
330
529
  function loadAsset(relativePath) {
331
530
  return readFileSync(join(generatedRoot, relativePath), "utf8");
332
531
  }
@@ -385,7 +584,7 @@ function generatedFilesForTarget(target, targetDir, force, languagePreference) {
385
584
  return files;
386
585
  }
387
586
 
388
- if (target === "codex" || target === "both") {
587
+ if (target === "codex-repo" || target === "both") {
389
588
  addLanguageConfig(files, languagePreference);
390
589
  for (const codexPath of codexPluginFiles) {
391
590
  files.push({
@@ -425,7 +624,7 @@ function generatedFilesForTarget(target, targetDir, force, languagePreference) {
425
624
  }
426
625
  }
427
626
 
428
- if (target === "opencode") {
627
+ if (target === "opencode-repo") {
429
628
  addLanguageConfig(files, languagePreference);
430
629
  const openCodeConfigTargetPath = existsSync(join(targetDir, "opencode.json")) && !force ? openCodeConfigFragmentPath : "opencode.json";
431
630
  files.push({
@@ -481,20 +680,23 @@ function printNextSteps(target, destination, files, wroteAgentsFragment, wroteOp
481
680
  if (wroteAgentsFragment) {
482
681
  console.log(`- Existing AGENTS.md detected. Merge ${agdfFragmentPath} into your current AGENTS.md before using Copilot with AGDF.`);
483
682
  }
484
- if (target === "codex" || target === "both") {
683
+ if (target === "codex-repo" || target === "both") {
485
684
  console.log("- Restart Codex in this repository, open /plugins, select This repository and install agdf.");
486
685
  console.log("- Start a new Codex thread in this repository and ask: Run an AGDF gate check for this request.");
487
686
  }
488
687
  if (target === "both") {
489
688
  console.log(`- Optional global Claude Code install: ${pluginInstallCommand}`);
490
689
  }
491
- if (target === "opencode") {
690
+ if (target === "opencode-repo") {
492
691
  if (wroteOpenCodeConfigFragment) {
493
692
  console.log(`- Existing opencode.json detected. Merge ${openCodeConfigFragmentPath} into your current opencode.json so OpenCode loads .opencode/AGDF.md.`);
494
693
  }
495
694
  console.log(`- OpenCode will install the ${pluginDefinition.opencode.npmPackage} npm plugin from opencode.json at startup.`);
695
+ console.log("- Optional: also add create-agdf to ~/.config/opencode/opencode.json plugin[] for a user-wide OpenCode hook.");
696
+ console.log("- The global hook does not replace repository instructions or subagents; this repository's .opencode files remain the AGDF source of truth.");
496
697
  console.log("- Start OpenCode in this repository; it will load opencode.json, .opencode/AGDF.md and the AGDF subagents.");
497
- console.log("- Use @agdf-gate-check for new build/change intent or unclear approval before later artefacts or implementation.");
698
+ console.log("- AGDF OpenCode agents are mode: subagent workflow controls; they are not .opencode/skills entries or primary menu agents.");
699
+ console.log("- Use @agdf-gate-check as the visible entry point for new build/change intent or unclear approval before later artefacts or implementation.");
498
700
  console.log("- Run npx --yes @agdf/cli@latest init when the repository needs live AGDF control files.");
499
701
  }
500
702
  if (target === "copilot" || target === "both") {
@@ -1631,12 +1833,30 @@ function evaluateGateCheck(targetDir) {
1631
1833
  };
1632
1834
  }
1633
1835
 
1634
- function printGateCheckReport(report, json) {
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) {
1635
1850
  if (json) {
1636
1851
  console.log(JSON.stringify(report, null, 2));
1637
1852
  return;
1638
1853
  }
1639
1854
 
1855
+ if (statusCard) {
1856
+ printGateCheckStatusCard(report);
1857
+ return;
1858
+ }
1859
+
1640
1860
  console.log(`AGDF gate-check: ${report.status}`);
1641
1861
  console.log(`Current gate: ${report.current_gate}`);
1642
1862
  console.log(`Blocking reason: ${report.blocking_reason}`);
@@ -1747,7 +1967,7 @@ function main() {
1747
1967
 
1748
1968
  if (options.target === "gate-check") {
1749
1969
  const report = evaluateGateCheck(options.dir);
1750
- printGateCheckReport(report, options.json);
1970
+ printGateCheckReport(report, options.json, options.statusCard);
1751
1971
  process.exit(report.status === "blocked" ? 2 : 0);
1752
1972
  }
1753
1973
 
@@ -1757,6 +1977,51 @@ function main() {
1757
1977
  process.exit(report.status === "block" ? 2 : 0);
1758
1978
  }
1759
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
+
1987
+ if (options.target === "codex") {
1988
+ try {
1989
+ installCodexGlobalPlugin();
1990
+ console.log("AGDF Codex plugin installed globally.");
1991
+ console.log("Run npx --yes @agdf/cli@latest codex-repo in a repository when you want to test AGDF from repository-local plugin files.");
1992
+ } catch (error) {
1993
+ console.error(error.message);
1994
+ process.exit(1);
1995
+ }
1996
+ return;
1997
+ }
1998
+
1999
+ if (options.target === "claude") {
2000
+ try {
2001
+ installClaudeGlobalPlugin();
2002
+ console.log("AGDF Claude Code plugin installed globally.");
2003
+ } catch (error) {
2004
+ console.error(error.message);
2005
+ process.exit(1);
2006
+ }
2007
+ return;
2008
+ }
2009
+
2010
+ if (options.target === "opencode") {
2011
+ const configDir = options.dirExplicit ? options.dir : defaultOpenCodeConfigDir();
2012
+ try {
2013
+ const result = installOpenCodeGlobalPlugin(configDir);
2014
+ console.log(`AGDF OpenCode global plugin ${result.added ? "installed" : "already present"}: ${result.configPath}`);
2015
+ const report = evaluateOpenCodeStatus(options.dir, configDir);
2016
+ printOpenCodeStatus(report, false);
2017
+ console.log("Restart OpenCode so it loads the updated global plugin config.");
2018
+ } catch (error) {
2019
+ console.error(error.message);
2020
+ process.exit(1);
2021
+ }
2022
+ return;
2023
+ }
2024
+
1760
2025
  const files = generatedFilesForTarget(options.target, options.dir, options.force, options.language);
1761
2026
  const wroteAgentsFragment = files.some(file => file.path === agdfFragmentPath);
1762
2027
  const wroteOpenCodeConfigFragment = files.some(file => file.path === openCodeConfigFragmentPath);
@@ -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.
@@ -99,8 +99,13 @@ For relevant runs that change durable state, code, artefacts or gate status:
99
99
  ## OpenCode Files
100
100
 
101
101
  - OpenCode loads this file through `opencode.json` `instructions`.
102
+ - AGDF for OpenCode has two layers: an optional global npm plugin hook and this repository-local governance surface.
103
+ - The global plugin hook does not replace this file, `.opencode/agents/` or `.agdf/control/`; repository files remain the AGDF source of truth.
102
104
  - OpenCode agents live under `.opencode/agents/` and use the `agdf-` prefix.
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
+ - 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.
103
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.
104
109
  - OpenCode permissions keep `edit` and `bash` on explicit approval by default.
105
110
  - Shared output and gate rules live in `.opencode/agdf-runtime-contract.md`.
106
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.
@@ -3,8 +3,14 @@
3
3
  These files were generated from the AGDF source repository for OpenCode.
4
4
 
5
5
  - `opencode.json` loads the npm plugin `create-agdf` and `.opencode/AGDF.md` as repository instructions.
6
+ - AGDF for OpenCode has two layers: an optional global npm plugin hook and this repository-local governance surface.
7
+ - The global plugin hook does not replace `.opencode/AGDF.md`, `.opencode/agents/` or `.agdf/control/`; repository files remain the AGDF source of truth.
6
8
  - `opencode.json` keeps `edit` and `bash` on `ask` so execution remains permissioned.
7
9
  - `.opencode/agents/` contains AGDF subagents generated from the canonical AGDF skills.
10
+ - These files intentionally do not install OpenCode Skills under `.opencode/skills/`; the AGDF agents are background workflow controls, not primary menu agents.
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.
8
14
  - `.opencode/agdf-runtime-contract.md` is the shared gate and output contract.
9
15
 
10
16
  ## Agents
@@ -3,11 +3,6 @@ description: after gate-check permits Brownfield Review or implementation prepar
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-brownfield-analysis
8
- description: Use this skill after gate-check or live AGDF control state confirms that Brownfield Review or implementation preparation is allowed. Use it after Approval: UR as the lightweight Brownfield Review after G-00 before PRD when existing systems may be affected, and again before non-trivial implementation after TP. Do not use it as the first AGDF skill for a fresh "I want to build/change X" prompt when approval, scope, or next allowed action is unclear.
9
- ---
10
-
11
6
  # brownfield-analysis
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: inspect workarounds, fallbacks, parallel structures or symptom fixe
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-clean-implementation-review
8
- description: Use this skill to determine whether an implementation is a clean primary solution or whether fallbacks, workarounds, guards, defaults, shims, or parallel structures have made it unnecessarily complex. Use it after code changes, before QA, or whenever symptom treatment is suspected.
9
- ---
10
-
11
6
  # clean-implementation-review
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: mandatory CR step after code changes, focused on defects, regressio
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-code-review
8
- description: Use this skill after code changes and before QA to produce the mandatory Code Review Report for correctness, regression, security, and maintainability findings in the actual diff. It standardizes the CR step without replacing TP review, clean review, or QA.
9
- ---
10
-
11
6
  # code-review
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: commit/PR-near handoff after QA/OR/UAT
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-delivery-closeout
8
- description: Use this skill for the final delivery handoff after QA, OR, or UAT when a run should move toward commit, push, or PR. It standardizes commit-ready summaries, UAT-gated commit offers, and the next delivery step without replacing QA or OR decisions.
9
- ---
10
-
11
6
  # delivery-closeout
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: new build/change intent, unclear approval, Structured Delivery, lat
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-gate-check
8
- description: Use this skill as the default first AGDF skill for any new build, change, extension, refactor, feature, CLI, app, fix with product semantics, Structured Delivery request, unclear approval, later-gate artefact request, or unclear next permissible step. Use it before brownfield-analysis, implementation, formal artefacts, QA, or release when approval/evidence/next action is not already explicit.
9
- ---
10
-
11
6
  # gate-check
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: final QA decision
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-qa-gate
8
- description: Use this skill before any QA decision to determine whether implementation can be classified as pass, revise, or block based on TP coverage, Brownfield fit, solution integrity, evidence, and open blockers. Use it after CD+Tests, after reviews, and before UAT or release decisions.
9
- ---
10
-
11
6
  # qa-gate
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: auditable closeout for every relevant run
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-release-or
8
- description: Use this skill at the end of every relevant run to produce a compact, auditable Orchestration Report. It summarizes gate status, delivered and intentionally not delivered work, TP coverage, Brownfield fit, solution integrity, open risks, and the next permissible step.
9
- ---
10
-
11
6
  # release-or
12
7
 
13
8
  ## Purpose
@@ -3,11 +3,6 @@ description: after implementation and before QA, verify TP coverage
3
3
  mode: subagent
4
4
  ---
5
5
 
6
- ---
7
- name: agdf-task-plan-review
8
- description: Use this skill after code changes and before QA to verify whether the approved Task Plan was actually fulfilled. It checks each task_id against implementation, acceptance criteria, tests, visible evidence, and deviations, and provides TP coverage for QA.
9
- ---
10
-
11
6
  # task-plan-review
12
7
 
13
8
  ## Purpose
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.3.5",
3
+ "version": "0.4.1",
4
4
  "description": "Codex-first workflow skills for gated, auditable AI-assisted software delivery.",
5
5
  "author": {
6
6
  "name": "AI-native Governance & Delivery Framework",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "agdf",
4
- "version": "0.3.5",
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.",
@@ -1,30 +1,56 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+
3
+ const packageJson = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
4
+
1
5
  export const AGDFPlugin = async ({ directory, client }) => {
2
6
  const controlDir = `${directory}/.agdf/control`;
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
+ });
3
14
 
4
15
  return {
5
16
  event: async ({ event }) => {
6
17
  if (event?.type === "session.created") {
18
+ const currentStatus = status();
7
19
  await client.app.log({
8
20
  body: {
9
21
  service: "agdf",
10
22
  level: "info",
11
- message: "AGDF OpenCode surface active",
12
- extra: { controlDir },
23
+ message: currentStatus.repositorySurface ? "AGDF OpenCode active" : "AGDF OpenCode global hook active without repository surface",
24
+ extra: currentStatus,
13
25
  },
14
26
  });
15
27
  }
16
28
  },
17
29
 
18
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;
19
34
  output.env.AGDF_CONTROL_DIR = controlDir;
35
+ output.env.AGDF_OPENCODE_REPOSITORY_SURFACE = currentStatus.repositorySurface ? "1" : "0";
20
36
  },
21
37
 
22
38
  "experimental.session.compacting": async (_input, output) => {
39
+ if (!hasRepositorySurface()) {
40
+ output.context.push([
41
+ "## AGDF Plugin Notice",
42
+ "The AGDF OpenCode npm plugin is loaded, but this repository does not contain the AGDF OpenCode surface.",
43
+ "Do not apply AGDF gates from the global plugin alone; repository instructions, subagents and control files are the source of truth.",
44
+ "Run `npx --yes @agdf/cli@latest opencode-repo` in this repository when AGDF governance should be active here.",
45
+ ].join("\n"));
46
+ return;
47
+ }
48
+
23
49
  output.context.push([
24
50
  "## AGDF Runtime Reminder",
25
51
  "Use `.opencode/AGDF.md`, `.opencode/agents/` and `.agdf/control/` as the AGDF source for this OpenCode session.",
26
52
  "For new build/change intent or unclear approval, route first to `agdf-gate-check` before later artefacts or implementation.",
27
- "Use `npx --yes @agdf/cli@latest gate-check --json` only as deterministic proof, not as a replacement for AGDF judgement.",
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.",
28
54
  ].join("\n"));
29
55
  },
30
56
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.3.5",
3
+ "version": "0.4.1",
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": [