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.
Files changed (103) hide show
  1. package/README.md +39 -3
  2. package/generated/.opencode/contracts/control-scaffold.md +17 -2
  3. package/generated/.opencode/contracts/interaction.md +2 -2
  4. package/generated/.opencode/skills/agdf-delivery-path-search/SKILL.md +16 -4
  5. package/generated/.opencode/skills/agdf-gate-check/SKILL.md +6 -4
  6. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  7. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  8. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  9. package/generated/plugins/agdf/meta/contracts/control-scaffold.md +17 -2
  10. package/generated/plugins/agdf/meta/contracts/interaction.md +2 -2
  11. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +3 -3
  12. package/generated/plugins/agdf/meta/distribution-profile-history.json +125 -0
  13. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  14. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
  15. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
  16. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
  17. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
  18. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
  19. package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
  20. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
  21. package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
  22. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
  23. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
  24. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
  25. package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
  26. package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
  27. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
  28. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  29. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  30. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -0
  31. package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +16 -4
  32. package/generated/plugins/agdf/skills/gate-check/SKILL.md +6 -4
  33. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  34. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  35. package/generated/plugins/agdf/submission/openai/release-notes.md +7 -1
  36. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  37. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +71 -51
  38. package/generated/plugins/copilot/agdf/copilot-skills/agdf-delivery-path-search/SKILL.md +16 -4
  39. package/generated/plugins/copilot/agdf/copilot-skills/agdf-gate-check/SKILL.md +6 -4
  40. package/generated/plugins/copilot/agdf/copilot-skills/contracts/control-scaffold.md +17 -2
  41. package/generated/plugins/copilot/agdf/copilot-skills/contracts/interaction.md +2 -2
  42. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
  43. package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +125 -0
  44. package/generated/plugins/copilot/agdf/plugin.json +1 -1
  45. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
  46. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +8 -1
  47. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
  48. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +3 -0
  49. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +13 -0
  50. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +64 -13
  51. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +6 -0
  52. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-identity.js +9 -0
  53. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +4 -2
  54. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
  55. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
  56. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
  57. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
  58. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +57 -7
  59. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +46 -3
  60. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
  61. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
  62. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  63. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
  64. package/generated/submissions/openai/agdf/meta/contracts/control-scaffold.md +17 -2
  65. package/generated/submissions/openai/agdf/meta/contracts/interaction.md +2 -2
  66. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +3 -3
  67. package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +125 -0
  68. package/generated/submissions/openai/agdf/skills/delivery-path-search/SKILL.md +16 -4
  69. package/generated/submissions/openai/agdf/skills/gate-check/SKILL.md +6 -4
  70. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  71. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  72. package/generated/submissions/openai/agdf/submission/openai/inventory.json +18 -14
  73. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  74. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  75. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  76. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +7 -1
  77. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  78. package/lib/cli/application.js +24 -6
  79. package/lib/cli/command-registry.js +8 -1
  80. package/lib/cli/delivery-path-search-command.js +51 -19
  81. package/lib/cli/parse-args.js +3 -0
  82. package/lib/control-evaluation/doctor.js +13 -0
  83. package/lib/control-evaluation/gate-check.js +64 -13
  84. package/lib/control-evaluation/run-state.js +6 -0
  85. package/lib/control-state/run-identity.js +9 -0
  86. package/lib/control-state/run-state-parser.js +4 -2
  87. package/lib/delivery-path-search/contracts.js +37 -0
  88. package/lib/delivery-path-search/persistence.js +14 -2
  89. package/lib/delivery-path-search/search-engine.js +126 -36
  90. package/lib/delivery-path-search/state-adapter.js +40 -92
  91. package/lib/installers/claude-cache-recovery.js +76 -0
  92. package/lib/installers/copilot-settings.js +146 -16
  93. package/lib/installers/local-marketplace.js +169 -14
  94. package/lib/installers/plugin-installers.js +96 -9
  95. package/lib/interaction-presentation.js +57 -7
  96. package/lib/lifecycle/operations.js +28 -4
  97. package/lib/lifecycle/result.js +4 -4
  98. package/lib/release/profile-history.js +222 -0
  99. package/lib/release/version-bump.js +527 -0
  100. package/lib/release/version-coherence.js +92 -38
  101. package/lib/runtime/distribution-profile-history.js +173 -0
  102. package/lib/runtime/plugin-provenance.js +46 -3
  103. package/package.json +7 -3
@@ -1,11 +1,10 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { join } from "node:path";
3
1
  import {
4
2
  CONTRACT_VERSION,
5
3
  GENERATOR_CONTRACT_VERSION,
6
4
  validateGeneratorRequest,
7
5
  } from "./contracts.js";
8
- import { resolveRuns, verifyLegacyProjection } from "../control-state/index.js";
6
+ import { evaluateGateCheck } from "../control-evaluation/gate-check.js";
7
+ import { readRunState } from "../control-evaluation/run-state.js";
9
8
 
10
9
  function section(content, heading) {
11
10
  return (
@@ -15,100 +14,44 @@ function section(content, heading) {
15
14
  );
16
15
  }
17
16
 
18
- function tableAnswers(content) {
19
- const answers = {};
20
- for (const line of section(content, "Current Control State").split(/\r?\n/)) {
21
- const cells = line
22
- .split("|")
23
- .slice(1, -1)
24
- .map((cell) => cell.trim());
25
- if (
26
- cells.length >= 2 &&
27
- cells[0] &&
28
- !cells[0].startsWith("---") &&
29
- cells[0] !== "Question"
30
- )
31
- answers[cells[0]] = cells[1];
32
- }
33
- return answers;
34
- }
35
-
36
- function statusCard(content) {
37
- const card = {};
38
- for (const line of section(content, "Run Status Card").split(/\r?\n/)) {
39
- const cells = line
40
- .split("|")
41
- .slice(1, -1)
42
- .map((cell) => cell.trim().replace(/^`|`$/g, ""));
43
- if (
44
- cells.length >= 2 &&
45
- cells[0] &&
46
- !cells[0].startsWith("---") &&
47
- cells[0] !== "Run status"
48
- )
49
- card[cells[0]] = cells[1];
50
- }
51
- return card;
17
+ function metaField(content, name) {
18
+ return content.match(new RegExp(`^- ${name}:\\s*(.+)$`, "m"))?.[1]
19
+ ?.replace(/^`|`$/g, "")
20
+ .trim() ?? "";
52
21
  }
53
22
 
54
- function listCell(value) {
55
- return String(value ?? "")
56
- .split(/\s*;\s*/)
57
- .map((item) => item.trim())
58
- .filter(Boolean);
59
- }
60
-
61
- export function searchInputFromControl(targetDir, options = {}) {
62
- const canonicalRoot = join(targetDir, ".agdf", "control", "runs");
63
- if (existsSync(canonicalRoot)) {
64
- const projection = verifyLegacyProjection(targetDir);
65
- if (!["absent", "valid"].includes(projection.status)) {
66
- throw new Error(`AGDF_LEGACY_PROJECTION_DRIFT:${projection.status}`);
67
- }
23
+ export function searchInputFromControl(targetDir, options = {}, dependencies = {}) {
24
+ const evaluate = dependencies.evaluateGateCheck ?? evaluateGateCheck;
25
+ const readRun = dependencies.readRunState ?? readRunState;
26
+ const selection = options.scopeKey ? { runId: options.scopeKey } : {};
27
+ const gate = evaluate(targetDir, selection);
28
+ const run = readRun(targetDir, selection);
29
+ const content = run.content ?? "";
30
+ const evaluatedRunId = gate.status_card?.run_id ?? "";
31
+ const evaluatedRevision = gate.status_presentation?.revision_id ?? "";
32
+ const runId = metaField(content, "run_id");
33
+ const runRevision = metaField(content, "revision_id");
34
+ const runGate = metaField(content, "current_gate");
35
+ let inputFailureCode = "";
36
+ if (!content || run.resolution_error) inputFailureCode = "canonical_control_unavailable";
37
+ else if (!evaluatedRunId || !evaluatedRevision) inputFailureCode = "canonical_snapshot_identity_missing";
38
+ else if (evaluatedRunId !== runId || evaluatedRevision !== runRevision || gate.current_gate !== runGate) {
39
+ inputFailureCode = "stale_control_snapshot";
40
+ } else if (!Array.isArray(gate.allowed) || gate.allowed.length === 0) {
41
+ inputFailureCode = "canonical_actions_unavailable";
68
42
  }
69
- const resolved = existsSync(canonicalRoot)
70
- ? resolveRuns(targetDir, {
71
- runIdArg: options.scopeKey,
72
- runIdEnv: process.env.AGDF_RUN_ID,
73
- })
74
- : null;
75
- const runPath =
76
- resolved?.run.path ?? join(targetDir, ".agdf", "control", "AGDF_RUN.md");
77
- if (!existsSync(runPath)) throw new Error("missing AGDF run state");
78
- const content = readFileSync(runPath, "utf8");
79
- const meta = Object.fromEntries(
80
- [...content.matchAll(/^- ([a-z_]+):\s*(.+)$/gm)].map((match) => [
81
- match[1],
82
- match[2].replace(/^`|`$/g, "").trim(),
83
- ]),
84
- );
85
- const answers = tableAnswers(content);
86
- const card = statusCard(content);
87
43
  const result = {
88
44
  contract_version: CONTRACT_VERSION,
89
- scope_key: options.scopeKey ?? meta.run_id ?? "unknown-scope",
90
- objective: section(content, "Objective").trim(),
91
- current_gate: card["Current gate"] ?? meta.current_gate ?? "unknown",
92
- allowed_actions: options.allowedActions ?? listCell(card["Allowed now"]),
93
- forbidden_actions:
94
- options.forbiddenActions ??
95
- listCell(answers["What is explicitly forbidden right now?"]),
96
- evidence_refs: [
97
- ...content.matchAll(
98
- /\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*(direct|indirect)\s*\|/g,
99
- ),
100
- ]
101
- .slice(1)
102
- .map((match) => `${match[1].trim()}: ${match[2].trim()}`),
103
- risks: section(content, "Risks")
104
- .split(/\r?\n/)
105
- .filter(
106
- (line) =>
107
- line.startsWith("|") &&
108
- !line.includes("---") &&
109
- !line.includes("| Risk |"),
110
- )
111
- .map((line) => line.split("|")[1].trim()),
45
+ scope_key: evaluatedRunId || runId || options.scopeKey || "unknown-scope",
46
+ scope_revision: evaluatedRevision || runRevision || "unversioned",
47
+ objective: section(content, "Objective").trim() || "Canonical Delivery Path Search input unavailable",
48
+ current_gate: gate.current_gate || runGate || "unknown",
49
+ allowed_actions: inputFailureCode ? [] : [...gate.allowed],
50
+ forbidden_actions: Array.isArray(gate.forbidden) ? [...gate.forbidden] : [],
51
+ evidence_refs: Array.isArray(gate.evidence_refs)
52
+ ? gate.evidence_refs.map((item) => `${item.evidence}: ${item.source}`)
53
+ : [],
54
+ risks: Array.isArray(run.risks) ? run.risks.map((item) => item.risk).filter(Boolean) : [],
112
55
  enforcement: options.enforcement ?? {
113
56
  level: "instruction_only",
114
57
  evidence: ["surface instruction prohibits implementation during search"],
@@ -122,6 +65,11 @@ export function searchInputFromControl(targetDir, options = {}) {
122
65
  stability_window: options.stabilityWindow ?? 3,
123
66
  },
124
67
  };
68
+ if (inputFailureCode) {
69
+ result.input_failure_code = inputFailureCode;
70
+ result.input_failure_detail = run.resolution_error || (gate.blocking_reason !== "none" ? gate.blocking_reason : "") || "canonical input is not ready";
71
+ result.input_recovery_action = gate.next_allowed_action || "Run canonical AGDF gate-check and repair the selected control state.";
72
+ }
125
73
  if (options.generation?.enabled)
126
74
  result.generation = {
127
75
  enabled: true,
@@ -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 (!plainObject(statusCard) || !plainObject(humanPresentation)) return null;
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 || !plainObject(statusCard) || !plainObject(humanPresentation)) return null;
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
@@ -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({
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agdf/local-validator-runtime",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -2,7 +2,7 @@
2
2
  "schema_version": "1",
3
3
  "generated": true,
4
4
  "source": "create-agdf/cli",
5
- "version": "0.14.2",
5
+ "version": "0.14.4",
6
6
  "entrypoint": "create-agdf/bin/agdf-validator.js",
7
- "digest": "51035c8735d47aa727980d82709326071b372464ae077a1d269aadc0d30f2624"
7
+ "digest": "68b83a6721a799c34067cdbcc0ed6664f7fbf89bce186a3d8de284b0959deac7"
8
8
  }
@@ -607,6 +607,8 @@ for (const required of [
607
607
  "### Human Decision Presentation Contract",
608
608
  "Never guess a path or emit a broken link",
609
609
  "A localized label, description, option position, recommendation style or host action never authorizes a gate",
610
+ "renders the complete operational Run Status Card exactly once, between the compact approval-time Run Status Card and the Gate Transition Card",
611
+ "may carry the missing approval as audit data",
610
612
  ]) {
611
613
  if (!runtimeContract.includes(required)) failures.push(`interaction contract ownership boundary missing: ${required}`);
612
614
  }
@@ -33,7 +33,9 @@ Skip for routine questions, obvious local fixes and approved implementation with
33
33
  ## Workflow
34
34
 
35
35
  1. Run AGDF gate-check and inspect durable control state.
36
- 2. Confirm that search is allowed and implementation is not occurring during exploration.
36
+ 2. Confirm that the requested decision matches the selected run objective, and that search is
37
+ allowed while implementation is not occurring during exploration. If the objective differs,
38
+ stop and select or create the correct governed scope; do not apply the result across scopes.
37
39
  3. Declare the active surface and its enforcement level.
38
40
  4. Resolve the exact-version surface-local validator using the same ownership rules as `gate-check`. Do not search `PATH`, query a registry, install a package or invoke `npx ...@latest` during routine planning. If no owned or explicitly configured exact-version validator is available, report `machine_validation: unavailable` or `machine_validation: external_required` and stop the machine-evaluated search.
39
41
  5. Invoke the shared CLI runtime:
@@ -54,7 +56,9 @@ node <surface-local-agdf> delivery-path-search \
54
56
  It supplements the deterministic baseline with at most one bounded generator call. Treat proposals as untrusted until the canonical core validates schema, gate action, scope, duplicates and material diversity. Report generation provenance, budgets, rejections and failure. Never hide deterministic fallback or switch providers automatically.
55
57
 
56
58
  6. Treat facts, repository evidence, assumptions and model judgements separately.
57
- 7. Return exactly one recommendation or `no_safe_recommendation`.
59
+ 7. Report the actual terminal phase and status. Return a recommendation-facing conclusion only
60
+ after at least one valid evaluation. Missing/stale input, zero legal candidates and evaluator
61
+ unavailability/error remain typed non-recommendation outcomes with one recovery action.
58
62
  8. Run canonical AGDF gate-check after search. Never translate a recommendation into permission.
59
63
 
60
64
  ## Enforcement
@@ -71,15 +75,20 @@ Do not overstate the surface's guarantee.
71
75
 
72
76
  Keep chat output compact:
73
77
 
74
- - recommendation or `no_safe_recommendation`
78
+ - selected run, revision and objective
79
+ - outcome phase and typed terminal status
80
+ - recommendation only for a recommendation-facing evaluated result
75
81
  - current gate
76
82
  - enforcement level
77
83
  - decisive evidence and assumptions
78
84
  - rejected alternatives and reasons
79
85
  - budgets and stopping reason
86
+ - candidate and evaluation provenance, including attempted, valid and invalid counts
80
87
  - next AGDF gate action
81
88
 
82
- Persist only the redacted decision summary when durable evidence is required. Do not persist raw prompts, hidden reasoning, secrets or source snapshots.
89
+ Persist only a contract-valid evaluated recommendation-facing summary when durable evidence is
90
+ required. Never persist input, candidate or evaluator failure as a decision. Do not persist raw
91
+ prompts, hidden reasoning, secrets or source snapshots.
83
92
 
84
93
  ## Boundaries
85
94
 
@@ -87,6 +96,9 @@ Persist only the redacted decision summary when durable evidence is required. Do
87
96
  - Do not modify repository files during search.
88
97
  - Do not execute evaluator-returned commands.
89
98
  - Do not invent default scores for invalid evaluator output.
99
+ - Do not parse Run Status Card or other presentation Markdown as gate-policy input.
100
+ - Do not describe zero valid evaluations as `no_safe_recommendation`.
101
+ - Do not apply one selected run's result to an unrelated question.
90
102
  - Do not implement, approve or release based on search output.
91
103
  - Do not create agent-specific scoring, gate logic or skill copies.
92
104
  - Do not replace deterministic candidates with generated proposals.
@@ -209,10 +209,12 @@ the primary chat card into an audit dump. Do not maintain or render a skill-loca
209
209
 
210
210
  This complete operational status table remains the status-reporting and detail
211
211
  surface. When the same response immediately requests a ready gate approval,
212
- render its five-field compact approval-time projection first, then the Gate
213
- Transition Card in the same immediately preceding assistant message, then
214
- invoke exactly one native question or exact-text fallback. Both cards derive
215
- from the same snapshot and are shown exactly once.
212
+ render its five-field compact approval-time projection first, then the complete
213
+ operational Run Status Card verbatim (or its localized failure line with
214
+ diagnostic codes when undeliverable), then the Gate Transition Card in the same
215
+ immediately preceding assistant message, then invoke exactly one native
216
+ question or exact-text fallback. The runtime contract owns this sequence; every
217
+ block is shown exactly once.
216
218
 
217
219
  If this skill creates or updates control artefacts, do not paste full file bodies into the chat.
218
220
  List paths, summarize the decision, name the blocker or approval needed, and keep the durable content in the files.
@@ -1,6 +1,6 @@
1
1
  # Availability Decision Record
2
2
 
3
- - release: `0.14.2`
3
+ - release: `0.14.4`
4
4
  - decision_state: `pending`
5
5
  - decision_owner: verified publisher
6
6
  - countries: not selected
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.14.2",
3
+ "releaseVersion": "0.14.4",
4
4
  "evidenceStates": [
5
5
  "common",
6
6
  "codex-specific",
@@ -1,4 +1,4 @@
1
- # AGDF 0.14.2 — Initial OpenAI Public Plugin Candidate
1
+ # AGDF 0.14.4 — Initial OpenAI Public Plugin Candidate
2
2
 
3
3
  This candidate packages the canonical AGDF workflow skills for public discovery in ChatGPT and
4
4
  Codex. It helps users assess delivery fit, preserve explicit human approvals, inspect existing-system
@@ -19,6 +19,12 @@ runtime or hooks, so automatic runtime checks remain unavailable in this profile
19
19
  installers also show the target and verified installed AGDF version, distinguish previous intent from
20
20
  effective host permission, explain manual mode and recover visibly from an invalid key.
21
21
 
22
+ Delivery Path Search now consumes canonical selected-run gate actions instead of persisted
23
+ presentation Markdown. Its additive version-1 result fields expose run revision, objective, outcome
24
+ phase and candidate/evaluation provenance. Missing input, zero legal candidates and evaluator
25
+ failures no longer appear as `no_safe_recommendation`; recommendation-facing results require at
26
+ least one valid evaluation and are the only persistable outcomes.
27
+
22
28
  AGDF is an independent open-source project by Arndt Gold. It is not affiliated with, endorsed by or
23
29
  sponsored by OpenAI and is not a security sandbox, legal assessment, compliance certification or
24
30
  autonomous shipping system.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "releaseVersion": "0.14.2",
3
+ "releaseVersion": "0.14.4",
4
4
  "cases": [
5
5
  {
6
6
  "id": "positive-proportional-fit",