create-agdf 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/bin/create-agdf.js +168 -3
- package/generated/.agdf/control/README.md +2 -0
- package/generated/.github/skills/agdf-gate-check/SKILL.md +13 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -2
- package/generated/plugins/agdf/control/README.md +2 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +2 -2
- package/generated/plugins/agdf/skills/gate-check/SKILL.md +13 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-agdf
|
|
2
2
|
|
|
3
|
-
Bootstrap AGDF repository instructions for one repository.
|
|
3
|
+
Bootstrap AGDF repository instructions and a machine-checkable control loop for one repository.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -10,6 +10,7 @@ npm create agdf@latest copilot
|
|
|
10
10
|
npm create agdf@latest both
|
|
11
11
|
npm create agdf@latest init
|
|
12
12
|
npm create agdf@latest doctor
|
|
13
|
+
npm create agdf@latest gate-check
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
Optional flags:
|
|
@@ -62,6 +63,17 @@ npm create agdf@latest doctor --json
|
|
|
62
63
|
|
|
63
64
|
The doctor reports missing live control files, missing current gate, missing next allowed action, empty evidence, empty backlog pointer, empty source-of-truth registry, duplicate active SoT rows and invalid quality contracts. It exits non-zero only for blocking control failures.
|
|
64
65
|
|
|
66
|
+
Use `gate-check` to derive the next process decision from the doctor result and `AGDF_RUN.md`:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm create agdf@latest gate-check
|
|
70
|
+
npm create agdf@latest gate-check --json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The gate check reports `open | blocked`, the current gate, blocking reason, missing exact approval, allowed outputs, forbidden outputs, next allowed action, evidence references and the embedded doctor report.
|
|
74
|
+
|
|
75
|
+
Together, `init`, `doctor` and `gate-check --json` turn AGDF from an instruction layer into a repository control system: the agent can be guided by rules, and the repository state can be checked before the next governed step.
|
|
76
|
+
|
|
65
77
|
## Single source of truth
|
|
66
78
|
|
|
67
79
|
The repository-facing AGDF sources are maintained in:
|
package/bin/create-agdf.js
CHANGED
|
@@ -11,8 +11,9 @@ const generatedRoot = join(packageRoot, "generated");
|
|
|
11
11
|
const pluginDefinitionPath = join(generatedRoot, "plugins", "agdf", "meta", "agdf-plugin.definition.json");
|
|
12
12
|
const pluginDefinition = JSON.parse(readFileSync(pluginDefinitionPath, "utf8"));
|
|
13
13
|
const pluginInstallCommand = "claude plugin add arndtgold/ai-native-governance-delivery-framework";
|
|
14
|
-
const allowedTargets = new Set(["codex", "copilot", "both", "init", "doctor"]);
|
|
14
|
+
const allowedTargets = new Set(["codex", "copilot", "both", "init", "doctor", "gate-check"]);
|
|
15
15
|
const agdfFragmentPath = "AGENTS.agdf.md";
|
|
16
|
+
const userGateOrder = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
|
|
16
17
|
const codexSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.codex.skillPrefix}${skill.slug}`);
|
|
17
18
|
const copilotSkillNames = pluginDefinition.skillSet.map((skill) => `${pluginDefinition.copilot.skillPrefix}${skill.slug}`);
|
|
18
19
|
const codexPluginFiles = [
|
|
@@ -89,11 +90,12 @@ Usage:
|
|
|
89
90
|
npm create agdf@latest both
|
|
90
91
|
npm create agdf@latest init
|
|
91
92
|
npm create agdf@latest doctor
|
|
93
|
+
npm create agdf@latest gate-check
|
|
92
94
|
|
|
93
95
|
Options:
|
|
94
96
|
--dir <path> Write files into a specific directory
|
|
95
97
|
--force Overwrite existing generated files
|
|
96
|
-
--json Print doctor output as JSON
|
|
98
|
+
--json Print doctor or gate-check output as JSON
|
|
97
99
|
--help Show this help
|
|
98
100
|
`);
|
|
99
101
|
}
|
|
@@ -156,7 +158,7 @@ function parseArgs(argv) {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
if (!target || !allowedTargets.has(target)) {
|
|
159
|
-
console.error("Please choose one target: codex, copilot, both, init or
|
|
161
|
+
console.error("Please choose one target: codex, copilot, both, init, doctor or gate-check.");
|
|
160
162
|
printUsage();
|
|
161
163
|
process.exit(1);
|
|
162
164
|
}
|
|
@@ -517,6 +519,163 @@ function printDoctorReport(report, json) {
|
|
|
517
519
|
}
|
|
518
520
|
}
|
|
519
521
|
|
|
522
|
+
function extractField(content, field) {
|
|
523
|
+
const pattern = new RegExp(`^- ${field}:[^\\S\\r\\n]*(.*)$`, "m");
|
|
524
|
+
return content.match(pattern)?.[1]?.trim() ?? "";
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function cleanStatusCell(value) {
|
|
528
|
+
return value.replace(/^`|`$/g, "").trim();
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function readRunState(targetDir) {
|
|
532
|
+
const runPath = join(".agdf", "control", "AGDF_RUN.md");
|
|
533
|
+
if (!existsSync(join(targetDir, runPath))) {
|
|
534
|
+
return {
|
|
535
|
+
path: runPath,
|
|
536
|
+
content: "",
|
|
537
|
+
current_gate: "",
|
|
538
|
+
next_allowed_action: "",
|
|
539
|
+
approvals: new Map(),
|
|
540
|
+
evidence_refs: [],
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const content = readTargetFile(targetDir, runPath);
|
|
545
|
+
const approvalsSection = content.match(/## Approvals([\s\S]*?)(?:\n## |\n# |$)/)?.[1] ?? "";
|
|
546
|
+
const approvals = new Map();
|
|
547
|
+
for (const cells of tableRows(approvalsSection)) {
|
|
548
|
+
const [gate, status, evidence] = cells;
|
|
549
|
+
if (!userGateOrder.includes(gate)) continue;
|
|
550
|
+
approvals.set(gate, {
|
|
551
|
+
status: cleanStatusCell(status ?? ""),
|
|
552
|
+
evidence: evidence ?? "",
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const evidenceSection = content.match(/## Evidence([\s\S]*?)(?:\n## |\n# |$)/)?.[1] ?? "";
|
|
557
|
+
const evidence_refs = tableRows(evidenceSection)
|
|
558
|
+
.filter((cells) => cells[0] !== "Evidence")
|
|
559
|
+
.filter((cells) => Boolean(cells[0] || cells[1] || cells[2]))
|
|
560
|
+
.map((cells) => ({
|
|
561
|
+
evidence: cells[0] ?? "",
|
|
562
|
+
source: cells[1] ?? "",
|
|
563
|
+
covers: cells[2] ?? "",
|
|
564
|
+
strength: cleanStatusCell(cells[3] ?? ""),
|
|
565
|
+
}));
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
path: runPath,
|
|
569
|
+
content,
|
|
570
|
+
current_gate: extractField(content, "current_gate"),
|
|
571
|
+
next_allowed_action: extractField(content, "next_allowed_action"),
|
|
572
|
+
approvals,
|
|
573
|
+
evidence_refs,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function firstUnapprovedGate(approvals) {
|
|
578
|
+
for (const gate of userGateOrder) {
|
|
579
|
+
const status = approvals.get(gate)?.status ?? "";
|
|
580
|
+
if (status !== "approved" && status !== "not_applicable") return gate;
|
|
581
|
+
}
|
|
582
|
+
return "OR";
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function normalizeCurrentGate(value, fallbackGate) {
|
|
586
|
+
if (isPlaceholderValue(value)) return fallbackGate;
|
|
587
|
+
const normalized = value.replace(/`/g, "").trim();
|
|
588
|
+
return normalized || fallbackGate;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function gateApprovalStatus(runState, gate) {
|
|
592
|
+
if (!userGateOrder.includes(gate)) return "not_applicable";
|
|
593
|
+
return runState.approvals.get(gate)?.status ?? "";
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function evaluateGateCheck(targetDir) {
|
|
597
|
+
const doctorReport = evaluateDoctor(targetDir);
|
|
598
|
+
const runState = readRunState(targetDir);
|
|
599
|
+
const fallbackGate = firstUnapprovedGate(runState.approvals);
|
|
600
|
+
const currentGate = normalizeCurrentGate(runState.current_gate, fallbackGate);
|
|
601
|
+
const currentApprovalStatus = gateApprovalStatus(runState, currentGate);
|
|
602
|
+
const doctorBlocker = doctorReport.findings.find((finding) => finding.severity === "block");
|
|
603
|
+
const doctorRevise = doctorReport.findings.find((finding) => finding.severity === "revise");
|
|
604
|
+
|
|
605
|
+
let status = "open";
|
|
606
|
+
let blockingReason = "none";
|
|
607
|
+
let missingApproval = "none";
|
|
608
|
+
let allowed = [
|
|
609
|
+
"continue with the documented next allowed action",
|
|
610
|
+
"update evidence when new facts are observed",
|
|
611
|
+
"run doctor or gate-check again after control changes",
|
|
612
|
+
];
|
|
613
|
+
let forbidden = [
|
|
614
|
+
"bypass the documented gate state",
|
|
615
|
+
"treat warnings as resolved without evidence",
|
|
616
|
+
];
|
|
617
|
+
let nextAllowedAction = isPlaceholderValue(runState.next_allowed_action)
|
|
618
|
+
? "Continue with the current documented gate only after setting next_allowed_action."
|
|
619
|
+
: runState.next_allowed_action;
|
|
620
|
+
|
|
621
|
+
if (doctorBlocker) {
|
|
622
|
+
status = "blocked";
|
|
623
|
+
blockingReason = doctorBlocker.code;
|
|
624
|
+
allowed = ["repair the AGDF control scaffold", "run doctor again"];
|
|
625
|
+
forbidden = ["continue governed delivery", "create later-gate artefacts", "implement gated work"];
|
|
626
|
+
nextAllowedAction = doctorBlocker.next_step;
|
|
627
|
+
} else if (doctorRevise) {
|
|
628
|
+
status = "blocked";
|
|
629
|
+
blockingReason = doctorRevise.code;
|
|
630
|
+
allowed = ["repair the incomplete control state", "run doctor again"];
|
|
631
|
+
forbidden = ["continue governed delivery", "create later-gate artefacts", "implement gated work"];
|
|
632
|
+
nextAllowedAction = doctorRevise.next_step;
|
|
633
|
+
} else if (userGateOrder.includes(currentGate) && currentApprovalStatus !== "approved" && currentApprovalStatus !== "not_applicable") {
|
|
634
|
+
status = "blocked";
|
|
635
|
+
blockingReason = "missing_exact_approval";
|
|
636
|
+
missingApproval = `Approval: ${currentGate}`;
|
|
637
|
+
allowed = ["clarify the current gate", "record evidence", "write OR-lite status", "request exact approval"];
|
|
638
|
+
forbidden = ["create later-gate artefacts", "implement gated work", "mark QA or UAT as passed"];
|
|
639
|
+
nextAllowedAction = `Request exact approval: Approval: ${currentGate}`;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return {
|
|
643
|
+
schema_version: "1",
|
|
644
|
+
status,
|
|
645
|
+
current_gate: currentGate,
|
|
646
|
+
blocking_reason: blockingReason,
|
|
647
|
+
missing_approval: missingApproval,
|
|
648
|
+
allowed,
|
|
649
|
+
forbidden,
|
|
650
|
+
next_allowed_action: nextAllowedAction,
|
|
651
|
+
doctor_status: doctorReport.status,
|
|
652
|
+
doctor_summary: doctorReport.summary,
|
|
653
|
+
evidence_refs: runState.evidence_refs,
|
|
654
|
+
doctor_report: doctorReport,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function printGateCheckReport(report, json) {
|
|
659
|
+
if (json) {
|
|
660
|
+
console.log(JSON.stringify(report, null, 2));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
console.log(`AGDF gate-check: ${report.status}`);
|
|
665
|
+
console.log(`Current gate: ${report.current_gate}`);
|
|
666
|
+
console.log(`Blocking reason: ${report.blocking_reason}`);
|
|
667
|
+
console.log(`Missing approval: ${report.missing_approval}`);
|
|
668
|
+
console.log(`Doctor: ${report.doctor_status} (${report.doctor_summary.findings} findings)`);
|
|
669
|
+
console.log("");
|
|
670
|
+
console.log("Allowed:");
|
|
671
|
+
for (const item of report.allowed) console.log(`- ${item}`);
|
|
672
|
+
console.log("");
|
|
673
|
+
console.log("Forbidden:");
|
|
674
|
+
for (const item of report.forbidden) console.log(`- ${item}`);
|
|
675
|
+
console.log("");
|
|
676
|
+
console.log(`Next allowed action: ${report.next_allowed_action}`);
|
|
677
|
+
}
|
|
678
|
+
|
|
520
679
|
function main() {
|
|
521
680
|
const options = parseArgs(process.argv.slice(2));
|
|
522
681
|
|
|
@@ -526,6 +685,12 @@ function main() {
|
|
|
526
685
|
process.exit(report.status === "block" ? 2 : 0);
|
|
527
686
|
}
|
|
528
687
|
|
|
688
|
+
if (options.target === "gate-check") {
|
|
689
|
+
const report = evaluateGateCheck(options.dir);
|
|
690
|
+
printGateCheckReport(report, options.json);
|
|
691
|
+
process.exit(report.status === "blocked" ? 2 : 0);
|
|
692
|
+
}
|
|
693
|
+
|
|
529
694
|
const files = generatedFilesForTarget(options.target, options.dir, options.force);
|
|
530
695
|
const wroteAgentsFragment = files.some(file => file.path === agdfFragmentPath);
|
|
531
696
|
|
|
@@ -39,9 +39,11 @@ Then check whether the live state is actionable:
|
|
|
39
39
|
```bash
|
|
40
40
|
npm create agdf@latest doctor
|
|
41
41
|
npm create agdf@latest doctor --json
|
|
42
|
+
npm create agdf@latest gate-check --json
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
`doctor` does not replace agent judgment. It catches basic control failures: missing live files, missing current gate, missing next allowed action, empty evidence, empty backlog pointer, empty source-of-truth registry, duplicate active SoT rows and invalid quality contracts.
|
|
46
|
+
`gate-check` consumes the doctor result and live run state to report whether the next process step is `open` or `blocked`.
|
|
45
47
|
|
|
46
48
|
## Operating Rules
|
|
47
49
|
|
|
@@ -20,6 +20,19 @@ This skill must not create later artefacts such as PRD, SD, TP, CD, CR, QA, or U
|
|
|
20
20
|
## Runtime Contract
|
|
21
21
|
Use `../agdf-runtime-contract.md` for gate terms, closeout discipline, and non-duplication rules.
|
|
22
22
|
|
|
23
|
+
## Machine-Readable Control Path
|
|
24
|
+
|
|
25
|
+
When the target repository contains live AGDF control files, prefer the executable control path before deriving a gate decision manually:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm create agdf@latest doctor --json
|
|
29
|
+
npm create agdf@latest gate-check --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`doctor` checks whether `.agdf/control/` is actionable. `agdf-gate-check` consumes that result and `AGDF_RUN.md` to report the operative process decision: `open | blocked`, current gate, blocking reason, missing approval, allowed outputs, forbidden outputs, next allowed action and evidence references.
|
|
33
|
+
|
|
34
|
+
The CLI report is evidence for this skill, not a second rule system. If the report says `blocked`, do not continue with later-gate artefacts until the reported blocker is resolved.
|
|
35
|
+
|
|
23
36
|
## Rules
|
|
24
37
|
1. Fail closed when a required approval or artefact status is missing.
|
|
25
38
|
2. The earliest blocking gate wins.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Codex-first workflow skills for gated, auditable AI-assisted software delivery.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "AI-native Governance & Delivery Framework",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"interface": {
|
|
16
16
|
"displayName": "AI Governance & Delivery Framework",
|
|
17
17
|
"shortDescription": "Codex-first workflow skills for gated, auditable AI-assisted delivery.",
|
|
18
|
-
"longDescription": "AI Governance & Delivery Framework (AGDF) packages reusable Codex-first skills
|
|
18
|
+
"longDescription": "AI Governance & Delivery Framework (AGDF) packages reusable Codex-first skills, control templates and machine-readable repository checks for gate decisions, Brownfield analysis, task-plan review, solution-integrity review, QA decisions, durable run state and auditable delivery closeout.",
|
|
19
19
|
"developerName": "AI-native Governance & Delivery Framework",
|
|
20
20
|
"category": "Productivity",
|
|
21
21
|
"capabilities": ["Read", "Write"],
|
|
@@ -39,9 +39,11 @@ Then check whether the live state is actionable:
|
|
|
39
39
|
```bash
|
|
40
40
|
npm create agdf@latest doctor
|
|
41
41
|
npm create agdf@latest doctor --json
|
|
42
|
+
npm create agdf@latest gate-check --json
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
`doctor` does not replace agent judgment. It catches basic control failures: missing live files, missing current gate, missing next allowed action, empty evidence, empty backlog pointer, empty source-of-truth registry, duplicate active SoT rows and invalid quality contracts.
|
|
46
|
+
`gate-check` consumes the doctor result and live run state to report whether the next process step is `open` or `blocked`.
|
|
45
47
|
|
|
46
48
|
## Operating Rules
|
|
47
49
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "AI-native Governance & Delivery Framework",
|
|
7
7
|
"description": "Codex-first workflow skills for gated, auditable AI-assisted software delivery.",
|
|
8
8
|
"claudeDescription": "Codex-first workflow skills and control templates for gated, auditable AI-assisted software delivery.",
|
|
9
9
|
"shortDescription": "Codex-first workflow skills for gated, auditable AI-assisted delivery.",
|
|
10
|
-
"longDescription": "AI Governance & Delivery Framework (AGDF) packages reusable Codex-first skills
|
|
10
|
+
"longDescription": "AI Governance & Delivery Framework (AGDF) packages reusable Codex-first skills, control templates and machine-readable repository checks for gate decisions, Brownfield analysis, task-plan review, solution-integrity review, QA decisions, durable run state and auditable delivery closeout.",
|
|
11
11
|
"homepage": "https://agdf.iself.eu",
|
|
12
12
|
"repository": "https://github.com/arndtgold/ai-native-governance-delivery-framework",
|
|
13
13
|
"license": "Apache-2.0",
|
|
@@ -20,6 +20,19 @@ This skill must not create later artefacts such as PRD, SD, TP, CD, CR, QA, or U
|
|
|
20
20
|
## Runtime Contract
|
|
21
21
|
Use `../../meta/agdf-runtime-contract.md` for gate terms, closeout discipline, and non-duplication rules.
|
|
22
22
|
|
|
23
|
+
## Machine-Readable Control Path
|
|
24
|
+
|
|
25
|
+
When the target repository contains live AGDF control files, prefer the executable control path before deriving a gate decision manually:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm create agdf@latest doctor --json
|
|
29
|
+
npm create agdf@latest gate-check --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`doctor` checks whether `.agdf/control/` is actionable. `gate-check` consumes that result and `AGDF_RUN.md` to report the operative process decision: `open | blocked`, current gate, blocking reason, missing approval, allowed outputs, forbidden outputs, next allowed action and evidence references.
|
|
33
|
+
|
|
34
|
+
The CLI report is evidence for this skill, not a second rule system. If the report says `blocked`, do not continue with later-gate artefacts until the reported blocker is resolved.
|
|
35
|
+
|
|
23
36
|
## Rules
|
|
24
37
|
1. Fail closed when a required approval or artefact status is missing.
|
|
25
38
|
2. The earliest blocking gate wins.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agdf",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Bootstrap AGDF repository-local
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Bootstrap AGDF repository-local plugin files, Copilot instructions, skills, control files and machine-readable checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin",
|