Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# ADR-0001: deck as panel-host for Mystira ops tooling in a generic shell

## Status

Proposed

## Date

2026-07-11 (proposed). Re-grounded against `dev` @ `bc0d1c5` on 2026-08-10 before commit — the
evidence in §Context was refreshed for PR #3 (Camera panel) and PR #5 (CI); the decision itself is
unchanged and still awaiting ratification.

## Context

deck was extracted from `mystira-workspace/apps/devhub` (March 2026) with the explicit goal of
becoming a **generic phoenixvc ops shell** — a VSCode-style Tauri desktop app with a Service
Manager, an Infrastructure panel, a Dashboard, and a .NET sidecar, reusable across the org. During
extraction the Mystira-specific panels (Cosmos Explorer, Migration Manager) were stripped so the
base shell would not carry Mystira coupling.

R13 now wants deck to be the **operator cockpit over the Mystira AI-content pipeline**
(`sluice → story-generator → publisher`; `docket` meters spend), across three facets (see
`docs/specs/deck-ops-cockpit.md`):

1. a Dashboard **cost/ops** section (sluice health + docket spend),
2. **re-porting** the Cosmos Explorer + Migration Manager panels, and
3. a Service-Manager **batch-run monitor** over the story-generator nightly Batch API.

This reintroduces Mystira-specific surfaces into the very shell that was just made generic. Two
observations sharpen the decision:

- The extraction was **incomplete**: the panel directories and their `VIEWS` entries are gone, but
the Rust `cosmos.rs` backend and the `.NET` `MigrationService` remained, `Dashboard.tsx` still
offers three Cosmos/Migration quick-actions that now silently land on the Service Manager, and
`StatisticsPanel.tsx` / `ExportPanel.tsx` still invoke `cosmos_stats` / `cosmos_export` while
nothing renders them. So Mystira coupling was never fully removed — it was left **half-wired**,
with live backends under no UI. (When first drafted this bullet also cited dangling
`AppContent.tsx` / `AppSidebar.tsx` imports that broke the build; PR #3 removed those, and CI is
green. The residue above is what survives, and the conclusion is unchanged.)
- Every R13 facet is fundamentally **Mystira-shaped** (Mystira Cosmos containers, the Mystira
story-gen Batch API, Mystira's spend in docket). None of it is generic ops.

The question this ADR settles: **should deck host Mystira-specific ops panels, and if so, how does
it stay a reusable generic shell rather than collapsing back into "Mystira DevHub"?**

Alternatives considered:

1. **Keep deck strictly generic; build the Mystira cockpit elsewhere** (e.g. a new Mystira-only
desktop app, or back inside `mystira-workspace`). Rejected: it discards deck's entire reason for
existing (it *is* the extracted DevHub), duplicates the Tauri/Service-Manager/exec machinery,
and the ecosystem docs (README, ecosystem-provisioning design) already designate **deck** as the
operator window into sluice/docket/story-gen.
2. **Fold the Mystira panels into the generic shell as first-class, always-present features.**
Rejected: it re-Mystira-fies the shell — a second org adopting deck would inherit Cosmos/Migration/
batch panels it does not want, and the "generic" claim becomes false.
3. **deck is a generic panel-host; Mystira panels are pluggable, clearly-bounded modules.** The
shell (VSCode layout, activity bar, Service Manager, Infrastructure panel, exec primitives,
.NET sidecar bridge) stays generic and org-agnostic; Mystira-specific surfaces are added through
the existing four-file panel recipe as **cohesive, self-contained modules** that consume
external Mystira/phoenixvc contracts and can be omitted without touching the shell.
Comment on lines +56 to +60

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Align the plugin boundary with the actual panel recipe.

The ADR says Mystira modules can be omitted without touching the shell and that VIEWS is the only shared touch-point. The companion specification requires changes to constants.ts, App.tsx, AppContent.tsx, and AppSidebar.tsx for each panel. Either define a real registry/plugin mechanism, or describe these as build-time modules that require shell registration.

Proposed wording adjustment
- can be omitted without touching the shell.
+ can be omitted through build-time panel registration; the current recipe requires explicit shell registration.

Also applies to: 73-77, 110-113

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md` around lines 56
- 60, Align the ADR’s plugin-boundary description with the four-file panel
recipe: either specify an actual registry/plugin mechanism, or state that
Mystira panels are build-time modules requiring registration changes in
constants.ts, App.tsx, AppContent.tsx, and AppSidebar.tsx. Remove or revise
claims that panels can be omitted without touching the shell and that VIEWS is
the sole shared touch-point, including the corresponding statements in the
referenced sections.


## Decision

**deck is a generic panel-host, and Mystira ops tooling is hosted as bounded panel modules on top
of it (Alternative 3).**

Concretely:

- The **shell is the generic asset**: `VSCodeLayout`, the activity bar / `VIEWS` routing, the
Service Manager, the Infrastructure panel, the Rust exec primitives (`Command::new`, argv-only),
and the `cli.rs` ↔ .NET-sidecar JSON bridge carry **no Mystira semantics** and remain reusable by
any phoenixvc project.
- **Mystira-coupled surfaces are panels/modules**, added via deck's existing recipe (a `VIEWS`
entry + `ACTIVITY_BAR_ITEMS` + an `AppContent` route + an `AppSidebar` block) plus a dedicated
backend module (`cost.rs`, `story_gen.rs`, the re-ported `cosmos`/`migration` panels over the
existing `cosmos.rs` + `MigrationService`). Each module owns its Mystira coupling; the shell does
not.
- Panels **consume external contracts, they do not embed Mystira domain logic**: Facet 1 reads
sluice `/health`,`/metrics` and docket's MCP tools; Facet 3 reads the story-gen Batch operation
model (`BatchGenerationItem` / `BatchSubmission`, operation-id + status); Facet 2 talks to Mystira
Cosmos via the operator's `az` session. deck holds **no** Mystira business rules — it is a viewer
and a trigger.
- **Secrets never enter the repo.** The docket `MCP_SECRET`, Mystira-Cosmos connection strings, and
the story-gen API token are session/local-only (env or machine-local app-config), consistent with
deck's `security.md` and the org MCP-bearer rule.
- **The interrupted extraction is completed, not perpetuated.** Re-porting Facet 2 means finishing
the half-removal cleanly (re-add the two `VIEWS` entries + panels, restore the stripped
`cosmos.stats`/`cosmos.export` .NET CLI handlers, fix the DevHub→Deck naming/CLI-path residue) so
the tree is consistent and the coupling is explicit and bounded — not dangling.

The full technical design is `docs/specs/deck-ops-cockpit.md`.

## Consequences

### Positive

- **deck stays reusable.** A future adopter gets the generic shell without Mystira panels; the
Mystira modules are additive and omissible.
- **One cockpit, one payoff.** Health, spend, data tooling, and batch ops live in a single operator
window, and the modules can cross-link (e.g. a batch run → its docket spend slice) precisely
because they are co-located but individually bounded.
- **Clear ownership.** The shell is deck's; each panel owns its upstream contract; Mystira domain
logic stays in `mystira-workspace`. No repo crosses that line.
- **Honest dependency posture.** Because panels consume external contracts, deck degrades
gracefully when an upstream is only specced (docket MCP, story-gen Batch API) instead of pretending
data exists.

### Negative / Costs

- **Coupling creep risk.** "Generic shell + Mystira modules" is a discipline, not a mechanism —
nothing stops a future change from leaking Mystira assumptions into the shell. Mitigation: keep
Mystira strings/types inside the panel modules and their backend files; the shell's `VIEWS`
registry is the only shared touch-point.
- **Multi-tenant panel selection is unsolved.** Today all `VIEWS` are compiled in. If a second org
adopts deck, panel visibility should become config-driven (feature flags / a panel registry).
This ADR does not build that; it only keeps the coupling bounded so it is a later, tractable step.
- **Restores Mystira-specific maintenance to deck.** deck now tracks Mystira upstreams (sluice
endpoints, docket tool names, the Batch API contract) and must follow their changes.

### Boundary summary

| Layer | Generic (org-agnostic) | Mystira-coupled (panel modules) |
| --- | --- | --- |
| Shell / layout / routing | ✅ `VSCodeLayout`, activity bar, `VIEWS` mechanism | — |
| Exec + sidecar bridge | ✅ `Command::new` argv-only, `cli.rs`, .NET sidecar protocol | — |
| Service Manager / Infrastructure | ✅ generic panels | Batch-run **section** consumes story-gen |
| Dashboard | ✅ generic panel | Cost/Ops **sections** consume sluice + docket |
| Cosmos / Migration | — | ✅ Mystira Cosmos panels + `MigrationService` |

## Notes on placement of this ADR

Before this ADR, deck had **no** ADR directory. The only breadcrumb was a dangling reference in
`docs/guides/contracts-migration.md` (lines 20 and 267) to
`../adr/0020-package-consolidation-strategy.md` — an artifact inherited from mystira-workspace's
4-digit ADR numbering (that file does not exist in deck, and this ADR does not create it). deck is
**not** onboarded to AgentKit/Retort, so there is no generated `decisions/` registry to collide
with (unlike docket's ADR-09, which had to skip reserved numbers).

Decision on location and number:

- **Location:** `docs/adr/` — matches the single existing breadcrumb (`../adr/…`) and keeps ADRs
beside the existing `docs/guides/` and the proposed `docs/specs/`. (The phoenixvc/docket
convention `docs/architecture/decisions/NN-*.md` was considered; `docs/adr/` was chosen to honour
deck's own inherited breadcrumb and avoid inventing an `architecture/` tree deck doesn't have.)
- **Number:** **`0001`** — deck's first hand-authored ADR, 4-digit to match the inherited breadcrumb
style.
- **Format:** the org/mystira **narrative** ADR shape (Status / Context / Decision / Consequences /
placement note), not a weighted decision-matrix — this records a decision narrative, not a tool
bake-off.

This establishes `docs/adr/NNNN-*.md` as deck's ADR home for future decisions.

## References

- `docs/specs/deck-ops-cockpit.md` — deck ops cockpit technical spec (this ADR's companion).
- `mystira-workspace .agents/roadmaps/video-generation/design-ecosystem-provisioning.md` — deck's
ecosystem role (Models panel + sluice hybrid routing; §1 fit-with-what-deck-already-is).
- `phoenixvc/sluice docs/planning/sluice-go-live-audit-2026-07.md` — sluice LIVE verification;
`/health`, `/metrics`, `/spend/logs` surfaces + the master-key caveat.
- `phoenixvc/docket docs/architecture/specs/07_docket_mcp_server.md` + `decisions/09-docket-mcp-domain-service.md`
— docket MCP tool surface, phasing, and the domain-service-MCP shape deck consumes.
- `mystira-workspace apps/story-generator/docs/specs/BATCH_API_GENERATION_ROUTING.md` — the batch
operation-id + status model deck's Facet 3 renders against.
Loading