@erclx/aitk 0.46.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-address-review/REQUIREMENT.md +13 -1
- package/claude/skills/claude-address-review/SKILL.md +101 -7
- package/claude/skills/claude-tasks/SKILL.md +1 -1
- package/claude/skills/create-snippet/references/snippets.md +12 -1
- package/claude/skills/git-followup/REQUIREMENT.md +2 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-pr/SKILL.md +1 -1
- package/docs/ai-workflow.md +2 -2
- package/docs/operating-model.md +10 -2
- package/package.json +1 -1
- package/scripts/core/install-check.sh +5 -1
- package/snippets/align.md +12 -0
- package/snippets/snippets.toml +8 -2
- package/standards/bundled/snippets.md +12 -1
- package/standards/tasks.md +6 -3
- package/tooling/claude/manifest.toml +1 -1
- package/tooling/claude/reference.md +1 -1
- package/snippets/create-snippet.md +0 -7
|
@@ -9,14 +9,21 @@ description: What the review return leg is for, the gaps it closes, and why the
|
|
|
9
9
|
|
|
10
10
|
Without this skill, review findings are worked in whatever order the author read them and the thread never records which landed. A reply posted before the push describes code the remote does not have, so a reviewer checks the branch and finds the old version. A failing check gets treated as separate from the review, which produces a follow-up that answers every comment and leaves continuous integration red. One finding nobody can resolve stalls the rest.
|
|
11
11
|
|
|
12
|
+
A branch also goes stale from `main` moving rather than from anything the branch did. Nothing in the return leg rebases it, so the worker closes every finding, reports the pull request answered, and the branch still cannot merge. Half the resolution is mechanical and wrong to do by hand, since a generated file merged manually produces a diff the next regen discards.
|
|
13
|
+
|
|
12
14
|
## Must
|
|
13
15
|
|
|
14
16
|
- Treat a failing check as a finding alongside the review comments, so the follow-up closes both
|
|
15
17
|
- Handle each finding independently, so one unresolved item does not block the others
|
|
16
18
|
- Verify before pushing, since a red follow-up costs the reviewer a second pass
|
|
19
|
+
- Rebase onto `origin/main` when the branch no longer merges, after the findings are addressed and before the push, so one force-push carries both
|
|
20
|
+
- Test staleness on every invocation, including one carrying no findings, since a branch goes stale from `main` moving rather than from anything the review said
|
|
21
|
+
- Re-test once the fixes are commits, since the first test reads committed history and cannot see a fix that touches lines `main` moved
|
|
22
|
+
- Rebuild a generated file through the project check rather than resolving its conflict by hand
|
|
17
23
|
- Push before replying, so the comment never runs ahead of the code it describes
|
|
18
24
|
- Map every finding to what changed, or to a one-line reason when it is a question or a conscious accept
|
|
19
25
|
- Post the terminal comment only when the findings are addressed and every check passes
|
|
26
|
+
- Say what the run actually did on a rebase-only pass, since a reply mapping findings and a terminal comment claiming they were addressed are both false on a pull request carrying none
|
|
20
27
|
- Scan the reply for banned characters and internal phase labels before posting, since the comment leaves for the remote unchecked
|
|
21
28
|
|
|
22
29
|
## Must not
|
|
@@ -26,11 +33,15 @@ Without this skill, review findings are worked in whatever order the author read
|
|
|
26
33
|
- Post the closing comment while a check is failing
|
|
27
34
|
- Reimplement the follow-up push or the doc refresh. Both have owners, and a second copy here drifts from them.
|
|
28
35
|
- Edit silently. A finding answered without a reply leaves the reviewer re-deriving the change from the diff.
|
|
36
|
+
- Take one side of a conflict wholesale. Both sides are valid content, so `--ours` or `--theirs` drops one silently and passes every check.
|
|
37
|
+
- Merge `main` into the branch. The repository squash-merges, so a merge commit reads as noise on the pull request.
|
|
38
|
+
- Guess at a hunk the tree does not settle. That case reaches the operator as an ordinary finding on the next pass only if the worker stops.
|
|
29
39
|
|
|
30
40
|
## Guards
|
|
31
41
|
|
|
32
42
|
- No open pull request for the current branch: stop
|
|
33
|
-
- The pull request carries no review comments or threads: stop with a pass
|
|
43
|
+
- The pull request carries no review comments or threads and the branch still merges: stop with a pass. A closed review says nothing about whether the branch still merges, so the staleness test decides this one rather than the finding count.
|
|
44
|
+
- A conflict needing a decision the tree does not carry: stop with the branch left on its old base
|
|
34
45
|
|
|
35
46
|
## Out of scope
|
|
36
47
|
|
|
@@ -38,3 +49,4 @@ Without this skill, review findings are worked in whatever order the author read
|
|
|
38
49
|
- Staging, committing, and pushing the follow-up, which `git-followup` owns under this skill's direction
|
|
39
50
|
- Refreshing the `.claude/` docs the fixes made stale, which `claude-docs` owns
|
|
40
51
|
- Re-reviewing its own fixes, which hands back to the orchestrator
|
|
52
|
+
- Re-reading a rewritten branch, which `claude-pr-review` absorbs by testing whether the prior reviewed commit still reaches the head and paying for a full pass when it does not
|
|
@@ -11,7 +11,7 @@ the PR from an independent session. This skill consumes them: fix, reply, push.
|
|
|
11
11
|
## Guards
|
|
12
12
|
|
|
13
13
|
- If no open PR resolves for the current branch via `gh pr view`, stop: `❌ No open PR. Nothing to address.`
|
|
14
|
-
- If the PR has no review comments or threads,
|
|
14
|
+
- If the PR has no review comments or threads, run step 5's staleness test before deciding. A branch that still merges stops here: `✅ No review findings to address.` One that does not skips steps 1 through 4 and runs step 5 onward, since a branch goes stale from `main` moving and a closed review says nothing about whether it still merges.
|
|
15
15
|
- Fix findings. Do not merge.
|
|
16
16
|
|
|
17
17
|
## Step 1: pull the review findings and CI status
|
|
@@ -48,7 +48,57 @@ Do not push a red follow-up.
|
|
|
48
48
|
|
|
49
49
|
The fixes may have changed or added behavior that `.claude/` context entries, docs, or wireframes describe. Refresh them with the `claude-docs` skill, which maps the changed files to the entries that reference them and rewrites the stale sections. Do not reimplement that mapping here. When a fix adds a new capability with no existing entry, `claude-docs` flags it rather than creating one.
|
|
50
50
|
|
|
51
|
-
## Step 5:
|
|
51
|
+
## Step 5: rebase a stale branch
|
|
52
|
+
|
|
53
|
+
A branch goes stale from `main` moving rather than from anything the branch did,
|
|
54
|
+
so the test runs on every invocation, including the one the second guard sends
|
|
55
|
+
straight here with no findings to fix. Fetch first. A stale local `origin/main`
|
|
56
|
+
reports no conflict on a branch that has one.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git fetch origin main
|
|
60
|
+
git merge-tree --write-tree origin/main HEAD
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
A zero exit means the branch still merges. Skip to step 6. A non-zero exit means
|
|
64
|
+
it does not. Stash the fixes first when `git status --porcelain` reports
|
|
65
|
+
anything, since a rebase refuses to run over a dirty tree, then rebase onto
|
|
66
|
+
`origin/main` and restore them:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git stash push -u
|
|
70
|
+
git rebase origin/main
|
|
71
|
+
git stash pop
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Pop only when the stash ran. On a clean tree, which is what a run whose findings
|
|
75
|
+
were all conscious-accepts leaves behind, `git stash push` saves nothing and
|
|
76
|
+
exits zero, so the pop restores an unrelated entry from an earlier session.
|
|
77
|
+
|
|
78
|
+
Never merge `main` into the branch. The repository squash-merges, so a merge
|
|
79
|
+
commit here reads as noise on the pull request.
|
|
80
|
+
|
|
81
|
+
Resolve every conflict under these rules, which apply to a hunk from the rebase
|
|
82
|
+
and a hunk from the stash pop alike:
|
|
83
|
+
|
|
84
|
+
- Never take one side wholesale with `--ours` or `--theirs`. Both sides are valid content, so the drop is silent and passes every check.
|
|
85
|
+
- Never resolve a generated file by hand. A file the project check rebuilds, such as an `index.md` carrying no `auto: false`, takes either side to clear the conflict and gets its real content from the regen below.
|
|
86
|
+
- Where two branches wrote prose into one file, keep both sides and rewrite what the merge broke. A section that opens by counting what follows needs the count updated rather than the two versions concatenated.
|
|
87
|
+
- When a hunk needs a decision the tree does not carry, stop rather than guessing, and name where the branch was left. The two sources recover differently. A hunk raised by the rebase takes `git rebase --abort`, which restores the old base: `❌ Conflict needs a decision at <file>. Branch left on its old base.` A hunk raised by the stash pop arrives after the rebase already landed, so no abort applies and the conflict stays in the tree: `❌ Conflict needs a decision at <file>. Branch rebased, fixes left conflicted in the tree.` A guess that compiles is the failure this stage would otherwise introduce, and either case reaches the operator as an ordinary finding on the next review pass.
|
|
88
|
+
|
|
89
|
+
Both sides of every hunk sit in the conflict and `git log origin/main` names what
|
|
90
|
+
landed, so the tree carries the context. Do not wait on the orchestrator for it.
|
|
91
|
+
|
|
92
|
+
Re-run the project check after the rebase. It rebuilds the generated files and
|
|
93
|
+
covers what the replayed commits broke, and step 6 commits the result alongside
|
|
94
|
+
the fixes.
|
|
95
|
+
|
|
96
|
+
`git merge-tree` reads committed history, so this test says nothing about the
|
|
97
|
+
fixes still sitting in the working tree. A branch that merges clean as committed,
|
|
98
|
+
whose fixes touch lines `main` moved, passes here and reaches the remote
|
|
99
|
+
unmergeable. Step 6 re-runs the test once those fixes are commits.
|
|
100
|
+
|
|
101
|
+
## Step 6: push, then reply
|
|
52
102
|
|
|
53
103
|
Push the fixes before posting the reply so the comment never runs ahead of the
|
|
54
104
|
code it describes. Ship the fixes as a follow-up commit on the same branch with
|
|
@@ -56,7 +106,21 @@ the `git-followup` skill, invoked with `reply-owned` so it stages, commits,
|
|
|
56
106
|
pushes, and refreshes the open PR body without posting its own comment. This
|
|
57
107
|
skill owns the reply. Do not reimplement that flow here. For in-place fixes to
|
|
58
108
|
files the PR body already covers, `git-followup` leaves the body untouched and
|
|
59
|
-
the reply comment carries the fix log.
|
|
109
|
+
the reply comment carries the fix log. A rebase in step 5 rewrote the branch, so
|
|
110
|
+
that push is a force-push and `git-followup` resolves it from the tracking
|
|
111
|
+
branch. Worker branches are single-owner here, which is what makes overwriting
|
|
112
|
+
the remote safe.
|
|
113
|
+
|
|
114
|
+
`git-followup` stops on an unchanged tree. A run that answered every finding as a
|
|
115
|
+
conscious-accept and whose rebase left the generated files alone has nothing for
|
|
116
|
+
it to commit, so the rebase would never reach the remote. Push that case directly
|
|
117
|
+
with `git push --force-with-lease`, then post the reply below.
|
|
118
|
+
|
|
119
|
+
Once the fixes are commits, re-run step 5's staleness test against the new head.
|
|
120
|
+
A conflict that appears only now is one the fixes introduced against lines `main`
|
|
121
|
+
moved, which the earlier test could not see. Rebase again under step 5's rules
|
|
122
|
+
and force-push, then continue. The second push costs one extra force-push in a
|
|
123
|
+
case that needs the fix and the sibling to touch the same lines.
|
|
60
124
|
|
|
61
125
|
Then write a summary reply to `.claude/.tmp/address-review/reply-<number>.md`
|
|
62
126
|
mapping each finding to what changed, or to a one-line reason when it is a
|
|
@@ -72,6 +136,18 @@ review itself carries. Follow it with a one-line summary sentence, then one
|
|
|
72
136
|
bullet per finding, each opening with the bolded finding identifier.
|
|
73
137
|
Close the body with `🤖 Addressed by Claude Code` on its own line so the reply
|
|
74
138
|
reads as an independent machine pass, not a human sign-off.
|
|
139
|
+
When step 5 rebased the branch, say so in the summary sentence and name which
|
|
140
|
+
files were resolved by hand and which the regen rebuilt. The next review is a
|
|
141
|
+
full pass rather than a delta, and the reader is owed the reason.
|
|
142
|
+
|
|
143
|
+
A run the second guard sent straight to step 5 has no findings to map, so it
|
|
144
|
+
takes a different body rather than an empty list. Open it with `## Rebase`, not
|
|
145
|
+
`## Review response`, since nothing on the pull request is being responded to and
|
|
146
|
+
that heading claims a review this run never read. State that the branch stopped
|
|
147
|
+
merging, name what landed on `main`, name the files resolved by hand and those
|
|
148
|
+
the regen rebuilt, and close the same way. The heading stays outside the
|
|
149
|
+
`## Review` family so the close-out's equality test on the first line never
|
|
150
|
+
matches it.
|
|
75
151
|
|
|
76
152
|
Before posting, run the scan in `.claude/standards/publish.md`
|
|
77
153
|
against the reply, or `${CLAUDE_SKILL_DIR}/../../standards/publish.md` when
|
|
@@ -82,7 +158,7 @@ only gate on the published reply. Post it to the PR:
|
|
|
82
158
|
gh pr comment <number> --body-file .claude/.tmp/address-review/reply-<number>.md
|
|
83
159
|
```
|
|
84
160
|
|
|
85
|
-
## Step
|
|
161
|
+
## Step 7: confirm resolution
|
|
86
162
|
|
|
87
163
|
After the follow-up push, watch CI on the PR. Poll `gh pr checks <number>`
|
|
88
164
|
until no check is pending, then read the final status. When every finding is
|
|
@@ -93,15 +169,33 @@ clear terminal state:
|
|
|
93
169
|
gh pr comment <number> --body "✅ All review findings addressed, CI green."
|
|
94
170
|
```
|
|
95
171
|
|
|
172
|
+
A rebase-only run addressed no finding, so it takes its own terminal comment
|
|
173
|
+
rather than that one. Claiming findings were addressed on a pull request that
|
|
174
|
+
carries none is false on a surface nothing else checks:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
gh pr comment <number> --body "✅ Rebased onto origin/main, CI green. No review findings were open."
|
|
178
|
+
```
|
|
179
|
+
|
|
96
180
|
If any check fails, do not post the closing comment. Report the failing check
|
|
97
181
|
so it can be fixed first. This is a resolution signal, not a formal approval,
|
|
98
182
|
since the PR author cannot approve their own PR.
|
|
99
183
|
|
|
100
|
-
## Step
|
|
184
|
+
## Step 8: output
|
|
101
185
|
|
|
102
186
|
```plaintext
|
|
103
187
|
Addressed <N> findings on PR #<number>. Follow-up pushed.
|
|
188
|
+
<Rebased onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Omit the second line when the branch still merged. Name any finding left as a
|
|
192
|
+
reply rather than a code change, with its one-line reason.
|
|
193
|
+
|
|
194
|
+
A rebase-only run drops the first line rather than reporting zero findings
|
|
195
|
+
addressed, and leads with the rebase instead:
|
|
196
|
+
|
|
197
|
+
```plaintext
|
|
198
|
+
Rebased PR #<number> onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.
|
|
104
199
|
```
|
|
105
200
|
|
|
106
|
-
|
|
107
|
-
reason. Do not merge. Hand back to the orchestrator for re-review.
|
|
201
|
+
Do not merge. Hand back to the orchestrator for re-review.
|
|
@@ -36,7 +36,7 @@ Do not derive the label from a version file. `.claude/standards/versioning.md` p
|
|
|
36
36
|
|
|
37
37
|
Write `.claude/tasks/vXX.Y-<slug>.md` following the format in `.claude/standards/tasks.md`. Include a link line only when the file or folder it names exists. A link to a plan nobody has written yet is the broken pointer the archive rules exist to prevent.
|
|
38
38
|
|
|
39
|
-
Write `Plan
|
|
39
|
+
Write `Plan:`, `Groundwork:`, and `Intake:` as markdown links relative to `.claude/tasks/`, as in `Plan: [feature-<slug>](../plans/feature-<slug>.md)`. Leave `Issue:` a bare `#NNN`. A task written in the older bare-path form still parses, so it costs the board a clickable line rather than an archive, but it leaves the board in two shapes for every reader after.
|
|
40
40
|
|
|
41
41
|
Never write a `Pull request:` line here. `git-pr` adds it when a pull request opens, and a number guessed at create time points at someone else's work.
|
|
42
42
|
|
|
@@ -8,7 +8,7 @@ consumers: create-snippet
|
|
|
8
8
|
|
|
9
9
|
## Scope
|
|
10
10
|
|
|
11
|
-
Governs a snippet file: what one is for, how it is invoked, and the structure of its body.
|
|
11
|
+
Governs a snippet file: what one is for, whether a prompt qualifies as one, how it is invoked, and the structure of its body.
|
|
12
12
|
|
|
13
13
|
Does not govern:
|
|
14
14
|
|
|
@@ -19,6 +19,17 @@ Does not govern:
|
|
|
19
19
|
|
|
20
20
|
A snippet is a short, focused prompt stored as a plain markdown file. Invoke one to insert a prepared instruction into any AI chat without retyping it. Each snippet covers one purpose. If a prompt needs headers or multiple goals, use a system prompt instead.
|
|
21
21
|
|
|
22
|
+
## Admission
|
|
23
|
+
|
|
24
|
+
Two tests decide whether a prompt becomes a snippet, and both have to pass. Apply them when adding one and when auditing the catalog.
|
|
25
|
+
|
|
26
|
+
- Cadence: a prompt invoked many times across sessions qualifies. A one-shot audit, migration, or bootstrap prompt does not, and belongs in notes outside the catalog.
|
|
27
|
+
- Audience: a prompt the consuming project would invoke ships in `snippets/`. One only the authoring repository can run stays outside every installable folder, which is a rule for a repository that authors snippets for others rather than for one that only consumes them.
|
|
28
|
+
|
|
29
|
+
A subfolder under `snippets/` names where a prompt is invoked rather than what it is about. A prompt that reads or writes the project's own files goes in a folder, and one carrying its whole context in the message goes at the root.
|
|
30
|
+
|
|
31
|
+
Overlapping a skill that does the same job is not disqualifying on its own. A snippet fires when a person asks for it by name and a skill fires on a description match, so the two coexist when those paths differ and the outputs do. Record the reason where the project keeps its decisions, or drop the snippet.
|
|
32
|
+
|
|
22
33
|
## Invocation channels
|
|
23
34
|
|
|
24
35
|
- Chrome extension: type `>slug` in a supported chat UI (claude.ai, gemini.google.com) to insert the snippet text inline
|
|
@@ -7,7 +7,7 @@ description: What the follow-up push is for, the gaps it closes, and how it spli
|
|
|
7
7
|
|
|
8
8
|
## Gap
|
|
9
9
|
|
|
10
|
-
Without this skill, an edit made after a pull request is already open ships as a bare push. The body still describes the scope from before the edit, so a reviewer returning to the page reads a description the diff no longer matches. A reviewer who left comments gets no reply, and when a caller has already posted its own reply, a second one lands underneath it.
|
|
10
|
+
Without this skill, an edit made after a pull request is already open ships as a bare push. The body still describes the scope from before the edit, so a reviewer returning to the page reads a description the diff no longer matches. A reviewer who left comments gets no reply, and when a caller has already posted its own reply, a second one lands underneath it. A caller that rebased the branch before handing over hits a rejected push, since the tracking branch no longer reaches the head.
|
|
11
11
|
|
|
12
12
|
## Must
|
|
13
13
|
|
|
@@ -16,6 +16,7 @@ Without this skill, an edit made after a pull request is already open ships as a
|
|
|
16
16
|
- Sync the body when the new commit moves the scope, and the title when the shift makes it inaccurate
|
|
17
17
|
- Reply on the pull request when it carries review comments, and scan that reply for the banned characters and internal phase labels before posting. The hook watches files and never sees a comment body on its way to the remote.
|
|
18
18
|
- Suppress the reply when the caller owns it, and still run the push and the body sync
|
|
19
|
+
- Force the push under a lease when the tracking branch no longer reaches the head, so a caller's rebase lands and a commit this session never read is not overwritten
|
|
19
20
|
|
|
20
21
|
## Must not
|
|
21
22
|
|
|
@@ -22,7 +22,7 @@ its own reply, so skip the comment in step 6. The push and body sync still run.
|
|
|
22
22
|
1. Run `git status` to confirm the changes are intentional
|
|
23
23
|
2. Run `git add -A` to stage every change
|
|
24
24
|
3. Invoke `aitk:git-commit` to generate one conventional commit from the staged diff
|
|
25
|
-
4. Run `git push` to the tracking branch
|
|
25
|
+
4. Run `git push` to the tracking branch. When `git merge-base --is-ancestor @{u} HEAD` exits non-zero, a caller rewrote the branch and a plain push is rejected, so push with `--force-with-lease` instead. The lease is what stops the force from overwriting a commit this session never read.
|
|
26
26
|
5. Check for existing review comments: `gh api 'repos/{owner}/{repo}/pulls/<number>/comments' --jq 'length'`, resolving `<number>` from `gh pr view --json number`.
|
|
27
27
|
6. When invoked with `reply-owned`, skip this step's comment: the caller posts the reply. Otherwise, if the count is above zero, the followup addresses review feedback: post a one-line summary of the fix with `gh pr comment --body`, first running the scan in `.claude/standards/publish.md` against it, or `${CLAUDE_SKILL_DIR}/../../standards/publish.md` when the project does not have it, since the hook does not see an inline comment body. If it is zero, run `gh pr view --json url,title,body` and update the body with `gh pr edit --body` when the new commit changes scope, and the title with `gh pr edit --title` when the scope shifted enough to make it inaccurate.
|
|
28
28
|
|
|
@@ -109,7 +109,7 @@ Write the `number` the final command printed onto the task the branch is closing
|
|
|
109
109
|
|
|
110
110
|
Find the task by reading `.claude/tasks/` at the main worktree root, resolved with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`. The board is shared scratch, so a linked worktree writing to its own `pwd` creates a second board nothing reads.
|
|
111
111
|
|
|
112
|
-
Confirm the match against the task's `Plan:` line, which names the plan this branch implemented. A branch name does not derive a plan slug and a plan slug does not derive a branch, so neither one alone identifies the task. Add `Pull request: #NNN` under the existing `Plan:`, `Groundwork:`, or `Issue:` lines when the task carries no such line, and correct the number in place when it does.
|
|
112
|
+
Confirm the match against the task's `Plan:` line, which names the plan this branch implemented. A branch name does not derive a plan slug and a plan slug does not derive a branch, so neither one alone identifies the task. Add `Pull request: #NNN` under the existing `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines when the task carries no such line, and correct the number in place when it does.
|
|
113
113
|
|
|
114
114
|
Skip this silently in three cases: no `.claude/tasks/` folder, no task whose `Plan:` line matches, or more than one match. One task, one pull request, so a second match is a misfile that a guessed write would compound. A wrong match archives the wrong task unattended once the branch merges.
|
|
115
115
|
|
package/docs/ai-workflow.md
CHANGED
|
@@ -88,7 +88,7 @@ The sweep reads the whole board rather than the tasks the session touched. It is
|
|
|
88
88
|
|
|
89
89
|
`aitk tasks validate` checks what those rows claim against what the tree holds: every plan pointer resolves, every row and task file map one to one, no task sits in two groups, and no two rows marked ready touch the same file. That last check is the half a reader cannot run by eye, and it is what keeps two workers from being handed colliding work. It reports and never writes, because a row is the orchestrator's claim and a validator repairing one would assert the claim it exists to test. Nothing fires it automatically, since the board is gitignored per-machine scratch with no shared moment to hang a hook on, so the orchestrator's sweep calls it at the point the readiness claim is made.
|
|
90
90
|
|
|
91
|
-
`aitk:claude-tasks` owns the two operations that bracket a task's life. It creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and it moves a shipped task to `.claude/.tmp/task-archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, or an issue, since a task with no origin is either lost context or work nobody decided to do. Archiving a task leaves its plan alone, because `aitk:claude-docs` owns the plans sweep and already holds the last-live-citation rule. That makes the order load-bearing, so the archive verb refuses to run while the `Plan:` line still points into `.claude/plans/`. The sweep only reaches tasks still in the live folder, and archiving the task first would strand the plan there with nothing citing it.
|
|
91
|
+
`aitk:claude-tasks` owns the two operations that bracket a task's life. It creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and it moves a shipped task to `.claude/.tmp/task-archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do. Archiving a task leaves its plan alone, because `aitk:claude-docs` owns the plans sweep and already holds the last-live-citation rule. That makes the order load-bearing, so the archive verb refuses to run while the `Plan:` line still points into `.claude/plans/`. The sweep only reaches tasks still in the live folder, and archiving the task first would strand the plan there with nothing citing it.
|
|
92
92
|
|
|
93
93
|
Nothing chained that archive until the `post-merge` git hook landed. Every earlier step fires from `aitk:claude-autoship` or `aitk:git-ship`, both of which finish while the pull request is still open, so a task archived there would close for work that may be abandoned. The board is gitignored, which rules out reading it from anywhere but the machine that pulled. The hook names the board's archive candidates and stays silent otherwise, including on a project with no board.
|
|
94
94
|
|
|
@@ -139,7 +139,7 @@ Before the first feature session on a UI-heavy project, pick a design tier. The
|
|
|
139
139
|
| `aitk:claude-design-extract` | Draft `.claude/DESIGN.md`, sourcing tokens from existing UI code or proposing them from requirements on day one |
|
|
140
140
|
| `aitk:claude-review` | In a fresh session, review all changes since main |
|
|
141
141
|
| `aitk:claude-pr-review` | Review an open PR from an independent session, then re-review the commits added since until nothing is open |
|
|
142
|
-
| `aitk:claude-address-review` | Address PR findings and CI status, refresh stale docs, then push a follow-up
|
|
142
|
+
| `aitk:claude-address-review` | Address PR findings and CI status, refresh stale docs, rebase a branch that stopped merging, then push a follow-up |
|
|
143
143
|
| `aitk:claude-tasks` | Add a task to `.claude/tasks/` or archive a shipped one out of the folder |
|
|
144
144
|
| `aitk:claude-docs` | When decisions diverged from plan, update `.claude/` docs |
|
|
145
145
|
| `aitk:claude-ui-test` | After UI changes, generate and run e2e tests + visual checklist |
|
package/docs/operating-model.md
CHANGED
|
@@ -33,9 +33,9 @@ One feature travels this path end to end.
|
|
|
33
33
|
2. Orchestrator plans the next feature with `claude-feature`, writing a plan to `.claude/plans/`. Planning stays in the warm session because good planning is cross-feature. It needs the contract other features consume and the shared wiring seam. A cold session would re-derive or guess.
|
|
34
34
|
3. The human opens a worker worktree with `claude-worktree` and runs `claude-autoship` against the plan. The worker builds, self-checks, opens a PR, and stops at the PR boundary.
|
|
35
35
|
4. Orchestrator reviews the PR with `claude-pr-review` and posts findings to it.
|
|
36
|
-
5. Worker addresses the findings with `claude-address-review`, then pushes a follow-up.
|
|
36
|
+
5. Worker addresses the findings with `claude-address-review`, rebases onto `origin/main` when a sibling landed first and left the branch unable to merge, then pushes a follow-up.
|
|
37
37
|
6. Orchestrator closes the review out with `claude-pr-review` again. The second pass reads only the commits the follow-up added, and posts under `## Review closed` when it finds nothing open or under `## Review` when it does, so a reader learns the state from the heading. Repeat from step 5 until the review closes.
|
|
38
|
-
7. The human reads the result and merges. The orchestrator tells any trailing worker
|
|
38
|
+
7. The human reads the result and merges. The orchestrator tells any trailing worker whose branch shares a seam with the merged one to run `claude-address-review`, which rebases whether or not the review left anything open.
|
|
39
39
|
|
|
40
40
|
There is no loop construct here. Each worker is a single build that halts at the
|
|
41
41
|
PR. The merge stays a manual human gate. Reliability comes from the plan being
|
|
@@ -61,6 +61,14 @@ the PR. `claude-address-review` reads them back, fixes each, replies or resolves
|
|
|
61
61
|
the threads, and pushes a follow-up. `claude-pr-review` then runs again, reading
|
|
62
62
|
only what the follow-up added.
|
|
63
63
|
|
|
64
|
+
A branch that stopped merging while the review was open is the worker's problem
|
|
65
|
+
to close. `claude-address-review` rebases onto `origin/main` between the fixes
|
|
66
|
+
and the push, so one force-push carries both and the reviewer reads one delta.
|
|
67
|
+
The staleness test sits ahead of the no-findings guard, so a branch whose review
|
|
68
|
+
closed clean and then went stale still rebases when the skill is invoked. The
|
|
69
|
+
re-read costs a full pass rather than a delta, since the prior reviewed commit no
|
|
70
|
+
longer reaches the head, and `claude-pr-review` detects that itself.
|
|
71
|
+
|
|
64
72
|
The heading carries the state rather than the pass number. A pass with a finding
|
|
65
73
|
takes `## Review` and a pass with none takes `## Review closed`, so a thread can
|
|
66
74
|
be scanned for what is still open without opening a comment. The feedback
|
package/package.json
CHANGED
|
@@ -75,7 +75,11 @@ log_step "Assert scaffold"
|
|
|
75
75
|
# no assertion can truncate silently: init still exits 0 because run_domain
|
|
76
76
|
# catches a failed domain, and the gate stays green while the target is
|
|
77
77
|
# missing everything that domain provides.
|
|
78
|
-
|
|
78
|
+
#
|
|
79
|
+
# The snippets path has to name a slug the default preset still carries, since
|
|
80
|
+
# init resolves snippets through `essentials`. Editing that preset without
|
|
81
|
+
# editing this line fails the gate on a correct install.
|
|
82
|
+
for path in "CLAUDE.md" ".claude/snippets/decision-help.md" ".claude/standards/prose.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
|
|
79
83
|
".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
|
|
80
84
|
".claude/rules/core/000-constitution.md"; do
|
|
81
85
|
if [ ! -e "$TARGET_DIR/$path" ]; then
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Check alignment before acting, not after. State three lines, then proceed.
|
|
2
|
+
|
|
3
|
+
- Outcome: what will be true when this is done
|
|
4
|
+
- Scope: what this deliberately does not touch
|
|
5
|
+
- Assumption: the one inference that would change the work if it is wrong
|
|
6
|
+
|
|
7
|
+
Act without waiting, unless being wrong about the assumption wastes the work rather than costing an edit.
|
|
8
|
+
|
|
9
|
+
- Three lines, not three paragraphs
|
|
10
|
+
- Name the inference you are least sure of, not the safest one
|
|
11
|
+
- Do not ask what the request already answers
|
|
12
|
+
- Silence is agreement
|
package/snippets/snippets.toml
CHANGED
|
@@ -8,7 +8,7 @@ consumers: create-snippet
|
|
|
8
8
|
|
|
9
9
|
## Scope
|
|
10
10
|
|
|
11
|
-
Governs a snippet file: what one is for, how it is invoked, and the structure of its body.
|
|
11
|
+
Governs a snippet file: what one is for, whether a prompt qualifies as one, how it is invoked, and the structure of its body.
|
|
12
12
|
|
|
13
13
|
Does not govern:
|
|
14
14
|
|
|
@@ -19,6 +19,17 @@ Does not govern:
|
|
|
19
19
|
|
|
20
20
|
A snippet is a short, focused prompt stored as a plain markdown file. Invoke one to insert a prepared instruction into any AI chat without retyping it. Each snippet covers one purpose. If a prompt needs headers or multiple goals, use a system prompt instead.
|
|
21
21
|
|
|
22
|
+
## Admission
|
|
23
|
+
|
|
24
|
+
Two tests decide whether a prompt becomes a snippet, and both have to pass. Apply them when adding one and when auditing the catalog.
|
|
25
|
+
|
|
26
|
+
- Cadence: a prompt invoked many times across sessions qualifies. A one-shot audit, migration, or bootstrap prompt does not, and belongs in notes outside the catalog.
|
|
27
|
+
- Audience: a prompt the consuming project would invoke ships in `snippets/`. One only the authoring repository can run stays outside every installable folder, which is a rule for a repository that authors snippets for others rather than for one that only consumes them.
|
|
28
|
+
|
|
29
|
+
A subfolder under `snippets/` names where a prompt is invoked rather than what it is about. A prompt that reads or writes the project's own files goes in a folder, and one carrying its whole context in the message goes at the root.
|
|
30
|
+
|
|
31
|
+
Overlapping a skill that does the same job is not disqualifying on its own. A snippet fires when a person asks for it by name and a skill fires on a description match, so the two coexist when those paths differ and the outputs do. Record the reason where the project keeps its decisions, or drop the snippet.
|
|
32
|
+
|
|
22
33
|
## Invocation channels
|
|
23
34
|
|
|
24
35
|
- Chrome extension: type `>slug` in a supported chat UI (claude.ai, gemini.google.com) to insert the snippet text inline
|
package/standards/tasks.md
CHANGED
|
@@ -125,6 +125,7 @@ description: One line on what this task achieves
|
|
|
125
125
|
|
|
126
126
|
Plan: [feature-<slug>](../plans/feature-<slug>.md)
|
|
127
127
|
Groundwork: [<slug>](../.tmp/groundwork/<slug>/)
|
|
128
|
+
Intake: [<slug>](../intake/<slug>/)
|
|
128
129
|
Issue: #NNN
|
|
129
130
|
Pull request: #NNN
|
|
130
131
|
|
|
@@ -144,11 +145,11 @@ Why this task exists and what it depends on.
|
|
|
144
145
|
|
|
145
146
|
## Origin
|
|
146
147
|
|
|
147
|
-
Every task names where it came from, through a `Plan:`, `Groundwork:`, or `Issue:` line under the title. Include each only when the file, folder, or issue it names exists.
|
|
148
|
+
Every task names where it came from, through a `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` line under the title. Include each only when the file, folder, or issue it names exists.
|
|
148
149
|
|
|
149
|
-
A task with no origin is either lost context or work nobody decided to do. The invariant runs both ways, and the second direction is the one that bites: a groundwork track or an open issue that no task points at is work already decided and on its way to being forgotten.
|
|
150
|
+
A task with no origin is either lost context or work nobody decided to do. The invariant runs both ways, and the second direction is the one that bites: a groundwork track or an open issue that no task points at is work already decided and on its way to being forgotten. An intake folder is exempt from that direction, since it dispositions many items at once and most of them close without ever becoming a task.
|
|
150
151
|
|
|
151
|
-
`Plan
|
|
152
|
+
`Plan:`, `Groundwork:`, and `Intake:` name their target as a markdown link whose text is the file or folder stem, so the line resolves on a ctrl-click the way `priority.md` rows already do. Write the path relative to `.claude/tasks/`, which makes it `../plans/`, `../.tmp/groundwork/`, and `../intake/`. A path written from the project root renders as a link and resolves to nothing in an editor rooted at the project. `Issue:` stays a bare `#NNN`, since an issue number is not a path and a full URL would write the remote into a gitignored file.
|
|
152
153
|
|
|
153
154
|
Phase-label format and where labels may appear are governed by `standards/versioning.md`.
|
|
154
155
|
|
|
@@ -156,6 +157,8 @@ Phase-label format and where labels may appear are governed by `standards/versio
|
|
|
156
157
|
|
|
157
158
|
`Groundwork:` points at `../.tmp/groundwork/<slug>/`, the folder `claude-groundwork` fills. It names the surface it points at the way `Plan:` does. Use this key alone. `Research record` and `Decision record` are earlier spellings of the same thing and both convert to it.
|
|
158
159
|
|
|
160
|
+
`Intake:` points at `../intake/<slug>/`, the folder an intake pass fills. Use it rather than `Groundwork:`, because a groundwork track measures one question in depth while an intake dispositions many across a tree, and one key covering both loses which kind of pass produced the task. The line names the folder rather than an item inside it. A task routinely promotes several items at once, so an anchored line would name one and drop the rest, and the item numbers belong in that task's `## Findings`.
|
|
161
|
+
|
|
159
162
|
`Pull request:` records which pull request carries the task's work, as a bare `#NNN` the way `Issue:` does. It is not an origin, so a task without one is well-formed. `git-pr` writes it when a pull request opens, which is the one step that always runs whether the chain drives it or a person does.
|
|
160
163
|
|
|
161
164
|
The line is what lets a merge close its own task. Every merge on `main` is a squash carrying the number in its subject, so the number survives where a branch name does not, and `aitk tasks archive --pull-request <n>` resolves the task from it. Without the line the board can only be swept blind, and a blind sweep cannot tell a shipped task from an abandoned one. One task, one pull request: two tasks naming the same number refuse to archive rather than both moving.
|
|
@@ -8,4 +8,4 @@ runtime = ""
|
|
|
8
8
|
scaffold = ""
|
|
9
9
|
|
|
10
10
|
[gitignore]
|
|
11
|
-
"# Claude" = [".claude/.tmp/", ".claude/memory/", ".claude/plans/", ".claude/review/", ".claude/worktrees/", ".claude/tasks/"]
|
|
11
|
+
"# Claude" = [".claude/.tmp/", ".claude/intake/", ".claude/memory/", ".claude/plans/", ".claude/review/", ".claude/worktrees/", ".claude/tasks/"]
|
|
@@ -49,7 +49,7 @@ A project installed before the diagram surface became a folder still holds `.cla
|
|
|
49
49
|
|
|
50
50
|
## Gitignore
|
|
51
51
|
|
|
52
|
-
- `# Claude`: `.claude/.tmp/`, `.claude/memory/`, `.claude/plans/`, `.claude/review/`, `.claude/worktrees/`, `.claude/tasks/`
|
|
52
|
+
- `# Claude`: `.claude/.tmp/`, `.claude/intake/`, `.claude/memory/`, `.claude/plans/`, `.claude/review/`, `.claude/worktrees/`, `.claude/tasks/`
|
|
53
53
|
|
|
54
54
|
## CLI
|
|
55
55
|
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
Draft a new snippet following these conventions:
|
|
2
|
-
|
|
3
|
-
- Filename is the slug: kebab-case, no capitals, no underscores
|
|
4
|
-
- Plain markdown only, no YAML frontmatter, no headers or nested structure
|
|
5
|
-
- One focused purpose, self-contained with no external file references
|
|
6
|
-
|
|
7
|
-
Output the slug and the full file content.
|