Repository navigation
check:platform-checklist is red on main again — four coverage kinds UNCLASSIFIED (batch_endpoints, crud_endpoints, metadata_endpoints, route_generation) #14961
Description
Activity
- addedbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Sep 4, 2026 Triage (R+146): lands in
docs/qa/platform-checklist/coverage.jsonplus the checklist items ⇒domain:devx. GradedBug·priority:p2.Bug: a gate is red onmain, and the card proved it is not the finding PR's doing rather than asserting it — theca3fd4b1version of the script was written to a sibling path in the same tree and run there, and its four findingsdiffempty against the branch's. The gate's own--self-testis green at 141 assertions.priority:p2— red onmain, and the third recurrence of the same shape (#11421manifest, #7347 theqaledger, now four kinds at once). ⛔ Not p1:.github/workflows/lint.ymlstates this gate is validated by maintainer action and is deliberately not CI-wired, so nothing is blocked and no other lane is paying for it.⚠️ That is also why it went unseen, and it is the standing subject of decision card #11730 — "check:platform-checklist has no reporting channel". ⛔ This card is the concrete instance onmaintoday, ⛔ not a re-raise of the channel question. Fixing the four kinds does not close #11730, and #11730 landing would not fix these four.⭐ The instance stream being real, with different kinds each time, is itself the argument for #11730: three recurrences means the population drifts faster than a maintainer-triggered run catches it.
What is owed
For each of
batch_endpoints,crud_endpoints,metadata_endpoints,route_generation: either checklist items or a waiver with a stated reason incoverage.json.⚠️ The choice is checklist-authoring judgement, ⛔ not a mechanical edit — which is why this is a card and not a rider. A waiver with no reason, or items that exist only to clear the count, reproduce the defect with a green gate. ⇒ The repo ships thechecklist-authorskill for exactly this work; use it rather than hand-rolling the five-angle sweep.⚠️ Re-run the gate on today'sorigin/mainbefore starting: the reading is fromca3fd4b1(2026-09-03) and the four kinds may have moved.
Generated by Claude Code
Claim: PM seat
domain:devx @ objectstack(#6023), sessionsession_012zGPuVVX3deAx9LdjK8jCk, dispatching to anos-devsubagent on branchclaude/issue-14961-platform-checklist-four-rest-kinds. P2 Bug, M (content). Scope: for each ofbatch_endpoints,crud_endpoints,metadata_endpoints,route_generation— checklist items authored with thechecklist-authorfive-angle sweep against the capability's liveness ledger, or a waiver with a stated reason indocs/qa/platform-checklist/coverage.json;pnpm check:platform-checklistexit 0 afterwards, self-test 141 unchanged. ⛔ Not the channel question (#11730 stays a maintainer decision;lint.ymlwiring untouched). #15167 is the same instance filed earlier and is closed as its duplicate.docs/qa/**is not a governed surface. Hot-file: the only open PR touchingdocs/qa/platform-checklist/**is draft #15395 (another lane,areas/records-forms.json+4/−4 — a different area file, notcoverage.json); no overlap with the four REST kinds. Assignee field was empty at the read immediately before this write.
Generated by Claude Code
os-dev-report
{
"issue": 14961,
"status": "done",
"branch": "claude/issue-14961-platform-checklist-four-rest-kinds",
"pr": "#15541",
"premise_still_valid": true,
"summary": "The premise held — check:platform-checklist was red on origin/main 6f94458 — but the kind set had drifted: the gate reported FIVE UNCLASSIFIED ledgers, not the card's four. realtime_subscription was enrolled the morning of dispatch (commit 368a82e, the SubscriptionSchema liveness enrolment), which the card's own triage anticipated by asking for a re-run on today's main. Clearing only the four named kinds would have left the gate red, so all five are classified. AUTHORED (4 new items in areas/api-backend.json, grounded in packages/rest and packages/spec/src/api/rest-server.zod.ts, not in the ledgers' prose): crud_endpoints (five switches gate six mounts — operations.list also gates POST /:object/query; dataPrefix moves the routes and the /discovery routes.data advertisement together; two tombstones refuse at construction); batch_endpoints (enableBatchEndpoint gates only the per-object door, the cross-object POST /batch is unconditional; all four bulk gates are ANDs with a protocol member; maxBatchSize is the one cap all five doors measure); metadata_endpoints (P1 — prefix moves the surface and its advertisement, the three endpoint switches gate more routes than their declared meaning says, maskObjectFields is the ADR-0106 D8 disclosure gate with six cache carve-outs); route_generation (the one kind with no live property left — authored rather than waived because the refusal-with-a-prescription IS the shipped behaviour, driven at the constructor, the plugin path and tsc, with the two controls the retirement must not break). Each kind also maps the existing items that genuinely drive the mounted routes. WAIVED (1): realtime_subscription — the only capability with nothing to drive. SubscriptionSchema has zero runtime readers (every property dead at a same-day census that declares its method and scope; the shipped in-memory adapter reads RealtimeSubscriptionOptions, a different type), and /discovery advertises realtime with handlerReady:false and no route, which is the open decision on #14646. The waiver reason is written out in coverage.json and names both of its exits (a mounted transport, or the ADR-0049 retirement making the entry an ORPHAN). FOLLOW-UPS.md gains a §10 declaring the sweep degraded-but-honest: scoped to SWEEP.md angle 3 and executed SEQUENTIALLY by one reader (no sub-agent tool in the session), so the authored items stand on their own evidence but the run supports no claim that nothing else is missing. §10 is the first FOLLOW-UPS section to carry symbol anchors, so scripts/checklist-symbol-anchor-baseline.json gains a floor for it at the censused count (2) — additive; lowering a floor stays maintainer-only. areas/records-forms.json untouched (PR #15395 owns it); the one records-forms item needed is referenced by id from coverage.json, which that PR does not edit. skip-changeset applied and read back.",
"tests": "All exit codes captured by redirect BEFORE any pipe. Union re-run on branch head 00b063d (git rev-parse --short HEAD), after the last content edit. (1) BASE 6f94458, node scripts/check-platform-checklist.mjs -> EXIT=1, verdict 'check-platform-checklist: 5 problem(s)' with batch_endpoints / crud_endpoints / metadata_endpoints / realtime_subscription / route_generation each UNCLASSIFIED. (2) BRANCH, pnpm check:platform-checklist -> EXIT=0, verdict line: 'check-platform-checklist: OK — 15 areas, 264 items (264 active); coverage: 35 kinds mapped, 1 waived; traps: 19 documented, 19 in use; provisioning: 5 area recipes, 8 item references resolved (1 area-qualified), 5/5 recipes referenced; meta-URL spelling: 19 call strings scanned against 34 folded spellings; source citations: 20 family files carry no file:line pin; symbol anchors: 624/624 resolved against 306 cited sources, 17 file floors held'. (3) node scripts/check-platform-checklist.mjs --self-test -> EXIT=0, '176 assertions'. NOT 141: 141 was ca3fd4b's count, 176 is what 6f94458 reports, and this PR does not edit the gate script (the diff is 4 files, none of them scripts/check-platform-checklist.mjs). Recorded in FOLLOW-UPS §10e. (4) node scripts/checklist-select.mjs -> EXIT=0 for each new item id, and 'file:packages/rest/src/rest-server.ts -> 16 runnable item(s)' lists all four new items, so the source citations wire into the runner. (5) node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> EXIT=0, changeset derived by the tool itself (4 paths), 19 commands. ALL 19 EXIT=0. check:platform-checklist is NOT among them — it is not CI-wired, which is #11730's subject. First pass 7 of the 19 answered EXIT=3 / ERR_MODULE_NOT_FOUND on a fresh worktree = NOT MEASURED, never recorded as failures: all were the missing pnpm install, and @objectstack/formula plus @objectstack/lint additionally needed building (both under the shared verify lock, OS_VERIFY_LOCK_SLOT=issue-14961; one attempt returned 99 = did not get the lock, the interval was spent on the commit, then the same slot resumed its place). (6) pnpm check:nul-bytes -> EXIT=0, 'check-nul-bytes: OK (scanned 7518 text file(s) ... no raw ASCII control bytes)'. (7) The 6 artifact-roster gates the derivation flags as unreadable-from-silence (their allowlists live under scripts/, which one diff path is in) were run, not assumed: check-published-list-mirrors + its --self-test, check:console-injection, check:engine-double-contract, check:i18n-stale-fill all EXIT=0. check:published-readme-exports EXIT=1 and is NOT MEASURED by its own verdict line — '160 package(s) are not built, so this run measured nothing there' — with a green --self-test and zero content findings; it needs a whole-repo build and this diff touches no README and no package. Left to CI. (8) pnpm lint is NOT in the derived family for these paths, so it is not owed. Two derivation caveats recorded rather than hidden: dispatch-gates warns the tree is 3 commits behind origin/main (this branch is based on 6f94458; the two files that moved are unrelated durability gates, neither matched by these paths), and 16 families 'apply once this card's changeset exists' — there is deliberately no changeset. No ablation was run: this is a docs/QA ledger change with no code path to mutate; the before/after pair on the gate is the measurement.",
"mcp_calls": "0 — the whole run used the REST API over $GH_TOKEN (probe: GET /issues/14961 -> 200), never an MCP GitHub tool; /search/issues was not needed because the dedup ran over the full paginated open-issue list (571 open issues across 7 pages) plus a local grep",
"open_questions": [
{
"question": "realtime_subscription is the first waiver since the checklist reached zero waivers, in a file whose own SWEEP.md records 6 of 6 waivers ever written turning out stale. Is a waiver acceptable here, or does the maintainer want the kind carried differently until #14646 is decided?",
"options": [
"A — keep the waiver as written: it claims the READER is missing (measured by a census that declares its method and scope, plus the /discovery reading), not 'no runtime behaviour', which is the claim all six stale waivers made; it names both exits and asks the next sweep to re-audit it",
"B — author an absence-asserting item instead (an expected-fail probe in the ledger's existing style), so the kind is 'mapped' and a run records the absence rather than a waiver claiming it",
"C — leave route_generation-style authoring aside and block the card on #14646 first, so the kind is classified once the transport question is answered"
],
"recommendation": "A, because option B would put an item in the ledger whose every clause asserts that nothing happens — coverage by construction, which is exactly the 'items that exist only to clear the count' the triage warned against — and C would leave the gate red on main for the length of a decision card that has been open since before this one was filed. A keeps the debt visible, dated, and re-auditable, which is what a waiver is for."
}
],
"out_of_scope_findings": [
"filed as #15542: metadata.endpoints.items gates four routes — the POST /meta/_migrate-stored write door and the /meta/diagnostics sweep among them — while its declared meaning names only the type listing; endpoints.item is the same shape (four mounts incl. the book tree)",
"filed as #15543: no shipped boot path authors RestServerConfig at all — os serve constructs the plugin with a fixed config (two api keys from CLI flags) and the dev plugin passes none, so every live crud/metadata/batch key is embedder-only; sharpens the already-open #14879",
"filed as #15544: the MOUNT half of every RestServerConfig switch is unpinned — the tests assert what a switch normalizes to and the cap's effect, and nothing asserts that a false switch removes its route from RestServer#getRoutes()"
]
}
Generated by Claude Code
LANDED — PM seat
domain:devx @ objectstack(#6023), sessionsession_012zGPuVVX3deAx9LdjK8jCk.PR #15541 merged 2026-09-04T20:57:58Z (merge-queue;
merged: true, main70c939953). This gate is not CI-wired (#11730), so the landing probe IS the measurement: on this seat's checkout of the re-fetched main,node scripts/check-platform-checklist.mjsexits 0 —check-platform-checklist: OK — 15 areas, 264 items (264 active); coverage: 35 kinds mapped, 1 waived; traps: 19 documented, 19 in use; provisioning: 5 area recipes, 8 item references resolved (1 are— against
5 problem(s)/ exit 1 before the merge.Fixesclosed this card on merge;pm:dispatchedand the assignee are stripped.mainis green on this gate again; the third recurrence is the standing argument on #11730 (untouched).
Generated by Claude Code
Found while working #13800 (verdict handshake, PR #14960). Filed unassigned; not fixed there, and out of that card's scope.
The reading
On
origin/mainatca3fd4b1, in a clean worktree afterpnpm install:Not caused by that PR, and proven so rather than asserted. The
ca3fd4b1version ofscripts/check-platform-checklist.mjswas written to a sibling path in the same tree and run there; its four findings are byte-identical to the branch's (diffof the two finding sets is empty). The gate's own--self-testis green (141 assertions).Why nobody saw it
.github/workflows/lint.ymlstates the gate is validated "by MAINTAINER action" and is deliberately not CI-wired. That is the standing subject of the open decision card #11730 — this issue is the concrete instance sitting onmaintoday, not a re-raise of the channel question.Prior instances of the same shape, both closed after being acted on: #11421 (
manifestUNCLASSIFIED) and #7347 (theqaliveness ledger). This is the third recurrence, so the instance stream is real and the kinds differ each time.What is owed
For each of the four kinds, either checklist items or a waiver with a stated reason in
docs/qa/platform-checklist/coverage.json. Deciding which is a checklist-authoring judgment, not a mechanical edit, which is why this is a card rather than a rider on #14960.Generated by Claude Code