create-agdf 0.6.8 → 0.6.9

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
@@ -51,8 +51,8 @@ If no language is provided, `create-agdf` derives the preference from the local
51
51
  - `codex-repo` writes a repository-local Codex marketplace under `.agents/plugins/` and a local AGDF plugin copy under `plugins/agdf/`
52
52
  - `claude` installs the AGDF plugin globally for Claude Code
53
53
  - `copilot` writes `AGENTS.md`, Copilot custom instructions under `.github/`, visible repository skills under `.github/skills/`, 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
54
+ - `opencode` installs the AGDF npm plugin and nine native skills as a user-wide OpenCode surface
55
+ - `opencode-status` reports OpenCode global config, package loadability, global native-skill completeness, session signals and repository surface presence
56
56
  - `opencode-repo` writes `opencode.json`, `.opencode/AGDF.md`, prefixed native OpenCode skills under `.opencode/skills/`, explicit edit/bash/skill permissions, and AGDF control templates under `.agdf/control/`
57
57
  - `both` writes the Codex repository-local marketplace plus the Copilot-facing repository files
58
58
  - `config` writes or updates only `.agdf/control/config.json` for an already installed plugin or an existing repository
@@ -75,7 +75,7 @@ Then verify the visible installation state:
75
75
  npx --yes @agdf/cli@latest opencode-status --json
76
76
  ```
77
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.
78
+ The status command reports global configuration, package loadability, global native-skill completeness, 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
79
  In JSON schema version 1, `repository_surface.gate_check_agent` remains a deprecated compatibility alias for the native `gate_check_skill` path so existing status consumers keep working during the agent-to-skill migration.
80
80
 
81
81
  Use the `opencode-repo` target when AGDF should be available to OpenCode from repository files:
@@ -84,10 +84,10 @@ Use the `opencode-repo` target when AGDF should be available to OpenCode from re
84
84
  npm create agdf@latest -- opencode-repo
85
85
  ```
86
86
 
87
- OpenCode loads the AGDF npm plugin from global OpenCode config or repository `opencode.json`, AGENTS-style rules from `.opencode/AGDF.md`, explicit `edit`/`bash`/`skill` permissions and the `agdf-` prefixed native skills under `.opencode/skills/`. 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
+ OpenCode loads the AGDF npm plugin and global native skills from global OpenCode config, plus repository instructions from `.opencode/AGDF.md`, explicit `edit`/`bash`/`skill` permissions and canonical `agdf-` project skills under `.opencode/skills/`. Global adapters use the collision-safe `agdf-global-` prefix. AGDF for OpenCode has a global discoverability layer installed with `npx --yes @agdf/cli@latest opencode` and a repository-local governance surface generated by `opencode-repo`.
88
88
  Those generated skills load on demand through OpenCode's native `skill` tool. Use `agdf-gate-check` first for new build/change intent or unclear approval.
89
89
  If `opencode.json` already exists, AGDF keeps it unchanged and writes `opencode.agdf.json` as a merge fragment.
90
- 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 native skills. The `opencode-repo` target writes the repository files together.
90
+ The global layer makes the nine native AGDF skills discoverable, but does not activate repository governance by itself. Global skills fail closed until the current repository has `.opencode/AGDF.md`, `.opencode/skills/agdf-gate-check/SKILL.md` and `.agdf/control/`. Use `opencode-repo` to write that repository surface.
91
91
 
92
92
  ## Control scaffold
93
93
 
@@ -80,6 +80,10 @@ const gateProgressOrder = [
80
80
  const codexSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.codex.skillPrefix}${skill.slug}`);
81
81
  const copilotSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.copilot.skillPrefix}${skill.slug}`);
82
82
  const openCodeSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.opencode.skillPrefix}${skill.slug}`);
83
+ const globalOpenCodeSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.opencode.globalSkillPrefix}${skill.slug}`);
84
+ const globalOpenCodeSkillOwnershipMarker = "<!-- AGDF-GLOBAL-SKILL: ";
85
+ const globalOpenCodeInstructionsOwnershipMarker = "<!-- AGDF-GLOBAL-INSTRUCTIONS -->";
86
+ const globalOpenCodeRuntimeContractOwnershipMarker = "<!-- AGDF-GLOBAL-RUNTIME-CONTRACT -->";
83
87
  const codexPluginFiles = [
84
88
  join(".agents", "plugins", "marketplace.json"),
85
89
  join("plugins", "agdf", ".codex-plugin", "plugin.json"),
@@ -476,6 +480,7 @@ function defaultOpenCodeConfigDir() {
476
480
  }
477
481
 
478
482
  function installOpenCodeGlobalPlugin(configDir) {
483
+ assertGlobalOpenCodeSurfaceWritable(configDir);
479
484
  const configPath = join(configDir, "opencode.json");
480
485
  let config = {};
481
486
 
@@ -503,6 +508,24 @@ function installOpenCodeGlobalPlugin(configDir) {
503
508
  plugin: plugins,
504
509
  };
505
510
 
511
+ if (nextConfig.instructions !== undefined && !Array.isArray(nextConfig.instructions)) {
512
+ throw new Error(`Refusing to update OpenCode config with non-array instructions field: ${configPath}`);
513
+ }
514
+ nextConfig.instructions = [...(nextConfig.instructions ?? [])];
515
+ if (!nextConfig.instructions.includes("AGDF.md")) nextConfig.instructions.push("AGDF.md");
516
+
517
+ if (nextConfig.permission === undefined) {
518
+ nextConfig.permission = { skill: { "agdf-*": "allow" } };
519
+ } else if (nextConfig.permission && typeof nextConfig.permission === "object" && !Array.isArray(nextConfig.permission)) {
520
+ nextConfig.permission = { ...nextConfig.permission };
521
+ if (nextConfig.permission.skill === undefined) {
522
+ nextConfig.permission.skill = { "agdf-*": "allow" };
523
+ } else if (nextConfig.permission.skill && typeof nextConfig.permission.skill === "object" && !Array.isArray(nextConfig.permission.skill)) {
524
+ nextConfig.permission.skill = { ...nextConfig.permission.skill };
525
+ if (nextConfig.permission.skill["agdf-*"] === undefined) nextConfig.permission.skill["agdf-*"] = "allow";
526
+ }
527
+ }
528
+
506
529
  mkdirSync(configDir, { recursive: true });
507
530
  try {
508
531
  execFileSync(npmCommand, [...npmPrefixArgs, "install", "--silent", "--save-prod", "--prefix", configDir, packageRoot], { stdio: "pipe" });
@@ -517,6 +540,110 @@ function installOpenCodeGlobalPlugin(configDir) {
517
540
  };
518
541
  }
519
542
 
543
+ function globalOpenCodeConfigPaths(configDir) {
544
+ return {
545
+ instructions: join(configDir, pluginDefinition.opencode.instructionsFileName),
546
+ runtimeContract: join(configDir, pluginDefinition.opencode.runtimeContractFileName),
547
+ skills: join(configDir, "skills"),
548
+ };
549
+ }
550
+
551
+ function globalOpenCodeOwnershipMarkerIsValid(content, marker, placement) {
552
+ const lines = content.split(/\r?\n/);
553
+ if (placement === "first-line") return lines[0] === marker;
554
+ const frontmatterEnd = lines.findIndex((line, index) => index > 0 && line === "---");
555
+ return frontmatterEnd >= 0 && lines[frontmatterEnd + 1] === marker;
556
+ }
557
+
558
+ function assertGlobalOpenCodeFileWritable(path, marker, placement) {
559
+ if (!existsSync(path)) return;
560
+ const existing = readFileSync(path, "utf8");
561
+ if (!globalOpenCodeOwnershipMarkerIsValid(existing, marker, placement)) {
562
+ throw new Error(`Refusing to overwrite unowned global OpenCode file: ${path}`);
563
+ }
564
+ }
565
+
566
+ function assertGlobalOpenCodeSurfaceWritable(configDir) {
567
+ const paths = globalOpenCodeConfigPaths(configDir);
568
+ assertGlobalOpenCodeFileWritable(paths.instructions, globalOpenCodeInstructionsOwnershipMarker, "first-line");
569
+ assertGlobalOpenCodeFileWritable(paths.runtimeContract, globalOpenCodeRuntimeContractOwnershipMarker, "first-line");
570
+ for (const skillName of globalOpenCodeSkillNames) {
571
+ assertGlobalOpenCodeFileWritable(
572
+ join(paths.skills, skillName, "SKILL.md"),
573
+ `${globalOpenCodeSkillOwnershipMarker}${skillName} -->`,
574
+ "after-frontmatter",
575
+ );
576
+ }
577
+ }
578
+
579
+ function writeOwnedGlobalOpenCodeFile(path, content, marker, placement) {
580
+ if (existsSync(path)) {
581
+ assertGlobalOpenCodeFileWritable(path, marker, placement);
582
+ }
583
+ mkdirSync(dirname(path), { recursive: true });
584
+ writeFileSync(path, content, "utf8");
585
+ }
586
+
587
+ function globalOpenCodeBoundary() {
588
+ return [
589
+ "## Global OpenCode Surface Boundary",
590
+ "",
591
+ "This skill is globally discoverable, but global plugin or skill presence is not repository governance activation.",
592
+ "Before applying AGDF gates, later artefacts or implementation guidance, inspect the current repository for `.opencode/AGDF.md`, `.opencode/skills/agdf-gate-check/SKILL.md` and `.agdf/control/`.",
593
+ "If the repository surface is absent, stop and direct the user to `npx --yes @agdf/cli@latest opencode-repo` in this repository.",
594
+ "When the repository surface exists, its local instructions, native skills and `.agdf/control/` state are authoritative.",
595
+ "",
596
+ ].join("\n");
597
+ }
598
+
599
+ function toGlobalOpenCodeContent(content) {
600
+ let next = content;
601
+ for (const skill of pluginDefinition.skillSet) {
602
+ const localName = `${pluginDefinition.opencode.skillPrefix}${skill.slug}`;
603
+ const globalName = `${pluginDefinition.opencode.globalSkillPrefix}${skill.slug}`;
604
+ next = next.replaceAll(localName, globalName);
605
+ }
606
+ return next;
607
+ }
608
+
609
+ function installOpenCodeGlobalSurface(configDir) {
610
+ const paths = globalOpenCodeConfigPaths(configDir);
611
+ const generatedOpenCodeRoot = join(generatedRoot, ".opencode");
612
+ const generatedInstructions = readFileSync(join(generatedOpenCodeRoot, pluginDefinition.opencode.instructionsFileName), "utf8");
613
+ const generatedRuntimeContract = readFileSync(join(generatedOpenCodeRoot, pluginDefinition.opencode.runtimeContractFileName), "utf8");
614
+ const globalInstructions = [
615
+ globalOpenCodeInstructionsOwnershipMarker,
616
+ "# AGDF Global OpenCode instructions",
617
+ "",
618
+ "AGDF native skills are globally discoverable through OpenCode.",
619
+ "",
620
+ globalOpenCodeBoundary(),
621
+ "The repository-local `.opencode/AGDF.md`, `.opencode/skills/` and `.agdf/control/` files remain the source of truth for active governance.",
622
+ "",
623
+ toGlobalOpenCodeContent(generatedInstructions),
624
+ ].join("\n");
625
+ const globalRuntimeContract = `${globalOpenCodeRuntimeContractOwnershipMarker}\n${generatedRuntimeContract}`;
626
+
627
+ writeOwnedGlobalOpenCodeFile(paths.instructions, globalInstructions, globalOpenCodeInstructionsOwnershipMarker, "first-line");
628
+ writeOwnedGlobalOpenCodeFile(paths.runtimeContract, globalRuntimeContract, globalOpenCodeRuntimeContractOwnershipMarker, "first-line");
629
+
630
+ for (let index = 0; index < openCodeSkillNames.length; index += 1) {
631
+ const sourceName = openCodeSkillNames[index];
632
+ const skillName = globalOpenCodeSkillNames[index];
633
+ const sourcePath = join(generatedOpenCodeRoot, "skills", sourceName, "SKILL.md");
634
+ const sourceContent = readFileSync(sourcePath, "utf8");
635
+ const marker = `${globalOpenCodeSkillOwnershipMarker}${skillName} -->`;
636
+ const content = toGlobalOpenCodeContent(sourceContent).replace(/^(---[\s\S]*?\n---\n)/, `$1${marker}\n\n${globalOpenCodeBoundary()}`);
637
+ writeOwnedGlobalOpenCodeFile(join(paths.skills, skillName, "SKILL.md"), content, marker, "after-frontmatter");
638
+ }
639
+
640
+ return {
641
+ instructions: paths.instructions,
642
+ runtimeContract: paths.runtimeContract,
643
+ skills: paths.skills,
644
+ };
645
+ }
646
+
520
647
  function readOpenCodeConfig(configPath) {
521
648
  if (!existsSync(configPath)) return { exists: false, parseError: "", config: {} };
522
649
  try {
@@ -552,12 +679,27 @@ function resolveOpenCodePackage(configDir) {
552
679
  }
553
680
  }
554
681
 
682
+ function evaluateGlobalOpenCodeSurface(configDir) {
683
+ const paths = globalOpenCodeConfigPaths(configDir);
684
+ const skillCount = globalOpenCodeSkillNames.filter((skillName) => existsSync(join(paths.skills, skillName, "SKILL.md"))).length;
685
+ return {
686
+ path: paths.skills,
687
+ instructions: paths.instructions,
688
+ runtime_contract: paths.runtimeContract,
689
+ expected_skill_count: globalOpenCodeSkillNames.length,
690
+ skill_count: skillCount,
691
+ present: existsSync(paths.skills),
692
+ complete: existsSync(paths.instructions) && existsSync(paths.runtimeContract) && skillCount === openCodeSkillNames.length,
693
+ };
694
+ }
695
+
555
696
  function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir()) {
556
697
  const configPath = join(configDir, "opencode.json");
557
698
  const configState = readOpenCodeConfig(configPath);
558
699
  const plugins = Array.isArray(configState.config.plugin) ? configState.config.plugin : [];
559
700
  const globalConfigured = plugins.includes(pluginDefinition.opencode.npmPackage);
560
701
  const packageState = resolveOpenCodePackage(configDir);
702
+ const globalNativeSurface = evaluateGlobalOpenCodeSurface(configDir);
561
703
  const sessionSignals = {
562
704
  active: process.env.AGDF_PLUGIN_ACTIVE === "1",
563
705
  version: process.env.AGDF_PLUGIN_VERSION || "",
@@ -572,6 +714,7 @@ function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir(
572
714
  if (configState.parseError) findings.push(`OpenCode global config is not valid JSON: ${configState.parseError}`);
573
715
  if (!globalConfigured) findings.push(`OpenCode global config does not include ${pluginDefinition.opencode.npmPackage}.`);
574
716
  if (!packageState.loadable) findings.push(`${pluginDefinition.opencode.npmPackage} is not loadable from the OpenCode config directory.`);
717
+ if (!globalNativeSurface.complete) findings.push(`Global OpenCode native skill surface is incomplete (${globalNativeSurface.skill_count}/${globalNativeSurface.expected_skill_count} skills).`);
575
718
  if (!sessionSignals.active) findings.push("No active AGDF OpenCode session signal is visible in this process.");
576
719
  if (!repositorySurface) findings.push("Current repository does not contain the AGDF OpenCode surface.");
577
720
 
@@ -590,6 +733,7 @@ function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir(
590
733
  resolved_path: packageState.path,
591
734
  error: packageState.error,
592
735
  },
736
+ global_native_surface: globalNativeSurface,
593
737
  session: sessionSignals,
594
738
  repository_surface: {
595
739
  path: targetDir,
@@ -600,7 +744,9 @@ function evaluateOpenCodeStatus(targetDir, configDir = defaultOpenCodeConfigDir(
600
744
  },
601
745
  visible_entrypoint: repositorySurface ? `${pluginDefinition.opencode.skillPrefix}gate-check (native skill)` : "none until opencode-repo is installed for this repository",
602
746
  findings,
603
- next_step: repositorySurface
747
+ next_step: !globalNativeSurface.complete
748
+ ? "Run npx --yes @agdf/cli@latest opencode to install or repair the global native OpenCode skill surface."
749
+ : repositorySurface
604
750
  ? `Restart OpenCode if needed, then load ${pluginDefinition.opencode.skillPrefix}gate-check through the native skill tool for new build/change intent.`
605
751
  : "Run npx --yes @agdf/cli@latest opencode-repo in repositories where AGDF governance should be active and reviewable.",
606
752
  };
@@ -618,6 +764,8 @@ function printOpenCodeStatus(report, json) {
618
764
  if (report.global_config.parse_error) console.log(`Config parse error: ${report.global_config.parse_error}`);
619
765
  console.log(`Package loadable: ${report.package.loadable ? "yes" : "no"}`);
620
766
  if (report.package.resolved_path) console.log(`Package path: ${report.package.resolved_path}`);
767
+ console.log(`Global native skills: ${report.global_native_surface.complete ? "complete" : "incomplete"} (${report.global_native_surface.skill_count}/${report.global_native_surface.expected_skill_count})`);
768
+ console.log(`Global skill path: ${report.global_native_surface.path}`);
621
769
  console.log(`Session active signal: ${report.session.active ? "yes" : "no"}`);
622
770
  if (report.session.version) console.log(`Session plugin version: ${report.session.version}`);
623
771
  if (report.session.control_dir) console.log(`Session control dir: ${report.session.control_dir}`);
@@ -2497,6 +2645,7 @@ async function main() {
2497
2645
  const configDir = options.dirExplicit ? options.dir : defaultOpenCodeConfigDir();
2498
2646
  try {
2499
2647
  const result = installOpenCodeGlobalPlugin(configDir);
2648
+ installOpenCodeGlobalSurface(configDir);
2500
2649
  console.log(`AGDF OpenCode global plugin ${result.added ? "installed" : "already present"}: ${result.configPath}`);
2501
2650
  const report = evaluateOpenCodeStatus(options.dir, configDir);
2502
2651
  printOpenCodeStatus(report, false);
@@ -101,13 +101,13 @@ For relevant runs that change durable state, code, artefacts or gate status:
101
101
  ## OpenCode Files
102
102
 
103
103
  - OpenCode loads this file through `opencode.json` `instructions`.
104
- - AGDF for OpenCode has two layers: an optional global npm plugin hook and this repository-local governance surface.
105
- - The global plugin hook does not replace this file, `.opencode/skills/` or `.agdf/control/`; repository files remain the AGDF source of truth.
104
+ - AGDF for OpenCode has a global npm/native-skill discoverability layer and this repository-local governance surface.
105
+ - The global plugin and skills do not replace this file, `.opencode/skills/` or `.agdf/control/`; repository files remain the AGDF source of truth.
106
106
  - Native OpenCode skills live under `.opencode/skills/` and use the `agdf-` prefix.
107
107
  - The generated AGDF skills are loaded on demand through OpenCode's native `skill` tool; they are not parallel subagents or primary menu agents.
108
108
  - For new build/change intent or unclear approval, load the `agdf-gate-check` skill before later artefacts or implementation.
109
109
  - The AGDF OpenCode plugin is loaded from npm through `opencode.json` `plugin: ["create-agdf"]`.
110
- - Use `npx --yes @agdf/cli@latest opencode-status --json` to verify global config, package loadability, active session signals and repository surface presence separately.
111
- - OpenCode permissions keep `edit` and `bash` on explicit approval and allow the generated `agdf-*` skills explicitly.
110
+ - Use `npx --yes @agdf/cli@latest opencode-status --json` to verify global config, package loadability, global native-skill completeness, active session signals and repository surface presence separately.
111
+ - OpenCode permissions keep `edit` and `bash` on explicit approval and allow the generated `agdf-*` skills explicitly; global adapters use the `agdf-global-*` namespace.
112
112
  - Shared output and gate rules live in `.opencode/agdf-runtime-contract.md`.
113
113
  - 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,12 +3,12 @@
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/skills/` or `.agdf/control/`; repository files remain the AGDF source of truth.
8
- - `opencode.json` keeps `edit` and `bash` on `ask` and explicitly allows the generated `agdf-*` skills.
6
+ - AGDF for OpenCode has a global npm/native-skill discoverability layer and this repository-local governance surface.
7
+ - The global plugin and skills do not replace `.opencode/AGDF.md`, `.opencode/skills/` or `.agdf/control/`; repository files remain the AGDF source of truth.
8
+ - `opencode.json` keeps `edit` and `bash` on `ask` and explicitly allows the generated `agdf-*` skills; global adapters use `agdf-global-*` to avoid same-name masking.
9
9
  - `.opencode/skills/` contains native OpenCode skills generated from the canonical AGDF skills.
10
10
  - For new build/change intent or unclear approval, load `agdf-gate-check` through OpenCode's native `skill` tool.
11
- - Use `npx --yes @agdf/cli@latest opencode-status --json` to distinguish global hook configuration, package loadability, session activity and this repository surface.
11
+ - Use `npx --yes @agdf/cli@latest opencode-status --json` to distinguish global hook/native-skill configuration, package loadability, session activity and this repository surface.
12
12
  - Use `npx --yes @agdf/cli@latest gate-check --status-card` for compact interactive gate state; reserve full `--json` output for automation or audit evidence.
13
13
  - `.opencode/agdf-runtime-contract.md` is the shared gate and output contract.
14
14
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "description": "Codex-first operating system for governed AI-assisted delivery.",
5
5
  "author": {
6
6
  "name": "Arndt Gold",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "agdf",
4
- "version": "0.6.8",
4
+ "version": "0.6.9",
5
5
  "displayName": "AI Governance & Delivery Framework",
6
6
  "developerName": "Arndt Gold",
7
7
  "description": "Codex-first operating system for governed AI-assisted delivery.",
@@ -52,6 +52,7 @@
52
52
  },
53
53
  "opencode": {
54
54
  "skillPrefix": "agdf-",
55
+ "globalSkillPrefix": "agdf-global-",
55
56
  "runtimeContractFileName": "agdf-runtime-contract.md",
56
57
  "instructionsFileName": "AGDF.md",
57
58
  "npmPackage": "create-agdf",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
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": [