@nusoft/nuos-build-catalogue 0.24.0 → 0.25.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/package.json +1 -1
- package/templates/agents/coder.md +2 -0
- package/templates/agents/reviewer.md +4 -0
- package/templates/agents/tester.md +4 -2
- package/templates/protocols/build-wu.md +31 -0
- package/templates/starter-kit/methodfile.json +9 -0
- package/templates/testing/README.md +21 -0
- package/templates/testing/example.test.ts +7 -0
- package/templates/testing/vitest.config.ts +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nusoft/nuos-build-catalogue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "NuOS build-catalogue tooling: semantic search (WU 110) + migration runner that lifts markdown artefacts into JSON-backed workflow records (WU 111, Phase G).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -46,6 +46,8 @@ If anything in the work unit is ambiguous, **stop and surface the ambiguity to t
|
|
|
46
46
|
|
|
47
47
|
5. **No comments unless WHY is non-obvious.** A hidden constraint, a workaround for a specific bug, behaviour that would surprise a reader. If removing the comment wouldn't confuse a future reader, don't write it.
|
|
48
48
|
|
|
49
|
+
6. **Write testable code (vitest gate).** If `methodfile.json` declares `testing.framework: "vitest"` with `testing.enforced: true`, every source file you create or substantially modify in this WU must end up covered by at least one vitest test — the tester writes them, but your job is to make that cheap. Export the units the tester needs to reach; avoid burying observable logic inside untestable closures; keep side effects at the edges. Files that genuinely can't be unit-tested (pure type declarations, config glue) are fine — flag them in your notes so the reviewer doesn't treat them as drift.
|
|
50
|
+
|
|
49
51
|
## When you finish
|
|
50
52
|
|
|
51
53
|
Append a brief note to the work unit's `## Notes / log` section:
|
|
@@ -52,6 +52,10 @@ nuos-catalogue memory store --value="<the pattern and why it matters>" --wu=<han
|
|
|
52
52
|
|
|
53
53
|
7. **Is jargon being introduced into user-facing copy?** If the work unit serves a non-engineer persona, the surface text should match the project's voice file. Flag anything that sounds like dev-speak in a user-facing surface.
|
|
54
54
|
|
|
55
|
+
8. **Does the vitest gate pass (JS/TS projects)?** If `methodfile.json` declares `testing.framework: "vitest"` with `testing.enforced: true`, run both gates from [build-wu.md §Step 5.5](../protocols/build-wu.md):
|
|
56
|
+
- **Gate A:** Run `npx vitest run` (or whatever `testing.command` says) from the implementation repo root. Capture the full output. Non-zero exit → BLOCKER finding with the failing test list.
|
|
57
|
+
- **Gate B:** Compute `git diff --name-only <swarm-base>...HEAD`, filter to source files (`.ts/.tsx/.js/.jsx` under `src/`, `app/`, `routes/`, `pages/`, `lib/`, `components/`, `api/` — exclude `*.test.*`, `*.spec.*`, `*.d.ts`, configs). For each remaining file, grep the test directories for an import of that module or a colocated `*.test.*` file. Any uncovered file → BLOCKER finding naming the file. The coder may rebut by flagging files as genuinely untestable (type-only, config glue) in the WU notes — accept those rebuttals when reasonable.
|
|
58
|
+
|
|
55
59
|
## How you write findings
|
|
56
60
|
|
|
57
61
|
Each finding has:
|
|
@@ -39,9 +39,11 @@ nuos-catalogue memory store --value="<what you learned about testing this area>"
|
|
|
39
39
|
|
|
40
40
|
3. **Failure paths matter as much as happy paths.** If the work unit's walkthrough mentions what happens when data is missing or the user makes a mistake, write a test for each.
|
|
41
41
|
|
|
42
|
-
4. **Use the
|
|
42
|
+
4. **Use the framework declared in `methodfile.json`'s `testing.framework`.** For JS/TS projects this defaults to **vitest** — the harness pre-wires it. If `testing.framework` is null or names a non-vitest runner (e.g. `pytest`), match the project's existing idiom instead. Never silently switch frameworks; if the declared framework is missing from the repo, escalate to the coordinator before writing tests.
|
|
43
43
|
|
|
44
|
-
5. **
|
|
44
|
+
5. **Per-touched-file coverage is mandatory (vitest gate).** When `testing.framework` is vitest and `testing.enforced` is true, every source file the coder created or substantially modified in this WU must have at least one test file referencing it. Run `git diff --name-only <swarm-base>...HEAD` to get the list. For each `.ts/.tsx/.js/.jsx` file under `src/`, `app/`, `routes/`, `pages/`, `lib/`, `components/`, or `api/` (excluding test files, `.d.ts`, configs), write or extend a test that imports the module and exercises observable behaviour. Colocated (`foo.test.ts` next to `foo.ts`) or `tests/`-mirrored layout — match what already exists.
|
|
45
|
+
|
|
46
|
+
6. **Tests must be reproducible.** No flaky timing, no relying on order, no shared mutable state between tests unless the framework explicitly supports it.
|
|
45
47
|
|
|
46
48
|
## When you run the tests
|
|
47
49
|
|
|
@@ -88,6 +88,14 @@ Use Claude Code's **Task tool**. Each spawn names the agent (`subagent_type`), t
|
|
|
88
88
|
|
|
89
89
|
Omit `null` fields. If `techStack.defined` is `false` or the section is absent, note it in the swarm audit entry and suggest the operator define the stack (`/plan-orientation` or edit `methodfile.json` directly) before the next swarm run — agents generating code without a known stack default to generic patterns that often need rework.
|
|
90
90
|
|
|
91
|
+
**Vitest pre-flight (JS/TS projects only).** Before spawning the coder, check `methodfile.json`'s `testing` block. If `testing.framework` is `vitest` and `testing.enforced` is `true`, verify the implementation repo has vitest installed and a `vitest.config.ts` (or `.js`/`.mts`) present. If either is missing, before any agent runs:
|
|
92
|
+
|
|
93
|
+
1. Surface to the operator in one line: *"Vitest is the declared test runner but isn't wired up in the implementation repo yet. I'll install it (`npm i -D vitest @vitest/coverage-v8`) and drop a minimal `vitest.config.ts` before the coder starts. OK?"*
|
|
94
|
+
2. On confirmation: (a) run `npm i -D vitest @vitest/coverage-v8` in the implementation repo; (b) copy the harness's `vitest.config.ts` template into the repo root and `example.test.ts` into `tests/example.test.ts` (create the directory if missing). The templates ship inside the installed harness package at `node_modules/@nusoft/nuos-build-catalogue/templates/testing/` — read them from there; if the harness is being run from a checkout, they're at `<harness-repo>/templates/testing/`; (c) add a `"test": "vitest run"` script to the implementation repo's `package.json` if absent; (d) run `npx vitest run` once to confirm the wiring works.
|
|
95
|
+
3. Record the setup in the swarm audit entry under a `## Setup` section so the next swarm doesn't repeat the check.
|
|
96
|
+
|
|
97
|
+
If `testing.framework` is not vitest (e.g. the project is Python), skip this pre-flight — the existing "match the project's idiom" rule applies.
|
|
98
|
+
|
|
91
99
|
**Spawn in parallel where possible.** If two agents can work independently (e.g. tester writing tests while reviewer reads design), spawn them in the same message. Sequential when an agent's output is the next agent's input (architect → coder).
|
|
92
100
|
|
|
93
101
|
For each spawn:
|
|
@@ -102,6 +110,25 @@ When each agent returns, capture their output. Three outcomes are typical:
|
|
|
102
110
|
- **REQUEST CHANGES** by reviewer → re-spawn coder with reviewer's findings as input. Cap at 3 retry loops; if still failing, escalate to debugger or operator.
|
|
103
111
|
- **ESCALATE** (any agent surfaces an architectural issue, a design ambiguity, a need for the operator's call) → STOP the swarm. Surface the issue to the operator in plain English; do not auto-decide.
|
|
104
112
|
|
|
113
|
+
## Step 5.5 — Run the test gate (JS/TS projects)
|
|
114
|
+
|
|
115
|
+
If `methodfile.json` has `testing.framework: "vitest"` and `testing.enforced: true`, this gate is mandatory before the reviewer's APPROVE can stand. The reviewer is responsible for running it (see [reviewer.md](../agents/reviewer.md)), but the coordinator owns the outcome.
|
|
116
|
+
|
|
117
|
+
**Gate A — the suite passes:** Run the command in `testing.command` (default `npx vitest run`) from the implementation repo root. The command must exit 0. Capture full output. If any test fails, the gate fails — re-spawn the coder + tester with the failure output, counted against the retry cap in Step 5.
|
|
118
|
+
|
|
119
|
+
**Gate B — every touched source file is covered:**
|
|
120
|
+
|
|
121
|
+
1. Compute the WU's changed files: `git diff --name-only <base>...HEAD` where `<base>` is the swarm's starting commit (recorded in the audit entry's `## Setup` section, or `HEAD~1` if not).
|
|
122
|
+
2. Filter to source files: anything matching `*.ts`, `*.tsx`, `*.js`, `*.jsx` under `src/`, `app/`, `routes/`, `pages/`, `lib/`, `components/`, or `api/`. Exclude `*.test.*`, `*.spec.*`, `*.d.ts`, config files, and anything under `node_modules/`, `dist/`, `build/`, `.next/`.
|
|
123
|
+
3. For each remaining file, check at least one `.test.ts(x)` or `.spec.ts(x)` references it. Acceptable references: (a) an `import` statement naming the file's module path, (b) a colocated `foo.test.ts` next to `foo.ts`, (c) a `tests/foo.test.ts` whose basename matches.
|
|
124
|
+
4. Any source file with no matching test is a Gate B failure. Re-spawn the tester with the uncovered file list and a directive to add at least one passing test per file.
|
|
125
|
+
|
|
126
|
+
If both gates pass, record `✓ vitest gate passed (N tests, M files covered)` in the swarm audit entry under `## Test gate` and continue to Step 6.
|
|
127
|
+
|
|
128
|
+
If either gate fails, re-spawn agents per the retry rules in Step 5. Gate failures count against the 3-attempt cap. After the third failure, escalate to the operator in plain English: *"After three attempts the vitest gate still fails on [list]. Either the tests need redesign or the touched files genuinely shouldn't be tested (config glue, declaration files). How would you like to proceed?"*
|
|
129
|
+
|
|
130
|
+
**Non-JS projects:** Skip this gate but note in the audit entry that the WU shipped without an enforced test gate (e.g. *"Python project — vitest gate N/A; pytest suite run separately"*).
|
|
131
|
+
|
|
105
132
|
## Step 6 — Record the swarm run
|
|
106
133
|
|
|
107
134
|
Write an audit entry at `docs/build/swarm/YYYY-MM-DD-wu-<handle>.md`. Use the template at `docs/build/swarm/_template.md`. Capture:
|
|
@@ -213,6 +240,10 @@ For full-feature swarms (architect → coder → tester → reviewer), after the
|
|
|
213
240
|
|
|
214
241
|
If anything looks misaligned, escalate to the operator before spending more tokens on the tester.
|
|
215
242
|
|
|
243
|
+
### Vitest test gate (JS/TS projects)
|
|
244
|
+
|
|
245
|
+
Step 5.5 above defines the gate in full. Restated as a verification rule: a JS/TS work unit cannot promote with reviewer APPROVE unless `vitest run` exits 0 AND every source file the WU touched has at least one test file referencing it. The reviewer runs the gate; the coordinator enforces the outcome. This is the load-bearing gate for code quality — drift here means shipping untested behaviour.
|
|
246
|
+
|
|
216
247
|
### Recording gate triggers
|
|
217
248
|
|
|
218
249
|
Every gate trigger gets recorded in the swarm audit entry under a `## Gate triggers` section. Even if the swarm continues, the trigger is logged. This builds the audit trail for the operator to review when reasoning about whether the swarm pattern is paying off.
|
|
@@ -19,6 +19,15 @@
|
|
|
19
19
|
"externalServices": [],
|
|
20
20
|
"notes": null
|
|
21
21
|
},
|
|
22
|
+
"testing": {
|
|
23
|
+
"framework": "vitest",
|
|
24
|
+
"command": "npx vitest run",
|
|
25
|
+
"configPath": "vitest.config.ts",
|
|
26
|
+
"enforced": true,
|
|
27
|
+
"policy": "every-touched-source-file-must-be-covered-by-a-passing-test",
|
|
28
|
+
"appliesTo": ["typescript", "javascript", "tsx", "jsx"],
|
|
29
|
+
"comment": "Vitest is the default test runner for JS/TS implementation repos. The swarm enforces two gates before a WU can promote: (1) `npx vitest run` exits 0; (2) every source file touched by the WU is referenced by at least one .test.ts(x) or .spec.ts(x). If the project's techStack does not include JS/TS, set framework to whatever idiom the stack uses (or null to opt out — the coordinator will warn but not block)."
|
|
30
|
+
},
|
|
22
31
|
"catalogue": {
|
|
23
32
|
"root": "docs/build/",
|
|
24
33
|
"registers": {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Vitest scaffolding
|
|
2
|
+
|
|
3
|
+
These files are copied into a JS/TS implementation repo by the swarm coordinator (see [build-wu.md §Step 4 — Vitest pre-flight](../protocols/build-wu.md)) when:
|
|
4
|
+
|
|
5
|
+
- `methodfile.json` has `testing.framework: "vitest"` AND `testing.enforced: true`, and
|
|
6
|
+
- the implementation repo does not yet have vitest installed or a `vitest.config.ts` present.
|
|
7
|
+
|
|
8
|
+
## Files
|
|
9
|
+
|
|
10
|
+
- `vitest.config.ts` — minimal Node-environment config with sensible include/exclude globs for typical `src/`, `app/`, `routes/`, `lib/` layouts and v8 coverage wired in.
|
|
11
|
+
- `example.test.ts` — single passing test, dropped at `tests/example.test.ts` so the operator can confirm the runner works end-to-end.
|
|
12
|
+
|
|
13
|
+
## What the coordinator does
|
|
14
|
+
|
|
15
|
+
1. Runs `npm i -D vitest @vitest/coverage-v8` in the implementation repo.
|
|
16
|
+
2. Copies `vitest.config.ts` to the repo root.
|
|
17
|
+
3. Copies `example.test.ts` to `tests/example.test.ts` (creates the directory if missing).
|
|
18
|
+
4. Adds `"test": "vitest run"` to the implementation repo's `package.json` `scripts` block if absent.
|
|
19
|
+
5. Runs `npx vitest run` once to confirm the wiring works before spawning the coder.
|
|
20
|
+
|
|
21
|
+
The example test is meant to be deleted as soon as the first real WU adds real tests — its purpose is purely to prove the wiring before the swarm depends on it.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts', 'app/**/*.test.{ts,tsx}', 'routes/**/*.test.{ts,tsx}'],
|
|
6
|
+
exclude: ['node_modules', 'dist', '.next', 'build'],
|
|
7
|
+
environment: 'node',
|
|
8
|
+
reporters: ['default'],
|
|
9
|
+
coverage: {
|
|
10
|
+
provider: 'v8',
|
|
11
|
+
reporter: ['text', 'json-summary'],
|
|
12
|
+
include: ['src/**/*.{ts,tsx}', 'app/**/*.{ts,tsx}', 'routes/**/*.{ts,tsx}', 'lib/**/*.{ts,tsx}'],
|
|
13
|
+
exclude: ['**/*.test.*', '**/*.spec.*', '**/*.d.ts'],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|