Skip to content

Phase 4A: ProposalManager (Changeset Semantics) #13

@mikewolfd

Description

@mikewolfd

Motivation

The changeset/proposal system is the architectural centerpiece of the unified authoring architecture. It enables AI changes to be reviewed, accepted, or rejected using git merge semantics — the user is never locked out of editing.

Parent epic: #9 — Unified Authoring Architecture

Key Design Decisions

  • Middleware-based recording — captures commands by construction via CommandPipeline, never misses
  • Git merge model — user never locked out, conflicts detected at merge time, not prevented by locking
  • Command-level replay — deterministic (same commands + same snapshot = same state), not tool-level
  • Layered savepoints — error recovery at each replay phase (AI groups, user overlay, structural validation)
  • Undo/redo disabled during open changeset — the changeset IS the undo mechanism

Scope

Pass 4a-A: Recording Infrastructure (formspec-core)

  • ChangesetRecorderControl interface in core types
  • createChangesetMiddleware() factory function
  • Middleware injects via ProjectOptions.middleware
  • Actor-tagged recording ('ai' | 'user')
  • Unit tests for middleware capture behavior

Pass 4a-B: State Restoration (formspec-core)

  • IProjectCore.restoreState(snapshot: ProjectState) method
  • Implementation in RawProject — state assignment + notification
  • Must invalidate _cachedComponent and handle generatedComponent reconciliation
  • History stack cleared on restore
  • Unit tests for restore + re-notification

Pass 4a-C: ProposalManager (formspec-studio-core)

  • Changeset and ChangeEntry types
  • ProposalManager class — changeset lifecycle (open, close, merge, reject)
  • Actor-tagged recording orchestration (beginEntry/endEntry brackets)
  • Snapshot-and-replay for reject/partial merge
  • User overlay track (concurrent user edits during AI work)
  • Content immutability enforcement (VP-02: refuse changeset on non-draft definitions)
  • Undo/redo disabled guard during open changeset
  • Edge case handling: initialValue = prefix value capture, prePopulate, now() non-determinism
  • Error recovery with layered savepoints
  • Integration tests for full lifecycle

Pass 4a-D: Rust Dependency Analysis

  • New crate or extension to existing crate for dependency analysis
  • FEL expression scanning (reusing fel-core dependency extraction)
  • Reference edge extraction (bind paths, shape composition, variable scopes, optionSet refs, etc.)
  • Order-dependent grouping (screener routes, theme selectors)
  • Connected component computation for dependency groups
  • Cross-document edge detection (locale, ontology, references, theme overrides, component bindings)
  • WASM bridge for compute_dependency_groups()
  • Unit tests in Rust + integration tests via WASM

Pass 4a-E: Changeset MCP Tools

  • formspec_changeset_open — start changeset, capture snapshot
  • formspec_changeset_close — seal changeset, compute dependency groups
  • formspec_changeset_list — list changesets with status and groups
  • formspec_changeset_accept — accept all or specific dependency groups
  • formspec_changeset_reject — reject all or specific groups, snapshot-and-replay
  • Tool annotations: formspec_changeset_list readOnly, formspec_changeset_reject destructive

Acceptance Criteria

  • Recording middleware captures all commands flowing through the pipeline, tagged by actor
  • Changeset lifecycle works end-to-end: open -> AI mutations -> user edits -> close -> review -> merge/reject
  • Partial merge correctly replays accepted groups + user overlay in chronological order
  • Reject all preserves user overlay edits
  • Post-merge diagnose() runs and reports structural issues
  • Error recovery restores to safe state on replay failure
  • Dependency grouping correctly identifies related operations

Layer

Management Instance (Layers 1-4, plus Rust/WASM)

Dependencies

Spec Reference

thoughts/specs/2026-03-24-unified-authoring-architecture.md — Section 2 (ProposalManager)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions