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 +41 -9
- package/bin/create-agdf.js +276 -11
- package/generated/.github/copilot-instructions.md +1 -0
- package/generated/.opencode/AGDF.md +5 -0
- package/generated/.opencode/README.md +6 -0
- package/generated/.opencode/agents/agdf-brownfield-analysis.md +0 -5
- package/generated/.opencode/agents/agdf-clean-implementation-review.md +0 -5
- package/generated/.opencode/agents/agdf-code-review.md +0 -5
- package/generated/.opencode/agents/agdf-delivery-closeout.md +0 -5
- package/generated/.opencode/agents/agdf-gate-check.md +0 -5
- package/generated/.opencode/agents/agdf-qa-gate.md +0 -5
- package/generated/.opencode/agents/agdf-release-or.md +0 -5
- package/generated/.opencode/agents/agdf-task-plan-review.md +0 -5
- 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 +29 -3
- package/package.json +1 -1
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`
|
|
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`
|
|
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
|
|
66
|
+
Use the `opencode` target to install the AGDF npm plugin as a user-wide OpenCode hook:
|
|
54
67
|
|
|
55
68
|
```bash
|
|
56
|
-
|
|
69
|
+
npx --yes @agdf/cli@latest opencode
|
|
57
70
|
```
|
|
58
71
|
|
|
59
|
-
|
|
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
|
|
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
|
|
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
|
|
package/bin/create-agdf.js
CHANGED
|
@@ -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 = "
|
|
14
|
-
const
|
|
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("-
|
|
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
|
|
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.
|
|
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,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
|
|
12
|
-
extra:
|
|
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,
|
|
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