@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.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-address-review/SKILL.md +4 -3
- package/claude/skills/claude-design-extract/SKILL.md +3 -3
- package/claude/skills/claude-docs/SKILL.md +1 -1
- package/claude/skills/claude-memory-capture/SKILL.md +2 -2
- package/claude/skills/claude-pr-review/SKILL.md +1 -1
- package/claude/skills/claude-standards-audit/SKILL.md +8 -6
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/claude/skills/create-snippet/SKILL.md +2 -2
- package/claude/skills/create-snippet/references/snippets.md +2 -2
- package/claude/skills/create-standard/SKILL.md +2 -2
- package/claude/skills/docs-sync/SKILL.md +2 -2
- package/claude/skills/git-issue/SKILL.md +2 -2
- package/claude/skills/git-issue/references/issue.md +2 -2
- package/claude/skills/git-pr/SKILL.md +2 -2
- package/claude/skills/git-pr/references/pr.md +2 -2
- package/claude/skills/git-split/references/pr.md +2 -2
- package/claude/skills/git-stage/SKILL.md +2 -2
- package/claude/skills/migration-standards/SKILL.md +1 -1
- package/claude/skills/setup-indexes/SKILL.md +1 -1
- package/claude/skills/write-human/REQUIREMENT.md +46 -0
- package/claude/skills/write-human/SKILL.md +68 -0
- package/claude/skills/write-human/references/density.md +38 -0
- package/claude/skills/write-human/references/machine-tells.md +107 -0
- package/claude/skills/write-human/references/source-material.md +37 -0
- package/docs/agents/context-audit-checks.md +6 -0
- package/docs/agents/markdown-audit.md +7 -7
- package/docs/ai-workflow.md +1 -0
- package/docs/target-projects.md +1 -1
- package/governance/rules/claude/500-prose.md +7 -5
- package/governance/rules/claude/501-markdown.md +5 -4
- package/package.json +1 -1
- package/scripts/core/install-check.sh +1 -1
- package/src/commands/context.ts +54 -7
- package/src/commands/markdown.ts +2 -2
- package/src/comments/vocabulary.ts +1 -1
- package/src/context/audit.ts +89 -0
- package/src/markdown/bans.ts +2 -2
- package/src/standards/closure.ts +1 -1
- package/standards/bundled/issue.md +2 -2
- package/standards/bundled/pr.md +2 -2
- package/standards/bundled/snippets.md +2 -2
- package/standards/diagrams.md +5 -5
- package/standards/glossary.md +2 -2
- package/standards/groundwork.md +2 -2
- package/standards/index.md +1 -2
- package/standards/intake.md +2 -2
- package/standards/markdown.md +55 -6
- package/standards/memory.md +2 -2
- package/standards/plan.md +2 -2
- package/standards/publish.md +2 -2
- package/standards/readme.md +4 -4
- package/standards/skill.md +2 -2
- package/standards/standard.md +2 -2
- package/standards/teach.md +2 -2
- package/standards/versioning.md +2 -2
- package/standards/wireframes.md +3 -3
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +2 -2
- 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
|
|
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
|
|
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`
|
|
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
|
|
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. `
|
|
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
|
|
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. `
|
|
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
|
|
package/docs/ai-workflow.md
CHANGED
|
@@ -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
|
|
package/docs/target-projects.md
CHANGED
|
@@ -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/
|
|
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
|
|
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
|
|
7
|
+
# Markdown voice standards
|
|
8
8
|
|
|
9
9
|
## Authority
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
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
|
|
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,
|
|
12
|
-
- Read it before a substantial markdown edit. Do not work the banned characters from memory.
|
|
13
|
-
-
|
|
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
|
@@ -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/
|
|
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
|
package/src/commands/context.ts
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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(
|
|
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
|
}
|
package/src/commands/markdown.ts
CHANGED
|
@@ -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
|
|
91
|
-
'
|
|
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
|
-
*
|
|
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) {
|
package/src/context/audit.ts
CHANGED
|
@@ -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
|
package/src/markdown/bans.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { BanSets } from '@/markdown/scan'
|
|
|
10
10
|
const CHARACTERS = ['—', ';'] as const
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Single lowercase words `
|
|
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 `
|
|
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
|
package/src/standards/closure.ts
CHANGED
|
@@ -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 `
|
|
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
|
|
18
|
-
- Punctuation and
|
|
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
|
|
package/standards/bundled/pr.md
CHANGED
|
@@ -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
|
|
19
|
-
- Punctuation and
|
|
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
|
|
17
|
-
- Punctuation and
|
|
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
|
|
package/standards/diagrams.md
CHANGED
|
@@ -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 `
|
|
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
|
-
-
|
|
19
|
-
-
|
|
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 `
|
|
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 `
|
|
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
|
package/standards/glossary.md
CHANGED
|
@@ -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
|
|
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
|
|
package/standards/groundwork.md
CHANGED
|
@@ -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
|
|
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
|
package/standards/index.md
CHANGED
|
@@ -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
|
|
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
|
package/standards/intake.md
CHANGED
|
@@ -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
|
|
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
|
package/standards/markdown.md
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
|
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,
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
+
```
|