@erclx/canon 5.64.0 → 5.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/git-pr/references/labels.md +6 -2
  4. package/claude/skills/git-pr-close/REQUIREMENT.md +29 -0
  5. package/claude/skills/git-pr-close/SKILL.md +55 -0
  6. package/claude/skills/git-pr-close/references/close.md +54 -0
  7. package/claude/skills/pr-evidence/SKILL.md +2 -2
  8. package/claude/skills/pr-evidence/references/evidence.md +3 -1
  9. package/claude/skills/role-worker/SKILL.md +2 -2
  10. package/claude/skills/test-craft/references/e2e.md +1 -1
  11. package/docs/workflow/skill-map.md +1 -0
  12. package/governance/ledger/skills/codebase-layout/SKILL.md +64 -0
  13. package/governance/ledger/skills/codebase-layout/frontend.md +62 -0
  14. package/governance/ledger/skills/codebase-layout/tests.md +26 -0
  15. package/governance/ledger/skills/review-craft/SKILL.md +61 -0
  16. package/governance/ledger/skills/review-craft/security.md +34 -0
  17. package/governance/ledger/skills/teach-craft/SKILL.md +33 -0
  18. package/governance/ledger/skills/teach-craft/lesson-craft.md +47 -0
  19. package/governance/ledger/skills/teach-craft/pedagogy.md +77 -0
  20. package/governance/ledger/skills/test-craft/SKILL.md +67 -0
  21. package/governance/ledger/skills/test-craft/component.md +49 -0
  22. package/governance/ledger/skills/test-craft/e2e.md +55 -0
  23. package/governance/ledger/skills/test-craft/unit.md +54 -0
  24. package/package.json +3 -3
  25. package/src/claude/cases/git.ts +4 -0
  26. package/src/claude/skills-audit.ts +7 -0
  27. package/src/commands/labels.ts +152 -4
  28. package/src/commands/pr.ts +263 -2
  29. package/src/commands/sandbox.ts +247 -2
  30. package/src/gate/measures.ts +3 -0
  31. package/src/gate/stages.ts +25 -0
  32. package/src/labels/apply.ts +10 -5
  33. package/src/labels/sync.ts +17 -0
  34. package/src/migrate/records.ts +6 -0
  35. package/src/pr/close.ts +152 -0
  36. package/src/pr/health.ts +56 -0
  37. package/src/pr/local.ts +49 -8
  38. package/src/pr/rest.ts +10 -2
  39. package/src/sandbox/replay/expected.ts +137 -0
  40. package/src/sandbox/replay/run.ts +348 -0
  41. package/src/sandbox/replay/verdict.ts +102 -0
  42. package/src/tooling/verify-stack.ts +4 -5
  43. package/tooling/astro/configs/playwright.config.ts +2 -2
  44. package/tooling/base/reference.md +1 -0
  45. package/tooling/base/seeds/canon/config/pr-labels.toml +41 -0
  46. package/tooling/nextjs/configs/playwright.config.ts +2 -2
  47. package/tooling/vite-react/configs/playwright.config.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.66.0](https://github.com/erclx/canon/compare/v5.65.0...v5.66.0) (2026-10-25)
4
+
5
+
6
+ ### Features
7
+
8
+ * **labels:** seed a starter label map and create its labels ([#2715](https://github.com/erclx/canon/issues/2715)) ([82a11b1](https://github.com/erclx/canon/commit/82a11b13870960926f0844519a76e039afd0ed5c))
9
+ * **pr:** close a pull request with a required reason ([#2718](https://github.com/erclx/canon/issues/2718)) ([963f784](https://github.com/erclx/canon/commit/963f784e46e25e3c42ea1f6027a7b04860ec544e))
10
+ * **pr:** probe declared health paths before linking the local preview ([#2712](https://github.com/erclx/canon/issues/2712)) ([a16c3f9](https://github.com/erclx/canon/commit/a16c3f966211f5bd9b8af9f82720d42251ac41b9))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **sandbox:** retry the replay checkout copy on a vanished file ([#2720](https://github.com/erclx/canon/issues/2720)) ([64d964b](https://github.com/erclx/canon/commit/64d964bdae0e26f79ab5c0ddc0c1f0e80bc20e6b))
16
+ * **tooling:** install Go for the go stack verify job ([#2717](https://github.com/erclx/canon/issues/2717)) ([e87d433](https://github.com/erclx/canon/commit/e87d433bdbf64945165923d1b6f7294e2d873b7b))
17
+
18
+ ## [5.65.0](https://github.com/erclx/canon/compare/v5.64.0...v5.65.0) (2026-10-25)
19
+
20
+
21
+ ### Features
22
+
23
+ * **sandbox:** fail the consumer replay when a snapshot read drifts ([#2709](https://github.com/erclx/canon/issues/2709)) ([68dc0b7](https://github.com/erclx/canon/commit/68dc0b7b55634ac9f7affca6da92cb523ed61754))
24
+ * **sandbox:** replay consumer snapshots through sync in the gate ([#2703](https://github.com/erclx/canon/issues/2703)) ([3fd2934](https://github.com/erclx/canon/commit/3fd2934779b7f242a66ea273b3c53f79802e6494))
25
+ * **skills:** ledger the review and teach craft sources ([#2702](https://github.com/erclx/canon/issues/2702)) ([877b660](https://github.com/erclx/canon/commit/877b66007e7e28c46c6de63d5a891083c19df6c1))
26
+ * **skills:** source every test-craft and codebase-layout bullet ([#2704](https://github.com/erclx/canon/issues/2704)) ([44a23e9](https://github.com/erclx/canon/commit/44a23e936c62cab229a49f82a8775933e540460e))
27
+
3
28
  ## [5.64.0](https://github.com/erclx/canon/compare/v5.63.0...v5.64.0) (2026-10-24)
4
29
 
5
30
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canon",
3
3
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
4
- "version": "5.64.0",
4
+ "version": "5.66.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -109,10 +109,14 @@ Labelling runs whenever this skill runs and at no other time, recomputing over t
109
109
  Warn and continue rather than creating it, naming the command in the warning:
110
110
 
111
111
  ```bash
112
- gh label create <name> --description "<text>"
112
+ canon labels sync
113
113
  ```
114
114
 
115
- Creating a label writes to the repository settings from a run invoked to open a pull request, and a label created from a map typo is harder to notice than a warning.
115
+ It creates every label the map names that the remote lacks, and never edits or deletes one.
116
+
117
+ - An installed `canon` predating the verb takes `gh label create <name>` per label instead
118
+ - Creating a label writes to the repository settings, and a label created from a map typo is harder to notice than a warning
119
+ - So the operator runs the sync on purpose after reading the map, and a run invoked to open a pull request never does
116
120
 
117
121
  The refusal names the label it rejected and applies none of the set, so an unseen warning leaves the run reading like one that labelled. Surface it beside the result line rather than letting the pull request URL stand alone.
118
122
 
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: git-pr-close
3
+ description: What closing a pull request unmerged is for, the gap it closes, and how it splits from merging and from the verb it calls
4
+ ---
5
+
6
+ # Git PR close requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, a session asked to close a pull request improvises a bare close. Most hand-closed pull requests then carry no reason, so a reader who finds one later cannot tell a rejected idea from a superseded one or a pause. No `git-*` skill covered the act, so the request had nowhere to route.
11
+
12
+ ## Must
13
+
14
+ - Every close goes through `canon pr close`, which refuses without a reason and posts it before the close
15
+ - The reason follows the shape `references/close.md` fixes, opening on what happened and ending on what replaces it or how to reopen
16
+ - A close of another branch's pull request names that branch through `--head`, so a wrong number refuses rather than closing someone else's work
17
+
18
+ ## Must not
19
+
20
+ - Merge, mark ready, or reopen a pull request
21
+ - Guess a number from the newest pull request in view
22
+ - Close with no reason, or post the reason any way other than through the verb
23
+ - Exist only to be typed by name. It earns its place when a session routes "close this PR" or a superseded batch here unprompted.
24
+
25
+ ## Out of scope
26
+
27
+ - Writing the gate on the reason, which the verb owns
28
+ - Merging, which the operator runs through `canon pr merge`
29
+ - Closing an issue, which `git-issue` covers
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: git-pr-close
3
+ description: Closes an open pull request without merging it, posting a short reason first and deleting its head branch, through `canon pr close`. Use when asked to "close this PR", "close #N", "supersede #N with #M", "abandon this pull request", or "drop this PR". Do NOT use to merge, which the operator does, or to close an issue, which `git-issue` covers.
4
+ metadata:
5
+ family: after-pr
6
+ ---
7
+
8
+ # Git PR close
9
+
10
+ Close one pull request unmerged with its reason on the thread, so a later reader finds why without asking.
11
+
12
+ Read `${CLAUDE_SKILL_DIR}/references/close.md` before writing the reason, for its shape and the two forms it takes.
13
+
14
+ ## Guards
15
+
16
+ - Take the number the caller named. With none named, "this pull request" means the current branch's, read from the `number` of `canon pr head --json`.
17
+ - Never guess a number from the newest pull request in view, since a wrong number closes another branch's work
18
+ - If the caller gave no reason and none follows from the conversation, stop: `❌ No reason to post. Say why this pull request is closing.`
19
+
20
+ ## Step 1: write the reason
21
+
22
+ Write the reason to `.canon/tmp/pr/close/close-<number>.md` in its own call, in the shape `close.md` fixes.
23
+
24
+ ## Step 2: close
25
+
26
+ Run the verb. It refuses unless the pull request's head is the branch `--head` names, defaulting to the current branch, so a wrong number writes nothing.
27
+
28
+ ```bash
29
+ canon pr close <number> --reason-file .canon/tmp/pr/close/close-<number>.md --json
30
+ ```
31
+
32
+ - Pass `--head <branch>` only when closing a branch this checkout is not on, taking the branch from the caller, such as a dispatch naming it or the batch a replacement merged
33
+ - Never read `--head` off the pull request being closed, since a branch read from the same number agrees with any number and the check proves nothing
34
+ - Pass `--keep-branch` only when the caller says the branch stays
35
+ - The verb posts the reason, closes, then deletes the branch, and refuses before any write on a reason it cannot publish
36
+
37
+ ## Step 3: read the record
38
+
39
+ Branch on `reason` rather than the exit, since a shell function wrapping `canon` can flatten it.
40
+
41
+ | `reason` | Route |
42
+ | ---------------------- | ---------------------------------------------------------------------------- |
43
+ | `closed` | Report the comment URL, and name the branch when `branch` is `delete-failed` |
44
+ | `reason-unpublishable` | Rewrite the sentence each finding names, then run Step 2 again |
45
+ | `head-mismatch` | Stop and report it, since the number names another branch's pull request |
46
+ | `close-failed` | Report that the comment posted and the pull request is still open |
47
+ | Any other refusal | Report the `message` and stop |
48
+
49
+ ## Output
50
+
51
+ One line on a close:
52
+
53
+ ```plaintext
54
+ ✅ Closed #<number>: <comment url>
55
+ ```
@@ -0,0 +1,54 @@
1
+ ---
2
+ title: Closing comment reference
3
+ description: The shape of the comment a pull request carries when it closes unmerged, its two forms, and the limits the verb checks
4
+ ---
5
+
6
+ # Closing comment reference
7
+
8
+ ## Scope
9
+
10
+ Governs the comment posted when a pull request closes without merging.
11
+
12
+ Does not govern:
13
+
14
+ - A pull request body or title: `${CLAUDE_SKILL_DIR}/../git-pr/references/pr.md`
15
+ - A review reply, which `review-address` writes
16
+
17
+ ## Shape
18
+
19
+ A reader who finds the closed pull request later learns why it closed and where the work went, in two sentences at most.
20
+
21
+ - Open on what happened: `Superseded by #<number>` when another pull request carries the work, or `Closing unmerged.` otherwise
22
+ - Say why in one sentence, naming the decision rather than retelling the discussion that reached it
23
+ - End on what replaces it, or how to reopen when the close is a pause
24
+ - Keep each paragraph under 350 characters, and two paragraphs at most
25
+
26
+ ### Superseded
27
+
28
+ Another pull request carries the work, so the comment links it and says nothing is left behind.
29
+
30
+ ```markdown
31
+ Superseded by #<replacement>, which combines this batch with the five other context rebuilds and carries every reviewed change from this branch. Nothing here is left to carry over.
32
+ ```
33
+
34
+ ### Closed for a decision
35
+
36
+ Nothing replaces the work, so the comment names the decision that ended it.
37
+
38
+ ```markdown
39
+ Closing unmerged. Base's starter label map should stay stack-neutral rather than list every stack's configs, so each project adds rows for its own stack.
40
+ ```
41
+
42
+ ## What the verb refuses
43
+
44
+ `canon pr close` checks the reason before it reads the pull request, and refuses `reason-unpublishable` with the findings in its record.
45
+
46
+ - A banned character, a phase label, a board reference, or a session link, the checks `canon labels scan` runs on a body
47
+ - A paragraph or a run of paragraphs past the density limits, measured on the reason itself
48
+ - The scan measures density only on a post opening on a known heading, so the verb measures it here
49
+
50
+ ## Sources
51
+
52
+ - [Zephyr pull request lifecycle policy](https://docs.zephyrproject.org/latest/contribute/pr_lifecycle_policy.html)
53
+ - "Close with explicit rationale and a reopen path."
54
+ - For a superseded one: "Link the replacement pull request." and "Add a short summary comment preserving context."
@@ -43,11 +43,11 @@ Collect only the lines below whose condition holds, and nothing when none does.
43
43
  | A checklist posted alone | `📋 Posted the UI checklist to <number>, on its own.` |
44
44
  | The preview step returned an address | `🔗 Preview: <url>` |
45
45
  | The evidence step posted the local link | `🖥️ Local preview: <url>` |
46
- | The local step refused and evidence or a checklist posted | `🖥️ No local preview: <reason>` |
46
+ | The local step refused and evidence or a checklist posted | `🖥️ No local preview: <reason>: <message>` |
47
47
  | A git refusal or a preview refusal the reference reports | `⚠️ <reason>: <message>` |
48
48
 
49
49
  ### The no-local-preview line
50
50
 
51
- It fires when the local step refused as `no-server` or `no-listener-reader`, since that pull request changes a rendered surface and a reviewer could have used the link. A later run only carries a link forward, so it cannot add one the comment never had.
51
+ It fires when the local step refused under any reason the reference holds, `unhealthy` included, since that pull request changes a rendered surface and a reviewer could have used the link. The `message` names what to fix, such as the failing health path. A later run only carries a link forward, so it cannot add one the comment never had.
52
52
 
53
53
  To add the link later, start the server and run this skill again, adding `--checklist` to the evidence call when one is still owed.
@@ -35,7 +35,9 @@ canon pr local --json
35
35
  The verb reports the lowest port serving an HTML page whose process runs inside this worktree, never one in another worktree or the main checkout, which shows a different branch. `canon pr local --help` states the contract. Read `reason` on the record rather than the exit code.
36
36
 
37
37
  - `ok`: hold the record's `url` for the evidence step below.
38
- - `no-server` or `no-listener-reader`: hold the reason for the closing report and pass no link. Never start a server here, since the ship chain cannot own one. A worker starts one under `role-worker`.
38
+ - `no-server`, `no-listener-reader`, `unhealthy`, or `invalid-config`: hold the reason and the record's `message` for the closing report, and pass no link.
39
+ - `unhealthy` means a page answered but a health path declared in `canon/config/local.toml` failed. `invalid-config` means that file cannot be read, so nothing was checked.
40
+ - Never start a server here, since the ship chain cannot own one. A worker starts one under `role-worker`.
39
41
  - Anything else, including no record or an older binary's unknown-subcommand error: move on silently, as a skip rather than a stop.
40
42
 
41
43
  ### Where the link lands
@@ -46,8 +46,8 @@ Open the task's `## Findings` line for an override with the bold source-and-date
46
46
 
47
47
  A painted pull request needs a server in this worktree for `canon pr local` to find, and this session is the one with a lifetime to own it. `auto-ship` Step 5 decides whether the diff is painted, so this body restates no file test.
48
48
 
49
- - Run `canon pr local --json` first and start nothing when `reason` reads `ok`
50
- - Otherwise start the stack's `dev` script as a background command from the worktree root before the pull request step. `dev` follows the worktree, so a `review-address` fix shows on the same link.
49
+ - Run `canon pr local --json` first. Start nothing on `ok`, `unhealthy`, or `invalid-config`, and carry a refusal's `message` in the announcement
50
+ - Otherwise start the stack's `dev` in the background from the worktree root before the pull request step, so a `review-address` fix shows on the same link.
51
51
  - Wait up to 60 seconds for the verb to read `ok`, then ship either way. A stack with no `dev` script gets no start, and `pr-evidence` reports `no-server`.
52
52
  - Never detach it with `nohup`, `setsid`, or `disown`, since the owning session is the stop. `canon worktrees reclaim` ends any listener left in a worktree it removes.
53
53
 
@@ -31,7 +31,7 @@ An element counts as stable once it "has maintained the same bounding box for at
31
31
 
32
32
  - Run with motion reduced unless the test asserts motion, and opt back in per test with `page.emulateMedia({ reducedMotion: 'no-preference' })`.
33
33
  - Set it once in the config's `use` block as `contextOptions: { reducedMotion: 'reduce' }`, since the option defaults to `'no-preference'` ([BrowserContext options](https://playwright.dev/docs/api/class-browser#browser-new-context)).
34
- - A top-level `use.reducedMotion` reaches no page and type-checks nowhere, so a spec asserting the media query is what catches it
34
+ - From Playwright 1.50 a top-level `use: { reducedMotion: 'reduce' }` works too ([TestOptions](https://playwright.dev/docs/api/class-testoptions)). Before 1.50 it is no test option, so a spec asserting the media query catches it
35
35
 
36
36
  A site honoring the reduced preference then has nothing to wait out in any test that does not opt back in.
37
37
 
@@ -80,6 +80,7 @@ Groups run in the order a project meets them. Every name `canon claude skills li
80
80
  | `canon:git-followup` | A small edit on a branch with an open PR |
81
81
  | `canon:pr-evidence` | A new head needs its screenshots re-posted |
82
82
  | `canon:git-split` | A branch carries unrelated commits |
83
+ | `canon:git-pr-close` | A pull request closes without merging |
83
84
  | `canon:git-issue` | Something belongs on the tracker |
84
85
  | `canon:git-worktree` | After a merge, to reclaim worktrees |
85
86
 
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: Codebase layout skill ledger
3
+ description: Sources for claude/skills/codebase-layout/SKILL.md, one row per bullet in its concern groups
4
+ ---
5
+
6
+ # Codebase layout skill ledger
7
+
8
+ The field is source organization. Robert Martin carries cohesion and folder naming, Kent C. Dodds and Robin Wieruch carry colocation and promotion, bulletproof-react carries the import direction, and the Go blog carries file and package naming. The closing sections and `## What this delegates` restate these rules or route, so they take no table.
9
+
10
+ No outside source takes a side on when a plan states a path, so the rows for stating a reason, naming a new folder, and reading a reference are house choices naming the misplacement each prevents.
11
+
12
+ ## Read the project's strategy first
13
+
14
+ | Bullet | Source | Read |
15
+ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
16
+ | Name the project's layout first | [React, File Structure](https://legacy.reactjs.org/docs/faq-structure.html): "React doesn’t have opinions on how you put files into folders", so the project's own layout is the only one a new file can follow | 2026-10-24 |
17
+ | Keep to that strategy | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): "choose a strategy that works for you and your team and be consistent across the project" | 2026-10-24 |
18
+ | A strategy change is its own decision | House choice: a strategy changed as a side effect of placing one file leaves two strategies in the tree, and every later reader guesses which one a file follows | 2026-10-24 |
19
+
20
+ ## Group what changes together
21
+
22
+ | Bullet | Source | Read |
23
+ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
24
+ | One folder per reason to change | [Martin, The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html): "Gather together the things that change for the same reasons. Separate those things that change for different reasons." | 2026-10-24 |
25
+ | Name a folder for what it holds | [Martin, Screaming Architecture](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html): "Your architectures should tell readers about the system, not about the frameworks you used in your system." | 2026-10-24 |
26
+ | No bare `utils` or `helpers` bucket | [Gerrand, Package names](https://go.dev/blog/package-names): "Packages named util , common , or misc provide clients with no sense of what the package contains." | 2026-10-24 |
27
+
28
+ ## Name a file for what it covers inside its folder
29
+
30
+ | Bullet | Source | Read |
31
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
32
+ | The stem never repeats the folder | [Gerrand, Package names](https://go.dev/blog/package-names): "Since client code uses the package name as a prefix when referring to the package contents, the names for those contents need not repeat the package name." | 2026-10-24 |
33
+ | Drop the prefix and retarget on a move | House choice: a file moved into a subfolder that keeps its old prefix says its folder twice, and a citation left on the old path resolves nowhere | 2026-10-24 |
34
+ | The stem runs to the first dot | House choice: reading the stem past a suffix lets `checkout/checkout.test.ts` pass a check that `checkout/checkout.md` fails, though both repeat their folder | 2026-10-24 |
35
+
36
+ ## Split before the file lands
37
+
38
+ | Bullet | Source | Read |
39
+ | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
40
+ | Split on a second role, before landing | [Martin, The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html): "Separate those things that change for different reasons." Splitting before the file lands is a House choice: the split costs a handful of paths then and 98 later, as the body records | 2026-10-24 |
41
+ | Ten files is a prompt, not a gate | House choice: no source gives a reliable ceiling, and a count fails a large folder of one role that reads fine flat while passing a small one mixing two | 2026-10-24 |
42
+ | A new role gets a named folder | House choice: a role whose first file lands beside its nearest neighbor leaves the folder holding two roles, and the next file copies the first | 2026-10-24 |
43
+
44
+ ## Place a file with its consumer
45
+
46
+ | Bullet | Source | Read |
47
+ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
48
+ | Colocate with the one consumer | [Dodds, Colocation](https://kentcdodds.com/blog/colocation): "Place code as close to where it's relevant as possible" | 2026-10-24 |
49
+ | Promote on the second consumer | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): "if exactly one feature uses a util, it lives inside that feature", and "once two or more features need it, it moves up to the shared layer" | 2026-10-24 |
50
+ | Imports flow one way | [bulletproof-react, Project Structure](https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md): "the code should flow in one direction, from shared parts of the code to the application (shared -> features -> app)" | 2026-10-24 |
51
+
52
+ ## State the reason on every new path
53
+
54
+ | Bullet | Source | Read |
55
+ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
56
+ | A one-clause reason per new path | House choice: a worker copies the path a plan gives it, so a path with no stated reason lands beside its nearest neighbor and the plan's placement call is never made | 2026-10-24 |
57
+ | Name a new folder where it is created | House choice: a folder the plan leaves implied is inferred by the worker, who drops the file in the nearest existing folder instead | 2026-10-24 |
58
+
59
+ ## Read the reference for the category
60
+
61
+ | Bullet | Source | Read |
62
+ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
63
+ | Interface source reference | House choice: an interface file placed without `frontend.md` lands in the shared `components/` or `lib/` folder whatever its consumer, the flat growth that reference records | 2026-10-24 |
64
+ | Test file reference | House choice: a test helper placed without `tests.md` lands beside the specs it serves, so the end to end folder stops holding one role | 2026-10-24 |
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Frontend layout reference ledger
3
+ description: Sources for claude/skills/codebase-layout/references/frontend.md, one row per bullet
4
+ ---
5
+
6
+ # Frontend layout reference ledger
7
+
8
+ The field is interface source organization. bulletproof-react carries feature folders and the import direction, Robin Wieruch carries the levels and the promotion rule, and the Next.js docs carry routing. Each row cites the bullet's own inline link where the reference carries one.
9
+
10
+ The worked failure reports what one project's folders did, so its rows are house choices naming the failure the incident shows rather than outside citations.
11
+
12
+ ## Feature folders against shared UI
13
+
14
+ | Bullet | Source | Read |
15
+ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
16
+ | One feature's code under its folder | [bulletproof-react, Project Structure](https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md): "organize most of the code within the features folder", and "Only include the ones that are necessary for the feature." | 2026-10-24 |
17
+ | Shared `components/` for two features | [bulletproof-react, Project Structure](https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md): `components` holds "shared components used across the entire application" | 2026-10-24 |
18
+ | One feature's component is feature code | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): feature components "are often only used once in a React project", while generic UI components "are used by more than one component" | 2026-10-24 |
19
+ | No feature imports another | [bulletproof-react, Project Structure](https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md): "It might not be a good idea to import across the features. Instead, compose different features at the application level." | 2026-10-24 |
20
+ | Enforce the flow with an import lint | [bulletproof-react, Project Structure](https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md): "To forbid cross-feature imports, you can use ESLint", through `import/no-restricted-paths` | 2026-10-24 |
21
+
22
+ ## Grow in levels
23
+
24
+ | Bullet | Source | Read |
25
+ | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
26
+ | Start flat | [React, File Structure](https://legacy.reactjs.org/docs/faq-structure.html): "If you feel completely stuck, start by keeping all files in a single folder. Eventually it will grow large enough that you will want to separate some files from the rest." | 2026-10-24 |
27
+ | The next level on a named event | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): "The day the customer feature needs it too, it moves up to the top-level hooks/ folder." | 2026-10-24 |
28
+ | One level per change | House choice: a plan that jumps from flat to a full feature tree rewrites every import in the project in one diff no review can follow | 2026-10-24 |
29
+
30
+ ## Routes
31
+
32
+ | Bullet | Source | Read |
33
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
34
+ | The router's own conventions first | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): the page gives "an overview of all the folder and file conventions in Next.js, and recommendations for organizing your project" | 2026-10-24 |
35
+ | An unopinionated framework leaves it open | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): "Next.js is unopinionated about how you organize and colocate your project files." | 2026-10-24 |
36
+ | One strategy, kept consistent | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): "choose a strategy that works for you and your team and be consistent across the project" | 2026-10-24 |
37
+ | A route's component in a private folder | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): private folders "colocate non-routable files", as `app/blog/_components/Post.tsx` is marked "Not routable" and a "safe place for UI utilities" | 2026-10-24 |
38
+ | `components` and `lib` are placeholders | [Next.js, Project structure](https://nextjs.org/docs/app/getting-started/project-structure): "we're using components and lib folders as generalized placeholders, their naming has no special framework significance" | 2026-10-24 |
39
+
40
+ ## Hooks and helpers
41
+
42
+ | Bullet | Source | Read |
43
+ | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
44
+ | One feature's hook inside it | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): "A hook that only the project feature uses lives inside features/project/hooks/ ." | 2026-10-24 |
45
+ | Promote on the second feature | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): "once two or more features need it, it moves up to the shared layer" | 2026-10-24 |
46
+ | Split a shared `lib/` holding two roles | [Martin, The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html): "Separate those things that change for different reasons." | 2026-10-24 |
47
+ | A helper named for what it does | [Gerrand, Package names](https://go.dev/blog/package-names): "Avoid meaningless package names. Packages named util , common , or misc provide clients with no sense of what the package contains." | 2026-10-24 |
48
+
49
+ ## Fixtures and sample data
50
+
51
+ | Bullet | Source | Read |
52
+ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
53
+ | Fixtures beside their feature | [Dodds, Colocation](https://kentcdodds.com/blog/colocation): "Things that change together should be located as close as reasonable." | 2026-10-24 |
54
+ | Promote a fixture on two features | House choice: a fixture moved to shared code for one feature's tests drifts from that feature, and the next change to it lands far from the tests it breaks | 2026-10-24 |
55
+
56
+ ## A worked failure
57
+
58
+ | Bullet | Source | Read |
59
+ | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
60
+ | The rules said split, and nobody applied them | House choice: a rule loaded beside a plan that names every file as a sibling of the last loses to the plan, so placement has to be decided where the path is written | 2026-10-24 |
61
+ | The split touched 98 files | House choice: a split put off until a folder overflows touches every import of every file in it, and a folder left without a placement rule grows flat again | 2026-10-24 |
62
+ | A named subfolder at the twelfth file | House choice: the cost of placement grows with the folder, so the cheapest split is the one a plan names when the second role's first file arrives | 2026-10-24 |
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: Test layout reference ledger
3
+ description: Sources for claude/skills/codebase-layout/references/tests.md, one row per bullet
4
+ ---
5
+
6
+ # Test layout reference ledger
7
+
8
+ The field is test file organization. Kent C. Dodds carries colocating a test with its module, and Playwright's fixtures and page object docs carry the split between specs and support. The reference's worked failure is prose rather than bullets, so it takes no table.
9
+
10
+ ## Unit and component tests
11
+
12
+ | Bullet | Source | Read |
13
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
14
+ | A test beside its module | [Dodds, Colocation](https://kentcdodds.com/blog/colocation): "we should co-locate our tests files with the file or group of files they are testing" | 2026-10-24 |
15
+ | The test moves with the module | [Dodds, Colocation](https://kentcdodds.com/blog/colocation): with a mirrored tree, "We'd move or delete a src/ file without updating the corresponding" file beside it, and "All the pitfalls described above apply here as well" for tests | 2026-10-24 |
16
+ | A one-file factory stays in that file | [Wieruch, React Folder Structure](https://www.robinwieruch.de/react-folder-structure/): "if exactly one feature uses a util, it lives inside that feature", and "once two or more features need it, it moves up to the shared layer" | 2026-10-24 |
17
+
18
+ ## End to end tests
19
+
20
+ | Bullet | Source | Read |
21
+ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
22
+ | Only specs in the runner's folder | House choice: support code among the specs gives a new spec no single place to find its setup, and the next helper lands beside the others | 2026-10-24 |
23
+ | One merged fixtures module | [Playwright, Fixtures](https://playwright.dev/docs/test-fixtures): an extended test "can be used in multiple test files, and each of them will get the fixtures", and `mergeTests` combines "test fixtures from multiple files or modules" | 2026-10-24 |
24
+ | Each page object its own module | [Playwright, Fixtures](https://playwright.dev/docs/test-fixtures) imports each page object from its own module, as `TodoPage` from `./todo-page`, and [page object models](https://playwright.dev/docs/pom) capture "element selectors in one place" | 2026-10-24 |
25
+ | Support in its own folder, named by use | House choice: a single `helpers` file every spec imports grows into a bucket naming no role, the fault the body's naming rule forbids for any folder | 2026-10-24 |
26
+ | Group specs by journey once they mix | House choice: specs for two journeys in one folder hold two roles, so a reader finds a journey's specs only by opening each file | 2026-10-24 |
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: Review craft skill ledger
3
+ description: Sources for claude/skills/review-craft/SKILL.md, one row per bullet or ordered step in its concern groups
4
+ ---
5
+
6
+ # Review craft skill ledger
7
+
8
+ The field is code review. Google's reviewer guide carries the axes, Parnas, Ousterhout, and Beck as Fowler records him carry the design walk, and the skills pinned at `addyosmani/agent-skills@2686b620` carry the bar, performance, and scope checks.
9
+
10
+ Steps 4, 5, and 8 of the walk have no source in the skill's `adopted.md`, so their rows cite Fowler's FlagArgument with Refactoring Guru's Message Chains, Martin's Single Responsibility Principle post, and Cockburn's Hexagonal Architecture.
11
+
12
+ The proof ladder and the evidence bar are this toolkit's own, so their rows name the failure each prevents. Closing sections and `## What this delegates` restate these rules or route, so they take no table.
13
+
14
+ Parnas's paper refused a read at its ACM DOI, `10.1145/361598.361623`, so the rows quote an open copy of the same paper.
15
+
16
+ ## Open with the one fact the change's safety rests on
17
+
18
+ | Bullet | Source | Read |
19
+ | -------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------- |
20
+ | Asserted | House choice: a risky claim taken on the description's word merges unproven, since nothing marks it as the weakest proof | 2026-10-24 |
21
+ | Pointed at | House choice: a claim naming its test reads as proven when nobody opened the test, so naming the code is its own lower rung | 2026-10-24 |
22
+ | Walked through | House choice: reasoning that traces the path still misses the input it never imagined, so it ranks below a test that runs | 2026-10-24 |
23
+ | Tested | House choice: a claim with no failing test regresses silently on the next change, so a test in the diff outranks any argument | 2026-10-24 |
24
+ | Reproduced | House choice: a test can pass on a stubbed path, so a recorded run of the real thing is the one rung above it | 2026-10-24 |
25
+
26
+ ## Read the axes in this order
27
+
28
+ | Bullet | Source | Read |
29
+ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
30
+ | Design and scope | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "The most important thing to cover in a review is the overall design of the CL", and "Reviewers should be especially vigilant about over-engineering" | 2026-10-24 |
31
+ | Correctness and edge cases | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "you should still be thinking about edge cases, looking for concurrency problems, trying to think like a user" | 2026-10-24 |
32
+ | What breaks outside the diff | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "Sometimes you have to look at the whole file to be sure that the change actually makes sense", and a change that "deletes or deprecates code" asks "whether the documentation should also be deleted" | 2026-10-24 |
33
+ | Tests | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "Will the tests actually fail when the code is broken?" | 2026-10-24 |
34
+ | Guard the bar | [agent-skills, constraint-driven-development](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/constraint-driven-development/SKILL.md): it watches the diff for a weakened bar, being "new @ts-ignore or eslint-disable suppressions, skipped or deleted tests, assertions stripped out, unimplemented stubs, thresholds edited down" | 2026-10-24 |
35
+ | Performance | [agent-skills, code-review-and-quality](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/code-review-and-quality/SKILL.md): "Any N+1 query patterns?", "Any unbounded loops or unconstrained data fetching?", "Any missing pagination on list endpoints?" | 2026-10-24 |
36
+ | Security | [agent-skills, security-and-hardening](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/security-and-hardening/SKILL.md): "Where does untrusted data cross into your system?", asked before any control is checked | 2026-10-24 |
37
+ | Rendered output | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): a UI change is when checking behavior matters most, since "It's hard to understand how some changes will impact a user when you're just reading the code" | 2026-10-24 |
38
+ | Developer experience and operations | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "If a CL changes how users build, test, interact with, or release code, check to see that it also updates associated documentation" | 2026-10-24 |
39
+ | Executable prose | House choice: a skill body or rule is run by a model with no reviewer in the loop, so a race, an unstated precondition, or a contradiction between two steps ships as a bug that no test of the code catches | 2026-10-24 |
40
+ | Name the next change and count its reach | [Parnas, On the Criteria To Be Used in Decomposing Systems into Modules](https://www.win.tue.nl/~wstomv/edu/2ip30/references/criteria_for_modularization.pdf): "one begins with a list of difficult design decisions or design decisions which are likely to change" | 2026-10-24 |
41
+ | State what each unit hides | [Ousterhout and Martin, A Philosophy of Software Design vs Clean Code](https://github.com/johnousterhout/aposd-vs-clean-code): "I call these interfaces 'shallow': they don't help much in terms of reducing what the programmer needs to know" | 2026-10-24 |
42
+ | Each rule or constant in one place | [Fowler, BeckDesignRules](https://martinfowler.com/bliki/BeckDesignRules.html): Beck's rules include "No duplication", and the code "Has no duplicated logic" | 2026-10-24 |
43
+ | Flag parameters, chains, and global state | [Fowler, FlagArgument](https://martinfowler.com/bliki/FlagArgument.html): "A flag argument is a kind of function argument that tells the function to carry out a different operation depending on its value", and [Refactoring Guru, Message Chains](https://refactoring.guru/smells/message-chains): "the client is dependent on navigation along the class structure". House choice for global state: a read or write of it couples every caller to an order nothing in the signature shows | 2026-10-24 |
44
+ | One reason to change per file | [Martin, The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html): "Gather together the things that change for the same reasons. Separate those things that change for different reasons." | 2026-10-24 |
45
+ | List the hidden inputs | House choice: code reading the clock, the environment, the filesystem, or a random source runs differently in a test than in use, so its tests flake or fake the input and its reuse breaks on the next machine | 2026-10-24 |
46
+ | Match each pattern to a problem today | [Fowler, BeckDesignRules](https://martinfowler.com/bliki/BeckDesignRules.html): the last rule, "Fewest elements", so the code "Has the fewest possible classes and methods" | 2026-10-24 |
47
+ | Domain rules apart from data in and out | [Cockburn, Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/): an application "developed and tested in isolation from its eventual run-time devices and databases" | 2026-10-24 |
48
+ | Names, literals, dropped errors, effects | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "Did the developer pick good names for everything?" | 2026-10-24 |
49
+ | Name the split of two concerns | [Google, Small CLs](https://google.github.io/eng-practices/review/developer/small-cls.html): "the right size for a CL is one self-contained change", one that "addresses just one thing" | 2026-10-24 |
50
+ | Count concepts before and after | [agent-skills, code-review-and-quality](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/code-review-and-quality/SKILL.md): "Does this refactor reduce complexity or just relocate it? Count the concepts a reader must hold to follow the change." | 2026-10-24 |
51
+ | Say why removed code existed | [agent-skills, code-simplification](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/code-simplification/SKILL.md): "Before changing or removing anything, understand why it exists", and "Check git blame" | 2026-10-24 |
52
+
53
+ ## Hold every finding to the evidence bar
54
+
55
+ | Bullet | Source | Read |
56
+ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
57
+ | Confirm against the reviewed head | [Google, What to look for in a code review](https://google.github.io/eng-practices/review/reviewer/looking-for.html): "Usually the code review tool will only show you a few lines of code around the parts that are being changed" | 2026-10-24 |
58
+ | Quote the rule cited | House choice: a finding citing a rule by name alone sends the author to find it first, and a paraphrase drifts from what the rule says | 2026-10-24 |
59
+ | Name the input that breaks | House choice: a finding with no failing input cannot be reproduced or refuted, so the author either guesses at a fix or dismisses a real bug | 2026-10-24 |
60
+ | Drop what a gate already owns | House choice: a review restating a linter or a type error reports it with less certainty than the gate, and the noise buries the findings only a reader can make | 2026-10-24 |
61
+ | Drop what rests on unread state | House choice: a finding about state the reviewer never opened is a guess posted as a fact, and the author spends a round disproving it | 2026-10-24 |
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Review craft security ledger
3
+ description: Sources for claude/skills/review-craft/references/security.md, one row per bullet
4
+ ---
5
+
6
+ # Review craft security ledger
7
+
8
+ The field is application security review. MITRE's CWE entries name each weakness, ShellCheck carries the shell fixes, npm's own docs and Snyk's lockfile write-up carry the supply chain, and Anthropic's security review action pinned at `anthropics/claude-code-security-review@0c6a49f1` carries the exclusions.
9
+
10
+ The threat model section and the classes stated as prose carry no bullet, so they take no row.
11
+
12
+ ## Classes to check
13
+
14
+ | Bullet | Source | Read |
15
+ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
16
+ | The paths into a shell | [CWE-78, OS Command Injection](https://cwe.mitre.org/data/definitions/78.html): "The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements" | 2026-10-24 |
17
+ | Quoting at the call site | [ShellCheck, SC2086](https://github.com/koalaman/shellcheck/wiki/SC2086): "Double quote to prevent globbing and word splitting." | 2026-10-24 |
18
+ | An empty value collapsing to a root | [ShellCheck, SC2115](https://github.com/koalaman/shellcheck/wiki/SC2115): "Use `\"${var:?}\"` to ensure this never expands to `/*`", against `rm -rf "$STEAMROOT/"*` | 2026-10-24 |
19
+ | A glob or symlink carrying it out | [CWE-59, Link Following](https://cwe.mitre.org/data/definitions/59.html): "does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource" | 2026-10-24 |
20
+ | No check one level below a root | [agent-skills, security-and-hardening](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/security-and-hardening/SKILL.md): the resolved target "sits under an allowlisted root", and "it is at least one level below that root" | 2026-10-24 |
21
+ | No read of what is there | [agent-skills, security-and-hardening](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/security-and-hardening/SKILL.md): the target "carries ownership evidence read before the operation" | 2026-10-24 |
22
+ | Name the class whose fix applies | House choice: one bug filed under two classes gets two fixes or neither, so the finding names the class whose fix the author applies | 2026-10-24 |
23
+ | Unpinned one-shot package execution | [npm, npx](https://docs.npmjs.com/cli/v10/commands/npx): a package "not present in the local project dependencies" is installed to the npm cache and run, so an unpinned name runs whatever the registry serves | 2026-10-24 |
24
+ | A new dependency's install scripts | [npm, scripts](https://docs.npmjs.com/cli/v10/using-npm/scripts): its life cycle order runs `preinstall`, `install`, and `postinstall` on `npm install` | 2026-10-24 |
25
+ | A lockfile changing with no manifest | [Snyk, Why npm lockfiles can be a security blindspot](https://snyk.io/blog/why-npm-lockfiles-can-be-a-security-blindspot-for-injecting-malicious-modules/): an install "will consult the lockfile as the primary source of truth for package versions and their sources" | 2026-10-24 |
26
+
27
+ ## Excluded
28
+
29
+ | Bullet | Source | Read |
30
+ | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
31
+ | Denial of service and exhaustion | [Anthropic, claude-code-security-review prompts](https://github.com/anthropics/claude-code-security-review/blob/0c6a49f1fa56a1d472575da86a94dbc1edb78eda/claudecode/prompts.py): "Denial of Service (DOS) vulnerabilities or resource exhaustion attacks", and "Rate limiting concerns" | 2026-10-24 |
32
+ | Generic input validation | [Anthropic, claude-code-security-review prompts](https://github.com/anthropics/claude-code-security-review/blob/0c6a49f1fa56a1d472575da86a94dbc1edb78eda/claudecode/prompts.py): "If there isn't a proven problem from a lack of input validation, don't report it." | 2026-10-24 |
33
+ | Open redirects | [Anthropic, claude-code-security-review findings filter](https://github.com/anthropics/claude-code-security-review/blob/0c6a49f1fa56a1d472575da86a94dbc1edb78eda/claudecode/findings_filter.py): drops a finding as "Open redirect vulnerability (not high impact)" | 2026-10-24 |
34
+ | A theoretical attack needing access held | [Anthropic, claude-code-security-review prompts](https://github.com/anthropics/claude-code-security-review/blob/0c6a49f1fa56a1d472575da86a94dbc1edb78eda/claudecode/prompts.py): "Skip theoretical issues, style concerns, or low-impact findings" | 2026-10-24 |