devrites 1.19.0 → 2.1.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/CHANGELOG.md CHANGED
@@ -2,12 +2,30 @@
2
2
 
3
3
  All notable changes to DevRites are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and DevRites adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases are generated automatically by [semantic-release](https://semantic-release.gitbook.io/) from Conventional Commits on `main`.
4
4
 
5
- ## [1.19.0](https://github.com/ViktorsBaikers/DevRites/compare/v1.18.0...v1.19.0) (2026-06-22)
5
+ ## [2.1.0](https://github.com/ViktorsBaikers/DevRites/compare/v2.0.0...v2.1.0) (2026-06-23)
6
6
 
7
- ### Features
7
+ ### Added
8
+
9
+ * **agents:** perf reviewer gets Source/Measured CWV modes ([be82b20](https://github.com/ViktorsBaikers/DevRites/commit/be82b20b37252a9f55d77e0f71659ec58a213ca6))
10
+
11
+ ## [2.0.0](https://github.com/ViktorsBaikers/DevRites/compare/v1.18.0...v2.0.0) (2026-06-23)
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * **installer:** drop the Claude Code plugin install path
16
+
17
+ ### Added
8
18
 
9
19
  * **installer:** add npx devrites full-pack installer + npm publishing ([316a0d3](https://github.com/ViktorsBaikers/DevRites/commit/316a0d372dad1afe2fade08f0045370fd5b3d801))
10
20
 
21
+ ### Changed
22
+
23
+ * **release:** group changelog by Added/Changed/Removed ([ea5772a](https://github.com/ViktorsBaikers/DevRites/commit/ea5772abca3d44ee1da496f3d904bcbe3b9ccc21))
24
+
25
+ ### Removed
26
+
27
+ * **installer:** drop the Claude Code plugin install path ([beb825f](https://github.com/ViktorsBaikers/DevRites/commit/beb825fcb0738d4b03b32dce056871c80616ab49))
28
+
11
29
  ## [1.18.0](https://github.com/ViktorsBaikers/DevRites/compare/v1.17.0...v1.18.0) (2026-06-22)
12
30
 
13
31
  ### Features
package/README.md CHANGED
@@ -94,13 +94,13 @@ Full diagram set (lifecycle, polish orchestrator, review fan-out, debug loop,
94
94
  rules carrier, workspace state, namespace map) →
95
95
  [`docs/flow.md`](docs/flow.md).
96
96
 
97
- **Status:** [`v1.19.0`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v1.19.0) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
97
+ **Status:** [`v2.1.0`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v2.1.0) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
98
98
 
99
99
  ## Contents
100
100
 
101
101
  - [Why distributed skills](#why-distributed-skills-not-one-engine)
102
102
  - [Modes — HITL & AFK](#modes--hitl--afk)
103
- - [Install](#install) — [npx / bash (A, recommended)](#option-a-npx--bash-installer-recommended-full-install) · [plugin (B, partial)](#option-b-claude-code-plugin-partial--skills--agents-only)
103
+ - [Install](#install) — [npx / bash](#installing) · [upgrade](#upgrading-an-existing-install)
104
104
  - [Recommended setup](#recommended-setup-optional-but-devrites-is-much-sharper-with-it) — codegraph · graphify · browser-harness
105
105
  - [Skills](#skills) — 31 total · full catalogue in [`docs/skills.md`](docs/skills.md)
106
106
  - [Typical workflow](#typical-workflow) · [Worked examples](docs/usage.md)
@@ -137,19 +137,10 @@ Full rationale: [`docs/architecture.md`](docs/architecture.md).
137
137
  ## Install
138
138
 
139
139
  DevRites installs **into a project** (project-local only — it never writes to
140
- `~/.claude`). Two install paths are supported:
140
+ `~/.claude`). Install with `npx` (recommended) or the `curl | bash` one-liner —
141
+ both run the same installer and ship skills, agents, **rules**, and aliases.
141
142
 
142
- | Path | Ships | When to use |
143
- |---|---|---|
144
- | **A. `npx` or bash installer** *(recommended)* | skills, agents, **rules**, aliases | full DevRites — `npx devrites@latest`, or `curl \| bash` on any Claude Code version |
145
- | B. Claude Code plugin | skills, agents *(no rules)* | Claude Code 2.1+ if you want plugin-managed updates and don't need the engineering rules |
146
-
147
- > **Heads-up:** the Claude Code plugin manifest only ships `skills/` and
148
- > `agents/` — there is no plugin field for the DevRites engineering rules.
149
- > If you install via the plugin you'll need a follow-up `--rules-only` bash
150
- > run to drop the rules into `.claude/rules/` (see Option B below).
151
-
152
- ### Option A: npx / bash installer (recommended, full install)
143
+ ### Installing
153
144
 
154
145
  **Fastest — `npx` (Node 18+):**
155
146
 
@@ -209,7 +200,7 @@ Common flags:
209
200
  | `--force` | Overwrite existing non-DevRites files |
210
201
  | `--no-rules` | Skip the engineering rules |
211
202
  | `--no-agents` | Skip the review subagents |
212
- | `--rules-only` | Install only the engineering rules — pair with Option B below |
203
+ | `--rules-only` | Install only the engineering rules |
213
204
  | `--short-aliases=all` | Add `/define`, `/build`, `/prove`, `/seal` short aliases (off by default) |
214
205
 
215
206
  Every installed file is recorded in `.claude/devrites.manifest` (with the installed
@@ -217,40 +208,6 @@ version and the original install flags in the header). `./uninstall.sh` removes
217
208
  exactly those files (and prunes empty dirs) — your feature data in
218
209
  `.devrites/work/` and `.devrites/ACTIVE` is preserved.
219
210
 
220
- ### Option B: Claude Code plugin (partial — skills + agents only)
221
-
222
- ```bash
223
- claude plugin marketplace add ViktorsBaikers/DevRites
224
- claude plugin install devrites@devrites-marketplace
225
- ```
226
-
227
- The plugin runtime places **skills + agents** in their canonical Claude Code
228
- locations and lets you manage updates with `claude plugin update devrites`.
229
- Uninstall with `claude plugin uninstall devrites`.
230
-
231
- **The plugin does not install the DevRites engineering rules.** The Claude
232
- Code plugin manifest has no `rules` field — `core.md`, `afk-hitl.md`,
233
- `coding-style.md`, `testing.md`, `security.md`, and the rest of
234
- `.claude/rules/` won't be present. Many skills (`/rite-build`, `/rite-prove`,
235
- `/rite-polish`, …) cite those rules at runtime and degrade noticeably without
236
- them.
237
-
238
- To add the rules after a plugin install, run the bash installer in
239
- `--rules-only` mode:
240
-
241
- ```bash
242
- # Drop only the engineering rules into the current project's .claude/rules/
243
- curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/install.sh | bash -s -- --rules-only
244
-
245
- # Or target a specific project
246
- curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/install.sh | bash -s -- --target /path/to/your/project --rules-only
247
- ```
248
-
249
- This writes nothing outside `.claude/rules/` and records the rule files in
250
- `.claude/devrites.manifest`. Running `./uninstall.sh` later removes only
251
- what's in the manifest (just the rules in this case) — the plugin's own
252
- skills + agents are managed by `claude plugin uninstall devrites`.
253
-
254
211
  ### Upgrading an existing install
255
212
 
256
213
  **One-liner over the network**:
@@ -519,7 +476,7 @@ real UI state, and **prove both layers** (contract tests + browser proof).
519
476
 
520
477
  ```
521
478
  devrites/
522
- .claude-plugin/ # plugin.json + marketplace.json (claude plugin install path)
479
+ bin/ # devrites.mjs npx CLI entry point (wraps install.sh)
523
480
  .github/ # workflows/ (ci, release, dependabot-auto-merge) + dependabot.yml
524
481
  .husky/ # commit-msg hook (Conventional Commits via commitlint)
525
482
  .releaserc.json # semantic-release config (CHANGELOG, version sync, tarball, GitHub Release)
@@ -566,7 +523,7 @@ written by the installer (cf. CVE-2026-33068).
566
523
 
567
524
  - **Changelog:** [`CHANGELOG.md`](CHANGELOG.md) — Keep-a-Changelog + SemVer, regenerated by semantic-release on every release.
568
525
  - **Code of conduct:** [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) (Contributor Covenant 2.1).
569
- - **Code owners:** [`CODEOWNERS`](CODEOWNERS) — review required on `pack/`, `scripts/`, `install.sh`, `uninstall.sh`, `.claude-plugin/`.
526
+ - **Code owners:** [`CODEOWNERS`](CODEOWNERS) — review required on `pack/`, `scripts/`, `install.sh`, `uninstall.sh`, `bin/`.
570
527
  - **Notices:** [`NOTICE.md`](NOTICE.md).
571
528
  - **CI:** GitHub Actions runs `scripts/validate.sh`, install/uninstall smoke, fixture install, commitlint, and the eval suite on every PR.
572
529
  - **Commits:** Conventional Commits enforced via husky + commitlint.
@@ -575,7 +532,7 @@ written by the installer (cf. CVE-2026-33068).
575
532
  ## License
576
533
 
577
534
  **Free to use, with approval gating redistribution.** Personal use and *listing this
578
- repository in plugin marketplaces* are permitted without approval. Any other use —
535
+ repository in package registries or plugin marketplaces* are permitted without approval. Any other use —
579
536
  distributing it, distributing modified versions, mirroring as a fork, or commercial /
580
537
  organizational use — requires **approval on request** (ask via
581
538
  [the repo](https://github.com/ViktorsBaikers/DevRites)). Source-available. See
package/SECURITY.md CHANGED
@@ -38,8 +38,8 @@ Once a `1.0` release ships, the latest two minor lines will be supported.
38
38
  ### Scope
39
39
 
40
40
  DevRites is a Claude Code **skills pack**: Markdown skill files, a few helper
41
- shell scripts, a bash installer, and (in plugin form) a `.claude-plugin/`
42
- manifest. It ships **no binary and no network service**. The only server is an
41
+ shell scripts, a bash installer, and a thin `npx` CLI wrapper (`bin/devrites.mjs`)
42
+ that shells out to that installer. It ships **no binary and no network service**. The only server is an
43
43
  **optional, opt-in MCP stdio server** (`mcp/devrites-mcp.mjs`) that speaks
44
44
  JSON-RPC over stdin/stdout (no port, no socket), is not installed or registered
45
45
  by default, and only shells out to the local `devrites` CLI — read/gate ops over
@@ -121,13 +121,13 @@ uninstall.
121
121
  The installer touches no global state. It does not invoke `sudo`, modify
122
122
  shell rc files, fetch remote code, or alter Claude Code settings.
123
123
 
124
- ### Plugin install path
124
+ ### npx install path
125
125
 
126
- When installed via `claude plugin install devrites@devrites-marketplace`,
127
- the plugin runtime owns file placement. DevRites does not ship a post-install
128
- hook that modifies user files. The plugin manifest ships only skills and agents
129
- the engineering rules are not delivered by the plugin and are never written into
130
- the user's `~/.claude/CLAUDE.md` (add them with a `--rules-only` bash install).
126
+ When installed via `npx devrites@latest`, the CLI (`bin/devrites.mjs`) is a thin
127
+ shim that runs the **bundled** `install.sh` against the pack shipped inside the npm
128
+ package no remote code is fetched at install time, and the install is pinned to
129
+ the requested package version. It has no runtime npm dependencies and makes no
130
+ global writes; the same project-local guarantees as the bash installer apply.
131
131
 
132
132
  ### Recommended Claude Code permissions for managed deployments
133
133
 
package/docs/release.md CHANGED
@@ -3,10 +3,11 @@
3
3
  Releases are **fully automated** via [semantic-release](https://semantic-release.gitbook.io/): every push to `main` is analyzed; if the merged commits carry a `feat:`, `fix:`, `perf:`, `refactor:`, `build:`, `docs(README):` (or a `BREAKING CHANGE:` footer) the `.github/workflows/release.yml` job determines the next SemVer version and:
4
4
 
5
5
  1. Runs `scripts/validate.sh` + install / uninstall smoke tests.
6
- 2. Syncs the new version into `package.json`, `.claude-plugin/plugin.json`, and `.claude-plugin/marketplace.json` (`scripts/sync-version.sh`).
7
- 3. Builds a `dist/devrites-v<version>.tar.gz` release artifact via `scripts/build-release-tarball.sh` — the extractable bundle end-users get if they don't install via the plugin marketplace.
6
+ 2. Syncs the new version into `package.json` and the README status line (`scripts/sync-version.sh`).
7
+ 3. Builds a `dist/devrites-v<version>.tar.gz` release artifact via `scripts/build-release-tarball.sh` — the extractable bundle end-users get from the `curl | bash` installer.
8
8
  4. Regenerates `CHANGELOG.md` from the commits.
9
- 5. Commits the version bump + changelog as `chore(release): <version> [skip ci]`, creates a git tag `v<version>`, and publishes a GitHub Release with the tarball attached.
9
+ 5. Publishes the `devrites` package to the npm registry (`@semantic-release/npm`, needs the `NPM_TOKEN` secret) this is what `npx devrites@latest` resolves.
10
+ 6. Commits the version bump + changelog as `chore(release): <version> [skip ci]`, creates a git tag `v<version>`, and publishes a GitHub Release with the tarball attached.
10
11
 
11
12
  Local dry-run: `npm run release:dry` (shows the version bump + draft notes without publishing). The release job is gated by passing CI — a broken `main` won't ship.
12
13
 
package/install.sh CHANGED
@@ -8,8 +8,6 @@
8
8
  # ./install.sh --no-agents skip the review subagents
9
9
  # ./install.sh --no-rules skip the DevRites engineering rules
10
10
  # ./install.sh --rules-only install only the engineering rules
11
- # (use after `claude plugin install devrites`
12
- # to add the rules the plugin can't ship)
13
11
  # ./install.sh --short-aliases=all install /define /build /prove /seal aliases
14
12
  #
15
13
  # Network install (no git clone needed):
@@ -308,10 +306,12 @@ fi
308
306
 
309
307
  # ---- detect installed version + flags (recorded in manifest header) -----
310
308
  DR_INSTALLED_VERSION="unknown"
311
- _plugin_json="$SELF_DIR/.claude-plugin/plugin.json"
312
- if [ -r "$_plugin_json" ]; then
309
+ _pkg_json="$SELF_DIR/package.json"
310
+ if [ -r "$_pkg_json" ]; then
313
311
  # Best-effort: extract the top-level "version" field without depending on jq.
314
- DR_INSTALLED_VERSION="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$_plugin_json" | head -n1)"
312
+ # package.json's first "version" key is the top-level one (devDependency keys
313
+ # are package names, not "version"), so head -n1 is safe.
314
+ DR_INSTALLED_VERSION="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$_pkg_json" | head -n1)"
315
315
  [ -n "$DR_INSTALLED_VERSION" ] || DR_INSTALLED_VERSION="unknown"
316
316
  fi
317
317
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: devrites-performance-reviewer
3
- description: Fresh-context, measure-first performance reviewer for /rite-seal. Use to independently review a DevRites feature diff for N+1s, hot-path work, payload/bundle size, and Core Web Vitals risks. Won't claim a slowdown without a number or a measurement to take.
3
+ description: Fresh-context, measure-first performance reviewer for /rite-seal. Use to independently review a DevRites feature diff for N+1s, hot-path work, payload/bundle size, and Core Web Vitals risks. Runs in Source mode (static scan, findings tagged potential) or Measured mode (judges real Lighthouse/PSI/CrUX/trace numbers and leads with a source-labeled CWV scorecard). Won't claim a slowdown without a number or a measurement to take, and never presents lab data as field data.
4
4
  tools: Read, Grep, Glob, Bash
5
5
  hooks:
6
6
  PreToolUse:
@@ -17,19 +17,50 @@ You are measure-first: no performance claim without a number or a specified meas
17
17
 
18
18
  ## Inputs
19
19
  Workspace `.devrites/work/<slug>/`: read `spec.md` (any perf budget), `evidence.md`,
20
- `touched-files.md`. Run `git diff` and read the touched files.
20
+ `touched-files.md`. Run `git diff` and read the touched files. Also look for Core Web
21
+ Vitals artifacts — numbers already in `evidence.md`, a Lighthouse / PageSpeed Insights /
22
+ CrUX JSON path the builder left, or a browser-proof capture in `browser-evidence.md`.
23
+
24
+ Read the baseline checklist on demand (resolve the path like the readonly hook):
25
+ ```
26
+ C=.claude/skills/rite-review/reference/performance-checklist.md
27
+ [ -f "$C" ] || C="$CLAUDE_PLUGIN_ROOT/pack/.claude/skills/rite-review/reference/performance-checklist.md"
28
+ [ -f "$C" ] || C=pack/.claude/skills/rite-review/reference/performance-checklist.md
29
+ ```
30
+
31
+ ## Two modes (the inputs set the mode, not a flag)
32
+ - **Source mode** — default, no perf artifacts present. Scan the diff statically for
33
+ structural anti-patterns. Every frontend finding is **potential impact**, never a
34
+ measurement; name the command that would confirm it. Emit **no scorecard**.
35
+ - **Measured mode** — a CWV artifact or a real number exists. Judge it against the
36
+ `spec.md` budget or the pre-change baseline, and lead with the scorecard.
37
+
38
+ Source mode is the same discipline as the old "specify the measurement" — it just names
39
+ the contract for when the scorecard appears.
21
40
 
22
41
  ## Review (feature scope)
23
- - **Backend** — N+1 queries, missing indexes on new queries, unbounded result sets,
24
- per-request work that should be cached/batched, blocking sync work.
25
- - **Frontend (Core Web Vitals)** — LCP (oversized images, render-blocking work), CLS
26
- (layout shift), INP (interaction latency), bundle growth, unnecessary re-renders.
42
+ - **Backend** (always, every feature) — N+1 queries, missing indexes on new queries,
43
+ unbounded result sets, per-request work that should be cached/batched, blocking sync
44
+ work. *AI-codegen smell:* over-fetching "just in case", sequential `await`s where
45
+ `Promise.all` fits, redundant calls a dedup would collapse.
46
+ - **Frontend (Core Web Vitals)** — only when the feature is UI-facing. Identify the
47
+ framework and rendering model first (React / Vue / Svelte / Angular / Next / Astro /
48
+ vanilla) and apply only that stack's idioms — don't recommend `next/image` to a Vue app
49
+ or `React.memo` to Svelte. Check LCP (oversized images, render-blocking work, missing
50
+ `fetchpriority`), CLS (layout shift, missing image dimensions), INP (long tasks, heavy
51
+ event handlers), bundle growth, unnecessary re-renders. *AI-codegen smell:* `memo` /
52
+ `useMemo` / `useCallback` wrapping everything, over-eager effect deps, broad watchers.
27
53
  - **General** — accidental quadratic loops, repeated hot-path work, large allocations.
28
54
 
29
55
  ## Measure-first discipline
30
- - If a real number exists in `evidence.md`, judge it against the budget/baseline.
56
+ - If a real number exists, judge it against the budget/baseline; state the before/after.
31
57
  - If not, **specify the measurement** (command, scenario, metric) instead of asserting a
32
58
  regression. Distinguish "measured regression" from "likely hot spot, verify with X".
59
+ - **Source-honesty.** Label every measured CWV value with where it came from —
60
+ `Field (CrUX)` (real users, p75), `Lab (Lighthouse)` (one synthetic run), or
61
+ `Trace (DevTools)`. Field and lab are not interchangeable; presenting one as the other
62
+ is fabrication. Reading static source cannot measure LCP / INP / CLS — never invent a
63
+ number for a value you did not capture.
33
64
 
34
65
  ## Rules
35
66
  - Don't edit. Findings only, labeled Critical / Important / Suggestion / Nit / FYI with
@@ -37,9 +68,26 @@ Workspace `.devrites/work/<slug>/`: read `spec.md` (any perf budget), `evidence.
37
68
  micro-opt with no measured impact is a Suggestion at most. Feature scope only.
38
69
 
39
70
  ## Output
71
+
72
+ **Measured mode** — lead with a compact scorecard, then the line findings:
73
+ ```
74
+ Performance review (<slug>) — independent
75
+ Scorecard (source-labeled):
76
+ LCP <value> <Field(CrUX) | Lab(LH) | Trace> <Good/Needs Work/Poor> (target ≤2.5s)
77
+ INP <value> <source> <status> (target ≤200ms)
78
+ CLS <value> <source> <status> (target ≤0.1)
79
+ [Lighthouse perf <score> Lab(LH)] Artifacts: <which> Stack: <detected>
80
+ [Critical]/[Important] file:line — issue. measured: <number>. direction.
81
+ [Suggestion]/[Nit]/[FYI] ...
82
+ Budget: <breached? | none stated>
83
+ Verdict: <blockers? none/list>
84
+ ```
85
+
86
+ **Source mode** — no artifacts; one scorecard line, findings tagged `potential`:
40
87
  ```
41
88
  Performance review (<slug>) — independent
42
- [Important] file:line issue. measured: <number | "measure: <cmd/metric>">. direction.
89
+ Scorecard: not measured (Source mode)
90
+ [Important] file:line — issue. potential; verify: <cmd/metric>. direction.
43
91
  [Suggestion]/[Nit]/[FYI] ...
44
92
  Budget: <breached? | none stated>
45
93
  To prove any win: <measure X before/after>
@@ -21,6 +21,15 @@ Measure first. An optimization without a measurement is a guess that adds comple
21
21
  - Don't trade correctness or readability for a micro-win that doesn't matter.
22
22
  - Prefer a better algorithm or query over micro-tuning; the big wins are structural.
23
23
 
24
+ ## Frontend — Core Web Vitals
25
+ For UI work, measure-first means LCP / INP / CLS judged against real numbers, each labeled
26
+ by source (`Field (CrUX)`, `Lab (Lighthouse)`, `Trace (DevTools)`) — field and lab are not
27
+ interchangeable, and static source cannot measure a CWV. The reviewer captures these via the
28
+ browser-proof ladder when a budget exists, then judges them in Measured mode (a
29
+ source-labeled scorecard); with no artifact it runs in Source mode and names the command.
30
+ Baseline checks + measurement commands:
31
+ [`rite-review/reference/performance-checklist.md`](../skills/rite-review/reference/performance-checklist.md).
32
+
24
33
  ## Scope
25
34
  Optimize what the change touches or what a measurement flags. Project-wide performance
26
35
  work is its own effort — record it as a follow-up, don't smuggle it into an unrelated
@@ -11,7 +11,7 @@ Dispatch one read-only review subagent against the active feature's workspace +
11
11
 
12
12
  This is the **inline single-axis pass** used during build / polish — one axis at a time, on demand, where a quick read keeps a slice honest. It is intentionally distinct from the seal/review **gate**, where the reviewer agents fan out in parallel across all relevant axes in their own fresh contexts (see `/rite-seal`). Same agents, different role: the audit is a cheap mid-flight check; the seal fan-out is the blocking gate. Both reading the same agent disciplines is the point, not a divergence.
13
13
 
14
- Why a subagent rather than inline: an adversarial reviewer with no author context is more likely to find what's wrong. Anthropic bug [#49559](https://github.com/anthropics/claude-code/issues/49559) leaves `context: fork` silently inline under plugin install, so `Task` dispatch is the reliable path under both plugin and bash installs.
14
+ Why a subagent rather than inline: an adversarial reviewer with no author context is more likely to find what's wrong. Anthropic bug [#49559](https://github.com/anthropics/claude-code/issues/49559) can leave `context: fork` silently inline, so `Task` dispatch is the reliable path.
15
15
 
16
16
  ## Axis selection
17
17
 
@@ -22,12 +22,32 @@ of the ladder that's available; record which one.
22
22
  the project's existing commands. Don't add a new framework.
23
23
  5. **Manual fallback** — none available: record the limitation + exact manual steps.
24
24
 
25
+ ## Core Web Vitals capture (when the spec states a perf budget)
26
+ If `spec.md` carries a perf budget — or a frontend regression risk is visible — capture the
27
+ CWV numbers here so the perf reviewer judges real data instead of guessing. Use the highest
28
+ rung available; **detect, don't install**.
29
+
30
+ 1. **Chrome DevTools MCP** (if configured) — `lighthouse_audit` for LCP/INP/CLS + the
31
+ Lighthouse performance score. Source label: **Lab (Lighthouse)**. A `performance_*` trace
32
+ gives **Trace (DevTools)** attribution.
33
+ 2. **browser-harness** — drive the route, capture a performance trace over CDP. Source
34
+ label: **Trace (DevTools)**.
35
+ 3. **CrUX / PageSpeed Insights** — only if the user supplied an API key. Field data, p75.
36
+ Source label: **Field (CrUX)**.
37
+ 4. **None available** → mark CWV **pending (manual)** and name the exact command
38
+ (`npx lighthouse <url> --output json …`). Don't install anything; don't fake a number.
39
+
40
+ Write each captured value **with its source label** to `evidence.md` (so the perf reviewer
41
+ reads it in Measured mode) and note the tool + route in `browser-evidence.md`. Never present
42
+ a lab value as a field value or vice versa.
43
+
25
44
  ## Evidence schema → `browser-evidence.md`
26
45
  Tooling used · route(s) · viewports (375/768/1280) · screenshot paths **opened and
27
46
  described** · console errors/warnings · network failures · interaction path tested ·
28
- accessibility basics · responsive checks · **design-reference match** (if the spec saved
29
- references in `references/`, compare the built UI to them and note match/diffs) ·
30
- limitations.
47
+ accessibility basics · responsive checks · **CWV capture** (tool + route + each
48
+ source-labeled value, or `pending (manual)` + the command) · **design-reference match** (if
49
+ the spec saved references in `references/`, compare the built UI to them and note
50
+ match/diffs) · limitations.
31
51
 
32
52
  ## Hard rules
33
53
  - A screenshot **path is not proof** — open it and describe what's visible.
@@ -0,0 +1,80 @@
1
+ # Performance checklist (baseline for the perf reviewer)
2
+
3
+ The minimum baseline `devrites-performance-reviewer` checks against, in feature scope. It
4
+ is a checklist, not a mandate: flag what the diff actually touches or what a measurement
5
+ flags, never a project-wide sweep. The philosophy lives in
6
+ [`rules/performance.md`](../../../rules/performance.md) (measure first) — this file is the
7
+ concrete what-to-look-for.
8
+
9
+ ## Core Web Vitals targets
10
+
11
+ | Metric | Good | Needs work | Poor |
12
+ |---|---|---|---|
13
+ | LCP — Largest Contentful Paint | ≤ 2.5s | ≤ 4.0s | > 4.0s |
14
+ | INP — Interaction to Next Paint | ≤ 200ms | ≤ 500ms | > 500ms |
15
+ | CLS — Cumulative Layout Shift | ≤ 0.1 | ≤ 0.25 | > 0.25 |
16
+
17
+ A CWV value only counts when it carries a source — `Field (CrUX)`, `Lab (Lighthouse)`, or
18
+ `Trace (DevTools)`. No source → it's a Source-mode hypothesis, not a measurement.
19
+
20
+ ## Frontend (only when the feature is UI-facing)
21
+
22
+ Identify the framework first; apply only its idioms.
23
+
24
+ - **Images** — modern format (WebP/AVIF); responsive `srcset`/`sizes`; explicit
25
+ `width`/`height` to reserve space (CLS); below-the-fold `loading="lazy"`; the LCP image
26
+ gets `fetchpriority="high"` and is **not** lazy-loaded.
27
+ - **JavaScript** — initial bundle stays small (≈200KB gzipped is the usual line); code-split
28
+ routes and heavy features; no blocking script in `<head>` without `defer`/`async`; break
29
+ long tasks (>50ms) so the main thread stays free (the main INP lever); `memo`/`useMemo`/
30
+ `useCallback` only where profiling shows a win, not wrapped over everything.
31
+ - **CSS** — critical CSS not render-blocking; no per-render CSS-in-JS runtime cost in prod.
32
+ - **Fonts** — 2–3 families max; WOFF2; self-hosted where possible; preload the LCP font;
33
+ `font-display: swap`; subset with `unicode-range`.
34
+ - **Rendering** — no layout thrashing (batch reads, then writes); animate `transform`/
35
+ `opacity` only; virtualize long lists; `content-visibility: auto` for off-screen sections;
36
+ don't break bfcache (no `unload` handler, no `Cache-Control: no-store` on HTML).
37
+
38
+ ## Backend (every feature, UI or not)
39
+
40
+ - No N+1 queries; eager-load / join / batch instead.
41
+ - New queries have the indexes they need for their filter/sort columns.
42
+ - List endpoints paginate — never an unbounded `SELECT *`.
43
+ - Per-request work that doesn't change per call is cached or hoisted.
44
+ - Responses compressed (gzip/brotli); bulk operations instead of a loop of single calls.
45
+
46
+ ## Network
47
+
48
+ - Static assets cached with a long `max-age` + content hashing.
49
+ - Known origins `preconnect`-ed; no unnecessary redirects; HTTP/2 or HTTP/3 where available.
50
+
51
+ ## AI-codegen perf smells (fold into the area above, not a separate finding category)
52
+
53
+ - State duplicated instead of lifted; effects with over-broad deps that re-run needlessly.
54
+ - Sequential `await`s where `Promise.all` / parallel fetch fits.
55
+ - Over-fetching "just in case"; redundant calls a dedup would collapse.
56
+ - Defensive memoization wrapping cheap components — cost with no benefit.
57
+
58
+ ## Modern APIs to consider (one-liners — reach for these, don't gate on them)
59
+
60
+ `scheduler.yield()` to keep input responsive in long loops · Speculation Rules for
61
+ prefetch/prerender · View Transitions on SPA navigation · Long Animation Frames (LoAF) for
62
+ production INP attribution · `fetchpriority` on critical non-image resources.
63
+
64
+ ## Measurement commands (name these in Source mode; don't run installs in review)
65
+
66
+ ```bash
67
+ # Lighthouse (lab)
68
+ npx lighthouse <url> --output json --output-path ./report.json
69
+ # or via the Chrome DevTools MCP CLI, no install:
70
+ npx -p chrome-devtools-mcp chrome-devtools lighthouse_audit --output-format=json > report.json
71
+
72
+ # Bundle size
73
+ npx vite-bundle-visualizer # Vite
74
+ npx webpack-bundle-analyzer stats.json # webpack
75
+
76
+ # Field data: CrUX / PageSpeed Insights (real users, p75) — needs an API key
77
+ ```
78
+
79
+ Field is what real users experienced; lab is one synthetic run. Don't present one as the
80
+ other.
@@ -17,6 +17,10 @@ a hunch.
17
17
  unnecessary re-renders.
18
18
  - **General**: accidental quadratic loops, repeated work in hot paths, large allocations.
19
19
 
20
+ The agent runs **Source mode** (static scan, findings tagged `potential` + the verify
21
+ command) or **Measured mode** (real CWV numbers → a source-labeled scorecard). Baseline
22
+ checks + measurement commands: [`performance-checklist.md`](performance-checklist.md).
23
+
20
24
  ## Optimize responsibly
21
25
  - Fix the measured bottleneck, then **re-measure** to prove the win (before/after in
22
26
  `evidence.md`). An optimization with no measured improvement is just added complexity.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devrites",
3
- "version": "1.19.0",
3
+ "version": "2.1.0",
4
4
  "description": "DevRites — disciplined senior-engineer workflow skills pack for Claude Code",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://github.com/ViktorsBaikers/DevRites#readme",
@@ -33,7 +33,6 @@
33
33
  "install.sh",
34
34
  "uninstall.sh",
35
35
  "update.sh",
36
- ".claude-plugin/",
37
36
  "mcp/",
38
37
  "docs/",
39
38
  "README.md",
@@ -27,7 +27,6 @@ mkdir -p "$STAGE"
27
27
  # Files and directories shipped to end-users.
28
28
  PAYLOAD=(
29
29
  pack
30
- .claude-plugin
31
30
  scripts
32
31
  mcp
33
32
  docs
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
- # Sync the semantic-release-determined version across every DevRites manifest
3
- # so plugin.json, marketplace.json and package.json stay in lockstep.
2
+ # Sync the semantic-release-determined version into package.json and the README
3
+ # status line so the published version stays in step with the released tag.
4
4
  #
5
5
  # Usage: sync-version.sh <version>
6
6
  set -euo pipefail
@@ -23,8 +23,6 @@ const version = process.argv[2];
23
23
 
24
24
  const updates = [
25
25
  { file: 'package.json', set: (j) => { j.version = version; } },
26
- { file: '.claude-plugin/plugin.json', set: (j) => { j.version = version; } },
27
- { file: '.claude-plugin/marketplace.json', set: (j) => { j.plugins.forEach(p => { if (p.name === 'devrites') p.version = version; }); } },
28
26
  ];
29
27
 
30
28
  for (const u of updates) {
@@ -65,29 +65,6 @@ for a in $AGENT_FILES; do
65
65
  if [ -f "$AGENTS/$a.md" ]; then good "$a"; else bad "missing agent: $a"; fi
66
66
  done
67
67
 
68
- section "plugin manifest agents list matches pack/.claude/agents"
69
- PLUGIN_JSON="$ROOT/.claude-plugin/plugin.json"
70
- if [ -r "$PLUGIN_JSON" ] && command -v python3 >/dev/null 2>&1; then
71
- manifest_list="$(python3 -c '
72
- import json, sys
73
- m = json.load(open(sys.argv[1]))
74
- a = m.get("agents", [])
75
- if isinstance(a, str):
76
- a = [a]
77
- for p in a:
78
- print(p.lstrip("./"))
79
- ' "$PLUGIN_JSON" | sort -u)"
80
- disk_list="$(cd "$ROOT" && ls pack/.claude/agents/*.md 2>/dev/null | sort -u)"
81
- if [ "$manifest_list" = "$disk_list" ]; then
82
- good "plugin.json agents array matches pack/.claude/agents/*.md"
83
- else
84
- bad "plugin.json agents array out of sync with pack/.claude/agents/*.md"
85
- diff <(printf '%s\n' "$manifest_list") <(printf '%s\n' "$disk_list") || true
86
- fi
87
- else
88
- echo "skip: cannot validate manifest sync (missing python3 or plugin.json)"
89
- fi
90
-
91
68
  # ---- 5. frontmatter validation ------------------------------------------
92
69
  section "frontmatter"
93
70
  if command -v python3 >/dev/null 2>&1; then
@@ -169,30 +146,7 @@ else
169
146
  bad "rule-uniqueness check failed (see scripts/check-rule-uniqueness.sh)"
170
147
  fi
171
148
 
172
- # ---- 12. version lockstep across manifests -------------------------------
173
- section "version lockstep (package.json == plugin.json == marketplace.json)"
174
- if command -v python3 >/dev/null 2>&1; then
175
- if python3 - "$ROOT" <<'PY'
176
- import json, sys, os
177
- root = sys.argv[1]
178
- pkg = json.load(open(os.path.join(root, "package.json")))["version"]
179
- plug = json.load(open(os.path.join(root, ".claude-plugin/plugin.json")))["version"]
180
- mkt = json.load(open(os.path.join(root, ".claude-plugin/marketplace.json")))
181
- mver = next((p.get("version") for p in mkt.get("plugins", []) if p.get("name") == "devrites"), None)
182
- print(" package.json %s" % pkg)
183
- print(" plugin.json %s" % plug)
184
- print(" marketplace.json %s" % mver)
185
- if pkg == plug == mver and mver is not None:
186
- sys.exit(0)
187
- print("FAIL: version mismatch across manifests")
188
- sys.exit(1)
189
- PY
190
- then good "versions match across package.json / plugin.json / marketplace.json"; else bad "version mismatch across manifests (run scripts/sync-version.sh)"; fi
191
- else
192
- echo "skip: python3 not found"
193
- fi
194
-
195
- # ---- 13. no runtime-broken pack/.claude/ path in installed prose ---------
149
+ # ---- 12. no runtime-broken pack/.claude/ path in installed prose ---------
196
150
  # After install the leading pack/ is stripped, so any literal pack/.claude/rules/
197
151
  # or pack/.claude/skills/ in shipped SKILL.md / reference prose is a dead path
198
152
  # at runtime. (Repo README/docs links are out of scope — they're GitHub links.)
@@ -1,24 +0,0 @@
1
- {
2
- "name": "devrites-marketplace",
3
- "description": "DevRites — disciplined senior-engineer workflow skills pack for Claude Code.",
4
- "owner": {
5
- "name": "Viktors Baikers",
6
- "url": "https://github.com/ViktorsBaikers"
7
- },
8
- "plugins": [
9
- {
10
- "name": "devrites",
11
- "source": "./",
12
- "description": "Spec → plan → build → prove → polish → review → seal → ship workflow with persistent state, drift guard, browser-proof ladder, and anti-AI-slop guardrails.",
13
- "version": "1.19.0",
14
- "license": "personal-use-or-by-approval",
15
- "keywords": [
16
- "workflow",
17
- "skills",
18
- "senior-engineer",
19
- "spec-driven",
20
- "anti-slop"
21
- ]
22
- }
23
- ]
24
- }
@@ -1,43 +0,0 @@
1
- {
2
- "name": "devrites",
3
- "version": "1.19.0",
4
- "description": "Disciplined senior-engineer workflow skills pack — spec/plan/build/prove/polish/review/seal/ship with persistent .devrites/ Markdown state, Spec Drift Guard, browser-proof ladder, fullstack contract-first slicing, and anti-AI-slop guardrails.",
5
- "author": {
6
- "name": "Viktors Baikers",
7
- "url": "https://github.com/ViktorsBaikers"
8
- },
9
- "homepage": "https://github.com/ViktorsBaikers/DevRites",
10
- "repository": "https://github.com/ViktorsBaikers/DevRites",
11
- "license": "SEE LICENSE IN LICENSE",
12
- "keywords": [
13
- "claude-code",
14
- "skills",
15
- "agent-skills",
16
- "workflow",
17
- "senior-engineer",
18
- "spec-driven",
19
- "tdd",
20
- "code-review",
21
- "polish",
22
- "frontend",
23
- "fullstack",
24
- "anti-slop",
25
- "design-system",
26
- "devrites"
27
- ],
28
- "skills": "./pack/.claude/skills",
29
- "hooks": "./pack/.claude/hooks/hooks.json",
30
- "agents": [
31
- "./pack/.claude/agents/devrites-code-reviewer.md",
32
- "./pack/.claude/agents/devrites-doubt-reviewer.md",
33
- "./pack/.claude/agents/devrites-frontend-reviewer.md",
34
- "./pack/.claude/agents/devrites-performance-reviewer.md",
35
- "./pack/.claude/agents/devrites-plan-reviewer.md",
36
- "./pack/.claude/agents/devrites-security-auditor.md",
37
- "./pack/.claude/agents/devrites-simplifier-reviewer.md",
38
- "./pack/.claude/agents/devrites-slice-wright.md",
39
- "./pack/.claude/agents/devrites-spec-reviewer.md",
40
- "./pack/.claude/agents/devrites-strategy-reviewer.md",
41
- "./pack/.claude/agents/devrites-test-analyst.md"
42
- ]
43
- }