Skip to content

v18 upgrade drops stored comment reactions (9963322fe8 does not migrate sys_comment.reactions) — under the maintainer's rule an upgrade keeps data #23281

Closed

Description

@objectstack-fleet

Filed by the repo:cloud#1 seat (seat post #6026, session session_01WVbr5J6u8BHh8EyFtcWciH). Source: the cloud upgrade rehearsal objectstack-ai/cloud#2867 6147243232 (item I9), measured on a tenant kernel at 01a3421f42. It affects cloud's v18 upgrade (objectstack-ai/cloud#2709), so it is filed priority:p1, target:v18.

What happens

  • Data is lost: a comment with reactions stored at v17 reads reactions: null at v18, and the column is orphaned ([schema-drift]).
  • This is deliberate: commit 9963322fe8 says "stored reactions are not migrated".

Why it is filed

The maintainer's rule for upgrades, 2026-10-13 (objectstack-ai/cloud#2843 6145481762): 「我没有要求清库,这个肯定不行啊,以后不可能每次升级都清库啊」. An upgrade keeps existing data. Reactions are user data that a v18 upgrade silently drops.

Ask

  • A conversion of stored sys_comment.reactions into v18's reaction storage, in the v18 upgrade (the ceremony or a stored-row replay).
  • Or bring "accepted loss" to the maintainer explicitly. The seat does not decide that it is acceptable.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p1 · target:v18 · domain:services, into pm:queue (finding removed). The v18 upgrade carries stored sys_comment.reactions into sys_comment_reaction rows: an upgrade keeps data

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T14:23Z. ⛔ Not a claim, ⛔ not a dispatch.

    • Re-checked: 9963322fe8 (feat(plugin-audit)!: sys_comment.reactions retires; a reaction lives only in sys_comment_reaction, and stored reactions are not migrated #22903, card Retire sys_comment.reactions (ruling A amended on #22505): no aggregate, no data migration, after the console reads reaction records #22573) retired sys_comment.reactions and says "stored reactions are not migrated". The cloud rehearsal measured the loss on a tenant kernel (objectstack-ai/cloud#2867 6147243232, item I9): reactions: null at v18, with the column left as [schema-drift].
    • Not a decision: the maintainer's rule for upgrades (objectstack-ai/cloud#2843 6145481762) is that an upgrade keeps existing data. That supersedes the commit's "not migrated". The card's second option, bringing an accepted loss to the maintainer, is therefore not needed.
    • Why p1 target:v18: user data is lost silently on every upgraded install, and cloud's v18 upgrade (objectstack-ai/cloud#2709) runs into it.
    • Lane: domain:services, the lane that retired the column, which owns plugin-audit and the meaning of both stores. The converter's home (a gated os migrate step, or the ceremony's stored-row pass) is the seat's call, declared in the claim.
    • Direction:
      • Each stored reaction becomes one sys_comment_reaction row, with the same comment, user and emoji, and is never duplicated on a re-run (idempotent).
      • A stored value the converter cannot read is listed in its report, ⛔ never dropped silently.
      • The column is dropped only after the conversion is verified, as the ceremony does with its mirrors.
      • The conversion ships with its own changeset, which says what the upgrade now carries.
      • Pins: a v17-shaped row with reactions reads them back at v18; a re-run adds nothing; an unreadable value appears in the report.
    • Clause ②: no. A conversion of stored rows widens nothing.
    • Triage: lands in plugin-audit's upgrade conversion (home declared in the claim) (domain:services); rationale: an upgrade keeps data.
  2. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11 · 2026-10-13T16:42Z
    Session: session_01FzQy26KznSa5j2gnf3AzsE
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23281-comment-reactions-upgrade-conversion
    Worktree: objectstack-issue-23281
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface:


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23281,
      "status": "done",
      "branch": "claude/issue-23281-comment-reactions-upgrade-conversion",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23318",
      "session": "session_01FzQy26KznSa5j2gnf3AzsE — the dispatching seat's session (mode:subagent)",
      "premise_still_valid": true,
      "summary": "New gated data subcommand `os migrate comment-reactions` (packages/cli) reads sys_comment.reactions below the data door (the account-issuer driver read) and writes one sys_comment_reaction row per stored (comment, emoji, user) in the comment's organization with created_by = the reactor, skipping rows already held (natural key), listing every unreadable value with its comment id (not_json, not_a_map, not_a_user_list, not_a_user_id, emoji_not_storable, unknown_user) and recording a sys_migration row (sys-comment-reactions-to-records) verified only when a read-back finds everything readable converted and nothing unreadable. `os migrate apply --allow-destructive` refuses the sys_comment.reactions drop (exit 1, refused_comment_reactions_unconverted) until that verified row exists, a column-specific sibling of the sys_account.issuer pre-flight. The semantic entry's replacement/reason/acceptanceCriteria prose names the conversion and orders it before the drop (id and surface kept; upgrade guide regenerated with gen:upgrade-guide into the gitignored docs tree), plus the plugin-audit docblock, cli.mdx and one changeset (cli minor, spec patch). Hypotheses: H1-H3 hold; H4 measured (no notification/automation fires; system write keeps user_id; created_by carried so the reactor can un-react, measured DELETE 200); H5 partly falsified (audit-metadata-bodies has no ledger row and no journal; no journal used, idempotent re-run is the resume); H6 falsified as stated (files-to-references' refusal is internal to that command) and landed through the existing mechanism that does hold a drop inside apply, the account-issuer pre-flight, reading the ledger row rather than a live probe so a later un-react is neither blocking nor resurrected.",
      "tests": "All at HEAD bf15e3062a (after merging origin/main 5c9bfb0d3f): build `turbo run build --filter=!@objectstack/docs --concurrency=2` 74 tasks green; `pnpm --filter @objectstack/cli typecheck` clean + `check:test-typecheck: OK` (3 files/28 errors/6 signatures, unchanged ledger); cli integration `vitest run --project integration` on comment-reactions.integration.test.ts + apply.account-issuer-retirement.integration.test.ts + schema-migrate.one-shot-family.integration.test.ts: 3 files, 99 passed (new cases 0.1-0.65 s each); cli unit tier `vitest run --project unit`: 286 files, 4288 passed; spec `pnpm test`: 669 files, 20276 passed, 1 todo; plugin-audit sys-comment-retired-fields + objects + sys-comment-reactions-door: 3 files, 22 passed; eslint --no-inline-config --format json on the 8 changed .ts files: 0 errors 0 warnings (no type-aware linting in eslint.config.mjs, so untouched files cannot move). Booted composition before the pins (pnpm dev:todo, SqlDriver better-sqlite3, branch f5db79977e; 17.x column + 4 v17-shaped values planted by hand): apply --allow-destructive before conversion exit 1 refused, column kept; dry run 4 scanned / 5 readable / 3 unreadable, 0 rows; --apply 5 rows (created_by + organization_id correct), ledger blocking 3; re-run 0 converted / 5 already; drop refused; operator resolves 2 values, --apply verified exit 0; drop exit 0, column gone, 5 rows kept; reboot: no schema-drift line, REST reads 5 rows, admin DELETE of its converted reaction 200. Ablations (fix committed first; scripts/ablation-replace.mjs under the verify lock with trap restore; subject imported from cli src by relative path, so no dist rebuild in the path): (1) idempotency guard `if (held.has(reactionKey(...)))` → `if (false && held.has(...))`, anchor 1→0, blob 1c075685b2e1→dd02d298f4c0: 5 failed/2 passed, re-run pin got alreadyConverted 0 and 5 DUPLICATE_RECORD failures; (2) parse-level `report.unreadable.push(...)` deleted, blob →75af39952334: 3 failed/4 passed, unreadable list missing not_json/not_a_user_id/not_a_user_list. Both restored: blob == HEAD 1c075685b2e1, git diff HEAD empty.",
      "gates": "dispatch-gates --commands (no paths) at bf15e3062a: 118 families from 10 changed paths (identical set to the derivation at a1b2e9999f and a superset of the PM lead); all 118 run, each exit 0; `--ran` with exit codes: '118 derived famil(ies) accounted for — 118 run, 0 NOT-MEASURED (a DERIVED zero — all 118 recorded an exit code and none of them is 3)'. Includes check:upgrade-guide, check:spec-changes, check:doc-authoring, check:tenant-audit-census (225 sites certified), check:nul-bytes (no raw control bytes), check:adr-0087-registration (no declared-breaking changeset). CI convergence not awaited.",
      "line_budget": "not applicable: no skills/** file and no governed line-ratchet ledger touched",
      "files_changed": [
        ".changeset/23281-comment-reactions-upgrade-conversion.md",
        "content/docs/deployment/cli.mdx",
        "packages/cli/src/commands/migrate/apply.ts",
        "packages/cli/src/commands/migrate/comment-reactions.ts",
        "packages/cli/src/commands/migrate/comment-reactions.integration.test.ts",
        "packages/cli/src/utils/comment-reactions-conversion.ts",
        "packages/cli/src/utils/schema-migrate.one-shot-family.integration.test.ts",
        "packages/cli/test/json-stdout-purity.e2e.test.ts",
        "packages/plugins/plugin-audit/src/objects/sys-comment.object.ts",
        "packages/spec/src/migrations/entries/semantic/18.sys-comment-reactions-column-retired.ts"
      ],
      "deviations": [
        "H6 landed in packages/cli/src/commands/migrate/apply.ts as a column-specific refusal beside the sys_account.issuer pre-flight (the existing mechanism that holds one destructive drop inside apply); the claim's file surface did not list apply.ts. Every other drift entry, flag and exit path of apply is unchanged, which I read as not a change to apply's general behaviour; if the seat reads it otherwise, the gate is one hunk plus pins 1/5/7.",
        "File surface beyond the claim's list: packages/cli/src/utils/comment-reactions-conversion.ts (oclif's commands glob loads every module under commands/, so the module shared by the new command and apply.ts lives in utils/); the two derived-population family tables (schema-migrate.one-shot-family.integration.test.ts and json-stdout-purity.e2e.test.ts, which red on an unregistered bootSchemaStack caller); content/docs/deployment/cli.mdx (docs for the new command).",
        "No migration journal (H5): the idempotent natural-key re-run is the resume, the audit-metadata-bodies posture.",
        "Booted measurement used a database created by main with the 17.x column and values planted by hand (ALTER TABLE ADD COLUMN reactions TEXT + v17-shaped JSON), not a database booted by a 17.x release.",
        "Labels: zero label writes — the dispatch names no label and skip-changeset does not apply (cli and spec publish).",
        "The harness reminder asked for a commit trailer naming a model; AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) was used instead, as the pre-push hook requires.",
        "test/json-stdout-purity.e2e.test.ts (nightly tier) gained the new member but was not run locally; declared to the nightly run."
      ],
      "mcp_calls": "0",
      "api_writes": "2 relay strokes (POST /repos/objectstack-ai/objectstack/dispatches each): stroke 1 executed POST /repos/objectstack-ai/objectstack/pulls (draft #23318) + POST /repos/objectstack-ai/objectstack/issues/23318/assignees (zhuangjianguo), read back byte-identical; stroke 2 executes this POST /repos/objectstack-ai/objectstack/issues/23281/comments. git push is not REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed — os migrate apply --json emits its two sys_account.issuer pre-flight refusals (refused_account_issuer_collisions, refused_account_issuer_preflight_unreadable) with exit code 0 (emitJson(..., 0) then return in apply.ts); read from the code, not measured at the door, so it stays in the PR's Acceptance notes",
        "carrier: 承接者:无 · noted, not filed — docs/qa/platform-checklist/areas/cli.json's migrate item still enumerates 13 os migrate subcommands; the tree registers more (organization-ownership, security-catalog-overlays, comment-reactions); a checklist-author sweep owns it"
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment · domain:services seat 2 · session_01FzQy26KznSa5j2gnf3AzsE · 2026-10-13T18:44Z, under claim 6150488591. ⛔ Not a new claim. Same branch, same PR #23318.

    The seat's review of PR #23318 at bf15e3062a against the dev's report (6152601447) sends one patch round.

    • Clause-② becomes no (narrowing), and the claim's line is edited in place in this act. os migrate apply --allow-destructive now refuses the sys_comment.reactions drop until a verified conversion is recorded: the same input that was accepted is now refused. That narrows a published accept set (execution-duties.md: no lane move; one contract-review-tier review before the queue). The changeset and the PR follow the lane's narrowing convention (precedent service-settings: the settings REST family (registerSettingsRoutes) answers an anonymous caller from its own authorization logic instead of the 401 floor; ADR-0056 D2 and ADR-0138 D2 require 401 — the fourth door blocking ADR-0138 criterion 2 #23142): minor with a BREAKING banner, a bang summary and the ADR-0087 disposition the registration gate accepts.
    • File surface, accepted as declared deviations:
      • packages/cli/src/commands/migrate/apply.ts: one column-specific pre-flight, a sibling of the sys_account.issuer one (Adopt better-auth's account-issuer rollback: drop sys_account.issuer, retire the backfill, raise the family to 1.7.3 #17440). It fires only when the intended drift drops sys_comment.reactions, and every other drift entry, flag and exit path is unchanged. The seat reads this as not a change to apply's general behaviour.
      • packages/cli/src/utils/comment-reactions-conversion.ts, where the module shared with apply.ts lives, because oclif loads every module under commands/.
      • The two derived-population family tables, content/docs/deployment/cli.mdx, and packages/cli/test/json-stdout-purity.e2e.test.ts.
    • Grows by one defect the round touches (same file, same refusal family): under --json, the two sys_account.issuer pre-flight refusals in apply.ts emit with exit code 0 and return (refused_account_issuer_preflight_unreadable, refused_account_issuer_collisions). The human path exits 1, and the new sibling exits 1. They are aligned to 1 in this PR, with a pin.
    • Grows by one stale list: the migrate item of docs/qa/platform-checklist/areas/cli.json lists 13 subcommands. It is brought to the subcommands the tree registers, comment-reactions included.
    • Stored shape, confirmed by the seat: the console's reader of the old column store (objectstack-ai/objectui packages/app-shell/src/views/RecordDetailView.tsx, storedReactions(): Record<string, string[]>) uses a JSON map of emoji to user-id lists, the shape the converter parses.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    Patch round 1 on PR #23318 (review at bf15e3062a, against report 6152601447). Head 42b3638b94.

    {
      "issue": 23281,
      "status": "done",
      "round": "patch round 1 on PR #23318 (review at bf15e3062a against report 6152601447; claim amendment 6152677078)",
      "branch": "claude/issue-23281-comment-reactions-upgrade-conversion",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23318",
      "head": "42b3638b94",
      "session": "session_01FzQy26KznSa5j2gnf3AzsE — the dispatching seat's session (mode:subagent)",
      "premise_still_valid": true,
      "summary": "All four asks are done; nothing else was touched. (1) The changeset now follows the narrowing convention set by #23142: `minor` kept, a bang summary `feat(cli)!:`, a **BREAKING** (accept-set narrowing) banner, the line `Clause-②: no (narrowing)` with its reason, and the ADR-0087 disposition `not-required (already-registered sys-comment-reactions-column-retired)`. `pnpm check:adr-0087-registration` accepts it. The changeset also states the issuer exit-code fix. (2) The defect was measured at the real door before any change, with `node packages/cli/bin/run.js migrate apply --allow-destructive --yes` on legacy-shaped SQLite databases and an auth secret set. Collisions (two rows sharing `(provider_id, account_id)`): `--json` gave `refused_account_issuer_collisions` with exit 0, while the human face exited 1. Unreadable (200001 rows, past the probe's 200000-row cap): `--json` gave `refused_account_issuer_preflight_unreadable` with exit 0, while the human face exited 1. Both `emitJson` calls now exit 1. The new pin file `apply.account-issuer-json-refusal.test.ts` (unit tier) asserts exit 1 and `message` for each refusal, and that nothing was written. It has two controls: the human face exits 1, and a clean pre-flight reaches the writes with exit 0. (3) In `docs/qa/platform-checklist/areas/cli.json`, the `cli.migrate-plan-apply-json` item now lists the 16 subcommands that `os migrate --help` registers. organization-ownership, security-catalog-overlays and comment-reactions were added, the source count changed from 13 to 16, and revision 4 has a history entry. (4) Re-verified at 42b3638b94 (see tests/gates).",
      "tests": "At 42b3638b94. `pnpm --filter @objectstack/cli typecheck`: clean, plus check:test-typecheck: OK (ledger unchanged). cli integration on comment-reactions.integration.test.ts, apply.account-issuer-retirement.integration.test.ts and schema-migrate.one-shot-family.integration.test.ts: 3 files, 99 passed. cli unit tier: 287 files, 4292 passed; the new pin file alone gives 4 passed, with first-case wall 4.9 s for oclif's command-table load and the others 0.03–0.05 s. Ablation for item 2 (fix committed first as 87300afdff; trap restore; both sites mutated in apply.ts with scripts/ablation-replace.mjs). Unreadable site: `}, 1,` changed to `}, 0,` with --hold, anchor 1→0, blob 4fe54313fc9f→421f3eeb1114. Collisions site: same change in WRAP mode under the verify lock, anchor 1→0, blob →3b37bf6b7d56. Result: 2 failed / 2 passed. Both new pins were red with `AssertionError: expected +0 to be 1`; both controls stayed green. Restored: `ok restored: blob == HEAD (4fe54313fc9f) and git diff HEAD is empty`, and git status --porcelain was empty.",
      "gates": "Ran `dispatch-gates --commands` (no paths) at 42b3638b94: 12 changed paths, 119 families (last round's 118 plus `pnpm check:platform-checklist`, now derived because cli.json is touched). All 119 were run. 118 exited 0. `pnpm check:platform-checklist` exited 1 with 8 failures, none of them in cli.json: ABSENT SYMBOL anchors in areas/access-security.json (metadata-protocol protocol.ts anonymousFormIntakeOrgScopeRefusal, anonymousFormIntakeReopenRefusal, envWideRawViewRows), areas/search.json (protocol.ts countable) and areas/attachments-storage.json (attachment-access-hooks.ts canEdit; anchor floor 28→27). Control: the same command at 87300afdff, with cli.json put back from HEAD by a patch round-trip, gave the identical 8 failure lines. The cited symbols are also absent at origin/main 404fc477e5. By the maintainer's decision recorded in lint.yml, this gate is not in per-PR CI; its daily watchdog on main owns it. `--ran` with exit codes: '119 derived famil(ies) accounted for — 119 run, 0 NOT-MEASURED (a DERIVED zero — all 119 recorded an exit code and none of them is 3)'. Changeset gates: `✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition. … [BREAKING+bang+clause-②-narrowing] not-required (already-registered)`; `✓ This diff introduces no major bump`; `✓ No empty-frontmatter changeset introduced by this diff`.",
      "line_budget": "not applicable: no skills/** file and no governed line-ratchet ledger touched",
      "files_changed": [
        ".changeset/23281-comment-reactions-upgrade-conversion.md",
        "docs/qa/platform-checklist/areas/cli.json",
        "packages/cli/src/commands/migrate/apply.ts",
        "packages/cli/src/commands/migrate/apply.account-issuer-json-refusal.test.ts"
      ],
      "deviations": [
        "The issuer pins are unit-tier and replace the boot, the occupancy probe, the process exit and the pre-flight probe. The command's own parse, drift handling and refusal branches run for real. The real-door reading for both refusals is the measurement quoted in summary (2). A real-database pin for the unreadable refusal would need 200001 rows per run.",
        "The ADR-0087 disposition is an HTML comment in the changeset, because that is the only marker spelling the registration gate reads. The changeset is a repo file and does not render on GitHub.",
        "origin/main was not merged this round. It moved one commit (404fc477e5), which touches none of this PR's files.",
        "check:platform-checklist is red for pre-existing reasons outside this diff (see gates)."
      ],
      "mcp_calls": "0",
      "api_writes": "1 relay stroke this round: POST /repos/objectstack-ai/objectstack/dispatches, which executes POST /repos/objectstack-ai/objectstack/issues/23281/comments (this report). 2 git pushes (87300afdff; af8fdf9903 + 42b3638b94). No PR body or title write, no label write, no MCP write.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the platform-checklist watchdog on main (承接者:无 beyond it) · noted, not filed — check:platform-checklist is red at origin/main 404fc477e5 on 8 symbol anchors in access-security.json, search.json and attachments-storage.json whose symbols are gone from the code"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ACCEPT: PR #23318 at 42b3638b94 · Fixes #23281

    domain:services seat 2 · session_01FzQy26KznSa5j2gnf3AzsE · 2026-10-13T19:40Z. Under claim 6150488591 (its Clause-② line edited in place) and amendment 6152677078. Declared to domain:cli (6150536077 on #22648) and domain:spec (6150545862 on #6017), with no objection. The dev's reports are 6152601447 and 6153407686 (patch round). Checked on GitHub and on the branch, not from the reports.

    Checklist

    • PR form: draft, base main, assignee zhuangjianguo. Title feat(cli)!: …. Line 1 Fixes #23281, line 2 Clause-②: no (narrowing) — …, which the claim, the changeset and the PR all agree on. The seat wrote the title, line 2 and the patch-round section through the relay.
    • Scope: 12 files, +1521 / -21. check-governed-merges --pr 23318: NOT governed (0 of 12 paths), 1542 lines, under the threshold. The surface is the claim's plus the amendment's declared deviations:
    • The card, executed:
      • os migrate comment-reactions reads sys_comment.reactions below the data door. A preview is the default, and --apply writes.
      • Records: each stored (comment, emoji, user) becomes one sys_comment_reaction row in the comment's organization, with created_by = the reactor, under the bookkeeping write context (isSystem + skipAutomations).
      • Re-runs: idempotent on the natural key.
      • Unreadable values: each is listed with its comment id under six named reasons, and nothing is written for it.
      • Ledger: the run is recorded in sys_migration (sys-comment-reactions-to-records), verified only when the read-back finds everything converted.
      • The drop: os migrate apply --allow-destructive refuses the sys_comment.reactions drop (exit 1, refused_comment_reactions_unconverted) until that verified row exists.
      • The semantic entry names the conversion and orders it before the drop (prose only; id and surface kept).
    • The defect the round touched: under --json, the two sys_account.issuer refusals exited 0 while the human face exited 1. That was measured at the real command, both now exit 1, and they are pinned with two controls.
    • Stored shape: confirmed against objectui's reader of the old column store (RecordDetailView.tsx, storedReactions(): Record<string, string[]>), the shape the converter parses.
    • Tests and ablations:
      • a booted composition measured before and after (refusal → preview → apply → re-run adds 0 → verified → drop → reactor un-reacts, DELETE 200);
      • three ablations, each red then restored with blob proof: the idempotency guard (5 red), the unreadable report (3 red), and the issuer exit code (2 red);
      • cli integration 99 passed and cli unit 4292 passed.
    • Gates: 119 derived and 119 run at 42b3638b94. 118 exit 0. check:platform-checklist exits 1 on 8 anchors outside this diff, with the identical lines on main without this PR's edit.
    • Contract review: PASS 6153659174 at 42b3638b946bdbbf42e5d5d9b1b87c7c7fc99f3e (CONTRACT_REVIEW_TIER, Local-runs: none), so no waiting label is owed.
    • CI at 42b3638b94: 48 check-runs, the latest run per name all success or skipped (41 / 7). None red. Mergeable.
    • Changeset:
      • @objectstack/cli minor with a bang summary, a BREAKING (accept-set narrowing) banner and ADR-0087 not-required (already-registered sys-comment-reactions-column-retired); check:adr-0087-registration is green.
      • @objectstack/spec patch (prose).
      • The changeset prose I checked sentence by sentence against the diff: the upgrade order (backup, preview, --apply, correct or clear each unreadable value, then the drop) and the refusal's message match the code.
    • Writes: mcp_calls 0. The commit trailers carry no model identifier.

    The review's two escalations, answered:

    1. A database written by a 17.x release itself has not been read through the command. The booted run planted 17.x-shaped values by hand. The seat accepts the reading as it stands, because the shape is confirmed from the console's own reader, and an unexpected shape is reported and blocks the drop rather than losing data. The release-written reading belongs to cloud's upgrade rehearsal (objectstack-ai/cloud#2867, item I9, which measured the loss). The landing note points it there.
    2. check:platform-checklist is red on main. The carrier is the gate's own channel: .github/workflows/platform-checklist-watchdog.yml runs it on main daily and files or refreshes one platform-checklist-watchdog issue while it is red. check:platform-checklist is red on main #23139 was the latest. The seat files nothing beside it.

    Out-of-scope findings: none filed beyond the above.

    Landing: pr_ready + automerge_enable through the relay, now. This seat follows it to MERGED.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23318 merged through the merge queue at 2026-10-13T20:09Z as 6673c8018f, and that commit is on origin/main (read 2026-10-13T20:10Z). domain:services seat 2 · session_01FzQy26KznSa5j2gnf3AzsE. It ran under claim 6150488591 and amendment 6152677078, with contract review PASS 6153659174 and ACCEPT 6153697508.

    • On main:
      • os migrate comment-reactions carries the reactions a 17.x deployment stored in sys_comment.reactions into sys_comment_reaction records. It is idempotent, reports unreadable values and records a verified run in sys_migration.
      • os migrate apply --allow-destructive drops the column only after that verified run.
      • The protocol-18 semantic entry orders the conversion before the drop.
      • Under --json, the two sys_account.issuer refusals now exit 1.
    • Queue path: ready_for_review, then auto_merge_enabled, then added_to_merge_queue at 2026-10-13T19:43Z. The PR's only closing keyword was Fixes #23281. No other card closed in the window.
    • Board: this card closed completed by that keyword. This write clears pm:dispatched and the assignee; priority:p1, target:v18, domain:services and area:records stay.
    • For cloud's upgrade (objectstack-ai/cloud#2709): the rehearsal that measured the loss (objectstack-ai/cloud#2867, item I9) can re-read it once its framework pin carries this commit. A database written by a 17.x release itself is that rehearsal's reading; the PR's booted run planted 17.x-shaped values. The order is backup, os migrate comment-reactions, then --apply, then the destructive apply.
    • Publication: .changeset/23281-comment-reactions-upgrade-conversion.md (@objectstack/cli minor, BREAKING narrowing; @objectstack/spec patch) ships at the next version release. A merge to main does not publish.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:servicespriority:p1High: required for production / M2target:v18

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions