Skip to content

Make DashboardAuthoringSession use the shared workspace mutation pipeline before adding callers #349

Closed

Description

@BorisTyshkevich

Status

createDashboardAuthoringSession has no production callers on current main; it is referenced only by its implementation and unit tests. This is therefore latent correctness/design debt, not a presently reachable user-facing defect.

Keep the issue open, but it does not block current Dashboard work. It does block wiring this session into Workbench, AI, MCP, or any other production caller.

Problem

DashboardAuthoringSession.commit() currently builds a complete StoredWorkspaceV1 from session-local snapshots and calls WorkspaceRepository.commit() directly.

That bypasses the shared mutation contract introduced by #341/#344:

  1. enter the application workspace write queue;
  2. load the latest committed aggregate at dequeue time;
  3. apply a mutation to that latest aggregate;
  4. commit atomically;
  5. project the committed result.

Once this session gains a live caller, its current implementation can overwrite query, Dashboard, import, rename, or other workspace changes committed by another same-tab producer while the authoring session was open.

Required design

Do not inject a raw repository commit capability into the authoring session.

Inject an application-level mutation seam equivalent to:

mutateWorkspace(
  transform: (latest: StoredWorkspaceV1 | null) =>
    StoredWorkspaceV1 | null | Promise<StoredWorkspaceV1 | null>,
): Promise<WorkspaceCommitResult | null>;

At commit time, the session must rebase its intended Dashboard/query changes onto the dequeue-time latest workspace rather than replacing latest with the session's original workspace snapshot.

The implementation must define explicit conflict semantics for session-local edits when the latest workspace changed incompatibly. It must not silently discard either side.

Scope

Preferred: adapt and retain DashboardAuthoringSession because it remains a useful reusable boundary for future non-DOM callers.

Acceptable alternative: delete the unused module and tests, then recreate it against the shared mutation API when the first production caller is introduced.

This issue is separate from #343. #343 protects cross-tab writes with repository/storage-level optimistic concurrency. This issue ensures this future producer obeys the existing same-tab mutation pipeline.

Resolution

The acceptable deletion alternative was selected for shipping: remove the unused authoring-session module and its dedicated tests before it gains a production caller. Any future non-DOM authoring boundary must be recreated against the shared mutateWorkspace pipeline.

Cleanup acceptance:

  • The unused implementation and its session-only API types are deleted.
  • The dedicated authoring-session tests are deleted.
  • No production caller or stale repository reference remains.
  • The surviving pure Dashboard command/model coverage remains at the repository gate.

The behavior criteria below applied to the retained-session design and are superseded by this resolution.

Superseded retention acceptance criteria

  • DashboardAuthoringSession no longer receives or calls raw WorkspaceRepository.commit().
  • Its candidate is constructed from the workspace loaded inside the serialized mutation slot.
  • Unrelated query and workspace metadata changes made after session creation survive a session commit.
  • Dashboard revision advances from the latest committed Dashboard revision.
  • A missing or incompatibly changed Dashboard produces an explicit abort/conflict result rather than a stale replacement.
  • Successful commits update the session's clean baseline from the committed result.
  • Failed or aborted commits leave the draft dirty and preserve diagnostics.
  • Unit tests include a mixed-producer regression where another mutation lands after session creation but before session commit.
  • No production caller may be added until these criteria are met.

Related

Activity

  1. BorisTyshkevich commented on Jul 20, 2026

    @BorisTyshkevich
    CollaboratorAuthor

    Plan (small standalone PR, unblocked):

    createDashboardAuthoringSession currently takes the raw WorkspaceRepository and calls repository.commit(candidate) with a session-locally built candidate — the exact pre-queue-snapshot pattern PR #344 eliminated from every live producer. Since the module has no callers yet, the fix is an interface change, not a behavior change:

    1. Replace the injected repository commit dependency with an injected mutate: App['mutateWorkspace'] seam (the session may keep a read-only loadCurrent for its own snapshot needs).
    2. Build the commit candidate inside the transform from the dequeue-time latest (re-apply the session's pending command/document delta to it), mirroring runCommand in src/ui/dashboard.ts.
    3. Update its unit tests to the stateful fake repo + queue-mirroring mutateWorkspace helpers added to tests/helpers/fake-app.ts in fix(#341): one committed workspace for Dashboard + Workbench, consistent exports #344, including one mixed-producer regression.

    Alternative if we'd rather not maintain speculative code: delete the module and recreate it against mutateWorkspace when the first AI/MCP caller lands. Either resolution prevents the footgun; wiring it to the seam preserves the design investment.

  2. changed the title [-]dashboard-authoring-session commits outside the serialized workspace write queue[/-] [+]Make DashboardAuthoringSession use the shared workspace mutation pipeline before adding callers[/+] on Jul 21, 2026
  3. added
    enhancementNew feature or request
    and removed
    inboxFiled mid-task; not yet triaged into the roadmap
    enhancementNew feature or request
    on Jul 21, 2026
  4. added a commit that references this issue on Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions