You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: align security & contributor guides with codebase reality
- README/AGENTS/skills now describe `dangerouslySetInnerHTML` accurately (allowed only for the existing JSON-LD scripts) and require `rel="noopener noreferrer"` on external links to match what the code already does.
- README expands the agent list, refreshes the "Server-first; client islands" stack row, and drops `tmp-clones/` from Layout + Operational concerns. AGENTS fixes the "Adding a host" seed pointer (`scripts/seed-list.ts`) and the `dangerouslyInnerHTML` typo.
- CONTRIBUTING aligns the PR-size guidance with the lefthook 300-line cap.
- Removes remaining `tmp-clones/` mentions across docs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-`dangerouslySetInnerHTML` is allowed only for the existing server-built JSON-LD scripts (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`) with the `<` → `<` escape preserved. Reject any new use.
58
+
- External links include `rel="noopener noreferrer"`.
Copy file name to clipboardExpand all lines: .claude/skills/quality-check/SKILL.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,13 +39,13 @@ Run the four checks below on any diff affecting UI or I/O. Report findings group
39
39
## Security
40
40
41
41
-**SQL parameterisation**: every query uses `?` placeholders. No string concatenation.
42
-
-**No `dangerouslySetInnerHTML`.**
43
-
-**External URLs** in `<a target="_blank">` always include `rel="noopener"`.
42
+
-**`dangerouslySetInnerHTML`** is allowed only for server-built JSON-LD (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`) and must keep the `<` → `<` escape. Any other use must be rejected.
43
+
-**External URLs** in `<a target="_blank">` always include `rel="noopener noreferrer"`.
44
44
-**User input at every boundary** is validated: `parseRepoUrl` for repo URLs, `Number.isFinite` for numeric params, length caps on search strings.
45
45
-**Clone safety**: `git clone --depth 1 --single-branch`; never execute code from a clone (no `bun install`, no `npm install`, no post-clone scripts).
46
46
-**Secrets never in code**. `.env.example` documents required vars; `.env.local` is gitignored.
47
47
-**Operational concerns** (flag for ops review, not code):
48
-
- Disk cap on `tmp-clones/`.
48
+
- Disk cap on the clone workspace.
49
49
- Rate limit on the public API before launch.
50
50
- Sandbox the cloner in a container for production.
Copy file name to clipboardExpand all lines: AGENTS.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -142,7 +142,7 @@ Keep it that way when adding features. If a component needs data, fetch in the p
142
142
143
143
1. Extend `parseRepoUrl` in `lib/clients/github.ts`.
144
144
2. Extend `fetchRepoMeta` with that host's API (use `process.env.<HOST>_TOKEN` if needed).
145
-
3. Add a seed URL in `scripts/seed.ts`.
145
+
3. Add a seed URL to the `SEEDS` list in `scripts/seed-list.ts`.
146
146
4. Add the label to `lib/constants/hosts.ts`.
147
147
148
148
## Working from tasks/
@@ -165,7 +165,7 @@ The `Stop` guard exists because reminders alone weren't enough — agents would
165
165
`.claude/skills/` holds project skills that are auto-selected based on task relevance or invoked manually (`/skill-name`). Skills **do not auto-fire on file edits** — that's what the Stop guard is for. The guard enforces `post-change-check`, which orchestrates the other two.
166
166
167
167
-**`code-review`** — writing-time conventions. Covers Tailwind-first (utilities > custom classes; `@theme` tokens > hex), **Phosphor Icons only** (blocks Lucide / Heroicons / React Icons / inline SVG / emoji-as-icon), the I/O boundary (`lib/scoring/` pure, all SQL in `lib/db.ts`), RSC preference, and when to extract into `components/` / `lib/constants/` / `lib/utils/`.
168
-
-**`quality-check`** — review-time sweep. Four dimensions: accessibility (landmarks, aria, contrast, reduced motion, keyboard reachability), responsiveness (320 → 1080+ viewports, mobile nav, tables), performance (RSC default, `next/script` for third-party, bundle size), security (parameterised SQL, no innerHTML, `rel=noopener`, clone safety).
168
+
-**`quality-check`** — review-time sweep. Four dimensions: accessibility (landmarks, aria, contrast, reduced motion, keyboard reachability), responsiveness (320 → 1080+ viewports, mobile nav, tables), performance (RSC default, `next/script` for third-party, bundle size), security (parameterised SQL, `dangerouslySetInnerHTML` only for the existing server-built JSON-LD scripts, `rel="noopener noreferrer"` on external links, clone safety).
169
169
-**`post-change-check`** — end-of-turn orchestrator. Runs a four-phase report: diff collection, docs-sync audit (changelog / tasks / AGENTS / README / .env.example / skills), then delegates to `code-review` and `quality-check`. The Stop guard blocks turn-close until this has run when watched paths changed.
170
170
171
171
Skill granularity rule of thumb: one skill per _phase_ of work (writing, reviewing, wrapping-up), not one skill per _rule_. Narrow skills fragment context; broad skills stay coherent.
- We `git clone --depth 1 --single-branch` arbitrary URLs — safe by default. We never run post-clone scripts, never `npm install`, never execute code from the clone.
178
178
- SQL: all queries parameterised. No interpolation.
179
-
- HTML: React auto-escapes; no `dangerouslyInnerHTML` anywhere.
180
-
- Local-path mode reads files; never writes outside `data/` and `tmp-clones/`.
179
+
- HTML: React auto-escapes. The only `dangerouslySetInnerHTML` is server-built JSON-LD with `<` escaped to `<` (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`); never feed user-controlled strings into it.
180
+
- Local-path mode reads files; never writes outside `data/` and the clone workspace passed to `shallowClone`.
181
181
- No auth yet (read-only dashboard). When auth lands (`tasks/0.6.0/01-opt-out-claim-flow.md`), do it via OAuth and gate DB writes per user.
182
182
183
183
**Operational concerns** (not code-level security) worth flagging before public launch:
184
184
185
-
-`tmp-clones/` can fill disk — add a cron/cap.
185
+
-The clone workspace can fill disk — add a cron/cap.
186
186
- Unauthenticated API → add rate limits before going public.
187
187
- Sandbox the cloner in a container when running on remote infra, just in case of future git CVEs.
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -102,7 +102,7 @@ When the PR qualifies, move the item atomically: append a one-line capability bu
102
102
103
103
### Size
104
104
105
-
PRs under ~400 lines of diff review fastest. If your change is larger, split by feature or by layer (scoring → DB → UI) so each PR is independently reviewable.
105
+
PRs under ~300 lines of diff review fastest — the same cap the `file-length` pre-commit job enforces per file. If your change is larger, split by feature or by layer (scoring → DB → UI) so each PR is independently reviewable.
Copy file name to clipboardExpand all lines: README.md
+4-5Lines changed: 4 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -26,7 +26,7 @@ Follows `prefers-color-scheme` automatically — same tokens, different values.
26
26
27
27
## The idea
28
28
29
-
AI coding agents — Claude Code, Cursor, Devin, GPT-5 Codex — succeed dramatically more often on some repos than others. The difference is rarely the agent; it's the repo. A codebase with fast tests, a clear `AGENTS.md`, a Makefile, and CI is a massively different environment than one without.
29
+
AI coding agents — Claude Code, Cursor, Devin, GPT-5 Codex, Gemini CLI, Aider, OpenHands, Pi — succeed dramatically more often on some repos than others. The difference is rarely the agent; it's the repo. A codebase with fast tests, a clear `AGENTS.md`, a Makefile, and CI is a massively different environment than one without.
30
30
31
31
**Goal**: a public leaderboard where anyone can look up a repo and see:
32
32
@@ -75,12 +75,12 @@ Short answer: **low risk**. The app:
75
75
- Only **reads** files after a shallow clone; never executes anything from the cloned tree (no `npm install`, no post-clone hooks).
76
76
- Uses `--depth 1 --single-branch` and never clones submodules.
77
77
- Runs all SQL via prepared statements.
78
-
- Renders through React (auto-escaping); no `dangerouslySetInnerHTML`.
78
+
- Renders through React (auto-escaping); the only `dangerouslySetInnerHTML` use is server-built JSON-LD with `<` escaped to `<`.
79
79
- Has no auth and no writable API endpoints — read-only dashboard.
80
80
81
81
**Operational concerns** for a public launch (not code-level security):
82
82
83
-
- Disk quotas for `tmp-clones/`.
83
+
- Disk quotas for the clone workspace.
84
84
- Rate limiting the public API.
85
85
- Sandbox the cloner in a container (future-proofing against hypothetical git CVEs).
86
86
@@ -120,7 +120,7 @@ Run the unit tests with `bun run test` (uses `node --test` + `tsx`; requires Nod
120
120
|**Node runtime (with `tsx` for CLI scripts)**| Matches Vercel's serverless runtime — no Bun-only imports in prod. Bun still works locally as a fast package manager. | Unlikely — only if the deployment target changes. |
121
121
|**Tailwind CSS 4**| Zero-config via `@theme` tokens, no `tailwind.config.*` needed. Tight bundle output. | Would only leave for something with a stronger design-system story. |
122
122
|**`better-sqlite3`**| Single file, inspectable, zero ops overhead. Node-native so Vercel's serverless runtime can load it directly. | Postgres when concurrent writers / access control arrive (`tasks/1.0.0/01-postgres-migration.md`). |
123
-
|**Server components + links, no client JS**| Cheap, fast, SEO-friendly. | When a feature genuinely needs interactivity — e.g. live filter combinators. |
123
+
|**Server-first; client islands where needed**| Cheap, fast, SEO-friendly. Client components only where interactivity demands — mobile nav, search, selects, copy, back-to-top.| When client islands grow past presentational interactivity → reach for client state mgmt.|
124
124
|**Shallow git clones** (`--depth 1 --single-branch`) | Bandwidth + speed. Current signals don't need history. | History-aware signals → host APIs or `--filter=blob:none` partial clones. |
125
125
|**Exact-pinned deps**| Deterministic scoring across environments. | Never. |
126
126
|**One file per signal**| Each signal is a small, independent concern — keeps `git log` and code review focused. | When we bundle signals into dynamic checks (then the unit becomes the bundle). |
Copy file name to clipboardExpand all lines: tasks/0.2.0/02-self-score.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,4 +21,4 @@ Confirm this repo hits ≥ 90 overall on its own rubric once `tasks/0.2.0/01-tes
21
21
22
22
- Scored via local-path mode (`bun run score .`) so the score reflects the tree _with_ the new `tests/` suite rather than the yet-to-be-pushed GitHub state:
23
23
- Overall **90.6**. Per-model: Claude Code 90.0, Cursor 92.7, Devin 89.0, GPT-5 Codex 90.7 — every model within 2.7 pts of overall.
24
-
-`tests` flipped from 0 → 1. `dev_env` still partial at 0.6 (package.json scripts only). `size` drops to 0.2 locally because the `tmp-clones/`workspace directory pollutes the count — not a signal bug (remote scoring clones into `tmp-clones/<slug>/` and scans the inner dir, so the sibling never shows up); called out here rather than patched.
24
+
-`tests` flipped from 0 → 1. `dev_env` still partial at 0.6 (package.json scripts only). `size` drops to 0.2 locally because the local clone workspace pollutes the count — not a signal bug (remote scoring clones into a per-repo subdirectory and scans the inner dir, so the sibling never shows up); called out here rather than patched.
0 commit comments