create-religion 0.1.1 → 0.3.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 (41) hide show
  1. package/dist/lib/doctor.js +5 -1
  2. package/package.json +1 -1
  3. package/template/.agents/skills/audit/SKILL.md +1 -0
  4. package/template/.agents/skills/auto/SKILL.md +75 -8
  5. package/template/.agents/skills/capture/SKILL.md +65 -0
  6. package/template/.agents/skills/complete/SKILL.md +29 -3
  7. package/template/.agents/skills/doctor/SKILL.md +1 -0
  8. package/template/.agents/skills/feature/SKILL.md +16 -0
  9. package/template/.agents/skills/fix/SKILL.md +6 -1
  10. package/template/.agents/skills/implement/SKILL.md +50 -5
  11. package/template/.agents/skills/refactor/SKILL.md +165 -0
  12. package/template/.agents/skills/rollback/SKILL.md +35 -1
  13. package/template/.agents/skills/spike/SKILL.md +92 -0
  14. package/template/.agents/skills/status/SKILL.md +1 -0
  15. package/template/.agents/skills/try/SKILL.md +1 -0
  16. package/template/.claude/hooks/guard-rendered-output.mjs +33 -4
  17. package/template/.claude/hooks/guard-tier-one.mjs +37 -5
  18. package/template/.claude/hooks/scan-untrusted-input.mjs +114 -0
  19. package/template/.claude/skills/audit/SKILL.md +1 -0
  20. package/template/.claude/skills/auto/SKILL.md +75 -8
  21. package/template/.claude/skills/capture/SKILL.md +65 -0
  22. package/template/.claude/skills/complete/SKILL.md +29 -3
  23. package/template/.claude/skills/doctor/SKILL.md +1 -0
  24. package/template/.claude/skills/feature/SKILL.md +16 -0
  25. package/template/.claude/skills/fix/SKILL.md +6 -1
  26. package/template/.claude/skills/implement/SKILL.md +50 -5
  27. package/template/.claude/skills/refactor/SKILL.md +165 -0
  28. package/template/.claude/skills/rollback/SKILL.md +35 -1
  29. package/template/.claude/skills/spike/SKILL.md +92 -0
  30. package/template/.claude/skills/status/SKILL.md +1 -0
  31. package/template/.claude/skills/try/SKILL.md +1 -0
  32. package/template/AGENTS.md +30 -2
  33. package/template/CLAUDE.md +26 -2
  34. package/template/religion/.state/settings-template.json +29 -3
  35. package/template/religion/config.json +12 -2
  36. package/template/religion/context/ai-interaction.md +16 -2
  37. package/template/religion/context/current-work.md +7 -5
  38. package/template/religion/context/inbox.md +10 -0
  39. package/template/religion/context/untrusted-input.md +57 -0
  40. package/template/religion/history/refactors/README.md +9 -0
  41. package/template/religion/history/spikes/README.md +9 -0
@@ -14,17 +14,21 @@ const REQUIRED = [
14
14
  "build-plan.md",
15
15
  "context/project-overview.md",
16
16
  "context/coding-standards.md",
17
+ "context/untrusted-input.md",
17
18
  "context/ai-interaction.md",
18
19
  "context/current-work.md",
19
20
  "context/findings.md",
21
+ "context/inbox.md",
20
22
  "history/features",
21
23
  "history/fixes",
22
24
  "history/rollbacks",
25
+ "history/refactors",
26
+ "history/spikes",
23
27
  "reference"
24
28
  ];
25
29
  const ALLOWED = {
26
30
  "workflow.stepReview": ["every", "item"],
27
- "git.mode": ["trunk", "branch-per-item"],
31
+ "git.mode": ["trunk", "branch-per-item", "pull-request"],
28
32
  "git.checkpoints": ["none", "every-step", "squash"],
29
33
  "verification.logicTests": ["when-configured", "required"],
30
34
  "verification.uiEvidence": ["when-available", "required"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-religion",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "A file-backed, spec-driven AI development workflow. Spec before code, small reviewed diffs, and project state in markdown so a cleared context costs nothing.",
5
5
  "license": "MIT",
6
6
  "author": "Nate",
@@ -2,6 +2,7 @@
2
2
  name: audit
3
3
  summary: review the code itself across four lenses, recording findings in the ledger
4
4
  description: "Read-only code review across four lenses (quality, security, performance, tests) and four scopes (current work, changed files, a path, or the whole project), fanning the lenses out to subagents that read and return findings while this skill performs the single write. Records each finding in religion/context/findings.md with a durable identifier, a severity from P0 to P3, and a status, where an open or fixed P0 or P1 blocks completion. Use when the user runs $audit, asks for a code, quality, security, performance, or test review, wants dead code or duplication found, or wants a repair re-reviewed before it closes."
5
+ allowed-tools: Read, Grep, Glob, Bash, Agent, Write, Edit
5
6
  ---
6
7
 
7
8
  # audit - review the code, and record what you find
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: auto
3
3
  summary: run the loop unattended, within explicit bounds
4
- description: "Run the reviewed loop without stopping between steps, within bounds you set. With no argument it takes one work item and stops before completing it; `all` runs the remaining build plan; a number runs that many items. Specs, implements, verifies, applies the configured gates, repairs confirmed high-severity findings, and completes each item. Its invocation grants committing, dependency installs, and remote reads for the run, and grants nothing else: it still stops to ask before any merge. Use only when the user runs $auto or explicitly asks for an unattended run."
4
+ description: "Run the reviewed loop without stopping between steps, within bounds you set. With no argument it takes one work item and stops before completing it; `all` runs the remaining build plan; a number runs that many items. Specs, implements, verifies, applies the configured gates, repairs confirmed high-severity findings, and completes each item. Its invocation grants committing, dependency installs, and remote reads for the run, and grants nothing else: it still stops to ask before any merge. Under git.mode pull-request it lands every item on one shared integration branch and ends by opening a single aggregate review packet it never merges, after stating that whole remote budget up front and being told yes. Use only when the user runs $auto or explicitly asks for an unattended run."
5
5
  ---
6
6
 
7
7
  # auto - the same loop, without the pauses
@@ -29,14 +29,32 @@ produced.
29
29
  Running this authorizes, for this run only: committing, installing dependencies, and
30
30
  network reads. That is the second authority tier, and the invocation is the approval.
31
31
 
32
- It grants **nothing** in the first tier. Merging, pushing, deploying, publishing, deleting
33
- data, and rewriting history each still stop and ask, every time, no matter how many items
34
- remain.
32
+ It grants **nothing** in the first tier. Merging into the default branch, pushing to it,
33
+ deploying, publishing, deleting data, and rewriting history each still stop and ask, every
34
+ time, no matter how many items remain.
35
35
 
36
36
  Under `git.mode: trunk` there is no merge, so a run completes items and keeps going. Under
37
37
  `branch-per-item` it stops once per item to ask. That is not a flaw in the mode; landing
38
38
  work on a shared branch is a decision, and it stays one.
39
39
 
40
+ Under `pull-request` nothing lands on the default branch, so there is no merge to stop for.
41
+ What the run does need is the one grant the authority rules allow to be given ahead of time,
42
+ and it is asked for **before any work starts**, in full:
43
+
44
+ This run will, without asking again:
45
+ create and push the integration branch <integrationBranchPrefix><date>
46
+ create and push one branch per item
47
+ open a pull request from each item into the integration branch
48
+ merge those pull requests into the integration branch
49
+ open one aggregate pull request into <default branch>
50
+
51
+ It will not merge or push <default branch>, and it will not merge
52
+ the aggregate pull request.
53
+
54
+ Print that, naming the real branches, and wait. **The enumeration is the approval, and it is
55
+ the whole remote budget.** A general yes to running is not it, and neither is silence. If the
56
+ answer is no, the run does not start.
57
+
40
58
  ## Step 1 - preflight once
41
59
 
42
60
  Before the first item:
@@ -48,6 +66,21 @@ Before the first item:
48
66
  than one that never began.
49
67
  - The working tree is clean, or the only dirt belongs to work being resumed.
50
68
  - The plan has unchecked items.
69
+ - Under `pull-request`, the repository can host one: a remote exists and the host command
70
+ works. A repository that cannot is a stop, not a reason to fall back to local merges. The
71
+ mode exists to produce review gates, and silently producing a different history instead
72
+ would be worse than not running.
73
+
74
+ Record the default branch's current commit. It bounds what the aggregate pull request will
75
+ carry, and the final report refers to it.
76
+
77
+ Under `pull-request`, then establish the run's integration branch, named from
78
+ `git.integrationBranchPrefix` and the date. Create it from that recorded commit and push it.
79
+ Every item branches off it and lands back into it, which is what lets item three build on
80
+ items one and two. On a resume, reuse the branch of that name rather than opening a second;
81
+ if one exists that does not descend from the recorded commit, stop, because the run's base
82
+ moved and that needs a person. Never rebase, reset, or force-push it: it is append-only for
83
+ the run.
51
84
 
52
85
  State the bounds, the gates in force, and how many items are in range. Then start.
53
86
 
@@ -66,9 +99,39 @@ For every item, in plan order:
66
99
  the finding recorded rather than trying variations.
67
100
  5. **Complete it**, following $complete, which archives, ticks the plan, prunes the
68
101
  ledger, and commits. Ask before any merge.
69
- 6. **Report one line** and move on.
102
+ 6. **Land it**, under `pull-request` only: push the item's branch, open its pull request
103
+ **into the integration branch** rather than the default branch, and merge it there once
104
+ its checks are green. Merge only a pull request this run opened, only into the integration
105
+ branch. A failing or conflicted one is a stop, never something to force. Then delete the
106
+ item branch, confirming the work commit is in the integration branch first, since a
107
+ squash leaves no merge parent for `git branch -d` to find. Return to the integration
108
+ branch clean before the next item.
109
+ 7. **Report one line** and move on.
110
+
111
+ An item counts against `auto.maxItems` once it has landed, not once it is built.
112
+
113
+ ## Step 3 - close the run
114
+
115
+ Under `trunk` and `branch-per-item` there is nothing to close: the items are done and the
116
+ run reports.
117
+
118
+ Under `pull-request`, open one aggregate pull request from the integration branch into the
119
+ default branch. Title it for the run rather than for any one item. Its body is the run's
120
+ review packet, and it is the artefact a person actually reads:
121
+
122
+ - one section per completed item, in plan order, naming what it delivered, its merged pull
123
+ request, and the checks that proved it
124
+ - findings still open or fixed, by identifier, and anything deliberately left out
125
+ - what the run did not reach, and why it stopped
126
+
127
+ Report the URL and stop. **Never merge it.** It is the review gate the mode exists to reach.
128
+
129
+ Open it even when the run stopped early with completed items behind it, saying plainly in
130
+ the body that it stopped short: work that passed every gate deserves to be reviewable, and a
131
+ packet describing three of six items beats an integration branch nobody knows about. When
132
+ the run completed no items at all, open nothing and say so.
70
133
 
71
- ## Step 3 - stop
134
+ ## Step 4 - stop
72
135
 
73
136
  Stop immediately, keeping all state intact, when any of these happens:
74
137
 
@@ -84,9 +147,11 @@ Stop immediately, keeping all state intact, when any of these happens:
84
147
  A stopped run leaves the branch, the spec, and the ticked steps exactly as they are.
85
148
  `$auto resume` picks up from there, because the state is in files rather than in the run.
86
149
 
87
- ## Step 4 - report
150
+ ## Step 5 - report
88
151
 
89
152
  - items completed, by name, and what each delivered
153
+ - under `pull-request`, the recorded starting commit, the integration branch and its head,
154
+ each item's merged pull request, and the aggregate pull request URL or why none was opened
90
155
  - what stopped the run, exactly, and the state it stopped in
91
156
  - findings raised, repaired, and still open
92
157
  - checks run, and any that could not run
@@ -100,7 +165,9 @@ the part it got wrong.
100
165
 
101
166
  - Explicit invocation only.
102
167
  - The gates are the same gates. Unattended is not a reason to lower one.
103
- - Never merge, push, deploy, publish, or delete without asking, however long the queue is.
168
+ - Never write to the default branch, in any mode. Never merge the aggregate pull request,
169
+ and never force-push anything, the integration branch included.
170
+ - Never deploy, publish, or delete without asking, however long the queue is.
104
171
  - Never widen an item's scope to make its gate pass.
105
172
  - Stop on ambiguity. There is nobody to ask mid-run, so a guess compounds silently.
106
173
 
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: capture
3
+ summary: note something for later without breaking the one thing in progress
4
+ description: "Write a one-line note into religion/context/inbox.md and carry on, so noticing something worth doing does not cost the work item in progress. Takes the note as an argument, records it dated with where it came from, and stops. It never specs, never plans, and never starts work: $fix and $feature read the inbox when choosing what to build next. Use when the user runs $capture, says to note, park, remember or jot something down, mentions something worth doing later or some other time, or spots a problem mid-build that is not the thing being built."
5
+ allowed-tools: Read, Grep, Glob, Bash, Write, Edit
6
+ ---
7
+
8
+ # capture - note it, keep building
9
+
10
+ This exists because of a rule elsewhere: one work item at a time. That rule is what makes a
11
+ cleared context cheap, and it is also what makes noticing something mid-build awkward, since
12
+ there is nowhere to put it. Without an answer, a good observation either derails the work or
13
+ is lost.
14
+
15
+ The answer is a line in a file and no ceremony at all.
16
+
17
+ ## Input
18
+
19
+ The note, as an argument:
20
+
21
+ $capture "the rate limiter drops the first request after an idle period"
22
+
23
+ With no argument, ask what to note. Do not guess from the conversation, and do not sweep up
24
+ everything recently mentioned: a note nobody chose is a note nobody wants.
25
+
26
+ ## What it does
27
+
28
+ Append one line to `religion/context/inbox.md` with the date and, when there is one, the file
29
+ or area it concerns. Then stop, and return to whatever was happening.
30
+
31
+ That is the whole skill. It is deliberately small: anything more, and using it costs more
32
+ attention than the thought was worth, which is the failure mode that makes people stop
33
+ noting things.
34
+
35
+ ## What it does not do
36
+
37
+ - **It does not spec.** A note is not a work item. $fix turns one into a spec when you
38
+ decide to.
39
+ - **It does not start work**, touch the active spec, or tick anything.
40
+ - **It does not record code defects found by review.** Those are findings, they carry
41
+ severities and block completion, and $audit owns them. A note is something you
42
+ thought of; a finding is something a review proved.
43
+ - **It does not judge.** Write down what was said. Triage happens when the note is read, not
44
+ when it is written.
45
+
46
+ ## How a note leaves the inbox
47
+
48
+ $fix and $feature read the inbox when they start, and offer what is in it
49
+ alongside the build plan. Choosing one specs it and removes the line; that is the only way a
50
+ note leaves, other than you deleting it.
51
+
52
+ An inbox nobody reads is a list of things nobody did, so the reading is the point rather
53
+ than the writing.
54
+
55
+ ## Rules
56
+
57
+ - One line per note. If it needs a paragraph, it needs a spec, and that is $fix.
58
+ - Never interrupt the work in progress to discuss the note.
59
+ - Never write to the findings ledger.
60
+ - Never let the inbox become a plan. The build plan is the plan.
61
+
62
+ ## Formatting
63
+
64
+ Match the conventions in `religion/context/ai-interaction.md`: concise, scannable markdown,
65
+ lists for enumerations and tables for matrices rather than dense paragraphs.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: complete
3
3
  summary: run the final gate, archive the work, commit it, and close it out
4
- description: "Close out a finished feature, fix, or rollback. Runs the full Verify command and the final safety pass, applies the configured quality gates, archives the spec under religion/history/, ticks the build plan, prunes resolved findings into the archive, resets the active spec, and makes the work commit. Under branch-per-item it squash-merges only with explicit approval, then asks separately before pushing. Ends with a manual walkthrough of what landed. Use when the user runs $complete, or asks to finish, wrap up, close out, or merge the current work item once it is built and reviewed."
4
+ description: "Close out a finished feature, fix, rollback, or refactor campaign. Runs the full Verify command and the final safety pass, applies the configured quality gates, archives the spec under religion/history/, ticks the build plan, prunes resolved findings into the archive, resets the active spec, and makes the work commit. Under branch-per-item it squash-merges only with explicit approval, then asks separately before pushing. Under pull-request it pushes the branch and opens a pull request into the default branch, merging nothing. Ends with a manual walkthrough of what landed. Use when the user runs $complete, or asks to finish, wrap up, close out, or merge the current work item once it is built and reviewed."
5
5
  ---
6
6
 
7
7
  # complete - close out the finished work
@@ -80,6 +80,9 @@ Read the spec's type.
80
80
  - **Rollback** - archive to `religion/history/rollbacks/YYYY-MM-DD-NN-name.md`, leaving
81
81
  the original feature archive intact. Untick the target item, and append a short note to
82
82
  that line with the date and the rollback's archive path. Keep the number stable.
83
+ - **Refactor** - archive to `religion/history/refactors/area-lens.md`. A campaign is not a
84
+ plan item, so there is nothing to tick. Carry the deferred candidates across into the
85
+ archive, since they are what the next campaign over that area starts from.
83
86
 
84
87
  The number lives in the path. It never appears in the commit message.
85
88
 
@@ -149,10 +152,33 @@ Under **`branch-per-item`**:
149
152
  2. Delete the branch after a clean merge.
150
153
  3. Stop.
151
154
 
152
- Then, in either mode, ask separately whether to push. **Approval to merge is not approval
153
- to push.** Push only after an explicit yes to pushing, in this conversation. If there is no
155
+ In those two modes, ask separately whether to push. **Approval to merge is not approval to
156
+ push.** Push only after an explicit yes to pushing, in this conversation. If there is no
154
157
  remote, say so rather than guessing.
155
158
 
159
+ Under **`pull-request`** nothing is merged here and the default branch is never written to.
160
+ The branch goes up, the pull request describes it, and the merge is the user's, on the host:
161
+
162
+ 1. Confirm the repository can host one: a remote exists and the host command works. If it
163
+ cannot, stop and say so plainly. The work is committed on its branch and the user can
164
+ open the pull request themselves. Never invent a remote, and never quietly fall back to
165
+ a local merge, which would swap the history model without saying so.
166
+ 2. Push the branch and set its upstream, only with an explicit yes in this conversation.
167
+ **That yes covers pushing this branch and nothing else.** Neither running this skill nor
168
+ "looks good" is that yes.
169
+ 3. Open the pull request from the branch into the default branch. Title it from the work
170
+ commit. The body carries what changed and why, the checks that ran with the exact command
171
+ or output proving each, the manual walkthrough from Step 5, and anything left open:
172
+ unresolved findings, deliberate omissions, follow-ups.
173
+ 4. Report the pull request URL and stop. Do not merge it, do not wait or poll for it, and do
174
+ not touch the default branch.
175
+
176
+ Deleting the branch is a separate, later action, because the merge happens outside this
177
+ session. When the user says it merged: check out the default branch, fast-forward it,
178
+ confirm the work commit is actually in it, and only then delete the branch locally and on
179
+ the remote. A squash-merge leaves no merge parent, so `git branch -d` will refuse; verify
180
+ the content landed before reaching for `-D`.
181
+
156
182
  ## Step 5 - say how to try it
157
183
 
158
184
  Always end with the manual walkthrough for what just landed: what to start, where to go,
@@ -2,6 +2,7 @@
2
2
  name: doctor
3
3
  summary: check the setup is healthy and explain anything that is not
4
4
  description: "Read-only health check of the installation: required files present, adapter trees in sync, the entry file's commands accurate, configuration valid, plans usable, overview fresh, ignore rules sane, and git state workable. Runs the religion command-line tool for the deterministic checks when it is installed, then explains what any failure means and offers the fix. Use when the user runs $doctor, asks whether the setup is correct, wants a health check, or says something feels wrong before starting or resuming work."
5
+ allowed-tools: Read, Grep, Glob, Bash
5
6
  ---
6
7
 
7
8
  # doctor - is this set up correctly
@@ -22,6 +22,11 @@ lines into something buildable is this skill's whole job. It plans; it never bui
22
22
  - **A description with no match in the plan** - goes through **New work intake** below.
23
23
  - **`preview`** appended to any of the above - a read-only briefing, writing nothing.
24
24
 
25
+ Read `religion/context/inbox.md` before choosing. When it holds anything and no argument
26
+ named a specific item, list what is in it alongside the plan item you would otherwise take,
27
+ and let the user pick. A note that is specced leaves the inbox with the line removed; the
28
+ rest stay. An inbox nobody reads is a list of things nobody did.
29
+
25
30
  ## Step 0 - make sure the ground is solid
26
31
 
27
32
  Two checks before anything else.
@@ -127,9 +132,20 @@ visual spec from words alone when an image could exist.
127
132
 
128
133
  **Build steps** are the core of the file. Each is a small diff, ends with something that
129
134
  works, depends only on earlier steps, and carries an outcome that can actually be observed.
135
+
136
+ Where two steps genuinely do not depend on each other, mark the later one `(with N)`. It is
137
+ an assertion, not a hint: that these steps touch different files and neither needs the
138
+ other's result. Mark nothing you are unsure of. An unmarked spec is sequential, which is
139
+ always correct and never wrong, and a project with `workflow.parallelSteps` off ignores the
140
+ markers entirely.
130
141
  Read the Commands section of the entry file while writing the Testing section, so predicted
131
142
  coverage matches the gate that is actually on.
132
143
 
144
+ When writing the spec needed a broad read of the codebase first, run that read in a subagent
145
+ and have it return what it found. A survey large enough to be worth doing is large enough to
146
+ crowd out the context that has to write the spec from it. The subagent reads and returns; this
147
+ skill writes, as it always does.
148
+
133
149
  This is a draft. Do not present it yet.
134
150
 
135
151
  ## Step 4 - red-team the draft, then tighten
@@ -16,7 +16,12 @@ numbered, it ticks nothing, and it archives on its own.
16
16
  something wrong.
17
17
  - **A finding identifier** - `$fix F-03` specs the repair of that ledger entry.
18
18
 
19
- Without either, ask what is wrong. Do not guess.
19
+ - **Nothing** - read `religion/context/inbox.md` and offer what is there. Those notes were
20
+ taken mid-build precisely because they were not worth stopping for at the time, and this is
21
+ the moment they are worth something. Specced notes leave the inbox; the rest stay.
22
+
23
+ Without any of those, ask what is wrong. Do not guess, and do not scan the project hoping to
24
+ find something.
20
25
 
21
26
  ## Step 1 - understand the problem
22
27
 
@@ -50,9 +50,11 @@ Read `git.mode`.
50
50
  If the current branch looks wrong for this work, say so and ask; do not switch or create
51
51
  one unprompted.
52
52
 
53
- **`branch-per-item`** creates and checks out a branch named from the spec using the
54
- configured prefix. On a resume the branch exists already, so check it out rather than
55
- creating a second one.
53
+ **`branch-per-item`** and **`pull-request`** both create and check out a branch named from
54
+ the spec, using the prefix configured for its kind: feature, fix, rollback, or refactor.
55
+ They differ only in how the work leaves the branch at completion, which is not this skill's
56
+ concern. On a resume the branch exists already, so check it out rather than creating a
57
+ second one.
56
58
 
57
59
  Either way, if the project is not a git repository, say so and ask the user to initialize
58
60
  one. The loop needs history to be reviewable.
@@ -63,7 +65,7 @@ Set the spec's status to `in progress` before the first code change of this run,
63
65
  whenever work resumes after a passing check and touches product code. That invalidates
64
66
  stale verification state.
65
67
 
66
- Work through the build steps **in order, one at a time**. For each:
68
+ Work through the build steps **in order, one at a time**, unless a wave applies. For each:
67
69
 
68
70
  1. **Implement just that step.** The smallest change that satisfies its stated outcome.
69
71
  Nothing from a later step, nothing nobody asked for.
@@ -90,8 +92,13 @@ Work through the build steps **in order, one at a time**. For each:
90
92
  is failing, and offer to hand it to $debug, which reproduces the failure and
91
93
  tests competing hypotheses in parallel. Do not keep trying variations.
92
94
  6. **Tick the step** (`- [x]`) once its gate is satisfied, so progress survives a cleared
93
- context. If the step repaired a finding, mark that finding `fixed` and note the repair
95
+ context. In a wave, tick each step that passed, and only those. If the step repaired a finding, mark that finding `fixed` and note the repair
94
96
  in its resolution line. Never mark it `closed`; see Step 3.
97
+
98
+ **Tick it then, not later.** Never save several ticks to write in one go. The spec on
99
+ disk is the only record of what is done, and a session that ends between the work and
100
+ the bookkeeping loses exactly the step it just finished: the next one rebuilds it,
101
+ because an unticked step is indistinguishable from one never started.
95
102
  7. **Then prompt, according to config.**
96
103
 
97
104
  With `workflow.stepReview: "item"`, do not prompt. Continue to the next step and
@@ -115,6 +122,44 @@ Work through the build steps **in order, one at a time**. For each:
115
122
  Never batch the whole item into one diff. A diff too large to read means the step was too
116
123
  large; split it.
117
124
 
125
+ ## Waves, when the spec asks for them
126
+
127
+ Off unless `workflow.parallelSteps` is `true`. When it is off, ignore every marker and build
128
+ in order: a spec carrying markers must behave identically in a project that never opted in.
129
+
130
+ A step marked `(with N)` may run alongside step `N`. Those steps and everything transitively
131
+ joined to them form one **wave**. A step with no marker waits for every step before it, which
132
+ is why an unmarked spec is exactly as sequential as it has always been.
133
+
134
+ - [ ] 1. Add the schema migration
135
+ - [ ] 2. Build the endpoint
136
+ - [ ] 3. Build the client (with 2)
137
+ - [ ] 4. Update the docs
138
+
139
+ Two waves of one, then a wave of two, then a wave of one.
140
+
141
+ **Refuse a wave rather than guess at one.** Run the wave sequentially, and say why, when:
142
+
143
+ - a marker names a later step, itself, or a step that does not exist
144
+ - two steps in the wave would change the same file, which is a conflict the spec did not
145
+ intend and the author is better placed to resolve than a merge
146
+ - the wave is larger than three steps, which usually means the spec is describing one step
147
+ badly rather than three independent ones
148
+
149
+ **Building a wave.** Each step runs in its own subagent with the step, the spec, the
150
+ standards, and nothing else. They build and **return**; they do not tick, do not write the
151
+ spec, and do not touch the ledger. The parent applies what comes back, runs the gate for each
152
+ step, and performs every write. This is the same rule audit's lenses follow, for the same
153
+ reason: concurrent writers to one file is the one thing waves must never introduce.
154
+
155
+ **A failure stops the wave.** Report which steps passed and which did not, tick only what
156
+ passed, and stop. Do not retry the wave; the next run resumes at the first unticked step,
157
+ sequentially, because a wave that failed once has already shown its independence was wrong.
158
+
159
+ **One packet per wave.** Steps that ran together are reviewed together: one diff with a
160
+ section per step and its evidence, prompted once. `workflow.stepReview` still decides whether
161
+ that prompt happens per wave or is collected to the end; a wave never lands unreviewed.
162
+
118
163
  ## Step 3 - clear the ledger before handing off
119
164
 
120
165
  Read `religion/context/findings.md`. A P0 or P1 finding that is `open` or `fixed` will
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: refactor
3
+ summary: simplify existing code in one behaviour-preserving campaign at a time
4
+ description: "Simplify code that already exists, one behaviour-preserving campaign at a time. Takes a target that must be named (a single file, a folder, one package, or a monorepo root) and surveys it across five lenses: bloat, structure, over-implementation, duplication, and reinvention of what the language, the standard library, or an installed dependency already provides. Specs one lens in one area into religion/context/current-work.md and stops, leaving $implement to build it. Refuses to start when no test reaches the target, since a change meant to preserve behaviour needs something able to notice when it does not. Use when the user runs $refactor, asks to simplify, shrink, tidy, consolidate, or clean up existing or inherited code, says something is bloated or over-engineered, or wants a hand-rolled implementation replaced by something already available."
5
+ ---
6
+
7
+ # refactor - simplify what is already there
8
+
9
+ Refactoring is the one kind of change defined by what it must **not** do. The code gets
10
+ smaller; what it does stays identical. That constraint is the whole skill, and every rule
11
+ below exists to protect it.
12
+
13
+ This skill surveys and plans. It writes one campaign into
14
+ `religion/context/current-work.md` and stops, the same as $feature and $fix.
15
+ $implement builds it under the usual review gates.
16
+
17
+ ## Input
18
+
19
+ A **target is required**, and may be any size:
20
+
21
+ $refactor src/lib/date.ts a single file
22
+ $refactor src/legacy a folder
23
+ $refactor packages/api one package
24
+ $refactor . a monorepo root
25
+
26
+ There is no default and no implicit whole-project mode. Refactoring without a named target
27
+ is how a work item becomes unbounded. If no target is given, ask for one rather than
28
+ guessing at what looks worst.
29
+
30
+ A **lens** may follow, to survey only that axis: `$refactor packages/api duplication`.
31
+
32
+ ## The five lenses
33
+
34
+ Ordered as the campaign order is ordered, by how much each depends on a judgement about
35
+ equivalence. The earlier ones are safe because nothing has to be judged equal to anything.
36
+
37
+ | Lens | Finds | The judgement it rests on |
38
+ | --- | --- | --- |
39
+ | `bloat` | comments restating the code, banner blocks and section dividers, dead code, unreachable branches, unused imports, variables and exports | none: the code is not reached |
40
+ | `structure` | files and functions past the configured size, god objects, control flow nested past following | none: a move preserves behaviour by construction |
41
+ | `over-implementation` | abstraction layers, configuration options, generality and extension points nothing calls | that nothing calls it |
42
+ | `duplication` | the same utility, type, component or constant defined repeatedly, when one definition would serve | that the copies are actually the same |
43
+ | `reinvention` | hand-rolled implementations of what the language, the standard library, or an already-installed dependency provides | that the replacement matches every edge case |
44
+
45
+ `structure` reads its thresholds from `refactor.maxFileLines` and
46
+ `refactor.maxFunctionLines` in `religion/config.json`. They are defaults rather than a
47
+ standard this project agreed to, so a project that has set its own limits in a linter
48
+ should have those numbers copied into the configuration and used instead.
49
+
50
+ ## Step 1 - resolve the target
51
+
52
+ Establish what was named: a file, a folder, a package, or a workspace root holding several.
53
+ For a package or a workspace, read the manifests to learn where each package begins and
54
+ what each one publishes. That boundary matters twice over, in Step 4 and in Step 5.
55
+
56
+ Exclude what is not the project's to simplify: dependencies, generated files, build output,
57
+ caches, vendored code, minified assets, and anything the project's ignore rules already
58
+ exclude. State the exclusions before surveying, so nobody mistakes a skipped directory for
59
+ a clean one.
60
+
61
+ ## Step 2 - establish the safety net, or stop
62
+
63
+ **A declared test command is not the gate. Tests that reach the target are the gate.**
64
+
65
+ Run the project's declared test command and confirm the suite both passes and exercises the
66
+ target. A suite of six hundred green tests proves nothing about a directory none of them
67
+ import, and proceeding on it is worse than proceeding on nothing, because it feels safe.
68
+
69
+ When no test command is declared, or none reaches the target, stop and say so plainly:
70
+ name the target, say what the suite does cover, and point at $tests to cover the
71
+ target first. A required check that cannot run is a blocker, not a pass.
72
+
73
+ When the net holds, record the exact command and its result. That green baseline goes into
74
+ the spec in Step 5, so every step can be measured against the state before anything moved.
75
+
76
+ ## Step 3 - survey
77
+
78
+ **Run the survey in a subagent and have it return the map.** For anything larger than a
79
+ single file this is the difference between writing a campaign with room to think and writing
80
+ it from a context already full of the survey. The subagent reads and returns counts and
81
+ candidate locations; it never writes, and this skill performs the single write, exactly as
82
+ $audit does with its lenses.
83
+
84
+ Read the target across the selected lenses, or all five when none was named. Read
85
+ `religion/context/findings.md` as well: quality findings recorded by $audit against
86
+ this area are candidates already identified, and folding them in avoids rediscovering them
87
+ under a second name. **Never write to the ledger.** $audit owns that file, and a
88
+ finding's status stays its to change.
89
+
90
+ Report what was found as counts per area and per lens, densest first:
91
+
92
+ packages/api bloat 41 structure 7 duplication 12
93
+ packages/shared bloat 6 structure 2 duplication 21
94
+ packages/cli bloat 3 structure 0 duplication 1
95
+
96
+ For a single file the map is one row, which is fine. The point is that the size of the job
97
+ is visible before anyone commits to it.
98
+
99
+ ## Step 4 - choose one lens, in one area
100
+
101
+ **A campaign is one lens in one area.** Not five lenses, not the whole monorepo. A spec
102
+ mixing safe deletions with semantic replacements cannot be reviewed as one thing, because
103
+ the reviewer's attention is spent on the easy half.
104
+
105
+ Propose the widest win, say why, and let the user choose. Everything else stays in the
106
+ report, unspecced, waiting for the next run after this campaign completes.
107
+
108
+ Two boundaries constrain what may enter the campaign:
109
+
110
+ - **The published surface stops and asks.** Anything reachable only from inside the project
111
+ can be merged, renamed or reshaped freely, which is what makes the duplication lens work
112
+ at all. Anything a consumer can import, taken from the manifest's entry points, is a
113
+ breaking change wearing a refactor's clothes. Name it, say what would break, and let the
114
+ user decide whether it belongs in this campaign or in a feature.
115
+ - **A new dependency needs its own yes, and has to earn it.** When the language and the
116
+ installed dependencies genuinely cannot replace hand-rolled code, a new dependency may be
117
+ proposed, never assumed. Propose one only when it would be used in **several places**. A
118
+ dependency that saves fifty lines in a single file is a bad trade: the code leaves and the
119
+ supply chain stays.
120
+
121
+ ## Step 5 - write the campaign
122
+
123
+ Write the spec into `religion/context/current-work.md`: the target, the lens, the green
124
+ baseline from Step 2, and the change broken into steps small enough to read as diffs.
125
+
126
+ Order the steps so each one stands alone and can be verified against the baseline. Record
127
+ what would prove the behaviour unchanged, which is the test command from Step 2 for logic,
128
+ and for anything with a visible surface a route to walk and what should appear.
129
+
130
+ Candidates that were found but not specced go in as a short list at the end, so the next run
131
+ has them and nothing is rediscovered from scratch.
132
+
133
+ Completion archives the campaign under `religion/history/refactors/`. Refactor campaigns
134
+ are their own kind of work: they are not build-plan items, they tick nothing, and keeping
135
+ them separate is what makes the refactoring history of an area readable later.
136
+
137
+ ## Step 6 - report and stop
138
+
139
+ The target and what it resolved to, the baseline and the command that produced it, the
140
+ density map, the lens and area chosen and why, what the campaign contains, what was deferred,
141
+ and any published-surface or dependency decision waiting on the user.
142
+
143
+ Then stop. This skill does not build. $implement does.
144
+
145
+ ## Rules
146
+
147
+ - **Behaviour is the invariant.** Every step must leave the target doing exactly what it did.
148
+ - **Never fix a bug in a refactor step.** A refactor that uncovers a genuine defect stops and
149
+ points at $fix. Discovering that four copies of a function behave differently means
150
+ choosing one is a behaviour change, not a merge, and the reviewer cannot see it inside a
151
+ diff that also moves code.
152
+ - **Never delete a comment that carries a why.** The bloat lens removes comments restating
153
+ the code. A comment recording a decision, a gotcha, a workaround, or a link to a spec is
154
+ the opposite of bloat, and it is unrecoverable once gone.
155
+ - **Never reformat alongside a change.** Whitespace, import order and style churn never share
156
+ a step with a structural edit. A diff where fifteen real lines hide among three hundred
157
+ cosmetic ones gets rubber-stamped, which costs more than the formatting saved.
158
+ - One lens, one area, one campaign.
159
+ - A target is always named. Never scan the project hoping to find something worth doing.
160
+ - Read the findings ledger; never write it.
161
+
162
+ ## Formatting
163
+
164
+ Match the conventions in `religion/context/ai-interaction.md`: concise, scannable
165
+ markdown, lists for enumerations and tables for matrices rather than dense paragraphs.