create-agdf 0.13.5 → 0.13.7

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 (38) hide show
  1. package/README.md +7 -1
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -3
  4. package/generated/plugins/agdf/hooks/session-start.sh +31 -0
  5. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +30 -9
  6. package/generated/plugins/agdf/runtime/agdf-local.js +8 -1
  7. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +30 -9
  8. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +116 -31
  9. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +206 -0
  10. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  11. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  12. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +64 -19
  13. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  14. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  15. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  16. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  17. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  18. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +30 -9
  19. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  20. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  21. package/generated/submissions/openai/agdf/submission/openai/inventory.json +9 -9
  22. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  23. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  24. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  25. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  26. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  27. package/lib/cli/application.js +4 -3
  28. package/lib/fs-swap.js +26 -0
  29. package/lib/installers/local-development.js +202 -0
  30. package/lib/installers/local-marketplace.js +253 -46
  31. package/lib/installers/opencode.js +17 -2
  32. package/lib/installers/plugin-installers.js +88 -22
  33. package/lib/lifecycle/operations.js +9 -5
  34. package/lib/lifecycle/status.js +10 -2
  35. package/lib/public-plugin/builder.js +5 -4
  36. package/lib/runtime/local-validator.js +116 -31
  37. package/lib/runtime/plugin-provenance.js +206 -0
  38. package/package.json +6 -2
@@ -0,0 +1,206 @@
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
+
8
+ const EXPECTED_PROFILES = Object.freeze({
9
+ "source-development": Object.freeze({ runtime: "absent", installable: false, machineValidation: "unavailable" }),
10
+ "runtime-plugin": Object.freeze({ runtime: "required", installable: true, machineValidation: "local_exact_version_digest" }),
11
+ "opencode-config-local": Object.freeze({ runtime: "config_local_package", installable: true, machineValidation: "local_exact_version" }),
12
+ "portable-skills": Object.freeze({ runtime: "absent", installable: true, machineValidation: "unavailable_or_external_required" }),
13
+ });
14
+
15
+ function readJson(path) {
16
+ try {
17
+ return JSON.parse(readFileSync(path, "utf8"));
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ export function digestDirectory(root) {
24
+ const files = [];
25
+ function visit(directory) {
26
+ for (const name of readdirSync(directory).sort()) {
27
+ const path = join(directory, name);
28
+ const stats = statSync(path);
29
+ if (stats.isDirectory()) visit(path);
30
+ else if (stats.isFile()) files.push(path);
31
+ }
32
+ }
33
+ visit(root);
34
+ const hash = createHash("sha256");
35
+ for (const path of files) {
36
+ hash.update(relative(root, path).replaceAll("\\", "/"));
37
+ hash.update("\0");
38
+ hash.update(readFileSync(path));
39
+ hash.update("\0");
40
+ }
41
+ return hash.digest("hex");
42
+ }
43
+
44
+ export function digestNormalizedPluginSource(root, canonicalVersion) {
45
+ const files = [];
46
+ function visit(directory) {
47
+ for (const name of readdirSync(directory).sort()) {
48
+ const path = join(directory, name);
49
+ const stats = statSync(path);
50
+ if (stats.isDirectory()) visit(path);
51
+ else if (stats.isFile()) files.push(path);
52
+ }
53
+ }
54
+ visit(root);
55
+ const hash = createHash("sha256");
56
+ for (const path of files) {
57
+ const normalizedPath = relative(root, path).replaceAll("\\", "/");
58
+ if ([INSTALLATION_PROVENANCE_FILE, LEGACY_LOCAL_INSTALL_FILE].includes(normalizedPath)) continue;
59
+ let content = readFileSync(path);
60
+ if (normalizedPath === ".codex-plugin/plugin.json") {
61
+ const manifest = readJson(path);
62
+ if (!manifest) throw new Error(`Invalid Codex plugin manifest: ${path}`);
63
+ content = `${JSON.stringify({ ...manifest, version: canonicalVersion }, null, 2)}\n`;
64
+ }
65
+ hash.update(normalizedPath);
66
+ hash.update("\0");
67
+ hash.update(content);
68
+ hash.update("\0");
69
+ }
70
+ return hash.digest("hex");
71
+ }
72
+
73
+ export function validateDistributionProfiles(definition) {
74
+ const contract = definition?.distributionProfiles;
75
+ if (contract?.schemaVersion !== 1) return { status: "invalid", reason: "profile_invalid" };
76
+ if (contract.marketplaceIdentities?.durable !== "agdf"
77
+ || contract.marketplaceIdentities?.generatedRepository !== "agdf-repo") {
78
+ return { status: "invalid", reason: "profile_invalid" };
79
+ }
80
+ for (const [profileId, expected] of Object.entries(EXPECTED_PROFILES)) {
81
+ const observed = contract.profiles?.[profileId];
82
+ if (!observed
83
+ || Object.keys(observed).length !== Object.keys(expected).length
84
+ || Object.keys(expected).some((key) => observed[key] !== expected[key])) {
85
+ return { status: "invalid", reason: "profile_invalid" };
86
+ }
87
+ }
88
+ if (Object.keys(contract.profiles ?? {}).length !== Object.keys(EXPECTED_PROFILES).length) {
89
+ return { status: "invalid", reason: "profile_invalid" };
90
+ }
91
+ return { status: "matched", contract };
92
+ }
93
+
94
+ export function inspectGeneratedRepositoryMarketplace(targetDir) {
95
+ const marketplacePath = join(targetDir, ".agents", "plugins", "marketplace.json");
96
+ if (!existsSync(marketplacePath)) return { status: "absent", marketplacePath };
97
+ const marketplace = readJson(marketplacePath);
98
+ const plugin = marketplace?.plugins?.length === 1 ? marketplace.plugins[0] : null;
99
+ const pluginPath = plugin?.source?.source === "local" ? plugin.source.path : null;
100
+ if (marketplace?.name !== "agdf-repo" || plugin?.name !== "agdf" || pluginPath !== "./plugins/agdf") {
101
+ return { status: "invalid", reason: "repository_marketplace_invalid", marketplacePath };
102
+ }
103
+ const pluginRoot = resolve(targetDir, pluginPath);
104
+ const rel = relative(resolve(targetDir), pluginRoot);
105
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
106
+ return { status: "invalid", reason: "repository_marketplace_path_escape", marketplacePath };
107
+ }
108
+ const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"));
109
+ const runtimeManifest = readJson(join(pluginRoot, "runtime", "runtime-manifest.json"));
110
+ const codexManifest = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
111
+ const claudeManifest = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"));
112
+ const runtimeRoot = join(pluginRoot, "runtime");
113
+ const runtimePackageRoot = join(pluginRoot, "runtime", "create-agdf");
114
+ const runtimeEntrypoint = resolve(runtimeRoot, runtimeManifest?.entrypoint ?? "");
115
+ const runtimeEntrypointRel = relative(runtimeRoot, runtimeEntrypoint);
116
+ if (validateDistributionProfiles(definition).status !== "matched"
117
+ || definition?.version !== runtimeManifest?.version
118
+ || codexManifest?.version !== definition?.version
119
+ || claudeManifest?.version !== definition?.version
120
+ || !/^[a-f0-9]{64}$/.test(runtimeManifest?.digest ?? "")
121
+ || !existsSync(join(runtimeRoot, "agdf-local.js"))
122
+ || !runtimeManifest?.entrypoint
123
+ || runtimeEntrypointRel === ".."
124
+ || runtimeEntrypointRel.startsWith(`..${sep}`)
125
+ || isAbsolute(runtimeEntrypointRel)
126
+ || !existsSync(runtimeEntrypoint)
127
+ || !existsSync(runtimePackageRoot)) {
128
+ return { status: "invalid", reason: "repository_runtime_incomplete", marketplacePath, pluginRoot };
129
+ }
130
+ let runtimeDigest;
131
+ try { runtimeDigest = digestDirectory(runtimePackageRoot); } catch {
132
+ return { status: "invalid", reason: "repository_runtime_incomplete", marketplacePath, pluginRoot };
133
+ }
134
+ if (runtimeDigest !== runtimeManifest.digest) {
135
+ return { status: "invalid", reason: "runtime_digest_mismatch", marketplacePath, pluginRoot };
136
+ }
137
+ return {
138
+ status: "matched",
139
+ marketplacePath,
140
+ pluginRoot,
141
+ selector: `${plugin.name}@${marketplace.name}`,
142
+ runtimeDigest,
143
+ };
144
+ }
145
+
146
+ export function inspectInstallationProvenance(pluginRoot, {
147
+ definition,
148
+ runtimeManifest,
149
+ pluginVersion,
150
+ allowLegacy = false,
151
+ } = {}) {
152
+ const markerPath = join(pluginRoot, INSTALLATION_PROVENANCE_FILE);
153
+ const legacyPath = join(pluginRoot, LEGACY_LOCAL_INSTALL_FILE);
154
+ if (!existsSync(markerPath)) {
155
+ if (allowLegacy && existsSync(legacyPath)) {
156
+ const marker = readJson(legacyPath);
157
+ if (!marker
158
+ || marker.schema_version !== 1
159
+ || marker.owner !== "create-agdf"
160
+ || marker.kind !== "codex_local_development_projection"
161
+ || marker.canonical_version !== definition.version
162
+ || marker.codex_install_version !== pluginVersion
163
+ || !/^[a-f0-9]{64}$/.test(marker.source_digest ?? "")) {
164
+ return { status: "invalid", reason: "installation_provenance_invalid", marker };
165
+ }
166
+ let observedSourceDigest;
167
+ try { observedSourceDigest = digestNormalizedPluginSource(pluginRoot, definition.version); } catch {
168
+ return { status: "invalid", reason: "source_digest_mismatch", marker };
169
+ }
170
+ return observedSourceDigest === marker.source_digest
171
+ ? { status: "legacy", marker, observedSourceDigest, reason: "legacy_installation_provenance" }
172
+ : { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
173
+ }
174
+ const profile = validateDistributionProfiles(definition);
175
+ if (profile.status !== "matched") return profile;
176
+ return { status: "missing", reason: "installation_provenance_missing" };
177
+ }
178
+ const profile = validateDistributionProfiles(definition);
179
+ if (profile.status !== "matched") return profile;
180
+ const marker = readJson(markerPath);
181
+ if (!marker
182
+ || marker.schema_version !== 1
183
+ || marker.owner !== "create-agdf"
184
+ || marker.profile_id !== "runtime-plugin"
185
+ || marker.marketplace_id !== profile.contract.marketplaceIdentities.durable
186
+ || marker.canonical_version !== definition.version
187
+ || marker.codex_install_version !== pluginVersion
188
+ || marker.runtime_digest !== runtimeManifest?.digest
189
+ || !/^[a-f0-9]{64}$/.test(marker.source_digest ?? "")) {
190
+ return { status: "invalid", reason: "installation_provenance_invalid", marker };
191
+ }
192
+ let observedSourceDigest;
193
+ try {
194
+ observedSourceDigest = digestNormalizedPluginSource(pluginRoot, definition.version);
195
+ } catch {
196
+ return { status: "invalid", reason: "source_digest_mismatch", marker };
197
+ }
198
+ if (observedSourceDigest !== marker.source_digest) {
199
+ return { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
200
+ }
201
+ return { status: "matched", marker, observedSourceDigest };
202
+ }
203
+
204
+ export const distributionProfileContract = Object.freeze({
205
+ expectedProfiles: EXPECTED_PROFILES,
206
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agdf/local-validator-runtime",
3
- "version": "0.13.5",
3
+ "version": "0.13.7",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -2,7 +2,7 @@
2
2
  "schema_version": "1",
3
3
  "generated": true,
4
4
  "source": "create-agdf/cli",
5
- "version": "0.13.5",
5
+ "version": "0.13.7",
6
6
  "entrypoint": "create-agdf/bin/agdf-validator.js",
7
- "digest": "8a076d7647c39ea3c19f6cc7c30052d798ec65abe705b56065c784f2bebc8068"
7
+ "digest": "05afaf9ec478d50900a79cbdda8fcd7c61fa5627f4770ba093b19908fa6df91b"
8
8
  }
@@ -1,7 +1,8 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
2
3
  import { spawnSync } from "node:child_process";
3
4
  import { fileURLToPath } from "node:url";
4
- import { dirname, join, resolve } from "node:path";
5
+ import { dirname, join, relative, resolve } from "node:path";
5
6
 
6
7
  const scriptPluginRoot = resolve(fileURLToPath(new URL("..", import.meta.url)));
7
8
 
@@ -46,7 +47,6 @@ function hasPluginLayout(root) {
46
47
  function hasSourceLayout(root) {
47
48
  return hasPluginLayout(join(root, "plugin"))
48
49
  && [
49
- ".claude-plugin/marketplace.json",
50
50
  "agdf/package.json",
51
51
  "create-agdf/package.json",
52
52
  "pages/package.json",
@@ -92,9 +92,12 @@ try {
92
92
  console.error("- AGDF_AGENT_SKILLS_VALIDATOR_MISSING: scripts/agent-skills-conformance.mjs must be present and loadable");
93
93
  process.exit(1);
94
94
  }
95
- const marketplacePath = sourceMode ? join(repoRoot, ".claude-plugin", "marketplace.json") : null;
95
+ const codexSourceMarketplacePath = sourceMode ? join(repoRoot, ".agents", "plugins", "marketplace.json") : null;
96
+ const claudeSourceMarketplacePath = sourceMode ? join(repoRoot, ".claude-plugin", "marketplace.json") : null;
96
97
  const codexPluginPath = join(pluginRoot, ".codex-plugin", "plugin.json");
97
98
  const claudePluginPath = join(pluginRoot, ".claude-plugin", "plugin.json");
99
+ const installationProvenancePath = join(pluginRoot, ".agdf-installation.json");
100
+ const legacyLocalInstallMarkerPath = join(pluginRoot, ".agdf-local-install.json");
98
101
  const pluginDefinitionPath = join(pluginRoot, "meta", "agdf-plugin.definition.json");
99
102
  const agentRouterPath = join(pluginRoot, "meta", "agdf-agent-router.md");
100
103
  const runtimeContractPath = join(pluginRoot, "meta", "agdf-runtime-contract.md");
@@ -203,6 +206,32 @@ function readJson(path, label) {
203
206
  }
204
207
  }
205
208
 
209
+ function digestPluginSource(root, canonicalVersion) {
210
+ const files = [];
211
+ function visit(directory) {
212
+ for (const name of readdirSync(directory).sort()) {
213
+ const path = join(directory, name);
214
+ const stats = statSync(path);
215
+ if (stats.isDirectory()) visit(path);
216
+ else if (stats.isFile()) files.push(path);
217
+ }
218
+ }
219
+ visit(root);
220
+ const hash = createHash("sha256");
221
+ for (const path of files) {
222
+ const normalizedPath = relative(root, path).replaceAll("\\", "/");
223
+ if ([".agdf-installation.json", ".agdf-local-install.json"].includes(normalizedPath)) continue;
224
+ const content = normalizedPath === ".codex-plugin/plugin.json"
225
+ ? `${JSON.stringify({ ...readJson(path, "Codex plugin manifest"), version: canonicalVersion }, null, 2)}\n`
226
+ : readFileSync(path);
227
+ hash.update(normalizedPath);
228
+ hash.update("\0");
229
+ hash.update(content);
230
+ hash.update("\0");
231
+ }
232
+ return hash.digest("hex");
233
+ }
234
+
206
235
  function stripAllowedGerman(content) {
207
236
  let next = content;
208
237
  for (const fragment of allowedGermanFragments) {
@@ -300,7 +329,8 @@ assertFile(join(controlRoot, "README.md"), "AGDF control scaffold README");
300
329
  assertFile(pluginLicensePath, "plugin LICENSE");
301
330
 
302
331
  if (sourceMode) {
303
- assertFile(marketplacePath, "plugin marketplace");
332
+ if (isFile(codexSourceMarketplacePath)) failures.push("source checkout must not expose a runtime-free Codex marketplace");
333
+ if (isFile(claudeSourceMarketplacePath)) failures.push("source checkout must not expose a runtime-free Claude marketplace");
304
334
  assertFile(agdfPackagePath, "agdf CLI package manifest");
305
335
  assertFile(createAgdfPackagePath, "create-agdf package manifest");
306
336
  assertFile(pagesPackagePath, "Pages package manifest");
@@ -328,6 +358,7 @@ for (const forbiddenRuntimeDirectory of ["installers", "lifecycle", "scaffold"])
328
358
  }
329
359
  for (const requiredRuntimeFile of sourceMode ? [] : [
330
360
  "runtime/create-agdf/lib/runtime/validator-application.js",
361
+ "runtime/create-agdf/lib/runtime/plugin-provenance.js",
331
362
  "runtime/create-agdf/lib/cli/validation-handlers.js",
332
363
  ]) assertFile(join(pluginRoot, requiredRuntimeFile), `focused surface-local runtime module ${requiredRuntimeFile}`);
333
364
  if (!sourceMode && isFile(localRuntimeEntrypointPath)) {
@@ -401,6 +432,8 @@ for (const required of [
401
432
  }
402
433
  const codexPlugin = isFile(codexPluginPath) ? readJson(codexPluginPath, "Codex plugin manifest") : null;
403
434
  const claudePlugin = isFile(claudePluginPath) ? readJson(claudePluginPath, "Claude plugin manifest") : null;
435
+ const installationProvenance = isFile(installationProvenancePath) ? readJson(installationProvenancePath, "AGDF installation provenance") : null;
436
+ const legacyLocalInstallMarker = isFile(legacyLocalInstallMarkerPath) ? readJson(legacyLocalInstallMarkerPath, "legacy AGDF local install marker") : null;
404
437
  const agdfPackage = isFile(agdfPackagePath) ? readJson(agdfPackagePath, "agdf CLI package manifest") : null;
405
438
  const createAgdfPackage = isFile(createAgdfPackagePath) ? readJson(createAgdfPackagePath, "create-agdf package manifest") : null;
406
439
  const pagesPackage = isFile(pagesPackagePath) ? readJson(pagesPackagePath, "Pages package manifest") : null;
@@ -637,8 +670,18 @@ if (pluginDefinition) {
637
670
  if (!skill?.boundary) failures.push(`canonical AGDF plugin definition skill ${skill?.slug ?? "<unknown>"} must declare boundary`);
638
671
  }
639
672
  }
640
- if (pluginDefinition.marketplaces?.repository?.name !== "agdf-repo") failures.push("canonical AGDF plugin definition repository marketplace name must be agdf-repo");
641
- if (pluginDefinition.marketplaces?.repository?.displayName !== "This repository") failures.push("canonical AGDF plugin definition repository marketplace display name must be This repository");
673
+ const expectedProfiles = {
674
+ "source-development": { runtime: "absent", installable: false, machineValidation: "unavailable" },
675
+ "runtime-plugin": { runtime: "required", installable: true, machineValidation: "local_exact_version_digest" },
676
+ "opencode-config-local": { runtime: "config_local_package", installable: true, machineValidation: "local_exact_version" },
677
+ "portable-skills": { runtime: "absent", installable: true, machineValidation: "unavailable_or_external_required" },
678
+ };
679
+ if (pluginDefinition.distributionProfiles?.schemaVersion !== 1
680
+ || pluginDefinition.distributionProfiles?.marketplaceIdentities?.durable !== "agdf"
681
+ || pluginDefinition.distributionProfiles?.marketplaceIdentities?.generatedRepository !== "agdf-repo"
682
+ || JSON.stringify(pluginDefinition.distributionProfiles?.profiles) !== JSON.stringify(expectedProfiles)) {
683
+ failures.push("canonical AGDF plugin definition distribution profiles must match the runtime integrity contract");
684
+ }
642
685
  expectedSkills = (pluginDefinition.skillSet ?? [])
643
686
  .map((skill) => `${pluginDefinition.codex?.skillPrefix ?? ""}${skill?.slug ?? ""}`)
644
687
  .sort();
@@ -709,7 +752,21 @@ if (isFile(pagesSiteDataPath)) {
709
752
 
710
753
  if (codexPlugin && pluginDefinition) {
711
754
  if (codexPlugin.name !== pluginDefinition.id) failures.push("Codex plugin manifest name must match canonical AGDF plugin definition");
712
- if (codexPlugin.version !== pluginDefinition.version) failures.push("Codex plugin manifest version must match canonical AGDF plugin definition");
755
+ const expectedInstallVersion = installationProvenance?.codex_install_version ?? pluginDefinition.version;
756
+ const validInstalledProjection = !sourceMode
757
+ && installationProvenance?.schema_version === 1
758
+ && installationProvenance?.owner === "create-agdf"
759
+ && installationProvenance?.profile_id === "runtime-plugin"
760
+ && installationProvenance?.marketplace_id === "agdf"
761
+ && installationProvenance?.canonical_version === pluginDefinition.version
762
+ && /^[a-f0-9]{64}$/.test(installationProvenance?.source_digest ?? "")
763
+ && installationProvenance?.source_digest === digestPluginSource(pluginRoot, pluginDefinition.version)
764
+ && installationProvenance?.runtime_digest === localRuntimeManifest?.digest
765
+ && codexPlugin.version === expectedInstallVersion;
766
+ if (codexPlugin.version !== pluginDefinition.version && !validInstalledProjection) failures.push("Codex plugin manifest version must match canonical AGDF plugin definition or one owned installed projection");
767
+ if (installationProvenance && !validInstalledProjection) failures.push("AGDF installation provenance must match plugin, runtime and normalized source digests");
768
+ if (sourceMode && (installationProvenance || legacyLocalInstallMarker)) failures.push("source plugin must not contain AGDF installation provenance");
769
+ if (!sourceMode && legacyLocalInstallMarker) failures.push("installed plugin must not retain the legacy AGDF local install marker");
713
770
  if (codexPlugin.description !== pluginDefinition.description) failures.push("Codex plugin manifest description must match canonical AGDF plugin definition");
714
771
  if (codexPlugin.homepage !== pluginDefinition.homepage) failures.push("Codex plugin manifest homepage must match canonical AGDF plugin definition");
715
772
  if (codexPlugin.repository !== pluginDefinition.repository) failures.push("Codex plugin manifest repository must match canonical AGDF plugin definition");
@@ -962,18 +1019,6 @@ if (isFile(runtimeContractPath)) {
962
1019
  }
963
1020
  }
964
1021
 
965
- if (sourceMode) {
966
- const marketplace = isFile(marketplacePath) ? readJson(marketplacePath, "plugin marketplace") : null;
967
- const agdfMarketplaceEntry = marketplace?.plugins?.find((plugin) => plugin?.name === "agdf");
968
- if (!agdfMarketplaceEntry) {
969
- failures.push("plugin marketplace must expose agdf");
970
- } else {
971
- if (agdfMarketplaceEntry.source !== "./plugin/") failures.push("plugin marketplace agdf source must point to ./plugin/");
972
- if (Object.hasOwn(agdfMarketplaceEntry, "policy")) failures.push("Claude plugin marketplace agdf entry must not use unsupported policy field");
973
- if (agdfMarketplaceEntry.category !== "Productivity") failures.push("plugin marketplace agdf category must be Productivity");
974
- }
975
- }
976
-
977
1022
  const actualSkills = readdirSync(skillRoot)
978
1023
  .filter((entry) => statSync(join(skillRoot, entry)).isDirectory())
979
1024
  .sort();
@@ -1,6 +1,6 @@
1
1
  # Availability Decision Record
2
2
 
3
- - release: `0.13.5`
3
+ - release: `0.13.7`
4
4
  - decision_state: `pending`
5
5
  - decision_owner: verified publisher
6
6
  - countries: not selected
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "evidenceStates": [
5
5
  "common",
6
6
  "codex-specific",
@@ -1,4 +1,4 @@
1
- # AGDF 0.13.5 — Initial OpenAI Public Plugin Candidate
1
+ # AGDF 0.13.7 — Initial OpenAI Public Plugin Candidate
2
2
 
3
3
  This candidate packages the canonical AGDF workflow skills for public discovery in ChatGPT and
4
4
  Codex. It helps users assess delivery fit, preserve explicit human approvals, inspect existing-system
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "cases": [
5
5
  {
6
6
  "id": "positive-proportional-fit",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.13.5",
3
+ "version": "0.13.7",
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.13.5",
4
+ "version": "0.13.7",
5
5
  "displayName": "AI Governance & Delivery Framework",
6
6
  "developerName": "Arndt Gold",
7
7
  "description": "Control layer for governed AI-assisted delivery.",
@@ -33,9 +33,8 @@
33
33
  "Write"
34
34
  ],
35
35
  "defaultPrompt": [
36
- "Assess whether AGDF is proportionate for this repository and request before proposing any implementation. Explain AGDF's purpose and practical benefits, weigh governance overhead against the project's delivery risk, and recommend the lightest suitable path — or explicitly advise against AGDF where it would add more process than value.",
36
+ "Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
37
37
  "Start this request under AGDF governance.",
38
- "Create durable AGDF control state for this repository.",
39
38
  "Close this delivery run with an auditable AGDF report."
40
39
  ],
41
40
  "hooks": "hooks/hooks.json"
@@ -44,9 +43,8 @@
44
43
  "skillPrefix": "",
45
44
  "agentRouter": "meta/agdf-agent-router.md",
46
45
  "defaultPrompt": [
47
- "Assess whether AGDF is proportionate for this repository and request before proposing any implementation. Explain AGDF's purpose and practical benefits, weigh governance overhead against the project's delivery risk, and recommend the lightest suitable path — or explicitly advise against AGDF where it would add more process than value.",
46
+ "Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
48
47
  "Start this request under AGDF governance.",
49
- "Create durable AGDF control state for this repository.",
50
48
  "Close this delivery run with an auditable AGDF report."
51
49
  ]
52
50
  },
@@ -254,10 +252,33 @@
254
252
  "boundary": "supports Quality Readiness; no final QA decision"
255
253
  }
256
254
  ],
257
- "marketplaces": {
258
- "repository": {
259
- "name": "agdf-repo",
260
- "displayName": "This repository"
255
+ "distributionProfiles": {
256
+ "schemaVersion": 1,
257
+ "marketplaceIdentities": {
258
+ "durable": "agdf",
259
+ "generatedRepository": "agdf-repo"
260
+ },
261
+ "profiles": {
262
+ "source-development": {
263
+ "runtime": "absent",
264
+ "installable": false,
265
+ "machineValidation": "unavailable"
266
+ },
267
+ "runtime-plugin": {
268
+ "runtime": "required",
269
+ "installable": true,
270
+ "machineValidation": "local_exact_version_digest"
271
+ },
272
+ "opencode-config-local": {
273
+ "runtime": "config_local_package",
274
+ "installable": true,
275
+ "machineValidation": "local_exact_version"
276
+ },
277
+ "portable-skills": {
278
+ "runtime": "absent",
279
+ "installable": true,
280
+ "machineValidation": "unavailable_or_external_required"
281
+ }
261
282
  }
262
283
  }
263
284
  }
@@ -1,6 +1,6 @@
1
1
  # Availability Decision Record
2
2
 
3
- - release: `0.13.5`
3
+ - release: `0.13.7`
4
4
  - decision_state: `pending`
5
5
  - decision_owner: verified publisher
6
6
  - countries: not selected
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "evidenceStates": [
5
5
  "common",
6
6
  "codex-specific",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
4
- "digest": "5e93c979972386a5b255c67bcbc491e13a21b7a6a046c292bd0fd4cfd60a72e0",
3
+ "releaseVersion": "0.13.7",
4
+ "digest": "66e5c26d1673393afd09b24ff17306497f958414ab24f2e1e3b55fb7cd3ad18e",
5
5
  "files": [
6
6
  {
7
7
  "path": ".codex-plugin/plugin.json",
8
- "sha256": "50cfbd46d2b9584ce53fd58ef30d78560dff54f086f138bacb4e882ce558d06f"
8
+ "sha256": "be5e69d2c1c1a1ac8e1da3b4770003b027ddbf32b7dd7eeab2519aa6316a7b32"
9
9
  },
10
10
  {
11
11
  "path": "assets/agdf-icon.svg",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  {
31
31
  "path": "meta/agdf-plugin.definition.json",
32
- "sha256": "65918917ec5a640a093b26638fca4151de2863d659280e97cb88a10722951312"
32
+ "sha256": "ce61ec6a7210c34616e4eda529029629c3e3b74756921c437bc2aa51387dc56a"
33
33
  },
34
34
  {
35
35
  "path": "meta/agdf-runtime-contract.md",
@@ -157,23 +157,23 @@
157
157
  },
158
158
  {
159
159
  "path": "submission/openai/availability.md",
160
- "sha256": "65cb1697e3d7a9cd096e8adee1aa5670f3a075f3ff000d1c8d0e4dcc4a2f65a9"
160
+ "sha256": "940be7ccc82c41be6c2a53e58e7fac6e1d580d1c622ee8457134ddb9d502b2ba"
161
161
  },
162
162
  {
163
163
  "path": "submission/openai/capability-matrix.json",
164
- "sha256": "0509483fd59a74e924fb1339bbe71f68bc00dd70c948dfda99f77c6b74edc8ac"
164
+ "sha256": "108c87450f6c234dec7c371df21a80a31647fb158eaae9768af14095f3dbc448"
165
165
  },
166
166
  {
167
167
  "path": "submission/openai/listing.json",
168
- "sha256": "55d09444fcbc0b8f4d953d1ede9e930647f6551236e6fac54f759f127c2ccf6a"
168
+ "sha256": "daeaad9b36df9f37b07c505ef081297e67bc171b3a58bca5e2b022f3658c36f3"
169
169
  },
170
170
  {
171
171
  "path": "submission/openai/release-notes.md",
172
- "sha256": "dfca2f38093336d508e341ce9ddd79fefa76db59aac9a9bed7b513ab39a21bf3"
172
+ "sha256": "69fb2e3dfd2af90de40c07019f4dac960d950871dfdf5819be59613688286b7b"
173
173
  },
174
174
  {
175
175
  "path": "submission/openai/reviewer-cases.json",
176
- "sha256": "6e242aaf7b381353ffd5924f91cc257bc65c14b1f8960612ec33db9558ee0c35"
176
+ "sha256": "dc3b27cd47fb390e105c386c3e842f9da0ea554d357d42a4d99a8a13655431b1"
177
177
  }
178
178
  ]
179
179
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "submissionType": "skills",
5
5
  "identity": {
6
6
  "technicalId": "agdf",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "candidateState": "repository_ready",
5
5
  "submissionReady": false,
6
6
  "submissionBlockers": [
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "bundle": {
18
18
  "state": "pass",
19
- "detail": "43 inventoried files; inventory digest 5e93c979972386a5b255c67bcbc491e13a21b7a6a046c292bd0fd4cfd60a72e0"
19
+ "detail": "43 inventoried files; inventory digest 66e5c26d1673393afd09b24ff17306497f958414ab24f2e1e3b55fb7cd3ad18e"
20
20
  },
21
21
  "installed_host": {
22
22
  "state": "unverified",
@@ -1,6 +1,6 @@
1
1
  # AGDF Public Plugin Readiness
2
2
 
3
- - release: `0.13.5`
3
+ - release: `0.13.7`
4
4
  - candidate_state: `repository_ready`
5
5
  - submission_ready: `false`
6
6
 
@@ -9,7 +9,7 @@
9
9
  | Class | State | Detail |
10
10
  |---|---|---|
11
11
  | repository | pass | canonical contract and deterministic source checks |
12
- | bundle | pass | 43 inventoried files; inventory digest 5e93c979972386a5b255c67bcbc491e13a21b7a6a046c292bd0fd4cfd60a72e0 |
12
+ | bundle | pass | 43 inventoried files; inventory digest 66e5c26d1673393afd09b24ff17306497f958414ab24f2e1e3b55fb7cd3ad18e |
13
13
  | installed_host | unverified | PPD-L02 and PPD-L03 not performed |
14
14
  | portal | unverified | unverified |
15
15
  | post_publication | unverified | not published |
@@ -1,4 +1,4 @@
1
- # AGDF 0.13.5 — Initial OpenAI Public Plugin Candidate
1
+ # AGDF 0.13.7 — Initial OpenAI Public Plugin Candidate
2
2
 
3
3
  This candidate packages the canonical AGDF workflow skills for public discovery in ChatGPT and
4
4
  Codex. It helps users assess delivery fit, preserve explicit human approvals, inspect existing-system
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.13.5",
3
+ "releaseVersion": "0.13.7",
4
4
  "cases": [
5
5
  {
6
6
  "id": "positive-proportional-fit",