@erclx/aitk 0.81.0 → 0.82.1

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.81.0",
4
+ "version": "0.82.1",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -7,9 +7,10 @@ disable-model-invocation: true
7
7
  # Claude orchestrate
8
8
 
9
9
  This session is the orchestrator: the one warm session that holds the
10
- cross-feature picture. It plans and reviews. It does not build, and it does not
11
- merge. Building happens in cold worker sessions the human launches. Merging is
12
- the human's gate.
10
+ cross-feature picture. It plans and reviews.
11
+
12
+ It does not build, and it does not merge. Building happens in cold worker
13
+ sessions the human launches. Merging is the human's gate.
13
14
 
14
15
  This skill holds the framing, the board procedure, and the dispatch. Every step
15
16
  that builds something runs an existing skill. The queue rules below decide which
@@ -35,7 +36,11 @@ Then output the state of play so the human knows what to launch, review, and mer
35
36
 
36
37
  The roadmap is optional and this skill does not require it. It carries why a sequence is what it is, changes only when strategy changes, and is absent in a project whose scope has already shipped. Report what it says and name it as the source. Never assert an active version the file does not state, and say nothing about one when the file is missing.
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 captures what the session learned, then 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. That capture is the only one this session runs, since the refill sweep reports it as owed rather than paying it. 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
+ 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.
40
+
41
+ On a request to write the handoff or save the session, read `${CLAUDE_SKILL_DIR}/references/orchestrator-handoff.md` and follow it. It captures what the session learned, then 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. That capture is the only one this session runs, since the refill sweep reports it as owed rather than paying it. Write nothing to the handoff that the board, a task file, or a groundwork folder already carries.
42
+
43
+ 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.
39
44
 
40
45
  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. A session holding a recurring-prompt scheduler starts and cancels that loop itself, and no hook or check does, so the condition holds only while whoever holds the loop applies it.
41
46
 
@@ -95,12 +100,16 @@ Write no shape for a correction. A correction is a sentence, and a format for ad
95
100
 
96
101
  ## The loop
97
102
 
98
- 1. Own the roadmap while a scope exists to sequence. Capture a needed draft or resequence of `.claude/ROADMAP.md` in the plan or a task file, naming the MVP list in `.claude/REQUIREMENTS.md` as the source, so a worker runs `claude-roadmap` in its branch and the tracked edit ships in a PR rather than dirtying main. Stop owning it once that list has shipped, since later work then arrives as discrete items rather than as versions.
103
+ 1. Own the roadmap while a scope exists to sequence.
104
+ - Capture a needed draft or resequence of `.claude/ROADMAP.md` in the plan or a task file, naming the MVP list in `.claude/REQUIREMENTS.md` as the source, so a worker runs `claude-roadmap` in its branch and the tracked edit ships in a PR rather than dirtying main
105
+ - Stop owning it once that list has shipped, since later work then arrives as discrete items rather than as versions
99
106
  2. Plan the next feature. Run `claude-feature` here, with the cross-feature context, to write a plan to `.claude/plans/`. Planning stays in this warm session so the plan front-loads reasoning a cold worker would otherwise re-derive. Every plan written from here also carries a constraint per track in flight, which the paragraph below this list states.
100
107
  3. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
101
108
  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.
102
109
  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.
103
- 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.
110
+ 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.
111
+ - 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
112
+ - The poll 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
104
113
  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.
105
114
 
106
115
  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.
@@ -114,7 +123,9 @@ A plan written here is written against a tree several branches are already chang
114
123
  - Do not edit tracked files from this session, at any size. The boundary offers no proportionality exception and nothing enforces it.
115
124
  - Do not hand a worker anything but a plan, since scope lives there. A plan carries exact diffs only when they are already known, otherwise it states the scope and the open questions and lets the worker write the diff.
116
125
 
117
- The tracked-file boundary collides with `CLAUDE.md`, which says to handle a small edit immediately without a task entry, and this rule wins wherever the two meet. A session that writes a change cannot review it independently afterwards and no later session recovers that vantage, which is the separation `claude-pr-review` exists to supply. Record a change identified while orchestrating against the task that owns it, fold one no task owns into the next task touching the same surface, and file a task only when no such task exists or is expected. Run `claude-review` when the boundary is crossed anyway, since a branch-diff pass is not independent and is the only check a self-authored change can get.
126
+ The tracked-file boundary collides with `CLAUDE.md`, which says to handle a small edit immediately without a task entry, and this rule wins wherever the two meet. A session that writes a change cannot review it independently afterwards and no later session recovers that vantage, which is the separation `claude-pr-review` exists to supply.
127
+
128
+ Record a change identified while orchestrating against the task that owns it, fold one no task owns into the next task touching the same surface, and file a task only when no such task exists or is expected. Run `claude-review` when the boundary is crossed anyway, since a branch-diff pass is not independent and is the only check a self-authored change can get.
118
129
 
119
130
  ## Refilling the ready queue
120
131
 
@@ -128,10 +139,13 @@ It counts unclaimed plans against workers rather than reading the reserve in ste
128
139
 
129
140
  1. Run `gh pr list --state open` and `git log --oneline -8`. Report any pull request whose review has not been posted and stop for that one first.
130
141
  2. For each pull request merged since the last sweep, place every finding it produced. Route a finding that changes a rule to the standard or rule that states it, one that changes another task to that task's Findings, and one that overturns a groundwork lean to that folder marked answered. Never leave a finding in a pull request thread alone.
131
- 3. Archive what closed. A task whose outcomes are all `[x]` runs `claude-docs` for the plan sweep, then `claude-tasks` to archive. A task whose outcomes describe standing policy rather than a deliverable never closes on its own, so hand it to a worker to encode the policy where it is enforced, then cut the outcomes with the reason recorded and archive once that branch merges. Encoding it from this session would write a tracked file, which Boundaries forbids.
142
+ 3. Archive what closed.
143
+ - A task whose outcomes are all `[x]` runs `claude-docs` for the plan sweep, then `claude-tasks` to archive
144
+ - A task whose outcomes describe standing policy rather than a deliverable never closes on its own, so hand it to a worker to encode the policy where it is enforced, then cut the outcomes with the reason recorded and archive once that branch merges. Encoding it from this session would write a tracked file, which Boundaries forbids.
132
145
  4. Read `.claude/tasks/priority.md` and count entries under its `## Run now` heading that carry a written plan. Keep one in reserve beyond what is running.
133
146
  5. Promote by whether a task establishes functionality rather than by age. Prefer a task that adds or proves a mechanism over one that trims, tidies, or audits an existing surface.
134
- 6. Before promoting a candidate, list the files it touches against every task already running, per Parallelism below. Name the overlap and serialize when the sets are not disjoint. A candidate held by something outside the tree stays where it is whatever those sets show. A collision is one of the reasons a task cannot start, so disjointness clears that reason alone and leaves an external condition standing.
147
+ 6. Before promoting a candidate, list the files it touches against every task already running, per Parallelism below. Name the overlap and serialize when the sets are not disjoint.
148
+ - A candidate held by something outside the tree stays where it is whatever those sets show. A collision is one of the reasons a task cannot start, so disjointness clears that reason alone and leaves an external condition standing.
135
149
  7. Write a plan for each newly promoted task with `claude-feature`, carrying the in-flight constraint that The loop above states, then report:
136
150
 
137
151
  ```plaintext
@@ -158,8 +172,10 @@ Promoting, demoting, and archiving a row all write `.claude/tasks/priority.md`,
158
172
  - Edit the file with the file-editing tool. A shell stream editor and an inline string replace both exit clean on a non-match, so a promotion that matched nothing leaves the board wrong with nothing reporting it, and the file-editing tool errors instead.
159
173
  - Put a pointer in the Plan column, never prose. `## Run now` claims a written plan covers every open outcome, and `claude-autoship` refuses at its guard when it follows the column and finds no plan, which spends a worker dispatch to learn what the row should have said.
160
174
  - Name the file set in the Touches column. The disjointness call in step 6 is only checkable later when the sets are written down rather than reasoned once and discarded.
161
- - Re-resolve every Plan pointer after anything archives a plan. `claude-docs` moves a plan to `.claude/plans-archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.claude/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
162
- - Read the file back after writing it, since the row that lands is the row a worker acts on.
175
+ - Re-resolve every Plan pointer after anything archives a plan
176
+ - Read the file back after writing it, since the row that lands is the row a worker acts on
177
+
178
+ A Plan pointer goes stale from a branch this board never sees. `claude-docs` moves a plan to `.claude/plans-archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.claude/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
163
179
 
164
180
  ## Parallelism
165
181
 
@@ -167,9 +183,11 @@ No fixed number caps worker tracks. Collision between file sets is what binds, s
167
183
  list the files a candidate touches against every track already in flight and open
168
184
  it only when the sets are disjoint. What thins as tracks multiply is the review
169
185
  attention each output gets, so add a track while you can still review every one
170
- properly and stop when you cannot. Serialize any track that touches a shared
171
- wiring seam with another in flight. Merge the branch with the smallest
172
- shared-file footprint first, and merge a branch touching `CLAUDE.md`, a Claude
173
- context entry, or a regenerated `index.md` last. Have every sibling rebase on
174
- the new `main` before the next merge. Assign a distinct port per track when two
175
- workers run a server, since each session spawns its own process.
186
+ properly and stop when you cannot.
187
+
188
+ Serialize any track that touches a shared wiring seam with another in flight.
189
+ Merge the branch with the smallest shared-file footprint first, and merge a
190
+ branch touching `CLAUDE.md`, a Claude context entry, or a regenerated `index.md`
191
+ last. Have every sibling rebase on the new `main` before the next merge. Assign
192
+ a distinct port per track when two workers run a server, since each session
193
+ spawns its own process.
@@ -9,6 +9,8 @@ description: What pull request generation is for, the gaps it closes, and what i
9
9
 
10
10
  Without this skill, a pull request body is written from memory of the branch rather than from its diff, so it describes the intent and omits what the work turned into. Testing boxes get ticked from intent, which records what was meant to run instead of what ran, and a reviewer trusts the list. A second push either errors on create or opens a duplicate pull request, and banned characters survive into a body the hook never sees.
11
11
 
12
+ Every pull request also lands unlabelled, so a merged list is a wall of titles with no way to filter it by surface. A reader looking for what changed in one domain reads all of them, and the conventional commit type in the title says what kind of change it is rather than where.
13
+
12
14
  A lookup that resolves by head branch alone carries its own failure. A branch name reused after an earlier pull request merged resolves to the closed one, so the run rewrites a merged pull request's title and body and reports its URL as the one it opened. Both fields are recoverable only through the issue timeline and the edit history, and nothing reports that the write landed on the wrong object.
13
15
 
14
16
  ## Must
@@ -21,6 +23,9 @@ A lookup that resolves by head branch alone carries its own failure. A branch na
21
23
  - Detect an open pull request and edit it in place, so a follow-up push keeps the body in sync instead of failing
22
24
  - Scope that detection to an open pull request on the current head and the default base, so neither a reused branch name nor a second base resolves the wrong one
23
25
  - Resolve the pull request once and reuse what that resolution returned, so the number recorded never depends on how a lookup ranks two pull requests sharing a head
26
+ - Label from the paths the branch changed, against a map the project declares, so the label set belongs to the project rather than to the skill
27
+ - Apply labels after the pull request exists, so a label the remote does not carry costs a warning rather than the pull request
28
+ - Report a refused label, since a warning nothing surfaces leaves the run indistinguishable from one that labelled
24
29
 
25
30
  ## Must not
26
31
 
@@ -28,12 +33,15 @@ A lookup that resolves by head branch alone carries its own failure. A branch na
28
33
  - Put a request for the reviewer in the Testing list, since a request is not a result
29
34
  - Create a second pull request when one is open
30
35
  - Edit a pull request that is not open, or record its number on a task
36
+ - Name a domain of any one project in the skill body or its references
37
+ - Create a label the map names and the remote lacks
31
38
  - Emit anything after the result line
32
39
 
33
40
  ## Guards
34
41
 
35
42
  - Branch name does not conform: stop and route to the skill that renames
36
43
  - No commits ahead of main: stop
44
+ - No label map in the project: label nothing and warn nothing, since an absent map is a decision rather than a gap
37
45
 
38
46
  ## Out of scope
39
47
 
@@ -11,6 +11,7 @@ Read these files in parallel:
11
11
 
12
12
  - `${CLAUDE_SKILL_DIR}/references/branch.md`: branch format, valid types, and constraints
13
13
  - `${CLAUDE_SKILL_DIR}/references/pr.md`: structure, rules, and banned phrases
14
+ - `${CLAUDE_SKILL_DIR}/references/labels.md`: label map format, matching, and the missing-label warning. Skip when the project has no `.claude/pr-labels.toml`.
14
15
  - `.claude/standards/prose.md` from the project root: voice and banned words for all generated text
15
16
  - `.claude/standards/markdown.md` from the project root: punctuation and formatting for all generated text
16
17
  - `.claude/standards/versioning.md` from the project root: phase label vs semver discipline
@@ -29,6 +30,7 @@ Then run these commands in parallel to gather git context:
29
30
  - `git branch --show-current 2>/dev/null || echo "unknown"`
30
31
  - `git log <base>..HEAD --oneline 2>/dev/null || echo "NO_COMMITS"`
31
32
  - `git diff <base> HEAD -- . ':(exclude)*.lock' ':(exclude)*-lock.json' 2>/dev/null || echo "NO_DIFF"`
33
+ - `git diff --name-only <base> HEAD 2>/dev/null || echo "NO_FILES"`
32
34
 
33
35
  ## Diff baseline
34
36
 
@@ -82,15 +84,24 @@ The lookup scopes to the base as well as the head. One head can carry open pull
82
84
 
83
85
  A detached HEAD gives `git branch --show-current` an empty result, which would read as no open pull request and create a second one. The branch-name guard above stops the run first, since an empty name does not match `<type>/<description>`.
84
86
 
87
+ ### Labels
88
+
89
+ Read `.claude/pr-labels.toml` from the project root. A project that has not declared a map gets no labels and no warning, since a label set this skill supplied would be a guess about that project's surfaces.
90
+
91
+ When the file resolves, match it against the name-only diff per `${CLAUDE_SKILL_DIR}/references/labels.md` and write the comma-separated result into `pr_labels` below. Leave `pr_labels` empty when no map resolves or no prefix matches, which skips the labelling command rather than running it against nothing.
92
+
85
93
  ### Final command
86
94
 
87
95
  Detect an open pull request on the current head and branch: edit it in place when one exists, create it otherwise. This keeps the body in sync on a follow-up push instead of erroring on `gh pr create`.
88
96
 
97
+ Labels apply after that branch converges, against a pull request that already exists. `gh pr create --label` refuses a label the remote does not carry and opens no pull request at all, so a mistyped row costs the run rather than the label. One command after the fact also covers the create and the edit path together.
98
+
89
99
  ```bash
90
100
  mkdir -p .claude/.tmp/pr
91
101
  cat <<'BODY' > .claude/.tmp/pr/body.md
92
102
  <body content following pr.md template exactly>
93
103
  BODY
104
+ pr_labels="<comma-separated labels, empty when the map resolves to nothing>"
94
105
  git push -u origin HEAD || exit 1
95
106
  base_branch=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name) || exit 1
96
107
  pr_number=$(gh pr list --head "$(git branch --show-current)" --base "$base_branch" --state open --json number --jq '.[0].number // empty')
@@ -100,6 +111,10 @@ else
100
111
  pr_url=$(gh pr create --title "<title>" --body-file .claude/.tmp/pr/body.md) || exit 1
101
112
  pr_number=${pr_url##*/}
102
113
  fi
114
+ if [ -n "$pr_labels" ]; then
115
+ gh pr edit "$pr_number" --add-label "$pr_labels" >/dev/null ||
116
+ printf 'Label apply failed. Create a missing label with: gh label create <name>\n' >&2
117
+ fi
103
118
  rm -rf .claude/.tmp/pr
104
119
  printf 'number=%s\nurl=%s\n' "$pr_number" "$pr_url"
105
120
  ```
@@ -124,8 +139,12 @@ The number is what lets the merge close the task. Every merge on `main` is a squ
124
139
 
125
140
  ## After execution
126
141
 
127
- Respond with exactly one line, using the `url` the final command printed:
142
+ Respond with one line, using the `url` the final command printed:
128
143
 
129
144
  `✅ PR: <url>`
130
145
 
146
+ Add a second line only when the labelling command printed its warning, quoting the label `gh` refused:
147
+
148
+ `⚠️ Labels not applied: <what gh reported>`
149
+
131
150
  Do not add any other text.
@@ -0,0 +1,59 @@
1
+ ---
2
+ title: Label reference
3
+ description: Path-to-label map format, prefix matching against the changed set, and the one-time label creation a map requires
4
+ ---
5
+
6
+ # Label reference
7
+
8
+ ## Scope
9
+
10
+ Governs the labels a pull request carries: the map a project declares, how a changed path resolves to a label, and what a label missing from the remote costs.
11
+
12
+ Does not govern:
13
+
14
+ - Pull request title and body: `pr.md`
15
+ - Branch naming: `branch.md`
16
+ - Issue labels, which `git-issue` derives from the issue type rather than from a diff
17
+
18
+ ## Map format
19
+
20
+ The map lives at `.claude/pr-labels.toml` in the project root. Each key under `[domains]` is a label name and its value is the list of path prefixes that earn it.
21
+
22
+ ```toml
23
+ [domains]
24
+ api = ["services/api/"]
25
+ web = ["apps/web/", "packages/ui/"]
26
+ ```
27
+
28
+ A label takes more than one prefix when two folders read as one surface. Two labels may claim overlapping prefixes, and a path under both earns both.
29
+
30
+ The map is authored by hand and nothing detects a directory it fails to cover, so a surface added after the map was written labels nothing until someone adds a row.
31
+
32
+ ## Matching
33
+
34
+ - Take the changed set from `git diff --name-only <base> HEAD`, resolved against the same base as the diff the body is written from
35
+ - A path earns a label when the path starts with one of that label's prefixes
36
+ - Collect the distinct labels across the whole set, ordered as the map declares them, so two runs over one branch produce one string
37
+ - Pass the result as a single comma-separated value. An empty result runs no labelling step.
38
+
39
+ ## Applying
40
+
41
+ Apply labels after the pull request resolves, never as a flag on the create. `gh pr create --label` fails whole on a label the remote does not carry, so a name the map got wrong opens no pull request at all and the run stops with the branch pushed and nothing to review. A `gh pr edit --add-label` against a pull request that already exists costs a warning instead, and it is one command across both the create and the edit path rather than two flags that have to stay in step.
42
+
43
+ `--add-label` adds and never removes. A label a person applied by hand is not this skill's to strip, so a domain that stops applying between two pushes keeps its label until someone takes it off.
44
+
45
+ ## A label the remote does not carry
46
+
47
+ Warn and continue rather than creating it, naming the command in the warning:
48
+
49
+ ```bash
50
+ gh label create <name> --description "<text>"
51
+ ```
52
+
53
+ Creating a label writes to the repository settings from a run the user invoked to open a pull request, and a label created from a typo in the map is harder to notice than a warning is.
54
+
55
+ The refusal names the label it rejected and applies none of the set, so a warning that reaches nobody leaves the run reading exactly like one that labelled. Surface it beside the result line rather than letting the pull request URL stand alone.
56
+
57
+ ## Release pull requests
58
+
59
+ Release automation opens its own pull requests without this skill and applies its own labels, so nothing here needs a skip condition for them.
@@ -55,7 +55,9 @@ Every weight and depth measure counts the text a reader is shown. A link reduces
55
55
 
56
56
  A code span is walked around rather than through, so a path quoting link or angle-bracket syntax keeps the width the page gives it. Masking inside one takes back the decision to count it, and the placeholders this toolkit writes are where that shows.
57
57
 
58
- The paragraph check measures both halves of one rule. `markdown.md` caps a paragraph at four sentences, and a sentence cap on its own is satisfied by writing fewer and longer ones: 36 paragraphs in this corpus sit inside four sentences and past the weight checkpoint, and the heaviest of those runs 1121 characters. The standard therefore states a weight beside the sentence cap, and the verb reads it as its own checkpoint.
58
+ The paragraph check measures both halves of one rule. `markdown.md` caps a paragraph at four sentences, and a sentence cap on its own is satisfied by writing fewer and longer ones: 15 paragraphs in this corpus sit inside four sentences and past the weight checkpoint, and the heaviest of those runs 886 characters. The standard therefore states a weight beside the sentence cap, and the verb reads it as its own checkpoint.
59
+
60
+ A sentence boundary closes on terminal punctuation ahead of a capital or a code span. The capital is what keeps a version pin and a decimal from each reading as two sentences, and the code span is admitted beside it because a command name opening a sentence carries no capital to find.
59
61
 
60
62
  The paragraph weight sits at 700 and the bullet weight at 400. Both shipped at 400, because the paragraph number was borrowed from the bullet rule when the two checks landed together, and each has since been read against a sample of its own. They are separate checkpoints in the standard and separate patterns in the parser, so a read that moves one leaves the other where it is.
61
63
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.81.0",
4
+ "version": "0.82.1",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -15,8 +15,14 @@ const BLOCKQUOTE = /^\s*>/
15
15
  * one. An abbreviation ahead of a capitalized word still counts, which
16
16
  * over-reports by one on the sentence that carries it and is why this measure
17
17
  * reports rather than gates.
18
+ *
19
+ * A code span opens a sentence that carries no capital at all, since a command
20
+ * name is lowercase and the requirement above would catch nothing there. The
21
+ * backtick therefore stands alone rather than joining the delimiters a capital
22
+ * follows, and the price is that a span opening a fragment mid-paragraph reads
23
+ * as a sentence start.
18
24
  */
19
- const SENTENCE_END = /[.!?]["'’”)\]]*(?=\s+["'“(\[]*[A-Z]|\s*$)/g
25
+ const SENTENCE_END = /[.!?]["'’”)\]]*(?=\s+(?:["'“(\[]*[A-Z]|`)|\s*$)/g
20
26
 
21
27
  const NUMBER_WORDS: Record<string, number> = {
22
28
  one: 1,
@@ -8,4 +8,4 @@ runtime = ""
8
8
  scaffold = ""
9
9
 
10
10
  [gitignore]
11
- "# Claude" = [".claude/.tmp/", ".claude/groundwork/", ".claude/intake/", ".claude/memory/", ".claude/plans/", ".claude/plans-archive/", ".claude/review/", ".claude/task-archive/", ".claude/worktrees/", ".claude/tasks/"]
11
+ "# Claude" = [".claude/.records.git/", ".claude/.tmp/", ".claude/groundwork/", ".claude/intake/", ".claude/memory/", ".claude/plans/", ".claude/plans-archive/", ".claude/review/", ".claude/task-archive/", ".claude/worktrees/", ".claude/tasks/"]