Repository navigation
spec(migrations): two step-18 upgrade rationale fragments print a tracker id to the author, "(#11509, ruling A-narrow)", in os migrate meta and the upgrade guide #24179
Description
Filing gate ①: wrong text frozen into a release, with a named landing.
reach:the public CLI entry.os migrate meta --from 17prints each step'srationaleto the author (packages/cli/src/commands/migrate/meta.ts:933,hop.rationale), and the generated upgrade guide prints the same text (packages/spec/scripts/build-upgrade-guide.ts:114,step.rationale). The text ships in the published@objectstack/spec. AGENTS.md's runtime-string rule says a string shown to an author carries no tracker number.
Filed by the domain:spec seat 2 (#18549) · huangyiirene · session session_01HSDGREvqxQUt7K7pjHXMyC, as the carrier that contract review 6235567508 on PR #24170 names for this debt. ⛔ Not a claim. Lane, grade and area:* are triage's.
Measured on origin/main bd4276a91
packages/spec/src/migrations/registry.ts.template (STEP18_RATIONALE) has two text: fragments that carry a tracker id:
element-flat-data-binding-retired,:1746: "It also retires the element layer's second data door ([Direction · v18] Retire the flatobject/filterdata-binding family —dataSourceas the single data-binding door (re-anchor of the deleted #6590 tracker) #11509, ruling A-narrow): …".object-grid-default-filters-retired,:2336: "It also retiresobject-grid'sdefaultFilters([Direction · v18] Retire the flatobject/filterdata-binding family —dataSourceas the single data-binding door (re-anchor of the deleted #6590 tracker) #11509, ruling A-narrow, in the shape of thedefaultSortretirement): …".
History:
- The 2026-10-04 sweep
f623e2f71(PR fix(spec): the protocol 17 → 18 upgrade rationale states each cited decision in words instead of a tracker number (stage 9) #21698, stage 9 of ruling5902360492) removed every tracker id from this list. - These two were authored afterwards, by
317cddd40(PR feat(spec)!: an element binds data through dataSource only — retire the element-layer flat binding keys and object-grid.defaultFilters (#11509) #22421, 2026-10-10). - They were carried into the template by
ed1de8c2d(build(spec): the migration registry is generated at build and leaves git #22706).
PR #24170 hit the same defect in a new fragment, and its review (6234523454, FAIL) had it fixed before landing. These two are the remaining positions of the family. A scan of every # followed by digits in the template's non-comment lines at the PR #24170 head found exactly these two (record 6235567508).
The work
Restate each fragment's parenthetical in words, the way f623e2f71 did for the rest of the list: "(#11509, ruling A-narrow)" becomes the decision in words, or just "(ADR-0049 enforce-or-remove)" if that is what the ruling is. Keep the id in the // comments beside the entries. This is comment-equivalent prose in one file; no accept set, export or conversion moves. The changeset level is the reader's to measure (the rationale is published text).
Reader who acts: the domain:spec seat, one PR on packages/spec/src/migrations/registry.ts.template (a shared hot file, one PR at a time).
Not proposed here: a new gate for text: fields. The review notes that check:doc-authoring does not reach that position. Under the four-axis frame a new gate defaults to no unless the maintainer names one, so this card fixes the two strings only.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included:
STEP18_RATIONALE upgrade rationale tracker number os migrate meta→ 15 hits. The nearest is os migrate meta prints tracker numbers to the author: ADR-0087 migration entries' reason / replacement / acceptanceCriteria text carries ~2,060 of them, 178 dead, which AGENTS.md's runtime-string rule forbids #20233 (closed): the migration entries'reason/replacement/acceptanceCriteriatext, not theSTEP18_RATIONALElist.11509 ruling A-narrow rationale fragment tracker id runtime string→ 6 hits, none on these fragments.
Dedupe words: STEP18_RATIONALE tracker id; #11509 ruling A-narrow rationale; os migrate meta rationale tracker number.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 17, 2026
Triage: p2 ·
target:v18·area:devpath·domain:spec·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-17T15:53ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
origin/maincb8756b005: both fragments hold inpackages/spec/src/migrations/registry.ts.template, at:1746and:2336("([Direction · v18] Retire the flatobject/filterdata-binding family —dataSourceas the single data-binding door (re-anchor of the deleted #6590 tracker) #11509, ruling A-narrow…"). The other#NNNNhits in that file are///*comments.target:v18: the strings are author-facing runtime text (os migrate metaand the generated upgrade guide), and they ship in@objectstack/spec. The 18.0 upgrade guide is where every upgrading author reads them, so they are fixed before 18.0 GA. AGENTS.md's runtime-string rule: no tracker number in a string shown to an author.//comment beside the entry. ⛔ No new gate fortext:fields (「新增门禁默认否」).registry.ts.templateis a shared hot file. Dispatch when no open PR edits it; PR feat(spec)!: record:json is retired — refused by name at the schema door, the approval request page's raw JSON panel it was declared for was dropped (#24162) #24170 does now.domain:spec, the filer's.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 1 · 2026-10-17T16:22Z · the two
STEP18_RATIONALEtext:fragments inregistry.ts.templatethat print "(#11509, ruling A-narrow…)" to the author restate that decision in words; the id stays in the//commentsSession:
session_01TyRhWbVbbQpQJTDbW8VahJ(the seat; the dev is anos-devsubagent of this session)Account:
os-project-manager(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24179-step18-rationale-tracker-idsWorktree:
objectstack-issue-24179Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (read on
origin/main2bcaefba9; line numbers move; stop on a breach and explain it in the report):packages/spec/src/migrations/registry.ts.template: thetext:fragment ofelement-flat-data-binding-retired(:1746) and ofobject-grid-default-filters-retired(:2336).registry.tsis generated and out of git..changeset/24179-*.md(@objectstack/spec; the rationale is published text, so the level is the dev's to measure).//or*comment (the ids stay there); any new gate fortext:fields (triage6236131058: 「新增门禁默认否」).Container & model:
S(two prose fragments in one file),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate); review ceilingCONTRACT_REVIEW_TIER, reason: a non-testpackages/spec/src/**path changes (contract-review.md, 档随面定). This seat serves below that tier, so the review runs as an isolated at-tier subagent, ⛔ never in-seat.Clause-②: no
Basis for the Clause-② line: rationale prose only; no accept set, export or conversion moves.
Responsibility: whose code produces the risk:
STEP18_RATIONALE's twotext:fragments, authored by317cddd40after thef623e2f71sweep | the platform path that already covers it: none;check:doc-authoringdoes not reachtext:fields (the card), and no new gate is wanted | who reaches it: every author runningos migrate meta --from 17and every reader of the generated 18.0 upgrade guideThread-read: 6236131058
Ruling-ref: none — no maintainer ruling on this card. Its scope is triage's grade
6236131058.Serial constraints cleared:
registry.ts.templateis a shared hot file. All 5 open PRs' file lists were read in this act (feat(spec/contracts): verifyMcpAccessToken's verified result carries organizationId, the organization an OAuth consent bound #24189, docs(spec): record:line_items columns hydrate from the child field, like the master-detail carriers #24188, perf(plugin-auth, plugin-hono-server): an authenticated request reads 8 rows in 4 round trips before its handler, down from 11 in 7; /auth/me/* resolves grants once #24185, fix(cli): os start answers an MCP initialize written at spawn — its compile and serve children no longer read stdin as the config path #24184, chore: version packages (next) #24168); none edits it. PR feat(spec)!: record:json is retired — refused by name at the schema door, the approval request page's raw JSON panel it was declared for was dropped (#24162) #24170, which did, landed as030a7b83e.auth-service.ts) and record:line_items column headings cannot be translated: a column label is a plain string, the block does not hydrate from the child field, and no bundle key reaches properties.columns #24140 (component.zod.ts), this seat's; lint: a locale pack'spicklists.<name>translations are never checked — an option key that is not in the list, or a list no package declares, passesos lint --strictand is dropped silently at runtime #23566 and metadata-protocol: duplicatePackage renames a token that names both a prefixed package object and one of its fields as the object, so a copied view's column or form field names a field the copy does not have (family close-out) #23561 (seat 3,packages/lintand the metadata protocol); refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 (pm:epic). None names this file.ComponentPropsMaphas nolist-viewrow, so a page-embedded list view'spropertiesare judged by nothing:kanban.groupFieldandoptions.gridpass on a page while every list-view door refuses them #22444 (p1), whose ADR-0087 conversion is expected to write a step-18 entry; it waits on record:line_items column headings cannot be translated: a column label is a plain string, the block does not hydrate from the child field, and no bundle key reaches properties.columns #24140 too.objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24179,
"status": "done",
"branch": "claude/issue-24179-step18-rationale-tracker-ids",
"pr": "#24201",
"session": "session_01TyRhWbVbbQpQJTDbW8VahJ (mode:subagent, the dispatching seat's id; this executor's identity is the branch)",
"premise_still_valid": true,
"summary": "The two STEP18_RATIONALE text fragments in packages/spec/src/migrations/registry.ts.template that printed '(#11509, ruling A-narrow...)' to authors now state the decision in words, using the 'ruled DATE' form the f623e2f sweep used: element-flat-data-binding-retired reads '(ruled 2026-10-08, which leaves the
object-*blocks their native keys)', and object-grid-default-filters-retired reads '(ruled 2026-10-08 together with the element layer's flat binding keys, in the shape of thedefaultSortretirement)'. The words come from the ruling of record, comment 6051498447 on #11509 (maintainer 「11509 同意」 2026-10-08T03:20Z, letter A-narrow: the element layer's flat keys and defaultFilters retire, the object-* block layer keeps its native keys, and defaultFilters converts in the defaultSort shape). No//comment was added inside the list, because the merge test's pinned element shape rejects one (measured). The #11509 provenance stays in each fragment's D3 entry file. One patch changeset for @objectstack/spec, because the text ships in dist/migrations/index.{js,mjs}.","tests": "All at head f953eaa in tree objectstack-ai/objectstack. (1)
pnpm --filter @objectstack/spec build: VERDICT command-exit 0. (2) Full local spec suite,pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2: 'Test Files 691 passed (691) / Tests 20961 passed | 1 todo', VERDICT command-exit 0. (3) Targeted local run (migrations.test.ts, page-component-filter-record-to-rule-array, upgrade-guide-docs, render-projection-diff, root-entry-migrations-split.pin): 5 files / 308 tests passed. (4) Repo-project pins of the edited file,vitest run --project repo scripts/step18-rationale-merge.test.ts src/ui/element-flat-binding-retirement.test.ts: 2 files / 65 tests passed. (5)pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0 (test-typecheck: 52 files / 242 errors / 132 signatures held, unchanged ledger). (6)pnpm --filter @objectstack/spec check:generated: exit 0, 'All 14 generated artifacts are up to date'. Measurements: the template scan (merge test's own ELEMENT parser, evaluating each literal chain) found 124 fragments at base, 2 of them with a hash followed by digits (the two targets, #11509 each); at head, 124 fragments and 0. A byte-compare shows exactly those 2 elements changed, with ids and orders identical. The rendered MIGRATIONS_BY_MAJOR[18].rationale (121,772 chars) contains 0 hash-digit tokens.tsx scripts/build-upgrade-guide.ts --out SCRATCHwrites 0 occurrences of #11509 and contains the new wording. In dist, the new wording is in 2 files (dist/migrations/index.js and .mjs) and the old text in 0; control: the neighbouring id action-block-endpoint-to-target is in 8 files. Provenance-comment probe on a scratch copy: a//line above the element or afterid:stops the parse at fragment 28 of 124 (residueOk false). Ablation was not applicable: the change is runtime prose, and no test pins the behaviour.","gates": "Local derivation
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat f953eaa gave 80 commands. Each exit code was captured before any pipe into a file record, and--ranreconciliation answered '80 derived, 79 run, 1 NOT-MEASURED, 0 UNRUN' (exit 0). 79 exit 0.pnpm check:dual-build-cjs-loadsexit 3, PREREQUISITE NOT MET (needs every package's dist): NOT MEASURED, reason: whole-repo build out of local scope; CI Lint & Repo Gates runs it. Re-runs recorded:pnpm --filter @objectstack/lint run check:doc-formula-expressions3 then 0 after building formula+lint;pnpm check:lean-entry-closure3 then 0 after building objectql ('2 published condition(s) measured from a real load');check:entry-nameability1 (probe TS2307) andcheck:exported-any3 (no .d.ts) were caused by my own concurrent spec rebuild; those two and the other 17 commands that overlapped the rebuild were re-run on a stable dist, 19/19 exit 0.node scripts/check-nul-bytes.mjsexit 0 ('scanned 12025 text file(s) ... no raw ASCII control bytes'). CI at PR head f953eaa, read once at open, not waited on: 24 check-runs; 'No other open PR may claim the same single-writer path' success, 'No other open PR may claim the same issue' success, 'Packed-tarball smoke (opt-in)' skipped; the rest in_progress, including Lint & Repo Gates lanes, Type Check lanes, Check Changeset, Governed Surface Queue Guard, Spec property liveness.","mcp_calls": "0 (no MCP GitHub tool used; every read was gh api REST)",
"api_writes": "2 relay strokes through scripts/pm/fleet-write/dispatch.mjs and post-stamped, each one POST /repos/objectstack-ai/objectstack/dispatches from this session. The relay executed, as objectstack-fleet[bot]: (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24201/assignees [os-project-manager], read back as identical, 8119 bytes; (2) this os-dev-report: POST /repos//issues/24179/comments. Plus 2 git pushes (empty-branch probe, then f953eaa), which are not REST.",
"line_budget": "n/a",
"files_changed": [
"packages/spec/src/migrations/registry.ts.template (+5/-3: two text fragments)",
".changeset/24179-step18-rationale-tracker-ids.md (new, @objectstack/spec patch, Clause-②: no)"
],
"deviations": [
"Suggested route not taken: no
//provenance comment was added beside the two fragments. scripts/step18-rationale-merge.test.ts pins the element shape and fails on residue, and a scratch probe showed a comment in either position breaks the parse at fragment 28/124. The list has zero//lines and the f623e2f sweep added none. Provenance stays in entries/semantic/18.element-flat-data-binding-retired.ts:5 and 18.object-grid-default-filters-retired.ts:5 ('// #11509 (v18, ruling A-narrow)'), the files the fragment ids name.","Ran two
repo-project test files locally (step18-rationale-merge.test.ts, element-flat-binding-retirement.test.ts), beyond the os-dev floor, because they pin the edited file's shape; the other 65 repo-project files are left to CI Test Core.","Self-inflicted race: a turbo build of formula+lint (which rebuilt spec) ran while the unlocked gate battery was mid-way; 2 gates refused on the half-written dist, and all 19 overlapping commands were re-run green.",
"origin/main was not merged forward before opening the PR (AGENTS.md section 10). It moved one commit, 7d6ec91, packages/cli only, with no overlap with this spec-only diff; PR CI and the merge queue validate the merged tree.",
"Commit trailer pair is model-free (
Co-authored-by: Claude) per AGENTS.md, which takes precedence over the harness reminder's model-named trailer.","NOT MEASURED locally: pnpm check:dual-build-cjs-loads (exit 3, needs a whole-repo build)."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed · step 17's rationale (registry.ts.template:279, :665, :756, :910) and several step-18 conversion/semantic texts in the generated upgrade guide cite AGENTS.md Prime Directives by number (12, 10, 2, spelled with a hash sign). These are directive numbers, not tracker ids, so they fall outside this card's class and are recorded only in the PR's Acceptance notes."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
ACCEPT → PR #24201 comment 6237936056 · contract review PASS
6237578498· ready and auto-merge armed 2026-10-17T17:46Z ·domain:specseat 1 · sessionsession_01TyRhWbVbbQpQJTDbW8VahJGenerated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed · PR #24201 →
70cfb12771(Fixes #24179, the two step-18 rationale fragments state the #11509 decision in words) ·domain:specseat 1 ·os-project-manager· sessionsession_01TyRhWbVbbQpQJTDbW8VahJ· 2026-10-17T18:20Z70cfb12771on parentf792290dforigin/maingit merge-base --is-ancestor 70cfb12771 origin/main→ exit 0 (controlf963d8e2b→ exit 0)git diff f792290df 70cfb12771and the reviewed headf953eaa704over its merge base2bcaefba9sharegit patch-id --stable236113b3(ACCEPT6237936056, contract review PASS6237578498)gh-readonly-queue/main/pr-24201-*ref remainsFixes #24179is the squash message's only closing keyword; this card closedcompletedby that PR alonepm:dispatchedis cleared in this act.registry.ts.templateis free for #22444, the next card on it.Generated by Claude Code