begin: surface forced cells in the UI#35
Merged
Conversation
Spec covers disabling Inspector fields for forced cells, highlighting forced cells and their producing edge in the D3 graph, and extending the demo source with a conditional relationship that forces a cell. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GraphData::forced mirrors the existing changed field, populated from Sheet::forced_cells(), so graph_view/graph.js can highlight cells (and their producing edge) that an active relationship guarantees will always be overwritten by propagate(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A forced cell's value is always overwritten by an active relationship on the next propagate(), regardless of what the user types, so the field is disabled rather than silently discarding edits. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…raph Cells reported by GraphData::forced (see Task 1) get a distinct purple outline, along with the constraint edge that feeds them, so it's visible at a glance which cells can never be edited. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DEMO_SOURCE's p == 1 branch now also activates a single-method relationship g = c * 10, so g is forced (per Sheet::is_forced) only while that branch is active — exercising the Inspector-disable and graph-highlight behavior added in prior tasks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ional form Final whole-branch review flagged that DEMO_SOURCE's doc comment and the design spec still describe folding g's method into the existing p == 1 branch, which the planner's forced-output intersection makes a no-op. Update both to describe and explain the two-conditional form actually shipped in the prior commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A forced cell's value is just as guaranteed downstream as it is produced upstream, so the edges carrying it onward to other relationships should read as forced too, not just the edge that produces it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Surfaces forced cells (as reported by property_model::Sheet::{is_forced, forced_cells}) in the begin demo app so users can see which cell values will be overwritten by active relationships and avoid editing values that cannot “stick”.
Changes:
- Add
GraphData::forcedand populate it fromSheet::forced_cells()so the graph UI can style forced cells/edges. - Disable the Inspector textfield when
Sheet::is_forced(id)is true. - Extend the demo pm-lang source with a conditionally-forced cell
gand add unit tests covering forced/unforced transitions.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/superpowers/specs/2026-07-09-begin-forced-cells-ui-design.md | Design spec for forced-cell Inspector/graph behavior and demo source changes. |
| docs/superpowers/plans/2026-07-09-begin-forced-cells-ui.md | Implementation plan describing how to plumb forced-cell state into UI + demo source. |
| begin/src/spectrum.rs | Add disabled: bool prop to SpTextfield and map it to <sp-textfield disabled>. |
| begin/src/inspector.rs | Compute forced per cell and disable the Inspector input for forced cells. |
| begin/src/bridge.rs | Add GraphData::forced and tests verifying it tracks active conditional forcing. |
| begin/src/app.rs | Update DEMO_SOURCE to include conditionally forced cell g, plus tests for g forced/unforced across p toggles. |
| begin/assets/graph.js | Highlight forced cell nodes and any constraint edge touching a forced cell. |
| begin/assets/graph.css | Add purple styling for forced cells (.node-cell.forced) and forced edges (.link.forced-edge). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…d-cell edges The design spec still described highlighting only the incoming edge and still presented the superseded single-conditional demo-source form as current, contradicting the two-conditional structure and source-or-target edge highlighting actually shipped. Rewrite the spec's Demo Source/Testing/ Out of Scope sections to match, and mark the plan's now-stale JS/DEMO_SOURCE snippets as superseded (matching the existing convention) so they don't mislead readers about the final form. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
property_model::Sheet::is_forced/forced_cells()(already implemented inproperty-model) after everypropagate()in thebegindemo app.DEMO_SOURCE) with a new cellgforced by a single-method relationship, gated on the existingpconditional — togglingpbetween 0 and 1 togglesgbetween editable and forced/disabled/highlighted.Notable implementation detail
g's forcing relationship is declared in its ownconditional p { 1i32 => { .. } }block rather than folded into the existing1i32branch. pm-lang groups everymethodin one branch into a single relationship, and a relationship's forced outputs are the intersection of its methods' pure outputs — mixing[c] -> [g]in with the existingc/fmethods would make that intersection empty, forcing nothing. Two conditionals sharing the same match cell compose independently, so this is a distinct relationship gated on the samep == 1condition (this also means the graph now renders two diamond nodes forp). See the doc comment onDEMO_SOURCEinbegin/src/app.rsand the design spec's superseded-approach note for the full reasoning.Test plan
cargo build --workspace— zero warningscargo test --workspace/cargo test --doc --workspace— all passingcargo clippy --workspace --exclude begin -- -D warnings— cleancargo clippy -p begin --no-default-features -- -D warnings— cleanbridge.rs(GraphData::forcedpopulated/excluded by conditional branch activity),app.rs(gforced/unforced acrossptoggling, including round-trip back to unforced)dx serve --platform desktop, togglepbetween 0 and 1, confirmg's Inspector field disables/enables and the graph highlightsgplus its edges accordingly — not yet run in this environment (no GUI available); recommend a quick pass before mergingDesign spec:
docs/superpowers/specs/2026-07-09-begin-forced-cells-ui-design.mdImplementation plan:
docs/superpowers/plans/2026-07-09-begin-forced-cells-ui.md🤖 Generated with Claude Code
Note
Low Risk
Demo/UI-only changes in
beginusing existing property-model APIs; no auth, persistence, or core solver changes.Overview
The begin demo now surfaces forced cells from
Sheet::is_forced/forced_cells: values that an active relationship will always overwrite onpropagate(), so editing them in the UI was misleading.Bridge → D3:
GraphDatagains aforcedlist of stable cell node IDs (same pattern aschanged).graph.jsappliesforced/forced-edgeclasses so those cells and any constraint edge touching them (incoming or outgoing) render in purple.Inspector:
CellRowdisablesSpTextfieldwhen the cell is forced;SpTextfieldadds adisabledprop on<sp-textfield>.Demo:
DEMO_SOURCEadds cellgand a secondconditional p { 1i32 => … }withg = c * 10so forcing works as a single-method relationship (documented in theDEMO_SOURCEcomment). Tests inapp.rsandbridge.rscover forced state vs conditional branch activity.Design/plan docs under
docs/superpowers/were added for this work.Reviewed by Cursor Bugbot for commit 19ffc25. Bugbot is set up for automated code reviews on this repo. Configure here.