@erclx/canon 4.16.0 → 4.18.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-diagram/SKILL.md +2 -2
- package/docs/agents/index.md +1 -1
- package/docs/agents/standards-audit.md +9 -7
- package/governance/rules/claude/502-mermaid.md +14 -0
- package/governance/rules/claude/560-diagrams.md +3 -2
- package/package.json +1 -1
- package/src/gate/measures.ts +88 -0
- package/src/gate/stages.ts +12 -0
- package/src/standards/audit.ts +17 -3
- package/standards/diagrams.md +4 -29
- package/standards/index.md +1 -0
- package/standards/issue.md +23 -3
- package/standards/mermaid.md +64 -0
|
@@ -24,7 +24,7 @@ Read these from the project root in parallel, skipping any that do not exist:
|
|
|
24
24
|
|
|
25
25
|
Do not recurse speculatively.
|
|
26
26
|
|
|
27
|
-
Follow `${CLAUDE_SKILL_DIR}/../../standards/diagrams.md` for frontmatter, entry kinds, layout, budgets, accessibility,
|
|
27
|
+
Follow `${CLAUDE_SKILL_DIR}/../../standards/diagrams.md` for frontmatter, entry kinds, and explanation rules. Follow `${CLAUDE_SKILL_DIR}/../../standards/mermaid.md` for what goes inside the fence: layout, budgets, accessibility, labels, and verification.
|
|
28
28
|
|
|
29
29
|
### Migrating a pre-split flat file
|
|
30
30
|
|
|
@@ -124,7 +124,7 @@ When the render fails for any reason (no browser engine, no network, no package
|
|
|
124
124
|
|
|
125
125
|
## Step 6: read the renders back
|
|
126
126
|
|
|
127
|
-
Read each PNG and judge the picture against what the entry means to say. Apply the verification properties in
|
|
127
|
+
Read each PNG and judge the picture against what the entry means to say. Apply the verification properties in `${CLAUDE_SKILL_DIR}/../../standards/mermaid.md`.
|
|
128
128
|
|
|
129
129
|
Fix the source and re-render. Stop after two correction passes on an entry.
|
|
130
130
|
|
package/docs/agents/index.md
CHANGED
|
@@ -38,7 +38,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
38
38
|
- [Sessions](sessions.md): Resolving live peer sessions to the worktree and branch each holds, reading which row is the caller, the liveness confidence field, and what each session surface can see
|
|
39
39
|
- [Skill audit](skills-audit.md): Measuring both skill corpora against standards/skill.md, the checks it reads, the requirement gate that is the only failing one, and the drift verb that names bodies rewritten since a ref
|
|
40
40
|
- [Citation reach](skills-reach.md): Reporting the skill bodies that cite a path no target project receives, which corpus the verb reads, the ownership key that decides what counts, the one-word qualifier that marks a citation as decided, and why the verb reports instead of gating
|
|
41
|
-
- [Standard success criteria](standards-audit.md): Reading the corpus against the
|
|
41
|
+
- [Standard success criteria](standards-audit.md): Reading the corpus against the success-criterion gate, the two headings it accepts, why the check scopes to arrival rather than the whole corpus, and the exit codes it sets
|
|
42
42
|
- [State-scoped risk](state-scoped-risk.md): Reading committed state rather than an arriving change, the shipped-tree corpus the secret scan reads, what it keys on and how a deliberate value is exempted, the advisory check and its network failure mode, and why one gates while the other reports
|
|
43
43
|
- [Superseded values](superseded.md): Reading where the tree still asserts a value a changed convention no longer produces, why the sweep keys on the value rather than the file, the family stem behind a templated citation, the exemption marker, the blind spots it cannot reach, and why it reports rather than gates
|
|
44
44
|
- [Targets](targets.md): The projects this toolkit installed into, the record the install writes against the sweep that backs it, what bounds each answer, and the cross-target pull request read
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Standard success criteria
|
|
3
|
-
description: Reading the corpus against the
|
|
3
|
+
description: Reading the corpus against the success-criterion gate, the two headings it accepts, why the check scopes to arrival rather than the whole corpus, and the exit codes it sets
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Standard success criteria
|
|
7
7
|
|
|
8
|
-
`canon standards audit` reads the corpus at `standards/` and reports which files
|
|
8
|
+
`canon standards audit` reads the corpus at `standards/` and reports which files state a success criterion against which do not, per `standards/standard.md`. It fails only on a standard new to the current branch, never on one already short the section.
|
|
9
|
+
|
|
10
|
+
Two headings count, at any casing. `## Success criterion` is the wording that standard states the rule under, and `## What a working <document type> looks like` is the wording its template prescribes for the section itself. Most of the corpus writes the templated form, so accepting the rule's wording alone would refuse a conforming standard.
|
|
9
11
|
|
|
10
12
|
```bash
|
|
11
13
|
canon standards audit
|
|
@@ -25,11 +27,11 @@ canon standards audit --arrivals-only
|
|
|
25
27
|
|
|
26
28
|
## Exit codes and refusals
|
|
27
29
|
|
|
28
|
-
| Code | Meaning
|
|
29
|
-
| ---- |
|
|
30
|
-
| `0` | every arriving standard carries the section
|
|
31
|
-
| `1` | refused, with `reason` naming the cause
|
|
32
|
-
| `2` | a standard new to this branch
|
|
30
|
+
| Code | Meaning |
|
|
31
|
+
| ---- | ---------------------------------------------------------------------- |
|
|
32
|
+
| `0` | every arriving standard carries the section |
|
|
33
|
+
| `1` | refused, with `reason` naming the cause |
|
|
34
|
+
| `2` | a standard new to this branch states no criterion under either heading |
|
|
33
35
|
|
|
34
36
|
A project authoring no standards refuses with `no-corpus`, the ordinary state of most targets, the same absence `canon claude skills audit` reads as its own `no-corpus`.
|
|
35
37
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route a drafted Mermaid fence to the mermaid standard for layout, budgets, accessibility, labels, and render verification
|
|
3
|
+
paths:
|
|
4
|
+
- '**/*.md'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Mermaid diagram standards
|
|
8
|
+
|
|
9
|
+
## Authority
|
|
10
|
+
|
|
11
|
+
- Apply this rule only when the edit drafts or revises a Mermaid fence. Skip it on a markdown edit carrying no diagram.
|
|
12
|
+
- Follow the mermaid standard for direction and layout, node and edge budgets, the accessibility fields, punctuation inside labels, and how a render is verified. It is the single source. Read it with `canon standards mermaid`.
|
|
13
|
+
- Read it before drafting the fence. Do not work the layout or the budgets from memory.
|
|
14
|
+
- Which diagram a document carries and what question it answers is a separate topic. `560-diagrams` routes it.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Route .canon/diagrams edits to the diagrams standard for
|
|
2
|
+
description: Route .canon/diagrams edits to the diagrams standard for entry kinds, frontmatter, and explanation prose
|
|
3
3
|
paths:
|
|
4
4
|
- '.canon/diagrams/**'
|
|
5
5
|
- '.claude/DIAGRAMS.md'
|
|
@@ -9,7 +9,8 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
## Authority
|
|
11
11
|
|
|
12
|
-
- Follow the diagrams standard for
|
|
12
|
+
- Follow the diagrams standard for which question an entry answers, the entry kinds and their source signals, the frontmatter, and the explanation prose beneath the fence. It is the single source. Read it with `canon standards diagrams`.
|
|
13
|
+
- Layout, budgets, accessibility, labels, and render verification inside the fence are a separate topic. `502-mermaid` routes them to `mermaid.md`.
|
|
13
14
|
- A diagram entry carries structure and flow, not implementation. Read the standard before adding or revising a kind.
|
|
14
15
|
|
|
15
16
|
## Scope
|
package/package.json
CHANGED
package/src/gate/measures.ts
CHANGED
|
@@ -164,6 +164,94 @@ export const unreferencedRules: Measure = async (ctx) => {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/**
|
|
168
|
+
* The files the sweep would rewrite, each with its own count, taken from the
|
|
169
|
+
* `paths` array the record carries beside the total.
|
|
170
|
+
*
|
|
171
|
+
* Every field is tested rather than trusted. The record reaches here as parsed
|
|
172
|
+
* JSON rather than as a type the compiler checked, so a shape that moved
|
|
173
|
+
* upstream drops the entries it can no longer read and leaves the count that
|
|
174
|
+
* was read from a field of its own standing.
|
|
175
|
+
*/
|
|
176
|
+
function citedPaths(record: { paths?: unknown } | undefined): string[] {
|
|
177
|
+
if (!Array.isArray(record?.paths)) return []
|
|
178
|
+
|
|
179
|
+
return record.paths.flatMap((entry) => {
|
|
180
|
+
const cited = entry as { path?: unknown; rewritten?: unknown }
|
|
181
|
+
if (typeof cited.path !== 'string') return []
|
|
182
|
+
return typeof cited.rewritten === 'number'
|
|
183
|
+
? [`${cited.path} (${cited.rewritten})`]
|
|
184
|
+
: [cited.path]
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* A second run of the records move should rewrite nothing, and the count is
|
|
190
|
+
* only knowable once the folders themselves have landed.
|
|
191
|
+
*
|
|
192
|
+
* `moves` empty means every record folder already sits at `.canon/`, so any
|
|
193
|
+
* citation the sweep would still rewrite is one the move left stale, which is
|
|
194
|
+
* the defect this stage exists to catch. Where `moves` is nonempty the tree has
|
|
195
|
+
* not migrated at all and a nonzero rewrite count is the verb describing its
|
|
196
|
+
* own first pass, so the reading is reported and never failed on.
|
|
197
|
+
*
|
|
198
|
+
* Exit `0` is a tree with nothing to do and exit `2` is a plan drawn without
|
|
199
|
+
* `--write`, so both read a tree and both carry a record. Every other exit is a
|
|
200
|
+
* refusal that planned nothing, which is unmeasured for the reason the markdown
|
|
201
|
+
* stage treats its own refusal exit so.
|
|
202
|
+
*/
|
|
203
|
+
export const recordIdempotence: Measure = async (ctx) => {
|
|
204
|
+
const run = await ctx.cli(['migrate', 'records', '--json'])
|
|
205
|
+
|
|
206
|
+
if (run.exitCode !== 0 && run.exitCode !== 2) {
|
|
207
|
+
return {
|
|
208
|
+
emissions: [],
|
|
209
|
+
unmeasured: `The records sweep refused (exit ${run.exitCode}) and planned nothing.`,
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const record = parseJson(run.stdout) as
|
|
214
|
+
| { moves?: unknown; rewritten?: unknown; paths?: unknown }
|
|
215
|
+
| undefined
|
|
216
|
+
const moves = record?.moves
|
|
217
|
+
const rewritten = record?.rewritten
|
|
218
|
+
|
|
219
|
+
if (!Array.isArray(moves) || typeof rewritten !== 'number') {
|
|
220
|
+
return {
|
|
221
|
+
emissions: [],
|
|
222
|
+
unmeasured:
|
|
223
|
+
'The records sweep carried no plan, so the stage read no count. Run bun src/cli.ts migrate records --json.',
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (moves.length > 0) {
|
|
228
|
+
return {
|
|
229
|
+
emissions: [
|
|
230
|
+
info(
|
|
231
|
+
`${moves.length} record folder(s) still at the old root, with ${rewritten} citation(s) that move with them`,
|
|
232
|
+
),
|
|
233
|
+
],
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (rewritten > 0) {
|
|
238
|
+
return {
|
|
239
|
+
// The payload already names every file, so listing them here is what
|
|
240
|
+
// separates a count a reader has to go and reproduce from a remedy they
|
|
241
|
+
// can act on. A malformed `paths` costs the list and not the finding,
|
|
242
|
+
// since the count above it was read from a field of its own.
|
|
243
|
+
emissions: citedPaths(record).map((path) => warn(path)),
|
|
244
|
+
failure: `The records are at .canon/ and ${rewritten} citation(s) still name the old root, so a second run of canon migrate records would rewrite them. Repoint each one, or mark it canon-keep-record-root where the sentence has to keep the old spelling.`,
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
emissions: [
|
|
250
|
+
info('Records at .canon/, and a re-run of the move rewrites nothing'),
|
|
251
|
+
],
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
167
255
|
/**
|
|
168
256
|
* A banned character, word, or spelling is a fact rather than a threshold, so
|
|
169
257
|
* it fails the push while bullet, paragraph, and depth weight stay advisory.
|
package/src/gate/stages.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
markdownBans,
|
|
5
5
|
type Measure,
|
|
6
6
|
pluginManifests,
|
|
7
|
+
recordIdempotence,
|
|
7
8
|
sandboxCoverage,
|
|
8
9
|
seedStandards,
|
|
9
10
|
standardCriteria,
|
|
@@ -337,6 +338,17 @@ export const STAGES: readonly Stage[] = [
|
|
|
337
338
|
],
|
|
338
339
|
success: 'Rule citations resolve',
|
|
339
340
|
},
|
|
341
|
+
{
|
|
342
|
+
// A citation naming the old record root resolves to nothing once the
|
|
343
|
+
// folders have moved, and the sweep that would repoint it only runs when a
|
|
344
|
+
// person calls it. Reading its plan back is what turns a silent stale
|
|
345
|
+
// citation into a stopped push, and it sits with the two citation stages
|
|
346
|
+
// above rather than at the end of the file because it answers their
|
|
347
|
+
// question about a root rather than a path.
|
|
348
|
+
id: 'record-idempotence',
|
|
349
|
+
label: 'Record idempotence',
|
|
350
|
+
checks: [{ kind: 'measure', measure: recordIdempotence }],
|
|
351
|
+
},
|
|
340
352
|
{
|
|
341
353
|
id: 'markdown-bans',
|
|
342
354
|
label: 'Markdown bans',
|
package/src/standards/audit.ts
CHANGED
|
@@ -5,11 +5,25 @@ import { gitEnv } from '@/git-env'
|
|
|
5
5
|
import { resolveBaseRef } from '@/git-files'
|
|
6
6
|
import { INDEX_FILE, standardsSourceDir } from '@/standards/read'
|
|
7
7
|
|
|
8
|
-
/** Returned when a standard new to this branch
|
|
8
|
+
/** Returned when a standard new to this branch states no success criterion under either heading `CRITERION_HEADING` accepts, the gating check. */
|
|
9
9
|
export const EXIT_MISSING_CRITERION = 2
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Matched at any casing, level-2 only, in either heading the corpus writes a
|
|
13
|
+
* criterion under.
|
|
14
|
+
*
|
|
15
|
+
* `standards/standard.md` states the rule under `## Success criterion` and
|
|
16
|
+
* templates the section itself as `## What a working <document type> looks
|
|
17
|
+
* like`, and the template wins where the two disagree, which that file says in
|
|
18
|
+
* as many words. Reading the rule group's own heading as the one to match is
|
|
19
|
+
* what the first spelling here did, and no standard in the corpus carries a
|
|
20
|
+
* criterion under it: 12 of 28 use the templated form and `standard.md` alone
|
|
21
|
+
* carries the literal words, over its rules about criteria rather than over its
|
|
22
|
+
* own. Nothing caught that, because the gate reads a standard new since the
|
|
23
|
+
* merge base and none had arrived since it shipped.
|
|
24
|
+
*/
|
|
25
|
+
const CRITERION_HEADING =
|
|
26
|
+
/^##\s+(?:success criterion|what a working .+ looks like)\s*$/im
|
|
13
27
|
|
|
14
28
|
/**
|
|
15
29
|
* The reasons an audit produces no reading. `no-corpus` is the ordinary state
|
package/standards/diagrams.md
CHANGED
|
@@ -11,10 +11,11 @@ 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 `.canon/diagrams/`: which question each answers,
|
|
14
|
+
Governs per-kind diagram entries under `.canon/diagrams/`: which question each answers, which kinds exist and what each is drawn from, the frontmatter, and the explanation prose beneath the fence. 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
|
+
- How the drawing inside the fence is laid out, budgeted, made accessible, and verified against its render: `mermaid.md`
|
|
18
19
|
- Rhythm and sentence construction in explanation prose: the `write-human` skill, whose rules the yield does not lift beyond voice
|
|
19
20
|
- Language, word choice, punctuation, and formatting in explanation prose and node labels: `markdown.md`, which the yield does not reach
|
|
20
21
|
- The mechanism behind any component a diagram draws: `context.md`
|
|
@@ -63,28 +64,9 @@ The kinds drift at rates spanning roughly an order of magnitude, which is why th
|
|
|
63
64
|
|
|
64
65
|
A second entry for one kind takes a suffixed name (`request-flow-admin.md`) and repeats the kind's `category` verbatim, which is what the grouping field is for. One entry per kind is the ordinary case, so most catalogs show one entry under each heading.
|
|
65
66
|
|
|
66
|
-
## Layout
|
|
67
|
-
|
|
68
|
-
- Declare `flowchart TB` by default. Mermaid ignores a subgraph's direction whenever that subgraph links outward, and an architecture diagram links across its subgraphs as the normal case, so top-bottom is a declaration rather than a guarantee.
|
|
69
|
-
- Restructure a diagram that renders diagonal or left-to-right. Repeating the direction keyword does not fix it.
|
|
70
|
-
- Render a context, component, or pipeline diagram taller than wide. A `sequenceDiagram` is wide by construction and is exempt.
|
|
71
|
-
- Do not let independent nodes render in a row. A row of siblings reads as a sequential chain and asserts a pipeline the system does not have.
|
|
72
|
-
- Do not converge many edges on one node from one side. A crossing bundle is unreadable whatever it encodes.
|
|
73
|
-
- Keep node labels short. Three or four words max. Detail goes in the paragraph below the diagram.
|
|
74
|
-
- Use `<br/>` for a second short line on a node when the label is two ideas, never for a sentence.
|
|
75
|
-
- Subgraphs are for grouping unrelated lanes such as offline versus online or browser versus server. Do not subgraph a single linear flow.
|
|
76
|
-
|
|
77
67
|
## Budgets
|
|
78
68
|
|
|
79
|
-
- Hold a diagram to roughly 5 to 10 nodes. Split it past 15.
|
|
80
|
-
- Watch edge count harder than node count. It binds first, and a diagram whose edges outnumber its nodes is already too dense to read.
|
|
81
|
-
- Treat a diagram that cannot be described in one sentence as two diagrams.
|
|
82
69
|
- Keep an entry to one diagram by default. A second fence in the same file needs its own H2 naming what it adds, and a third is a sign the entry covers two kinds.
|
|
83
|
-
- Warn rather than refuse on a budget, and name the split that would fix it. These numbers come from published Mermaid practice rather than from a measurement in this repository, so a hard refusal on them will be wrong sometimes and unarguable when it is.
|
|
84
|
-
|
|
85
|
-
## Accessibility
|
|
86
|
-
|
|
87
|
-
- Give every diagram `accTitle` and `accDescr`. `accTitle` names what the diagram answers. `accDescr` states the structure in one sentence for a reader who cannot see the render.
|
|
88
70
|
|
|
89
71
|
## Explanation
|
|
90
72
|
|
|
@@ -96,13 +78,6 @@ A second entry for one kind takes a suffixed name (`request-flow-admin.md`) and
|
|
|
96
78
|
|
|
97
79
|
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
80
|
|
|
99
|
-
## Verification
|
|
100
|
-
|
|
101
|
-
- Judge a diagram from its rendered image, not from its source. Direction, sibling rows, and edge bundles are visible only in the output.
|
|
102
|
-
- Render to PNG. An SVG export reads back as markup with no recoverable spatial meaning.
|
|
103
|
-
- Apply four tests as a reviewer, the same ones the author applied: direction held, no sibling row reading as a chain, no crossing edge bundle, taller than wide outside a sequence diagram.
|
|
104
|
-
- State which verification was skipped when no renderer is available. A diagram written without a render is still shippable, and one reported as verified without a render is not.
|
|
105
|
-
|
|
106
81
|
## What moves to .claude/context/
|
|
107
82
|
|
|
108
83
|
Implementation detail that answers how a component is built belongs in a `.claude/context/` entry, not a diagram:
|
|
@@ -120,13 +95,13 @@ Reference the context entry by path when a reader needs the mechanism. The diagr
|
|
|
120
95
|
- A diagram showing a defunct host or library is worse than no diagram. Audit the affected entry in the same PR.
|
|
121
96
|
- `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
97
|
- Nothing watches the folder for you. The entries are redrawn on demand rather than swept on every ship, so `verified` carries the whole signal: an entry whose date sits far behind the branch is due a read, and no pass is going to name which one.
|
|
123
|
-
- 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.
|
|
124
|
-
- 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.
|
|
125
98
|
|
|
126
99
|
## Template
|
|
127
100
|
|
|
128
101
|
The filename and the `category` value both come from Entry kinds and are fixed per kind. A stub nobody has drawn yet carries `TODO: never verified` in place of the SHA and date. The node names and labels inside the fence are placeholders, written bare because Mermaid reads an angle bracket as markup.
|
|
129
102
|
|
|
103
|
+
What goes inside the fence, and how the render is checked once it is drawn, is `mermaid.md`. This template fixes the frame around it.
|
|
104
|
+
|
|
130
105
|
````markdown
|
|
131
106
|
---
|
|
132
107
|
title: <what the entry answers>
|
package/standards/index.md
CHANGED
|
@@ -19,6 +19,7 @@ Reference docs for consistent authoring across the toolkit and target projects.
|
|
|
19
19
|
- [Issue reference](issue.md): GitHub issue title, labels, and body conventions
|
|
20
20
|
- [Markdown reference](markdown.md): Headings, paragraph and list structure, code spans, the date form, punctuation, emphasis, file references, banned words, and frontmatter wording
|
|
21
21
|
- [Memory reference](memory.md): Filename and type prefix, frontmatter, the body shape per type, links between entries, and the lifecycle from write to retire
|
|
22
|
+
- [Mermaid reference](mermaid.md): Direction and layout, node and edge budgets, accessibility fields, label punctuation, and render verification for a Mermaid diagram
|
|
22
23
|
- [Plan reference](plan.md): Filename and slug, required sections, the suggested-and-answer contract, and the lifecycle from the live folder to the archive
|
|
23
24
|
- [Pull request reference](pr.md): Pull request title and body conventions
|
|
24
25
|
- [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
|
package/standards/issue.md
CHANGED
|
@@ -19,13 +19,14 @@ Does not govern:
|
|
|
19
19
|
## Title
|
|
20
20
|
|
|
21
21
|
- Format: `<type>: <subject>`
|
|
22
|
-
- Type is `bug` or `
|
|
22
|
+
- Type is `bug`, `task`, or `feedback`. Lowercase the type and the first word of the subject for `bug` and `task`, both hand-composed. `feedback` is always lowercase. Its subject is derived by the CLI from the report's `### Surface` field verbatim, so the subject alone carries no casing rule.
|
|
23
23
|
- Length: 72 characters maximum, no trailing period.
|
|
24
24
|
|
|
25
25
|
## Labels
|
|
26
26
|
|
|
27
|
-
- Apply `bug` for a defect and `enhancement` for a task or improvement.
|
|
28
|
-
-
|
|
27
|
+
- Apply `bug` for a defect and `enhancement` for a task or improvement. Both are GitHub default labels.
|
|
28
|
+
- Apply `feedback` to a report filed through `canon feedback --github`, which sets the label unconditionally rather than a session choosing it. It is not a GitHub default. Create it once per project with `gh label create feedback`.
|
|
29
|
+
- A label that does not exist makes `gh` reject the issue. Create each one once with `gh label create`.
|
|
29
30
|
- One label per issue unless a second genuinely applies.
|
|
30
31
|
|
|
31
32
|
## Content
|
|
@@ -37,16 +38,35 @@ Does not govern:
|
|
|
37
38
|
|
|
38
39
|
## Sections
|
|
39
40
|
|
|
41
|
+
### Bug and task
|
|
42
|
+
|
|
40
43
|
- `## Summary`: one line naming what and why.
|
|
41
44
|
- `## Details`: for a bug, what happens versus what is expected. For a task, what to build.
|
|
42
45
|
- `## Context`: for a bug, repro steps or commands. For a task, the driving reason, or `none`.
|
|
43
46
|
- `## Proposed` (optional): one line naming a fix or approach. Omit when open.
|
|
44
47
|
|
|
48
|
+
### Feedback
|
|
49
|
+
|
|
50
|
+
- One `## Toolkit feedback` wrapper holds every field as a nested `###` heading. A flat `##` field is not recognized.
|
|
51
|
+
- `### From project` (optional): the reporting project's name or kind.
|
|
52
|
+
- `### Surface` (required): the toolkit surface and its type, and the specific file or name when known.
|
|
53
|
+
- `### Observed` (required): the observed behavior.
|
|
54
|
+
- `### Expected` (optional): the expected behavior, or `unclear`.
|
|
55
|
+
- `### Repro` (optional): repro details, or `none`.
|
|
56
|
+
- `### Proposed fix` (required): a proposed fix, or `open` when the session settled on no direction.
|
|
57
|
+
- A required field is refused when present but empty. Write the fallback literal for an optional field rather than leaving it blank.
|
|
58
|
+
|
|
45
59
|
## Formatting
|
|
46
60
|
|
|
61
|
+
### Bug and task
|
|
62
|
+
|
|
47
63
|
- End every bullet with a period.
|
|
48
64
|
- Keep each section to one or two lines.
|
|
49
65
|
|
|
66
|
+
### Feedback
|
|
67
|
+
|
|
68
|
+
- A field may run to multiple paragraphs and may hold a fenced code block. The one-or-two-line rule and the trailing-period rule do not apply.
|
|
69
|
+
|
|
50
70
|
## Examples
|
|
51
71
|
|
|
52
72
|
### Correct (bug)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Mermaid reference
|
|
3
|
+
description: Direction and layout, node and edge budgets, accessibility fields, label punctuation, and render verification for a Mermaid diagram
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Mermaid reference
|
|
7
|
+
|
|
8
|
+
Applies to every Mermaid fence, wherever it is written. A fence sits inside a document some other standard shapes, so this file reaches the drawing and stops at the fence markers.
|
|
9
|
+
|
|
10
|
+
## Scope
|
|
11
|
+
|
|
12
|
+
Governs the Mermaid attribute wherever a fence is written, naming no path because an attribute standard governs a drawing rather than a document type: direction and layout, node and edge budgets, the accessibility fields, how punctuation reaches a label, and how a rendered diagram is verified. It carries no template, since a fence has no document shape of its own and sits inside one another standard sets.
|
|
13
|
+
|
|
14
|
+
Does not govern:
|
|
15
|
+
|
|
16
|
+
- Which diagram a document carries, what question it answers, its frontmatter, and the explanation prose beneath it: `diagrams.md`
|
|
17
|
+
- Language, word choice, punctuation, and formatting in the prose around a fence: `markdown.md`
|
|
18
|
+
- Voice, rhythm, and sentence construction in that prose: the `write-human` skill
|
|
19
|
+
- The mechanism behind any component a diagram draws: `context.md`
|
|
20
|
+
|
|
21
|
+
## What a working diagram looks like
|
|
22
|
+
|
|
23
|
+
A diagram works when a reviewer holding the rendered image, and nothing else, answers yes four times:
|
|
24
|
+
|
|
25
|
+
- Did the declared direction hold?
|
|
26
|
+
- Is every row of siblings free of a sequential reading the system does not have?
|
|
27
|
+
- Is every convergence free of a crossing edge bundle?
|
|
28
|
+
- Is it taller than wide, outside a sequence diagram?
|
|
29
|
+
|
|
30
|
+
A diagram failing these is non-conforming even when it satisfies every shape rule below. The rules are the means. These four questions are the test.
|
|
31
|
+
|
|
32
|
+
## Layout
|
|
33
|
+
|
|
34
|
+
- Declare `flowchart TB` by default. Mermaid ignores a subgraph's direction whenever that subgraph links outward, and an architecture diagram links across its subgraphs as the normal case, so top-bottom is a declaration rather than a guarantee.
|
|
35
|
+
- Restructure a diagram that renders diagonal or left-to-right. Repeating the direction keyword does not fix it.
|
|
36
|
+
- Render a context, component, or pipeline diagram taller than wide. A `sequenceDiagram` is wide by construction and is exempt.
|
|
37
|
+
- Do not let independent nodes render in a row. A row of siblings reads as a sequential chain and asserts a pipeline the system does not have.
|
|
38
|
+
- Do not converge many edges on one node from one side. A crossing bundle is unreadable whatever it encodes.
|
|
39
|
+
- Keep node labels short. Three or four words max. Detail goes in the paragraph below the diagram.
|
|
40
|
+
- Use `<br/>` for a second short line on a node when the label is two ideas, never for a sentence.
|
|
41
|
+
- Subgraphs are for grouping unrelated lanes such as offline versus online or browser versus server. Do not subgraph a single linear flow.
|
|
42
|
+
|
|
43
|
+
## Budgets
|
|
44
|
+
|
|
45
|
+
- Hold a diagram to roughly 5 to 10 nodes. Split it past 15.
|
|
46
|
+
- Watch edge count harder than node count. It binds first, and a diagram whose edges outnumber its nodes is already too dense to read.
|
|
47
|
+
- Treat a diagram that cannot be described in one sentence as two diagrams.
|
|
48
|
+
- Warn rather than refuse on a budget, and name the split that would fix it. These numbers come from published Mermaid practice rather than from a measurement against a corpus, so a hard refusal on them will be wrong sometimes and unarguable when it is.
|
|
49
|
+
|
|
50
|
+
## Labels
|
|
51
|
+
|
|
52
|
+
- Apply the punctuation bans in `markdown.md` to node and subgraph labels. A label is not prose, so a check scoped to prose does not reach it, and reading the labels before shipping is the only gate they have.
|
|
53
|
+
- Treat the prose around a fence and the text inside it as two surfaces. The paragraphs are prose and follow `markdown.md` and the `write-human` skill. The fenced block is not, which is why a check scoped to prose is the wrong thing to rely on for what sits inside it.
|
|
54
|
+
|
|
55
|
+
## Accessibility
|
|
56
|
+
|
|
57
|
+
- Give every diagram `accTitle` and `accDescr`. `accTitle` names what the diagram answers. `accDescr` states the structure in one sentence for a reader who cannot see the render.
|
|
58
|
+
|
|
59
|
+
## Verification
|
|
60
|
+
|
|
61
|
+
- Judge a diagram from its rendered image, not from its source. Direction, sibling rows, and edge bundles are visible only in the output.
|
|
62
|
+
- Render to PNG. An SVG export reads back as markup with no recoverable spatial meaning.
|
|
63
|
+
- Apply the four questions above as a reviewer, against the same render the author judged.
|
|
64
|
+
- State which verification was skipped when no renderer is available. A diagram written without a render is still shippable, and one reported as verified without a render is not.
|