create-agdf 0.13.8 → 0.14.2

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.
Files changed (134) hide show
  1. package/README.md +14 -10
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -4
  4. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +26 -2
  5. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +7 -0
  6. package/generated/plugins/agdf/runtime/agdf-local.js +1 -1
  7. package/generated/plugins/agdf/runtime/agdf-session-check.js +10 -5
  8. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +26 -2
  9. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +6 -7
  10. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +29 -17
  11. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +50 -1
  12. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +3 -1
  13. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  14. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  15. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +32 -3
  16. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  17. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  18. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  19. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  20. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +771 -0
  21. package/generated/plugins/copilot/agdf/LICENSE +201 -0
  22. package/generated/plugins/copilot/agdf/hooks/copilot-hooks.json +15 -0
  23. package/generated/{AGENTS.md → plugins/copilot/agdf/meta/agdf-agent-router.md} +49 -33
  24. package/generated/plugins/copilot/agdf/meta/agdf-constitution.md +329 -0
  25. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +331 -0
  26. package/generated/plugins/copilot/agdf/meta/agdf-runtime-contract.md +16 -0
  27. package/generated/plugins/copilot/agdf/plugin.json +22 -0
  28. package/generated/plugins/copilot/agdf/runtime/agdf-local.js +18 -0
  29. package/generated/plugins/copilot/agdf/runtime/agdf-session-check.js +97 -0
  30. package/generated/plugins/copilot/agdf/runtime/create-agdf/NOTICE +10 -0
  31. package/generated/plugins/copilot/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
  32. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +512 -0
  33. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +331 -0
  34. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +144 -0
  35. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +139 -0
  36. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +173 -0
  37. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
  38. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +46 -0
  39. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +301 -0
  40. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +272 -0
  41. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +455 -0
  42. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +305 -0
  43. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
  44. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
  45. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
  46. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +345 -0
  47. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
  48. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
  49. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
  50. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
  51. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
  52. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +265 -0
  53. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
  54. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
  55. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
  56. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
  57. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
  58. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +35 -0
  59. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +44 -0
  60. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
  61. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
  62. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
  63. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
  64. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
  65. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
  66. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
  67. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
  68. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +155 -0
  69. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
  70. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +27 -0
  71. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
  72. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +842 -0
  73. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/local-validator.js +239 -0
  74. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +255 -0
  75. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
  76. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +73 -0
  77. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +6 -0
  78. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +8 -0
  79. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -2
  80. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +26 -2
  81. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +7 -0
  82. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  83. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  84. package/generated/submissions/openai/agdf/submission/openai/inventory.json +13 -9
  85. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  86. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  87. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  88. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  89. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  90. package/lib/cli/application.js +64 -8
  91. package/lib/cli/command-registry.js +6 -7
  92. package/lib/installers/copilot-precedence.js +34 -0
  93. package/lib/installers/copilot-settings.js +84 -0
  94. package/lib/installers/local-marketplace.js +112 -30
  95. package/lib/installers/plugin-installers.js +184 -5
  96. package/lib/lifecycle/operations.js +3 -0
  97. package/lib/lifecycle/result.js +1 -0
  98. package/lib/lifecycle/status.js +3 -3
  99. package/lib/public-plugin/copilot-profile.js +126 -0
  100. package/lib/public-plugin/manifest.js +34 -2
  101. package/lib/public-plugin/validator.js +1 -1
  102. package/lib/release/version-coherence.js +4 -0
  103. package/lib/runtime/local-validator.js +29 -17
  104. package/lib/runtime/plugin-provenance.js +50 -1
  105. package/lib/runtime-check-consent/contract.js +3 -1
  106. package/lib/runtime-check-consent/coordinator.js +1 -0
  107. package/lib/runtime-check-consent/service.js +1 -1
  108. package/lib/runtime-check-consent/state.js +3 -3
  109. package/lib/scaffold/plan.js +3 -89
  110. package/lib/scaffold/presentation.js +3 -22
  111. package/package.json +6 -3
  112. package/generated/.github/copilot-instructions.md +0 -16
  113. package/generated/.github/instructions/agdf-governance.instructions.md +0 -14
  114. package/generated/.github/skills/README.md +0 -20
  115. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-brownfield-analysis/SKILL.md +0 -0
  116. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-clean-implementation-review/SKILL.md +0 -0
  117. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-code-review/SKILL.md +0 -0
  118. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-delivery-closeout/SKILL.md +0 -0
  119. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-delivery-path-search/SKILL.md +0 -0
  120. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-gate-check/SKILL.md +0 -0
  121. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-interaction-locales.json +0 -0
  122. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-qa-gate/SKILL.md +0 -0
  123. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-release-or/SKILL.md +0 -0
  124. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-runtime-contract.md +0 -0
  125. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-task-plan-review/SKILL.md +0 -0
  126. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-ux-intent-definition/SKILL.md +0 -0
  127. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/closeout.md +0 -0
  128. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/context-graph.md +0 -0
  129. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/control-scaffold.md +0 -0
  130. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/gate-transition.md +0 -0
  131. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/interaction.md +0 -0
  132. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/modes.md +0 -0
  133. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/quality.md +0 -0
  134. /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/task-target-resolution.md +0 -0
@@ -0,0 +1,126 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
3
+ import { join, relative } from "node:path";
4
+
5
+ export const COPILOT_PROFILE_ID = "copilot-runtime-plugin";
6
+ export const COPILOT_INVENTORY_FILE = ".agdf-payload-inventory.json";
7
+
8
+ function sha256(content) {
9
+ return createHash("sha256").update(content).digest("hex");
10
+ }
11
+
12
+ function filesUnder(root) {
13
+ const files = [];
14
+ function visit(directory) {
15
+ for (const name of readdirSync(directory).sort()) {
16
+ const path = join(directory, name);
17
+ const stats = statSync(path);
18
+ if (stats.isDirectory()) visit(path);
19
+ else if (stats.isFile()) files.push(path);
20
+ }
21
+ }
22
+ visit(root);
23
+ return files;
24
+ }
25
+
26
+ export function payloadInventoryDigest(inventory) {
27
+ return sha256(`${JSON.stringify(inventory, null, 2)}\n`);
28
+ }
29
+
30
+ export function buildCopilotPayloadInventory({ profileRoot, mappings, version, baseline }) {
31
+ const files = filesUnder(profileRoot)
32
+ .map((path) => ({ path, relativePath: relative(profileRoot, path).replaceAll("\\", "/") }))
33
+ .filter(({ relativePath }) => relativePath !== COPILOT_INVENTORY_FILE);
34
+ const byDestination = new Map(mappings.map((entry) => [entry.destination, entry]));
35
+ const unmapped = files.filter(({ relativePath }) => !byDestination.has(relativePath));
36
+ if (unmapped.length) throw new Error(`AGDF_COPILOT_PAYLOAD_UNMAPPED: ${unmapped.map(({ relativePath }) => relativePath).join(", ")}`);
37
+ const missing = mappings.filter(({ destination }) => !files.some(({ relativePath }) => relativePath === destination));
38
+ if (missing.length) throw new Error(`AGDF_COPILOT_PAYLOAD_MISSING: ${missing.map(({ destination }) => destination).join(", ")}`);
39
+ if (new Set(mappings.map(({ destination }) => destination)).size !== mappings.length) {
40
+ throw new Error("AGDF_COPILOT_PAYLOAD_DUPLICATE_DESTINATION");
41
+ }
42
+ const entries = files.map(({ path, relativePath }) => {
43
+ const mapping = byDestination.get(relativePath);
44
+ const content = readFileSync(path);
45
+ return {
46
+ destination: relativePath,
47
+ component: mapping.component,
48
+ owner: mapping.owner,
49
+ rule: mapping.rule,
50
+ requirement: mapping.requirement,
51
+ ...(mapping.source ? { source: mapping.source } : {}),
52
+ ...(mapping.sourceDigest ? { source_digest: mapping.sourceDigest } : {}),
53
+ digest: sha256(content),
54
+ bytes: content.byteLength,
55
+ };
56
+ });
57
+ const totalBytes = entries.reduce((sum, entry) => sum + entry.bytes, 0);
58
+ const inventory = {
59
+ schema_version: 1,
60
+ profile_id: COPILOT_PROFILE_ID,
61
+ version,
62
+ baseline,
63
+ stats: { files: entries.length, bytes: totalBytes },
64
+ entries,
65
+ };
66
+ writeFileSync(join(profileRoot, COPILOT_INVENTORY_FILE), `${JSON.stringify(inventory, null, 2)}\n`, "utf8");
67
+ return inventory;
68
+ }
69
+
70
+ export function validateCopilotPayload({ profileRoot, repoRoot, expectedVersion, expectedSkills, baseline }) {
71
+ const inventoryPath = join(profileRoot, COPILOT_INVENTORY_FILE);
72
+ if (!existsSync(inventoryPath)) throw new Error("AGDF_COPILOT_PAYLOAD_INVENTORY_MISSING");
73
+ let inventory;
74
+ try { inventory = JSON.parse(readFileSync(inventoryPath, "utf8")); } catch {
75
+ throw new Error("AGDF_COPILOT_PAYLOAD_INVENTORY_INVALID");
76
+ }
77
+ if (inventory.schema_version !== 1 || inventory.profile_id !== COPILOT_PROFILE_ID || inventory.version !== expectedVersion) {
78
+ throw new Error("AGDF_COPILOT_PAYLOAD_INVENTORY_INVALID");
79
+ }
80
+ const actualFiles = filesUnder(profileRoot)
81
+ .map((path) => relative(profileRoot, path).replaceAll("\\", "/"))
82
+ .filter((path) => path !== COPILOT_INVENTORY_FILE);
83
+ const entries = Array.isArray(inventory.entries) ? inventory.entries : [];
84
+ if (new Set(entries.map(({ destination }) => destination)).size !== entries.length) {
85
+ throw new Error("AGDF_COPILOT_PAYLOAD_DUPLICATE_DESTINATION");
86
+ }
87
+ const mapped = new Set(entries.map(({ destination }) => destination));
88
+ const unmapped = actualFiles.filter((path) => !mapped.has(path));
89
+ if (unmapped.length) throw new Error(`AGDF_COPILOT_PAYLOAD_UNMAPPED: ${unmapped.join(", ")}`);
90
+ const missing = entries.filter(({ destination }) => !actualFiles.includes(destination));
91
+ if (missing.length) throw new Error(`AGDF_COPILOT_PAYLOAD_MISSING: ${missing.map(({ destination }) => destination).join(", ")}`);
92
+ for (const entry of entries) {
93
+ const content = readFileSync(join(profileRoot, entry.destination));
94
+ if (sha256(content) !== entry.digest || content.byteLength !== entry.bytes) {
95
+ throw new Error(`AGDF_COPILOT_PAYLOAD_DIGEST_MISMATCH: ${entry.destination}`);
96
+ }
97
+ if (repoRoot && entry.source) {
98
+ const source = readFileSync(join(repoRoot, entry.source));
99
+ if (sha256(source) !== entry.source_digest) {
100
+ throw new Error(`AGDF_COPILOT_PAYLOAD_STALE_SOURCE: ${entry.destination}`);
101
+ }
102
+ }
103
+ }
104
+ const excluded = actualFiles.filter((path) => path === "skills" || path.startsWith("skills/")
105
+ || path.startsWith(".codex-plugin/") || path.startsWith(".claude-plugin/")
106
+ || path === "hooks/hooks.json" || path === "hooks/session-start.sh"
107
+ || path.startsWith("submission/"));
108
+ if (excluded.length) throw new Error(`AGDF_COPILOT_PAYLOAD_EXCLUDED_SURFACE: ${excluded.join(", ")}`);
109
+ const skillFiles = actualFiles.filter((path) => /^copilot-skills\/agdf-[^/]+\/SKILL\.md$/.test(path));
110
+ const expectedSkillFiles = expectedSkills.map((slug) => `copilot-skills/agdf-${slug}/SKILL.md`).sort();
111
+ if (JSON.stringify(skillFiles.sort()) !== JSON.stringify(expectedSkillFiles)) {
112
+ throw new Error("AGDF_COPILOT_PAYLOAD_SKILL_SET_MISMATCH");
113
+ }
114
+ const stats = {
115
+ files: entries.length,
116
+ bytes: entries.reduce((sum, entry) => sum + entry.bytes, 0),
117
+ };
118
+ if (stats.files > baseline.max_files || stats.bytes > baseline.max_bytes) {
119
+ throw new Error(`AGDF_COPILOT_PAYLOAD_GROWTH: observed ${stats.files} files/${stats.bytes} bytes; baseline ${baseline.max_files}/${baseline.max_bytes}`);
120
+ }
121
+ if (inventory.stats?.files !== stats.files || inventory.stats?.bytes !== stats.bytes
122
+ || inventory.baseline?.max_files !== baseline.max_files || inventory.baseline?.max_bytes !== baseline.max_bytes) {
123
+ throw new Error("AGDF_COPILOT_PAYLOAD_BASELINE_MISMATCH");
124
+ }
125
+ return { inventory, inventoryDigest: payloadInventoryDigest(inventory), stats };
126
+ }
@@ -39,14 +39,12 @@ export function createCodexPluginManifest(definition, { publicCandidate = false
39
39
  websiteURL: distribution.urls.website,
40
40
  privacyPolicyURL: distribution.urls.privacy,
41
41
  termsOfServiceURL: distribution.urls.terms,
42
- supportURL: distribution.urls.support,
43
42
  composerIcon: definition.codex.composerIcon,
44
43
  logo: definition.codex.logo,
45
44
  defaultPrompt: pluginInterface.defaultPrompt,
46
45
  brandColor: definition.brandColor,
47
46
  },
48
47
  };
49
- if (!publicCandidate) manifest.hooks = `./${definition.codex.hooks}`;
50
48
  return manifest;
51
49
  }
52
50
 
@@ -70,3 +68,37 @@ export function createClaudePluginManifest(definition) {
70
68
  export function renderClaudePluginManifest(definition) {
71
69
  return `${JSON.stringify(createClaudePluginManifest(definition), null, 2)}\n`;
72
70
  }
71
+
72
+ function requireCopilotPath(value, field) {
73
+ if (typeof value !== "string" || !value || value.startsWith("/") || value.includes("..") || value.includes("\\")) {
74
+ throw new Error(`AGDF_COPILOT_PLUGIN_CONTRACT_INVALID: ${field} must be a relative POSIX path`);
75
+ }
76
+ return value;
77
+ }
78
+
79
+ export function createCopilotPluginManifest(definition) {
80
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(definition.id ?? "") || definition.id.length > 64) {
81
+ throw new Error("AGDF_COPILOT_PLUGIN_CONTRACT_INVALID: kebab-case name is required");
82
+ }
83
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(definition.version ?? "")) {
84
+ throw new Error("AGDF_COPILOT_PLUGIN_CONTRACT_INVALID: semantic version is required");
85
+ }
86
+ const copilot = definition.copilot ?? {};
87
+ return {
88
+ name: definition.id,
89
+ version: definition.version,
90
+ description: definition.description,
91
+ author: definition.author,
92
+ homepage: definition.homepage,
93
+ repository: definition.repository,
94
+ license: definition.license,
95
+ keywords: definition.keywords,
96
+ category: definition.category,
97
+ skills: requireCopilotPath(copilot.skills, "skills"),
98
+ hooks: requireCopilotPath(copilot.hooks, "hooks"),
99
+ };
100
+ }
101
+
102
+ export function renderCopilotPluginManifest(definition) {
103
+ return `${JSON.stringify(createCopilotPluginManifest(definition), null, 2)}\n`;
104
+ }
@@ -80,7 +80,7 @@ export function validateCandidate(root) {
80
80
  if (unicodeLength(manifest.interface?.developerName) > LISTING_LIMITS.developerName) throw new Error("AGDF_PUBLIC_PLUGIN_LISTING_LIMIT_EXCEEDED: developerName");
81
81
  const prompts = manifest.interface?.defaultPrompt ?? [];
82
82
  if (prompts.length !== LISTING_LIMITS.promptCount || prompts.some((prompt) => unicodeLength(prompt) > LISTING_LIMITS.promptLength)) throw new Error("AGDF_PUBLIC_PLUGIN_LISTING_LIMIT_EXCEEDED: defaultPrompt");
83
- for (const field of ["websiteURL", "privacyPolicyURL", "termsOfServiceURL", "supportURL"]) {
83
+ for (const field of ["websiteURL", "privacyPolicyURL", "termsOfServiceURL"]) {
84
84
  let url;
85
85
  try { url = new URL(manifest.interface?.[field]); } catch { throw new Error(`AGDF_PUBLIC_PLUGIN_CONTRACT_INVALID: ${field}`); }
86
86
  if (url.protocol !== "https:") throw new Error(`AGDF_PUBLIC_PLUGIN_CONTRACT_INVALID: ${field} must use HTTPS`);
@@ -34,6 +34,10 @@ const VERSION_SURFACES = [
34
34
  jsonVersion("create-agdf/generated/plugins/agdf/.claude-plugin/plugin.json"),
35
35
  jsonVersion("create-agdf/generated/plugins/agdf/runtime/runtime-manifest.json"),
36
36
  jsonVersion("create-agdf/generated/plugins/agdf/runtime/create-agdf/package.json"),
37
+ jsonVersion("create-agdf/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json"),
38
+ jsonVersion("create-agdf/generated/plugins/copilot/agdf/plugin.json"),
39
+ jsonVersion("create-agdf/generated/plugins/copilot/agdf/runtime/runtime-manifest.json"),
40
+ jsonVersion("create-agdf/generated/plugins/copilot/agdf/runtime/create-agdf/package.json"),
37
41
  jsonVersion("create-agdf/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json"),
38
42
  jsonVersion("create-agdf/generated/submissions/openai/agdf/.codex-plugin/plugin.json"),
39
43
  jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/capability-matrix.json", (value) => value.releaseVersion),
@@ -5,6 +5,7 @@ import process from "node:process";
5
5
  import {
6
6
  INSTALLATION_PROVENANCE_FILE,
7
7
  digestDirectory,
8
+ inspectCopilotPayloadInventory,
8
9
  inspectGeneratedRepositoryMarketplace,
9
10
  inspectInstallationProvenance,
10
11
  validateDistributionProfiles,
@@ -83,41 +84,52 @@ export function resolveLocalValidator(options) {
83
84
  }
84
85
  const codexManifest = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
85
86
  const claudeManifest = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"));
86
- const pluginVersion = codexManifest?.version ?? null;
87
- if (!codexManifest || !claudeManifest || claudeManifest.version !== definition.version) {
88
- return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile: "runtime-plugin", provenanceStatus: "invalid", reason: "manifest_invalid" }) };
87
+ const copilotManifest = readJson(join(pluginRoot, "plugin.json"));
88
+ const copilotProfile = Boolean(copilotManifest && !codexManifest && !claudeManifest);
89
+ const distributionProfile = copilotProfile ? "copilot-runtime-plugin" : "runtime-plugin";
90
+ const pluginVersion = copilotProfile ? copilotManifest?.version ?? null : codexManifest?.version ?? null;
91
+ if (copilotProfile
92
+ ? copilotManifest.version !== definition.version
93
+ : (!codexManifest || !claudeManifest || claudeManifest.version !== definition.version)) {
94
+ return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile, provenanceStatus: "invalid", reason: "manifest_invalid" }) };
95
+ }
96
+ const copilotInventory = copilotProfile ? inspectCopilotPayloadInventory(pluginRoot, definition.version) : null;
97
+ if (copilotProfile && copilotInventory.status !== "matched") {
98
+ return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile, provenanceStatus: "invalid", reason: copilotInventory.reason }) };
89
99
  }
90
100
  const packageRoot = join(options.runtimeRoot, "create-agdf");
91
101
  if (!existsSync(packageRoot)) {
92
- return { envelope: envelope("unavailable", options, { source: "plugin_bundle", pluginRoot, pluginVersion, distributionProfile: "runtime-plugin", reason: "runtime_missing" }) };
102
+ return { envelope: envelope("unavailable", options, { source: "plugin_bundle", pluginRoot, pluginVersion, distributionProfile, reason: "runtime_missing" }) };
93
103
  }
94
104
  const packageManifest = readJson(join(packageRoot, "package.json"));
95
105
  const observedVersion = packageManifest?.version ?? manifest.version ?? null;
96
106
  if (observedVersion !== options.expectedVersion || manifest.version !== options.expectedVersion) {
97
- return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile: "runtime-plugin" }) };
107
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile }) };
98
108
  }
99
109
  let observedDigest = null;
100
110
  try { observedDigest = digestDirectory(packageRoot); } catch {}
101
111
  if (!observedDigest || manifest.digest !== observedDigest) {
102
- return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "runtime_digest_mismatch" }) };
112
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "runtime_digest_mismatch" }) };
103
113
  }
104
114
  const entrypoint = resolve(options.runtimeRoot, manifest.entrypoint ?? "");
105
115
  const entrypointRelative = relative(options.runtimeRoot, entrypoint);
106
116
  if (!manifest.entrypoint || entrypointRelative === ".." || entrypointRelative.startsWith(`..${sep}`) || isAbsolute(entrypointRelative)) {
107
- return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "invalid_entrypoint" }) };
117
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "invalid_entrypoint" }) };
108
118
  }
109
119
  if (!existsSync(entrypoint)) {
110
- return { envelope: envelope("unavailable", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "entrypoint_missing" }) };
120
+ return { envelope: envelope("unavailable", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "entrypoint_missing" }) };
111
121
  }
112
122
  const installed = existsSync(join(pluginRoot, INSTALLATION_PROVENANCE_FILE));
113
123
  let provenanceStatus = "not_applicable";
114
124
  let sourceDigest = null;
115
- let evidencePlane = "loaded_session";
125
+ let evidencePlane = options.expectedPluginRoot ? "loaded_session" : "installed_plugin_root";
116
126
  if (installed) {
117
127
  const provenance = inspectInstallationProvenance(pluginRoot, {
118
128
  definition,
119
129
  runtimeManifest: manifest,
120
130
  pluginVersion,
131
+ profileId: distributionProfile,
132
+ inventoryDigest: copilotInventory?.inventoryDigest ?? null,
121
133
  });
122
134
  provenanceStatus = provenance.status;
123
135
  sourceDigest = provenance.marker?.source_digest ?? null;
@@ -130,8 +142,8 @@ export function resolveLocalValidator(options) {
130
142
  canonicalVersion: definition.version,
131
143
  runtimeDigest: observedDigest,
132
144
  sourceDigest,
133
- distributionProfile: "runtime-plugin",
134
- evidencePlane: "loaded_session",
145
+ distributionProfile,
146
+ evidencePlane,
135
147
  provenanceStatus,
136
148
  reason: provenance.reason,
137
149
  }) };
@@ -144,16 +156,16 @@ export function resolveLocalValidator(options) {
144
156
  pluginVersion,
145
157
  canonicalVersion: definition.version,
146
158
  runtimeDigest: observedDigest,
147
- distributionProfile: "runtime-plugin",
159
+ distributionProfile,
148
160
  evidencePlane: "loaded_session",
149
161
  provenanceStatus: "missing",
150
162
  reason: "installation_provenance_missing",
151
163
  }) };
152
164
  } else {
153
- const generatedRepository = inspectGeneratedRepositoryMarketplace(resolve(pluginRoot, "..", ".."));
165
+ const generatedRepository = copilotProfile ? null : inspectGeneratedRepositoryMarketplace(resolve(pluginRoot, "..", ".."));
154
166
  if (pluginVersion !== definition.version
155
- || generatedRepository.status !== "matched"
156
- || canonicalPath(generatedRepository.pluginRoot) !== pluginRoot) {
167
+ || (!copilotProfile && (generatedRepository.status !== "matched"
168
+ || canonicalPath(generatedRepository.pluginRoot) !== pluginRoot))) {
157
169
  return { envelope: envelope("unavailable", options, {
158
170
  observedVersion,
159
171
  source: "plugin_bundle",
@@ -161,7 +173,7 @@ export function resolveLocalValidator(options) {
161
173
  pluginVersion,
162
174
  canonicalVersion: definition.version,
163
175
  runtimeDigest: observedDigest,
164
- distributionProfile: "runtime-plugin",
176
+ distributionProfile,
165
177
  evidencePlane: "installed_plugin_root",
166
178
  provenanceStatus: "missing",
167
179
  reason: "installation_provenance_missing",
@@ -178,7 +190,7 @@ export function resolveLocalValidator(options) {
178
190
  canonicalVersion: definition.version,
179
191
  runtimeDigest: observedDigest,
180
192
  sourceDigest,
181
- distributionProfile: "runtime-plugin",
193
+ distributionProfile,
182
194
  evidencePlane,
183
195
  provenanceStatus,
184
196
  }),
@@ -4,10 +4,12 @@ import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
 
5
5
  export const INSTALLATION_PROVENANCE_FILE = ".agdf-installation.json";
6
6
  export const LEGACY_LOCAL_INSTALL_FILE = ".agdf-local-install.json";
7
+ export const COPILOT_PAYLOAD_INVENTORY_FILE = ".agdf-payload-inventory.json";
7
8
 
8
9
  const EXPECTED_PROFILES = Object.freeze({
9
10
  "source-development": Object.freeze({ runtime: "absent", installable: false, machineValidation: "unavailable" }),
10
11
  "runtime-plugin": Object.freeze({ runtime: "required", installable: true, machineValidation: "local_exact_version_digest" }),
12
+ "copilot-runtime-plugin": Object.freeze({ runtime: "required", installable: true, machineValidation: "local_exact_version_digest_inventory" }),
11
13
  "opencode-config-local": Object.freeze({ runtime: "config_local_package", installable: true, machineValidation: "local_exact_version" }),
12
14
  "portable-skills": Object.freeze({ runtime: "absent", installable: true, machineValidation: "unavailable_or_external_required" }),
13
15
  });
@@ -41,6 +43,50 @@ export function digestDirectory(root) {
41
43
  return hash.digest("hex");
42
44
  }
43
45
 
46
+ export function digestFile(path) {
47
+ return createHash("sha256").update(readFileSync(path)).digest("hex");
48
+ }
49
+
50
+ export function inspectCopilotPayloadInventory(pluginRoot, expectedVersion) {
51
+ const inventoryPath = join(pluginRoot, COPILOT_PAYLOAD_INVENTORY_FILE);
52
+ const inventory = readJson(inventoryPath);
53
+ if (!inventory || inventory.schema_version !== 1 || inventory.profile_id !== "copilot-runtime-plugin"
54
+ || inventory.version !== expectedVersion || !Array.isArray(inventory.entries)) {
55
+ return { status: "invalid", reason: "copilot_payload_inventory_invalid" };
56
+ }
57
+ const destinations = inventory.entries.map((entry) => entry.destination);
58
+ if (new Set(destinations).size !== destinations.length) {
59
+ return { status: "invalid", reason: "copilot_payload_inventory_duplicate" };
60
+ }
61
+ const actual = [];
62
+ function visit(directory) {
63
+ for (const name of readdirSync(directory).sort()) {
64
+ const path = join(directory, name);
65
+ const stats = statSync(path);
66
+ if (stats.isDirectory()) visit(path);
67
+ else if (stats.isFile()) {
68
+ const normalized = relative(pluginRoot, path).replaceAll("\\", "/");
69
+ if (![COPILOT_PAYLOAD_INVENTORY_FILE, INSTALLATION_PROVENANCE_FILE, LEGACY_LOCAL_INSTALL_FILE].includes(normalized)) actual.push(normalized);
70
+ }
71
+ }
72
+ }
73
+ try { visit(pluginRoot); } catch { return { status: "invalid", reason: "copilot_payload_incomplete" }; }
74
+ if (JSON.stringify(actual.sort()) !== JSON.stringify([...destinations].sort())) {
75
+ return { status: "invalid", reason: "copilot_payload_inventory_mismatch" };
76
+ }
77
+ for (const entry of inventory.entries) {
78
+ const path = join(pluginRoot, entry.destination);
79
+ if (!existsSync(path) || digestFile(path) !== entry.digest || statSync(path).size !== entry.bytes) {
80
+ return { status: "invalid", reason: "copilot_payload_digest_mismatch", entry: entry.destination };
81
+ }
82
+ }
83
+ const excluded = actual.some((path) => path.startsWith("skills/") || path.startsWith(".codex-plugin/")
84
+ || path.startsWith(".claude-plugin/") || path.startsWith("submission/")
85
+ || path === "hooks/hooks.json" || path === "hooks/session-start.sh");
86
+ if (excluded) return { status: "invalid", reason: "copilot_payload_excluded_surface" };
87
+ return { status: "matched", inventory, inventoryDigest: digestFile(inventoryPath) };
88
+ }
89
+
44
90
  export function digestNormalizedPluginSource(root, canonicalVersion) {
45
91
  const files = [];
46
92
  function visit(directory) {
@@ -148,6 +194,8 @@ export function inspectInstallationProvenance(pluginRoot, {
148
194
  runtimeManifest,
149
195
  pluginVersion,
150
196
  allowLegacy = false,
197
+ profileId = "runtime-plugin",
198
+ inventoryDigest = null,
151
199
  } = {}) {
152
200
  const markerPath = join(pluginRoot, INSTALLATION_PROVENANCE_FILE);
153
201
  const legacyPath = join(pluginRoot, LEGACY_LOCAL_INSTALL_FILE);
@@ -181,11 +229,12 @@ export function inspectInstallationProvenance(pluginRoot, {
181
229
  if (!marker
182
230
  || marker.schema_version !== 1
183
231
  || marker.owner !== "create-agdf"
184
- || marker.profile_id !== "runtime-plugin"
232
+ || marker.profile_id !== profileId
185
233
  || marker.marketplace_id !== profile.contract.marketplaceIdentities.durable
186
234
  || marker.canonical_version !== definition.version
187
235
  || marker.codex_install_version !== pluginVersion
188
236
  || marker.runtime_digest !== runtimeManifest?.digest
237
+ || (profileId === "copilot-runtime-plugin" && marker.inventory_digest !== inventoryDigest)
189
238
  || !/^[a-f0-9]{64}$/.test(marker.source_digest ?? "")) {
190
239
  return { status: "invalid", reason: "installation_provenance_invalid", marker };
191
240
  }
@@ -32,6 +32,7 @@ export function validateRuntimeCheckCapability(capability) {
32
32
  }
33
33
  const surfaces = capability.surfaces ?? {};
34
34
  if (surfaces.codex !== "native-hook-review" || surfaces.claude !== "exact-command-rule"
35
+ || surfaces.copilot !== "plugin-hook-review"
35
36
  || surfaces.opencode !== "plugin-internal"
36
37
  || surfaces["portable-skills"] !== "manual-external-required") {
37
38
  throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: surface contract");
@@ -41,7 +42,7 @@ export function validateRuntimeCheckCapability(capability) {
41
42
 
42
43
  export function runtimeCheckCapabilityIdentity({ capability, surface, runtimeDigest, sourceDigest, command }) {
43
44
  validateRuntimeCheckCapability(capability);
44
- if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_SURFACE_INVALID");
45
+ if (!["codex", "claude", "copilot", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_SURFACE_INVALID");
45
46
  for (const [name, value] of Object.entries({ runtimeDigest, sourceDigest })) {
46
47
  if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) throw new Error(`AGDF_RUNTIME_CHECK_IDENTITY_INVALID: ${name}`);
47
48
  }
@@ -59,6 +60,7 @@ export function runtimeCheckCapabilityIdentity({ capability, surface, runtimeDig
59
60
 
60
61
  export function fixedRuntimeCheckCommand(surface, pluginRoot, platform = process.platform) {
61
62
  if (surface === "opencode") return "plugin:agdf:automatic-runtime-checks";
63
+ if (surface === "copilot") return 'node "${PLUGIN_ROOT}/runtime/agdf-session-check.js"';
62
64
  if (surface === "codex" || surface === "claude") {
63
65
  return platform === "win32"
64
66
  ? "node \"$([Environment]::GetEnvironmentVariable('PLUGIN_ROOT') + [Environment]::GetEnvironmentVariable('CLAUDE_PLUGIN_ROOT'))\\runtime\\agdf-session-check.js\""
@@ -18,6 +18,7 @@ export function resolveRuntimeCheckDecision({ explicitValue, interactive = false
18
18
  export function consentDisclosure(surface) {
19
19
  const permissionOwner = surface === "codex" ? "Codex native hook trust"
20
20
  : surface === "claude" ? "Claude Code user permission settings"
21
+ : surface === "copilot" ? "GitHub Copilot plugin hook review"
21
22
  : "OpenCode plugin and explicit permission configuration";
22
23
  return Object.freeze({
23
24
  surface,
@@ -35,7 +35,7 @@ function prospectiveRuntimeCheckIdentity(surface, platform = process.platform) {
35
35
  command: fixedRuntimeCheckCommand(surface, installed.root, platform),
36
36
  });
37
37
  }
38
- if (!["codex", "claude"].includes(surface)) return null;
38
+ if (!["codex", "claude", "copilot"].includes(surface)) return null;
39
39
  const pluginRoot = join(generatedRoot, "plugins", "agdf");
40
40
  let runtimeManifest;
41
41
  try { runtimeManifest = JSON.parse(readFileSync(join(pluginRoot, "runtime", "runtime-manifest.json"), "utf8")); } catch { return null; }
@@ -4,12 +4,12 @@ import { dirname, join, resolve } from "node:path";
4
4
  import { renameSyncWithRetry } from "../fs-swap.js";
5
5
 
6
6
  export function runtimeCheckReceiptPath(dataRoot, surface) {
7
- if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
7
+ if (!["codex", "claude", "copilot", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
8
8
  return join(resolve(dataRoot), "runtime-checks", `${surface}.json`);
9
9
  }
10
10
 
11
11
  export function createRuntimeCheckReceipt({ surface, decision, capabilityIdentity, command }) {
12
- if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
12
+ if (!["codex", "claude", "copilot", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
13
13
  if (!["enable", "manual"].includes(decision)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_DECISION_INVALID");
14
14
  if (!/^[a-f0-9]{64}$/.test(capabilityIdentity)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_IDENTITY_INVALID");
15
15
  return Object.freeze({
@@ -26,7 +26,7 @@ export function createRuntimeCheckReceipt({ surface, decision, capabilityIdentit
26
26
  export function validateRuntimeCheckReceipt(receipt) {
27
27
  if (receipt?.schema_version !== 1 || receipt.owner !== "create-agdf"
28
28
  || receipt.capability_id !== "automatic-runtime-checks") return { status: "receipt_unowned", receipt: null };
29
- if (!["codex", "claude", "opencode"].includes(receipt.surface)
29
+ if (!["codex", "claude", "copilot", "opencode"].includes(receipt.surface)
30
30
  || !["enabled", "manual"].includes(receipt.requested_state)
31
31
  || !/^[a-f0-9]{64}$/.test(receipt.capability_identity)
32
32
  || typeof receipt.command !== "string" || !receipt.command.trim()) {
@@ -1,11 +1,9 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { generatedRoot, languageConfigContent, pluginDefinition } from "../cli/runtime-context.js";
4
4
  export { doctorRequiredFiles } from "../control-evaluation/required-files.js";
5
5
 
6
- export const agdfFragmentPath = "AGENTS.agdf.md";
7
6
  const codexSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.codex.skillPrefix}${skill.slug}`);
8
- const copilotSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.copilot.skillPrefix}${skill.slug}`);
9
7
  const globalOpenCodeSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.opencode.globalSkillPrefix}${skill.slug}`);
10
8
  const contractModules = [
11
9
  "gate-transition.md",
@@ -96,63 +94,11 @@ const artefactTemplateFiles = [
96
94
  join(".agdf", "control", "templates", "artefacts", "QA_REPORT.md"),
97
95
  join(".agdf", "control", "templates", "artefacts", "OR.md"),
98
96
  ];
99
- const copilotInstructionFiles = [
100
- join(".github", "copilot-instructions.md"),
101
- join(".github", "instructions", "agdf-governance.instructions.md"),
102
- ];
103
- const copilotSkillFiles = [
104
- join(".github", "skills", "README.md"),
105
- join(".github", "skills", pluginDefinition.copilot.runtimeContractFileName),
106
- ...contractModules.map((moduleName) => join(".github", "skills", "contracts", moduleName)),
107
- ...copilotSkillNames.map((skillName) => join(".github", "skills", skillName, "SKILL.md")),
108
- ];
109
97
 
110
98
  function loadAsset(relativePath) {
111
99
  return readFileSync(join(generatedRoot, relativePath), "utf8");
112
100
  }
113
101
 
114
- function isAgdfOwnedAgentsFile(content) {
115
- return content.includes("## Surface Convention")
116
- && content.includes("GitHub Copilot repository skills do not have a plugin namespace")
117
- && content.includes("AGDF is agent-native first and CLI-verifiable by design");
118
- }
119
-
120
- function addCopilotAgentsFile(files, targetDir, force) {
121
- const agentsPath = join(targetDir, "AGENTS.md");
122
- if (!existsSync(agentsPath) || force) {
123
- files.push({
124
- path: "AGENTS.md",
125
- content: loadAsset("AGENTS.md"),
126
- });
127
- return;
128
- }
129
-
130
- const existingAgents = readFileSync(agentsPath, "utf8");
131
- if (isAgdfOwnedAgentsFile(existingAgents)) {
132
- files.push({
133
- path: "AGENTS.md",
134
- content: loadAsset("AGENTS.md"),
135
- allowOverwrite: true,
136
- action: "refreshed",
137
- });
138
- return;
139
- }
140
-
141
- files.push({
142
- path: agdfFragmentPath,
143
- content: loadAsset("AGENTS.md"),
144
- allowOverwrite: true,
145
- action: "refreshed",
146
- preserved: "AGENTS.md",
147
- });
148
- }
149
-
150
- function shouldWriteLanguageConfig(target, targetDir, force) {
151
- if (force) return true;
152
- if ((target === "copilot" || target === "both") && existsSync(join(targetDir, ".agdf", "control", "config.json"))) return false;
153
- return true;
154
- }
155
-
156
102
  function addLanguageConfig(files, languagePreference) {
157
103
  files.push({
158
104
  path: join(".agdf", "control", "config.json"),
@@ -196,8 +142,8 @@ export function generatedFilesForTarget(target, targetDir, force, languagePrefer
196
142
  return files;
197
143
  }
198
144
 
199
- if (target === "codex-repo" || target === "both") {
200
- if (shouldWriteLanguageConfig(target, targetDir, force)) addLanguageConfig(files, languagePreference);
145
+ if (target === "codex-repo") {
146
+ addLanguageConfig(files, languagePreference);
201
147
  for (const codexPath of codexPluginFiles) {
202
148
  files.push({
203
149
  path: codexPath,
@@ -206,38 +152,6 @@ export function generatedFilesForTarget(target, targetDir, force, languagePrefer
206
152
  }
207
153
  }
208
154
 
209
- if (target === "copilot" || target === "both") {
210
- if (target !== "both" && shouldWriteLanguageConfig(target, targetDir, force)) addLanguageConfig(files, languagePreference);
211
- addCopilotAgentsFile(files, targetDir, force);
212
-
213
- for (const controlPath of controlFiles) {
214
- files.push({
215
- path: controlPath,
216
- content: loadAsset(controlPath),
217
- allowOverwrite: true,
218
- action: "refreshed",
219
- });
220
- }
221
-
222
- for (const instructionPath of copilotInstructionFiles) {
223
- files.push({
224
- path: instructionPath,
225
- content: loadAsset(instructionPath),
226
- allowOverwrite: true,
227
- action: "refreshed",
228
- });
229
- }
230
-
231
- for (const skillPath of copilotSkillFiles) {
232
- files.push({
233
- path: skillPath,
234
- content: loadAsset(skillPath),
235
- allowOverwrite: true,
236
- action: "refreshed",
237
- });
238
- }
239
- }
240
-
241
155
  if (target === "opencode-repo") {
242
156
  addLanguageConfig(files, languagePreference);
243
157
  for (const controlPath of controlFiles) {