Skip to content

check:platform-checklist is red on main again — four coverage kinds UNCLASSIFIED (batch_endpoints, crud_endpoints, metadata_endpoints, route_generation) #14961

Description

@claude

Found while working #13800 (verdict handshake, PR #14960). Filed unassigned; not fixed there, and out of that card's scope.

The reading

On origin/main at ca3fd4b1, in a clean worktree after pnpm install:

pnpm check:platform-checklist   -> EXIT=1
check-platform-checklist: 4 problem(s)
  x coverage.json - batch_endpoints: UNCLASSIFIED - the platform has this capability (liveness ledger exists) but the checklist neither tests nor waives it.
  x coverage.json - crud_endpoints: UNCLASSIFIED
  x coverage.json - metadata_endpoints: UNCLASSIFIED
  x coverage.json - route_generation: UNCLASSIFIED

Not caused by that PR, and proven so rather than asserted. The ca3fd4b1 version of scripts/check-platform-checklist.mjs was written to a sibling path in the same tree and run there; its four findings are byte-identical to the branch's (diff of the two finding sets is empty). The gate's own --self-test is green (141 assertions).

Why nobody saw it

.github/workflows/lint.yml states 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 on main today, not a re-raise of the channel question.

Prior instances of the same shape, both closed after being acted on: #11421 (manifest UNCLASSIFIED) and #7347 (the qa liveness 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

Activity

  1. added theissue type on Sep 4, 2026
  2. os-zhuang commented on Sep 4, 2026

    @os-zhuang
    Contributor

    Triage (R+146): lands in docs/qa/platform-checklist/coverage.json plus the checklist items ⇒ domain:devx. Graded Bug · priority:p2.

    Bug: a gate is red on main, and the card proved it is not the finding PR's doing rather than asserting it — the ca3fd4b1 version of the script was written to a sibling path in the same tree and run there, and its four findings diff empty against the branch's. The gate's own --self-test is green at 141 assertions.

    priority:p2 — red on main, and the third recurrence of the same shape (#11421 manifest, #7347 the qa ledger, now four kinds at once). ⛔ Not p1: .github/workflows/lint.yml states 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 on main today, ⛔ 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 in coverage.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 the checklist-author skill for exactly this work; use it rather than hand-rolling the five-angle sweep.

    ⚠️ Re-run the gate on today's origin/main before starting: the reading is from ca3fd4b1 (2026-09-03) and the four kinds may have moved.


    Generated by Claude Code

  3. claude commented on Sep 4, 2026

    @claude
    ContributorAuthor

    Claim: PM seat domain:devx @ objectstack (#6023), session session_012zGPuVVX3deAx9LdjK8jCk, dispatching to an os-dev subagent on branch claude/issue-14961-platform-checklist-four-rest-kinds. P2 Bug, M (content). Scope: for each of batch_endpoints, crud_endpoints, metadata_endpoints, route_generation — checklist items authored with the checklist-author five-angle sweep against the capability's liveness ledger, or a waiver with a stated reason in docs/qa/platform-checklist/coverage.json; pnpm check:platform-checklist exit 0 afterwards, self-test 141 unchanged. ⛔ Not the channel question (#11730 stays a maintainer decision; lint.yml wiring 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 touching docs/qa/platform-checklist/** is draft #15395 (another lane, areas/records-forms.json +4/−4 — a different area file, not coverage.json); no overlap with the four REST kinds. Assignee field was empty at the read immediately before this write.


    Generated by Claude Code

  4. claude commented on Sep 4, 2026

    @claude
    ContributorAuthor

    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

  5. claude commented on Sep 4, 2026

    @claude
    ContributorAuthor

    LANDED — PM seat domain:devx @ objectstack (#6023), session session_012zGPuVVX3deAx9LdjK8jCk.

    PR #15541 merged 2026-09-04T20:57:58Z (merge-queue; merged: true, main 70c939953). 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.mjs exits 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. Fixes closed this card on merge; pm:dispatched and the assignee are stripped. main is green on this gate again; the third recurrence is the standing argument on #11730 (untouched).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions