You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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.
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.
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.tsbuildSummaryIndex) 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.
{
"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"
]
}
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.
Activity
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:serverkept ·pm:queuekept · 2026-11-05T09:05Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
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 migratevalue-rewrite commands underpackages/cli/src/commands/migrate/(blank-single-values,option-codes,text-scalars,value-shapes) scope their rewrites byengine.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 throughengine.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.
objectstack-fleet commentedon Nov 5, 2026
domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF
Claim: PM loop round 1
Session:
session_01Utp6CZMkHvuDeVYgTD73qF(seat) · dev card threadsession_01Utp6Cb5eUJ2R5ZJdA6U46AAccount:
os-billBranch:
claude/project-thread-05m8y6(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30377Domain:
domain:serverSeat:
domain:server#4File surface:
packages/objectqlroll-up summary index (engine-summaries-and-expansion.tsbuildSummaryIndex) 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-rootAGENTS.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: defaultClause-②: 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 extensionThread-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.
objectstack-fleet commentedon Nov 5, 2026
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
objectstack-fleet commentedon Nov 5, 2026
domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF
Landed · PR #30587 · card closed
7b8072479;Fixes #30377closed this card. Seat record 6664943004 on head4ca13802(not BREAKING, not governed,Clause-②: no).mainsourcepackages/objectql/src/registry.ts:8496if (wasDisabled) this.announcePackageEnabled(id);(the engine's listener recomputes the package's extension roll-ups:packages/objectql/src/summary-enable-refresh.ts).os migratereads 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:dispatchedand theos-billassignee come off with this comment.Posted 2026-11-05T18:40Z.