@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.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-orchestrate/SKILL.md +35 -17
- package/claude/skills/git-pr/REQUIREMENT.md +8 -0
- package/claude/skills/git-pr/SKILL.md +20 -1
- package/claude/skills/git-pr/references/labels.md +59 -0
- package/docs/agents/markdown-audit.md +3 -1
- package/package.json +1 -1
- package/src/markdown/structure.ts +7 -1
- package/tooling/claude/manifest.toml +1 -1
|
@@ -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.
|
|
11
|
-
|
|
12
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
|
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:
|
|
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
|
@@ -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/"]
|