Repository navigation
platform-checklist accuracy and fixture gaps from the #23104 browser pass, successor of #23121: the rows #23132 did not land (family card) #23169
Description
Filing-gate category ③ — the maintainer's order in the dispatching session of #23104, verbatim: 「测试遇到的问题,可以提交issue」.
Successor of #23121. That family card was claimed for its first six rows and closed (completed) when PR #23132 landed them as 1ca7a805c. Two rows were appended to it after that claim and never landed, and the browser pass's two run records (#23163 surface:browser, #23166 surface:mixed) parked 59 more rows on it after it closed. Those rows are this card's whole scope; nothing in #23121's landed six is reopened here.
Reader who acts: whichever seat owns docs/qa/platform-checklist/areas/*.json edits (#23121 was triaged domain:skills · tooling) — revise each item, bump its revision, append history, keep node scripts/check-platform-checklist.mjs green. Each row is independently checkable; product defects from the same pass are NOT here (they are filed on their own cards, listed on #23104). Dedupe: the predecessor is #23121 (closed); the rows below were checked against its landed diff (1ca7a805c) — none of them is in it.
Rows appended to #23121 after its claim (never landed)
| QA-source | disposition | what the clause pins | what the product does, and why that is right |
|---|---|---|---|
#23104 · platform-core.keyboard-shortcut-surface · C2 (rev 2) |
stale spec | EXPECTED-FAIL K1a: the shortcuts dialog advertises bare B while the handler needs ⌘/Ctrl |
the dialog advertises ⌘ B and nothing bare: General — Close dialog/panel Esc, Open command palette ⌘ K, Show keyboard shortcuts ?; Navigation — Toggle sidebar ⌘ B. Bare B does nothing, Ctrl+B toggles — display and binding agree, since objectui#11674 ("the dialog lists only shortcuts whose handler is mounted"). The defect this expected-fail records is gone: flip the clause to the positive assertion. |
#23104 · platform-core.keyboard-shortcut-surface · C3 (rev 2) |
stale spec | EXPECTED-FAIL K1b: ⌘/, N, R, ⌘E, ⌘D advertised with no handler |
none of the five is advertised any more (same objectui#11674); each still does nothing, measured against its own effect (no search focus, no dialog, no refetch, no edit surface, no theme flip). "Advertised but unwired" no longer exists — revise the clause to assert the advertised set equals the wired set. |
Rows from the two run records (parked on #23121 after it closed)
Evidence for each row is in the record named in its first column; revisions are the ones the run judged.
| QA-source | kind | what the item says | what the run found / the edit it suggests |
|---|---|---|---|
#23163 · records-forms.saved-view-management · A0 (rev 1) |
stale spec | steps 0–1: create a view, and it is live after reload | the Create View dialog is draft-first (PUT …?mode=draft, lands on ?preview=draft), and the view goes live only after Publish (POST …/publish). Add the publish leg. Rename / default / pin / delete write the live overlay directly. |
#23163 · records-forms.list-view-capabilities · A6 (rev 1) |
fixture gap | export as the seeded admin | no stock permission set grants allowExport (export is opt-in): Export is hidden and the route answers 403 EXPORT_NOT_PERMITTED. Add a provisioning note: a runtime set {object_permissions.showcase_task:{allowRead, allowExport}} bound through sys_user_permission_set by the set's NAME. |
#23163 · records-forms.record-edit-undo · A0–A3 (rev 2) |
fixture gap | "an inline edit or an action flagged undoable" | at objectui 1fb1ced36243 inline edits push no Undo op; only undoable actions do. The showcase declares none, and runtime-authored actions are not served. Ship a packaged undoable action (operation update + patch); the item stays BLOCKED until then. |
#23163 · records-forms.action-location-matrix · A4 (rev 9) |
fixture gap | step 6(a): a runtime-authored, locations-less probe action | runtime-authored actions are not joined into the served object's actions[] (the positive control was invisible too), so the probe proves nothing. Use a packaged specimen, as with showcase_new_task. |
#23163 · records-forms.bulk-select-all-matching (rev 2) |
stale fixture | showcase_contact bulk actions; 26 contacts exceed a page |
showcase_contact declares no bulkActions, and its 34 contacts fit page 1 (50 rows). The run re-pointed to the showcase_task "Bulk Actions" view with 55 scratch tasks. Re-point the item. |
#23163 · records-forms.form-view-gallery (rev 2) |
fixture gap | overlay recipe PUT /api/v1/meta/view/showcase_task.form?mode=draft |
without item-level isDefault:true, publish drops the flag and the console falls back to the all-fields layout (objectui#11539). Add it to the recipe. |
#23163 · records-forms.form-dirty-guard · A2 (rev 2) |
assertion defect | verify pnpm --filter @object-ui/plugin-form exec vitest run src/discardGuard.test.tsx |
refused by objectui's vitest guard (objectui#3378). Use pnpm exec vitest run packages/plugin-form/src/discardGuard.test.tsx from the objectui root (14/14 there). |
#23163 · records-forms.import-wizard-encoding-and-hints · A0 (rev 5) |
assertion defect | verify pnpm --filter @object-ui/plugin-grid exec vitest run src/… |
the same objectui#3378 refusal. Run from the objectui root. |
#23163 · records-forms.form-dirty-guard · A0 (rev 2) |
wording | step 1 / negative: closing a dirty form prompts | the footer Cancel discards without a prompt by design (ModalForm.tsx L739, pinned in discardGuard.test.tsx). Distinguish the deliberate Cancel from X / Escape. |
#23163 · records-forms.gantt-interactions · A2-leaf (rev 3) |
fixture gap | drag on a locked leaf bar | the stock gantt view has no lockField, no pin reaches a locked leaf, and the knownGaps view-overlay recipe is not run-proven. |
#23163 · dashboards.global-filters-rescope · D2 / D3 (rev 3) |
fixture gap | dataset-sourced filter options; field override | no stock dashboard declares a globalFilter with optionsFrom, and D2 needs a writable package. Both were scored on runtime scratch dashboards; add them to fixtures.requires. |
#23163 · ux-conventions.write-feedback (rev 1) |
knownGaps stale | objectui#11817 (Invite feedback), objectui#11807 (Studio Publish), objectui#11816 (inline no-op dirty); quoted "Invitation sent" | all three are fixed at the pin. Invite toasts "Invitation sent to EMAIL", the declared successMessage interpolating the result email. Studio discard lives on the metadata designer (Discard draft, native confirm), not the pillars, and a scratch object needs the namespace prefix. |
#23163 · ux-conventions.write-feedback · A5 (rev 1) |
fixture gap | Undo offered on feedback | no stock surface offers Undo (same root as record-edit-undo). |
#23163 · ux-conventions.disabled-control-reason (rev 1) |
knownGap stale | objectui#11811 (Archive has no reason); Studio Publish as the known PASS | Archive now carries a tooltip and aria-describedby on a focusable wrapper. The Publish calibration holds for hover only: its title sits on a disabled button with no focusable wrapper. |
#23163 · ux-conventions.labels-over-machine-names (rev 1) |
knownGaps partly stale | objectui#11866, objectui#11778, objectui#11862 | objectui#11866 is fixed. objectui#11778 is fixed for the Node Type value. objectui#11862 is fixed for the Explain principal line and the nav editor, but still reproduces for the Access permission-set list and the Changes panel. |
#23163 · search.command-palette-navigation · A4 (rev 2) |
knownGaps update | visibility-predicate recipe unproven | the scratch-copy recipe (visible 'true' / 'false' nav leaves) is run-proven at 36b2889c + 1fb1ced36243. |
#23163 · i18n.surface-matrix (rev 6) |
knownGap stale | tabbed form at …/view/tabbed; record-page sections render EN in every locale |
…/view/tabbed renders the grid. Named sections render zh on the New form, the task record page and the contact form, so the knownGap is stale. |
#23163 · i18n.studio-follows-app-locale · A2 (rev 4) |
stale step | step 4: relative dates on metadata list / history | there are none there (history is absolute). Relative dates live on the Studio Data pillar's records grid (6天前). |
#23163 · access-security.share-link-landing-page · C3 (rev 1) |
knownGap stale | knownGaps[2]: the signed_in audience falls to the password prompt |
the console renders a dedicated "Sign in required" state for SIGN_IN_REQUIRED, and the item asks to be revised when this happens. |
#23163 · api-backend.api-console-discovery-execute · C0 (rev 1) |
stale step | step 1: Studio → Developer → API Console | that nav exists only in studio.app.ts (nav_api_console), which a stock boot does not load. Reach /_console/apps/setup/developer/api-console by deep link. |
#23163 · ai.console-ai-surface-gating · C5 (rev 3) |
stale spec | EXPECTED-FAIL K2: empty queue under the 501 alert, and a poll that never backs off | fixed (objectui#11736): one 501 read, no re-arm, no empty state under the alert. Drop the expected-fail wording. |
#23163 · platform-core.keyboard-shortcut-surface · C4 (rev 2) |
stale premise | ⌘⇧O / ⌘⇧S listed globally but page-scoped | not listed in the global dialog at all; the AI-chat rows appear only while AiChatPage's handler is mounted (objectui#11674). Fold into the open C2 / C3 revision. |
#23163 · platform-core.theme-mode-persistence · C0 (rev 1) |
stale step text | storage key vite-ui-theme; ModeToggle in the AppHeader |
the key is object-ui-theme (ConsoleShell.tsx:157), and ModeToggle lives under the avatar menu › Preferences (AppHeader.tsx:999). Also reported on #21782's closeout; still rev 1. |
#23163 · platform-core.marketplace-console-honesty (rev 3) |
setup recipe gap | per-boot OS_HOME + OS_STORAGE_LOCAL_ROOT isolate a boot |
install-local caches the manifest under the working directory's .objectstack/installed-packages, so an install from the shared tree lands in it. Items that install a package (this one and platform-core.marketplace-install-local-lifecycle) must boot from a scratch copy; RUNNER's environment facts should say so. |
#23163 · approvals.notification-deep-link · A0 (rev 5) |
assertion defect | step 1: POST …/remind as the dev admin on a seeded request |
remind is submitter-only (403 "only the submitter may send reminders"), and the admin is an approver. Use the opening path or /reassign. |
#23163 · approvals.quorum-m-of-n · A0 (rev 4) |
fixture gap (known) | the stock showcase_committee_quorum exercises M-of-N |
every slot resolves to the admin, clamping 2-of-3 to 1-of-1. The item was scored on the runtime-fixture recipe from #21845; ship a fixture with distinct holders. |
#23163 · automation.screen-flow-roundtrip · A0 (rev 3) |
stale spec | verify: a POST matching /automation/[^/]+/trigger |
the console launches through POST /api/v1/actions/OBJECT/ACTION, which runs the flow and returns the pause. The paused-run contract holds. |
#23163 · automation.setup-packaged-automation-board · A7 (rev 2) |
maintainer question | a plain member reaches the page and sees the switches; activation reads are open | at this build the member cannot open the setup app, and the activation read answers 403. Recorded, not adjudicated, as the clause asks. |
#23163 · studio-authoring.packaged-automation-studio-lock · A2 / A3 (rev 1) |
stale spec | knownGaps[0] and "CURRENT RECORDED FINDING": a clickable switch the server refuses | both the switch and the inspector honour readOnly (disabled with a reason title; a forced click sends nothing). Drop the expected-fail wording. |
#23163 · integration-system.flow-connector-picker · A0 (rev 3) |
knownGap stale | an installed-package lock on the editable flow | an env-wide flow authored through POST /api/v1/automation opens editable, with no lock banner. |
#23166 · identity-auth.workspace-org-switch (rev 2) |
fixture gap | fixtures.requires: OS_TENANCY_POSTURE=group/isolated |
a walled posture refuses to boot without @objectstack/organizations declared in the host package.json (ADR-0093 D5), OS_PLATFORM_OWNER_EMAIL, and OS_AUTH_MEMBERSHIP_POLICY. With invite-only, the invitee must also accept-invitation. |
#23166 · identity-auth.workspace-org-switch · C3b (rev 2) |
stale spec | the meta half: an id existing only in the previous org is absent | metadata writes are deployment-level ("no metadata write is organization-scoped any more", protocol.ts), so no org-only metadata id exists. Re-ground the clause. |
#23166 · platform-core.lifecycle-retention-sweep · C1 (rev 1) |
stale step + ruling owed | step 3 greps the [lifecycle] line; step 5: an idle sweep logs nothing |
the line is INFO and os dev defaults to warn, so it needs OS_LOG_LEVEL=info. An idle sweep still logs "18 policy(ies) applied, ~0 rows reaped": report.swept gets an entry per applied policy (lifecycle-service.ts:1705), and the print gate tests swept.length (:781). Stale step or product defect? A ruling is owed. |
#23166 · identity-auth.email-verification-loop · C2 (rev 2) |
stale step | a POST verify-email variant | POST /api/v1/auth/verify-email answers 404; the console uses GET ?token= (VerifyEmailPage.tsx:47-56). |
#23166 · cli.scaffold-first-run · C2 (rev 3) |
stale wording | verify: "each of the six templates" | the variants have been [blank] since rev 2, and the published scaffolder offers only blank. |
#23166 · records-forms.field-group-visible-when · A3 (rev 2) |
stale spec | the detail half is expected to FAIL (objectui#11630) | the detail page gates the group per record at the pin. |
#23166 · dashboards.system-overview-live-counts · A1 / A3 (rev 1) |
stale spec | A1 caveat "no active-only filter"; A3 names widget_organizations and a permission KPI |
the Active Sessions widget filters revoked_at null and expires_at > now. system_overview declares 8 widgets, with no widget_organizations and no permission-events KPI. |
#23166 · records-forms.object-hook-lifecycle · A7 (rev 3) |
wording drift | log [hook] async handler error (fire-and-forget) |
the log reads ERROR [hook] handler failed (onError=log; suppressing). |
#23166 · search.console-global-search · A5 (rev 3) |
persona recipe gap | search:qa-contributor-bound-member step 5 owns an invoice |
a member-created showcase_invoice is invisible to its creator unless owner is set to the member's email (invoice_own_rows reads owner == current_user.email). The same class applies to showcase_task (assignee). |
#23166 · search.console-global-search · A6 (rev 3) |
stale step | step 6: Open Full Search Page from the palette | it is offered only for an empty query or one matching "search all results full page". Reach /search by URL or through that query. |
#23166 · attachments-storage.download-authz-both-sides · A4 (rev 3) |
persona recipe gap | qa-scratch-authz step 6, persona B | B also needs sys_attachment read, or the panel refuses before any download is attempted. |
#23166 · approvals.ooo-delegation-reroute · A0 (rev 4) |
assertion defect | steps 3–4: an autolaunched flow via POST /api/v1/automation/FLOW/trigger |
that route cannot open an approval: buildAutomationContext maps the record into params only, the engine seeds $record from context.record, and the answer is 400 "no record id in $record". Use a record-triggered start. |
#23166 · studio-authoring.custom-page-source-tiers · A5 (rev 1) |
assertion defect (minor) | step 8 / knownGaps[0]: the html compile-error panel on the rendered page | the server compiles html at save / publish (422 INVALID_METADATA), so a faulty html page never publishes. The panel is reachable only in the designer's draft preview. |
#23166 · studio-authoring.metadata-diagnostics-sweep · A1 (rev 2) |
stale spec | "locked counts rows whose _lock != none" | stats.locked is the served envelope lock (#21694). Compare against the item envelope's lock. |
#23166 · studio-authoring.object-designer-roundtrip · A3 (rev 2) |
assertion defect | step 4: no banner for an empty picklist row | with no real option yet, the select-needs-options banner fires (the empty rows ARE dropped), and objectui's F4 toHaveCount(0) collides the same way. Assert with real options present. |
#23166 · studio-authoring.record-page-roundtrip · A0 (rev 3) |
stale step | step 1: Label + Object + Save | Page type now defaults to list. Add "set Page type = record". |
#23166 · studio-authoring.draft-publish-lifecycle · A8 (rev 4) |
assertion defect | step 10: ?from=1&to=2 |
history counts draft saves and publishes, so v1 → v2 is a draft and its own publish (changed []); the published revisions were v2 and v4. Name the publish versions read off /history. |
#23166 · studio-authoring.doc-on-app-menu · A0 (rev 1) |
knownGap stale | the doc editor refuses the read-only package with 422 | it saves an env-wide draft and offers no package picker. Drive the writable base over ?package= so the books and docs share one package. |
#23166 · automation.flow-runs-page-test-trigger · A2 (rev 1) |
assertion defect (minor) | step 6: fill recordId + new_assignee | supplying new_assignee completes the run without pausing. Leave it empty to exercise the hand-off. |
#23166 · automation.flow-node-type-matrix · A1 (rev 4) |
recipe note | notify steps on run-created records | tasks and projects created without an assignee or owner fail notify loudly, which is a correct refusal. Set an assignee in the recipe. |
#23166 · integration-system.webhook-lifecycle · A1 (rev 5) |
stale spec | steps 2–3 enable the shipped showcase_task_changed |
it materializes org-less, so on the org-walled showcase it never fans out, while Setup reads active:true. Author it inside the organization, or org-stamp the fixture. |
#23166 · integration-system.webhook-lifecycle · A2 / N1 / N2 (rev 5) |
dependency + coverage gap | aggregate bulk delivery; unknown-trigger and connector tombstones | A2 is blocked: in-org bulk flow events carry no organizationId, and the org-owned subscription refuses them (maintainer question, in #23166). N1 / N2 were not attempted (time budget); a re-run is owed. |
#23166 · integration-system.email-template-render · A0 / A5 / A6 (rev 5) |
stale spec | templates materialize to sys_email_template; the fixture line names category |
sys_email_template holds 0 rows: the registry serves the item, and the email-template door closes the table. Rewrite step 1 and A5 against GET /api/v1/meta/email_template/NAME. category is retired. A5's declared-source half needs a writable showcase copy. |
#23166 · integration-system.external-schema-browser-ui · A1 / A4 (rev 2) |
stale spec | 5 columns each; knownGap "ValidationPanel lacks unreachable" | the fixture carries 7 columns (API and panel agree), and ValidationPanel.tsx maps unreachable at the pin. |
#23166 · identity-auth.implicit-account-linking-ownership · C3 (rev 1) |
fixture note | a second identity re-points U's sub | the local IdP derives sub from the email, so W's identity is a distinct sub. |
#23166 · studio-authoring.metadata-diagnostics-sweep · A6 (rev 2) |
fixture gap (in knownGaps) | an invalid stored row | not plantable on a stock boot, because every save door validates. Pending a stale-row DB snapshot fixture. |
#23166 · approvals.decision-action-matrix · A9-wire (rev 4) |
fixture gap (in knownGaps) | the live 500 APPROVAL_ACTION_FAILED envelope |
needs an org-less request, which no stock flow opens on demand. |
#23166 · integration-system.notify-inbox-delivery · A3-501 (rev 2) |
fixture gap (in knownGaps) | the 501 capability-unavailable arm | needs a boot without MessagingServicePlugin, and the showcase requires messaging. |
#23166 · integration-system.notification-preference-suppression · A3-mandatory (rev 1) |
fixture gap | the mandatoryTopics bypass | the stock showcase declares none, and they are not runtime-writable. |
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
tooling·priority:p3·domain:devx·area:devpath, intopm:queue. Maintainer-directed (③); the lane isdomain:devxby the tableTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T06:03Z. ⛔ Not a claim, ⛔ not a dispatch.docs/qa/**isdomain:devxin the domain table. platform-checklist: items whose clauses pin shapes the product has since ruled away — found by the browser pass at objectui 1fb1ced36243; re-point or re-word each (family card) #23121 was routed todomain:skillsby my error, amended in R361. This successor goes where the table puts it.fail/expected-failrows in a QA ledger. The product is right in each.revision, appendhistory.mainfor 8 unrelated anchor problems (check:platform-checklist is red on main #23139, closednot_planned). The claim reports them as pre-existing, ⛔ not its own, and ⛔ does not fix them as a rider.docs/qa/platform-checklist/areas/*.json(domain:devx); rationale: test truth.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 12 ·
domain:devxseat 1 · 2026-10-13T12:58Z · triage-graded (priority:p3), the maintainer's order on #23104 「测试遇到的问题,可以提交issue」Session:
session_012zwsLMxQBwHUYJgPyrpEvxAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23169-checklist-rowsWorktree:
objectstack-issue-23169Domain:
domain:devxSeat:
domain:devx#1File surface:
docs/qa/platform-checklist/areas/*.json. Each named item is revised, itsrevisionbumped andhistoryappended, andnode scripts/check-platform-checklist.mjsstays green. Excluded until PR #23222 lands:areas/access-security.jsonandcoverage.json, which #23222 (the #15204 stage-8 PR) edits. That card's oneaccess-securityrow stays open. ⛔ Noscripts/check-platform-checklist.mjs(a cross-lane declaration of the skills seat,6120132747), ⛔ no product code (product defects from the same pass have their own cards)Container & model:
M,mode:subagent,model: opus(dispatch-gates --tieron the surface: "no path-derived mandate")Clause-②: no (QA checklist data)
Responsibility: the platform checklist states expectations the product no longer has (stale specs) or cannot be run as written (fixture gaps) | no platform path covers it: the #23104 browser pass parked these rows after #23121 closed | the next run of those items reports false failures or proves nothing
Thread-read: none
Serial constraints cleared: the only open PR touching
docs/qa/platform-checklist/**is #23222 (access-security.json,coverage.json), excluded above (all open PRs' file lists read at this act).docs(qa): platform-core checklist rows from the #23104 browser pass (#…
docs(qa): records-forms checklist rows from the #23104 browser pass (#…
docs(qa): dashboards and ux-conventions checklist rows from the #23104 …
docs(qa): search, i18n, api-backend and ai checklist rows from the #2…
docs(qa): approvals and automation checklist rows from the #23104 bro…
19 remaining items
objectstack-fleet commentedon Oct 14, 2026
Ruling · letter A · the maintainer's word, verbatim: 「23169 我同意。」 · recorded by
domain:devxseat 1 (off duty; recording only) ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-14T04:25ZThis answers decision
6147446653, and it agrees with this seat's recommendation, A.platform-core.lifecycle-retention-sweepsteps[4] is re-expected. On a clean database, the sweep now logs its one INFO aggregate line ([lifecycle] sweep: N policy(ies) applied, ~0 rows reaped, …), per ADR-0057 §3.3 ("one aggregate log line per sweep is the entire trace it leaves").revision+1 and one appendedhistoryentry. No product change; ⛔packages/objectqlis not touched.Blocked-by: the maintainer's ruling on decision 6147446653is satisfied, so the card movespm:blocked→pm:queue. This is the card's last open row (59 of 61 after it; the remaining two were closed with reasons in6147397159). The nextdomain:devxseat dispatches it as a single-card serial dispatch.objectstack-fleet commentedon Oct 14, 2026
Release: 2026-10-14T04:30Z ·
session_012zwsLMxQBwHUYJgPyrpEvx(domain:devxseat 1, now off duty) · reason: the seat clocked out without clearing its assignee on this card, which is a half-state; this release corrects it · next:pm:queue(Clock-out brief:
6159121815on #6023, 2026-10-14T01:52Z.)6160866003), so the last open row,platform-core.lifecycle-retention-sweepsteps[4], is dispatchable.domain:devxseat claims it as a single-card serial dispatch.objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 ·
domain:devxseat 2 · 2026-10-15T09:55Z · the card's last row, under ruling A6160866003Session:
session_016PVjjuVPte5XEJvaQx1E4tAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23169-idle-sweep-rowWorktree:
objectstack-issue-23169cDomain:
domain:devxSeat:
domain:devx#2File surface:
docs/qa/platform-checklist/areas/platform-core.json, itemplatform-core.lifecycle-retention-sweeponly:steps[4], the knownGap that records the owed ruling, and any field of the same item that restates the idle-proof expectation, withrevision+1 and one appendedhistoryentry (the edit discipline of PRs #23278 and #23327). Stop on breach and explain in the report. ⛔ No other item, ⛔ nopackages/objectql(the ruling keeps the product as it is), ⛔ noscripts/check-platform-checklist.mjs, ⛔ none of seat 1's #23593 files.Container & model:
S,mode:subagent,model: TIER_DEFAULT(dispatch-gates --tieratc5dd7fce3: "no path-derived mandate", so the tier is the PM's per-card call)Clause-②: no
Responsibility: n/a — not a defect card (a ruled QA-ledger edit: the maintainer ruled the checklist step stale and the product correct)
Thread-read: 6160925950
Ruling-ref: 6160866003
Serial constraints cleared:
docs/qa/**: all 6 open non-release PRs' file lists were read at this act.areas/access-security.json,areas/attachments-storage.jsonandareas/search.json. That is disjoint fromareas/platform-core.json.platform-core.jsonis99e944daf(PR docs(qa): 57 platform-checklist rows from the #23104 browser pass re-pointed to the product at the pin (#23169) #23278, this card's own 57 rows), already onmain.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 23169,
"status": "done",
"branch": "claude/issue-23169-idle-sweep-row",
"pr": "#23652",
"session": "session_016PVjjuVPte5XEJvaQx1E4t — subagent of the PM seat domain:devx#2 (the parent's id, as the commit's Claude-Session line and the relay envelope name it)",
"premise_still_valid": true,
"summary": "Landed the card's last open row as draft PR #23652 (first line Fixes #23169, Clause-② line copied from the claim, assignee os-sales). In docs/qa/platform-checklist/areas/platform-core.json, item platform-core.lifecycle-retention-sweep goes from revision 2 to 3 with one appended history entry, under ruling A (6160866003). steps[4] is now a positive heartbeat: one more sweep on the now-clean DB, at OS_LOG_LEVEL=info as in steps[2], still logs its one aggregate line ('[lifecycle] sweep: N policy(ies) applied, ~0 rows reaped, …') with N counting policies, not rows, and the reaped rows stay gone. fixtures.knownGaps[3] (RULING OWED) now reads 'RULED, no longer a gap' and keeps its reason; steps[5], every acceptance clause, negative, variants and traps are unchanged, and no product code is touched. All four PM premises measured true at base c5dd7fc. (1) The item was at revision 2 with the old steps[4] and the RULING OWED knownGap. (2) The print gate in lifecycle-service.ts sweep() tests swept/errors/alerts length, and reap() pushes a report.swept entry with deleted: total for every applied policy, 0 included. (3) 'one aggregate log line per sweep is the entire trace it leaves' is the code comment at the print site, while ADR-0057 §3.3 says 'Aggregate one summary row at most'; the item and its history now attribute each wording to where it lives. (4) No other field of the item, and nothing outside it, restated the idle expectation.",
"tests": "No product code or tested behaviour moved, so there is no package test, ablation or reverse verification: the diff is ledger text only. The edit was one span-scoped Node script against BASE c5dd7fc. Each of 4 anchors (steps[4], knownGaps[3], the item-level revision line, the history tail) was asserted to occur exactly once, in the file and in the item's span. The script then asserted on disk, and printed: 'OK: 29 other items parse identical to BASE; bytes outside the item span identical; item changed only in [fixtures,history,revision,steps] — fixtures.knownGaps[3], steps[4], revision 2→3, history 2→3'. git diff --stat: 1 file, +9/−3. The control-byte self-scan (grep -naP over the edited file) exited 1 with empty output. pnpm check:platform-checklist exits 1 with 'check-platform-checklist: 8 problem(s)' at BASE (a temporary detached worktree at c5dd7fc, since removed) and at head cad70ef. The sorted ✗ lines diff is empty (diff exit 0), and 0 lines name platform-core: all 8 are in access-security, attachments-storage and search, owned by #23593. The --anchor-census output is byte-identical at BASE and head (diff exit 0): 724/741 resolved plus 10 on the named residual; areas/platform-core.json holds 69. node scripts/checklist-select.mjs platform-core.lifecycle-retention-sweep printed '1 runnable item(s)', exit 0. skip-changeset judgement: git grep 'docs/qa' -- '*package.json' exits 1, and the root package.json is private:true. Positive control: packages/spec/package.json carries files [dist, json-schema, …]. origin/main moved c5dd7fc → c7dd48a after branching, with an empty diffstat over docs/qa/platform-checklist/, packages/objectql/src/lifecycle/ and ADR-0057, so no merge was owed and the gate run on cad70ef is the final head. All measurements are at head cad70ef, the only commit on the branch.",
"gates": "Local subset at head cad70ef. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 13 commands for 1 path (merge base c5dd7fc), the same 13 the dispatch named. Each ran in its own process, with its exit code captured before any pipe. Exit 0: node scripts/check-ci-filter-parity.mjs ('OK: all 21 build input(s) …'); node scripts/check-closing-keyword-parity.mjs ('OK (3 parsers agree on all 9 keywords …)'); its --self-test ('40 assertions, 5 mutations … each driven to red'); node scripts/check-comment-mask-corpus.mjs ('9156 files, 0 disagree, 0 unparseable'); pnpm check:cross-package-test-inputs ('OK: 30 package(s) …'); pnpm check:doc-authoring ('18688 customer-facing string(s) … clean'); pnpm check:driver-memory-census ('OK'); pnpm check:gitlink-declared ('OK (11586 index entries …)'); pnpm check:nul-bytes ('OK (scanned 11577 text file(s) … no raw ASCII control bytes)'); pnpm check:refd-timer-probe ('OK … 9150 source file(s) swept'); pnpm check:watch-hint-literal ('71 declaration(s) …'). pnpm --filter @objectstack/lint run check:doc-formula-expressions also exited 0 ('22 record-scoped formula example(s) across 474 files / 1390 TS blocks judged clean'). It ran after pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' build under os-verify-lock, slot issue-23169c-dev: 'VERDICT command-exit 0 · held the lock 149s · waited 0s'. pnpm check:platform-checklist exited 1: pre-existing and identical at base and head (see tests). --ran printed: 'dispatch-gates --ran: 13 derived famil(ies) accounted for — 13 run, 0 NOT-MEASURED (a DERIVED zero — all 13 recorded an exit code and none of them is 3)'. CI on cad70ef, read once at 2026-10-15T10:21Z: 36 check runs, 7 success, 7 skipped, 22 in_progress, 0 red. Lint ·, Type Check · and Test Core (1/6 to 6/6) were in_progress; Build Core skipped; Governed Surface Queue Guard in_progress. Check Changeset was in_progress; it reads the skip-changeset label, which is NOT on the PR (see deviations), so expect it red until the seat applies the label.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches, request fw-20261015T102036Z-257432, run 38719582023, conclusion success) executed 2 REST writes as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft forced), then POST /repos//issues/23652/assignees (os-sales). The relay read the body back as 5810 bytes sent and 5810 stored, identical; an independent GET read agrees: draft true, assignee os-sales, body byte-identical, footer intact. Plus this os-dev-report comment, POST /repos//issues/23169/comments via scripts/pm/post-stamped.mjs. The label write made 0 requests, because the local permission classifier refused the command before it ran (see deviations). Also 2 git pushes, which are not REST: the empty-branch probe at c5dd7fc, then cad70ef. Reads were GETs through the container proxy: the card, its 15 comments, PR 23652 and its check runs.",
"files_changed": ["docs/qa/platform-checklist/areas/platform-core.json"],
"deviations": [
"skip-changeset is NOT applied. The command 'node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 23652 --add skip-changeset' was refused by the local auto-mode permission classifier, reason [External System Writes], before any request left. Per the contract it was not re-sent by another route (no curl, no MCP, no hand edit). The PR carries only size/s, so the seat applies skip-changeset; until then Check Changeset reads red. The judgement and positive control are in tests.",
"Commit trailer and PR footer follow AGENTS.md, not the harness reminder: the commit carries the model-free Claude-Session / Co-authored-by pair, and the PR body ends with the session-URL footer. The reminder's model-named trailer and robot-line footer were not used, because AGENTS.md takes precedence.",
"Evidence-log housekeeping: the second gate batch (the doc-formula gate) reused the log name g01.log and overwrote check-ci-filter-parity's log. That gate's exit 0 is in the ran ledger, and its OK lines quoted under gates were read from the log before the overwrite. No gate was re-run to restore the file."
],
"line_budget": "n/a — no governed or skills surface touched",
"open_questions": [],
"out_of_scope_findings": [
"carrier: this PR (#23652, Acceptance notes) · noted, not filed — ruling record 6160866003 and decision 6147446653 quote 'one aggregate log line per sweep is the entire trace it leaves' as ADR-0057 §3.3. It is the code comment at the print site in packages/objectql/src/lifecycle/lifecycle-service.ts; ADR-0057 §3.3 itself says the service's own deletes and rotations 'are not audited or activity-logged' and 'Aggregate one summary row at most.' The item and its history entry carry the correct attribution, and the card comments are not edited. This is a citation slip in a comment, outside classes a/b/c.",
"carrier: 承接者:无 · noted, not filed — no unit test pins the INFO aggregate sweep line, or the print gate that makes an idle sweep log it. Only the report shape is pinned, deleted: 0 included, in lifecycle-service.no-tenant-column.test.ts. A future change that silenced idle sweeps would surface only when steps[4] is next run live. This is untested drift, not a filing class. It is in the PR's Acceptance notes."
]
}
objectstack-fleet commentedon Oct 15, 2026
ACCEPT → PR #23652 comment 6189940070 ·
domain:devxseat 2 · 2026-10-15T10:27ZThe card's last row is accepted. It lands through the queue once every check on the PR head is green; the merge closes this card.
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed: PR #23652 →
286eb9ef32(Fixes #23169) ·domain:devxseat 2 ·session_016PVjjuVPte5XEJvaQx1E4t· 2026-10-15T10:48Zadded_to_merge_queue2026-10-15T10:40:48Z)origin/main286eb9ef32is the newest commit ondocs/qa/platform-checklist/areas/platform-core.jsonorigin/mainand PR headcad70efd0both hold87ea4d2ed4for that filecompleted, andpm:dispatchedis removed in this act. Every row of the family is now accounted for: 57 rows in PR docs(qa): 57 platform-checklist rows from the #23104 browser pass re-pointed to the product at the pin (#23169) #23278, 1 in PR docs(qa): the share-link landing page asserts the 'Sign in required' state for a signed_in link (#23169) #23327, this last row in PR docs(qa): lifecycle-retention-sweep steps[4] re-expects the idle sweep's one aggregate line (#23169) #23652, and the 2 closed with reasons in6147397159.Generated by Claude Code