create-agdf 0.14.3 → 0.14.5

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 (80) hide show
  1. package/README.md +34 -2
  2. package/generated/.opencode/contracts/interaction.md +2 -2
  3. package/generated/.opencode/skills/agdf-gate-check/SKILL.md +6 -4
  4. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  5. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  6. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  7. package/generated/plugins/agdf/meta/contracts/interaction.md +2 -2
  8. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
  9. package/generated/plugins/agdf/meta/distribution-profile-history.json +132 -0
  10. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  11. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
  12. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
  13. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
  14. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
  15. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
  16. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
  17. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
  18. package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
  19. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
  20. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  21. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  22. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -0
  23. package/generated/plugins/agdf/skills/gate-check/SKILL.md +6 -4
  24. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  25. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  26. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  27. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  28. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +55 -35
  29. package/generated/plugins/copilot/agdf/copilot-skills/agdf-gate-check/SKILL.md +6 -4
  30. package/generated/plugins/copilot/agdf/copilot-skills/contracts/interaction.md +2 -2
  31. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
  32. package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +132 -0
  33. package/generated/plugins/copilot/agdf/plugin.json +1 -1
  34. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  35. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
  36. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
  37. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
  38. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
  39. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
  40. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
  41. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
  42. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
  43. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
  44. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
  45. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
  46. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  47. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
  48. package/generated/submissions/openai/agdf/meta/contracts/interaction.md +2 -2
  49. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
  50. package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +132 -0
  51. package/generated/submissions/openai/agdf/skills/gate-check/SKILL.md +6 -4
  52. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  53. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  54. package/generated/submissions/openai/agdf/submission/openai/inventory.json +16 -12
  55. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  56. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  57. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  58. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  59. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  60. package/lib/cli/application.js +24 -6
  61. package/lib/cli/command-registry.js +8 -1
  62. package/lib/cli/parse-args.js +3 -0
  63. package/lib/control-evaluation/doctor.js +13 -0
  64. package/lib/control-evaluation/gate-check.js +64 -13
  65. package/lib/control-evaluation/run-state.js +6 -0
  66. package/lib/control-state/run-identity.js +9 -0
  67. package/lib/control-state/run-state-parser.js +4 -2
  68. package/lib/installers/claude-cache-recovery.js +76 -0
  69. package/lib/installers/copilot-settings.js +146 -16
  70. package/lib/installers/local-marketplace.js +169 -14
  71. package/lib/installers/plugin-installers.js +96 -9
  72. package/lib/interaction-presentation.js +57 -7
  73. package/lib/lifecycle/operations.js +28 -4
  74. package/lib/lifecycle/result.js +4 -4
  75. package/lib/release/profile-history.js +222 -0
  76. package/lib/release/version-bump.js +549 -0
  77. package/lib/release/version-coherence.js +92 -38
  78. package/lib/runtime/distribution-profile-history.js +173 -0
  79. package/lib/runtime/plugin-provenance.js +46 -3
  80. package/package.json +7 -3
@@ -1,34 +1,78 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
 
4
- function jsonVersion(relativePath, select = (value) => value.version) {
5
- return {
4
+ function valueAtPath(value, path) {
5
+ return path.reduce((current, key) => current?.[key], value);
6
+ }
7
+
8
+ function setValueAtPath(value, path, nextVersion) {
9
+ let current = value;
10
+ for (const key of path.slice(0, -1)) {
11
+ if (!current?.[key] || typeof current[key] !== "object" || Array.isArray(current[key])) {
12
+ throw new Error(`missing JSON version path ${path.join(".")}`);
13
+ }
14
+ current = current[key];
15
+ }
16
+ const key = path.at(-1);
17
+ if (typeof current?.[key] !== "string") {
18
+ throw new Error(`missing JSON version path ${path.join(".")}`);
19
+ }
20
+ current[key] = nextVersion;
21
+ }
22
+
23
+ function jsonVersion(relativePath, path = ["version"], options = {}) {
24
+ return Object.freeze({
6
25
  relativePath,
7
- read: (repoRoot) => select(JSON.parse(readFileSync(join(repoRoot, relativePath), "utf8"))),
8
- };
26
+ writable: options.writable ?? false,
27
+ evidence: options.evidence ?? true,
28
+ readContent(content) {
29
+ return valueAtPath(JSON.parse(content), path);
30
+ },
31
+ updateContent(content, nextVersion) {
32
+ const value = JSON.parse(content);
33
+ setValueAtPath(value, path, nextVersion);
34
+ return `${JSON.stringify(value, null, 2)}\n`;
35
+ },
36
+ });
9
37
  }
10
38
 
11
- function textVersion(relativePath, pattern) {
12
- return {
39
+ function textVersion(relativePath, pattern, replacement, options = {}) {
40
+ return Object.freeze({
13
41
  relativePath,
14
- read: (repoRoot) => readFileSync(join(repoRoot, relativePath), "utf8").match(pattern)?.[1],
15
- };
42
+ writable: options.writable ?? false,
43
+ evidence: options.evidence ?? true,
44
+ readContent(content) {
45
+ return content.match(pattern)?.[1];
46
+ },
47
+ updateContent(content, nextVersion) {
48
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
49
+ const matches = [...content.matchAll(new RegExp(pattern.source, flags))];
50
+ if (matches.length !== 1) {
51
+ throw new Error(`expected exactly one version field in ${relativePath}; found ${matches.length}`);
52
+ }
53
+ return content.replace(pattern, replacement(nextVersion));
54
+ },
55
+ });
16
56
  }
17
57
 
18
- const VERSION_SURFACES = [
19
- jsonVersion("plugin/.codex-plugin/plugin.json"),
20
- jsonVersion("plugin/.claude-plugin/plugin.json"),
21
- jsonVersion("create-agdf/package.json"),
22
- jsonVersion("agdf/package.json"),
23
- jsonVersion("agdf/package.json", (value) => value.dependencies?.["create-agdf"]),
24
- jsonVersion("pages/package.json"),
25
- jsonVersion("pages/package-lock.json"),
26
- jsonVersion("pages/package-lock.json", (value) => value.packages?.[""]?.version),
27
- textVersion("pages/src/data/site.ts", /version:\s*"([^"]+)"/),
28
- jsonVersion("plugin/submission/openai/capability-matrix.json", (value) => value.releaseVersion),
29
- jsonVersion("plugin/submission/openai/reviewer-cases.json", (value) => value.releaseVersion),
30
- textVersion("plugin/submission/openai/release-notes.md", /^# AGDF (\S+) —/m),
31
- textVersion("plugin/submission/openai/availability.md", /^- release: `([^`]+)`$/m),
58
+ const writable = Object.freeze({ writable: true });
59
+ const authority = Object.freeze({ writable: true, evidence: false });
60
+
61
+ export const RELEASE_VERSION_SURFACES = Object.freeze([
62
+ jsonVersion("plugin/meta/agdf-plugin.definition.json", ["version"], authority),
63
+ jsonVersion("plugin/.codex-plugin/plugin.json", ["version"], writable),
64
+ jsonVersion("plugin/.claude-plugin/plugin.json", ["version"], writable),
65
+ jsonVersion("create-agdf/package.json", ["version"], writable),
66
+ jsonVersion("agdf/package.json", ["version"], writable),
67
+ jsonVersion("agdf/package.json", ["dependencies", "create-agdf"], writable),
68
+ jsonVersion("pages/package.json", ["version"], writable),
69
+ jsonVersion("pages/package-lock.json", ["version"], writable),
70
+ jsonVersion("pages/package-lock.json", ["packages", "", "version"], writable),
71
+ textVersion("pages/src/data/site.ts", /version:\s*"([^"]+)"/, (version) => `version: "${version}"`, writable),
72
+ jsonVersion("plugin/submission/openai/capability-matrix.json", ["releaseVersion"], writable),
73
+ jsonVersion("plugin/submission/openai/reviewer-cases.json", ["releaseVersion"], writable),
74
+ textVersion("plugin/submission/openai/release-notes.md", /^# AGDF (\S+) —/m, (version) => `# AGDF ${version} —`, writable),
75
+ textVersion("plugin/submission/openai/availability.md", /^- release: `([^`]+)`$/m, (version) => `- release: \`${version}\``, writable),
32
76
  jsonVersion("create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json"),
33
77
  jsonVersion("create-agdf/generated/plugins/agdf/.codex-plugin/plugin.json"),
34
78
  jsonVersion("create-agdf/generated/plugins/agdf/.claude-plugin/plugin.json"),
@@ -40,25 +84,35 @@ const VERSION_SURFACES = [
40
84
  jsonVersion("create-agdf/generated/plugins/copilot/agdf/runtime/create-agdf/package.json"),
41
85
  jsonVersion("create-agdf/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json"),
42
86
  jsonVersion("create-agdf/generated/submissions/openai/agdf/.codex-plugin/plugin.json"),
43
- jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/capability-matrix.json", (value) => value.releaseVersion),
44
- jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json", (value) => value.releaseVersion),
45
- jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/listing.json", (value) => value.releaseVersion),
46
- jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/inventory.json", (value) => value.releaseVersion),
47
- jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/readiness.json", (value) => value.releaseVersion),
48
- textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/release-notes.md", /^# AGDF (\S+) —/m),
49
- textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/availability.md", /^- release: `([^`]+)`$/m),
50
- textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/readiness.md", /^- release: `([^`]+)`$/m),
51
- ];
87
+ jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/capability-matrix.json", ["releaseVersion"]),
88
+ jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json", ["releaseVersion"]),
89
+ jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/listing.json", ["releaseVersion"]),
90
+ jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/inventory.json", ["releaseVersion"]),
91
+ jsonVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/readiness.json", ["releaseVersion"]),
92
+ textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/release-notes.md", /^# AGDF (\S+) —/m, () => ""),
93
+ textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/availability.md", /^- release: `([^`]+)`$/m, () => ""),
94
+ textVersion("create-agdf/generated/submissions/openai/agdf/submission/openai/readiness.md", /^- release: `([^`]+)`$/m, () => ""),
95
+ ]);
96
+
97
+ export const WRITABLE_RELEASE_VERSION_SURFACES = Object.freeze(
98
+ RELEASE_VERSION_SURFACES.filter((surface) => surface.writable),
99
+ );
52
100
 
53
101
  export function collectReleaseVersionEvidence({ repoRoot }) {
54
102
  repoRoot = resolve(repoRoot);
55
- const definitionPath = join(repoRoot, "plugin", "meta", "agdf-plugin.definition.json");
56
- const expectedVersion = JSON.parse(readFileSync(definitionPath, "utf8")).version;
57
- const entries = VERSION_SURFACES.map(({ relativePath, read }) => {
58
- const absolutePath = join(repoRoot, relativePath);
59
- if (!existsSync(absolutePath)) return { relativePath, actualVersion: undefined };
60
- return { relativePath, actualVersion: read(repoRoot) };
61
- });
103
+ const authoritySurface = RELEASE_VERSION_SURFACES[0];
104
+ const definitionPath = join(repoRoot, authoritySurface.relativePath);
105
+ const expectedVersion = authoritySurface.readContent(readFileSync(definitionPath, "utf8"));
106
+ const entries = RELEASE_VERSION_SURFACES
107
+ .filter((surface) => surface.evidence)
108
+ .map((surface) => {
109
+ const absolutePath = join(repoRoot, surface.relativePath);
110
+ if (!existsSync(absolutePath)) return { relativePath: surface.relativePath, actualVersion: undefined };
111
+ return {
112
+ relativePath: surface.relativePath,
113
+ actualVersion: surface.readContent(readFileSync(absolutePath, "utf8")),
114
+ };
115
+ });
62
116
  return { expectedVersion, entries };
63
117
  }
64
118
 
@@ -0,0 +1,173 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ const SHA256 = /^[a-f0-9]{64}$/;
4
+ const RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
5
+ const TOP_LEVEL_KEYS = ["contracts", "releases", "schema_version"];
6
+ const CONTRACT_KEYS = ["contract_digest", "distribution_profiles"];
7
+ const RELEASE_KEYS = ["contract_id", "entry_digest", "profile_id", "provenance_schema_version", "status"];
8
+
9
+ function canonicalize(value) {
10
+ if (Array.isArray(value)) return value.map(canonicalize);
11
+ if (value && typeof value === "object") {
12
+ return Object.fromEntries(
13
+ Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]),
14
+ );
15
+ }
16
+ return value;
17
+ }
18
+
19
+ function canonicalJson(value) {
20
+ return JSON.stringify(canonicalize(value));
21
+ }
22
+
23
+ function digest(value) {
24
+ return createHash("sha256").update(canonicalJson(value)).digest("hex");
25
+ }
26
+
27
+ function exactKeys(value, expected) {
28
+ return value && typeof value === "object" && !Array.isArray(value)
29
+ && JSON.stringify(Object.keys(value).sort()) === JSON.stringify(expected);
30
+ }
31
+
32
+ function sortedKeys(value) {
33
+ const keys = Object.keys(value);
34
+ return JSON.stringify(keys) === JSON.stringify([...keys].sort());
35
+ }
36
+
37
+ function invalid(reason) {
38
+ return { status: "invalid", reason };
39
+ }
40
+
41
+ export function canonicalDistributionProfileDigest(distributionProfiles) {
42
+ return digest(distributionProfiles);
43
+ }
44
+
45
+ export function canonicalDistributionProfileEntryDigest({
46
+ version,
47
+ contract_id,
48
+ contract_digest,
49
+ provenance_schema_version = 1,
50
+ profile_id = "runtime-plugin",
51
+ status = "supported",
52
+ }) {
53
+ return digest({
54
+ version,
55
+ contract_id,
56
+ contract_digest,
57
+ provenance_schema_version,
58
+ profile_id,
59
+ status,
60
+ });
61
+ }
62
+
63
+ export function validateDistributionProfileHistory(catalogue) {
64
+ if (!exactKeys(catalogue, TOP_LEVEL_KEYS)
65
+ || catalogue.schema_version !== 1
66
+ || !catalogue.contracts || typeof catalogue.contracts !== "object" || Array.isArray(catalogue.contracts)
67
+ || !catalogue.releases || typeof catalogue.releases !== "object" || Array.isArray(catalogue.releases)
68
+ || !sortedKeys(catalogue.contracts)
69
+ || !sortedKeys(catalogue.releases)
70
+ || Object.keys(catalogue.contracts).length === 0
71
+ || Object.keys(catalogue.releases).length === 0) {
72
+ return invalid("profile_history_invalid");
73
+ }
74
+
75
+ const contractDigests = new Set();
76
+ for (const contract of Object.values(catalogue.contracts)) {
77
+ if (!exactKeys(contract, CONTRACT_KEYS)
78
+ || !contract.distribution_profiles
79
+ || typeof contract.distribution_profiles !== "object"
80
+ || Array.isArray(contract.distribution_profiles)
81
+ || !SHA256.test(contract.contract_digest ?? "")
82
+ || canonicalDistributionProfileDigest(contract.distribution_profiles) !== contract.contract_digest) {
83
+ return invalid("profile_history_invalid");
84
+ }
85
+ if (contractDigests.has(contract.contract_digest)) return invalid("profile_history_invalid");
86
+ contractDigests.add(contract.contract_digest);
87
+ }
88
+
89
+ const referencedContracts = new Set();
90
+ for (const [version, release] of Object.entries(catalogue.releases)) {
91
+ const contract = catalogue.contracts[release?.contract_id];
92
+ if (!RELEASE_VERSION.test(version)
93
+ || !exactKeys(release, RELEASE_KEYS)
94
+ || !contract
95
+ || release.provenance_schema_version !== 1
96
+ || release.profile_id !== "runtime-plugin"
97
+ || release.status !== "supported"
98
+ || !SHA256.test(release.entry_digest ?? "")) {
99
+ return invalid("profile_history_invalid");
100
+ }
101
+ referencedContracts.add(release.contract_id);
102
+ const expectedDigest = canonicalDistributionProfileEntryDigest({
103
+ version,
104
+ contract_id: release.contract_id,
105
+ contract_digest: contract.contract_digest,
106
+ provenance_schema_version: release.provenance_schema_version,
107
+ profile_id: release.profile_id,
108
+ status: release.status,
109
+ });
110
+ if (release.entry_digest !== expectedDigest) return invalid("profile_history_invalid");
111
+ }
112
+ if (referencedContracts.size !== Object.keys(catalogue.contracts).length) {
113
+ return invalid("profile_history_invalid");
114
+ }
115
+
116
+ return { status: "matched", reason: "profile_history_valid" };
117
+ }
118
+
119
+ export function classifyHistoricalDistributionProfile({ catalogue, version, distributionProfiles }) {
120
+ const validation = validateDistributionProfileHistory(catalogue);
121
+ if (validation.status !== "matched") {
122
+ return {
123
+ status: "invalid",
124
+ reason: "profile_history_invalid",
125
+ release_version: null,
126
+ contract_id: null,
127
+ contract_digest: null,
128
+ entry_digest: null,
129
+ };
130
+ }
131
+ const release = Object.hasOwn(catalogue.releases, version) ? catalogue.releases[version] : null;
132
+ if (!release) {
133
+ return {
134
+ status: "unsupported",
135
+ reason: "historical_contract_unsupported",
136
+ release_version: null,
137
+ contract_id: null,
138
+ contract_digest: null,
139
+ entry_digest: null,
140
+ };
141
+ }
142
+ const contract = catalogue.contracts[release.contract_id];
143
+ if (!distributionProfiles || typeof distributionProfiles !== "object" || Array.isArray(distributionProfiles)) {
144
+ return {
145
+ status: "invalid",
146
+ reason: "historical_contract_invalid",
147
+ release_version: version,
148
+ contract_id: release.contract_id,
149
+ contract_digest: contract.contract_digest,
150
+ entry_digest: release.entry_digest,
151
+ };
152
+ }
153
+ const observedDigest = canonicalDistributionProfileDigest(distributionProfiles);
154
+ if (observedDigest !== contract.contract_digest
155
+ || canonicalJson(distributionProfiles) !== canonicalJson(contract.distribution_profiles)) {
156
+ return {
157
+ status: "invalid",
158
+ reason: "historical_contract_invalid",
159
+ release_version: version,
160
+ contract_id: release.contract_id,
161
+ contract_digest: contract.contract_digest,
162
+ entry_digest: release.entry_digest,
163
+ };
164
+ }
165
+ return {
166
+ status: "matched",
167
+ reason: "historical_contract_matched",
168
+ release_version: version,
169
+ contract_id: release.contract_id,
170
+ contract_digest: contract.contract_digest,
171
+ entry_digest: release.entry_digest,
172
+ };
173
+ }
@@ -137,6 +137,22 @@ export function validateDistributionProfiles(definition) {
137
137
  return { status: "matched", contract };
138
138
  }
139
139
 
140
+ function classifyInstalledHistoricalProfile(catalogue, definition, classifyHistoricalProfile) {
141
+ if (typeof classifyHistoricalProfile !== "function") {
142
+ return { status: "invalid", reason: "profile_history_invalid" };
143
+ }
144
+ const result = classifyHistoricalProfile({
145
+ catalogue,
146
+ version: definition?.version,
147
+ distributionProfiles: definition?.distributionProfiles,
148
+ });
149
+ if (result.status !== "matched") return result;
150
+ return {
151
+ ...result,
152
+ contract: catalogue.contracts[result.contract_id].distribution_profiles,
153
+ };
154
+ }
155
+
140
156
  export function inspectGeneratedRepositoryMarketplace(targetDir) {
141
157
  const marketplacePath = join(targetDir, ".agents", "plugins", "marketplace.json");
142
158
  if (!existsSync(marketplacePath)) return { status: "absent", marketplacePath };
@@ -196,11 +212,23 @@ export function inspectInstallationProvenance(pluginRoot, {
196
212
  allowLegacy = false,
197
213
  profileId = "runtime-plugin",
198
214
  inventoryDigest = null,
215
+ allowHistoricalProfilesForMigration = false,
216
+ distributionProfileHistory = null,
217
+ classifyHistoricalProfile = null,
199
218
  } = {}) {
200
219
  const markerPath = join(pluginRoot, INSTALLATION_PROVENANCE_FILE);
201
220
  const legacyPath = join(pluginRoot, LEGACY_LOCAL_INSTALL_FILE);
202
221
  if (!existsSync(markerPath)) {
203
222
  if (allowLegacy && existsSync(legacyPath)) {
223
+ const currentProfile = validateDistributionProfiles(definition);
224
+ if (Object.hasOwn(definition ?? {}, "distributionProfiles")
225
+ && currentProfile.status !== "matched") {
226
+ return allowHistoricalProfilesForMigration
227
+ ? classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile).status === "matched"
228
+ ? { status: "invalid", reason: "installation_provenance_invalid" }
229
+ : classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile)
230
+ : currentProfile;
231
+ }
204
232
  const marker = readJson(legacyPath);
205
233
  if (!marker
206
234
  || marker.schema_version !== 1
@@ -223,8 +251,14 @@ export function inspectInstallationProvenance(pluginRoot, {
223
251
  if (profile.status !== "matched") return profile;
224
252
  return { status: "missing", reason: "installation_provenance_missing" };
225
253
  }
226
- const profile = validateDistributionProfiles(definition);
227
- if (profile.status !== "matched") return profile;
254
+ const currentProfile = validateDistributionProfiles(definition);
255
+ const historicalProfile = currentProfile.status !== "matched" && allowHistoricalProfilesForMigration
256
+ ? classifyInstalledHistoricalProfile(distributionProfileHistory, definition, classifyHistoricalProfile)
257
+ : null;
258
+ if (currentProfile.status !== "matched" && historicalProfile?.status !== "matched") {
259
+ return historicalProfile ?? currentProfile;
260
+ }
261
+ const profile = currentProfile.status === "matched" ? currentProfile : historicalProfile;
228
262
  const marker = readJson(markerPath);
229
263
  if (!marker
230
264
  || marker.schema_version !== 1
@@ -247,7 +281,16 @@ export function inspectInstallationProvenance(pluginRoot, {
247
281
  if (observedSourceDigest !== marker.source_digest) {
248
282
  return { status: "invalid", reason: "source_digest_mismatch", marker, observedSourceDigest };
249
283
  }
250
- return { status: "matched", marker, observedSourceDigest };
284
+ return {
285
+ status: "matched",
286
+ marker,
287
+ observedSourceDigest,
288
+ profileClassification: historicalProfile ? "supported_historical" : "current",
289
+ historicalReleaseVersion: historicalProfile?.release_version ?? null,
290
+ historicalContractId: historicalProfile?.contract_id ?? null,
291
+ historicalContractDigest: historicalProfile?.contract_digest ?? null,
292
+ historicalEntryDigest: historicalProfile?.entry_digest ?? null,
293
+ };
251
294
  }
252
295
 
253
296
  export const distributionProfileContract = Object.freeze({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
4
4
  "description": "Install AGDF plugins, bootstrap supported repository surfaces and validate durable governance state.",
5
5
  "type": "module",
6
6
  "files": [
@@ -27,8 +27,11 @@
27
27
  "install:copilot": "node ./scripts/install-local-plugin.js copilot",
28
28
  "install:opencode": "node ./scripts/install-local-plugin.js opencode",
29
29
  "test:release-version-coherence": "node ./scripts/release-version-coherence-test.js",
30
+ "release:bump": "node ./scripts/release-bump.js",
31
+ "test:release-bump": "node ./scripts/release-bump-test.js",
32
+ "test:distribution-profile-history": "node ./scripts/distribution-profile-history-test.js",
30
33
  "test:public-plugin": "node ./scripts/public-plugin-test.js",
31
- "release:prepare": "npm run sync-package-assets && npm run test:release-version-coherence && npm run test:public-plugin",
34
+ "release:prepare": "npm run sync-package-assets && npm run test:distribution-profile-history && npm run test:release-bump && npm run test:release-version-coherence && npm run test:public-plugin",
32
35
  "test:delivery-path-search": "node ./scripts/delivery-path-search-test.js",
33
36
  "test:delivery-path-search-unit": "node ./scripts/delivery-path-search-unit-test.js",
34
37
  "test:delivery-path-search-generator": "node ./scripts/delivery-path-search-generator-test.js",
@@ -37,6 +40,7 @@
37
40
  "test:cli-modularization": "node ./scripts/cli-modularization-test.js",
38
41
  "test:local-validator": "node ./scripts/local-validator-test.js",
39
42
  "test:local-marketplace": "node ./scripts/local-marketplace-test.js",
43
+ "test:claude-cache-recovery": "node ./scripts/claude-cache-recovery-test.js",
40
44
  "test:copilot-profile": "node ./scripts/copilot-profile-test.js",
41
45
  "test:local-development-install": "npm run release:prepare && node ./scripts/local-development-install-test.js",
42
46
  "test:package-contents": "node ./scripts/package-contents-test.js",
@@ -58,7 +62,7 @@
58
62
  "test:proportionality": "node ./scripts/proportionality-benchmark-test.js",
59
63
  "test:release-bootstrap": "node ./scripts/release-bootstrap-smoke-test.js",
60
64
  "test:routing": "npm run sync-package-assets && node ./scripts/test-routing.js",
61
- "smoke-test": "npm run release:prepare && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:copilot-profile && npm run test:local-development-install && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:copilot-repository-retention && npm run test:control-state && npm run test:parent-reconciliation && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:agent-skills-conformance && npm run test:skill-evals && npm run eval:skills && npm run test:proportionality && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
65
+ "smoke-test": "npm run release:prepare && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:claude-cache-recovery && npm run test:copilot-profile && npm run test:local-development-install && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:copilot-repository-retention && npm run test:control-state && npm run test:parent-reconciliation && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:agent-skills-conformance && npm run test:skill-evals && npm run eval:skills && npm run test:proportionality && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
62
66
  "prepack": "npm run release:prepare"
63
67
  },
64
68
  "keywords": [