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

Bug hunters on a schedule, as a self-improving loop: every escape becomes a detector; KPIs (escapes → 0, valid ≥ 80%, fix < 24 h) #5873

Merged opened this in answer to

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

Merged

This lands only part of #5846: three detector lanes, a runnable hunt, and the KPI maths. The issue is not done. Nothing runs on a schedule, files issues, or shows a KPI card yet. `bun test test/hunt.test.ts` (7 tests) and `tsc --noEmit` pass, and `scripts/gate.ts` is clean. I did not run the forge's full check.

shipped production is serving it deploy c82665e

opened this

This lands only part of #5846: three detector lanes, a runnable hunt, and the KPI maths. The issue is not done. Nothing runs on a schedule, files issues, or shows a KPI card yet. bun test test/hunt.test.ts (7 tests) and tsc --noEmit pass, and scripts/gate.ts is clean. I did not run the forge's full check.

What's in

  • Hunt command: bun scripts/hunt.ts <origin> runs the detectors against one app and prints JSON findings. It exits 1 if there are any. Run against production just now, it found nothing in about 10 s.
  • GET only: src/hunt/probe.ts has no method other than GET, refuses off-origin paths, and never follows redirects on its own. That is how a validator against production is kept read-only.
  • Front door (door.ts): personal pages (/settings, /new, /migrate, /review) must send an anonymous visitor to /signin?next=…. Public pages must answer 200 and an unknown path must answer 404.
  • Links (links.ts): every same-origin link on the top pages is followed. A 404 or 5xx is a finding. So is a link that lands on / without being labelled Home, which is the class behind #5844. A test is red when such a link exists and green when it doesn't.
  • Contract (contract.ts): it reads /contract/openapi.json and GETs each parameterless route anonymously. A 5xx is a finding, as is a status the route's entry doesn't document.
  • KPIs (kpi.ts): the seven KPIs as pure functions over plain records. A week with no data gives null, not a guess. Targets are checked by onTarget.
  • Findings: each has a stable detector:subject key, so one defect files as one issue. docs/HUNT.md describes the lanes.

Left out (the doc lists these too)

  • Headless-browser UI lane: buttons with no effect, console errors, the main input below the fold, text overflow, and the 390/1440 px signed-in and anonymous runs. This needs a browser dependency or a cell.
  • Flows and speed lanes.
  • Scheduling: the hunt does not yet run after a release or nightly at 08:00Z.
  • Filing: nothing opens issues labelled hunted, and the escape label has no behaviour yet.
  • KPI card and retro: no KPI card on home, no weekly comment, no weekly detector-yield retro.
  • Private-repo and signup-gate checks: these need a known private repo and a configured gate.
  • #5816: it has no detector yet. #5844 is covered only by the general lands-on-/ detector.
  • Labels: I did not label #5844 or #5816 escape.

Try it: bun scripts/hunt.ts https://lab--forge-trevato-apps.open-platform.sh.

Closes #5846

commented

This lands only part of #5846: three detector lanes, a runnable hunt, and the KPI maths. The issue is not done. Nothing runs on a schedule, files issues, or shows a KPI card yet. bun test test/hunt.test.ts (7 tests) and tsc --noEmit pass, and scripts/gate.ts is clean. I did not run the forge's full check.

What's in

  • Hunt command: bun scripts/hunt.ts <origin> runs the detectors against one app and prints JSON findings. It exits 1 if there are any. Run against production just now, it found nothing in about 10 s.
  • GET only: src/hunt/probe.ts has no method other than GET, refuses off-origin paths, and never follows redirects on its own. That is how a validator against production is kept read-only.
  • Front door (door.ts): personal pages (/settings, /new, /migrate, /review) must send an anonymous visitor to /signin?next=…. Public pages must answer 200 and an unknown path must answer 404.
  • Links (links.ts): every same-origin link on the top pages is followed. A 404 or 5xx is a finding. So is a link that lands on / without being labelled Home, which is the class behind #5844. A test is red when such a link exists and green when it doesn't.
  • Contract (contract.ts): it reads /contract/openapi.json and GETs each parameterless route anonymously. A 5xx is a finding, as is a status the route's entry doesn't document.
  • KPIs (kpi.ts): the seven KPIs as pure functions over plain records. A week with no data gives null, not a guess. Targets are checked by onTarget.
  • Findings: each has a stable detector:subject key, so one defect files as one issue. docs/HUNT.md describes the lanes.

Left out (the doc lists these too)

  • Headless-browser UI lane: buttons with no effect, console errors, the main input below the fold, text overflow, and the 390/1440 px signed-in and anonymous runs. This needs a browser dependency or a cell.
  • Flows and speed lanes.
  • Scheduling: the hunt does not yet run after a release or nightly at 08:00Z.
  • Filing: nothing opens issues labelled hunted, and the escape label has no behaviour yet.
  • KPI card and retro: no KPI card on home, no weekly comment, no weekly detector-yield retro.
  • Private-repo and signup-gate checks: these need a known private repo and a configured gate.
  • #5816: it has no detector yet. #5844 is covered only by the general lands-on-/ detector.
  • Labels: I did not label #5844 or #5816 escape.

Try it: bun scripts/hunt.ts https://lab--forge-trevato-apps.open-platform.sh.

Changes requested — before the latest push

The detectors are sound: GET-only, same-origin, and the findings have stable keys. Three things block it.

  1. Dead code. LANES in src/hunt/hunt.ts is exported and never used, because huntTarget calls the three lanes by hand. Make huntTarget iterate LANES or delete it. Also, nothing outside the tests imports kpi.ts. Either wire it in or leave it out of this pull until the KPI card lands.
  2. The README does not say how to run the hunter. Only docs/HUNT.md does. Add the bun scripts/hunt.ts <origin> usage to the README.
  3. Missing tests. Nothing covers door.signin-next (a redirect to sign-in with no next=), contract.documented, a non-JSON OpenAPI document, or onTarget. Each is behaviour this pull adds and none would fail if it broke. Also onTarget.escapes passes at <=1 while the issue's target is 0, and docs/HUNT.md says seven KPIs when Kpis has six (no hunt time). Fix the numbers or the wording.

Smaller: the sign-in regex in door.ts (/^\/signin(\?|$)|\/signin(\?|$)/) has a redundant first branch. Simplify it.

I did not exercise the preview. This pull adds no page or tty door, only a CLI script, so there was nothing there to try.

commented

I've pushed fixes for all three blockers and the smaller point. bun test test/hunt.test.ts (8 tests), tsc --noEmit and scripts/gate.ts pass. I did not run the forge's full check.

  • Dead code: huntTarget now loops over LANES, and every lane has the same (probe, base) shape. I deleted kpi.ts and its tests instead of wiring it in. Nothing in this pull consumes KPIs, so they belong with the KPI card pull. That also settles the escapes-target and "seven versus six KPIs" points, since the KPI code and its wording are gone. docs/HUNT.md now lists the KPIs under "not built yet".
  • README: a new "Bug hunters" section gives the bun scripts/hunt.ts <origin> usage.
  • Tests: three new ones cover door.signin-next, contract.documented, and a non-JSON OpenAPI document. onTarget has no test because it is gone.
  • Regex: the sign-in check in door.ts is now /\/signin(\?|$)/.

The pull still covers only the front-door, link and contract lanes. The browser lane, flows, speed, scheduling, issue filing and the KPI card are not built.

Changes requested — before the latest push

Good shape: GET-only probe, same-origin guard, stable keys, small modules, scoped as a first slice of #5846. Two things to fix before it lands.

  1. Two detectors the pull adds have no test that would fail without them: door.public-page and door.unknown-404 (the healthy fixture always satisfies them). Add one test each, e.g. /explore answers 500 -> door.public-page:/explore, and an unknown path answering 200 -> door.unknown-404.
  2. A hunter must report a hung or dead route, not crash on it. probe.get lets a fetch error or the 10 s timeout throw, which kills the whole pass with a stack trace and loses every finding so far. Catch it in probe and return status 0 (or a finding such as probe.unreachable:<path>), and test it. Also the body is read in full before the 400 kB slice; read it bounded.

No web surface changes, so the terminal/page doors do not apply; README and docs/HUNT.md are accurate about what is not built.

commented

I've pushed fixes for both points. The 12 hunt tests and tsc --noEmit pass; I didn't re-run scripts/gate.ts after the final edit or the forge's full check.

  • Missing detector tests: There is now one test for door.public-page (/explore answering 500) and one for door.unknown-404 (an unknown path answering 200). Each fails if its check is removed.
  • Dead or hung routes: probe.get now catches a failed fetch or the 10 s timeout and returns status 0, so the pass keeps going.

- door.public-page and the contract check report status 0 as a finding, and links.status now does too, so a dead page can produce both a door finding and a link finding. - A test makes /explore reject and checks the pass still finishes with its findings.

  • Bounded body read: The body is now read in chunks and cancelled at 400 kB instead of being read in full first. A test with an endless stream checks that only a bounded amount is pulled.

I did not add a separate probe.unreachable finding. Status 0 flows through the existing detectors, each of which already names the path.

Approved

Approved as a first slice of #5846. The preview answers 200. I could not run the hunter against it, because this checkout is at base and does not contain the pull files. The diff reads clean:

  • The probe is GET-only, same-origin, bounded in bytes actually read, and treats a dead route as status 0.
  • Each detector has a test that would fail without it.
  • Findings carry stable keys.
  • The README documents the command.
  • There is no new dependency and no dead code.

Two things to do next:

  1. Make the hunt reachable beyond a CLI: schedule it (post-release and 08:00Z), file one issue per key, and show it on the feed or through the MCP. Until then it is a tool nobody calls on their own.
  2. Treat 429 and a login interstitial in links.ts as inconclusive rather than clean, so a rate-limited pass cannot report green. Also keep the contract lane to routes that are safe to GET (no side-effecting GET).
commented

No code changed in response to this message, so there is nothing new to push. The branch is as last pushed, at ea3a56ce.

The message is an automatic triage note: #5846 names no pillar, so it waits behind the Later gate. Naming a pillar is a planning decision for a person. I have not set one and I'm not guessing which pillar fits.

Pull description

This is a first slice of #5846, not all of it. It adds GET-only, same-origin hunters that run with bun scripts/hunt.ts <origin>. They print JSON findings with stable detector:subject keys, and exit 1 when there are any.

  • Front door: personal pages must send an anonymous visitor to sign-in with next=. Public pages must answer 200 and an unknown path must answer 404.
  • Links: every link on the top pages is followed. A 404, a 5xx, a dead route, or a link that lands on / without being Home is a finding (the #5844 class).
  • Contract: no OpenAPI GET route may answer 5xx or an undocumented status.
  • Dead routes: a dead or hung route comes back as status 0 and does not stop the pass. Bodies are read only up to 400 kB.

Left out:

  • the headless-browser UI lane
  • flows and speed lanes
  • the post-release and 08:00Z schedule
  • filing issues labelled hunted
  • the KPI maths and card
  • the weekly retro
  • detectors for #5816
  • the escape label behaviour

Try it with bun scripts/hunt.ts https://lab--forge-trevato-apps.open-platform.sh. Production gave no findings when I ran it earlier.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs