Repository navigation
docs(qa): 18.0 sweep anchor round 16 — QA round 4's remaining checklist findings and round 15's carried rule-6 texts - #24963
Merged
objectstack-fleet[bot] merged 15 commits intoOct 20, 2026
Conversation
…boot console split, procedural negatives Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…ot-health console split, seed-mode prefix, procedural negatives Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…thout a clock wait Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…efusal arms read per RUNNER rule 6 Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…k to the unit pin Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…nd datasource-admin ref read per RUNNER rule 6 Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…r own layer, hosted-door pin named Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…cle, record-history spec object Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…he console pin Ledger text only; see the round-16 PR body for the per-finding table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…iners One environment fact, from QA run #24841. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…rm read per RUNNER rule 6 The item keeps one revision bump and one history row for the round; ledger text only. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…lder The 27 new history rows were committed with the placeholder ref; this swaps in the PR's number 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-round16
branch
October 20, 2026 19:27
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 16 of the 18.0 sweep's wave anchor (claim
6297142170, PM loop round 27). It applies three sets of checklist text. First, QA round 4's remaining checklist-accuracy findings (summary6288485402, records #24838 and #24841, framework307ce4c4). Second, round 15's carried rule-6 texts (PR #24891's acceptance notes). Third, round 14's two text fixes (report6289612504on PR #24857).Only checklist text changes. 27 items in 11 area files each take one
revisionbump and onehistoryrow, and each row names its record and finding.RUNNER.mdtakes one environment fact: two lines, the entry and its blank separator. There is no product code, test, pin or changeset text.feb09db14a.origin/main223ae939bbis merged in79a13e85b7. It touches nodocs/qa/**path and none of the sources these edits cite.revisionand the one new history row.#PENDING-24579R16, 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.What a negative is, and the 14 procedural negatives
A
negativenames a product outcome whose occurrence is the FAIL. The format documentation already defines it so: the README's item anatomy callsnegative"the other side of every gate (deny/absence cases)". SoRUNNER.mdtakes no line for it (ruling 3).Each of #24841's 14 procedural negatives was handled one of two ways:
steps. That is the schema's runner-procedure field ("how to exercise it"). There is no notes field, andtrapsis a closed vocabulary of trap names. The text is appended, so no step index shifts. Where the item already carries the same text in a procedure or notes field, the negative is removed and that carrier is named instead.automation.packaged-flow-disable-durablenegative[3]describeDisabledFlow)access-security.packaged-flow-write-door-paritynegative[1]/api/v1/automation/...answers 2xx on the artifact the/metadoor refusedaccess-security.packaged-flow-write-door-paritynegative[2]steps[6]automation.packaged-flow-subflow-disable-refusalnegative[2]steps[7]access-security.owd-save-gatenegative[2]fixtures.knownGaps[0]search.rls-both-personasnegative[1]steps[6]; the outcome it guards isnegative[0]platform-core.runtime-config-boot-readnegative[3]steps[6]cli.build-own-contractnegative[2]steps[9]cli.hook-body-extraction-gatesnegative[4]steps[6]cli.migrate-duplicates-inventorynegative[2]steps[9];negative[3]is nownegative[2], and nothing in the item cites either by indexcli.qa-suite-executionnegative[4]steps[12]platform-core.seed-mode-matrixnegative[2]steps[5]andacceptance[4]platform-core.seed-mode-matrixnegative[3]fixtures.requires[1], which now carries its reason tooplatform-core.marketplace-install-local-lifecyclenegative[5]fixtures.knownGaps[0]Two are (a) and twelve are (b).
Changes
feb09db14acli.organization-ownership-ceremonyacceptance[5],steps[5],fixtures.requires[2]added18.0.0-next.*database is refused at boot, takes the ceremony, and boots with its identity mail, global setting audit, pending mail jobs and declared webhook carried over. Each leg is read at its own layer: the boot output, a row read, the door's answer. The fixture is a database the pre-release's ownos devcreated, plus HTTP writes; without one the clause isblocked(fixture).organization-ownership-apply.tsSIBLING_MOVES: identity mail isrelated_objectsys_user plus the magic link, organization invitations stay, global audit moves. The mail-job rewrite coversemail.send.asyncandemail.attachment.reclaim. The oracle is #24838's measured matrix.platform-core.v18-boot-refusalsfixtures.knownGaps[0]addedacceptance[5]identity-auth.self-service-password-resetsteps[5]sys_verification.expires_atinto the past with node:sqlite, then expect 400 INVALID_TOKEN and an unchanged passwordauth-schema-config.tsAUTH_VERIFICATION_CONFIGmaps expiresAt toexpires_at. NostoreIdentifieris set, so the row is keyedreset-password:TOKENin plain text. better-auth 1.7.3'sconsumeVerificationValuetreats a row past expiresAt as invalid. The TTL isresetPasswordTokenExpiresInor 3600 s.cli.migrate-meta-codemodnegative[3],steps[11],acceptance[7].verify--jsonreports it aswrite.range.meta.tsprintWriteOutcome,printRangeOutcomeandwriteOutcomeJson(since #22252). The block also exists at QA's307ce4c4.cli.migrate-duplicates-inventoryacceptance[3].verifyregistry.tsregisterItemprints "Overwriting TYPE: KEY" for a held key, then "Registered TYPE: KEY" on every registrationplatform-core.seed-mode-matrixsteps[0]NS_SHORT. NS is the manifest's namespace, or one derived from the id's last segment. An unprefixed publish answers 422 NAMESPACE_PREFIX.namespace-prefix.tsvalidateObjectNamespacePrefixandderiveNamespaceFromPackageId. The package create inprotocol.tsderives a missing namespace, and the publish doors judge it (ADR-0129 D2).requirescli.build-own-contractsteps[3]requires: ['automation', 'triggers'], ordefineStackrefuses an auto-launched flow at loadstack.zod.tsvalidateTriggerCapability. The blank scaffold and the showcase both declare the pair, so the note covers a trimmed config.cli.dev-boot-contractacceptance[0](clause, verify, evidence),acceptance[7]added,fixtures.requires[2]re-pointedblocked(environment)on an unbuilt tree.console.tscreateConsoleNotBuiltPluginanswers 503 with "The ObjectStack Console is not built …"cli.dev-boot-contractsteps[9]added,acceptance[2].verifyresolve-project-database.tsreadConfigDeclaredDefaultreads the compiled artifact's{ default: true, datasource: NAME }rule and that datasource'sconfig.filename, resolved against the project root.dev.tscompiles only when no artifact exists.platform-core.boot-healthacceptance[3](clause, verify, evidence),acceptance[5]addedconsole.tsnegative(andsteps,fixtures.requires[1]where named)RUNNER.mdrsyncis absent; copy withtarorcp -acommand -v rsyncexits 1 here, whiletarandcpexit 0api-backend.packaged-action-disabled-dispatchfixtures.knownGaps[0]blocked(environment), with the pin beside itaction-activation-dispatch.test.ts"door 2" callsinvokeBusinessActionin-process over stubs, with no MCP transport and no HTTPautomation.packaged-flow-subflow-disable-refusalfixtures.knownGaps[0],negative[1]blocked(fixture)without a scratch callerflow-activation-ledger.test.tsruns over a fake storecli.datasource-introspect-codegenacceptance[0].verify,fixtures.knownGaps[2],steps[1]blocked(fixture), with the pins beside itremote-tables-twin.equivalence.test.ts(real Hono adapter), the service test,envelope-unwrap.test.ts(the CLI over a stubbed fetch)integration-system.connector-auth-kind-applicationacceptance[0].verify,fixtures.knownGaps[0]blocked(fixture), with the pin beside itrest-connector.test.tsinjects a fetch stub (fetchImpl)approvals.email-action-token-doorfixtures.knownGaps[0],fixtures.knownGaps[2]action-page-member.integration.test.tsruns a started kernel (driver-sql, in-memory SQLite) on a real Hono app and mintsttlMs: 1for the expired page.approval-service.test.tspins the reasons.approvals.act-door-and-admin-rescue-slatefixtures.requires[1],acceptance[1](verify, evidence),automated.refpackages/qa/http-conformance/src/hono-approvals-act.conformance.test.tscreateHonoApp→HttpDispatcher→ the realApprovalServicemember with a live token: "GET renders the confirm page for a live token; a form POST redeems it".approvals-act.test.tsuses a stub member.integration-system.datasource-admin-lifecycleautomated.ref;acceptance[3](verify, evidence);steps[8]acceptance[7],negative[4]andnegative[5]whole, and route-layer halves ofacceptance[0],[2],[4],[6]and[8]. The bind arm, once "scored from the unit pin", is nowblocked(fixture)with the pin beside it.registerDatasourceAdminRouteson the realHonoHttpServerover stubbed services and fake auth.datasource-credential-migration.test.tsdrives the planner over row objects.testoraclerecords-forms.field-unique-enforcementacceptance[4].clause,automated.refisUniqueViolationError, measured at SqlDriver throughcreateAsApi, never over a REST doorcreateAsApiand@objectstack/typesisUniqueViolationError; objectqlenvelopeUniqueViolation.acceptance[0]to[3]drive the REST door live, so no knownGaps line is owed.records-forms.crud-roundtripacceptance[4].verifyshowcase_account, the showcase'senable.trackHistoryobjecte2e/live/record-history-display.spec.ts, blob7ebc45106cffat the console pin616df6598b42studio-authoring.first-run-loopacceptance[0].verifystudio-pkg-chip,package-form-id-inputandpackage-form-submit, all declared at the pin, so it is citable when run theree2e/live/studio-object-designer.spec.ts, blob58a7f1cbf024; agit grepat616df6598b42finds them in app-shell'sStudioDesignSurface.tsxandPackageFormDialog.tsxItems left alone, with reasons
automation.trigger-status-contractsteps[5](QA run · t2:24681-touched (28/28) · 307ce4c4 · 2026-10-20 · 12 PASS / 16 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #24841): no longer holds. Revision 4 (docs(qa): 18.0 sweep round 12 — QA round 3's api and build checklist-accuracy findings outside cli.json: refs narrowed per clause, stale steps and wording corrected #24824) already spells{"inputs": {"new_assignee": "…"}, "output": {"$x": 1}}. Re-read at the base: the wizard's screen requiresnew_assignee, andrefuseInvalidScreenInputruns beforeapplyResumeSignal(engine.ts).identity-auth.self-service-password-reset, thesys_emailhalf (QA run · t2:24681-touched (28/28) · 307ce4c4 · 2026-10-20 · 12 PASS / 16 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #24841): no longer holds. Revision 4 (docs(qa): 18.0 sweep round 12 — QA round 3's api and build checklist-accuracy findings outside cli.json: refs narrowed per clause, stale steps and wording corrected #24824) movedrequires,steps[1],knownGaps[0]andacceptance[0]tosys_identity_email, and the remainingsys_emailmentions say "never sys_email".IDENTITY_EMAIL_OBJECTis'sys_identity_email'(email-log-objects.ts).cli.migrate-duplicates-inventory, the index-drop half (QA run · t2:24681-touched (28/28) · 307ce4c4 · 2026-10-20 · 12 PASS / 16 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #24841): no longer holds. Revision 9 (docs(qa): 18.0 sweep anchor round 13 — QA round 3 surface:cli findings in cli.json, plus three carried items #24850) already says to dropuniq_OBJ_organization_id_FIELDfirst (schema-drift.tsbuildIndexName).RUNNER.md, a line defining a negative: not added, because the README's item anatomy already defines it.os migrate applyfirst, thenos serve): not added.platform-core.v18-boot-refusalsscopes the refusal of a 17.x-shaped database and has no fresh-install clause, so it is a candidate for the anchor. The change ships in 18.1.0:@objectstack/cliis in the changesetsfixedgroup at 18.0.0,.changeset/24827-migrate-apply-birth-marker.mdisminor, and no pending changeset ismajor. It is unpublished at the base (npmlatestis 18.0.0).records-forms.crud-roundtripacceptance[6]: its readonly half says "Score that half from the pins inautomated, never as blocked(fixture)", under anapioracle, from a protocol pin over a stub engine and an engine pin. That is the rule-6 class, but it is not in this round's list, and changing a P0 clause's verdict rule is the anchor's call. Carried.cli.datasource-introspect-codegenautomated.refstill names "acceptance[0]'s NARROWING half ONLY". Under round 15's reading no pin holds a full clause, soautomatedwould go and a knownGap would replace it. The dispatch named the spelling only. Carried.records-forms.record-discussion-mentionsknownGaps[0]/personas[1](anchor comment6290946648, "a second signed-up user"): still present at the base, and not in this dispatch. Carried.studio-editor/form-view-subformswidening candidates, and round 12's 80 "showcase isolated" spellings.PM hypotheses, measured
platform-core.v18-boot-refusalsis the home, and the ceremony item takes a cross-reference." This does not hold.cli.organization-ownership-ceremony's title names "an 18.0 pre-release (18.0.0-next.*)" database, the moves, the webhook settlement and the boot that refuses or serves.platform-core.v18-boot-refusals' title names a 17.x-shaped database. So by the ruling ("the item whose scope it is") the clause sits in the ceremony item, and the boot-refusals item takes the cross-reference.Acceptance notes
automation.packaged-flow-subflow-disable-refusalnegative[1];cli.datasource-introspect-codegensteps[1]andfixtures.knownGaps[2];approvals.email-action-token-doorfixtures.knownGaps[2];approvals.act-door-and-admin-rescue-slateacceptance[1]andautomated.ref;integration-system.datasource-admin-lifecycleacceptance[3]andsteps[8];records-forms.field-unique-enforcementautomated.ref, whose sentence quoted the old clause wording;cli.dev-boot-contractfixtures.requires[2](re-pointed toacceptance[7]) andacceptance[2].verify.integration-system.datasource-admin-lifecycletook its edit in two commits on this branch. The net diff against the base is one revision bump and one history row.acceptance[5]rests on QA run · upgrade:ceremony (9/9) · 307ce4c4 · 2026-10-20 · 6 PASS / 3 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #24838's measurements and on the source. Itssteps[5], andcli.dev-boot-contractsteps[9], were not replayed live here.steps[9]says so.auth.emailAndPassword.resetPasswordTokenExpiresIn, and auth-manager.ts forwards it to better-auth. It was not used for the expiry step. Its plumbing from a stack config was not measured, it has no liveness row, and it would still need a wait.hono-approvals-act.conformance.test.tswas read, not run, here. The objectui specs were read at the console pin616df6598b42with a read-onlygit show. Their verdicts at the pin are NOT MEASURED.integration-system.datasource-admin-lifecycle: two pins are not in the ref,admin-routes-auth-guard.test.ts(the floor) anddatasource-route-ledger.conformance.test.ts(cited byacceptance[8].verify). Whether either holds a whole clause at its layer was not measured.Gates
The derived list is
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, computed on the actual change set: 12 paths against merge base223ae939b, at heade208b693b5. 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 first run of
check:doc-formula-expressions(at79a13e85b7) refused with exit 3, a prerequisite, because@objectstack/formulaand@objectstack/lintwere not built. Both were built under the shared verify lock (VERDICT command-exit 0, held 116 s, waited 0 s), and the rerun exited 0. The--ranreconciliation reads "13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN".No per-PR CI job runs
pnpm check:platform-checklist, so this local reading is its evidence:feb09db14ae208b693b5The ten new anchors all resolve, and the residual is unchanged.
git merge-tree --write-tree origin/main HEADexited 0 against223ae939bb, and again against19e5338cc8, which touches nodocs/qa/**path. No open PR touchesdocs/qa/platform-checklist/: all 16 open PRs' file lists were read in full, every page. So there was no second merge-tree to run.There is no ablation, because no tested behaviour changed.
skip-changesetwas re-measured:docs/qa/**appears in none of the 73 non-private manifests'files[](86 trackedpackage.jsonfiles), and the repo root is private.Generated by Claude Code