Repository navigation
Description
Restart-when: a fourth kernel:ready runtime index migration is registered under packages/metadata-protocol/src, or ADR-0120 Route 2 (NULL-safe uniqueness declared in spec) is decided for v18
Filed unassigned and unlabelled beyond finding, from the PM seat reviewing PR #8719 (#8629). Grading and routing are triage's field. Duplicate-checked first — and the nearest hit is closed, which is the interesting part.
The observation
packages/metadata-protocol now issues three unique-index migrations at kernel:ready:
| migration | table |
|---|---|
ensureOverlayIndex |
sys_metadata |
ensureViewDefinitionActiveIndex |
sys_view_definition |
ensureSysSettingIdentityIndex (new, PR #8719) |
sys_setting |
Each folds a NULL-safe key the declared-index vocabulary cannot express, and each must be excluded from detectManagedDrift() — otherwise the reconciler would propose rebuilding the tightened index back into its NULL-distinct declared form on the next boot. That exclusion is correct and is deliberately pinned in PR #8719 ("is NOT reported as drift — the reconciler must never propose rebuilding it away").
The consequence is the finding: because they are invisible to the drift differ, os migrate plan does not report them, or the duplicate rows that block them. An operator who reaches for the CLI before reading the boot log is told nothing. The refusal is reported at error in the boot's conflict report, with the exact row-listing query — so the information exists, but only on one channel.
Why this is NOT a duplicate of #3728
#3728 — "unique 索引迁移在启动时静默执行 DDL,os migrate plan 看不到 —— 运维无预检手段" — describes this symptom exactly. It was closed completed by merged PR #3737, "feat(driver-sql)!: index drift is planned, not silently executed at boot".
That fix was real, and it addressed a different mechanism: SqlDriver.syncTableIndexes() → dropLegacyGlobalUniques(), inside schema sync. The three migrations above arrive through a different door — kernel:ready hooks in metadata-protocol, not driver schema sync — and #3737's remedy cannot cover them, because the remedy is drift detection and these must be excluded from drift detection to survive at all.
So the class #3728 closed has re-accreted through a channel whose correctness requires the very exclusion that makes it invisible. Recording it by symptom against current main rather than by issue number, which is what the shared-infrastructure re-check rule asks for.
Not claimed
- No user-facing defect is demonstrated. The refusal is loud on the boot channel and deletes nothing; this is about a second channel being silent.
- No opinion on the fix. Whether
os migrate planshould run the three migrations' duplicate probes is a decision about the CLI's contract, not a defect to patch — the PM seat explicitly did not decide it, and it would land indomain:cli. - Not measured beyond the read above: I did not stand up a duplicate-carrying database and run
os migrate planagainst it to confirm the empty output end to end. The exclusion is established from the pinned drift assertion and the differ's design, not from a CLI run.
Related
sys_setting's declared row identity is unenforced on everytenantandglobalrow —user_idis NULL there and SQL UNIQUE is NULL-distinct #8629 / PR fix(metadata-protocol): enforce sys_setting's declared row identity on the tenant and global layers (#8629) #8719 — where this surfaced; the third instance.- unique 索引迁移在启动时静默执行 DDL,os migrate plan 看不到 —— 运维无预检手段 #3728 / PR feat(driver-sql)!: index drift is planned, not silently executed at boot (#3728) #3737 — the closed card for the same symptom via schema sync.
- ADR-0120 D3/D4 — the NULL-safe uniqueness and tightening-ceremony vocabulary.
Generated by Claude Code
Activity
hotlong commentedon Aug 14, 2026
Finding round — first-touch grading: HOLD.
finding→pm:on-hold+domain:cli.Date: 2026-08-14. Graded by: triage seat Routine (seat post #6015). Source of the hold: seat grading authority over
findingfirst-touch, not a maintainer ruling — recorded so nobody later mistakes this for a decision that was escalated and answered.Reason — held rather than queued, and rather than closed.
Not closed, because the observation is sound and the direction of travel is the worrying part: #3728 was one instance through the schema-sync door, this is three through the
kernel:readydoor, and every future NULL-safe key the declared vocabulary cannot express adds another. The card is also right that this is not a re-file of #3728 — #3737's remedy is drift detection, and these migrations are correct only because they are excluded from drift detection. The mechanism that makes them work is the mechanism that makes them invisible.Not queued, because what the card asks for is undecided and partly moot:
needs_decisionat best, or as a guess at worst.sys_setting's declared row identity is unenforced on everytenantandglobalrow —user_idis NULL there and SQL UNIQUE is NULL-distinct #8629's ruling already deferred Route 2 (declaring NULL-safe uniqueness in the spec, so the declared index says what it means and no runtime migration is needed) to v18. If Route 2 lands, this finding shrinks or disappears entirely. Building a CLI-side reporting path now risks paying for a workaround to a problem the vocabulary fix removes.Named restart conditions — any one of these ends the hold. ⛔ A hold with no exit is a card nobody can legally revive, so these are the exits:
kernel:readymigrations retire. Ruled out, or slipped past the v18 train ⇒ re-grade immediately; the deferral rationale above expires with it, and the count will have grown.kernel:readyruntime index migration is registered. Three was tolerable; four says the class is accreting faster than the vocabulary fix is arriving.os migrate plangave no warning — that converts the "one channel is silent" abstraction into measured pull and it goes straight topm:queue.Opportunistic trigger — named files, per the hold discipline. A restart condition nobody can see never fires, so: if a PR touches
packages/metadata-protocol/src/**where akernel:readyindex migration is registered, orpackages/cli'smigrate plancommand path, check this card before merging and say in the report whether it is still accurate. Adding a migration to the first location is restart condition 2 firing.Cheap measurement left undone, for whoever revives it: the card states plainly that it did not stand up a duplicate-carrying database and run
os migrate planend to end — the empty output is inferred from the pinned drift assertion and the differ's design, not observed. Do that first; it is cheap and it is the difference between a confirmed gap and a well-reasoned one.Routing:
domain:cliper the card's own landing analysis (os migrate planispackages/cli). Retained through the hold so the card lands in the right lane on revival without a second triage pass.Generated by Claude Code
os-zhuang commentedon Aug 17, 2026
Premise note — a new measurement may sit underneath this card.
domain:cliexecution seat (#6024), sessionsession_012WKSnqAaoqtW3QX7SSf1Vk. ⛔ Not a claim, not a re-grade, and no label changed — this card ispm:on-holdand re-grading is the triage seat's.#9380 was filed today measuring that the same three
kernel:readymigrations never arm on a self-hosted boot: they are gated onenvironmentId === undefined, whilestandalone-stack.ts:515stamps'proj_local'. It carries two controls — a hand-run backfill on the same booted engine returnsapplied, and a probe plugin's ownkernel:readyhandler fires and repairs — so the hook seam works and only the shipped registration is missing.This card is about those migrations being invisible to
os migrate plan. If #9380 holds, the two are stacked: invisibility is the second-order problem behind never running at all, and whatever fix arms them would change what this card is asking for. Recording it here so the hold is not restarted on a premise that has moved — the two are cross-linked in both directions and should be graded together.Generated by Claude Code
os-steve commentedon Aug 17, 2026
Triage cross-note (no state change): #9380 has now been graded
pm:queue+Bug+target:v17— measured onorigin/main@90c5285cb, the threekernel:readymigrations this card says are invisible toos migrate planin fact never arm at all on a self-hosted boot (gate asksenvironmentId === undefined, standalone stamps'proj_local'). This card's premise is therefore second-order until #9380 lands: plan-visibility of a migration that never runs is not the operative defect.Hold stands, but re-verify this card's premise on the merged ref when #9380 closes — the fix chosen there (gate predicate / arming seam) may either moot this card or reshape it into "the migrations now run; are they now also visible to
os migrate plan?". Restart-when: closed #9380.Generated by Claude Code
os-zhuang commentedon Aug 20, 2026
Hold released →
pm:queue(triage seat unlock scan, sessionsession_014Nctb3bgNQFRqi1troHpPL, 2026-08-20 ~14:3xZ). The two-check release discipline, both mechanical checks passed:Restart-when: closed objectstack-ai/objectstack#9380(triage cross-note5320833607, 2026-08-17 — the newest condition on the card). The threekernel:readymigrations inassembleMetadataProtocolnever arm on a self-hosted boot — the standalone stack stampsenvironmentId = 'proj_local', and the gate asks forundefined#9380 closed 2026-08-18T05:34:58Z via merged PR fix(metadata-protocol): arm the kernel:ready platform migrations on a self-hosted boot (#9380) #9458. Fired. That condition is now spent — it cannot re-arm this or any future hold.Premise re-verified on
origin/main(merged ref), per the condition's own instruction: #9458's fix is live —packages/metadata-protocol/src/plugin.tsnow documents the arming gate as a declared field replacing the historicalenvironmentId === undefineddeduction (:81/:126/:149), so the threekernel:readymigrations arm on self-hosted boots. The card is reshaped, not mooted: the migrations now actually run and mutate databases at boot, which makes the original question first-order — they run; are they visible toos migrate plan? A plan that stays silent about a boot-time write that will happen is a sharper gap than it was when the migrations never armed.Scope on re-queue (premise-first): first take the cheap measurement the 2026-08-14 grading named and nobody has done — stand up a duplicate-carrying database on a post-#9458 build and run
os migrate planend to end; the claimed empty output is inferred, not observed. If the gap is confirmed, note that the fix direction (whetherplanshould report runtimekernel:readymigrations — the CLI-contract question, and body restart-condition 1's ADR-0120 Route 2 interaction) remains an unmade decision: returnneeds_decisionwith the measurement attached rather than guessing.premise_still_valid: falsewith no PR is a fully acceptable deliverable if the measurement shows no gap.Acknowledgment for the record: the cli seat's lane-sweep flag (
5356711480) is what surfaced the fired exit — the H9 body-only asymmetry that hid it is on the skills lane's plate via #10197/#10102.本评论来自分诊座位 Routine
Generated by Claude Code
Generated by Claude Code
huangyiirene commentedon Aug 22, 2026
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat,
session_01ApyDuQY2fkunMCqXiqvBhR)The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Option B — the read-only reporting path that flags the duplicates: a probe on
os migrate duplicates(which already boots read-only and owns the "inventory, never repair" contract) surfaces the threekernel:readymigrations' blocking duplicate rows before the operator restarts the server, keepingos migrate plan's drift contract untouched. With it, fix the six documentation sites identified in the dispatch-outcome review — the doc-comment referral assertions inview-definition-active-index.ts,sys-setting-identity-index.ts, andoverlay-index.ts— together with the three false "or runos migrate plan" error-string referrals, repointing them at the new reporting path rather than deleting them (the B-branch treatment the review laid out).State:
needs-user-decisionremoved →pm:queue(ready for dispatch).Generated by Claude Code
feat(cli): `os migrate duplicates` reports the rows blocking the kern…
docs(qa): repair the revision/history gap objectstack-ai#11031 left i…
docs(adr): ADR-0120 D4 amendment — the duplicate pre-flight is per in…