@erclx/aitk 3.34.0 → 3.34.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": "3.34.0",
4
+ "version": "3.34.1",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -61,7 +61,7 @@ Two ban shapes stay unmeasured and the report says so on every run. A multi-word
61
61
 
62
62
  ### Bullets, paragraphs, and depth
63
63
 
64
- Bullet weight and depth are the checks that moved off `aitk context audit`, unchanged in what they measure. A top-level bullet reports past roughly 400 characters with continuation lines folded in and nested items left out. A run of lines no heading breaks reports past roughly 40 rendered lines, measured at 80 columns, skipping fenced blocks and exempting a flat peer list averaging under 130 characters a bullet and a run that is entirely table rows. Each file reports its longest run alone, so a second run past the checkpoint in the same file is never named.
64
+ Bullet weight and depth are the checks that moved off `aitk context audit`, carrying what they measured at the time. A top-level bullet reports past roughly 400 characters with continuation lines folded in and nested items left out. A run reports past roughly 40 rendered lines, measured at 80 columns, where a heading breaks one and so does a bold section marker taking the whole line at column zero and ending in a colon, skipping fenced blocks and exempting a flat peer list averaging under 130 characters a bullet and a run that is entirely table rows. Each file reports its longest run alone, so a second run past the checkpoint in the same file is never named.
65
65
 
66
66
  Every weight and depth measure counts the text a reader is shown. A link reduces to its anchor text and an autolink drops whole, since no reader is shown either destination. A backticked path stays counted, which is where these measures part from the ban scan above: that one blanks a code span so a standard quoting its own banned character does not report itself, and discounting the same span here would under-report a paragraph carrying several. One file holds both span sets and each answers its own question.
67
67
 
@@ -136,7 +136,7 @@ Measured at `4b7b13a2` across 444 files with the paragraph checkpoint at 600: 8
136
136
 
137
137
  The ban half reached zero, which was the precondition the gate waited on, and it was re-measured against the same corpus at the moment the gate landed. Three sweep slices then took the structural half, and the corpus reports 1 heavy bullet and 22 heavy paragraphs across 6 files on 2026-08-06, every one on a ground the triage record holds as exempt.
138
138
 
139
- Depth is the one measure no slice triaged, so its figure moved with the sweep rather than with the corpus. Read all four structural counts from a run rather than from this paragraph.
139
+ Depth is the one measure no slice triaged, so its figure moved with the sweep rather than with the corpus. The break rule widened to bold section markers on 2026-08-28, which drops the count again with no edit to any file, so the 41 above reads against a rule the command no longer runs. Read all four structural counts from a run rather than from this paragraph.
140
140
 
141
141
  ### What a hit asks of an author
142
142
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.34.0",
4
+ "version": "3.34.1",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -519,6 +519,9 @@ function reportDepth(
519
519
  logInfo(
520
520
  'A run that is entirely table rows is excluded too, since a heading inside a table splits the table rather than the run.',
521
521
  )
522
+ logInfo(
523
+ 'A heading breaks a run and so does a bold section marker at column zero ending in a colon, such as a line reading only Risks in bold. A colon-less or indented one stays prose.',
524
+ )
522
525
 
523
526
  const over = reports
524
527
  .filter((report) => report.structure.longestRun > checkpoints.run)
@@ -1,6 +1,38 @@
1
1
  import { type BodyLine, visibleText } from '@/markdown/scan'
2
2
 
3
3
  const HEADING = /^#{1,6}\s/
4
+
5
+ /**
6
+ * A section marker holding its line alone, which is the signpost a document
7
+ * uses where its own template asks for bold rather than a heading.
8
+ *
9
+ * `standards/plan.md` gives `## Summary` a heading and marks the four sections
10
+ * below it this way, so a conforming plan read as one run from its first line
11
+ * to its last and all seven live plans reported past the depth checkpoint, at
12
+ * 106 to 166 rendered lines. A measure firing on a whole corpus says nothing
13
+ * about it, and it costs more than silence, since a reader who learns to skip
14
+ * the depth section skips it on the file where a deep run genuinely sits.
15
+ *
16
+ * Breaking on the marker clears two of those seven and moves the other five
17
+ * onto the seams inside them, at 42 to 77 lines, which is the measure telling
18
+ * a long section from a long file for the first time. Moving the template to
19
+ * headings was the alternative and it clears no plan already written, leaving
20
+ * each flagged until someone rewrites it.
21
+ *
22
+ * The marker starts at column zero and carries a colon, and the whole line is
23
+ * the marker or none of it is. A bold phrase opening a sentence is emphasis
24
+ * rather than a seam, and an indented one is a label inside a list item, so
25
+ * both stay prose. This ships as package data every project reads, where a
26
+ * missed break costs one unbroken run and a false one shortens every run around
27
+ * it until the measure stops reporting, which is the dearer of the two.
28
+ *
29
+ * The colon is what a colon-less `**Testing**` is held out by, and that shape
30
+ * is a real section marker in a review body rather than a hypothetical. Widening
31
+ * to reach it moves the shipped pattern rather than the wording, so the rule
32
+ * states the colon and the widening stays open for a decision of its own.
33
+ */
34
+ const SECTION_MARKER = /^\*\*[^*]+:\*\*\s*$/
35
+
4
36
  const LIST_ITEM = /^(\s*)([-*+]|\d+\.)\s+/
5
37
  const TABLE_ROW = /^\s*\|/
6
38
  const TABLE_SEPARATOR = /^\s*\|[\s:|-]+\|\s*$/
@@ -241,7 +273,11 @@ function isTableRun(run: readonly BodyLine[]): boolean {
241
273
  }
242
274
 
243
275
  /**
244
- * Measures the longest run of lines no heading breaks, in rendered lines.
276
+ * Measures the longest run of lines no signpost breaks, in rendered lines.
277
+ *
278
+ * A heading breaks a run and so does a section marker, which is the same
279
+ * signpost written the way a template asked for it. `SECTION_MARKER` above
280
+ * fixes which lines qualify.
245
281
  *
246
282
  * Fenced lines are skipped rather than treated as breaks, per the standard:
247
283
  * they leave the count without ending the run, so prose either side of an
@@ -289,7 +325,7 @@ export function longestRun(
289
325
  for (const line of lines) {
290
326
  if (line.fenced) continue
291
327
 
292
- if (HEADING.test(line.text)) {
328
+ if (HEADING.test(line.text) || SECTION_MARKER.test(line.text)) {
293
329
  close()
294
330
  continue
295
331
  }
@@ -36,6 +36,8 @@ Does not govern:
36
36
  - Mixing prose with that list, or nesting levels inside it, ends the exemption at any weight.
37
37
  - Exempt a block whose lines are all table rows, at any length. The peer list above is exempt because it is already navigable, and a table because the remedy does not exist: a subheading dropped inside one splits the table rather than the run, so no edit short of rewriting it as a list clears the checkpoint.
38
38
  - Prose either side of the table ends that exemption, since the block has a seam and a heading breaks it there.
39
+ - Break a run on a bold section marker holding its line alone, the way a heading breaks one. A document whose template separates sections with `**Risks:**` rather than `## Risks` has written the seam a reader lands on, and reading only the heading reported every such file at its full length whatever it carried.
40
+ - Require the marker to start at column zero and to end in a colon inside the bold, and to be the whole line. `**Risks:**` breaks a run, a bold phrase opening a sentence stays emphasis, and an indented one stays a label inside its list item. A colon-less `**Testing**` does not break either, which holds a real section marker out and is the cost of keeping the pattern narrow on data every project is measured against.
39
41
 
40
42
  ## Paragraphs and lists
41
43
 
package/standards/plan.md CHANGED
@@ -57,6 +57,7 @@ The document opens with `# Feature: <short title>` and one paragraph stating wha
57
57
 
58
58
  - Write each marker as the table gives it. `Summary` opens the prose a reader scans, so it takes an H2, and the four that follow are labels over lists rather than sections of prose.
59
59
  - A section written in the other spelling is still that section. `## Risks` and `**Risks:**` name one thing, and a plan carrying either has stated its risks, so neither reads as an omission. Write the table's form in a new plan and leave an existing plan's spelling alone.
60
+ - Both spellings break a depth run, so `aitk markdown audit` reads either as the seam it is and reports a plan for a section that genuinely runs long rather than for its whole body. The markdown standard states the rule.
60
61
  - Write `None identified.` under a required section with nothing to report rather than dropping the marker. A dropped section and an unconsidered one read identically.
61
62
  - Aim `## Summary` at a person scanning the plan, not at the session executing it. The other sections carry what execution needs.
62
63
  - Give every `**Files to touch:**` entry a backticked path and something said about it. A bare path states scope and not intent, and the reason is what an executing session checks its edit against. Lead with the path or lead with a label carrying the path, whichever reads better for the entry.