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
docs(qa): studio-authoring checklist rows from the #23104 browser pass (
docs(qa): integration-system, identity-auth, cli and attachments chec…
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{
"issue": 23169,
"status": "done",
"branch": "claude/issue-23169-checklist-rows",
"pr": "#23278",
"session": "session_012zwsLMxQBwHUYJgPyrpEvx — subagent of the PM seat domain:devx#1 (the parent's id, as the relay's container derivation and the claim name it)",
"premise_still_valid": true,
"summary": "Landed 57 of the card's 61 rows in draft PR #23278 (Part of #23169, Clause-② no, assignee zhuangjianguo, skip-changeset read back). The PR revises 51 items across 15 area files (each item revision +1 with one appended history entry naming the row, its run and the fields touched), two area recipes (search:qa-contributor-bound-member step 5, attachments-storage:qa-scratch-authz step 6) and one RUNNER.md environment fact (install-local caches under the working directory). Every row was re-checked against today's sources: the objectui pin on main is still 1fb1ced, the console both runs drove, and console rows were re-read from objectui source at that pin; framework rows were re-read at base 6d7f4df. No browser was driven and no app was booted, so rows that only a live run can show rest on the run record's evidence, and their history entries name it. #23169 stays open for two things: the access-security.share-link-landing-page C3 row, which waits for PR #23222, and a maintainer ruling on platform-core.lifecycle-retention-sweep steps[4] (open_questions). Three rows needed no edit because their items already record the gap in full (approvals.quorum-m-of-n A0, approvals.decision-action-matrix A9-wire, studio-authoring.metadata-diagnostics-sweep A6), and webhook-lifecycle N1/N2 owe a re-run, not an edit.",
"tests": "Gates at head ec744f7 (the branch after merging origin/main b4d573a; no checklist file or .objectui-sha moved in that range). Each gate ran in its own process with its own log, and the exit code was read before any pipe. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 13 families for 16 paths; --ran with exit codes 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)'. Exit 0 for 12 of them: check-ci-filter-parity 'OK: all 21 build input(s) …'; check-closing-keyword-parity 'OK (3 parsers agree on all 9 keywords …)'; its --self-test '40 assertions, 5 mutations … each driven to red'; check-comment-mask-corpus '8975 files, 0 disagree, 0 unparseable'; check:doc-formula-expressions '22 record-scoped formula example(s) across 474 files / 1391 TS blocks judged clean' (after pnpm --filter '@objectstack/lint...' build under os-verify-lock, slot issue-23169-dev: VERDICT command-exit 0, 171 s held, 0 s waited); check:cross-package-test-inputs 'OK: 30 package(s) …'; check:doc-authoring '✓ doc authoring guard …'; check:driver-memory-census 'OK'; check:gitlink-declared 'OK (11258 index entries …)'; check:nul-bytes 'OK (scanned 11249 text file(s) … no raw ASCII control bytes)'; check:refd-timer-probe 'OK … 8969 source file(s) swept'; check:watch-hint-literal '73 declaration(s) …'. pnpm check:platform-checklist exits 1 with 'check-platform-checklist: 8 problem(s)', the same 8 lines as at base 6d7f4df (the sorted ✗ lines diff empty, run after every area batch and at head). None is in an item this PR touches. Symbol anchors only rose (--anchor-census base vs head 716 → 725 resolved: api-backend 66→67, dashboards 22→24, identity-auth 90→91, platform-core 67→69, records-forms 94→96, studio-authoring 36→37; no file fell). Every edit was a span-scoped scripted replacement that asserts its anchor occurs exactly once inside the item, and every save asserted that untouched items parse identical to base and that each touched item gained exactly revision +1 and one history entry. The selector reads the new blocked annotation: 'records-forms.record-edit-undo → 0 runnable item(s) (1 blocked, hidden — pass --include-blocked)'. No ablation or reverse verification: the change is ledger text only. skip-changeset: docs/qa/** sits outside every package, and no package.json names it (positive control: packages/spec/package.json carries a files field).",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "3 relay dispatches (each POST /repos/objectstack-ai/objectstack/dispatches), executing 4 REST writes as objectstack-fleet[bot]: (1) pr_create, run 38409540391: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/23278/assignees (zhuangjianguo); body read back 20946 bytes sent and stored, identical. (2) labels_add via scripts/pm/label-write.mjs, run 38409629133: POST /repos//issues/23278/labels (skip-changeset), read back documentation, size/l, skip-changeset. (3) this os-dev-report comment via scripts/pm/post-stamped.mjs: POST /repos//issues/23169/comments. Plus git push (not REST): the empty-branch probe and 8 pushes ending at ec744f7. Reads were unauthenticated-header curl GETs through the container proxy (issues, comments, PR files, the PR read-back)",
"deviations": [
"records-forms.record-edit-undo gets an item-level blocked annotation, so the item 'stays BLOCKED' as the card suggests. No card tracks the packaged-undoable fixture, so blocked.ref names the gap in words. The selector now hides the item from default runs, and --include-blocked lists it",
"dashboards.system-overview-live-counts A3: the card says system_overview has 'no widget_organizations'. The source declares 9 widgets, widget_organizations among them, and the server strips it on an unmet requiresService (meta-item-read-gate.ts filterDashboardForUser), so 8 are served. The item names both layers",
"integration-system.notify-inbox-delivery A3-501 was listed as '(in knownGaps)', but the item carried no such knownGap; one was added",
"platform-core.lifecycle-retention-sweep C1: only the step-3 log-level half is applied (OS_LOG_LEVEL=info on the control boot and the kill-switch boot). steps[4] is not rewritten; a knownGap says the ruling is owed and how a run scores the step meanwhile",
"automation.setup-packaged-automation-board A7: the measured member posture is recorded beside the authored one without adjudicating it, and the note adds that acceptance[5]'s member cell cannot be reached through the page while that posture holds",
"Coupled fields of the same item that restated the same stale fact were revised too, the same practice as #23132, and each is named in its history entry. The largest are email-template-render (title, steps[3], acceptance[0] and [2], and source[2] — the row projector it cited, bootstrap-declared-email-templates.ts, no longer exists) and draft-publish-lifecycle (steps[8] and acceptance[7]: history counts drafts too)",
"write-feedback, disabled-control-reason and labels-over-machine-names: besides retiring the fixed knownGaps, the edits name the same run's new cards (objectui#12303, #23157), so the next run cites them rather than re-filing",
"The two recipe corrections bump only the item each row names. Recipes carry no revision, and the other consumers' clauses did not change (search.rls-both-personas, search.global-search-skips-unreadable, records-forms.crud-roundtrip, and the other two qa-scratch-authz users). Each recipe's provenance records the correction",
"One PR, not one per area: 792 changed lines (+526 / -266, 16 files), under the 3000-line threshold, and not governed. The dispatch allowed a split, but did not require it",
"Merged origin/main into the branch before the gates, because dispatch-gates flagged a stale tree (scripts/engine-double-contract.pinned.json moved). No conflict, and nothing in the merged range touches docs/qa or the pin",
"I fetched the pinned objectui commit object into the shared /home/user/objectui checkout so I could read source at 1fb1ced. This was a read-only fetch, but it overwrote that checkout's FETCH_HEAD; its working tree and HEAD (7578323) are untouched",
"Commit trailers use AGENTS.md's model-free pair (Claude-Session plus 'Co-authored-by: Claude'), not the harness reminder's model-named Co-Authored-By, per the reminder's own precedence clause. The PR body ends with the AGENTS.md session-URL footer",
"Cleanup: the root node_modules is removed before this comment posts. The worktree /home/user/objectstack-issue-23169 is removed right after it, because this comment is posted with that checkout's scripts/pm/post-stamped.mjs. A temporary detached comparison worktree at base was already removed (git worktree remove, no --force)"
],
"rows_landed": "57 rows across 51 items (marketplace-install-local-lifecycle is revised because the marketplace row names it). The full per-row table — item, revision, the run's lane label, what changed, and what it was checked against — is in the PR body's 'Rows landed' section",
"rows_not_edited": [
"approvals.quorum-m-of-n A0 (fixture gap, known): knownGaps[0] and [1] already record the clamp, the runtime fixture and the seed line that would retire it; seed-approval-demo.ts is unchanged at 6d7f4df. Shipping a distinct-holder fixture is showcase work",
"approvals.decision-action-matrix A9-wire: knownGaps[0] already records it in full",
"studio-authoring.metadata-diagnostics-sweep A6: knownGaps[0] already records it in full (the item's A1 row is landed)",
"integration-system.webhook-lifecycle N1 / N2: not attempted by the run, and the item's text for them is right. The new knownGaps[1] says a re-run owes them"
],
"rows_remaining": [
"access-security.share-link-landing-page C3 (knownGaps[2] stale: the signed_in audience now renders a dedicated 'Sign in required' state). It waits for PR #23222 to land, because #23222 edits access-security.json",
"platform-core.lifecycle-retention-sweep steps[4]: a maintainer ruling is owed (open_questions); the follow-up edit depends on it"
],
"open_questions": [
{
"question": "platform-core.lifecycle-retention-sweep steps[4] (QA run #23166 C1): should an idle lifecycle sweep log nothing? Today it logs '[lifecycle] sweep: 18 policy(ies) applied, ~0 rows reaped, …' at INFO on every sweep. The print gate tests report.swept.length, every applied policy pushes an entry (deleted 0 included), and the LifecycleSweepReport.swept docblock reads 'Policies applied, one entry per (object, policy)'.",
"options": [
"A — Stale step, product right. One aggregate line per sweep is the design (ADR-0057 §3.3 'one aggregate log line per sweep is the entire trace it leaves'). Revise steps[4] to expect the line with ~0 rows reaped on a clean DB. Cost: one checklist edit on this family card, no product change. Effort: XS",
"B — Product defect. An idle sweep should print nothing: change the print gate in packages/objectql/src/lifecycle/lifecycle-service.ts to fire only when rows moved (deleted, dropped shards or archived above zero), errors or alerts, and pin it in lifecycle-service.test.ts. The checklist step stays. Cost: an objectql patch with a changeset and a test. Effort: S"
],
"recommendation": "A. Business need: the line is the only trace that the platform enforcer ran, and this very item uses it as the armed control that makes the kill-switch's missing line meaningful. A heartbeat at INFO, which
os devhides by default, is what an operator proving retention runs actually reads. Long-term: A follows ADR-0057 §3.3's one-line-per-sweep wording as written, and B would make 'swept, nothing to do' and 'never ran' the same silence, against the repo's 'absence must be loud' rule. AI mistakes: under B a run or an agent can only infer from an absent line, which is the absence-inference trap this item already guards against; A keeps a positive signal. No scope creep: A changes no product code, adds no gate and no surface. If the maintainer instead wants quieter logs, B is cheap, but it should then add a distinct liveness signal rather than silence"}
],
"out_of_scope_findings": [
"carrier: platform-checklist-watchdog workflow (daily on main; files or refreshes one issue while the gate is red) · noted, not filed · evidence: pnpm check:platform-checklist gives the same 8 problems at base 6d7f4df and at head ec744f7, all outside this card's rows. They are 5 ABSENT SYMBOL in access-security.public-form-withdrawal-layers; 1 ABSENT SYMBOL in attachments-storage.attach-requires-parent-edit (attachment-access-hooks.ts#canEdit) plus that file's SYMBOL ANCHORS LOST (27 of floor 28); and 1 ABSENT SYMBOL in search.rls-both-personas (protocol.ts#countable). #23139 closed them not_planned",
"carrier: 承接者:无 · noted in the PR's Acceptance notes, not filed (a source read, not reproduced) · evidence: at objectui 1fb1ced the console's boot splash (apps/console/index.html installBootSplash) reads localStorage 'vite-ui-theme', while the shell's ThemeProvider stores under 'object-ui-theme' (packages/app-shell/src/console/ConsoleShell.tsx). From source, a user who picked Dark on a light-OS machine may get a light first frame. Dedupe words: boot splash theme key, vite-ui-theme object-ui-theme, first paint dark flash",
"carrier: the maintainer question already on automation.setup-packaged-automation-board acceptance[7] · noted, not filed · evidence: packages/platform-objects/src/system/sys-metadata-activation.object.ts says 'Reads stay open so operability surfaces can answer what is disabled here', while QA run #23163 measured a plain member's activation read answering 403",
"carrier: 承接者:无 · noted, not filed (recorded by the run as a fixture gap; whether it is a defect is not judged here) · evidence: QA run #23163 found runtime-authored actions are not joined into the served object's actions[], and its positive control was invisible too. records-forms.action-location-matrix and record-edit-undo now record it as a fixture precondition",
"carrier: QA run #23166's maintainer question on webhook-lifecycle A2 (in-org bulk events carry no organizationId) · noted, not filed · evidence: the shipped showcase_task_changed webhook materializes org-less, so auto-enqueuer.ts never hands it an organization-walled event, while Setup reads it active:true. The card's own row offers 'org-stamp the fixture' as the product-side option",
"carrier: 承接者:无 · noted, not filed (showcase fixture work, outside a checklist edit) · evidence: each item now records its stock-fixture precondition, and none has a tracking card. They are a packaged undoable update action, a packaged locations-less action specimen, distinct quorum holders (a seed line), a lockField on the gantt view, an optionsFrom global filter, a MessagingServicePlugin host with mandatoryTopics, and an org-stamped showcase webhook. Dedupe words: showcase fixture gap, packaged undoable action, locations-less specimen, quorum distinct holders"
]
}
objectstack-fleet commentedon Oct 13, 2026
Review: ACCEPT · PR #23278 (draft, head
ec744f7fd3,Part of #23169) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T14:05ZChecked on GitHub, not on the report's say-so.
RUNNER.md(one environment fact), +526 / −266, 792 lines.access-security.jsonand nocoverage.json, as the claim required while PR feat(plugin-security)!: retire the four security-catalog row objects (#15204 stage 8) #23222 is open.check-platform-checklist.mjs, no product code.documentation,size/landskip-changeset(QA data inside no package, with a positive control onpackages/spec).revision +1and one appendedhistoryentry naming the row, its run and the fields touched. That was asserted per save, as was that every untouched item parses identical to base. Two area recipes are corrected, with provenance recorded.1fb1ced36243, which is stillmain's pin;6d7f4df3c.dashboards.system-overview-live-countsA3: the source declares 9 widgets, and the server strips one on an unmetrequiresService.notify-inbox-deliveryA3-501: the knownGap the card assumed was absent, so it was added.record-edit-undonow carries an item-levelblockedannotation, hidden from default runs.pnpm check:platform-checklistreports the same 8 problems at base6d7f4df3cand at head: the sorted lines diff is empty, and none is in a touched item. That gate stays out of per-PR CI by the maintainer's decision (checklist-status.yml:18), and the watchdog owns those 8. Symbol anchors only rose, 716 to 725.ec744f7fd3: 29 green, 11 skipped, 2 running, none red. The seat arms auto-merge.access-security.share-link-landing-pageC3, after PR feat(plugin-security)!: retire the four security-catalog row objects (#15204 stage 8) #23222;platform-core.lifecycle-retention-sweepsteps[4], which waits on a maintainer ruling. It is posted on this card next.objectstack-fleet commentedon Oct 13, 2026
决策:空闲的生命周期清理(lifecycle sweep)该不该打日志 ·
domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T14:08Z一句话问题: 清单条目
platform-core.lifecycle-retention-sweep的 steps[4] 要求"空闲时清理不打日志"。但产品现在每次清理都会在 INFO 级打一行汇总,没东西可删时也一样。要么改清单,要么改产品。Governing text:
LifecycleSweepReport.swept的 docblock:"Policies applied, one entry per (object, policy)"。report.swept.length,每条已应用的策略都会推一项,删除数为 0 也算。实测(QA run #23166 C1,dev 已对照源码): 每次清理都打
[lifecycle] sweep: 18 policy(ies) applied, ~0 rows reaped, …。packages/objectql/src/lifecycle/lifecycle-service.ts的打印条件,只在真有行被删、分片、归档,或有错误、告警时才打四轴:
os dev下默认隐藏,运维要证明保留策略在跑,读的正是这一行。推荐 A。 若你更想要更安静的日志,B 也不贵,但应另加一个明确的存活信号,而不是靠沉默。
#23169 上其余可落的 57 行已在 PR #23278。裁决后由本席补这一行;
access-security那一行等 PR #23222。objectstack-fleet commentedon Oct 13, 2026
Landed (57 of 61 rows): PR #23278 →
99e944daf2(Part of #23169) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T14:17Zmain, 16/16 files equal the PR headec744f7fd3: 15 area files andRUNNER.md.pm:dispatchedremoved, for two rows:access-security.share-link-landing-pageC3. Its knownGaps[2] is stale: the signed_in audience now renders a dedicated "Sign in required" state. It waits for PR feat(plugin-security)!: retire the four security-catalog row objects (#15204 stage 8) #23222 (the refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage-8 PR), which editsaccess-security.json.platform-core.lifecycle-retention-sweepsteps[4]. It waits for the maintainer's ruling, decision6147446653(A: the checklist step is stale, recommended; B: the product is wrong).6146552291on [PM seat] domain:devx @ objectstack — 🟢 os-elon-musk · 由 os-elon-musk 账户的项目负责 #6023).objectstack-fleet commentedon Oct 13, 2026
Blocked-by: #23222
Blocked-by: the maintainer's ruling on decision 6147446653
Seat state line ·
domain:devxseat 1 · 2026-10-13T14:19Z: the two open rows each wait on one of the above (see 6147639530).objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:queue, one row ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T15:59ZBlocked-by: the maintainer's ruling on decision 6147446653 (only the
platform-core.lifecycle-retention-sweepsteps[4] row)#23222blocker has cleared. PR feat(plugin-security)!: retire the four security-catalog row objects (#15204 stage 8) #23222 (S8) merged tomainas66949b7729at 14:44Z, and it editedaccess-security.json. So theaccess-security.share-link-landing-pageC3 row can be dispatched now: its stale knownGaps[2] is corrected against whatmainrenders today.6146552291): tooling(pm): dispatch-gates' scratch-dir scan reads a.d.tsdeclarationexport function mkdtempSync(prefix: string)as a call site, so the full battery reds on main since PR #23273 #23294 (in flight), then release(next): the Version PR refresh fails with ENOENT.changeset/pre/changes.mdsince the 18.0.0-next.0 cut moved consumed changesets into.changeset/pre/, so no next.1 Version Packages PR can open #23282, then C3 #15204 docs sweep: ten content/docs pages still describe the four retired catalog row objects; draft now, land after stage 8 #22976, then this row.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 17 (serial) ·
domain:devxseat 1 · 2026-10-13T19:13Z · the one row of this card unblocked by PR #23222 (6149680011)Session:
session_012zwsLMxQBwHUYJgPyrpEvxAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23169-share-link-landing-rowWorktree:
objectstack-issue-23169bDomain:
domain:devxSeat:
domain:devx#1File surface:
docs/qa/platform-checklist/areas/access-security.json, itemaccess-security.share-link-landing-pageonly, using the same edit discipline as PR #23278 (revision +1 and one appendedhistoryentry). ⛔ No other item, nocoverage.json, nocheck-platform-checklist.mjsand no product code. ⛔ Theplatform-core.lifecycle-retention-sweeprow is not included; it still waits on decision6147446653.Container & model:
S,mode:subagent,model: opus(the default judgment tier)Clause-②: no (QA data)
Responsibility: the item's recorded knownGap says the
signed_inaudience falls to the password prompt. The console now renders a dedicated "Sign in required" state forSIGN_IN_REQUIRED, and the item itself asks to be revised when that happens. No platform path covers this: checklist rows change only by hand. A runner reads a fixed gap as an expected failure.Thread-read: 6149680011
Serial constraints cleared:
docs/qa/platform-checklist/areas/cli.json, a disjoint file. No other open PR touchesaccess-security.json; I read the file lists of all open PRs at this act.6153165283) and armed. This is therefore the seat's only dispatch in flight (serial order6146552291).objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{
"issue": 23169,
"status": "done",
"branch": "claude/issue-23169-share-link-landing-row",
"pr": "#23327",
"session": "session_012zwsLMxQBwHUYJgPyrpEvx — subagent of the PM seat domain:devx#1 (the parent's id, as the commit's Claude-Session line and the relay's container derivation name it)",
"premise_still_valid": true,
"summary": "Landed the access-security.share-link-landing-page C3 row (QA run #23163) as draft PR #23327 (Part of #23169, Clause-② line copied from the claim, assignee zhuangjianguo, skip-changeset read back). The stale knownGap is at JSON path .items[27].fixtures.knownGaps[2] of docs/qa/platform-checklist/areas/access-security.json (knownGaps sits under fixtures, not at top level). The item goes revision 1 to 2 with one appended history entry. knownGaps[2] becomes a FIXED regression row, acceptance[3] (the item's clause 4) asserts the 'Sign in required' state instead of recording whichever state renders, and variants[5] names it. Both sides were re-read from source and agree: objectui at the pin 1fb1ced (still main's .objectui-sha) reads a 401 by error.code (shared-record-shape.ts resolveGateOf) and renders 'Sign in required' with a Sign in link for SIGN_IN_REQUIRED, with pins in SharedRecordPage-11649.test.tsx and shared-record-shape.test.ts. Framework at base 87e902d: both resolve mounts (plugin-sharing share-link-routes.ts and the runtime dispatcher twin share-links.ts) answer 401 SIGN_IN_REQUIRED. No other item and no other field of this item changed. #23169 stays open for the lifecycle-retention-sweep steps[4] row (decision 6147446653), which is not touched.",
"tests": "Gates at head 88a65fb, the only commit on the branch, base 87e902d; origin/main moved one commit since (4d4040c), touching no checklist file, no .objectui-sha and no share-link producer. Each gate ran in its own process with its own log, and the exit code was read before any pipe. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 13 commands for 1 path. --ran with exit codes 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)'. Exit 0 for 12: check-ci-filter-parity 'OK: all 21 build input(s) …'; check-closing-keyword-parity 'OK (3 parsers agree on all 9 keywords …)'; its --self-test '40 assertions, 5 mutations … each driven to red'; check-comment-mask-corpus '8983 files, 0 disagree, 0 unparseable'; check:doc-formula-expressions '22 record-scoped formula example(s) across 474 files / 1391 TS blocks judged clean' (after pnpm --filter '@objectstack/lint...' build under os-verify-lock, slot issue-23169b-dev: VERDICT command-exit 0, 151 s held, 0 s waited); check:cross-package-test-inputs 'OK: 30 package(s) …'; check:doc-authoring '✓ doc authoring guard: 18522 customer-facing string(s) … clean'; check:driver-memory-census 'OK'; check:gitlink-declared 'OK (11279 index entries …)'; check:nul-bytes 'OK (scanned 11270 text file(s) … no raw ASCII control bytes)'; check:refd-timer-probe 'OK … 8977 source file(s) swept'; check:watch-hint-literal '73 declaration(s) …'. pnpm check:platform-checklist exits 1 with 'check-platform-checklist: 8 problem(s)' at base 87e902d and at head; the sorted ✗ lines diff empty (diff exit 0). The 8 are 7 ABSENT SYMBOL lines in access-security.public-form-withdrawal-layers, attachments-storage.attach-requires-parent-edit and search.rls-both-personas, plus the attachments-storage anchor floor; none is in the touched item. --anchor-census base (a temporary detached worktree at 87e902d, since removed) vs head: 724/741 resolved plus 10 residual on both, every per-file count identical, access-security 63. The edit was one scripted span-scoped replacement set: each anchor asserted to occur exactly once in the item and in the file; after the save the script asserted the 27 other items parse identical to base, the item changed only in revision/fixtures/acceptance/variants/history, and inside those only knownGaps[2], acceptance[3].clause/.verify and variants[5]; revision +1 and history = base + 1 entry. The new text carries no line number and no #symbol anchor. node scripts/checklist-select.mjs access-security.share-link-landing-page → '1 runnable item(s)'. skip-changeset: git grep 'docs/qa' -- 'package.json' exits 1 (no hit); positive control packages/spec/package.json carries a files field (dist, json-schema, …). No ablation or reverse verification: the change is ledger text only. CI on 88a65fb, read once after the label write: 40 check runs, 11 success, 11 skipped, 18 in_progress, 0 red (Test Core in_progress, Governed Surface Queue Guard success). Out-of-scope probe (finding 1): a throwaway test file in packages/plugins/plugin-sharing/src, run under os-verify-lock after pnpm --filter '@objectstack/plugin-sharing^...' build (VERDICT command-exit 0, 242 s held); the probe run VERDICT command-exit 1 with the expected assertion failure 'expected WRONG_PASSWORD not to be WRONG_PASSWORD'; the file was removed by an EXIT trap and git status --porcelain is empty at 88a65fb.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "3 relay dispatches (each POST /repos/objectstack-ai/objectstack/dispatches), executing 4 REST writes as objectstack-fleet[bot]: (1) pr_create, run 38457543926: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/23327/assignees (zhuangjianguo); body read back 9118 bytes sent and stored, identical. (2) labels_add via scripts/pm/label-write.mjs, run 38457664944: POST /repos//issues/23327/labels (skip-changeset); read back size/s, skip-changeset. (3) this os-dev-report comment via scripts/pm/post-stamped.mjs: POST /repos//issues/23169/comments. Plus git push (not REST): the empty-branch probe and one push ending at 88a65fb. Reads were header-less curl GETs through the container proxy (the card, its comments, run record #23163, PR #23278, PR #23327, check runs)",
"deviations": [
"The claim names worktree objectstack-issue-23169b as created from origin/main; it did not exist on disk, so this run created it (git worktree add --no-track, BASE 87e902d).",
"Commit trailers and the PR footer follow AGENTS.md (the model-free Claude-Session / Co-authored-by pair; the session-URL footer), not the harness reminder's model-named trailer and footer: AGENTS.md takes precedence.",
"The Clause-② line is copied verbatim from the claim ('Clause-②: no (QA data)'); scripts/pm/clause2-line.mjs readClause2Line reads it as declared no, arm null.",
"Out-of-scope work, for finding 1 only: a throwaway probe test file was written into packages/plugins/plugin-sharing/src and deleted by trap (never committed), after a 242 s locked build of that package's dependency closure."
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: named producer — objectui packages/components/src/share/ShareDialog.tsx at 1fb1ced sends an audience and a password in one create, and the public door GET /api/v1/share-links/TOKEN/resolve answers that link wrong, measured through plugin-sharing's registered resolve route on a real SqlDriver (:memory:) · evidence: a link minted with a password and audience signed_in, opened anonymously: no password → 401 NEEDS_PASSWORD; wrong password → 401 WRONG_PASSWORD; CORRECT password → 401 WRONG_PASSWORD; signed in with the correct password → 200. Cause: resolveToken (plugin-sharing share-link-service.ts) refuses on the audience before it checks the password, and the resolve route's probe (share-link-routes.ts) then answers from the row password-first, judging only whether a password was SENT; the dispatcher twin packages/runtime/src/domains/share-links.ts has the same arm order (source read). User-visible: the landing page says 'Wrong password.' for the right password and never offers sign-in. The arm order of a fix is the fixing lane's call: an answer that differs by password correctness before sign-in would be an anonymous password oracle. Fix lands in objectstack (both mounts) · dedupe words: share link password signed_in WRONG_PASSWORD; correct password answered wrong password; resolve probe password before audience; SIGN_IN_REQUIRED password-protected share link",
"carrier: 承接者:无 · noted, not filed — this item's untouched fields keep comma-spelled line ranges that no longer point at those code paths at objectui 1fb1ced (acceptance[1].verify SharedRecordPage.tsx,143-176; acceptance[2].verify ,178-186; knownGaps[1] and source[1] ,190-234). The comma spelling sits outside the line-citation grammar (scripts/symbol-anchors.mjs judges file:line), with 44 occurrences across areas/.json. In the PR's Acceptance notes."
]
}
objectstack-fleet commentedon Oct 13, 2026
Review: ACCEPT · PR #23327 (draft, head
88a65fb624,Part of #23169) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T19:52ZI checked the PR on GitHub and checked both sides of its claim against the source; I did not take the dev report's word for it.
docs/qa/platform-checklist/areas/access-security.json, +11 / −5, touching one item:access-security.share-link-landing-page.revision1 to 2, with one appendedhistoryentry naming the row, its run and the fields it touches.fixtures.knownGaps[2],acceptance[3].clause/.verifyandvariants[5]change. The dev's script asserted that the other 27 items parse identical to the base.size/s,skip-changeset(there is a positive control)..objectui-sha=1fb1ced36243, stillmain's):SharedRecordPage.tsx:97reads the 401 body throughresolveGateOf, and:192rendersSign in required. The pins areSharedRecordPage-11649.test.tsx:217andshared-record-shape.test.ts:90.main: both resolve mounts answer401 SIGN_IN_REQUIRED—plugin-sharing/src/share-link-routes.ts:440and the dispatcher twinruntime/src/domains/share-links.ts:325.Sign inlink withredirect=, no password input) instead of recording "whichever renders", exactly as the knownGap itself asked.pnpm check:platform-checklistreports the same 8 problems at base and at head; the sorted-lines diff is empty, and none of the 8 is in this item.checklist-select→ 1 runnable item.88a65fb624: 28 green, 11 skipped, 2 running, none red. The seat arms auto-merge.platform-core.lifecycle-retention-sweepsteps[4], which waits on decision6147446653.audience: 'signed_in', an anonymous open with the correct password is answered401 WRONG_PASSWORD, measured on a real SqlDriver. The landing page then says "Wrong password." and never offers sign-in.objectstack-fleet commentedon Oct 13, 2026
Landed: PR #23327 →
cc14657ede(Part of #23169) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T20:14ZBlocked-by: the maintainer's ruling on decision 6147446653
main,docs/qa/platform-checklist/areas/access-security.jsonis identical to the PR head88a65fb624.access-security.share-link-landing-pageC3 row is done. With PR docs(qa): 57 platform-checklist rows from the #23104 browser pass re-pointed to the product at the pin (#23169) #23278 that makes 58 of the card's 61 rows.pm:blocked, for one row:platform-core.lifecycle-retention-sweepsteps[4]. It waits on the maintainer's ruling6147446653: A, the checklist step is stale (recommended), or B, the product is wrong. Once ruled, it is a single-card dispatch under this seat's serial order (6146552291).domain:services, p2): a password-protectedsigned_inlink opened anonymously with the correct password is answeredWRONG_PASSWORD.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