Repository navigation
platform-checklist: revise the items the #23878 full run and the #23879 since:v18 run found stale (knownGaps, steps, fixtures, oracles, source anchors across 15 areas; no clause red) — ledger follow-up #24036
Description
Filing gate ①: a defect in the shipped QA ledger, with a named landing for each finding. The items below in docs/qa/platform-checklist/areas/*.json describe a product that has moved on, through their knownGaps, steps, fixtures, oracle shapes or source anchors. None of these makes a clause red. The six that did were #23950, which landed in PR #24000. Per checklist-test §4/§5, a checklist-accuracy finding is therefore carried on the wave anchor #23878, not extracted. This card is the one follow-up the #23879 report asked for (open question 1, option A: "a follow-up ledger card after #23878 closes, revising each with a history entry").
Reader who acts: the domain:devx seat owning docs/qa/platform-checklist/areas/**. For each item:
- revise it per
checklist-test§3: bumprevision, append ahistoryrow naming this card, and keepnode scripts/check-platform-checklist.mjsgreen; - re-run the item once (
checklist-testwith the item selector) wherever the edit changes a fixture, a step's request or an oracle; a pure wording fix needs no re-run.
Splitting the work by area file into several PRs is fine, with one writer per area file at a time.
Filed by the domain:devx seat 1 PM (seat post #6023) · os-sales · session_014eFvbvGK4FjXvscggDNTD4, at the close-out of the #23878 wave. ⛔ This is not a claim.
Sources (full evidence lives there)
- qa(checklist): run the whole platform checklist on main (selector
all, 272 items) and extract every new failure into its own card #23878 close-out 6216941109:- § "Checklist-accuracy findings", from the main runner: access-security, ai, search, api-backend, approvals, cli, integration-system, platform-core and records-forms. Some lines are cut at about 200 characters in that comment; where a line below ends early, re-measure on the item.
- § "The two PM-carried readings".
- The cloud slices' reports on qa(checklist): run the whole platform checklist on main (selector
all, 272 items) and extract every new failure into its own card #23878:- 6216199424: dashboards;
- 6216468427: automation;
- 6216550639: studio-authoring;
- 6216631966: identity-auth;
- 6216814713: attachments-storage, i18n and ux-conventions.
- The last sections of records QA run · area:i18n (5/5) · 2034975a · 2026-10-16 · 4 PASS / 0 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #23951 and QA run · area:ux-conventions (3/3) · 2034975a · 2026-10-16 · 0 PASS / 0 PARTIAL / 3 FAIL / 0 BLOCKED / 0 NOT-RUN #23953.
- The qa(checklist): no ledger item carries
since: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 report 6215306571,out_of_scope_findings: the stale existing items and the two carried readings.
Already landed or dropped (not in scope here)
- PR docs(qa): re-point six stale platform-checklist clauses across five items to the shapes their rulings shipped #24000 (platform-checklist: 6 clauses across 5 items pin shapes the product has since ruled away (found by the #23878 full run on 94114c1f) - re-point each (family card) #23950) landed:
ai.mcp-stdio-fail-closedclauses 6 and 1;- all of
cli.migrate-meta-codemod, r5, including the protocol-18 and step-8 notes; approvals.approver-resolution-matrixclauses 4 and 5, plus the team and manager fixtures;platform-core.shell-nav-personalizationclause 5;platform-core.activation-ledger-row-contractclause 4.
- PR docs(qa): re-point identity-auth.api-key-ui-lifecycle's revoke oracle to 403 API_KEY_REVOKED #24012 landed
identity-auth.api-key-ui-lifecycleA2 (403API_KEY_REVOKED). - Findings on those revised items that still hold on
mainfd0e72aare listed below, marked "(residual)". - Dropped as disproved: qa(checklist): no ledger item carries
since: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879's "platform-core.shell-nav-personalizationdrag reorder removed (unchecked)". QA run · area:platform-core (30/30) · 94114c1f · 2026-10-16 · 27 PASS / 1 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN #23939 drove pointer and keyboard reorder on clause 2, and both passed.
access-security
capability-declaration-lifecycle:sys_capabilityis no longer a registered object (GET /data/sys_capability→ 404OBJECT_NOT_FOUND), yet steps 7–8 still describe asys_capabilityupsert (qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 flags this too).- Step 3 says not to probe
/api/v1/actions/…, but the dispatcher's/actionsdomain is mounted at/api/v1/actions/:object/:action[/:recordId]and enforcesactionPermissionError. Name it as the surface to drive. - The REGRANT step edits
showcase_ops, which is now sealed (PUT /meta/permission/showcase_ops→ 403NOT_OVERRIDABLE, ADR-0126). Use a scratch or cloned set carryingshowcase.export_data.
record-share-grant-revoke(carried reading, confirmed): source[1] says the record-shares family is "registered inline, under no registrar of its own". In factregisterSharingEndpoints(packages/rest/src/sharing-routes.tsL101) registersGET/POST …/:id/sharesandDELETE …/shares/:shareId.crud-permission-matrix:- knownGaps[4] ("A1 is a KNOWN FAIL until [finding] The delegated-admin gate resolves an EMPTY subtree on a stock
objectstack devboot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057") is stale. [finding] The delegated-admin gate resolves an EMPTY subtree on a stockobjectstack devboot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057 closed on 2026-10-08; the seededsys_business_unitrows carryorganization_id, and the delegate's in-subtreesys_user_positioncreate answers 201. access-matrix.jsonhas 45 rows (41showcase_*plus 4 delegate ×sys_*). Fixtures, knownGaps and steps still say 47 rows and 6 delegate rows.
- knownGaps[4] ("A1 is a KNOWN FAIL until [finding] The delegated-admin gate resolves an EMPTY subtree on a stock
sharing-rules-widen:- The position-audience variant is confounded. The manager position binds
showcase_manager, which has readScopeorgonshowcase_contact, so the audience member sees non-matching contacts through depth (explaindecidedBydepth). - Step 7 / clause 5 (A13) says "edit a materialized share", but
sys_record_shareis get/list only (PATCH → 405). The editable seeded artifact is thesys_sharing_rulerow.
- The position-audience variant is confounded. The manager position binds
write-path-guards: the steps leave out wire shapes:createManytakes a bare JSON array, andupdateManytakes{records:[{id,data}]};- the bulk run stops at the first validation failure by default (later rows
NOT_ATTEMPTED), which clause 6's mixed-outcome step has to account for.
readonly-package-locks-studio, step 5:- The
POST /api/v1/packagesinstall door needs a manifest withtype(for exampleapp), or it answers 400VALIDATION_ERROR. - An object authored into the scratch base needs
sharingModel, or it answers 422security-owd-unset.
- The
fls-mask-and-strip, clause 3: it asks for the disabled state of three budget controls, but the edit form renders onlybudgetandspent.budget_remainingis a formula and is not on the form.audit-log-browser, clause 0: a fresh member is refusedsys_audit_logat object level (403), rather than being served an empty filtered list.share-link-landing-page: knownGaps[2] and history r2 say objectui1fb1ced36243is "still this repo's.objectui-sha". The pin is nowdaeb77fc84dd, and the behaviour still holds there.share-link-capability-tokens:- Clause 8 says public routes carry "exactly"
Vary: X-Share-Password, X-Share-Password-Encoding. Live answers appendOrigin(the CORS middleware), and authenticated routes carryVary: Origin. Reword it to "Vary includes". - qa(checklist): no ledger item carries
since: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 also marks the item stale against v18's combined gates; see the newaccess-security.share-link-combined-gates.
- Clause 8 says public routes carry "exactly"
sharing-rule-authoring-ui:- knownGaps[0] says four rules are seeded and none covers
showcase_contact. Stock serves two, one of them "Key-Account Qualified Contacts → Managers" onshowcase_contact(positionmanager). - fixtures/source cite objectui
plugin-sharing/src/sharing-plugin.ts#nav_sharing_rules, which does not exist atdaeb77fc. The Setup nav comes from platform-objects' setup app.
- knownGaps[0] says four rules are seeded and none covers
record-view-read-audit:- The install line logs at INFO and
os devdefaults towarn, so "boot log lacks install line" is vacuous on a default boot. The steps should setOS_LOG_LEVEL=info. - The configured half has no stock fixture. A scripted scratch-copy recipe is worth adding: symlinked
node_modulesplus@objectstack/plugin-auditand@objectstack/platform-objects.
- The install line logs at INFO and
platform-owner-email-anchor: the step order runs the malformed variant while M is still unverified, so its refusal cannot be told apart from the unverified arm. The well-formed-sibling check only bites once M is verified. Reorder the steps.public-form-intake:- Clause 1 speaks of "the server-stamped owner", but the landed anonymous row's
owner_idis null. The forged value is stripped either way. /forms/contact-usredirects to/_console/f/contact-us;/_console/forms/:nameis the authed internal route.- The heading showing the raw view name is product-side; see the end of this card.
- Clause 1 speaks of "the server-stamped owner", but the landed anonymous row's
activation-write-operator-gate: no API exposes the tenancy posture. The proof used was the boot banner line "Tenancy: single"; the item should name it.
ai and search
ai.mcp-validate-expression: fixtures and steps nameshowcase_task.est_hours, but the field isestimate_hours(est_hoursanswers "unknown field").ai.mcp-run-action-exposure-gate, step 1: it callslist_actionswithobjectName.list_actionstakes no arguments and refuses it with-32602(unrecognized key).ai.mcp-http-surface, clause 4: the tool list omitsresume_run, whichtools/listnow returns.ai.agent-tool-skill-metadata-roundtrip, clause 3: it says a GET with?mode=draftserves the active item or 404s. It now answers 400VALIDATION_ERROR"The mode query parameter is not supported by this endpoint".ai.mcp-stdio-fail-closed(residual):os startsign-in needs anOriginheader (403MISSING_OR_NULL_ORIGIN). This is a runner note for minting keys on the start boot.ai.skill-instructions-mcp-prompts, step "flip active, reload metadata": underos dev,/metaserves the built dist artifact, so a restart alone leaves/metastale against the MCP projection. Rebuild before re-listing.search.pinyin-flag-both-sides, clause 2: it listswfas an account initials form, butwfis 王芳, a contact. The roster numbers 48/47 are now 52/51.search.global-search-skips-unreadable: knownGaps calls pinyin OFF "the stock default". On showcase the flag defaults ON through the zh-CN locale.
api-backend
error-envelope-ledger, step 6: it usesoptions {atomic:false}.batch.zodstrips that, so the batch succeeds (200, creates a row). TheBATCH_NOT_ATOMICsample needs a top-levelatomic:false, asbatch-transactional-discoveryalready says.bulk-write-contract:updateMany/deleteManyare id-based (records[{id,data}],ids[]), so the steps' "where clause" body answers 400VALIDATION_FAILED.- The baseline member holds no
allowDeleteon the target object.
package-rest-lifecycle, step 2:- The manifest's
scope: 'custom'is invalid; the allowed values arecloud|system|project, and anything else answers 400. - The semver message reads "version must be a SemVer 2.0.0 string (e.g. 1.0.0, 2.0.0-beta.1)".
- The manifest's
route-ledger-live-parity: the REST ledger carries 18 families, sincereportswas retired (retire the saved-report stack —sys_saved_report/sys_report_schedule,/api/v1/reports,client.reports,IReportService, thereportscapability and@objectstack/plugin-reports(zero consumers; not thereportmetadata kind) #20102). "19 REST families" and the variants list are stale.server-timing-admin-gated: the span list total/auth/db/hooks/serialize is stale. The hono adapter emitsparse,db,serialize,handlerandtotal.rest-metadata-config-contract: the masking step namesshowcase_account, but no stock persona has FLS there. The stock FLS fixture isshowcase_project, whereclient_liaisoncannot readbudget/spent/budget_remaining.aggregate-contract-matrix: neither named restricted persona gives a differing visible set. Mei is refused 403 at the object gate, and Ada is VAMA. Usesearch:qa-contributor-bound-member.batch-transactional-discovery: the fixture saysshowcase_taskaccepts baseline creates, but a create needs the requiredprojectlookup.enforce-or-remove-authoring-gates: no concrete "silently-stripped-by-design display annotation" key is named, and none was found in spec docblocks. Name one, or drop the leg.retired-def-refusal:RETIRED_DEFSentries are schema-export definitions with no metadata-type binding or stack collection. "A stack that declares metadata of each sampled retired type" can therefore only be an invented key; reword the step.declarative-endpoint-execution:os buildreports "3 APIs" on stock showcase, while the fixture text names two.date-range-preset-matrix(from qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879): the rolling presets now end today.
approvals
approver-resolution-matrix(residual): the fixtures still callapprover-bindings.flow.ts"a DRAFT designer specimen, not a runnable fixture". Draft flows fire their triggers, so everyshowcase_field_zooupdate opens anadmin_rescuerequest. Reword this once app-showcase:showcase_approver_bindingsisstatus: 'draft'on the belief that draft "keeps it out of the runtime" — draft flows fire, so every showcase_field_zoo edit opens an admin_rescue approval request on the org admins #23965 settles the showcase flow.ooo-delegation-reroute: the knownGap "authoring the scratch flow needs a writable/scratch package" is stale.POST /api/v1/automationregisters a runtime flow on stock showcase. The same holds forapprover-resolution-matrixandstatus-mirror-field.record-page-decisions:- The both-sides clause should name a non-override persona: the dev admin sees Override Approve/Reject on a record routed away from them.
- The item's route
/apps/showcase_app/showcase_project/:idis not the served one; re-measure it.
pending-count-surfaces: knownGap The Account app's Notifications entry 403s for every non-admin — no permission set grants sys_inbox_message #7344 ("a plain member's notification count is structurally 0") did not hold. nina (contributor and finance positions) saw "2 notifications".per-group-signoff, clause 5: the wording ("actorId is a hint … regardless of any actorId") describes a silent override, but the server refuses a mismatchedactorIdwith 403 "cannot act as". Align the wording with the stricter behaviour.decision-action-matrix: request-info is approver-only (the admin got 403 after reassigning away), so that step needs the pending approver.email-action-token-door: the step "reassign the bound approver away first" needs the approver themselves or a from-slot. An admin reassign replaces the caller's slot, so the target token stays live.quorum-m-of-n: the drawer's "N eligible approvers" counts duplicate slots. That is product-side (approvals: the decision-progress line's "N eligible approvers" counts pending_approvers slots, so one person holding two slots is counted twice (5 eligible shown for 3 people) objectui#12781), with no ledger edit.
attachments-storage
attach-requires-parent-edit(from qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879): a non-reader outsider now gets 404.download-authz-both-sides, step 7: persona B never reaches the panel. The reachable shape is a stale panel after the grant is revoked.sys-file-status-pipeline, step 8 vs step 9: the hooked attach un-tombstones before any download.upload-session-abort, step 8: a bogus eTag list now answers 409 before the backend is called, sofailedis reachable only through the test seam.field-accept-maxsize-server-enforced, knownGaps WIRE-ENVELOPE and clause 2: the wire is now 400ERR_FILE_CONSTRAINTwith prose, not a sanitized 500.qa-scratch-authzrecipe, step 6: members hold no baseline grant on runtime-authored objects. Pin the three permission-set payloads; their bodies are in QA run · area:attachments-storage (9/9) · 2034975a · 2026-10-16 · 9 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23929.
automation
trigger-type-matrix,time-relative-triggerand RUNNER: the schedule and time_relative legs needOS_AUTOMATION_SCHEDULED_WORK_ENABLED=1; on a default boot both showcase flows are unbound by deployment policy. qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 flags the same, and also forplatform-core.notification-center.flow-node-type-matrix,flow-error-handling,packaged-flow-subflow-disable-refusal,connector-dispatch-matrixandflow-toggle-kill-switch: "POST a task, PATCH done" fails as written.showcase_taskrequiresproject, andstatus → doneis allowed only fromin_review(task_status_flow).trigger-status-contract, clause 3: theqa-flow-status-doorsrecipe'sqa_always_failsshould author anerrorMessage, ordetails.errorMessagenever appears.connector-dispatch-matrixand RUNNER:GET /automation/connectorsexposes nobaseUrl. The premise-guard step and RUNNER's self-URL fact point at a key that isn't there.packaged-flow-disable-durable, clause 2: the activation-ledger boot line logs at info, so the log corroboration needs--log-level info(dev defaults towarn).packaged-flow-clone-contract, clause 6: the automation: a cloned packaged flow reaches no Studio surface — the clone is stored with no package, and every Studio Automations rail lists only package-scoped flows #21332 expected-fail is stale. Studio/_console/studio/~org/automationslists and opens the package-less clone.flow-runs-page-test-trigger, step 2: the step names the label "Batch Task Reminders (Loop)", but the picker shows machine names. That is a product defect (console Flow Runs page: the flow picker shows only machine names — it reads the label from it.spec.label, but meta.getItems('flow') serves flattened items whose label is top-level objectui#12783), so leave the step as written.flow-node-type-matrix, http node: the stock owners need egress. Success was located on a self-pinging scratch flow; name that recipe.
cli
hook-body-extraction-gates: the clause 6 EXPECTED-FAIL has flipped. The default build prints "N handlers could not be lowered…" with per-hook reasons, and--jsoncarriesbodyExtractionWarnings. The title, the clause and the knownGaps ("invisible on a default build") are stale (qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879, 22853).build-own-contract, step 6 (排查「手抄 spec 清单 + "keep in sync" 注释」模式:一天内确认三例,全部曾静默漂移 #3786 undeclared key): as written this is now a hard refusal, because object, field, report and enable shapes are closed. The advisory is reachable only at a nested strip-mode site (for example a field'svisibleWhen) underdefineStack(…, {strict:false}).dev-automigrate-policy: the fixture and steps are stale.- A config-declared datasource named
defaultis refused bydefineStack. required: trueno longer makes a NOT NULL column (storage.notNull, ADR-0113).relax_not_nullisneeds_confirm, not safe.
- A config-declared datasource named
migrate-duplicates-inventory, step 5: the index recipe is stale.sys_metadatahas noorganization_id, andidx_sys_metadata_overlay_activeis(type,name,package_id,bundle_member).doctor-health-report: orphan-view staging needsdefineStackstrict:false. The default load refuses it, and doctor then skips config analysis.dev-boot-contract: the variant "config-declared default datasource" is adatasourceMapping {default:true, datasource: NAME}rule; a datasource literally nameddefaultis refused.scaffold-console-first-paint:- It probes port 3000, so runners confined to a port range must use
OS_PORT/-p. - The published scaffold serves its own console, so this item does not exercise the vendored
.objectui-shabundle.
- It probes port 3000, so runners confined to a port range must use
datasource-introspect-codegen: wiring the draft into a scratch config requires the manifest namespace to equal the draft object's prefix.scaffold-first-run(from qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879): skills now come from@objectstack/skills.
dashboards
cube-query, clause 0: the verify text says "the meta response'scubes[]entry", but the wire is a bare array underdata; there is nocubeswrapper (analytics.zod.ts).dataset-report-authoring, clause 5: "open_block totals + done_block totals == unfiltered totals" cannot be computed as written, because the blocks carry different measures. Reconcile it per measure.chart-type-matrixfixture requires[2]:- The compareTo probe needs a
dateRange. - On the stock seed the previous 90-day window is empty, so the item needs tasks older than 90 days.
- The compareTo probe needs a
system-overview-live-counts, clause 1: add a step that revokes or expires one session first.
i18n (record #23951 notes)
notification-localized-and-clears: knownGaps[0] and step 2 are stale.sys_user.localeexists, and the avatar switcher writeszh-CN.- The notify node has a per-recipient
templatepath. - Tokens use
{{ record.title }}.
studio-follows-app-localeandsurface-matrix: the cited "451 untranslated declared labels" is now 414 (scripts/i18n-coverage-baseline.json).studio-follows-app-locale, clause 0: the premise is wrong. The Studio object editor's strings come from objectui's metadata-admin catalogue, not the servedmetadataFormsgroup.surface-matrix:- variants[5] still marks the view-empty-state variant blocked(fixture), but it runs.
- acceptance[7]'s group counts are off: the spec declares eleven per-app and twelve platform groups.
- The
automated.refrevision is stale. - The dashboards and pages steps should name the translated widget key and a platform page.
identity-auth (report 6216631966)
- Mail capture in
self-service-password-reset,email-verification-loopandimplicit-account-linking-ownership:EMAIL_TRANSPORT_PROVIDERSis a const, not an env switch, andLogTransportlogs no body or link. Name thesys_emailrow (adminGET /api/v1/data/sys_email) as the capture oracle. self-signup-gate(step 6 / A4) andfirst-run-owner-bootstrap(step 8 / A4): on anOS_DISABLE_SIGNUPboot, an uninvited forge is refused first by the audience gate (403SELF_REGISTRATION_CLOSED). Only an invited address reaches the toggle (400EMAIL_PASSWORD_SIGN_UP_DISABLED). Say which address proves which door.self-signup-gate: the knownGap is stale. The open posture through the env door is now measured live.email-verification-loop:- A2: verify answers
{status:true,user:null}, so don't imply a user object. - A3: a consumed token for an already-verified user answers a silent 200.
- A2: verify answers
two-factor-verify-to-activate, A1 / step 3: the cookie-laneTOTP_NOT_ENABLEDbranch is unreachable over HTTP.two-factor-enrollment-reveal, A4:get-totp-urire-reveals the same secret. "Shown only once" holds only for backup codes; reword it or record that as accepted design.two-factor-backup-codes, step 8: it cites "step-5 regenerate", but the regenerate is step 4.api-key-ui-lifecycle(residual):showcase_taskreturns the same rows to member and admin, so it cannot discriminate; usesys_session.- The Integrations page is at
/_console/apps/com.objectstack.account/developer/integrations.
session-list-revoke:revoked_atandrevoke_reasonlive on therevokedview.- The owner's raw list includes their own tombstones.
workspace-org-switch: the sentinel-absent check holds only underisolated.invitation-scope-gates:- Step 7: cancel is owner/admin only.
- The invite affordance lives at
/_console/apps/com.objectstack.account/sys_invitation, which no nav entry links to.
org-membership-team-management, A4: name an org-membership-scoped oracle, becauseeveryonebaseline reads survive remove-member on thesingleposture.admin-lifecycle-operations: Impersonate is only in the Users list row menu.linked-accounts-social:sys_accountapiMethods are live[get,list,aggregate,export]; r4 onmainstill says['get','list'].link_socialis retired, so A3 cannot discriminate.- The callbackURL lands on the "All" tab.
sso-enforced-first-paint:- Step 5 is outside the console's watchdog, which covers only the hung sign-in request (20 s).
- The sign-up half of A2 cannot discriminate on invite_only showcase.
auth-method-matrix:- The no-SMS state needs
NODE_ENV=production. - Generic
oidcProviderssurface associalProviders[]of typeoidc, whilefeatures.ssotracks only@better-auth/sso. - Magic-link is off on stock (404).
- Generic OIDC is drivable with a localhost IdP.
- The no-SMS state needs
oauth-app-consent-loop, step 2:create-clientdefaults to typeweb, which refuses http and loopback redirect URIs. Use an https non-loopback URI.- Design observations to rule on, not edit:
two-factor-disable-lifecycle: an MFA-gated admin gets 403MFA_REQUIREDonPUT /api/settings/auth.two-factor-enrollment-reveal: the secret re-reveal noted above.
integration-system
job-scheduled-run:- Fixtures and steps do not name
OS_AUTOMATION_SCHEDULED_WORK_ENABLED. - acceptance[4] calls the
enabled:falseskip LOUD, but it logs at debug.
- Fixtures and steps do not name
notify-inbox-delivery, acceptance[4]: it says the dispatcher records the dead-letter. In fact emit refuses the delivery row up front (WARN "refused 1 delivery row(s)…"), and nosys_notification_deliveryrow exists.external-datasource-federated-read: OData$filteris refused with 400INVALID_FILTER. The JSONfilterparam andtopwork.email-template-render, knownGaps[1]: name the workable door, a scratch notify flow authored throughPOST /api/v1/automationthat lands insys_email.notification-preference-suppression, acceptance[4] "with locale fallback": the store ladder only walks down (en-US → en), so a recipient with no locale resolvesenand an en-US-only template row is never used. Author the fixture row at a locale the ladder reaches.flow-connector-picker: the picker is a native datalist that a screenshot cannot show open. Say to read it from the DOM.webhook-lifecycle: creating ashowcase_taskneedsproject.
platform-core
settings-hub-roundtrip:- steps[1]: on
os dev --seed-adminthe dev seed already writeslocalization.timezoneat tenant scope. - Clause 11 / steps[11] expect anon 403
SETTINGS_FORBIDDEN. The ADR-0056 D2 floor answers 401UNAUTHENTICATEDfirst. - Clause 7 names
sys_setting.value_enc, but global-scope secrets live insys_platform_setting.value_enc. - steps[3] has no stock observable for the analytics date bucket.
- steps[1]: on
metadata-authoring-roundtrip:- steps[1]: a plain PUT saves
state=active.?mode=draftis required, and view names must be qualified (OBJECT.view). - Clause 2: the create form is
/_console/apps/showcase_app/metadata/page/new, and Page type defaults to "list".
- steps[1]: a plain PUT saves
manifest-install-contract:- The steps use
scope:"custom", which is refused. - The legacy
engine.objectstackrange must be full semver (^17.0.0).
- The steps use
app-management-toggle, knownGap and clause 5: it is 403ITEM_LOCKED, notNOT_OVERRIDABLE. Delete shows an info toast onreset:false.shell-nav-personalization(residual): the favorites star is in the record header's More actions menu ("Add to favorites"), and nav pinning is under the per-entry More actions menu. There is no hover pin button and no star button.notification-center:GET /notifications?view=minerows carry nonotification_id.- The scheduled-digest fixture needs
OS_AUTOMATION_SCHEDULED_WORK_ENABLED(qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879).
activation-ledger-registration-home, acceptance[3]:sys_automation_runis a same-answer parity check (both undefined), not an anti-vacuity control.activation-ledger-row-contract(residual):- The 405
allowedset is[get,list,aggregate,search,export], not apiMethods['get','list']. - PRAGMA also lists a
__searchcolumn.
- The 405
packaged-object-extend-only, steps[2] (qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 too): theNOT_OVERRIDABLErefusal now reads "provided by a managed package and is sealed", in one sentence.marketplace-install-local-lifecycle:storageDirsits on the listing envelope, not on each entry.marketplace-console-honesty, steps[2] / acceptance[2]: reseed and purge are in the package Details page's "More install options" menu (objectui#11627), not on the Installed Apps list. The stale note is objectui#12684.lifecycle-retention-sweep: the knownGaps say there is no telemetry datasource on stock. Stockservenow provisions one (data.telemetry.db).seed-mode-matrix:- The seed body refuses a
namekey, and a scratch object needssharingModel. - Replace routing is at
seed-loader.ts~2650, not:2106.
- The seed body refuses a
settings-audit-secret-fingerprint: the non-secret digest is FNV-1a 32 (fnv32:) of canonical JSON, not SHA-256. Step 6, acceptance[4] and the N4 control must compute FNV-1a.keyboard-shortcut-surface: the settled inventory matches steps[3] atdaeb77fctoo; update the pin note.
records-forms
concurrent-edit-conflict:- (Carried reading, confirmed.) source[] cites
packages/rest/src/approvals-routes.ts#mappingforCONCURRENT_UPDATE→ 409. That map (L106–127) has no such row. The row is inpackages/types/src/data-error-classification.ts(~L1046), and the error class is inpackages/metadata-protocol/src/protocol.ts(~L2887). - Step 5 / acceptance[2] say "in B choose Reload". The modal-form dialog offers only Keep editing and Overwrite; Reload exists on the inline-edit
ConcurrentUpdateDialog.
- (Carried reading, confirmed.) source[] cites
validation-rule-type-matrix:- variants[3] says cross_field names
end_date, but the server targets fields[0] =start_date. - The write answer now carries
warnings[](qa(checklist): no ledger item carriessince: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879).
- variants[3] says cross_field names
adhoc-filter-sort-builder:- The toolbar filter and sort live in
sys_user_preference(objectui#12418), not inlocalStorage list-filters:…. - The negative should say whether
uf__sortcounts.
- The toolbar filter and sort live in
list-view-capabilities:- The console sends
filter/top/skip/search/sortwithout$. - The aggregate dispatch body carries
_selectedIdsat the top level, to/api/v1/apps/showcase/recalc. - Name a fixture with more rows than the page size.
- Export sits in the Display popover footer.
- The console sends
crud-roundtrip, negative[0]: the Lifecycle select cannot be emptied; use Account Name.field-type-matrix, clause 1: the richtext, markdown, html and code widgets are textarea-based by design. Say what counts.action-location-matrix, steps[3]: select a row before the toolbar dispatch.object-hook-lifecycle:- The
ctx.log.infooracles needOS_LOG_LEVEL=info. - An uncompilable condition is refused at authoring (422), so the fail-closed scratch must be runtime-unevaluable.
- The
predicate-relationship-traversal, acceptance[1]: the 400 carries the authored message, not the rule name.grid-personalization:- Column state and row height now also persist to a user-scoped
sys_user_preference. - Step 4:
summarizeFieldtotals are a kanban config; the grid shows counts. - Step 6 has no row-color authoring surface named.
- Column state and row height now also persist to a user-scoped
field-group-visible-when, step 2: the scratch needshighlightFields(for example['kind']) for the detail half to be observable.lookup-picker-create-new, step 6: the picker debounces, sending one request per settled term.import-job-undo-cancel: no showcase object hasname/email/status, so name the scratch object.field-unique-enforcement, acceptance[0]: on SQLite the object-naming sentences are indeveloperMessage; the user-facingerroris generic.cascading-multilevel-and-clear, step 2: the canonical URL usesshowcase_app, not the package id.conditional-rules-grid(QA run · area:records-forms (40/40) · 94114c1f · 2026-10-16 · 39 PASS / 1 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23949 note for the next author): the objectui pin asserts only the inline required flag. A client-blocked grid save still sends one batch, which the server refuses; this is by design, per the recheck 6218243967 item 13.
studio-authoring (report 6216550639)
org-override-registry-gate: the variants still say "field (… create open)", butfieldhas hadallowRuntimeCreate:falsesince meta-field-write-inert: an acceptedfieldPUT never reaches the object — a runtime-created field is storedvalid=trueand is absent fromfieldsforever #7893.metadata-diagnostics-sweep, clause 1: the envelope'slockis absent from the defaultGET /meta/TYPE/NAMEby design. NameGET /meta/TYPE/NAME/layersin the verify text.object-designer-roundtrip:- In a namespaced writable package the object must be
NS_repair_asset. /apps/com.objectstack.studio/…renders in Showcase chrome.
- In a namespaced writable package the object must be
draft-publish-lifecycle, clause 6:- "Changes · n" is now a numbered pill (objectui#12459).
- Stage the draft in a writable package.
packaged-automation-studio-lock:- Clause 1: the forged write answers 403
ITEM_LOCKEDorNOT_OVERRIDABLE, not 422. - Clause 2 / step 4: the reason is in
aria-describedbyand a tooltip, not in atitle(objectui#12303).
- Clause 1: the forged write answers 403
packaged-display-class-direct-edit:- The banner text is "This item is locked and cannot be edited or deleted."
- The showcase ships individual views, not a container.
system_overview/layersreportscom.objectstack.plugin-auth.
permission-matrix-editor-ux, clause 5: there are three read-only reasons, and the type gate is unreachable on stock.custom-page-source-tiers, step 8(a): the compile panel is reachable only for a page in a writable package that an app's nav references.doc-on-app-menu, knownGaps:daeb77fcis past the fork window.
ux-conventions (record #23953 notes)
write-feedback:- The knownGaps are stale at
daeb77fc: Save All toasts "1 row saved", Discard gives feedback, and Approve toastsApproved "EXP-2001". - acceptance[3] should admit "blocked in the browser, no request".
- The approvals and inline-edit variants name the wrong surfaces.
- The knownGaps are stale at
disabled-control-reason, knownGaps[1]: this is stale for Studio Publish and import Next, which are now keyboard-reachable with a description.labels-over-machine-names:- knownGaps[0] (objectui#11862) is mostly stale.
- Clause 3 does not say whether ADR references in server prose, or tracker ids in authored labels, count.
Not ledger edits (dispositions, so nothing is lost)
- Product defects found inside these sections:
- The public form page heading shows the raw view name. This is the same root cause as meta read: a view stored with no
labelis served withlabel= its qualified name (recheck_gate.default), invented by the read-side translator, so the console view tab shows the machine name #23967:GET /api/v1/forms/:slugserveslabel: match.view?.label, which is the machine-name fallback when no label is authored. It goes to meta read: a view stored with nolabelis served withlabel= its qualified name (recheck_gate.default), invented by the read-side translator, so the console view tab shows the machine name #23967 as a second surface. - The approvals "N eligible approvers" count includes duplicate slots: approvals: the decision-progress line's "N eligible approvers" counts pending_approvers slots, so one person holding two slots is counted twice (5 eligible shown for 3 people) objectui#12781.
- The Flow Runs picker shows machine names, because it reads only
spec.labelwhile listed items are flat: console Flow Runs page: the flow picker shows only machine names — it reads the label from it.spec.label, but meta.getItems('flow') serves flattened items whose label is top-level objectui#12783.
- The public form page heading shows the raw view name. This is the same root cause as meta read: a view stored with no
- From qa(checklist): no ledger item carries
since: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879's report (6215306571):- ADR-0131 C8 (
applyTenantScopestill carries.orWhereNull) is feat(spec,drivers,objectql,plugin-security):organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212's scope. That card is open and carries protocol 18. POST /api/v1/keysdropping unknown body keys is the documented whitelist, in the safe direction: by design.- The dormant
flow-start-admissionarm needs a third-party automation service withoutgetFlow, and the in-tree engine has one. Not filed. - The registry-id pin counts (12 of 72
MAJOR_18_CONVERSIONS, 297 of 38918.*semantic entries, and two retirements with no pin: the discard-overlay route15204-s7preandos meta resync15204-s6b2a) are a coverage input for the nextchecklist-authorsweep. - The plugin-audit reactions CHANGELOG line is changelog(plugin-audit): the published 18.0.0-next entry still says stored comment reactions "are not converted" and are gone after the upgrade —
os migrate comment-reactions(23281) converts them; amend the entry, not an erratum #23938. Changeset22360'ssys_positionwording could not be located onmainor in history, so it is unverified and not filed.
- ADR-0131 C8 (
Dedupe
- MCP
search_issueson objectstack-ai/objectstack, closed included, queryplatform-checklist revise stale items checklist-accuracy findings knownGaps full run follow-up ledger card: 260 hits, top 10 read. Onlyqa-runrecords (QA run · ai.mcp-stdio-fail-closed (1/1) · fb82f9b1 · 2026-10-16 · 1 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23995–QA run · platform-core.activation-ledger-row-contract (1/1) · fb82f9b1 · 2026-10-16 · 1 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23999 from PR docs(qa): re-point six stale platform-checklist clauses across five items to the shapes their rulings shipped #24000's re-run, and this wave's), plus platform-checklist: 6 clauses across 5 items pin shapes the product has since ruled away (found by the #23878 full run on 94114c1f) - re-point each (family card) #23950 (closed, its six red clauses), matched; no open ledger card covers these items. - Re-run at filing, sorted newest first:
platform-checklist revise stale items checklist-accuracy findings knownGaps ledger follow-up→ 247 hits, newest 8 read: theqa-runrecords QA run · ai.mcp-stdio-fail-closed (1/1) · fb82f9b1 · 2026-10-16 · 1 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23995–QA run · platform-core.activation-ledger-row-contract (1/1) · fb82f9b1 · 2026-10-16 · 1 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #23999, Audit log: confirm the sys_user_preference exclusion (#23804) reaches a published platform; HotCRM on 18.0.0-next.2 still logs every ui.recent write #23961 (audit-log exclusion, unrelated), and this wave's closed records and platform-checklist: 6 clauses across 5 items pin shapes the product has since ruled away (found by the #23878 full run on 94114c1f) - re-point each (family card) #23950. No open ledger card exists.git log fd0e72a..origin/main -- docs/qa/platform-checklist/areas/is empty, so no finding above has been fixed since it was measured. - The two PRs that touched these items since the run are docs(qa): re-point six stale platform-checklist clauses across five items to the shapes their rulings shipped #24000 and docs(qa): re-point identity-auth.api-key-ui-lifecycle's revoke oracle to 403 API_KEY_REVOKED #24012 (
git log origin/main -- docs/qa/platform-checklist/areas/). Their scope is excluded above.
QA-source: #23878 · wave close-out 6216941109 · checklist-accuracy
QA-source: #23879 · report 6215306571 · stale existing items
Activity
objectstack-fleet commentedon Oct 16, 2026
Correction to this card's last section, measured live 2026-10-16T21:27Z by the filing seat (
domain:devxseat 1 PM, seat post #6023 ·os-sales·session_014eFvbvGK4FjXvscggDNTD4)."The public form page heading shows the raw view name … It goes to #23967 as a second surface" is withdrawn. It is not reproducible on current
main, so no product card is owed.labelis served withlabel= its qualified name (recheck_gate.default), invented by the read-side translator, so the console view tab shows the machine name #23967 was closed by PR fix(rest)!: the /meta item and list reads serve a view stored with no label without an invented label #24013. That fix touched only the REST/metaread gate (packages/rest/src/meta-item-read-gate.ts). The anonymous form door instead readsp.getMetaItems({type:'view'})(rest-server.tsresolveFormBySlug), so the fix alone did not settle the question, and I measured it.maind731b89a,pnpm install --frozen-lockfile && pnpm build(75/75), thenexamples/app-showcaseobjectstack dev --seed-admin -p 47611on a fresh file DB.GET /api/v1/forms/contact-us→ 200 with keysslug, object, form, objectSchema.labelis absent,form.titleandform.labelare absent, andobjectSchema.labelis"Inquiry".labeland notitle, the console'sFormPagechain (payload.label ?? form.title ?? form.label ?? (objectSchema.label || object), objectuiapps/console/src/components/FormPage.tsx~L1434) heads the page "Inquiry", the object label, notshowcase_inquiry.contact.The
access-security.public-form-intakeledger bullet above still stands as written (owner_id null; the/forms/contact-us→/_console/f/contact-usredirect). Only its pointer to the heading is void.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Triage: grade,
documentation·priority:p2·pm:queue· the filer'sdomain:devxandarea:devpathstand · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T22:00ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
since: "v18"— author the v18 line's new and changed capabilities into the platform checklist, then run them #23879 report asked for.objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 14 ·
domain:devxseat 2 · 2026-10-16T22:54Z · triage grade6225515535(documentation, p2,pm:queue; the filer'sdomain:devxstands)Session:
session_016PVjjuVPte5XEJvaQx1E4tAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24036-ledger-a(half A; half B is onclaude/issue-24036-ledger-b, see File surface)Worktree:
objectstack-issue-24036-aandobjectstack-issue-24036-bDomain:
domain:devxSeat:
domain:devx#2File surface: the card's split by area file, one writer per file, with two
Part of #24036PRs.claude/issue-24036-ledger-a) covers these files underdocs/qa/platform-checklist/areas/:access-security.json,ai.json,search.json,api-backend.json,approvals.json,attachments-storage.json,automation.jsonandcli.json.claude/issue-24036-ledger-b) coversdashboards.json,i18n.json,identity-auth.json,integration-system.json,platform-core.json,records-forms.json,studio-authoring.jsonandux-conventions.json.docs/qa/platform-checklist/(for exampleaccess-matrix.jsonfor half A), the generated outputscheck-platform-checklistrequires, and theqa-runrecords of its re-runs.⛔ No product code. ⛔ No loosening a clause past its ruling. Stop on breach and explain it in the report. The seat closes the card when both halves have landed.
Container & model:
M,mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: "no path-derived mandate")Clause-②: no
Responsibility:
product changes since each item's last revision (sealed sets, retired objects, moved routes, new codes) that left knownGaps, steps, fixtures, oracles and source anchors describing an older product | none: check-platform-checklist reads anchors and symbols, not their truth | every checklist-test runner, who would re-derive or misread the stale linesThread-read: 6225515535
Serial constraints cleared:
6216376921on [PM seat] domain:devx · seat 2 — 🟢 os-sales · session_016PVjjuVPte5XEJvaQx1E4t · serial (maintainer) #20163). Nothing else is in flight in either seat; ci(rerun-safety): a truthful verdict, passes bounded by the job's time, and a card on a red night #23975 waits on approval with no dev running. These two halves are the two slots.packages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050 slice 11, draft) changes one line ofaccess-security.json, an anchor. It is not a single-writer path, and whichever lands second mergesmain. No other open PR touchesdocs/qa/platform-checklist/**. The file lists of all 16 open PRs were read at this act.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24036,
"half": "A (claim 6226218270: access-security, ai, search, api-backend, approvals, attachments-storage, automation, cli)",
"status": "done",
"branch": "claude/issue-24036-ledger-a",
"pr": "#24118",
"session": "session_016PVjjuVPte5XEJvaQx1E4t — the dispatching seat's session (subagent run); commits carry it in the model-free trailer pair",
"premise_still_valid": true,
"summary": "Half A revised 66 items across the 8 area files: access-security 15, ai 6, search 2, api-backend 11, approvals 8, attachments-storage 5, automation 10, cli 9. Each revision bumps revision, adds a #24036 history row and keeps check-platform-checklist green, and two findings were disproved with the reading recorded. Every revision that changed a fixture, a step request or an oracle was re-run once on main c91af8e with the console at objectui f8267df93aba. The re-runs cover two showcase boots, a scratch showcase copy, minimal scratch stacks and a create-objectstack@next scaffold, and are recorded in 8 qa-run records: #24104 access-security, #24105 ai, #24106 search, #24107 api-backend, #24108 approvals, #24109 attachments-storage, #24111 automation, #24114 cli. No clause failed in them. Disproved or routed: date-range-preset-matrix (no stale text); the doctor 'strict:false is required' claim held only for malformed view bodies; quorum-m-of-n is objectui#12781; flow-runs-page-test-trigger is objectui#12783; the public-form heading pointer was withdrawn by 6225030762. Left with reasons: the time-relative-trigger due-date sweep was not driven (only the binding leg was); the status-mirror-field returned/maxRevisions/cascade legs were not re-run; the platform-owner-email-anchor clause-6 unit pins were not run.",
"tests": "Re-run evidence is in the 8 qa-run records and in each item's #24036 history row. Pins run under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0 each): @objectstack/mcp src/skill-prompts.test.ts 12 passed; @objectstack/driver-sql sql-driver-unique-tenancy.test.ts + sql-driver-schema-drift.test.ts 38 passed; @objectstack/service-storage storage-routes.test.ts + tombstone-download-live-reference.test.ts 57 passed; @objectstack/plugin-audit audit-log-read-visibility.test.ts + .integration.test.ts + read-audit.test.ts 70 passed. No ablation: the diff is ledger JSON only, with no tested behaviour changed.",
"gates": "Local subset at HEAD 364c082 (after merging origin/main twice, no rebase). node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 13 commands. Each ran with its exit code captured before any pipe, all exit 0: check-ci-filter-parity, check-closing-keyword-parity, check-closing-keyword-parity --self-test, check-comment-mask-corpus, lint check:doc-formula-expressions, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:platform-checklist, check:refd-timer-probe, check:watch-hint-literal. The --ran reconciliation reads '13 derived, 13 run, 0 NOT-MEASURED' (a derived zero, every line carrying exit 0). node scripts/pm/check-governed-merges.mjs --branch claude/issue-24036-ledger-a exit 0: NOT governed, 975 changed lines. The control-byte self-scan of the 8 files matched nothing. PR check-runs at 364c082, read once with no waiting: success for Auto Label, Dogfood Regression Gate, 'Part-of PR must not also close its card', filter, 'The card this PR closes must claim this branch', Check Documentation Links, the two no-other-open-PR claim checks and Check PR Size; in_progress for Test Core 1-6, the Type Check and Lint families, Governed Surface Queue Guard and Check Changeset (the seat applies skip-changeset); the rest skipped by selector.",
"mcp_calls": "0",
"api_writes": "11 — 8x issue_create through scripts/pm/issue-create.mjs and the fleet-write relay (POST /repos/objectstack-ai/objectstack/issues, label qa-run): #24104, #24105, #24106, #24107, #24108, #24109, #24111, #24114, each read back byte-identical; 1x pr_create through scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/pulls, draft, plus POST /issues/24118/assignees with os-sales), body read back byte-identical; 1x os-dev-report comment through scripts/pm/post-stamped.mjs (POST /repos//issues/24036/comments). git push is not counted. No label writes, no PR body PATCH. Reads only otherwise: gh api GETs of #24036, #21332, PR #24118 and its check-runs.",
"files_changed": [
"docs/qa/platform-checklist/areas/access-security.json",
"docs/qa/platform-checklist/areas/ai.json",
"docs/qa/platform-checklist/areas/search.json",
"docs/qa/platform-checklist/areas/api-backend.json",
"docs/qa/platform-checklist/areas/approvals.json",
"docs/qa/platform-checklist/areas/attachments-storage.json",
"docs/qa/platform-checklist/areas/automation.json",
"docs/qa/platform-checklist/areas/cli.json"
],
"changed_lines": "+659 / -316 over 8 files (git diff --numstat origin/main...HEAD); PR #24054's anchor line in access-security.json untouched; no half-B file touched",
"deviations": [
"qa-run records are one per area selector (bare area name, so qa-rollup classifies them as area); 'partial' marks a scoped re-run where the clauses the revision touched were driven and passed and the rest were skipped as out of scope; all 8 titles parse in qa-rollup (run with NODE_USE_ENV_PROXY=1). The records stay open: closing or parking them is a write outside this budget, so close-out is the seat's",
"the two scaffold items were re-run from create-objectstack@next (18.0.0-next.2) rather than @latest (17.7.0), because the skills finding concerns the 18 line and @objectstack/skills is published only as 18.0.0-next.x",
"capability-declaration-lifecycle: the build-clause re-run was folded into its existing #24036 r4 history row (same PR, unlanded), not given a second revision",
"the system reminder's attribution lines (a model-named Co-Authored-By trailer and a different PR footer) were not used; os-dev.md's model-free trailer pair and session-URL footer were followed, as that reminder defers to the user's own instructions",
"worktree cleanup: every server this run started was stopped by its own PID and listener (ports 48731-48734 free, every recorded PID gone) before this report; node_modules removal and git worktree remove follow immediately after this comment is posted"
],
"open_questions": [
{
"question": "RUNNER.md (outside the card's file surface) still states two stale facts: the connector self-URL fact reads a baseUrl that GET /api/v1/automation/connectors does not carry (/meta/connector shows the build-time http://127.0.0.1:3000), and the scheduled-work notes predate the OS_AUTOMATION_SCHEDULED_WORK_ENABLED opt-in. Who revises it?",
"options": [
"A: a small follow-up docs edit by the seat owning docs/qa/platform-checklist/**",
"B: leave it until the next checklist-author sweep"
],
"recommendation": "A, because runners read RUNNER before any item and both facts send them to a key or a behaviour that is not there"
}
],
"out_of_scope_findings": [
"class: a · reach: public door
os migrate plan(also with --database-url) on a project whose primary store is a config-declared datasource routed by datasourceMapping {default:true, datasource: qa_main} printed 'Examined 0 managed table(s)', a PARTIAL plan and '[ObjectQL] Datasource qa_main mapped for object sys_metadata is not registered'.os devon the same config reported three drifts in that same file, and the drift warnings name 'os migrate' as the remedy. · evidence: minimal scratch stack on main c91af8e (rva/am scratch, see cli.dev-automigrate-policy r2 history); the plan resolved the right file ('the project config's default datasource qa_main') but composed no driver for it · Seam: runtime:resolve-project-database.ts readConfigDeclaredDefault → cli migrate plan stack composition (no driver for the declared datasource) · lands in objectstack · dedupe words: os migrate plan config-declared datasource datasourceMapping default examined 0 tables partial","class: a (user-visible) · reach: browser Home as a baseline member (and Ada Auditor): the 'Activity feed' card shows 'An unexpected error occurred.' because GET /api/v1/data/sys_activity?top=20&sort=-timestamp&filter=object_name-in-list answers 403, while the record page's activity panel renders a proper permission message for the same refusal · evidence: showcase boot on main c91af8e, console objectui f8267df93aba · Seam: runtime:/api/v1/data/sys_activity 403 → renderer: objectui Home activity feed card (generic error instead of the mapped permission copy) · dedupe words: Home activity feed unexpected error sys_activity 403 member",
"carrier: none · noted, not filed — on a stale os dev boot (dist older than sources, with the boot's own warning) the MCP prompts projection follows the source while GET /api/v1/meta/skill/NAME serves the stale dist, so the two surfaces disagree until a rebuild; dev-mode only and announced, recorded in ai.skill-instructions-mcp-prompts r2",
"carrier: the domain:devx seat (RUNNER.md owner) · noted, not filed — the RUNNER.md stale facts in open_questions"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Pointer for half A, from
domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-17T01:20Z · ⛔ not a claim and not an edit of this card's scope; one stale anchor in the file this card owns.docs/qa/platform-checklist/areas/access-security.json, item 14 (access-security.public-form-withdrawal-layers). Itsacceptanceverify prose (:1556at PR refactor(rest): move registerFormEndpoints into form-routes.ts (#23050 slice 11) #24054's head) namespackages/rest/src/rest-server.ts#registerFormEndpointsfor the code that reads the environment's view list and drops a withdrawn candidate.packages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050 slice 11) moves that body topackages/rest/src/form-routes.tsand re-points the item'ssourcestring only. The prose still resolves by name, because the private method stays as a stub, so it is not red.rest-server.ts#registerFormEndpoints→form-routes.ts#registerFormEndpointsin that sentence. Declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed: half A · the eight half-A platform-checklist areas are re-pointed at the current product ·
domain:devxseat 2 ·session_016PVjjuVPte5XEJvaQx1E4t· 2026-10-17T01:48Z50ccfa6697onorigin/main, merged 2026-10-17T01:46Z from the merge queueaccess-security,ai,api-backend,approvals,attachments-storage,automation,cli,searchunderdocs/qa/platform-checklist/areas/) have the same blob onorigin/mainas at the PR head364c08264c; 0 of 8 differPart of, so this card stays open andpm:dispatchedstays on while half B is in flight. The card closes when half B lands.checklist-test§5 with aParked-online naming each PARTIAL gap.domain:clipointer (6227883776): half A has landed, soaccess-security.jsonis no longer in flight from this card.origin/main, item 14's verify prose namingrest-server.ts#registerFormEndpointsis still correct, because the body has not moved yet.rest-server.ts#registerFormEndpoints→form-routes.ts#registerFormEndpointsin that one sentence.sourcestring. That call is refactor(rest): move registerFormEndpoints into form-routes.ts (#23050 slice 11) #24054's seat's.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24036,
"half": "B (claim 6226218270: dashboards, i18n, identity-auth, integration-system, platform-core, records-forms, studio-authoring, ux-conventions)",
"status": "done",
"branch": "claude/issue-24036-ledger-b",
"pr": "#24141",
"session": "session_016PVjjuVPte5XEJvaQx1E4t (subagent: the parent PM seat's id)",
"premise_still_valid": true,
"summary": "Half B is landed as draft PR #24141: Part of #24036, Clause-② no, assignee os-sales. It revises 75 items across the eight half-B area files: dashboards 4, i18n 3, identity-auth 18, integration-system 7, platform-core 15, records-forms 16, studio-authoring 9, ux-conventions 3. Each item has a revision bump and a history row naming #24036; check-platform-checklist is green; no product code is touched. Every item whose edit changed a fixture, a step's request or an oracle was re-run once on an app built from this tree. 26 re-runs were filed as qa-run records #24074–#24125 before the PM's final ruling. The later 37 re-runs are evidenced in the PR body (item, clauses driven, verdict, oracle line) and filed no record. Re-runs that showed a still-stale clause were each fixed in place in this diff: validation-rule-type-matrix A4 code, object-hook-lifecycle steps[1], notify-inbox-delivery knownGaps[2], job-scheduled-run fixtures.requires[2], settings-hub-roundtrip A0/A1/A3, draft-publish-lifecycle steps[2], self-service-password-reset steps[1], org-membership-team-management steps[6]/A4 and linked-accounts-social steps[5]/A4. No re-run found a product defect in a clause it drove. Not re-run, with reasons in the PR body: identity-auth.workspace-org-switch (needs a walled-posture scratch boot) and identity-auth.sso-enforced-first-paint (needs an SSO-enforced boot with a provider). Partial re-runs: invitation-scope-gates (no delegated_admin persona), linked-accounts steps[1] (needs a provider), auth-method-matrix generic OIDC (needs a localhost IdP). One slice finding did not reproduce as worded: sys_account apiMethods still serve ['get','list']; only the aggregate and export routes pass the method gate.",
"tests": "Gate: node scripts/check-platform-checklist.mjs → 'check-platform-checklist: OK — 16 areas, 327 items (322 active, 1 planned) … symbol anchors: 852/862 resolved'. Re-runs: per-item scripts in the scratchpad (runs/*.mjs), each against an objectstack dev boot of examples/app-showcase from this worktree (port per boot, file DB). The identity-auth re-runs came after merging main and a full turbo build under the verify lock (VERDICT command-exit 0, 7m44s). Key oracle lines (full set in the PR body):\n- packaged-display-class-direct-edit: DELETE …/view/showcase_task.default and …/dashboard/system_overview 200 reset:true; post-reset sha256 b6a5a989… / 765c0c00… equal a pristine boot.\n- system-overview-live-counts: Active Sessions 197 = live COUNT 197, against unfiltered 199.\n- chart-type-matrix compareTo: invoice_count 7, invoice_count__compare 3 = literal windows 7/3; tile '133% vs previous period'.\n- dataset-report-authoring: est_hours 220+24=244, task_count 8+2=10; blocks render 220.0 / 2.\n- self-signup-gate: uninvited 403 SELF_REGISTRATION_CLOSED, invited 400 EMAIL_PASSWORD_SIGN_UP_DISABLED.\n- email-verification-loop: verify-email 200 {status:true,user:null}; consumed token 200 (silent).\n- org-membership: fresh session 403 USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION; old session revoked organization_membership_ended.\n- auth-method-matrix: NODE_ENV=production send-otp 400 SMS_SERVICE_REQUIRED; dev control 200.\nPins run earlier through os-verify-lock, each with Tests N passed:\n- dogfood packaged-activation-ledger-reach 11.\n- driver-memory unique 42. pins2's lock verdict is batch-last-exit, because the parts were sequenced with ';'.\n- service-messaging preference-resolver plus dogfood 4.\n- objectql lifecycle plus dogfood 6.\n- spec strictness batch20 and field-group-layout 8.\n- dogfood field-zoo 91.\n- metadata-protocol readonly-insert plus objectql 21.\n- metadata-protocol diagnostics 25.\nNo ablation: docs-only diff, no tested behaviour changed. Final head 8faaa0d; the gate union was re-run on it after the last merge.",
"gates": "Local, on head 8faaa0d. Derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, whose change set is 8 paths vs merge base c1c0a90, then 27d7c2a after the last merge (same 13 families). Each was run with its exit captured before any pipe:\n- node scripts/check-ci-filter-parity.mjs: exit 0\n- node scripts/check-closing-keyword-parity.mjs: exit 0\n- node scripts/check-closing-keyword-parity.mjs --self-test: exit 0\n- node scripts/check-comment-mask-corpus.mjs: exit 0 (9395 files, 0 disagree)\n- pnpm --filter @objectstack/lint run check:doc-formula-expressions: exit 0 (script name echoed)\n- pnpm check:cross-package-test-inputs: exit 0\n- pnpm check:doc-authoring: exit 0\n- pnpm check:driver-memory-census: exit 0\n- pnpm check:gitlink-declared: exit 0\n- pnpm check:nul-bytes: exit 0 ('no raw ASCII control bytes')\n- pnpm check:platform-checklist: exit 0\n- pnpm check:refd-timer-probe: exit 0\n- pnpm check:watch-hint-literal: exit 0\nReconciliation: --ran (lines 'CMD :: exit N') → '13 derived famil(ies) accounted for — 13 run, 0 NOT-MEASURED (a DERIVED zero)'. check-governed-merges --branch claude/issue-24036-ledger-b → 'NOT governed', 0 of 8 paths on the register, 1040 changed lines (+675/-365). CI on #24141, read once with no waiting: 36 check-runs = 20 success, 7 skipped, 8 in_progress (Lint · ESLint, docs & code guards, repo & tooling gates, CI/release & engine gates, among others), 1 failure: Check Changeset. That failure is expected for a docs-only diff, and the seat applies skip-changeset per the dispatch; this run wrote no labels. Already green: Lint · PM dispatch-gates, Lint · scoped · tooling self-tests. in_progress is the honest state at report time.",
"mcp_calls": "0 — no MCP GitHub tools used",
"api_writes": "28 REST writes, all through the fleet-write relay as objectstack-fleet[bot]; each stroke is carried by a POST /repos/objectstack-ai/objectstack/dispatches:\n- 26 × POST /repos/objectstack-ai/objectstack/issues: the qa-run records #24074–#24125, via scripts/pm/issue-create.mjs.\n- 1 × POST /repos/objectstack-ai/objectstack/pulls: draft #24141 with assignees [os-sales], via fleet-write pr_create, read back byte-identical (57040 bytes).\n- 1 × POST /repos//issues/24036/comments: this report, via scripts/pm/post-stamped.mjs.\nAlso: git push to claude/issue-24036-ledger-b several times (not REST). write-pace --announce-batch is local pacing, not a GitHub write. No label writes, no PR body PATCH, no other issue creation.",
"files_changed": [
"docs/qa/platform-checklist/areas/dashboards.json",
"docs/qa/platform-checklist/areas/i18n.json",
"docs/qa/platform-checklist/areas/identity-auth.json",
"docs/qa/platform-checklist/areas/integration-system.json",
"docs/qa/platform-checklist/areas/platform-core.json",
"docs/qa/platform-checklist/areas/records-forms.json",
"docs/qa/platform-checklist/areas/studio-authoring.json",
"docs/qa/platform-checklist/areas/ux-conventions.json"
],
"changed_lines": "+675 / -365 over 8 files (git diff origin/main...HEAD at 8faaa0d)",
"deviations": [
"Records: 26 one-item qa-run records were filed before the PM's mid-run rulings. After the final ruling ('file only when there is a problem') no record was filed, and none was closed: the seat does the close-out.",
"The identity-auth findings cite the #23878 slice report comment 6216631966, not a qa-run record, because no record backs that slice.",
"Merged origin/main twice more (a846933, 8faaa0d), never rebased. The re-runs before a846933 ran on the pre-merge build. The identity-auth re-runs ran after a full rebuild of the merged tree.",
"The first --ran reconciliation was mis-invoked: --commands together with --ran was refused, exit 2. The second recorded no exit codes. The third, with 'CMD :: exit N' lines, is the cited one.",
"Env-hygiene disclosure: while confirming that the production-mode boot carried NODE_ENV, I piped cat /proc/PID/environ through grep -c. Only a match count was printed, no value. Variable named: NODE_ENV.",
"To fit the relay's 60000-byte body cap, the PR body's per-item change lines are truncated at 210 characters. The full history rows are in the diff.",
"Not driven, as the dispatch allows for an oversize half: workspace-org-switch and sso-enforced-first-paint, with the partials listed in the summary."
],
"open_questions": [
{
"question": "ux-conventions.labels-over-machine-names A3: should an ADR number cited in user-facing server-built prose FAIL, or stay recorded and unscored as the clause now says?",
"options": [
"A keep recorded and unscored (status quo after this PR)",
"B score it FAIL like a tracker id",
"C allow ADR citations only in admin/diagnostic prose"
],
"recommendation": "A, until a maintainer rules: the re-run met no platform-built match, and changing the oracle is a ruling, not a ledger edit"
},
{
"question": "two-factor-enrollment-reveal: is a password-gated get-totp-uri that re-reveals the same TOTP secret after enrollment accepted design?",
"options": [
"A accept and record (the enable dialog's 'shown only once' covers backup codes only)",
"B treat as a defect: the secret should not be re-revealable after verification"
],
"recommendation": "A for the ledger (no copy is contradicted); B is a product security ruling for the maintainer"
},
{
"question": "two-factor-disable-lifecycle: an MFA-gated admin gets 403 MFA_REQUIRED on PUT /api/settings/auth — intended step-up or a lockout path?",
"options": [
"A intended step-up; record it",
"B defect; the settings write should accept the admin's verified session"
],
"recommendation": "A pending a maintainer ruling; recorded as a design observation, not edited"
}
],
"out_of_scope_findings": [
"class: a · reach: public door GET /api/v1/data/showcase_task/export?format=csv answers an empty 'Search Index' header column, and the console object designer canvas lists 'Search Index __search' as a Text field · evidence: GET /api/v1/meta/object/showcase_task serves the internal __search field; the Studio record-page highlights PUT seeds __search; the permission matrix lists showcase_account.__search readable/editable · Seam: spec:__search (internal search column) → runtime:meta object serializer + CSV export | renderer:object designer, permission matrix, record-page highlights · dedupe words: __search, Search Index column, internal search field exposed, export Search Index",
"class: a · reach: console /_console/apps/setup/system/marketplace/installed on a boot with a local install renders 'by zzcY4WkWgS0tzeWgo0L2WtE6HCBrVl1C' (a raw user id) · evidence: objectui InstalledListWidget.tsx renders marketplace.installedBy with entry.installedBy, the user id the install-local listing serves (admin GET /api/v1/marketplace/install-local) · Seam: spec:install-local listing installedBy → renderer:InstalledListWidget (objectui) · dedupe words: installedBy raw id, Installed Apps by user id, marketplace installed by",
"carrier: none · noted, not filed (PR Acceptance notes): HookConditionError surfaces as a generic 500 INTERNAL_ERROR; authoring into a never-created package id is admitted (by design, package-writability.ts); the showcase Quick View row action opens a 'Component Gallery' page; an API-created invoice line reads amount null; audit-log login rows carry the user id as Record ID under sys_session; the vendor redirect-URI refusal text reads 'https … on non-loopback hosts' for an https loopback URI too"
]
}
objectstack-fleet commentedon Oct 17, 2026
Landed: half B, and with it this card ·
domain:devxseat 2 ·session_016PVjjuVPte5XEJvaQx1E4t· 2026-10-17T04:00Z9ffe8af094onorigin/main, merged 2026-10-17T03:59Z from the merge queuedashboards,i18n,identity-auth,integration-system,platform-core,records-forms,studio-authoring,ux-conventionsunderdocs/qa/platform-checklist/areas/) have the same blob onorigin/mainas at the PR head8faaa0d5f; 0 of 8 differ50ccfa6697, landing record abovecompletedin this act andpm:dispatchedis removed.__searchsearch companion #24143, the__searchcolumn in a schema-derived CSV export.domain:clipointer6227883776(item 14 ofaccess-security) goes stale when refactor(rest): move registerFormEndpoints into form-routes.ts (#23050 slice 11) #24054 lands. The landing record above says who carries it.RUNNER.mdfacts.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Rulings on half B's two two-factor questions (
os-dev-report6229192520, open questions 2 and 3) ·domain:devxseat 2 ·session_016PVjjuVPte5XEJvaQx1E4t· 2026-10-17T06:24ZQuestion 2,
identity-auth.two-factor-enrollment-reveal: accepted as design.POST /two-factor/get-totp-uriis better-auth 1.7.3's own endpoint (plugins/two-factor/totp/index.mjs). It requires a session, plus the password whenevershouldRequirePasswordholds.POST /two-factor/disabletakes the same two.Question 3,
identity-auth.two-factor-disable-lifecycle: withdrawn by the seat. The governing text already rules it.MFA_REQUIREDonPUT /api/settings/authis ADR-0069 D3's enforced-MFA gate.plugin-authauth-manager.tsgates a user without TOTP enrolled oncemfaGracePeriodDays(default 7) elapses.AUTH_GATE_SCOPESdeclaresMFA_REQUIREDwith scopeaccount.Generated by Claude Code