create-agdf 0.6.1 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1001,6 +1001,10 @@ const backlogArtefactLabels = new Map([
1001
1001
  ["qa", "qa"],
1002
1002
  ["or", "or"],
1003
1003
  ]);
1004
+ const backlogScopeLabels = new Map([
1005
+ ["framework-maintenance", "framework_maintenance"],
1006
+ ["external-delivery", "external_delivery"],
1007
+ ]);
1004
1008
 
1005
1009
  function normalizeBacklogHeader(value) {
1006
1010
  return value.replace(/`/g, "").trim().toLowerCase();
@@ -1062,11 +1066,32 @@ function normalizeBacklogStatus(value, findings, backlogPath) {
1062
1066
  return cleaned;
1063
1067
  }
1064
1068
 
1069
+ function normalizeBacklogScope(workItem, findings, backlogPath) {
1070
+ const match = (workItem ?? "").match(/^\[([^\]]+)\]/);
1071
+ if (!match) return undefined;
1072
+ const cleaned = match[1].trim();
1073
+ const lookup = cleaned.replaceAll("_", " ").toLowerCase().replaceAll(" ", "-");
1074
+ const normalized = backlogScopeLabels.get(lookup);
1075
+ if (normalized) return normalized;
1076
+ if (findings) {
1077
+ addFinding(
1078
+ findings,
1079
+ "revise",
1080
+ "AGDF_BACKLOG_SCOPE_LABEL_UNKNOWN",
1081
+ `MASTER_BACKLOG.md uses an unknown Work item scope tag: [${cleaned}].`,
1082
+ backlogPath,
1083
+ "Use [framework-maintenance] or [external-delivery], or remove the bracketed tag.",
1084
+ );
1085
+ }
1086
+ return cleaned;
1087
+ }
1088
+
1065
1089
  function emptyBacklogPointer() {
1066
1090
  return {
1067
1091
  prio: "",
1068
1092
  key: "",
1069
1093
  title: "",
1094
+ scope: "",
1070
1095
  status: "",
1071
1096
  ur: "",
1072
1097
  brownfield_review: "",
@@ -1181,6 +1206,7 @@ function parseBacklogSection(section, findings = null, backlogPath = ".agdf/cont
1181
1206
  pointer.prio = cells[0] ?? "";
1182
1207
  pointer.key = cleanStatusCell(cells[1] ?? "");
1183
1208
  pointer.title = cells[2] ?? "";
1209
+ pointer.scope = normalizeBacklogScope(cells[2], findings, backlogPath) ?? "";
1184
1210
  pointer.status = normalizeBacklogStatus(cells[3], findings, backlogPath);
1185
1211
  parseCompactArtefacts(cells[4] ?? "", pointer, findings, backlogPath);
1186
1212
  pointer.current_spec = normalizedBacklogLinkTarget(cells[5] ?? "", findings, backlogPath, "Current spec");
@@ -1316,41 +1342,53 @@ function evaluateDoctor(targetDir, selection = {}) {
1316
1342
  const selectedRunState = readRunState(targetDir, selection);
1317
1343
  const runPath = selectedRunState.path;
1318
1344
  const run = selectedRunState.content;
1319
- const currentGateLine = run.match(/^- current_gate:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
1320
- const nextActionLine = run.match(/^- next_allowed_action:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
1321
- const hasEvidence = hasFilledEvidenceRow(run);
1322
1345
 
1323
- if (isPlaceholderValue(currentGateLine)) {
1346
+ if (selectedRunState.resolution_error) {
1324
1347
  addFinding(
1325
1348
  findings,
1326
- "revise",
1327
- "AGDF_CURRENT_GATE_MISSING",
1328
- "The selected run state does not name the current gate.",
1349
+ "block",
1350
+ selectedRunState.resolution_error.split(":")[0] || "AGDF_ACTIVE_RUN_UNRESOLVED",
1351
+ `Run selection failed: ${selectedRunState.resolution_error}`,
1329
1352
  runPath,
1330
- "Set current_gate to the current delivery gate or none.",
1353
+ "Pass --run <run_id> or set AGDF_RUN_ID to select the intended run, or use --all-active to evaluate every active run independently.",
1331
1354
  );
1332
- }
1355
+ } else {
1356
+ const currentGateLine = run.match(/^- current_gate:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
1357
+ const nextActionLine = run.match(/^- next_allowed_action:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
1358
+ const hasEvidence = hasFilledEvidenceRow(run);
1333
1359
 
1334
- if (isPlaceholderValue(nextActionLine)) {
1335
- addFinding(
1336
- findings,
1337
- "revise",
1338
- "AGDF_NEXT_ALLOWED_ACTION_MISSING",
1339
- "The selected run state does not state the next allowed action.",
1340
- runPath,
1341
- "Fill the next allowed action before asking an agent to continue delivery work.",
1342
- );
1343
- }
1360
+ if (isPlaceholderValue(currentGateLine)) {
1361
+ addFinding(
1362
+ findings,
1363
+ "revise",
1364
+ "AGDF_CURRENT_GATE_MISSING",
1365
+ "The selected run state does not name the current gate.",
1366
+ runPath,
1367
+ "Set current_gate to the current delivery gate or none.",
1368
+ );
1369
+ }
1344
1370
 
1345
- if (!hasEvidence) {
1346
- addFinding(
1347
- findings,
1348
- "warn",
1349
- "AGDF_EVIDENCE_EMPTY",
1350
- "The selected run state has no visible evidence row yet.",
1351
- runPath,
1352
- "Add at least one evidence row or explicitly document that no evidence exists yet.",
1353
- );
1371
+ if (isPlaceholderValue(nextActionLine)) {
1372
+ addFinding(
1373
+ findings,
1374
+ "revise",
1375
+ "AGDF_NEXT_ALLOWED_ACTION_MISSING",
1376
+ "The selected run state does not state the next allowed action.",
1377
+ runPath,
1378
+ "Fill the next allowed action before asking an agent to continue delivery work.",
1379
+ );
1380
+ }
1381
+
1382
+ if (!hasEvidence) {
1383
+ addFinding(
1384
+ findings,
1385
+ "warn",
1386
+ "AGDF_EVIDENCE_EMPTY",
1387
+ "The selected run state has no visible evidence row yet.",
1388
+ runPath,
1389
+ "Add at least one evidence row or explicitly document that no evidence exists yet.",
1390
+ );
1391
+ }
1354
1392
  }
1355
1393
 
1356
1394
  const backlogPath = join(".agdf", "control", "MASTER_BACKLOG.md");
@@ -1489,16 +1527,21 @@ function cleanStatusCell(value) {
1489
1527
  function readRunState(targetDir, selection = {}) {
1490
1528
  let runPath = join(".agdf", "control", "AGDF_RUN.md");
1491
1529
  const canonicalRoot = join(targetDir, ".agdf", "control", "runs");
1530
+ let resolutionError;
1492
1531
  if (existsSync(canonicalRoot)) {
1493
- const selected = resolveRuns(targetDir, {
1494
- runIdArg: selection.runId,
1495
- runIdEnv: process.env.AGDF_RUN_ID,
1496
- });
1497
- runPath = selected.run.path.startsWith(targetDir)
1498
- ? selected.run.path.slice(targetDir.length + 1)
1499
- : selected.run.path;
1532
+ try {
1533
+ const selected = resolveRuns(targetDir, {
1534
+ runIdArg: selection.runId,
1535
+ runIdEnv: process.env.AGDF_RUN_ID,
1536
+ });
1537
+ runPath = selected.run.path.startsWith(targetDir)
1538
+ ? selected.run.path.slice(targetDir.length + 1)
1539
+ : selected.run.path;
1540
+ } catch (error) {
1541
+ resolutionError = error.message;
1542
+ }
1500
1543
  }
1501
- if (!existsSync(join(targetDir, runPath))) {
1544
+ if (resolutionError || !existsSync(join(targetDir, runPath))) {
1502
1545
  return {
1503
1546
  path: runPath,
1504
1547
  content: "",
@@ -1515,6 +1558,7 @@ function readRunState(targetDir, selection = {}) {
1515
1558
  quality_outlook: "",
1516
1559
  source_scope: {},
1517
1560
  memory: {},
1561
+ resolution_error: resolutionError,
1518
1562
  };
1519
1563
  }
1520
1564
 
@@ -2168,7 +2212,7 @@ function evaluateDeliveryMap(targetDir, selection = {}) {
2168
2212
  next_step: "Repair or remove the invalid run entry.",
2169
2213
  })),
2170
2214
  ...runs.flatMap((item) =>
2171
- item.report.findings.map((finding) => ({
2215
+ (item.report.doctor_report?.findings ?? item.report.findings).map((finding) => ({
2172
2216
  ...finding,
2173
2217
  run_id: item.run_id,
2174
2218
  })),
@@ -18,6 +18,8 @@ This file is the living control pointer for active AGDF delivery work. Detailed
18
18
  12. `Status` must be one of the human-readable labels `create-agdf/bin/create-agdf.js`'s `backlogStatusLabels` normalizes: Needs UR, Awaiting Brownfield Review, Awaiting PRD, Awaiting PRD Approval, Awaiting SD, Awaiting SD Approval, Awaiting TP, Awaiting TP Approval, In Progress, Blocked, Awaiting QA, Awaiting UAT, Completed, Superseded, Abandoned. That map is authoritative; this list only mirrors it for readability.
19
19
  13. `Artefacts` link labels must be one of `backlogArtefactLabels`: `ur`, `brownfield`, `prd`, `sd`, `tp`, `qa`, `or` (case-insensitive). Do not invent other labels such as a raw artefact filename.
20
20
  14. After writing or updating this file, run `doctor --json` (or the locally available equivalent) and resolve any `AGDF_BACKLOG_STATUS_UNKNOWN` or `AGDF_BACKLOG_ARTEFACT_LABEL_UNKNOWN` finding before treating the edit as done.
21
+ 15. A `Work item` cell may optionally start with a bracketed scope tag, one of `[framework-maintenance]` or `[external-delivery]`, so the split between AGDF's own maintenance work and external product delivery stays visible at a glance. The tag is never required retroactively on `Completed / Superseded Pointers` rows. `create-agdf/bin/create-agdf.js`'s `backlogScopeLabels` map is authoritative for the two accepted values.
22
+ 16. After writing or updating this file, also resolve any `AGDF_BACKLOG_SCOPE_LABEL_UNKNOWN` finding, which fires only for a present-but-unrecognized bracketed tag, never for an absent one.
21
23
 
22
24
  ## Active Backlog
23
25
 
@@ -47,6 +47,22 @@ A `MASTER_BACKLOG.md` entry is required only when the change is otherwise a "Rel
47
47
  change that is not clearly and fully outside every listed path fails closed to the existing, unchanged
48
48
  ceremony — ambiguity is never read as permission for the lighter path.
49
49
 
50
+ #### Narrow Code-Fix Criterion
51
+
52
+ A change that touches one of the otherwise-excluded code paths above may still close with only the
53
+ compact Quick Task Output shape — Code Review remains mandatory regardless — when **all** of the
54
+ following hold. Any single condition failing, or any ambiguity about whether a condition holds, keeps
55
+ the full existing ceremony unchanged:
56
+
57
+ 1. The diff is confined to a single function, or a function together with its direct,
58
+ necessarily-coupled caller, in exactly one file.
59
+ 2. A new or updated automated regression test exercises the fixed behavior and passes.
60
+ 3. No PRD, SD, TP, gate name, exact approval formula, or documented CLI flag/output-schema field is
61
+ added, removed, or changed — only internal correctness of already-approved behavior.
62
+ 4. `doctor` (or the locally available equivalent) and the directly affected existing test suite both
63
+ pass unchanged in shape after the fix, with no assertion skipped or weakened beyond what the fix
64
+ itself introduces.
65
+
50
66
  ## Run Status Card
51
67
 
52
68
  When a run needs an operational status view, use the Run Status Card as a compact projection of existing control state.
@@ -47,6 +47,22 @@ A `MASTER_BACKLOG.md` entry is required only when the change is otherwise a "Rel
47
47
  change that is not clearly and fully outside every listed path fails closed to the existing, unchanged
48
48
  ceremony — ambiguity is never read as permission for the lighter path.
49
49
 
50
+ #### Narrow Code-Fix Criterion
51
+
52
+ A change that touches one of the otherwise-excluded code paths above may still close with only the
53
+ compact Quick Task Output shape — Code Review remains mandatory regardless — when **all** of the
54
+ following hold. Any single condition failing, or any ambiguity about whether a condition holds, keeps
55
+ the full existing ceremony unchanged:
56
+
57
+ 1. The diff is confined to a single function, or a function together with its direct,
58
+ necessarily-coupled caller, in exactly one file.
59
+ 2. A new or updated automated regression test exercises the fixed behavior and passes.
60
+ 3. No PRD, SD, TP, gate name, exact approval formula, or documented CLI flag/output-schema field is
61
+ added, removed, or changed — only internal correctness of already-approved behavior.
62
+ 4. `doctor` (or the locally available equivalent) and the directly affected existing test suite both
63
+ pass unchanged in shape after the fix, with no assertion skipped or weakened beyond what the fix
64
+ itself introduces.
65
+
50
66
  ## Run Status Card
51
67
 
52
68
  When a run needs an operational status view, use the Run Status Card as a compact projection of existing control state.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdf",
3
- "version": "0.6.1",
3
+ "version": "0.6.5",
4
4
  "description": "Codex-first operating system for governed AI-assisted delivery.",
5
5
  "author": {
6
6
  "name": "Arndt Gold",
@@ -18,6 +18,8 @@ This file is the living control pointer for active AGDF delivery work. Detailed
18
18
  12. `Status` must be one of the human-readable labels `create-agdf/bin/create-agdf.js`'s `backlogStatusLabels` normalizes: Needs UR, Awaiting Brownfield Review, Awaiting PRD, Awaiting PRD Approval, Awaiting SD, Awaiting SD Approval, Awaiting TP, Awaiting TP Approval, In Progress, Blocked, Awaiting QA, Awaiting UAT, Completed, Superseded, Abandoned. That map is authoritative; this list only mirrors it for readability.
19
19
  13. `Artefacts` link labels must be one of `backlogArtefactLabels`: `ur`, `brownfield`, `prd`, `sd`, `tp`, `qa`, `or` (case-insensitive). Do not invent other labels such as a raw artefact filename.
20
20
  14. After writing or updating this file, run `doctor --json` (or the locally available equivalent) and resolve any `AGDF_BACKLOG_STATUS_UNKNOWN` or `AGDF_BACKLOG_ARTEFACT_LABEL_UNKNOWN` finding before treating the edit as done.
21
+ 15. A `Work item` cell may optionally start with a bracketed scope tag, one of `[framework-maintenance]` or `[external-delivery]`, so the split between AGDF's own maintenance work and external product delivery stays visible at a glance. The tag is never required retroactively on `Completed / Superseded Pointers` rows. `create-agdf/bin/create-agdf.js`'s `backlogScopeLabels` map is authoritative for the two accepted values.
22
+ 16. After writing or updating this file, also resolve any `AGDF_BACKLOG_SCOPE_LABEL_UNKNOWN` finding, which fires only for a present-but-unrecognized bracketed tag, never for an absent one.
21
23
 
22
24
  ## Active Backlog
23
25
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "agdf",
4
- "version": "0.6.1",
4
+ "version": "0.6.5",
5
5
  "displayName": "AI Governance & Delivery Framework",
6
6
  "developerName": "Arndt Gold",
7
7
  "description": "Codex-first operating system for governed AI-assisted delivery.",
@@ -47,6 +47,22 @@ A `MASTER_BACKLOG.md` entry is required only when the change is otherwise a "Rel
47
47
  change that is not clearly and fully outside every listed path fails closed to the existing, unchanged
48
48
  ceremony — ambiguity is never read as permission for the lighter path.
49
49
 
50
+ #### Narrow Code-Fix Criterion
51
+
52
+ A change that touches one of the otherwise-excluded code paths above may still close with only the
53
+ compact Quick Task Output shape — Code Review remains mandatory regardless — when **all** of the
54
+ following hold. Any single condition failing, or any ambiguity about whether a condition holds, keeps
55
+ the full existing ceremony unchanged:
56
+
57
+ 1. The diff is confined to a single function, or a function together with its direct,
58
+ necessarily-coupled caller, in exactly one file.
59
+ 2. A new or updated automated regression test exercises the fixed behavior and passes.
60
+ 3. No PRD, SD, TP, gate name, exact approval formula, or documented CLI flag/output-schema field is
61
+ added, removed, or changed — only internal correctness of already-approved behavior.
62
+ 4. `doctor` (or the locally available equivalent) and the directly affected existing test suite both
63
+ pass unchanged in shape after the fix, with no assertion skipped or weakened beyond what the fix
64
+ itself introduces.
65
+
50
66
  ## Run Status Card
51
67
 
52
68
  When a run needs an operational status view, use the Run Status Card as a compact projection of existing control state.
@@ -57,15 +57,16 @@ export function migrateLegacy(root, requested, io = {}) {
57
57
  }
58
58
  return { status: "migrated", path: dest };
59
59
  }
60
- export function renderLegacyProjection(path) {
60
+ export function renderLegacyProjection(path, root = process.cwd()) {
61
61
  const content = readFileSync(path, "utf8"),
62
62
  parsed = parseRunState(content),
63
63
  digest = createHash("sha256").update(content).digest("hex");
64
64
  if (!parsed.valid) throw Error("AGDF_RUN_NOT_SELECTABLE");
65
- return `<!-- AGDF LEGACY PROJECTION: NON-AUTHORITATIVE -->\n<!-- canonical_source: ${path} -->\n<!-- run_id: ${parsed.meta.run_id} -->\n<!-- revision_id: ${parsed.meta.revision_id} -->\n<!-- sha256: ${digest} -->\n${content}`;
65
+ const canonicalSource = relative(resolve(root), resolve(path)).replaceAll("\\", "/");
66
+ return `<!-- AGDF LEGACY PROJECTION: NON-AUTHORITATIVE -->\n<!-- canonical_source: ${canonicalSource} -->\n<!-- run_id: ${parsed.meta.run_id} -->\n<!-- revision_id: ${parsed.meta.revision_id} -->\n<!-- sha256: ${digest} -->\n${content}`;
66
67
  }
67
68
  export function writeLegacyProjection(path, canonical) {
68
- atomicWrite(path, renderLegacyProjection(canonical));
69
+ atomicWrite(path, renderLegacyProjection(canonical, resolve(dirname(path), "../..")));
69
70
  }
70
71
  export function verifyLegacyProjection(root) {
71
72
  const path = join(root, ".agdf", "control", "AGDF_RUN.md");
@@ -78,7 +79,7 @@ export function verifyLegacyProjection(root) {
78
79
  projected = projectedStart >= 0 ? p.slice(projectedStart) : undefined;
79
80
  if (!source || !runId || !digest || projected === undefined)
80
81
  return { status: discoverRuns(root).length ? "mixed_authority" : "legacy" };
81
- const target = resolve(source),
82
+ const target = resolve(root, source.replaceAll("\\", "/")),
82
83
  rel = relative(resolve(root), target),
83
84
  expected = relative(resolve(root), resolve(runPath(root, runId)));
84
85
  if (rel.startsWith("..") || !rel || rel !== expected || !existsSync(target))
@@ -15,6 +15,7 @@ import { dirname } from "node:path";
15
15
  import { parseRunState } from "./run-state-parser.js";
16
16
 
17
17
  function fsyncDirectory(path) {
18
+ if (process.platform === "win32") return;
18
19
  const descriptor = openSync(path, "r");
19
20
  try {
20
21
  fsyncSync(descriptor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.6.1",
3
+ "version": "0.6.5",
4
4
  "description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
5
5
  "type": "module",
6
6
  "files": [
@@ -25,6 +25,7 @@
25
25
  "test:delivery-path-search-unit": "node ./scripts/delivery-path-search-unit-test.js",
26
26
  "test:delivery-path-search-generator": "node ./scripts/delivery-path-search-generator-test.js",
27
27
  "test:control-state": "node ./scripts/control-state-test.js",
28
+ "test:release-bootstrap": "node ./scripts/release-bootstrap-smoke-test.js",
28
29
  "test:routing": "npm run sync-package-assets && node ./scripts/test-routing.js",
29
30
  "smoke-test": "npm run sync-package-assets && npm run test:control-state && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
30
31
  "prepack": "npm run sync-package-assets"