create-agdf 0.14.1 → 0.14.2

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 (112) hide show
  1. package/README.md +8 -2
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  4. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  5. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +7 -0
  6. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  7. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +29 -17
  8. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +50 -1
  9. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  10. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  11. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -1
  12. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  13. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  14. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  15. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  16. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +771 -0
  17. package/generated/plugins/copilot/agdf/LICENSE +201 -0
  18. package/generated/plugins/copilot/agdf/meta/agdf-agent-router.md +129 -0
  19. package/generated/plugins/copilot/agdf/meta/agdf-constitution.md +329 -0
  20. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +331 -0
  21. package/generated/plugins/copilot/agdf/meta/agdf-runtime-contract.md +16 -0
  22. package/generated/plugins/{agdf → copilot/agdf}/plugin.json +1 -1
  23. package/generated/plugins/copilot/agdf/runtime/agdf-local.js +18 -0
  24. package/generated/plugins/copilot/agdf/runtime/agdf-session-check.js +97 -0
  25. package/generated/plugins/copilot/agdf/runtime/create-agdf/NOTICE +10 -0
  26. package/generated/plugins/copilot/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
  27. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +512 -0
  28. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +331 -0
  29. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +144 -0
  30. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +139 -0
  31. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +173 -0
  32. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
  33. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +46 -0
  34. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +301 -0
  35. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +272 -0
  36. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +455 -0
  37. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +305 -0
  38. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
  39. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
  40. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
  41. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +345 -0
  42. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
  43. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
  44. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
  45. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
  46. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
  47. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +265 -0
  48. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
  49. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
  50. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
  51. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
  52. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
  53. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +35 -0
  54. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +44 -0
  55. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
  56. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
  57. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
  58. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
  59. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
  60. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
  61. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
  62. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
  63. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +155 -0
  64. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
  65. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +27 -0
  66. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
  67. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +842 -0
  68. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/local-validator.js +239 -0
  69. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +255 -0
  70. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
  71. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +73 -0
  72. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +6 -0
  73. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +8 -0
  74. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  75. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +6 -1
  76. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +7 -0
  77. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  78. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  79. package/generated/submissions/openai/agdf/submission/openai/inventory.json +13 -9
  80. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  81. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  82. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  83. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  84. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  85. package/lib/installers/local-marketplace.js +112 -30
  86. package/lib/installers/plugin-installers.js +45 -9
  87. package/lib/public-plugin/copilot-profile.js +126 -0
  88. package/lib/release/version-coherence.js +4 -1
  89. package/lib/runtime/local-validator.js +29 -17
  90. package/lib/runtime/plugin-provenance.js +50 -1
  91. package/package.json +3 -2
  92. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-brownfield-analysis/SKILL.md +0 -0
  93. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-clean-implementation-review/SKILL.md +0 -0
  94. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-code-review/SKILL.md +0 -0
  95. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-closeout/SKILL.md +0 -0
  96. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-path-search/SKILL.md +0 -0
  97. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-gate-check/SKILL.md +0 -0
  98. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-interaction-locales.json +0 -0
  99. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-qa-gate/SKILL.md +0 -0
  100. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-release-or/SKILL.md +0 -0
  101. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-runtime-contract.md +0 -0
  102. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-task-plan-review/SKILL.md +0 -0
  103. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-ux-intent-definition/SKILL.md +0 -0
  104. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/closeout.md +0 -0
  105. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/context-graph.md +0 -0
  106. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/control-scaffold.md +0 -0
  107. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/gate-transition.md +0 -0
  108. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/interaction.md +0 -0
  109. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/modes.md +0 -0
  110. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/quality.md +0 -0
  111. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/task-target-resolution.md +0 -0
  112. /package/generated/plugins/{agdf → copilot/agdf}/hooks/copilot-hooks.json +0 -0
@@ -0,0 +1,173 @@
1
+ import { resolve } from "node:path";
2
+ import process from "node:process";
3
+ import { configuredLanguage, resolveLanguagePreference } from "./runtime-context.js";
4
+ import { resolveCommand, supportedCommandNames } from "./command-registry.js";
5
+
6
+ export class CliUsageError extends Error {
7
+ constructor(message, { showUsage = false } = {}) {
8
+ super(message);
9
+ this.name = "CliUsageError";
10
+ this.exitCode = 1;
11
+ this.showUsage = showUsage;
12
+ }
13
+ }
14
+
15
+ function requiredValue(args, index, option) {
16
+ const next = args[index + 1];
17
+ if (!next) throw new CliUsageError(`Missing value for ${option}`);
18
+ return next;
19
+ }
20
+
21
+ export function parseArgs(argv, dependencies = {}) {
22
+ const cwd = dependencies.cwd ?? process.cwd();
23
+ const languagePreference = dependencies.resolveLanguagePreference ?? resolveLanguagePreference;
24
+ const normalizeLanguage = dependencies.configuredLanguage ?? configuredLanguage;
25
+ const args = [...argv];
26
+ let target;
27
+ let dir = ".";
28
+ let force = false;
29
+ let json = false;
30
+ let verbose = false;
31
+ let statusCard = false;
32
+ let approvalEnvelope = false;
33
+ let language;
34
+ let dirExplicit = false;
35
+ let surface = "generic";
36
+ let fixture;
37
+ let persist = false;
38
+ let model;
39
+ let generateCandidates = false;
40
+ let generatorModel;
41
+ let maxGeneratedCandidates = 5;
42
+ let generationTimeoutMs = 30000;
43
+ let generationCostUnits = 5;
44
+ let runId;
45
+ let allActive = false;
46
+ let scope;
47
+ let confirm = false;
48
+ let runtimeChecksDecision;
49
+ let runtimeChecksAction;
50
+
51
+ for (let i = 0; i < args.length; i += 1) {
52
+ const arg = args[i];
53
+ if (!arg) continue;
54
+ if (arg === "--help" || arg === "-h") return { kind: "help" };
55
+ if (arg === "--force") { force = true; continue; }
56
+ if (arg === "--json") { json = true; continue; }
57
+ if (arg === "--verbose") { verbose = true; continue; }
58
+ if (arg === "--status-card") { statusCard = true; continue; }
59
+ if (arg === "--approval-envelope") { approvalEnvelope = true; continue; }
60
+ if (arg === "--persist") { persist = true; continue; }
61
+ if (arg === "--generate-candidates") { generateCandidates = true; continue; }
62
+ if (arg === "--all-active") { allActive = true; continue; }
63
+ if (arg === "--confirm") { confirm = true; continue; }
64
+
65
+ if (arg === "--runtime-checks") {
66
+ const next = requiredValue(args, i, arg);
67
+ if (!["enable", "manual", "cancel"].includes(next)) throw new CliUsageError("--runtime-checks must be enable, manual or cancel.");
68
+ runtimeChecksDecision = next;
69
+ i += 1;
70
+ continue;
71
+ }
72
+
73
+ if (arg === "--run") {
74
+ runId = requiredValue(args, i, arg);
75
+ i += 1;
76
+ continue;
77
+ }
78
+
79
+ if (["--surface", "--scope", "--fixture", "--model", "--generator-model", "--max-generated-candidates", "--generation-timeout-ms", "--generation-cost-units"].includes(arg)) {
80
+ const next = requiredValue(args, i, arg);
81
+ if (arg === "--surface") {
82
+ if (!["codex", "claude", "copilot", "opencode", "generic"].includes(next)) {
83
+ throw new CliUsageError("Unsupported surface. Use codex, claude, copilot, opencode or generic.");
84
+ }
85
+ surface = next;
86
+ } else if (arg === "--scope") {
87
+ if (!["repository", "global"].includes(next)) throw new CliUsageError("Unsupported scope. Use repository or global.");
88
+ scope = next;
89
+ } else if (arg === "--fixture") fixture = next;
90
+ else if (arg === "--model") model = next;
91
+ else if (arg === "--generator-model") generatorModel = next;
92
+ else {
93
+ const value = Number(next);
94
+ const maximum = arg === "--generation-timeout-ms" ? 30000 : 5;
95
+ if (!Number.isInteger(value) || value < 1 || value > maximum) {
96
+ throw new CliUsageError(`${arg} must be an integer from 1 to ${maximum}.`);
97
+ }
98
+ if (arg === "--max-generated-candidates") maxGeneratedCandidates = value;
99
+ else if (arg === "--generation-timeout-ms") generationTimeoutMs = value;
100
+ else generationCostUnits = value;
101
+ }
102
+ i += 1;
103
+ continue;
104
+ }
105
+
106
+ if (arg === "--language" || arg === "--lang") {
107
+ const next = requiredValue(args, i, arg);
108
+ const normalized = normalizeLanguage(next);
109
+ if (!normalized) throw new CliUsageError("Invalid language tag. Use a BCP 47 tag such as de, en or fr-CA.");
110
+ language = normalized;
111
+ i += 1;
112
+ continue;
113
+ }
114
+
115
+ if (arg === "--dir") {
116
+ dir = requiredValue(args, i, arg);
117
+ dirExplicit = true;
118
+ i += 1;
119
+ continue;
120
+ }
121
+
122
+ if (arg === "--target" || arg === "-t") {
123
+ target = requiredValue(args, i, arg);
124
+ i += 1;
125
+ continue;
126
+ }
127
+
128
+ if (!arg.startsWith("-") && !target) {
129
+ target = arg;
130
+ continue;
131
+ }
132
+ if (!arg.startsWith("-") && target === "runtime-checks" && !runtimeChecksAction) {
133
+ if (!["status", "enable", "manual"].includes(arg)) throw new CliUsageError("runtime-checks action must be status, enable or manual.");
134
+ runtimeChecksAction = arg;
135
+ continue;
136
+ }
137
+ throw new CliUsageError(`Unknown argument: ${arg}`);
138
+ }
139
+
140
+ if (!target || !resolveCommand(target)) {
141
+ throw new CliUsageError(`Please choose one target: ${supportedCommandNames().join(", ")}.`, { showUsage: true });
142
+ }
143
+
144
+ return {
145
+ kind: "command",
146
+ options: {
147
+ target,
148
+ dir: resolve(cwd, dir),
149
+ force,
150
+ json,
151
+ verbose,
152
+ statusCard,
153
+ approvalEnvelope,
154
+ dirExplicit,
155
+ language: languagePreference(language),
156
+ surface,
157
+ fixture: fixture ? resolve(cwd, fixture) : null,
158
+ persist,
159
+ model,
160
+ generateCandidates,
161
+ runId,
162
+ allActive,
163
+ scope,
164
+ confirm,
165
+ runtimeChecksDecision,
166
+ runtimeChecksAction: runtimeChecksAction ?? "status",
167
+ generatorModel,
168
+ maxGeneratedCandidates,
169
+ generationTimeoutMs,
170
+ generationCostUnits,
171
+ },
172
+ };
173
+ }
@@ -0,0 +1,83 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import process from "node:process";
5
+ import {
6
+ canonicalizeLanguageTag,
7
+ resolvePresentationLocale,
8
+ } from "../interaction-presentation.js";
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+
12
+ export const packageRoot = resolve(__dirname, "../..");
13
+ export const generatedRoot = join(packageRoot, "generated");
14
+
15
+ const pluginDefinitionPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-plugin.definition.json");
16
+ const interactionLocalesPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-interaction-locales.json");
17
+
18
+ export const pluginDefinition = JSON.parse(readFileSync(pluginDefinitionPath, "utf8"));
19
+ export const interactionLocales = JSON.parse(readFileSync(interactionLocalesPath, "utf8"));
20
+
21
+ export function configuredLanguage(value) {
22
+ const normalized = canonicalizeLanguageTag(value);
23
+ if (!normalized) return "";
24
+ const language = normalized.split("-")[0];
25
+ if (interactionLocales.locales[normalized] || interactionLocales.locales[language]) {
26
+ return resolvePresentationLocale(interactionLocales, normalized);
27
+ }
28
+ return normalized;
29
+ }
30
+
31
+ export function detectSystemLocale(env = process.env) {
32
+ const envLocale = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE || "";
33
+ if (envLocale) return envLocale;
34
+ try {
35
+ return Intl.DateTimeFormat().resolvedOptions().locale || "";
36
+ } catch {
37
+ return "";
38
+ }
39
+ }
40
+
41
+ export function resolveLanguagePreference(explicitLanguage, env = process.env) {
42
+ const explicit = configuredLanguage(explicitLanguage);
43
+ if (explicit) {
44
+ return {
45
+ artifact_language: explicit,
46
+ chat_language: explicit,
47
+ runtime_language: "en",
48
+ source: "parameter",
49
+ detected_locale: detectSystemLocale(env) || "unknown",
50
+ };
51
+ }
52
+
53
+ const detectedLocale = detectSystemLocale(env);
54
+ const detected = configuredLanguage(detectedLocale) || interactionLocales.fallbackLocale;
55
+ return {
56
+ artifact_language: detected,
57
+ chat_language: detected,
58
+ runtime_language: "en",
59
+ source: detectedLocale ? "system_locale" : "default",
60
+ detected_locale: detectedLocale || "unknown",
61
+ };
62
+ }
63
+
64
+ export function resolveConfiguredChatLanguage(targetDir) {
65
+ const configPath = join(targetDir, ".agdf", "control", "config.json");
66
+ if (!existsSync(configPath)) return interactionLocales.fallbackLocale;
67
+ try {
68
+ const config = JSON.parse(readFileSync(configPath, "utf8"));
69
+ return resolvePresentationLocale(interactionLocales, config.chat_language);
70
+ } catch {
71
+ return interactionLocales.fallbackLocale;
72
+ }
73
+ }
74
+
75
+ export function languageConfigContent(languagePreference) {
76
+ return `${JSON.stringify({
77
+ artifact_language: languagePreference.artifact_language,
78
+ chat_language: languagePreference.chat_language,
79
+ runtime_language: languagePreference.runtime_language,
80
+ source: languagePreference.source,
81
+ detected_locale: languagePreference.detected_locale,
82
+ }, null, 2)}\n`;
83
+ }
@@ -0,0 +1,46 @@
1
+ import {
2
+ buildStatusCard,
3
+ evaluateGateCheck,
4
+ printApprovalEnvelope,
5
+ postApprovalTransition,
6
+ printGateCheckReport,
7
+ } from "../control-evaluation/gate-check.js";
8
+ import { evaluateDeliveryMap, printDeliveryMapReport } from "../control-evaluation/delivery-map.js";
9
+ import { evaluateDoctor, printDoctorReport } from "../control-evaluation/doctor.js";
10
+ import { executeDeliveryPathSearch } from "./delivery-path-search-command.js";
11
+
12
+ const deliveryMapDependencies = Object.freeze({ evaluateDoctor, buildStatusCard, postApprovalTransition });
13
+
14
+ export function createValidationHandlers(io = console) {
15
+ return new Map([
16
+ ["doctor", (options) => {
17
+ const report = evaluateDoctor(options.dir, options);
18
+ printDoctorReport(report, options.json, io);
19
+ return report.status === "block" ? 2 : 0;
20
+ }],
21
+ ["gate-check", (options) => {
22
+ const report = evaluateGateCheck(options.dir, options);
23
+ if (options.approvalEnvelope) {
24
+ const output = printApprovalEnvelope(report, { io, reEvaluate: () => evaluateGateCheck(options.dir, options) });
25
+ return output.status === "blocked" ? 2 : 0;
26
+ }
27
+ const presentationRendered = printGateCheckReport(report, options.json, options.statusCard, io);
28
+ if (presentationRendered === false) return 2;
29
+ return report.status === "blocked" ? 2 : 0;
30
+ }],
31
+ ["delivery-map", (options) => {
32
+ const report = evaluateDeliveryMap(options.dir, options, deliveryMapDependencies);
33
+ printDeliveryMapReport(report, options.json, io);
34
+ return report.status === "block" ? 2 : 0;
35
+ }],
36
+ ["delivery-path-search", async (options) => {
37
+ try {
38
+ const result = await executeDeliveryPathSearch(options, io);
39
+ return result.status === "recommendation" ? 0 : 2;
40
+ } catch (error) {
41
+ io.error(`Delivery Path Search failed: ${error.message}`);
42
+ return 2;
43
+ }
44
+ }],
45
+ ]);
46
+ }
@@ -0,0 +1,301 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { aggregate, resolveRuns } from '../control-state/index.js';
4
+ import { resolveConfiguredChatLanguage } from '../cli/runtime-context.js';
5
+ import { isGateSatisfied, transitionDecisionForRunState } from './gate-policy.js';
6
+ import { gateApprovalStatus, readRunState, resolvedArtefactFile } from './run-state.js';
7
+ import { allowNoActiveRuns, filled, isPlaceholderValue, markdownSection, parseBacklogSection, readTargetFile } from './shared.js';
8
+ import { evaluateReconciliationState } from './parent-reconciliation.js';
9
+
10
+ const deliveryRelationships = [
11
+ { from: "UR", relationship: "approved_by", to: "Approval: UR", requiredBy: "UR" },
12
+ { from: "PRD", relationship: "derived_from", to: "UR", requiredBy: "PRD" },
13
+ { from: "SD", relationship: "derived_from", to: "PRD", requiredBy: "SD" },
14
+ { from: "TP", relationship: "derived_from", to: "SD", requiredBy: "TP" },
15
+ { from: "QA_REPORT", relationship: "tests", to: "TP", requiredBy: "QA" },
16
+ ];
17
+
18
+ function relationshipRequired(runState, requiredBy) {
19
+ if (gateApprovalStatus(runState, requiredBy) === "not_applicable") return false;
20
+ if (requiredBy === "QA") {
21
+ return isGateSatisfied(runState, "QA");
22
+ }
23
+
24
+ return isGateSatisfied(runState, requiredBy);
25
+ }
26
+
27
+ function findRelationship(runState, expected) {
28
+ return runState.artefact_chain.find((row) =>
29
+ row.from === expected.from
30
+ && row.relationship === expected.relationship
31
+ && row.to === expected.to
32
+ );
33
+ }
34
+
35
+ function severityFromImpact(value) {
36
+ if (value === "block") return "block";
37
+ if (value === "revise") return "revise";
38
+ if (value === "warning" || value === "warn") return "warn";
39
+ return null;
40
+ }
41
+
42
+ export function analyzeDeliveryMap(runState, dependencies = {}) {
43
+ const findings = [];
44
+ const reconciliation = evaluateReconciliationState(runState, dependencies);
45
+ findings.push(...reconciliation.findings);
46
+ const relationships = deliveryRelationships.map((expected) => {
47
+ const row = findRelationship(runState, expected);
48
+ const required = relationshipRequired(runState, expected.requiredBy);
49
+ const evidence = row?.evidence ?? "";
50
+ const status = !row ? "missing" : filled(evidence) ? "pass" : required ? "missing_evidence" : "template";
51
+
52
+ if (required && status !== "pass") {
53
+ findings.push({
54
+ severity: "revise",
55
+ code: status === "missing" ? "AGDF_DELIVERY_RELATIONSHIP_MISSING" : "AGDF_DELIVERY_RELATIONSHIP_EVIDENCE_MISSING",
56
+ message: `${expected.from} must be traceable via ${expected.relationship} ${expected.to}.`,
57
+ path: runState.path,
58
+ next_step: "Fill the Artefact Chain row with concrete evidence before treating the delivery map as complete.",
59
+ });
60
+ }
61
+
62
+ return {
63
+ from: expected.from,
64
+ relationship: expected.relationship,
65
+ to: expected.to,
66
+ required,
67
+ status,
68
+ evidence,
69
+ };
70
+ });
71
+
72
+ for (const item of runState.missing_evidence) {
73
+ const severity = severityFromImpact(item.impact);
74
+ if (!severity) continue;
75
+ findings.push({
76
+ severity,
77
+ code: "AGDF_MISSING_EVIDENCE_DECLARED",
78
+ message: item.missing_evidence,
79
+ path: runState.path,
80
+ next_step: item.required_next_step || "Resolve or explicitly accept the missing evidence before advancing the gate.",
81
+ });
82
+ }
83
+
84
+ for (const item of runState.risks) {
85
+ const severity = severityFromImpact(item.impact);
86
+ if (!severity) continue;
87
+ findings.push({
88
+ severity,
89
+ code: "AGDF_RISK_DECLARED",
90
+ message: item.risk,
91
+ path: runState.path,
92
+ next_step: item.mitigation_or_owner || "Assign mitigation or ownership before advancing the gate.",
93
+ });
94
+ }
95
+
96
+ const contextSeverity = severityFromImpact(runState.context_graph?.gate_effect);
97
+ if (contextSeverity) {
98
+ findings.push({
99
+ severity: contextSeverity,
100
+ code: "AGDF_CONTEXT_GRAPH_GATE_EFFECT",
101
+ message: `Context Graph impact is ${runState.context_graph.impact || "unspecified"} with gate effect ${runState.context_graph.gate_effect}.`,
102
+ path: runState.path,
103
+ next_step: runState.context_graph.required_action && runState.context_graph.required_action !== "none"
104
+ ? `Resolve Context Graph action: ${runState.context_graph.required_action}.`
105
+ : "Clarify the Context Graph impact before advancing the gate.",
106
+ });
107
+ }
108
+
109
+ const multiScopeState = runState.source_scope?.multi_scope_state;
110
+ if (multiScopeState === "ambiguous" || multiScopeState === "blocked") {
111
+ findings.push({
112
+ severity: multiScopeState === "blocked" ? "block" : "revise",
113
+ code: "AGDF_SCOPE_AMBIGUOUS",
114
+ message: "Multiple active scope lines are plausible; the agent must not choose one silently.",
115
+ path: runState.path,
116
+ next_step: "List competing scope lines with gate and artefact evidence, then clarify the active scope.",
117
+ });
118
+ }
119
+
120
+ const branchEffect = runState.source_scope?.branch_workspace_scope_effect;
121
+ if (branchEffect === "conflicts" || branchEffect === "insufficient") {
122
+ findings.push({
123
+ severity: branchEffect === "conflicts" ? "revise" : "warn",
124
+ code: "AGDF_BRANCH_NOT_SCOPE_PROOF",
125
+ message: "Branch or workspace evidence is not sufficient scope proof.",
126
+ path: runState.path,
127
+ next_step: "Confirm the active scope from durable artefacts or record why branch/workspace evidence is only supporting evidence.",
128
+ });
129
+ }
130
+
131
+ if (runState.memory?.target && runState.memory.target !== "none" && !filled(runState.memory.reason)) {
132
+ findings.push({
133
+ severity: "warn",
134
+ code: "AGDF_MEMORY_TARGET_REASON_MISSING",
135
+ message: "Knowledge persistence target is set without a reason.",
136
+ path: runState.path,
137
+ next_step: "Fill memory_reason or set memory_target to none.",
138
+ });
139
+ }
140
+
141
+ return {
142
+ relationships,
143
+ missing_evidence: runState.missing_evidence,
144
+ risks: runState.risks,
145
+ context_graph: runState.context_graph,
146
+ source_scope: runState.source_scope,
147
+ memory: runState.memory,
148
+ parent_reconciliation: reconciliation.parent_reconciliation,
149
+ programme_aggregation: reconciliation.programme_aggregation,
150
+ findings,
151
+ };
152
+ }
153
+
154
+ export function deriveQualityOutlook(runState, findings = []) {
155
+ if (filled(runState.quality_outlook)) return runState.quality_outlook;
156
+ if (findings.some((finding) => finding.severity === "block" || finding.severity === "revise")) {
157
+ return "Resolve blocking or revise-level delivery-map findings before making stronger quality claims.";
158
+ }
159
+ if (findings.some((finding) => finding.severity === "warn")) {
160
+ return "Review warning-level findings when investing further in delivery confidence.";
161
+ }
162
+ return "No additional quality follow-up identified from the current control state.";
163
+ }
164
+
165
+ function readBacklogPointers(targetDir) {
166
+ const backlogPath = join(".agdf", "control", "MASTER_BACKLOG.md");
167
+ if (!existsSync(join(targetDir, backlogPath))) return [];
168
+
169
+ const backlog = readTargetFile(targetDir, backlogPath);
170
+ const activeSection = markdownSection(backlog, "Active Backlog");
171
+ return parseBacklogSection(activeSection);
172
+ }
173
+
174
+ export function evaluateDeliveryMap(targetDir, selection = {}, dependencies = {}) {
175
+ const { evaluateDoctor, buildStatusCard, postApprovalTransition } = dependencies;
176
+ if (typeof evaluateDoctor !== "function" || typeof buildStatusCard !== "function" || typeof postApprovalTransition !== "function") {
177
+ throw new TypeError("evaluateDeliveryMap requires doctor and status-card composition dependencies.");
178
+ }
179
+ if (selection.allActive) {
180
+ const selected = resolveRuns(targetDir, { allActive: true });
181
+ const runs = selected.runs.map((run) => ({
182
+ run_id: run.run_id,
183
+ report: evaluateDeliveryMap(targetDir, { runId: run.run_id }, dependencies),
184
+ }));
185
+ const status = selected.findings.length
186
+ ? "block"
187
+ : aggregate(
188
+ runs.map((item) => ({
189
+ run_id: item.run_id,
190
+ status: item.report.status,
191
+ })),
192
+ { allowNoActiveRuns: allowNoActiveRuns(targetDir) },
193
+ ).status;
194
+ const findings = [
195
+ ...selected.findings.map((finding) => ({
196
+ ...finding,
197
+ severity: "block",
198
+ message: "Invalid canonical run entry.",
199
+ next_step: "Repair or remove the invalid run entry.",
200
+ })),
201
+ ...runs.flatMap((item) =>
202
+ (item.report.doctor_report?.findings ?? item.report.findings).map((finding) => ({
203
+ ...finding,
204
+ run_id: item.run_id,
205
+ })),
206
+ ),
207
+ ];
208
+ return {
209
+ schema_version: "1",
210
+ status,
211
+ current_gate: "all-active",
212
+ next_allowed_action: runs.length
213
+ ? "Resolve per-run findings."
214
+ : "Create or activate a governed run.",
215
+ quality_outlook: "Keep every active run independently actionable.",
216
+ relationships: runs.flatMap((item) => item.report.relationships),
217
+ findings,
218
+ runs,
219
+ };
220
+ }
221
+ const doctorReport = evaluateDoctor(targetDir, selection);
222
+ const runState = readRunState(targetDir, selection);
223
+ const map = analyzeDeliveryMap(runState, {
224
+ loadRun: (runId) => readRunState(targetDir, { runId }),
225
+ resolveFile: (path) => resolvedArtefactFile(targetDir, path),
226
+ });
227
+ const gateDecision = transitionDecisionForRunState(runState);
228
+ const currentGate = gateDecision.current_gate;
229
+
230
+ const severityRank = { block: 3, revise: 2, warn: 1 };
231
+ const deliverySeverity = map.findings.reduce((max, finding) => Math.max(max, severityRank[finding.severity] ?? 0), 0);
232
+ const doctorSeverity = severityRank[doctorReport.status] ?? 0;
233
+ const maxSeverity = Math.max(deliverySeverity, doctorSeverity);
234
+ const status = maxSeverity >= 3 ? "block" : maxSeverity === 2 ? "revise" : maxSeverity === 1 ? "warn" : "pass";
235
+
236
+ const qualityOutlook = deriveQualityOutlook(runState, map.findings);
237
+ const nextAllowedAction = isPlaceholderValue(runState.next_allowed_action) ? gateDecision.next_allowed_action : runState.next_allowed_action;
238
+ const postApproval = postApprovalTransition(gateDecision.missing_approval);
239
+
240
+ return {
241
+ schema_version: "1",
242
+ status,
243
+ checked_at: new Date().toISOString(),
244
+ target_dir: targetDir,
245
+ current_gate: currentGate,
246
+ next_allowed_action: nextAllowedAction,
247
+ next_gate_after_approval: postApproval.next_gate_after_approval,
248
+ allowed_after_approval: postApproval.allowed_after_approval,
249
+ quality_outlook: qualityOutlook,
250
+ status_card: buildStatusCard({
251
+ status,
252
+ currentGate,
253
+ allowed: gateDecision.allowed,
254
+ forbidden: gateDecision.forbidden,
255
+ blockingReason: gateDecision.blocking_reason,
256
+ missingApproval: gateDecision.missing_approval,
257
+ nextAllowedAction,
258
+ runState,
259
+ chatLanguage: resolveConfiguredChatLanguage(targetDir),
260
+ findings: map.findings,
261
+ }),
262
+ backlog_pointers: readBacklogPointers(targetDir),
263
+ artefacts: Object.fromEntries([...runState.artefacts.entries()]),
264
+ approvals: Object.fromEntries([...runState.approvals.entries()]),
265
+ mode_slice_decision: runState.mode_slice_decision,
266
+ relationships: map.relationships,
267
+ evidence_refs: runState.evidence_refs,
268
+ missing_evidence: map.missing_evidence,
269
+ risks: map.risks,
270
+ context_graph: map.context_graph,
271
+ source_scope: map.source_scope,
272
+ memory: map.memory,
273
+ parent_reconciliation: map.parent_reconciliation,
274
+ programme_aggregation: map.programme_aggregation,
275
+ findings: map.findings,
276
+ doctor_status: doctorReport.status,
277
+ doctor_summary: doctorReport.summary,
278
+ doctor_report: doctorReport,
279
+ };
280
+ }
281
+
282
+ export function printDeliveryMapReport(report, json, io = console) {
283
+ if (json) {
284
+ io.log(JSON.stringify(report, null, 2));
285
+ return;
286
+ }
287
+
288
+ io.log(`AGDF delivery-map: ${report.status}`);
289
+ io.log(`Current gate: ${report.current_gate}`);
290
+ io.log(`Next allowed action: ${report.next_allowed_action}`);
291
+ io.log(`Quality outlook: ${report.quality_outlook}`);
292
+ io.log(`Relationships: ${report.relationships.filter((item) => item.status === "pass").length}/${report.relationships.length} evidenced`);
293
+ io.log(`Findings: ${report.findings.length}`);
294
+
295
+ for (const finding of report.findings) {
296
+ io.log("");
297
+ io.log(`[${finding.severity}] ${finding.code}`);
298
+ io.log(finding.message);
299
+ io.log(`Next step: ${finding.next_step}`);
300
+ }
301
+ }