@erclx/aitk 0.89.1 → 0.91.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "0.89.1",
4
+ "version": "0.91.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -11,6 +11,8 @@ Without this skill, review findings are worked in whatever order the author read
11
11
 
12
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
13
 
14
+ A declined finding fails on a third axis, which is where its reason ends up. A worker answering a dispatch by naming the plan question that already settled the finding, or the constraint the diff never showed, settles it in whichever session heard the answer. Both sessions end, so a reader opening the thread later finds a finding that stopped being mentioned and no record of what stopped it, which is the durability the posted review already has by design.
15
+
14
16
  ## Must
15
17
 
16
18
  - Treat a failing check as a finding alongside the review comments, so the follow-up closes both
@@ -22,6 +24,7 @@ A branch also goes stale from `main` moving rather than from anything the branch
22
24
  - Rebuild a generated file through the project check rather than resolving its conflict by hand
23
25
  - Push before replying, so the comment never runs ahead of the code it describes
24
26
  - Map every finding to what changed, or to a one-line reason when it is a question or a conscious accept
27
+ - Carry the fact behind a declined finding into the posted reply rather than into the message that answered the dispatch, since both sessions end and the thread is what the next reader opens
25
28
  - Post the terminal comment only when the findings are addressed and every check passes
26
29
  - 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
27
30
  - Scan the reply for banned characters and internal phase labels before posting, since the comment leaves for the remote unchecked
@@ -33,6 +36,8 @@ A branch also goes stale from `main` moving rather than from anything the branch
33
36
  - Post the closing comment while a check is failing
34
37
  - Reimplement the follow-up push or the doc refresh. Both have owners, and a second copy here drifts from them.
35
38
  - Edit silently. A finding answered without a reply leaves the reviewer re-deriving the change from the diff.
39
+ - Answer a finding in the channel alone. A reply that changes what the review concluded is the one the thread has to carry.
40
+ - Post a correction to what the reviewing session believes about the world. That class changes no finding here and belongs in the session record.
36
41
  - Take one side of a conflict wholesale. Both sides are valid content, so `--ours` or `--theirs` drops one silently and passes every check.
37
42
  - Merge `main` into the branch. The repository squash-merges, so a merge commit reads as noise on the pull request.
38
43
  - 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.
@@ -114,6 +114,23 @@ bullet per finding, each opening with the bolded finding identifier.
114
114
  Close the body with `🤖 Addressed by Claude Code` on its own line so the reply
115
115
  reads as an independent machine pass, not a human sign-off.
116
116
 
117
+ A finding this run declined carries the fact that settled it, inside its own
118
+ bullet rather than in a section of its own. Name the plan question that already
119
+ answered it, the constraint the diff does not show, or the measurement the
120
+ reviewer did not have. Answering the dispatch in the channel and leaving that
121
+ fact there loses it when both sessions end, and the reviewer is left with a
122
+ finding that stopped being mentioned. The rule fires on a bullet the body already
123
+ writes, so nothing depends on judging mid-reply whether a reply was important.
124
+
125
+ The rule reaches a finding and nothing else. A correction to what the reviewing
126
+ session believes about the world, such as which session holds which branch or
127
+ what an edit passes through before it lands, changes no finding on this pull
128
+ request and belongs in that session's own record rather than on a thread that
129
+ closes. Keep it off the comment, and answer it wherever the dispatch reached this
130
+ session when one did. Nothing tests the reply for either rule, since the scan
131
+ below reads it for banned characters and phase labels alone, so both halves hold
132
+ while a run applies them.
133
+
117
134
  When step 5 rebased the branch, say so in the summary sentence and name which
118
135
  files were resolved by hand and which the regen rebuilt. The next review is a
119
136
  full pass rather than a delta, and the reader is owed the reason.
@@ -97,7 +97,7 @@ Do not close while an open question quietly fails an outcome. Resolve it, or rec
97
97
 
98
98
  ## Output
99
99
 
100
- Emit the full relative path from the project root for every file written or updated. Bare filenames are not clickable.
100
+ Emit the full relative path from the project root for every file written or updated. A bare filename names a file the reader cannot open.
101
101
 
102
102
  Open and resume:
103
103
 
@@ -101,7 +101,14 @@ A file the pass only read gets no line, which is what keeps the block short.
101
101
 
102
102
  **Open questions:** <N> awaiting your call
103
103
 
104
- Next: answer the `You:` slots, then /claude-tasks to promote what is ready
104
+ Next: /claude-intake-answer to answer the `You:` slots from here, or type them
105
+ into the files, then /claude-tasks to promote what is ready
105
106
  ```
106
107
 
107
108
  Use `📂 Resumed` in place of `📂 Opened` on a resume pass.
109
+
110
+ ## Answering what this pass wrote
111
+
112
+ The slots this pass leaves empty are answered by editing each cluster file, or from chat through `claude-intake-answer`, which walks the unread items in batches and writes each selection back onto the item it answers. Name that route in the closing line so the operator finds it where they look for it.
113
+
114
+ Do not invoke it from here. It is operator-triggered, and a pass that files a dump and answers it in the same run decides items on silence.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: claude-intake-answer
3
+ description: Scope boundary for answering a filed intake from chat, and the write-back contract that keeps the file rather than the conversation as the record
4
+ ---
5
+
6
+ # Claude intake answer requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, an operator answers a filed intake by opening each cluster file and typing under each item, so a dump spanning six clusters is six files navigated in turn and the cost scales with how well the pass split the domains. The folders that go unanswered are the large ones, which are the ones a breadth pass exists to produce.
11
+
12
+ A session asked to help with that fails in shapes the intake standard already names. It reads an empty slot as agreement and reports items decided that nobody reached. It writes an answer into the conversation and never into the file, so the record still reads as unread and the next session re-asks. It types the answer into `00-overview.md`, where retrieval walks item headings and finds nothing. It overwrites a slot the operator already filled, discarding a decision already made.
13
+
14
+ The write itself fails a fourth way that no prose rule prevents. Every worker runs in a linked worktree where the file-editing tools refuse a main-root path, and a stream editor expands an unescaped ampersand in the replacement to the whole match and exits zero when it matches nothing. A body instructing either route reports success and loses the answer.
15
+
16
+ The batching fails a fifth way. A folder holding thirty unread items put as thirty questions is unanswerable, and put as one flat batch it hides which cluster the operator is in and leaves a file half answered when attention runs out.
17
+
18
+ ## Must
19
+
20
+ - Offer every item carrying an empty answer slot, not only the ones carrying an open question, since the standard's one-token accept exists for a verdict with no question attached
21
+ - Batch by cluster in the folder's own numbering, so the operator has a stopping point that leaves whole clusters unread rather than a file half answered
22
+ - Cap a batch at four items, which is what a structured question tool takes
23
+ - Rank the item's own suggestion or verdict first and give every option what it costs, since the pass already made a recommendation and burying it asks the operator to re-derive it
24
+ - Land every selection through a verb that resolves the root in-process and rewrites the whole line, which is the only route that works from a linked worktree
25
+ - Write one cluster per call, since concurrent calls against one file race on the read and keep only the last answer
26
+ - Carry the cluster and the label together, because items are labeled per file and a label alone names an item in every cluster at once
27
+ - Pass a label exactly as its heading spells it, letter suffix included, since a pass that splits a finding after the fact labels the halves rather than renumbering the file
28
+ - Report what stays unread by count after each cluster
29
+
30
+ ## Must not
31
+
32
+ - Fill a slot the operator did not answer, including the remainder of a batch they abandoned
33
+ - Infer an answer from the conversation having happened, which is the inversion the intake standard states against the plan standard
34
+ - Overwrite a slot already carrying an answer, which is a decision already made
35
+ - Write anywhere in the folder but an item's answer slot, and never into the index, which carries none
36
+
37
+ ## Guards
38
+
39
+ - No intake folder at all, stop and name the skill that files one
40
+ - The named folder carrying no unread item, stop rather than re-asking answered items
41
+
42
+ ## Out of scope
43
+
44
+ - Filing a dump and writing the items, which is `claude-intake` and owns every other write into the folder
45
+ - Promoting an answered item onto the board, which is `claude-tasks` and runs after the answers land
46
+ - The item format, the answer contract, and retrieval, which `standards/intake.md` owns and this skill cites
47
+ - The comparable answer slots in groundwork and feature plans, which carry their own contracts and are a separate measurement
48
+ - Deciding when to fire. The skill is user-invoked through `disable-model-invocation`, so answering is the operator's call rather than a description match.
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: claude-intake-answer
3
+ description: Walks an intake folder's unread items and puts them as batched questions in chat, writing each selection back onto the item it answers. Use when asked to "answer the intake", "work through the open items", "answer my intake questions", "go through the dump", or "let me answer these from here". Do NOT use to file a dump or write new items, which is `claude-intake`.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # Claude intake answer
8
+
9
+ Put an intake folder's unread items as batched questions, then land each selection in the slot it answers.
10
+
11
+ A folder is answered by opening each cluster file and typing under the item, which on a dump spanning six clusters means navigating to each in turn. This walks the same items in chat and writes the answers back, so the file rather than the conversation stays the record.
12
+
13
+ Read `.claude/standards/intake.md` from the project root before writing anything, or `${CLAUDE_SKILL_DIR}/../../standards/intake.md` when the project does not have it. It holds the item format and the answer contract this skill is bound by.
14
+
15
+ ## Guards
16
+
17
+ - If `aitk intake list --json` reports no folder, stop: `❌ No intake to answer. Run /claude-intake to file a dump first.`
18
+ - If the named folder has no unread item, stop: `❌ Every item in <slug> carries an answer. Nothing to ask.`
19
+ - Never fill a slot the operator did not answer. An abandoned batch leaves every unreached item unread, which is what the empty slot already means.
20
+ - Never infer an answer from the conversation having happened. A selection reaches the file through the verb or not at all.
21
+ - Do not promote an item, edit a verdict, or write outside the answer slots. Promoting runs through `claude-tasks` after the answers land.
22
+
23
+ ## Step 1: pick the folder
24
+
25
+ Run `aitk intake list --json` and read the per-folder counts. With one folder carrying unread items, take it. With several, put the folders as one question carrying each slug and its unread count, and let the operator pick.
26
+
27
+ Never guess from the topic of the conversation. A session resuming against the wrong folder answers items nobody asked about.
28
+
29
+ ## Step 2: collect one cluster
30
+
31
+ Run `aitk intake list <slug> --unread --json`. It returns the unread items grouped by the cluster file holding them, each carrying its label, title, open question, and suggestion.
32
+
33
+ Work one cluster at a time, in the order the folder numbers them. A dump of six clusters holding five items each is thirty questions, and a surface putting all of them at once is unusable. The cluster boundary is also where an operator who runs out of attention stops cleanly, leaving whole clusters unread rather than one file half answered.
34
+
35
+ ## Step 3: put the batch
36
+
37
+ Cap each batch at four items, which is what a structured question tool takes. A cluster carrying more than four unread items takes several batches in file order.
38
+
39
+ Every item with an empty slot is offered, not only the ones carrying an open question. An item with a verdict and no question is still asking whether the verdict stands, and the standard's one-token accept exists for exactly that case.
40
+
41
+ Shape each question from what the item carries:
42
+
43
+ - The item's label and title name the question, so the operator knows which item is being asked about
44
+ - An item carrying `Open:` puts that question with its `Suggested:` line ranked first and marked as the suggestion
45
+ - An item carrying no `Open:` puts its verdict, with accepting it ranked first as `ok` and the alternatives drawn from what the verdict could otherwise be
46
+
47
+ Give every option what it means and what it costs. An option with no stated cost is not an option, since the operator picks it without knowing what the other one buys.
48
+
49
+ Send the whole batch in one turn. When the session runs on a surface carrying a structured question tool, such as `AskUserQuestion` in Claude Code, send it through one call with one entry per item. Otherwise write it as a numbered list in one message with the suggestion marked.
50
+
51
+ ## Step 4: write the batch back
52
+
53
+ Land every answered item in the cluster with one call:
54
+
55
+ ```bash
56
+ aitk intake answer <slug> --cluster <file> --set <label>=<answer> --set <label>=<answer>
57
+ ```
58
+
59
+ One call per cluster, never one per item. Items are labeled per cluster file, so the label alone does not identify an item and the cluster travels with it. Four separate calls against one file also race on the read and drop every answer but the last.
60
+
61
+ Pass the label exactly as the heading spells it, including a letter suffix such as `3a`. Write the operator's selection as the answer, using `ok` for a verdict accepted as it stands.
62
+
63
+ The verb refuses an item that already carries an answer rather than overwriting it, and refuses the whole batch when any item in it is filled. A filled slot is a decision already made. On that refusal, drop the named item from the batch and send the rest.
64
+
65
+ An item the operator left unanswered is omitted from the call entirely. Do not pass it with an empty value, which writes a slot that reads as answered.
66
+
67
+ ## Step 5: continue or stop
68
+
69
+ After each cluster, state how many clusters still carry unread items and continue to the next. Stop when the operator says to stop, and report what is left rather than pressing on.
70
+
71
+ Answers are on disk as each cluster completes, so a session ending mid-folder loses nothing.
72
+
73
+ ## Output
74
+
75
+ Report per cluster as it lands, then close with the folder's state:
76
+
77
+ ```plaintext
78
+ ✅ <N> answered in <file>
79
+ <label>. <answer>
80
+
81
+ 📋 <N> cluster(s) still carrying unread items in <slug>
82
+ ```
83
+
84
+ Close the run with the path so the reader can open what changed:
85
+
86
+ ```plaintext
87
+ ✅ <N> answered across <N> cluster(s) in <slug>
88
+ <M> item(s) left unread
89
+ .claude/intake/<slug>/
90
+ ```
@@ -33,6 +33,8 @@ The runbooks the session cannot run from memory fail on a third axis, which is w
33
33
 
34
34
  Every one of them therefore has to ship inside the skill, the four covering the moments the loop cannot detect and the fifth holding the review trigger. That last one fails on an axis of its own, since it names one client's command as the way to start the loop, so a session holding a different recurring-prompt scheduler reaches no path and a client without that command reaches none either, and the file ships to every target holding the plugin.
35
35
 
36
+ The dispatch's return leg is unplaced for the same reason. A reply reaches this session as a message and settles a finding, corrects which session holds which branch, or names a gate a worker's edits pass through, and reading it is the whole of what happens to it. Both sessions then end, so the half that belonged on the pull request never reaches it and the half that belonged on the board is rediscovered by whoever needs it next.
37
+
36
38
  The session also records nothing of what it learns. Both other callers of memory capture are ship-chain skills and this one never ships, so the session taking every operator correction is the session with no moment that writes one down. Hanging that moment on the merge sweep answers it and bills the operator a capture pass per batch of merges while nothing is being built, which is a cost paid on the days shipping is fastest.
37
39
 
38
40
  ## Must
@@ -42,6 +44,7 @@ The session also records nothing of what it learns. Both other callers of memory
42
44
  - Verify a plan against the tree before handing it over, counting the sites it claims and opening the files it describes
43
45
  - List a candidate's file set against every track in flight, and serialize when the sets are not disjoint
44
46
  - Place every finding a merged pull request produced against the surface that owns it
47
+ - Place what the return leg carries by what it changes, sending an answer that settles a finding onto the pull request and one that corrects this session's model of the world to the task owning that surface, since neither becomes a record by being read
45
48
  - Date the roadmap line from that file's last commit, so an old sequence reads as old
46
49
  - Keep one planned, non-conflicting task in reserve beyond what is running
47
50
  - Refill the queue while a wave is still building, rather than on a merge and a thinning list alone, since neither of those fires across the window planning costs nothing
@@ -120,6 +120,8 @@ A session is reachable when it appears in a live listing, which reads what each
120
120
 
121
121
  The channel runs both ways and the return leg carries what the pull request cannot. A worker answering a posted finding by naming the plan question that had already declined it changes the outcome in the moment, where a thread comment waits on whoever reads it next. Read what a worker volunteers as part of the review rather than as an aside.
122
122
 
123
+ What arrives there does not become a record by being read, so place it by what it changes. An answer that settles a finding goes onto the pull request through the next pass, which withdraws or regrades that finding and names the fact behind it, per `claude-pr-review`. An answer that changes what this session believes about the world instead, which is a mapping correction or a constraint on what a worker can do, settles no finding and reaches no thread, so route it the way Boundaries below routes a change found while orchestrating, which lands it on the task owning the surface it describes. Writing a tracked file to hold either is forbidden here, which leaves the pull request and the board as the two surfaces this session writes.
124
+
123
125
  A plan written here is written against a tree several branches are already changing, so it names the file set of every track in flight as a constraint, one set per track, read from the Touches column of that track's row. State for each set which of the two acts it forbids, per Constraints in `.claude/standards/plan.md`, or `${CLAUDE_SKILL_DIR}/../../standards/plan.md` when the project does not have it. A bare path list leaves the worker guessing, which is how a plan ends up forbidding the repair of a citation the change broke.
124
126
 
125
127
  ## Boundaries
@@ -9,6 +9,8 @@ description: What the independent pull request review is for, the gaps it closes
9
9
 
10
10
  Without this skill, a pull request is reviewed only by the session that wrote it, which cannot see the roadmap sequence or a sibling branch in flight. Findings land in chat, where they are read once and leave the thread with no record. A review that opens and never closes is worse than none, since a reader scanning the thread cannot tell an unanswered review from a confirmed one, and the author's claim that findings are fixed is the only evidence they are.
11
11
 
12
+ A finding also stops being true by argument rather than by a fix. A worker naming the plan question that already declined it, or a constraint the pass could not see, settles it in the exchange that carried the answer, and the pass that accepts the argument drops the finding from its next body. A reader then sees a finding raised once and never mentioned again, which is indistinguishable from one everyone forgot.
13
+
12
14
  ## Must
13
15
 
14
16
  - Post until the review closes. A first pass opens against the whole change, and each later pass checks whether the prior findings landed.
@@ -17,6 +19,7 @@ Without this skill, a pull request is reviewed only by the session that wrote it
17
19
  - Scope a later pass to the commits added since the prior one, once that commit is confirmed to still reach the head
18
20
  - Apply the integration, contract, and consumer lenses a self-review structurally cannot
19
21
  - Post the closing pass even with nothing to report, since a review left unanswered reads as one nobody closed
22
+ - State a withdrawal or a regrade on the thread with the fact that settled it, since a finding dropped in silence reads the same as one nobody answered
20
23
  - Key the body file on the pull request number and the head commit, and on the response it answers once the head repeats, so no two passes overwrite each other
21
24
  - Scan the comment for banned characters and internal phase labels before posting, since a finding phrased against a phase label reaches a reader with no task board
22
25
 
@@ -87,6 +87,8 @@ Apply the high-signal filter: flag only what will cause incorrect behavior, brea
87
87
 
88
88
  A later pass applies the same axes to the delta, and adds one check the first pass cannot make: did each prior finding land, and did the fix regress anything it touched. Findings of its own are normal findings, stated at the same severity and counted the same way. That count is what Step 4 reads to pick the heading, so a pass raising one of its own is not a close-out.
89
89
 
90
+ A prior finding can also be settled by argument rather than by a fix. A reply naming the plan question that already declined it, or a constraint this session could not see, withdraws the finding or moves its grade. State that outcome in the body under the finding it changes, naming the fact that produced it, whether the argument arrived on the thread or through the channel that carried the dispatch. Dropping the finding from this body instead leaves a reader unable to tell a withdrawal from an oversight, and the reasoning goes with the session that heard it. A withdrawal removes the finding from the count, so a pass that withdrew every open item is a close-out. Write the withdrawal and its cause into that body rather than taking the short close-out line Step 4 supplies, which reports prior findings addressed and would credit a fix nobody made.
91
+
90
92
  Use severity: `critical` (blocks merge), `should-fix` (fix before merge), `minor` (visibility only).
91
93
 
92
94
  ## Step 4: post to the PR
@@ -166,6 +168,8 @@ gh pr review <number> --comment --body-file .claude/.tmp/pr-review/body-<number>
166
168
 
167
169
  A pass with no findings takes `## Review closed` and a short body, with the footer line included either way. On a first pass, post `✅ No blocking findings. Reviewed against project docs and roadmap.` On a later pass, post `✅ Prior findings addressed. Re-reviewed <short-sha>, N commits since the prior pass.`
168
170
 
171
+ A pass that closed by withdrawing a finding rather than by reading its fix takes neither line, per the withdrawal rule in Step 3. Both claim a fix landed, and the second names it, so posting either over a withdrawal credits work nobody did on the one comment a reader treats as the verdict. Write the withdrawal and the fact that settled it in place of the canned line, keeping the heading and the footer.
172
+
169
173
  Post that one even when there is nothing to report. A review left with no closing comment reads as one nobody answered.
170
174
 
171
175
  ## Step 5: output
@@ -97,7 +97,7 @@ The command drops the task's row from `.claude/tasks/priority.md` and leaves pro
97
97
 
98
98
  ## Output
99
99
 
100
- Emit the full relative path from the project root for every file written or moved. Bare filenames are not clickable.
100
+ Emit the full relative path from the project root for every file written or moved. A bare filename names a file the reader cannot open.
101
101
 
102
102
  Create:
103
103
 
@@ -58,7 +58,7 @@ cat <<'EOF' | aitk feedback
58
58
  EOF
59
59
  ```
60
60
 
61
- Report the printed path back to the user on its own line so the terminal makes it clickable.
61
+ Report the printed path back to the user on its own line, in the form the project's instruction file sets under `## Output`.
62
62
 
63
63
  For a durable, cross-machine report instead of local scratch, add `--github`. The CLI opens a GitHub issue on the toolkit repo and prints the issue URL. It needs `gh` authenticated, and falls back to local scratch with a warning when `gh` is absent.
64
64
 
@@ -16,7 +16,7 @@ Two smaller failures follow the fetch. A video with no captions produces a file
16
16
  ## Must
17
17
 
18
18
  - Run the CLI, which owns the fetch, the caption cleanup, and the frontmatter
19
- - Surface the written path as a full relative path so the terminal makes it clickable
19
+ - Surface the written path as a full relative path, in the form the project's instruction file sets under `## Output`
20
20
  - Report a video with no captions as a fact about the video, since the file still exists and carries its metadata
21
21
  - Name the missing external binary and stop, leaving the install to the user
22
22
 
@@ -26,7 +26,7 @@ aitk transcripts <url>
26
26
 
27
27
  - Pass `--keep-timestamps` when the user wants `[mm:ss]` markers per line instead of prose.
28
28
  - Pass `--out <dir>` to override the output directory. The default is `transcripts/` in the current directory.
29
- - The written file path prints to stdout. Surface it back to the user as a full relative path so it is clickable.
29
+ - The written file path prints to stdout. Surface it back to the user as a full relative path, in the form the project's instruction file sets under `## Output`.
30
30
 
31
31
  ## After the fetch
32
32
 
@@ -30,6 +30,8 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
30
30
  | `aitk tasks pull-request` | Record a pull request number on the task a branch closes, by stem or `--plan` (`--json`) |
31
31
  | `aitk tasks outcome` | Mark outcomes `[x]` on a task by position, repeating `--close` (`--json`) |
32
32
  | `aitk tasks validate` | Report board rows whose plan, task file, group, or file set does not hold (`--json`) |
33
+ | `aitk intake list` | Report intake folder counts, or one folder's items, keeping what is unread with `--unread` (`--json`) |
34
+ | `aitk intake answer` | Write selections into one cluster's answer slots, repeating `--set <item>=<answer>` (`--json`) |
33
35
  | `aitk records validate` | Report a session record against the standard governing it, per kind (`--json`) |
34
36
  | `aitk records push` | Commit the eight backed record folders and push them to a private records remote (`--json`) |
35
37
  | `aitk records pull` | Fetch the records remote and write it back, refusing rather than discarding unpushed records (`--json`) |
@@ -54,6 +56,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
54
56
  | `design` | `render` |
55
57
  | `slides` | `render`, `list` |
56
58
  | `tasks` | `archive`, `validate` |
59
+ | `intake` | `list`, `answer` |
57
60
  | `comments` | `scan` |
58
61
  | `context` | `audit` |
59
62
  | `markdown` | `audit` |
@@ -16,6 +16,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
16
16
  - [Docs](docs.md): How aitk docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
17
17
  - [Indexes](indexes.md): Flags, exit codes, and JSON shape for aitk indexes regen, plus when it auto-stages what it rewrote
18
18
  - [Install and sync](install-and-sync.md): What each install and sync verb writes, refuses, or leaves alone, and how drift is attributed in a target project
19
+ - [Intake](intake.md): Reading intake folder counts and items, the three read states an item can be in, landing a batch of selections in one cluster, the refusal reasons, and why a call is scoped to one file
19
20
  - [Markdown audit](markdown-audit.md): Running the audit over any markdown path, where its bans and checkpoints are read from, what each check reports, and why the ban half gates while the structural half reports
20
21
  - [Output shape](output-shape.md): Two framed shapes every command renders into, how JSON and --names modes keep stdout clean, and the exit discipline that lets piped output drain
21
22
  - [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: Intake
3
+ description: Reading intake folder counts and items, the three read states an item can be in, landing a batch of selections in one cluster, the refusal reasons, and why a call is scoped to one file
4
+ ---
5
+
6
+ # Intake
7
+
8
+ ## List
9
+
10
+ `aitk intake list` reports the intake folders under `.claude/intake/`, or the items one folder holds. It reads and never writes, because an answer belongs to the operator and a verb that filled one would decide what the folder exists to ask.
11
+
12
+ ```bash
13
+ aitk intake list
14
+ aitk intake list toolkit-overview --unread --json
15
+ ```
16
+
17
+ | Option | Behavior |
18
+ | --------------- | ------------------------------------------------------------------------- |
19
+ | `--unread` | Keep only what is unread: folders carrying one, or a folder's empty slots |
20
+ | `--json` | Emit a machine-readable record on stdout |
21
+ | `--root <path>` | Intake root, defaulting to the main worktree |
22
+
23
+ With no slug it reports per-folder counts. With one it reports every item grouped by the cluster file holding it, each carrying its label, title, open question, suggestion, and answer.
24
+
25
+ An item sits in one of three read states, and the counts keep them apart:
26
+
27
+ | State | What it means |
28
+ | --------- | ------------------------------------------------------- |
29
+ | unread | The slot is present and empty, so nobody has reached it |
30
+ | answered | The slot carries text, which is a decision already made |
31
+ | malformed | The item carries no slot, so no verb here can answer it |
32
+
33
+ The third is counted apart from both rather than folded into either. Counted as answered it hides a file that needs fixing behind a folder reading as fully worked through, and counted as unread it joins a list whose every entry `answer` then refuses.
34
+
35
+ The index is skipped, since it points at items and answers nothing itself. So is any item a file displays inside a fence, which is how a folder copying the item format into its own overview is read as the sample it is rather than as an item offering a slot no reader owns.
36
+
37
+ ## Answer
38
+
39
+ `aitk intake answer` writes selections into the answer slots of one cluster file.
40
+
41
+ ```bash
42
+ aitk intake answer toolkit-overview --cluster 05-coverage.md --set 3=ok
43
+ aitk intake answer toolkit-overview --cluster 11-intake-skill.md --set 3d=ok --set 9="not worth it" --json
44
+ ```
45
+
46
+ | Option | Behavior |
47
+ | --------------------- | ----------------------------------------------------- |
48
+ | `--cluster <file>` | Cluster file the items live in, with or without `.md` |
49
+ | `--set <item=answer>` | Answer to land on an item, repeatable |
50
+ | `--json` | Emit a machine-readable record on stdout |
51
+ | `--root <path>` | Intake root, defaulting to the main worktree |
52
+
53
+ Items are labeled per cluster file, so a selection names the cluster and the label together. A label alone names an item in every cluster at once.
54
+
55
+ A label may carry a letter suffix, as in `3a` beside `3`, which is how a pass records a finding split after the fact rather than renumbering every item below it. Pass it exactly as the heading spells it.
56
+
57
+ One call writes one cluster. A call per selection is the alternative, and several of those against the same file read it before any of them writes, so every answer but the last is lost with nothing reporting it. The selections split on the first `=`, so an answer carrying its own survives intact.
58
+
59
+ An item already carrying an answer refuses rather than being overwritten, and one filled item refuses the whole batch, so a partly applied write never lands. Drop the named item and send the rest.
60
+
61
+ Exit codes: `0` every named item now carries its answer, `1` refused. The `reason` field carries `no-intake`, `no-folder`, `no-cluster`, `no-item`, `answered`, or `bad-input`.
62
+
63
+ `bad-input` covers a malformed command line: no cluster, no selection, a selection that parses to no label and answer, an empty answer, an answer carrying a line break, or two answers for one item. It is separate from the reasons describing the folder, so a caller that mistyped a flag is not sent to repair a file that is fine.
64
+
65
+ An empty answer refuses rather than writing an empty slot. The slot means unread while it is empty, so writing one back would report an item as answered that nobody decided.
66
+
67
+ An answer occupies one line, and one carrying a line break refuses before anything is read. Writing it splices a bare continuation into the item that matches none of the patterns the reader tests, so the slot reads back as the text before the break while the item counts as answered, and the refusal on an already-answered item then leaves hand-editing the file as the only correction. The whole batch refuses, so a good selection beside a broken one never lands half applied.
68
+
69
+ The folder is shared scratch at the main worktree root, so `--root` defaults to the first entry of `git worktree list` rather than the working directory. The write is an edit inside a file that already exists, which `Edit` and `Write` refuse from a linked worktree and a shell stream editor may not do, so the verb resolves the root in-process and rewrites whole lines.
70
+
71
+ Skills branch on the reason rather than on the exit code:
72
+
73
+ ```bash
74
+ aitk intake list toolkit-overview --unread --json | jq -r '.clusters[] | .cluster'
75
+ ```
76
+
77
+ For the folder layout, the item format, the answer contract, and retrieval, see `.claude/standards/intake.md`.
@@ -74,6 +74,19 @@ reply that changes an outcome, such as a worker naming the plan question that
74
74
  already declined a finding, still belongs back on the PR, since the session
75
75
  holding it ends and the thread is what a later reader opens.
76
76
 
77
+ Two rules put it there rather than leaving that to whoever remembers. A finding
78
+ the worker declines carries the fact that settled it in the same reply body that
79
+ already maps every finding, and a pass accepting that argument states the
80
+ withdrawal or the regrade with what produced it instead of dropping the finding
81
+ from its next comment. Both fire on a line the body already writes, so neither
82
+ asks a session to judge mid-reply whether its own message mattered.
83
+
84
+ A reply that corrects the reviewing session rather than a finding stays off the
85
+ thread. Which session holds which branch, or what gate a worker's edits pass
86
+ through, changes no finding on a pull request that closes, so it goes to the task
87
+ owning that surface. Nothing checks either rule, so both hold while a session
88
+ applies them.
89
+
77
90
  A finding answered without a commit leaves the head where the first pass read it,
78
91
  which a gitignored record and a finding accepted as recorded both produce. The
79
92
  close-out is still owed there, since the newest heading is what tells an operator
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.89.1",
4
+ "version": "0.91.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
package/src/cli.ts CHANGED
@@ -20,6 +20,7 @@ import { register as capture } from '@/commands/capture'
20
20
  import { register as feedback } from '@/commands/feedback'
21
21
  import { register as transcripts } from '@/commands/transcripts'
22
22
  import { register as tasks } from '@/commands/tasks'
23
+ import { register as intake } from '@/commands/intake'
23
24
  import { register as comments } from '@/commands/comments'
24
25
  import { register as context } from '@/commands/context'
25
26
  import { register as markdown } from '@/commands/markdown'
@@ -53,6 +54,7 @@ function showHelp(): void {
53
54
  `${GREY}│${NC} feedback ${GREY}# Write toolkit feedback from stdin to .claude/review/${NC}`,
54
55
  `${GREY}│${NC} transcripts <url> ${GREY}# Fetch a YouTube transcript with metadata frontmatter${NC}`,
55
56
  `${GREY}│${NC} tasks [cmd] ${GREY}# Task board commands (archive)${NC}`,
57
+ `${GREY}│${NC} intake [cmd] ${GREY}# Intake folders under .claude/intake/ (list, answer)${NC}`,
56
58
  `${GREY}│${NC} comments [cmd] ${GREY}# Measure comment density and trend (scan)${NC}`,
57
59
  `${GREY}│${NC} context [cmd] ${GREY}# Report context folder health (audit)${NC}`,
58
60
  `${GREY}│${NC} markdown [cmd] ${GREY}# Report markdown against the attribute standards (audit)${NC}`,
@@ -87,6 +89,7 @@ function showHelp(): void {
87
89
  `${GREY}│${NC} pbpaste | aitk feedback`,
88
90
  `${GREY}│${NC} aitk transcripts https://youtu.be/VIDEO_ID`,
89
91
  `${GREY}│${NC} aitk tasks archive --pull-request 673 --json`,
92
+ `${GREY}│${NC} aitk intake list toolkit-overview --unread --json`,
90
93
  `${GREY}│${NC} aitk comments scan src --json`,
91
94
  `${GREY}│${NC} aitk context audit --json`,
92
95
  `${GREY}│${NC} aitk markdown audit .claude/rules --json`,
@@ -143,6 +146,7 @@ capture(program)
143
146
  feedback(program)
144
147
  transcripts(program)
145
148
  tasks(program)
149
+ intake(program)
146
150
  comments(program)
147
151
  context(program)
148
152
  markdown(program)