azcodr 2.4.0 → 2.6.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/.agents/hooks.json +18 -3
- package/.agents/hooks.json.example +18 -3
- package/.agents/lib/agent-guard-command.js +103 -0
- package/.agents/lib/agent-guard-file.js +77 -0
- package/.agents/lib/agent-guard-tdd.js +77 -0
- package/.agents/lib/agent-guard.js +80 -0
- package/.agents/lib/boundaries.js +158 -0
- package/.agents/scripts/agent_guard.js +35 -3
- package/.agents/scripts/boundary_guard.js +93 -0
- package/.agents/skills/clean-code-refactor/SKILL.md +1 -0
- package/.agents/skills/lets-build/SKILL.md +3 -2
- package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +166 -0
- package/.agents/skills/relentless-questioner/SKILL.md +1 -1
- package/AGENTS.md +3 -3
- package/CONTRIBUTING.md +10 -4
- package/README.md +14 -12
- package/docs/generated-enforcement-analysis.md +162 -0
- package/docs/rules/clean_code.md +3 -2
- package/docs/rules/test_driven_development.md +8 -5
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/scaffold.d.ts.map +1 -1
- package/lib/scaffold.js +4 -1
- package/lib/scaffold.js.map +1 -1
- package/lib/starter-ci.d.ts +29 -0
- package/lib/starter-ci.d.ts.map +1 -0
- package/lib/starter-ci.js +59 -0
- package/lib/starter-ci.js.map +1 -0
- package/memory.md +24 -0
- package/package.json +3 -3
- package/scripts/validate/toolchain.js +60 -0
- package/scripts/validate.js +12 -2
- package/src/index.ts +1 -1
- package/src/scaffold.ts +4 -1
- package/src/starter-ci.ts +61 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Test-Driven Development (London School TDD) & Test Isolation Standards
|
|
2
2
|
|
|
3
|
-
> **Core Mandate:** Drive all features through the non-negotiable 5-Phase Agile Domain Lifecycle (Outside-In Double-Loop TDD, Uncle Bob's 3 Laws), enforcing transactional database rollback per test, zero-sleep determinism, and
|
|
3
|
+
> **Core Mandate:** Drive all features through the non-negotiable 5-Phase Agile Domain Lifecycle (Outside-In Double-Loop TDD, Uncle Bob's 3 Laws), enforcing transactional database rollback per test, zero-sleep determinism, and CI-enforced 100% coverage on all metrics plus mutation floor (assertion-free tests rejected).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ flowchart TD
|
|
|
14
14
|
P2["Phase 2: Tactical Domain Analysis<br/>• Ubiquitous Language & Bounded Contexts<br/>• Aggregate Roots & Business Invariants"]
|
|
15
15
|
P3["Phase 3: Outer Acceptance Test (RED)<br/>• Failing UI component or API route test<br/>• Verifies failure for expected reason"]
|
|
16
16
|
P4["Phase 4: Inner TDD & Collaborator Discovery (RED-GREEN-REFACTOR)<br/>• Discovers Use Cases & Ports<br/>• Nano-cycles with Uncle Bob's 3 Laws"]
|
|
17
|
-
P5["Phase 5: Outer Verification & Proof (GREEN)<br/>• Outer test passes with zero regressions<br/>• 100
|
|
17
|
+
P5["Phase 5: Outer Verification & Proof (GREEN)<br/>• Outer test passes with zero regressions<br/>• 100% coverage on all metrics + mutation gate & boundary smoke verification"]
|
|
18
18
|
|
|
19
19
|
P1 --> P2 --> P3 --> P4 --> P5
|
|
20
20
|
```
|
|
@@ -125,10 +125,13 @@ sequenceDiagram
|
|
|
125
125
|
|
|
126
126
|
---
|
|
127
127
|
|
|
128
|
-
## 7. Mandatory 100
|
|
128
|
+
## 7. Mandatory 100% Coverage on All Metrics + Mutation Floor (No Assertion-Free Tests)
|
|
129
129
|
|
|
130
|
-
- **Strict
|
|
131
|
-
- **
|
|
130
|
+
- **Strict 100% thresholds:** CI fails unless line, function, branch, AND statement coverage are all 100% (`jest.config.js`: lines 100 / functions 100 / branches 100 / statements 100). Generated projects must hold the same 100% bar in their own stack via the per-language gates in `docs/rules/clean_code.md`. Lowering any metric requires an ADR.
|
|
131
|
+
- **Mutation floor on guards:** line coverage alone proves little. Behavioral guards (`agent-guard-*`, `boundaries.ts`, protected-target checks) must hold a 100% mutant-kill gate (`npm run test:mutation`, `benchmark/mutation-test.js`). A green suite that lets a `blocked: true → false` or `return cycles → return []` mutant survive is a failure, even at 100% lines.
|
|
132
|
+
- **Assertion-density check:** agents asked to hit a line number write assertion-free tests to cover lines. Reject that explicitly: every new behavioral test must contain at least one behavior-asserting expectation (no `expect(true).toBe(true)`, no tests without assertions). Prefer `benchmark/evaluate.js --strict-tests` style checks (assertions per test ≥ 1, critical paths ≥ 2) over raising the line percentage.
|
|
133
|
+
- **What this repo enforces vs what users get:** this repo's exact thresholds live in `jest.config.js` (100% lines, branches, functions, statements) and are locked by `tests/coverage-config.test.ts`. Generated polyglot projects get the equivalent per-language fitness gates in `docs/rules/clean_code.md` (ESLint / ruff / clippy / golangci-lint / Checkstyle / Roslyn) at the same 100% bar — the tooling differs by stack, the bar must not.
|
|
134
|
+
- **Exhaustive status codes & error branches:** explicitly test all HTTP/gRPC response codes:
|
|
132
135
|
- Success: `200 OK`, `201 Created`, `204 No Content`
|
|
133
136
|
- Client Errors: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `409 Conflict`, `422 Unprocessable Entity`, `429 Too Many Requests`
|
|
134
137
|
- Server Failures: `500 Internal Server Error`, `503 Service Unavailable`
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @azcodr/azcodr
|
|
3
|
-
*
|
|
3
|
+
* Architecture governance toolkit, with an optional starter.
|
|
4
4
|
*
|
|
5
5
|
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
6
|
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @azcodr/azcodr
|
|
3
|
-
*
|
|
3
|
+
* Architecture governance toolkit, with an optional starter.
|
|
4
4
|
*
|
|
5
5
|
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
6
|
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
package/lib/scaffold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAW3C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmCD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,IAAI,CAW3F;AA6FD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,WAAW,GAAE,MAAyB,EACtC,OAAO,GAAE,mBAAwB,GAChC,MAAM,EAAE,CAeV;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,CActE;AAED,OAAO,EACL,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAChE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAC3D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAC5D,CAAC;AAEF,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AAE5F,wBAKE"}
|
package/lib/scaffold.js
CHANGED
|
@@ -7,6 +7,7 @@ import { assertInside, isProtectedTarget, getTemplateDir } from './guards.js';
|
|
|
7
7
|
import { ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile } from './links.js';
|
|
8
8
|
import { makeScriptsExecutable } from './permissions.js';
|
|
9
9
|
import { isInsideGitWorkTree, initGit } from './repo.js';
|
|
10
|
+
import { writeStarterCi } from './starter-ci.js';
|
|
10
11
|
export { getTemplateDir };
|
|
11
12
|
/**
|
|
12
13
|
* Canonical list of template files and directories copied into a new workspace.
|
|
@@ -126,11 +127,12 @@ function starterPackageJson(resolvedTarget) {
|
|
|
126
127
|
version: '0.1.0',
|
|
127
128
|
type: 'module',
|
|
128
129
|
private: true,
|
|
129
|
-
description: 'Scaffolded with azcodr
|
|
130
|
+
description: 'Scaffolded with the azcodr architecture governance toolkit',
|
|
130
131
|
scripts: {
|
|
131
132
|
test: 'node --test',
|
|
132
133
|
'test:coverage': 'jest --coverage',
|
|
133
134
|
lint: 'echo "No linter configured yet. Run /lets-build to configure toolchain."',
|
|
135
|
+
boundaries: 'node .agents/scripts/boundary_guard.js',
|
|
134
136
|
validate: 'node scripts/validate-cli.js'
|
|
135
137
|
}
|
|
136
138
|
};
|
|
@@ -173,6 +175,7 @@ export function copyTemplate(targetDir, templateDir = getTemplateDir(), options
|
|
|
173
175
|
actions.push(...ensureHarnessParity(resolvedTarget, dryRun));
|
|
174
176
|
actions.push(...ensureCopilotParity(resolvedTarget, dryRun));
|
|
175
177
|
actions.push(...ensureStarterPackageJson(resolvedTarget, dryRun));
|
|
178
|
+
actions.push(...writeStarterCi(resolvedTarget, dryRun));
|
|
176
179
|
const inspectDir = dryRun ? resolvedTemplate : resolvedTarget;
|
|
177
180
|
actions.push(...chmodTemplateScripts(inspectDir, dryRun));
|
|
178
181
|
return actions;
|
package/lib/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,WAAW;IACX,WAAW;IACX,WAAW;IACX,MAAM;IACN,SAAS;IACT,SAAS;IACT,SAAS;IACT,YAAY;IACZ,eAAe;IACf,SAAS;CACV,CAAC;AA2CF,SAAS,kBAAkB,CAAC,cAAsB,EAAE,gBAAwB;IAC1E,IAAI,cAAc,KAAK,gBAAgB;QAAE,OAAO;IAChD,MAAM,IAAI,aAAa,CACrB,sBAAsB,EACtB,GAAG,WAAW,CAAC,oBAAoB,KAAK,cAAc,EAAE,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,cAAsB,EACtB,WAAmB,EACnB,cAAuB;IAEvB,IAAI,cAAc;QAAE,OAAO;IAC3B,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,CAAC;QAAE,OAAO;IAChE,MAAM,IAAI,aAAa,CACrB,uBAAuB,EACvB,GAAG,WAAW,CAAC,qBAAqB,KAAK,cAAc,IAAI;QAC3D,oGAAoG,CACrG,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,cAAsB,EAAE,KAAc;IAClE,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK;QAAE,OAAO;IAC1C,MAAM,IAAI,aAAa,CACrB,oBAAoB,EACpB,GAAG,WAAW,CAAC,kBAAkB,KAAK,OAAO,CAAC,MAAM,iBAAiB,cAAc,KAAK;QACxF,0CAA0C,CAC3C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,UAAiC,EAAE;IACnF,MAAM,EAAE,WAAW,GAAG,cAAc,EAAE,EAAE,KAAK,GAAG,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,cAAc,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC1G,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD,kBAAkB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACrD,qBAAqB,CAAC,cAAc,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IACnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM;YAAE,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IACD,oBAAoB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,mBAAmB,CAAC,gBAAwB,EAAE,IAAY;IACjE,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;QACtE,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;QAChE,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,OAAO,GAAG,aAAa,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,cAAsB,EAAE,gBAAwB,EAAE,MAAe;IAC1F,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QACjD,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACxC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,OAAO,QAAQ,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM;YAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,cAAsB,EAAE,MAAe;IAClE,MAAM,KAAK,GAAgC;QACzC,CAAC,WAAW,EAAE,WAAW,CAAC;QAC1B,CAAC,WAAW,EAAE,WAAW,CAAC;QAC1B,CAAC,WAAW,EAAE,WAAW,CAAC;QAC1B,CAAC,cAAc,EAAE,WAAW,CAAC;QAC7B,CAAC,gBAAgB,EAAE,WAAW,CAAC;KAChC,CAAC;IACF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,KAAK,EAAE,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,OAAO,cAAc,EAAE,CAAC,CAAC;QAC1D,aAAa,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,cAAsB,EAAE,MAAe;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvF,sBAAsB,CAAC;QACrB,SAAS,EAAE,SAAS;QACpB,QAAQ,EAAE,yBAAyB;QACnC,cAAc,EAAE,cAAc;QAC9B,MAAM;KACP,CAAC,CAAC;IACH,OAAO,CAAC,0DAA0D,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,kBAAkB,CAAC,cAAsB;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,YAAY,CAAC;IAClE,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,4DAA4D;QACzE,OAAO,EAAE;YACP,IAAI,EAAE,aAAa;YACnB,eAAe,EAAE,iBAAiB;YAClC,IAAI,EAAE,0EAA0E;YAChF,UAAU,EAAE,wCAAwC;YACpD,QAAQ,EAAE,8BAA8B;SACzC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,cAAsB,EAAE,MAAe;IACvE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAC9D,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1C,IAAI,MAAM;QAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,kBAAkB,CAAC,cAAc,CAAC,CAAC;IACtD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IACnF,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,oBAAoB,CAAC,UAAkB,EAAE,MAAe;IAC/D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,cAAsB,cAAc,EAAE,EACtC,UAA+B,EAAE;IAEjC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9C,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,cAAc,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC5E,OAAO,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,UAA2B,EAAE;IACpD,MAAM,EACJ,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,EACzB,KAAK,GAAG,KAAK,EACb,KAAK,GAAG,KAAK,EACb,WAAW,GAAG,cAAc,EAAE,EAC9B,MAAM,GAAG,KAAK,EACf,GAAG,OAAO,CAAC;IACZ,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,cAAc,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,YAAY,CAAC,cAAc,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAClE,IAAI,cAAc;QAAE,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACvF,CAAC;AAED,OAAO,EACL,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAChE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAC3D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAC5D,CAAC;AAIF,eAAe;IACb,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa;IACrD,sBAAsB,EAAE,yBAAyB,EAAE,qBAAqB;IACxE,mBAAmB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM;IACpD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB;CAC5E,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* azcodr's own release/CI workflows. They target this repository's scripts
|
|
3
|
+
* (build, mutation, benchmark) and must never run inside a scaffolded project;
|
|
4
|
+
* `writeStarterCi` removes them from the target and installs a starter CI.
|
|
5
|
+
*/
|
|
6
|
+
export declare const AZCODR_DEV_WORKFLOWS: readonly string[];
|
|
7
|
+
/**
|
|
8
|
+
* Starter governance CI written into every scaffolded project. It depends only
|
|
9
|
+
* on Node + the vendored guard engine, so it is green out of the box (unlike
|
|
10
|
+
* azcodr's own dev workflows, which call scripts a fresh project does not have).
|
|
11
|
+
*/
|
|
12
|
+
export declare const STARTER_CI = "name: ci\n\non:\n push:\n branches: [main]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n governance:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 22.x\n - name: Architectural boundary & cycle check\n run: node .agents/scripts/boundary_guard.js\n - name: Governance validation\n run: node scripts/validate-cli.js\n";
|
|
13
|
+
/**
|
|
14
|
+
* Writes the starter governance CI into a scaffold target and removes azcodr's
|
|
15
|
+
* own dev workflows from it, so a generated project's CI is green out of the
|
|
16
|
+
* box instead of calling scripts a fresh project does not have.
|
|
17
|
+
*
|
|
18
|
+
* @param resolvedTarget - Absolute path to the scaffold target directory.
|
|
19
|
+
* @param dryRun - Record the action without touching the filesystem.
|
|
20
|
+
* @returns Recorded scaffolding action descriptions.
|
|
21
|
+
*/
|
|
22
|
+
export declare function writeStarterCi(resolvedTarget: string, dryRun: boolean): string[];
|
|
23
|
+
declare const _default: {
|
|
24
|
+
STARTER_CI: string;
|
|
25
|
+
AZCODR_DEV_WORKFLOWS: readonly string[];
|
|
26
|
+
writeStarterCi: typeof writeStarterCi;
|
|
27
|
+
};
|
|
28
|
+
export default _default;
|
|
29
|
+
//# sourceMappingURL=starter-ci.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starter-ci.d.ts","sourceRoot":"","sources":["../src/starter-ci.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAA8B,CAAC;AAEjF;;;;GAIG;AACH,eAAO,MAAM,UAAU,sdAsBtB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAUhF;;;;;;AAED,wBAAoE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* azcodr's own release/CI workflows. They target this repository's scripts
|
|
5
|
+
* (build, mutation, benchmark) and must never run inside a scaffolded project;
|
|
6
|
+
* `writeStarterCi` removes them from the target and installs a starter CI.
|
|
7
|
+
*/
|
|
8
|
+
export const AZCODR_DEV_WORKFLOWS = ['ci.yml', 'publish.yml'];
|
|
9
|
+
/**
|
|
10
|
+
* Starter governance CI written into every scaffolded project. It depends only
|
|
11
|
+
* on Node + the vendored guard engine, so it is green out of the box (unlike
|
|
12
|
+
* azcodr's own dev workflows, which call scripts a fresh project does not have).
|
|
13
|
+
*/
|
|
14
|
+
export const STARTER_CI = `name: ci
|
|
15
|
+
|
|
16
|
+
on:
|
|
17
|
+
push:
|
|
18
|
+
branches: [main]
|
|
19
|
+
pull_request:
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
governance:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: 22.x
|
|
32
|
+
- name: Architectural boundary & cycle check
|
|
33
|
+
run: node .agents/scripts/boundary_guard.js
|
|
34
|
+
- name: Governance validation
|
|
35
|
+
run: node scripts/validate-cli.js
|
|
36
|
+
`;
|
|
37
|
+
/**
|
|
38
|
+
* Writes the starter governance CI into a scaffold target and removes azcodr's
|
|
39
|
+
* own dev workflows from it, so a generated project's CI is green out of the
|
|
40
|
+
* box instead of calling scripts a fresh project does not have.
|
|
41
|
+
*
|
|
42
|
+
* @param resolvedTarget - Absolute path to the scaffold target directory.
|
|
43
|
+
* @param dryRun - Record the action without touching the filesystem.
|
|
44
|
+
* @returns Recorded scaffolding action descriptions.
|
|
45
|
+
*/
|
|
46
|
+
export function writeStarterCi(resolvedTarget, dryRun) {
|
|
47
|
+
const actions = ['generate: .github/workflows/ci.yml (starter governance CI)'];
|
|
48
|
+
if (dryRun)
|
|
49
|
+
return actions;
|
|
50
|
+
const workflowsDir = path.join(resolvedTarget, '.github', 'workflows');
|
|
51
|
+
fs.mkdirSync(workflowsDir, { recursive: true });
|
|
52
|
+
for (const name of AZCODR_DEV_WORKFLOWS) {
|
|
53
|
+
fs.rmSync(path.join(workflowsDir, name), { force: true });
|
|
54
|
+
}
|
|
55
|
+
fs.writeFileSync(path.join(workflowsDir, 'ci.yml'), STARTER_CI, 'utf-8');
|
|
56
|
+
return actions;
|
|
57
|
+
}
|
|
58
|
+
export default { STARTER_CI, AZCODR_DEV_WORKFLOWS, writeStarterCi };
|
|
59
|
+
//# sourceMappingURL=starter-ci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starter-ci.js","sourceRoot":"","sources":["../src/starter-ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBzB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,cAAsB,EAAE,MAAe;IACpE,MAAM,OAAO,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC/E,IAAI,MAAM;QAAE,OAAO,OAAO,CAAC;IAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACvE,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;QACxC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,eAAe,EAAE,UAAU,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC"}
|
package/memory.md
CHANGED
|
@@ -35,6 +35,9 @@
|
|
|
35
35
|
| [ADR-016](./memory.md#adr-016-standalone-architectural-validator-agent-runtime-hooks-boundary-engine--empirical-benchmark) | Standalone Architectural Validator, Agent Runtime Hooks, Boundary Engine & Empirical Benchmark | 2026-10-08 | ACCEPTED | [`agentic_configuration.md`](./docs/rules/agentic_configuration.md) |
|
|
36
36
|
| [ADR-017](./memory.md#adr-017-continuous-mutation-and-benchmark-ci-gates-oss-governance-and-reference-example) | Continuous Mutation & Benchmark CI Gates, OSS Governance & Reference Example | 2026-10-08 | ACCEPTED | [`devops_ci_cd.md`](./docs/rules/devops_ci_cd.md) |
|
|
37
37
|
| [ADR-018](./memory.md#adr-018-first-class-architectural-boundary-and-cycle-inspection-cli-subcommand) | First-Class Architectural Boundary and Cycle Inspection CLI Subcommand | 2026-10-08 | ACCEPTED | [`clean_code.md`](./docs/rules/clean_code.md) |
|
|
38
|
+
| [ADR-019](./memory.md#adr-019-honest-claims-100-percent-all-metrics-gate-and-benchmark-limits-on-the-record) | Honest claims, 100% all-metrics gate, and benchmark limits on the record | 2026-10-08 | ACCEPTED | [`test_driven_development.md`](./docs/rules/test_driven_development.md) |
|
|
39
|
+
| [ADR-020](./memory.md#adr-020-generated-projects-get-deterministic-enforcement) | Generated projects get deterministic enforcement | 2026-10-08 | ACCEPTED | [`clean_code.md`](./docs/rules/clean_code.md) |
|
|
40
|
+
| [ADR-021](./memory.md#adr-021-default-on-guards-boundaries-and-starter-ci-ship-in-the-scaffold) | Default-on guards; boundaries & starter CI ship in the scaffold | 2026-10-09 | ACCEPTED | [`clean_code.md`](./docs/rules/clean_code.md) |
|
|
38
41
|
|
|
39
42
|
---
|
|
40
43
|
|
|
@@ -96,6 +99,20 @@
|
|
|
96
99
|
- **Consequences:** ✅ Every PR and push automatically verifies 100% mutation resistance and benchmark assertions. ✅ Full open-source governance compliance achieved (`SECURITY.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`). ✅ Concrete, working reference example proves downstream architectural boundaries and Clean Code limits. ✅ 100.00% lines, functions, statements, and branches coverage maintained across all 40 test suites and 489 tests.
|
|
97
100
|
- **Enforced In:** `.github/workflows/ci.yml`, `benchmark/mutation-test.js`, `CODE_OF_CONDUCT.md`, `examples/clean-architecture-todo/`, `tests/example-project.test.ts`, `README.md`, `package.json`
|
|
98
101
|
|
|
102
|
+
#### ADR-020: Generated Projects Get Deterministic Enforcement
|
|
103
|
+
- **Date:** 2026-10-08 | **Status:** ACCEPTED
|
|
104
|
+
- **Context:** The generated-enforcement analysis (`docs/generated-enforcement-analysis.md`) proved three defects by execution: (1) zero deterministic linter configs in any generated project (starter `lint` is an echo placeholder), (2) LANGUAGE recorded but never generative, (3) the shipped `agent_guard.js` crashed on its missing `../../lib` engine and its catch-all `exit(0)` silently allowed everything — including `rm -rf /` — in scaffolded projects.
|
|
105
|
+
- **Decision:** (1) Vendor the closed guard-engine set (`agent-guard{,-command,-file,-tdd}.js`) into `.agents/lib/` (byte-locked to `lib/` output by test; re-copy after every build per `CONTRIBUTING.md`); the hook resolves vendored-first, repo-layout second, `AZCODR_GUARD_ENGINE` override first. (2) Fail CLOSED (exit 2, naming every path tried) only when the engine itself cannot load — a broken install, not an ambiguous input; unparseable tool payloads still fail open inside `inspectPreTool` per ADR-005. (3) `bootstrap_workspace.sh` emits the pinned per-language gate config (11 profiles; `generic` emits none; create-if-absent so re-runs never clobber); build manifests stay agent-authored (naming decisions), and the agent installs the tool plus proves the gate with a live block in Phase 5. (4) `hooks.json` (+`.example`) wires an `architectural-guard` PreToolUse entry, disabled by default like all hooks — auto-enabling Stop/lint hooks in a dependency-less fresh scaffold would brick agent loops. (5) New validator phase 7 checks gate-config presence from `.azcodr/workspace-profile.env`, skipping cleanly without a profile (this repo unaffected). (6) Benchmark Arm D (`runArmD` + `auditScaffoldEnforcement`) scores a real scaffold before/after bootstrap; agent-layer state (tool installed, lint wired, hooks on) is reported, never gating.
|
|
106
|
+
- **Consequences:** ✅ Same `rm -rf /` payload now BLOCKED from vendored layout; missing engine exits 2 instead of allowing. ✅ Every recorded language produces its gate config; `validate` fails when one is deleted. ✅ 100% coverage holds on the new `scripts/validate/toolchain.js`. ⚠️ Hooks still require harness opt-in; tool installation still requires network at agent time — both recorded openly in `benchmark/RESULTS.md` §5–8.
|
|
107
|
+
- **Enforced In:** `.agents/lib/`, `.agents/scripts/agent_guard.js`, `.agents/hooks.json`, `.agents/skills/lets-build/scripts/bootstrap_workspace.sh`, `scripts/validate/toolchain.js`, `benchmark/evaluate.js`, `benchmark/run-benchmark.js`, `tests/agent-guard.test.ts`, `tests/bootstrap-toolchain.test.ts`, `tests/validate-toolchain.test.ts`, `tests/benchmark.test.ts`
|
|
108
|
+
|
|
109
|
+
#### ADR-019: Honest Claims, 100% All-Metrics Gate, and Benchmark Limits on the Record
|
|
110
|
+
- **Date:** 2026-10-08 | **Status:** ACCEPTED
|
|
111
|
+
- **Context:** An outside consolidated review found the engineering real but several claims ahead of evidence: "Enterprise starter" positioning vs a governance toolkit, coverage badges without a linked report, and a benchmark that proved drift reduction on synthetic fixtures while reading as a live-agent trial. Separately, the Jest gate enforced 100% lines but only 97% functions / 98% branches even though actual coverage measured 100/100/100/100.
|
|
112
|
+
- **Decision:** (1) Reposition wording to "Architecture governance toolkit, with an optional starter" (`package.json`, `jsr.json`, `AGENTS.md`, `README.md`, `src/index.ts`). (2) Raise the Jest gate to 100% lines, functions, branches, AND statements, locked by `tests/coverage-config.test.ts`; badges link to the CI workflow and the `coverage-report` artifact; docs keep the 100% bar AND the mutation floor plus assertion-density rejection so the number cannot be gamed with assertion-free tests. (3) Harden the benchmark honestly instead of inflating it: `evaluate.js` adds a test-quality proxy and marks cost metrics as manual-only, `run-benchmark.js` writes timestamped JSON transcripts to `benchmark/results/` and prints limitations, `RESULTS.md` gains "Where Azcodr Loses" and "Threats to validity" sections.
|
|
113
|
+
- **Consequences:** ✅ Claims match evidence; the gate is stricter than reality required (no new tests needed — 503 already pass at 100%). ✅ Every benchmark citation now ships with a transcript and a limits section. ⚠️ Synthetic single-run limits remain (no multi-model variance, no token/review-minute measurement) — recorded openly rather than fixed.
|
|
114
|
+
- **Enforced In:** `jest.config.js`, `tests/coverage-config.test.ts`, `benchmark/evaluate.js`, `benchmark/run-benchmark.js`, `benchmark/RESULTS.md`, `README.md`, `CONTRIBUTING.md`, `docs/rules/test_driven_development.md`
|
|
115
|
+
|
|
99
116
|
#### ADR-018: First-Class Architectural Boundary and Cycle Inspection CLI Subcommand
|
|
100
117
|
- **Date:** 2026-10-08 | **Status:** ACCEPTED
|
|
101
118
|
- **Context:** Following the implementation of the zero-dependency boundary and cycle engine (`src/boundaries.ts`, ADR-016), inspecting dependency cycles and Clean Architecture layer breaches required either running the empirical benchmark or importing the internal TypeScript engine programmatically. Users and CI pipelines lacked a direct, dedicated CLI entry point (`npx azcodr boundaries [dir]`) to run boundary and circular dependency inspections as a standalone architectural linter.
|
|
@@ -117,6 +134,13 @@
|
|
|
117
134
|
- **Consequences:** ✅ The catastrophic `--force` paths are closed, locked by `tests/protected-target.test.js` (14 tests, including symlink-alias and fault-injection cases for the two defensive catches). ✅ Only the exact protected directories are blocked: `~/my-project` and any normal subdirectory still scaffold. ✅ New stable error code follows the existing contract (branch on `code`, never message). ⚠️ A user who genuinely wants a project AT `~` must pick a subdirectory; that friction is the point.
|
|
118
135
|
- **Enforced In:** `lib/scaffold.js` (`isProtectedTarget`, `validateTarget`), `bin/azcodr.js` (fail-fast), `lib/index.d.ts`, `tests/protected-target.test.js`, `tests/error-codes.test.js`, `README.md` (security notes)
|
|
119
136
|
|
|
137
|
+
#### ADR-021: Default-On Guards; Boundaries & Starter CI Ship in the Scaffold
|
|
138
|
+
- **Date:** 2026-10-09 | **Status:** ACCEPTED
|
|
139
|
+
- **Context:** The 2026-10-08 consolidated external review left three open severity items: (1) the benchmark read as a live-agent trial while its fixtures were synthetic ("100% drift elimination" over fixtures no agent produced); (2) "your agent cannot skip" was false because every shipped hook in `.agents/hooks.json` was `enabled: false`; (3) the boundary engine — the component that stopped the cycle and the layer breach in the results — was not wired into generated projects or their CI. A further finding from the review's follow-up audit: scaffolded projects inherited azcodr's own `ci.yml`/`publish.yml`, which call scripts (build, mutation, benchmark) a fresh project does not have, so generated CI failed on every push out of the box.
|
|
140
|
+
- **Decision:** (1) Retitle the benchmark as detector validation on synthetic fixtures, pre-register the real-agent trial in `benchmark/REAL-AGENT-RUNBOOK.md` with a result template, and stop narrating "the agent" in `benchmark/RESULTS.md`. (2) Ship all four hooks with `enabled: true` in `.agents/hooks.json` (+`.example`), amending ADR-020 — default-off contradicts the tagline; the cost that lint/stop hooks can interrupt a bare scaffold is accepted and recorded. (3) Vendor `lib/boundaries.js` into `.agents/lib/boundaries.js` (byte-locked by test), add a vendored-first runner `.agents/scripts/boundary_guard.js` (exit 0/1 verdict, exit 2 on missing engine), point the starter `package.json` `boundaries` script at it, and make `bootstrap_workspace.sh`'s smoke test execute it. (4) The scaffolder writes a starter `.github/workflows/ci.yml` (boundary guard + `validate-cli.js`; Node only) and removes azcodr's dev-only workflows from the target, so a scaffolded repo's CI is green out of the box. (5) Remove the personal author email from `package.json` (role-scoped `+security`/`+conduct` addresses stay: they are functional routing, not identity).
|
|
141
|
+
- **Consequences:** ✅ Enforcement is on by default where the harness loads the file; boundary checks run in generated CI. ✅ Generated CI no longer fails because of azcodr's own scripts. ✅ The benchmark headline no longer overclaims. ⚠️ Default-on hooks can interrupt a harnessed session in a bare scaffold; ⚠️ live-agent drift-reduction evidence is still unmeasured; ⚠️ azcodr's dev workflows no longer propagate into user projects.
|
|
142
|
+
- **Enforced In:** `.agents/hooks.json`, `.agents/hooks.json.example`, `.agents/scripts/boundary_guard.js`, `.agents/lib/boundaries.js`, `src/scaffold.ts`, `src/starter-ci.ts`, `.agents/skills/lets-build/scripts/bootstrap_workspace.sh`, `benchmark/RESULTS.md`, `benchmark/REAL-AGENT-RUNBOOK.md`, `package.json`, `tests/boundary-guard.test.ts`, `tests/scaffold-ci.test.ts`, `tests/hooks-default.test.ts`
|
|
143
|
+
|
|
120
144
|
#### ADR-009: memory.md Is Append-Only; the Scaffolder Never Rewrites the Ledger
|
|
121
145
|
- **Date:** 2026-10-07 | **Status:** ACCEPTED
|
|
122
146
|
- **Context:** `.agents/skills/lets-build/scripts/bootstrap_workspace.sh` overwrote `memory.md` with a heredoc whenever the file contained any ADR heading that was not the untouched "No decisions recorded yet" placeholder. Reproduced directly: a project whose ADR read "we will never drop SQLite support" was silently replaced with an empty template after one `/lets-build` run — no error, no backup. It also fired on *high* numbering, so a mature project's ledger was equally destroyed. The intent was to strip template ADRs leaked from this repo; the trigger was the presence of real ones. ADRs are immutable history by rule (`docs/rules/agentic_configuration.md`), so a scaffolder rewriting them was a category error. Two further determinism defects in the same script: Topologies D (Canvas Game) and F (Systems Library) were documented in `SKILL.md` but had no `case` arm, so they fell through to a generic tree and **exited 0** — a wrong-but-successful scaffold the agent would report as done; and the `$LANGUAGE` argument was echoed and never used, so every language produced an identical tree while the skill claimed determinism.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azcodr",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.6.0",
|
|
4
|
+
"description": "Architecture governance toolkit, with an optional starter (early release)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"azcodr": "bin/azcodr.js"
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"agents",
|
|
45
45
|
"npx"
|
|
46
46
|
],
|
|
47
|
-
"author": "Subodh Khanal
|
|
47
|
+
"author": "Subodh Khanal",
|
|
48
48
|
"license": "MIT",
|
|
49
49
|
"repository": {
|
|
50
50
|
"type": "git",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const TOOLCHAIN_FILES = {
|
|
5
|
+
typescript: ['eslint.config.js'],
|
|
6
|
+
javascript: ['eslint.config.js'],
|
|
7
|
+
deno: ['eslint.config.js'],
|
|
8
|
+
bun: ['eslint.config.js'],
|
|
9
|
+
python: ['ruff.toml'],
|
|
10
|
+
rust: ['clippy.toml'],
|
|
11
|
+
go: ['.golangci.yml'],
|
|
12
|
+
java: ['checkstyle.xml'],
|
|
13
|
+
csharp: ['.editorconfig'],
|
|
14
|
+
cpp: ['.clang-tidy'],
|
|
15
|
+
c: ['.clang-tidy'],
|
|
16
|
+
generic: []
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function readProfileLanguage(workspaceRoot) {
|
|
20
|
+
const profile = path.join(workspaceRoot, '.azcodr', 'workspace-profile.env');
|
|
21
|
+
if (!fs.existsSync(profile)) return null;
|
|
22
|
+
const match = /^language=(.+)$/m.exec(fs.readFileSync(profile, 'utf-8'));
|
|
23
|
+
return match ? match[1].trim() : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function expectedToolchainFiles(language) {
|
|
27
|
+
if (!language) return [];
|
|
28
|
+
return TOOLCHAIN_FILES[language] || [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function reportMissing(ctx, language, expected) {
|
|
32
|
+
let missing = 0;
|
|
33
|
+
for (const name of expected) {
|
|
34
|
+
if (!fs.existsSync(path.join(ctx.workspaceRoot, name))) {
|
|
35
|
+
ctx.fail(`Missing toolchain gate '${name}' for language '${language}'; re-run bootstrap or restore the config.`);
|
|
36
|
+
missing += 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return missing;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function phaseToolchain(ctx) {
|
|
43
|
+
ctx.log('');
|
|
44
|
+
ctx.heading('7. Checking Toolchain Enforcement...');
|
|
45
|
+
const language = readProfileLanguage(ctx.workspaceRoot);
|
|
46
|
+
if (language === null) {
|
|
47
|
+
ctx.pass('No workspace profile; toolchain check skipped.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const expected = expectedToolchainFiles(language);
|
|
51
|
+
if (expected.length === 0) {
|
|
52
|
+
ctx.pass(`Language '${language}' declares no toolchain configs; nothing to enforce.`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (reportMissing(ctx, language, expected) === 0) {
|
|
56
|
+
ctx.pass(`Toolchain gates present for language '${language}' (${expected.join(', ')}).`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default { TOOLCHAIN_FILES, readProfileLanguage, expectedToolchainFiles, phaseToolchain };
|
package/scripts/validate.js
CHANGED
|
@@ -11,6 +11,7 @@ import { phaseRootConfig } from './validate/root.js';
|
|
|
11
11
|
import { phaseRules } from './validate/rules.js';
|
|
12
12
|
import { phaseSkills } from './validate/skills.js';
|
|
13
13
|
import { phaseLinks } from './validate/links.js';
|
|
14
|
+
import { phaseToolchain, readProfileLanguage, expectedToolchainFiles, TOOLCHAIN_FILES } from './validate/toolchain.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* NOTE: this module is a library. It never self-executes, so importing it from
|
|
@@ -105,6 +106,7 @@ function runValidation(workspaceRoot, reporter = createReporter()) {
|
|
|
105
106
|
phaseLinks(ctx);
|
|
106
107
|
phaseMemory(ctx);
|
|
107
108
|
phaseLedger(ctx);
|
|
109
|
+
phaseToolchain(ctx);
|
|
108
110
|
reportSummary(counts, reporter);
|
|
109
111
|
return {
|
|
110
112
|
errors: counts.errors,
|
|
@@ -138,7 +140,11 @@ export {
|
|
|
138
140
|
createLowercaseParityLink,
|
|
139
141
|
stripHtmlComments,
|
|
140
142
|
stripFencedCode,
|
|
141
|
-
walkMarkdown
|
|
143
|
+
walkMarkdown,
|
|
144
|
+
phaseToolchain,
|
|
145
|
+
readProfileLanguage,
|
|
146
|
+
expectedToolchainFiles,
|
|
147
|
+
TOOLCHAIN_FILES
|
|
142
148
|
};
|
|
143
149
|
|
|
144
150
|
export default {
|
|
@@ -154,5 +160,9 @@ export default {
|
|
|
154
160
|
createLowercaseParityLink,
|
|
155
161
|
stripHtmlComments,
|
|
156
162
|
stripFencedCode,
|
|
157
|
-
walkMarkdown
|
|
163
|
+
walkMarkdown,
|
|
164
|
+
phaseToolchain,
|
|
165
|
+
readProfileLanguage,
|
|
166
|
+
expectedToolchainFiles,
|
|
167
|
+
TOOLCHAIN_FILES
|
|
158
168
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @azcodr/azcodr
|
|
3
|
-
*
|
|
3
|
+
* Architecture governance toolkit, with an optional starter.
|
|
4
4
|
*
|
|
5
5
|
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
6
|
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
package/src/scaffold.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { EnsureSymlinkOptions } from './links.js';
|
|
|
10
10
|
import { makeScriptsExecutable } from './permissions.js';
|
|
11
11
|
import { isInsideGitWorkTree, initGit } from './repo.js';
|
|
12
12
|
import type { InitGitOptions } from './repo.js';
|
|
13
|
+
import { writeStarterCi } from './starter-ci.js';
|
|
13
14
|
|
|
14
15
|
export { getTemplateDir };
|
|
15
16
|
|
|
@@ -184,11 +185,12 @@ function starterPackageJson(resolvedTarget: string): Record<string, unknown> {
|
|
|
184
185
|
version: '0.1.0',
|
|
185
186
|
type: 'module',
|
|
186
187
|
private: true,
|
|
187
|
-
description: 'Scaffolded with azcodr
|
|
188
|
+
description: 'Scaffolded with the azcodr architecture governance toolkit',
|
|
188
189
|
scripts: {
|
|
189
190
|
test: 'node --test',
|
|
190
191
|
'test:coverage': 'jest --coverage',
|
|
191
192
|
lint: 'echo "No linter configured yet. Run /lets-build to configure toolchain."',
|
|
193
|
+
boundaries: 'node .agents/scripts/boundary_guard.js',
|
|
192
194
|
validate: 'node scripts/validate-cli.js'
|
|
193
195
|
}
|
|
194
196
|
};
|
|
@@ -236,6 +238,7 @@ export function copyTemplate(
|
|
|
236
238
|
actions.push(...ensureHarnessParity(resolvedTarget, dryRun));
|
|
237
239
|
actions.push(...ensureCopilotParity(resolvedTarget, dryRun));
|
|
238
240
|
actions.push(...ensureStarterPackageJson(resolvedTarget, dryRun));
|
|
241
|
+
actions.push(...writeStarterCi(resolvedTarget, dryRun));
|
|
239
242
|
const inspectDir = dryRun ? resolvedTemplate : resolvedTarget;
|
|
240
243
|
actions.push(...chmodTemplateScripts(inspectDir, dryRun));
|
|
241
244
|
return actions;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* azcodr's own release/CI workflows. They target this repository's scripts
|
|
6
|
+
* (build, mutation, benchmark) and must never run inside a scaffolded project;
|
|
7
|
+
* `writeStarterCi` removes them from the target and installs a starter CI.
|
|
8
|
+
*/
|
|
9
|
+
export const AZCODR_DEV_WORKFLOWS: readonly string[] = ['ci.yml', 'publish.yml'];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Starter governance CI written into every scaffolded project. It depends only
|
|
13
|
+
* on Node + the vendored guard engine, so it is green out of the box (unlike
|
|
14
|
+
* azcodr's own dev workflows, which call scripts a fresh project does not have).
|
|
15
|
+
*/
|
|
16
|
+
export const STARTER_CI = `name: ci
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
push:
|
|
20
|
+
branches: [main]
|
|
21
|
+
pull_request:
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
governance:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: actions/setup-node@v4
|
|
32
|
+
with:
|
|
33
|
+
node-version: 22.x
|
|
34
|
+
- name: Architectural boundary & cycle check
|
|
35
|
+
run: node .agents/scripts/boundary_guard.js
|
|
36
|
+
- name: Governance validation
|
|
37
|
+
run: node scripts/validate-cli.js
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Writes the starter governance CI into a scaffold target and removes azcodr's
|
|
42
|
+
* own dev workflows from it, so a generated project's CI is green out of the
|
|
43
|
+
* box instead of calling scripts a fresh project does not have.
|
|
44
|
+
*
|
|
45
|
+
* @param resolvedTarget - Absolute path to the scaffold target directory.
|
|
46
|
+
* @param dryRun - Record the action without touching the filesystem.
|
|
47
|
+
* @returns Recorded scaffolding action descriptions.
|
|
48
|
+
*/
|
|
49
|
+
export function writeStarterCi(resolvedTarget: string, dryRun: boolean): string[] {
|
|
50
|
+
const actions = ['generate: .github/workflows/ci.yml (starter governance CI)'];
|
|
51
|
+
if (dryRun) return actions;
|
|
52
|
+
const workflowsDir = path.join(resolvedTarget, '.github', 'workflows');
|
|
53
|
+
fs.mkdirSync(workflowsDir, { recursive: true });
|
|
54
|
+
for (const name of AZCODR_DEV_WORKFLOWS) {
|
|
55
|
+
fs.rmSync(path.join(workflowsDir, name), { force: true });
|
|
56
|
+
}
|
|
57
|
+
fs.writeFileSync(path.join(workflowsDir, 'ci.yml'), STARTER_CI, 'utf-8');
|
|
58
|
+
return actions;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default { STARTER_CI, AZCODR_DEV_WORKFLOWS, writeStarterCi };
|