create-agdf 0.14.1 → 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 (112) hide show
  1. package/README.md +8 -2
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  4. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  5. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +7 -0
  6. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  7. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +29 -17
  8. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +50 -1
  9. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  10. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  11. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -1
  12. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  13. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  14. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  15. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  16. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +771 -0
  17. package/generated/plugins/copilot/agdf/LICENSE +201 -0
  18. package/generated/plugins/copilot/agdf/meta/agdf-agent-router.md +129 -0
  19. package/generated/plugins/copilot/agdf/meta/agdf-constitution.md +329 -0
  20. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +331 -0
  21. package/generated/plugins/copilot/agdf/meta/agdf-runtime-contract.md +16 -0
  22. package/generated/plugins/{agdf → copilot/agdf}/plugin.json +1 -1
  23. package/generated/plugins/copilot/agdf/runtime/agdf-local.js +18 -0
  24. package/generated/plugins/copilot/agdf/runtime/agdf-session-check.js +97 -0
  25. package/generated/plugins/copilot/agdf/runtime/create-agdf/NOTICE +10 -0
  26. package/generated/plugins/copilot/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
  27. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +512 -0
  28. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +331 -0
  29. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +144 -0
  30. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +139 -0
  31. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +173 -0
  32. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
  33. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +46 -0
  34. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +301 -0
  35. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +272 -0
  36. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +455 -0
  37. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +305 -0
  38. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
  39. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
  40. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
  41. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +345 -0
  42. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
  43. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
  44. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
  45. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
  46. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
  47. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +265 -0
  48. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
  49. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
  50. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
  51. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
  52. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
  53. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +35 -0
  54. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +44 -0
  55. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
  56. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
  57. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
  58. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
  59. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
  60. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
  61. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
  62. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
  63. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +155 -0
  64. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
  65. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +27 -0
  66. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
  67. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +842 -0
  68. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/local-validator.js +239 -0
  69. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +255 -0
  70. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
  71. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +73 -0
  72. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +6 -0
  73. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +8 -0
  74. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  75. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +6 -1
  76. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +7 -0
  77. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  78. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  79. package/generated/submissions/openai/agdf/submission/openai/inventory.json +13 -9
  80. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  81. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  82. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  83. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  84. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  85. package/lib/installers/local-marketplace.js +112 -30
  86. package/lib/installers/plugin-installers.js +45 -9
  87. package/lib/public-plugin/copilot-profile.js +126 -0
  88. package/lib/release/version-coherence.js +4 -1
  89. package/lib/runtime/local-validator.js +29 -17
  90. package/lib/runtime/plugin-provenance.js +50 -1
  91. package/package.json +3 -2
  92. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-brownfield-analysis/SKILL.md +0 -0
  93. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-clean-implementation-review/SKILL.md +0 -0
  94. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-code-review/SKILL.md +0 -0
  95. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-closeout/SKILL.md +0 -0
  96. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-path-search/SKILL.md +0 -0
  97. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-gate-check/SKILL.md +0 -0
  98. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-interaction-locales.json +0 -0
  99. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-qa-gate/SKILL.md +0 -0
  100. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-release-or/SKILL.md +0 -0
  101. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-runtime-contract.md +0 -0
  102. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-task-plan-review/SKILL.md +0 -0
  103. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-ux-intent-definition/SKILL.md +0 -0
  104. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/closeout.md +0 -0
  105. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/context-graph.md +0 -0
  106. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/control-scaffold.md +0 -0
  107. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/gate-transition.md +0 -0
  108. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/interaction.md +0 -0
  109. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/modes.md +0 -0
  110. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/quality.md +0 -0
  111. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/task-target-resolution.md +0 -0
  112. /package/generated/plugins/{agdf → copilot/agdf}/hooks/copilot-hooks.json +0 -0
@@ -0,0 +1,239 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
3
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import process from "node:process";
5
+ import {
6
+ INSTALLATION_PROVENANCE_FILE,
7
+ digestDirectory,
8
+ inspectCopilotPayloadInventory,
9
+ inspectGeneratedRepositoryMarketplace,
10
+ inspectInstallationProvenance,
11
+ validateDistributionProfiles,
12
+ } from "./plugin-provenance.js";
13
+
14
+ function readJson(path) {
15
+ try {
16
+ return JSON.parse(readFileSync(path, "utf8"));
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ function canonicalPath(path) {
23
+ try { return realpathSync(path); } catch { return resolve(path); }
24
+ }
25
+
26
+ export { digestDirectory };
27
+
28
+ function envelope(machineValidation, options, evidence = {}) {
29
+ return {
30
+ schema_version: "1",
31
+ machine_validation: machineValidation,
32
+ surface: options.surface,
33
+ expected_version: options.expectedVersion,
34
+ observed_version: evidence.observedVersion ?? null,
35
+ source: evidence.source ?? null,
36
+ registry_access: false,
37
+ distribution_profile: evidence.distributionProfile ?? null,
38
+ evidence_plane: evidence.evidencePlane ?? null,
39
+ canonical_version: evidence.canonicalVersion ?? options.expectedVersion ?? null,
40
+ plugin_version: evidence.pluginVersion ?? null,
41
+ runtime_digest: evidence.runtimeDigest ?? null,
42
+ source_digest: evidence.sourceDigest ?? null,
43
+ plugin_root: evidence.pluginRoot ?? null,
44
+ provenance_status: evidence.provenanceStatus ?? null,
45
+ ...(evidence.reason ? { reason: evidence.reason } : {}),
46
+ };
47
+ }
48
+
49
+ export function resolveLocalValidator(options) {
50
+ if (options.ownedPackageRoot) {
51
+ const packageManifest = readJson(join(options.ownedPackageRoot, "package.json"));
52
+ const observedVersion = packageManifest?.version ?? null;
53
+ if (!packageManifest) {
54
+ return { envelope: envelope("unavailable", options, { source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", reason: "package_missing" }) };
55
+ }
56
+ if (observedVersion !== options.expectedVersion) {
57
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local" }) };
58
+ }
59
+ const entrypoint = join(options.ownedPackageRoot, "bin", "create-agdf.js");
60
+ if (!existsSync(entrypoint)) {
61
+ return { envelope: envelope("unavailable", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", reason: "entrypoint_missing" }) };
62
+ }
63
+ return {
64
+ envelope: envelope("owned_version_matched", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", provenanceStatus: "matched" }),
65
+ executable: process.execPath,
66
+ prefixArgs: [entrypoint],
67
+ };
68
+ }
69
+ const manifestPath = join(options.runtimeRoot, "runtime-manifest.json");
70
+ const manifestExists = existsSync(manifestPath);
71
+ const manifest = manifestExists ? readJson(manifestPath) : null;
72
+ if (manifestExists && !manifest) {
73
+ return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", reason: "manifest_invalid" }) };
74
+ }
75
+ if (manifest) {
76
+ const pluginRoot = canonicalPath(options.pluginRoot ?? join(options.runtimeRoot, ".."));
77
+ if (options.expectedPluginRoot && canonicalPath(options.expectedPluginRoot) !== pluginRoot) {
78
+ return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, evidencePlane: "loaded_session", distributionProfile: "runtime-plugin", provenanceStatus: "mismatch", reason: "plugin_root_mismatch" }) };
79
+ }
80
+ const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"));
81
+ const profile = validateDistributionProfiles(definition);
82
+ if (profile.status !== "matched") {
83
+ return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, distributionProfile: "runtime-plugin", provenanceStatus: "invalid", reason: "profile_invalid" }) };
84
+ }
85
+ const codexManifest = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
86
+ const claudeManifest = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"));
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 }) };
99
+ }
100
+ const packageRoot = join(options.runtimeRoot, "create-agdf");
101
+ if (!existsSync(packageRoot)) {
102
+ return { envelope: envelope("unavailable", options, { source: "plugin_bundle", pluginRoot, pluginVersion, distributionProfile, reason: "runtime_missing" }) };
103
+ }
104
+ const packageManifest = readJson(join(packageRoot, "package.json"));
105
+ const observedVersion = packageManifest?.version ?? manifest.version ?? null;
106
+ if (observedVersion !== options.expectedVersion || manifest.version !== options.expectedVersion) {
107
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile }) };
108
+ }
109
+ let observedDigest = null;
110
+ try { observedDigest = digestDirectory(packageRoot); } catch {}
111
+ if (!observedDigest || manifest.digest !== observedDigest) {
112
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "runtime_digest_mismatch" }) };
113
+ }
114
+ const entrypoint = resolve(options.runtimeRoot, manifest.entrypoint ?? "");
115
+ const entrypointRelative = relative(options.runtimeRoot, entrypoint);
116
+ if (!manifest.entrypoint || entrypointRelative === ".." || entrypointRelative.startsWith(`..${sep}`) || isAbsolute(entrypointRelative)) {
117
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "invalid_entrypoint" }) };
118
+ }
119
+ if (!existsSync(entrypoint)) {
120
+ return { envelope: envelope("unavailable", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile, reason: "entrypoint_missing" }) };
121
+ }
122
+ const installed = existsSync(join(pluginRoot, INSTALLATION_PROVENANCE_FILE));
123
+ let provenanceStatus = "not_applicable";
124
+ let sourceDigest = null;
125
+ let evidencePlane = options.expectedPluginRoot ? "loaded_session" : "installed_plugin_root";
126
+ if (installed) {
127
+ const provenance = inspectInstallationProvenance(pluginRoot, {
128
+ definition,
129
+ runtimeManifest: manifest,
130
+ pluginVersion,
131
+ profileId: distributionProfile,
132
+ inventoryDigest: copilotInventory?.inventoryDigest ?? null,
133
+ });
134
+ provenanceStatus = provenance.status;
135
+ sourceDigest = provenance.marker?.source_digest ?? null;
136
+ if (provenance.status !== "matched") {
137
+ return { envelope: envelope("version_mismatch", options, {
138
+ observedVersion,
139
+ source: "plugin_bundle",
140
+ pluginRoot,
141
+ pluginVersion,
142
+ canonicalVersion: definition.version,
143
+ runtimeDigest: observedDigest,
144
+ sourceDigest,
145
+ distributionProfile,
146
+ evidencePlane,
147
+ provenanceStatus,
148
+ reason: provenance.reason,
149
+ }) };
150
+ }
151
+ } else if (existsSync(join(pluginRoot, ".agdf-local-install.json"))) {
152
+ return { envelope: envelope("unavailable", options, {
153
+ observedVersion,
154
+ source: "plugin_bundle",
155
+ pluginRoot,
156
+ pluginVersion,
157
+ canonicalVersion: definition.version,
158
+ runtimeDigest: observedDigest,
159
+ distributionProfile,
160
+ evidencePlane: "loaded_session",
161
+ provenanceStatus: "missing",
162
+ reason: "installation_provenance_missing",
163
+ }) };
164
+ } else {
165
+ const generatedRepository = copilotProfile ? null : inspectGeneratedRepositoryMarketplace(resolve(pluginRoot, "..", ".."));
166
+ if (pluginVersion !== definition.version
167
+ || (!copilotProfile && (generatedRepository.status !== "matched"
168
+ || canonicalPath(generatedRepository.pluginRoot) !== pluginRoot))) {
169
+ return { envelope: envelope("unavailable", options, {
170
+ observedVersion,
171
+ source: "plugin_bundle",
172
+ pluginRoot,
173
+ pluginVersion,
174
+ canonicalVersion: definition.version,
175
+ runtimeDigest: observedDigest,
176
+ distributionProfile,
177
+ evidencePlane: "installed_plugin_root",
178
+ provenanceStatus: "missing",
179
+ reason: "installation_provenance_missing",
180
+ }) };
181
+ }
182
+ evidencePlane = "generated_bundle";
183
+ }
184
+ return {
185
+ envelope: envelope("owned_version_matched", options, {
186
+ observedVersion,
187
+ source: "plugin_bundle",
188
+ pluginRoot,
189
+ pluginVersion,
190
+ canonicalVersion: definition.version,
191
+ runtimeDigest: observedDigest,
192
+ sourceDigest,
193
+ distributionProfile,
194
+ evidencePlane,
195
+ provenanceStatus,
196
+ }),
197
+ executable: process.execPath,
198
+ prefixArgs: [entrypoint],
199
+ };
200
+ }
201
+
202
+ const configuredPath = options.configuredPath ?? process.env.AGDF_VALIDATOR_PATH ?? "";
203
+ if (configuredPath) {
204
+ if (!isAbsolute(configuredPath) || !existsSync(configuredPath)) {
205
+ return { envelope: envelope("unavailable", options, { source: "configured_path", reason: "invalid_absolute_path" }) };
206
+ }
207
+ const versionProbe = spawnSync(configuredPath, ["--version", "--json"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
208
+ let observedVersion = null;
209
+ try { observedVersion = JSON.parse(versionProbe.stdout)?.version ?? null; } catch {}
210
+ if (versionProbe.status !== 0 || observedVersion !== options.expectedVersion) {
211
+ return { envelope: envelope("version_mismatch", options, { observedVersion, source: "configured_path" }) };
212
+ }
213
+ return {
214
+ envelope: envelope("configured_version_matched", options, { observedVersion, source: "configured_path" }),
215
+ executable: configuredPath,
216
+ prefixArgs: [],
217
+ };
218
+ }
219
+
220
+ return { envelope: envelope(options.externalRequired ? "external_required" : "unavailable", options) };
221
+ }
222
+
223
+ export function runLocalValidator(options, args, io = console) {
224
+ const resolved = resolveLocalValidator(options);
225
+ if (args[0] === "--resolve-only") {
226
+ io.log(JSON.stringify(resolved.envelope, null, args.includes("--json") ? 2 : 0));
227
+ return resolved.executable ? 0 : 2;
228
+ }
229
+ if (!resolved.executable) {
230
+ io.error(JSON.stringify(resolved.envelope));
231
+ return 2;
232
+ }
233
+ const child = spawnSync(resolved.executable, [...resolved.prefixArgs, ...args], {
234
+ cwd: options.cwd ?? process.cwd(),
235
+ env: { ...process.env, AGDF_MACHINE_VALIDATION: resolved.envelope.machine_validation },
236
+ stdio: "inherit",
237
+ });
238
+ return child.status ?? 2;
239
+ }
@@ -0,0 +1,255 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
+
5
+ export const INSTALLATION_PROVENANCE_FILE = ".agdf-installation.json";
6
+ export const LEGACY_LOCAL_INSTALL_FILE = ".agdf-local-install.json";
7
+ export const COPILOT_PAYLOAD_INVENTORY_FILE = ".agdf-payload-inventory.json";
8
+
9
+ const EXPECTED_PROFILES = Object.freeze({
10
+ "source-development": Object.freeze({ runtime: "absent", installable: false, machineValidation: "unavailable" }),
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" }),
13
+ "opencode-config-local": Object.freeze({ runtime: "config_local_package", installable: true, machineValidation: "local_exact_version" }),
14
+ "portable-skills": Object.freeze({ runtime: "absent", installable: true, machineValidation: "unavailable_or_external_required" }),
15
+ });
16
+
17
+ function readJson(path) {
18
+ try {
19
+ return JSON.parse(readFileSync(path, "utf8"));
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+
25
+ export function digestDirectory(root) {
26
+ const files = [];
27
+ function visit(directory) {
28
+ for (const name of readdirSync(directory).sort()) {
29
+ const path = join(directory, name);
30
+ const stats = statSync(path);
31
+ if (stats.isDirectory()) visit(path);
32
+ else if (stats.isFile()) files.push(path);
33
+ }
34
+ }
35
+ visit(root);
36
+ const hash = createHash("sha256");
37
+ for (const path of files) {
38
+ hash.update(relative(root, path).replaceAll("\\", "/"));
39
+ hash.update("\0");
40
+ hash.update(readFileSync(path));
41
+ hash.update("\0");
42
+ }
43
+ return hash.digest("hex");
44
+ }
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
+
90
+ export function digestNormalizedPluginSource(root, canonicalVersion) {
91
+ const files = [];
92
+ function visit(directory) {
93
+ for (const name of readdirSync(directory).sort()) {
94
+ const path = join(directory, name);
95
+ const stats = statSync(path);
96
+ if (stats.isDirectory()) visit(path);
97
+ else if (stats.isFile()) files.push(path);
98
+ }
99
+ }
100
+ visit(root);
101
+ const hash = createHash("sha256");
102
+ for (const path of files) {
103
+ const normalizedPath = relative(root, path).replaceAll("\\", "/");
104
+ if ([INSTALLATION_PROVENANCE_FILE, LEGACY_LOCAL_INSTALL_FILE].includes(normalizedPath)) continue;
105
+ let content = readFileSync(path);
106
+ if (normalizedPath === ".codex-plugin/plugin.json") {
107
+ const manifest = readJson(path);
108
+ if (!manifest) throw new Error(`Invalid Codex plugin manifest: ${path}`);
109
+ content = `${JSON.stringify({ ...manifest, version: canonicalVersion }, null, 2)}\n`;
110
+ }
111
+ hash.update(normalizedPath);
112
+ hash.update("\0");
113
+ hash.update(content);
114
+ hash.update("\0");
115
+ }
116
+ return hash.digest("hex");
117
+ }
118
+
119
+ export function validateDistributionProfiles(definition) {
120
+ const contract = definition?.distributionProfiles;
121
+ if (contract?.schemaVersion !== 1) return { status: "invalid", reason: "profile_invalid" };
122
+ if (contract.marketplaceIdentities?.durable !== "agdf"
123
+ || contract.marketplaceIdentities?.generatedRepository !== "agdf-repo") {
124
+ return { status: "invalid", reason: "profile_invalid" };
125
+ }
126
+ for (const [profileId, expected] of Object.entries(EXPECTED_PROFILES)) {
127
+ const observed = contract.profiles?.[profileId];
128
+ if (!observed
129
+ || Object.keys(observed).length !== Object.keys(expected).length
130
+ || Object.keys(expected).some((key) => observed[key] !== expected[key])) {
131
+ return { status: "invalid", reason: "profile_invalid" };
132
+ }
133
+ }
134
+ if (Object.keys(contract.profiles ?? {}).length !== Object.keys(EXPECTED_PROFILES).length) {
135
+ return { status: "invalid", reason: "profile_invalid" };
136
+ }
137
+ return { status: "matched", contract };
138
+ }
139
+
140
+ export function inspectGeneratedRepositoryMarketplace(targetDir) {
141
+ const marketplacePath = join(targetDir, ".agents", "plugins", "marketplace.json");
142
+ if (!existsSync(marketplacePath)) return { status: "absent", marketplacePath };
143
+ const marketplace = readJson(marketplacePath);
144
+ const plugin = marketplace?.plugins?.length === 1 ? marketplace.plugins[0] : null;
145
+ const pluginPath = plugin?.source?.source === "local" ? plugin.source.path : null;
146
+ if (marketplace?.name !== "agdf-repo" || plugin?.name !== "agdf" || pluginPath !== "./plugins/agdf") {
147
+ return { status: "invalid", reason: "repository_marketplace_invalid", marketplacePath };
148
+ }
149
+ const pluginRoot = resolve(targetDir, pluginPath);
150
+ const rel = relative(resolve(targetDir), pluginRoot);
151
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
152
+ return { status: "invalid", reason: "repository_marketplace_path_escape", marketplacePath };
153
+ }
154
+ const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"));
155
+ const runtimeManifest = readJson(join(pluginRoot, "runtime", "runtime-manifest.json"));
156
+ const codexManifest = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
157
+ const claudeManifest = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"));
158
+ const runtimeRoot = join(pluginRoot, "runtime");
159
+ const runtimePackageRoot = join(pluginRoot, "runtime", "create-agdf");
160
+ const runtimeEntrypoint = resolve(runtimeRoot, runtimeManifest?.entrypoint ?? "");
161
+ const runtimeEntrypointRel = relative(runtimeRoot, runtimeEntrypoint);
162
+ if (validateDistributionProfiles(definition).status !== "matched"
163
+ || definition?.version !== runtimeManifest?.version
164
+ || codexManifest?.version !== definition?.version
165
+ || claudeManifest?.version !== definition?.version
166
+ || !/^[a-f0-9]{64}$/.test(runtimeManifest?.digest ?? "")
167
+ || !existsSync(join(runtimeRoot, "agdf-local.js"))
168
+ || !runtimeManifest?.entrypoint
169
+ || runtimeEntrypointRel === ".."
170
+ || runtimeEntrypointRel.startsWith(`..${sep}`)
171
+ || isAbsolute(runtimeEntrypointRel)
172
+ || !existsSync(runtimeEntrypoint)
173
+ || !existsSync(runtimePackageRoot)) {
174
+ return { status: "invalid", reason: "repository_runtime_incomplete", marketplacePath, pluginRoot };
175
+ }
176
+ let runtimeDigest;
177
+ try { runtimeDigest = digestDirectory(runtimePackageRoot); } catch {
178
+ return { status: "invalid", reason: "repository_runtime_incomplete", marketplacePath, pluginRoot };
179
+ }
180
+ if (runtimeDigest !== runtimeManifest.digest) {
181
+ return { status: "invalid", reason: "runtime_digest_mismatch", marketplacePath, pluginRoot };
182
+ }
183
+ return {
184
+ status: "matched",
185
+ marketplacePath,
186
+ pluginRoot,
187
+ selector: `${plugin.name}@${marketplace.name}`,
188
+ runtimeDigest,
189
+ };
190
+ }
191
+
192
+ export function inspectInstallationProvenance(pluginRoot, {
193
+ definition,
194
+ runtimeManifest,
195
+ pluginVersion,
196
+ allowLegacy = false,
197
+ profileId = "runtime-plugin",
198
+ inventoryDigest = null,
199
+ } = {}) {
200
+ const markerPath = join(pluginRoot, INSTALLATION_PROVENANCE_FILE);
201
+ const legacyPath = join(pluginRoot, LEGACY_LOCAL_INSTALL_FILE);
202
+ if (!existsSync(markerPath)) {
203
+ if (allowLegacy && existsSync(legacyPath)) {
204
+ const marker = readJson(legacyPath);
205
+ if (!marker
206
+ || marker.schema_version !== 1
207
+ || marker.owner !== "create-agdf"
208
+ || marker.kind !== "codex_local_development_projection"
209
+ || marker.canonical_version !== definition.version
210
+ || marker.codex_install_version !== pluginVersion
211
+ || !/^[a-f0-9]{64}$/.test(marker.source_digest ?? "")) {
212
+ return { status: "invalid", reason: "installation_provenance_invalid", marker };
213
+ }
214
+ let observedSourceDigest;
215
+ try { observedSourceDigest = digestNormalizedPluginSource(pluginRoot, definition.version); } catch {
216
+ return { status: "invalid", reason: "source_digest_mismatch", marker };
217
+ }
218
+ return observedSourceDigest === marker.source_digest
219
+ ? { status: "legacy", marker, observedSourceDigest, reason: "legacy_installation_provenance" }
220
+ : { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
221
+ }
222
+ const profile = validateDistributionProfiles(definition);
223
+ if (profile.status !== "matched") return profile;
224
+ return { status: "missing", reason: "installation_provenance_missing" };
225
+ }
226
+ const profile = validateDistributionProfiles(definition);
227
+ if (profile.status !== "matched") return profile;
228
+ const marker = readJson(markerPath);
229
+ if (!marker
230
+ || marker.schema_version !== 1
231
+ || marker.owner !== "create-agdf"
232
+ || marker.profile_id !== profileId
233
+ || marker.marketplace_id !== profile.contract.marketplaceIdentities.durable
234
+ || marker.canonical_version !== definition.version
235
+ || marker.codex_install_version !== pluginVersion
236
+ || marker.runtime_digest !== runtimeManifest?.digest
237
+ || (profileId === "copilot-runtime-plugin" && marker.inventory_digest !== inventoryDigest)
238
+ || !/^[a-f0-9]{64}$/.test(marker.source_digest ?? "")) {
239
+ return { status: "invalid", reason: "installation_provenance_invalid", marker };
240
+ }
241
+ let observedSourceDigest;
242
+ try {
243
+ observedSourceDigest = digestNormalizedPluginSource(pluginRoot, definition.version);
244
+ } catch {
245
+ return { status: "invalid", reason: "source_digest_mismatch", marker };
246
+ }
247
+ if (observedSourceDigest !== marker.source_digest) {
248
+ return { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
249
+ }
250
+ return { status: "matched", marker, observedSourceDigest };
251
+ }
252
+
253
+ export const distributionProfileContract = Object.freeze({
254
+ expectedProfiles: EXPECTED_PROFILES,
255
+ });
@@ -0,0 +1,40 @@
1
+ import process from "node:process";
2
+ import { createValidationHandlers } from "../cli/validation-handlers.js";
3
+ import { validateCommandOptions } from "../cli/command-registry.js";
4
+ import { CliUsageError, parseArgs } from "../cli/parse-args.js";
5
+ import { pluginDefinition } from "../cli/runtime-context.js";
6
+
7
+ const validatorCommands = new Set(["doctor", "gate-check", "delivery-map", "delivery-path-search"]);
8
+
9
+ export async function runValidatorCli(argv = process.argv.slice(2), adapters = {}) {
10
+ const io = adapters.io ?? console;
11
+ if (argv.includes("--version")) {
12
+ const output = { name: "create-agdf", version: pluginDefinition.version };
13
+ io.log(argv.includes("--json") ? JSON.stringify(output) : output.version);
14
+ return 0;
15
+ }
16
+ let parsed;
17
+ try {
18
+ parsed = parseArgs(argv, adapters.parser);
19
+ } catch (error) {
20
+ if (!(error instanceof CliUsageError)) throw error;
21
+ io.error(error.message);
22
+ return error.exitCode;
23
+ }
24
+ if (parsed.kind === "help") {
25
+ io.log("AGDF surface-local validator: doctor | gate-check | delivery-map | delivery-path-search");
26
+ return 0;
27
+ }
28
+ let options;
29
+ try {
30
+ options = validateCommandOptions(parsed.options);
31
+ } catch (error) {
32
+ io.error(error instanceof Error ? error.message : String(error));
33
+ return 1;
34
+ }
35
+ if (!validatorCommands.has(options.target)) {
36
+ io.error(`The surface-local validator does not support lifecycle command: ${options.target}`);
37
+ return 1;
38
+ }
39
+ return await createValidationHandlers(io).get(options.target)(options);
40
+ }
@@ -0,0 +1,73 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ const OPERATIONS = Object.freeze([
4
+ "resolve-local-runtime",
5
+ "inspect-control-state",
6
+ "render-bounded-orientation",
7
+ ]);
8
+
9
+ function stable(value) {
10
+ if (Array.isArray(value)) return value.map(stable);
11
+ if (!value || typeof value !== "object") return value;
12
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
13
+ }
14
+
15
+ export function validateRuntimeCheckCapability(capability) {
16
+ if (capability?.schemaVersion !== 1 || capability.capabilityId !== "automatic-runtime-checks") {
17
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: schema or capability id");
18
+ }
19
+ if (!Number.isInteger(capability.adapterContractVersion) || capability.adapterContractVersion < 1) {
20
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: adapter contract version");
21
+ }
22
+ if (capability.entrypoint !== "runtime/agdf-session-check.js") {
23
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: fixed entrypoint required");
24
+ }
25
+ if (JSON.stringify(capability.operations) !== JSON.stringify(OPERATIONS)) {
26
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: closed operation vocabulary required");
27
+ }
28
+ const constraints = capability.constraints ?? {};
29
+ if (constraints.arguments !== "forbidden" || constraints.filesystemWrites !== "forbidden"
30
+ || constraints.network !== "forbidden" || constraints.gateAuthority !== "none") {
31
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: read-only constraints required");
32
+ }
33
+ const surfaces = capability.surfaces ?? {};
34
+ if (surfaces.codex !== "native-hook-review" || surfaces.claude !== "exact-command-rule"
35
+ || surfaces.copilot !== "plugin-hook-review"
36
+ || surfaces.opencode !== "plugin-internal"
37
+ || surfaces["portable-skills"] !== "manual-external-required") {
38
+ throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: surface contract");
39
+ }
40
+ return capability;
41
+ }
42
+
43
+ export function runtimeCheckCapabilityIdentity({ capability, surface, runtimeDigest, sourceDigest, command }) {
44
+ validateRuntimeCheckCapability(capability);
45
+ if (!["codex", "claude", "copilot", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_SURFACE_INVALID");
46
+ for (const [name, value] of Object.entries({ runtimeDigest, sourceDigest })) {
47
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) throw new Error(`AGDF_RUNTIME_CHECK_IDENTITY_INVALID: ${name}`);
48
+ }
49
+ if (typeof command !== "string" || !command.trim()) throw new Error("AGDF_RUNTIME_CHECK_IDENTITY_INVALID: command");
50
+ const payload = stable({
51
+ schema_version: 1,
52
+ surface,
53
+ capability,
54
+ runtime_digest: runtimeDigest,
55
+ source_digest: sourceDigest,
56
+ command: command.trim(),
57
+ });
58
+ return createHash("sha256").update(JSON.stringify(payload)).digest("hex");
59
+ }
60
+
61
+ export function fixedRuntimeCheckCommand(surface, pluginRoot, platform = process.platform) {
62
+ if (surface === "opencode") return "plugin:agdf:automatic-runtime-checks";
63
+ if (surface === "copilot") return 'node "${PLUGIN_ROOT}/runtime/agdf-session-check.js"';
64
+ if (surface === "codex" || surface === "claude") {
65
+ return platform === "win32"
66
+ ? "node \"$([Environment]::GetEnvironmentVariable('PLUGIN_ROOT') + [Environment]::GetEnvironmentVariable('CLAUDE_PLUGIN_ROOT'))\\runtime\\agdf-session-check.js\""
67
+ : "node \"${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/runtime/agdf-session-check.js\"";
68
+ }
69
+ const normalizedRoot = platform === "win32" ? pluginRoot.replaceAll("/", "\\") : pluginRoot;
70
+ return `node \"${normalizedRoot}${platform === "win32" ? "\\" : "/"}runtime${platform === "win32" ? "\\" : "/"}agdf-session-check.js\"`;
71
+ }
72
+
73
+ export const runtimeCheckOperations = OPERATIONS;
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@agdf/local-validator-runtime",
3
+ "version": "0.14.2",
4
+ "private": true,
5
+ "type": "module"
6
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "schema_version": "1",
3
+ "generated": true,
4
+ "source": "create-agdf/cli",
5
+ "version": "0.14.2",
6
+ "entrypoint": "create-agdf/bin/agdf-validator.js",
7
+ "digest": "51035c8735d47aa727980d82709326071b372464ae077a1d269aadc0d30f2624"
8
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "Control layer 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.14.1",
4
+ "version": "0.14.2",
5
5
  "displayName": "AI Governance & Delivery Framework",
6
6
  "developerName": "Arndt Gold",
7
7
  "description": "Control layer for governed AI-assisted delivery.",
@@ -311,6 +311,11 @@
311
311
  "installable": true,
312
312
  "machineValidation": "local_exact_version_digest"
313
313
  },
314
+ "copilot-runtime-plugin": {
315
+ "runtime": "required",
316
+ "installable": true,
317
+ "machineValidation": "local_exact_version_digest_inventory"
318
+ },
314
319
  "opencode-config-local": {
315
320
  "runtime": "config_local_package",
316
321
  "installable": true,
@@ -0,0 +1,7 @@
1
+ {
2
+ "schema_version": 1,
3
+ "profile_id": "copilot-runtime-plugin",
4
+ "max_files": 78,
5
+ "max_bytes": 539607,
6
+ "rationale": "Reviewed Copilot-only manifest, ten prefixed skills, required contracts, exact-version runtime and evidence-plane separation. Any further increase requires review."
7
+ }