devrites 1.19.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-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +43 -0
- package/CHANGELOG.md +391 -0
- package/LICENSE +56 -0
- package/NOTICE.md +18 -0
- package/README.md +582 -0
- package/SECURITY.md +193 -0
- package/bin/devrites.mjs +100 -0
- package/docs/architecture.md +272 -0
- package/docs/cli-mcp.md +57 -0
- package/docs/command-map.md +143 -0
- package/docs/flow.md +360 -0
- package/docs/release.md +29 -0
- package/docs/skills.md +214 -0
- package/docs/usage.md +325 -0
- package/install.sh +359 -0
- package/mcp/devrites-mcp.mjs +103 -0
- package/pack/.claude/agents/devrites-code-reviewer.md +50 -0
- package/pack/.claude/agents/devrites-doubt-reviewer.md +55 -0
- package/pack/.claude/agents/devrites-frontend-reviewer.md +52 -0
- package/pack/.claude/agents/devrites-performance-reviewer.md +47 -0
- package/pack/.claude/agents/devrites-plan-reviewer.md +79 -0
- package/pack/.claude/agents/devrites-security-auditor.md +53 -0
- package/pack/.claude/agents/devrites-simplifier-reviewer.md +75 -0
- package/pack/.claude/agents/devrites-slice-wright.md +181 -0
- package/pack/.claude/agents/devrites-spec-reviewer.md +72 -0
- package/pack/.claude/agents/devrites-strategy-reviewer.md +62 -0
- package/pack/.claude/agents/devrites-test-analyst.md +47 -0
- package/pack/.claude/hooks/devrites-a1-guard.sh +81 -0
- package/pack/.claude/hooks/devrites-allow.sh +44 -0
- package/pack/.claude/hooks/devrites-cursor.sh +28 -0
- package/pack/.claude/hooks/devrites-orient.sh +53 -0
- package/pack/.claude/hooks/devrites-redwatch.sh +39 -0
- package/pack/.claude/hooks/devrites-refresh-indexes.sh +127 -0
- package/pack/.claude/hooks/devrites-reviewer-readonly.sh +28 -0
- package/pack/.claude/hooks/devrites-statusline.sh +18 -0
- package/pack/.claude/hooks/devrites-stop-gate.sh +45 -0
- package/pack/.claude/hooks/devrites-wright-scope.sh +35 -0
- package/pack/.claude/hooks/hooks.json +52 -0
- package/pack/.claude/rules/README.md +48 -0
- package/pack/.claude/rules/afk-hitl.md +245 -0
- package/pack/.claude/rules/agents.md +98 -0
- package/pack/.claude/rules/anti-patterns.md +48 -0
- package/pack/.claude/rules/code-review.md +38 -0
- package/pack/.claude/rules/coding-style.md +55 -0
- package/pack/.claude/rules/context-hygiene.md +97 -0
- package/pack/.claude/rules/core.md +119 -0
- package/pack/.claude/rules/development-workflow.md +40 -0
- package/pack/.claude/rules/documentation.md +27 -0
- package/pack/.claude/rules/error-handling.md +33 -0
- package/pack/.claude/rules/git-workflow.md +35 -0
- package/pack/.claude/rules/hooks.md +38 -0
- package/pack/.claude/rules/patterns.md +45 -0
- package/pack/.claude/rules/performance.md +27 -0
- package/pack/.claude/rules/prose-style.md +101 -0
- package/pack/.claude/rules/security.md +63 -0
- package/pack/.claude/rules/testing.md +88 -0
- package/pack/.claude/rules/tooling.md +72 -0
- package/pack/.claude/settings.json +53 -0
- package/pack/.claude/skills/devrites-api-interface/SKILL.md +45 -0
- package/pack/.claude/skills/devrites-audit/SKILL.md +73 -0
- package/pack/.claude/skills/devrites-browser-proof/SKILL.md +38 -0
- package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +50 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +47 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +17 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/regression-test.md +31 -0
- package/pack/.claude/skills/devrites-doubt/SKILL.md +75 -0
- package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +96 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/craft.md +59 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +116 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/fullstack.md +45 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +215 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/reuse-first.md +59 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/shape.md +60 -0
- package/pack/.claude/skills/devrites-interview/SKILL.md +81 -0
- package/pack/.claude/skills/devrites-lib/SKILL.md +76 -0
- package/pack/.claude/skills/devrites-lib/scripts/analyze.sh +78 -0
- package/pack/.claude/skills/devrites-lib/scripts/check-acceptance.sh +75 -0
- package/pack/.claude/skills/devrites-lib/scripts/close-out.sh +47 -0
- package/pack/.claude/skills/devrites-lib/scripts/conventions.py +273 -0
- package/pack/.claude/skills/devrites-lib/scripts/coverage.sh +51 -0
- package/pack/.claude/skills/devrites-lib/scripts/devrites.sh +69 -0
- package/pack/.claude/skills/devrites-lib/scripts/doctor.sh +92 -0
- package/pack/.claude/skills/devrites-lib/scripts/evidence-fresh.sh +63 -0
- package/pack/.claude/skills/devrites-lib/scripts/footprint.sh +45 -0
- package/pack/.claude/skills/devrites-lib/scripts/learnings.sh +74 -0
- package/pack/.claude/skills/devrites-lib/scripts/mutation-gate.sh +52 -0
- package/pack/.claude/skills/devrites-lib/scripts/package-existence.sh +68 -0
- package/pack/.claude/skills/devrites-lib/scripts/preamble.sh +76 -0
- package/pack/.claude/skills/devrites-lib/scripts/progress.sh +103 -0
- package/pack/.claude/skills/devrites-lib/scripts/readiness.sh +62 -0
- package/pack/.claude/skills/devrites-lib/scripts/reconcile.sh +123 -0
- package/pack/.claude/skills/devrites-lib/scripts/resolve.sh +279 -0
- package/pack/.claude/skills/devrites-lib/scripts/stuck.sh +67 -0
- package/pack/.claude/skills/devrites-lib/scripts/test-integrity.sh +87 -0
- package/pack/.claude/skills/devrites-lib/scripts/tick-afk.sh +52 -0
- package/pack/.claude/skills/devrites-prose-craft/SKILL.md +105 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/banned-phrases.md +95 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/examples.md +88 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/structures.md +134 -0
- package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +54 -0
- package/pack/.claude/skills/devrites-source-driven/SKILL.md +36 -0
- package/pack/.claude/skills/devrites-ux-shape/SKILL.md +121 -0
- package/pack/.claude/skills/devrites-ux-shape/reference/brief-template.md +93 -0
- package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
- package/pack/.claude/skills/rite/SKILL.md +135 -0
- package/pack/.claude/skills/rite/reference/menu.md +32 -0
- package/pack/.claude/skills/rite-adopt/SKILL.md +83 -0
- package/pack/.claude/skills/rite-adopt/reference/adoption.md +58 -0
- package/pack/.claude/skills/rite-adopt/reference/anti-patterns.md +19 -0
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +96 -0
- package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +35 -0
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +54 -0
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +59 -0
- package/pack/.claude/skills/rite-build/SKILL.md +261 -0
- package/pack/.claude/skills/rite-build/reference/afk-discipline.md +145 -0
- package/pack/.claude/skills/rite-build/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +149 -0
- package/pack/.claude/skills/rite-build/reference/evidence-standard.md +32 -0
- package/pack/.claude/skills/rite-build/reference/frontend-trigger.md +39 -0
- package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +38 -0
- package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +43 -0
- package/pack/.claude/skills/rite-build/reference/tdd.md +26 -0
- package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +115 -0
- package/pack/.claude/skills/rite-define/SKILL.md +157 -0
- package/pack/.claude/skills/rite-define/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-define/reference/gates.md +152 -0
- package/pack/.claude/skills/rite-define/reference/plan-template.md +65 -0
- package/pack/.claude/skills/rite-doctor/SKILL.md +50 -0
- package/pack/.claude/skills/rite-frame/SKILL.md +116 -0
- package/pack/.claude/skills/rite-frame/reference/failure-modes.md +68 -0
- package/pack/.claude/skills/rite-handoff/SKILL.md +95 -0
- package/pack/.claude/skills/rite-handoff/reference/handoff-template.md +34 -0
- package/pack/.claude/skills/rite-learn/SKILL.md +82 -0
- package/pack/.claude/skills/rite-plan/SKILL.md +82 -0
- package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +24 -0
- package/pack/.claude/skills/rite-plan/reference/dependency-graph.md +33 -0
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +42 -0
- package/pack/.claude/skills/rite-plan/reference/slicing.md +52 -0
- package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +34 -0
- package/pack/.claude/skills/rite-polish/SKILL.md +90 -0
- package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +177 -0
- package/pack/.claude/skills/rite-polish/reference/anti-patterns.md +27 -0
- package/pack/.claude/skills/rite-polish/reference/backend-polish.md +80 -0
- package/pack/.claude/skills/rite-polish/reference/browser-polish-evidence.md +31 -0
- package/pack/.claude/skills/rite-polish/reference/code.md +85 -0
- package/pack/.claude/skills/rite-polish/reference/design-system-discovery.md +35 -0
- package/pack/.claude/skills/rite-polish/reference/harden-checklist.md +109 -0
- package/pack/.claude/skills/rite-polish/reference/ui.md +136 -0
- package/pack/.claude/skills/rite-pressure-test/SKILL.md +43 -0
- package/pack/.claude/skills/rite-prototype/SKILL.md +87 -0
- package/pack/.claude/skills/rite-prove/SKILL.md +120 -0
- package/pack/.claude/skills/rite-prove/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-prove/reference/browser-proof.md +26 -0
- package/pack/.claude/skills/rite-prove/reference/failure-triage.md +25 -0
- package/pack/.claude/skills/rite-prove/reference/proof-ladder.md +26 -0
- package/pack/.claude/skills/rite-prove/reference/test-command-discovery.md +30 -0
- package/pack/.claude/skills/rite-quick/SKILL.md +81 -0
- package/pack/.claude/skills/rite-resolve/SKILL.md +113 -0
- package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +114 -0
- package/pack/.claude/skills/rite-review/SKILL.md +170 -0
- package/pack/.claude/skills/rite-review/reference/anti-patterns.md +32 -0
- package/pack/.claude/skills/rite-review/reference/cognitive-load.md +90 -0
- package/pack/.claude/skills/rite-review/reference/feature-scoped-review.md +26 -0
- package/pack/.claude/skills/rite-review/reference/five-axis-review.md +46 -0
- package/pack/.claude/skills/rite-review/reference/nielsen-heuristics.md +130 -0
- package/pack/.claude/skills/rite-review/reference/parallel-dispatch.md +62 -0
- package/pack/.claude/skills/rite-review/reference/performance-review.md +28 -0
- package/pack/.claude/skills/rite-review/reference/security-review.md +32 -0
- package/pack/.claude/skills/rite-seal/SKILL.md +183 -0
- package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +27 -0
- package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +63 -0
- package/pack/.claude/skills/rite-seal/reference/final-evidence.md +72 -0
- package/pack/.claude/skills/rite-seal/reference/go-no-go.md +37 -0
- package/pack/.claude/skills/rite-seal/reference/parallel-dispatch.md +69 -0
- package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +30 -0
- package/pack/.claude/skills/rite-seal/reference/seal-template.md +36 -0
- package/pack/.claude/skills/rite-ship/SKILL.md +120 -0
- package/pack/.claude/skills/rite-ship/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-ship/reference/close-out.md +31 -0
- package/pack/.claude/skills/rite-ship/reference/design-memory.md +120 -0
- package/pack/.claude/skills/rite-ship/reference/git-ship.md +42 -0
- package/pack/.claude/skills/rite-ship/reference/ship-template.md +33 -0
- package/pack/.claude/skills/rite-spec/SKILL.md +126 -0
- package/pack/.claude/skills/rite-spec/reference/acceptance-criteria.md +31 -0
- package/pack/.claude/skills/rite-spec/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-spec/reference/interview-patterns.md +56 -0
- package/pack/.claude/skills/rite-spec/reference/investigation.md +64 -0
- package/pack/.claude/skills/rite-spec/reference/question-protocol.md +61 -0
- package/pack/.claude/skills/rite-spec/reference/references-intake.md +57 -0
- package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +73 -0
- package/pack/.claude/skills/rite-spec/reference/spec-template.md +124 -0
- package/pack/.claude/skills/rite-spec/reference/state-workspace.md +159 -0
- package/pack/.claude/skills/rite-status/SKILL.md +101 -0
- package/pack/.claude/skills/rite-temper/SKILL.md +119 -0
- package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +29 -0
- package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +65 -0
- package/pack/.claude/skills/rite-temper/reference/scope-modes.md +53 -0
- package/pack/.claude/skills/rite-temper/reference/significance.md +46 -0
- package/pack/.claude/skills/rite-temper/reference/strategy-template.md +90 -0
- package/pack/.claude/skills/rite-vet/SKILL.md +155 -0
- package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +29 -0
- package/pack/.claude/skills/rite-vet/reference/artifacts.md +135 -0
- package/pack/.claude/skills/rite-vet/reference/cross-model.md +41 -0
- package/pack/.claude/skills/rite-vet/reference/depth.md +53 -0
- package/pack/.claude/skills/rite-vet/reference/eng-lenses.md +48 -0
- package/pack/.claude/skills/rite-vet/reference/review-axes.md +167 -0
- package/pack/.claude/skills/rite-zoom-out/SKILL.md +75 -0
- package/package.json +68 -0
- package/scripts/build-release-tarball.sh +74 -0
- package/scripts/check-cross-refs.py +121 -0
- package/scripts/check-no-global-writes.sh +44 -0
- package/scripts/check-rule-uniqueness.sh +73 -0
- package/scripts/devrites-detect.sh +175 -0
- package/scripts/eval-runner.py +273 -0
- package/scripts/grade-feature.sh +104 -0
- package/scripts/install-lib.sh +83 -0
- package/scripts/pin.sh +166 -0
- package/scripts/render-eval-summary.py +48 -0
- package/scripts/run-evals.sh +149 -0
- package/scripts/run-outcome-evals.sh +49 -0
- package/scripts/scan-pack-security.py +209 -0
- package/scripts/scan-supply-chain-iocs.py +127 -0
- package/scripts/supply-chain-iocs.json +11 -0
- package/scripts/sync-version.sh +56 -0
- package/scripts/validate-frontmatter.py +149 -0
- package/scripts/validate-workflow-security.py +86 -0
- package/scripts/validate.sh +234 -0
- package/uninstall.sh +137 -0
- package/update.sh +196 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# The vet review — scope challenge, four axes, required outputs
|
|
2
|
+
|
|
3
|
+
The body of `/rite-vet`. Run §0 first as a blocking gate, then the four axes one at a time,
|
|
4
|
+
then the required outputs. Apply the senior-engineer lenses in [`eng-lenses.md`](eng-lenses.md)
|
|
5
|
+
throughout — they're how you *see* the findings, not a separate checklist. Every finding is
|
|
6
|
+
calibrated and gated (see "Confidence + verification gate" below) before it reaches the human.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## §0. Scope Challenge (blocking gate — runs before any axis)
|
|
11
|
+
|
|
12
|
+
Before reviewing *how* the plan builds, challenge *whether it should build this much*. This is
|
|
13
|
+
implementation-scope discipline (the spec's ambition is settled — that was `/rite-temper`).
|
|
14
|
+
|
|
15
|
+
1. **What already exists?** For each sub-problem in the plan, find the existing code/flow that
|
|
16
|
+
already solves it (use a code-intelligence index if available — see `../../../rules/tooling.md`).
|
|
17
|
+
Can the plan **capture outputs from an existing
|
|
18
|
+
flow** instead of building a parallel one? Reuse → extend → build new, in that order
|
|
19
|
+
(`coding-style.md`). List every reuse opportunity the plan misses.
|
|
20
|
+
2. **Minimum diff.** What's the smallest set of changes that meets the spec's *acceptance
|
|
21
|
+
criteria*? Flag any planned work that can be deferred without blocking acceptance. Be ruthless
|
|
22
|
+
about implementation scope creep — but never cut an acceptance criterion (that's a Drift Guard
|
|
23
|
+
matter, not a trim).
|
|
24
|
+
3. **Complexity smell.** If `plan.md` touches **>8 files** or adds **>2 new services / modules /
|
|
25
|
+
classes**, treat it as a smell. Check the plan's complexity gate justifies it. If it doesn't
|
|
26
|
+
→ **STOP**: name what's overbuilt, propose a smaller version that meets acceptance, and ask
|
|
27
|
+
via `AskUserQuestion` whether to reduce or proceed. Do not start the axes until answered.
|
|
28
|
+
4. **Built-in check.** For each new pattern / infra component / concurrency approach the plan
|
|
29
|
+
introduces, verify a framework/runtime built-in doesn't already do it, and that the choice is
|
|
30
|
+
current best practice with no known footgun — dispatch `devrites-source-driven` to confirm at
|
|
31
|
+
the source and record the citation. A custom roll where a built-in exists is a scope-reduction
|
|
32
|
+
finding.
|
|
33
|
+
5. **Completeness check.** Is the plan doing the complete version or a shortcut? With AI-assisted
|
|
34
|
+
coding the cost of completeness (full edge-case handling, complete error paths, real test
|
|
35
|
+
coverage) is a fraction of what it was — a shortcut that saves human-hours but only saves
|
|
36
|
+
minutes here is a false economy. Prefer the complete option; flag shortcuts that exist only to
|
|
37
|
+
save effort that AI has already made cheap.
|
|
38
|
+
6. **Distribution check.** If the plan introduces a new artifact (CLI binary, package, container,
|
|
39
|
+
deployable), does it include how it gets built / published / installed? If distribution is
|
|
40
|
+
deferred, say so explicitly in "NOT in scope" — don't let it silently drop.
|
|
41
|
+
|
|
42
|
+
> **STOP discipline.** If the complexity smell trips, the `AskUserQuestion` is a tool call, not
|
|
43
|
+
> prose. Naming the 80%-solution in chat and continuing is the failure this gate exists to prevent.
|
|
44
|
+
|
|
45
|
+
If the smell does not trip, present the §0 findings and proceed to Axis 1.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## The four axes (one at a time, ≤8 findings each)
|
|
50
|
+
|
|
51
|
+
For each axis: evaluate, then **walk each finding WITH the human** via `AskUserQuestion` (one
|
|
52
|
+
issue per call — see "How to ask" below). HITL pauses on each material finding; AFK auto-applies
|
|
53
|
+
within the gate ceiling (`depth.md`). If an axis genuinely has no issue, say "No issues,
|
|
54
|
+
moving on" and continue — don't manufacture findings.
|
|
55
|
+
|
|
56
|
+
### 1. Architecture
|
|
57
|
+
- Component boundaries, coupling, data-flow patterns, single points of failure.
|
|
58
|
+
- Scaling characteristics; where the plan's approach breaks under real load.
|
|
59
|
+
- Security architecture at the seams (auth, data access, API boundaries) — does the plan name
|
|
60
|
+
the trust boundary for each untrusted input?
|
|
61
|
+
- For each new codepath / integration point: **one realistic production failure scenario** and
|
|
62
|
+
whether the plan accounts for it (feeds the failure-mode table).
|
|
63
|
+
- Does any key flow deserve an ASCII diagram in the plan or an inline comment in the code the
|
|
64
|
+
build will write? Name the files that should carry one.
|
|
65
|
+
|
|
66
|
+
### 2. Plan code-quality
|
|
67
|
+
- Module structure the plan implies; DRY across the slices (flag planned repetition aggressively).
|
|
68
|
+
- Error-handling + edge cases the plan names — and the ones it doesn't (call those out explicitly).
|
|
69
|
+
- Over-engineering (premature abstraction, an extension point with no second caller) vs
|
|
70
|
+
under-engineering (fragile / hacky) relative to `patterns.md` + `coding-style.md`.
|
|
71
|
+
- Tech-debt hotspots the plan walks into; existing inline diagrams in touched files that the
|
|
72
|
+
change will make stale.
|
|
73
|
+
|
|
74
|
+
### 3. Test-coverage design
|
|
75
|
+
The differentiator: design the tests *before* the code, so the build writes them alongside.
|
|
76
|
+
- **Framework detection** — find the project's existing test runner + conventions; match them
|
|
77
|
+
(never introduce a new runner to prove one change — `testing.md`).
|
|
78
|
+
- **Map acceptance → tests.** Every spec acceptance criterion must map to ≥1 planned test.
|
|
79
|
+
- **Tool per path** — unit (pure logic, single function, edge cases), integration/E2E (a user
|
|
80
|
+
flow spanning 3+ components, an auth/payment/data-loss path, a mock-hides-failure boundary),
|
|
81
|
+
eval (an LLM/prompt change that needs a quality bar).
|
|
82
|
+
- **Interaction inventory (UI slices) — enumerate every interactive element + flow.** List each
|
|
83
|
+
input field, checkbox, radio, select, toggle, button, and actionable link, plus each user
|
|
84
|
+
flow; assign each ≥1 asserting test **at the right level** — elements/fields → unit/component,
|
|
85
|
+
critical journeys → one E2E (never one-per-field). Every element/flow with no asserting test
|
|
86
|
+
is a GAP; no element ships unverified. Write the inventory to `test-plan.md` (table in
|
|
87
|
+
`artifacts.md`). This is `testing.md` "Completeness" made concrete for the plan.
|
|
88
|
+
- **Regression rule (mandatory, no question):** when the plan modifies existing behavior and the
|
|
89
|
+
current suite doesn't cover the changed path, a regression test is added to the plan as a
|
|
90
|
+
**Critical** requirement — no `AskUserQuestion`, no skipping. Regressions are the highest-priority
|
|
91
|
+
test because they prove something broke. When unsure whether a change is a regression, write the test.
|
|
92
|
+
- Produce the **coverage diagram** (shape below) and add a specific test requirement per GAP.
|
|
93
|
+
|
|
94
|
+
#### Coverage diagram (write to `test-plan.md`)
|
|
95
|
+
Both code paths and user flows in one view; mark E2E-worthy `[→E2E]` and eval-worthy `[→EVAL]`:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
CODE PATHS USER FLOWS
|
|
99
|
+
[+] services/billing [+] Checkout
|
|
100
|
+
├── processPayment() ├── [★★★ planned] complete purchase — checkout.e2e
|
|
101
|
+
│ ├── [★★★ planned] happy + declined + timeout ├── [GAP] [→E2E] double-click submit
|
|
102
|
+
│ └── [GAP] invalid currency └── [GAP] navigate away mid-payment
|
|
103
|
+
└── refundPayment() [+] Error states
|
|
104
|
+
└── [★ planned] full refund only └── [GAP] network-timeout UX
|
|
105
|
+
|
|
106
|
+
COVERAGE: 4/9 planned (44%) | GAPS: 5 (2 E2E) | REGRESSIONS: 1 (Critical)
|
|
107
|
+
```
|
|
108
|
+
Legend: ★★★ behavior+edge+error · ★★ happy path · ★ smoke · [→E2E] integration · [→EVAL] LLM eval.
|
|
109
|
+
**Fast path:** every acceptance criterion already maps to a planned test → "Test coverage: all
|
|
110
|
+
acceptance criteria covered ✓" and continue.
|
|
111
|
+
|
|
112
|
+
### 4. Performance
|
|
113
|
+
- N+1 / unbounded queries and DB access patterns; memory concerns; caching opportunities;
|
|
114
|
+
high-complexity hot paths.
|
|
115
|
+
- Per `performance.md`: name a number to measure or a budget — don't recommend speculative
|
|
116
|
+
micro-tuning. A perf finding is "measure X against budget Y", not "this feels slow".
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Confidence + verification gate (applies to every finding, all axes)
|
|
121
|
+
Tag each finding `[severity] (confidence: N/10) <plan/task/spec ref> — finding`:
|
|
122
|
+
- **9-10** verified against a quoted line · **7-8** strong pattern match → report normally.
|
|
123
|
+
- **5-6** moderate → report with "verify this is real".
|
|
124
|
+
- **≤4** speculative → **suppress from the walk-through**, appendix only.
|
|
125
|
+
|
|
126
|
+
**The gate:** before raising a finding, quote the line(s) that motivate it. Can't quote it →
|
|
127
|
+
force confidence ≤4 and suppress. This kills the "the plan doesn't handle X" finding when the
|
|
128
|
+
plan *does* and you skimmed. Don't fabricate 7+ to dodge it. (Same discipline the reviewer agent
|
|
129
|
+
runs — `devrites-plan-reviewer`.)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## How to ask (the interactive walk)
|
|
134
|
+
Use `AskUserQuestion` per the pack's standard. Plan-review specifics:
|
|
135
|
+
- **One finding = one call.** Never batch findings into one question.
|
|
136
|
+
- Concrete: name the plan/task section + the quoted line.
|
|
137
|
+
- 2-3 options, including "do nothing / proceed as-is" where reasonable.
|
|
138
|
+
- Per option, one line: **effort** (human ~X / with the build agent ~Y), **risk**, **maintenance**.
|
|
139
|
+
If the complete option is only marginally more effort than the shortcut (AI makes it cheap),
|
|
140
|
+
recommend complete.
|
|
141
|
+
- **Map to a rule.** One sentence tying the recommendation to a DevRites rule (reuse-first,
|
|
142
|
+
fail-fast, test-behavior, measure-first, minimum diff).
|
|
143
|
+
- **Coverage vs kind:** if the options differ in *coverage* (more tests vs fewer, complete vs
|
|
144
|
+
happy-path), add `Completeness: N/10` per option. If they differ in *kind* (two different
|
|
145
|
+
architectures), skip the score and note "options differ in kind, not coverage". Never fabricate
|
|
146
|
+
a score on a kind question.
|
|
147
|
+
- Every material finding ends as a **recorded decision** — a resolved `questions.md` qid (HITL) or
|
|
148
|
+
a `decisions.md` ADR (AFK) — so the walk leaves an auditable trail, not just chat.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Required outputs (after the axes)
|
|
153
|
+
1. **"NOT in scope"** — work considered and explicitly deferred, one-line rationale each. Folds
|
|
154
|
+
into `plan.md` §Scope boundaries + `spec.md` Non-goals (via the Guard) so it can't silently re-enter.
|
|
155
|
+
2. **"What already exists"** — existing code/flows that solve sub-problems, and whether the plan
|
|
156
|
+
reuses or rebuilds them. Every missed reuse becomes a §0 finding.
|
|
157
|
+
3. **Failure-mode table** — for each new codepath: a realistic failure, and whether (a) a test
|
|
158
|
+
covers it, (b) error handling exists, (c) the user sees a clear error or a silent failure. A
|
|
159
|
+
failure with **no test AND no handling AND silent** is a **Critical gap**. (Shape in
|
|
160
|
+
[`artifacts.md`](artifacts.md).)
|
|
161
|
+
4. **Worktree parallelization strategy** — analyze the slices for parallel execution. **Skip** if
|
|
162
|
+
all slices touch the same module or there are <2 independent workstreams ("Sequential, no
|
|
163
|
+
parallelization opportunity"). Otherwise: a dependency table (module-level, not file-level),
|
|
164
|
+
parallel lanes (shared module → same lane/sequential; independent → separate lanes), execution
|
|
165
|
+
order, and conflict flags where two lanes touch the same module dir. This feeds `/rite-build`'s
|
|
166
|
+
isolation strategy and the autocomplete loop. (Shape in [`artifacts.md`](artifacts.md).)
|
|
167
|
+
5. **Completion summary** — the one-glance recap (shape in [`artifacts.md`](artifacts.md)).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rite-zoom-out
|
|
3
|
+
description: Zoom out one abstraction layer in unfamiliar code — return a structural map (modules, callers, callees, ADR/decisions touching the area) in the project's vocabulary. Use when the user says "zoom out", "map this", "bigger picture", "I don't know this area", "what calls this". Not for implementing changes (read-only) or one-symbol lookups (use grep).
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /rite-zoom-out — step up one abstraction layer
|
|
8
|
+
|
|
9
|
+
When the agent (or the user) is staring at unfamiliar code without a working mental
|
|
10
|
+
model of how it fits the larger system. Stops the "open more files" reflex by returning
|
|
11
|
+
a single, structured map instead.
|
|
12
|
+
|
|
13
|
+
Read `.claude/rules/core.md` first — chiefly its vocabulary / existing-conventions
|
|
14
|
+
disciplines, which keep the map in the project's own language. The other rule files load
|
|
15
|
+
on demand.
|
|
16
|
+
|
|
17
|
+
## What this skill returns
|
|
18
|
+
|
|
19
|
+
A **map, not an essay**. One pass should answer:
|
|
20
|
+
|
|
21
|
+
- **The area** — what this code is for, in one sentence, using the project's own
|
|
22
|
+
vocabulary.
|
|
23
|
+
- **Modules in scope** — the related files / packages / slices, with a one-line
|
|
24
|
+
purpose each.
|
|
25
|
+
- **Callers (in)** — who calls into this area from outside. Keep to the highest-signal
|
|
26
|
+
3–6; collapse the rest.
|
|
27
|
+
- **Calls (out)** — what this area depends on downstream.
|
|
28
|
+
- **Decisions touching it** — ADRs (under `docs/adr/` if present) or notes in
|
|
29
|
+
`.devrites/work/<slug>/decisions.md` that pre-decide something here.
|
|
30
|
+
- **Smallest sensible change-scope** — where a fix would naturally land, so the next
|
|
31
|
+
step doesn't drift into a project-wide refactor.
|
|
32
|
+
|
|
33
|
+
## Prefer a code-intelligence index (if available)
|
|
34
|
+
|
|
35
|
+
If the project has them — `codebase-memory-mcp` (`get_architecture` / `search_graph`) first,
|
|
36
|
+
cross-checked with `codegraph` (`.codegraph/`) and `graphify` (`graphify-out/`) — use them. For
|
|
37
|
+
codegraph, `codegraph_context` + one `codegraph_explore` return the map in two calls — vastly
|
|
38
|
+
cheaper than a file-walk and more accurate for callers/callees. Fall back to standard methods
|
|
39
|
+
(LSP, then `Grep` + `Read`) when no index is available. See `.claude/rules/tooling.md`.
|
|
40
|
+
|
|
41
|
+
## Vocabulary discipline
|
|
42
|
+
|
|
43
|
+
Use the **project's** domain language — `CONTEXT.md`, glossaries, the active feature's
|
|
44
|
+
`spec.md` / `decisions.md`. Don't invent fresh names for things the project already
|
|
45
|
+
names. If you notice a fuzzy or overloaded term while mapping, flag it as a FYI at the
|
|
46
|
+
end; don't try to fix it here.
|
|
47
|
+
|
|
48
|
+
## When NOT to use
|
|
49
|
+
|
|
50
|
+
- You already have a clear mental model — zooming out is just tax.
|
|
51
|
+
- The question is a literal text lookup (a string, a comment, an error message) — use
|
|
52
|
+
`Grep`.
|
|
53
|
+
- You need to design or change something — that's `/rite-spec` (new feature) or
|
|
54
|
+
`/rite-define` (plan an approved spec).
|
|
55
|
+
- You want a project-wide architecture audit — that's `improve-codebase-architecture`,
|
|
56
|
+
out of DevRites' feature-scoped remit.
|
|
57
|
+
|
|
58
|
+
## Output shape
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Area: <one line, project's vocabulary>
|
|
62
|
+
Modules:
|
|
63
|
+
- path/x.ts — <purpose>
|
|
64
|
+
- path/y.ts — <purpose>
|
|
65
|
+
Callers (in):
|
|
66
|
+
- <module> — <how it calls in>
|
|
67
|
+
Calls (out):
|
|
68
|
+
- <module> — <what it calls for>
|
|
69
|
+
Decisions touching it:
|
|
70
|
+
- ADR-NNNN / decisions.md entry — <one-line claim>
|
|
71
|
+
Smallest sensible change-scope: <where a fix would land>
|
|
72
|
+
FYI (optional): <fuzzy term / suspected drift / open question>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Print the path of any decisions/ADR files referenced so the user can open them.
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devrites",
|
|
3
|
+
"version": "1.19.0",
|
|
4
|
+
"description": "DevRites — disciplined senior-engineer workflow skills pack for Claude Code",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"homepage": "https://github.com/ViktorsBaikers/DevRites#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ViktorsBaikers/DevRites.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/ViktorsBaikers/DevRites/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"claude-code",
|
|
16
|
+
"skills",
|
|
17
|
+
"agent-skills",
|
|
18
|
+
"workflow",
|
|
19
|
+
"senior-engineer",
|
|
20
|
+
"spec-driven",
|
|
21
|
+
"tdd",
|
|
22
|
+
"code-review",
|
|
23
|
+
"anti-slop",
|
|
24
|
+
"devrites"
|
|
25
|
+
],
|
|
26
|
+
"bin": {
|
|
27
|
+
"devrites": "bin/devrites.mjs"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/",
|
|
31
|
+
"pack/",
|
|
32
|
+
"scripts/",
|
|
33
|
+
"install.sh",
|
|
34
|
+
"uninstall.sh",
|
|
35
|
+
"update.sh",
|
|
36
|
+
".claude-plugin/",
|
|
37
|
+
"mcp/",
|
|
38
|
+
"docs/",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"SECURITY.md",
|
|
42
|
+
"NOTICE.md",
|
|
43
|
+
"CHANGELOG.md"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"prepare": "husky || true",
|
|
50
|
+
"prepack": "rm -rf scripts/__pycache__ scripts/.cache docs/internal",
|
|
51
|
+
"commitlint": "commitlint --edit",
|
|
52
|
+
"validate": "bash scripts/validate.sh",
|
|
53
|
+
"test": "for t in tests/*.sh; do echo \"== $t ==\"; bash \"$t\" || exit 1; done",
|
|
54
|
+
"release": "semantic-release",
|
|
55
|
+
"release:dry": "semantic-release --dry-run --no-ci"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@commitlint/cli": "^21.0.2",
|
|
59
|
+
"@commitlint/config-conventional": "^21.0.2",
|
|
60
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
61
|
+
"@semantic-release/exec": "^7.1.0",
|
|
62
|
+
"@semantic-release/git": "^10.0.1",
|
|
63
|
+
"@semantic-release/npm": "^13.1.5",
|
|
64
|
+
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
65
|
+
"husky": "^9.1.7",
|
|
66
|
+
"semantic-release": "^25.0.5"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build the DevRites release tarball — the artifact attached to the GitHub Release
|
|
3
|
+
# by semantic-release. Extracting yields a `devrites-v<version>/` directory with
|
|
4
|
+
# everything an end-user needs (pack/, install.sh, uninstall.sh, scripts/, docs).
|
|
5
|
+
#
|
|
6
|
+
# Usage: build-release-tarball.sh <version>
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
VERSION="${1:-}"
|
|
10
|
+
if [[ -z "$VERSION" ]]; then
|
|
11
|
+
echo "usage: build-release-tarball.sh <version>" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
16
|
+
DIST="$ROOT/dist"
|
|
17
|
+
NAME="devrites-v${VERSION}"
|
|
18
|
+
STAGE="$DIST/$NAME"
|
|
19
|
+
|
|
20
|
+
cd "$ROOT"
|
|
21
|
+
|
|
22
|
+
echo "Building release tarball: ${NAME}.tar.gz"
|
|
23
|
+
|
|
24
|
+
rm -rf "$STAGE"
|
|
25
|
+
mkdir -p "$STAGE"
|
|
26
|
+
|
|
27
|
+
# Files and directories shipped to end-users.
|
|
28
|
+
PAYLOAD=(
|
|
29
|
+
pack
|
|
30
|
+
.claude-plugin
|
|
31
|
+
scripts
|
|
32
|
+
mcp
|
|
33
|
+
docs
|
|
34
|
+
install.sh
|
|
35
|
+
uninstall.sh
|
|
36
|
+
update.sh
|
|
37
|
+
README.md
|
|
38
|
+
CHANGELOG.md
|
|
39
|
+
LICENSE
|
|
40
|
+
SECURITY.md
|
|
41
|
+
NOTICE.md
|
|
42
|
+
CODE_OF_CONDUCT.md
|
|
43
|
+
CODEOWNERS
|
|
44
|
+
package.json
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
for item in "${PAYLOAD[@]}"; do
|
|
48
|
+
if [[ -e "$item" ]]; then
|
|
49
|
+
cp -R "$item" "$STAGE/"
|
|
50
|
+
fi
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
# Drop dev-only artifacts that may have been copied transitively.
|
|
54
|
+
rm -rf "$STAGE/docs/internal" "$STAGE/scripts/.cache" 2>/dev/null || true
|
|
55
|
+
|
|
56
|
+
tar -C "$DIST" -czf "$DIST/${NAME}.tar.gz" "$NAME"
|
|
57
|
+
rm -rf "$STAGE"
|
|
58
|
+
|
|
59
|
+
# Emit a sibling checksum so install.sh can verify the artifact when present.
|
|
60
|
+
# Write just "<sha256> <filename>" (no path) so it verifies from any cwd.
|
|
61
|
+
(
|
|
62
|
+
cd "$DIST"
|
|
63
|
+
if command -v shasum >/dev/null 2>&1; then
|
|
64
|
+
shasum -a 256 "${NAME}.tar.gz" > "${NAME}.tar.gz.sha256"
|
|
65
|
+
elif command -v sha256sum >/dev/null 2>&1; then
|
|
66
|
+
sha256sum "${NAME}.tar.gz" > "${NAME}.tar.gz.sha256"
|
|
67
|
+
else
|
|
68
|
+
echo "warning: no sha256 tool found; skipping ${NAME}.tar.gz.sha256" >&2
|
|
69
|
+
fi
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
echo " → $DIST/${NAME}.tar.gz"
|
|
73
|
+
ls -lh "$DIST/${NAME}.tar.gz"
|
|
74
|
+
[[ -f "$DIST/${NAME}.tar.gz.sha256" ]] && { echo " → $DIST/${NAME}.tar.gz.sha256"; cat "$DIST/${NAME}.tar.gz.sha256"; } || true
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Cross-reference linter for the DevRites pack.
|
|
3
|
+
|
|
4
|
+
Catches the maintenance-drift class the skills audit surfaced: a SKILL.md or
|
|
5
|
+
reference file pointing at another file that has moved, been renamed, or never
|
|
6
|
+
existed. Three checks, tuned for near-zero false positives:
|
|
7
|
+
|
|
8
|
+
1. Markdown links to local .md targets — `](path.md)` resolved relative to the
|
|
9
|
+
containing file; the target must exist.
|
|
10
|
+
2. Bare backtick .md filenames — `` `name.md` `` must exist SOMEWHERE in
|
|
11
|
+
the pack (by basename). Catches references to a file that exists nowhere.
|
|
12
|
+
3. "canonical version: `path`" claims — the named path (relative to the skills
|
|
13
|
+
root) must exist. Catches a file disclaiming itself secondary to a missing one.
|
|
14
|
+
|
|
15
|
+
Scans pack/.claude/. Exit 1 on any dead reference. Read-only.
|
|
16
|
+
"""
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
ROOT = os.path.join("pack", ".claude")
|
|
22
|
+
SKILLS_ROOT = os.path.join(ROOT, "skills")
|
|
23
|
+
|
|
24
|
+
# Runtime artifacts live under .devrites/ (per-feature work/<slug>/ files, plus the
|
|
25
|
+
# project-level conventions ledger), not in the pack. References to them by filename are
|
|
26
|
+
# legitimate, not dead refs.
|
|
27
|
+
WORKSPACE_ARTIFACTS = {
|
|
28
|
+
"spec.md", "plan.md", "tasks.md", "state.md", "decisions.md", "assumptions.md",
|
|
29
|
+
"questions.md", "drift.md", "evidence.md", "browser-evidence.md", "touched-files.md",
|
|
30
|
+
"review.md", "seal.md", "ship.md", "brief.md", "design-brief.md", "strategy.md",
|
|
31
|
+
"polish-report.md", "handoff.md", "eng-review.md", "test-plan.md", "references.md",
|
|
32
|
+
"conventions.md", "coverage.md", "analysis.md", "learnings.md",
|
|
33
|
+
# spec-quality checklists (.devrites/work/<slug>/checklists/<domain>.md)
|
|
34
|
+
"functional.md", "data-model.md", "interaction.md", "non-functional.md", "edge-cases.md",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Files the skills legitimately tell Claude to read in the USER's project / the repo,
|
|
38
|
+
# which are not part of the shipped pack.
|
|
39
|
+
PROJECT_DOCS = {
|
|
40
|
+
"CLAUDE.md", "AGENTS.md", "DESIGN.md", "PRODUCT.md", "CONTEXT.md", "NOTES.md",
|
|
41
|
+
"README.md", "CHANGELOG.md", "CONTRIBUTING.md", "cli-mcp.md",
|
|
42
|
+
"ADR-NNN.md", # generated per-decision ADR in the user repo (docs/adr/), promoted at /rite-ship
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def resolve(here, link):
|
|
47
|
+
"""Resolve a link. `.claude/...`-rooted paths are install-root-relative (= pack/
|
|
48
|
+
in this repo); everything else is relative to the containing file."""
|
|
49
|
+
if link.startswith(".claude/"):
|
|
50
|
+
return os.path.normpath(os.path.join("pack", link))
|
|
51
|
+
return os.path.normpath(os.path.join(here, link))
|
|
52
|
+
|
|
53
|
+
md_files = []
|
|
54
|
+
all_basenames = set()
|
|
55
|
+
for base, _dirs, files in os.walk(ROOT):
|
|
56
|
+
for f in files:
|
|
57
|
+
if f.endswith(".md"):
|
|
58
|
+
p = os.path.join(base, f)
|
|
59
|
+
md_files.append(p)
|
|
60
|
+
all_basenames.add(f)
|
|
61
|
+
|
|
62
|
+
LINK_RE = re.compile(r"\]\(([^)]+)\)")
|
|
63
|
+
BACKTICK_MD_RE = re.compile(r"`([A-Za-z0-9._/\-]+\.md)`")
|
|
64
|
+
SEE_RE = re.compile(r"\(see\s+`?([A-Za-z0-9._/\-]+\.md)`?[^)]*\)")
|
|
65
|
+
CANONICAL_RE = re.compile(r"[Cc]anonical version:\s*`?\s*`?([A-Za-z0-9._/\-]+\.md)`")
|
|
66
|
+
|
|
67
|
+
errors = []
|
|
68
|
+
|
|
69
|
+
for path in md_files:
|
|
70
|
+
with open(path, encoding="utf-8") as fh:
|
|
71
|
+
text = fh.read()
|
|
72
|
+
here = os.path.dirname(path)
|
|
73
|
+
|
|
74
|
+
# 1. markdown links to .md
|
|
75
|
+
for link in LINK_RE.findall(text):
|
|
76
|
+
link = link.strip()
|
|
77
|
+
if link.startswith(("http://", "https://", "mailto:", "#")):
|
|
78
|
+
continue
|
|
79
|
+
target = link.split("#", 1)[0]
|
|
80
|
+
if not target.endswith(".md"):
|
|
81
|
+
continue
|
|
82
|
+
resolved = resolve(here, target)
|
|
83
|
+
if not os.path.isfile(resolved):
|
|
84
|
+
errors.append(f"{path}: markdown link -> {link} (resolved {resolved}) does not exist")
|
|
85
|
+
|
|
86
|
+
# 2. bare backtick filenames must exist somewhere in the pack (by basename),
|
|
87
|
+
# excluding runtime workspace artifacts and user-project docs.
|
|
88
|
+
for tok in BACKTICK_MD_RE.findall(text):
|
|
89
|
+
base = os.path.basename(tok)
|
|
90
|
+
if base in WORKSPACE_ARTIFACTS or base in PROJECT_DOCS or base in all_basenames:
|
|
91
|
+
continue
|
|
92
|
+
if "/" in tok: # a path inside the pack must actually resolve
|
|
93
|
+
if not os.path.isfile(resolve(here, tok)):
|
|
94
|
+
errors.append(f"{path}: backtick `{tok}` does not resolve")
|
|
95
|
+
continue
|
|
96
|
+
errors.append(f"{path}: backtick `{tok}` — no `{base}` exists anywhere in the pack")
|
|
97
|
+
|
|
98
|
+
# 4. "(see X.md)" prose pointers: slash form resolves (install-aware);
|
|
99
|
+
# bare form must exist in the pack (or be a workspace artifact / project doc).
|
|
100
|
+
for tok in SEE_RE.findall(text):
|
|
101
|
+
base = os.path.basename(tok)
|
|
102
|
+
if "/" in tok:
|
|
103
|
+
resolved = resolve(here, tok)
|
|
104
|
+
if not os.path.isfile(resolved):
|
|
105
|
+
errors.append(f"{path}: (see {tok}) (resolved {resolved}) does not exist")
|
|
106
|
+
elif base not in WORKSPACE_ARTIFACTS and base not in PROJECT_DOCS and base not in all_basenames:
|
|
107
|
+
errors.append(f"{path}: (see {tok}) — no `{base}` exists anywhere in the pack")
|
|
108
|
+
|
|
109
|
+
# 3. "canonical version: `path`" must resolve against the skills root
|
|
110
|
+
for claim in CANONICAL_RE.findall(text):
|
|
111
|
+
resolved = os.path.normpath(os.path.join(SKILLS_ROOT, claim))
|
|
112
|
+
if not os.path.isfile(resolved):
|
|
113
|
+
errors.append(f"{path}: 'canonical version' -> {claim} (resolved {resolved}) does not exist")
|
|
114
|
+
|
|
115
|
+
if errors:
|
|
116
|
+
print(f"check-cross-refs: {len(errors)} dead reference(s):\n")
|
|
117
|
+
for e in sorted(errors):
|
|
118
|
+
print(" " + e)
|
|
119
|
+
sys.exit(1)
|
|
120
|
+
|
|
121
|
+
print(f"check-cross-refs: OK — {len(md_files)} markdown files, no dead references.")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-no-global-writes.sh — static guard that the installer/uninstaller never
|
|
3
|
+
# writes to the user's global ~/.claude, and that the global guard is present.
|
|
4
|
+
# Exits non-zero on violation.
|
|
5
|
+
|
|
6
|
+
set -u
|
|
7
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
8
|
+
fail=0
|
|
9
|
+
|
|
10
|
+
SCRIPTS="$ROOT/install.sh $ROOT/uninstall.sh"
|
|
11
|
+
for f in "$ROOT"/scripts/*.sh; do SCRIPTS="$SCRIPTS $f"; done
|
|
12
|
+
|
|
13
|
+
# 1) the no-global guard marker must exist in install.sh
|
|
14
|
+
if ! grep -q 'GUARD:no-global' "$ROOT/install.sh"; then
|
|
15
|
+
echo "FAIL: install.sh is missing the GUARD:no-global guard"
|
|
16
|
+
fail=1
|
|
17
|
+
else
|
|
18
|
+
echo "ok: install.sh contains the no-global guard"
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# 2) no write operation may target ~/.claude or \$HOME/.claude.
|
|
22
|
+
# Write verbs are actual file-writing commands / redirections. ('install' is
|
|
23
|
+
# intentionally excluded: the installer uses cp/mkdir, and "install" appears in
|
|
24
|
+
# prose like "install into a project", which is not a write.)
|
|
25
|
+
WRITE_RE='(\bmkdir\b|\bcp\b|\btee\b|\brsync\b|\bmv\b|\bln\b|>>?)'
|
|
26
|
+
GLOBAL_RE='(\$HOME/\.claude|~/\.claude)'
|
|
27
|
+
for f in $SCRIPTS; do
|
|
28
|
+
[ -f "$f" ] || continue
|
|
29
|
+
# lines that contain a global-claude path AND a write verb, excluding comments
|
|
30
|
+
hits="$(grep -nE "$GLOBAL_RE" "$f" | grep -vE '^\s*[0-9]+:\s*#' | grep -E "$WRITE_RE" || true)"
|
|
31
|
+
if [ -n "$hits" ]; then
|
|
32
|
+
echo "FAIL: possible global write in ${f#$ROOT/}:"
|
|
33
|
+
printf '%s\n' "$hits" | sed 's/^/ /'
|
|
34
|
+
fail=1
|
|
35
|
+
fi
|
|
36
|
+
done
|
|
37
|
+
[ "$fail" -eq 0 ] && echo "ok: no write operations target ~/.claude"
|
|
38
|
+
|
|
39
|
+
if [ "$fail" -eq 0 ]; then
|
|
40
|
+
echo "PASS: no global-write risks detected"
|
|
41
|
+
else
|
|
42
|
+
echo "FAILED: global-write check"
|
|
43
|
+
fi
|
|
44
|
+
exit "$fail"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/check-rule-uniqueness.sh — assert each canonical principle heading
|
|
3
|
+
# appears in exactly one canonical file under pack/.claude/.
|
|
4
|
+
#
|
|
5
|
+
# Drift catcher: if someone re-duplicates a principle's full treatment, this
|
|
6
|
+
# script fails and names the offenders. Cross-link summaries are fine — they
|
|
7
|
+
# don't use the canonical heading.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# scripts/check-rule-uniqueness.sh
|
|
11
|
+
# Exits non-zero if any principle is duplicated or missing from its canonical
|
|
12
|
+
# home. Add new entries to PRINCIPLES below as principles get a canonical
|
|
13
|
+
# home.
|
|
14
|
+
|
|
15
|
+
set -u
|
|
16
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
17
|
+
PACK="$ROOT/pack/.claude"
|
|
18
|
+
|
|
19
|
+
# Format: <grep-pattern>|<canonical-relative-path>
|
|
20
|
+
PRINCIPLES=(
|
|
21
|
+
'^## Reuse before you write|pack/.claude/rules/coding-style.md'
|
|
22
|
+
'^## Trust boundary (three tiers)|pack/.claude/rules/security.md'
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
fail=0
|
|
26
|
+
|
|
27
|
+
for entry in "${PRINCIPLES[@]}"; do
|
|
28
|
+
pattern="${entry%%|*}"
|
|
29
|
+
canonical="${entry##*|}"
|
|
30
|
+
# Use literal-string grep (-F) to avoid regex meta-char surprises in headings.
|
|
31
|
+
# Match anchored to line start by adding the '## ' prefix ourselves.
|
|
32
|
+
needle="${pattern#^}"
|
|
33
|
+
matches="$(grep -rln -F -- "$needle" "$PACK"/rules "$PACK"/skills "$PACK"/agents 2>/dev/null | sort -u)"
|
|
34
|
+
count="$(printf '%s\n' "$matches" | grep -c .)"
|
|
35
|
+
if [ "$count" -eq 1 ] && [ "$matches" = "$ROOT/$canonical" ]; then
|
|
36
|
+
printf 'ok: unique heading "%s" (canonical: %s)\n' "$needle" "$canonical"
|
|
37
|
+
else
|
|
38
|
+
printf 'FAIL: heading "%s" should appear only in %s; found in:\n' "$needle" "$canonical" >&2
|
|
39
|
+
printf '%s\n' "$matches" | sed 's|^| |' >&2
|
|
40
|
+
fail=1
|
|
41
|
+
fi
|
|
42
|
+
done
|
|
43
|
+
|
|
44
|
+
# Anti-rationalization table: core.md keeps a minimal 5-row subset that MUST be
|
|
45
|
+
# byte-identical to the matching rows in anti-patterns.md (the single source of
|
|
46
|
+
# the full table). The unique-heading check above can't see this — the rows live
|
|
47
|
+
# under the same heading in both files — so assert the 5 shared excuse strings
|
|
48
|
+
# (the excuse-column text, stable across both files) appear verbatim in both.
|
|
49
|
+
# These cover the five rows core.md duplicates:
|
|
50
|
+
# tests-later / small-refactor / special-case / user-will-tell / lint-and-build.
|
|
51
|
+
CORE="$PACK/rules/core.md"
|
|
52
|
+
ANTI="$PACK/rules/anti-patterns.md"
|
|
53
|
+
SHARED_EXCUSES=(
|
|
54
|
+
'"I'\''ll add the tests later."'
|
|
55
|
+
'"It'\''s only a small refactor while I'\''m in here."'
|
|
56
|
+
'"This is a special case, the pattern doesn'\''t apply."'
|
|
57
|
+
'"The user will tell me if something is wrong."'
|
|
58
|
+
'"Lint and build pass — that proves quality."'
|
|
59
|
+
)
|
|
60
|
+
for excuse in "${SHARED_EXCUSES[@]}"; do
|
|
61
|
+
in_core=0; in_anti=0
|
|
62
|
+
grep -qF -- "$excuse" "$CORE" 2>/dev/null && in_core=1
|
|
63
|
+
grep -qF -- "$excuse" "$ANTI" 2>/dev/null && in_anti=1
|
|
64
|
+
if [ "$in_core" -eq 1 ] && [ "$in_anti" -eq 1 ]; then
|
|
65
|
+
printf 'ok: shared excuse present in core.md + anti-patterns.md: %s\n' "$excuse"
|
|
66
|
+
else
|
|
67
|
+
printf 'FAIL: shared excuse must appear verbatim in BOTH core.md and anti-patterns.md: %s (core=%d anti=%d)\n' \
|
|
68
|
+
"$excuse" "$in_core" "$in_anti" >&2
|
|
69
|
+
fail=1
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
exit "$fail"
|