create-agdf 0.14.3 → 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 +34 -2
- package/generated/.opencode/contracts/interaction.md +2 -2
- 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/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/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/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/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 +1 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +55 -35
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-gate-check/SKILL.md +6 -4
- 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/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/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/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/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 +16 -12
- 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 +1 -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/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/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
|
@@ -4,10 +4,22 @@ import { join, resolve } from "node:path";
|
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { pluginDefinition } from "../cli/runtime-context.js";
|
|
6
6
|
import { digestNormalizedPluginSource } from "../runtime/plugin-provenance.js";
|
|
7
|
+
import { recoverClaudeCacheTemp } from "./claude-cache-recovery.js";
|
|
7
8
|
import { CODEX_REGISTRATION_REVISION, classifyMarketplaceList, inspectLocalMarketplaceProjection, inspectOwnedSharedMarketplaceForCopilotMigration, isCodexLocalInstallVersion, prepareCopilotMarketplace, prepareLocalMarketplace } from "./local-marketplace.js";
|
|
8
9
|
|
|
9
10
|
export const COPILOT_CLI_NPM_PACKAGE = "@github/copilot@1.0.80";
|
|
10
11
|
|
|
12
|
+
function historicalEvidenceEntries(transaction) {
|
|
13
|
+
const historical = transaction.historicalEvidence;
|
|
14
|
+
if (!historical) return [];
|
|
15
|
+
return [
|
|
16
|
+
`historical_release:${historical.releaseVersion}`,
|
|
17
|
+
`historical_contract:${historical.contractId}`,
|
|
18
|
+
`historical_contract_digest:${historical.contractDigest}`,
|
|
19
|
+
`historical_entry_digest:${historical.entryDigest}`,
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
export function installCodexGlobalPlugin({ exec = execFileSync, prepare = prepareLocalMarketplace, dataRoot } = {}) {
|
|
12
24
|
const expectedVersion = pluginDefinition.version;
|
|
13
25
|
const nativeOutput = [];
|
|
@@ -34,12 +46,15 @@ export function installCodexGlobalPlugin({ exec = execFileSync, prepare = prepar
|
|
|
34
46
|
...(transaction.sourceDigest ? [`source_digest:${transaction.sourceDigest}`] : []),
|
|
35
47
|
...(transaction.digest ? [`plugin_digest:${transaction.digest}`] : []),
|
|
36
48
|
...(transaction.existingClassification === "owned_pre_provenance_rebuild" ? ["marketplace_recovery:owned_pre_provenance_rebuild", "loaded_session:restart_required"] : []),
|
|
49
|
+
...(transaction.existingClassification === "owned_supported_historical_rebuild" ? ["marketplace_recovery:owned_supported_historical_rebuild", "loaded_session:fresh_session_required"] : []),
|
|
50
|
+
...historicalEvidenceEntries(transaction),
|
|
37
51
|
...(expectedInstallVersion === expectedVersion ? [] : [`canonical_version:${expectedVersion}`, `local_install_version:${expectedInstallVersion}`]),
|
|
38
52
|
],
|
|
39
53
|
pluginRoot: transaction.pluginRoot ?? null,
|
|
40
54
|
digest: transaction.digest ?? null,
|
|
41
55
|
runtimeDigest: transaction.runtimeDigest ?? null,
|
|
42
56
|
sourceDigest: transaction.sourceDigest ?? null,
|
|
57
|
+
historicalEvidence: transaction.historicalEvidence ?? null,
|
|
43
58
|
nativeOutput: nativeOutput.filter(Boolean).map(String),
|
|
44
59
|
};
|
|
45
60
|
} catch (error) {
|
|
@@ -48,11 +63,19 @@ export function installCodexGlobalPlugin({ exec = execFileSync, prepare = prepar
|
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
|
|
51
|
-
export function installClaudeGlobalPlugin({
|
|
66
|
+
export function installClaudeGlobalPlugin({
|
|
67
|
+
exec = execFileSync,
|
|
68
|
+
prepare = prepareLocalMarketplace,
|
|
69
|
+
dataRoot,
|
|
70
|
+
recoverCache = recoverClaudeCacheTemp,
|
|
71
|
+
cacheRecoveryOptions = {},
|
|
72
|
+
} = {}) {
|
|
52
73
|
const expectedVersion = pluginDefinition.version;
|
|
53
74
|
const nativeOutput = [];
|
|
54
75
|
const transaction = prepare({ expectedVersion, ...(dataRoot ? { dataRoot } : {}) });
|
|
55
76
|
const migration = { state: "unknown", source: "", addedLocal: false, removedLegacy: false };
|
|
77
|
+
let previousPluginRemoved = false;
|
|
78
|
+
let pluginInstalled = false;
|
|
56
79
|
try {
|
|
57
80
|
const marketplaceOutput = runPluginPhase(exec, "claude", ["plugin", "marketplace", "list", "--json"], "marketplace", captureOptions());
|
|
58
81
|
migrateMarketplace({ surface: "claude", exec, output: marketplaceOutput, root: transaction.root, nativeOutput, migration });
|
|
@@ -63,11 +86,41 @@ export function installClaudeGlobalPlugin({ exec = execFileSync, prepare = prepa
|
|
|
63
86
|
// same-version local source change never reaches the host; reinstall replaces the content.
|
|
64
87
|
if (alreadyInstalled) {
|
|
65
88
|
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "uninstall", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
89
|
+
previousPluginRemoved = true;
|
|
90
|
+
}
|
|
91
|
+
let cacheRecovery = null;
|
|
92
|
+
try {
|
|
93
|
+
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "install", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
94
|
+
pluginInstalled = true;
|
|
95
|
+
} catch (installError) {
|
|
96
|
+
cacheRecovery = recoverCache({
|
|
97
|
+
error: installError,
|
|
98
|
+
expectedVersion,
|
|
99
|
+
...cacheRecoveryOptions,
|
|
100
|
+
});
|
|
101
|
+
if (cacheRecovery.status !== "recovered") {
|
|
102
|
+
installError.evidence = {
|
|
103
|
+
...(installError.evidence ?? {}),
|
|
104
|
+
claude_cache_recovery: cacheRecovery.reason,
|
|
105
|
+
};
|
|
106
|
+
throw installError;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "install", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
110
|
+
pluginInstalled = true;
|
|
111
|
+
} catch (retryError) {
|
|
112
|
+
retryError.evidence = {
|
|
113
|
+
...(retryError.evidence ?? {}),
|
|
114
|
+
claude_cache_recovery: "claude_cache_temp_retry_exhausted",
|
|
115
|
+
};
|
|
116
|
+
throw retryError;
|
|
117
|
+
}
|
|
66
118
|
}
|
|
67
|
-
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "install", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
68
119
|
const afterList = runPluginPhase(exec, "claude", ["plugin", "list"], "verification", captureOptions());
|
|
69
120
|
const installedVersion = pluginVersionFromList(afterList, "agdf@agdf");
|
|
70
|
-
|
|
121
|
+
const historicalRebuild = transaction.existingClassification === "owned_supported_historical_rebuild";
|
|
122
|
+
if ((historicalRebuild && installedVersion !== expectedVersion)
|
|
123
|
+
|| (installedVersion && installedVersion !== expectedVersion)) {
|
|
71
124
|
throw lifecycleAdapterError("version", versionMismatchMessage("Claude Code", "agdf@agdf", expectedVersion, installedVersion, "npx --yes @agdf/cli@latest claude"));
|
|
72
125
|
}
|
|
73
126
|
transaction.commit();
|
|
@@ -85,16 +138,20 @@ export function installClaudeGlobalPlugin({ exec = execFileSync, prepare = prepa
|
|
|
85
138
|
...(transaction.sourceDigest ? [`source_digest:${transaction.sourceDigest}`] : []),
|
|
86
139
|
...(transaction.digest ? [`plugin_digest:${transaction.digest}`] : []),
|
|
87
140
|
...(transaction.existingClassification === "owned_pre_provenance_rebuild" ? ["marketplace_recovery:owned_pre_provenance_rebuild", "loaded_session:restart_required"] : []),
|
|
141
|
+
...(transaction.existingClassification === "owned_supported_historical_rebuild" ? ["marketplace_recovery:owned_supported_historical_rebuild", "loaded_session:fresh_session_required"] : []),
|
|
142
|
+
...historicalEvidenceEntries(transaction),
|
|
143
|
+
...(cacheRecovery?.status === "recovered" ? ["claude_cache_temp_recovery:bounded_retry"] : []),
|
|
88
144
|
...(installedVersion ? [] : ["host_did_not_expose_version"]),
|
|
89
145
|
],
|
|
90
146
|
pluginRoot: transaction.pluginRoot ?? null,
|
|
91
147
|
digest: transaction.digest ?? null,
|
|
92
148
|
runtimeDigest: transaction.runtimeDigest ?? null,
|
|
93
149
|
sourceDigest: transaction.sourceDigest ?? null,
|
|
150
|
+
historicalEvidence: transaction.historicalEvidence ?? null,
|
|
94
151
|
nativeOutput: nativeOutput.filter(Boolean).map(String),
|
|
95
152
|
};
|
|
96
153
|
} catch (error) {
|
|
97
|
-
recoverMarketplace({ surface: "claude", exec, migration, transaction, error });
|
|
154
|
+
recoverMarketplace({ surface: "claude", exec, migration, transaction, error, previousPluginRemoved, pluginInstalled });
|
|
98
155
|
throw error;
|
|
99
156
|
}
|
|
100
157
|
}
|
|
@@ -118,7 +175,7 @@ export function installCopilotGlobalPlugin({ exec = execFileSync, packagedCopilo
|
|
|
118
175
|
try {
|
|
119
176
|
before = activeExec("copilot", ["plugin", "list"], captureOptions());
|
|
120
177
|
} catch (error) {
|
|
121
|
-
if (error
|
|
178
|
+
if (!copilotCliUnavailable(error)) {
|
|
122
179
|
transaction?.rollback();
|
|
123
180
|
throw lifecycleAdapterError("verification", commandErrorText(error), { executable: "copilot", args: ["plugin", "list"] });
|
|
124
181
|
}
|
|
@@ -126,7 +183,10 @@ export function installCopilotGlobalPlugin({ exec = execFileSync, packagedCopilo
|
|
|
126
183
|
activeExec = (_executable, args, options) => packagedCopilotExec(invocation.executable, [...invocation.args, ...args], options);
|
|
127
184
|
try {
|
|
128
185
|
before = activeExec("copilot", ["plugin", "list"], captureOptions());
|
|
129
|
-
bootstrapEvidence.push(
|
|
186
|
+
bootstrapEvidence.push(
|
|
187
|
+
error?.code === "ENOENT" ? "copilot_cli_not_found" : "copilot_cli_launcher_unavailable",
|
|
188
|
+
`copilot_cli_npm_package:${COPILOT_CLI_NPM_PACKAGE}`,
|
|
189
|
+
);
|
|
130
190
|
} catch (bootstrapError) {
|
|
131
191
|
transaction?.commit();
|
|
132
192
|
return {
|
|
@@ -302,7 +362,15 @@ function migrateMarketplace({ surface, exec, output, root, nativeOutput, migrati
|
|
|
302
362
|
}
|
|
303
363
|
}
|
|
304
364
|
|
|
305
|
-
function recoverMarketplace({
|
|
365
|
+
function recoverMarketplace({
|
|
366
|
+
surface,
|
|
367
|
+
exec,
|
|
368
|
+
migration,
|
|
369
|
+
transaction,
|
|
370
|
+
error,
|
|
371
|
+
previousPluginRemoved = false,
|
|
372
|
+
pluginInstalled = false,
|
|
373
|
+
}) {
|
|
306
374
|
const executable = surface === "claude" ? "claude" : "codex";
|
|
307
375
|
const recovery = [];
|
|
308
376
|
const attempt = (args) => {
|
|
@@ -316,13 +384,19 @@ function recoverMarketplace({ surface, exec, migration, transaction, error }) {
|
|
|
316
384
|
}
|
|
317
385
|
};
|
|
318
386
|
if (migration?.refreshOwnedLocal) {
|
|
387
|
+
if (surface === "claude" && pluginInstalled) {
|
|
388
|
+
attempt(["plugin", "uninstall", "agdf@agdf"]);
|
|
389
|
+
}
|
|
319
390
|
const refreshedRegistrationRemoved = migration.addedLocal
|
|
320
391
|
? attempt(["plugin", "marketplace", "remove", "agdf", "--json"])
|
|
321
392
|
: true;
|
|
322
|
-
rollbackMarketplaceFilesystem(transaction, recovery);
|
|
393
|
+
const filesystemRestored = rollbackMarketplaceFilesystem(transaction, recovery);
|
|
323
394
|
if (migration.removedOwnedLocal && refreshedRegistrationRemoved) {
|
|
324
395
|
attempt(["plugin", "marketplace", "add", migration.source || transaction.root, "--json"]);
|
|
325
396
|
}
|
|
397
|
+
if (surface === "claude" && previousPluginRemoved && filesystemRestored) {
|
|
398
|
+
attempt(["plugin", "install", "agdf@agdf"]);
|
|
399
|
+
}
|
|
326
400
|
error.evidence = { ...(error.evidence ?? {}), rollback: recovery };
|
|
327
401
|
return;
|
|
328
402
|
}
|
|
@@ -336,7 +410,13 @@ function recoverMarketplace({ surface, exec, migration, transaction, error }) {
|
|
|
336
410
|
? ["plugin", "marketplace", "add", migration.source, "--scope", "user"]
|
|
337
411
|
: ["plugin", "marketplace", "add", migration.source, "--json"]);
|
|
338
412
|
}
|
|
339
|
-
|
|
413
|
+
if (surface === "claude" && pluginInstalled) {
|
|
414
|
+
attempt(["plugin", "uninstall", "agdf@agdf"]);
|
|
415
|
+
}
|
|
416
|
+
const filesystemRestored = rollbackMarketplaceFilesystem(transaction, recovery);
|
|
417
|
+
if (surface === "claude" && previousPluginRemoved && filesystemRestored) {
|
|
418
|
+
attempt(["plugin", "install", "agdf@agdf"]);
|
|
419
|
+
}
|
|
340
420
|
error.evidence = { ...(error.evidence ?? {}), rollback: recovery };
|
|
341
421
|
}
|
|
342
422
|
|
|
@@ -344,8 +424,10 @@ function rollbackMarketplaceFilesystem(transaction, recovery) {
|
|
|
344
424
|
try {
|
|
345
425
|
transaction.rollback();
|
|
346
426
|
recovery.push({ filesystem: transaction.root, status: "restored" });
|
|
427
|
+
return true;
|
|
347
428
|
} catch (rollbackError) {
|
|
348
429
|
recovery.push({ filesystem: transaction.root, status: "failed", message: rollbackError.message });
|
|
430
|
+
return false;
|
|
349
431
|
}
|
|
350
432
|
}
|
|
351
433
|
|
|
@@ -404,6 +486,11 @@ function commandErrorText(error) {
|
|
|
404
486
|
return (error.stderr || error.stdout || error.message || "").toString().trim();
|
|
405
487
|
}
|
|
406
488
|
|
|
489
|
+
function copilotCliUnavailable(error) {
|
|
490
|
+
return error?.code === "ENOENT"
|
|
491
|
+
|| /^Cannot find GitHub Copilot CLI(?:\s|$|\()/i.test(commandErrorText(error));
|
|
492
|
+
}
|
|
493
|
+
|
|
407
494
|
export function pluginListHasPlugin(output, pluginId) {
|
|
408
495
|
const escapedPluginId = pluginId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
409
496
|
return output
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RUN_ID_PATTERN } from "./control-state/run-identity.js";
|
|
2
|
+
|
|
1
3
|
const REQUIRED_GATES = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
|
|
2
4
|
const ARTEFACT_ORDER = ["UR", "PRD", "SD", "TP"];
|
|
3
5
|
const OUTCOMES = new Set(["approve", "revise", "decline", "cancel", "no_response", "timeout", "empty", "invalid", "stale"]);
|
|
@@ -313,17 +315,37 @@ function operationalBreadcrumb(value, labels) {
|
|
|
313
315
|
.join(labels.breadcrumbSeparator);
|
|
314
316
|
}
|
|
315
317
|
|
|
318
|
+
export function validateOperationalStatusCardPreconditions(statusCard, {
|
|
319
|
+
registry,
|
|
320
|
+
humanPresentation,
|
|
321
|
+
} = {}) {
|
|
322
|
+
const errors = [];
|
|
323
|
+
if (!plainObject(statusCard)) errors.push("status_card_missing");
|
|
324
|
+
if (humanPresentation !== undefined && !plainObject(humanPresentation)) errors.push("human_presentation_missing");
|
|
325
|
+
if (plainObject(statusCard)) {
|
|
326
|
+
if (!String(statusCard.run_id ?? "").trim()) errors.push("run_id_missing");
|
|
327
|
+
if (!String(statusCard.current_gate ?? "").trim()) errors.push("current_gate_missing");
|
|
328
|
+
let locale = "";
|
|
329
|
+
try {
|
|
330
|
+
locale = resolvePresentationLocale(registry, statusCard.presentation_language);
|
|
331
|
+
} catch {
|
|
332
|
+
locale = "";
|
|
333
|
+
}
|
|
334
|
+
if (!locale) errors.push("locale_unresolved");
|
|
335
|
+
}
|
|
336
|
+
return Object.freeze({ valid: errors.length === 0, errors: Object.freeze(errors) });
|
|
337
|
+
}
|
|
338
|
+
|
|
316
339
|
export function renderOperationalStatusCard(statusCard, {
|
|
317
340
|
registry,
|
|
318
341
|
humanPresentation,
|
|
319
342
|
revisionId = "",
|
|
320
343
|
} = {}) {
|
|
321
|
-
if (!
|
|
344
|
+
if (!validateOperationalStatusCardPreconditions(statusCard, { registry, humanPresentation: humanPresentation ?? null }).valid) return null;
|
|
322
345
|
const runId = String(statusCard.run_id ?? "").trim();
|
|
323
346
|
const currentGate = String(statusCard.current_gate ?? "").trim();
|
|
324
347
|
const revision = String(revisionId ?? "").trim() || "unversioned";
|
|
325
348
|
const locale = resolvePresentationLocale(registry, statusCard.presentation_language);
|
|
326
|
-
if (!runId || !currentGate || !locale) return null;
|
|
327
349
|
|
|
328
350
|
const pack = localePack(registry, locale);
|
|
329
351
|
const labels = pack.statusCard;
|
|
@@ -537,6 +559,37 @@ export function normalizeInteractionOutcome(value, { expectedApproval, stale = f
|
|
|
537
559
|
return "invalid";
|
|
538
560
|
}
|
|
539
561
|
|
|
562
|
+
export function validateApprovalOrientationPreconditions({
|
|
563
|
+
statusCard,
|
|
564
|
+
humanPresentation,
|
|
565
|
+
registry,
|
|
566
|
+
requestedLocale,
|
|
567
|
+
} = {}) {
|
|
568
|
+
const errors = [];
|
|
569
|
+
if (!plainObject(statusCard)) return Object.freeze({ valid: false, errors: Object.freeze(["status_card_missing"]) });
|
|
570
|
+
if (humanPresentation !== undefined && !plainObject(humanPresentation)) errors.push("human_presentation_missing");
|
|
571
|
+
const gate = String(statusCard.current_gate ?? "").trim();
|
|
572
|
+
const runId = String(statusCard.run_id ?? "").trim();
|
|
573
|
+
if (!REQUIRED_GATES.includes(gate)) errors.push("gate_not_user_gate");
|
|
574
|
+
if (!RUN_ID_PATTERN.test(runId)) errors.push("run_id_invalid");
|
|
575
|
+
if (statusCard.status !== "open") errors.push("status_not_open");
|
|
576
|
+
if (statusCard.missing_approval !== `Approval: ${gate}`) errors.push("missing_approval_mismatch");
|
|
577
|
+
const nextGate = String(statusCard.next_gate_after_approval ?? "none");
|
|
578
|
+
const nextUserGate = String(statusCard.next_user_gate ?? "").trim();
|
|
579
|
+
const userActionRequired = String(statusCard.user_action_required ?? "").trim();
|
|
580
|
+
const userActionSemanticsValid = (userActionRequired === "no" && nextUserGate === "none")
|
|
581
|
+
|| (userActionRequired === "yes" && REQUIRED_GATES.includes(nextUserGate) && nextGate === nextUserGate);
|
|
582
|
+
if (!userActionSemanticsValid) errors.push("user_action_semantics_invalid");
|
|
583
|
+
let locale = "";
|
|
584
|
+
try {
|
|
585
|
+
locale = resolvePresentationLocale(registry, requestedLocale);
|
|
586
|
+
} catch {
|
|
587
|
+
locale = "";
|
|
588
|
+
}
|
|
589
|
+
if (!locale) errors.push("locale_unresolved");
|
|
590
|
+
return Object.freeze({ valid: errors.length === 0, errors: Object.freeze(errors) });
|
|
591
|
+
}
|
|
592
|
+
|
|
540
593
|
export function buildApprovalOrientationSnapshot({
|
|
541
594
|
ready = false,
|
|
542
595
|
statusCard,
|
|
@@ -545,11 +598,11 @@ export function buildApprovalOrientationSnapshot({
|
|
|
545
598
|
registry,
|
|
546
599
|
requestedLocale,
|
|
547
600
|
} = {}) {
|
|
548
|
-
if (!ready
|
|
601
|
+
if (!ready) return null;
|
|
602
|
+
if (!validateApprovalOrientationPreconditions({ statusCard, humanPresentation: humanPresentation ?? null, registry, requestedLocale }).valid) return null;
|
|
549
603
|
const gate = String(statusCard.current_gate ?? "").trim();
|
|
550
604
|
const runId = String(statusCard.run_id ?? "").trim();
|
|
551
605
|
const expectedApproval = `Approval: ${gate}`;
|
|
552
|
-
if (!REQUIRED_GATES.includes(gate) || !/^[A-Za-z0-9._-]+$/.test(runId) || statusCard.status !== "open" || statusCard.missing_approval !== expectedApproval) return null;
|
|
553
606
|
|
|
554
607
|
const locale = resolvePresentationLocale(registry, requestedLocale);
|
|
555
608
|
const pack = localePack(registry, locale);
|
|
@@ -560,9 +613,6 @@ export function buildApprovalOrientationSnapshot({
|
|
|
560
613
|
const nextGate = String(statusCard.next_gate_after_approval ?? "none");
|
|
561
614
|
const nextUserGate = String(statusCard.next_user_gate ?? "").trim();
|
|
562
615
|
const userActionRequired = String(statusCard.user_action_required ?? "").trim();
|
|
563
|
-
const userActionSemanticsValid = (userActionRequired === "no" && nextUserGate === "none")
|
|
564
|
-
|| (userActionRequired === "yes" && REQUIRED_GATES.includes(nextUserGate) && nextGate === nextUserGate);
|
|
565
|
-
if (!userActionSemanticsValid) return null;
|
|
566
616
|
const narration = pack.primary.narration.gates[gate] ?? {};
|
|
567
617
|
const nextDecision = userActionRequired === "no"
|
|
568
618
|
? pack.primary.narration.noAction
|
|
@@ -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
|
+
}
|