@freetesh/canon 0.0.0-stage → 0.16.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 (136) hide show
  1. package/.claude-plugin/marketplace.json +15 -0
  2. package/.claude-plugin/plugin.json +5 -0
  3. package/LICENSE +21 -0
  4. package/README.md +161 -2
  5. package/cli/dist/api.d.ts +3 -0
  6. package/cli/dist/api.js +4 -0
  7. package/cli/dist/check.d.ts +19 -0
  8. package/cli/dist/check.js +40 -0
  9. package/cli/dist/checks/architecture.d.ts +23 -0
  10. package/cli/dist/checks/architecture.js +135 -0
  11. package/cli/dist/checks/canonical-values.d.ts +2 -0
  12. package/cli/dist/checks/canonical-values.js +48 -0
  13. package/cli/dist/checks/commands.d.ts +7 -0
  14. package/cli/dist/checks/commands.js +33 -0
  15. package/cli/dist/checks/context-layout.d.ts +5 -0
  16. package/cli/dist/checks/context-layout.js +83 -0
  17. package/cli/dist/checks/context-size.d.ts +2 -0
  18. package/cli/dist/checks/context-size.js +46 -0
  19. package/cli/dist/checks/features.d.ts +2 -0
  20. package/cli/dist/checks/features.js +38 -0
  21. package/cli/dist/checks/index.d.ts +2 -0
  22. package/cli/dist/checks/index.js +34 -0
  23. package/cli/dist/checks/listing.d.ts +2 -0
  24. package/cli/dist/checks/listing.js +51 -0
  25. package/cli/dist/checks/metrics-definitions.d.ts +2 -0
  26. package/cli/dist/checks/metrics-definitions.js +14 -0
  27. package/cli/dist/checks/pipeline.d.ts +8 -0
  28. package/cli/dist/checks/pipeline.js +34 -0
  29. package/cli/dist/checks/refs.d.ts +2 -0
  30. package/cli/dist/checks/refs.js +92 -0
  31. package/cli/dist/checks/shared-files.d.ts +22 -0
  32. package/cli/dist/checks/shared-files.js +84 -0
  33. package/cli/dist/checks/sources.d.ts +2 -0
  34. package/cli/dist/checks/sources.js +40 -0
  35. package/cli/dist/checks/stale-copies.d.ts +2 -0
  36. package/cli/dist/checks/stale-copies.js +18 -0
  37. package/cli/dist/checks/standards-copies.d.ts +2 -0
  38. package/cli/dist/checks/standards-copies.js +57 -0
  39. package/cli/dist/checks/tasks.d.ts +2 -0
  40. package/cli/dist/checks/tasks.js +66 -0
  41. package/cli/dist/checks/types.d.ts +23 -0
  42. package/cli/dist/checks/types.js +1 -0
  43. package/cli/dist/checks/wiki-frontmatter.d.ts +3 -0
  44. package/cli/dist/checks/wiki-frontmatter.js +84 -0
  45. package/cli/dist/commands/add.d.ts +3 -0
  46. package/cli/dist/commands/add.js +24 -0
  47. package/cli/dist/commands/approve.d.ts +2 -0
  48. package/cli/dist/commands/approve.js +20 -0
  49. package/cli/dist/commands/check.d.ts +3 -0
  50. package/cli/dist/commands/check.js +19 -0
  51. package/cli/dist/commands/copies.d.ts +3 -0
  52. package/cli/dist/commands/copies.js +23 -0
  53. package/cli/dist/commands/doctor.d.ts +2 -0
  54. package/cli/dist/commands/doctor.js +16 -0
  55. package/cli/dist/commands/hooks.d.ts +6 -0
  56. package/cli/dist/commands/hooks.js +55 -0
  57. package/cli/dist/commands/init.d.ts +3 -0
  58. package/cli/dist/commands/init.js +78 -0
  59. package/cli/dist/commands/learn.d.ts +3 -0
  60. package/cli/dist/commands/learn.js +36 -0
  61. package/cli/dist/commands/mcp.d.ts +2 -0
  62. package/cli/dist/commands/mcp.js +11 -0
  63. package/cli/dist/commands/pipeline.d.ts +3 -0
  64. package/cli/dist/commands/pipeline.js +26 -0
  65. package/cli/dist/commands/search.d.ts +2 -0
  66. package/cli/dist/commands/search.js +13 -0
  67. package/cli/dist/commands/standards.d.ts +3 -0
  68. package/cli/dist/commands/standards.js +26 -0
  69. package/cli/dist/commands/status.d.ts +3 -0
  70. package/cli/dist/commands/status.js +11 -0
  71. package/cli/dist/commands/sync.d.ts +3 -0
  72. package/cli/dist/commands/sync.js +23 -0
  73. package/cli/dist/commands/ui.d.ts +3 -0
  74. package/cli/dist/commands/ui.js +64 -0
  75. package/cli/dist/commands/weigh.d.ts +2 -0
  76. package/cli/dist/commands/weigh.js +16 -0
  77. package/cli/dist/config/load.d.ts +23 -0
  78. package/cli/dist/config/load.js +116 -0
  79. package/cli/dist/config/schema.d.ts +200 -0
  80. package/cli/dist/config/schema.js +116 -0
  81. package/cli/dist/doctor.d.ts +12 -0
  82. package/cli/dist/doctor.js +31 -0
  83. package/cli/dist/format.d.ts +6 -0
  84. package/cli/dist/format.js +35 -0
  85. package/cli/dist/index.d.ts +2 -0
  86. package/cli/dist/index.js +48 -0
  87. package/cli/dist/init.d.ts +46 -0
  88. package/cli/dist/init.js +119 -0
  89. package/cli/dist/learn.d.ts +44 -0
  90. package/cli/dist/learn.js +80 -0
  91. package/cli/dist/lib/env.d.ts +7 -0
  92. package/cli/dist/lib/env.js +6 -0
  93. package/cli/dist/lib/files.d.ts +3 -0
  94. package/cli/dist/lib/files.js +23 -0
  95. package/cli/dist/lib/frontmatter.d.ts +6 -0
  96. package/cli/dist/lib/frontmatter.js +16 -0
  97. package/cli/dist/lib/qmd.d.ts +9 -0
  98. package/cli/dist/lib/qmd.js +13 -0
  99. package/cli/dist/lib/system.d.ts +4 -0
  100. package/cli/dist/lib/system.js +19 -0
  101. package/cli/dist/packs.d.ts +40 -0
  102. package/cli/dist/packs.js +85 -0
  103. package/cli/dist/pipeline.d.ts +20 -0
  104. package/cli/dist/pipeline.js +30 -0
  105. package/cli/dist/standards.d.ts +14 -0
  106. package/cli/dist/standards.js +42 -0
  107. package/cli/dist/status.d.ts +3 -0
  108. package/cli/dist/status.js +26 -0
  109. package/cli/dist/sync.d.ts +19 -0
  110. package/cli/dist/sync.js +30 -0
  111. package/cli/dist/ui.d.ts +15 -0
  112. package/cli/dist/ui.js +69 -0
  113. package/package.json +54 -4
  114. package/packs/expo/pack.yaml +5 -0
  115. package/packs/firebase/pack.yaml +5 -0
  116. package/packs/nextjs/pack.yaml +5 -0
  117. package/packs/react/pack.yaml +5 -0
  118. package/packs/revenuecat/pack.yaml +5 -0
  119. package/packs/uniwind/pack.yaml +5 -0
  120. package/scripts/log-verdict.mjs +56 -0
  121. package/skills/ask/SKILL.md +40 -0
  122. package/skills/decision/SKILL.md +36 -0
  123. package/skills/ingest/SKILL.md +45 -0
  124. package/skills/standards/SKILL.md +16 -0
  125. package/skills/weigh/SKILL.md +160 -0
  126. package/skills/wiki-lint/SKILL.md +67 -0
  127. package/standards/README.md +14 -0
  128. package/standards/agent-contract.md +47 -0
  129. package/standards/constitution.md +104 -0
  130. package/standards/context-layout.md +129 -0
  131. package/standards/dev-methods.md +29 -0
  132. package/standards/wiki-schema.md +71 -0
  133. package/templates/dependency-cruiser/app.cjs +23 -0
  134. package/templates/dependency-cruiser/base.cjs +52 -0
  135. package/templates/dependency-cruiser/package.cjs +31 -0
  136. package/templates/dependency-cruiser/root.cjs +15 -0
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: weigh
3
+ description: Decision gate run BEFORE acting on a non-trivial request in a product repo — a new feature, screen or product, a new dependency or library, a migration or rewrite, a schema, money, pricing or store change, a release or deploy, deleting something, or a change that spans more than one product. Weighs the request against the canon constitution, the product's wiki and ADRs, existing features and tasks, cost vs value, and writing less code, then returns do it / do it differently / push back with citations. Also use when the user types /weigh or asks "should we…", "is it worth…", "does this make sense".
4
+ ---
5
+
6
+ # Weigh before acting
7
+
8
+ You are deciding whether and how to do a request — not doing it yet.
9
+ Request: `$ARGUMENTS` (empty = the user's latest request in this conversation).
10
+
11
+ ## Skip the gate when it is trivial
12
+
13
+ Answer and act directly, with no verdict block, when **all** are true: one file,
14
+ no new dependency, no schema / money / store / release / delete, and the change is
15
+ fully specified (a typo, a spacing fix, a copy edit the user dictated). A
16
+ product's `.claude/canon.yaml` may tighten this under `weigh.trivial`.
17
+
18
+ ## Steps
19
+
20
+ 1. **Restate the goal** in one line — what outcome the user wants, not the
21
+ mechanism they named. A named mechanism ("use library X", "move to Firebase")
22
+ is a proposal to weigh, not a given. Then **list the claims** the request
23
+ makes or rests on: "users want it", "it will help retention", "it is
24
+ missing", "it is slow". The request is not a fact (C-14); each claim is
25
+ checked in step 4.
26
+
27
+ 2. **Rules.** Run `canon standards --constitution` for the principle titles
28
+ (canon's and any the team added), and read the constitution files that
29
+ `canon standards` lists — or `../../standards/constitution.md` (relative to
30
+ this skill) if the CLI is not installed. Note every principle the request
31
+ touches, by ID. Read a standard from `canon standards` only if the request is
32
+ in its area.
33
+
34
+ 3. **Domain.** Search before you judge. Run `mcp__plugin_canon_qmd__query` with
35
+ the goal in plain words, then the key nouns, scoped with `collections` to
36
+ this product's `<repo>-wiki` and `<repo>-features` (the names `canon init`
37
+ gives them; add `pack-<name>` when the question is about a vendor's API). Other products' hits are noise here; step 5 is where
38
+ siblings are searched. Read the top hits with `mcp__plugin_canon_qmd__get`. Look for: an ADR that already
39
+ decided this, a canonical value it would change, a concept it would break.
40
+ If qmd is unavailable, read `.context/wiki/index.md` and `decisions/`.
41
+ **Architecture:** if `.claude/canon.yaml` lists the `architecture` module, read
42
+ the repo's `.dependency-cruiser.cjs` and its wiki architecture concept page.
43
+ A request whose code would need an import a rule forbids is DO IT
44
+ DIFFERENTLY (name the allowed path) or PUSH BACK; one that changes a rule
45
+ is **too-large** unless a decision page already approves it. Cite the rule
46
+ by its `name`.
47
+
48
+ 4. **Claims.** Mark each claim from step 1 **backed**, **partly backed** or
49
+ **not backed**, with the fact and its source. Look in what step 3 read, the
50
+ code and `.context/raw/`. When that is not enough, look for a data source:
51
+ query qmd for `SOURCE` pages in this product's wiki. Each says what it holds,
52
+ how to read it (`mcp:`, `skill:`, `cli:` or `manual:`) and which claims it
53
+ answers. For `manual:`, ask the user for the numbers and say where to find
54
+ them; do not guess. If one fits, run its query and follow the query rules in `wiki-schema.md`
55
+ ("Data sources"): read only, one or two small queries, counts not people.
56
+ Save a result that decides the verdict to `.context/raw/`. If the tool is not
57
+ available, say so and leave the claim not backed. If no source fits, name
58
+ the kind of source that would answer it ("an analytics tool with weekly
59
+ active users"). Never mark a claim backed because the user said it again.
60
+
61
+ 5. **Duplicates and conflicts.** Check `.context/features/` and `.context/tasks.md`
62
+ of this product, and the features collections of sibling products in qmd:
63
+ is this already planned, built, shelved, or in progress elsewhere? Would it
64
+ conflict with something in `## Now`?
65
+
66
+ 6. **Cost vs value.**
67
+ - Size: **small** (1 file, < 50 lines) · **medium** (2–5 files, < 200 lines) ·
68
+ **large** (5+ files) · **too-large** (architecture change — split it).
69
+ - Ongoing cost: new dependency, new service bill, more to maintain, more to
70
+ test, store review risk.
71
+ - Value: name the user or the metric it moves (`metrics/definitions.yml` if
72
+ the product has one). If neither can be named, say "value unproven". A
73
+ value claim is checked like any other claim, in step 4.
74
+ - Evidence: say which evidence from `dev-methods.md` the work must leave — a
75
+ feature page, a failing test first, or a metric and snapshot.
76
+
77
+ 7. **Write less.** Climb the ladder and stop at the first rung that works:
78
+ delete it → reuse something in this repo → reuse from a sibling product or
79
+ shared script → platform or standard library → an existing well-used package
80
+ → fewer lines → new code. If the `ponytail` plugin is installed, follow its
81
+ ladder for this step.
82
+
83
+ 8. **Too-large, or the user asked for a second opinion?** Then, and only then,
84
+ ask the `challenger` agent for an independent read. It costs tens of
85
+ thousands of tokens, so hand it what you already have: the request, the repo
86
+ path, your draft verdict, and every file and wiki page you read with one line
87
+ on what each says. It checks your reasoning and looks only where you did
88
+ not. Where you and it disagree, show both. A large request is weighed by you
89
+ alone.
90
+
91
+ ## Verdict
92
+
93
+ Reply with exactly this block, then stop or proceed as the verdict says:
94
+
95
+ ```
96
+ Verdict: DO IT | DO IT DIFFERENTLY | PUSH BACK
97
+ Goal: <one line>
98
+ Size: small | medium | large | too-large
99
+ Why:
100
+ - <C-xx> <one line> — <file or wiki page cited>
101
+ - ...
102
+ Instead: <only for DO IT DIFFERENTLY — the cheaper or safer way>
103
+ Claims:
104
+ - "<claim>" — backed | partly backed | not backed — <fact and source, or what was searched>
105
+ Assumed: <every claim not backed, or "none">
106
+ Open questions: <only if a real ambiguity blocks a good answer>
107
+ ```
108
+
109
+ - Every bullet under **Why** cites a principle ID and a source (a wiki page, ADR,
110
+ standard, feature, file or saved query result). A reason with no source is an
111
+ opinion: drop it, or list it under **Assumed**.
112
+ - **DO IT** only when **Assumed** is "none". Proceed with the work in the same
113
+ turn.
114
+ - **DO IT DIFFERENTLY** → proceed with the *Instead* version only if the user
115
+ already accepted it and **Assumed** is "none"; otherwise stop and ask.
116
+ - **PUSH BACK** → stop. Do not start the work, not even a part of it.
117
+ - **Something is assumed** → stop, and give the user three choices: bring the
118
+ facts (and say where they would go), agree to terms, or drop it. Any terms
119
+ you show, here or later, are a numbered list, so the user can agree line by
120
+ line.
121
+
122
+ Write the whole reply in plain words (C-15): short sentences, common words, no
123
+ jargon the wiki does not define.
124
+
125
+ ## Terms (when the user wants to go on anyway)
126
+
127
+ When the user wants to go on despite a PUSH BACK or an assumption, write the
128
+ terms as a numbered list: what is in scope, what is out, which rule changes and
129
+ which stays, and how the assumption will be checked later (a metric and a
130
+ date). A fact the user gives in chat is saved to `.context/raw/` first, then
131
+ listed as a fact, not as proof of more than it shows.
132
+
133
+ Proceed only after the user agrees in writing ("agree", or "agree to 1–4").
134
+ "Go ahead" to a verdict is not agreement to terms that were never shown. Work
135
+ covers only the terms agreed to.
136
+
137
+ ## Logging (every verdict)
138
+
139
+ Log every verdict once, when you know what happened next. A trivial request
140
+ that skipped the gate is not logged. `--outcome` is one of:
141
+
142
+ - `proceeded` — work went ahead as the verdict said (DO IT, or an accepted
143
+ *Instead*).
144
+ - `stopped` — you stopped and asked, and the user has not answered yet. Log it
145
+ when you stop; if the user later overrides, log a second line.
146
+ - `overridden` — the user went on against a PUSH BACK, rejected a DO IT
147
+ DIFFERENTLY, or agreed to terms. `--reason` is required: the user's reason,
148
+ verbatim. Pass each agreed term with its own `--term`.
149
+ - `dropped` — the user chose to drop the request.
150
+
151
+ ```bash
152
+ node ../../scripts/log-verdict.mjs --verdict push-back --outcome overridden \
153
+ --principles C-04,C-14 --request "<one line>" \
154
+ --reason "<the user's reason, verbatim>" --term "<term 1>" --term "<term 2>"
155
+ ```
156
+
157
+ (path relative to this skill). It writes to `.context/raw/canon/verdicts.jsonl`
158
+ in the current repo. Never edit or delete existing lines. `canon learn` reads
159
+ the log across products: how often the gate stops work, and which rules keep
160
+ being overridden.
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: wiki-lint
3
+ description: Audit .context/wiki/ for drift — broken [[links]], orphan pages, contradictions between entities, stale last-verified dates, unprocessed raw files. Optionally auto-fix safe issues and regenerate .context/wiki/index.md. Usage `/wiki-lint` (audit) or `/wiki-lint --fix` (audit + auto-fix).
4
+ ---
5
+
6
+ You are linting the wiki at `.context/wiki/` against the wiki schema (the `wiki-schema.md` that `canon standards` lists — a team's own replaces canon's; without the CLI, `../../standards/wiki-schema.md` relative to this skill).
7
+
8
+ Mode: `$ARGUMENTS` (empty = audit only; `--fix` = audit + auto-fix safe issues).
9
+
10
+ ## Steps
11
+
12
+ 1. **Read the wiki schema** to refresh the folders, the one test and the caps.
13
+
14
+ 2. **Run `canon check` first** if the CLI is installed. It checks frontmatter,
15
+ placeholders, caps, dated decision names, duplicate IDs, staleness and
16
+ prices held by no entity in under a second,
17
+ plus any checker the repo declares. Start from its output rather than
18
+ re-deriving it.
19
+
20
+ 3. **Enumerate pages.** List every `.md` file under `.context/wiki/` (excluding `index.md` and `CLAUDE.md`). For each, parse the frontmatter.
21
+
22
+ 4. **Build the graph:**
23
+ - Map `id → file path`.
24
+ - For each page, extract all `[[wikilink]]` tokens from the body.
25
+ - Build inbound and outbound link sets per page.
26
+
27
+ 5. **Run the checks below.** Group findings into **Blockers** and **Warnings**.
28
+
29
+ ### Blockers (must be fixed)
30
+
31
+ | Check | Rule |
32
+ |---|---|
33
+ | Broken `[[wikilink]]` | Target page does not exist |
34
+ | Duplicate `id` | Two pages claim the same ID |
35
+ | Contradictory canonical value | Two `entity` pages list the same key with different values |
36
+ | Placeholder text | `TBD`, `none yet`: write the fact or delete the section |
37
+ | `type` does not match folder | If a page sets `type`, it lives in that type's folder |
38
+
39
+ ### Warnings
40
+
41
+ | Check | Rule |
42
+ |---|---|
43
+ | Over a cap | Page 60 lines, decision 30, README 30, tasks 100 |
44
+ | Restates code, a design or git | Delete the lines; link the source instead |
45
+ | Two pages on one topic | Merge into one, edited in place |
46
+ | Stale `last-verified` | > 90 days from today. |
47
+ | Unprocessed raw file | A file under `.context/raw/` that no wiki page references in its `Sources`. |
48
+ | User-facing string violates copy rules | Check quoted copy against the rules in the root `CLAUDE.md`. Best-effort. |
49
+
50
+ 6. **Auto-fix (only if `--fix` is in `$ARGUMENTS`):**
51
+ - Regenerate `.context/wiki/index.md` from scratch: enumerate pages by type, sort alphabetically by slug, keep the structure the file already has.
52
+ - Fix `last-verified` to today's date on any page whose body was edited in the working tree.
53
+ - **Never** auto-fix: contradictory canonical values, broken `[[wikilinks]]`, merges or cuts. These need a human decision.
54
+
55
+ 7. **Report.** Print:
56
+ - Counts: pages, blockers, warnings, auto-fixes applied.
57
+ - Per-finding lines: `[BLOCKER|WARN] <path>:<rule> — <detail>`.
58
+ - For each blocker, one suggested fix.
59
+ - For broken `[[wikilinks]]`, list candidate existing pages by name similarity.
60
+
61
+ ## Rules
62
+
63
+ - **Never edit pages other than auto-fixes above.** Lint reports; the user (or `/ingest`) fixes.
64
+ - **Never delete pages from this skill.** Propose the cut; the user approves it. Git keeps what is deleted.
65
+ - **Never modify `.context/raw/`** except to warn about unprocessed files.
66
+ - If a blocker resists auto-fix, exit non-zero (in CI mode) but always print the full report first.
67
+ - Today's date is in the session context — use it for staleness math (>90 days).
@@ -0,0 +1,14 @@
1
+ # standards/
2
+
3
+ canon's default standards. `canon standards` lists the ones that apply to a repo:
4
+ these first, then each folder named under `standards:` in the estate's and the
5
+ repo's `.claude/canon.yaml`. A configured file with the same name as one of these
6
+ replaces it; a configured `constitution.md` adds principles instead.
7
+
8
+ | File | What it holds |
9
+ |---|---|
10
+ | `constitution.md` | The principles a request is weighed against (C-01 to C-13) |
11
+ | `wiki-schema.md` | Wiki page types, frontmatter, required sections, lint rules |
12
+ | `context-layout.md` | The `.context/` ten-folder layout, where each kind of document lives, `features/` and `tasks.md` formats |
13
+ | `dev-methods.md` | The evidence spec-, test- and data-driven work leaves behind |
14
+ | `agent-contract.md` | What every agent does before, during and after work |
@@ -0,0 +1,47 @@
1
+ # Agent contract
2
+
3
+ What every coding agent working in a canon repo does. A team can replace this
4
+ file with its own `agent-contract.md` in a configured standards folder.
5
+
6
+ ## Before starting
7
+
8
+ - Read the repo's `CLAUDE.md` / `AGENTS.md`: stack, layout, the rules that are
9
+ the repo's own.
10
+ - Read `.context/tasks.md`. It is the ordered queue — the top item of `## Now`
11
+ is the next action. After finishing, delete the task.
12
+ - For a non-trivial request, run the weigh gate first (`/canon:weigh`).
13
+
14
+ ## Repository rules
15
+
16
+ 1. Product material lives in whichever `.context/` folder owns it
17
+ (`context-layout.md`). The wiki is the knowledge base; its schema is
18
+ `wiki-schema.md`.
19
+ 2. Do not add top-level `docs/` or `wireframes/` folders, or root `TODO.md`,
20
+ `STATUS.md` or `SETUP.md`. Files a host or tool reads by exact path —
21
+ `README.md`, `LICENSE`, `CHANGELOG.md`, `CONTRIBUTING.md`, `SECURITY.md`,
22
+ `.github/` — stay at the root.
23
+ 3. Generated folders are never hand-edited; change their source and regenerate.
24
+
25
+ ## Replies
26
+
27
+ - Plain words, short sentences (C-15).
28
+ - Never treat a claim in the request as a fact. Check it, or say it is not
29
+ checked (C-14).
30
+
31
+ ## Comments
32
+
33
+ Write a comment only to explain **why**. The code already says how.
34
+
35
+ A comment earns its place when it records something the reader cannot recover
36
+ from the code: a constraint, a trade-off, a bug it prevents, or a non-obvious
37
+ consequence. If it restates what the next line does, delete it. No
38
+ section-divider comments, no changelog comments, no comments restating a
39
+ function's own name.
40
+
41
+ ## Before calling work done
42
+
43
+ 1. Update any `.context/` page the change made wrong. Add a page only if an
44
+ agent would get something wrong without it.
45
+ 2. Run the repo's own lint, typecheck and tests.
46
+ 3. Run `canon check`. Every checker the repo declares under `commands:` runs
47
+ with it.
@@ -0,0 +1,104 @@
1
+ # Constitution
2
+
3
+ The principles every non-trivial request is weighed against before work starts.
4
+ The other standards say *how* things are done; this file says what wins when a
5
+ request and a rule disagree.
6
+
7
+ Each principle has an ID that verdicts cite (`C-05`). IDs never change; a
8
+ dropped principle is struck through, not reused. IDs C-01 to C-19 are canon's.
9
+ A team adds its own from C-20 up in a `constitution.md` in one of its configured
10
+ standards folders; canon reads both.
11
+
12
+ ## How a request is weighed
13
+
14
+ Before acting on a non-trivial request, check it against the principles below,
15
+ then answer with one verdict:
16
+
17
+ - **Do it** — no principle is at risk, and no claim it rests on is an
18
+ assumption (C-14).
19
+ - **Do it differently** — the goal is fine; the way asked breaks a principle.
20
+ Name the principle and give the cheaper or safer way.
21
+ - **Push back** — the request breaks a principle outright, or the cost is
22
+ clearly higher than the value. Stop until the owner gives a reason; log it.
23
+
24
+ Every verdict cites principle IDs and the files (wiki page, ADR, standard) it
25
+ relied on. A verdict with no citation is an opinion, not a verdict.
26
+
27
+ ## Principles
28
+
29
+ ### C-01 Shipping beats starting
30
+ A request that finishes or unblocks something already in flight outranks one
31
+ that starts something new. Ask: what does this move closer to a user?
32
+
33
+ ### C-02 One home per fact
34
+ Every rule, value and artifact has exactly one source; everything else imports,
35
+ links or is generated from it. A second copy is a future contradiction.
36
+
37
+ ### C-03 Knowledge is written down, in the repo
38
+ A decision that lives only in chat or in one machine's memory is lost. Decisions
39
+ become ADRs; canonical values become wiki entities; both live in git. Check the
40
+ wiki and ADRs before answering from memory.
41
+
42
+ ### C-04 Decided things stay decided — until a new decision says otherwise
43
+ A request that contradicts an ADR is not done silently. Either it follows the
44
+ ADR, or a new ADR supersedes it, with the reason.
45
+
46
+ ### C-05 Value must beat cost
47
+ Weigh effort, tokens, money and the maintenance it adds forever against who
48
+ gains and how much. Name the user or the metric it moves; if neither can be
49
+ named, the value is unproven.
50
+
51
+ ### C-06 Write less
52
+ Before writing code: can something be deleted, reused from this repo or a
53
+ sibling, done with the platform or standard library, or done in fewer lines?
54
+ New code is the last rung, not the first.
55
+
56
+ ### C-07 Tested tools over custom ones
57
+ Use a maintained, widely used tool before building one. Build only what no tool
58
+ covers, and keep it small.
59
+
60
+ ### C-08 Products evolve together
61
+ A fix that applies to more than one product goes into the shared standard,
62
+ template or script — not into one product by hand. A product differs from the
63
+ others only with a written reason.
64
+
65
+ ### C-09 Hard rules are code
66
+ A rule that must never break is enforced by a linter, a check or a hook, not by
67
+ prose. When prose keeps getting broken, turn it into a check.
68
+
69
+ ### C-10 Secrets are never lost and never leaked
70
+ Every credential is backed up the moment it exists; no secret value goes into a
71
+ commit, a Markdown file or a chat reply.
72
+
73
+ ### C-11 Verified, one step at a time
74
+ Prove each step works before the next. Report failures as failures. Commit when
75
+ asked; push only when asked.
76
+
77
+ ### C-12 Reversible before irreversible
78
+ Prefer the change that can be undone. Deletes, force-pushes, store submissions,
79
+ production deploys and permission changes are confirmed first, every time.
80
+ Changing who can see, install or use what ships — a repo's visibility, a
81
+ licence, a package name, merging or splitting repos — is in this class: weigh it
82
+ before anything else, and when the owner picks an option, say what each one
83
+ loses first.
84
+
85
+ ### C-13 Users' money and data are handled exactly
86
+ Money in integer minor units; privacy promises match what the code does; store
87
+ claims match the app. Correctness beats speed here.
88
+
89
+ ### C-14 Facts, not assumptions
90
+ A request is not a fact. Every claim in it ("users want this", "it is slow",
91
+ "it is missing") is checked against the repo and the repo's data sources. A
92
+ claim with no fact behind it is an assumption. Work that rests on an assumption
93
+ does not start until the user agrees to it, in writing, as numbered terms.
94
+
95
+ ### C-15 Plain words
96
+ Short sentences and common words. No jargon unless the repo's wiki defines it.
97
+ Say what was checked, what was found and what happens next.
98
+
99
+ ## Weights
100
+
101
+ A repo's `.claude/canon.yaml` may raise or lower the weight of a principle under
102
+ `weigh.weights` (a game might weigh C-05 higher; a finance product C-13). It may
103
+ not remove one without a written reason, and every override shows up in
104
+ `canon check`.
@@ -0,0 +1,129 @@
1
+ # The `.context/` layout
2
+
3
+ Every repo keeps its non-code product material in `.context/`, in the same ten
4
+ folders. Each has one job, and none is a bucket meaning "everything else". A team
5
+ can replace this file with its own `context-layout.md` in a configured standards
6
+ folder.
7
+
8
+ ```
9
+ <repo>/.context/
10
+ ├── README.md what this is, and where to start
11
+ ├── tasks.md the ordered queue. The top item is the next action.
12
+ ├── raw/ sources you didn't write. Immutable.
13
+ ├── wiki/ everything you concluded. Schema: wiki-schema.md
14
+ ├── features/ what's next.
15
+ ├── designs/ what it looks like.
16
+ ├── listing/ what the stores show.
17
+ ├── marketing/ how it's sold.
18
+ ├── metrics/ the numbers.
19
+ ├── support/ what you tell users.
20
+ ├── legal/ what you promise.
21
+ └── ops/ how you run it.
22
+ ```
23
+
24
+ ## Rules
25
+
26
+ 1. **Ten folders, one job each.** There is no `documents/`, `research/`,
27
+ `architecture/` or `decisions/` folder: a research brief is a wiki synthesis
28
+ page, an architecture note is a wiki concept, an ADR is `wiki/decisions/`.
29
+ A product that truly needs another folder adds it in `.claude/canon.yaml`,
30
+ with the reason: `context: { folders: [{ folder: research, reason: … }] }`.
31
+ The ten cannot be removed.
32
+ 2. **`README.md` and `tasks.md` are the only files at `.context/` root.**
33
+ A repo names only what it uses. Its README, its `canon.yaml` and its docs never
34
+ list a folder, file or tool it does without; absence is shown by absence.
35
+ 3. **Nothing is created empty.** A folder appears with its first file — git does
36
+ not track empty folders, so a placeholder disappears on clone. `raw/` is the
37
+ one exception and carries a `.gitkeep`.
38
+ 4. **One home per artifact; everything else is an export.** Source art lives in
39
+ `designs/`; store images and press kits are generated from it.
40
+ 5. **Authored vs generated is visible.** A generated file is committed but never
41
+ hand-edited.
42
+
43
+ ## What a repo is expected to have
44
+
45
+ | Stage | Expected |
46
+ |---|---|
47
+ | any repo | `README.md` · `tasks.md` |
48
+ | uses the `docs` or `knowledge` module | + `raw/` · `wiki/` · `features/` |
49
+ | draws its UI | + `designs/` (optional; an estate can require it with a command) |
50
+ | has a store presence | + `listing/` |
51
+ | is live to users | + `marketing/` · `metrics/` · `support/` · `legal/` |
52
+ | once something runs | + `ops/` |
53
+
54
+ ## Naming and frontmatter
55
+
56
+ - Dated sources (`raw/`) → ISO date: `YYYY-MM-DD-slug.md`.
57
+ - Features → zero-padded number: `NNNN-slug.md`.
58
+ - Everything else is named by topic and edited in place.
59
+ - Frontmatter: `last-verified`, kebab-case keys. See the wiki schema.
60
+
61
+ ## Where each kind of document lives
62
+
63
+ Teams name documents many ways. Each name maps to one home; there is no
64
+ separate folder per name.
65
+
66
+ | Document | Home |
67
+ |---|---|
68
+ | ADR | `wiki/decisions/<topic>.md`, overwritten when the choice changes |
69
+ | RFC | `features/`; once accepted, the choice goes in `wiki/decisions/` |
70
+ | PRD | `features/`, `type: feature` |
71
+ | Experiment | `features/`, `type: experiment`; the result is a decision page |
72
+ | Initiative | `wiki/synthesis/`, linking its features and decisions |
73
+ | Finding | the dated data in `raw/`; what it means in `wiki/synthesis/` or a concept |
74
+ | Know-how | `wiki/concepts/`; `ops/` when it is a runbook |
75
+ | Bug | the issue tracker; a wiki concept only when it teaches a rule |
76
+ | Data source | `wiki/entities/` — see the wiki schema, "Data sources" |
77
+
78
+ If a document fits none of these for a real product, add a wiki type or a
79
+ folder in `.claude/canon.yaml` with its reason — not a new convention by hand.
80
+
81
+ ## `features/` — what is next
82
+
83
+ One page per feature, `NNNN-<slug>.md`:
84
+
85
+ ```markdown
86
+ ---
87
+ id: FEAT-0031
88
+ type: feature # feature | experiment | chore | platform
89
+ status: building # planned | building | shipped | shelved | superseded
90
+ last-verified: 2026-04-02
91
+ release: 3.4.0
92
+ ---
93
+ ## Summary · ## Motivation · ## Acceptance scenarios (Given/When/Then)
94
+ ## Out of scope · ## Open questions
95
+ ## Store copy
96
+ > One or two sentences users will read in the release notes.
97
+ ```
98
+
99
+ An experiment adds `## Hypothesis`, `## Metric` (a name from
100
+ `metrics/definitions.yml`) and `## Result` once it has run.
101
+
102
+ The wiki describes what *is*; `features/` describes what is *next*. A shipped
103
+ feature goes `status: shipped`.
104
+
105
+ ## `tasks.md` — open work only
106
+
107
+ ```markdown
108
+ # Tasks
109
+
110
+ ## Now <!-- position is the dependency; do in order -->
111
+ 1. [ ] T001 Add a screenshot mode `feat:0002` ~1d
112
+ 2. [ ] T002 Write the capture flows needs:T001 ~3h
113
+
114
+ ## Parallel <!-- independent, safe to batch -->
115
+ - [ ] T004 Move the SKU IDs into the wiki ~1h
116
+
117
+ ## Blocked
118
+ - [ ] T005 Submit the iOS build
119
+ blocked-by: store account access since:2026-09-16
120
+ unblock: ask for the role next-check:2026-10-06
121
+
122
+ ## Waiting <!-- deferred by time, not by a task -->
123
+ - [ ] T006 Second-language listing wait:2026-11-01
124
+ ```
125
+
126
+ Delete a task when it is done — the commit records it. No `## Done`, no session
127
+ notes. Cap: 100 lines. A blocker with no unblocking action and no check date is a
128
+ silent leak. A task that needs more than a line and a continuation is a
129
+ `features/` page.
@@ -0,0 +1,29 @@
1
+ # Development methods
2
+
3
+ canon does not run a method; it checks that the method left evidence a later
4
+ reader (or the weigh gate) can follow. A team replaces this file with its own
5
+ `dev-methods.md` in a configured standards folder.
6
+
7
+ | Method | The evidence it leaves |
8
+ |---|---|
9
+ | Spec-driven | A `features/` page with acceptance scenarios, written before the code. Code and tests cite its ID (`FEAT-0031`) or a wiki ID (`FLOW.…`, `DECISION.…`). |
10
+ | Test-driven | A test that failed before the change and passes after. Bug fixes start with the failing test. The test path goes in the feature page or decision. |
11
+ | Data-driven | A named metric in `metrics/definitions.yml`, the query that measured it, and a dated snapshot in `raw/`. The decision cites the snapshot, not a memory of a dashboard. |
12
+
13
+ ## Which one, when
14
+
15
+ - **New behaviour users see** → spec-driven: the feature page comes first.
16
+ - **Logic that can break** (money, parsing, data writes, a bug fix) → test-driven.
17
+ - **A bet on what users want** → data-driven: an experiment page with its metric
18
+ before the build, the result as a decision after.
19
+
20
+ They combine. A paywall change is a spec (what users see), tests (the price
21
+ logic) and an experiment (does conversion move).
22
+
23
+ ## Rules
24
+
25
+ 1. No evidence, not done. "It works" without a test, a scenario or a number is
26
+ an opinion.
27
+ 2. Evidence lives in the repo (C-03). A dashboard link alone is not evidence —
28
+ it changes; the snapshot in `raw/` does not.
29
+ 3. When a method keeps being skipped, make it a check (C-09), not a longer doc.
@@ -0,0 +1,71 @@
1
+ # Wiki — rules
2
+
3
+ `.context/wiki/` holds what an agent would get wrong without being told. `.context/raw/` holds
4
+ sources, never edited. Answer from the wiki, not from raw.
5
+
6
+ ## The test
7
+
8
+ Keep a line only if an agent would make a mistake without it. Never write what the
9
+ code, an HTML design, or `git log` already says. Describe what is true **now**:
10
+ history is git's job.
11
+
12
+ ## Folders
13
+
14
+ | Folder | Holds | Example |
15
+ |---|---|---|
16
+ | `concepts/` | a rule or invariant | `money-in-minor-units` |
17
+ | `entities/` | canonical values (prices, SKUs, limits) — the one home for each | `plan-pro` |
18
+ | `decisions/` | one file per topic: the current choice | `pricing` |
19
+ | `surfaces/` | a screen's notes: what its HTML can't show (only screens that have some) | `paywall` |
20
+ | `synthesis/` | research and cross-cutting analysis | `tax-table-verification-ay-2026-27` |
21
+
22
+ There is no page per screen: the HTML design is the screen spec. A screen gets a
23
+ `surfaces/<slug>.md` only when it has a constraint or decision invisible in its pixels;
24
+ the design set's notes button shows it, and `routes.js` sets `notes: null` for every
25
+ other screen. A user journey worth keeping is a concept.
26
+ A product may add a folder in `.claude/canon.yaml` under `wiki.types`, with a reason.
27
+
28
+ ## Pages
29
+
30
+ - Frontmatter: `last-verified: YYYY-MM-DD` is the only required field. `id` is kept
31
+ where code references it (`SOURCE.*`, entity keys).
32
+ - Write only the sections you have something to say in. No `TBD`, no `none yet`.
33
+ - One file per topic, edited in place. No dated names, no `v2`, no supersede chains.
34
+ - Caps: page 60 lines, decision 30. Synthesis is exempt.
35
+ - Link with `[[slug]]` (the file name without `.md`). `index.md` is one line per page.
36
+
37
+ ## Decisions
38
+
39
+ ```markdown
40
+ ---
41
+ last-verified: 2026-10-27
42
+ ---
43
+ # Pricing
44
+ **Choice:** annual plan only, ₹249 ([[plan-pro]]).
45
+ **Why:** monthly churn was 3× annual in the 2026-06 test.
46
+ **Rejected:** monthly plan (churn) · lifetime deal (no recurring revenue).
47
+ ```
48
+
49
+ When the choice changes, overwrite the file. `Rejected:` is what stops the same idea
50
+ being proposed again; keep it. Fix lists and audit results go in commit messages or
51
+ `CHANGELOG.md`, not here.
52
+
53
+ ## Data sources
54
+
55
+ Each tool that holds product data is one entity page, `id: SOURCE.<NAME>`, with a
56
+ `## How to query` section and a `SOURCE.<NAME>.ACCESS` row: `mcp: <server>`,
57
+ `skill: <name>`, `cli: <command>` (also listed in `doctor.tools`) or `manual: <where>`.
58
+ Queries are read-only, one or two per claim, with a row limit. Save counts and
59
+ rates to `raw/YYYY-MM-DD-<source>-<slug>.md`, never rows that name a person. Never
60
+ put a key or token on the page.
61
+
62
+ ## Not for
63
+
64
+ Code docs (they go next to the code) · tasks (`tasks.md`) · plans (`features/`) ·
65
+ chat logs · session notes · changelogs.
66
+
67
+ ## Checked by `canon check`
68
+
69
+ `wiki-frontmatter` (last-verified, placeholders, stale > 90 days) · `context-size`
70
+ (caps, dated decision names, no `flows/`) · `canonical-values` (a
71
+ price in a decision or screen note is held by an entity) · `sources`.
@@ -0,0 +1,23 @@
1
+ /* global module */
2
+ // This app's architecture rules, enforced by `canon check` (architecture module).
3
+ // canon wrote this starter once; it is yours now. Add the layers this app has
4
+ // and keep the why in a wiki concept page.
5
+ // Rule reference: https://github.com/sverweij/dependency-cruiser/blob/main/doc/rules-reference.md
6
+
7
+ /** @type {import('dependency-cruiser').IConfiguration} */
8
+ module.exports = {
9
+ extends: "../../.dependency-cruiser.base.cjs",
10
+ forbidden: [
11
+ {
12
+ name: "no-app-to-app",
13
+ comment: "An app never imports another app; share code through packages/.",
14
+ severity: "error",
15
+ from: {},
16
+ to: { path: "^\\.\\./[^./]" },
17
+ },
18
+ ],
19
+ options: {
20
+ // The level `canon ui` draws the architecture graph at: one box per match.
21
+ reporterOptions: { archi: { collapsePattern: "^src/[^/]+/[^/]+|^src/[^/]+|^[^/.][^/]*|^\\.\\./\\.\\./packages/[^/]+" } },
22
+ },
23
+ };