wei-wuwei 0.0.0-stage → 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.
Files changed (36) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +241 -2
  4. package/agents/_template/agent.md +28 -0
  5. package/agents/wuwei-audit-composition/agent.md +85 -0
  6. package/agents/wuwei-audit-contract/agent.md +97 -0
  7. package/agents/wuwei-audit-coverage/agent.md +93 -0
  8. package/agents/wuwei-implementer/agent.md +34 -0
  9. package/agents/wuwei-pre-implementation-doubt/agent.md +158 -0
  10. package/agents/wuwei-review-claims/agent.md +187 -0
  11. package/agents/wuwei-review-code/agent.md +219 -0
  12. package/agents/wuwei-review-defects/agent.md +180 -0
  13. package/agents/wuwei-review-design/agent.md +177 -0
  14. package/agents/wuwei-review-drift/agent.md +184 -0
  15. package/agents/wuwei-review-structure/agent.md +86 -0
  16. package/agents/wuwei-security-auditor/agent.md +229 -0
  17. package/bin/wuwei.js +2832 -0
  18. package/package.json +44 -4
  19. package/skills/_template/skill.md +34 -0
  20. package/skills/wuwei-brainstorm/skill.md +69 -0
  21. package/skills/wuwei-commit-hygiene/skill.md +38 -0
  22. package/skills/wuwei-debug-root-cause/skill.md +48 -0
  23. package/skills/wuwei-execute-phase/skill.md +624 -0
  24. package/skills/wuwei-grill/skill.md +67 -0
  25. package/skills/wuwei-legible-output/skill.md +27 -0
  26. package/skills/wuwei-map-codebase/skill.md +171 -0
  27. package/skills/wuwei-plan-phases/skill.md +326 -0
  28. package/skills/wuwei-review/references/lens-rules.md +41 -0
  29. package/skills/wuwei-review/references/prep.md +35 -0
  30. package/skills/wuwei-review/references/scopes.md +56 -0
  31. package/skills/wuwei-review/references/stream.md +94 -0
  32. package/skills/wuwei-review/skill.md +495 -0
  33. package/skills/wuwei-tdd/skill.md +47 -0
  34. package/templates/code-review.md +137 -0
  35. package/templates/pr.md +35 -0
  36. package/wuwei.config.json +51 -0
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: wuwei-grill
3
+ description: >-
4
+ Use when the user proposes a new feature or rough idea — "build X",
5
+ "我想要..." — before any spec or code exists, or when the doubt gate returns
6
+ Open Questions that need a human decision. Adversarially interrogates the
7
+ requirement and its assumptions. Cold phase: no solutions are designed here.
8
+ version: 0.1.0
9
+ mode: triggered
10
+ targets: [claude-code, codex]
11
+ tags: [requirements, workflow]
12
+ ---
13
+
14
+ # Grill
15
+
16
+ ## When to use
17
+
18
+ - A new requirement arrives and no signed SPEC covers it.
19
+ - The user's ask contains an unexamined assumption ("just add caching", "we
20
+ need a dashboard") — the *why* is missing or inherited.
21
+ - `wuwei-pre-implementation-doubt` returned Open Questions; grill them with the user
22
+ (HIGH first).
23
+
24
+ ## When NOT to use
25
+
26
+ - The requirement is grilled and the question is *how* to build — that is
27
+ `wuwei-brainstorm`. Do not design solutions inside grill.
28
+ - The SPEC for this stream is already signed off — changes go through a new
29
+ grill round, not silent edits.
30
+ - Trivial, self-evident fixes (typo, broken link). Grilling those is theater.
31
+
32
+ ## Procedure
33
+
34
+ 1. Ground in wuwei's own state first: `.wuwei/streams/`, `.wuwei/STATE.md`,
35
+ and `.wuwei/codebase/MAP.md` are the only live sources of truth. If
36
+ `.planning/` (GSD) exists but was never imported, it is not project
37
+ state — it is a one-shot import candidate wired through `ww init`,
38
+ nothing more. No wuwei stream yet means exactly that: nothing planned in
39
+ wuwei so far, never a cue to go read GSD's un-imported docs and treat
40
+ them as established context or ask the user questions sourced from them.
41
+ If the user wants that content brought in, point at `ww init`'s import
42
+ flow — don't substitute for it here.
43
+ 2. Restate the ask in one sentence and get confirmation you understood it.
44
+ 3. Enumerate the hidden assumptions: who is the user, what problem does this
45
+ solve, why now, what does success look like, what is the smallest version,
46
+ what is explicitly NOT included.
47
+ 4. Attack each assumption: what evidence supports it? what breaks if it is
48
+ false? what is the cheapest way to disprove it? Read the codebase where it
49
+ makes claims about existing behavior — verify, don't trust.
50
+ 5. Ask the user in batches (3–4 questions, highest-leverage first). When they
51
+ answer "both" or "all of it", state the cost of that answer and make them
52
+ pay it knowingly.
53
+ 6. Converge: write the sharpened requirement into
54
+ `.wuwei/streams/<stream>/SPEC.md` — goals, **non-goals** (must be
55
+ non-empty), constraints, and an Open Questions list for anything still
56
+ undecided. This exact path, not a convention borrowed from any other tool.
57
+ 7. Verify: every assumption from step 3 now has evidence, a user decision, or
58
+ an Open Questions entry. If any HIGH question remains open, say so and stop
59
+ — do not hand off to `wuwei-brainstorm` on top of an unresolved HIGH.
60
+
61
+ ## Notes
62
+
63
+ - Idea credit: grill-me. Rewritten for wuwei.
64
+ - Grill is cold, brainstorm is hot — keeping them separate is deliberate.
65
+ Interrogation that starts designing stops killing bad premises.
66
+ - In auto mode this runs once at stream start (the head touchpoint feeds on
67
+ its output); it is never skipped by autonomy.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: wuwei-legible-output
3
+ description: >-
4
+ Always-on output discipline (wuwei 律): diagrams and tables over prose walls,
5
+ diagrams generated from truth sources, review comments token-frugal, reports
6
+ led by what happened, decisions offered two at a time, replies in the
7
+ caller's language, paths and error text verbatim. Applies to every response,
8
+ report, digest, and document.
9
+ version: 0.1.0
10
+ mode: always
11
+ targets: [claude-code, codex]
12
+ tags: [output, rules]
13
+ ---
14
+
15
+ # Legible output
16
+
17
+ - Structure in three sentences → draw it: mermaid or a table beats a prose wall.
18
+ - Diagrams come from truth sources (codegraph edges, `depends-on`), never
19
+ impression; a not-yet-built design is labelled intended.
20
+ - Review comments: one finding, `file:line`, ≤ 2 sentences, no restating the diff.
21
+ - Lead with what you did, whether it worked, what to do next. Details after.
22
+ - Cut preamble, restatement and hedging; when the answer is known, lead with it.
23
+ - Decisions: two options max, the context to choose fast, and your pick.
24
+ - Reply in the caller's language; paths, commands, symbols and error text are
25
+ verbatim — never translated, tidied or shortened.
26
+ - Plain words over jargon, but never a false simplification — name the hard part.
27
+ - Acceptance bar: skimmable in under a minute, and says what changed and why.
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: wuwei-map-codebase
3
+ description: >-
4
+ Use when starting work in an existing or unfamiliar codebase — before
5
+ planning changes to legacy code, when the user asks "how does this project
6
+ work / 分析這個專案", or when a stream touches modules not yet mapped.
7
+ Produces an evidence-based architecture map: diagrams from the code graph,
8
+ never from impression.
9
+ version: 0.1.0
10
+ mode: triggered
11
+ targets: [claude-code, codex]
12
+ tags: [analysis, legacy]
13
+ ---
14
+
15
+ # Map codebase
16
+
17
+ ## When to use
18
+
19
+ - A stream is about to modify code you have not mapped.
20
+ - Onboarding into a legacy project; the user asks for an architecture
21
+ overview or "先看懂再動".
22
+ - Before `wuwei-plan-phases` on brownfield work — phases sliced against an
23
+ imagined architecture are sliced wrong.
24
+
25
+ ## When NOT to use
26
+
27
+ - Greenfield projects — there is nothing to map yet.
28
+ - A question about one file or one function: just read it.
29
+ - A map already exists (`.wuwei/codebase/MAP.md` or the current stream's
30
+ `MAP.md`) and the code has not moved since — refresh only what is stale.
31
+
32
+ ## Procedure
33
+
34
+ 1. Fix the scope before scanning anything — scope follows the output
35
+ location (step 7), never the conversation. A baseline map (no stream
36
+ open) covers the **entire repo**: every app/package in a monorepo, not
37
+ only the one the current conversation happens to be about. A stream's
38
+ map covers only what that stream touches — **except a SPEC goal that
39
+ quantifies over the repo** ("every entry point", "no other path"): that
40
+ set is enumerated repo-wide by search, not through the feature being
41
+ changed. Getting this backwards silently
42
+ produces a "baseline" that is really just whatever was being discussed —
43
+ wrong the moment the repo has more than one app.
44
+ 2. Prefer the code graph for **internal** structure, detected as
45
+ `wuwei-review` §5 does: `codegraph status --json` — use it when
46
+ `initialized` is true, `worktreeMismatch` is null and nothing is pending;
47
+ offer `codegraph init` when it is missing. Then `codegraph explore`,
48
+ `query`, `callers` and `node` — the CLI, which every tool with a shell can
49
+ run; the MCP server exposes only `codegraph_explore` by default — for the
50
+ questions below, scoped per step 1. Without it, fall back to Glob (entrypoints, manifests, directory
51
+ shape) and Grep — for a baseline map, Glob from the repo root, not from
52
+ whatever subdirectory the conversation was already in. Record which path
53
+ was taken — the output must say so (step 7). Codegraph deliberately
54
+ excludes `node_modules`/vendor directories ("your code, not their
55
+ code") — it will never surface external SDK usage (Firebase, Stripe,
56
+ AWS SDK, etc.) even when indexed. Step 3's external-boundary scan below
57
+ is unconditional, not a fallback for when codegraph is unavailable.
58
+ 3. Answer, with file/symbol citations: entrypoints; core modules and their
59
+ one-line responsibilities; data flow between them; **external
60
+ boundaries** — the test is whether it crosses a network or process
61
+ boundary at runtime, never "is this an SDK" or "is this a big/important
62
+ dependency": a local-only crypto/signature check (e.g. verifying a SIWE
63
+ message in-process) makes no call out, so it is not one; a pure
64
+ UI/rendering library (e.g. MUI) is not one either, no matter how central
65
+ it is to the app. Read the manifest (`package.json`, `go.mod`,
66
+ `requirements.txt`, etc.) for dependencies that actually make a
67
+ network/process call (API client, DB driver, queue, cloud/SaaS SDK), then
68
+ Grep each one's actual import sites to confirm it's really used, not just
69
+ declared. Do this regardless of whether codegraph found anything in
70
+ step 2 — codegraph cannot see this by design.
71
+ Separately, flag **opaque compiled artifacts** — WASM modules, native
72
+ bindings, minified/vendored blobs — anything no available method
73
+ (codegraph or Glob/Grep) can trace into structurally, whether or not it
74
+ ever crosses a network boundary. This is a different kind of gap than an
75
+ external boundary: it is about analysis blindness (can't see what's
76
+ inside), not about crossing a runtime boundary — never fold the two into
77
+ the same bucket just because both feel "not fully knowable".
78
+ 4. Record conventions under a `## Conventions` heading — one table,
79
+ `area | convention | example`. `example` is `file:line` plus, whenever the
80
+ pattern fits on one line, an inline snippet in backticks right next to
81
+ it — a bare path forces a click-through to see what the rule actually
82
+ looks like; a row should be readable on its own. Scan across: naming,
83
+ file/module layout, testing (framework, what's expected to be covered),
84
+ error handling, commit style, dependency management, and any other
85
+ repo-specific idiom actually observed. Skip an area with no discernible
86
+ convention — a guessed or aspirational rule is worse than an absent row;
87
+ every row cites a real file that demonstrates it, same discipline as
88
+ Hotspots (step 6). An area with **two or more genuinely conflicting**
89
+ patterns (not "no pattern" — real, inconsistent ones, e.g. half the
90
+ codebase in camelCase files, the other half kebab-case) is a different
91
+ case from a missing convention: never silently pick a side or report
92
+ only the majority as "the" convention. Cite both variants in the row,
93
+ mark it inconsistent, and ask the user which is intended (or whether a
94
+ migration is mid-flight) before the map treats either as settled —
95
+ picking wrong here would steer later work in the wrong direction, the
96
+ same kind of call this skill always defers upward rather than decides
97
+ on its own.
98
+ 5. Draw the architecture as a mermaid diagram **generated from actual edges**
99
+ (imports/calls). With codegraph: edges come from its call/import graph —
100
+ real, queryable relationships. Without it: edges come from your own
101
+ Glob/Grep reading, which is a best-effort reconstruction, not a verified
102
+ graph — never present it with the same confidence as a codegraph-backed
103
+ one. External boundaries from step 3 (APIs, DB, queues, files) are nodes
104
+ in this same diagram, distinguishable from internal modules (e.g. a
105
+ different shape or an explicit `external` label) — never left as prose
106
+ only, or the diagram undercounts the system's real edges. Label each
107
+ external node with the actual service/package, not a generic bucket
108
+ (`Firebase App Check`, not `External API`) — one node per vendor even if
109
+ several internal modules call into it, so a reader can see every
110
+ third-party the system depends on at a glance, not just that "something
111
+ external" exists. Opaque compiled artifacts from step 3 get their own
112
+ distinguishable style — separate from external-boundary nodes, since the
113
+ gap they represent is different — labeled with what they are and why
114
+ they're opaque (e.g. `ziwei-generator (WASM, opaque to static analysis)`);
115
+ never merge one into the other or into a plain internal module box.
116
+ 6. Mark risk items under a `## Hotspots` heading — one table,
117
+ `category | location | why it matters`. Scan across: complexity (high
118
+ fan-in symbols, god files), test gaps (untested critical paths), tech
119
+ debt (known shortcuts/workarounds), known bugs, security exposure,
120
+ performance bottlenecks, scaling limits (capacity ceilings, breaking
121
+ points), fragile-to-change areas, at-risk dependencies (vulnerable or
122
+ abandoned packages), missing capabilities that block other work. Skip a
123
+ category with no evidence — a table padded to look complete
124
+ is worse than a short one; this is a scan for what's actually there, not
125
+ a checklist to fill in. These feed `wuwei-plan-phases` as risk input and
126
+ threat candidates; never write `CONCERNS` or any other heading — the
127
+ scan's breadth borrows GSD's categories (credited below), the shape and
128
+ vocabulary stay wuwei's own.
129
+ 7. Write the map with sections `## Architecture` (mermaid), `## Modules`
130
+ (table: module | responsibility), `## Conventions` (table, step 4),
131
+ `## Hotspots` (table, step 6), and a leading line stating the evidence
132
+ source: `Source: codegraph (indexed <path>)` or `Source: static scan
133
+ (Glob/Grep, no codegraph — treat edges as best-effort, not verified)`.
134
+ Pick the location by scope: a stream is already open and this map is
135
+ about the code that stream touches → **`.wuwei/streams/<stream>/MAP.md`**;
136
+ general onboarding with no stream yet (or a project-wide baseline this is
137
+ refreshing) → **`.wuwei/codebase/MAP.md`**. Never invent a third location
138
+ or fall back to an inline-only answer — both scopes persist so later runs
139
+ can refresh instead of rediscovering.
140
+ 8. Verify: the scope from step 1 was honored — a baseline map names every
141
+ app/package in the repo, not only the one under discussion; every box in
142
+ the diagram cites a real file or symbol; the external-boundary scan
143
+ (step 3) checked the manifest, not just what codegraph happened to
144
+ surface — a project using Firebase/Stripe/AWS SDK etc. has each one named
145
+ in the diagram, not folded into one generic "external" node; the
146
+ network/process-crossing test was applied correctly — a local-only
147
+ crypto check or a pure UI library was not mistaken for a boundary just
148
+ because it's an SDK; opaque compiled artifacts (WASM, native bindings,
149
+ vendored blobs) are labeled distinctly from external-boundary nodes, not
150
+ merged into that bucket or into a plain internal module box; every
151
+ external boundary from step 3 appears in the diagram, not only in prose;
152
+ every Conventions row
153
+ (step 4) and every Hotspots row (step 6) has real evidence, and every
154
+ category/area with real evidence has a row — no silent drops, no padding
155
+ to look complete; any conflicting-convention area (step 4) was asked
156
+ about, not silently resolved to one side; a newcomer reading the map can
157
+ say where a given change
158
+ would go; the Source line accurately reflects which path step 2 took; the
159
+ output landed at `.wuwei/streams/<stream>/MAP.md` or
160
+ `.wuwei/codebase/MAP.md` — never a path or heading borrowed from GSD or
161
+ any other tool.
162
+
163
+ ## Notes
164
+
165
+ - Idea credit: GSD map-codebase, including the Hotspots scan's category
166
+ breadth (tech debt, bugs, security, performance, fragility, scaling,
167
+ dependency risk, missing capabilities, test gaps — GSD spreads these
168
+ across its own `CONCERNS.md`); the graph-first method is codegraph's.
169
+ Rewritten for wuwei.
170
+ - The map is a projection of the code, not a second truth — when they
171
+ disagree, the code wins and the map gets rebuilt.
@@ -0,0 +1,326 @@
1
+ ---
2
+ name: wuwei-plan-phases
3
+ description: >-
4
+ Use to turn an agreed approach into phases and an acceptance contract —
5
+ "plan this / 切 phase / 開一條 stream" — after wuwei-grill/wuwei-brainstorm
6
+ converge, or when a resumed stream has a missing or stale plan. Produces the
7
+ stream's phases, acceptance contract, and sign-off package. Ends at the head
8
+ human touchpoint: nothing executes before sign-off.
9
+ version: 0.1.0
10
+ mode: triggered
11
+ targets: [claude-code, codex]
12
+ inline-agents: [wuwei-pre-implementation-doubt]
13
+ tags: [planning, workflow]
14
+ ---
15
+
16
+ # Plan phases
17
+
18
+ ## When to use
19
+
20
+ - SPEC draft exists (grilled, approach chosen) and needs slicing into
21
+ executable phases.
22
+ - Resuming a stream whose `phases/` is empty, stale, or contradicts SPEC.
23
+
24
+ ## When NOT to use
25
+
26
+ - Requirement not grilled — the plan would be confident nonsense.
27
+ - Single trivial change: `wuwei-tdd` + `wuwei-commit-hygiene` suffice; a stream for a
28
+ one-liner is ceremony.
29
+
30
+ ## Procedure
31
+
32
+ 1. **Delivery strategy — first question, before any other planning work.**
33
+ How the work becomes real directs everything downstream: what is worth
34
+ researching, how the phases are cut, how e2e binds. Settle it after any
35
+ of those and that work was aimed by a decision nobody had made yet.
36
+ Resuming a stream whose `## Sign-off` already records a strategy? Read it — do not re-ask,
37
+ and do not silently re-slice to a different shape. Otherwise ask, one
38
+ question, default `mvp-first`. (This never blocks `auto`: a stream only
39
+ enters auto at sign-off, so a stream being planned for the first time
40
+ always has someone there, and a resumed auto stream reads the recorded
41
+ answer.)
42
+
43
+ | | `mvp-first` (default) | `feature-complete` |
44
+ |---|---|---|
45
+ | phase 01 | walking skeleton — the thinnest path that runs end to end through every layer in `## Target architecture`, deliberately shallow | one feature, vertically complete and independently shippable |
46
+ | later phases | deepen one part at a time; the skeleton stays green throughout | same again, one whole feature each |
47
+ | buys | integration risk answered first, and something runnable early | every phase is releasable and UAT-able on its own |
48
+ | defers | feature completeness — intermediate phases are not shippable, and some UAT items are not checkable until later | integration risk — the architecture is not exercised end to end until late |
49
+
50
+ Two knock-on effects, so this is not merely a label:
51
+ - **e2e binding differs** (step 6): `mvp-first` binds the critical path's
52
+ thin form to phase 01 and depth items to the phases that deepen it;
53
+ `feature-complete` binds each feature's items inside its own phase.
54
+ - **`depends-on` shape differs**: `mvp-first` serialises early, since
55
+ everything hangs off the skeleton; `feature-complete` usually leaves more
56
+ phases mutually independent, so more can be claimed in parallel.
57
+
58
+ Under `feature-complete`, if `## Target architecture` contains a boundary
59
+ no phase exercises until late and no spike de-risked it, name it as a
60
+ threat in the contract rather than discovering it in the last phase.
61
+ Record the choice in `## Sign-off`; step 3 researches to it and step 4
62
+ slices to it.
63
+ 2. **Stream**: ensure `.wuwei/streams/<name>/` exists; write or refresh
64
+ `SPEC.md` from `wuwei-grill` + `wuwei-brainstorm` output.
65
+ 3. **Research** the remaining unknowns (read code, external references —
66
+ library/API docs, RFCs — and wuwei's own `.wuwei/` state; spawn research
67
+ subagents where available). **A URL is not evidence until its content was
68
+ actually fetched and read** — a research subagent's finding about a
69
+ library, API, or RFC carries the fetched excerpt, never a bare link
70
+ standing in for the claim; **field names, units and example values are
71
+ quoted verbatim per endpoint**, since a paraphrase is where a field name
72
+ gets renamed; unreachable or unchecked goes into SPEC as unverified, not
73
+ as fact.
74
+
75
+ For anything about the existing code — what calls this, what breaks if
76
+ it changes, where does this shape come from — **query the code graph
77
+ before reading files**: check codegraph
78
+ `status`, index if stale, then `explore` / `search` / `callers` /
79
+ `impact`, falling back to Glob/Grep only when it is unavailable. Same
80
+ precedence as `wuwei-map-codebase` and the doubt gate. A plan sliced from
81
+ a guessed dependency graph produces phases whose `depends-on` is wrong,
82
+ which is the one field the whole execution order rests on. `.wuwei/codebase/MAP.md`, if a
83
+ baseline map exists, is the cheaper first read — but it is a snapshot and
84
+ the graph is live; where they disagree, the graph wins and the map is
85
+ stale. An un-imported `.planning/` (GSD) is not a
86
+ source here either — same boundary as `wuwei-grill` step 1: a one-shot
87
+ import candidate via `ww init`, never live project material to research
88
+ from directly.
89
+
90
+ **One exception to graph-first: a shared incrementing namespace.** The
91
+ next migration number or the next enum ordinal is not this repo's alone to
92
+ allocate, and the graph indexes one branch — it cannot see what another
93
+ pushed branch has already taken. `git fetch --all`, then for each branch
94
+ `git branch -r --no-merged <integration-branch>` (step 8) lists: a
95
+ filename-based slot (a migration file's leading number) needs
96
+ `git ls-tree -r --name-only <branch> -- <dir>`, since `grep`/`git grep`
97
+ search file contents and would miss it; a value written inside a file
98
+ needs `git grep <value> <branch>`. Two branches racing for the same slot
99
+ is a collision neither can see from its own history — this scan is bounded
100
+ by branch count, not free, but it targets one directory and one pattern,
101
+ not the whole tree. Step 11 verifies it was checked. Research to the strategy, not in general: `mvp-first` needs
102
+ the integration path answered first — can these layers actually talk? —
103
+ and can defer depth questions to the phases that deepen them;
104
+ `feature-complete` needs the first feature's depth resolved now and defers
105
+ the integration questions. Findings go into SPEC, not chat scrollback.
106
+ 4. **Slice phases** into `phases/NN-<name>.md`, to the shape step 1 chose:
107
+ - completion evidence stated in one sentence — can't state it, split it;
108
+ - evidence independently verifiable — needs the next phase to verify,
109
+ merge or re-cut;
110
+ - `depends-on` marked honestly (phases without mutual deps may run in
111
+ parallel);
112
+ - **cut so a phase can be reverted on its own.** On production `main` a
113
+ phase is the rollback unit — the fix for a bad release is `git revert` of
114
+ one commit — so independence is something planning delivers, not
115
+ something merging confers. `feature-complete` gives it by construction.
116
+ `mvp-first` does not: a later phase deepens an earlier one's skeleton, so
117
+ that pair reverts together. **Name those pairs here**, and say in
118
+ `## Sign-off` which phases are revert units — a phase nobody marked will
119
+ be assumed revertable by whoever is holding the incident. **A revert unit
120
+ leaves the phases before it safe and truthful** — no guard that lives only
121
+ in the reverted phase, no screen claiming what is no longer so;
122
+ - a task checklist inside the file, each task carrying **`depends-on`**
123
+ when it has one (omit when it has none, so an absent field means
124
+ independent, never forgotten). One task ≈ one commit;
125
+ - **a task dependency diagram** — mermaid, in the phase file, from the
126
+ `depends-on` fields. Order in a list cannot distinguish "this must come
127
+ second" from "I wrote it second"; the field carries the intent and the
128
+ diagram makes it readable at a glance. Omit only for a single-task
129
+ phase, and say so in one line;
130
+ - an `## Intended design` section — the target structure as a mermaid
131
+ diagram: the modules/interfaces this phase adds or changes and how they
132
+ connect. This describes what does not exist yet, so it is labelled
133
+ intended, never stated as observed fact (`wuwei-legible-output`);
134
+ `wuwei-execute-phase` diffs the built result against it. Omit only for
135
+ phases that add no structure (config bump, copy change) — and say which
136
+ in one line, so an absent diagram is never ambiguous with a forgotten one;
137
+ - each `## Intended design` is a **slice of SPEC's `## Target
138
+ architecture`**, not an independent design that happens to coexist with
139
+ the others — phases are how that target gets built, in order. A phase
140
+ that cannot be cut from it means either the target is wrong or the
141
+ slicing is: fix one of them here. Finding the mismatch during execution
142
+ is the expensive version of the same discovery. If `wuwei-brainstorm`
143
+ was skipped (the call was already made, or this is a bugfix) there is no
144
+ target to reconcile against — say so in one line, so its absence is
145
+ never ambiguous with an oversight;
146
+ - UI-touching phases add an **ASCII wireframe** under that same heading:
147
+ boxes, field order, button placement, and the empty / loading / error
148
+ states. Plain text, so it diffs in review like everything else — the
149
+ fidelity is layout intent, not pixels. Deciding these at plan time is
150
+ the point; discovering them mid-implementation is what this prevents;
151
+ - when a design genuinely needs more fidelity than text carries (colour,
152
+ type, multi-screen flow), the **source file** goes in
153
+ `.wuwei/streams/<stream>/sketches/` and is committed *before* it is
154
+ rendered or published anywhere. A rendered page is a projection of that
155
+ source — the same relation an issue has to a phase file — never the only
156
+ copy. A scratchpad or temp dir is not storage: it gets wiped, and a
157
+ published page you no longer hold the source for cannot be edited, only
158
+ rebuilt from nothing. The wireframe still goes in the phase file, so the
159
+ plan stays readable without opening anything;
160
+ - phases touching auth / payments / migrations / irreversible ops get a
161
+ proposed `review: human`.
162
+ 5. **Doubt gate**: run the `wuwei-pre-implementation-doubt` agent (Claude Code);
163
+ without subagents (Codex), read `references/wuwei-pre-implementation-doubt.md`
164
+ — the same agent, emitted beside this skill — and walk it inline, one
165
+ perspective at a time. Loop revisions until no HIGH finding
166
+ stands. **Each re-round reads the whole stream diff since the last round**,
167
+ not the list of fixes — a fix in one file is what leaves another stale.
168
+ **An edit made after the last round is unreviewed**: step 7 lists it, and
169
+ one touching money movement or persisted state gets a re-round, not a
170
+ skip.
171
+ 6. **Acceptance contract** `ACCEPTANCE.md`: derive critical paths from SPEC;
172
+ route each to automatable e2e (bound to a phase per step 1's strategy —
173
+ red blocks that phase)
174
+ or manual UAT (steps + expected result). **A repo with no e2e harness is
175
+ not a reason for UAT**: the first phase with a bound item adds one
176
+ (Playwright, which `wuwei verify` runs on too) as its first task.
177
+ **`## Verify`** lists each page that shows fetched data — `- <page>:
178
+ <route> · phase: NN`, the phase that builds it; its error, 403, empty,
179
+ loading and failed-refetch states are `wuwei verify`'s, not UAT's. No
180
+ such page → `verify: none`. Add `Threats` when an attack
181
+ surface exists (each: mitigate | accept | transfer, bound to a phase);
182
+ otherwise write `threats: none` explicitly.
183
+ 7. **Sign-off** — the head human touchpoint, never skipped in any mode.
184
+
185
+ Present, in this order: SPEC + contract + phase list (a `depends-on`
186
+ diagram, per `wuwei-legible-output`), SPEC's `## Target architecture`,
187
+ each phase's `## Intended design` (structure diagram, wireframe where
188
+ there is UI), and step 1's delivery strategy — whole-system target first,
189
+ then how the phases cut it up — plus **every edit made after the last
190
+ doubt-gate round**. This is the only point where a human sees the intended
191
+ shape before it is built, so **deliver it as files the person can open**
192
+ (sent files or a published page), never bare paths into a worktree.
193
+
194
+ Collect in **one round**:
195
+
196
+ - approval, or amendments;
197
+ - **tracker**: `per-phase` | `single` | `none`, and where. When linked,
198
+ also the **three status names in order** — which state means
199
+ in-progress, in-review, and done;
200
+ - which phases are circled **`review: human`**;
201
+ - **drive mode**: `manual` | `auto`;
202
+ - **merge method**: unsquashed by default — a merge commit — so ask only
203
+ whether this stream squashes instead, plus which methods the repo allows
204
+ (table below);
205
+ - **model policy** for review: `inherit` (default) | `roles`. Ask only
206
+ whether to change the default;
207
+ - **Codex**, when it runs execute: the model and effort it is started
208
+ with — `codex: <model> / <effort>`. A skill cannot set Codex's model;
209
+ `wuwei claim` prints the launch (`wuwei init` offers the profile);
210
+ - whether the plan goes through **its own PR** first — if so, steps 8–9
211
+ wait for that PR to merge.
212
+
213
+ Implementation is not on the menu: execute runs, and dispatches its
214
+ implementer, at sonnet / xhigh (`wuwei.config.json` `modelRoles`). The
215
+ policy sets **review** — step 5's `review:design` and `review:defects`,
216
+ which dispatch as subagents. The panel's other lenses inherit the session's
217
+ model, **except `wuwei-security-auditor`**, which pins `fable` / `high` in
218
+ frontmatter and holds under every policy including `inherit`. Say so,
219
+ rather than letting a `roles` answer imply it was chosen.
220
+
221
+ Write the outcome to `SPEC.md` under `## Sign-off`: date, what was
222
+ approved, delivery strategy, drive mode, tracker linkage and its three
223
+ status names, the three branch fields from step 8, **which merge methods
224
+ the target repo allows**, and the model policy —
225
+ **recording only what departs from the default**, since a table of
226
+ restated defaults is filler. `STATE.md` still carries `mode`/`tracker` for
227
+ index scannability; `## Sign-off` is where the decision lives, and what
228
+ `wuwei-execute-phase` reads.
229
+
230
+ **The merge method** gets asked here for the same reason the status names
231
+ do: a repo can disable merge commits or require linear history, and a rule
232
+ naming a method then fails at a button nobody can press. Record what the
233
+ repo allows, and which of them this stream uses:
234
+
235
+ | phase PR merges as | rollback of one phase | the phase's own commits |
236
+ |---|---|---|
237
+ | **merge commit — the default** | one command (`revert -m 1`) | kept, and readable |
238
+ | squash — opt in | one command (`revert`) | gone; the body lists their subjects |
239
+ | rebase — only where the repo allows nothing else | **unavailable** — say so here, so nobody plans a rollback around it | kept |
240
+
241
+ **Squashing is a human's choice, not a default**, since `wuwei-execute-phase`
242
+ step 2 makes every commit atomic and step 6 no longer squashes rounds: the
243
+ history a squash discards is now worth reading. The default keeps both
244
+ halves — one-command rollback *and* those commits — so the reason to
245
+ depart from it is a repo that forbids merge commits, or a person who wants
246
+ `main` carrying one commit per phase.
247
+
248
+ Asked once per stream, never re-asked.
249
+
250
+ 8. **Stream branch**: cut `wuwei/<stream>/base` from the current integration
251
+ branch — `/base`, so phase branches `wuwei/<stream>/NN-<name>` sit beside
252
+ it: git refuses a branch whose name is another's path — and record **three separate labelled fields** in `## Sign-off` —
253
+ later phases read two of them and must not read the third:
254
+
255
+ | field | read by |
256
+ |---|---|
257
+ | stream branch name | every phase — its PR base, and what phase branches are cut from |
258
+ | integration branch name | execute step 1, which syncs from its **tip** |
259
+ | the ref it was cut from | nobody. Historical marker only, **never a sync target** — syncing to a pinned old sha does nothing and reports nothing |
260
+
261
+ Separate fields, not one sentence: "cut from `main`@a1b2c3d" invites
262
+ exactly the wrong read. Without this step the first phase PR targets a
263
+ branch nobody created.
264
+
265
+ 9. **Tracker**: if linked, create the epic/issues via the connected MCP at
266
+ the chosen granularity, then **write every key back**: each phase's into
267
+ that phase file's `tracker-issue` frontmatter, the epic/milestone's into
268
+ `## Sign-off`. Without a recorded key, "this phase's issue" is something a
269
+ later session has to guess by title-matching, and it will eventually
270
+ transition a stranger's ticket. Now that the issues exist, **check the
271
+ three status names from sign-off against the tracker's real states** and
272
+ fix any that do not exist — sign-off had to ask before there was anything
273
+ to check them against, and a status name that does not exist is a
274
+ transition that silently does nothing. Issues are projections of the
275
+ phase files.
276
+ 10. **State**: write `STATE.md` (phase index, mode, tracker, empty claims);
277
+ commit the stream files.
278
+ 11. **Verify** — `wuwei plan-check <stream>` reads the checkable half:
279
+ `depends-on` resolves and is acyclic for tasks and phases, each task
280
+ diagram matches its fields, every phase carries an `## Intended design` or
281
+ says why not, `## Sign-off` has its fields and the stream branch is on
282
+ origin under `/base`, `STATE.md` agrees with `phases/`, a linked tracker
283
+ has a `tracker-issue` in every phase file, and auto mode never stands over
284
+ an open field. Errors are fixed before sign-off is shown as done.
285
+
286
+ Then the half it cannot read: every phase is a revert unit or paired with
287
+ the one it reverts with; the repo's allowed merge methods are recorded,
288
+ and the stream's own whenever it departs from the unsquashed default;
289
+ **any shared incrementing namespace this stream allocates from was checked
290
+ against unmerged branches, and the ref it was checked against named**;
291
+ **the phases match the recorded strategy** — a skeleton first phase under
292
+ `feature-complete`, or five shippable features under `mvp-first`, means
293
+ one of the two is a lie; a linked stream's three status names, and any
294
+ non-default model tier, are recorded where a resuming session will look; every e2e item maps to a phase; every
295
+ threat has a disposition; every UI-touching phase has a wireframe; each
296
+ design reconciles with SPEC's `## Target architecture`, or that target's
297
+ absence is explained; every mermaid block parses (quote an edge label
298
+ carrying punctuation).
299
+
300
+ ## Notes
301
+
302
+ - Idea credit: GSD plan/discuss + secure-phase (declaration side). Rewritten
303
+ for wuwei.
304
+ - The contract is what makes auto mode safe: the executor never defines its
305
+ own finish line.
306
+ - In auto mode execute's steps 2–6 run without the user, and its steps 4–6
307
+ loop at least three times inside that; execute's step 7 always stops. Step 1's
308
+ strategy question is not an exception to that: auto is only ever entered at
309
+ a sign-off, which recorded the answer, so a resumed auto stream reads it
310
+ instead of asking.
311
+ - Sign-off is why step 8 sits where it does: the stream stops being paper
312
+ there, and it is the only moment a human is present to confirm what the
313
+ branch is based on. Cutting earlier leaves a branch behind for a stream
314
+ that might still be rejected.
315
+ - **The two-level branch shape is what makes `mode: auto` safe.** An auto
316
+ phase merging itself needs somewhere to land that is not main, and the
317
+ stream branch is it; only the finished stream opens a PR to the
318
+ integration branch, and that one is always human.
319
+ - Tracker status names cannot be inferred — JIRA workflows are per-project,
320
+ GitHub Issues has only open/closed plus labels, GitHub Projects uses
321
+ custom fields — and a guessed name is a transition that silently no-ops.
322
+ That is why sign-off asks for all three by name.
323
+ - `inherit` is the model-policy default because the session is already the
324
+ user's own decision, and pinning would silently override it — including
325
+ downgrading a deliberately strong session. It is also the only shape that
326
+ behaves the same whether work is dispatched to subagents or run inline.
@@ -0,0 +1,41 @@
1
+ # Lens rules
2
+
3
+ Read when the panel runs inline — no subagents (Codex). On Claude Code each
4
+ lens carries these in its agent file; this is the same list, and a rule
5
+ changed in one is changed in the other.
6
+
7
+ ## Code panel (`wuwei-review` §2)
8
+
9
+ | Lens | Rule |
10
+ |---|---|
11
+ | design | a changed default, narrowed semantic or new enum value means nothing without **what already exists** — the rows, and the artifacts already built that an operator will redeploy (an old image still demanding the variable the new workflow no longer sends); "the new rule is right" and "existing data satisfies it" are two claims, and a migration is what connects them |
12
+ | design | **compatible is not affordable**: for schema changes, read what the engine actually does to a table with rows — rebuild or in-place, what it locks and for how long, what a mid-failure leaves behind. Read the engine's answer, never assume it |
13
+ | design | **turning a no-op live is not neutral**: when this change makes a dormant path actually run, ask what pre-existing bugs downstream were survivable only because it never fired. `impact`/`callers` answer the wrong (upstream) direction — walk what the newly-live call reaches by reading it; raise exploitability, leave rating it to `audit:security`. **And the mirror**: what depended on the *other* branch staying reachable — a fixture that only passed while the veto fired, a doc scoped to "once the flag is on" |
14
+ | defects | **duplication is against the repo, not within the diff** — grep for an existing helper before accepting a new one; report as `reuse:` naming the file that already had it |
15
+ | defects | an **exclusivity claim needs the complement** — enumerate the candidates (`wuwei sites`), subtract the compliant ones, report the rest; `callers(X)` answers the opposite question. **"Never" is a claim about history**: `git log -S<name>` is its complement, HEAD is not |
16
+ | defects | **anything the diff deletes that can be spelled gets grepped** — identifiers, paths, ticket ids, the tokens inside deleted prose — in addition to the graph: after a move the old name has no referent, so `impact` comes back clean while every string spelling it points at nothing. A string literal is not an edge, and a spec asserting on a ticket id that lived only in a deleted comment is the hit a symbol grep never makes. **And the facts deleted prose stated are grepped for another home** — a block deleted to fix one stale line can take facts the tree states nowhere else. **And the old size of any set the diff shrinks** — an enum, a route table, an error map — is grepped as a literal in assertions; the number is valid syntax and contains none of the removed names |
17
+ | defects | **prose inside code is code**, checked against whatever it names — markdown included. A comment naming an external consumer is a claim about that artifact; absence is the finding |
18
+ | defects | **but the absence has to be reached before it is reported** — a zero-hit grep is a claim about the pattern, not the repo (`describe(` misses a top-level `it(`; a rename check that greps the new name proves nothing about the old). Positive control, or read what the pattern covers; if that needs a write or the suite, your own worktree of the reviewed sha — none possible, `PLAUSIBLE` and say so |
19
+ | defects | **a hit on a removed name is a finding only if its clause still offers the name as available** — a clause recording the removal is not one. Quote the clause |
20
+ | defects | **a zero-hit claim written into the diff is checked against the tree the change produces, not the base** — the change itself can add the first hit. Name the ref the claim holds for |
21
+ | design | **for a queue or batch the diff reorders or filters, the row that never qualifies** — with no cursor it is selected forever and everything behind it starves, fed from an entry point the diff may never touch |
22
+ | security | **reachability gates severity** — an unreachable sink is not HIGH |
23
+ | security | **a missing value is an exceptional condition** — a guard whose input is `undefined`/`null` falling to the allow side (`!== expected` is true for a missing value) is fail-open; a bypass search does not find it, reading the polarity does |
24
+ | code | judge by **this project's own standards**, and a spec that asserts a convention *is* the convention; **a permission recorded outside the repo** (the author's own instructions, a word in chat) is unobservable — ask for it in one line, never report its absence; **and the review never grants it** — a ruling posted from the review side is not the permission the rule names |
25
+ | code, design | **a claim about a third-party tool's behaviour, or that a fix/guard/test catches some condition, is PLAUSIBLE until it's read/run — or the condition is actually constructed and the catch observed** — e.g. a migration tool's hash logic described from memory, a test called evergreen without trying to break it, or "removing this call produces N failures" without removing it and counting |
26
+ | code | **two mutations are always in the set**: the sibling that can override what the guard reads (`tsconfig.build.json` beside the `tsconfig.json` it checks), and the opposite polarity (the guard firing when it should not) |
27
+ | code | **a file that opens on disk is not proof it belongs to the repo** — `git ls-files -- <path>` it (check the output, not the exit code) before citing it as convention. Untracked but carrying a `GENERATED BY wuwei` marker → cite its tracked source instead; untracked with no such marker → this repo declares none of what it names, take the plain-read path |
28
+
29
+ ## Document panel (`wuwei-review` §3)
30
+
31
+ | Lens | Rule |
32
+ |---|---|
33
+ | claims | **a document that instructs is reviewed for what it invites**: enumerate the positions a safety claim covers, subtract the ones its mechanism protects, report the rest. Confirming it for the cases that exist proves nothing about the ones the document teaches someone to write. **A position the syntax permits is reachable — the reader is the path**, so "no such case exists yet" does not make it PLAUSIBLE. This governs *claims in documents*, not sinks in code: `audit:security`'s reachability rule is unchanged, and the two lenses reaching opposite severities on one subject is a real disagreement for a human, not a contradiction to resolve by collation |
34
+ | claims | **a checkable gate (an acceptance item, a `grep -c … >= 1`, a `test -f`) is a claim about what will satisfy it** — ask what *else* in the tree satisfies it, not only whether the intended thing does; **a gate reading a measurement is checked for its emitter in the tree the change produces** (a deleted emitter reads as a fake zero); **a gate names its enforcer** or is a registered gap, and **N copies of a claim by one author are one claim**; **every gate is re-run after the fixes land**, since a refactor the panel asked for is how a gate stops matching. Three ways it is false and **the dangerous ones pass**: satisfied by the wrong thing (a grep meant to prove a method exists, whose one hit is a comment about another class — green, certifying work nobody did), never satisfiable (greps a since-renamed name), or its emitter deleted by the change (a fake zero). Run it against the tree as it is now and say which it currently is — **and running its syntax is not running it**, since a fragment that parses can still be case-blind or satisfied by a superstring; a fix that would satisfy the gate on arrival is itself a finding, not a reason to stay quiet |
35
+ | claims | **a claim about history ("never", "since it landed", "every version") is answered by `git log -S` / `git log -- <path>`, not by the tree**; and **a claim to be complete is verified by re-deriving the set, never by checking off the set it lists** — "all four call sites", "every place this is mapped", "the only consumer". Ticking each listed item passes while a fifth one exists, so derive the set from the tree instead: grep the type, the decorator, the shape — **not the names the document handed you**, which are the claim under test — then subtract. This is `defects`' exclusivity rule aimed at prose, and it bites hardest on a plan, where the executor works the list rather than the tree |
36
+ | structure | **for every claim about what is or is not required, find the procedure section that would have to change with it** — a new section asserting a new fact with the old checklist untouched is the pattern |
37
+ | drift | **a fact this change establishes gets grepped across the whole tree for anything still asserting the opposite** — code comments included, not only `docs/`; same shape as the rename rule: the dangerous hit is in a file the change never opened. Check the document the audience actually reads first |
38
+ | drift | **a cross-branch or cross-version comparison uses §6's three-dot form** (`<a>...<b>`), not `<a> <b>` — tip-to-tip answers "do these differ", not "did `<b>` change what `<a>` changed", and is wrong exactly when `<a>` moved since the merge base. Three-dot fails closed (errors with no common ancestor); state which form you used |
39
+ | drift | **a claim about an external platform's live configuration is checked against that platform, not the repo's copy of it** — on GitHub check both `.../branches/<branch>/protection` (classic, 404s under rulesets) and `.../rules/branches/<branch>` (rulesets); GET only, `per_page=100`, every page — a list endpoint's first page is a pattern with a reach. **A platform fact the dispatcher supplied (§1) is that check**; re-query only to dispute it. Can't query it → `PLAUSIBLE`, name what went unqueried, never fall back to the repo's copy as settling it |
40
+ | drift | **a hit on a removed name is a finding only if its clause still asserts the name as current** — a clause recording the removal is not one. Quote the clause |
41
+ | claims, drift | **a suggested fix is checked against precedent, not invented** — grep the repo for how the same kind of staleness was corrected before, and match that shape. A repo with an existing convention already answered the question. **And the anchor must survive the repo's merge settings** — a commit SHA dies under `allow_squash_merge`; anchor to the file tree. **A record (a plan, a summary, a decision log) is corrected beside the sentence, dated, not rewritten** — it is also evidence of what was believed |