@erclx/aitk 3.38.0 → 3.38.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/docs/agents/counts.md +10 -2
- package/package.json +1 -1
- package/src/counts/scan.ts +69 -13
package/docs/agents/counts.md
CHANGED
|
@@ -35,12 +35,18 @@ The set is closed rather than derived, so widening it is a deliberate change to
|
|
|
35
35
|
|
|
36
36
|
## How a match is decided
|
|
37
37
|
|
|
38
|
-
A sentence has to carry an assertion verb (`loads`, `ships`, `carries`, `holds`, `counts`, `totals`, `documents`, `declares`, `installs`, `lists`, `contains`, `comprises`) or an article (`the`, `a`, `an`) immediately ahead of the number, which is immediately ahead of the catalog noun, with one optional qualifying word between the number and the noun (`sixty-one shipped skills`). The number reads either as digits or as a spelled-out cardinal through ninety-nine, since this corpus states a catalog size in words as often as in digits.
|
|
38
|
+
A sentence has to carry an assertion verb (`loads`, `ships`, `carries`, `holds`, `counts`, `totals`, `documents`, `declares`, `installs`, `lists`, `contains`, `comprises`, `authors`), the quantifier `all`, or an article (`the`, `a`, `an`) immediately ahead of the number, which is immediately ahead of the catalog noun, with one optional qualifying word between the number and the noun (`sixty-one shipped skills`). The number reads either as digits or as a spelled-out cardinal through ninety-nine, since this corpus states a catalog size in words as often as in digits.
|
|
39
|
+
|
|
40
|
+
Nothing stands between the trigger and the number, which is the rule an author writing a new count has to know. It separates `the toolkit authors 69 rules` and `took all 69 rules`, both read, from `a domain of 55 skills` and `denominator of sixty-one shipped skills`, neither of them read. A figure meant as a past state takes a date in the same sentence instead, which reads the sentence past whatever its shape.
|
|
41
|
+
|
|
42
|
+
## How the trigger set grew
|
|
39
43
|
|
|
40
44
|
The verb gate is not the first design tried. A bare number next to a catalog noun anywhere in the tracked corpus returned 290 findings against a repository whose actionable instance count was one. Reading that run showed why: `18 rules citing a standard`, `21 skill bodies`, and `eight internal skills` all pair a number with a catalog noun while naming a subset, an example, or a different catalog than the one matched, and that shape dominates ordinary prose. Every instance this sweep was written against reads the number as the direct object of a verb asserting the catalog's own total, and gating on that verb is what took the false-positive count from 290 to five on the same tree.
|
|
41
45
|
|
|
42
46
|
The article half was added after a first review of the shipped design found a live miss: `.claude/context/development/gates.md` stated a stale audit total while the tree held 20, and the verb gate never reached it, since that sentence puts its verb after the noun rather than ahead of the number. Widening the trigger set to admit an article ahead of the number closed that gap.
|
|
43
47
|
|
|
48
|
+
The quantifier `all` and the verb `authors` joined on the same evidence, two more live misses failing only the trigger test. Allowing words to stand between the trigger and the number was the other candidate, measured and declined: at widths of one, two, and three it reached 77, 104, and 132 sentences against a baseline of 65, missed `took all 69 rules` at every width, and reached `the toolkit authors 69 rules` only at a width admitting the indirect-noun shape below. The two words reach both at 75 sentences and no false positive.
|
|
49
|
+
|
|
44
50
|
## The plausibility filter
|
|
45
51
|
|
|
46
52
|
The verb gate alone still left four false positives standing: `carries two rules about a standard's own lifecycle`, `holds one rule or one fact` (twice, once per mirrored copy), and `documents two similar commands`. Each pairs an assertion verb with a catalog noun used for something the `rules` or `commands` catalog does not mean, and what tells those apart from the one live finding is magnitude: a catalog this sweep tracks drifts by a few members between the day a sentence was written and the day it is read, so a genuine staleness claim sits near the true count. `2` beside a true count of `59` is not a catalog that shrank, it is a different `rules` entirely.
|
|
@@ -51,7 +57,9 @@ The article gate is looser than the verb list and carries a real cost. Re-runnin
|
|
|
51
57
|
|
|
52
58
|
## What it does not measure
|
|
53
59
|
|
|
54
|
-
A delta phrased as a transition (`from fourteen to fifteen`), a fraction (`thirteen of sixteen`), and a total reached through an indirect noun (`denominator of sixty-one shipped skills`) are all catalog-size claims this corpus carries, and none matches the
|
|
60
|
+
A delta phrased as a transition (`from fourteen to fifteen`), a fraction (`thirteen of sixteen`), and a total reached through an indirect noun (`denominator of sixty-one shipped skills`) are all catalog-size claims this corpus carries, and none matches the trigger shape this reads. Each stays a known gap. The false-positive rate that gated closing them has a measurement behind it now, and what it showed is that the widening these three need is the one that costs a false positive rather than the one that does not.
|
|
61
|
+
|
|
62
|
+
A second figure in a sentence whose first figure already matched is a fourth gap and a structural one, since one match is taken per catalog per sentence. `authors 69 rules under governance/rules/ and consumes 54 into .claude/rules/` is read for its 69 alone, which is correct here because the two figures name different populations, and a sentence stating one catalog twice would go unread the same way.
|
|
55
63
|
|
|
56
64
|
A calendar date (`2026-08-21`) or a backticked commit reference in the same sentence reads the whole sentence past, since that is how this corpus already marks a figure as a historical record rather than a live claim. `.claude/ARCHITECTURE.md` and the context entries carry a figure this way deliberately, and every one of them stays correct forever.
|
|
57
65
|
|
package/package.json
CHANGED
package/src/counts/scan.ts
CHANGED
|
@@ -78,6 +78,16 @@ function sentencesOf(line: string): string[] {
|
|
|
78
78
|
* asserting the catalog's own total, `the full entry loads 59 skills` being
|
|
79
79
|
* the live one, and gating the match on that verb is what a full re-read of
|
|
80
80
|
* the 290 showed removing all of them while keeping that one.
|
|
81
|
+
*
|
|
82
|
+
* `authors` joined the list on a corpus measurement rather than on the shape
|
|
83
|
+
* argument above. `.claude/context/development/regeneration.md` states `the
|
|
84
|
+
* toolkit authors 69 rules under governance/rules/`, which is the assertion
|
|
85
|
+
* shape this list was built for with a verb the list did not carry, and the
|
|
86
|
+
* word costs one further sentence across the whole corpus and no finding.
|
|
87
|
+
* Extending the vocabulary is the narrow half of this fix and it is taken
|
|
88
|
+
* knowingly: a list of thirteen verbs still grows by whatever the next author
|
|
89
|
+
* writes, and the measurement below is what ruled out the general axis that
|
|
90
|
+
* would have replaced it.
|
|
81
91
|
*/
|
|
82
92
|
const ASSERTION_VERBS = [
|
|
83
93
|
'loads',
|
|
@@ -92,8 +102,26 @@ const ASSERTION_VERBS = [
|
|
|
92
102
|
'lists',
|
|
93
103
|
'contains',
|
|
94
104
|
'comprises',
|
|
105
|
+
'authors',
|
|
95
106
|
]
|
|
96
107
|
|
|
108
|
+
/**
|
|
109
|
+
* A quantifier asserting the whole of a catalog immediately ahead of the
|
|
110
|
+
* number, which is the one trigger class that states a total outright rather
|
|
111
|
+
* than by implication.
|
|
112
|
+
*
|
|
113
|
+
* `all 69 rules` names the catalog entire, where `the 69 rules` leaves a
|
|
114
|
+
* reader to decide whether a qualifier narrows it. That makes this class
|
|
115
|
+
* tighter than the articles below rather than looser, and the corpus agrees:
|
|
116
|
+
* adding it reached 9 further sentences and produced 2 further findings, both
|
|
117
|
+
* of them real staleness this repository then repaired.
|
|
118
|
+
*
|
|
119
|
+
* `every` and `both` were measured beside `all` and reached nothing, so
|
|
120
|
+
* neither ships. A quantifier earns a place here by naming a sentence in the
|
|
121
|
+
* corpus, not by belonging to the same part of speech.
|
|
122
|
+
*/
|
|
123
|
+
const QUANTIFIERS = ['all']
|
|
124
|
+
|
|
97
125
|
/**
|
|
98
126
|
* An article immediately ahead of the number, admitting the shape a bare verb
|
|
99
127
|
* gate cannot reach: `the twelve audits read gitignored folders` asserts the
|
|
@@ -120,8 +148,9 @@ const ASSERTION_VERBS = [
|
|
|
120
148
|
const ARTICLES = ['the', 'a', 'an']
|
|
121
149
|
|
|
122
150
|
/**
|
|
123
|
-
* Matches a catalog's stated size: an assertion verb or an
|
|
124
|
-
* number, an optional single qualifying word, then the noun in
|
|
151
|
+
* Matches a catalog's stated size: an assertion verb, a quantifier, or an
|
|
152
|
+
* article, the number, an optional single qualifying word, then the noun in
|
|
153
|
+
* either number.
|
|
125
154
|
*
|
|
126
155
|
* The optional word between the number and the noun is what reaches a form
|
|
127
156
|
* like `installs 11 shipped snippets` without also reaching past an
|
|
@@ -130,16 +159,34 @@ const ARTICLES = ['the', 'a', 'an']
|
|
|
130
159
|
* double as its match narrows the corpus this reads without hand-listing
|
|
131
160
|
* every irregular plural, since none of these six is irregular.
|
|
132
161
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
162
|
+
* The gap between the trigger and the number was the second axis this comment
|
|
163
|
+
* used to name as open to widening once the false-positive rate had been
|
|
164
|
+
* measured over more than two runs. It was measured over the whole corpus at
|
|
165
|
+
* 518 files and 31,836 sentences and it is not the axis to take. Widths of
|
|
166
|
+
* one, two, and three optional words reached 77, 104, and 132 sentences
|
|
167
|
+
* against a baseline of 65, and the two live misses that motivated the
|
|
168
|
+
* measurement came back missed at every width but one: no width reaches `took
|
|
169
|
+
* all 69 rules`, whose nearest verb or article is the `The` opening the
|
|
170
|
+
* sentence, with five words standing between it and the number, and the width
|
|
171
|
+
* that does reach `the toolkit authors 69 rules` is the same
|
|
172
|
+
* width that admits `a domain of 55 skills`, which is the indirect-noun shape
|
|
173
|
+
* this module already records as out of scope. Widening the gap buys one of
|
|
174
|
+
* two misses at 60 percent more reach and a false positive of a class already
|
|
175
|
+
* named.
|
|
176
|
+
*
|
|
177
|
+
* The trigger vocabulary carries both misses instead, at 75 sentences reached
|
|
178
|
+
* against 65 and no false positive: `all` reaches the first and `authors` the
|
|
179
|
+
* second. Two of the four findings that shape reports were new, and both were
|
|
180
|
+
* real. Measured at `ffe7e7c6` on 2026-08-28.
|
|
181
|
+
*
|
|
182
|
+
* What this still drops: `denominator of sixty-one shipped skills` states a
|
|
183
|
+
* real catalog total through an indirect noun and reads past, which the gap
|
|
184
|
+
* measurement above is the argument for leaving alone rather than an
|
|
185
|
+
* oversight.
|
|
139
186
|
*/
|
|
140
187
|
function buildMatcher(catalog: Catalog): RegExp {
|
|
141
188
|
const [singular, plural] = catalog.nouns
|
|
142
|
-
const triggers = [...ASSERTION_VERBS, ...ARTICLES].join('|')
|
|
189
|
+
const triggers = [...ASSERTION_VERBS, ...QUANTIFIERS, ...ARTICLES].join('|')
|
|
143
190
|
return new RegExp(
|
|
144
191
|
`\\b(?:${triggers})\\s+(${NUMBER_PATTERN})(?:\\s+[a-z]+)?\\s+(?:${singular}|${plural})\\b`,
|
|
145
192
|
'gi',
|
|
@@ -187,10 +234,19 @@ function isPlausibleClaim(stated: number, actual: number): boolean {
|
|
|
187
234
|
* What it does not measure: a delta phrased as a transition (`from fourteen
|
|
188
235
|
* to fifteen`), a fraction (`thirteen of sixteen`), and a total reached
|
|
189
236
|
* through an indirect noun (`denominator of sixty-one shipped skills`) are
|
|
190
|
-
* all catalog-size claims this corpus carries, and none matches the
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
237
|
+
* all catalog-size claims this corpus carries, and none matches the trigger
|
|
238
|
+
* shape this reads. Each stays a known gap. The rate that used to gate
|
|
239
|
+
* closing them is measured now, and what it showed is that the widening they
|
|
240
|
+
* would need is the one that costs a false positive rather than the one that
|
|
241
|
+
* does not, which `buildMatcher` records with its numbers.
|
|
242
|
+
*
|
|
243
|
+
* A second figure in a sentence whose first figure already matched is a
|
|
244
|
+
* fourth gap and a structural one: `regex.exec` takes one match per catalog
|
|
245
|
+
* per sentence, so `authors 69 rules under governance/rules/ and consumes 54
|
|
246
|
+
* into .claude/rules/` is read for its 69 alone. Reaching the 54 would be
|
|
247
|
+
* wrong here rather than better, since it counts the consumed mirror rather
|
|
248
|
+
* than the source catalog this sweep tracks, but a sentence stating one
|
|
249
|
+
* catalog twice would go unread the same way.
|
|
194
250
|
*/
|
|
195
251
|
export async function scanCounts(root: string): Promise<CountsReport> {
|
|
196
252
|
const scope = await resolveMarkdown(root, [])
|