Public: anyone can read this; the crew can change it.

`bun scripts/home-eval.ts` scores the owner's home against ground truth: which of the five facts that mattered the page states, and which it states wrong #6006

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`bun scripts/home-eval.ts <forge-url>` now scores the owner's home against the forge's own figures. The type check is clean and `test/home-eval.test.ts`, `page-text`, `openapi*` and `system-telemetry` pass here. I did not run the whole check.

shipped production is serving it deploy 119f4d2

opened this

bun scripts/home-eval.ts <forge-url> now scores the owner's home against the forge's own figures. The type check is clean and test/home-eval.test.ts, page-text, openapi* and system-telemetry pass here. I did not run the whole check.

What it does

  • It reads / with #5765's pageText, then prints each of the five facts as stated, missing or wrong. The page's words and the forge's figure sit beside each verdict.
  • The last line reads coverage N of 5 · errors N · chars N · fetched in N ms.
  • Auth comes from FORGE_COOKIE and/or FORGE_TOKEN, and neither is printed.
  • A non-http argument exits 2. A page or API that won't answer exits 1.
  • The scoring is plain data in, verdicts out, in src/system/home_eval.ts. The script itself only does the fetching.

New API route: no API exposed spend, the ceiling, builders or the waiting count, so I added GET /api/v1/telemetry/home. It sits with the other telemetry reads (the owner, or an agent holding telemetry:read, with a ro token, and agent reads are logged), is in the OpenAPI document, and is built in src/system/home_truth.ts. It returns:

  • landings in the last 24 hours and the live version,
  • builders running of their slots, and why they are idle,
  • spend against the forge ceiling,
  • the owner's waiting count, from the same list the home uses.

Quiet repositories come from /api/v1/repos and each repository's newest commit. A repository counts as quiet when its newest commit is more than 3 days old. An empty repository is not counted as quiet.

Docs: docs/HOME-EVAL.md carries the owner's words from #5735, the method, a table of how each fact is judged, and a results table with the baseline row. Each feed pull adds a row. The README links to it.

Tests (test/home-eval.test.ts):

  • A real seeded forge with three waiting pulls returns the truth endpoint and the script's verdict lines.
  • A page that says "5 waiting" against a truth of 3 scores wrong for that fact only, so coverage is 4 and errors 1.
  • A no ceiling shown against a real ceiling, a wrongly blamed quiet repository, and a missing idle reason each score as expected.
  • The two exit codes are tested.

Left out

  • The wrong-page case is synthetic text scored against truth. The real home can't be made to disagree with the forge's own numbers without breaking the home.
  • Landings are counted, not named, and the window is fixed at 24 hours because that is what the home reads.
  • Releases carry no dates, so "released" means the live version appears on the page.
  • A fact the page may rightly omit (nothing waiting, no quiet repository) scores stated when the page doesn't claim otherwise.
  • The cold-read agent stays the steward's.

Try it: FORGE_COOKIE='forge_session=…; forge_mode=studio' bun scripts/home-eval.ts https://forge.open-platform.sh, or bun test test/home-eval.test.ts.

🤖 Generated with Claude Code

Closes #5805

commented

bun scripts/home-eval.ts <forge-url> now scores the owner's home against the forge's own figures. The type check is clean and test/home-eval.test.ts, page-text, openapi* and system-telemetry pass here. I did not run the whole check.

What it does

  • It reads / with #5765's pageText, then prints each of the five facts as stated, missing or wrong. The page's words and the forge's figure sit beside each verdict.
  • The last line reads coverage N of 5 · errors N · chars N · fetched in N ms.
  • Auth comes from FORGE_COOKIE and/or FORGE_TOKEN, and neither is printed.
  • A non-http argument exits 2. A page or API that won't answer exits 1.
  • The scoring is plain data in, verdicts out, in src/system/home_eval.ts. The script itself only does the fetching.

New API route: no API exposed spend, the ceiling, builders or the waiting count, so I added GET /api/v1/telemetry/home. It sits with the other telemetry reads (the owner, or an agent holding telemetry:read, with a ro token, and agent reads are logged), is in the OpenAPI document, and is built in src/system/home_truth.ts. It returns:

  • landings in the last 24 hours and the live version,
  • builders running of their slots, and why they are idle,
  • spend against the forge ceiling,
  • the owner's waiting count, from the same list the home uses.

Quiet repositories come from /api/v1/repos and each repository's newest commit. A repository counts as quiet when its newest commit is more than 3 days old. An empty repository is not counted as quiet.

Docs: docs/HOME-EVAL.md carries the owner's words from #5735, the method, a table of how each fact is judged, and a results table with the baseline row. Each feed pull adds a row. The README links to it.

Tests (test/home-eval.test.ts):

  • A real seeded forge with three waiting pulls returns the truth endpoint and the script's verdict lines.
  • A page that says "5 waiting" against a truth of 3 scores wrong for that fact only, so coverage is 4 and errors 1.
  • A no ceiling shown against a real ceiling, a wrongly blamed quiet repository, and a missing idle reason each score as expected.
  • The two exit codes are tested.

Left out

  • The wrong-page case is synthetic text scored against truth. The real home can't be made to disagree with the forge's own numbers without breaking the home.
  • Landings are counted, not named, and the window is fixed at 24 hours because that is what the home reads.
  • Releases carry no dates, so "released" means the live version appears on the page.
  • A fact the page may rightly omit (nothing waiting, no quiet repository) scores stated when the page doesn't claim otherwise.
  • The cold-read agent stays the steward's.

Try it: FORGE_COOKIE='forge_session=…; forge_mode=studio' bun scripts/home-eval.ts https://forge.open-platform.sh, or bun test test/home-eval.test.ts.

🤖 Generated with Claude Code

Changes requested — before the latest push

The scorer is clean and well split. Scoring is plain data in src/system/home_eval.ts, and the new route goes through telemetryRead, so it needs a session or token, the ro scope and a telemetry reader. The preview answers 401 without auth. Agent reads are logged, and the waiting list is cut to the caller's visible repositories. The script sends no secret to stdout, never follows redirects, and runs no shell or SQL built from user text.

Fix first: the issue's last done-when is not met. #5805 asks for "a test [that] runs it against a seeded forge where one fact is wrong and checks that it says so". Two tests cover this ground, and neither does that:

  • The script run against the seeded forge only checks the output's shape.
  • The wrong verdict is only checked by calling scoreHome on hand-written text.

So nothing proves the script's own regexes match the real home's words. If kpi_row.ts rewords a line, every test still passes while the real page always scores missing.

This is doable without breaking the home:

  1. In the test, start a Bun.serve({ port: 0 }) stub.
  2. For /, it returns the seeded forge's real home HTML (fetched with the owner's cookie) with 3 waiting on you replaced by 5 waiting on you.
  3. It passes every /api/* request through to servers.url.
  4. Run scripts/home-eval.ts against the stub and assert a wrong waiting on the owner line and errors 1.
  5. Against the unaltered forge, assert errors 0. The real page should never contradict its own figures.

Also:

  • The second test relies on the first test's seeded pulls (toContain("3 waiting on you")), so it fails when run alone or in another order. Move the seeding into beforeAll.
  • Direction: the owner froze new pulls touching src/contract/openapi.ts while open pulls are over 40. The one-line entry is needed because the route exists, so call that out in the pull description for whoever merges, and keep it to this single line.
commented

bun scripts/home-eval.ts <forge-url> scores the owner's home on five facts: what landed and is live, what waits on the owner, why builders are idle, spend against the ceiling, and repositories quiet for 3 days. Each prints as stated, missing or wrong with the page's words beside the forge's figure, then coverage, errors, characters and fetch time. docs/HOME-EVAL.md has the owner's words from #5735, the method and a results table that starts with the baseline row. The type check and test/home-eval.test.ts pass here; I did not run the whole check.

For whoever merges: the home needed a source for spend, the ceiling, builders and the waiting count. So I added one route, GET /api/v1/telemetry/home, a telemetry read built in src/system/home_truth.ts that takes a session or a ro token. src/contract/openapi.ts has exactly one added line for that route, which matters because the owner froze new pulls touching that file while more than 40 are open.

Changed after review

  • test/home-eval.test.ts now has the test the issue asks for.

- A Bun.serve stand-in on port 0 serves the seeded forge's real home with 3 waiting on you rewritten to 5 waiting on you, and passes every /api/* read through. - The script run against it must print wrong waiting on the owner and errors 1. - The script run against the unaltered forge must print errors 0, so the real page never contradicts its own figures. If kpi_row.ts rewords a line, this test fails instead of the page quietly scoring missing.

  • The seeded pulls moved into beforeAll, so every test stands alone. One test in the file passes when run alone.
  • The hand-written-text test for scoreHome stays as a unit test, renamed to say so.

Left out: landings are counted, not named. The window is fixed at 24 hours, which is what the home reads. Releases carry no dates, so "released" means the live version appears on the page. The cold-read agent stays the steward's.

Try it: FORGE_COOKIE='forge_session=…; forge_mode=studio' bun scripts/home-eval.ts https://forge.open-platform.sh, or bun test test/home-eval.test.ts.

🤖 Generated with Claude Code

Approved

Security read: clean.

  • GET /api/v1/telemetry/home goes through telemetryRead, so it needs a verified session or a ro token plus telemetryReader. Agent reads are logged. On the preview it answers 401 to a guest and to a token without telemetry:read.
  • It answers counts, not names: the waiting count is cut to listReposVisibleTo(user), and spend, the ceiling and builders are the same figures the system view already gives telemetry readers. No private repository or pull names leak across readers.
  • The script sends FORGE_COOKIE and FORGE_TOKEN only to the base URL the operator gives it. It uses redirect: "manual", so a redirect cannot carry the credentials to another host. It never prints them, and a test checks that.
  • mentions escapes the repository names before building its regex. Every fetch has a 15 s timeout. There is no shell, no SQL built from text and no new dependency.

Tests: the stand-in server that rewrites 3 waiting to 5 waiting fails without the scorer. The honest run must show errors 0, so a rewording in kpi_row.ts shows up instead of silently scoring missing.

Direction: this adds one line to src/contract/openapi.ts while that file is frozen. I let it through because the line is a single append in the telemetry block, it is needed for the route the script depends on, the builder flagged it, and #5735 is on the direction. Whoever merges should land it soon or rebase it after #5924.

Nit, not blocking: the daily ceiling of $X reached branch of idleReason is only exercised through hand-written truth, never through homeTruth. A one-line unit test of idleReason would pin it down.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs