@erclx/aitk 0.60.0 → 0.62.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/SKILL.md +7 -34
- package/claude/skills/claude-address-review/references/rebase-conflicts.md +37 -0
- package/claude/skills/claude-docs/SKILL.md +2 -72
- package/claude/skills/claude-docs/references/diagram-sweep.md +58 -0
- package/claude/skills/claude-docs/references/wireframe-sweep.md +45 -0
- package/claude/skills/claude-memory-review/SKILL.md +1 -35
- package/claude/skills/claude-memory-review/references/receipt-format.md +46 -0
- package/claude/skills/claude-orchestrate/SKILL.md +3 -1
- package/claude/skills/claude-orchestrate/references/orchestrator-poll.md +44 -0
- package/claude/skills/claude-orchestrate/scripts/poll.sh +202 -0
- package/docs/agents/skills-audit.md +1 -1
- package/package.json +4 -4
- package/src/commands/claude.ts +3 -1
- package/standards/skill.md +5 -1
|
@@ -60,38 +60,10 @@ git fetch origin main
|
|
|
60
60
|
git merge-tree --write-tree origin/main HEAD
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
A zero exit means the branch still merges. Skip to step 6
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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.
|
|
63
|
+
A zero exit means the branch still merges. Skip to step 6, which is the ordinary
|
|
64
|
+
run. A non-zero exit means it does not, so read
|
|
65
|
+
`${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md` for the stash-and-rebase
|
|
66
|
+
sequence, the conflict resolution rules, and the check to re-run afterward.
|
|
95
67
|
|
|
96
68
|
`git merge-tree` reads committed history, so this test says nothing about the
|
|
97
69
|
fixes still sitting in the working tree. A branch that merges clean as committed,
|
|
@@ -118,8 +90,9 @@ with `git push --force-with-lease`, then post the reply below.
|
|
|
118
90
|
|
|
119
91
|
Once the fixes are commits, re-run step 5's staleness test against the new head.
|
|
120
92
|
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
|
|
122
|
-
and force-push, then
|
|
93
|
+
moved, which the earlier test could not see. Rebase again under
|
|
94
|
+
`${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md` and force-push, then
|
|
95
|
+
continue. The second push costs one extra force-push in a
|
|
123
96
|
case that needs the fix and the sibling to touch the same lines.
|
|
124
97
|
|
|
125
98
|
Then write a summary reply to `.claude/.tmp/address-review/reply-<number>.md`
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Rebase a stale branch
|
|
3
|
+
description: The stash-and-rebase sequence, the conflict resolution rules, and the two recovery messages a hunk needing a decision takes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rebase a stale branch
|
|
7
|
+
|
|
8
|
+
Mechanics for Step 5 of `claude-address-review` once `git merge-tree` exits non-zero. A branch that still merges skips this file entirely, which is the ordinary run.
|
|
9
|
+
|
|
10
|
+
## The sequence
|
|
11
|
+
|
|
12
|
+
Stash the fixes first when `git status --porcelain` reports anything, since a rebase refuses to run over a dirty tree, then rebase onto `origin/main` and restore them:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git stash push -u
|
|
16
|
+
git rebase origin/main
|
|
17
|
+
git stash pop
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Pop only when the stash ran. On a clean tree, which is what a run whose findings were all conscious-accepts leaves behind, `git stash push` saves nothing and exits zero, so the pop restores an unrelated entry from an earlier session.
|
|
21
|
+
|
|
22
|
+
Never merge `main` into the branch. The repository squash-merges, so a merge commit here reads as noise on the pull request.
|
|
23
|
+
|
|
24
|
+
## Resolving a conflict
|
|
25
|
+
|
|
26
|
+
These rules apply to a hunk from the rebase and a hunk from the stash pop alike:
|
|
27
|
+
|
|
28
|
+
- Never take one side wholesale with `--ours` or `--theirs`. Both sides are valid content, so the drop is silent and passes every check.
|
|
29
|
+
- 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.
|
|
30
|
+
- 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.
|
|
31
|
+
- 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.
|
|
32
|
+
|
|
33
|
+
Both sides of every hunk sit in the conflict and `git log origin/main` names what landed, so the tree carries the context. Do not wait on the orchestrator for it.
|
|
34
|
+
|
|
35
|
+
## After the rebase
|
|
36
|
+
|
|
37
|
+
Re-run the project check. It rebuilds the generated files and covers what the replayed commits broke, and step 6 commits the result alongside the fixes.
|
|
@@ -107,35 +107,7 @@ Skip this step silently when `.claude/wireframes/` does not exist or has no surf
|
|
|
107
107
|
|
|
108
108
|
Reuse the diff from the baseline above and filter for UI-affecting paths. UI-affecting paths are framework-dependent. Default heuristic: any file under a `components/`, `features/`, `pages/`, `app/`, `routes/`, or `screens/` folder, plus any `*.tsx`, `*.jsx`, `*.vue`, or `*.svelte` file anywhere in the diff.
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- **Contradicted sections:** when a surface file exists for a path in the diff and the diff renames or removes a literal string that appears in the wireframe prose (e.g. provider name, button label, copy string), output a one-line report entry and stop. Do not auto-rewrite prose. Operator resolves.
|
|
113
|
-
- **Uncovered surfaces:** when a UI-affecting path has no matching surface file by slug, write `.claude/wireframes/<slug>.md` with this stub:
|
|
114
|
-
|
|
115
|
-
```markdown
|
|
116
|
-
---
|
|
117
|
-
title: <Slug as title case>
|
|
118
|
-
description: TODO: describe the surface.
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
# <Slug as title case>
|
|
122
|
-
|
|
123
|
-
TODO: describe when and where this surface appears.
|
|
124
|
-
|
|
125
|
-
## Behavior
|
|
126
|
-
|
|
127
|
-
- TODO
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Skip the write when the slug would collide with an existing file (different surface, same slug). Surface the collision in the report instead.
|
|
131
|
-
|
|
132
|
-
Output one line per finding:
|
|
133
|
-
|
|
134
|
-
- `⚠ Wireframe drift in .claude/wireframes/<surface>.md: <contradicted string>`
|
|
135
|
-
- `📝 Stubbed: .claude/wireframes/<surface>.md`
|
|
136
|
-
- `⚠ Slug collision: <slug> matches existing <existing-surface>.md, review and rename`
|
|
137
|
-
|
|
138
|
-
If the sweep finds nothing, skip silently.
|
|
110
|
+
Skip silently when the filter leaves nothing, which is every branch touching no UI. Otherwise read `${CLAUDE_SKILL_DIR}/references/wireframe-sweep.md` for the slug derivation, the two findings it reports, the stub it writes, and the output lines.
|
|
139
111
|
|
|
140
112
|
## Step 5: diagram staleness sweep
|
|
141
113
|
|
|
@@ -147,49 +119,7 @@ Follow `.claude/standards/diagrams.md` for the marker fields this step writes, o
|
|
|
147
119
|
|
|
148
120
|
Both findings key on something literally entering or leaving the tree. Anything looser fires on ordinary feature work and rebuilds the ignored warning this sweep replaced.
|
|
149
121
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
```yaml
|
|
153
|
-
stale: 'src/gov/install.ts no longer exists'
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Append that key alone. Never edit `verified`, `title`, `description`, or `category`, and never touch the body. When the entry already carries `stale`, extend the existing line rather than adding a second key.
|
|
157
|
-
|
|
158
|
-
**Uncovered kinds.** The standard fixes one source signal per kind. Stub a kind when the diff adds its signal file and no entry covers that kind. The trigger is the signal appearing, never a file under it changing, so a branch editing a component folder that `components.md` already covers produces nothing here.
|
|
159
|
-
|
|
160
|
-
| Signal added by the diff | Kind stubbed when absent |
|
|
161
|
-
| ------------------------------------------------------------------------------------------------------------------ | ------------------------ |
|
|
162
|
-
| `.claude/REQUIREMENTS.md` | `system-context.md` |
|
|
163
|
-
| `.claude/ARCHITECTURE.md` | `components.md` |
|
|
164
|
-
| A deploy or infrastructure config (`Dockerfile`, `.github/workflows/*`, `vercel.json`, `fly.toml`, `compose.yaml`) | `deployment.md` |
|
|
165
|
-
|
|
166
|
-
Leave `request-flow.md` and `data-pipeline.md` out. Neither has a source signal a diff can point at, so a rule covering them would guess at when they went stale.
|
|
167
|
-
|
|
168
|
-
Write the stub at `.claude/diagrams/<kind>.md`:
|
|
169
|
-
|
|
170
|
-
```markdown
|
|
171
|
-
---
|
|
172
|
-
title: <Kind as title case>
|
|
173
|
-
description: 'TODO: name the question this entry settles.'
|
|
174
|
-
category: <the category the standard fixes for this kind>
|
|
175
|
-
verified: 'TODO: never verified'
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
# <Kind as title case>
|
|
179
|
-
|
|
180
|
-
TODO: draw this. `<signal path>` entered the tree with no entry covering this kind.
|
|
181
|
-
|
|
182
|
-
Run `/claude-diagram <kind>` to replace the stub.
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
No mermaid fence. An empty stub is visible debt that reaches review through the branch diff, while a generated diagram nobody rendered is invisible debt that reads as verified. A fence here invites the next session to fill it in without a render.
|
|
186
|
-
|
|
187
|
-
Output one line per finding:
|
|
188
|
-
|
|
189
|
-
- `⚠ Diagram stale: .claude/diagrams/<kind>.md cites <path>, which left the tree`
|
|
190
|
-
- `📝 Stubbed: .claude/diagrams/<kind>.md`
|
|
191
|
-
|
|
192
|
-
If the sweep finds nothing, skip silently. An ordinary change that adds no signal and deletes no cited path produces no output at all.
|
|
122
|
+
Past the skip above, read `${CLAUDE_SKILL_DIR}/references/diagram-sweep.md` for the two findings, the signal table deciding an uncovered kind, the stub it writes, and the output lines. Both tests need the cited paths and the signal list that file carries, so the folder check is the only one the body can settle on its own.
|
|
193
123
|
|
|
194
124
|
## Step 6: flag CLAUDE.md drift
|
|
195
125
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Diagram staleness sweep
|
|
3
|
+
description: The contradicted-entry marker, the source-signal table that decides an uncovered kind, the stub it writes, and the report lines
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Diagram staleness sweep
|
|
7
|
+
|
|
8
|
+
Mechanics for Step 5 of `claude-docs`. The body owns the skip conditions, the frontmatter-only constraint, and the standard citation, and this file owns what the sweep does once the diff carries a delete or a new source signal.
|
|
9
|
+
|
|
10
|
+
## Contradicted entries
|
|
11
|
+
|
|
12
|
+
For each entry, collect the backticked code paths its explanation cites. When a cited path is in the diff as a delete or a rename and no longer exists in the tree, append a `stale` key to that entry's frontmatter naming the path:
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
stale: 'src/gov/install.ts no longer exists'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Append that key alone. Never edit `verified`, `title`, `description`, or `category`, and never touch the body. When the entry already carries `stale`, extend the existing line rather than adding a second key.
|
|
19
|
+
|
|
20
|
+
## Uncovered kinds
|
|
21
|
+
|
|
22
|
+
The standard fixes one source signal per kind. Stub a kind when the diff adds its signal file and no entry covers that kind. The trigger is the signal appearing, never a file under it changing, so a branch editing a component folder that `components.md` already covers produces nothing here.
|
|
23
|
+
|
|
24
|
+
| Signal added by the diff | Kind stubbed when absent |
|
|
25
|
+
| ------------------------------------------------------------------------------------------------------------------ | ------------------------ |
|
|
26
|
+
| `.claude/REQUIREMENTS.md` | `system-context.md` |
|
|
27
|
+
| `.claude/ARCHITECTURE.md` | `components.md` |
|
|
28
|
+
| A deploy or infrastructure config (`Dockerfile`, `.github/workflows/*`, `vercel.json`, `fly.toml`, `compose.yaml`) | `deployment.md` |
|
|
29
|
+
|
|
30
|
+
Leave `request-flow.md` and `data-pipeline.md` out. Neither has a source signal a diff can point at, so a rule covering them would guess at when they went stale.
|
|
31
|
+
|
|
32
|
+
Write the stub at `.claude/diagrams/<kind>.md`:
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+
---
|
|
36
|
+
title: <Kind as title case>
|
|
37
|
+
description: 'TODO: name the question this entry settles.'
|
|
38
|
+
category: <the category the standard fixes for this kind>
|
|
39
|
+
verified: 'TODO: never verified'
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
# <Kind as title case>
|
|
43
|
+
|
|
44
|
+
TODO: draw this. `<signal path>` entered the tree with no entry covering this kind.
|
|
45
|
+
|
|
46
|
+
Run `/claude-diagram <kind>` to replace the stub.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
No mermaid fence. An empty stub is visible debt that reaches review through the branch diff, while a generated diagram nobody rendered is invisible debt that reads as verified. A fence here invites the next session to fill it in without a render.
|
|
50
|
+
|
|
51
|
+
## Output
|
|
52
|
+
|
|
53
|
+
Output one line per finding:
|
|
54
|
+
|
|
55
|
+
- `⚠ Diagram stale: .claude/diagrams/<kind>.md cites <path>, which left the tree`
|
|
56
|
+
- `📝 Stubbed: .claude/diagrams/<kind>.md`
|
|
57
|
+
|
|
58
|
+
If the sweep finds nothing, skip silently. An ordinary change that adds no signal and deletes no cited path produces no output at all.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Wireframe coverage sweep
|
|
3
|
+
description: Slug derivation from a UI-affecting path, the contradicted and uncovered findings, the surface stub, and the report lines
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Wireframe coverage sweep
|
|
7
|
+
|
|
8
|
+
Mechanics for Step 4 of `claude-docs`. The body owns the skip conditions and the UI-path filter, and this file owns what the sweep does once a UI-affecting path survives that filter.
|
|
9
|
+
|
|
10
|
+
## Deriving a candidate slug
|
|
11
|
+
|
|
12
|
+
For each UI-affecting path, derive a candidate surface slug from the file's basename and parent folder (e.g. `web/src/features/mock/MockDemoStrip.tsx` → `mock-demo-strip` or `mock`). Cross-reference against the surface files in `.claude/wireframes/`.
|
|
13
|
+
|
|
14
|
+
## Findings
|
|
15
|
+
|
|
16
|
+
**Contradicted sections.** When a surface file exists for a path in the diff and the diff renames or removes a literal string that appears in the wireframe prose (e.g. provider name, button label, copy string), output a one-line report entry and stop. Do not auto-rewrite prose. Operator resolves.
|
|
17
|
+
|
|
18
|
+
**Uncovered surfaces.** When a UI-affecting path has no matching surface file by slug, write `.claude/wireframes/<slug>.md` with this stub:
|
|
19
|
+
|
|
20
|
+
```markdown
|
|
21
|
+
---
|
|
22
|
+
title: <Slug as title case>
|
|
23
|
+
description: TODO: describe the surface.
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# <Slug as title case>
|
|
27
|
+
|
|
28
|
+
TODO: describe when and where this surface appears.
|
|
29
|
+
|
|
30
|
+
## Behavior
|
|
31
|
+
|
|
32
|
+
- TODO
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Skip the write when the slug would collide with an existing file (different surface, same slug). Surface the collision in the report instead.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
Output one line per finding:
|
|
40
|
+
|
|
41
|
+
- `⚠ Wireframe drift in .claude/wireframes/<surface>.md: <contradicted string>`
|
|
42
|
+
- `📝 Stubbed: .claude/wireframes/<surface>.md`
|
|
43
|
+
- `⚠ Slug collision: <slug> matches existing <existing-surface>.md, review and rename`
|
|
44
|
+
|
|
45
|
+
If the sweep finds nothing, skip silently.
|
|
@@ -88,41 +88,7 @@ Rules that resist crisp one-line phrasing default to **Retire** over promote. Ne
|
|
|
88
88
|
|
|
89
89
|
Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../standards/slug.md` when the project does not have it. Fall back to `latest` on an empty result.
|
|
90
90
|
|
|
91
|
-
Write the full proposal to `.claude/review/memory-review-<slug>.md` at the main worktree root. Do not print it inline.
|
|
92
|
-
|
|
93
|
-
Structure: a summary block at the top, a legend, then one H2 per numbered item. Number items across all actions so the user can reference them by number. Fuse the status, action, and target into each H2. Put the memory filename on its own line, a one-line Why, the rewritten rule inline in a fenced `diff` block prefixed with `+` so reviewers see the additions in green, and a `Decision:` slot for the user. Do not include a `Take:` slot in the template. Discuss inserts one directly under `Decision:` only when responding to a question item. Status starts as 📝 pending for every item at proposal time.
|
|
94
|
-
|
|
95
|
-
````plaintext
|
|
96
|
-
# Memory review: <slug>
|
|
97
|
-
|
|
98
|
-
**Pending:** <all numbers>
|
|
99
|
-
|
|
100
|
-
Legend: ✅ applied · ⏭ skipped · 📦 retired · 🤝 handed off · 📝 pending
|
|
101
|
-
|
|
102
|
-
How to respond: fill in `Decision:` per item (`apply`, `skip`, `defer`, or a question with `?`), then re-ping the skill. Say "discuss" for question rounds, "apply" to commit. Chat shortcut: `all`, `none`, or a list of numbers.
|
|
103
|
-
|
|
104
|
-
## 1. 📝 Promote → `<target>`
|
|
105
|
-
|
|
106
|
-
`<memory-file>`
|
|
107
|
-
|
|
108
|
-
Why: <one-line pulled from the memory's Why>
|
|
109
|
-
|
|
110
|
-
```diff
|
|
111
|
-
+ <rewritten rule text>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Decision:
|
|
115
|
-
|
|
116
|
-
## 2. 📝 Retire
|
|
117
|
-
|
|
118
|
-
`<memory-file>`
|
|
119
|
-
|
|
120
|
-
Reason: <one-line reason>
|
|
121
|
-
|
|
122
|
-
Decision:
|
|
123
|
-
````
|
|
124
|
-
|
|
125
|
-
For Hand off items, the body is a pointer to the governance target instead of a rewritten rule: `aitk-governance` and `.claude/standards/rule.md` in the toolkit repo, or the `create-rule` skill in a target project. For Retire items, skip the rewrite block. Every item gets a `Decision:` slot regardless of action. `Take:` is added only when a question response is needed.
|
|
91
|
+
Write the full proposal to `.claude/review/memory-review-<slug>.md` at the main worktree root. Do not print it inline. Read `${CLAUDE_SKILL_DIR}/references/receipt-format.md` for the file structure, the item template, and how each action type varies the body. The four phases below rewrite items inside an existing receipt rather than authoring one, so none of them opens it.
|
|
126
92
|
|
|
127
93
|
Tell the user `✅ Wrote proposal to .claude/review/memory-review-<slug>.md`. Ask them to fill in `Decision:` per item, then re-ping with "discuss" for question rounds or "apply" to commit.
|
|
128
94
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Memory review receipt format
|
|
3
|
+
description: The proposal file structure, its item template, and how each action type varies the body
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Memory review receipt format
|
|
7
|
+
|
|
8
|
+
The shape Step 4 of the Propose phase writes to `.claude/review/memory-review-<slug>.md`. Only Propose writes this file. Challenge, Discuss, and Apply rewrite items inside a receipt that already exists, and Cleanup deletes one, so none of the four needs this file.
|
|
9
|
+
|
|
10
|
+
## Structure
|
|
11
|
+
|
|
12
|
+
A summary block at the top, a legend, then one H2 per numbered item. Number items across all actions so the user can reference them by number. Fuse the status, action, and target into each H2. Put the memory filename on its own line, a one-line Why, the rewritten rule inline in a fenced `diff` block prefixed with `+` so reviewers see the additions in green, and a `Decision:` slot for the user. Do not include a `Take:` slot in the template. Discuss inserts one directly under `Decision:` only when responding to a question item. Status starts as 📝 pending for every item at proposal time.
|
|
13
|
+
|
|
14
|
+
````plaintext
|
|
15
|
+
# Memory review: <slug>
|
|
16
|
+
|
|
17
|
+
**Pending:** <all numbers>
|
|
18
|
+
|
|
19
|
+
Legend: ✅ applied · ⏭ skipped · 📦 retired · 🤝 handed off · 📝 pending
|
|
20
|
+
|
|
21
|
+
How to respond: fill in `Decision:` per item (`apply`, `skip`, `defer`, or a question with `?`), then re-ping the skill. Say "discuss" for question rounds, "apply" to commit. Chat shortcut: `all`, `none`, or a list of numbers.
|
|
22
|
+
|
|
23
|
+
## 1. 📝 Promote → `<target>`
|
|
24
|
+
|
|
25
|
+
`<memory-file>`
|
|
26
|
+
|
|
27
|
+
Why: <one-line pulled from the memory's Why>
|
|
28
|
+
|
|
29
|
+
```diff
|
|
30
|
+
+ <rewritten rule text>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Decision:
|
|
34
|
+
|
|
35
|
+
## 2. 📝 Retire
|
|
36
|
+
|
|
37
|
+
`<memory-file>`
|
|
38
|
+
|
|
39
|
+
Reason: <one-line reason>
|
|
40
|
+
|
|
41
|
+
Decision:
|
|
42
|
+
````
|
|
43
|
+
|
|
44
|
+
## Variation by action
|
|
45
|
+
|
|
46
|
+
For Hand off items, the body is a pointer to the governance target instead of a rewritten rule: `aitk-governance` and `.claude/standards/rule.md` in the toolkit repo, or the `create-rule` skill in a target project. For Retire items, skip the rewrite block. Every item gets a `Decision:` slot regardless of action. `Take:` is added only when a question response is needed.
|
|
@@ -37,6 +37,8 @@ The roadmap is optional and this skill does not require it. It carries why a seq
|
|
|
37
37
|
|
|
38
38
|
A compaction is a moment this skill cannot detect, so the human asks for each side of it and this skill reads the matching runbook when they do. On a request to write the handoff or save the session, read `${CLAUDE_SKILL_DIR}/references/orchestrator-handoff.md` and follow it. It writes `.claude/tasks/session.md` with the state of play, the decisions taken under delegated authority, the mistakes worth not repeating, and the standing cautions. On a request to resume after a compaction, read `${CLAUDE_SKILL_DIR}/references/orchestrator-resume.md`, which reads that file back with the board and the groundwork behind the live work. Write nothing to the handoff that the board, a task file, or a groundwork folder already carries.
|
|
39
39
|
|
|
40
|
+
The review trigger takes the same shape. `references/orchestrator-poll.md` holds the loop prompt and the condition under which the poll runs, and `scripts/poll.sh` is what the prompt invokes. Nothing starts or stops that loop on its own, so the condition holds only while a session applies it.
|
|
41
|
+
|
|
40
42
|
That routing lives in this body and this skill is user-invoked, so a session that has dropped the body routes nothing and the request lands as ordinary conversation. Approaching a compaction is when a long session is likeliest to have dropped it, which is the same moment the handoff exists for. Re-invoke `/aitk:claude-orchestrate` first whenever the session has run long or the ask goes unanswered. The two runbooks sit at `references/orchestrator-handoff.md` and `references/orchestrator-resume.md` inside this skill's own folder, so a person who knows their plugin root opens either one directly and follows it without this skill loaded at all.
|
|
41
43
|
|
|
42
44
|
## Output
|
|
@@ -96,7 +98,7 @@ Write no shape for a correction. A correction is a sentence, and a format for ad
|
|
|
96
98
|
3. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
|
|
97
99
|
4. Verify the plan against the tree. Reading it is not enough, since a plan goes stale from whatever merged after it was written. Grep for each construct it names and count the sites against the count it claims. Check that every phase label it cites is still open. Open each file it describes rather than trusting its account of the contents. Correct the plan before handing it over.
|
|
98
100
|
5. Hand off. The human opens a worker worktree with `claude-worktree` and runs `claude-autoship` against the plan. The orchestrator does not spawn workers.
|
|
99
|
-
6. Review the PR. When a worker opens a PR, run `claude-pr-review` to post findings to it. This is the deep, independent pass. The worker's autoship self-review was only the green gate.
|
|
101
|
+
6. Review the PR. When a worker opens a PR, run `claude-pr-review` to post findings to it. This is the deep, independent pass. The worker's autoship self-review was only the green gate. Learning that a PR moved is the mechanical half, so read `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` and start the poll it carries on the first dispatch rather than checking the board by hand. It routes a moved or answered pull request straight to a re-review and reports an opened one without acting, which keeps every first pass a batched judgment this session triggers.
|
|
100
102
|
7. Close the loop. After the worker runs `claude-address-review`, re-review if needed, then the human merges. Tell the trailing worker to rebase when its branch shares a seam with the merged one.
|
|
101
103
|
|
|
102
104
|
## Boundaries
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Orchestrator poll runbook
|
|
3
|
+
description: The review trigger, the condition under which it runs, and how to read what it reports
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run the orchestrator's review trigger. The poll reports pull request movement and the session acts on what it reports. It reads only, and it never starts a first-pass review.
|
|
7
|
+
|
|
8
|
+
`${CLAUDE_SKILL_DIR}/scripts/poll.sh` is the script. It needs `gh` authenticated against the remote and `jq` on the path, and it reads the base branch from `origin/HEAD` rather than assuming a name.
|
|
9
|
+
|
|
10
|
+
## When to run it
|
|
11
|
+
|
|
12
|
+
Start the poll on a dispatch and stop it when the last pull request merges with nothing else out. An open pull request or a dispatched worker is the condition, and both resolve from the board plus `gh pr list` without asking the operator. A release pull request alone does not qualify, since its sweep carries no findings.
|
|
13
|
+
|
|
14
|
+
Nothing enforces this. No hook starts the poll and no check stops it, so the condition holds only while a session applies it. Left always-on it fires into an empty board through every gap between a dispatch and its push, which leaves stopping it to the operator.
|
|
15
|
+
|
|
16
|
+
The poll is session-scoped and dies with the session that started it. Restart it after a compaction, and take the prompt from this file rather than from a transcript, since a running loop holds whatever wording it was started with and a correction here does not reach it.
|
|
17
|
+
|
|
18
|
+
## The prompt
|
|
19
|
+
|
|
20
|
+
Resolve `${CLAUDE_SKILL_DIR}/scripts/poll.sh` to an absolute path and paste that in place of `<POLL_SCRIPT>` below. The variable expands while this runbook renders and not in a `/loop` turn, which arrives as a standalone prompt, so a block carrying the variable reaches the session as a literal string and the run improvises a substitute.
|
|
21
|
+
|
|
22
|
+
```plaintext
|
|
23
|
+
/loop 3m Poll GitHub for pull request movement by running <POLL_SCRIPT>, then act on what it reports.
|
|
24
|
+
|
|
25
|
+
- MOVED or RESPONSE on a pull request I have already reviewed: run the aitk:claude-pr-review skill on it immediately, narrow pass. Re-reviews read prior..head and gain nothing from waiting.
|
|
26
|
+
- OPENED, or a pull request with no prior review pass: report it and stop. First passes wait for the operator, because reading several together is what surfaces cross-PR findings.
|
|
27
|
+
- SEEN: report it and stop. A pass already covers that head, whether it arrived out of band or before the poll first saw the pull request, so no review follows.
|
|
28
|
+
- CONFLICT: report it and stop. The branch owner rebases, not this session.
|
|
29
|
+
- GONE: report it, then sweep the board by invoking the aitk:claude-orchestrate skill and following its queue-refill sweep.
|
|
30
|
+
- A line starting `poll:`: report it verbatim and treat that pull request as unread this run. It is a failed query, not a state.
|
|
31
|
+
- Nothing changed: say exactly "No movement." and nothing else.
|
|
32
|
+
|
|
33
|
+
Never start a first-pass review on your own.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Reading the output
|
|
37
|
+
|
|
38
|
+
Every classification line names a pull request and a state. A line starting `poll:` is not a classification. It means a query failed and the script declined to guess, so that pull request keeps its last known state and is neither reported as moved nor swept as merged. Treat it as unread and let the next run classify it.
|
|
39
|
+
|
|
40
|
+
The script exits non-zero and classifies nothing when the open pull request list itself fails to load. That case would otherwise report every tracked pull request as merged, so the baseline is left untouched and the run says so.
|
|
41
|
+
|
|
42
|
+
The baseline lives at `.claude/.tmp/pr-poll/baseline.txt` under the main worktree root and is per-machine. A first run against a board already in flight reports each open pull request once before it settles.
|
|
43
|
+
|
|
44
|
+
The four review headings the script matches are written by `claude-pr-review` and `claude-address-review`. A project that posts its reviews under different headings edits the two jq filters in the script to match, or every pull request reads as never reviewed.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Reports pull request movement since the last run. Reads only.
|
|
3
|
+
#
|
|
4
|
+
# The shebang is load-bearing. An earlier version ran under the operator's zsh,
|
|
5
|
+
# where an unquoted parameter expansion does not word-split, so `set -- $line`
|
|
6
|
+
# left every field but the first empty and every head compared unequal. The
|
|
7
|
+
# poll reported movement that had not happened, which is the one failure that
|
|
8
|
+
# makes a detection tool worth less than no tool.
|
|
9
|
+
set -e
|
|
10
|
+
set -o pipefail
|
|
11
|
+
|
|
12
|
+
# The baseline is per-machine mutable state, so it stays in gitignored scratch
|
|
13
|
+
# even though the script is tracked. Resolving the main worktree root rather
|
|
14
|
+
# than this file's own folder keeps a poll started from a linked worktree
|
|
15
|
+
# reading the baseline a poll started from main wrote.
|
|
16
|
+
MAIN_ROOT="$(git worktree list --porcelain 2>/dev/null | awk '/^worktree /{print $2; exit}')"
|
|
17
|
+
if [ -z "$MAIN_ROOT" ]; then
|
|
18
|
+
echo "poll: not a git repository, so nothing is classified" >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
STATE_DIR="$MAIN_ROOT/.claude/.tmp/pr-poll"
|
|
22
|
+
mkdir -p "$STATE_DIR"
|
|
23
|
+
STATE="$STATE_DIR/baseline.txt"
|
|
24
|
+
touch "$STATE"
|
|
25
|
+
|
|
26
|
+
# The base branch is read rather than assumed, since this ships to projects that
|
|
27
|
+
# do not all call it `main`. A wrong base is not a visible failure: merge-tree
|
|
28
|
+
# reports every pull request as conflicted against a ref that does not resolve.
|
|
29
|
+
BASE_REF="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)"
|
|
30
|
+
if [ -z "$BASE_REF" ]; then
|
|
31
|
+
BASE_REF="origin/$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name 2>/dev/null || echo main)"
|
|
32
|
+
fi
|
|
33
|
+
BASE_BRANCH="${BASE_REF#origin/}"
|
|
34
|
+
|
|
35
|
+
# These four strings are owned elsewhere and pinned here. `claude-pr-review`
|
|
36
|
+
# writes `## Review` and `## Review closed`, and `claude-address-review` writes
|
|
37
|
+
# `## Review response` and `## Rebase`. All three surfaces ship separately, so a
|
|
38
|
+
# heading added in either skill breaks a test here that no check reaches across.
|
|
39
|
+
#
|
|
40
|
+
# Both families match on the first line alone so the two tests stay symmetric.
|
|
41
|
+
# The reply family carries `## Rebase` because a run sent straight to the rebase
|
|
42
|
+
# step posts under a heading deliberately kept outside the `## Review` family.
|
|
43
|
+
# Widening one family without the other is what left the reply test narrow, so
|
|
44
|
+
# a fifth heading is added here beside its sibling.
|
|
45
|
+
JQ_LAST_REVIEWED_HEAD='
|
|
46
|
+
[ .reviews[]
|
|
47
|
+
| select((.body // "") | split("\n")[0] | rtrimstr("\r")
|
|
48
|
+
| . == "## Review" or . == "## Review closed")
|
|
49
|
+
] | last | .commit.oid // empty
|
|
50
|
+
'
|
|
51
|
+
JQ_REPLY_COUNT='
|
|
52
|
+
[ .comments[]
|
|
53
|
+
| select((.body // "") | split("\n")[0] | rtrimstr("\r")
|
|
54
|
+
| . == "## Review response" or . == "## Rebase")
|
|
55
|
+
] | length
|
|
56
|
+
'
|
|
57
|
+
|
|
58
|
+
# A pull request this run could not read keeps the line it had, so the GONE
|
|
59
|
+
# sweep below does not read the gap as a merge and the baseline does not lose
|
|
60
|
+
# the head it already knew. Saying so on stderr is the point: a silent skip is
|
|
61
|
+
# how the failure this script was fixed for went unnoticed for a session.
|
|
62
|
+
carry_forward() {
|
|
63
|
+
local n=$1 reason=$2 old
|
|
64
|
+
old=$(grep "^$n " "$STATE" || true)
|
|
65
|
+
if [ -n "$old" ]; then
|
|
66
|
+
echo "$old"
|
|
67
|
+
echo "poll: #$n $reason, so it keeps its last known state and goes unclassified" >&2
|
|
68
|
+
else
|
|
69
|
+
echo "poll: #$n $reason, and it has no last known state, so it goes unclassified" >&2
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
snapshot() {
|
|
74
|
+
local numbers n payload head prior resp merges
|
|
75
|
+
git fetch -q origin "$BASE_BRANCH" 2>/dev/null || true
|
|
76
|
+
|
|
77
|
+
# A failed list reaches the caller as no open pull requests, and that reports
|
|
78
|
+
# every tracked one as GONE. It is a louder wrong answer than the one this
|
|
79
|
+
# script was fixed for, so the run aborts rather than classify on it.
|
|
80
|
+
if ! numbers=$(gh pr list --state open --json number --jq '.[].number' 2>/dev/null); then
|
|
81
|
+
echo "poll: the open pull request list could not be read" >&2
|
|
82
|
+
return 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
for n in $numbers; do
|
|
86
|
+
# A query that failed and a pull request with genuinely no reviews both
|
|
87
|
+
# arrive as an empty result. Reading the first as the second reported a
|
|
88
|
+
# reviewed pull request as never reviewed, which routes the re-review to
|
|
89
|
+
# the first-pass branch, where it reports and stops, so the movement sits
|
|
90
|
+
# unreviewed until a person notices. One query per pull request gives that
|
|
91
|
+
# failure a single place to surface.
|
|
92
|
+
if ! payload=$(gh pr view "$n" --json headRefOid,reviews,comments 2>/dev/null); then
|
|
93
|
+
carry_forward "$n" "could not be read"
|
|
94
|
+
continue
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
head=$(jq -r '.headRefOid // empty' <<<"$payload")
|
|
98
|
+
if [ -z "$head" ]; then
|
|
99
|
+
carry_forward "$n" "returned no head"
|
|
100
|
+
continue
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
prior=$(jq -r "$JQ_LAST_REVIEWED_HEAD" <<<"$payload")
|
|
104
|
+
resp=$(jq -r "$JQ_REPLY_COUNT" <<<"$payload")
|
|
105
|
+
|
|
106
|
+
# `gh pr view --json mergeable` reports UNKNOWN until GitHub finishes
|
|
107
|
+
# computing it, which is exactly when a poll asks. merge-tree answers
|
|
108
|
+
# locally against the base this machine has, so it never returns UNKNOWN.
|
|
109
|
+
git fetch -q origin "pull/$n/head" 2>/dev/null || true
|
|
110
|
+
if ! git cat-file -e "${head}^{commit}" 2>/dev/null ||
|
|
111
|
+
! git rev-parse --verify -q "$BASE_REF" >/dev/null; then
|
|
112
|
+
# merge-tree exits non-zero on a ref it cannot resolve as well as on a
|
|
113
|
+
# real conflict, and the two are indistinguishable from its status. Both
|
|
114
|
+
# sides are checked, because an unresolvable base reports every pull
|
|
115
|
+
# request as conflicted rather than one, which is the louder half.
|
|
116
|
+
merges=unknown
|
|
117
|
+
elif git merge-tree --write-tree "$BASE_REF" "$head" >/dev/null 2>&1; then
|
|
118
|
+
merges=clean
|
|
119
|
+
else
|
|
120
|
+
merges=conflict
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
echo "$n $head ${prior:-none} $resp $merges"
|
|
124
|
+
done
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# The reason is printed by whichever branch failed, since this one cannot tell
|
|
128
|
+
# a list query from a parse and naming either would misattribute the other.
|
|
129
|
+
if ! NEW=$(snapshot); then
|
|
130
|
+
echo "poll: nothing is classified this run and the baseline is unchanged" >&2
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
CHANGED=0
|
|
134
|
+
|
|
135
|
+
while read -r n head prior resp merges; do
|
|
136
|
+
[ -z "$n" ] && continue
|
|
137
|
+
old=$(grep "^$n " "$STATE" || true)
|
|
138
|
+
if [ -z "$old" ]; then
|
|
139
|
+
# A pull request first seen here may already carry a pass, when it opened
|
|
140
|
+
# and was reviewed between two runs. Reporting it as new invites a first
|
|
141
|
+
# pass the thread already has.
|
|
142
|
+
if [ "$prior" = "$head" ]; then
|
|
143
|
+
echo "SEEN #$n at ${head:0:7}, first sighting, already covered by a pass"
|
|
144
|
+
elif [ "$merges" = unknown ]; then
|
|
145
|
+
# `unknown` means no merge was attempted, so it is left off the line
|
|
146
|
+
# rather than printed where a verdict belongs.
|
|
147
|
+
echo "OPENED #$n at ${head:0:7}"
|
|
148
|
+
else
|
|
149
|
+
echo "OPENED #$n at ${head:0:7}, $merges against $BASE_BRANCH"
|
|
150
|
+
fi
|
|
151
|
+
CHANGED=1
|
|
152
|
+
continue
|
|
153
|
+
fi
|
|
154
|
+
old_head=$(echo "$old" | cut -d' ' -f2)
|
|
155
|
+
old_resp=$(echo "$old" | cut -d' ' -f4)
|
|
156
|
+
old_merges=$(echo "$old" | cut -d' ' -f5)
|
|
157
|
+
|
|
158
|
+
# A conflict arrives from the base moving, not from the branch, so it is
|
|
159
|
+
# reported on the transition rather than only when the head changes.
|
|
160
|
+
if [ "$merges" = conflict ] && [ "$old_merges" != conflict ]; then
|
|
161
|
+
echo "CONFLICT #$n no longer merges into $BASE_BRANCH"
|
|
162
|
+
CHANGED=1
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
if [ "$head" != "$old_head" ]; then
|
|
166
|
+
if [ "$prior" = "none" ]; then
|
|
167
|
+
echo "MOVED #$n -> ${head:0:7}, never reviewed"
|
|
168
|
+
elif [ "$prior" = "$head" ]; then
|
|
169
|
+
# An out-of-band pass reviewed this head before the poll saw it move, so
|
|
170
|
+
# the range is empty because it is covered rather than because it broke.
|
|
171
|
+
# Without this the force-push branch below claims a rewrite that never
|
|
172
|
+
# happened, which is the class of false report the shebang note names.
|
|
173
|
+
echo "SEEN #$n -> ${head:0:7}, already covered by the last pass"
|
|
174
|
+
else
|
|
175
|
+
# The range needs both commits local, and a force-push leaves the prior
|
|
176
|
+
# one unreachable. Count what resolves and say nothing when it does not,
|
|
177
|
+
# rather than reporting a zero that reads as no new work.
|
|
178
|
+
git fetch -q origin "pull/$n/head" 2>/dev/null || true
|
|
179
|
+
since=$(git log --oneline "${prior}..${head}" 2>/dev/null | wc -l | tr -d ' ' || true)
|
|
180
|
+
if [ -n "$since" ] && [ "$since" != "0" ]; then
|
|
181
|
+
echo "MOVED #$n -> ${head:0:7}, $since commit(s) since your last pass"
|
|
182
|
+
else
|
|
183
|
+
echo "MOVED #$n -> ${head:0:7}, range unresolved, likely force-pushed"
|
|
184
|
+
fi
|
|
185
|
+
fi
|
|
186
|
+
CHANGED=1
|
|
187
|
+
elif [ "$resp" -gt "$old_resp" ]; then
|
|
188
|
+
echo "RESPONSE #$n answered with no new commit"
|
|
189
|
+
CHANGED=1
|
|
190
|
+
fi
|
|
191
|
+
done <<<"$NEW"
|
|
192
|
+
|
|
193
|
+
while read -r n _rest; do
|
|
194
|
+
[ -z "$n" ] && continue
|
|
195
|
+
echo "$NEW" | grep -q "^$n " || {
|
|
196
|
+
echo "GONE #$n merged or closed"
|
|
197
|
+
CHANGED=1
|
|
198
|
+
}
|
|
199
|
+
done <"$STATE"
|
|
200
|
+
|
|
201
|
+
[ "$CHANGED" -eq 0 ] && echo "No movement."
|
|
202
|
+
echo "$NEW" >"$STATE"
|
|
@@ -40,7 +40,7 @@ A body whose frontmatter does not parse reports as declaring neither field rathe
|
|
|
40
40
|
|
|
41
41
|
## What it leaves alone
|
|
42
42
|
|
|
43
|
-
The report names its own blind spots on every run, including the run where everything passed. Whether each `Must` traces to a stated gap is the rule in that standard worth the most and no parser reads it. Whether a gap states an observed failure rather than an intent, and whether a description routes, are the same kind of judgment. The
|
|
43
|
+
The report names its own blind spots on every run, including the run where everything passed. Whether each `Must` traces to a stated gap is the rule in that standard worth the most and no parser reads it. Whether a gap states an observed failure rather than an intent, and whether a description routes, are the same kind of judgment. The 150-line body checkpoint is the one mechanical rule still absent here, and adding it would print a count rather than a defect, since the standard makes it a prompt to look with nothing enforcing it.
|
|
44
44
|
|
|
45
45
|
A check with no rule behind it prints an opinion as a defect, which is where the list stops.
|
|
46
46
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erclx/aitk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.62.0",
|
|
5
5
|
"description": "Infrastructure and quality tooling for developer workflows",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"check:spell": "cspell '**' '.*/**' '.*' --no-progress --color --show-context",
|
|
30
|
-
"format": "prettier --write --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --write --indent 2 scripts/ tooling/",
|
|
31
|
-
"check:format": "prettier --check --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --diff --indent 2 scripts/ tooling/",
|
|
32
|
-
"check:shell": "find scripts tooling .claude/hooks -name '*.sh' -exec shellcheck --severity=warning {} +",
|
|
30
|
+
"format": "prettier --write --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --write --indent 2 scripts/ tooling/ claude/",
|
|
31
|
+
"check:format": "prettier --check --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --diff --indent 2 scripts/ tooling/ claude/",
|
|
32
|
+
"check:shell": "find scripts tooling claude .claude/hooks -name '*.sh' -exec shellcheck --severity=warning {} +",
|
|
33
33
|
"check:types": "tsc --noEmit",
|
|
34
34
|
"check:install": "./scripts/core/install-check.sh",
|
|
35
35
|
"test": "bun --bun vitest run",
|
package/src/commands/claude.ts
CHANGED
|
@@ -689,5 +689,7 @@ function reportUnmeasured(): void {
|
|
|
689
689
|
logInfo(
|
|
690
690
|
'Whether each Must traces to a stated gap, whether a gap reads as an observed failure rather than an intent, and whether a description routes.',
|
|
691
691
|
)
|
|
692
|
-
logInfo(
|
|
692
|
+
logInfo(
|
|
693
|
+
'The 150-line body checkpoint is mechanical and still absent here, and it would print a count rather than a defect.',
|
|
694
|
+
)
|
|
693
695
|
}
|
package/standards/skill.md
CHANGED
|
@@ -184,7 +184,11 @@ Without this skill, a session <observed failure>, <observed failure>.
|
|
|
184
184
|
|
|
185
185
|
### Progressive disclosure
|
|
186
186
|
|
|
187
|
-
-
|
|
187
|
+
- Look at a body once it passes 150 lines. The number prompts a look rather than gating a build, so nothing enforces it and a body carrying nothing but procedure stays whole at any length.
|
|
188
|
+
- Move a catalog, a table of cases, or a format spec running past roughly 15 lines to `references/`. Procedure prose stays, since a session sent to a reference for its own steps pays two reads for one job.
|
|
189
|
+
- Name the branch that skips a block before moving it. Body lines are paid on every invocation and a reference only when the body sends the session to it, so a block every run dereferences costs a read and saves nothing.
|
|
190
|
+
- Keep the trigger, the skip condition, and the guard in the body. A run that never reaches the block has to decide that without opening the reference.
|
|
191
|
+
- Never point one skill at a sibling skill's folder for a reference both read. Each skill carries its own copy under `references/`, generated rather than hand-copied by the rule in `## Path resolution`.
|
|
188
192
|
- Use progressive disclosure: `SKILL.md` for core instructions, `references/` for detail, `scripts/` for deterministic operations
|
|
189
193
|
- Link to `references/` files explicitly so Claude knows to load them
|
|
190
194
|
|