create-religion 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/lib/dashboard.js +4 -3
  3. package/dist/lib/doctor.js +21 -7
  4. package/dist/lib/settings.js +4 -0
  5. package/dist/lib/state.js +143 -5
  6. package/dist/lib/status.js +36 -4
  7. package/package.json +1 -1
  8. package/template/.agents/skills/audit/SKILL.md +13 -7
  9. package/template/.agents/skills/auto/SKILL.md +120 -2
  10. package/template/.agents/skills/complete/SKILL.md +22 -6
  11. package/template/.agents/skills/complete/reference/land-on-top.md +188 -0
  12. package/template/.agents/skills/distill/SKILL.md +2 -1
  13. package/template/.agents/skills/feature/SKILL.md +6 -1
  14. package/template/.agents/skills/fix/SKILL.md +3 -2
  15. package/template/.agents/skills/implement/SKILL.md +18 -1
  16. package/template/.agents/skills/implement/reference/item-worktree.md +133 -0
  17. package/template/.agents/skills/rollback/SKILL.md +3 -1
  18. package/template/.claude/hooks/write-handoff.mjs +92 -3
  19. package/template/.claude/skills/audit/SKILL.md +13 -7
  20. package/template/.claude/skills/auto/SKILL.md +120 -2
  21. package/template/.claude/skills/complete/SKILL.md +22 -6
  22. package/template/.claude/skills/complete/reference/land-on-top.md +188 -0
  23. package/template/.claude/skills/distill/SKILL.md +2 -1
  24. package/template/.claude/skills/feature/SKILL.md +6 -1
  25. package/template/.claude/skills/fix/SKILL.md +3 -2
  26. package/template/.claude/skills/implement/SKILL.md +18 -1
  27. package/template/.claude/skills/implement/reference/item-worktree.md +133 -0
  28. package/template/.claude/skills/rollback/SKILL.md +3 -1
  29. package/template/AGENTS.md +12 -1
  30. package/template/CLAUDE.md +12 -1
  31. package/template/religion/config.json +2 -1
@@ -24,6 +24,10 @@ guess past broken configuration.
24
24
  **Read the spec.** If `religion/context/current-work.md` is still the stub, or its status
25
25
  is already complete, stop and say to run /feature, /fix, or
26
26
  /rollback first.
27
+ When it is the stub and `religion status --json` lists items under `inFlight` with `here`
28
+ false, or the handoff lists items in flight in other worktrees, name each with its worktree
29
+ and branch, and say that resuming one means working from that worktree. Never start one of
30
+ them again here.
27
31
 
28
32
  **Take the context.** Conventions from `religion/context/coding-standards.md`, the data
29
33
  model from the project overview. Code that ignores them is rework, not progress.
@@ -56,6 +60,18 @@ They differ only in how the work leaves the branch at completion, which is not t
56
60
  concern. On a resume the branch exists already, so check it out rather than creating a
57
61
  second one.
58
62
 
63
+ **With `workflow.parallelItems` on**, under either of those modes, a feature from the build
64
+ plan starts in its own worktree instead: follow `reference/item-worktree.md`, which creates
65
+ it on that branch beside the project and moves the spec there. Creating it is part of
66
+ positioning the work, as creating the branch is; removing it is deleting files, and asks.
67
+ An automated run keeps a plain branch per item, inside the run's own worktree when it has
68
+ one, since it removes each item's branch once it lands, and a worktree holding the branch would
69
+ stop that. From then on the item is the worktree's.
70
+ Move the session into it where the tool can; otherwise address every file and
71
+ command to the worktree's path, and tell the user to open later sessions there, since hooks
72
+ keep running where a session started. A resume inside the worktree is the ordinary resume
73
+ below. Fixes, rollbacks and refactor campaigns keep the branch above.
74
+
59
75
  Either way, if the project is not a git repository, say so and ask the user to initialize
60
76
  one. The loop needs history to be reviewable.
61
77
 
@@ -194,7 +210,8 @@ block completion, so close the loop now rather than discovering it later.
194
210
 
195
211
  For each `open` P0 or P1:
196
212
 
197
- 1. **Append it to the spec's build steps** first (`- [ ] Repair F-03 - <title>`), so the
213
+ 1. **Append it to the spec's build steps** first (`- [ ] Repair 39a/F-2 - <title>`, using
214
+ the identifier exactly as the ledger heads it), so the
198
215
  repair is on the record and survives a cleared context. That changes what the spec asks
199
216
  for, so record it as an amendment naming the finding, and renew the stamp.
200
217
  2. Build it through the same loop as Step 2: smallest change, diff, explanation, evidence.
@@ -0,0 +1,133 @@
1
+ # Starting an item in its own worktree
2
+
3
+ Used when `workflow.parallelItems` is `true`, `git.mode` is `branch-per-item` or
4
+ `pull-request`, the spec is a feature from the build plan, and no automated run is underway.
5
+ The item gets its own git worktree beside the project, on the branch Step 1 would otherwise
6
+ create, and its spec moves there. The main checkout is then idle, and `/feature` can spec
7
+ the next item from it. An automated run makes its own worktree with the same blocks; see
8
+ the last section.
9
+
10
+ Run each block as **one** command. Each runs in a subshell, so a stop ends that block and never
11
+ the shell a tool keeps between commands, and nothing set in one block survives into the next:
12
+ each sets what it needs. A block that stops ends the start: report what it printed and stop.
13
+
14
+ A branch whose name holds a `'` is refused before anything runs, since the blocks quote it.
15
+
16
+ ## 1. Check, then create
17
+
18
+ (
19
+ root=$(git rev-parse --show-toplevel) || exit 1
20
+ [ "$(git -C "$root" rev-parse --absolute-git-dir)" = "$(git -C "$root" rev-parse --path-format=absolute --git-common-dir)" ] ||
21
+ { echo "not the main checkout: $root"; exit 1; }
22
+ [ -z "$(git -C "$root" status --porcelain -- . ':!religion/context/current-work.md' ':!religion/context/handoff.md')" ] ||
23
+ { echo "uncommitted changes beyond the spec"; exit 1; }
24
+ branch='<the branch Step 1 names>'
25
+ tree="${root%/*}/${root##*/}.$(printf '%s' "$branch" | tr / -)"
26
+ [ ! -e "$tree" ] && [ ! -L "$tree" ] || { echo "already exists: $tree"; exit 1; }
27
+ ! git -C "$root" show-ref --verify --quiet "refs/heads/$branch" || { echo "branch exists: $branch"; exit 1; }
28
+ git -C "$root" worktree add -q -b "$branch" "$tree" HEAD || exit 1
29
+ echo "$tree"
30
+ )
31
+
32
+ Started from inside a linked worktree, the first check stops: that worktree is an item already,
33
+ and a second one made from it would land on top of it. Anything uncommitted but the spec and
34
+ the generated handoff stops it too, settings and plan edits included, since the worktree is
35
+ made from `HEAD` and would run without them. Commit them first.
36
+
37
+ The path is the project's directory name, a dot, and the branch with each `/` as `-`, in the
38
+ project's parent directory: `religion` building `feature/export-reports` gets
39
+ `religion.feature-export-reports`. Landing the item later looks for it there, so never choose
40
+ another. A path or branch that already exists is another item's, or a start that stopped after
41
+ this block: when the path is a worktree on this item's branch and the main checkout still holds
42
+ the spec, or for a run when it is a worktree on the run's branch, go on to block 2; otherwise
43
+ stop and say which, never reusing or replacing it.
44
+
45
+ ## 2. Copy what git does not carry, then move the spec
46
+
47
+ Safe to run again until block 3 has run, and it refuses after that. Use the same branch as
48
+ block 1:
49
+
50
+ (
51
+ root=$(git rev-parse --show-toplevel) || exit 1
52
+ branch='<the branch Step 1 names>'
53
+ move='yes'
54
+ tree="${root%/*}/${root##*/}.$(printf '%s' "$branch" | tr / -)"
55
+ [ "$(git -C "$tree" branch --show-current 2>/dev/null)" = "$branch" ] || { echo "not this item's worktree: $tree"; exit 1; }
56
+ spec="religion/context/current-work.md"
57
+ if [ "$move" = yes ]; then
58
+ ! grep -q '_Nothing in progress' "$root/$spec" || { echo "the main checkout holds no spec to move"; exit 1; }
59
+ if [ -f "$tree/$spec" ] && ! grep -q '_Nothing in progress' "$tree/$spec" && ! cmp -s "$root/$spec" "$tree/$spec"; then
60
+ echo "the worktree already holds another spec"; exit 1
61
+ fi
62
+ fi
63
+ for f in .claude/settings.json .claude/settings.local.json .claude/hooks; do
64
+ if [ -e "$root/$f" ] && git -C "$root" check-ignore -q "$f"; then
65
+ mkdir -p "$tree/$(dirname "$f")" && cp -RPp "$root/$f" "$tree/$(dirname "$f")/" || exit 1
66
+ fi
67
+ done
68
+ if git -C "$root" check-ignore -q religion; then
69
+ (cd "$root/religion" && find . -path ./.state -prune -o -type f -print) > "$tree.files" || exit 1
70
+ while IFS= read -r f; do
71
+ mkdir -p "$tree/religion/$(dirname "$f")" && cp -Pp "$root/religion/$f" "$tree/religion/$f" || exit 1
72
+ done < "$tree.files"
73
+ rm -f "$tree.files"
74
+ fi
75
+ for d in node_modules; do
76
+ [ -d "$root/$d" ] || continue
77
+ [ -e "$tree/$d" ] || [ -L "$tree/$d" ] || ln -s "$root/$d" "$tree/$d" || exit 1
78
+ git -C "$tree" check-ignore -q "$d" || printf '/%s\n' "$d" >> "$(git -C "$root" rev-parse --path-format=absolute --git-path info/exclude)" || exit 1
79
+ done
80
+ if git -C "$root" check-ignore -q religion && [ -f "$root/religion/context/findings.md" ]; then
81
+ mkdir -p "$tree/religion/.state" && cp -p "$root/religion/context/findings.md" "$tree/religion/.state/findings-at-start.md" || exit 1
82
+ fi
83
+ if [ "$move" = yes ]; then
84
+ mkdir -p "$tree/religion/context" && cp -p "$root/$spec" "$tree/$spec" && cmp -s "$root/$spec" "$tree/$spec" || exit 1
85
+ fi
86
+ echo "copied"
87
+ )
88
+
89
+ The installer's output that git ignores is copied only where git ignores it; a tracked copy is
90
+ already in the worktree. When `religion/` itself is ignored, which `doctor` reports as "state is
91
+ local only", every state file but `religion/.state/` is copied, since each worktree keeps its own
92
+ activity record; the ledger as it stood is saved in the worktree's `religion/.state/` as
93
+ `findings-at-start.md`, the base landing later tells this item's findings apart by. The list of files is written beside the worktree, not piped, so a failed copy
94
+ stops the block in every shell; a block that stopped there leaves that list, `<worktree>.files`,
95
+ and the rerun removes it.
96
+
97
+ The checks at the top are what make a rerun safe. Once block 3 has reset the main checkout's
98
+ spec, there is nothing to move, and copying would put the stub over the only copy of the spec.
99
+ A worktree that already holds a different spec belongs to work that has started, and copying the
100
+ main checkout's over it would replace that work.
101
+
102
+ Each installed dependency directory at the project root that the gate needs is linked, never
103
+ installed: an install needs its own yes. Name each one in the `for d` list; `node_modules` is the
104
+ usual one. A pattern such as `node_modules/` matches a directory but not a link to one, so a link
105
+ git would not ignore is added to the repository's own exclude file, which is never committed;
106
+ without that, the link would be committed with the item's work.
107
+
108
+ ## 3. Reset the main checkout's spec
109
+
110
+ Only after block 2 printed `copied`: reset the main checkout's
111
+ `religion/context/current-work.md` to its stub, exactly as shipped, as `/complete` does.
112
+ The spec now lives only in the worktree. That is a move, not a deletion: if the copy did not
113
+ match, nothing is reset, and the spec is still where it was.
114
+
115
+ ## 4. Confirm
116
+
117
+ From the main checkout, `religion status` lists the item under `inFlight` with its branch and
118
+ `here` false, and reports nothing active. From the worktree, it reports the item as active, and
119
+ `religion doctor` there names the main checkout in its git check. Without the `religion`
120
+ command, the handoff and the two specs say the same.
121
+
122
+ From here on, every file and command of this item is the worktree's. Removing the worktree is
123
+ deleting files, so it asks, every time.
124
+
125
+ ## A run's worktree
126
+
127
+ `/auto` under `pull-request` with `workflow.parallelItems` on makes its worktree with blocks
128
+ 1 and 2: `branch` is the run's integration branch, and block 2 sets `move='no'`, since a run
129
+ starts with no spec to move. Block 2 then copies only what git does not carry; the worktree's
130
+ spec is whatever its branch holds, the stub. Block 3 is an item's and never runs for a run.
131
+
132
+ Once the run writes its activity record there, `religion status` in the main checkout lists the
133
+ run under `inFlight` with the items it holds, as block 4 describes for an item.
@@ -67,7 +67,9 @@ Stop on any failure. Do not repair a mismatch by choosing a nearby commit.
67
67
  1. Every recorded identifier matches `^[0-9a-f]{40}$`. Reject abbreviated or uppercase
68
68
  values.
69
69
  2. Every recorded commit resolves in this repository and is an ancestor of `HEAD`.
70
- 3. The recorded base is the parent of the earliest recorded commit.
70
+ 3. The recorded base is the parent of the earliest recorded commit. For an item landed on top
71
+ of another, that commit is the merge that brought the other in, and the base must be its
72
+ second parent, what it brought in: the first parent would reverse the other item's work.
71
73
  4. The working tree is clean apart from the rollback spec being written.
72
74
 
73
75
  ## Step 3 - preview the product diff
@@ -43,7 +43,8 @@ Implementation lands one small step at a time, each with a diff to read and evid
43
43
  its stated outcome was met.
44
44
 
45
45
  `religion/context/current-work.md` holds exactly one work item. Finish it, archive it,
46
- then start the next. Progress lives in checkboxes inside that file, so a cleared context
46
+ then start the next. With `workflow.parallelItems` on, other items may be in flight in other
47
+ git worktrees, one each; they land one at a time. Progress lives in checkboxes inside that file, so a cleared context
47
48
  costs nothing: a fresh session reads which steps are ticked and resumes from the first
48
49
  one that is not.
49
50
 
@@ -221,6 +222,16 @@ its intended handoff, such as an unattended run waiting for review. Use `blocked
221
222
  exact recovery command when work can resume. `boundary` is `read-only`, `reviewed`, or
222
223
  `local-only`. Everything after `updatedAt` is optional.
223
224
 
225
+ An `auto` run given explicit items also writes `items`, the plan numbers it holds as strings,
226
+ such as `["6", "7", "8"]`, on every write in the checkout it runs from, starting once preflight
227
+ knows which that is. Other worktrees pass those items over, including the ones the run has not
228
+ reached yet. Only when none of them is left to build, after any aggregate pull request is open,
229
+ does its last write, `completed`, keep just the items it completed, and a parent number only
230
+ when all of its sub-items were; when none is left, a run that completed nothing releases at
231
+ once. Every earlier stop keeps them all and is `blocked`.
232
+
233
+ `$auto refresh` writes none: it acts on a run whose record holds that run's items.
234
+
224
235
  Writing this record grants nothing and bypasses nothing. A failure to write it is reported
225
236
  and ignored: reporting must never turn into a workflow failure.
226
237
 
@@ -35,7 +35,8 @@ Implementation lands one small step at a time, each with a diff to read and evid
35
35
  its stated outcome was met.
36
36
 
37
37
  `religion/context/current-work.md` holds exactly one work item. Finish it, archive it,
38
- then start the next. Progress lives in checkboxes inside that file, so a cleared context
38
+ then start the next. With `workflow.parallelItems` on, other items may be in flight in other
39
+ git worktrees, one each; they land one at a time. Progress lives in checkboxes inside that file, so a cleared context
39
40
  costs nothing: a fresh session reads which steps are ticked and resumes from the first
40
41
  one that is not.
41
42
 
@@ -185,6 +186,16 @@ its intended handoff, such as an unattended run waiting for review. Use `blocked
185
186
  exact recovery command when work can resume. `boundary` is `read-only`, `reviewed`, or
186
187
  `local-only`. Everything after `updatedAt` is optional.
187
188
 
189
+ An `auto` run given explicit items also writes `items`, the plan numbers it holds as strings,
190
+ such as `["6", "7", "8"]`, on every write in the checkout it runs from, starting once preflight
191
+ knows which that is. Other worktrees pass those items over, including the ones the run has not
192
+ reached yet. Only when none of them is left to build, after any aggregate pull request is open,
193
+ does its last write, `completed`, keep just the items it completed, and a parent number only
194
+ when all of its sub-items were; when none is left, a run that completed nothing releases at
195
+ once. Every earlier stop keeps them all and is `blocked`.
196
+
197
+ `/auto refresh` writes none: it acts on a run whose record holds that run's items.
198
+
188
199
  Writing this record grants nothing and bypasses nothing. A failure to write it is reported
189
200
  and ignored: reporting must never turn into a workflow failure.
190
201
 
@@ -2,7 +2,8 @@
2
2
  "schemaVersion": 1,
3
3
  "workflow": {
4
4
  "stepReview": "every",
5
- "parallelSteps": false
5
+ "parallelSteps": false,
6
+ "parallelItems": false
6
7
  },
7
8
  "git": {
8
9
  "mode": "trunk",