@erclx/canon 4.122.0 → 4.124.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/auto-ship/SKILL.md +7 -8
- package/claude/skills/auto-ship/references/tier-failures.md +7 -4
- package/claude/skills/backlog-triage/SKILL.md +1 -1
- package/claude/skills/codebase-layout/REQUIREMENT.md +1 -1
- package/claude/skills/codebase-layout/SKILL.md +1 -1
- package/claude/skills/create-rule/SKILL.md +5 -2
- package/claude/skills/design-taste/SKILL.md +1 -1
- package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
- package/claude/skills/draft-ready/SKILL.md +1 -1
- package/claude/skills/git-ship/SKILL.md +4 -3
- package/claude/skills/memory-capture/SKILL.md +14 -4
- package/claude/skills/memory-review/REQUIREMENT.md +4 -2
- package/claude/skills/memory-review/SKILL.md +18 -7
- package/claude/skills/memory-review/references/later-phases.md +7 -4
- package/claude/skills/memory-review/references/receipt-format.md +19 -3
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
- package/claude/skills/session-resume/SKILL.md +4 -3
- package/claude/skills/task-board/SKILL.md +1 -1
- package/claude/skills/task-board/references/archive.md +1 -1
- package/claude/skills/task-board/references/decline.md +1 -1
- package/claude/skills/test-first/REQUIREMENT.md +1 -1
- package/docs/agents/counts.md +3 -3
- package/docs/agents/drift-surfaces.md +2 -2
- package/docs/agents/rule-citations.md +4 -4
- package/docs/agents/tasks-archive.md +3 -3
- package/docs/agents/tasks-plans.md +5 -3
- package/docs/agents/tasks-validate.md +1 -1
- package/docs/agents/tasks.md +1 -1
- package/docs/agents/test-order.md +1 -1
- package/docs/index.md +3 -0
- package/docs/target-migrations.md +93 -0
- package/docs/target-projects.md +4 -216
- package/docs/target-scenarios.md +56 -0
- package/docs/target-sync.md +93 -0
- package/docs/workflow/ai-workflow.md +4 -203
- package/docs/workflow/index.md +2 -0
- package/docs/workflow/operating-model.md +18 -47
- package/docs/workflow/parallel-features.md +77 -0
- package/docs/workflow/skill-map.md +148 -0
- package/governance/renames.toml +34 -0
- package/governance/rules/{claude/555-tasks.md → canon/655-tasks.md} +2 -1
- package/governance/rules/{claude/560-diagrams.md → canon/660-diagrams.md} +1 -1
- package/governance/rules/{claude/562-session.md → canon/662-session.md} +1 -1
- package/governance/rules/code/000-code.md +21 -0
- package/governance/rules/lib/300-testing-ts.md +0 -4
- package/governance/rules/lib/330-testing-py.md +0 -4
- package/governance/rules/{claude/500-prose.md → writing/800-prose.md} +1 -1
- package/governance/rules/{claude/501-markdown.md → writing/801-markdown.md} +1 -1
- package/governance/rules/{claude/502-mermaid.md → writing/802-mermaid.md} +1 -1
- package/governance/stacks/base.toml +7 -6
- package/governance/stacks/node.toml +1 -1
- package/governance/stacks/python.toml +1 -1
- package/package.json +1 -1
- package/scripts/core/install-check.sh +3 -5
- package/src/claude/routing.ts +1 -1
- package/src/commands/gov.ts +1 -1
- package/src/commands/tasks.ts +39 -29
- package/src/gate/measures.ts +1 -6
- package/src/gate/stages.ts +1 -0
- package/src/gov/citations.ts +1 -1
- package/src/gov/list.ts +1 -1
- package/src/gov/restated.ts +2 -2
- package/src/init/steps.ts +1 -1
- package/src/labels/spelling.ts +1 -1
- package/src/records/prune.ts +1 -1
- package/src/shipped/references.ts +1 -1
- package/src/tasks/archive.ts +212 -105
- package/src/tasks/reach.ts +1 -1
- package/src/tasks/record.ts +59 -16
- package/src/tasks/validate.ts +1 -1
- package/standards/board.md +136 -0
- package/standards/commit.md +5 -0
- package/standards/groundwork.md +25 -36
- package/standards/index.md +2 -1
- package/standards/plan.md +20 -34
- package/standards/readme.md +8 -77
- package/standards/requirements.md +2 -2
- package/standards/rule.md +4 -6
- package/standards/tasks.md +18 -125
- package/standards/versioning.md +1 -1
- package/tooling/base/configs/commitlint.config.js +27 -1
- package/tooling/base/reference.md +2 -2
- package/tooling/claude/seeds/.claude/hooks/path-form.sh +1 -1
- package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +1 -1
- package/tooling/web/reference.md +1 -1
- package/governance/rules/core/000-constitution.md +0 -30
- package/governance/rules/core/020-concurrency.md +0 -22
- package/governance/rules/core/030-error-handling.md +0 -31
- package/governance/rules/core/040-performance.md +0 -20
- package/governance/rules/core/050-logging.md +0 -20
- package/governance/rules/core/060-naming.md +0 -19
- package/governance/rules/snippets/600-at-references.md +0 -9
- /package/governance/rules/{core/025-indexes.md → canon/601-indexes.md} +0 -0
- /package/governance/rules/{core/035-tasks.md → canon/602-tasks.md} +0 -0
- /package/governance/rules/{core/045-memory.md → canon/603-memory.md} +0 -0
- /package/governance/rules/{core/055-scratch.md → canon/604-scratch.md} +0 -0
- /package/governance/rules/{core/085-worktrees.md → canon/605-worktrees.md} +0 -0
- /package/governance/rules/{core/087-git.md → canon/606-git.md} +0 -0
- /package/governance/rules/{claude/510-context.md → canon/610-context.md} +0 -0
- /package/governance/rules/{claude/511-indexes.md → canon/611-indexes.md} +0 -0
- /package/governance/rules/{claude/520-wireframes.md → canon/620-wireframes.md} +0 -0
- /package/governance/rules/{claude/530-requirements.md → canon/630-requirements.md} +0 -0
- /package/governance/rules/{claude/540-architecture.md → canon/640-architecture.md} +0 -0
- /package/governance/rules/{claude/545-decisions.md → canon/645-decisions.md} +0 -0
- /package/governance/rules/{claude/550-design.md → canon/650-design.md} +0 -0
- /package/governance/rules/{claude/556-groundwork.md → canon/656-groundwork.md} +0 -0
- /package/governance/rules/{claude/557-intake.md → canon/657-intake.md} +0 -0
- /package/governance/rules/{claude/558-plan.md → canon/658-plan.md} +0 -0
- /package/governance/rules/{claude/559-memory.md → canon/659-memory.md} +0 -0
- /package/governance/rules/{claude/561-teach.md → canon/661-teach.md} +0 -0
- /package/governance/rules/{claude/563-ready.md → canon/663-ready.md} +0 -0
- /package/governance/rules/{core/005-behavior.md → claude/565-behavior.md} +0 -0
- /package/governance/rules/{core/015-output.md → claude/566-output.md} +0 -0
- /package/governance/rules/{core/070-planning.md → claude/567-planning.md} +0 -0
- /package/governance/rules/{core → code}/010-testing.md +0 -0
- /package/governance/rules/{ci → tooling}/700-ci-workflow.md +0 -0
- /package/governance/rules/{core/065-spelling.md → tooling/765-spelling.md} +0 -0
- /package/governance/rules/{core/075-dependencies.md → tooling/775-dependencies.md} +0 -0
- /package/governance/rules/{core/080-config-comments.md → tooling/780-config-comments.md} +0 -0
- /package/governance/rules/{core/090-code-comments.md → tooling/790-code-comments.md} +0 -0
- /package/governance/rules/{claude/580-readme.md → writing/880-readme.md} +0 -0
- /package/governance/rules/{claude/591-standard-authoring.md → writing/891-standard-authoring.md} +0 -0
package/standards/rule.md
CHANGED
|
@@ -32,7 +32,7 @@ Write both when both apply. A rule stating the directive and a skill stating how
|
|
|
32
32
|
## Location
|
|
33
33
|
|
|
34
34
|
- A toolkit-shipped rule lives at `.claude/rules/canon/<subdirectory>/<n>-<slug>.md`. The wrapper marks the file as toolkit-owned and replaced on sync, so a reader unfamiliar with the numbering convention still knows not to edit it.
|
|
35
|
-
- Subdirectories group by domain: `
|
|
35
|
+
- Subdirectories group by domain or audience: `code/`, `lang/`, `framework/`, `lib/`, `ui/`, `claude/`, `canon/`, `tooling/`, `writing/`
|
|
36
36
|
- `<n>` is a number from the band reserved for the rule's source and `<slug>` is a one-to-three-word kebab topic
|
|
37
37
|
- A rule the project authored itself lives at `.claude/rules/project/<subdirectory>/<n>-<slug>.md`, a sibling of `canon/` rather than nested inside it, keeping the same subdirectory names
|
|
38
38
|
- This repository's own toolkit-only rules, which never ship to a target, live at `.claude/rules/internal/<subdirectory>/<n>-<slug>.md`, a second sibling of `canon/`. See "Two sources numbering into one folder" below.
|
|
@@ -40,11 +40,9 @@ Write both when both apply. A rule stating the directive and a skill stating how
|
|
|
40
40
|
|
|
41
41
|
## Reserved numbers
|
|
42
42
|
|
|
43
|
-
`000-899` is reserved for a rule set that ships to targets
|
|
43
|
+
`000-899` is reserved for a rule set that ships to targets, and the nine subdirectories above divide it at 100 per subdirectory, in the order listed. No band is left over, so a subdirectory a shipped set adds later joins an existing band or takes one a retired subdirectory freed.
|
|
44
44
|
|
|
45
|
-
`
|
|
46
|
-
|
|
47
|
-
A project-authored rule takes `900-999`, one sequence across every subdirectory under `.claude/rules/project/`. Scanning for a free number instead is what fails, because a shipped set fills its own band release by release, so what reads as free today is what a later release lands on. One target authored `claude/561-self-check.md` on a day nothing shipped at 561, met `claude/561-teach.md` on its next install, and now reads two numbers differently from everywhere else.
|
|
45
|
+
A project-authored rule takes `900-999`, one sequence across every subdirectory under `.claude/rules/project/`. Scanning for a free number instead is what fails, because a shipped set fills its own band release by release, so what reads as free today is what a later release lands on. One target authored `claude/561-self-check.md` on a day nothing shipped at 561, met the shipped teach rule, then numbered 561, on its next install, and now reads two numbers differently from everywhere else.
|
|
48
46
|
|
|
49
47
|
The cost is that a project-authored rule's leading digit stops naming its domain. Its subdirectory names it instead, and install preserves that either way. What a shared band costs is worse: a session that loads two rules reading as one number, with nothing in the folder to say which is which.
|
|
50
48
|
|
|
@@ -54,7 +52,7 @@ The cost is that a project-authored rule's leading digit stops naming its domain
|
|
|
54
52
|
|
|
55
53
|
The reservation above divides one pair, being a shipped set against the rules a project wrote for itself. A third source, a rule set held back from targets and installed only where it was authored, needs its own division too. This repository is the one place all three sources exist at once, and it divides the third pair two ways at once rather than one: `canon/` and `internal/` separate a shipped rule from an internal one by location, the same way `project/` separates a project-authored one, and within each subdirectory the numbering still divides by source as well, one source taking the top of the band and the other the gaps between the tens.
|
|
56
54
|
|
|
57
|
-
The numbering half stays because location alone does not carry to a reader who only sees the number, such as one comparing `
|
|
55
|
+
The numbering half stays because location alone does not carry to a reader who only sees the number, such as one comparing `claude/567-planning.md` against a citation written before the rules moved into `canon/`.
|
|
58
56
|
|
|
59
57
|
The collision this prevents is silent. Two rules that resolve to the same `<n>-<slug>` path leave one file in the installed folder, and neither the install nor the session that reads it reports which source lost. Nothing checks a division outside the reserved bands, so it holds only while both sources follow it. Separating `canon/` from `internal/` by folder removes the filename-collision case specifically, since the two no longer install to the same directory, but the number still carries the source signal for a reader who has only the number in view.
|
|
60
58
|
|
package/standards/tasks.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Tasks reference
|
|
3
|
-
description: Folder layout, filename convention,
|
|
3
|
+
description: Folder layout, filename convention, file format, origin lines, and archiving for task files under .canon/tasks/
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Tasks reference
|
|
@@ -13,10 +13,11 @@ The folder is gitignored. Board state changes when work ships rather than when a
|
|
|
13
13
|
|
|
14
14
|
## Scope
|
|
15
15
|
|
|
16
|
-
Governs the task
|
|
16
|
+
Governs the task files under `.canon/tasks/`: folder layout, filenames, frontmatter, file format, origin lines, archiving, and declining.
|
|
17
17
|
|
|
18
18
|
Does not govern:
|
|
19
19
|
|
|
20
|
+
- Execution order, readiness groups, the backlog, and the generated index beside the tasks: `board.md`
|
|
20
21
|
- The plan file a task cites, its sections, and its answer contract: `plan.md`
|
|
21
22
|
- Phase-label format and which surfaces a label may appear on: `versioning.md`
|
|
22
23
|
- Architectural reasoning that outlives a task: `architecture.md`
|
|
@@ -37,114 +38,12 @@ Does not govern:
|
|
|
37
38
|
└── v13.0-toolkit-drift.md # canon-allow-reference: illustrates the vXX.Y-slug filename this section defines
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
`canon tasks list` reports each file's readiness from those two surfaces, so a reader never infers it from the folder.
|
|
41
|
-
|
|
42
41
|
One file per task is what keeps the board safe under parallel sessions. Two sessions working different tasks never write the same file, which matters because a gitignored board has no history to recover a clobbered write from.
|
|
43
42
|
|
|
44
|
-
Siblings sit in the folder without being tasks, and each earns its place by being governed somewhere. `index.md`, `priority.md`, and `backlog.md` are governed
|
|
45
|
-
|
|
46
|
-
`backlog.md` is optional too. A project small enough that every task it holds would be planned soon carries none, and the ordering rules below then describe the whole board.
|
|
47
|
-
|
|
48
|
-
The handoff takes one file per session for the reason a task does. A single shared path puts two sessions closing near each other on one file that neither can watch the other write, and the loser leaves no trace on a board with no history behind it.
|
|
49
|
-
|
|
50
|
-
`index.md` is generated from sibling frontmatter. The folder is gitignored, so the whole-repo index walk skips it and a hook passing the changed path regenerates it instead. Never hand-edit it.
|
|
51
|
-
|
|
52
|
-
The catalog is the one reader that filters nothing, so it carries a row per sibling alongside the tasks. That is what a folder catalog is for, and the handoffs are what make it worth stating: a board accumulates one row per session that ever wrote one, with nothing pruning them. Anything reading the catalog as the backlog therefore does its own filtering, and a reader that takes every row as a task reports the handoffs as queued work.
|
|
43
|
+
Siblings sit in the folder without being tasks, and each earns its place by being governed somewhere. `index.md`, `priority.md`, and `backlog.md` are governed by `board.md`. Every `session-` file is a pre-compaction handoff governed by `session.md`, and each is optional: a project whose sessions never approach a compaction carries none. Anything filtering the folder to tasks skips all of them, so a name outside the set is a task whatever it holds.
|
|
53
44
|
|
|
54
45
|
The `task-board` skill creates and archives task files, and the archive carries the task's plan with it. `context-fold` marks outcomes `[x]` in an existing file. Neither does the other's job.
|
|
55
46
|
|
|
56
|
-
## Ordering
|
|
57
|
-
|
|
58
|
-
`priority.md` carries execution order and what each task is waiting on. The generated index sorts by filename and says nothing about order, so without this file board state gets reconstructed by hand every session. Why a row sits where it does inside its group is stated on the row itself, in the column that already carries what the task is waiting on, one line per row.
|
|
59
|
-
|
|
60
|
-
That cell is the only home sequencing rationale has. Rationale spanning several rows, why one group of work runs before another, is carried by nothing and reaches a later session only through whoever remembers it. Naming the gap is deliberate: a second document holding it would be the version-sequencing surface this board replaced, and a row already states what it waits on, which is the part of the reasoning a reader acts on.
|
|
61
|
-
|
|
62
|
-
Group tasks by readiness rather than by status, one row per task, under the columns each group fixes below. Keep it to links and blockers: tables, plus at most one sentence per section. A paragraph in `priority.md` is a defect whatever it says. Stating the shape this way is what lets a single diff fail, since a size cap only trips after the fact and every addition looks defensible on its own.
|
|
63
|
-
|
|
64
|
-
Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and `## Needs a plan`, in that order. The names are the contract rather than a suggestion, because a board grouped by readiness under names of its own satisfies every other rule here and still reads as empty to anything counting rows under a heading. Add no fourth group. A task belongs to exactly one, and the tests are read in order.
|
|
65
|
-
|
|
66
|
-
- `## Run now`: a written plan covers every open outcome, and the task carries no reason it cannot start. A collision against the files something already running touches is one such reason, and the `Touches` column is what states it. A worker is handed a task from this group alone.
|
|
67
|
-
- `## Up next`: a written plan exists, and the task carries a stated reason it cannot start. The `Waiting on` column names that reason.
|
|
68
|
-
- `## Needs a plan`: everything else. The task has no plan, or the plan it carries no longer describes the work.
|
|
69
|
-
|
|
70
|
-
Each group fixes its own columns, which follow from the test above it rather than from preference. Neither half of the `## Run now` test is checkable without the file set and the plan sitting beside the task.
|
|
71
|
-
|
|
72
|
-
A `Touches` cell is copied from its plan's own list, so it states what the branch sets out to write rather than a bound on it, and a branch outgrows it while the row still reads as it did at dispatch. Correct the cell from the branch rather than from the plan once one is running, since the plan is the prediction that already went stale and only the diff says what was written. `canon tasks plan-reach <plan>` reads that diff against every live plan and every cell in this group, and the row's owner is the one who writes the correction: a worker never edits this board.
|
|
73
|
-
|
|
74
|
-
Row position inside `## Needs a plan` is the order those tasks get planned in, top first. The three tests answer whether a task can start, which is mechanical, and none of them answers which task is worth starting, which is a judgment no column holds. Position is where that judgment is recorded, so the top row is the answer to what to plan next and a reader needs no other surface to get it. The other two groups take the same reading, and it costs them little, since a group holding what is already planned is short by construction.
|
|
75
|
-
|
|
76
|
-
Position alone carries it, and no rank column exists. A number beside each row is a second thing to keep in step with the order it duplicates, and the file is edited by one session at a time, so the order the rows are written in is already unambiguous. State on each row why it sits where it does, in the same cell that carries what it is waiting on. A position with no stated reason is re-derived from memory by the next session, which is the failure the ordering replaces rather than moves.
|
|
77
|
-
|
|
78
|
-
The `Waiting on` column under `## Up next` carries that reason in one of three forms. `## Needs a plan` states no file set at all, because a task with no plan has no bounded one to state. A group with no rows keeps its heading and its header row.
|
|
79
|
-
|
|
80
|
-
Under `## Up next` a collision names the file held by the task already running, a sibling task names that task, and an external condition names both the condition and what would satisfy it. Naming what would satisfy it is what separates a blocked row from one nobody has examined, so a cell stating a condition with no way out of it fails the test. The header text is the contract the way the group names are, because anything reading the cell resolves the column by header rather than by position.
|
|
81
|
-
|
|
82
|
-
Under `## Needs a plan` the cell carries two halves and each takes one clause: what the task needs before it can be planned, then why it sits at this position. The second clause is comparative, and it names what the row is ranked against in one of two forms: a sibling row, or the class of rows it sits in. The row `leads`, `heads`, `opens`, `closes`, `trails`, `precedes`, `follows`, or `outranks` whichever it names, or `sits under`, `above`, or `below` it. Either form puts something other than this row in the clause, which is what makes the position readable by anyone but its author.
|
|
83
|
-
|
|
84
|
-
Why the task matters is not that claim, and it is what the cell drifts into. A reason naming no other row ranks against nothing, so every row reads defensible on its own and the order records when each was filed. The comparison replaces that reason rather than joining it, since the cell still takes two clauses and no third one is licensed by naming a rival in the second. A cell running past that is the paragraph this file already deletes, arriving one row at a time rather than all at once, and the group is where it costs the most, since it holds the rows nobody has read recently and is the longest group on any board that needs a backlog at all.
|
|
85
|
-
|
|
86
|
-
`canon tasks validate` reads that clause back, so a cell phrased comparatively and unusually reports as unranked. The vocabulary above is the whole of what it recognizes, and widening it is a change to the check rather than something the cell may decide for itself.
|
|
87
|
-
|
|
88
|
-
```markdown
|
|
89
|
-
---
|
|
90
|
-
title: Priority
|
|
91
|
-
description: One line on what the board covers
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
# Priority
|
|
95
|
-
|
|
96
|
-
## Run now
|
|
97
|
-
|
|
98
|
-
| Task | Touches | Plan |
|
|
99
|
-
| ------------------------------- | ----------------------- | ------------------------------------ |
|
|
100
|
-
| [vXX.Y <slug>](vXX.Y-<slug>.md) | <what the task touches> | [<slug>](../plans/feature-<slug>.md) |
|
|
101
|
-
|
|
102
|
-
## Up next
|
|
103
|
-
|
|
104
|
-
| Task | Touches | Waiting on |
|
|
105
|
-
| ---- | ------- | ---------- |
|
|
106
|
-
|
|
107
|
-
## Needs a plan
|
|
108
|
-
|
|
109
|
-
| Task | Waiting on |
|
|
110
|
-
| ------------------------------- | --------------------------------------------------------------------------------- |
|
|
111
|
-
| [vXX.Y <slug>](vXX.Y-<slug>.md) | <what it needs before it can be planned, and which row or class it ranks against> |
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
The tests live here so the board does not carry them. Writing them as a sentence under each heading produces the paragraph the rule above deletes, and a criterion with no home gets restated from memory every time the board is touched.
|
|
115
|
-
|
|
116
|
-
## The backlog
|
|
117
|
-
|
|
118
|
-
A task sits on the board when it would plausibly be planned within the next few waves, and on `backlog.md` otherwise. The call is a judgment, so restate it whenever the board is swept rather than making it once: a backlogged task rises when the work in front of it lands or the world changes under it, and a board row falls to the backlog when it stops being near-term.
|
|
119
|
-
|
|
120
|
-
A mechanical test over age or origin was the alternative and neither predicts what gets picked next, which is the judgment the ordering exists to carry. Leaving everything on the board is the other alternative, and it is what produces a group too long to rank, where the ordering means nothing because nobody can hold the whole list in one reading.
|
|
121
|
-
|
|
122
|
-
What the split buys is that the board is short enough for its order to be read, and what it costs is a second surface to keep. That trade only pays while the backlog stays honest about what it is, which is why it carries no order, no groups, and no readiness claim.
|
|
123
|
-
|
|
124
|
-
Nothing is deleted. A backlogged task keeps its file, its findings, and its frontmatter, and the backlog row is a pointer at that file. The folder is gitignored and has no history behind it, so a row dropped without landing somewhere readable is gone with nothing to recover it from.
|
|
125
|
-
|
|
126
|
-
The backlog is a flat list of links under one heading, sorted by filename. Sorting mechanically is what keeps it from reading as a queue: the order is the same order the index already sorts in, so no position on it means anything.
|
|
127
|
-
|
|
128
|
-
```markdown
|
|
129
|
-
---
|
|
130
|
-
title: Backlog
|
|
131
|
-
description: One line on what the backlog holds
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
# Backlog
|
|
135
|
-
|
|
136
|
-
Unordered. Nothing here is scheduled, and a task rises to `priority.md` when it becomes near-term.
|
|
137
|
-
|
|
138
|
-
- [vXX.Y <slug>](vXX.Y-<slug>.md)
|
|
139
|
-
- [vXX.Y <slug>](vXX.Y-<slug>.md)
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Add no fourth readiness group in place of this file. The three group names are the contract, and a backlog is a separate surface rather than a group because it makes no readiness claim at all: it says nobody has scheduled the task, which is a fact about attention rather than about whether the work can start.
|
|
143
|
-
|
|
144
|
-
## Validation
|
|
145
|
-
|
|
146
|
-
`canon tasks validate` reads the board against the tree, and what it checks, what it refuses on, and what it reports are at `canon docs tasks`. Run it when the readiness claim is made rather than on a schedule, since the board is gitignored per-machine scratch and no shared moment exists to hang it on.
|
|
147
|
-
|
|
148
47
|
## Filenames
|
|
149
48
|
|
|
150
49
|
`vXX.Y-<slug>.md`, where the version is the phase label zero-padded to two digits and the slug is kebab-case.
|
|
@@ -171,7 +70,7 @@ Two headings, `## Outcomes` and `## Findings`. Outcomes are future and checkable
|
|
|
171
70
|
|
|
172
71
|
Add no third heading. Status stays inline on an outcome rather than becoming an "In progress" section.
|
|
173
72
|
|
|
174
|
-
Size the outcomes so one pull request closes all of them
|
|
73
|
+
Size the outcomes so one pull request closes all of them, and split the task before handing it off rather than after. A task closes whole or not at all, so outcomes spanning two pull requests leave the board showing in-progress work no branch carries.
|
|
175
74
|
|
|
176
75
|
A sliced task is the one allowed exception: a task the operator decided to ship across several pull requests on purpose, one slice each. Its `Pull request:` line lists every slice, so the board records which merged work covered which outcomes, and it closes whole when the last slice's merge finds every outcome ticked.
|
|
177
76
|
|
|
@@ -215,29 +114,27 @@ Every task names where it came from, through a `Plan:`, `Groundwork:`, `Intake:`
|
|
|
215
114
|
|
|
216
115
|
A task with no origin is either lost context or work nobody decided to do. The invariant runs both ways, and the second direction is the one that bites: a groundwork track, an intake folder, or an open issue that no task points at is work already decided and on its way to being forgotten.
|
|
217
116
|
|
|
218
|
-
An intake folder answers that direction at folder scope rather than item scope
|
|
117
|
+
An intake folder answers that direction at folder scope rather than item scope. A folder with every item answered and no task citing it, live, archived, or declined, is a dump nobody acted on.
|
|
219
118
|
|
|
220
119
|
`Plan:`, `Groundwork:`, and `Intake:` name their target as a markdown link whose text is the file or folder stem, so the line resolves on a ctrl-click the way `priority.md` rows already do. Write the path relative to `.canon/tasks/`, which makes it `../plans/`, `../groundwork/`, and `../intake/`. A path written from the project root renders as a link and resolves to nothing in an editor rooted at the project. `Ready:` names the ready folder a task's plan copies from, as a link to `../ready/<nn>-<slug>/` with the trailing slash a folder carries. Include it only when the folder exists. `canon tasks archive` reads it to move the folder, and falls back to a `.canon/ready/<nn>-<slug>/` path in the plan when a task carries no line.
|
|
221
120
|
|
|
222
121
|
`Issue:` stays a bare `#NNN`, since an issue number is not a path and a full URL would write the remote into a gitignored file.
|
|
223
122
|
|
|
224
|
-
Phase-label format and where labels may appear are governed by `standards/versioning.md`.
|
|
225
|
-
|
|
226
123
|
`Plan:` points at `../plans/feature-<slug>.md` while the task is open. Once the task ships and the plan is archived, it points at `../plans/archive/feature-<slug>.md`, and at `../../plans/archive/feature-<slug>.md` once the task itself is archived a folder deeper. Retarget both halves of the link rather than dropping it, so a completed task still leads to the reasoning behind it.
|
|
227
124
|
|
|
228
|
-
A project that archived plans before the folder nested under `.canon/plans/` holds closed tasks pointing at `../plans-archive
|
|
125
|
+
A project that archived plans before the folder nested under `.canon/plans/` holds closed tasks pointing at `../plans-archive/` or `../.tmp/plans-archive/`. Leave those pointers where they are, since each resolves against the files it names and a task retargeted without its plan moving leads nowhere.
|
|
229
126
|
|
|
230
|
-
One plan per task. A plan cited by two tasks is a misfile rather than a shape to design for
|
|
127
|
+
One plan per task. A plan cited by two tasks is a misfile rather than a shape to design for.
|
|
231
128
|
|
|
232
|
-
`canon tasks plan-link <task> <plan>` writes or corrects the `Plan:` line
|
|
129
|
+
`canon tasks plan-link <task> <plan>` writes or corrects the `Plan:` line, so the line is a mechanical write rather than hand-edited markdown.
|
|
233
130
|
|
|
234
131
|
`Groundwork:` points at `../groundwork/<slug>/`, the folder `plan-groundwork` fills. It names the surface it points at the way `Plan:` does. Use this key alone. `Research record` and `Decision record` are earlier spellings of the same thing and both convert to it.
|
|
235
132
|
|
|
236
|
-
`Intake:` points at `../intake/<slug>/`, the folder an intake pass fills. Use it rather than `Groundwork:`,
|
|
133
|
+
`Intake:` points at `../intake/<slug>/`, the folder an intake pass fills. Use it rather than `Groundwork:`, so the line records which kind of pass produced the task. It names the folder rather than an item inside it, and the item numbers belong in that task's `## Findings`.
|
|
237
134
|
|
|
238
|
-
`Pull request:` records which pull requests carry the task's work, each as a bare `#NNN` the way `Issue:` does. It lists every pull request that shipped part of the task, oldest first and separated by commas, as in `Pull request: #NNN, #NNN`, and a task shipped whole lists one. It is not an origin, so a task without one is well-formed. `git-pr`
|
|
135
|
+
`Pull request:` records which pull requests carry the task's work, each as a bare `#NNN` the way `Issue:` does. It lists every pull request that shipped part of the task, oldest first and separated by commas, as in `Pull request: #NNN, #NNN`, and a task shipped whole lists one. It is not an origin, so a task without one is well-formed. `git-pr` appends to it when a pull request opens.
|
|
239
136
|
|
|
240
|
-
The line is what lets a merge close its own task.
|
|
137
|
+
The line is what lets a merge close its own task. `canon tasks archive --pull-request <n>` finds the task by any number the line lists and archives it only on the last. One pull request, one task: two tasks naming the same number refuse to archive rather than both moving.
|
|
241
138
|
|
|
242
139
|
## What goes in
|
|
243
140
|
|
|
@@ -257,26 +154,22 @@ The line is what lets a merge close its own task. Every merge on `main` is a squ
|
|
|
257
154
|
|
|
258
155
|
## Archiving
|
|
259
156
|
|
|
260
|
-
Never delete a task file. A shipped task moves to `.canon/tasks/archive/` under its own name, and the live index regenerates without it. `canon tasks archive` owns that move, and what it does and what it refuses on are at `canon docs tasks`.
|
|
261
|
-
|
|
262
|
-
The archive nests inside `.canon/tasks/` rather than sitting beside it as a flat `.claude/task-archive/`. Nesting is what lets a reader tell the two shapes apart on sight: the flat sibling is what a binary predating this convention still writes, so meeting one names an older checkout rather than a second archive to reconcile against this one.
|
|
263
|
-
|
|
264
|
-
One destination rather than a per-project choice is what lets the move happen without asking. It mirrors the plans archive at `.canon/plans/archive/`, sitting inside the folder it archives the same way, and it inherits the board's own ignore entry rather than needing one of its own. The cost is that an archived task does not appear in diffs, which is the cost the live board already carries.
|
|
157
|
+
Never delete a task file. A shipped task moves to `.canon/tasks/archive/` under its own name, and the live index regenerates without it. `canon tasks archive` owns that move, and what it does and what it refuses on are at `canon docs tasks-archive`.
|
|
265
158
|
|
|
266
|
-
|
|
159
|
+
The archive nests inside `.canon/tasks/` rather than sitting beside it as a flat `.claude/task-archive/`, which is what a binary predating this convention still writes. Meeting the flat sibling names an older checkout rather than a second archive to reconcile.
|
|
267
160
|
|
|
268
|
-
|
|
161
|
+
Archiving a task archives its plan alongside it, when the closing task is that plan's last live citation. The archived task's `Plan:` line is retargeted at `../../plans/archive/feature-<slug>.md`. The ready folder its `Ready:` line names moves with the plan to `.canon/ready/archive/<nn>-<slug>/`, and both pointers to it are retargeted. A plan several tasks share stays live with its ready folder, and the task archives anyway.
|
|
269
162
|
|
|
270
|
-
A task with an open outcome stays on the board, and so does its plan. Close it, or cut it from the task when the work is being abandoned, so what was dropped is recorded rather than inferred from an archived file. Cutting means striking the outcome's body: `- ~~<outcome>~~ <why>`.
|
|
163
|
+
A task with an open outcome stays on the board, and so does its plan. Close it, or cut it from the task when the work is being abandoned, so what was dropped is recorded rather than inferred from an archived file. Cutting means striking the outcome's body: `- ~~<outcome>~~ <why>`. A struck body reads as cut whatever its checkbox holds, so a task carrying only cut outcomes still archives.
|
|
271
164
|
|
|
272
165
|
## Declining
|
|
273
166
|
|
|
274
167
|
A task decided against moves to `.canon/tasks/declined/` rather than `.canon/tasks/archive/`. The two folders answer different questions: archive means the work shipped, declined means somebody decided against doing it. Neither reading fits a task that is merely unscheduled, which stays on `backlog.md` rather than moving anywhere, since nobody has decided against it and it may still rise when the board has room.
|
|
275
168
|
|
|
276
|
-
`canon tasks decline` carries no outcome-state gate
|
|
169
|
+
`canon tasks decline` carries no outcome-state gate, so a task can be decided against at any outcome state, open outcomes included.
|
|
277
170
|
|
|
278
171
|
The decision is recorded on the task itself with a `Declined:` line, in the `Plan:`/`Pull request:` family: `Declined: <reason>, <who> on <YYYY-MM-DD>`. It anchors the same way `Pull request:` does, after the last origin line the task carries. The line is free prose after the colon, since it names no file to link.
|
|
279
172
|
|
|
280
173
|
Declining a task moves its plan alongside it the same way archiving does, when the declining task is that plan's last live citation. A plan several tasks share stays where it is, and a declined task's plan lands in `.canon/plans/archive/` indistinguishable from a shipped one by folder alone. The task file under `.canon/tasks/declined/` is what records which it was.
|
|
281
174
|
|
|
282
|
-
The move clears whichever of `priority.md` or `backlog.md` holds the task's row
|
|
175
|
+
The move clears whichever of `priority.md` or `backlog.md` holds the task's row.
|
package/standards/versioning.md
CHANGED
|
@@ -14,7 +14,7 @@ Governs the two version namespaces, phase labels and semver tags, and which surf
|
|
|
14
14
|
Does not govern:
|
|
15
15
|
|
|
16
16
|
- The format of a phase label, which is project-specific by the rule below
|
|
17
|
-
- Task filenames and
|
|
17
|
+
- Task filenames and folder layout: `tasks.md`
|
|
18
18
|
- Commit subject, branch name, and pull request title format: `commit.md`, `branch.md`, and `pr.md`
|
|
19
19
|
- Voice, rhythm, and sentence construction in any text carrying a label: the `write-human` skill
|
|
20
20
|
- Punctuation, formatting, and word choice in any text carrying a label: `markdown.md`
|
|
@@ -22,12 +22,38 @@ const subjectFirstWordCase = (parsed) => {
|
|
|
22
22
|
]
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
const CO_AUTHOR_TRAILER = /^co-authored-by:/i
|
|
26
|
+
const CLAUDE_OR_ANTHROPIC = /\b(claude|anthropic)\b/i
|
|
27
|
+
|
|
28
|
+
// Reads raw rather than footer, since the parser files a lone trailer under
|
|
29
|
+
// body and leaves footer null.
|
|
30
|
+
const noClaudeCoAuthor = (parsed) => {
|
|
31
|
+
const offending = (parsed.raw ?? '')
|
|
32
|
+
.split('\n')
|
|
33
|
+
.find(
|
|
34
|
+
(line) => CO_AUTHOR_TRAILER.test(line) && CLAUDE_OR_ANTHROPIC.test(line),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return [
|
|
38
|
+
offending === undefined,
|
|
39
|
+
`remove the co-author trailer crediting Claude or Anthropic: ${offending}`,
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
25
43
|
const config = {
|
|
26
44
|
extends: ['@commitlint/config-conventional'],
|
|
27
|
-
plugins: [
|
|
45
|
+
plugins: [
|
|
46
|
+
{
|
|
47
|
+
rules: {
|
|
48
|
+
'subject-first-word-case': subjectFirstWordCase,
|
|
49
|
+
'no-claude-co-author': noClaudeCoAuthor,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
],
|
|
28
53
|
rules: {
|
|
29
54
|
'subject-case': [0],
|
|
30
55
|
'subject-first-word-case': [2, 'always'],
|
|
56
|
+
'no-claude-co-author': [2, 'always'],
|
|
31
57
|
'header-max-length': [2, 'always', 72],
|
|
32
58
|
'scope-case': [2, 'always', 'lower-case'],
|
|
33
59
|
'subject-full-stop': [2, 'never', '.'],
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
The base layer covers every project the toolkit scaffolds, whatever language sits on top. It ships formatting, spelling, shell linting, conventional commits, git hooks, CI, and one maintenance script. Every other stack extends it, so a decision made here is one every stack inherits.
|
|
6
6
|
|
|
7
|
-
A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs target-
|
|
7
|
+
A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs target-scenarios` carries the recipe.
|
|
8
8
|
|
|
9
9
|
## What ships as golden configs
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ Golden config files live in `tooling/base/configs/` and are copied into the targ
|
|
|
13
13
|
- `.prettierrc`: `semi: false`, `singleQuote: true`, plus a parser override per non-standard extension (`.mdx` to `markdown`).
|
|
14
14
|
- `.shellcheckrc`: `external-sources=true`. Required for shellcheck to follow `source` directives.
|
|
15
15
|
- `.editorconfig`: `root = true`, with an `[*.sh]` block setting `indent_style = space` and `indent_size = 2`.
|
|
16
|
-
- `commitlint.config.js`: ESM default export extending `@commitlint/config-conventional`. Rules are `header-max-length: 72`, `scope-case: lower-case`, `subject-full-stop: never`,
|
|
16
|
+
- `commitlint.config.js`: ESM default export extending `@commitlint/config-conventional`. Rules are `header-max-length: 72`, `scope-case: lower-case`, `subject-full-stop: never`, `subject-case` disabled, and a local `no-claude-co-author` rule refusing a `Co-authored-by` trailer that names Claude or Anthropic.
|
|
17
17
|
- `.husky/`: `pre-commit`, `commit-msg`, `pre-push`, `post-merge`, `post-rewrite`.
|
|
18
18
|
- `.vscode/extensions.json` and `.vscode/settings.json`: editor wiring for Prettier, cspell, shfmt, and shellcheck.
|
|
19
19
|
- `scripts/verify.sh`: the maintenance entry point behind `check`.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# to infer on every response and hands the answer back instead.
|
|
10
10
|
#
|
|
11
11
|
# The entrypoint branch (bare vs. `file://` link) stays prose in
|
|
12
|
-
# governance/rules/
|
|
12
|
+
# governance/rules/claude/566-output.md. CLAUDE_CODE_ENTRYPOINT is not among
|
|
13
13
|
# the environment variables Claude Code documents as passed to a hook
|
|
14
14
|
# subprocess, unlike CLAUDE_PROJECT_DIR, so a hook cannot read it reliably.
|
|
15
15
|
#
|
|
@@ -57,5 +57,5 @@ marker="$marker_dir/$key"
|
|
|
57
57
|
mkdir -p "$marker_dir"
|
|
58
58
|
: >"$marker"
|
|
59
59
|
|
|
60
|
-
msg='Temporary file write outside the project scratch folder. Write temp files to .canon/tmp/<slug>/ in the project root, or .claude/.tmp/<slug>/ where the project carries no .canon/ root, not system temp. See the Scratch rule (
|
|
60
|
+
msg='Temporary file write outside the project scratch folder. Write temp files to .canon/tmp/<slug>/ in the project root, or .claude/.tmp/<slug>/ where the project carries no .canon/ root, not system temp. See the Scratch rule (604-scratch, under canon/ in your installed governance rules).'
|
|
61
61
|
jq -nc --arg msg "$msg" '{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:$msg}}'
|
package/tooling/web/reference.md
CHANGED
|
@@ -16,7 +16,7 @@ Golden config files live in `tooling/web/configs/` and are copied into the targe
|
|
|
16
16
|
- `scripts/screenshot.sh`: sources `scripts/lib/preview-server.sh`, then runs the capture against the served preview.
|
|
17
17
|
- `scripts/lib/preview-server.sh`: sourced, never executed. Builds, serves on `PREVIEW_PORT`, blocks until the port answers, and traps the whole process group on exit, including the detached grandchild `lsof` finds. Both capture scripts source it so the startup lives once.
|
|
18
18
|
- `scripts/readme-screenshot.sh`: captures one case under `SCREENSHOT_FILTER` and copies its light and dark frames to `assets/evidence/readme/`. `README_FILTER` ships empty with `header/1280` as its example, and the script exits 1 until a project fills it, since a shipped default would capture the wrong part of the page in every project but one. Its copy reads from `screenshots/<hostname>/`, which is where the harness writes.
|
|
19
|
-
- `.github/workflows/readme-screenshot.yml`: refreshes that frame on a pull request and commits it back to the branch. The path list ships as `REPLACE_WITH_PROJECT_PATHS`, and the job's first step after checkout exits 1 while it stays, since a job that never fires leaves no run and no diff to notice. The workflow's own path is in the list so the installing pull request reaches that step. When a commit-back is right and when a report is, `governance/rules/
|
|
19
|
+
- `.github/workflows/readme-screenshot.yml`: refreshes that frame on a pull request and commits it back to the branch. The path list ships as `REPLACE_WITH_PROJECT_PATHS`, and the job's first step after checkout exits 1 while it stays, since a job that never fires leaves no run and no diff to notice. The workflow's own path is in the list so the installing pull request reaches that step. When a commit-back is right and when a report is, `governance/rules/tooling/700-ci-workflow.md` states the test.
|
|
20
20
|
- `.vscode/extensions.json` and `.vscode/settings.json`: editor wiring for ESLint, Tailwind, Playwright, Vitest.
|
|
21
21
|
- `.github/workflows/verify.yml`: `static-checks`, `unit-tests`, `build-verify`, and `e2e-tests` jobs.
|
|
22
22
|
- `scripts/verify.sh`: extends base verify with typecheck, lint, unit tests, and build in the full order. Its last stage runs `scripts/check-card-exclusion.sh` whenever that file is installed, which puts the social card route's build exclusion on the default path rather than behind a flag nobody passes. The stage tests for the script rather than for a framework, so this layer owns when the check runs and the stack shipping a card route owns what it reads. The astro reference carries the route itself.
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Define senior architect persona and core philosophy
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Role persona
|
|
6
|
-
|
|
7
|
-
You are a Senior Principal Architect.
|
|
8
|
-
Your primary directive is to maintain long-term system health over short-term convenience.
|
|
9
|
-
|
|
10
|
-
## Readability and simplicity
|
|
11
|
-
|
|
12
|
-
- Optimize for readability. Code is read far more than it is written.
|
|
13
|
-
- Code must be self-documenting through clear naming and explicit structure.
|
|
14
|
-
- Comments are permitted ONLY to explain intent, never logic.
|
|
15
|
-
- Prefer the simplest implementation that satisfies the requirement (KISS).
|
|
16
|
-
|
|
17
|
-
## Design philosophy
|
|
18
|
-
|
|
19
|
-
- Implement only the functionality required for the immediate task (YAGNI).
|
|
20
|
-
- Extract shared logic into single-purpose utilities. Never duplicate behavior across modules (DRY).
|
|
21
|
-
- Each function, module, and component should have a single reason to change (SRP).
|
|
22
|
-
- Apply SRP to directories: once a folder mixes distinct roles and grows past a handful of files, split it into subfolders by role. Load the `canon:codebase-layout` skill before placing a new file, and report it rather than proceeding silently when it does not resolve.
|
|
23
|
-
- Favor composition over inheritance.
|
|
24
|
-
- Prioritize native platform capabilities over third-party libraries.
|
|
25
|
-
|
|
26
|
-
## Data integrity
|
|
27
|
-
|
|
28
|
-
- Favor explicit behavior over implicit magic or conventions.
|
|
29
|
-
- Ensure data and configuration reside in designated Single Source of Truth locations.
|
|
30
|
-
- Treat data as immutable unless mutation is explicitly required.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce safe concurrency and async operation patterns
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Concurrency standards
|
|
6
|
-
|
|
7
|
-
## Async lifecycle
|
|
8
|
-
|
|
9
|
-
- Make async operations cancellable. Clean up on scope exit or caller cancellation.
|
|
10
|
-
- Coordinate dependent async operations explicitly. Document execution order.
|
|
11
|
-
- Set explicit timeouts on all external async operations.
|
|
12
|
-
- Do not fire-and-forget async operations without cleanup handlers.
|
|
13
|
-
- Batch independent async operations. Do not run them sequentially when parallelizable.
|
|
14
|
-
|
|
15
|
-
## Race conditions
|
|
16
|
-
|
|
17
|
-
- Do not ignore race conditions in concurrent flows.
|
|
18
|
-
- Protect shared mutable state with locks, queues, or single-writer patterns.
|
|
19
|
-
|
|
20
|
-
## Failure handling
|
|
21
|
-
|
|
22
|
-
- Handle partial failures in batched operations independently. Do not fail the entire batch for a single error.
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce consistent error handling patterns
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Error handling standards
|
|
6
|
-
|
|
7
|
-
## Boundary validation
|
|
8
|
-
|
|
9
|
-
- Validate inputs at system boundaries. Reject invalid data immediately.
|
|
10
|
-
- Do not use exceptions for control flow.
|
|
11
|
-
|
|
12
|
-
## Error classification
|
|
13
|
-
|
|
14
|
-
- Distinguish expected failures (validation, not found) from unexpected failures (null reference, network timeout).
|
|
15
|
-
- Return structured error types for recoverable failures.
|
|
16
|
-
- Propagate exceptions for programmer errors.
|
|
17
|
-
|
|
18
|
-
## Error propagation
|
|
19
|
-
|
|
20
|
-
- Handle errors at the layer with enough context to respond meaningfully.
|
|
21
|
-
- Do not catch and rethrow without adding value.
|
|
22
|
-
- Do not silently ignore errors.
|
|
23
|
-
|
|
24
|
-
## Error reporting
|
|
25
|
-
|
|
26
|
-
- Include actionable context in error messages.
|
|
27
|
-
- Never expose internal implementation details in error messages.
|
|
28
|
-
|
|
29
|
-
## Retry behavior
|
|
30
|
-
|
|
31
|
-
- Retry only idempotent operations with bounded attempts and backoff.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce performance constraints and optimization patterns
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Performance standards
|
|
6
|
-
|
|
7
|
-
## Resource loading
|
|
8
|
-
|
|
9
|
-
- Lazy load resources at architectural boundaries, not inline.
|
|
10
|
-
- Do not import entire modules when subsets are sufficient.
|
|
11
|
-
|
|
12
|
-
## Execution efficiency
|
|
13
|
-
|
|
14
|
-
- Defer non-critical work until after primary output completes.
|
|
15
|
-
- Do not fetch data inside loops.
|
|
16
|
-
|
|
17
|
-
## Data handling
|
|
18
|
-
|
|
19
|
-
- Paginate or stream unbounded data sets.
|
|
20
|
-
- Do not optimize without measurement.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce structured logging and observability
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Logging standards
|
|
6
|
-
|
|
7
|
-
## Log coverage
|
|
8
|
-
|
|
9
|
-
- Log state transitions at boundaries (requests received, external calls made, errors encountered).
|
|
10
|
-
- Do not log in performance-critical code paths.
|
|
11
|
-
|
|
12
|
-
## Log format
|
|
13
|
-
|
|
14
|
-
- Use structured formats with consistent metadata (timestamp, severity, correlation ID).
|
|
15
|
-
- Emit logs at appropriate severity: critical for failures, informational for significant events.
|
|
16
|
-
|
|
17
|
-
## Log safety
|
|
18
|
-
|
|
19
|
-
- Do not log credentials, tokens, or personally identifiable information.
|
|
20
|
-
- Log observable behavior, not implementation details.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce consistent naming semantics across all code
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Naming standards
|
|
6
|
-
|
|
7
|
-
## Semantics
|
|
8
|
-
|
|
9
|
-
- Prefer descriptive names over abbreviations: `getUserProfile` over `getUP`.
|
|
10
|
-
- Name functions as actions describing what they do: `fetchUser`, `calculateTotal`.
|
|
11
|
-
- Prefix booleans with `is`, `has`, `should`, or `can`: `isLoading`, `hasAccess`.
|
|
12
|
-
- Avoid negative boolean names: `isEnabled` over `isNotDisabled`.
|
|
13
|
-
- Prefix event handlers with `handle`: `handleClick`, `handleSubmit`.
|
|
14
|
-
- Name collections as plurals: `users`.
|
|
15
|
-
- Name items as singulars: `user`.
|
|
16
|
-
|
|
17
|
-
## Test naming
|
|
18
|
-
|
|
19
|
-
- Name tests with descriptive phrases that state the expected behavior.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Execute an @-referenced snippet's instructions immediately using session context
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Snippet reference standards
|
|
6
|
-
|
|
7
|
-
## Execution
|
|
8
|
-
|
|
9
|
-
- When a snippet is referenced with `@`, execute its instructions immediately using available session context
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|