docs: correct drift between the docs and the running system - #870
Conversation
Each of these was verified against the code rather than taken from a report: - README said there is no webhook receiver. There is one, at /api/pr-followup/webhook; issue-label events are still not consumed. - README said /api/sync does not require DISPATCH_AGENT_TOKEN. It calls authorizeRequest like the other agent endpoints. - README and hosted-groomer said Dispatch runs no in-process background loop and that a scheduler was "intentionally avoided". src/lib/scheduler.ts runs five jobs: sync, groomer, pr-followup, prune-closed, reconcile. - PR_FOLLOWUP_BOT_IDENTITIES was documented as a JSON object with an example. The code splits on commas, so following the docs produced garbage. - The env vars are DISPATCH_LANE_CONFIG_JSON and DISPATCH_GROOMER_INTERVAL_MS, not DISPATCH_LANE_CONFIG and DISPATCH_GROOMER_INTERVAL_SECONDS. - The default lanes are `default` and `backlog`, not normal/escalated/backlog. - The status label list omitted status/blocked entirely. Deliberately NOT changed: the ~29 `lane=normal` references. An audit flagged them as returning HTTP 400, which is true of the shipped defaults but not of this deployment, whose laneAliases maps normal -> local. Added one note saying so rather than rewriting working examples to match a config we do not run. Claude-Session: https://claude.ai/code/session_01YSuDvZq9ncvyX85Uzx3cQh
There was a problem hiding this comment.
AI Automated Review
Full PR review.
Analysis engine: MiniMax-M3@https://litellm.jory.dev/v1 (anthropic) — escalated (fast_low_confidence)
Recommendation: approve
This PR is a docs-only correction pass that aligns five markdown files with what the code on main actually does. Each change is verifiable against the running repo, the body documents seven concrete drift items with their respective source files, and the Deliberately not changed section explicitly explains the one item the author chose to leave alone (the lane=normal aliases). CI is green across the board (lint, typecheck, build, tests, smoke, migrations, Docker Build ×2, Coverage, Database integration, npm audit), so there is no infra regression hiding in the diff.
Change-by-change findings
AGENTS.md
- Adds a blockquote immediately above the worker loop calling out that
normalis a deployment-specific alias (normal→local) and that the shipped defaults aredefault+backlog. This is consistent withdocs/configurable-lanes.mdand withDISPATCH_LANE_CONFIG_JSONreference in the rest of AGENTS.md. Good. must_check: no mandatory checklist items were emitted for this file, and the standards file does not forbid this kind of inline caveat.
README.md
- Lanes description (Execution Lanes): "two lanes:
defaultandbacklog" andDISPATCH_LANE_CONFIG_JSON. Matchesdocs/configurable-lanes.mdtable and the env-var reference earlier in README. - Status labels: added
status/blockedline including theblockedReasonvs no-reason distinction. The grep evidence showssrc/lib/groomer/selector.ts:49andsrc/lib/groomer/selector.test.ts:295reference issue PR 862 with the parked/recoverable semantics, so the wording matches the code. - Groomer interval var:
DISPATCH_GROOMER_INTERVAL_SECONDS→DISPATCH_GROOMER_INTERVAL_MS, default 600000. AGENTS.md env-var table lists the same name with default 600000, so the docs are now internally consistent. PR_FOLLOWUP_BOT_IDENTITIES: the old docs claimed a JSON-object format thatsrc/lib/pr-followup-ingestion.tsdoes not actually consume. The new description (comma-separated logins, defaultgithub-actions[bot]) matches thesplit(",")behavior the PR body cites. This is the most consequential fix in the PR — operators following the old docs were getting silent misbehavior.- Scheduled Issue Sync Strategy: the framing that cache freshness is owned by the in-process scheduler in
src/lib/scheduler.ts(with heartbeat sync as a secondary path) replaces the prior claim that an internal scheduler is "Phase 1 intentionally avoided." The git history (29c9bdb feat(scheduler): in-app scheduler; internalize scheduled sync) and the reference tosrc/lib/scheduler.tsin the new README support this. The body also notes five jobs (sync, groomer, pr-followup, prune-closed, reconcile); AGENTS.md's env-var table separately mentionsDISPATCH_RECONCILE_*, which is consistent with the scheduler handling reconcile on its own interval. /api/syncauth: corrected to requireDISPATCH_AGENT_TOKENviaauthorizeRequest. Plausible — the body says the route callsauthorizeRequestlike other agent endpoints; the search did not surfacesrc/app/api/sync/route.tsitself, so I cannot independently verify the exact call, but the surrounding PR diff context and the linked "Deliberately not changed" rationale imply this was checked against the source.- Known Limitations: item 6 rewritten from "No webhook receiver for real-time updates" to "Partial webhook coverage" with a pointer at
/api/pr-followup/webhook. Issue-label events remain undocumented as consumed, which matches the diff and the body.
docs/configurable-lanes.md
- Default-lanes table drops
normal/escalatedand replaces them withdefault. Consistent with README and AGENTS.md. - New paragraph under the table:
DISPATCH_LANE_CONFIG_JSON,normal/escalatedare not built in, andlaneAliaseskeeps older stored IDs resolving. This makes the alias pattern discoverable for someone copy-pasting examples. - Two
DISPATCH_LANE_CONFIGreferences →DISPATCH_LANE_CONFIG_JSON(in the example block and the "if not set" sentence). Internally consistent.
docs/hosted-groomer.md
DISPATCH_GROOMER_INTERVAL_SECONDS→DISPATCH_GROOMER_INTERVAL_MSwith default600000, matching the AGENTS.md env-var table.- "Scheduling" section rewritten so the endpoint is driven by the in-process scheduler at
DISPATCH_GROOMER_INTERVAL_MS(default 10 min), while still allowing direct external invocations. Matches AGENTS.md and README.
docs/issue-lane-classification.md
- One rename:
DISPATCH_LANE_CONFIG→DISPATCH_LANE_CONFIG_JSON. Consistent with the rest of the PR.
Standards Compliance
The repository standards file (AGENTS.md excerpt) is the file being modified, so the relevant checks are whether the modifications remain consistent with the file's own conventions:
- "No agent-specific names in generic docs" — the new lane-alias caveat does not name agents. ✅
- "Validate inputs before database operations" / "API routes return appropriate HTTP status codes" — not applicable, docs only.
- "No commit of secrets" — diff is markdown only. ✅
- The standards file itself documents
DISPATCH_GROOMER_INTERVAL_MS(default 600000) andDISPATCH_LANE_CONFIG_JSONin its env-var table; this PR brings README/docs in line with those entries. The PR strengthens compliance with the standards, it does not weaken it.
Tool Harness Findings
The native harness issued no tool calls. CI results are reported as terminal-success across all 11 checks (lint, typecheck, build, tests, smoke, coverage, migrations, Database integration, Docker Build ×2, npm audit). Image-digest provenance shows no image changes — expected for a docs-only PR.
Unknowns or Needs Verification
- The exact auth call inside
src/app/api/sync/route.tswas not directly visible in the diff. The PR body's wording is plausible and consistent with the surrounding AGENTS.md/README guidance, but I cannot independently grep that file from this corpus. Treat as soft-verified via the author's claim and the diff context. - The
DISPATCH_RECONCILE_*family referenced by AGENTS.md is implied by the PR body to be part of the scheduler's five jobs; the exact scheduler job list and interval variables for reconcile were not surfaced by the diff itself, only by the README's rewrite. Low risk because the change is purely narrative, but flagging as a follow-up if reconcile interval naming needs its own doc pass later.
Findings
None of the corrections in this PR contradict what the repository impact scan or the linked git history show. The diff is internally consistent across the five files, removes concrete documented misbehavior (especially the JSON-vs-comma PR_FOLLOWUP_BOT_IDENTITIES discrepancy), and the deliberate decision not to rewrite the lane=normal examples is well-reasoned and disclosed in the PR body. Approving.
Summary
What was wrong
Each verified directly rather than taken from a report:
README.md)src/app/api/pr-followup/webhook/route.tsexists and ingests PR events. Issue-label events are still not consumed./api/synccurrently does not requireDISPATCH_AGENT_TOKEN"authorizeRequest, same as the other agent endpoints.src/lib/scheduler.tsruns five jobs: sync, groomer, pr-followup, prune-closed, reconcile.PR_FOLLOWUP_BOT_IDENTITIESis "a JSON object mapping bot logins to a behaviour label", with a JSON examplesrc/lib/pr-followup-ingestion.ts:41doessplit(","). Following the documented format produced garbage.DISPATCH_LANE_CONFIG/DISPATCH_GROOMER_INTERVAL_SECONDSDISPATCH_LANE_CONFIG_JSONandDISPATCH_GROOMER_INTERVAL_MS.normal,escalated,backlog"defaultandbacklog.status/blockedentirely, including the distinction that a block with ablockedReasonneeds a human while one without is recovered by the groomer (#862).The
PR_FOLLOWUP_BOT_IDENTITIESandDISPATCH_GROOMER_INTERVAL_SECONDSentries are the ones worth noting: both are documented in a form that cannot work, so anyone configuring from the docs gets silent misbehaviour rather than an error.Deliberately not changed
An audit flagged the ~29
lane=normalexamples inAGENTS.mdand the harness docs as returning HTTP 400. That is true of the shipped defaults but not of this deployment, whose liveDISPATCH_LANE_CONFIG_JSONcarrieslaneAliases: {normal: local, escalated: frontier, cloud: local}. Rewriting them would have broken working examples to match a configuration we do not run.Added one note in
AGENTS.mdrecording thatnormalis an alias rather than a built-in lane, so the dependency is visible to anyone copying the examples into a different deployment.Verification
main.