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…
10 remaining items
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 1fb1ced36243 (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 1fb1ced36243 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 1fb1ced36243 (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.