create-agdf 0.6.4 → 0.6.6
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/bin/create-agdf.js +80 -36
- package/generated/.agdf/control/templates/MASTER_BACKLOG.md +2 -0
- package/generated/.github/skills/agdf-runtime-contract.md +16 -0
- package/generated/.opencode/agdf-runtime-contract.md +16 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -1
- package/generated/plugins/agdf/control/templates/MASTER_BACKLOG.md +2 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -1
- package/generated/plugins/agdf/meta/agdf-runtime-contract.md +16 -0
- package/lib/control-state/legacy-migration.js +3 -2
- package/lib/control-state/run-state-writer.js +1 -0
- package/package.json +1 -1
package/bin/create-agdf.js
CHANGED
|
@@ -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 (
|
|
1346
|
+
if (selectedRunState.resolution_error) {
|
|
1324
1347
|
addFinding(
|
|
1325
1348
|
findings,
|
|
1326
|
-
"
|
|
1327
|
-
"
|
|
1328
|
-
|
|
1349
|
+
"block",
|
|
1350
|
+
selectedRunState.resolution_error.split(":")[0] || "AGDF_ACTIVE_RUN_UNRESOLVED",
|
|
1351
|
+
`Run selection failed: ${selectedRunState.resolution_error}`,
|
|
1329
1352
|
runPath,
|
|
1330
|
-
"
|
|
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
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
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
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
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
|
|
|
@@ -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.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "Codex-first operating system for governed AI-assisted delivery.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Arndt Gold",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"composerIcon": "./assets/agdf-icon.svg",
|
|
33
33
|
"logo": "./assets/agdf-logo.svg",
|
|
34
34
|
"defaultPrompt": [
|
|
35
|
+
"Evaluate whether AGDF is appropriate for this repository and request. Explain its purpose, practical value, governance overhead, and fit for the project's risk level. Recommend the smallest suitable AGDF path before proposing implementation.",
|
|
35
36
|
"Start this request under AGDF governance.",
|
|
36
37
|
"Create durable AGDF control state for this repository.",
|
|
37
38
|
"Close this delivery run with an auditable AGDF report."
|
|
@@ -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.
|
|
4
|
+
"version": "0.6.6",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Codex-first operating system for governed AI-assisted delivery.",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"Write"
|
|
36
36
|
],
|
|
37
37
|
"defaultPrompt": [
|
|
38
|
+
"Evaluate whether AGDF is appropriate for this repository and request. Explain its purpose, practical value, governance overhead, and fit for the project's risk level. Recommend the smallest suitable AGDF path before proposing implementation.",
|
|
38
39
|
"Start this request under AGDF governance.",
|
|
39
40
|
"Create durable AGDF control state for this repository.",
|
|
40
41
|
"Close this delivery run with an auditable AGDF report."
|
|
@@ -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.
|
|
@@ -62,7 +62,8 @@ export function renderLegacyProjection(path, root = process.cwd()) {
|
|
|
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
|
-
|
|
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
69
|
atomicWrite(path, renderLegacyProjection(canonical, resolve(dirname(path), "../..")));
|
|
@@ -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(root, 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))
|
package/package.json
CHANGED