@wairon/cli 5.1.1-dev.108 → 5.1.1-dev.109
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/CONTRIBUTING.md +193 -0
- package/README.md +14 -11
- package/dist/cli/index.js +2694 -1819
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +130 -7
- package/dist/index.js +2235 -1397
- package/dist/index.js.map +1 -1
- package/docs/cli.md +74 -23
- package/docs/design/approval-baseline.md +257 -0
- package/docs/design/connecting-agent-entrypoint.md +167 -0
- package/docs/design/execution-budgets.md +199 -0
- package/docs/design/pack-scoping.md +581 -0
- package/docs/design/supervisor-doctrine.md +110 -0
- package/docs/extending-wairon.md +2 -2
- package/package.json +9 -3
- package/schemas/design-export-2.json +9 -1
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Contributing to wairon
|
|
2
|
+
|
|
3
|
+
The conventions for making a delegated change — never hand-edit `.wai/`, read
|
|
4
|
+
every write back, the lock is the human's, measure before repairing, prove a
|
|
5
|
+
behaviour by revert without `git checkout` — are **not** in this file. They ship
|
|
6
|
+
with the tool, as the **Working conventions** section of the `sdd-implement`
|
|
7
|
+
skill (`src/templates/skills/sdd-implement.md`, installed as
|
|
8
|
+
`.agents/skills/sdd-implement/SKILL.md` and its siblings). Read them there: they
|
|
9
|
+
are true of any wairon project, and the brief-writing half is in `sdd-delegate`.
|
|
10
|
+
|
|
11
|
+
This file is only what is true of **this repository** and would be wrong to ship
|
|
12
|
+
to a wairon user.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Line endings: CRLF in the working tree, LF in the index
|
|
17
|
+
|
|
18
|
+
Git stores LF and checks out CRLF here. `.gitattributes` pins only `*.sh` to LF
|
|
19
|
+
(a CRLF shebang breaks `#!/usr/bin/env bash` on the Linux CI runners).
|
|
20
|
+
|
|
21
|
+
Most tools that write files emit LF, which turns a three-line change into a
|
|
22
|
+
whole-file diff. After any scripted or tool-driven write, normalise the file back
|
|
23
|
+
and confirm `git diff --stat` shows only the lines you meant.
|
|
24
|
+
|
|
25
|
+
**The rule is preserve what the file has, not "make it CRLF".** The heading above
|
|
26
|
+
describes the common case, not a uniform one: measured across `src/**/*.ts`, 212
|
|
27
|
+
files are CRLF, 52 are LF and 3 are mixed. `install.ps1`, `src/commands/aliases.ts`
|
|
28
|
+
and several tests are LF. Because `core.autocrlf` is true, git normalises on the way
|
|
29
|
+
in and `git status` reads clean either way, so the difference is invisible until a
|
|
30
|
+
scripted edit built for the wrong ending fails to match its anchor — or silently
|
|
31
|
+
rewrites the whole file. Detect each file's endings before editing it and write back
|
|
32
|
+
what was there.
|
|
33
|
+
|
|
34
|
+
Most obvious ways to check for carriage returns lie, including one that wraps the correct check:
|
|
35
|
+
|
|
36
|
+
| Command | What it actually does |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `grep '\r' f` | In a basic regular expression `\r` is the letter `r`. It matches every line containing an `r`, so an LF-only file "has carriage returns". |
|
|
39
|
+
| `grep $'\r' f` | Passes a real CR byte — but grep opens the file in text mode here and strips CR before matching, so it reports **0** on a genuinely CRLF file. |
|
|
40
|
+
| `grep -Uc $'\r' f` | Correct. `-U` suppresses the text conversion, so the CR survives to the match. |
|
|
41
|
+
| `file f` | Correct. Says `with CRLF line terminators`, or says nothing about them. |
|
|
42
|
+
| `x=$(grep -Uc $'\r' f)` | Lies, even though the command inside it is the correct one. Capturing it collapses the lone-CR argument to an empty pattern, which matches every line, so what comes back is the file's **line count** whatever its endings are. Run the check unwrapped, or put the CR in a variable first (`CR=$'\r'; grep -Uc "$CR" f`). |
|
|
43
|
+
|
|
44
|
+
Two traps for scripted edits specifically:
|
|
45
|
+
|
|
46
|
+
- **Never let a normaliser touch text that itself contains `\r` or `\n` escapes.**
|
|
47
|
+
A script that rewrites every line ending to CRLF will also rewrite the escape
|
|
48
|
+
sequence you meant to insert, putting a real carriage return inside a string
|
|
49
|
+
literal — which is an unterminated-string parse error, found at build time
|
|
50
|
+
rather than at write time. Build such text with `String.fromCharCode(13)`.
|
|
51
|
+
- **A quoted heredoc still loses doubled backslashes here.** `<<'EOF'` keeps a lone
|
|
52
|
+
backslash but collapses `\\` to `\`, so `p.replace(/\\/g, "/")` arrives as
|
|
53
|
+
`p.replace(/\/g, "/")` — an unterminated character class, and a syntax error at run
|
|
54
|
+
time. **It does not always fail loudly.** The same collapse inside an anchor string turns
|
|
55
|
+
`\\n` into a real newline, so the text simply does not match and the edit is skipped
|
|
56
|
+
with no error at all — which is how it was found the second time. Write the script with
|
|
57
|
+
the file-writing tool, or avoid doubled backslashes, and check the edit applied.
|
|
58
|
+
|
|
59
|
+
Byte counts show it too: a CRLF file loses exactly one byte per line when it is
|
|
60
|
+
flattened, so `wc -c` before and after a rewrite is evidence.
|
|
61
|
+
|
|
62
|
+
**Four generated files are deliberately LF — do not "fix" them:**
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
.wai/context/domains.md
|
|
66
|
+
.wai/context/wairon-guide.md
|
|
67
|
+
.wai/docs/topology.md
|
|
68
|
+
.wai/rules/topology.yaml
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Run wairon from this checkout, not the global install
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
npm run build
|
|
77
|
+
node dist/cli/index.js <command>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A globally installed `wairon` can lag this working tree — including its
|
|
81
|
+
validator, so it can pass a tree the code here rejects, or lock one under an
|
|
82
|
+
older rule set. The MCP server also runs `dist/`, so build *before* reconnecting
|
|
83
|
+
it.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## The gates, and today's baseline
|
|
88
|
+
|
|
89
|
+
| Gate | Baseline |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `npx tsc --noEmit` | clean |
|
|
92
|
+
| `npx vitest run` | 289 files / 4755 tests |
|
|
93
|
+
| `npx vitest run --config vitest.e2e.config.ts` | 7 files / 33 tests |
|
|
94
|
+
| `npm run build` | clean |
|
|
95
|
+
| `npm run build:web` | clean (typechecks the SPA) |
|
|
96
|
+
| `node dist/cli/index.js validate` | 0 errors, 0 warnings, 0 notices; register 303 findings / 406 units |
|
|
97
|
+
| `node dist/cli/index.js validate --ci` | passes |
|
|
98
|
+
|
|
99
|
+
The counts are a floor, not a target — they move as the suite grows, so update
|
|
100
|
+
this table when they do. `validate` also prints the **conformance debt register**
|
|
101
|
+
(findings carried under `rules.conformance.carried`); it is informational and
|
|
102
|
+
does not fail the gate, but a number that moved is a result worth reporting.
|
|
103
|
+
|
|
104
|
+
Some tests assert on the text of the shipped skill and agent templates
|
|
105
|
+
(`tests/core/template-vocabulary.test.ts`, `tests/core/skill-composition.test.ts`).
|
|
106
|
+
Changing that text is *supposed* to fail them — that is the assertion doing its
|
|
107
|
+
job. Fix it to match the new text; loosening it to match anything removes the one
|
|
108
|
+
thing keeping the templates and the validator's vocabulary in step.
|
|
109
|
+
|
|
110
|
+
A rule's `summary` is spec data, not a code string. `tests/core/rule-catalog.test.ts`
|
|
111
|
+
proves the registry's codes and the L3 `findings[].summary` values on
|
|
112
|
+
`iheuristic_rules.yaml` (and its siblings) are ONE list, so changing a summary in
|
|
113
|
+
the rule file alone fails the suite. Change it through the authoring tools first and
|
|
114
|
+
let the code string follow. This catches every contributor who touches a rule's
|
|
115
|
+
codes, and the suite is currently the only place that says so.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## A stale MCP server
|
|
120
|
+
|
|
121
|
+
When the build on disk changed after the server started — which is exactly what
|
|
122
|
+
`npm run build` does mid-session — every `sdd_*` answer carries
|
|
123
|
+
`staleServer: true` and a `⚠ STALE SERVER` banner, and `sdd_get_status` leads
|
|
124
|
+
with it. What happens to a write depends on what the rebuild changed:
|
|
125
|
+
|
|
126
|
+
- **The spec or tool schemas changed** (the server compares its own schema
|
|
127
|
+
fingerprint with the one the build on disk computes): every spec write, dry
|
|
128
|
+
runs included, is REFUSED and writes nothing, and the answers carry
|
|
129
|
+
`writesRefused: true`. A stale process with old schemas silently drops the
|
|
130
|
+
fields a newer schema introduced, and has — three times.
|
|
131
|
+
- **Only the build changed:** writes still go through, under the warning.
|
|
132
|
+
|
|
133
|
+
Either way the cure is the human reconnecting the server
|
|
134
|
+
(`/mcp reconnect wairon`). So author specs *before* a rebuild that changes a
|
|
135
|
+
schema. For a server old enough not to carry the flag, the tell is the shape of
|
|
136
|
+
the answer: a current `sdd_update_spec` returns a structured change report
|
|
137
|
+
naming what moved, an old one a single sentence.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Narrative jumps: use labels, not hand-counted step numbers
|
|
142
|
+
|
|
143
|
+
Inserting a step into an L5 narrative renumbers every later step, and
|
|
144
|
+
`sdd_update_spec` relocates the jump fields with it. That relocation has gone
|
|
145
|
+
wrong before, and the failure is quiet: a branch keeps a plausible number that
|
|
146
|
+
now points one step past where it meant to land, and nothing but a careful
|
|
147
|
+
re-read catches it.
|
|
148
|
+
|
|
149
|
+
Only STORED jumps relocate. A jump the delta itself writes — on a step it
|
|
150
|
+
inserts, appends or edits — is read in the numbering the whole delta leaves
|
|
151
|
+
behind, after all of its inserts and deletes, so write it as the final
|
|
152
|
+
narrative will number it.
|
|
153
|
+
|
|
154
|
+
Every jump-by-number field has a symbolic twin resolved at write time —
|
|
155
|
+
`label` on the step, and `onTrueLabel` / `onFalseLabel` / `toLabel` / `endLabel`
|
|
156
|
+
on the jump. A labelled jump survives an insert because it never named a number.
|
|
157
|
+
Prefer labels whenever a narrative is likely to grow.
|
|
158
|
+
|
|
159
|
+
When a numeric jump is edited anyway, verify the flow afterwards rather than
|
|
160
|
+
trusting the change report:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
awk '/^ - name: METHOD/{f=1} f&&/^ - name: /&&!/METHOD/{exit} f' <impl>.yaml \
|
|
164
|
+
| grep -E 'stepNumber|type:|onTrueStep|onFalseStep|toStep|outcome'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
That prints the control flow on its own, which is short enough to read in one
|
|
168
|
+
pass and is where a mis-relocated target is obvious.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Untracked paths are somebody else's work in flight
|
|
173
|
+
|
|
174
|
+
Run `git status` before you start. This repo regularly carries an uncommitted
|
|
175
|
+
design folder under `docs/design/` while an investigation is open (at the time of
|
|
176
|
+
writing, `docs/design/chained-subsystems/`). Do not touch, commit, stash, or
|
|
177
|
+
clean anything untracked that your task did not name.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Where repo-local guidance lives — and where it cannot
|
|
182
|
+
|
|
183
|
+
`CLAUDE.md`, `GEMINI.md`, and `.github/copilot-instructions.md` at the repo root
|
|
184
|
+
are rewritten wholesale by `wairon generate` (`writeRootGuideDelegator`), and
|
|
185
|
+
`.claude/` is gitignored entirely. Neither survives, so neither is a home for
|
|
186
|
+
anything a future contributor or agent should inherit. That home is **this file**
|
|
187
|
+
— and a brief points at it by name rather than paraphrasing it.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Bugs and questions
|
|
192
|
+
|
|
193
|
+
Actively developed. Open an issue.
|
package/README.md
CHANGED
|
@@ -224,9 +224,10 @@ git add .wai && git commit -m "Approve the design"
|
|
|
224
224
|
# never approved; plain lock-check only fails an approval that no longer matches.
|
|
225
225
|
wairon lock-check --strict
|
|
226
226
|
npm ci # TS/JS project with code: install the project's dependencies first
|
|
227
|
-
# (pnpm install --frozen-lockfile / yarn install --immutable)
|
|
228
|
-
# reads your code with YOUR TypeScript; without
|
|
229
|
-
#
|
|
227
|
+
# (pnpm install --frozen-lockfile / yarn install --immutable), so the
|
|
228
|
+
# gate reads your code with YOUR TypeScript (5 or 6); without one —
|
|
229
|
+
# or on TypeScript 7 — it reads with the copy wairon ships. The
|
|
230
|
+
# reusable workflow does this for you.
|
|
230
231
|
wairon validate --ci # the conformance gate, run at the FAMILY ROOT (the project that
|
|
231
232
|
# declares the members): there it is the family run, which judges
|
|
232
233
|
# the network proofs; externals are judged against their pins
|
|
@@ -267,9 +268,11 @@ See [docs/cli.md](docs/cli.md). Summary:
|
|
|
267
268
|
| `wairon diagram [--all] [--canvas] [--drawio] [--excalidraw] [--sequence <comp:method>]` | Mermaid, interactive canvas, and editable draw.io/Excalidraw exports |
|
|
268
269
|
| `wairon network flows \| policy \| diagram \| check \| why` | Networking derived from the design: allowed flows, Kubernetes `NetworkPolicy`, a trust-boundary diagram, live-flow checks ([details](docs/network.md)) |
|
|
269
270
|
| `wairon rules list` | The conformance rule registry (the architecture linter) |
|
|
270
|
-
| `wairon pack init \| build \| install \| use \| unuse \| impact \| sync \| bundle \| which \| list \| add \| remove` | Extension packs: injected profiles, language tables, and rules |
|
|
271
|
+
| `wairon pack init \| build \| install \| use \| unuse \| impact \| sync \| bundle \| which <name> \| list \| add \| remove` | Extension packs: injected profiles, language tables, and rules |
|
|
271
272
|
| `wairon member …` / `wairon subsystem externalize` / `wairon project rename` | Members (parts and projects) and the family migrations |
|
|
272
|
-
| `wairon externals add \| pin \| status \| list` | Declare, pin and check the externals a project consumes (`status` is the opt-in live gate) |
|
|
273
|
+
| `wairon externals add \| pin \| status \| list \| remove \| use \| consumers [--search <dirs>]` | Declare, pin and check the externals a project consumes (`status` is the opt-in live gate); from a producer, `consumers --search ..` finds who consumes it, sibling checkouts included |
|
|
274
|
+
| `wairon surface export \| import \| list \| diff [--against <ref\|file>]` | Exchange a public surface (native snapshot or OpenAPI, one document per portal); `diff` is the public-surface changelog since the last committed approval |
|
|
275
|
+
| `wairon method rename-param` / `wairon type rename-field` | Rename a contract parameter or a type field and respell every reference; the old name joins the rename trace |
|
|
273
276
|
| `wairon domains list \| scan \| add \| remove` | Domains (subsystem-derived + free-standing) |
|
|
274
277
|
| `wairon skills list \| install` | Manage the SDD skills installed into your tools |
|
|
275
278
|
| `wairon lock [-y]` | Validate the design as complete and record its approval in `.wai/lock.json`, code findings beside it; no spec file is rewritten |
|
|
@@ -291,12 +294,12 @@ See [docs/cli.md](docs/cli.md). Summary:
|
|
|
291
294
|
- [Vision](docs/vision.md) — long-term direction
|
|
292
295
|
- [CLI Reference](docs/cli.md) — all commands and MCP tools
|
|
293
296
|
- [Design export](docs/design-export.md) — the `wairon export` JSON format for generators and translators
|
|
294
|
-
- [Supervisor doctrine](
|
|
297
|
+
- [Supervisor doctrine](docs/design/supervisor-doctrine.md) — how Supervisors and Actors may depend on data and effects
|
|
295
298
|
- [Hosted server](https://github.com/SYW-Apps/Waffle-AIron/blob/main/docs/design/hosted-mcp-server.md) — self-host wairon over HTTP (Docker, auth, sizing)
|
|
296
|
-
- [Pack scoping](
|
|
297
|
-
- [Connecting-agent entrypoint](
|
|
298
|
-
- [Execution budgets](
|
|
299
|
-
- [Approval baselines](
|
|
299
|
+
- [Pack scoping](docs/design/pack-scoping.md) — the pack store, per-project selection, and reproducibility (design)
|
|
300
|
+
- [Connecting-agent entrypoint](docs/design/connecting-agent-entrypoint.md) — MCP `instructions`, prompts, and skill composition
|
|
301
|
+
- [Execution budgets](docs/design/execution-budgets.md) — what each agent's work costs to do, derived alongside what it owns (design)
|
|
302
|
+
- [Approval baselines](docs/design/approval-baseline.md) — what `lock` approves, and why it stopped rewriting your spec tree (design)
|
|
300
303
|
- [Extending wairon](docs/extending-wairon.md) — extension packs & wrapper products (with a [working example](https://github.com/SYW-Apps/Waffle-AIron/blob/main/examples/wrapper/))
|
|
301
304
|
- [Templates](docs/templates.md) — agent rendering templates
|
|
302
305
|
- [Standards](docs/standards/INDEX.md) — the architecture standards the SDD model is built on
|
|
@@ -315,7 +318,7 @@ validation), js-yaml, the MCP SDK, and Vitest. Bundled with tsup.
|
|
|
315
318
|
Actively developed. For bugs or questions, open an issue.
|
|
316
319
|
|
|
317
320
|
Working on this repo (or delegating work in it) — see
|
|
318
|
-
[CONTRIBUTING.md](
|
|
321
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for what this checkout does differently: line
|
|
319
322
|
endings, the gate commands and their baselines, and the stale-MCP-server tell.
|
|
320
323
|
The conventions that hold for *any* wairon project ship in the `sdd-implement`
|
|
321
324
|
and `sdd-delegate` skills.
|