@erclx/aitk 0.63.2 → 0.64.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.63.2",
4
+ "version": "0.64.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -32,7 +32,8 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
32
32
  | `aitk tasks validate` | Report board rows whose plan, task file, group, or file set does not hold (`--json`) |
33
33
  | `aitk records validate` | Report a session record against the standard governing it, per kind (`--json`) |
34
34
  | `aitk comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
35
- | `aitk context audit` | Report required sections, length, depth, bullet weight, cited paths, provenance, and drift |
35
+ | `aitk context audit` | Report required sections, length, cited paths, catalog tables, provenance, and index drift |
36
+ | `aitk markdown audit` | Report any markdown path against the character bans, word bans, and structural checkpoints |
36
37
  | `aitk claude skills audit` | Report both skill corpora against the mechanical rules in `standards/skill.md` |
37
38
  | `aitk capture [source]` | Render HTML capture sources to PNG, toolkit-only and absent from an installed package |
38
39
 
@@ -53,6 +54,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
53
54
  | `tasks` | `archive`, `validate` |
54
55
  | `comments` | `scan` |
55
56
  | `context` | `audit` |
57
+ | `markdown` | `audit` |
56
58
 
57
59
  Common patterns:
58
60
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Context audit checks
3
- description: What each non-gating check reports, the unit each checkpoint is measured in, and which folders each check reaches
3
+ description: What each non-gating check reports, the unit each checkpoint is measured in, which folders each check reaches, and what moved to the attribute tier
4
4
  ---
5
5
 
6
6
  # Context audit checks
@@ -17,19 +17,15 @@ It reports rather than gates by default, the closer call because a missing secti
17
17
 
18
18
  `--gate` promotes the finding to a failing exit code, which the seed stage runs and no other caller does. That mode needs an answer to the sanctioned omission above, so a file declaring `stub: true` in its frontmatter is dropped before the check and reported nowhere. Both are described in `context-audit.md`.
19
19
 
20
- ## Length and depth
20
+ ## Length
21
21
 
22
- Length quotes its checkpoint from `.claude/standards/context.md` and depth quotes its from `.claude/standards/markdown.md`, which states it over every markdown file: roughly 150 rendered lines for an entry, roughly 40 for a run no heading breaks. Depth measures the longest such run rather than everything under one `##`, skips fenced blocks so a markdown example does not read as three headings, and exempts a run whose lines are all list items at one indent averaging under 130 characters. The weight condition is what separates a scannable catalog of one-liners from a stack of paragraph-bullets, which reach the same count and read nothing alike.
22
+ Length quotes its checkpoint from `.claude/standards/context.md`: roughly 150 rendered lines for an entry. It counts rendered lines rather than source lines, wrapping each line at 80 columns and summing the heights. Entries here are authored one line per bullet, so a block of fifteen paragraph-bullets occupies fifteen source lines and renders past sixty, which source counting cannot see. The measure counts fenced blocks and frontmatter, so a reference-heavy entry ranks by its examples, which the legend states on every run alongside the width, since a number in rendered lines cannot be reproduced without it.
23
23
 
24
- Depth exempts a second shape, and the two are excused for opposite reasons. A peer list is already navigable, so a subheading dropped into it splits a set that belongs together. A table is exempt because the remedy does not exist: a heading placed inside one splits the table rather than the run, so a catalog renders as an unbroken stretch by construction and no edit short of rewriting it as a list clears the report. The test is whether the run is a table rather than whether it holds one, so a table with prose either side still reports and a heading breaks it at the seam. A run of piped lines carrying no delimiter row is not a table and reports like any other prose. The table finding above is unaffected, so a catalog silenced here still reports as a candidate for a bullet list, which is the measure whose remedy does exist.
24
+ Depth and bullet weight are quoted from `.claude/standards/markdown.md`, which states both over every markdown file rather than over a context entry, so `aitk markdown audit` measures them and this command no longer does. They share `renderedHeight` with the length measure, since the two checkpoints sit in one section of that standard and a reader compares them. What the split costs is that a session wanting both numbers for one entry runs two commands, and what it buys is that either number can be had for a file in a folder this audit refuses to resolve.
25
25
 
26
- Both checks count rendered lines rather than source lines, wrapping each line at 80 columns and summing the heights. Entries here are authored one line per bullet, so a block of fifteen paragraph-bullets occupies fifteen source lines and renders past sixty, which source counting cannot see. Measuring one checkpoint in each unit would put an entry length beside a run length that mean different things. Their exclusions still differ: the file measure counts fenced blocks and frontmatter, while the run measure skips a fence so an example cannot break the run around it. A reference-heavy entry therefore ranks by its examples, which the length legend states on every run. Runs count blank lines, which the standard leaves open, so a hand reader who drops them lands a line or two lower. Both sections state the width on every run, since a number in rendered lines cannot be reproduced without it.
26
+ ## Tables
27
27
 
28
- ## Bullet weight and tables
29
-
30
- The bullet check reports a top-level bullet past roughly 400 characters, which is where the overflow belongs in prose rather than in the bullet. A context entry specializes that remedy, sending the incident that motivated a decision to the change, issue, or research record behind it. Continuation lines fold into the bullet they belong to, so a heavy bullet cannot fall under the checkpoint by wrapping across two source lines, while a nested item is left out because the parent's own text is what the checkpoint asks about. Findings group by entry for the reason the provenance ones do, and reach every audited folder, since `.claude/standards/markdown.md` states the checkpoint over every markdown file. Unlike the peer-list threshold above it, this corpus has no gap behind the number: bullet weight decays smoothly from a median near 170, so the number is a judgment where that one was a measurement, and a bullet reading well past it means the number is wrong rather than the rule.
31
-
32
- The table check reports a catalog that grows a row per shipped thing, not a table count. A fixed comparison table never reflows, so its size costs nothing. A table qualifies at six or more body rows whose first column mostly carries a path, command, or link, which is what separates a catalog from a comparison without reading the prose.
28
+ The table check reports a catalog that grows a row per shipped thing, not a table count. A fixed comparison table never reflows, so its size costs nothing. A table qualifies at six or more body rows whose first column mostly carries a path, command, or link, which is what separates a catalog from a comparison without reading the prose. It stays here rather than moving with depth, because the shape it routes a catalog into is a judgment the context standard makes about an entry.
33
29
 
34
30
  ## Provenance
35
31
 
@@ -37,7 +33,9 @@ The provenance check reports the markers narrating how a domain reached its shap
37
33
 
38
34
  ## Which folders each check reaches
39
35
 
40
- The provenance and required-section checks cover `.claude/context/` alone, while length, depth, bullet weight, and the table finding reach every audited folder. What narrows the two is stated in `.claude/standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures. Depth and bullet weight are stated in `.claude/standards/markdown.md` over every markdown file, so both reach wherever the audit is pointed, and length and the table finding generalize as judgments about how far a reader travels. Required sections narrow for a plainer reason: the names are the context standard's own, and neither sibling standard states a required section at all. The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
36
+ The provenance and required-section checks cover `.claude/context/` alone, while length and the table finding reach every audited folder. What narrows the two is stated in `.claude/standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures. Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: the names are the context standard's own, and neither sibling standard states a required section at all.
37
+
38
+ The same test is what moved depth and bullet weight out of this command entirely. A rule stated at the attribute tier reaches every markdown file, and a check reaching every markdown file has no reason to require a folder that resolves. The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
41
39
 
42
40
  ## Index drift
43
41
 
@@ -7,6 +7,8 @@ description: Running the audit, its flags and folder scope, the exit codes, the
7
7
 
8
8
  `aitk context audit [path]` reports the structural state of the folders following the index-plus-entry contract, meaning a generated `index.md` beside entries carrying frontmatter. It reads and reports. Fixing what it finds is separate work. What each finding means is in `context-audit-checks.md`.
9
9
 
10
+ Findings stated over every markdown file rather than over a context entry are measured by `aitk markdown audit`, described in `markdown-audit.md`. That command resolves no folder, so it reaches trees this one refuses.
11
+
10
12
  ```bash
11
13
  aitk context audit
12
14
  aitk context audit --json
@@ -35,7 +37,7 @@ A run where no requested name resolves refuses, whichever list it read. Naming t
35
37
 
36
38
  ## Exit codes
37
39
 
38
- Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating finding. An unresolved citation gates under every mode. Length, depth, bullet weight, table, and provenance findings print and return `0` under every mode, because each is a judgment and failing a push on one would make the check something to route around.
40
+ Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating finding. An unresolved citation gates under every mode. Length, table, and provenance findings print and return `0` under every mode, because each is a judgment and failing a push on one would make the check something to route around.
39
41
 
40
42
  Required-section and index findings sit between the two. Both are answerable from the file rather than weighed, so `--gate` promotes them to failing codes while a bare run leaves them advisory. The toolkit runs the bare form against itself and the widened form against the seed tree, described below.
41
43
 
@@ -11,11 +11,12 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
11
11
  - [Capture](capture.md): Rendering committed HTML sources to PNG, what the command asserts about fonts, and why it is toolkit-only
12
12
  - [Command catalog](commands.md): Every project-level command and every domain subcommand, plus the shape each domain exposes
13
13
  - [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
14
- - [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, and which folders each check reaches
14
+ - [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, which folders each check reaches, and what moved to the attribute tier
15
15
  - [Context audit](context-audit.md): Running the audit, its flags and folder scope, the exit codes, the citation gate, and the widened gate the seed stage runs
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
+ - [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 nothing gates yet
19
20
  - [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
20
21
  - [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
21
22
  - [Records](records.md): Validating the gitignored session records under .claude/, the per-kind checks, the refusal reasons, and why the root defaults to the main worktree
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: Markdown audit
3
+ description: Running the audit over any markdown path, where its bans and checkpoints are read from, what each check reports, and why nothing gates yet
4
+ ---
5
+
6
+ # Markdown audit
7
+
8
+ `aitk markdown audit [path...]` reports any markdown file against the two attribute standards, `markdown.md` and `prose.md`. An attribute standard governs a file rather than a folder, so this resolves no folder and requires no `index.md`, which is what puts `.claude/rules/`, `governance/`, and `snippets/` in reach. Folder-shaped findings stay in `aitk context audit`, described in `context-audit.md`.
9
+
10
+ ```bash
11
+ aitk markdown audit
12
+ aitk markdown audit --json
13
+ aitk markdown audit .claude/rules governance
14
+ aitk markdown audit docs/agents/commands.md
15
+ aitk markdown audit 'snippets/**/*.md'
16
+ ```
17
+
18
+ | Option | Behavior |
19
+ | -------- | ---------------------------------------------------------- |
20
+ | `--json` | Add a machine-readable record on stdout, keeping the frame |
21
+
22
+ ## Scope
23
+
24
+ An argument is a file, a directory, or a glob. A directory narrows to everything under it and a glob narrows by match, both against the corpus git lists, which is what keeps `node_modules/` and the gitignored session-scratch folders out without naming either. An explicit file path is taken as given, so a gitignored draft can be measured before it is committed. Quote a glob the shell would expand first.
25
+
26
+ A bare run measures every markdown file git lists, tracked plus untracked-and-not-ignored, so a file added on this branch is in scope on the branch that adds it. An argument matching no markdown file is named on the scope line rather than passed over, since a run measuring the paths that did resolve otherwise reads as a pass over one it never opened.
27
+
28
+ ## Where the rules come from
29
+
30
+ Both ban sets and all five checkpoints are read out of the standards per run, resolved under `.claude/standards/` first and the authoring root second, so a target project measures against the copy it actually has. Holding the lists in code was the alternative and it puts each ban in two places, where an author adding one gets no enforcement until someone edits TypeScript.
31
+
32
+ The trade is a reader of prose that a reformat can break. `src/markdown/bans.test.ts` answers it by asserting the parsed sets against the shipped standards, so a rewrite that narrows a set fails there rather than passing quietly. A checkpoint falls back per number rather than per file, and the depth legend names every checkpoint that fell back on the run that used one.
33
+
34
+ ## What each check reports
35
+
36
+ ### Bans
37
+
38
+ Three closed sets report a hit: the characters `markdown.md` bans under `## Punctuation`, the single lowercase words `prose.md` bans under `## Language`, and the British spellings derived by applying that section's own suffix rules to its own examples.
39
+
40
+ Deriving the spellings rather than pattern-matching a suffix is what keeps `exercises`, `promises`, and `revised` out of the report. A suffix pattern over the same corpus produced 46 false positives from words of that shape, and a closed set of whole words reaches none of them.
41
+
42
+ Frontmatter, fenced blocks, inline code spans, and link destinations are excluded. Without the code-span exclusion each standard would report its own backticked examples, and without the link exclusion a semicolon in a query string would report as prose no rewrite can fix.
43
+
44
+ Two ban shapes stay unmeasured and the report says so on every run. A phrase ban carries a placeholder standing in for the rest of the sentence, so no literal match reaches it, and every rule under `## Voice` is a judgment. A report listing hits without naming those would read as a verdict on the whole standard.
45
+
46
+ ### Bullets, paragraphs, and depth
47
+
48
+ 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.
49
+
50
+ The paragraph check is new and 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: measured across 2906 paragraphs, 344 sit inside four sentences and past 400 characters, and the heaviest runs 1159 characters in two. The standard therefore states a weight beside the sentence cap, and the verb reads it as its own checkpoint.
51
+
52
+ The paragraph weight and the bullet weight are the same number today because the two shapes measure one population, sharing a median near 170 characters with no gap behind either candidate. They are separate checkpoints in the standard and separate patterns in the parser, so retuning one leaves the other where it is.
53
+
54
+ A bullet, a heading, a table row, a blockquote, a blank line, and a fence each end a paragraph, so a heavy bullet is reported by the bullet check alone and never counted twice.
55
+
56
+ ## Exit codes
57
+
58
+ Exit codes are `0` for a completed run and `1` for a refusal. Every finding reports and none gates.
59
+
60
+ A banned character is a fact rather than a judgment, which is the test that would ordinarily make it gate. What holds it back is that gating on day one against a corpus never checked mechanically fails loudly on work nobody has had a chance to fix. The order is to land the verb reporting, measure the corpus once, fix what it finds, and turn the gate on as its own change. Bullet, paragraph, and depth weight are judgments and stay advisory under any later gate.
61
+
62
+ Measured across 443 files on the day this shipped: 9 word hits, no character or spelling hits, 109 heavy bullets, 610 heavy paragraphs, and 42 files carrying a run past the depth checkpoint. The ban count is what a gate would have to hold at zero, and it is the only one of the five a gate should ever read.
63
+
64
+ ## What it does not cover
65
+
66
+ The verb reads the two attribute standards and nothing else. The five standards declaring `appliesTo: ["*"]` also include `publish.md`, `slug.md`, and `versioning.md`, none of which this implements.
67
+
68
+ `publish.md` describes a scan applying the same punctuation bans to finished text on its way out. No code implemented that scan before this command, so nothing is duplicated, and a later surface should call this verb rather than build a second one.
69
+
70
+ The list-density rule at `standards/markdown.md` is out of scope on purpose, since it carries no number and what a density figure should measure is still open.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.63.2",
4
+ "version": "0.64.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
package/src/cli.ts CHANGED
@@ -22,6 +22,7 @@ import { register as transcripts } from '@/commands/transcripts'
22
22
  import { register as tasks } from '@/commands/tasks'
23
23
  import { register as comments } from '@/commands/comments'
24
24
  import { register as context } from '@/commands/context'
25
+ import { register as markdown } from '@/commands/markdown'
25
26
  import { register as records } from '@/commands/records'
26
27
  import { PROJECT_ROOT } from '@/exec'
27
28
 
@@ -54,6 +55,7 @@ function showHelp(): void {
54
55
  `${GREY}│${NC} tasks [cmd] ${GREY}# Task board commands (archive)${NC}`,
55
56
  `${GREY}│${NC} comments [cmd] ${GREY}# Measure comment density and trend (scan)${NC}`,
56
57
  `${GREY}│${NC} context [cmd] ${GREY}# Report context folder health (audit)${NC}`,
58
+ `${GREY}│${NC} markdown [cmd] ${GREY}# Report markdown against the attribute standards (audit)${NC}`,
57
59
  `${GREY}│${NC} records [cmd] ${GREY}# Check session records under .claude/ (validate)${NC}`,
58
60
  `${GREY}│${NC}`,
59
61
  `${GREY}│${NC} ${WHITE}Sandbox:${NC}`,
@@ -87,6 +89,7 @@ function showHelp(): void {
87
89
  `${GREY}│${NC} aitk tasks archive --pull-request 673 --json`,
88
90
  `${GREY}│${NC} aitk comments scan src --json`,
89
91
  `${GREY}│${NC} aitk context audit --json`,
92
+ `${GREY}│${NC} aitk markdown audit .claude/rules --json`,
90
93
  `${GREY}│${NC} aitk records validate plans`,
91
94
  `${GREY}└${NC}`,
92
95
  ]
@@ -141,6 +144,7 @@ transcripts(program)
141
144
  tasks(program)
142
145
  comments(program)
143
146
  context(program)
147
+ markdown(program)
144
148
  records(program)
145
149
 
146
150
  program.parse()
@@ -1,17 +1,13 @@
1
1
  import { resolve } from 'node:path'
2
2
  import type { Command } from 'commander'
3
3
  import {
4
- BULLET_CHECKPOINT,
5
4
  type EntryReport,
6
5
  governsContent,
7
6
  LENGTH_CHECKPOINT,
8
7
  measureFolders,
9
8
  missingSections,
10
- PEER_BULLET_CHECKPOINT,
11
9
  PROVENANCE_FOLDER,
12
- RENDER_WIDTH,
13
10
  REQUIRED_SECTIONS,
14
- RUN_CHECKPOINT,
15
11
  type SectionFinding,
16
12
  } from '@/context/audit'
17
13
  import { auditCitations, type CitationReport } from '@/context/citations'
@@ -23,6 +19,7 @@ import {
23
19
  } from '@/context/folders'
24
20
  import { isGating } from '@/context/gate'
25
21
  import { auditIndexes, type FolderDrift } from '@/context/index-drift'
22
+ import { RENDER_WIDTH } from '@/markdown/structure'
26
23
  import {
27
24
  frameError,
28
25
  intro,
@@ -57,7 +54,7 @@ export function register(program: Command): void {
57
54
  context
58
55
  .command('audit')
59
56
  .description(
60
- 'Report required sections, entry length, depth, bullet weight, citations, provenance, and index drift',
57
+ 'Report required sections, entry length, citations, catalog tables, provenance, and index drift',
61
58
  )
62
59
  .argument('[path]', 'Project root, defaulting to the current directory')
63
60
  .helpOption('-h, --help', 'Show this help message')
@@ -82,8 +79,11 @@ export function register(program: Command): void {
82
79
  '',
83
80
  'An unresolved citation always gates. --gate widens the gate to the',
84
81
  'other two findings that are facts rather than judgments: a missing',
85
- 'required section and index drift. Length, depth, bullet, table, and',
86
- 'provenance findings are thresholds and stay advisory under both.',
82
+ 'required section and index drift. Length, table, and provenance',
83
+ 'findings are thresholds and stay advisory under both.',
84
+ '',
85
+ 'Depth and bullet weight are stated over every markdown file rather',
86
+ 'than over a context entry, so `aitk markdown audit` measures them.',
87
87
  '',
88
88
  'Examples:',
89
89
  ' aitk context audit',
@@ -192,8 +192,6 @@ async function runAudit(
192
192
  reportCitations(citations, cited)
193
193
  reportSections(sections, folders)
194
194
  reportLength(entries)
195
- reportDepth(entries)
196
- reportBullets(entries)
197
195
  reportTables(entries)
198
196
  reportProvenance(entries, folders)
199
197
  reportDrift(drift)
@@ -221,11 +219,7 @@ async function runAudit(
221
219
  indexDrift: drift,
222
220
  checkpoints: {
223
221
  lines: LENGTH_CHECKPOINT,
224
- run: RUN_CHECKPOINT,
225
- runCountsBlankLines: true,
226
222
  renderWidth: RENDER_WIDTH,
227
- peerBullet: PEER_BULLET_CHECKPOINT,
228
- bullet: BULLET_CHECKPOINT,
229
223
  provenanceFolder: PROVENANCE_FOLDER,
230
224
  requiredSections: REQUIRED_SECTIONS,
231
225
  },
@@ -395,7 +389,7 @@ function reportLength(entries: readonly EntryReport[]): void {
395
389
  `Entries measure rendered lines at ${RENDER_WIDTH} columns, counting frontmatter and fenced blocks.`,
396
390
  )
397
391
  logInfo(
398
- 'A reference-heavy entry therefore ranks by its examples, which the depth check excludes.',
392
+ 'A reference-heavy entry therefore ranks by its examples, which the depth check in `aitk markdown audit` excludes.',
399
393
  )
400
394
 
401
395
  const over = entries
@@ -415,96 +409,6 @@ function reportLength(entries: readonly EntryReport[]): void {
415
409
  )
416
410
  }
417
411
 
418
- /**
419
- * Names the render width and the blank-line convention on every run.
420
- *
421
- * The standard settles heading level and fenced blocks and stops there, so a
422
- * hand reader who drops blank lines lands a line or two below this number.
423
- * Stating both is what keeps the two measurements reconcilable, and the width
424
- * matters more than the blank lines because a number counted in rendered lines
425
- * cannot be reproduced without it.
426
- */
427
- function reportDepth(entries: readonly EntryReport[]): void {
428
- logStep('Depth')
429
- logInfo(
430
- `Runs measure rendered lines at ${RENDER_WIDTH} columns and count blank lines.`,
431
- )
432
- logInfo(
433
- `Fenced blocks are excluded, and so are peer lists averaging under ${PEER_BULLET_CHECKPOINT} characters a bullet.`,
434
- )
435
- logInfo(
436
- 'A run that is entirely table rows is excluded too, since a heading inside a table splits the table rather than the run.',
437
- )
438
-
439
- const over = entries
440
- .filter((entry) => entry.longestRun > RUN_CHECKPOINT)
441
- .sort((a, b) => b.longestRun - a.longestRun)
442
-
443
- if (over.length === 0) {
444
- logInfo(`No run past the ${RUN_CHECKPOINT}-line checkpoint.`)
445
- return
446
- }
447
-
448
- logWarn(`${over.length} past the ${RUN_CHECKPOINT}-line checkpoint`)
449
- pipeOutput(
450
- over
451
- .map(
452
- (entry) =>
453
- `${entry.rel}:${entry.longestRunLine} ${entry.longestRun} rendered lines unbroken`,
454
- )
455
- .join('\n'),
456
- )
457
- }
458
-
459
- /**
460
- * Groups by entry, and states its reach on every run, for the reasons the
461
- * provenance report does both.
462
- *
463
- * Bullets past the checkpoint cluster in a handful of entries and the heaviest
464
- * entries carry them a dozen at a time, so a flat list of bullets buries the
465
- * entry holding one. What a reader acts on is which file to open.
466
- */
467
- function reportBullets(entries: readonly EntryReport[]): void {
468
- logStep('Bullets')
469
-
470
- logInfo(
471
- 'Covers every audited folder, since the rule is stated in the standard governing every markdown file.',
472
- )
473
- logInfo(
474
- 'Top-level bullets measure characters, folding in continuation lines.',
475
- )
476
- logInfo(
477
- 'Nested items and fenced blocks are excluded. Weight is a judgment, never a defect.',
478
- )
479
-
480
- const carrying = entries
481
- .filter((entry) => entry.heavyBullets.length > 0)
482
- .sort((a, b) => b.heavyBullets.length - a.heavyBullets.length)
483
-
484
- if (carrying.length === 0) {
485
- logInfo(`No bullet past the ${BULLET_CHECKPOINT}-character checkpoint.`)
486
- return
487
- }
488
-
489
- const total = carrying.reduce(
490
- (sum, entry) => sum + entry.heavyBullets.length,
491
- 0,
492
- )
493
- logWarn(
494
- `${plural(total, 'bullet')} past the ${BULLET_CHECKPOINT}-character checkpoint across ${carrying.length} ${carrying.length === 1 ? 'entry' : 'entries'}`,
495
- )
496
- pipeOutput(
497
- carrying
498
- .map(
499
- (entry) =>
500
- `${entry.rel} ${plural(entry.heavyBullets.length, 'bullet')}\n${entry.heavyBullets
501
- .map((found) => ` :${found.line} ${found.characters} characters`)
502
- .join('\n')}`,
503
- )
504
- .join('\n'),
505
- )
506
- }
507
-
508
412
  function reportTables(entries: readonly EntryReport[]): void {
509
413
  logStep('Tables')
510
414