Repository navigation
docs(qa): 18.0 sweep anchor round 18 — approvals.record-page-decisions re-derived against the shipped record page, the packaged-automation board's Activation cell and 22 own-port boot respellings - #25018
Merged
objectstack-fleet[bot] merged 8 commits intoOct 21, 2026
Conversation
…ped record page The item described the record header's hand-written Approve/Reject (buildApprovalDecisionActions, a client-side canDecide), which objectui 99782f961 retired before both console pins. At the pin cf153eb2e535 the record page runs sys_approval_request's declared record_section actions through DeclaredActionsBar above the page body, each gated by its visible predicate over the server's viewer block. Steps, clauses, fixtures and sources are re-derived from that surface and from the server's declarations, viewer block and read gate; the off-slate admin's override framing gets its own step; the knownGap about the retired text is gone. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…own-port boot respellings automation.setup-packaged-automation-board steps[3] counted "31 On / 1 Off", but at the console pin the Activation cell's badge reads "Not running here", switch still checked, for an enabled flow the engine reports unarmed. The step now names the three readings and derives the default-boot count from the showcase's 32 declared flows (29 On, 2 Not running here, 1 Off). Three automation items named the own-port boot or its DB "isolated" (connector-dispatch-matrix, packaged-flow-subflow-disable-refusal, packaged-flow-clone-contract); they now name it by what it is. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
These texts named the own-port boot or its DB "isolated" in other words, which a runner can read as the isolated tenancy posture. They now name the boot or the DB by what it is: the run's own port and DB. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
These texts named the own-port boot or its DB "isolated" in other words, which a runner can read as the isolated tenancy posture. They now name the boot or the DB by what it is: the run's own port and DB. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
These texts named the own-port boot or its DB "isolated" in other words, which a runner can read as the isolated tenancy posture. They now name the boot or the DB by what it is: the run's own port and DB. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
These texts named the own-port boot or its DB "isolated" in other words, which a runner can read as the isolated tenancy posture. They now name the boot or the DB by what it is: the run's own port and DB. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
The 19 history rows were committed with a placeholder ref because the PR had no number yet. This swaps in #25018 and changes nothing else. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
Seat reviewACCEPT ·
This seat readies the PR and queues it with auto-merge. Generated by Claude Code |
objectstack-fleet
Bot
deleted the
claude/issue-24579-v18-sweep-round18
branch
October 21, 2026 01:28
This was referenced Oct 21, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #24579
Clause-②: no
Round 18 of the 18.0 sweep's wave anchor (claim
6304655523, PM loop round 33). It applies round 17's three carried checklist-text findings, PR #25003's out-of-scope findings as its ACCEPT6304389370and landing record6304641541carry them:approvals.record-page-decisionsre-derived against the record page objectui ships,automation.setup-packaged-automation-boardsteps[3], and 22 other texts that named the own-port boot or its DB "isolated".Only checklist text changes. 19 items in 6 area files each take one
revisionbump and onehistoryrow, and each row names PR #25003 and its finding. There is no product code, test, pin, changeset text orRUNNER.mdchange, no new item, and every item id is kept.93e6c1a5f8.origin/main62bc129308is merged in1fa304d42f. Its one commit touchespackages/clionly: nodocs/qa/**path and none of the sources these edits cite.cf153eb2e535(.objectui-shaonmain), withgit showfrom a full scratch clone (--is-shallow-repositoryfalse). objectui99782f961(objectui#3055) is an ancestor of the pin: exit 0. Control, the pin as an ancestor of99782f961: exit 1.revisionand the one new history row.#PENDING-24579R18, because a row'srefnames this PR and the PR had no number yet. The next commit on this branch swaps in this PR's number and changes nothing else. The gates are re-run on that head, and the report comment on qa(checklist): 18.0 release sweep anchor at 5b14b7f3 — re-point 5 red-row clauses + the wave's checklist-accuracy findings, fixture gaps and not-run handover (18 records) #24579 records them.1.
approvals.record-page-decisions(revision 3 → 4)At
cf153eb2e535the record page draws no header Approve/Reject.RecordDetailView.tsx(blob64a7c675e50d) mountsDeclaredActionsBar(blobf27b4ab0efff) above the page body whenever the record has a pending request. The dispatch record is the pendingsys_approval_requestrow, the location isrecord_section, andapproval_remindis excluded (recordApprovalActions.ts, blobf6aabe078ea0). The bar readssys_approval_request's declared actions and evaluates each one'svisiblepredicate, failing closed, against the row'sviewerblock. The server computes that block per caller (ApprovalService.attachViewers:can_act,is_submitter,can_override).useRecordApprovals.ts(blobb65a91f4a9a4) only reads, and holds nocanDecide.The steps, numbered from 1 as the item's own text numbers them:
steps[0])steps[1])approval-node.tspasses the run's trigger user assubmitterId;seed-approval-demo.tsADMIN_APPROVAL_POSITIONSsteps[2])buildApprovalDecisionActions, order -100 / -99,record_header)primary), Reject (destructive,danger), Reassign, Send back, Request info, Recall and Reply, in declaration order, each with adeclared-action-testid. Send reminder is excluded and Resubmit is hidden. Capture the approvals read and itsviewerblockRecordDetailView.tsx,DeclaredActionsBar.tsx,recordApprovalActions.ts;sys-approval-request.object.ts(the declarations and theirvisible)steps[3])lock_record: falseapproval-service.ts(lock_recordfrom the node'slockRecord);useRecordApprovals.tsrecordLockedByApprovalsteps[4])useConsoleActionRuntime.tsx(title fromlabel, description fromdescription);approval_rejectdeclares adescriptionand noconfirmTextsteps[5]):idis the request's id; the comment is in the body and on theGET …/:id/actionsrow; the bar draws nothing once no request is pendingapprovals-routes.ts(the decide and actions routes);DeclaredActionsBar.tsx(the row ridesparams._rowRecord)steps[6])approval_approveinsys-approval-request.object.ts; the flow'sneeds_execedgessteps[7])needs_execroutes to exec_review (positionexec, held by the admin), a new request withlock_record: true; inline edit hidden, and the approval band shows its locked stateBudgetApprovalFlow(edge e4,budget > 500000);resolveApprovalLock(objectuipackages/reactInlineEditContext.tsx)steps[8])approvals.canDecidefalse); not the dev adminFORBIDDEN, and the request stays pending; not the dev admin, who holds the overriderequest-read-gate.tsheader (participants and the override actor; the record-reader tier is off, and no showcase object declaresapprovalsVisibleToReaders);ApprovalService.decide;approvals-routes.ts(FORBIDDEN→ 403)steps[9], new)viewer(can_actfalse,can_overridetrue). The bar shows Override Approve / Override Reject / Override Reassign (amber,data-override-decision), no Send back or Request info, and a plain Recall and ReplyDeclaredActionsBar.tsxandapprovalOverride.ts(isOverrideDecision); the declarations'can_overridearmsThe clauses:
acceptance[0](screenshot)visibleover the row'sviewerblockRecordDetailView.tsx(its header-actions comment: no approval action is injected there);DeclaredActionsBar.tsxacceptance[1](network)descriptionand there is noconfirmText, so the runtime chains no confirmuseConsoleActionRuntime.tsx;sys-approval-request.object.tsacceptance[2](api)actionParams)commentparam and round-trips onto the/actionsrowapprovals-routes.ts;DeclaredActionsBar.tsxacceptance[3](screenshot)lock_recordand the band's locked stateapproval-service.ts;RecordDetailView.tsx(resolveApprovalLockgatescanEdit)acceptance[4](dom → api)approvals.canDecideis falsedeclared-action-*button renders, and a forged POST answers 403FORBIDDEN. The off-slate admin's Override framing is recorded separatelyApprovalService.attachViewersanddecide;request-read-gate.ts;DeclaredActionsBar.tsxThe item's other fields:
title: "Approve/Reject render in the record header; …" → "Approve/Reject render on the record page from sys_approval_request's declared actions; …". The intent (deciding an approval from the record page), the id and the priority (P2) are kept.fixtures.requires[0]now says that exec_review is reached only after manager_review approves, and that the admin holdsexecand submits each request.fixtures.requires[1]:buildApprovalDecisionActions→DeclaredActionsBarover the pending row,recordApprovalActions.ts, and the server's declarations.fixtures.knownGaps[0], round 17's note about the retired text, is removed. It was the only entry, sofixtures.knownGapsgoes.negative[2]: "Approve/Reject rendered on the header for a viewer who is not a pending approver (canDecide false)" → a declared decision action rendered for a viewer whoseviewerblock admits none.source[0]andsource[1]now citeRecordDetailView.tsxandDeclaredActionsBar.tsx(withuseRecordApprovals.tsanduseConsoleActionRuntime.tsx) at the pin.source[4](the declarations andattachViewers) andsource[5](the read gate anddecide) are added.source[2](the two pins) andsource[3](the flow) are unchanged.automatedis added. The item had noautomatedfield at the base: round 17 re-pointedsource[2]. Neither pin holds a clause whole at its layer. objectui'sRecordDetailView.approvalDeclaredActions.test.tsx(blob9519ae70f743) mounts the page in jsdom over a fetch double, with a hand-writtensys_approval_requestdefinition and the param dialog mocked.sys-approval-request.object.test.tsreads the declarations.2.
automation.setup-packaged-automation-boardsteps[3](revision 6 → 7)Old: "confirm every switch reads On except a flow authored status: 'obsolete' (showcase_approver_bindings, …), whose switch correctly reads Off — 31 On / 1 Off at QA run #24545's subject".
New: the Activation cell is read as two facts. The switch shows the activation flag. The badge beside it (
data-testidpackaged-flow-activation, with adata-readingattribute) reads 'On' for an enabled flow whose_statusrow carries nounboundCause, 'Not running here' with the switch still checked for one that carries one, and 'Off' with the switch unchecked for a disabled flow. On a default bootshowcase_scheduled_digestandshowcase_task_due_remindercarrydeployment_policy. Sources at the pin:packagedFlows.tsactivationReading(bloba85c96d28e5a) andPackagedAutomationPage.tsx(blobf4aa90e11d32). At the base:describeUnboundReason(service-automationengine.ts),FLOW_UNBOUND_CAUSES(specautomation-service.ts) and RUNNER.md's scheduled-work entry.The count is stated with its derivation from the 32 flows
allFlowsdeclares at93e6c1a5f8(examples/app-showcase/src/automation/flows/index.ts), each classified by its authoredstatusand its start trigger:api-triggered (1), all of which bindtype: 'schedule':showcase_scheduled_digest(interval),showcase_task_due_reminder(time_relative)status: 'obsolete':showcase_approver_bindingsThat is 29 On / 2 Not running here / 1 Off, and 31 On / 1 Off with
OS_AUTOMATION_SCHEDULED_WORK_ENABLEDexported. The 19 that bind agree with RUNNER.md's measured banner,32 flow(s) 19 boundon a default boot and21 boundwith the switch. Onlyobsoleteandinvaliddisable a flow (flowStatusDisabledin the engine), so the 10 flows with no authoredstatus(draft) are enabled. The step tells the run to reconcile against_statusrather than these digits.3. The 22 other "isolated" texts
22 respelled, in 21 strings across 17 items; 43 left. At the base, 65 non-history occurrences of "isolated" remained after round 17. Each one was read in its item:
isolatedtenancy posture (OS_TENANCY_POSTURE=isolated, "group/isolated", walled boots). They are untouched. One of them sits in an edited item:access-security.platform-owner-email-anchorsteps[0], "a walled posture (group / isolated)".dashboards.saved-report-ownership, its title) and "unroutable from the isolated env" (automation.flow-error-handling).At the head the scan reads 43 occurrences, which are those 41 and 2.
automation.connector-dispatch-matrixfixtures.requires[2]automation.connector-dispatch-matrixfixtures.knownGaps[1]automation.packaged-flow-subflow-disable-refusalsteps[6]automation.packaged-flow-clone-contractsteps[8]access-security.platform-owner-email-anchorfixtures.knownGaps[0]platform-core.boot-healthpreconditions[0]platform-core.seed-integrityfixtures.requires[0]platform-core.interrupted-migration-boot-reportfixtures.requires[1]platform-core.manifest-install-contractsteps[9]platform-core.manifest-install-contractsteps[9]platform-core.activation-ledger-registration-homefixtures.requires[0]platform-core.activation-ledger-registration-homesteps[1]objectstack dev, isolated port/DB)"objectstack dev, on its own port and DB)"platform-core.activation-ledger-row-contractfixtures.requires[0]platform-core.activation-ledger-row-contractsteps[0]platform-core.marketplace-install-local-lifecyclefixtures.requires[0]platform-core.runtime-config-boot-readfixtures.requires[0]platform-core.runtime-config-boot-readsteps[0]platform-core.lifecycle-retention-sweepfixtures.requires[0]platform-core.seed-mode-matrixsteps[7]records-forms.field-group-visible-whenfixtures.requires[0]records-forms.field-unique-enforcementfixtures.requires[0]studio-authoring.metadata-diagnostics-sweepfixtures.knownGaps[0]None of the 22 named RUNNER's canonical boot line, so each takes the "own port and DB" family of spellings, with "the run's own DB" where the text is about a teardown or a database. None of the 22 sits in a clause, and no posture text is touched.
Acceptance notes
title(it said "render in the record header"),fixtures.requires[0](exec_review is reached only after manager_review approves),negative[2](it namedcanDecide), the newsteps[9], andsource[4]–[5].automated.refonly for clauses a pin asserts whole at their layer. The item carries noautomatedat the base, because round 17 re-pointedsource[2], and neither pin holds a clause whole at its layer. So none is added.acceptance[4]'s oracle moves fromdomtoapi. The clause is the server's gate, and RUNNER.md rule 4 makes the server the authority. The UI absence is still read, after a screenshot.isOverrideDecisionleaves a lever the viewer holds through its submitter arm unframed (objectui#13225).Gates
The derived list is
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack. It is computed on the actual change set: 6 paths against merge base62bc12930, at head1fa304d42f. It gives 13 commands. Each one ran at that head with its exit code captured before any pipe, and each exited 0:node scripts/check-ci-filter-parity.mjs·node scripts/check-closing-keyword-parity.mjs·node scripts/check-closing-keyword-parity.mjs --self-test·node scripts/check-comment-mask-corpus.mjs·pnpm --filter @objectstack/lint run check:doc-formula-expressions·pnpm check:cross-package-test-inputs·pnpm check:doc-authoring·pnpm check:driver-memory-census·pnpm check:gitlink-declared·pnpm check:nul-bytes·pnpm check:platform-checklist·pnpm check:refd-timer-probe·pnpm check:watch-hint-literalThe same 13 were run before the merge, at
46f612b0a1. There, the first run ofcheck:doc-formula-expressionsrefused with exit 3, a prerequisite:@objectstack/formulaand@objectstack/lintwere not built. Both were built under the shared verify lock (VERDICT command-exit 0, held 11 s, waited 0 s), and the rerun exited 0. The--ranreconciliation reads "13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN" at both heads.No per-PR CI job runs
pnpm check:platform-checklist, so this local reading is its evidence:93e6c1a5f81fa304d42fThe four new anchors all resolve:
seed-approval-demo.ts#ADMIN_APPROVAL_POSITIONS,sys-approval-request.object.ts#approval_reject,approval-service.ts#attachViewersandapproval-service.ts#decide. No line citation is added.git merge-tree --write-tree origin/main HEADexited 0 against62bc129308. No open PR touchesdocs/qa/platform-checklist/: all 16 open PRs' file lists were read over REST, and the three with more than 100 files were read page by page, at 349, 367 and 235 files, each equal to itschanged_files. So there was no second merge-tree to run.There is no ablation, because no tested behaviour changed.
skip-changesetwas re-measured: nofiles[]entry of the 73 non-private manifests (86 trackedpackage.jsonfiles) reaches outside its own package or namesdocs/qa, and the repo root is private.Generated by Claude Code