create-agdf 0.11.3 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/generated/.agdf/control/templates/MASTER_BACKLOG.md +1 -1
- package/generated/.github/skills/contracts/control-scaffold.md +2 -0
- package/generated/.opencode/contracts/control-scaffold.md +2 -0
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/control/templates/MASTER_BACKLOG.md +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -1
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +2 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +2 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +78 -14
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +1 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +2 -11
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +2 -11
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +1 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +15 -2
- package/generated/plugins/agdf/runtime/create-agdf/package.json +3 -2
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/lib/cli/application.js +17 -2
- package/lib/cli/command-registry.js +2 -2
- package/lib/cli/delivery-path-search-command.js +78 -14
- package/lib/control-evaluation/shared.js +1 -0
- package/lib/delivery-path-search/evaluators/claude.js +2 -11
- package/lib/delivery-path-search/evaluators/codex.js +2 -11
- package/lib/delivery-path-search/evaluators/opencode.js +234 -0
- package/lib/delivery-path-search/evaluators/prompt.js +13 -0
- package/lib/delivery-path-search/search-engine.js +1 -0
- package/lib/delivery-path-search/surfaces/capabilities.js +15 -2
- package/lib/installers/opencode.js +214 -10
- package/lib/lifecycle/operations.js +4 -0
- package/opencode-plugin.js +19 -2
- package/package.json +3 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { generatedRoot, pluginDefinition } from "../cli/runtime-context.js";
|
|
7
7
|
import { evaluateOpenCodeRepositoryActivation } from "./opencode-activation.js";
|
|
@@ -14,6 +14,7 @@ const globalOpenCodeSkillOwnershipMarker = "<!-- AGDF-GLOBAL-SKILL: ";
|
|
|
14
14
|
const globalOpenCodeInstructionsOwnershipMarker = "<!-- AGDF-GLOBAL-INSTRUCTIONS -->";
|
|
15
15
|
const globalOpenCodeRuntimeContractOwnershipMarker = "<!-- AGDF-GLOBAL-RUNTIME-CONTRACT -->";
|
|
16
16
|
const globalOpenCodeValidatorOwnershipMarker = "// AGDF-GLOBAL-LOCAL-VALIDATOR";
|
|
17
|
+
const globalOpenCodeAgentOwnershipMarker = `<!-- AGDF-GLOBAL-AGENT: ${pluginDefinition.opencode.evaluatorAgentName} -->`;
|
|
17
18
|
const globalOpenCodeValidatorPackageOwner = "create-agdf";
|
|
18
19
|
const testNpmCliPath = process.env.NODE_ENV === "test" ? process.env.AGDF_TEST_NPM_CLI_PATH || "" : "";
|
|
19
20
|
const npmCommand = testNpmCliPath ? process.execPath : process.platform === "win32" ? process.execPath : "npm";
|
|
@@ -131,6 +132,7 @@ function globalOpenCodeConfigPaths(configDir) {
|
|
|
131
132
|
skills: join(configDir, "skills"),
|
|
132
133
|
localValidator: join(configDir, "agdf", "bin", "agdf-local.js"),
|
|
133
134
|
localValidatorPackage: join(configDir, "agdf", "package.json"),
|
|
135
|
+
evaluatorAgent: join(configDir, "agents", `${pluginDefinition.opencode.evaluatorAgentName}.md`),
|
|
134
136
|
};
|
|
135
137
|
}
|
|
136
138
|
|
|
@@ -179,6 +181,7 @@ function assertGlobalOpenCodeSurfaceWritable(configDir) {
|
|
|
179
181
|
assertGlobalOpenCodeFileWritable(paths.instructions, globalOpenCodeInstructionsOwnershipMarker, "first-line");
|
|
180
182
|
assertGlobalOpenCodeFileWritable(paths.runtimeContract, globalOpenCodeRuntimeContractOwnershipMarker, "first-line");
|
|
181
183
|
assertGlobalOpenCodeFileWritable(paths.localValidator, globalOpenCodeValidatorOwnershipMarker, "first-line");
|
|
184
|
+
assertGlobalOpenCodeFileWritable(paths.evaluatorAgent, globalOpenCodeAgentOwnershipMarker, "after-frontmatter");
|
|
182
185
|
assertGlobalOpenCodeValidatorPackageWritable(paths.localValidatorPackage);
|
|
183
186
|
for (const moduleName of contractModules) {
|
|
184
187
|
assertGlobalOpenCodeFileWritable(
|
|
@@ -212,6 +215,10 @@ function globalOpenCodeBoundary() {
|
|
|
212
215
|
"Before applying AGDF gates, later artefacts or implementation guidance, inspect the current repository for valid `.agdf/control/config.json` durable control.",
|
|
213
216
|
"If durable control is missing or invalid, stop and direct the user to `npx --yes @agdf/cli@latest opencode-repo` in this repository.",
|
|
214
217
|
"When durable control is valid, use the global `agdf-global-*` skill surface; existing local OpenCode assets remain a compatibility path.",
|
|
218
|
+
"Only exact `Approval: <GateName>` values can advance AGDF gates; host permissions and plugin hooks never grant delivery authority.",
|
|
219
|
+
"Resolve and use the installed version-matched `agdf/bin/agdf-local.js` validator for deterministic checks.",
|
|
220
|
+
"If activation, approval, evidence or validator ownership is missing or unclear, stop before later artefacts or implementation.",
|
|
221
|
+
"Use `opencode-status --json` to inspect installed hook declarations, version divergence and evaluator availability without treating SDK declarations as live hook execution proof.",
|
|
215
222
|
"",
|
|
216
223
|
].join("\n");
|
|
217
224
|
}
|
|
@@ -255,10 +262,27 @@ export function installOpenCodeGlobalSurface(configDir) {
|
|
|
255
262
|
].join("\n");
|
|
256
263
|
const globalRuntimeContract = `${globalOpenCodeRuntimeContractOwnershipMarker}\n${generatedRuntimeContract}`;
|
|
257
264
|
const localValidator = `${globalOpenCodeValidatorOwnershipMarker}\nimport process from "node:process";\nimport { fileURLToPath } from "node:url";\nimport { runLocalValidator } from "../../node_modules/create-agdf/lib/runtime/local-validator.js";\n\nconst ownedPackageRoot = fileURLToPath(new URL("../../node_modules/create-agdf", import.meta.url));\nprocess.exitCode = runLocalValidator({ ownedPackageRoot, expectedVersion: ${JSON.stringify(pluginDefinition.version)}, surface: "opencode" }, process.argv.slice(2));\n`;
|
|
265
|
+
const evaluatorAgent = [
|
|
266
|
+
"---",
|
|
267
|
+
"description: Evaluate one AGDF Delivery Path Search candidate without tools or side effects.",
|
|
268
|
+
"mode: primary",
|
|
269
|
+
"permission:",
|
|
270
|
+
' "*": deny',
|
|
271
|
+
"---",
|
|
272
|
+
globalOpenCodeAgentOwnershipMarker,
|
|
273
|
+
"",
|
|
274
|
+
"# AGDF Delivery Path Search evaluator",
|
|
275
|
+
"",
|
|
276
|
+
"Evaluate only the bounded candidate supplied in the user message.",
|
|
277
|
+
"Do not call tools, inspect files, delegate work or modify state.",
|
|
278
|
+
"Return only the requested JSON object; AGDF validates it independently.",
|
|
279
|
+
"",
|
|
280
|
+
].join("\n");
|
|
258
281
|
|
|
259
282
|
writeOwnedGlobalOpenCodeFile(paths.instructions, globalInstructions, globalOpenCodeInstructionsOwnershipMarker, "first-line");
|
|
260
283
|
writeOwnedGlobalOpenCodeFile(paths.runtimeContract, globalRuntimeContract, globalOpenCodeRuntimeContractOwnershipMarker, "first-line");
|
|
261
284
|
writeOwnedGlobalOpenCodeFile(paths.localValidator, localValidator, globalOpenCodeValidatorOwnershipMarker, "first-line");
|
|
285
|
+
writeOwnedGlobalOpenCodeFile(paths.evaluatorAgent, evaluatorAgent, globalOpenCodeAgentOwnershipMarker, "after-frontmatter");
|
|
262
286
|
mkdirSync(dirname(paths.localValidatorPackage), { recursive: true });
|
|
263
287
|
writeFileSync(paths.localValidatorPackage, `${JSON.stringify({
|
|
264
288
|
name: "agdf-opencode-validator-runtime",
|
|
@@ -296,6 +320,7 @@ export function installOpenCodeGlobalSurface(configDir) {
|
|
|
296
320
|
skills: paths.skills,
|
|
297
321
|
localValidator: paths.localValidator,
|
|
298
322
|
localValidatorPackage: paths.localValidatorPackage,
|
|
323
|
+
evaluatorAgent: paths.evaluatorAgent,
|
|
299
324
|
};
|
|
300
325
|
}
|
|
301
326
|
|
|
@@ -308,24 +333,64 @@ function readOpenCodeConfig(configPath) {
|
|
|
308
333
|
}
|
|
309
334
|
}
|
|
310
335
|
|
|
311
|
-
function
|
|
312
|
-
const
|
|
336
|
+
export function resolveOpenCodeInstalledPackage(configDir, packageName, dependencies = {}) {
|
|
337
|
+
const run = dependencies.execFileSync ?? execFileSync;
|
|
313
338
|
try {
|
|
314
|
-
const
|
|
339
|
+
const probe = [
|
|
340
|
+
'const fs = require("node:fs");',
|
|
341
|
+
'const path = require("node:path");',
|
|
342
|
+
`const packageName = ${JSON.stringify(packageName)};`,
|
|
343
|
+
'let resolvedPath = "";',
|
|
344
|
+
'try { resolvedPath = require.resolve(packageName); } catch {}',
|
|
345
|
+
'let manifestPath = "";',
|
|
346
|
+
'for (const root of require.resolve.paths(packageName) || []) {',
|
|
347
|
+
' const candidate = path.join(root, packageName, "package.json");',
|
|
348
|
+
' if (fs.existsSync(candidate)) { manifestPath = candidate; break; }',
|
|
349
|
+
'}',
|
|
350
|
+
'if (!manifestPath) throw new Error(`installed package manifest not found: ${packageName}`);',
|
|
351
|
+
'process.stdout.write(JSON.stringify({ resolvedPath, manifestPath }));',
|
|
352
|
+
].join("\n");
|
|
353
|
+
const rawResolution = run(process.execPath, ["-e", probe], {
|
|
315
354
|
cwd: configDir,
|
|
316
355
|
encoding: "utf8",
|
|
317
356
|
stdio: "pipe",
|
|
318
357
|
});
|
|
319
|
-
let
|
|
358
|
+
let resolvedPath = rawResolution;
|
|
359
|
+
let probedManifestPath = "";
|
|
320
360
|
try {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
361
|
+
const parsed = JSON.parse(rawResolution);
|
|
362
|
+
resolvedPath = parsed.resolvedPath || parsed.manifestPath;
|
|
363
|
+
probedManifestPath = parsed.manifestPath;
|
|
364
|
+
} catch {}
|
|
365
|
+
let current = probedManifestPath ? dirname(probedManifestPath) : dirname(resolvedPath);
|
|
366
|
+
let manifestPath = "";
|
|
367
|
+
let packageRoot = "";
|
|
368
|
+
let manifest = null;
|
|
369
|
+
for (let depth = 0; depth < 20; depth += 1) {
|
|
370
|
+
const candidate = join(current, "package.json");
|
|
371
|
+
if (existsSync(candidate)) {
|
|
372
|
+
try {
|
|
373
|
+
const value = JSON.parse(readFileSync(candidate, "utf8"));
|
|
374
|
+
if (value?.name === packageName) {
|
|
375
|
+
manifestPath = candidate;
|
|
376
|
+
packageRoot = current;
|
|
377
|
+
manifest = value;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
} catch {}
|
|
381
|
+
}
|
|
382
|
+
const parent = dirname(current);
|
|
383
|
+
if (parent === current) break;
|
|
384
|
+
current = parent;
|
|
325
385
|
}
|
|
386
|
+
if (!manifest) throw new Error(`resolved ${packageName} entry has no matching package manifest`);
|
|
387
|
+
const installedVersion = typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : "";
|
|
326
388
|
return {
|
|
327
389
|
loadable: true,
|
|
328
390
|
path: resolvedPath,
|
|
391
|
+
manifest_path: manifestPath,
|
|
392
|
+
package_root: packageRoot,
|
|
393
|
+
manifest,
|
|
329
394
|
installed_version: installedVersion,
|
|
330
395
|
error: "",
|
|
331
396
|
};
|
|
@@ -333,12 +398,127 @@ function resolveOpenCodePackage(configDir) {
|
|
|
333
398
|
return {
|
|
334
399
|
loadable: false,
|
|
335
400
|
path: "",
|
|
401
|
+
manifest_path: "",
|
|
402
|
+
package_root: "",
|
|
403
|
+
manifest: null,
|
|
336
404
|
installed_version: "",
|
|
337
405
|
error: (error.stderr || error.message || "package not resolvable").toString().trim(),
|
|
338
406
|
};
|
|
339
407
|
}
|
|
340
408
|
}
|
|
341
409
|
|
|
410
|
+
function resolveOpenCodePackage(configDir) {
|
|
411
|
+
return resolveOpenCodeInstalledPackage(configDir, pluginDefinition.opencode.npmPackage);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const requiredExperimentalHooks = [
|
|
415
|
+
"experimental.chat.system.transform",
|
|
416
|
+
"experimental.session.compacting",
|
|
417
|
+
];
|
|
418
|
+
|
|
419
|
+
function packageLocalPath(packageRoot, candidate) {
|
|
420
|
+
if (!packageRoot || !candidate) return "";
|
|
421
|
+
const path = resolve(packageRoot, candidate);
|
|
422
|
+
const relation = relative(packageRoot, path);
|
|
423
|
+
return relation === "" || (relation !== ".." && !relation.startsWith(`..${sep}`) && !isAbsolute(relation)) ? path : "";
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function openCodeHostProbe(dependencies = {}) {
|
|
427
|
+
const executable = dependencies.openCodeBin ?? process.env.AGDF_OPENCODE_BIN ?? "opencode";
|
|
428
|
+
const run = dependencies.execFileSync ?? execFileSync;
|
|
429
|
+
try {
|
|
430
|
+
return {
|
|
431
|
+
name: "opencode",
|
|
432
|
+
executable,
|
|
433
|
+
inspectable: true,
|
|
434
|
+
installed_version: run(executable, ["--version"], {
|
|
435
|
+
encoding: "utf8",
|
|
436
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
437
|
+
timeout: 5000,
|
|
438
|
+
}).trim(),
|
|
439
|
+
error: "",
|
|
440
|
+
};
|
|
441
|
+
} catch (error) {
|
|
442
|
+
return {
|
|
443
|
+
name: "opencode",
|
|
444
|
+
executable,
|
|
445
|
+
inspectable: false,
|
|
446
|
+
installed_version: "",
|
|
447
|
+
error: (error.stderr || error.message || "host version unavailable").toString().trim(),
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function openCodeSdkProbe(configDir, dependencies = {}) {
|
|
453
|
+
const sdk = resolveOpenCodeInstalledPackage(configDir, "@opencode-ai/plugin", dependencies);
|
|
454
|
+
let declarationPath = "";
|
|
455
|
+
let declaration = "";
|
|
456
|
+
if (sdk.loadable) {
|
|
457
|
+
const declaredEntry = sdk.manifest?.types || sdk.manifest?.typings || "dist/index.d.ts";
|
|
458
|
+
declarationPath = packageLocalPath(sdk.package_root, declaredEntry);
|
|
459
|
+
if (declarationPath && existsSync(declarationPath)) {
|
|
460
|
+
try {
|
|
461
|
+
declaration = readFileSync(declarationPath, "utf8");
|
|
462
|
+
} catch (error) {
|
|
463
|
+
sdk.error = error.message;
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
sdk.error = `SDK declaration not found: ${declaredEntry}`;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
const hooks = requiredExperimentalHooks.map((name) => ({
|
|
470
|
+
name,
|
|
471
|
+
state: !declaration
|
|
472
|
+
? "uninspectable"
|
|
473
|
+
: declaration.includes(`"${name}"`)
|
|
474
|
+
? "declared_supported"
|
|
475
|
+
: "declared_missing",
|
|
476
|
+
}));
|
|
477
|
+
const states = hooks.map((hook) => hook.state);
|
|
478
|
+
const aggregate = states.every((state) => state === "declared_supported")
|
|
479
|
+
? "declared_supported"
|
|
480
|
+
: states.some((state) => state === "uninspectable")
|
|
481
|
+
? "uninspectable"
|
|
482
|
+
: "degraded";
|
|
483
|
+
return {
|
|
484
|
+
package: {
|
|
485
|
+
name: "@opencode-ai/plugin",
|
|
486
|
+
loadable: sdk.loadable,
|
|
487
|
+
resolved_path: sdk.path,
|
|
488
|
+
manifest_path: sdk.manifest_path,
|
|
489
|
+
declaration_path: declarationPath,
|
|
490
|
+
installed_version: sdk.installed_version || null,
|
|
491
|
+
error: sdk.error,
|
|
492
|
+
},
|
|
493
|
+
hooks: {
|
|
494
|
+
evidence_level: "sdk_declaration",
|
|
495
|
+
aggregate,
|
|
496
|
+
hooks,
|
|
497
|
+
live_invocation_observed: false,
|
|
498
|
+
},
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export function evaluateOpenCodeHostSdk(configDir, dependencies = {}) {
|
|
503
|
+
const host = openCodeHostProbe(dependencies);
|
|
504
|
+
const sdk = openCodeSdkProbe(configDir, dependencies);
|
|
505
|
+
return {
|
|
506
|
+
host,
|
|
507
|
+
plugin_sdk: sdk.package,
|
|
508
|
+
experimental_hooks: sdk.hooks,
|
|
509
|
+
host_sdk_version: {
|
|
510
|
+
status: !host.installed_version || !sdk.package.installed_version
|
|
511
|
+
? "unknown"
|
|
512
|
+
: host.installed_version === sdk.package.installed_version
|
|
513
|
+
? "matching"
|
|
514
|
+
: "divergent",
|
|
515
|
+
host_version: host.installed_version || null,
|
|
516
|
+
sdk_version: sdk.package.installed_version || null,
|
|
517
|
+
policy: "warn_only",
|
|
518
|
+
},
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
342
522
|
function openCodePackageVersionStatus(packageState) {
|
|
343
523
|
if (!packageState.loadable) return "unloadable";
|
|
344
524
|
if (!packageState.installed_version) return "unknown";
|
|
@@ -393,18 +573,24 @@ function evaluateGlobalOpenCodeSurface(configDir) {
|
|
|
393
573
|
present: existsSync(paths.localValidator),
|
|
394
574
|
...validatorResolution.envelope,
|
|
395
575
|
},
|
|
576
|
+
evaluator_agent: {
|
|
577
|
+
name: pluginDefinition.opencode.evaluatorAgentName,
|
|
578
|
+
path: paths.evaluatorAgent,
|
|
579
|
+
present: existsSync(paths.evaluatorAgent),
|
|
580
|
+
},
|
|
396
581
|
present: existsSync(paths.skills),
|
|
397
582
|
complete: existsSync(paths.instructions)
|
|
398
583
|
&& existsSync(paths.runtimeContract)
|
|
399
584
|
&& contractCount === contractModules.length
|
|
400
585
|
&& skillCount === openCodeSkillNames.length
|
|
401
586
|
&& existsSync(paths.localValidator)
|
|
587
|
+
&& existsSync(paths.evaluatorAgent)
|
|
402
588
|
&& globalOpenCodeValidatorPackageIsValid(paths.localValidatorPackage)
|
|
403
589
|
&& validatorResolution.envelope.machine_validation === "owned_version_matched",
|
|
404
590
|
};
|
|
405
591
|
}
|
|
406
592
|
|
|
407
|
-
export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir(), transition = null) {
|
|
593
|
+
export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir(), transition = null, dependencies = {}) {
|
|
408
594
|
const configPath = join(configDir, "opencode.json");
|
|
409
595
|
const configState = readOpenCodeConfig(configPath);
|
|
410
596
|
const plugins = Array.isArray(configState.config.plugin) ? configState.config.plugin : [];
|
|
@@ -412,6 +598,7 @@ export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeCon
|
|
|
412
598
|
const packageState = resolveOpenCodePackage(configDir);
|
|
413
599
|
const packageVersionStatus = openCodePackageVersionStatus(packageState);
|
|
414
600
|
const globalNativeSurface = evaluateGlobalOpenCodeSurface(configDir);
|
|
601
|
+
const hostSdk = evaluateOpenCodeHostSdk(configDir, dependencies);
|
|
415
602
|
const sessionSignals = {
|
|
416
603
|
active: process.env.AGDF_PLUGIN_ACTIVE === "1",
|
|
417
604
|
version: process.env.AGDF_PLUGIN_VERSION || "",
|
|
@@ -434,6 +621,11 @@ export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeCon
|
|
|
434
621
|
`Global OpenCode native surface is incomplete (${globalNativeSurface.skill_count}/${globalNativeSurface.expected_skill_count} skills; ${globalNativeSurface.contract_count}/${globalNativeSurface.expected_contract_count} contract modules).`,
|
|
435
622
|
);
|
|
436
623
|
}
|
|
624
|
+
if (hostSdk.experimental_hooks.aggregate === "uninspectable") findings.push("Installed OpenCode plugin SDK hook declarations could not be inspected.");
|
|
625
|
+
if (hostSdk.experimental_hooks.aggregate === "degraded") findings.push("Installed OpenCode plugin SDK is missing one or more required experimental hook declarations.");
|
|
626
|
+
if (hostSdk.host_sdk_version.status === "divergent") {
|
|
627
|
+
findings.push(`OpenCode host ${hostSdk.host_sdk_version.host_version} and plugin SDK ${hostSdk.host_sdk_version.sdk_version} diverge; policy is warning-only.`);
|
|
628
|
+
}
|
|
437
629
|
if (!sessionSignals.active) findings.push("No active AGDF OpenCode session signal is visible in this process.");
|
|
438
630
|
if (!repositoryActivation.active) {
|
|
439
631
|
findings.push(repositoryActivation.state === "invalid_control"
|
|
@@ -460,6 +652,7 @@ export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeCon
|
|
|
460
652
|
...(transition ? { transition } : {}),
|
|
461
653
|
error: packageState.error,
|
|
462
654
|
},
|
|
655
|
+
...hostSdk,
|
|
463
656
|
global_native_surface: globalNativeSurface,
|
|
464
657
|
session: sessionSignals,
|
|
465
658
|
repository_activation: repositoryActivation.state,
|
|
@@ -482,6 +675,12 @@ export function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeCon
|
|
|
482
675
|
? "Run npx --yes @agdf/cli@latest opencode to install or repair the OpenCode package version."
|
|
483
676
|
: !globalNativeSurface.complete
|
|
484
677
|
? "Run npx --yes @agdf/cli@latest opencode to install or repair the global native OpenCode skill surface."
|
|
678
|
+
: hostSdk.experimental_hooks.aggregate === "uninspectable"
|
|
679
|
+
? "Repair the installed OpenCode plugin SDK so its declarations can be inspected; do not assume dynamic hook support."
|
|
680
|
+
: hostSdk.experimental_hooks.aggregate === "degraded"
|
|
681
|
+
? "Use static AGDF instructions and review OpenCode compatibility before relying on dynamic hook injection."
|
|
682
|
+
: hostSdk.host_sdk_version.status === "divergent"
|
|
683
|
+
? "Review OpenCode host/plugin-SDK compatibility; AGDF reports this divergence but does not align versions automatically."
|
|
485
684
|
: repositoryActivation.state === "invalid_control"
|
|
486
685
|
? "Repair .agdf/control/config.json so it contains valid artifact_language, chat_language and runtime_language values."
|
|
487
686
|
: repositoryActivation.active
|
|
@@ -505,6 +704,11 @@ export function printOpenCodeStatus(report, json, io = console) {
|
|
|
505
704
|
io.log(`Package version: ${report.package.installed_version || "unknown"}`);
|
|
506
705
|
io.log(`Expected version: ${report.package.expected_version}`);
|
|
507
706
|
io.log(`Version status: ${report.package.version_status}`);
|
|
707
|
+
io.log(`OpenCode host version: ${report.host.installed_version || "unknown"}`);
|
|
708
|
+
io.log(`Plugin SDK version: ${report.plugin_sdk.installed_version || "unknown"}`);
|
|
709
|
+
io.log(`Host/SDK version: ${report.host_sdk_version.status} (${report.host_sdk_version.policy})`);
|
|
710
|
+
io.log(`Experimental hook declarations: ${report.experimental_hooks.aggregate} (${report.experimental_hooks.evidence_level}; live invocation not observed)`);
|
|
711
|
+
for (const hook of report.experimental_hooks.hooks) io.log(`- ${hook.name}: ${hook.state}`);
|
|
508
712
|
if (report.package.transition?.status === "updated") {
|
|
509
713
|
io.log(`Version transition: ${report.package.transition.previous_version} -> ${report.package.transition.installed_version}`);
|
|
510
714
|
} else if (report.package.transition?.status === "installed") {
|
|
@@ -131,6 +131,10 @@ function openCodeOwnedGlobalFiles(configDir) {
|
|
|
131
131
|
const files = [
|
|
132
132
|
{ path: join(configDir, pluginDefinition.opencode.instructionsFileName), owned: firstLine("<!-- AGDF-GLOBAL-INSTRUCTIONS -->") },
|
|
133
133
|
{ path: join(configDir, pluginDefinition.opencode.runtimeContractFileName), owned: firstLine("<!-- AGDF-GLOBAL-RUNTIME-CONTRACT -->") },
|
|
134
|
+
{
|
|
135
|
+
path: join(configDir, "agents", `${pluginDefinition.opencode.evaluatorAgentName}.md`),
|
|
136
|
+
owned: afterFrontmatter(`<!-- AGDF-GLOBAL-AGENT: ${pluginDefinition.opencode.evaluatorAgentName} -->`),
|
|
137
|
+
},
|
|
134
138
|
];
|
|
135
139
|
for (const moduleName of ["gate-transition.md", "interaction.md", "modes.md", "quality.md", "context-graph.md", "control-scaffold.md", "closeout.md"]) {
|
|
136
140
|
files.push({ path: join(configDir, "contracts", moduleName), owned: firstLine("<!-- AGDF-GLOBAL-RUNTIME-CONTRACT -->") });
|
package/opencode-plugin.js
CHANGED
|
@@ -30,6 +30,23 @@ export const AGDFPlugin = async ({ directory, client }) => {
|
|
|
30
30
|
"Do not apply AGDF gates from the global plugin alone. Create or repair durable AGDF control state with `npx --yes @agdf/cli@latest opencode-repo` when governance should be active here.",
|
|
31
31
|
].join("\n");
|
|
32
32
|
|
|
33
|
+
const appendGuidance = async (output, key) => {
|
|
34
|
+
if (!output || !Array.isArray(output[key])) {
|
|
35
|
+
try {
|
|
36
|
+
await client.app.log({
|
|
37
|
+
body: {
|
|
38
|
+
service: "agdf",
|
|
39
|
+
level: "warn",
|
|
40
|
+
message: `AGDF OpenCode guidance degraded: ${key} output is unavailable`,
|
|
41
|
+
extra: { key, repositoryActivation: activation().state },
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
} catch {}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
output[key].push(activation().active ? activeGuidance : inactiveGuidance);
|
|
48
|
+
};
|
|
49
|
+
|
|
33
50
|
return {
|
|
34
51
|
event: async ({ event }) => {
|
|
35
52
|
if (event?.type === "session.created") {
|
|
@@ -55,11 +72,11 @@ export const AGDFPlugin = async ({ directory, client }) => {
|
|
|
55
72
|
},
|
|
56
73
|
|
|
57
74
|
"experimental.chat.system.transform": async (_input, output) => {
|
|
58
|
-
output
|
|
75
|
+
await appendGuidance(output, "system");
|
|
59
76
|
},
|
|
60
77
|
|
|
61
78
|
"experimental.session.compacting": async (_input, output) => {
|
|
62
|
-
output
|
|
79
|
+
await appendGuidance(output, "context");
|
|
63
80
|
},
|
|
64
81
|
};
|
|
65
82
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agdf",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test:delivery-path-search": "node ./scripts/delivery-path-search-test.js",
|
|
25
25
|
"test:delivery-path-search-unit": "node ./scripts/delivery-path-search-unit-test.js",
|
|
26
26
|
"test:delivery-path-search-generator": "node ./scripts/delivery-path-search-generator-test.js",
|
|
27
|
+
"test:opencode-hardening": "node ./scripts/opencode-hardening-test.js",
|
|
27
28
|
"test:cli-modularization": "node ./scripts/cli-modularization-test.js",
|
|
28
29
|
"test:local-validator": "node ./scripts/local-validator-test.js",
|
|
29
30
|
"test:local-marketplace": "node ./scripts/local-marketplace-test.js",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"eval:skills:record": "node ./scripts/record-skill-evals.js",
|
|
41
42
|
"test:release-bootstrap": "node ./scripts/release-bootstrap-smoke-test.js",
|
|
42
43
|
"test:routing": "npm run sync-package-assets && node ./scripts/test-routing.js",
|
|
43
|
-
"smoke-test": "npm run sync-package-assets && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:skill-evals && npm run eval:skills && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
44
|
+
"smoke-test": "npm run sync-package-assets && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:skill-evals && npm run eval:skills && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
44
45
|
"prepack": "npm run sync-package-assets"
|
|
45
46
|
},
|
|
46
47
|
"keywords": [
|