create-agdf 0.14.2 → 0.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -3
- package/generated/.opencode/contracts/control-scaffold.md +17 -2
- package/generated/.opencode/contracts/interaction.md +2 -2
- package/generated/.opencode/skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/.opencode/skills/agdf-gate-check/SKILL.md +6 -4
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/plugins/agdf/meta/contracts/interaction.md +2 -2
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/plugins/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -0
- package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/agdf/skills/gate-check/SKILL.md +6 -4
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +7 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +71 -51
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-gate-check/SKILL.md +6 -4
- package/generated/plugins/copilot/agdf/copilot-skills/contracts/control-scaffold.md +17 -2
- package/generated/plugins/copilot/agdf/copilot-skills/contracts/interaction.md +2 -2
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/plugins/copilot/agdf/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/submissions/openai/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/submissions/openai/agdf/meta/contracts/interaction.md +2 -2
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
- package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +125 -0
- package/generated/submissions/openai/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/submissions/openai/agdf/skills/gate-check/SKILL.md +6 -4
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +18 -14
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +7 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/cli/application.js +24 -6
- package/lib/cli/command-registry.js +8 -1
- package/lib/cli/delivery-path-search-command.js +51 -19
- package/lib/cli/parse-args.js +3 -0
- package/lib/control-evaluation/doctor.js +13 -0
- package/lib/control-evaluation/gate-check.js +64 -13
- package/lib/control-evaluation/run-state.js +6 -0
- package/lib/control-state/run-identity.js +9 -0
- package/lib/control-state/run-state-parser.js +4 -2
- package/lib/delivery-path-search/contracts.js +37 -0
- package/lib/delivery-path-search/persistence.js +14 -2
- package/lib/delivery-path-search/search-engine.js +126 -36
- package/lib/delivery-path-search/state-adapter.js +40 -92
- package/lib/installers/claude-cache-recovery.js +76 -0
- package/lib/installers/copilot-settings.js +146 -16
- package/lib/installers/local-marketplace.js +169 -14
- package/lib/installers/plugin-installers.js +96 -9
- package/lib/interaction-presentation.js +57 -7
- package/lib/lifecycle/operations.js +28 -4
- package/lib/lifecycle/result.js +4 -4
- package/lib/release/profile-history.js +222 -0
- package/lib/release/version-bump.js +527 -0
- package/lib/release/version-coherence.js +92 -38
- package/lib/runtime/distribution-profile-history.js +173 -0
- package/lib/runtime/plugin-provenance.js +46 -3
- package/package.json +7 -3
|
@@ -2,6 +2,11 @@ import { execFileSync } from "node:child_process";
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { pluginDefinition } from "../cli/runtime-context.js";
|
|
5
|
+
import {
|
|
6
|
+
applyCopilotRepositoryDisable,
|
|
7
|
+
planCopilotRepositoryDisable,
|
|
8
|
+
verifyCopilotRepositoryDisabled,
|
|
9
|
+
} from "../installers/copilot-settings.js";
|
|
5
10
|
import { evaluateOpenCodeStatus, openCodeNpmInvocation } from "../installers/opencode.js";
|
|
6
11
|
import { inspectPluginSurface } from "../installers/plugin-installers.js";
|
|
7
12
|
import { inspectGeneratedRepositoryMarketplace } from "../runtime/plugin-provenance.js";
|
|
@@ -19,8 +24,22 @@ function repositorySelector(targetDir, config = "") {
|
|
|
19
24
|
return pluginSection(config, "agdf@agdf-repo") ? "agdf@agdf-repo" : "agdf@agdf";
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
export function planRepositoryDisable(targetDir, surface) {
|
|
23
|
-
if (surface
|
|
27
|
+
export function planRepositoryDisable(targetDir, surface, { shared = false, exec = execFileSync } = {}) {
|
|
28
|
+
if (surface === "copilot") {
|
|
29
|
+
const settings = planCopilotRepositoryDisable({ targetDir, shared, exec });
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
operation: "disable",
|
|
32
|
+
surface,
|
|
33
|
+
scope: "repository",
|
|
34
|
+
audience: settings.audience,
|
|
35
|
+
mutations: Object.freeze(settings.changed
|
|
36
|
+
? [{ kind: "copilot_settings", path: settings.path, settings }]
|
|
37
|
+
: []),
|
|
38
|
+
retained: Object.freeze([join(targetDir, ".agdf", "control"), "global AGDF plugin availability", "independent repository instructions"]),
|
|
39
|
+
expected: Object.freeze({ repository_status: "configured_disabled", activation_status: "pending_restart", settings_path: settings.path }),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (surface !== "codex" || shared) {
|
|
24
43
|
throw new Error(`Repository disable is not supported safely for ${surface}; no files were changed.`);
|
|
25
44
|
}
|
|
26
45
|
const path = join(targetDir, ".codex", "config.toml");
|
|
@@ -49,7 +68,9 @@ export function planRepositoryDisable(targetDir, surface) {
|
|
|
49
68
|
});
|
|
50
69
|
}
|
|
51
70
|
|
|
52
|
-
export function verifyRepositoryDisabled(targetDir) {
|
|
71
|
+
export function verifyRepositoryDisabled(targetDir, surface = "codex", { shared = false } = {}) {
|
|
72
|
+
if (surface === "copilot") return verifyCopilotRepositoryDisabled(targetDir, { shared });
|
|
73
|
+
if (surface !== "codex") return { status: "failed", evidence: [`unsupported_surface:${surface}`] };
|
|
53
74
|
const path = join(targetDir, ".codex", "config.toml");
|
|
54
75
|
if (!existsSync(path)) return { status: "failed", evidence: [`missing:${path}`] };
|
|
55
76
|
const config = readFileSync(path, "utf8");
|
|
@@ -165,7 +186,7 @@ function nativeUninstallPlan(surface, executable, args) {
|
|
|
165
186
|
});
|
|
166
187
|
}
|
|
167
188
|
|
|
168
|
-
export function applyLifecyclePlan(plan, { exec = execFileSync } = {}) {
|
|
189
|
+
export function applyLifecyclePlan(plan, { exec = execFileSync, applyCopilotSettings = applyCopilotRepositoryDisable } = {}) {
|
|
169
190
|
const completed = [];
|
|
170
191
|
for (const mutation of plan.mutations) {
|
|
171
192
|
try {
|
|
@@ -173,6 +194,9 @@ export function applyLifecyclePlan(plan, { exec = execFileSync } = {}) {
|
|
|
173
194
|
mkdirSync(dirname(mutation.path), { recursive: true });
|
|
174
195
|
writeFileSync(mutation.path, mutation.content, "utf8");
|
|
175
196
|
completed.push({ kind: "write", path: mutation.path });
|
|
197
|
+
} else if (mutation.kind === "copilot_settings") {
|
|
198
|
+
const result = applyCopilotSettings(mutation.settings);
|
|
199
|
+
completed.push({ kind: "copilot_settings", path: mutation.path, status: result.status });
|
|
176
200
|
} else if (mutation.kind === "remove") {
|
|
177
201
|
rmSync(mutation.path);
|
|
178
202
|
completed.push({ kind: "remove", path: mutation.path });
|
package/lib/lifecycle/result.js
CHANGED
|
@@ -3,10 +3,10 @@ const RESULTS = new Set(["success", "partial", "failed", "preview"]);
|
|
|
3
3
|
const SCOPES = new Set(["global", "repository"]);
|
|
4
4
|
const SURFACES = new Set(["codex", "claude", "copilot", "opencode", "generic"]);
|
|
5
5
|
const GLOBAL_INSTALL_RESTART_ACTIONS = Object.freeze({
|
|
6
|
-
codex: "
|
|
7
|
-
claude: "
|
|
8
|
-
copilot: "
|
|
9
|
-
opencode: "
|
|
6
|
+
codex: "Fully restart Codex, then start a fresh session. Restoring the previous session can retain stale AGDF skills.",
|
|
7
|
+
claude: "Fully restart Claude Code, then start a fresh session. Restoring the previous session can retain stale AGDF skills.",
|
|
8
|
+
copilot: "Fully restart GitHub Copilot, then start a fresh session. Restoring the previous session can retain stale AGDF skills.",
|
|
9
|
+
opencode: "Fully restart OpenCode, then start a fresh session. Restoring the previous session can retain stale AGDF skills.",
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
function text(value) {
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
classifyHistoricalDistributionProfile,
|
|
6
|
+
validateDistributionProfileHistory,
|
|
7
|
+
} from "../runtime/distribution-profile-history.js";
|
|
8
|
+
|
|
9
|
+
export const SUPPORTED_PROFILE_RELEASES = Object.freeze([
|
|
10
|
+
"0.13.6",
|
|
11
|
+
"0.13.7",
|
|
12
|
+
"0.13.8",
|
|
13
|
+
"0.14.1",
|
|
14
|
+
"0.14.2",
|
|
15
|
+
"0.14.3",
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const HISTORY_PATH = "plugin/meta/distribution-profile-history.json";
|
|
19
|
+
const GENERATED_HISTORY_PATHS = [
|
|
20
|
+
"create-agdf/generated/plugins/agdf/meta/distribution-profile-history.json",
|
|
21
|
+
"create-agdf/generated/plugins/copilot/agdf/meta/distribution-profile-history.json",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function fail(reason, detail) {
|
|
25
|
+
const error = new Error(`${reason}: ${detail}`);
|
|
26
|
+
error.code = reason;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseJson(content, reason, label) {
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(content);
|
|
33
|
+
} catch {
|
|
34
|
+
fail(reason, `${label} is not valid JSON`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function defaultReadTagFile(repoRoot) {
|
|
39
|
+
return (tag, relativePath) => execFileSync(
|
|
40
|
+
"git",
|
|
41
|
+
["show", `${tag}:${relativePath}`],
|
|
42
|
+
{ cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] },
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function defaultTagExists(repoRoot) {
|
|
47
|
+
return (tag) => {
|
|
48
|
+
try {
|
|
49
|
+
execFileSync(
|
|
50
|
+
"git",
|
|
51
|
+
["rev-parse", "--verify", "--quiet", `refs/tags/${tag}`],
|
|
52
|
+
{ cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
53
|
+
);
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function assertTagRecord(catalogue, version, readTagFile) {
|
|
62
|
+
const tag = `agdf-v${version}`;
|
|
63
|
+
let definition;
|
|
64
|
+
let packageManifest;
|
|
65
|
+
let codexManifest;
|
|
66
|
+
try {
|
|
67
|
+
definition = parseJson(readTagFile(tag, "plugin/meta/agdf-plugin.definition.json"), "profile_history_tag_mismatch", `${tag} definition`);
|
|
68
|
+
packageManifest = parseJson(readTagFile(tag, "create-agdf/package.json"), "profile_history_tag_mismatch", `${tag} package`);
|
|
69
|
+
codexManifest = parseJson(readTagFile(tag, "plugin/.codex-plugin/plugin.json"), "profile_history_tag_mismatch", `${tag} Codex manifest`);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error.code === "profile_history_tag_mismatch") throw error;
|
|
72
|
+
fail("profile_history_tag_mismatch", `${tag} evidence is unavailable`);
|
|
73
|
+
}
|
|
74
|
+
if (definition.version !== version || packageManifest.version !== version || codexManifest.version !== version) {
|
|
75
|
+
fail("profile_history_tag_mismatch", `${tag} does not identify exact version ${version}`);
|
|
76
|
+
}
|
|
77
|
+
const classification = classifyHistoricalDistributionProfile({
|
|
78
|
+
catalogue,
|
|
79
|
+
version,
|
|
80
|
+
distributionProfiles: definition.distributionProfiles,
|
|
81
|
+
});
|
|
82
|
+
if (classification.status !== "matched") {
|
|
83
|
+
fail("profile_history_tag_mismatch", `${tag} does not match its catalogue contract`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function assertIncoherentTagNegative(catalogue, readTagFile) {
|
|
88
|
+
if (Object.hasOwn(catalogue.releases, "0.14.0")) {
|
|
89
|
+
fail("profile_history_tag_mismatch", "incoherent agdf-v0.14.0 must not have a release record");
|
|
90
|
+
}
|
|
91
|
+
const tag = "agdf-v0.14.0";
|
|
92
|
+
let versions;
|
|
93
|
+
try {
|
|
94
|
+
versions = [
|
|
95
|
+
parseJson(readTagFile(tag, "plugin/meta/agdf-plugin.definition.json"), "profile_history_tag_mismatch", `${tag} definition`).version,
|
|
96
|
+
parseJson(readTagFile(tag, "create-agdf/package.json"), "profile_history_tag_mismatch", `${tag} package`).version,
|
|
97
|
+
parseJson(readTagFile(tag, "plugin/.codex-plugin/plugin.json"), "profile_history_tag_mismatch", `${tag} Codex manifest`).version,
|
|
98
|
+
];
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error.code === "profile_history_tag_mismatch") throw error;
|
|
101
|
+
fail("profile_history_tag_mismatch", `${tag} negative evidence is unavailable`);
|
|
102
|
+
}
|
|
103
|
+
if (versions.some((version) => version !== "0.13.8")) {
|
|
104
|
+
fail("profile_history_tag_mismatch", `${tag} must remain the explicit internally-0.13.8 negative`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function baselineFromRepository(repoRoot) {
|
|
109
|
+
let mergeBase;
|
|
110
|
+
try {
|
|
111
|
+
mergeBase = execFileSync(
|
|
112
|
+
"git",
|
|
113
|
+
["merge-base", "HEAD", "origin/main"],
|
|
114
|
+
{ cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
115
|
+
).trim();
|
|
116
|
+
} catch {
|
|
117
|
+
fail("profile_history_continuity_break", "merge-base evidence is unavailable");
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return execFileSync(
|
|
121
|
+
"git",
|
|
122
|
+
["show", `${mergeBase}:${HISTORY_PATH}`],
|
|
123
|
+
{ cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
124
|
+
);
|
|
125
|
+
} catch {
|
|
126
|
+
let matchingPaths;
|
|
127
|
+
try {
|
|
128
|
+
matchingPaths = execFileSync(
|
|
129
|
+
"git",
|
|
130
|
+
["ls-tree", "--name-only", mergeBase, "--", HISTORY_PATH],
|
|
131
|
+
{ cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
132
|
+
).trim();
|
|
133
|
+
} catch {
|
|
134
|
+
fail("profile_history_continuity_break", "baseline tree evidence is unavailable");
|
|
135
|
+
}
|
|
136
|
+
if (matchingPaths === "") return null;
|
|
137
|
+
fail("profile_history_continuity_break", "baseline catalogue cannot be read");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function assertContinuity(catalogue, baselineContent) {
|
|
142
|
+
if (baselineContent === null) return "initial_catalogue";
|
|
143
|
+
if (baselineContent === undefined) {
|
|
144
|
+
fail("profile_history_continuity_break", "baseline continuity evidence is unavailable");
|
|
145
|
+
}
|
|
146
|
+
const baseline = parseJson(baselineContent, "profile_history_continuity_break", "baseline catalogue");
|
|
147
|
+
if (validateDistributionProfileHistory(baseline).status !== "matched") {
|
|
148
|
+
fail("profile_history_continuity_break", "baseline catalogue is invalid");
|
|
149
|
+
}
|
|
150
|
+
for (const [version, priorRelease] of Object.entries(baseline.releases)) {
|
|
151
|
+
const currentRelease = catalogue.releases[version];
|
|
152
|
+
const priorContract = baseline.contracts[priorRelease.contract_id];
|
|
153
|
+
const currentContract = catalogue.contracts[currentRelease?.contract_id];
|
|
154
|
+
if (JSON.stringify(currentRelease) !== JSON.stringify(priorRelease)
|
|
155
|
+
|| JSON.stringify(currentContract) !== JSON.stringify(priorContract)) {
|
|
156
|
+
fail("profile_history_continuity_break", `supported release ${version} was removed or changed`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return "matched";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function assertDistributionProfileHistory({
|
|
163
|
+
repoRoot,
|
|
164
|
+
catalogueContent,
|
|
165
|
+
generatedContents,
|
|
166
|
+
currentDefinition,
|
|
167
|
+
readTagFile,
|
|
168
|
+
tagExists,
|
|
169
|
+
baselineContent,
|
|
170
|
+
} = {}) {
|
|
171
|
+
repoRoot = repoRoot ? resolve(repoRoot) : null;
|
|
172
|
+
catalogueContent ??= readFileSync(join(repoRoot, HISTORY_PATH), "utf8");
|
|
173
|
+
const canonicalBytes = catalogueContent.replaceAll("\r\n", "\n");
|
|
174
|
+
const catalogue = parseJson(canonicalBytes, "profile_history_invalid", "distribution profile history");
|
|
175
|
+
if (validateDistributionProfileHistory(catalogue).status !== "matched") {
|
|
176
|
+
fail("profile_history_invalid", "catalogue schema or digest validation failed");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
currentDefinition ??= JSON.parse(readFileSync(join(repoRoot, "plugin", "meta", "agdf-plugin.definition.json"), "utf8"));
|
|
180
|
+
const current = classifyHistoricalDistributionProfile({
|
|
181
|
+
catalogue,
|
|
182
|
+
version: currentDefinition.version,
|
|
183
|
+
distributionProfiles: currentDefinition.distributionProfiles,
|
|
184
|
+
});
|
|
185
|
+
if (current.status !== "matched") {
|
|
186
|
+
fail("profile_history_current_release_mismatch", `current definition ${currentDefinition.version} has no exact matching snapshot`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
generatedContents ??= Object.fromEntries(GENERATED_HISTORY_PATHS.map((path) => [
|
|
190
|
+
path,
|
|
191
|
+
existsSync(join(repoRoot, path)) ? readFileSync(join(repoRoot, path), "utf8") : null,
|
|
192
|
+
]));
|
|
193
|
+
for (const path of GENERATED_HISTORY_PATHS) {
|
|
194
|
+
if (generatedContents[path] !== canonicalBytes) {
|
|
195
|
+
fail("profile_history_current_release_mismatch", `generated catalogue drift at ${path}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const suppliedReadTagFile = Boolean(readTagFile);
|
|
200
|
+
readTagFile ??= defaultReadTagFile(repoRoot);
|
|
201
|
+
tagExists ??= suppliedReadTagFile && !repoRoot ? () => true : defaultTagExists(repoRoot);
|
|
202
|
+
const supportedVersions = [...new Set([
|
|
203
|
+
...SUPPORTED_PROFILE_RELEASES,
|
|
204
|
+
...Object.keys(catalogue.releases),
|
|
205
|
+
])];
|
|
206
|
+
for (const version of supportedVersions) {
|
|
207
|
+
const tag = `agdf-v${version}`;
|
|
208
|
+
if (version === currentDefinition.version && !tagExists(tag)) continue;
|
|
209
|
+
assertTagRecord(catalogue, version, readTagFile);
|
|
210
|
+
}
|
|
211
|
+
assertIncoherentTagNegative(catalogue, readTagFile);
|
|
212
|
+
|
|
213
|
+
if (baselineContent === undefined && repoRoot) baselineContent = baselineFromRepository(repoRoot);
|
|
214
|
+
const continuity = assertContinuity(catalogue, baselineContent);
|
|
215
|
+
return {
|
|
216
|
+
catalogue,
|
|
217
|
+
currentVersion: currentDefinition.version,
|
|
218
|
+
supportedVersions,
|
|
219
|
+
generatedPaths: [...GENERATED_HISTORY_PATHS],
|
|
220
|
+
continuity,
|
|
221
|
+
};
|
|
222
|
+
}
|