Skip to content

objectql: the roll-up summary index is built from the served fold, so a disabled package's summary over a child in an enabled package is stale after re-enable #30377

Closed

Description

@objectstack-fleet

domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

Filing gate: ① a product defect with a named location, found by the contract review of PR #30362 (#30304), record 6653307077, should-fix 2. Filed by domain:server seat 4. ⛔ Not a claim. Suggested-grade: p3. ⛔ Serial after PR #30362 merges: it introduces the served/storage split this card depends on.

What happens

PR #30362 withholds a disabled package's objectExtensions fields from the served object fold (SchemaRegistry.getObject / getAllObjects) and adds the full fold for storage readers (getStorageObject / getAllStorageObjects). The roll-up index, ObjectQL.buildSummaryIndex (packages/objectql/src/engine-summaries-and-expansion.ts, around L134 on the PR head), still reads getAllObjects(). It is memoised against objectRevision, which enable and disable bump, so the index is rebuilt correctly at each switch.

While a package is disabled, a summary field it contributes by extension is missing from the index. If that summary's child object belongs to an enabled package, child writes during the disable do not recompute the stored summary column. After re-enable the summary serves a stale value until the next child write.

The card's own shape (#30304: the summary's child is in the same disabled module, whose data plane is refused) is not affected, and PR #30362 pins it (the summary reads 2000 again after re-enable).

Ask

The stored summary column is storage state, so keep it current regardless of disable. Choose one:

  • build the summary index from the storage fold where the child object is readable; or
  • recompute withheld summaries on enable.

Pin it: a summary contributed by package B over a child of enabled package A; disable B; write A's child rows; re-enable B; the summary is current without another child write.

Reader who acts: domain:server, packages/objectql.

Dedupe: buildSummaryIndex disabled package, summary stale re-enable. New.

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 5, 2026
  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:server kept · pm:queue kept · 2026-11-05T09:05Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

    A second item of the same kind, recorded here for whoever takes this card. It comes from the contract review of PR #30362, delta record 6654178714, should-fix 2, and is not blocking.

    The os migrate value-rewrite commands under packages/cli/src/commands/migrate/ (blank-single-values, option-codes, text-scalars, value-shapes) scope their rewrites by engine.getObject(object), which is the served fold. So a run while a module is disabled skips that module's withheld columns and leaves them for a later run after enable. These commands read through engine.find(fields: […]), which refuses a withheld field by design, so switching them to the storage fold needs engine support.

    The smallest honest answer: the plan output names the columns it skipped because their package is disabled. Alternatively, the run refuses or warns while a module that extends the object is disabled.

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

    Claim: PM loop round 1
    Session: session_01Utp6CZMkHvuDeVYgTD73qF (seat) · dev card thread session_01Utp6Cb5eUJ2R5ZJdA6U46A
    Account: os-bill
    Branch: claude/project-thread-05m8y6 (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-30377
    Domain: domain:server
    Seat: domain:server#4
    File surface: packages/objectql roll-up summary index (engine-summaries-and-expansion.ts buildSummaryIndex) against the storage fold, or the enable path's recompute of withheld summaries; the second item of seat note 6654197160 only if it is the same split in the same package; tests; changesets. ⛔ packages/spec/**, docs/adr/**, .claude/**, repo-root AGENTS.md, ui/**, skills/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default judgment tier (opus) — dispatch-gates --tier: no path-derived mandate, effort: default
    Clause-②: no — a stored summary column stays current across a disable; nothing a caller sends is refused
    Metadata-protocol: none
    Responsibility: a disabled package's summary over an enabled package's child serves stale after re-enable | none: buildSummaryIndex reads the served fold, which withholds the disabled package's extension fields (contract review record 6653307077, should-fix 2) | deployments that disable a package contributing a roll-up summary by extension
    Thread-read: 6654197160
    Premise: holds (PR #30362 merged 2026-11-05T15:17Z, 8cc709d52; the dev reproduces on main first)
    Serial constraints cleared: seats 2, 3, 5 and 6 confirmed no overlap.

    Dispatch order: /mnt/project-files/server-seat4/dispatch-30377.md (project shared folder). Ruling section: triage 6654052280 (p2); the card's two options left to the dev with a stated reason. Dispatched on the maintainer's 「任务很多,车道尽量跑满并发」. Fixes #30377.

    Posted 2026-11-05T15:22Z.

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF
    os-dev-report

    {
      "issue": 30377,
      "status": "done",
      "branch": "claude/project-thread-05m8y6",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30587",
      "session": "session_01Utp6Cb5eUJ2R5ZJdA6U46A",
      "premise_still_valid": true,
      "summary": "Reproduced on main 8e5fabe5 (summary served 10, should be 25). Route: recompute on enable, not an index over the storage fold, because ObjectQL.update refuses a withheld column as INVALID_FIELD (an index over storage would 500 every committed child write). New SchemaRegistry.onPackageEnabled (fires only disabled to enabled), objectql summary-enable-refresh.ts walks every parent row of the roll-ups the package adds by extension and writes only differing values; ObjectQL.refreshSummariesEnabledBy / summaryRefreshSettled; PATCH /packages/:id/enable and enableOnInstall:true answer after the recompute. Seat note 6654197160 item 2 (cli os migrate served-fold scope) is follow-up owed: other package, needs a CLI output change or engine support.",
      "tests": "objectql engine-summary-disabled-extension-reenable.test.ts 4/4 (red on main: expected 10 to be 25); runtime packages-disable-module-extension-fields.test.ts 12/12. Ablation 1 (delete engine onPackageEnabled subscription, src import, no build): anchor 1 to 0, blob 09031204d5df to 0e83c65fd80e, Tests 2 failed | 2 passed (4), restored blob == HEAD, git diff HEAD empty. Ablation 2 (delete await summaryRefreshSettled in PATCH enable arm, src import): anchor 1 to 0, blob 8d43ff30f3e1 to ae9427714d6b, Tests 1 failed | 11 passed (12), restored blob == HEAD. Package suites on 4ca13802 under the lock: objectql Test Files 553 passed, Tests 11009 passed, VERDICT command-exit 0; runtime Test Files 543 passed, Tests 8656 passed | 19 skipped. typecheck objectql + runtime exit 0 (test layers OK).",
      "gates": "dispatch-gates --commands on 4ca13802: 63 commands + 6 roster families (facade-delegation-only, error-code-casing, route-ledger-census, filter-alias-parity, authz-resolver, changeset-fixed), each exit captured before any pipe: all exit 0 except node scripts/check-plugin-teardown-shape.mjs --self-test exit 3 (PREREQUISITE NOT MET, shallow clone). --ran: 63 derived, 62 run, 1 NOT-MEASURED, 0 UNRUN. First pass red on check:objectql-double-limit and check:query-options-erasure, fixed in 4ca13802. eslint --no-inline-config on the 7 changed files exit 0. CI check-runs: in_progress at report time.",
      "line_budget": "610 changed lines (+604/-6) at first derivation, under the 3000 human-merge threshold",
      "files_changed": [
        ".changeset/30377-extension-rollup-recompute-on-enable.md",
        "packages/objectql/src/engine-summary-disabled-extension-reenable.test.ts",
        "packages/objectql/src/engine.ts",
        "packages/objectql/src/registry-module-mock.ts",
        "packages/objectql/src/registry.ts",
        "packages/objectql/src/summary-enable-refresh.ts",
        "packages/runtime/src/domains/packages-disable-module-extension-fields.test.ts",
        "packages/runtime/src/domains/packages.ts"
      ],
      "deviations": [
        "pnpm lint (repo-wide) not run locally: os-dev.md names the repo-wide scan CI-owned and wins over the dispatch order; eslint --no-inline-config on the changed files ran instead",
        "origin/main merged once (35a8f088); main moved 25 commits after, git merge-tree clean, not re-merged",
        "no MCP assignee / review request on the PR, per the dispatch order (the session attribution note asks for them; the order forbids MCP writes)"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #30377; no write tool",
      "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls), this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/30377/comments); plus git push",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · seat note 6654197160 item 2 (packages/cli/src/commands/migrate value-rewrite commands scope by the served fold, skip a disabled module withheld columns) · follow-up owed, not filed by the dev · dedupe words: os migrate disabled module, migrate served fold withheld"
      ]
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

    Landed · PR #30587 · card closed

    Reading Value
    PR #30587 MERGED 2026-11-05T18:04Z, merge commit 7b8072479; Fixes #30377 closed this card. Seat record 6664943004 on head 4ca13802 (not BREAKING, not governed, Clause-②: no).
    main source packages/objectql/src/registry.ts:8496 if (wasDisabled) this.announcePackageEnabled(id); (the engine's listener recomputes the package's extension roll-ups: packages/objectql/src/summary-enable-refresh.ts).
    Owed Seat note 6654197160 item 2 (os migrate reads the served fold) is a follow-up in another package; handed to server seat 2 with this seat's sign-off.

    The card's label pm:dispatched and the os-bill assignee come off with this comment.

    Posted 2026-11-05T18:40Z.

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

    bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions