SCALE-SEAM (95) — element state: two read/write pairs, and why the matrix loses - #412
Conversation
…trix loses
Moves `lodSummary`/`setLod` and `phasing`/`setPhase` out of `client.ts` into
`api/model.ts`. They answer one question — *what state are the model's elements
in, and set it?* — and `client.ts` goes 727 -> 711, 76 methods above the STAYING
banner.
The grouping is derived, not asserted:
- identical return shape `{ total, <x>ed, prop, counts: Record<...> }`;
- both writers are `(pid, guids, <enum>, publish) -> editIfc`;
- both readers are consumed by `viewer/tools/modelStatePanels.ts` (251, 316);
- both writers sit unwired and *adjacent* on `clientCallers.test.ts`'s UNCALLED
allowlist;
- `model.ts` already owned `/model/lod/census`, `/lod/handover-readiness` and
`/lod/assessment`, while the base distribution `/projects/{pid}/lod` was left
behind in `client.ts` — `lodSummary` was a sibling separated from its family.
`authoring_matrix.py` DISAGREES and is recorded as the losing vote rather than
elided. It files `set_lod` under `data` and `set_phase` under `lifecycle`,
because it categorises by the IFC output each recipe writes — an LOD stage tag
against `Massing_Phasing.Status`. Different property sets, same question, which
is (89)'s "storage is a HOW" trap. This is the first slice where the matrix has
been wrong after being right three running.
It also MEETS (94)'s objection rather than overriding it: that slice declined
`setPhase` because taking the writer alone would have stranded `phasing()`, the
reader/writer split (87) had to undo. Both halves move together here.
The four names are added to `surface.test.ts` because its floor is a slack
ratchet (788 actual vs 751 floor) — the count alone would not notice a loss —
and because the UNCALLED allowlist is about call sites, not the surface.
Verified: tsc 0, lint 0, `vitest run src/api` 27 files / 119 tests, build 0,
`test_file_sizes.py` / `test_claude_md_gates.py` / `test_roadmap_status.py` /
ruff all 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tt2XKB83wwNt2nrMbK6eEAibuilder
commented
Sep 4, 2026
@coderabbitai review Generated by Claude Code |
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe LOD and phasing read/write methods move from ChangesElement-state extraction
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk:⚪ Minimal · up to LOD and phasing state APIs are reorganized into the model API while retaining their existing read and write behavior. No concrete current-head merge risk remains. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 4 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Action performedReview finished.
|
Strix is installed on this repository, but we couldn't run this PR security review because this workspace's trial has ended. Add a card to resume code reviews here. So far, Strix has reviewed 28 pull requests, surfaced 3 security issues (1 critical/high) and blocked 2 risky merges across this workspace. |
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
Uh oh!
There was an error while loading. Please reload this page.
PR #412 was squash-merged, so origin/main carries (95) as b0e8281 while this branch still pointed at the pre-squash 44a6ed4. The content diff between the remote branch and origin/main was empty before this merge, so the branch held no unmerged work; -s ours keeps this branch's tree (origin/main plus (96)) and reconciles the histories without rewriting the remote branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tt2XKB83wwNt2nrMbK6eEA
PRs #412, #413, #414, #431, #432 and #433 were all squash-merged, so origin/main carries their work as new commits while this branch still held the pre-squash originals. Verified before merging: the content diff between the remote branch and origin/main is empty, and so is the diff between this branch and origin/main — every slice is already on main and nothing is unmerged on either side. -s ours keeps this branch's tree (identical to origin/main) and reconciles the histories so the branch can fast-forward push, without rewriting the remote branch's commits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tt2XKB83wwNt2nrMbK6eEA
What & why
apps/web/src/api/client.tsgoes 727 → 711 (76 methods above the STAYING banner, 4 below).Four methods move to
apps/web/src/api/model.ts— thelodSummary/setLodandphasing/setPhaseread/write pairs — because they answer one question: what state are the model's elements in, and
set it? Continues SCALE-SEAM in
docs/roadmap.md.The grouping is derived, not asserted. Five independent witnesses agree:
{ total, <x>ed, prop, counts: Record<…> };(pid, guids, <enum>, publish) → editIfc;apps/web/src/viewer/tools/modelStatePanels.ts(lines 251, 316);apps/web/src/api/clientCallers.test.ts's UNCALLEDallowlist;
model.tsalready owned/model/lod/census,/lod/handover-readinessand/lod/assessment,while the base distribution
/projects/{pid}/lodstayed behind —lodSummarywas a siblingseparated from its own family.
authoring_matrix.pydisagrees, and it is recorded as the losing vote rather than elided. Itfiles
set_lodunderdataandset_phaseunderlifecycle, because it categorises by the IFCoutput each recipe writes — an LOD stage tag against
Massing_Phasing.Status. Different propertysets, same question. That is (89)'s "storage is a HOW" trap: "they write different psets" has the
same shape as "they are all module records", and neither is a question. This is the first slice where
the matrix has been the losing vote after being right three running — worth naming, because three
straight wins is exactly how a corroborating source turns into an unexamined authority.
It meets (94)'s objection rather than overriding it. (94) declined
setPhasebecause taking thewriter alone would have stranded
phasing()inclient.ts— the reader/writer split (87) had toundo. Both halves move together here, so nothing is separated.
Scope claim, stated at the strength the evidence supports: these four answer that question and
belong together. This does not claim the question is now complete — no derivation of the complement
was done here, and the header says so.
The four names are added to
apps/web/src/api/surface.test.tsbecause its floor is a slack ratchet(788 actual vs a 751 floor), so the count alone would not notice a loss; and because the UNCALLED
allowlist is about call sites while that list is about the surface — an unwired writer can
still vanish in an extraction unnoticed.
Checklist (mirrors CONTRIBUTING.md)
cd services/api && python -m ruff check ../..cleantest_*.pypass —test_file_sizes.py,test_claude_md_gates.py,test_roadmap_status.pyall exit 0; full suite running as a cross-checknpx tsc --noEmit= 0,npm run lint= 0,npm run build= 0);npx vitest run src/api= 27 files / 119 testsCHANGELOG.mdentry added (newest at top);docs/roadmap.mdupdated🤖 Generated with Claude Code
https://claude.ai/code/session_01Tt2XKB83wwNt2nrMbK6eEA
Generated by Claude Code
Summary by CodeRabbit
Refactor
Documentation
Tests