Skip to content

feat(canvas): IM-0b-2 — canvasStore is the rich-map authoring authority#251

Merged
jukka-matti merged 5 commits into
mainfrom
im-0b-2-processmap-canvasstore
May 30, 2026
Merged

feat(canvas): IM-0b-2 — canvasStore is the rich-map authoring authority#251
jukka-matti merged 5 commits into
mainfrom
im-0b-2-processmap-canvasstore

Conversation

@jukka-matti
Copy link
Copy Markdown
Owner

IM-0b-2 (ADR-087 §8). Makes canvasStore the single authoring authority for rich-map fields and refactors ProcessMapBase to dispatch through it instead of building a next map + calling onChange — clearing canvasStore for Wave-3 (IM-4/IM-6).

What changed

  • 6 method-only canvasStore actions (setStepCtq, addTributary, removeTributary [cascades subgroupAxes + pinned hunches], toggleSubgroupAxis, addHunch, removeHunch) via applyUndoable with deterministic id minters.
  • ProcessMapBase dispatches the 6 new props (one production caller, Canvas/index.tsx); onChange fallback retained.
  • Preserved: per-step specs still route to project-wide setMeasureSpec (no node.capabilityScope authoring).
  • Deferred (logged in investigations.md + code comments): net-new node.capabilityScope authoring → IM-5/IM-6 holistic capability design; full visual retirement of ProcessMapBase → verify need at IM-4.

Verification

  • Full pr-ready-check green (all packages + both apps tsc/test, lint, PWA build).
  • 4-dimension adversarial review: no blockers/majors. The chore(deps): bump pnpm/action-setup from 4.1.0 to 4.4.0 #1 risk (hydration loop) confirmed absent — mutation-tested layered guard; discrimination test fails when wiring removed. Minor test-hardening folded in.
  • No core/ files touched.

🤖 Generated with Claude Code

jukka-matti and others added 5 commits May 30, 2026 15:13
IM-0b-2 (ADR-087 §5): make canvasStore the single authoring authority for
the rich-map fields previously mutated by ProcessMapBase -> onChange. Adds 6
method-only actions (not in the CanvasAction union, mirroring
addStepsFromColumn), each via applyUndoable:

  setStepCtq / addTributary / removeTributary (with the subgroupAxes + pinned-
  hunches cascade) / toggleSubgroupAxis / addHunch / removeHunch

Ids are minted from deterministic monotonic sequences (nextTributaryId /
nextHunchId), reset by resetCanvasLocalState() like generatedStepSequence — no
Date.now() / Math.random() / crypto.randomUUID(), so undo snapshots and tests
stay reproducible. addHunch trims + guards empty (defense-in-depth mirroring
the HunchList UI guard) and preserves the step / tributary pin.

20 new store tests (RED -> GREEN); 59/59 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
IM-0b-2 (ADR-087 §5): retire the second persistence path. ProcessMapBase's
ctqColumn / tributary / subgroupAxis / hunch mutators now DISPATCH new optional
props (onSetStepCtq / onAddTributary / onRemoveTributary / onToggleSubgroupAxis
/ onAddHunch / onRemoveHunch) when provided, instead of building a next:
ProcessMap and calling onChange directly. The onChange map-build stays as the
fallback when a prop is absent (back-compat; the only production caller wires
every prop).

Canvas/index.tsx forwards the six props (extending the onAddStep / onRenameStep
wiring). CanvasWorkspace adds the canvasStore-backed handlers — each dispatches
the store action then mirrors persistCanvasStoreMap() exactly like
handleAddStep, so edits land on processContext.processMap via the SAME persist
path as every step-structure edit. persistCanvasStoreMap sets
lastHydratedMapSignature to the post-edit map BEFORE handleChange, so the
controlled-prop round-trip does NOT re-trigger the hydration effect (no
re-hydrate / clobber loop). After this, canvasStore owns every rich-map
authoring mutation.

Per-step specs editor routing to setMeasureSpec (measureSpecs) is UNCHANGED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on-loop guard

IM-0b-2 (ADR-087 §5): CanvasProcessMap.test.tsx — re-point the ctqColumn /
tributary / subgroupAxis / hunch cases to assert the new dispatch props are
CALLED (with onChange NOT called) when wired, and keep a legacy onChange
map-build fallback case per group for back-compat. Specs-editor cases keep
asserting setMeasureSpec routing (unchanged); step-structure cases unchanged.

CanvasWorkspace.test.tsx — add the #1-regression-risk test: a ctqColumn edit
dispatches onSetStepCtq -> persistCanvasStoreMap -> setProcessContext (controlled
prop round-trip) and MUST NOT re-hydrate / clobber the canvasStore. Asserts the
store carries the new ctqColumn (proving the dispatch path, not the onChange
fallback) and that hydrateCanvasDocument is NOT called again beyond mount.
Verified discriminating: removing the CanvasWorkspace onSetStepCtq wiring fails it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rControlAdd prose

IM-0b-2 apply-phase docs:
- investigations.md: new "IM-0b-2 deferrals" entry — (1) per-step
  node.capabilityScope (SpecRule[]) authoring deferred to the IM-5/IM-6
  holistic design (specs keep routing to project-wide measureSpecs; no
  setStepCapabilityScope action added); (2) full visual retirement of
  ProcessMapBase deferred — verify the real need at IM-4 (it is now a thin
  dispatcher, harmless).
- ADR-087 (§Decision item 5 + §Consequences) + the investigation-surface spec
  §8: flag the onFactorControlAdd-"currently undefined" prose as STALE (it was
  already wired in IM-0b) and note the IM-0b-2 capabilityScope + ProcessMapBase-
  retirement scope cuts. Flag annotations only — the forward-looking design
  statements are left intact.
- `// IM-0b-2 deferral:` code comments at the per-step specs editor seam in
  ProcessMapBase.tsx + CanvasWorkspace.tsx, where authoring INTENTIONALLY still
  routes to setMeasureSpec (measureSpecs), not canvasStore / node.capabilityScope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- removeTributary cascade: assert pre-state populated (no vacuous post-assert)
- toggleSubgroupAxis: assert version bump + one undo entry (sibling parity)
- CanvasWorkspace hydration test: comment names the layered guard accurately

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mean-beoynd-lite-pwa Ready Ready Preview, Comment May 30, 2026 2:08pm
variscout_website Ready Ready Preview, Comment May 30, 2026 2:08pm

@jukka-matti jukka-matti merged commit 2d43291 into main May 30, 2026
1 of 3 checks passed
@jukka-matti jukka-matti deleted the im-0b-2-processmap-canvasstore branch May 30, 2026 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant