|
51 | 51 | llms.txt/route.ts # /llms.txt — markdown manifest for LLM crawlers (Perplexity, Claude, ChatGPT search) |
52 | 52 | api/repos/route.ts |
53 | 53 | api/repo/[id]/route.ts |
| 54 | + api/score/route.ts # /api/score?host=&repo=owner/name — public lookup (powers the action + agent skill) |
54 | 55 | api/badge/[host]/[owner]/[name]/route.ts # SVG badge for README embeds (?model=<id> for per-model) |
55 | 56 | api/package/[registry]/[name]/route.ts # npm/PyPI/Cargo lookup → source-repo score |
56 | 57 | repo/[id]/opengraph-image.tsx # next/og convention — per-repo OG image (auto-wired) |
57 | 58 | package/page.tsx # explainer + try-it examples |
58 | 59 | package/[registry]/[name]/page.tsx # scored | not_scored | unresolved states |
| 60 | + action/page.tsx # PR-diff GitHub Action explainer + install snippet (SEO landing for the sibling action repo) |
59 | 61 | globals.css # Tailwind import + @theme tokens (no custom utilities) |
60 | 62 | components/ # Tailwind-styled React components |
61 | 63 | Panel.tsx, ScoreBar.tsx, ScoreNumber.tsx, ScoreCell.tsx, |
62 | 64 | HostPill.tsx, HostSelect.tsx, Medal.tsx, ModelPills.tsx, |
63 | 65 | MobileNav.tsx, Pagination.tsx, SearchBar.tsx, SelectMenu.tsx, SortSelect.tsx, |
64 | 66 | SignalRow.tsx, SuggestionItem.tsx, VersionPill.tsx, |
65 | 67 | RepoHero.tsx, SignalListCard.tsx, ModelSuggestions.tsx, PerModelScores.tsx, |
| 68 | + BadgeEmbed.tsx, ActionEmbed.tsx, CopySnippet.tsx, PackageLookupForm.tsx, |
66 | 69 | BackToTop.tsx, GoogleAnalytics.tsx |
67 | 70 | lib/ |
68 | 71 | constants/ |
|
80 | 83 | git.ts, github.ts, registries.ts # registries.ts: npm/PyPI/Cargo package → source-repo URL |
81 | 84 | package-lookup.ts # shared registry → repo lookup (used by /api/package + /package page) |
82 | 85 | db.ts # better-sqlite3 schema + queries |
83 | | - version.ts # APP_NAME, APP_VERSION, IS_PRE_RELEASE, APP_URL, APP_DESCRIPTION, REPO_URL |
| 86 | + version.ts # APP_NAME, APP_VERSION, IS_PRE_RELEASE, APP_URL, APP_DESCRIPTION, REPO_URL, ACTION_REPO_URL, ACTION_USES |
84 | 87 | changelog.ts # typed ChangelogEntry[] |
85 | 88 | roadmap.ts # typed RoadmapVersion[] |
86 | 89 | scripts/ |
@@ -130,17 +133,31 @@ Keep it that way when adding features. If a component needs data, fetch in the p |
130 | 133 | - **Versioning + changelog**: bumps on `lib/version.ts` + `package.json` `version` happen only on a real release, coordinated with a new bucket in `lib/changelog.ts`. The changelog is a **user-facing capability log** — every bullet describes something a dashboard visitor or API caller can see, click, or call. Codebase hygiene (CI, linters, pre-commit, tests), pure internal refactors, dep bumps, and contributor-facing docs (CONTRIBUTING, PR templates) do **not** earn a changelog line — they stay in `tasks/` and the PR description. When a roadmap item ships, remove it from `lib/roadmap.ts` in the same PR — moved, not duplicated. |
131 | 134 | - **File length**: `.ts` / `.tsx` under `app/`, `components/`, `lib/` stay ≤ 300 lines — enforced by the `file-length` pre-commit job in `lefthook.yml`. Near the cap, split into subcomponents or extract helpers to `lib/utils/`. `scripts/` is exempt (seed data lists). |
132 | 135 |
|
| 136 | +## Sibling repos |
| 137 | + |
| 138 | +The PR-diff GitHub Action lives in a sibling directory: `../agent-friendly-action/`. It **vendors** the scorer (`lib/scoring/` from this repo) into its own bundle so it can run inside maintainer CI with no network call to this app. Extracting `agent-friendly-scorer` as a standalone npm package is deferred to `tasks/1.0.0/03-benchmark-harness.md`, when a second sibling consumer (the benchmark harness) appears. Until then, the two copies of the scorer must stay in sync by hand. |
| 139 | + |
| 140 | +**Whenever you change `lib/scoring/`** — adding a signal, tweaking a weight, refactoring `scorer.ts`, anything — also: |
| 141 | + |
| 142 | +1. Re-vendor the changed file(s) into `../agent-friendly-action/src/scoring/` (mirror the directory layout). |
| 143 | +2. Append a line under "Unreleased" in `../agent-friendly-action/CHANGELOG.md` describing what changed, so action consumers can read what shipped in each tagged release. |
| 144 | +3. The action's CI verifies its `dist/` bundle is in sync with `src/` on every push, but it can't catch upstream-source drift — that's on the agent doing the change. |
| 145 | + |
| 146 | +If `../agent-friendly-action/` isn't present locally, flag it; never silently skip the propagation. Both repos are siblings under the same `personal/` workspace. |
| 147 | + |
133 | 148 | ## Adding a signal |
134 | 149 |
|
135 | 150 | 1. New file at `lib/scoring/signals/<kebab-id>.ts` implementing `Signal` (including `improveSuggestion`). |
136 | 151 | 2. Import and add to the `SIGNALS` array in `lib/scoring/signals/index.ts`. |
137 | 152 | 3. Add a weight entry to **every** model in `lib/scoring/weights.ts` — missing weights default to 0, decide deliberately. |
138 | 153 | 4. Re-score: `bun run seed` is idempotent. |
| 154 | +5. **Mirror to the action** (per "Sibling repos" above): copy the new signal file into `../agent-friendly-action/src/scoring/signals/`, add the import + array entry to its `signals/index.ts`, copy the weights changes to its `weights.ts`, and log the addition in `../agent-friendly-action/CHANGELOG.md` under "Unreleased". |
139 | 155 |
|
140 | 156 | ## Adding a model |
141 | 157 |
|
142 | 158 | 1. Add a `ModelProfile` to `MODELS` in `lib/scoring/weights.ts` — weights for every signal. |
143 | 159 | 2. Appears automatically in the leaderboard model pills and repo-page suggestions. |
| 160 | +3. **Mirror to the action**: copy the weights change into `../agent-friendly-action/src/scoring/weights.ts` and log under "Unreleased" in its `CHANGELOG.md`. |
144 | 161 |
|
145 | 162 | ## Adding a host |
146 | 163 |
|
@@ -180,7 +197,7 @@ Hooks docs: <https://docs.claude.com/en/docs/claude-code/hooks.html>. |
180 | 197 |
|
181 | 198 | - 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. |
182 | 199 | - SQL: all queries parameterised. No interpolation. |
183 | | -- HTML: React auto-escapes. The only `dangerouslySetInnerHTML` is server-built JSON-LD with `<` escaped to `<` (`app/layout.tsx`, `app/page.tsx`, `app/methodology/page.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`); never feed user-controlled strings into it. |
| 200 | +- HTML: React auto-escapes. The only `dangerouslySetInnerHTML` is server-built JSON-LD with `<` escaped to `<` (`app/layout.tsx`, `app/page.tsx`, `app/action/page.tsx`, `app/methodology/page.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`); never feed user-controlled strings into it. |
184 | 201 | - Local-path mode reads files; never writes outside `data/` and the clone workspace passed to `shallowClone`. |
185 | 202 | - No auth yet (read-only dashboard). When auth lands (`tasks/0.7.0/01-opt-out-claim-flow.md`), do it via OAuth and gate DB writes per user. |
186 | 203 |
|
|
0 commit comments