@erclx/aitk 0.63.0 → 0.63.2
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-docs/SKILL.md +3 -1
- package/claude/skills/claude-feature/SKILL.md +2 -0
- package/claude/skills/claude-memory-capture/SKILL.md +9 -2
- package/claude/skills/claude-memory-review/SKILL.md +5 -2
- package/claude/skills/claude-review/SKILL.md +2 -0
- package/claude/skills/claude-screencast/SKILL.md +2 -0
- package/claude/skills/claude-seed-sync/SKILL.md +2 -0
- package/claude/skills/claude-tasks/SKILL.md +3 -1
- package/claude/skills/claude-ui-test/SKILL.md +2 -0
- package/claude/skills/claude-ux-audit/SKILL.md +2 -0
- package/claude/skills/git-pr/SKILL.md +9 -3
- package/docs/agents/commands.md +2 -0
- package/docs/agents/context-audit-checks.md +3 -3
- package/docs/agents/index.md +1 -1
- package/docs/agents/tasks.md +51 -2
- package/docs/ai-workflow.md +1 -1
- package/package.json +1 -1
- package/src/commands/context.ts +3 -14
- package/src/commands/records.ts +1 -18
- package/src/commands/tasks.ts +314 -19
- package/src/context/audit.ts +23 -21
- package/src/tasks/archive.ts +34 -3
- package/src/tasks/record.ts +311 -0
- package/src/worktree.ts +23 -0
- package/standards/context.md +2 -7
- package/standards/markdown.md +8 -1
- package/tooling/claude/seeds/CLAUDE.md +4 -1
|
@@ -88,7 +88,7 @@ For each doc with relevant changes, apply updates following these rules. Read a
|
|
|
88
88
|
|
|
89
89
|
**`.claude/tasks/`**
|
|
90
90
|
|
|
91
|
-
- Mark completed outcomes `[x]` in
|
|
91
|
+
- Mark completed outcomes `[x]` in the task's own file through `aitk tasks outcome <stem> --close <n> --json`, repeating `--close` for each. Positions count every outcome checkbox in file order from 1, which the read above already gives. The verb resolves the board at the main worktree root in-process, which is the route because this is an edit inside an existing file and the file-editing tools refuse that path from a linked worktree. Do not move or archive the file.
|
|
92
92
|
- Write a newly identified task as its own file, following `.claude/standards/tasks.md` for the filename and frontmatter.
|
|
93
93
|
- Do not touch task files this session did not change.
|
|
94
94
|
- Never hand-edit `.claude/tasks/index.md`. A hook regenerates it.
|
|
@@ -164,6 +164,8 @@ The base lint-staged config runs `aitk indexes regen` on every committed `*.md`,
|
|
|
164
164
|
|
|
165
165
|
Sweep reviews this session consumed, and sweep plans across the whole board. Resolve all paths at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`.
|
|
166
166
|
|
|
167
|
+
Every move and delete below is a shell operation, so send each as a plain single `Bash` command rather than joining a `mkdir -p` to the `mv` with `&&`, which is refused as compound from a linked worktree. The one edit inside an existing file is the `Plan:` retarget, and no verb covers it: read the task file and write it back whole with a heredoc, which the file-editing tools refuse from a linked worktree and no shell stream editor may do.
|
|
168
|
+
|
|
167
169
|
**Plans.** Scan every file in `.claude/tasks/`, not only the ones this session touched. For each task file whose outcomes are now all `[x]`, check for a `Plan:` line directly under the title and parse the target. The line carries a markdown link, so read the target out of the parentheses rather than taking the rest of the line. A task still carrying the older bare-path form parses the same way once the link is absent, so accept both. Resolve the target against `.claude/tasks/` before routing on it, which lands `../plans/x.md` and `.claude/plans/x.md` on the same file. The bullets below name resolved locations, so an unresolved target falls to the last one and no plan is ever archived. Never delete a plan. `.claude/standards/plan.md` owns the archive destination and why a shipped plan is moved rather than removed.
|
|
168
170
|
|
|
169
171
|
Board-wide scope is the one place this sweep reaches past Step 3's rule against touching task files the session did not change. A board carrying a task that closed while an earlier run missed its archive is the defect this exists to clear, and skipping those tasks would preserve it. Reaching them is safe because the archive moves the plan and points the task at the new path, so a task from unrelated work ends up with a working pointer rather than a broken one.
|
|
@@ -79,6 +79,8 @@ Omit empty sections. Do not print `None identified.` in chat.
|
|
|
79
79
|
|
|
80
80
|
Derive a 2-to-4-word kebab-case slug from the feature description. Write the full plan to `.claude/plans/feature-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist.
|
|
81
81
|
|
|
82
|
+
From a linked worktree the file-editing tools refuse that path, so the plan goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
83
|
+
|
|
82
84
|
The file follows the template in `.claude/standards/plan.md`. Copy the shape from there rather than from this body, so one edit to the standard moves every plan.
|
|
83
85
|
|
|
84
86
|
Run `aitk records validate plans` after writing the file when the CLI is on PATH. It reports a section, a filename, or an answer slot that does not hold, and it writes nothing.
|
|
@@ -14,6 +14,7 @@ The filename and its type prefix, the frontmatter, the body shape each type carr
|
|
|
14
14
|
## Guards
|
|
15
15
|
|
|
16
16
|
- All `.claude/memory/` reads and writes resolve at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`.
|
|
17
|
+
- From a linked worktree the file-editing tools refuse every path below, so each write in this skill goes out through `Bash` as a plain single command. A memory entry holds one fact and this session has read it, so an update rewrites the whole file with a heredoc rather than editing a line inside it.
|
|
17
18
|
- If `.claude/memory/` does not exist at the main worktree root, create it, along with an `index.md` carrying `title` and `subtitle` frontmatter. `aitk claude init` seeds both, and a project predating that seed has neither. Regeneration errors without the index, so the first write into a bare folder would report a frontmatter failure against a file that is fine.
|
|
18
19
|
- If the session produced no user corrections, confirmations, or context disclosures worth persisting, stop: `✅ Nothing worth capturing.`
|
|
19
20
|
- Routing edits a tracked file, so it runs only where the caller commits. When the session is in the main worktree, or the caller states it does not commit, skip Step 3 and write every candidate as a memory file. `claude-orchestrate` is the caller this covers.
|
|
@@ -45,7 +46,7 @@ For each project candidate, match its subject against `.claude/context/index.md`
|
|
|
45
46
|
|
|
46
47
|
Fail closed. A project candidate matching no entry stays a memory file, and so does one matching two entries where neither is clearly the owner. The residue is what the folder is for, and a fact filed under the wrong entry is worse than one in memory because a context entry is a surface sessions trust.
|
|
47
48
|
|
|
48
|
-
Do not edit a context entry here. `claude-docs` owns those edits and folds the routed facts in on its own pass, or two skills write one file at the same step. Write each routed fact to `.claude/.tmp/memory-routing/<slug>.md` at the main worktree root instead, appending when the file exists:
|
|
49
|
+
Do not edit a context entry here. `claude-docs` owns those edits and folds the routed facts in on its own pass, or two skills write one file at the same step. Write each routed fact to `.claude/.tmp/memory-routing/<slug>.md` at the main worktree root instead, appending when the file exists. An append is a whole-file operation the shell does directly, so send it as a plain single `Bash` command carrying a heredoc:
|
|
49
50
|
|
|
50
51
|
```markdown
|
|
51
52
|
## .claude/context/<domain>.md
|
|
@@ -59,7 +60,7 @@ The handoff is a file rather than a spoken result so the routed fact survives a
|
|
|
59
60
|
|
|
60
61
|
## Step 4: dedupe
|
|
61
62
|
|
|
62
|
-
For each remaining candidate, grep `.claude/memory/` for an existing file on the same topic. If one exists, update it in place rather than create a new file.
|
|
63
|
+
For each remaining candidate, grep `.claude/memory/` for an existing file on the same topic. If one exists, update it in place rather than create a new file. Read it first and write the whole file back, since the guard above rules out editing a line inside it.
|
|
63
64
|
|
|
64
65
|
## Step 5: write the residue
|
|
65
66
|
|
|
@@ -69,6 +70,12 @@ Two of its rules are the ones a capture pass gets wrong under time pressure. Sta
|
|
|
69
70
|
|
|
70
71
|
Do not edit the index. `.claude/memory/index.md` is generated from sibling frontmatter by a `PostToolUse` hook, the same way the task board's index is, so a hand-appended row is drift the next regeneration discards.
|
|
71
72
|
|
|
73
|
+
The hook matches `Write|Edit|MultiEdit`, so nothing fires on the shell writes a linked worktree makes. Regenerate the index once after the last write when the entries went out through `Bash`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
aitk indexes regen --no-stage --root <main-root> <main-root>/.claude/memory/index.md
|
|
77
|
+
```
|
|
78
|
+
|
|
72
79
|
Run `aitk records validate memory` when the writes are done and fix what it names. It reads the whole pen rather than this session's writes, so treat a finding on a carried entry as one to fix in place rather than as a reason to stop.
|
|
73
80
|
|
|
74
81
|
## Output
|
|
@@ -26,6 +26,7 @@ If the user re-pings the skill with no new phrase and a receipt exists, default
|
|
|
26
26
|
- If `.claude/memory/` contains no `*.md` entries other than `index.md`, stop: `✅ No memory entries to review.`
|
|
27
27
|
- Cleanup is exempt from the two stops above. It works on receipts in `.claude/review/`, and a drained pen is the normal state once Apply has run, so a pen-shaped stop would strand the receipt it exists to delete.
|
|
28
28
|
- Resolve the main root via `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd`. All review and memory reads anchor here.
|
|
29
|
+
- From a linked worktree the file-editing tools refuse every main-root path, so each write below goes out through `Bash` as a plain single command. The receipt and a memory entry are both short and this session has read them whole, so a rewrite replaces the file with a heredoc rather than editing a line inside it. Promotion targets are tracked files at `pwd` and keep taking `Edit`.
|
|
29
30
|
|
|
30
31
|
## Propose phase
|
|
31
32
|
|
|
@@ -90,6 +91,8 @@ Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../s
|
|
|
90
91
|
|
|
91
92
|
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.
|
|
92
93
|
|
|
94
|
+
A phase changing items reads the receipt, applies every change for that phase, and writes the whole file back in one command. Batching is what keeps a per-item rewrite from costing a full read each time, and it is the only route from a linked worktree, where the guard above rules out editing a line in place.
|
|
95
|
+
|
|
93
96
|
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.
|
|
94
97
|
|
|
95
98
|
Rewrite the review file in place whenever the proposal changes mid-review. The file stays the source of truth for the current decisions.
|
|
@@ -151,7 +154,7 @@ Action by action type:
|
|
|
151
154
|
- **Hand off**: do not edit governance. Archive the memory file only if the user confirmed the handoff explicitly. Otherwise leave it in place.
|
|
152
155
|
- **Retire**: archive the memory file.
|
|
153
156
|
|
|
154
|
-
Archiving means creating `.claude/.tmp/memory-archive/` at the main worktree root and moving the file there under its original name, overwriting any file already at that name. Never delete a memory entry. Nothing recovers one from a gitignored folder.
|
|
157
|
+
Archiving means creating `.claude/.tmp/memory-archive/` at the main worktree root and moving the file there under its original name, overwriting any file already at that name. Send the `mkdir -p` and the `mv` as two plain commands rather than joining them with `&&`, which is refused as compound from a linked worktree. Never delete a memory entry. Nothing recovers one from a gitignored folder.
|
|
155
158
|
|
|
156
159
|
Do not hand-edit `.claude/memory/index.md`. Once every archive move is done, regenerate it instead:
|
|
157
160
|
|
|
@@ -161,7 +164,7 @@ aitk indexes regen --no-stage --root <main-root> <main-root>/.claude/memory/inde
|
|
|
161
164
|
|
|
162
165
|
The `PostToolUse` hook that keeps the index current matches `Write|Edit|MultiEdit`, and an archive move is a shell `mv`, so nothing fires on it. Without this call the index keeps a row per archived entry and drifts exactly the way the hand-appended one did. Run it once after the last move rather than per item.
|
|
163
166
|
|
|
164
|
-
Apply edits one at a time via `Edit`. Claude Code's tool permission dialog is the confirmation gate per edit. Never rewrite a whole
|
|
167
|
+
Apply promotion edits one at a time via `Edit`. Claude Code's tool permission dialog is the confirmation gate per edit. Never rewrite a whole promotion target. This governs the tracked surfaces a promote lands in, which sit at `pwd` and take `Edit` from anywhere. The receipt and the memory entries are main-root scratch and follow the guard instead.
|
|
165
168
|
|
|
166
169
|
As each item resolves, update its status in the review file: flip the H2 emoji from 📝 to ✅ for applied, ⏭ for skipped, 📦 for retired, or 🤝 for handed off. Refresh the summary block counts at the top. Do not delete the review file. It stays as a receipt until Cleanup runs or the next Propose pass overwrites it.
|
|
167
170
|
|
|
@@ -122,6 +122,8 @@ Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../s
|
|
|
122
122
|
|
|
123
123
|
Write the full report directly to `.claude/review/review-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
|
|
124
124
|
|
|
125
|
+
From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
126
|
+
|
|
125
127
|
If there are no findings, write `✅ No findings.` to the file with a timestamp.
|
|
126
128
|
|
|
127
129
|
The `.claude/review/` directory is gitignored. Do not stage or commit the file.
|
|
@@ -43,6 +43,8 @@ Build a 2-to-4-word kebab-case slug from the topic and discovery answers. Exampl
|
|
|
43
43
|
|
|
44
44
|
Create `.claude/.tmp/screencast/<slug>.md` at the main worktree root. Create the directory if it does not exist. The file is gitignored.
|
|
45
45
|
|
|
46
|
+
From a linked worktree the file-editing tools refuse that path, so the draft goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
47
|
+
|
|
46
48
|
Write all eight sections. Pre-seed every section with concrete content so the draft is shippable as-is. The user edits down rather than fills blanks.
|
|
47
49
|
|
|
48
50
|
```markdown
|
|
@@ -68,6 +68,8 @@ Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../s
|
|
|
68
68
|
|
|
69
69
|
Write the full proposal to `.claude/review/seed-audit-<slug>.md` at the main worktree root. Do not print the proposal inline.
|
|
70
70
|
|
|
71
|
+
From a linked worktree the file-editing tools refuse that path, so the proposal goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
72
|
+
|
|
71
73
|
Structure: a summary block at the top, a legend, a scope table, then one H2 per numbered item. Number items across all files so the user can reference them by number. Fuse the status, action, and target into each H2. Every item starts as 📝 pending.
|
|
72
74
|
|
|
73
75
|
````markdown
|
|
@@ -12,9 +12,10 @@ Read `.claude/standards/tasks.md` from the project root before writing any file,
|
|
|
12
12
|
## Guards
|
|
13
13
|
|
|
14
14
|
- Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
|
|
15
|
+
- From a linked worktree the file-editing tools refuse that root, so a new task file goes out through `Bash` as a plain single command carrying a heredoc. Archiving already runs through `aitk tasks archive`, which resolves the root in-process. Marking an outcome shipped is `claude-docs` and runs through `aitk tasks outcome`. See Worktrees in `CLAUDE.md`.
|
|
15
16
|
- If `.claude/tasks/` does not exist at that root, stop: `❌ No .claude/tasks/ board. Run aitk claude init to set it up.`
|
|
16
17
|
- Route on the request rather than on a flag. Creating names work that does not exist yet, archiving names a task file already on the board. If the request fits neither, stop: `❌ Ambiguous. Say whether to create a task or archive one.`
|
|
17
|
-
- Never hand-edit `.claude/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly.
|
|
18
|
+
- Never hand-edit `.claude/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly, except after a shell write from a linked worktree: the hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case regenerates explicitly with `aitk indexes regen --no-stage --root <main-root> <main-root>/.claude/tasks/index.md`.
|
|
18
19
|
|
|
19
20
|
## Create
|
|
20
21
|
|
|
@@ -84,6 +85,7 @@ Each reason has one resolution and none of them is to archive around it:
|
|
|
84
85
|
- `plan-unswept`: stop and route to `claude-docs`, which owns the plans sweep and the last-live-citation rule. `❌ Plan not yet swept. Run /claude-docs first, then archive.`
|
|
85
86
|
- `ambiguous`: two tasks name one pull request, which is the misfile `.claude/standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
|
|
86
87
|
- `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
|
|
88
|
+
- `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
|
|
87
89
|
|
|
88
90
|
Do not move a plan from this skill. `claude-docs` owns that move. Two skills relocating the same file drift into relocating it differently.
|
|
89
91
|
|
|
@@ -61,6 +61,8 @@ Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../s
|
|
|
61
61
|
|
|
62
62
|
When a manual checklist is produced, write it directly to `.claude/review/ui-checklist-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
|
|
63
63
|
|
|
64
|
+
From a linked worktree the file-editing tools refuse that path, so the checklist goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
65
|
+
|
|
64
66
|
Skip the file write when all changes are covered by e2e tests and no checklist was produced.
|
|
65
67
|
|
|
66
68
|
The `.claude/review/` directory is gitignored. Do not stage or commit the file.
|
|
@@ -62,6 +62,8 @@ Derive `<slug>` per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../s
|
|
|
62
62
|
|
|
63
63
|
Write the full report directly to `.claude/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`. Create the directory if it does not exist. Always overwrite.
|
|
64
64
|
|
|
65
|
+
From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
|
|
66
|
+
|
|
65
67
|
If there are no observations, write `✅ No observations.` to the file with a timestamp.
|
|
66
68
|
|
|
67
69
|
The `.claude/review/` directory is gitignored. Do not stage or commit the file.
|
|
@@ -108,11 +108,17 @@ printf 'number=%s\nurl=%s\n' "$pr_number" "$pr_url"
|
|
|
108
108
|
|
|
109
109
|
Write the `number` the final command printed onto the task the branch is closing. Do not resolve it again. A head branch that carried an earlier pull request now has two, and a second `gh pr view` would pick between them by a precedence rule nothing here states. Reading what created or edited the pull request needs no such rule.
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
The task is the one whose `Plan:` line names the plan this branch implemented. Name that plan by its file, which is `.claude/plans/feature-<slug>.md` at the main worktree root with `<slug>` derived per `.claude/standards/slug.md`, or `${CLAUDE_SKILL_DIR}/../../standards/slug.md` when the project does not have it. `claude-feature` writes the plan under the branch slug, so the two correspond on any branch that came through the plan-to-execute path. When the session already knows which plan it implemented, because a caller read it earlier in the chain, use that filename instead of re-deriving.
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
```bash
|
|
114
|
+
aitk tasks pull-request <number> --plan feature-<slug> --json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The slug is a guess at which plan this branch carries rather than a fact about the task, which is why the verb re-checks it against the board and refuses instead of writing on a near miss. A branch whose slug names no plan file falls to the silent skip below, the same as one whose plan no task cites.
|
|
118
|
+
|
|
119
|
+
The verb resolves the board at the main worktree root in-process, adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already carries, and corrects the number in place when the line exists. This is the route because the write is an edit inside an existing file, which the file-editing tools refuse from a linked worktree and which no shell stream editor may make. See Worktrees in `CLAUDE.md`.
|
|
114
120
|
|
|
115
|
-
Skip this silently
|
|
121
|
+
Skip this silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`. Those are the three cases a guessed write would compound: no board, no task naming the plan, or more than one. One task, one pull request, and a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
|
|
116
122
|
|
|
117
123
|
The number is what lets the merge close the task. Every merge on `main` is a squash carrying it in the subject, so the number survives where a branch name does not, and `post-merge` reads it back to call `aitk tasks archive`. Writing it here rather than at worktree time is what makes it a pull request number rather than a branch the squash discards.
|
|
118
124
|
|
package/docs/agents/commands.md
CHANGED
|
@@ -27,6 +27,8 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
|
|
|
27
27
|
| `aitk feedback` | Write toolkit feedback from stdin to `.claude/review/`, or open a GitHub issue with `--github` |
|
|
28
28
|
| `aitk transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`) |
|
|
29
29
|
| `aitk tasks archive` | Move a shipped task off the board, clear its ordering row, and regenerate the index |
|
|
30
|
+
| `aitk tasks pull-request` | Record a pull request number on the task a branch closes, by stem or `--plan` (`--json`) |
|
|
31
|
+
| `aitk tasks outcome` | Mark outcomes `[x]` on a task by position, repeating `--close` (`--json`) |
|
|
30
32
|
| `aitk tasks validate` | Report board rows whose plan, task file, group, or file set does not hold (`--json`) |
|
|
31
33
|
| `aitk records validate` | Report a session record against the standard governing it, per kind (`--json`) |
|
|
32
34
|
| `aitk comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
|
|
@@ -19,7 +19,7 @@ It reports rather than gates by default, the closer call because a missing secti
|
|
|
19
19
|
|
|
20
20
|
## Length and depth
|
|
21
21
|
|
|
22
|
-
Length and depth
|
|
22
|
+
Length quotes its checkpoint from `.claude/standards/context.md` and depth quotes its from `.claude/standards/markdown.md`, which states it over every markdown file: roughly 150 rendered lines for an entry, roughly 40 for a run no heading breaks. Depth measures the longest such run rather than everything under one `##`, skips fenced blocks so a markdown example does not read as three headings, and exempts a run whose lines are all list items at one indent averaging under 130 characters. The weight condition is what separates a scannable catalog of one-liners from a stack of paragraph-bullets, which reach the same count and read nothing alike.
|
|
23
23
|
|
|
24
24
|
Depth exempts a second shape, and the two are excused for opposite reasons. A peer list is already navigable, so a subheading dropped into it splits a set that belongs together. A table is exempt because the remedy does not exist: a heading placed inside one splits the table rather than the run, so a catalog renders as an unbroken stretch by construction and no edit short of rewriting it as a list clears the report. The test is whether the run is a table rather than whether it holds one, so a table with prose either side still reports and a heading breaks it at the seam. A run of piped lines carrying no delimiter row is not a table and reports like any other prose. The table finding above is unaffected, so a catalog silenced here still reports as a candidate for a bullet list, which is the measure whose remedy does exist.
|
|
25
25
|
|
|
@@ -27,7 +27,7 @@ Both checks count rendered lines rather than source lines, wrapping each line at
|
|
|
27
27
|
|
|
28
28
|
## Bullet weight and tables
|
|
29
29
|
|
|
30
|
-
The bullet check reports a top-level bullet past roughly 400 characters, which is where
|
|
30
|
+
The bullet check reports a top-level bullet past roughly 400 characters, which is where the overflow belongs in prose rather than in the bullet. A context entry specializes that remedy, sending the incident that motivated a decision to the change, issue, or research record behind it. Continuation lines fold into the bullet they belong to, so a heavy bullet cannot fall under the checkpoint by wrapping across two source lines, while a nested item is left out because the parent's own text is what the checkpoint asks about. Findings group by entry for the reason the provenance ones do, and reach every audited folder, since `.claude/standards/markdown.md` states the checkpoint over every markdown file. Unlike the peer-list threshold above it, this corpus has no gap behind the number: bullet weight decays smoothly from a median near 170, so the number is a judgment where that one was a measurement, and a bullet reading well past it means the number is wrong rather than the rule.
|
|
31
31
|
|
|
32
32
|
The table check reports a catalog that grows a row per shipped thing, not a table count. A fixed comparison table never reflows, so its size costs nothing. A table qualifies at six or more body rows whose first column mostly carries a path, command, or link, which is what separates a catalog from a comparison without reading the prose.
|
|
33
33
|
|
|
@@ -37,7 +37,7 @@ The provenance check reports the markers narrating how a domain reached its shap
|
|
|
37
37
|
|
|
38
38
|
## Which folders each check reaches
|
|
39
39
|
|
|
40
|
-
The provenance
|
|
40
|
+
The provenance and required-section checks cover `.claude/context/` alone, while length, depth, bullet weight, and the table finding reach every audited folder. What narrows the two is stated in `.claude/standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures. Depth and bullet weight are stated in `.claude/standards/markdown.md` over every markdown file, so both reach wherever the audit is pointed, and length and the table finding generalize as judgments about how far a reader travels. Required sections narrow for a plainer reason: the names are the context standard's own, and neither sibling standard states a required section at all. The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
|
|
41
41
|
|
|
42
42
|
## Index drift
|
|
43
43
|
|
package/docs/agents/index.md
CHANGED
|
@@ -22,4 +22,4 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
22
22
|
- [Sandbox](sandbox.md): Scenario routing, the expectation scoring surface, and the coverage census over scenarios and skills
|
|
23
23
|
- [Scripting](scripting.md): The runtime catalogs that replace hardcoded names, what each carries, and a headless invocation per domain
|
|
24
24
|
- [Skill audit](skills-audit.md): Measuring both skill corpora against standards/skill.md, the checks it reads, and the requirement gate that is the only failing one
|
|
25
|
-
- [Tasks](tasks.md): Selecting a shipped task by stem or pull request, the refusal reasons, the board checks validate runs, and why the board root defaults to the main worktree
|
|
25
|
+
- [Tasks](tasks.md): Selecting a shipped task by stem or pull request, recording a number and closing an outcome, the refusal reasons, the board checks validate runs, and why the board root defaults to the main worktree
|
package/docs/agents/tasks.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Tasks
|
|
3
|
-
description: Selecting a shipped task by stem or pull request, the refusal reasons, the board checks validate runs, and why the board root defaults to the main worktree
|
|
3
|
+
description: Selecting a shipped task by stem or pull request, recording a number and closing an outcome, the refusal reasons, the board checks validate runs, and why the board root defaults to the main worktree
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Tasks
|
|
@@ -22,7 +22,9 @@ aitk tasks archive --pull-request 673 --json
|
|
|
22
22
|
| `--json` | Emit a machine-readable record on stdout |
|
|
23
23
|
| `--root <path>` | Board root, defaulting to the main worktree |
|
|
24
24
|
|
|
25
|
-
Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, or `
|
|
25
|
+
Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, `plan-unswept`, or `bad-input`.
|
|
26
|
+
|
|
27
|
+
`bad-input` covers a malformed command line, which all three task verbs answer the same way. It is separate from `ambiguous` and `no-match` because those describe the board, and a caller that passed two selectors would otherwise be sent to repair a task citation that is fine.
|
|
26
28
|
|
|
27
29
|
The board is shared scratch at the main worktree root, so `--root` defaults to the first entry of `git worktree list` rather than the working directory. A linked worktree archives against the same board every other session reads.
|
|
28
30
|
|
|
@@ -32,6 +34,53 @@ Skills branch on the reason rather than on the exit code:
|
|
|
32
34
|
aitk tasks archive --pull-request 673 --json | jq -r 'if .ok then .task else .reason end'
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
## Pull request
|
|
38
|
+
|
|
39
|
+
`aitk tasks pull-request` records the number a branch's pull request carries onto the task that branch closes. It adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already holds, and corrects the number in place when the line exists.
|
|
40
|
+
|
|
41
|
+
Name the task by its filename stem, or by the plan its `Plan:` line points at:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
aitk tasks pull-request 673 v28.1-trigger-escalation
|
|
45
|
+
aitk tasks pull-request 673 --plan worktree-scratch-routing --json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
| Option | Behavior |
|
|
49
|
+
| --------------- | -------------------------------------------------- |
|
|
50
|
+
| `--plan <slug>` | Select the task whose `Plan:` line names this plan |
|
|
51
|
+
| `--json` | Emit a machine-readable record on stdout |
|
|
52
|
+
| `--root <path>` | Board root, defaulting to the main worktree |
|
|
53
|
+
|
|
54
|
+
A plan is matched on the token both spellings share, so `worktree-scratch-routing`, `feature-worktree-scratch-routing`, and `.claude/plans/feature-worktree-scratch-routing.md` all select the same task. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same number safe.
|
|
55
|
+
|
|
56
|
+
Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, or `ambiguous`. `git-pr` skips silently on those three, because each is a case where a guessed write would archive the wrong task once the branch merges.
|
|
57
|
+
|
|
58
|
+
A malformed argument refuses as `bad-input` instead, which sits outside that set on purpose. `git-pr` derives the number by slicing whatever `gh pr create` printed, so a non-numeric value is reachable, and folding it into the swallowed set would lose the number with nothing reporting it.
|
|
59
|
+
|
|
60
|
+
## Outcome
|
|
61
|
+
|
|
62
|
+
`aitk tasks outcome` marks outcomes `[x]` on a task by their position in its outcome list, counting every checkbox in file order from 1.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
aitk tasks outcome v28.1-trigger-escalation --close 1 --close 3
|
|
66
|
+
aitk tasks outcome --plan worktree-scratch-routing --close 2 --json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
| Option | Behavior |
|
|
70
|
+
| -------------------- | -------------------------------------------------- |
|
|
71
|
+
| `--close <position>` | Outcome to mark `[x]`, 1-based, repeatable |
|
|
72
|
+
| `--plan <slug>` | Select the task whose `Plan:` line names this plan |
|
|
73
|
+
| `--json` | Emit a machine-readable record on stdout |
|
|
74
|
+
| `--root <path>` | Board root, defaulting to the main worktree |
|
|
75
|
+
|
|
76
|
+
An outcome already closed comes back under `alreadyClosed` rather than refusing, so a rerun against the same positions changes nothing. A position past the end of the list refuses as `out-of-range`, since a caller counting wrong should hear about it rather than mark a neighbor.
|
|
77
|
+
|
|
78
|
+
Positions skip fenced blocks. A checkbox inside a sample a task displays is not an outcome the task claims, and counting one would shift every position after it. `aitk tasks archive` reads the list through the same walker, so the two verbs cannot disagree about which checkboxes are outcomes.
|
|
79
|
+
|
|
80
|
+
Exit codes: `0` closed, `1` refused. The `reason` field adds `no-outcomes`, `out-of-range`, and `bad-input` to the three above.
|
|
81
|
+
|
|
82
|
+
Both verbs exist because the write is an edit inside a file that already exists. `Edit` and `Write` refuse a main-root path from a linked worktree, and a shell stream editor is banned for in-place edits, so a verb resolving the board root in-process is the only route a skill body has. Creating a whole file needs no verb, because a heredoc through `Bash` writes it safely.
|
|
83
|
+
|
|
35
84
|
## Validate
|
|
36
85
|
|
|
37
86
|
`aitk tasks validate` reports what each row of `priority.md` claims against what the tree holds. It reads and never writes, because a row is a session's claim about readiness and a validator that repaired one would be asserting the claim it exists to test.
|
package/docs/ai-workflow.md
CHANGED
|
@@ -77,7 +77,7 @@ Run one orchestrator at a time. The board is gitignored, so a second session rea
|
|
|
77
77
|
|
|
78
78
|
Before a handoff, the orchestrator checks the plan against the tree rather than reading it: grep each construct it names and count the sites, confirm every phase label it cites is still open, and open each file it describes. A plan goes stale from whatever merged after it was written, and reading cannot catch that.
|
|
79
79
|
|
|
80
|
-
`.claude/plans/`, `.claude/review/`, and `.claude/memory/` all resolve at the main worktree root, so artifacts created in any session are visible from any sibling worktree. See [Claude Code and git worktrees](../wiki/claude/claude-worktrees.md) for the full rule and the domain-level fan-out guidance.
|
|
80
|
+
`.claude/plans/`, `.claude/review/`, and `.claude/memory/` all resolve at the main worktree root, so artifacts created in any session are visible from any sibling worktree. A session inside a worktree reads them directly, since the file-editing tools refuse a main-root path but `Read` resolves normally. It writes a whole file through the shell and makes a change inside an existing file through an `aitk` verb, which resolves the main root in-process. See [Claude Code and git worktrees](../wiki/claude/claude-worktrees.md) for the full rule and the domain-level fan-out guidance.
|
|
81
81
|
|
|
82
82
|
The plan's shape is fixed by `.claude/standards/plan.md`: the section list, the filename, the lifecycle, and the contract its questions keep. Every question carries a `- Suggested:` line and an empty `- Answer:` slot, and a blank answer accepts the suggestion at execution time. That default is what makes a plan decision-ready in one pass, and it is the opposite of the contract an intake folder keeps, where an empty slot means nobody reached the item.
|
|
83
83
|
|
package/package.json
CHANGED
package/src/commands/context.ts
CHANGED
|
@@ -193,7 +193,7 @@ async function runAudit(
|
|
|
193
193
|
reportSections(sections, folders)
|
|
194
194
|
reportLength(entries)
|
|
195
195
|
reportDepth(entries)
|
|
196
|
-
reportBullets(entries
|
|
196
|
+
reportBullets(entries)
|
|
197
197
|
reportTables(entries)
|
|
198
198
|
reportProvenance(entries, folders)
|
|
199
199
|
reportDrift(drift)
|
|
@@ -464,22 +464,11 @@ function reportDepth(entries: readonly EntryReport[]): void {
|
|
|
464
464
|
* entries carry them a dozen at a time, so a flat list of bullets buries the
|
|
465
465
|
* entry holding one. What a reader acts on is which file to open.
|
|
466
466
|
*/
|
|
467
|
-
function reportBullets(
|
|
468
|
-
entries: readonly EntryReport[],
|
|
469
|
-
folders: readonly AuditedFolder[],
|
|
470
|
-
): void {
|
|
467
|
+
function reportBullets(entries: readonly EntryReport[]): void {
|
|
471
468
|
logStep('Bullets')
|
|
472
469
|
|
|
473
|
-
const governed = folders.filter(governsContent)
|
|
474
|
-
if (governed.length === 0) {
|
|
475
|
-
logInfo(
|
|
476
|
-
`Out of scope. The rule is stated in the standard governing .claude/${PROVENANCE_FOLDER}/, and no audited folder is that one.`,
|
|
477
|
-
)
|
|
478
|
-
return
|
|
479
|
-
}
|
|
480
|
-
|
|
481
470
|
logInfo(
|
|
482
|
-
|
|
471
|
+
'Covers every audited folder, since the rule is stated in the standard governing every markdown file.',
|
|
483
472
|
)
|
|
484
473
|
logInfo(
|
|
485
474
|
'Top-level bullets measure characters, folding in continuation lines.',
|
package/src/commands/records.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { $ } from 'bun'
|
|
2
1
|
import type { Command } from 'commander'
|
|
3
2
|
import {
|
|
4
3
|
type Finding,
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
validateRecords,
|
|
9
8
|
} from '@/records/validate'
|
|
10
9
|
import { intro, logError, logInfo, logStep, logWarn, outro } from '@/ui'
|
|
10
|
+
import { mainWorktreeRoot } from '@/worktree'
|
|
11
11
|
|
|
12
12
|
/** Returned when a record carries a finding, which is the gating result. */
|
|
13
13
|
const EXIT_FINDINGS = 2
|
|
@@ -17,23 +17,6 @@ interface ValidateCommandOptions {
|
|
|
17
17
|
readonly root?: string
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* The session-record folders are shared scratch at the main worktree root, and
|
|
22
|
-
* `git worktree list` puts that root first. Trusting the working directory would
|
|
23
|
-
* validate a linked worktree's empty folder and report it clean.
|
|
24
|
-
*/
|
|
25
|
-
async function mainWorktreeRoot(): Promise<string> {
|
|
26
|
-
const result = await $`git worktree list --porcelain`.quiet().nothrow()
|
|
27
|
-
if (result.exitCode !== 0) return process.cwd()
|
|
28
|
-
|
|
29
|
-
const line = result.stdout
|
|
30
|
-
.toString()
|
|
31
|
-
.split('\n')
|
|
32
|
-
.find((entry) => entry.startsWith('worktree '))
|
|
33
|
-
|
|
34
|
-
return line ? line.slice('worktree '.length).trim() : process.cwd()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
20
|
export function register(program: Command): void {
|
|
38
21
|
const records = program
|
|
39
22
|
.command('records')
|