@erclx/aitk 0.105.0 → 0.107.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.
Files changed (59) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/claude-address-review/SKILL.md +4 -3
  3. package/claude/skills/claude-design-extract/SKILL.md +3 -3
  4. package/claude/skills/claude-docs/SKILL.md +1 -1
  5. package/claude/skills/claude-memory-capture/SKILL.md +2 -2
  6. package/claude/skills/claude-pr-review/SKILL.md +1 -1
  7. package/claude/skills/claude-standards-audit/SKILL.md +8 -6
  8. package/claude/skills/create-skill/SKILL.md +2 -2
  9. package/claude/skills/create-snippet/SKILL.md +2 -2
  10. package/claude/skills/create-snippet/references/snippets.md +2 -2
  11. package/claude/skills/create-standard/SKILL.md +2 -2
  12. package/claude/skills/docs-sync/SKILL.md +2 -2
  13. package/claude/skills/git-issue/SKILL.md +2 -2
  14. package/claude/skills/git-issue/references/issue.md +2 -2
  15. package/claude/skills/git-pr/SKILL.md +2 -2
  16. package/claude/skills/git-pr/references/pr.md +2 -2
  17. package/claude/skills/git-split/references/pr.md +2 -2
  18. package/claude/skills/git-stage/SKILL.md +2 -2
  19. package/claude/skills/migration-standards/SKILL.md +1 -1
  20. package/claude/skills/setup-indexes/SKILL.md +1 -1
  21. package/claude/skills/write-human/REQUIREMENT.md +46 -0
  22. package/claude/skills/write-human/SKILL.md +68 -0
  23. package/claude/skills/write-human/references/density.md +38 -0
  24. package/claude/skills/write-human/references/machine-tells.md +107 -0
  25. package/claude/skills/write-human/references/source-material.md +37 -0
  26. package/docs/agents/context-audit-checks.md +6 -0
  27. package/docs/agents/markdown-audit.md +7 -7
  28. package/docs/ai-workflow.md +1 -0
  29. package/docs/target-projects.md +1 -1
  30. package/governance/rules/claude/500-prose.md +7 -5
  31. package/governance/rules/claude/501-markdown.md +5 -4
  32. package/package.json +1 -1
  33. package/scripts/core/install-check.sh +1 -1
  34. package/src/commands/context.ts +54 -7
  35. package/src/commands/markdown.ts +2 -2
  36. package/src/comments/vocabulary.ts +1 -1
  37. package/src/context/audit.ts +89 -0
  38. package/src/markdown/bans.ts +2 -2
  39. package/src/standards/closure.ts +1 -1
  40. package/standards/bundled/issue.md +2 -2
  41. package/standards/bundled/pr.md +2 -2
  42. package/standards/bundled/snippets.md +2 -2
  43. package/standards/diagrams.md +5 -5
  44. package/standards/glossary.md +2 -2
  45. package/standards/groundwork.md +2 -2
  46. package/standards/index.md +1 -2
  47. package/standards/intake.md +2 -2
  48. package/standards/markdown.md +55 -6
  49. package/standards/memory.md +2 -2
  50. package/standards/plan.md +2 -2
  51. package/standards/publish.md +2 -2
  52. package/standards/readme.md +4 -4
  53. package/standards/skill.md +2 -2
  54. package/standards/standard.md +2 -2
  55. package/standards/teach.md +2 -2
  56. package/standards/versioning.md +2 -2
  57. package/standards/wireframes.md +3 -3
  58. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +2 -2
  59. package/standards/prose.md +0 -89
@@ -5,7 +5,7 @@ description: Running the audit over any markdown path, where its bans and checkp
5
5
 
6
6
  # Markdown audit
7
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`.
8
+ `aitk markdown audit [path...]` reports any markdown file against the attribute standard `markdown.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
9
 
10
10
  ```bash
11
11
  aitk markdown audit
@@ -29,9 +29,9 @@ A bare run measures every markdown file git lists, tracked plus untracked-and-no
29
29
 
30
30
  The three ban sets and all six checkpoints ship with the `aitk` package as data, in `src/markdown/bans.ts` and `src/markdown/structure.ts`. Every project is measured against the same sets whether or not it installed any standards, and no file has to resolve for a run to mean something.
31
31
 
32
- Reading them out of the standards per run was the original design. It put a parser contract on two documents authored for people, and `prose.md` had to carry a paragraph of its own warning an author that a one-word backticked example in a `- Do not use ` bullet would be lifted into a literal ban set and ban that word everywhere. A rule existing to protect a parser from the prose it parses is the argument for separating them.
32
+ Reading them out of the standards per run was the original design. It put a parser contract on a document authored for people, and the standard had to carry a paragraph of its own warning an author that a one-word backticked example in a `- Do not use ` bullet would be lifted into a literal ban set and ban that word everywhere. A rule existing to protect a parser from the prose it parses is the argument for separating them.
33
33
 
34
- `markdown.md` and `prose.md` still state every ban and every checkpoint, and a reader follows those rather than the code. Nothing compares the two, so a number moved in one place and left in the other drifts silently. Move both in the same change.
34
+ `markdown.md` still states every ban and every checkpoint, and a reader follows it rather than the code. Nothing compares the two, so a number moved in one place and left in the other drifts silently. Move both in the same change.
35
35
 
36
36
  The sets are closed rather than extensible, so a project cannot add a term by editing a file. What decides that is the measurement behind them: 21 terms across 483 markdown files report a clean exit, and every occurrence of a banned word in the corpus sits inside the ban list itself or inside an example demonstrating the ban. The set is a prior an author already knows rather than a filter that has caught anything, and enumeration cannot close the gap it aims at, since `just`, `allows`, and `very` carry honest uses no literal match separates.
37
37
 
@@ -45,7 +45,7 @@ A set shipped empty is reported rather than passed. It finds nothing and would e
45
45
 
46
46
  ### Bans
47
47
 
48
- 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 of the American examples that section lists.
48
+ Three closed sets report a hit: the characters `markdown.md` bans under `## Punctuation`, the single lowercase words it bans under `## Language`, and the British spellings of the American examples that section lists.
49
49
 
50
50
  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.
51
51
 
@@ -120,7 +120,7 @@ Rewrite the sentence rather than swapping the banned token for a near-synonym. T
120
120
 
121
121
  A code span clears the report too, since the ban scan walks around one, and it is the answer only where the token is genuinely an identifier under discussion. `## Code and identifiers` in `markdown.md` reserves the span for commands, API names, file paths, and identifiers, so backticking a quoted utterance spends one rule to satisfy another and leaves the corpus no cleaner.
122
122
 
123
- A hit the closed set cannot separate from correct prose is the case with no third option. `prose.md` bans vague qualifiers and lists the tokens those qualifiers happen to spell, so the temporal `just` reports as the vague one. The rule as written reaches neither, and rewriting the sentence is what the toolkit settled on over building an exemption path, for the reasons below.
123
+ A hit the closed set cannot separate from correct prose is the case with no third option. `markdown.md` bans vague qualifiers and lists the tokens those qualifiers happen to spell, so the temporal `just` reports as the vague one. The rule as written reaches neither, and rewriting the sentence is what the toolkit settled on over building an exemption path, for the reasons below.
124
124
 
125
125
  ### Where the rules are enforced
126
126
 
@@ -150,9 +150,9 @@ Masking took 7 of the weight-only paragraphs the checkpoint reported at 400 and
150
150
 
151
151
  ### How the ban count reached zero
152
152
 
153
- Eight word hits stood between the baseline and a gate, and only three carried the sense `prose.md` bans. `leverage` sat in the requirements worldview, `allows` in the claude stack reference, and one `just` was the vague qualifier in a skill body. Those three lost the qualifier rather than the word.
153
+ Eight word hits stood between the baseline and a gate, and only three carried the sense the standard bans. `leverage` sat in the requirements worldview, `allows` in the claude stack reference, and one `just` was the vague qualifier in a skill body. Those three lost the qualifier rather than the word.
154
154
 
155
- The other five were correct prose the closed set cannot separate from a violation. Four were the temporal `just`, meaning a moment ago, in phrases like the implementation `just` completed and the field the user `just` edited. The fifth quoted an anti-pattern a skill exists to forbid. `prose.md` bans vague qualifiers and lists the tokens those qualifiers happen to spell, so the rule as written reaches none of the five while the scan reaches all of them.
155
+ The other five were correct prose the closed set cannot separate from a violation. Four were the temporal `just`, meaning a moment ago, in phrases like the implementation `just` completed and the field the user `just` edited. The fifth quoted an anti-pattern a skill exists to forbid. `markdown.md` bans vague qualifiers and lists the tokens those qualifiers happen to spell, so the rule as written reaches none of the five while the scan reaches all of them.
156
156
 
157
157
  ### Why they were rewritten rather than exempted
158
158
 
@@ -281,6 +281,7 @@ This section is the corpus the coverage claim is measured against: every name `a
281
281
  | `aitk:toolkit-cli` | Before a sync or install, to learn what it overwrites, merges, or leaves alone |
282
282
  | `aitk:youtube-transcripts` | When a video transcript is wanted in the repo as context |
283
283
  | `aitk:claude-teach` | To learn a subject across sessions, in a workspace that holds the progress |
284
+ | `aitk:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
284
285
 
285
286
  Every row answers a question rather than marking a point in a project's life, so a phase above would send a reader to the wrong group.
286
287
 
@@ -88,7 +88,7 @@ Run `aitk tooling list --json` and `aitk gov list --json` to see the current cat
88
88
 
89
89
  `governance`, `standards`, and `wiki` are skippable:
90
90
 
91
- - `--skip governance`: leave `.claude/rules/` empty. Standards still install, so `.claude/standards/prose.md` lands with nothing pointing at it and no coding standard loads on a file match. The preview names any `--add` rules the skip drops, and the run prints the `aitk gov install <stack> <path>` command to add rules afterward, carrying those extras so one paste restores what the skip declined.
91
+ - `--skip governance`: leave `.claude/rules/` empty. Standards still install, so `.claude/standards/markdown.md` lands with nothing pointing at it and no coding standard loads on a file match. The preview names any `--add` rules the skip drops, and the run prints the `aitk gov install <stack> <path>` command to add rules afterward, carrying those extras so one paste restores what the skip declined.
92
92
  - `--skip standards`: leave standards out. The governance rules still reference `.claude/standards/`, so their authority lines resolve to nothing for a reader following the path. Toolkit skills are unaffected, since each falls back to the copy in its own plugin root. `aitk standards <name>` searches the corpus inside the CLI's own package behind both project roots, so it prints a standard in a project that skipped the install, and `aitk markdown audit` needs no standard at all, its ban sets and checkpoints shipping with the package as data. What the skip costs is the editable copy rather than the enforcement.
93
93
  - `--skip wiki`: skip the `.claude/wiki/` scaffold. A target that already carries a root `wiki/` keeps it, since the verb reports that folder rather than migrating it.
94
94
 
@@ -1,13 +1,15 @@
1
1
  ---
2
- description: Route markdown edits to the prose standard for voice, language, and frontmatter wording
2
+ description: Route markdown edits to the write-human skill for voice, rhythm, sentence construction, and information density
3
3
  paths:
4
4
  - '**/*.md'
5
5
  ---
6
6
 
7
- # Markdown prose standards
7
+ # Markdown voice standards
8
8
 
9
9
  ## Authority
10
10
 
11
- - Follow `.claude/standards/prose.md` for voice, language, and the wording of a `title` or `description`. It is the single source.
12
- - Read it before a substantial prose edit. Do not work the banned words from memory.
13
- - Punctuation, formatting, and file references are a separate topic. `501-markdown` routes them.
11
+ - Load the `aitk:write-human` skill for voice, rhythm, sentence construction, and information density. It is the single source for all four.
12
+ - Load it before drafting a passage, not after revising one.
13
+ - Report it rather than proceeding silently when the skill does not resolve.
14
+ - Do not work these rules from memory.
15
+ - Banned words, spellings, punctuation, formatting, and file references are a separate topic. `501-markdown` routes them.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Route markdown edits to the markdown standard for headings, lists, punctuation, and file references
2
+ description: Route markdown edits to the markdown standard for headings, lists, punctuation, banned words, and frontmatter wording
3
3
  paths:
4
4
  - '**/*.md'
5
5
  ---
@@ -8,6 +8,7 @@ paths:
8
8
 
9
9
  ## Authority
10
10
 
11
- - Follow `.claude/standards/markdown.md` for headings, paragraph and list structure, code spans, punctuation, emphasis, and file references. It is the single source.
12
- - Read it before a substantial markdown edit. Do not work the banned characters from memory.
13
- - Voice, language, and frontmatter wording are a separate topic. `500-prose` routes them.
11
+ - Follow `.claude/standards/markdown.md` for headings, paragraph and list structure, code spans, punctuation, emphasis, file references, the banned words and spellings, and the wording of a `title` or `description`. It is the single source.
12
+ - Read it before a substantial markdown edit. Do not work the banned words or characters from memory.
13
+ - Run `aitk markdown audit <path>` after the edit, and rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
14
+ - Voice, rhythm, and sentence construction are a separate topic. `500-prose` routes them.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.105.0",
4
+ "version": "0.107.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -79,7 +79,7 @@ log_step "Assert scaffold"
79
79
  # The snippets path has to name a slug the default preset still carries, since
80
80
  # init resolves snippets through `essentials`. Editing that preset without
81
81
  # editing this line fails the gate on a correct install.
82
- for path in "CLAUDE.md" ".claude/snippets/decision-help.md" ".claude/standards/prose.md" ".claude/standards/markdown.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
82
+ for path in "CLAUDE.md" ".claude/snippets/decision-help.md" ".claude/standards/skill.md" ".claude/standards/markdown.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
83
83
  ".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
84
84
  ".claude/rules/core/000-constitution.md"; do
85
85
  if [ ! -e "$TARGET_DIR/$path" ]; then
@@ -3,6 +3,10 @@ import type { Command } from 'commander'
3
3
  import {
4
4
  type EntryReport,
5
5
  governsContent,
6
+ type LengthCause,
7
+ type LengthFinding,
8
+ lengthFindings,
9
+ type LengthQuestion,
6
10
  LENGTH_CHECKPOINT,
7
11
  matchesSiblings,
8
12
  measureFolders,
@@ -200,6 +204,7 @@ async function runAudit(
200
204
  )
201
205
  const drift = gateOnly ? [] : await auditIndexes(folders)
202
206
  const sections = gateOnly ? [] : missingSections(root, folders, entries)
207
+ const length = gateOnly ? undefined : lengthFindings(entries)
203
208
 
204
209
  if (gateOnly) {
205
210
  reportGate(citations)
@@ -209,7 +214,7 @@ async function runAudit(
209
214
  reportCitations(citations, cited)
210
215
  reportReferenceForm(entries, folders)
211
216
  reportSections(sections, folders)
212
- reportLength(entries)
217
+ reportLength(length ?? [])
213
218
  reportTables(entries)
214
219
  reportProvenance(entries, folders)
215
220
  reportNarration(entries, folders, narration)
@@ -234,6 +239,16 @@ async function runAudit(
234
239
  unresolved: citations.unresolved,
235
240
  },
236
241
  entries,
242
+ // The join is published rather than left to a consumer, since deriving
243
+ // it from `entries` means restating which question the provenance count
244
+ // answers, and one wrong restatement is a cause reported against the
245
+ // wrong entry.
246
+ //
247
+ // Absent rather than empty under `--citations-only`, for the reason
248
+ // `checkpoints.narration` below carries. That mode measures no entry,
249
+ // so an empty array here reads as a corpus with nothing past the
250
+ // checkpoint rather than as a run that never looked.
251
+ length,
237
252
  missingSections: sections,
238
253
  indexDrift: drift,
239
254
  checkpoints: {
@@ -475,7 +490,32 @@ function reportSections(
475
490
  )
476
491
  }
477
492
 
478
- function reportLength(entries: readonly EntryReport[]): void {
493
+ /** How each question reads in the report, in the standard's own order. */
494
+ const QUESTION_LABEL: Record<LengthQuestion, string> = {
495
+ domain: 'one domain',
496
+ reproduced: 'reproduced content',
497
+ history: 'own history',
498
+ }
499
+
500
+ function readCause(cause: LengthCause): string {
501
+ const label = QUESTION_LABEL[cause.question]
502
+
503
+ if (cause.state === 'unanswered') return `${label}: open`
504
+ if (cause.state === 'no') return `${label}: no`
505
+
506
+ return `${label}: yes, ${plural(cause.markers ?? 0, 'marker')}`
507
+ }
508
+
509
+ /**
510
+ * Names each entry past the checkpoint with the three questions the standard
511
+ * asks of it, rather than a count a reader has to cross-reference by eye.
512
+ *
513
+ * The checkpoint is not a cap, so the legend says what the list is for. An
514
+ * entry that answers all three and is still long is a correct outcome under a
515
+ * standard stating there is no hard cap, and a run reporting success as a
516
+ * smaller count would have adopted the number the standard declines.
517
+ */
518
+ function reportLength(over: readonly LengthFinding[]): void {
479
519
  logStep('Length')
480
520
  logInfo(
481
521
  `Entries measure rendered lines at ${RENDER_WIDTH} columns, counting frontmatter and fenced blocks.`,
@@ -484,19 +524,26 @@ function reportLength(entries: readonly EntryReport[]): void {
484
524
  'A reference-heavy entry therefore ranks by its examples, which the depth check in `aitk markdown audit` excludes.',
485
525
  )
486
526
 
487
- const over = entries
488
- .filter((entry) => entry.lines > LENGTH_CHECKPOINT)
489
- .sort((a, b) => b.lines - a.lines)
490
-
491
527
  if (over.length === 0) {
492
528
  logInfo(`No entry past the ${LENGTH_CHECKPOINT}-line checkpoint.`)
493
529
  return
494
530
  }
495
531
 
496
532
  logWarn(`${over.length} past the ${LENGTH_CHECKPOINT}-line checkpoint`)
533
+ logInfo(
534
+ 'The checkpoint is not a cap. Each entry carries the three questions the standard asks past it, and the fix goes to whichever is true.',
535
+ )
536
+ logInfo(
537
+ 'Own history is answered from the provenance markers below. The other two are judgments no measure settles, so they stay open for a reader.',
538
+ )
497
539
  pipeOutput(
498
540
  over
499
- .map((entry) => `${entry.rel} ${entry.lines} rendered lines`)
541
+ .map(
542
+ (finding) =>
543
+ `${finding.rel} ${finding.lines} rendered lines\n ${finding.causes
544
+ .map(readCause)
545
+ .join(' ')}`,
546
+ )
500
547
  .join('\n'),
501
548
  )
502
549
  }
@@ -87,8 +87,8 @@ export function register(program: Command): void {
87
87
  '',
88
88
  'Bans and checkpoints ship with the aitk package rather than being read',
89
89
  'out of a standards file, so a project that installed no standards is',
90
- 'measured the same as one that did. markdown.md and prose.md still state',
91
- 'every rule for a reader. No folder has to resolve and no index.md has',
90
+ 'measured the same as one that did. markdown.md still states every rule',
91
+ 'for a reader. No folder has to resolve and no index.md has',
92
92
  'to exist, so .claude/rules/, governance/, and snippets/ are in reach.',
93
93
  '',
94
94
  'Examples:',
@@ -57,7 +57,7 @@ export function parseVocabulary(markdown: string): string[] | undefined {
57
57
  *
58
58
  * Reading the list out of the rule rather than hardcoding it is what keeps one
59
59
  * definition when the rule installs into a target, the same way
60
- * `.claude/hooks/standards-audit.sh` reads its word bans out of `prose.md`.
60
+ * `aitk markdown audit` owns one copy of the ban sets for every caller.
61
61
  */
62
62
  export async function loadVocabulary(root: string): Promise<Vocabulary> {
63
63
  for (const ruleRoot of RULE_ROOTS) {
@@ -166,6 +166,52 @@ export interface EntryReport {
166
166
  * exempt from owing sections rather than from being well formed.
167
167
  */
168
168
  readonly stub: boolean
169
+ /**
170
+ * Whether a content rule reached this entry, which is what parts an empty
171
+ * `provenance` list that was measured from one that was never scanned. The
172
+ * length finding reads it, since reporting a clean history for an entry
173
+ * outside the governed folder answers a question nothing asked.
174
+ */
175
+ readonly governed: boolean
176
+ }
177
+
178
+ /**
179
+ * The three questions `standards/context.md` asks of an entry past the
180
+ * checkpoint, in the order it states them.
181
+ *
182
+ * The standard calls no entry over the checkpoint wrong. It asks whether the
183
+ * entry still covers a single domain, whether it has filled with content `ls`
184
+ * or `--help` reproduces, and whether it has accumulated the history of its own
185
+ * changes, then directs a fix at whichever is true. A report naming the count
186
+ * alone leaves all three unasked, which is why the finding carries them.
187
+ */
188
+ export type LengthQuestion = 'domain' | 'reproduced' | 'history'
189
+
190
+ /**
191
+ * What the audit can say about one question for one entry.
192
+ *
193
+ * `unanswered` is a state rather than an omission. Two of the three questions
194
+ * are judgments no measure settles, and dropping them would read as an entry
195
+ * nothing found rather than one nothing checked.
196
+ */
197
+ export type QuestionState = 'yes' | 'no' | 'unanswered'
198
+
199
+ export interface LengthCause {
200
+ readonly question: LengthQuestion
201
+ readonly state: QuestionState
202
+ /**
203
+ * Markers behind a `yes`, and absent wherever nothing was counted. It cites
204
+ * the provenance finding rather than restating it, so the two sections of the
205
+ * report describe the same measurement once.
206
+ */
207
+ readonly markers?: number
208
+ }
209
+
210
+ export interface LengthFinding {
211
+ readonly rel: string
212
+ readonly lines: number
213
+ /** One entry per question in `LengthQuestion` order, never empty. */
214
+ readonly causes: readonly LengthCause[]
169
215
  }
170
216
 
171
217
  export interface SectionFinding {
@@ -481,9 +527,52 @@ export function measureEntry(
481
527
  bareReferences: bareReferences(lines, siblings),
482
528
  sections: governsContent ? declaredSections(lines) : [],
483
529
  stub: isStubSeed(source),
530
+ governed: governsContent,
484
531
  }
485
532
  }
486
533
 
534
+ /**
535
+ * Names each entry past the checkpoint with the standard's three questions
536
+ * answered as far as anything measures them.
537
+ *
538
+ * Only accumulated history is mechanical, and it is already measured by the
539
+ * provenance check, so this joins that count rather than counting again. The
540
+ * other two are read by a person: whether an entry still covers one domain is a
541
+ * judgment about its subject, and recognizing content `ls` or `--help`
542
+ * reproduces needs a reader who knows what those emit.
543
+ *
544
+ * An entry outside the governed folder has no measured question at all, since
545
+ * provenance is scoped to the standard stating it, and reporting `no` there
546
+ * would answer from a scan that never ran.
547
+ *
548
+ * Sorted longest first, which is the order the report already printed and the
549
+ * order the questions are worth asking in.
550
+ */
551
+ export function lengthFindings(
552
+ entries: readonly EntryReport[],
553
+ ): LengthFinding[] {
554
+ return entries
555
+ .filter((entry) => entry.lines > LENGTH_CHECKPOINT)
556
+ .sort((a, b) => b.lines - a.lines)
557
+ .map((entry) => ({
558
+ rel: entry.rel,
559
+ lines: entry.lines,
560
+ causes: [
561
+ { question: 'domain', state: 'unanswered' },
562
+ { question: 'reproduced', state: 'unanswered' },
563
+ historyCause(entry),
564
+ ] satisfies LengthCause[],
565
+ }))
566
+ }
567
+
568
+ function historyCause(entry: EntryReport): LengthCause {
569
+ if (!entry.governed) return { question: 'history', state: 'unanswered' }
570
+
571
+ return entry.provenance.length > 0
572
+ ? { question: 'history', state: 'yes', markers: entry.provenance.length }
573
+ : { question: 'history', state: 'no' }
574
+ }
575
+
487
576
  /**
488
577
  * Measures every entry in the audited folders. A generated `index.md` is not
489
578
  * among them, since its body is rewritten on every regen and no checkpoint
@@ -10,7 +10,7 @@ import type { BanSets } from '@/markdown/scan'
10
10
  const CHARACTERS = ['—', ';'] as const
11
11
 
12
12
  /**
13
- * Single lowercase words `prose.md` bans under `## Language`.
13
+ * Single lowercase words `markdown.md` bans under `## Language`.
14
14
  *
15
15
  * A multi-word ban is absent by the same test the character set applies. The
16
16
  * standard bans a pattern like `It's not X, it's Y` with a placeholder standing
@@ -34,7 +34,7 @@ const WORDS = [
34
34
  ] as const
35
35
 
36
36
  /**
37
- * British spellings of the American examples `prose.md` lists.
37
+ * British spellings of the American examples `markdown.md` lists.
38
38
  *
39
39
  * The set is carried whole rather than derived from a suffix rule, because a
40
40
  * suffix pattern run over prose produced 46 of the 58 false positives measured
@@ -29,7 +29,7 @@ const CITATION = /`([^`\n]+?\.md)`/g
29
29
  const DELEGATION_START = /^Does not govern:/
30
30
  const HEADING = /^#{1,6}\s/
31
31
 
32
- /** Accepts `prose` and `prose.md` alike, since the catalog lists both spellings. */
32
+ /** Accepts `skill` and `skill.md` alike, since the catalog lists both spellings. */
33
33
  export function normalizeName(raw: string): string {
34
34
  const name = raw.trim()
35
35
  return name.endsWith('.md') ? name : `${name}.md`
@@ -14,8 +14,8 @@ Does not govern:
14
14
 
15
15
  - Pull request title and body: `pr.md`
16
16
  - Whether a phase label may appear in issue text: `versioning.md`
17
- - Voice and banned words in issue prose: `prose.md`
18
- - Punctuation and formatting in issue prose: `markdown.md`
17
+ - Voice, rhythm, and sentence construction in issue prose: the `write-human` skill
18
+ - Punctuation, formatting, and banned words in issue prose: `markdown.md`
19
19
 
20
20
  ## Title
21
21
 
@@ -15,8 +15,8 @@ Does not govern:
15
15
  - Commit subject format, which shares the title form: `commit.md`
16
16
  - Branch naming: `branch.md`
17
17
  - Whether a phase label or a semver tag may appear in a title or body: `versioning.md`
18
- - Voice and banned words in pull request prose: `prose.md`
19
- - Punctuation and formatting in pull request prose: `markdown.md`
18
+ - Voice, rhythm, and sentence construction in pull request prose: the `write-human` skill
19
+ - Punctuation, formatting, and banned words in pull request prose: `markdown.md`
20
20
 
21
21
  ## Title
22
22
 
@@ -13,8 +13,8 @@ Governs a snippet file: what one is for, whether a prompt qualifies as one, how
13
13
  Does not govern:
14
14
 
15
15
  - Skill folders, which carry frontmatter, references, and scripts a snippet has none of: `skill.md`
16
- - Voice and word choice in snippet prose: `prose.md`
17
- - Punctuation and formatting in snippet prose: `markdown.md`
16
+ - Voice, rhythm, and sentence construction in snippet prose: the `write-human` skill
17
+ - Punctuation, formatting, and word choice in snippet prose: `markdown.md`
18
18
 
19
19
  ## What a snippet is
20
20
 
@@ -11,12 +11,12 @@ A diagram entry answers one question about the system with one or more Mermaid d
11
11
 
12
12
  ## Scope
13
13
 
14
- Governs per-kind diagram entries under `.claude/diagrams/`: which question each answers, the Mermaid source, the accessibility fields, and the explanation prose beneath. It states the voice for that prose, which is the yield `prose.md` grants a surface whose own standard sets one.
14
+ Governs per-kind diagram entries under `.claude/diagrams/`: which question each answers, the Mermaid source, the accessibility fields, and the explanation prose beneath. It states the voice for that prose, which is the yield the `write-human` skill grants a surface whose own standard sets one.
15
15
 
16
16
  Does not govern:
17
17
 
18
- - Language and word choice in explanation prose and node labels: `prose.md`, whose bans the yield does not lift
19
- - Punctuation and formatting in explanation prose: `markdown.md`, which the yield does not reach
18
+ - Rhythm and sentence construction in explanation prose: the `write-human` skill, whose rules the yield does not lift beyond voice
19
+ - Language, word choice, punctuation, and formatting in explanation prose and node labels: `markdown.md`, which the yield does not reach
20
20
  - The mechanism behind any component a diagram draws: `context.md`
21
21
  - UI layout, on-screen copy, and interaction intent: `wireframes.md`
22
22
  - The decision record a components diagram is drawn from: `architecture.md`
@@ -94,7 +94,7 @@ A second entry for one kind takes a suffixed name (`request-flow-admin.md`) and
94
94
  - Do not duplicate prose across entries. An entry that restates its neighbor has taken the neighbor's job.
95
95
  - The audience is mixed, so vocabulary runs as a gradient across the set. `System context` assumes no knowledge of the repository. `Deployment` may assume the reader has read the others.
96
96
 
97
- This section states the voice for the surface, which is what claims the yield `prose.md` grants to a surface whose own standard sets it. Explanation prose is pedagogical here and the default developer-facing voice does not apply. The yield covers voice alone. The language bans in `prose.md` stay in force, as do the punctuation and formatting rules in `markdown.md`, which grants no yield at all.
97
+ This section states the voice for the surface, which is what claims the yield the `write-human` skill grants to a surface whose own standard sets it. Explanation prose is pedagogical here and the default developer-facing voice does not apply. The yield covers voice alone. The rhythm and density rules that skill carries stay in force, as do the language bans, punctuation, and formatting in `markdown.md`, which grants no yield at all.
98
98
 
99
99
  ## Verification
100
100
 
@@ -121,7 +121,7 @@ Reference the context entry by path when a reader needs the mechanism. The diagr
121
121
  - `System context` has no named source signal beyond `.claude/REQUIREMENTS.md`, so nothing tells a session it went stale. Re-read it when the boundary or the set of external dependencies moves.
122
122
  - The `claude-docs` sweep watches two things and writes frontmatter only. It appends `stale` when a path an entry cites leaves the tree, and it stubs a kind when a diff adds the source signal that kind is drawn from. Diagram bodies and explanation paragraphs are off limits to it, because a change that removes a module does not carry the new correct shape of the picture.
123
123
  - That watch samples thinly. It sees the one or two paths an entry happened to cite and nothing else, so a change elsewhere leaves the entry looking current. `verified` is what covers the gap, and an entry whose date sits far behind the branch is due a read whether or not anything flagged it.
124
- - The explanation paragraphs around a Mermaid block are prose and follow `prose.md` and `markdown.md`. The fenced block itself is not, which is why a check scoped to prose is the wrong thing to rely on for what sits inside it.
124
+ - The explanation paragraphs around a Mermaid block are prose and follow `markdown.md` and the `write-human` skill. The fenced block itself is not, which is why a check scoped to prose is the wrong thing to rely on for what sits inside it.
125
125
  - The punctuation bans still apply to node and subgraph labels, and nothing checks them there. An em dash in a label passes every gate the repository has, so read the labels before shipping the entry.
126
126
 
127
127
  ## Template
@@ -15,8 +15,8 @@ Does not govern:
15
15
 
16
16
  - The folder a learning workspace lays out around its glossary, and the other files in it: `teach.md`
17
17
  - Which surface a glossary moves to once it leaves the material that produced it, which belongs to the surface driving that move
18
- - Voice and word choice: `prose.md`
19
- - Headings, punctuation, and file references: `markdown.md`
18
+ - Voice, rhythm, and sentence construction: the `write-human` skill
19
+ - Headings, punctuation, word choice, and file references: `markdown.md`
20
20
 
21
21
  ## What a working glossary looks like
22
22
 
@@ -18,8 +18,8 @@ Does not govern:
18
18
  - A dump of many findings filed by domain, each carrying its own verdict: `intake.md`
19
19
  - The feature plan a closed track feeds, and the contract its answer slots keep: `plan.md`
20
20
  - The task file a closing track writes, and the origin line pointing back at the folder: `tasks.md`
21
- - Voice and word choice: `prose.md`
22
- - Headings, punctuation, and file references: `markdown.md`
21
+ - Voice, rhythm, and sentence construction: the `write-human` skill
22
+ - Headings, punctuation, word choice, and file references: `markdown.md`
23
23
  - When a project opens a track at all, and the procedure that runs one, which belong to the surface driving it
24
24
 
25
25
  ## What a working track looks like
@@ -14,10 +14,9 @@ Reference docs for consistent authoring across the toolkit and target projects.
14
14
  - [Glossary reference](glossary.md): Frontmatter, entry shape, ordering, and the rules deciding which terms a glossary carries
15
15
  - [Groundwork reference](groundwork.md): Folder layout, reserved numbering, frontmatter and dating, required file contents, and conventions for a measurement track
16
16
  - [Intake reference](intake.md): Folder layout, reserved index number, frontmatter and dating, the item template, the answer contract, and retrieval
17
- - [Markdown reference](markdown.md): Headings, paragraph and list structure, code spans, the date form, punctuation, emphasis, and file references
17
+ - [Markdown reference](markdown.md): Headings, paragraph and list structure, code spans, the date form, punctuation, emphasis, file references, banned words, and frontmatter wording
18
18
  - [Memory reference](memory.md): Filename and type prefix, frontmatter, the body shape per type, links between entries, and the lifecycle from write to retire
19
19
  - [Plan reference](plan.md): Filename and slug, required sections, the suggested-and-answer contract, and the lifecycle from the live folder to the archive
20
- - [Prose reference](prose.md): Voice, language, what prose may claim, and frontmatter wording for reference markdown
21
20
  - [Publish reference](publish.md): Scan an author runs against finished text, the cross-reference form each destination takes, and the response to an unreadable source
22
21
  - [Readme reference](readme.md): Readme voice, structure, and content conventions
23
22
  - [Requirements reference](requirements.md): Shape and content rules for .claude/REQUIREMENTS.md
@@ -18,8 +18,8 @@ Does not govern:
18
18
  - One question measured in depth before anyone can plan against it: `groundwork.md`
19
19
  - The feature plan a promoted item feeds, and the inverted answer contract it keeps: `plan.md`
20
20
  - The task file promoting an item onto the board, and the origin line pointing back at the folder: `tasks.md`
21
- - Voice and word choice: `prose.md`
22
- - Headings, punctuation, and file references: `markdown.md`
21
+ - Voice, rhythm, and sentence construction: the `write-human` skill
22
+ - Headings, punctuation, word choice, and file references: `markdown.md`
23
23
  - Which findings belong in a dump at all, and the procedure that files one, which belong to the surface driving it
24
24
 
25
25
  ## What a working intake looks like
@@ -1,22 +1,28 @@
1
1
  ---
2
2
  title: Markdown reference
3
- description: Headings, paragraph and list structure, code spans, the date form, punctuation, emphasis, and file references
3
+ description: Headings, paragraph and list structure, code spans, the date form, punctuation, emphasis, file references, banned words, and frontmatter wording
4
4
  ---
5
5
 
6
6
  # Markdown reference
7
7
 
8
- Applies to markdown reference docs, READMEs, and inline documentation in repos. These are mechanics rather than voice, so no surface yields them. A surface stating its own voice claims that yield from `prose.md` and formats by this file regardless.
8
+ Applies to markdown reference docs, READMEs, and inline documentation in repos. Every rule here is a fact a scan can settle rather than a judgment, so no surface yields any of them. A surface stating its own voice claims that yield from the voice guidance and formats and spells by this file regardless.
9
9
 
10
10
  ## Scope
11
11
 
12
- Governs the markdown mechanics of every markdown file: headings, paragraph and list structure, code spans and fences, the form a date takes, punctuation, emphasis, and file references. It is an attribute standard rather than a document-type one, so it applies over documents whose shape another standard sets, and it carries no template because mechanics are written across every document and have no shape of their own.
12
+ Governs what a check can decide about a markdown file: headings, paragraph and list structure, code spans and fences, the form a date takes, punctuation, emphasis, file references, the closed-set word and spelling bans, what prose may claim about its sources, and the wording of a catalog title and description. It is an attribute standard rather than a document-type one, so it applies over documents whose shape another standard sets, and it carries no template because these rules are written across every document and have no shape of their own.
13
+
14
+ The two frontmatter fields it reaches are `title` and `description`. They are named here rather than in the statement above, since a backticked token in a scope statement's first sentence is published as the standard's jurisdiction.
15
+
16
+ The split with the voice guidance is what reads the rule rather than what the rule covers. Every ban below ships as data `aitk markdown audit` and the installed audit hook both read, so a violation is measured on every run. Cadence, rhythm, and information density are judgments a reader settles, and those travel in the `write-human` skill, which a markdown edit routes to.
13
17
 
14
18
  Does not govern:
15
19
 
16
- - Voice, word choice, what prose may claim, and the wording of a `title` or `description`: `prose.md`
20
+ - Voice, rhythm, sentence construction, and information density, which the `write-human` skill carries
17
21
  - What sections a document has, or what belongs in each: the standard for that document type
22
+ - Which frontmatter fields a document carries, which is that standard's own subject. This file governs the wording of a `title` and a `description` and nothing else about them.
18
23
  - The text inside a fenced block, which follows the conventions of its own language rather than these
19
- - The scan that applies the punctuation bans to finished text on its way out: `publish.md`
24
+ - Phase-label and semver discipline: `versioning.md`
25
+ - The scan that applies these bans to finished text on its way out: `publish.md`
20
26
  - Whether a pull request or issue number is backticked, which turns on where the text is published rather than on the text: `publish.md`
21
27
 
22
28
  ## Headings
@@ -58,7 +64,30 @@ Does not govern:
58
64
  - Do not use em dashes (`—`) or semicolons (`;`). Rewrite or restructure the sentence to avoid them.
59
65
  - Do not use parenthetical asides in prose (`the config (which is optional) controls...`). Split into its own sentence or drop it. Parentheses in rule definitions for grouping examples are fine.
60
66
 
61
- The closed-set word bans sit in `prose.md` under `## Language` rather than here, because a banned word is a word-choice rule and these are character rules. A surface applying both reads both files.
67
+ ## Language
68
+
69
+ - Use American English spelling. Prefer `-ize` over `-ise`, `-or` over `-our`, `-er` over `-re` (`organize`, `analyze`, `summarize`, `recognize`, `behavior`, `color`, `center`)
70
+ - Do not use marketing buzzwords (`seamless`, `robust`, `powerful`, `revolutionary`, `enhanced`, `allows`, `leverage`)
71
+ - Do not use vague qualifiers (`simply`, `just`, `easily`, `quickly`, `very`, `really`)
72
+ - Open a sentence with its subject and action, not filler (`Note that`, `Basically`), a hollow connective (`That being said`, `It's worth noting`), or a gerund windup (`Leveraging the API...`). Substantive transitions that carry a real relationship are fine.
73
+ - Do not use the negative parallelism pattern (`It's not X, it's Y`, `not because X, but because Y`)
74
+ - Do not pad verb phrases or delay the action. Write the shortest form (`in order to` → `to`, `ensure that X is set` → `set X`, `By doing X, you can Y` → state Y directly).
75
+ - Do not address the reader as a participant (`Let's`, `Here's`, `Here are`). State the content directly.
76
+ - Commit to a position. Do not hedge in clusters (`It might be worth considering`) or use false balance (`While X is true, Y is also important`). Recommend, or state the tradeoff.
77
+ - Do not inflate significance. State what a thing does rather than calling it `a major milestone` or `a turning point for the field`.
78
+ - Do not name a person, company, or product to borrow its authority. Name a source only where the claim turns on who made it.
79
+ - Do not attribute a claim to an unnamed authority (`experts say`, `studies show`, `it is widely believed`). Name the source or cut the claim.
80
+ - Do not introduce a fact, name, date, or citation the source does not carry when rewriting existing text. A rewrite changes wording and never claims.
81
+
82
+ The word bans and the character bans sit under one file because one command reads both. `aitk markdown audit` ships them as package data, so a project that installed no standards is measured the same as one that did, and this section states them for a reader rather than for the parser.
83
+
84
+ ## Frontmatter descriptions
85
+
86
+ When frontmatter carries a short `title` or `description` used for catalog display:
87
+
88
+ - `title`: sentence case, identifies the file uniquely against its siblings in the same catalog. Proper nouns retain their casing. No trailing period.
89
+ - `description`: sentence case, names the specific topics covered so a reader can decide whether to open the file. Lead with concrete subjects, strip filler like "guide to", "overview of", or "documentation about". No trailing period, no leading article (`the`, `a`).
90
+ - Do not mechanically reuse the H1 as the description.
62
91
 
63
92
  ## Emphasis and dividers
64
93
 
@@ -83,3 +112,23 @@ Good: See `.claude/context/retrieval.md` for the retrieval flow.
83
112
  Bad: Read [docs/development.md](docs/development.md) before contributing.
84
113
  Good: Read the [development guide](docs/development.md) before contributing.
85
114
  ```
115
+
116
+ ```markdown
117
+ Bad: In order to configure the server, you'll need to ensure that the port is set.
118
+ Good: Set `port` in the server config.
119
+ ```
120
+
121
+ ```markdown
122
+ Bad: It's not just a cache. It's a system for intelligent memory management.
123
+ Good: The cache is an LRU store. It evicts the least-recently-used entry when full.
124
+ ```
125
+
126
+ ```markdown
127
+ Bad: Leveraging the retry mechanism, developers can build more resilient integrations.
128
+ Good: Use the `retry` option for failed webhooks. Set `maxRetries` to 3.
129
+ ```
130
+
131
+ ```markdown
132
+ Bad: It might be worth considering whether to enable caching.
133
+ Good: Enable caching for read-heavy endpoints. Skip it for writes.
134
+ ```