@erclx/canon 5.12.0 → 5.13.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/api-design/REQUIREMENT.md +1 -1
- package/claude/skills/api-design/SKILL.md +1 -1
- package/claude/skills/api-design/references/adopted.md +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +2 -2
- package/claude/skills/build-in-slices/REQUIREMENT.md +45 -0
- package/claude/skills/build-in-slices/SKILL.md +94 -0
- package/claude/skills/build-in-slices/references/adopted.md +41 -0
- package/claude/skills/code-craft/REQUIREMENT.md +48 -0
- package/claude/skills/code-craft/SKILL.md +107 -0
- package/claude/skills/code-craft/references/adopted.md +52 -0
- package/claude/skills/codebase-layout/REQUIREMENT.md +1 -1
- package/claude/skills/git-ship/REQUIREMENT.md +1 -0
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/claude/skills/review-craft/REQUIREMENT.md +3 -0
- package/claude/skills/review-craft/SKILL.md +1 -1
- package/claude/skills/review-craft/references/adopted.md +8 -0
- package/claude/skills/review-craft/references/security.md +5 -0
- package/claude/skills/review-ui/REQUIREMENT.md +1 -0
- package/claude/skills/review-ui/SKILL.md +11 -0
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +4 -0
- package/claude/skills/test-first/REQUIREMENT.md +3 -0
- package/claude/skills/test-first/SKILL.md +2 -1
- package/docs/agents/pr-preview.md +40 -12
- package/docs/workflow/skill-map.md +2 -0
- package/governance/rules/code/000-code.md +5 -1
- package/package.json +1 -1
- package/src/claude/cases/misc.ts +10 -0
- package/src/claude/skills-audit.ts +2 -0
- package/src/commands/pr.ts +107 -7
- package/src/commands/tooling.ts +39 -16
- package/src/pr/preview.ts +66 -0
- package/src/tooling/manifest.ts +16 -0
- package/src/tooling/verify-stack.ts +249 -0
- package/tooling/base/seeds/.cspell/tech-stack.txt +2 -0
- package/tooling/go/manifest.toml +3 -0
- package/tooling/go/reference.md +1 -0
- package/tooling/php/manifest.toml +3 -0
- package/tooling/php/reference.md +1 -0
- package/tooling/python/manifest.toml +3 -0
- package/tooling/python/reference.md +1 -1
- package/tooling/python/seeds/.cspell/tech-stack.txt +0 -1
- package/scripts/tooling/verify.sh +0 -184
|
@@ -43,7 +43,7 @@ The one skill nearest the subject leaves the pointer open. `codebase-layout` exc
|
|
|
43
43
|
## Out of scope
|
|
44
44
|
|
|
45
45
|
- Where the file holding a surface sits on disk: `codebase-layout`
|
|
46
|
-
- Interface depth, deep modules, and the internals behind a boundary
|
|
46
|
+
- Interface depth, deep modules, and the internals behind a boundary: `code-craft`
|
|
47
47
|
- Listing the consumers a finished change breaks, and the docs it made false: `review-craft`
|
|
48
48
|
- A visual interface, its layout, and its look: `design-taste`
|
|
49
49
|
- Retiring a surface and migrating its last consumers off it, beyond the additive rule stated here
|
|
@@ -99,4 +99,4 @@ Check each line against the surface the change produced. A line answering no is
|
|
|
99
99
|
- The structured error rule and hidden internals floor every code stack loads: `000-code`
|
|
100
100
|
- Listing the consumers a finished change breaks, and the docs it made false, during review: `review-craft`
|
|
101
101
|
- A visual interface, its layout, and its look: `design-taste`
|
|
102
|
-
- Interface depth and the internals behind a boundary
|
|
102
|
+
- Interface depth and the internals behind a boundary: `code-craft`
|
|
@@ -35,6 +35,6 @@ From `addyosmani/agent-skills@2686b620`, [`skills/api-and-interface-design/SKILL
|
|
|
35
35
|
|
|
36
36
|
**Protocol-specific guidance.** The source skill carries verbs, status codes, pagination, and URL shapes for one protocol style. Declined because the body has to hold for a function's exports, a command's flags, and a file format as much as an endpoint, and a protocol section would route every non-network surface to rules that do not apply. A project needing those conventions states them in its own stack rule.
|
|
37
37
|
|
|
38
|
-
**Interface depth.** Ousterhout's deep modules, after [A Philosophy of Software Design](https://web.stanford.edu/~ouster/cgi-bin/book.php), judge how much a module hides behind its surface. Declined here because depth is about what sits behind a boundary, and this skill owns only what crosses it.
|
|
38
|
+
**Interface depth.** Ousterhout's deep modules, after [A Philosophy of Software Design](https://web.stanford.edu/~ouster/cgi-bin/book.php), judge how much a module hides behind its surface. Declined here because depth is about what sits behind a boundary, and this skill owns only what crosses it. `code-craft` carries it.
|
|
39
39
|
|
|
40
40
|
**Versioned surfaces as the default.** Shipping a new version beside the old for every breaking change. Declined as the default because additive change avoids the break in the first place, and two live versions split the callers. The One-Version Rule covers a caller that cannot pin.
|
|
@@ -14,6 +14,7 @@ Review is the step that varies most. It gets skipped on a diff that needed one,
|
|
|
14
14
|
## Must
|
|
15
15
|
|
|
16
16
|
- Take the approved plan for the branch as the scope, and implement only what it describes
|
|
17
|
+
- Load `build-in-slices` before implementing, so the build reaches history as tested slices rather than one uncommitted pass
|
|
17
18
|
- Give every step a stop condition, and leave the code on the branch and the receipts on disk at each one
|
|
18
19
|
- Classify the changed-file list by path as well as by extension, so informational prose skips a code review with no signal on it and executable prose still reaches one
|
|
19
20
|
- Check the branch's committed history for a test-order violation between verify and review, and report any finding without gating on it, matching the verb's own contract
|
|
@@ -27,7 +27,7 @@ Prefer `origin/main` over local `main`, since a local `main` trailing the remote
|
|
|
27
27
|
|
|
28
28
|
The baseline is unusable when no merge base resolves against either ref. Stop: `❌ No diff baseline against main. Fetch origin, then re-run autoship.`
|
|
29
29
|
|
|
30
|
-
The base equalling HEAD stays usable
|
|
30
|
+
The base equalling HEAD stays usable, since nothing need be committed before Step 8. The classifier diffs the base against the working tree, so every slice Step 2 already committed stays in the changed set. Do not port the read-only siblings' `base == HEAD` stop into this skill.
|
|
31
31
|
|
|
32
32
|
## Step 0: take the role, then enter a worktree
|
|
33
33
|
|
|
@@ -67,7 +67,7 @@ Its sections and its answer contract are fixed by `${CLAUDE_SKILL_DIR}/../../sta
|
|
|
67
67
|
|
|
68
68
|
## Step 2: implement
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Load `canon:build-in-slices`, reporting it when it does not resolve, and implement only what the plan describes. Do not expand scope, refactor neighbors, or touch files outside the plan's "Files to touch" list without reason.
|
|
71
71
|
|
|
72
72
|
## Step 3: verify
|
|
73
73
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-in-slices
|
|
3
|
+
description: Why a building session needs stated rules for working through a plan in committed slices and for leaving what it notices outside the plan, and where that discipline stops short of the test loop, code shape, and the worker's boundaries
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build in slices requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, nothing in the toolkit says how a session works through a plan once it starts building. `test-first` loops per behavior and stops at refactor, and `auto-ship` Step 2 says to implement only what the plan describes and nothing about how. No skill asks for a commit per slice, for a build left passing between slices, or for a defect noticed outside the plan to be written down rather than fixed.
|
|
11
|
+
|
|
12
|
+
The ship chain assumed the work arrives uncommitted. `git-ship` ran `git-stage` unconditionally, and that skill stops on an empty index, so a session that committed as it went never reached the pull request whenever the sync steps wrote nothing.
|
|
13
|
+
|
|
14
|
+
## Must
|
|
15
|
+
|
|
16
|
+
- State the cycle per slice: implement, run the slice's tests and the checks its change could affect, commit through `git-commit`, then move on from the committed state
|
|
17
|
+
- State how the next slice is chosen: one path end to end, the riskiest piece first, and the contract first when two sides are written against it
|
|
18
|
+
- Keep each commit safe to revert on its own: one logical change, a test committed with or ahead of its code, and never a delete and its replacement in one commit
|
|
19
|
+
- Route a defect noticed outside the plan to the open task's `## Findings`, or to the handover where no task exists, and leave its file unchanged
|
|
20
|
+
- Limit the rule against re-running a check on unchanged code to the session's own repeats, so it never reads as permission to skip a verify step a chain runs
|
|
21
|
+
- Record the external sources adopted and declined with the reason for each, so a later session extends the position instead of re-deriving it
|
|
22
|
+
- Close with a table of the excuses a session gives for skipping a slice commit or widening scope, each with its rebuttal, the red flags a session can see in its own work mid-task, and a checklist each line of which answers yes or no against the branch the build produced
|
|
23
|
+
|
|
24
|
+
## Must not
|
|
25
|
+
|
|
26
|
+
- Restate the scope floors `565-behavior` already carries for every session
|
|
27
|
+
- Carry simplicity or abstraction rules, which `code-craft` owns
|
|
28
|
+
- Name a feature flag pattern, since the slices of one branch merge as one pull request rather than reaching trunk one at a time
|
|
29
|
+
- Name a framework, a test runner, or a line-count threshold, none of which holds across stacks
|
|
30
|
+
- Describe a raw `git commit` recipe in place of `git-commit`
|
|
31
|
+
|
|
32
|
+
## Guards
|
|
33
|
+
|
|
34
|
+
- A change that is already one behavior in one place skips the skill
|
|
35
|
+
- A defect outside the plan is fixed on the branch only when the plan's own change cannot pass without it, and the commit says so
|
|
36
|
+
|
|
37
|
+
## Out of scope
|
|
38
|
+
|
|
39
|
+
- The red, green, refactor loop inside one behavior: `test-first`
|
|
40
|
+
- Which layer a test belongs at: `test-craft`
|
|
41
|
+
- The shape of a function, class, or module a slice writes: `code-craft`
|
|
42
|
+
- What a building session may write, the board it may not, and the messages it owes: `role-worker`
|
|
43
|
+
- The message format of a commit: `git-commit`
|
|
44
|
+
- Safe defaults for a new interface, which belong to the skill shaping what a caller sees
|
|
45
|
+
- Whether the guidance changes what a session ships, which needs a measured with-and-without run rather than a rule here
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-in-slices
|
|
3
|
+
description: Carries how a building session works through an approved plan in thin slices, each one tested, committed, and left green before the next starts, and how it records what it noticed outside the plan rather than fixing it. Use before implementing a plan that touches more than one behavior or file, when a branch is piling up uncommitted work, or when asked "how should I build this", "how do I avoid one giant diff", "should I commit this now", or "should I fix this while I'm here". Do NOT use for the red, green, refactor loop inside one behavior, which is `test-first`, to shape the code a slice writes, which is `code-craft`, or to decide what a worker may write, which is `role-worker`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build in slices
|
|
7
|
+
|
|
8
|
+
A session handed a plan tends to build all of it in one pass and test at the end. The diff grows past what anyone can read, a failure late in the run could have come from any of the changes, and nothing in history marks a point that worked. A defect it notices on the way gets fixed in the same diff, so the review reads two changes as one. This skill carries the discipline that keeps each step small enough to verify and revert on its own.
|
|
9
|
+
|
|
10
|
+
Load it before implementing a plan with more than one behavior or more than one file to change. Skip it for a change that is already one behavior in one place.
|
|
11
|
+
|
|
12
|
+
## Run the cycle per slice
|
|
13
|
+
|
|
14
|
+
Each slice is the smallest piece of the plan that works on its own.
|
|
15
|
+
|
|
16
|
+
1. Implement the slice, driving each behavior in it through `test-first`.
|
|
17
|
+
2. Run the slice's own tests and every check its change could affect, such as the type checker over a changed signature or the linter over a changed file.
|
|
18
|
+
3. Commit the slice through `canon:git-commit`, staging only the files the slice changed. Report it rather than proceeding silently when that skill does not resolve.
|
|
19
|
+
4. Move to the next slice from the committed state, carrying forward rather than restarting.
|
|
20
|
+
|
|
21
|
+
Leave the build passing at every commit. A slice that cannot pass on its own is two slices in the wrong order, or one slice cut too thin to stand.
|
|
22
|
+
|
|
23
|
+
## Choose the next slice
|
|
24
|
+
|
|
25
|
+
- Prefer one path through every layer it needs, end to end, over one whole layer at a time. A finished path proves the layers fit, and a finished layer proves nothing until the next one meets it.
|
|
26
|
+
- Take the riskiest or least certain piece first. When it fails, the slices that would have rested on it are not built yet.
|
|
27
|
+
- Build the contract first when two sides are written against it, such as a command and the skill that calls it, or a format and its reader. Commit the contract as its own slice, then each side against it.
|
|
28
|
+
- Read the plan's file list as the scope of the whole branch, not as the order. Cut the order from the three rules above.
|
|
29
|
+
|
|
30
|
+
## Keep each commit safe to revert on its own
|
|
31
|
+
|
|
32
|
+
- Make each commit one logical change. A new behavior, a refactor it needed, and a configuration change are three commits.
|
|
33
|
+
- Commit a slice's test with its code or ahead of it, never after. A test landing in a later commit reads to `canon gov test-order` as code that reached history untested.
|
|
34
|
+
- Never delete something and add its replacement in one commit. Add the replacement, move callers to it, then delete the original, so reverting any one step leaves a working tree.
|
|
35
|
+
- Keep edits to existing code narrow, so a revert removes the slice and nothing a later slice leaned on.
|
|
36
|
+
|
|
37
|
+
## Note what you notice, and leave it
|
|
38
|
+
|
|
39
|
+
A defect outside the plan that turns up mid-build is a finding, not a slice. Fixing it on this branch widens a diff the plan scoped and hides the fix inside an unrelated review.
|
|
40
|
+
|
|
41
|
+
- Write it in one line under the open task's `## Findings`, naming the file and what is wrong, when the build is closing a task.
|
|
42
|
+
- Carry it in the handover message instead when no task exists, and never create a file to hold it.
|
|
43
|
+
- Leave the file as it is, even when the fix is one line.
|
|
44
|
+
- Fix it here only when the plan's own change cannot pass without it, and then say so in the commit that does.
|
|
45
|
+
|
|
46
|
+
## Run a check when the code under it changed
|
|
47
|
+
|
|
48
|
+
- Re-run a check after an edit it could see, not as reassurance. A second pass over unchanged code reports what the first pass already did.
|
|
49
|
+
- This covers repeats a session makes on its own between slices. A verify step a chain or a ship gate runs is a separate decision with its own reason, so run it whenever the chain reaches it.
|
|
50
|
+
|
|
51
|
+
Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidance or arguing against a rule in it. It records which external sources were adopted, which declined, and why.
|
|
52
|
+
|
|
53
|
+
## Excuses and rebuttals
|
|
54
|
+
|
|
55
|
+
| Excuse | Rebuttal |
|
|
56
|
+
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| I will test it all at the end | A defect in the first slice makes every later one wrong, and a failure at the end could have come from any of them. |
|
|
58
|
+
| It is faster to build it in one pass | It is faster until something breaks and the cause sits somewhere in a diff nobody can bisect. |
|
|
59
|
+
| These changes are too small to commit separately | A small commit costs one message. A large one hides which change broke the build and cannot be reverted in part. |
|
|
60
|
+
| The ship step commits everything anyway | It groups what is left by concern after the fact. It cannot recover which state worked between slices. |
|
|
61
|
+
| This fix is one line, so it can ride along | It lands in a review scoped to something else, and reverting the slice it rode in reverts the fix too. |
|
|
62
|
+
| The refactor is small enough to include | A refactor mixed into a feature makes both harder to review and to revert. Commit it as its own slice first. |
|
|
63
|
+
| I will commit the test once the code settles | The code reaches history untested, and `canon gov test-order` reports the pair on every later run of the branch. |
|
|
64
|
+
| Let me run the suite once more just to be sure | Nothing changed since it passed. Run it again after the next edit, where it can find something. |
|
|
65
|
+
|
|
66
|
+
## Red flags
|
|
67
|
+
|
|
68
|
+
- The working tree holds changes from more than one slice and none of them is committed.
|
|
69
|
+
- The next commit message needs "and" to say what it does.
|
|
70
|
+
- A slice has been implemented and its tests have not run yet.
|
|
71
|
+
- The build or a test is failing and the next slice has already started.
|
|
72
|
+
- You opened a file the plan does not name and are about to edit it.
|
|
73
|
+
- A commit deletes code and adds its replacement in the same change.
|
|
74
|
+
- You are about to stage a test in a commit after the one that added its code.
|
|
75
|
+
- You are running the same check twice with no edit between the runs.
|
|
76
|
+
|
|
77
|
+
## Before handing over
|
|
78
|
+
|
|
79
|
+
Check each line against the branch the build produced. A line answering no is fixed or reported, never left with a note.
|
|
80
|
+
|
|
81
|
+
- Every commit on the branch carries one logical change and passed the checks it could affect.
|
|
82
|
+
- No commit adds code whose test lands in a later commit.
|
|
83
|
+
- No commit deletes something and adds its replacement together.
|
|
84
|
+
- The working tree holds no uncommitted implementation work.
|
|
85
|
+
- Every file changed is in the plan's scope, or its commit says why the plan needed it.
|
|
86
|
+
- Every defect noticed outside the plan is written in the task's findings or the handover, and its file is unchanged.
|
|
87
|
+
|
|
88
|
+
## What this delegates
|
|
89
|
+
|
|
90
|
+
- The red, green, refactor loop inside one behavior: `test-first`
|
|
91
|
+
- Which layer a slice's test belongs at: `test-craft`
|
|
92
|
+
- The shape of the code a slice writes, including when an abstraction earns its place: `code-craft`
|
|
93
|
+
- What a building session may write and whom it reports to: `role-worker`
|
|
94
|
+
- Writing the commit message for a staged slice: `git-commit`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Adopted and declined
|
|
3
|
+
description: Which external sources on incremental building this skill adopted, which it declined, and why, so a later session extends the position instead of re-deriving it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Adopted and declined
|
|
7
|
+
|
|
8
|
+
External sources were read and filtered rather than imported. This file is the record. A later session extending the skill adds to it rather than re-arguing an item already settled here.
|
|
9
|
+
|
|
10
|
+
## Adopted
|
|
11
|
+
|
|
12
|
+
### From the default shelf
|
|
13
|
+
|
|
14
|
+
**Small changes.** [Small CLs](https://google.github.io/eng-practices/review/developer/small-cls.html), from Google's engineering practices: a change should be self-contained and address one thing, a refactor goes in a change apart from the feature that needs it, and a test goes in the same change as the code it covers. Adopted as the rule that each commit carries one logical change, the refactor excuse row, and the rule that a slice's test never lands after its code.
|
|
15
|
+
|
|
16
|
+
### The increment cycle
|
|
17
|
+
|
|
18
|
+
**Incremental implementation.** Addy Osmani's `agent-skills`, pinned at addyosmani/agent-skills@2686b620, [`skills/incremental-implementation/SKILL.md`](https://github.com/addyosmani/agent-skills/blob/2686b620/skills/incremental-implementation/SKILL.md). Adopted from it:
|
|
19
|
+
|
|
20
|
+
- The increment cycle of implement, test, verify, commit, and next slice, with the commit routed through `git-commit` rather than a message format of its own.
|
|
21
|
+
- Vertical, risk-first, and contract-first slicing, stated as rules for choosing the next slice rather than as worked examples tied to one stack.
|
|
22
|
+
- Rule 1, one thing at a time, as one logical change per commit.
|
|
23
|
+
- Rule 2, keep it compilable, as a build left passing at every commit.
|
|
24
|
+
- Rule 5, rollback-friendly, as the group on keeping each commit safe to revert and the rule against deleting and replacing in one commit.
|
|
25
|
+
- The "noticed but not touching" list from its scope section, routed to the open task's findings or the handover rather than offered as new tasks, since a worker may not add a row to the board.
|
|
26
|
+
- The note against re-running a command on unchanged code, scoped to a session's own repeats so it never reads as permission to skip a chain's verify step.
|
|
27
|
+
- The rationalizations and red flags that carry across stacks, reworded as reasons this toolkit's sessions give, with one row added for the ship step committing everything anyway.
|
|
28
|
+
|
|
29
|
+
## Declined
|
|
30
|
+
|
|
31
|
+
**Rule 0, simplicity first, and the abstraction red flags.** Declined because `code-craft` owns when an abstraction earns its place and when to write the plainest code that passes. Restating it here would put two owners on one rule.
|
|
32
|
+
|
|
33
|
+
**The rest of its scope section.** Declined because `565-behavior` already carries the scope floors every session loads, being minimal edits, no unrequested features, and edits limited to what the user named. Only the noticed list was new.
|
|
34
|
+
|
|
35
|
+
**Rule 3, feature flags for incomplete features.** Declined because the slices of one branch merge together as one pull request rather than reaching trunk one at a time, so nothing incomplete is exposed between them.
|
|
36
|
+
|
|
37
|
+
**Rule 4, safe defaults.** Declined because a conservative default is a concern of the interface a caller sees, which belongs to the skill shaping that interface rather than to how the work is sequenced.
|
|
38
|
+
|
|
39
|
+
**The 100-line threshold.** Its red flag of more than 100 lines written without running tests. Declined because a line count means something different on every stack and a session cannot carry it from one to the next. The red flag is stated as a check instead: a slice implemented whose tests have not run.
|
|
40
|
+
|
|
41
|
+
**Its per-stack command lists and its definition-of-done pointer.** Declined because the project's own `CLAUDE.md` names its verify commands, and a body naming runners stops holding on the next stack.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-craft
|
|
3
|
+
description: Why a session writing code needs stated rules on the shape of a function, a class, or a module's internals, and where that judgment stops short of placement, the test loop, a caller's contract, and review
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code craft requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, nothing in the toolkit shapes code at the moment it is written. `test-first` runs the loop around the code, `codebase-layout` places the file, `api-design` shapes what a caller sees, and the core code rule holds placement, error, and naming floors. The shape of a function, a class, or a module's internals is left to whatever the neighboring code suggests.
|
|
11
|
+
|
|
12
|
+
Agents fail there in recorded ways. Birgitta Böckeler's two articles on agentic coding name them: code that is copied rather than reused, a lack of modularity that spreads one change across files, features and business logic nobody asked for, assumptions filled in where the requirement was silent, and brute-force fixes that silence a symptom rather than its cause. Each reads fine in its own diff and costs the next change.
|
|
13
|
+
|
|
14
|
+
Before this skill, two shipped pointers left interface depth unowned. `api-design` declined depth and the internals behind a boundary, and `codebase-layout` named depth as having no owner, so a session routed away from either on that question landed nowhere. Both now point here.
|
|
15
|
+
|
|
16
|
+
## Must
|
|
17
|
+
|
|
18
|
+
- Open with the change test: name the change most likely to come next and count what it would touch before choosing a shape
|
|
19
|
+
- State depth as rules a session can act on: a unit earns its place when its interface is simpler than what it does, a pass-through is inlined, and a module splits by the decision it hides rather than by processing step
|
|
20
|
+
- State each tension as when one side wins: one piece of knowledge in one place against coupling two things that only look alike, building only what is asked against seams that ease change, and one reason to change against over-decomposition
|
|
21
|
+
- List patterns by their wrong case, short enough to stay in the body, with a plain function named as the usual replacement for the class
|
|
22
|
+
- State hidden inputs: pass in the clock, the environment, randomness, and globals, keep business rules free of transport and storage code, and skip ports and adapters for a thin read-and-write application
|
|
23
|
+
- Close the concern groups with the agent failure modes as checks on the session's own diff: a copy where a refactor belonged, one responsibility scattered across files, a feature nobody asked for, an assumption filled in rather than asked, and a brute-force fix
|
|
24
|
+
- Record the external sources adopted and declined with the reason for each, so a later session extends the position instead of re-deriving it
|
|
25
|
+
- Close with a table of the excuses a session gives for a shape that costs the next change, each with its rebuttal, the red flags a session can see in its own work mid-task, and a checklist each line of which answers yes or no against the code the change produced
|
|
26
|
+
|
|
27
|
+
## Must not
|
|
28
|
+
|
|
29
|
+
- Restate a definition a model already holds, such as what coupling or a design pattern is
|
|
30
|
+
- State a tension as one side only, such as "never duplicate"
|
|
31
|
+
- Name a language, a framework, or a type system feature in the body
|
|
32
|
+
- Restate the red, green, refactor loop `test-first` runs, or the design review procedure `review-craft` carries for a finished diff
|
|
33
|
+
- Restate the error and naming bullets of the core code rule
|
|
34
|
+
|
|
35
|
+
## Guards
|
|
36
|
+
|
|
37
|
+
- A change filling in a body whose shape is already fixed skips the skill
|
|
38
|
+
- A shape is never chosen for a change nobody can name, since that shape is a guess
|
|
39
|
+
|
|
40
|
+
## Out of scope
|
|
41
|
+
|
|
42
|
+
- Where a new file sits on disk: `codebase-layout`
|
|
43
|
+
- The red, green, refactor loop: `test-first`
|
|
44
|
+
- Which layer a test belongs at: `test-craft`
|
|
45
|
+
- The contract a caller depends on, being its exports, flags, output, errors, and versioning: `api-design`
|
|
46
|
+
- Judging a finished diff, including a design review of it: `review-craft`
|
|
47
|
+
- Service architecture and layering beyond the one hidden-inputs bullet kept here
|
|
48
|
+
- Whether the guidance changes what a session ships, which needs a measured with-and-without run rather than a rule here
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-craft
|
|
3
|
+
description: Carries the rules for shaping code while it is being written, being a function, a class, or a module's internals, so a session picks the shape the next change needs rather than copying its neighbor, splitting by step, or building for a case nobody asked for. Use before writing a new function, class, or module, when deciding whether to extract duplicated code, add an abstraction, a pattern, or a seam, or when asked "should I extract this", "is this abstraction worth it", "should this be a strategy", "is this class doing too much", or "should I just copy this". Do NOT use for the red, green, refactor loop, which is `test-first`, to decide where a file sits, which is `codebase-layout`, to shape what a caller sees, which is `api-design`, or to judge a finished diff, which is `review-craft`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code craft
|
|
7
|
+
|
|
8
|
+
A session writing code takes its shape from whatever sits nearby. It copies a function rather than changing the one it found, spreads one decision across the files it happened to open, and adds a class hierarchy for a second case that may never come. Each choice reads fine in the diff and costs the next change. This skill carries the judgment at the moment the shape is chosen, before the body exists.
|
|
9
|
+
|
|
10
|
+
Load it before writing a new function, class, or module, and before extracting, abstracting, or copying existing code. Skip it for a change that fills in a body whose shape is already fixed.
|
|
11
|
+
|
|
12
|
+
## Name the next change first
|
|
13
|
+
|
|
14
|
+
Good design is design that makes the likely change cheap. Judge a shape by the change it serves, not by how it looks.
|
|
15
|
+
|
|
16
|
+
- Name the change most likely to come next, from the task, the plan, or the history of the file, before choosing a shape.
|
|
17
|
+
- Count what that change would touch under each shape you are weighing. The shape where it touches one place wins.
|
|
18
|
+
- When no next change can be named, write the plainest code that passes, since a shape built for an unnamed change is a guess.
|
|
19
|
+
|
|
20
|
+
## Earn depth
|
|
21
|
+
|
|
22
|
+
A unit is worth having when its interface is much simpler than what it does, so a caller learns a little and gets a lot.
|
|
23
|
+
|
|
24
|
+
- Add a function or a class only when its name and parameters are easier to hold than its body. One that forwards its arguments to another call with nothing added is a pass-through, so inline it.
|
|
25
|
+
- Split a module by the decision it hides, such as a file format, a storage choice, or a pricing rule, rather than by processing step. A split by step makes every change to one decision touch every step.
|
|
26
|
+
- Keep a decision in one unit, so changing it opens one file. A decision whose details leak into its callers is not hidden, whatever the folder says.
|
|
27
|
+
- Prefer one longer function a reader can follow top to bottom over many tiny ones they have to stitch back together.
|
|
28
|
+
|
|
29
|
+
## Weigh the tensions
|
|
30
|
+
|
|
31
|
+
Each principle below has a case where the other side wins. State which case you are in before following either.
|
|
32
|
+
|
|
33
|
+
- **One piece of knowledge, one place, against false sharing.** Merge two copies when they encode the same rule, so changing the rule means changing both. Leave them apart when they only look alike and would change for different reasons, since merging them couples two things that drift.
|
|
34
|
+
- **Build only what is asked, against seams that ease change.** Build no capability for a feature nobody has asked for. A refactor, a test, or a parameter that makes the asked-for code easier to change is not speculative, and building it is not a breach.
|
|
35
|
+
- **One reason to change, against too many pieces.** Split a unit when two unrelated changes would both land in it. Stop splitting when the pieces only make sense read together, since a reader then rebuilds the whole across files.
|
|
36
|
+
|
|
37
|
+
## Reach for a pattern only past its wrong case
|
|
38
|
+
|
|
39
|
+
A pattern earns its indirection only when the problem it solves is present now. A plain function often replaces the class.
|
|
40
|
+
|
|
41
|
+
| Pattern | Wrong when | Write instead |
|
|
42
|
+
| --------- | ------------------------------------------------- | -------------------------------------- |
|
|
43
|
+
| Strategy | Two cases, or the case never varies at runtime | A conditional, or a function passed in |
|
|
44
|
+
| Factory | One concrete type, so the factory chooses nothing | A direct constructor call |
|
|
45
|
+
| Singleton | It exists so any code can reach shared state | The instance passed to what needs it |
|
|
46
|
+
| Observer | One listener, known when the code is written | A direct call |
|
|
47
|
+
| Decorator | One wrapper, always applied | The behavior inside the function |
|
|
48
|
+
| Adapter | It wraps your own code to fit your own code | A change to the interface it adapts |
|
|
49
|
+
|
|
50
|
+
## Pass hidden inputs in
|
|
51
|
+
|
|
52
|
+
- Pass the clock, the environment, randomness, and any global into the code that reads them, rather than reaching for them inside. A function that reads the time itself cannot be tested at a chosen time.
|
|
53
|
+
- Keep business rules free of transport and storage code, so a rule can be read and tested without a request or a database.
|
|
54
|
+
- Skip ports and adapters for an application that only reads and writes records. The layers cost more than the change they protect against.
|
|
55
|
+
|
|
56
|
+
## Check your own diff
|
|
57
|
+
|
|
58
|
+
Agents fail at writing time in recorded ways. Read the diff for each before calling it done.
|
|
59
|
+
|
|
60
|
+
- A copy where a change to the existing code belonged. Search for the code you just wrote, and change the original if it encodes the same rule.
|
|
61
|
+
- One responsibility scattered across files, so the change touched several places that each hold part of one decision.
|
|
62
|
+
- A feature, an option, or a branch nobody asked for.
|
|
63
|
+
- An assumption filled in, such as a default value or a business rule the task never stated, where a question belonged.
|
|
64
|
+
- A brute-force fix that silences a symptom, such as a broad catch, a disabled check, or a special case for one input.
|
|
65
|
+
|
|
66
|
+
Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidance or arguing against a rule in it. It records which external sources were adopted, which declined, and why.
|
|
67
|
+
|
|
68
|
+
## Excuses and rebuttals
|
|
69
|
+
|
|
70
|
+
| Excuse | Rebuttal |
|
|
71
|
+
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| Copying is safer than touching code that works | Two copies of one rule drift. The next change fixes one and leaves the other wrong, with no test pointing at it. |
|
|
73
|
+
| We will need this flexibility later | Later has no named change behind it. Build the seam when the second case arrives, and it costs the same then. |
|
|
74
|
+
| The task did not say, so a sensible default is fine | A default is a business rule nobody approved. Ask, or state the assumption where the reviewer reads it. |
|
|
75
|
+
| The test passes now, so the fix is done | A fix that suppresses the symptom passes the test it was aimed at and leaves the cause for the next one. |
|
|
76
|
+
| Following the existing pattern keeps the code consistent | Consistency with a shape that fails the next change spreads the cost. Match the neighbor only when it fits. |
|
|
77
|
+
|
|
78
|
+
## Red flags
|
|
79
|
+
|
|
80
|
+
- You are about to paste a block you just read elsewhere in the project.
|
|
81
|
+
- A new class has one method, or a new function's body is one call with the same arguments.
|
|
82
|
+
- The change you are making opens a third file to adjust one rule.
|
|
83
|
+
- You are writing an interface, a factory, or a registry with one implementation behind it.
|
|
84
|
+
- You wrote a default value, a threshold, or a fallback the task never named.
|
|
85
|
+
- A fix is adding a special case, a catch, or a disabled check rather than changing the code that misbehaved.
|
|
86
|
+
- The code reads the current time, an environment variable, or a global from inside a rule.
|
|
87
|
+
|
|
88
|
+
## Before handing over
|
|
89
|
+
|
|
90
|
+
Check each line against the code the change produced. A line answering no is fixed or reported, never left with a note.
|
|
91
|
+
|
|
92
|
+
- The next likely change is named, and it touches one place in the code as written.
|
|
93
|
+
- Every new function or class hides more than its interface asks a caller to learn, with no pass-through left.
|
|
94
|
+
- No rule the change wrote exists in a second place, and nothing was merged that changes for a different reason.
|
|
95
|
+
- Every pattern in the diff solves a problem present now, with more than one case behind it.
|
|
96
|
+
- Clock, environment, and global reads are passed in rather than taken inside a rule.
|
|
97
|
+
- The diff holds no feature, option, or default the task did not ask for or state.
|
|
98
|
+
- Every fix changes the code that misbehaved rather than silencing it.
|
|
99
|
+
|
|
100
|
+
## What this delegates
|
|
101
|
+
|
|
102
|
+
- Where a new file sits on disk: `codebase-layout`
|
|
103
|
+
- The red, green, refactor loop around the code: `test-first`
|
|
104
|
+
- Which layer a test belongs at: `test-craft`
|
|
105
|
+
- The contract a caller depends on, being its exports, flags, output, and errors: `api-design`
|
|
106
|
+
- Judging a finished diff, including a design review of it: `review-craft`
|
|
107
|
+
- The error and naming floors every code stack loads: `000-code`
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Adopted and declined
|
|
3
|
+
description: Which external software design sources this skill adopted, which it declined, and why, so a later session extends the position instead of re-deriving it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Adopted and declined
|
|
7
|
+
|
|
8
|
+
External sources were read and filtered rather than imported. This file is the record. A later session extending the skill adds to it rather than re-arguing an item already settled here.
|
|
9
|
+
|
|
10
|
+
## Adopted
|
|
11
|
+
|
|
12
|
+
### From the default shelf
|
|
13
|
+
|
|
14
|
+
**What to look for in a code review.** [Google's engineering practices](https://google.github.io/eng-practices/review/reviewer/looking-for.html): solve the problem known to need solving now rather than one speculated about, and read "too complex" as "cannot be understood quickly by a reader". Adopted as the writing-time half of the same judgment, behind the change test and the ban on building for an unnamed case. The review procedure itself stays with `review-craft`.
|
|
15
|
+
|
|
16
|
+
### Depth and decomposition
|
|
17
|
+
|
|
18
|
+
**Information hiding.** David Parnas, [On the Criteria To Be Used in Decomposing Systems into Modules](https://dl.acm.org/doi/10.1145/361598.361623), 1972: split a system by the design decision each module hides, not by the steps of processing. Adopted as the module-split rule under depth.
|
|
19
|
+
|
|
20
|
+
**Deep modules.** John Ousterhout, [A Philosophy of Software Design](https://web.stanford.edu/~ouster/cgi-bin/book.php): complexity is what makes a system hard to change, and a module is worth having when its interface is much simpler than its implementation. Adopted as the opening of the depth group and the pass-through flag. `api-design` declined depth as behind its boundary, so it lands here.
|
|
21
|
+
|
|
22
|
+
**The APoSD and Clean Code exchange.** [John Ousterhout and Robert Martin's discussion](https://github.com/johnousterhout/aposd-vs-clean-code): Martin argues for very small methods and Ousterhout for fewer, deeper ones a reader need not stitch together. Adopted as the third tension, stated as when each side wins rather than as a verdict, plus the depth bullet preferring one function a reader follows top to bottom.
|
|
23
|
+
|
|
24
|
+
**Reducing coupling.** Martin Fowler, [Reducing Coupling](https://martinfowler.com/ieeeSoftware/coupling.pdf), IEEE Software, 2001: a change in one module should not ripple into others. Adopted behind the rule that a decision stays in one unit and the red flag on a third file opened to adjust one rule.
|
|
25
|
+
|
|
26
|
+
### Tensions
|
|
27
|
+
|
|
28
|
+
**DRY as knowledge.** Andy Hunt and Dave Thomas, [Orthogonality and the DRY Principle](https://www.artima.com/articles/orthogonality-and-the-dry-principle): every piece of knowledge has one authoritative representation, which is broader than and different from avoiding repeated text. Adopted as the first tension, with its other side stated: two blocks that only look alike and change for different reasons stay apart.
|
|
29
|
+
|
|
30
|
+
**Yagni and its carve-out.** Ron Jeffries, [You're NOT Gonna Need It](https://ronjeffries.com/xprog/articles/practices/pracnotneed/), and Martin Fowler, [Yagni](https://martinfowler.com/bliki/Yagni.html): build no capability for a presumptive feature, though Yagni "does not apply to effort to make the software easier to modify". Adopted as the second tension, with Fowler's carve-out as the side that wins for a refactor, a test, or a parameter serving the asked-for code.
|
|
31
|
+
|
|
32
|
+
**Beck's design rules.** Martin Fowler, [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.html): passes the tests, reveals intention, no duplication, fewest elements, in that priority. Adopted for the ordering behind the closing checklist, where fewest elements stops the pattern table's indirection once the rules above it are met.
|
|
33
|
+
|
|
34
|
+
### Patterns and inputs
|
|
35
|
+
|
|
36
|
+
**Smells and patterns.** [Refactoring Guru's code smells](https://refactoring.guru/refactoring/smells) and [design patterns](https://refactoring.guru/design-patterns) catalogs. Adopted only for the wrong case of six common patterns and the smells a red flag can see, such as speculative generality and a lazy class. Each pattern's definition is left to the model.
|
|
37
|
+
|
|
38
|
+
**Injection.** Martin Fowler, [Inversion of Control Containers and the Dependency Injection pattern](https://martinfowler.com/articles/injection.html): hand a component what it depends on rather than letting it find it. Adopted as the hidden-inputs rule for the clock, the environment, randomness, and globals, without any container.
|
|
39
|
+
|
|
40
|
+
### Agent failure modes
|
|
41
|
+
|
|
42
|
+
Birgitta Böckeler, [The role of developer skills in agentic coding](https://martinfowler.com/articles/exploring-gen-ai/13-role-of-developer-skills.html), 2025, and [How far can we push AI autonomy in code generation?](https://martinfowler.com/articles/pushing-ai-autonomy.html), 2025. Together they record a lack of reuse and modularity, overeagerness that builds unrequested features, assumptions filled in for silent requirements, and brute-force fixes. Adopted as the closing concern group, worded as checks on the session's own diff, and as the source each excuse row and red flag traces to.
|
|
43
|
+
|
|
44
|
+
## Declined
|
|
45
|
+
|
|
46
|
+
**Definitions a model already holds.** What coupling, cohesion, or a given pattern is. Declined because a definition changes no behavior a session would otherwise get wrong.
|
|
47
|
+
|
|
48
|
+
**Language-specific pages.** Every page tied to one language, its type system, or its runtime. Declined because the body has to hold on every code stack, and the one language note the pattern table carried became "a plain function often replaces the class".
|
|
49
|
+
|
|
50
|
+
**Layering and hexagonal architecture.** Beyond the one bullet kept, keeping business rules free of transport and storage and skipping ports and adapters for a thin application. Declined because where layers sit is a structure call made once, not a writing-time one.
|
|
51
|
+
|
|
52
|
+
**The Gang of Four and The Pragmatic Programmer as books.** Gamma, Helm, Johnson, and Vlissides, Design Patterns, 1994, and Hunt and Thomas, The Pragmatic Programmer, 1999. Declined as cited sources because neither is open to read at a link, so a reader could not check the passage a rule rests on. The articles above carry the same positions where a reader can open them.
|
|
@@ -44,7 +44,7 @@ A placement rule in front of the session is also one it can argue past. Each fla
|
|
|
44
44
|
## Out of scope
|
|
45
45
|
|
|
46
46
|
- Which layer a test belongs at: `test-craft`
|
|
47
|
-
- Interface depth, seams, and where a module boundary sits in code, which govern a module's shape rather than its path on disk. What crosses that boundary is `api-design`, and depth
|
|
47
|
+
- Interface depth, seams, and where a module boundary sits in code, which govern a module's shape rather than its path on disk. What crosses that boundary is `api-design`, and depth is `code-craft`.
|
|
48
48
|
- Per-language placement conventions such as test suffixes and the top-level test folder: the language testing rules
|
|
49
49
|
- Backend, asset, and script layouts, which wait for a driving project before a reference is written
|
|
50
50
|
- Whether a plan that loaded the skill actually places files differently, which needs a measured run on a target rather than a rule here
|
|
@@ -17,6 +17,7 @@ The sequence also reaches the remote on work nothing re-checked. This skill is t
|
|
|
17
17
|
- Say so and continue when the project names no verify command, since silence there reads as a suite that passed
|
|
18
18
|
- Invoke each step through the Skill tool in the stated order and continue without waiting
|
|
19
19
|
- Stage after the sync skills write, so what they produced reaches a commit
|
|
20
|
+
- Reach the pull request on a branch whose work is already committed and whose sync steps wrote nothing, since `git-stage` stops on an empty index and a session building in slices leaves one
|
|
20
21
|
- Emit no text between steps. The sequence is the unit and prose inside it reopens settled decisions.
|
|
21
22
|
- Name the one point a wrapping caller may act at, so a chain built on this one is not left to pick a gap of its own
|
|
22
23
|
- Name the condition under which the closing block is not emitted, since a caller that closes on its own block leaves two instructions about the last line and nothing deciding between them
|
|
@@ -28,7 +28,7 @@ Run `git diff --cached --name-only 2>/dev/null` to check for staged files. If ou
|
|
|
28
28
|
3. Invoke `canon:docs-sync` to sync public docs against changes since main
|
|
29
29
|
4. Run `git add -A` to stage any files the sync skills wrote
|
|
30
30
|
5. Run `canon tasks plan-reach <plan> --json` and report both lists it carries. Name the plan this branch built under, by path or by slug. Read `claimed` first and say who holds each path, since that is the half a reader acts on, then say how many of the changed paths `undeclared` names. Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero. This step reports and never stops the sequence.
|
|
31
|
-
6. Invoke `canon:git-stage` to group staged changes and commit by concern
|
|
31
|
+
6. Invoke `canon:git-stage` to group staged changes and commit by concern, only when `git diff --cached --name-only` prints a path. When it prints nothing, the work already reached history in slices, so continue to step 7.
|
|
32
32
|
7. Invoke `canon:git-branch` to rename branch to match conventional format
|
|
33
33
|
8. Invoke `canon:git-pr` to push branch and open pull request
|
|
34
34
|
9. After the PR opens, watch CI in the background, so the session stays reachable while CI runs. Read `### Watching CI` below for the commands and the wake.
|
|
@@ -13,6 +13,8 @@ The miss is measured. On a seeded branch that deleted a dirty-tree guard while t
|
|
|
13
13
|
|
|
14
14
|
Rendered output is the larger hole. `git-pr` posts an `## Evidence` comment through `canon pr evidence`, carrying base and head screenshots and a checklist a reviewer ticks. The pull request review named that heading only in its heading set, and no step opened an image. On a seeded pull request whose narrow head screenshot shows the navigation running off the edge while a ticked box claims it collapses, the review filed the finding off the stylesheet diff and said it had not rendered the page. On a styling change with no screenshot at all, on a project whose trunk keeps them, it did not mention the absence.
|
|
15
15
|
|
|
16
|
+
A dependency upgrade is not a measured miss. On 2026-10-02 a seeded branch bumped one dependency across a major version beside a second, with a lockfile adding a transitive package that carried an install script, and the body without a dependency reference reported it. The run that measured it passed every assertion, including a graded finding naming the upgrade, so the case is a floor and no reference exists for it. An earlier run matched only a loose pattern and left no report to read, so it counts for nothing. The security reference still had no threat-model step and no class for a delete or clean on a derived path, both groundwork lifts with no miss to measure.
|
|
17
|
+
|
|
16
18
|
The axes also said nothing about a change that passes by lowering the bar it has to clear, such as a test skipped, a threshold moved, or a path excluded from a checker, nothing about performance, and one sentence about design with no procedure behind it. A refactor that only moved complexity read as a design gain, and a removal could call code dead without reading why it was added. The body carried no excuses, red flags, or closing checklist, so a session about to stop at the hunk met no answer first.
|
|
17
19
|
|
|
18
20
|
## Must
|
|
@@ -27,6 +29,7 @@ The axes also said nothing about a change that passes by lowering the bar it has
|
|
|
27
29
|
- State a design finding as a concrete cost, so it survives the procedure's filter against subjective suggestions
|
|
28
30
|
- Carry the evidence bar: confirm against the file at the reviewed head, quote a cited rule, name the breaking input, and drop what a gate owns or what rests on unread state
|
|
29
31
|
- Carry security as classes with an exclusion list, in a reference loaded when the diff reaches one
|
|
32
|
+
- Open the security reference with a threat model drawn from the diff, and carry destructive operations on a derived path as a class, so a cleanup deleting an unchecked variable's glob is read for the empty-value collapse
|
|
30
33
|
- Open the evidence images on a rendered change through `git show` at the row's own sha, never through the embedded address, within a stated read budget
|
|
31
34
|
- Test each ticked checklist box against an opened image, and name a ticked box no image covers as untested
|
|
32
35
|
- Flag a rendered change that carries no screenshot, as a finding where the trunk already keeps them and as a question elsewhere
|
|
@@ -36,7 +36,7 @@ An axis whose condition the diff meets is not optional. When the security or the
|
|
|
36
36
|
|
|
37
37
|
Read each of these when the diff reaches what it names.
|
|
38
38
|
|
|
39
|
-
7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes a file, handles input from outside the process, touches a secret, adds a dependency, or changes a default a consumer installs.
|
|
39
|
+
7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes or deletes a file, handles input from outside the process, touches a secret, adds a dependency, or changes a default a consumer installs.
|
|
40
40
|
8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff touches a file that paints, such as markup, a stylesheet, a component, a template, or a design token, or when the pull request carries an evidence comment. A finding read off a stylesheet diff says what the author changed, and only the screenshot says what a user sees, so the reference opens the images and checks whether any exist.
|
|
41
41
|
9. **Developer experience and operations.** Ports, hooks, scripts, config, and scaffold defaults a consumer installs. A new required step nobody documented, a default that fails on a clean machine, or a hook that slows every commit is a finding even when the code is correct.
|
|
42
42
|
10. **Executable prose.** A skill body, a rule, or a prompt is instructions a model runs. Read it the way you read code: a step that races another, a precondition it never states, a branch with no exit, and two instructions that contradict each other are bugs.
|
|
@@ -34,6 +34,10 @@ From `addyosmani/agent-skills@2686b620`, `skills/constraint-driven-development/S
|
|
|
34
34
|
|
|
35
35
|
From `addyosmani/agent-skills@2686b620`, `skills/code-review-and-quality/SKILL.md` for the axis itself, a call inside a loop and an unbounded fetch, and `skills/performance-optimization/SKILL.md` for keep or revert: measure before and after the same way, and a neutral result argues for removing the added complexity. The repeated-run requirement against noise is stated here so one run on each side reads as an anecdote.
|
|
36
36
|
|
|
37
|
+
### Security additions
|
|
38
|
+
|
|
39
|
+
From `addyosmani/agent-skills@2686b620`, `skills/security-and-hardening/SKILL.md`: the threat model first and the derived-path rule. Adopted as the opening step of `references/security.md`, which names who supplies each input and what the code can reach before any class is read, and as the destructive-operations class, which asks for the empty-value collapse, the glob or symlink escape, the missing root check, and no read of what is there before the call. Both stay stack-neutral. No red run measures them, so they ship as lifts rather than as an answer to a miss.
|
|
40
|
+
|
|
37
41
|
### Closing sections
|
|
38
42
|
|
|
39
43
|
The excuses, red flags, and closing checklist follow the practice skill shape every practice skill in this toolkit carries, taken from `addyosmani/agent-skills@2686b620`, [`docs/skill-anatomy.md`](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/docs/skill-anatomy.md). Each excuse row rebuts a reason a review stops at the hunk, such as passing tests against a test the diff skipped, rather than an objection nobody raised.
|
|
@@ -46,4 +50,8 @@ The excuses, red flags, and closing checklist follow the practice skill shape ev
|
|
|
46
50
|
|
|
47
51
|
**Named structural remedies as a catalog.** A list of refactorings to propose reads as a menu a session fills in. A design finding states the cost, and the remedy is the author's.
|
|
48
52
|
|
|
53
|
+
**A dependency upgrade reference.** From `addyosmani/agent-skills@2686b620`, `skills/code-review-and-quality/SKILL.md`: read the changelog across the range, one dependency per change, and the lockfile diff. Declined because the seeded upgrade is not a miss. The body without such a reference reported the planted major bump and the install script in the lockfile on the second of two runs, which passed the assertion naming them. Revisit when a run on a changed lockfile misses what a reference would have named.
|
|
54
|
+
|
|
55
|
+
**STRIDE and abuse-case tests as a procedure.** They belong to a design session rather than a diff read, and the threat-model opening in the security reference takes the one step a diff supports, naming who supplies each input.
|
|
56
|
+
|
|
49
57
|
**The web and database tables from `performance-optimization`.** They name a stack, and the axis stays stack-neutral until a target asks for a per-stack reference.
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Read each class against the diff. A class the diff does not reach is skipped, not reported as clean. Name the input that reaches the sink and the path it takes, since a class named with no path is a suspicion rather than a finding.
|
|
4
4
|
|
|
5
|
+
## Open with the threat model
|
|
6
|
+
|
|
7
|
+
Before the classes, name from the diff who supplies each input and what the code can reach with it: a file, a process, a network, a credential. Skip a class that model rules out, and say which one and why, so the skip reads as a decision rather than an oversight.
|
|
8
|
+
|
|
5
9
|
## Classes to check
|
|
6
10
|
|
|
7
11
|
- **Shell and command injection.** A value from an argument, an environment variable, a file, or a network response reaching a shell: through `eval`, an unquoted expansion, a string built into a command, or a subprocess call that takes a single command string. Quoting the variable at the call site is the fix to look for.
|
|
8
12
|
- **Path traversal in a file write.** A path built from outside input and written without being resolved and checked against the directory it must stay inside. A `..` segment, an absolute path, and a symlink inside the target each escape a naive join.
|
|
13
|
+
- **Destructive operation on a derived path.** A delete, overwrite, move, or clean whose path is built from a variable, a config value, or a listing. Look for the empty or unset value that collapses it to a root, a glob or a symlink that carries it outside the folder it was meant for, no check that the resolved path sits at least one level below an expected root, and no read of what is there, owned by this tool or not, before the call. The fix to look for is resolve, require the root, then act. A write escaping its folder is path traversal. When a finding fits both, name the class whose fix applies.
|
|
9
14
|
- **Secrets and personal data leaving the process.** A token, a key, a password, or personal data reaching a log line, an error message, a session transcript, a published page, a pull request comment, or a sync to a remote. Check what a debug line prints and what a verbose flag adds.
|
|
10
15
|
- **Supply chain.** One-shot package execution of an unpinned version, which runs whatever the registry serves that day. A new dependency, and what its install scripts run. A lockfile that changes without a manifest change.
|
|
11
16
|
- **Time of check to time of use on a file write.** An existence or permission check followed by a write to the same path in a later step, and a predictable name in a shared temporary directory. Another process can swap the path in between.
|
|
@@ -18,6 +18,7 @@ A verdict also goes stale without saying so. A push after the pass changes what
|
|
|
18
18
|
- Drive every checklist box in the running app and give each exactly one verdict: pass or fail read off the page with the value quoted, pass or fail against a frame with what it shows, needs eyes for a box marked as taste, or not driven with the reason
|
|
19
19
|
- Drive a box written before the drivable format all the same, naming the route or width it guessed, so no box is skipped silently
|
|
20
20
|
- Read the checklist and the address from the evidence record rather than from the diff, the plan, or the author's description
|
|
21
|
+
- Drive only a build of the head the verdict names, and stop with nothing posted when the hosted preview was built from an older one
|
|
21
22
|
- Take the hosted preview, then the local preview, then an address the launch names, and refuse when none exists
|
|
22
23
|
- Report an address that does not answer as not driven rather than as a fail, and leave the review closed on a box no commit on the branch can settle, so an absent preview never holds the draft mark at every head
|
|
23
24
|
- Sweep console errors, sideways overflow at each named width, and the focus and details probes over the states reached, and nothing beyond them
|