Skip to content

feat(calm-suite): Add comprehensive support for multi-doc and complex governance relationships#2740

Closed
eddie-knight wants to merge 3 commits into
fix/calmstudio-flowtocalm-graph-fidelityfrom
feat/calmstudio-gemara-controls
Closed

feat(calm-suite): Add comprehensive support for multi-doc and complex governance relationships#2740
eddie-knight wants to merge 3 commits into
fix/calmstudio-flowtocalm-graph-fidelityfrom
feat/calmstudio-gemara-controls

Conversation

@eddie-knight

@eddie-knight eddie-knight commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Description

Demo:
https://drive.google.com/file/d/1nrKWN0fidQC8MHq31GWxF8_aHDFnrr8_/view

Builds the FINOS governance + C4 story into CalmStudio as first-class, canonical CALM 1.2, and makes documents persist what users actually care about (name, layout). Three themes:

1. Gemara ↔ CALM governance (the headline)

  • Bind Gemara GRC catalogs to CALM via decorators — AIGF guidance (L1) + CCC controls (L2) — replacing the old hardcoded AIGF panel.
  • Connected AIGF↔CCC Governance view: per-element guidelines (recommended by node type) ↔ the CCC controls that satisfy them ↔ assessment requirements, with rolled-up coverage and one-click "Apply governance."
  • Attestation writes canonical CALM 1.2 controlsdomain-keyed (ai-governance), framework ids in config — never framework-prefixed keys.
  • Multi-catalog ("+ Add Reference", folded per-catalog groups), node-scoped references, and real-element scoping: whole-system bindings attach to the document's top-level system node (with containment inheritance via composed-of/deployed-in), not the non-canonical @architecture sentinel (kept only as a legacy fallback). This is the seam CALMGuard reads.
  • Legacy AIGF score/panel/validation-rules retired; decorators visualized on the canvas; governance changes are undoable (history now snapshots the model, not just the flow).

2. Link-based C4 navigation

  • Drilling follows node.details.detailed-architecture links across documents — no level tabs; one file = one diagram.
  • A reference CALM document series (Multi-Agent Reference Architecture, 3 C4 tiers) ships as a template and validates against the repo CLI.
  • Double-click a linked node → read-only doc view + breadcrumb + an "Edit this doc" bridge; containment edges hidden (nesting already conveys containment).

3. Document UX + persistence

  • Editable document title that feeds the save filename; "Unsaved Document" empty state + an unsaved-changes indicator.
  • Persist the document name in metadata.name and the diagram layout (node positions) in metadata.calmstudio-layout — both restored on load (auto-layout fallback for un-positioned nodes). Templates spawn in named.
  • Save + Export merged into one dropdown that distinguishes "JSON w/ CALM Suite Layout" (Save) from the portable, layout-free exports.
  • Fixes: stale filename + silent overwrite on template load, title not updating on Save, title clipping.

Canonical-CALM guarantee: the relationship shape stays nested, controls stay domain-keyed, and all presentation data (name, layout) lives in metadata (ignored by non-Studio consumers). Verified by calm-spec-expert (canonical CALM 1.2 ✓) and pedantic-qa-guardian (SHIP) reviews across the governance, C4, and persistence work.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ♻️ Refactoring (no functional changes)
  • ✅ Test additions or updates

Affected Components

Primary: CALM Suite — CalmStudio (calm-suite/calm-studio/) and @calmstudio/calm-core.

Testing

  • I have tested my changes locally

  • I have added/updated unit tests

  • All existing tests pass

  • CalmStudio app: 498 vitest tests green; calm-core: 124 green.

  • svelte-check at the established baseline (no new errors over the branch baseline).

  • Production npm run build green; reference CALM document series passes node cli/dist/index.js validate ("All documents valid").

  • Node 22 (CI baseline) throughout.

Checklist

  • My commits follow the conventional commit format (type(calm-suite): …, DCO-signed)
  • I have updated documentation if necessary (AGENTS.md guidance; in-code JSDoc for the new persistence/metadata helpers)
  • I have added tests for my changes
  • My changes follow the project's coding standards

🤖 Generated with Claude Code

… sidecar

The CalmStudio editor gains the gemara/governance and multi-document feature set:

- bind Gemara controls/guidance to CALM via grc.store-backed decorators (YAML/JSON)
- connected AIGF<->CCC Governance view, one-click Apply governance, CALM 1.2 attest
- link-based C4 cross-document navigation (drill on double-click + breadcrumb), plus
  a "Create new linked document" button that scaffolds a child doc from a node
- decorators persisted as a standalone *.decorators.json sidecar (split from the
  architecture document), document-scoped decorator panel, split JSON viewer, .zip export
- diagram layout + editable document title persisted in CALM metadata
- AIGF Multi-Agent Reference Architecture template as a C4 document series

Signed-off-by: Eddie Knight <knight@linux.com>
Bring CALMGuard onto the canonical nested relationship-type form for cross-tool interop with CalmStudio, updating the extractor/normalizer/types, examples, and tests.

Signed-off-by: Eddie Knight <knight@linux.com>
…file)

Add a Makefile to launch the suite apps, build @finos/calm-models before CALMGuard in CI, and update the root lockfile for the new Studio/Guard dependencies.

Signed-off-by: Eddie Knight <knight@linux.com>
@eddie-knight eddie-knight force-pushed the feat/calmstudio-gemara-controls branch from 6337eef to 7b168f4 Compare June 25, 2026 09:56

@initcron initcron left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Substantive PR — the canonical-CALM 1.2 discipline is genuinely impressive. attestControlOnNode writing controls['ai-governance'] with positive AND negative tests (attest.test.ts:39,41 — the negative assertion that air-prev-002 is NOT a framework-prefixed key is exactly the right defense), details.detailed-architecture honoring the canonical core.json:56-67 shape, and the Export-only discipline from #2691 explicitly preserved with a contributor warning at io/export.ts:92-96. The reference Multi-Agent Reference Architecture series validates cleanly against calm validate. Big build of well-tested work.

One blocker, two maintainer questions, and a few non-blocking notes.


🔴 Blocker

B-1: Cmd+Z keyboard undo from canvas does NOT restore governance

There are two divergent undo wirings:

calm-suite/calm-studio/apps/studio/src/lib/canvas/CalmCanvas.svelte:471-479 (the @svelte-put/shortcut Cmd+Z handler bound to the canvas):

```svelte
function handleUndo() {
if (readonly) return;
const snapshot = undo();
if (snapshot) {
nodes = snapshot.nodes;
edges = snapshot.edges;
applyFromCanvas(nodes, edges); // ← rebuilds model from flow projection
}
}
```

calm-suite/calm-studio/apps/studio/src/routes/+page.svelte:957-963 (the menu-bar / Tauri handler):

```svelte
undo: () => {
const snapshot = undo();
if (snapshot) {
applyFromJson(snapshot.model); // ← restores decorators/controls
nodes = snapshot.nodes;
edges = snapshot.edges;
}
},
```

applyFromCanvas rebuilds via flowToCalm(nodes, edges) and merges with the prior model. But decorators are explicitly NOT in flow projection data — see DecoratorBadge.svelte:7-9 ("the canvas node/edge data does not carry decorators"). So a keyboard Cmd+Z fires after a governance attestation will silently fail to restore decorators / node-level controls.

Commit 866a4472 ("make governance changes undoable") + history.test.ts:144-167 capture and exercise the model snapshot — but the test calls applyFromJson(snap!.model) directly. It doesn't drive the CalmCanvas.handleUndo keyboard path that most users will hit.

Action: Either (a) make CalmCanvas.handleUndo/handleRedo apply snapshot.model too (mirror +page.svelte's wiring), then add a test that drives the keyboard handler against a governance mutation; or (b) confirm the canvas Cmd+Z is unreachable in practice (e.g. suppressed when GovernanceView has focus) and document why. Until one is true, the PR body's claim "governance changes are undoable" holds for the menu path but breaks for the keyboard path.


🟡 Important

I-1: metadata.name and metadata.c4-level are not namespaced

calm-suite/calm-studio/apps/studio/src/lib/io/documentName.ts:20 uses NAME_KEY = 'name'; calm-suite/calm-studio/apps/studio/src/lib/c4/c4Documents.svelte.ts:52 uses 'c4-level'. Compare to metadata.calmstudio-layout which IS correctly calmstudio--prefixed.

CALM 1.2 metadata has additionalProperties: true so this is spec-valid today, but if CALM 1.3 adopts a top-level document name or a C4-level concept, the unprefixed keys risk collision. Recommend either:

  • (a) rename to calmstudio-name and calmstudio-c4-level for consistency with calmstudio-layout, or
  • (b) open spec issues / ADRs proposing name and c4-level as canonical CALM 1.3 vocabulary.

Don't silently squat on bare names — that's the kind of decision that becomes load-bearing once docs are in the wild.


Questions for the maintainer (not blocking, but worth a deliberate call)

Q-1: Should the three themes be split?

The PR body itself organises the work into three numbered themes (Gemara↔CALM governance, link-based C4 navigation, doc UX+persistence). The 57 commits cleanly bucket into those three (~22 / ~16 / ~12 / ~7 misc). Theme 3 is the cleanest to extract — different files almost entirely. If a regression surfaces in any one theme post-merge, the others can't be reverted independently.

Not asking @eddie-knight to redo the work — just calling it out so the reviewer can decide whether to land as one or ask for a split.

Q-2: GovernancePanel→GovernanceView feature reduction

The deleted GovernancePanel.svelte (-924) surfaced AIGF risks with severity badges (OP/SEC/RC), an architecture-level governance score (ffd3871 retired), and per-mitigation Apply buttons. The new GovernanceView.svelte (+835) reorganises around a guidance↔controls join — a richer model — but a user who consumed "show me applicable risks for this AI node" no longer has that view. The catalogue data still exists (@calmstudio/calm-core/src/aigf/catalogue.tsaigfRisks, 23 entries) but nothing renders it.

If this was always scaffolding, the rewrite is clean. If risk visibility was a documented user feature, this is a regression. Worth an explicit "yes I accept losing the risks UI" sign-off.

Q-3: Stack depth — #2740#2692#2691#2683, all open

If any of the three base PRs is rejected or substantively changed in review, this PR rebases through the cascade. I confirmed gh pr diff 2740 correctly filters to this PR's diff only (16,375 lines == matches numstat), so we're reviewing the right surface — but landing this requires the full stack to converge. Worth deciding the merge order explicitly before this is approved.


🔵 Nits (non-blocking)

  • All 57 commits carry a Claude-Session: https://claude.ai/code/session_... trailer. Not Co-Authored-By, doesn't trip EasyCLA, but the URL 404s for everyone else and adds noise to git log. Worth scrubbing in a future workflow.
  • hub.ts:11-15 honestly documents that there's no signature/provenance verification on fetched catalogs. Trust model OK for first cut, but worth a SECURITY.md note or follow-up issue tracking cosign/oras as a future server-side proxy task.
  • c4-level metadata key has a reader in c4Documents.svelte.ts:49-54 but no interactive writer (only generate.mjs:227,245 for the bundled series). Interactive multi-doc series won't get the key written. Cosmetic — falls back to depth-derived badge. Either add a writer or remove the read.
  • +page.svelte is 3089+ lines. Not for this PR, but future work should extract handlers into +page.actions.ts or per-feature modules.
  • No svelte-check baseline N→N count in the PR body. "No new errors over branch baseline" is unverifiable externally. Concrete numbers next time would close that gap.

Missing test coverage

Tests for the new work are mostly thoughtful — but three gaps stand out:

  1. CalmCanvas.handleUndo keyboard path with governance state (see B-1). Existing history.test.ts tests the snapshot mechanism, not the wired keyboard handler.
  2. @architecture legacy fallbackloadGovernance.ts:36-39 and scope.ts:13 both honor it on read, but no integration test boots a doc with @architecture decorators and verifies governance still loads from the fallback path.
  3. Cross-tool round-trip of metadata.calmstudio-layout and metadata.name — the body claims "ignored by non-Studio consumers" but the only verification is spec additionalProperties: true. A round-trip e2e through cli validate + cli docify + the CALMGuard normalizer would close this.

Will re-review once B-1 + I-1 land. Thanks for the careful work on the canonical-CALM discipline — it's the standout strength of this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants