Skip to content

Commit dfd72aa

Browse files
hsnice16claude
andauthored
release: 0.6.0 — auto-refresh (scheduled rescoring) (#7)
* feat: 0.6.0 task 01 — scheduled rescoring Adds a 6-hourly GitHub Actions cron that re-runs `bun run seed` and commits the refreshed `data/rank.db` to `main`. Surfaces the overall-score delta from the previous rescore on the repo detail page. Downscoped from the original webhook + queue design — see tasks/0.6.0/01-scheduled-rescoring.md for the rationale. Pieces: - .github/workflows/scheduled-rescore.yml — cron + concurrency group + sqlite3-snapshot diff so unchanged-score runs skip the commit (last_scored_at churn would otherwise force a binary diff). - lib/db.ts — new `previous_overall_score REAL` column; the UPSERT captures the row's pre-update overall_score on every rescore. - lib/types/db.ts — extracted shared row-shape types out of lib/db.ts (RepoRow, LeaderboardRow, …). Consumers now import from @/lib/types/db. - components/RepoHero.tsx — inline `+N.N pts` / `-N.N pts` next to "Last scored" in text-ok / text-bad; aria-label carries the previous absolute score for screen readers. - scripts/seed-list.ts — 16 new seed repos across JS/TS, Python, Rust, Go, Java, Ruby, and .NET so the cron has more material. - data/rank.db — re-seeded against the new schema. SEO + polish bundled in: - app/layout.tsx — googleBot robots directives (max-image-preview=large, max-snippet=-1, max-video-preview=-1) and OG image dimensions corrected to the actual file size (2312×924). - components/Panel.tsx — PanelHeading rendered as h2 (was h3) so every page has a clean h1 → h2 heading hierarchy. - app/sitemap.ts — privacy / terms now use a fixed LEGAL_LAST_UPDATED date instead of `now`, so legal pages don't churn lastmod on every deploy. Docs sync: - AGENTS.md, README.md, CONTRIBUTING.md, methodology FAQ, roadmap entry, tasks/0.5.0/02, tasks/1.0.0/01-02, and the SessionStart hook updated to reference the scheduled-rescore cron instead of the deferred webhook design. APP_VERSION stays at 0.5.0 — 0.6.0 still has task 02 (alternatives v2 embeddings) outstanding, so no changelog bucket yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: cut 0.6.0 — auto-refresh - Bump APP_VERSION / package.json to 0.6.0 and add the 0.6.0 changelog entry (scheduled rescoring + repo-page score delta + 16 new seeds). - Remove 0.6.0 from lib/roadmap.ts (released) and mark 0.6.0/02 (alternatives-v2 embeddings) deferred to backlog with the rationale and lighter-weight options. - Sync AGENTS.md status block, .claude/settings.json SessionStart banner, tasks/0.6.0/README.md, and the stale 0.3.0 references that pointed at the deferred v2 upgrade. - Add a dedicated home-route opengraph-image.tsx (1200x630) and add a `deferred` status to tasks/README.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: consolidate OG/twitter metadata defaults + auto-wire twitter cards Extract OG_DEFAULTS and TWITTER_DEFAULTS in lib/version.ts and spread them into every page's metadata — Next.js shallow-merges these objects, so defaults must be re-spread on every page. Drop the inline /demo/light.png override from the root layout in favour of the auto-wired app/opengraph-image.tsx, and add matching twitter-image.tsx re-exports at app/ and app/repo/[id]/ so the Twitter card uses the same generated image. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a2478a6 commit dfd72aa

44 files changed

Lines changed: 526 additions & 191 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"hooks": [
77
{
88
"type": "command",
9-
"command": "printf '\\n📦 Agent Friendly Code — current release: 0.5.0\\n • Read AGENTS.md for conventions, CONTRIBUTING.md for the PR workflow.\\n • Roadmap: 0.6.0 (auto-refresh + smarter matching — webhook rescoring + alternatives v2) → 0.7.0 (maintainer ownership + at-scale discovery — OAuth opt-out + package overlay at scale) → 1.0.0 (production cut — Postgres + at-scale indexing + benchmark harness).\\n • Changelog rule: user-facing capabilities only. Codebase hygiene (CI / linter / tests / CONTRIBUTING) does NOT go in lib/changelog.ts.\\n'"
9+
"command": "printf '\\n📦 Agent Friendly Code — current release: 0.6.0\\n • Read AGENTS.md for conventions, CONTRIBUTING.md for the PR workflow.\\n • Roadmap: 0.7.0 (maintainer ownership + at-scale discovery — OAuth opt-out + package overlay at scale) → 1.0.0 (production cut — Postgres + at-scale indexing + benchmark harness).\\n • Changelog rule: user-facing capabilities only. Codebase hygiene (CI / linter / tests / CONTRIBUTING) does NOT go in lib/changelog.ts.\\n'"
1010
}
1111
]
1212
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Scheduled rescore
2+
3+
on:
4+
schedule:
5+
- cron: "0 */6 * * *"
6+
workflow_dispatch:
7+
8+
concurrency:
9+
group: scheduled-rescore
10+
cancel-in-progress: false
11+
12+
permissions:
13+
contents: write
14+
15+
jobs:
16+
rescore:
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 60
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Setup Bun
23+
uses: oven-sh/setup-bun@v2
24+
with:
25+
bun-version: 1.2.16
26+
27+
- name: Setup Node
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: "22"
31+
32+
- name: Install
33+
run: bun install --frozen-lockfile
34+
35+
- name: Snapshot pre-rescore overall scores
36+
run: sqlite3 data/rank.db "SELECT url, overall_score FROM repo ORDER BY url;" > /tmp/scores-before.txt
37+
38+
- name: Rescore curated seeds
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
run: bun run seed
42+
43+
- name: Commit and push if any overall score changed
44+
run: |
45+
sqlite3 data/rank.db "SELECT url, overall_score FROM repo ORDER BY url;" > /tmp/scores-after.txt
46+
if diff -q /tmp/scores-before.txt /tmp/scores-after.txt > /dev/null; then
47+
echo "No overall-score changes — skipping commit (last_scored_at churn ignored)."
48+
exit 0
49+
fi
50+
git config user.name "github-actions[bot]"
51+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
52+
git add data/rank.db
53+
git commit -m "chore: scheduled rescore $(date -u +%Y-%m-%dT%H:%MZ)"
54+
git push

AGENTS.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ app/
5656
api/score/route.ts # /api/score?host=&repo=owner/name — public lookup for external integrators (siblings vendor the scorer; they don't call this)
5757
api/badge/[host]/[owner]/[name]/route.ts # SVG badge for README embeds (?model=<id> for per-model)
5858
api/package/[registry]/[name]/route.ts # npm/PyPI/Cargo lookup → source-repo score
59+
opengraph-image.tsx # next/og convention — home OG image, 1200×630 (auto-wired)
60+
twitter-image.tsx # next/og convention — twitter:image, re-exports opengraph-image (auto-wired)
5961
repo/[id]/opengraph-image.tsx # next/og convention — per-repo OG image (auto-wired)
62+
repo/[id]/twitter-image.tsx # next/og convention — per-repo twitter:image, re-exports (auto-wired)
6063
package/page.tsx # explainer + try-it examples
6164
package/[registry]/[name]/page.tsx # scored | not_scored | unresolved states
6265
action/page.tsx # PR-diff GitHub Action explainer + install snippet (SEO landing for the sibling action repo)
@@ -87,9 +90,11 @@ lib/
8790
scorer.ts # signals × weights, topImprovements
8891
clients/
8992
git.ts, github.ts, registries.ts # registries.ts: npm/PyPI/Cargo package → source-repo URL
93+
types/
94+
db.ts # shared row-shape types for lib/db.ts (RepoRow, LeaderboardRow, …)
9095
package-lookup.ts # shared registry → repo lookup (used by /api/package + /package page)
9196
db.ts # better-sqlite3 schema + queries
92-
version.ts # APP_NAME, APP_VERSION, IS_PRE_RELEASE, APP_URL, APP_DESCRIPTION, REPO_URL, SIBLING_VERSION, ACTION_REPO_URL, ACTION_USES, SKILL_REPO_URL, SKILL_INSTALL_CMD
97+
version.ts # APP_NAME, APP_VERSION, IS_PRE_RELEASE, APP_URL, APP_DESCRIPTION, REPO_URL, SIBLING_VERSION, ACTION_REPO_URL, ACTION_USES, SKILL_REPO_URL, SKILL_INSTALL_CMD, OG_DEFAULTS, TWITTER_DEFAULTS (spread into per-page openGraph / twitter — Next.js shallow-merges these objects so defaults must be re-spread on every page)
9398
changelog.ts # typed ChangelogEntry[]
9499
roadmap.ts # typed RoadmapVersion[]
95100
skill-content.ts # SKILL_FAQ + SCORE_BANDS + hook snippets — content for /skill page
@@ -108,7 +113,7 @@ tasks/
108113
0.3.0/ # released — embeddable scores + broader coverage (badge, more agents, alternatives, package lookup)
109114
0.4.0/ # released — credible scores + discoverability (docs-cited rationales + agent-specific signals + About/llms.txt/OG)
110115
0.5.0/ # released — quick wins (PR score-diff action + agent skill)
111-
0.6.0/ # planned — auto-refresh + smarter matching (webhook rescoring + alternatives v2)
116+
0.6.0/ # released — auto-refresh (scheduled rescoring)
112117
0.7.0/ # planned — maintainer ownership + at-scale discovery (OAuth opt-out + package overlay at scale)
113118
1.0.0/ # planned — production cut (Postgres + at-scale indexing + benchmark harness)
114119
.claude/

CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ bun run dev # http://localhost:3000
1414
bun run test # unit tests (node --test + tsx) — requires Node ≥20.9.0
1515
```
1616

17+
> **About `data/rank.db`** — a GitHub Actions cron (`.github/workflows/scheduled-rescore.yml`) re-runs `bun run seed` every six hours and commits the refreshed database to `main`. If your branch touches `scripts/seed-list.ts` and you also commit a re-seeded `rank.db`, you may hit a merge conflict against a cron commit. Easiest resolution: rebase, `git checkout --theirs -- data/rank.db`, and re-run `bun run seed` before pushing.
18+
1719
## Branch naming
1820

1921
Lowercase, kebab-case, prefixed by intent:
@@ -121,7 +123,7 @@ A PR is ready to merge when:
121123

122124
## Security
123125

124-
See the "Security / threat surface" section of [AGENTS.md](./AGENTS.md). For vulnerability reports that shouldn't be public, email hsnice16@gmail.com rather than opening an issue.
126+
See the "Security / threat surface" section of [AGENTS.md](./AGENTS.md). For vulnerability reports that shouldn't be public, email <hsnice16@gmail.com> rather than opening an issue.
125127

126128
## Code of conduct
127129

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Agent Friendly Code
22

3-
[![Release](https://img.shields.io/badge/release-0.5.0-blue?style=flat-square)](./lib/changelog.ts)
3+
[![Release](https://img.shields.io/badge/release-0.6.0-blue?style=flat-square)](./lib/changelog.ts)
44
[![License: MIT](https://img.shields.io/badge/license-MIT-green?style=flat-square)](./LICENSE)
55
[![Next.js 16](https://img.shields.io/badge/Next.js-16-black?style=flat-square)](https://nextjs.org)
66
[![Node ≥20.9](https://img.shields.io/badge/node-%E2%89%A520.9-43853d?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
@@ -9,7 +9,7 @@
99

1010
**A public dashboard that ranks open-source repos by how friendly they are for AI coding agents — per model.**
1111

12-
Next.js 16 + SQLite (`better-sqlite3`), styled with Tailwind CSS 4. Spans GitHub, GitLab, and Bitbucket out of the box. Current release: **0.5.0**.
12+
Next.js 16 + SQLite (`better-sqlite3`), styled with Tailwind CSS 4. Spans GitHub, GitLab, and Bitbucket out of the box. Current release: **0.6.0**.
1313

1414
![Agent Friendly Code — leaderboard](./public/demo/light.png)
1515

@@ -64,7 +64,7 @@ Not pretending the idea is free of risk:
6464
- **Factory.ai is already in this space.** Differentiation has to stay sharp.
6565
- **Public-shaming risk.** Ranking #47,823 without consent invites angry maintainers. Planned via `tasks/0.7.0/01-opt-out-claim-flow.md`.
6666
- **Score gaming.** Once public, people add boilerplate `AGENTS.md` to pass the rubric without being useful. Dynamic (actually-run-an-agent) checks are the counter — see benchmark harness.
67-
- **Freshness.** Scores decay with every push. Webhook-driven rescoring is roadmap.
67+
- **Freshness.** Scores decay with every push. A 6-hourly GitHub Actions cron rescores the curated set; webhook-driven sub-minute refresh is deferred until the claim flow lands in 0.7.0.
6868

6969
See `/methodology` in the running app for a candid walkthrough of what's measured today and what isn't.
7070

@@ -110,7 +110,7 @@ Run the unit tests with `bun run test` (uses `node --test` + `tsx`; requires Nod
110110

111111
## Versioning
112112

113-
`lib/version.ts` and `package.json` carry the current release number (currently **0.5.0**). Bumps happen only when we actually cut a release — never when merging intermediate work. The version pill in the header surfaces the number directly; `/changelog` lists what each release shipped.
113+
`lib/version.ts` and `package.json` carry the current release number (currently **0.6.0**). Bumps happen only when we actually cut a release — never when merging intermediate work. The version pill in the header surfaces the number directly; `/changelog` lists what each release shipped.
114114

115115
## Stack & rationale
116116

@@ -200,7 +200,6 @@ See `/roadmap` in the running app or the per-version `tasks/` folders for the fu
200200

201201
Versions are sequenced cheap-first so the highest-impact small additions don't get gated on heavy infra:
202202

203-
- **0.6.0 — auto-refresh + smarter matching**: webhook-driven rescoring (keep scores fresh on every push) + alternatives via README embeddings (cross-language matches the v0.3.0 SQL heuristic misses).
204203
- **0.7.0 — maintainer ownership + at-scale discovery**: OAuth opt-out / claim flow for maintainers + at-scale package overlay (per-registry leaderboards + userscript that renders the badge inline on npmjs.com / PyPI / crates.io).
205204
- **1.0.0 — production cut**: Postgres migration for concurrent writers + auto-discovered crawl (target 10k repos) + benchmark harness that derives per-model weights from measured agent success. From here on, breaking API changes require a MAJOR bump.
206205

app/about/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import Link from "next/link";
44
import { BreadcrumbJsonLd } from "@/components/BreadcrumbJsonLd";
55
import { ExternalLink } from "@/components/ExternalLink";
66
import { Panel, PanelHeading } from "@/components/Panel";
7-
import { APP_NAME, APP_URL, REPO_URL } from "@/lib/version";
7+
import { APP_NAME, APP_URL, OG_DEFAULTS, REPO_URL, TWITTER_DEFAULTS } from "@/lib/version";
88

99
export const metadata: Metadata = {
1010
title: "About",
1111
alternates: { canonical: "/about" },
12-
twitter: { title: `About — ${APP_NAME}` },
13-
openGraph: { title: `About — ${APP_NAME}`, url: "/about", type: "article" },
12+
twitter: { ...TWITTER_DEFAULTS, title: `About — ${APP_NAME}` },
13+
openGraph: { ...OG_DEFAULTS, title: `About — ${APP_NAME}`, url: "/about", type: "article" },
1414
description: `Who built ${APP_NAME}, why it exists, and what it isn't. Independent, MIT-licensed, no affiliation with any AI agent vendor.`,
1515
};
1616

app/action/page.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ import type { Metadata } from "next";
33
import { ActionEmbed } from "@/components/ActionEmbed";
44
import { ExternalLink } from "@/components/ExternalLink";
55
import { Panel, PanelHeading } from "@/components/Panel";
6-
import { ACTION_REPO_URL, ACTION_USES, APP_KEYWORDS, APP_NAME, APP_URL } from "@/lib/version";
6+
import {
7+
ACTION_REPO_URL,
8+
ACTION_USES,
9+
APP_KEYWORDS,
10+
APP_NAME,
11+
APP_URL,
12+
OG_DEFAULTS,
13+
TWITTER_DEFAULTS,
14+
} from "@/lib/version";
715

816
const PAGE_TITLE = "Agent Friendly Action — PR-diff GitHub Action for AI agent-friendliness";
917
const PAGE_DESCRIPTION =
@@ -27,8 +35,8 @@ export const metadata: Metadata = {
2735
keywords: PAGE_KEYWORDS,
2836
description: PAGE_DESCRIPTION,
2937
alternates: { canonical: "/action" },
30-
twitter: { title: PAGE_TITLE, description: PAGE_DESCRIPTION },
31-
openGraph: { title: PAGE_TITLE, description: PAGE_DESCRIPTION, url: "/action", type: "article" },
38+
twitter: { ...TWITTER_DEFAULTS, title: PAGE_TITLE, description: PAGE_DESCRIPTION },
39+
openGraph: { ...OG_DEFAULTS, title: PAGE_TITLE, description: PAGE_DESCRIPTION, url: "/action", type: "article" },
3240
};
3341

3442
const FAQ = [

app/changelog/page.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import Link from "next/link";
44
import { BreadcrumbJsonLd } from "@/components/BreadcrumbJsonLd";
55
import { Panel } from "@/components/Panel";
66
import { CHANGELOG } from "@/lib/changelog";
7+
import { OG_DEFAULTS, TWITTER_DEFAULTS } from "@/lib/version";
78

89
export const metadata: Metadata = {
910
title: "Changelog",
10-
twitter: { title: "Changelog" },
1111
alternates: { canonical: "/changelog" },
12-
openGraph: { title: "Changelog", url: "/changelog", type: "article" },
12+
twitter: { ...TWITTER_DEFAULTS, title: "Changelog" },
13+
openGraph: { ...OG_DEFAULTS, title: "Changelog", url: "/changelog", type: "article" },
1314
description:
1415
"What's shipped in each release of Agent Friendly Code — user-facing capabilities, not internal churn. Every bullet corresponds to a roadmap item that landed.",
1516
};

app/layout.tsx

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import { BackToTop } from "@/components/BackToTop";
66
import { GoogleAnalytics } from "@/components/GoogleAnalytics";
77
import { MobileNav } from "@/components/MobileNav";
88
import { VersionPill } from "@/components/VersionPill";
9-
import { APP_DESCRIPTION, APP_KEYWORDS, APP_NAME, APP_URL, REPO_URL } from "@/lib/version";
10-
11-
const OG_IMAGE = {
12-
width: 1200,
13-
height: 630,
14-
url: "/demo/light.png",
15-
alt: `${APP_NAME} — public leaderboard`,
16-
};
9+
import {
10+
APP_DESCRIPTION,
11+
APP_KEYWORDS,
12+
APP_NAME,
13+
APP_URL,
14+
OG_DEFAULTS,
15+
REPO_URL,
16+
TWITTER_DEFAULTS,
17+
} from "@/lib/version";
1718

1819
export const metadata: Metadata = {
1920
keywords: APP_KEYWORDS,
@@ -24,22 +25,29 @@ export const metadata: Metadata = {
2425
authors: [{ name: "Himanshu Singh", url: REPO_URL }],
2526
title: { default: APP_NAME, template: `%s · ${APP_NAME}` },
2627
openGraph: {
28+
...OG_DEFAULTS,
2729
url: "/",
28-
locale: "en_US",
2930
title: APP_NAME,
3031
type: "website",
31-
images: [OG_IMAGE],
32-
siteName: APP_NAME,
3332
description: APP_DESCRIPTION,
3433
},
3534
twitter: {
35+
...TWITTER_DEFAULTS,
3636
title: APP_NAME,
37-
images: [OG_IMAGE.url],
38-
card: "summary_large_image",
3937
description: APP_DESCRIPTION,
4038
},
4139
alternates: { canonical: "/" },
42-
robots: { index: true, follow: true },
40+
robots: {
41+
index: true,
42+
follow: true,
43+
googleBot: {
44+
index: true,
45+
follow: true,
46+
"max-snippet": -1,
47+
"max-video-preview": -1,
48+
"max-image-preview": "large",
49+
},
50+
},
4351
other: { "google-adsense-account": "ca-pub-8901860576820221" },
4452
};
4553

app/methodology/page.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import { ExternalLink } from "@/components/ExternalLink";
66
import { Panel, PanelHeading } from "@/components/Panel";
77
import { SIGNALS } from "@/lib/scoring/signals";
88
import { MODELS } from "@/lib/scoring/weights";
9+
import { OG_DEFAULTS, TWITTER_DEFAULTS } from "@/lib/version";
910

1011
export const metadata: Metadata = {
1112
title: "Methodology",
12-
twitter: { title: "Methodology" },
1313
alternates: { canonical: "/methodology" },
14-
openGraph: { title: "Methodology", url: "/methodology", type: "article" },
14+
twitter: { ...TWITTER_DEFAULTS, title: "Methodology" },
15+
openGraph: { ...OG_DEFAULTS, title: "Methodology", url: "/methodology", type: "article" },
1516
description:
1617
"How scores are computed today: the signals checked, the per-model weight profiles, the scoring formula, and what the static-heuristic approach deliberately doesn't measure yet.",
1718
};
@@ -47,7 +48,7 @@ const FAQ = [
4748
},
4849
{
4950
q: "How often is the data refreshed?",
50-
a: "Manually for nowrepositories are re-scored when the seed list changes or the rubric is updated. Webhook-driven rescoring on every push is planned for v0.6.0.",
51+
a: "Every six hoursa GitHub Actions cron runs the full scorer over the curated seed list and commits the refreshed database to the repo, which auto-deploys. Repositories are also re-scored whenever the seed list changes or the rubric is updated.",
5152
},
5253
{
5354
q: "Which forges are supported?",

0 commit comments

Comments
 (0)