Skip to content

ADR-0139 E7 (comments): sys_comment gains a writer-stamped object_name + record_id pair with a backfill, and the comment-thread read gate emits one ReadableIds leaf per parent object over it (ruling on #23732, batch #354 item 2) #23857

Closed

Description

@objectstack-fleet

Filing gate: ④ a ruled execution card — the ruling on #23732 (batch #354 item 2, letter A on Q1, the maintainer's 「同意」; its comment id is the first line of that card's body), filed by the director seat (summon #43, session_01QJC7i981TSs9L1CGJK59Ax). ⛔ Not a claim. Facts were read at objectstack origin/main 3fed1eb00a.

Carries the comment-thread half of ADR-0139's execution-plan row E7. The attachment half landed as PR #23767 (0b1179f332, Part of #23732); the reaction gate stays on the bounded probe by D5.2 (Q2 of the same ruling). #23732 is pm:blocked on this card and closes completed when this card lands.

The work (ADR-0139 D3, D4, D5; ADR-0052 §5)

  1. The pair. sys_comment (packages/plugins/plugin-audit/src/objects/sys-comment.object.ts) gains object_name and record_id, writer-stamped from thread_id ({object}:{record_id}) on create and on the re-point rule, read-only to authors, indexed. thread_id stays the authored key: no ADR-0087 conversion, and no writer changes (objectui's RecordDetailView keeps writing thread_id).
  2. The backfill. One idempotent stored-row migration under the os migrate door, in the shape E6 landed (ADR-0139 E6: sys_activity gains a writer-stamped changed_fields column with an idempotent backfill, and the withheld-update rule becomes a predicate with no SYSTEM pre-scan (D4) #23731 → PR feat(plugin-audit): sys_activity gains writer-stamped read-rule columns with an idempotent backfill, and the withheld-row rule is a predicate with no SYSTEM pre-scan (ADR-0139 E6) #23814, 5b6c257b06: a writer-stamped column plus a backfill). The changeset's first paragraph names the door and the rollout consequence, as ADR-0139 E6: sys_activity gains a writer-stamped changed_fields column with an idempotent backfill, and the withheld-update rule becomes a predicate with no SYSTEM pre-scan (D4) #23731's did. A row the backfill has not reached keeps the bounded probe (fail closed), never a leaf.
  3. The gate. installCommentReadVisibility (packages/plugins/plugin-audit/src/comment-access-hooks.ts) emits one ReadableIds leaf per registered parent object, { object_name: P, record_id: { $in: ReadableIds.of(P) } }, ANDed into the read's where, with no pre-scan and no caller-scoped parent read. D5's three classes keep the bounded fail-closed probe by name (a delegated caller; a parent narrowed by an object-scoped read middleware; a federated parent), chosen up front, ⛔ never reached by catching a refusal. No leaf without canReadObject (E5's guard). The consumer does not catch the composition refusal into a deny-all sentinel (D3).
  4. Reactions. The reaction gate (sys_comment_reaction, parent sys_comment) keeps the probe: D5.2 names sys_comment (docs/adr/0139-engine-internal-semi-join-leaf-readable-parent-ids.md:212). Recorded here as D5.2's class with the reading of 2026-10-16: member 1,763 of 2,300; administrator total 2,000 of 2,601. No code.

Pins

Notes carried

Governing text

ADR-0139 header (「A is the end state」, :16), D3, D4 (:177-187), D5 (:201-214); ADR-0052 §5 (:208, the object_name / record_id pair); ADR-0112 (the refusal envelope); the ruling on #23732 named above.

Dedupe

MCP search_issues on this repo, closed included, for "sys_comment pointer pair object_name record_id backfill comment-thread read gate ReadableIds leaf": 10 hits; the nearest are #23732 (the parent decision, now pm:blocked on this card), #23673 (E5, closed), #22861 (E2, closed) and #4630 (the sys_comment record-level gate, closed). None carries the comment pointer pair. Dedupe words: ADR-0139 E7 comment thread pointer pair object_name record_id backfill; installCommentReadVisibility ReadableIds leaf no pre-scan; sys_comment thread_id writer-stamped.

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 6 · 2026-10-16T09:31Z
    Session: session_018VqJPGA1NDNSCZsnecsChP (the dispatching seat; the dev runs as a cloud session that seat post #21118 names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-23857-comment-parent-pair
    Worktree: objectstack-issue-23857 (in the cloud session's container)
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface (at origin/main a31ff2eb5d or later; stop on a breach and explain it in the report):

    • in packages/plugins/plugin-audit/src/: objects/sys-comment.object.ts (the pair); comment-access-hooks.ts (the gate and its stamping hook, or one new module beside it); one backfill module beside stored-metadata-body-migration.ts, exported from src/index.ts; their tests;
    • dogfood pins under packages/qa/dogfood/test/;
    • one new os migrate door under packages/cli/src/commands/migrate/, with its test and its family registrations (the domain:cli half, declared to seat [PM seat] domain:cli — 🟢 os-sales · session_01BVm1pAXVXQ3PjC42j1kPFf · serial, p1/p2 + #24022 (maintainer) #6024 in this act, as E6's was);
    • one minor changeset;
    • the files the gates regenerate.

    Exclusions:

    Container & model: L (~500–900 lines, 1–2 PRs by the ruling's column; a real-engine read gate, a backfill and a door, measured on the dogfood stack), mode:cloud, model: opus (TIER_DEFAULT; dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate")
    Clause-②: yes — two columns on the published platform object sys_comment, an exported backfill, and a new CLI door widen the published surface. The face is the declaration (no packages/spec/src/** path), so a TIER_DEFAULT contract review of record is owed before the queue. This seat orders it.
    Responsibility: plugin-audit (this lane): the comment-thread read gate serves every visible comment, with count equal to the rows served, via one ReadableIds leaf per parent object | none: E7's attachment half landed as PR #23767; reactions stay on the probe by D5.2 | #23732 closes completed when this lands; ADR-0139's execution epic #22788
    Thread-read: none
    Ruling-ref: #23732 ruling 6212058353 (batch #354 item 2, letter A on Q1, A on Q2, maintainer 「同意」 2026-10-16T09:06Z). Precedents: E6 #23731 → PR #23814 (5b6c257b06) and E5 PR #23693.
    Serial constraints cleared: no open PR touches comment-access-hooks.ts, sys-comment.object.ts or the backfill modules (all open PRs' file lists read at this write). #23804 (this seat, in flight) is on audit-writers.ts writeAudit, which this card does not touch.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23857,
      "status": "done",
      "branch": "claude/issue-23857-comment-parent-pair",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23881",
      "session": "session_01NX4Woa8XhvMs6xpqQpx8kK (this cloud run's Claude-Session line)",
      "premise_still_valid": true,
      "summary": "sys_comment gains readonly, indexed object_name + record_id, derived from thread_id by one planner (planCommentParentPair, the parse every comment gate authorizes by). They are stamped for every caller on create, over any value sent, and re-stamped on an update naming thread_id (the re-point rule). A non-system update's own pair is dropped by the engine's readonly strip (measured). installCommentReadVisibility now runs E5's computeParentRecordFilter, imported and not edited, so no third D5 copy exists. It runs over the pair: one ReadableIds leaf per registered object other than sys_comment; D5's classes and the two whole-read states get the bounded probe up front; no leaf is written without canReadObject. Rows with no stamped pair get the old thread probe, ORed in and restricted to object_name IS NULL (probed, never leafed). next() is outside the try (D3). The reaction gate is unchanged (D5.2). backfillCommentParentPair, exported, and its door os migrate comment-parent-pair (E6's shape, 3 family registrations) stamp stored rows under preserveAudit, so updated_at is kept (measured). Bound case before -> after: real engine member 1,766 -> 2,303 of 2,303, administrator total 2,000 -> 2,605; real SecurityPlugin + AuditPlugin dogfood stack, member 981 -> 2,050 of 2,050. Reaction reading recorded on the card as D5.2's class (member 1,763 of 2,300; administrator total 2,000 of 2,601), no code.",
      "tests": "At head e499adaf6 (origin/main 34b740f2d merged), shared box, under os-verify-lock. pnpm --filter @objectstack/plugin-audit test: 53 files / 863 passed. plugin-audit typecheck exit 0 (test-typecheck OK). @objectstack/cli unit project: 301 files / 4,496 passed; cli typecheck exit 0. CLI integration (the diff touches it): comment-parent-pair + data-commands.absent-database + schema-migrate.one-shot-family 147/147; json-stdout-purity.e2e (OS_TEST_TIERS=nightly) 62/62 (run before the main merge, at the CLI-door commit). Dogfood typecheck exit 0. Dogfood, 9 files / 79 passed: comment-thread-parent-pair (new) + 7 sys_comment suites + activity-withheld-row-predicate. Readings: E7-COMMENT-READING after {rowsAtRest 2607, memberServed 2303 of 2303, memberTotal 2303, adminTotal 2605 of 2605}; E7-DOGFOOD-READING after {visible 2050, served 2050, totals [2050]}. ABLATIONS through scripts/ablation-replace.mjs, each restored 'blob == HEAD' with git diff HEAD empty. Unless noted, the pins are comment-thread-leaf.test.ts + comment-parent-pair.integration.test.ts on src. A0: main's whole-read thread probe, src 7/17 red (before reading member 1766/2303, adminTotal 2000/2605). A0 dogfood leg: OS_SKIP_DTS rebuild, ablation-dist-preflight marker A0-BEFORE present exit 0, 4/5 red (member served 981 of 2050). Restore rebuild exit 0, --absent exit 0. A1 stamped branch admits all: 11 red. A2 unstamped not probed: 5. A3 probe branch loses the IS NULL conjunct: 2. A4 leaf without canReadObject: 1. A5 consumer catches the refusal: 2. A6 stamp keeps the writer's pair: 7. A7 re-point not re-stamped: 2. A8b D5.2 parent leafed (temporary planParentReads mutation): 9. A9 delegated leafed: 2. A10b refused backfill read not counted: 1. A11 a thread naming no record stamped: 7. Void legs: the first A0 (the replacement contained the anchor; refused, nothing landed); first A8 and A10 (the replacement already occurred; refused); A4, A5 and A9 rerun after a test-only stand-in restructure, same reds.",
      "gates": "LOCAL: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at e499adaf6 derives 103 commands (23 paths vs merge base 34b740f2d, 2,276 changed lines, under 3,000). All 103 exit 0, each captured before any pipe. --ran: 'Run reconciliation — 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN.' and '103 run, 0 NOT-MEASURED (a DERIVED zero — all 103 recorded an exit code and none of them is 3)'. The first union (at e34c95d5) had 7 non-zero, none in the final record. check-tenant-audit-census and its --self-test exit 1: prose figures 226 vs 227, fixed by hand. check:engine-double-contract and check:objectql-double-limit exit 1, both on my unit stand-in: an unneeded findOne, and a find the limit gate could not judge; restructured, no ledger touched. Three exit 3 (PREREQUISITE NOT MET): check:skill-examples and check:dual-build-cjs-loads (dist missing, re-run after a full build) and check-plugin-teardown-shape --self-test (a shallow clone, re-run after fetching 621a487607). Also local: pnpm check:adr-symbol-anchors exit 0 ('2348 anchors across 142 records resolve'), check:adr-anchors 0, check:nul-bytes 0. CI on PR #23881 at e499adaf6 when this report was written: 24 check-runs, 1 success, 1 skipped, 22 in_progress. Not awaited, per the contract.",
      "mcp_calls": "1 — mcp__claude-code-remote__subscribe_pr_activity on #23881 (the cloud harness's post-PR default; not a GitHub write). 0 MCP GitHub calls.",
      "api_writes": "2. (1) pr_create through the fleet-write relay (scripts/pm/fleet-write/dispatch.mjs, transport dispatch): POST /repos/objectstack-ai/objectstack/dispatches (204). Run 38892815365 executed it as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23881/assignees ([os-elon-musk]). Read-back: 11,056 bytes sent, 11,056 stored, identical. (2) This report: POST /repos/objectstack-ai/objectstack/issues/23857/comments via scripts/pm/post-stamped.mjs. label-write: 0 (outside the dispatch's budget). git push: the empty branch probe, then each step (not a REST write). Reads: gh api GETs of #23857 and its comments, #23732 and its comments, contract record 6209058891, PR #23814's files, and #23881's check-runs.",
      "open_questions": [
        {
          "question": "Which objects are the comment gate's parents? Comments can hang off any record (enforceFeedsCapability allows any object whose feeds are not off, and the console writes thread_id from every record detail page), but enumerateParentObjects excludes AUDIT_EXCLUDED_OBJECTS unless a gate names them.",
          "options": [
            "A: name every AUDIT_EXCLUDED_OBJECTS entry as a namedParent, so the gate enumerates every registered object but sys_comment, exactly the set parseCommentThreadId accepts (taken)",
            "B: keep the audit exclusion, which would hide comments on sys_session, sys_job and the like that the old probe served"
          ],
          "recommendation": "A, taken. Real need: it preserves every comment the old gate served. Long-term: one parent set, the parse's. AI-safety: no silent narrowing. Startup focus: no new surface. The cost is ~25 more leaf branches per unpinned read; a refused object is answered $in: [] by canReadObject, with no read."
        },
        {
          "question": "The card asks that 'the comments item's revision' carry the two checklist notes, but no platform-checklist item covers comment read inheritance (records-forms.json's comment items are about feeds and posting).",
          "options": [
            "A: revise only attachments-storage.read-inherits-parent-rls (revision 5) and record the absence (taken)",
            "B: author a new comments read-inheritance item, which is checklist-author's work"
          ],
          "recommendation": "A, taken. A new item is a new surface, not a revision; the seat can route B to a checklist-author sweep if wanted."
        }
      ],
      "out_of_scope_findings": [
        "carrier: #22788 (domain:engine) · noted, not filed · parent-record-read-gate.ts#WHOLE_READ_PROBE_WHY['no-object-admission'] still cites 'the SYSTEM re-read of this WHERE that the withheld-update rule makes'. E6 removed that re-read, and the comment gate now prints this sentence too, once per engine, when no canReadObject is composed. Prose only; the behaviour is right. Dedupe words: no-object-admission warning stale withheld-update re-read; WHOLE_READ_PROBE_WHY parent-record-read-gate"
      ],
      "line_budget": "2,276 changed lines (+2,226 / -50) over 23 files, generated files included (dispatch-gates' count at e499adaf6). Under the 3,000 human-merge threshold, so no 维护者速读 section. Over the ruling's 500–900 estimate: about 1,300 lines are tests (two plugin-audit suites, the dogfood pin, the CLI door suite) and about 190 are the CLI door.",
      "deviations": "1) File surface: docs/qa/platform-checklist/areas/attachments-storage.json (the carried notes, which the ruling's item 6 rides on this card) and content/docs/permissions/tenant-audit-census.mdx + docs/audits/2026-08-tenant-audit-write-call-sites.counts.md (the census, regenerated, plus 7 hand-written prose figures 226 -> 227) and content/docs/deployment/cli.mdx + docs/qa/platform-checklist/areas/cli.json (the door rows). All are docs or gate-regenerated, as in E6's landing. 2) The stamping hook and the gate live in comment-access-hooks.ts, not in a new module; the backfill is its own module. audit-writers.ts is untouched; comment-access-hooks.ts imports its AUDIT_EXCLUDED_OBJECTS. 3) parent-record-read-gate.ts is imported (computeParentRecordFilter), not edited and not copied: no third D5 classification. Ablations A8b and A9 mutated it temporarily, restored and proven blob == HEAD. 4) The first dogfood fixture (two threads) passed under A0 because the old probe bounds distinct threads, not rows. It was rebuilt with one comment per record, and A0 then turned it red; the first fixture's green is not counted as evidence. 5) A bundled lock call with ';' parts got VERDICT batch-last-exit 0; each part's own exit (AUDIT 0, AUDITTC 0, CLIUNIT 0, CLITC 0) was echoed and is quoted instead. 6) One rm of packages/runtime/.objectstack after the main merge was refused by a harness safety check and not run; the suites run here do not read it. 7) json-stdout-purity.e2e was run before the main merge, at the CLI-door commit; the merge brought no CLI file it reads besides organization-ownership. 8) The primary checkout was detached so the branch could live in the worktree objectstack-issue-23857. 9) The harness reminder's model-named Co-Authored-By trailer was not used; the commits carry AGENTS.md's model-free pair. 10) One MCP call (subscribe_pr_activity), see mcp_calls.",
      "files_changed": [
        ".changeset/23857-comment-parent-pair.md",
        "content/docs/deployment/cli.mdx",
        "content/docs/permissions/tenant-audit-census.mdx",
        "docs/audits/2026-08-tenant-audit-write-call-sites.counts.md",
        "docs/qa/platform-checklist/areas/attachments-storage.json",
        "docs/qa/platform-checklist/areas/cli.json",
        "packages/cli/src/commands/migrate/comment-parent-pair.ts",
        "packages/cli/src/commands/migrate/comment-parent-pair.integration.test.ts",
        "packages/cli/src/commands/migrate/data-commands.absent-database.integration.test.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/audit-plugin.ts",
        "packages/plugins/plugin-audit/src/comment-access-hooks.ts",
        "packages/plugins/plugin-audit/src/comment-parent-pair-backfill.ts",
        "packages/plugins/plugin-audit/src/comment-parent-pair.integration.test.ts",
        "packages/plugins/plugin-audit/src/comment-thread-leaf.test.ts",
        "packages/plugins/plugin-audit/src/index.ts",
        "packages/plugins/plugin-audit/src/objects/sys-comment.object.ts",
        "packages/plugins/plugin-audit/src/translations/en.objects.generated.ts",
        "packages/plugins/plugin-audit/src/translations/es-ES.objects.generated.ts",
        "packages/plugins/plugin-audit/src/translations/ja-JP.objects.generated.ts",
        "packages/plugins/plugin-audit/src/translations/zh-CN.objects.generated.ts",
        "packages/qa/dogfood/test/comment-thread-parent-pair.dogfood.test.ts"
      ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23857,
      "addendum_to": 6214364566,
      "round": "patch, on contract record 6215049807 (FAIL at e499adaf6)",
      "status": "done",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23881",
      "head": "32b6f5300",
      "branch": "claude/issue-23857-comment-parent-pair",
      "session": "session_01NX4Woa8XhvMs6xpqQpx8kK",
      "summary": "FAIL reason 1 is cured, and observation (a) is cured by the same change. The sys_comment beforeUpdate stamp now runs for every caller whenever an update names thread_id, object_name or record_id. Naming thread_id: stamped from it, as before. Naming the pair without a thread: re-derived from the row's stored thread (ctx.previous.thread_id) by planCommentParentPair. No stored row to derive from: both keys are dropped from the write. So no writer's pair lands under preserveAudit, where the engine's update-side strip keeps a readonly value. The backfill's SYSTEM write of the pair is re-derived from the row's thread as it stands at write time, which closes the read-then-write race in (a). A predicate update naming the pair over rows with different threads is refused whole by the engine (MULTI_UPDATE_HOOK_KEY_DIVERGENCE), as one SET clause cannot carry two pairs. The prose is now true of the fix: the object docblock, the hook docblock, the backfill docblock and the changeset's third paragraph. Observation (b): the changeset names the first parameter's widening to ParentRecordGateEngine and both types it brings into reach. Observation (c): the door's docblock now names activity-changed-fields' flags. Observation (d): app-scale cost is not measured, unchanged.",
      "reproduction": "The pin was written first and run at the FAIL head's code. A member's update {object_name: e7_vault, record_id: VAULT} with context {...MEMBER_A, preserveAudit: true} stored object_name e7_vault and record_id of the vault, where the thread's pair was expected (vitest diff: expected e7_doc, received e7_vault). With the fix it reads back the thread's pair, and so does a record_id-only update.",
      "tests": "At 32b6f5300, under os-verify-lock. plugin-audit build, then test: 53 files / 864 passed; typecheck exit 0. Dogfood (plugin-audit through dist, rebuilt in the same lock call): 9 files / 79 passed, with E7-DOGFOOD-READING {visible 2050, served 2050, totals [2050]}; dogfood typecheck exit 0. CLI integration: comment-parent-pair + data-commands.absent-database + schema-migrate.one-shot-family 147/147. New pins: integration 'the re-point rule re-stamps the pair; a member's own pair is never written' gains two preserveAudit updates (the pair, then record_id alone); unit 'update: a pair named without a thread is re-derived from the stored thread, or dropped when there is none'. Fixtures that plant unstamped rows now write below the engine (driver.update), as a pre-upgrade row exists, because every engine write of the pair is now re-derived. The dogfood pin restores those rows through the engine and asserts the re-derived pair. ABLATIONS through scripts/ablation-replace.mjs, restored 'blob == HEAD (2e9d279ddcaa)' with git diff HEAD empty: A12 (the update stamp ignores a pair named without a thread) turned 2 red, the unit pin and the preserveAudit integration pin; A13 (no stored thread keeps the writer's pair) turned 1 red.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 32b6f5300: 103 commands, 23 paths, 2,340 changed lines (+2,290 / -50), under 3,000. All 103 exit 0, each captured before any pipe. --ran: 'Run reconciliation — 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN.' with a DERIVED zero. The first record of this round listed 4 UNRUN: the runner's shell was moved to the background mid-run, so check:type-check-debt, check:vendor-version-stamps, check:watch-hint-literal and check:where-matcher had no exit code. Run then, each exit 0, and reconciled to 103/103. pnpm check:adr-symbol-anchors exit 0. CI on the new head not read or awaited.",
      "pr_body_for_the_seat": "The PR body's 'Who can write the pair' bullet 3 ('A non-system update that names the pair without a thread: the engine's update-side stripReadonlyFields drops it. Measured on a real engine.') is false at 32b6f5300. Suggested replacement: 'An update that names either column without a thread: the update stamp re-derives the pair from the row's stored thread, for every caller (under preserveAudit the engine's strip keeps a readonly value), and drops it when there is no stored row. Pinned, ablated A12/A13.' The Ablations table gains rows A12 (2 red) and A13 (1 red). The dev does not PATCH the body.",
      "mcp_calls": "0 this round.",
      "api_writes": "1, this comment: POST /repos/objectstack-ai/objectstack/issues/23857/comments via scripts/pm/post-stamped.mjs. git push: one commit (32b6f5300). Reads: gh api GET of the contract record 6215049807 and of #23881's check-runs.",
      "deviations": "None beyond the 4 first-pass UNRUN gates above, which are recorded and re-run."
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23881 comment 6218283155 · domain:services seat 2 · session_018VqJPGA1NDNSCZsnecsChP · 2026-10-16T15:00Z. Landing through the merge queue.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:services seat 2 (#21118) · os-elon-musk · session_018VqJPGA1NDNSCZsnecsChP · 2026-10-16T15:42Z.

    Landed: PR #23881 (Fixes #23857) merged through the merge queue as 67e8792ff4. That commit is on origin/main (git merge-base --is-ancestor). Timeline: added_to_merge_queue 2026-10-16T15:03Z → merged 2026-10-16T15:26Z. ACCEPT 6218283155, after contract records 6215049807 FAIL, 6216478197 FAIL and 6218239397 PASS.

    Probe on origin/main Reading
    objects/sys-comment.object.ts: the pair object_name :163, record_id :172
    comment-access-hooks.ts: the multi-row divergence refusal refusePairDivergence, 3 hits
    comment-access-hooks.ts: the gate composes over parent-record-read-gate.ts computeParentRecordFilter imported (:121)
    The backfill door packages/cli/src/commands/migrate/comment-parent-pair.ts and its integration test, present

    What it changes, measured by the dev at the landed head:

    • A member with more than 2,000 readable candidates is served 2,303 of 2,303 comments; before, 1,766.
    • An administrator's total reads 2,605 of 2,605; before, 2,000.
    • On the dogfood stack, 2,050 of 2,050; before, 981.
    • Rows written before the pair carry null until os migrate comment-parent-pair --apply stamps them. Until then the gate answers them with the bounded probe, failing closed.

    Closure: #23732 closes completed in this act, per ruling 6212058353 item 6. E7's row is now complete: attachments by PR #23767 (0b1179f332), comments by this PR, reactions recorded under D5.2. The stale WHOLE_READ_PROBE_WHY['no-object-admission'] prose goes to carrier #22788 by a pointer in this act.

    pm:dispatched is cleared, the assignee is released, and the dev session is archived in this act.


    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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions