docs: add R13 ops-cockpit spec and ADR-0001 (deck as panel-host) - #6
Conversation
Lands the detailed spec and ADR that baton task 0e6c0c19 has been blocked
on ("NEXT: detailed spec + ADR required before build"). Both were authored
2026-07-11 and had lived only as untracked files in a working tree since.
- docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md (Proposed)
Records the decision that deck stays a generic panel-host and Mystira ops
tooling is hosted as bounded, omissible panel modules on top of it, rather
than folding Mystira surfaces into the shell or building the cockpit
elsewhere. Establishes docs/adr/NNNN-*.md as deck's ADR home.
- docs/specs/deck-ops-cockpit.md (Draft)
Technical design for the three R13 facets: a Dashboard cost/ops section
(sluice health + docket spend), the Cosmos Explorer + Migration Manager
re-port, and a Service-Manager story-gen batch-run monitor. Establishes
docs/specs/ as the home for deck design specs.
Re-grounded against dev @ bc0d1c5 before commit. The design is unchanged;
the current-state evidence was corrected where deck moved since July:
- §1.2 claimed the frontend could not typecheck because AppContent.tsx and
AppSidebar.tsx still imported the removed panels. PR #3 removed that
wiring and PR #5's CI proves the build is green. The finding is kept in
corrected form — the extraction is still unfinished, but the evidence is
now behavioural: three dead Dashboard quick-actions that fall through to
the Service Manager, orphaned StatisticsPanel/ExportPanel callers, and
live Rust/.NET backends with no UI above them.
- §1.1 now records crates/deck-camera and the CI gates, and cites the
Camera panel as the four-file recipe's most recent worked example.
- §1.4/§1.2 line references refreshed; get_cli_executable_path() is in
helpers.rs, not cli.rs.
Docs-only: no code, no CI surface touched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 40 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdded ADR-0001 and a draft specification for using Deck as a generic host for Mystira operations panels. The specification covers Dashboard monitoring, Cosmos and migration tooling, story-generator batch operations, security, readiness, and integration prerequisites. ChangesMystira operations cockpit
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with 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.
Inline comments:
In `@docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md`:
- Around line 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.
In `@docs/specs/deck-ops-cockpit.md`:
- Line 86: Remove the blank line within the blockquote in the drift note section
of the document, keeping the note contiguous with the surrounding blockquote
content or moving it outside the blockquote.
- Around line 153-160: Resolve the `/metrics` authentication ambiguity in the
deck-ops cockpit specification by selecting one deployed contract. Update the
signal table and related readiness or cross-repo dependency references
consistently, and document credential provisioning plus readiness behavior if
scrape-scoped authentication is selected.
- Around line 232-233: Update the Section 3.2 command plan around sluice_health
to expose a distinct sluice_liveliness command and corresponding DTO for
/health/liveliness, while retaining sluice_health for /health/readiness;
alternatively, explicitly aggregate both endpoints under the existing command
with documented targets.
- Around line 422-426: Update the docket MCP entry to use a single verified
status consistent with the stated built, deployed, and registered state; remove
the contradictory “specced, not built” wording while preserving the listed
tools, deployment details, registration, and references.
- Around line 390-392: Update the Rust command and service-health HTTP paths
using reqwest to enforce HTTPS and allow only the configured sluice, docket, and
story-gen hosts. Reject any destination outside that host allow-list, and ensure
check_service_health does not enable danger_accept_invalid_certs(true); preserve
the existing Tauri capability scope.
- Around line 320-331: Define explicit request and response types for POST
api/stories/batch and GET api/stories/batch/{operationId}, replacing the
undefined BatchOperation and keeping BatchGenerationItem distinct from
BatchSubmission. Reuse GeneratorConfig from story_generator.rs for supported
fields, defaults, and validation; document the submit-phase trigger contract,
kill-switch write semantics, and POST idempotency keyed by custom_id ==
BatchGenerationItem.Id.
- Around line 209-211: Update the docket /mcp request configuration to validate
the resolved endpoint before attaching the DOCKET_MCP_TOKEN bearer: require
HTTPS and an allowlisted base host, including the configured default and
approved override. Reject invalid endpoint overrides and do not send the
Authorization header when validation fails.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fc8dbe2c-fbac-4a49-840f-2c2e84e410e1
📒 Files selected for processing (2)
docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.mddocs/specs/deck-ops-cockpit.md
| 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. |
There was a problem hiding this comment.
📐 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.
| | Signal | Source | Endpoint | Auth | Transport | | ||
| | --- | --- | --- | --- | --- | | ||
| | Gateway liveness | sluice | `GET https://sluice.phoenixvc.tech/health/liveliness` | **none** | Rust `cost.rs` (reqwest) | | ||
| | Gateway readiness (db, litellm version, callbacks) | sluice | `GET …/health/readiness` → JSON | **none** | Rust `cost.rs` | | ||
| | Throughput / request rollups | sluice | `GET …/metrics` (Prometheus text) | **none** (or scrape-scoped) | Rust `cost.rs` — parse Prometheus | | ||
| | Spend summary / by-service / burn / trend | **docket MCP** | `get_burn_total`, `get_spend_by_service`, `get_cost_trend`, `get_ai_spend` | `MCP_SECRET` Bearer | see §3.3 | | ||
| | Optimization insights | docket MCP | `get_optimization_insights` | `MCP_SECRET` Bearer | see §3.3 | | ||
| | Per-component LLM spend | docket MCP | `get_llm_usage_by_component` | `MCP_SECRET` Bearer | **gated** — §7 of the docket spec | |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file exists and relevant ranges =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
wc -l docs/specs/deck-ops-cockpit.md
sed -n '130,180p' docs/specs/deck-ops-cockpit.md | cat -n
sed -n '380,430p' docs/specs/deck-ops-cockpit.md | cat -n
else
echo "docs/specs/deck-ops-cockpit.md not found"
fd -a 'deck-ops-cockpit.md|cockpit|deck-ops' .
fi
echo
echo "== search metrics/auth/readiness mentions =="
rg -n "metrics|readiness|liveliness|scrape|Authentication|auth|Bearer|Authorization|MCP_SECRET|health" docs/specs/deck-ops-cockpit.md || trueRepository: phoenixvc/deck
Length of output: 12076
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repository files mentioning /metrics or health endpoints =="
rg -n "/metrics|health/liveliness|health/readiness|readiness|liveliness|get_burn_total|MCP_SECRET" . --glob '!node_modules' --glob '!dist' --glob '!build' --glob '!out' --glob '!coverage' | head -200 || trueRepository: phoenixvc/deck
Length of output: 3705
Resolve the /metrics authentication contract before declaring Facet 1 buildable.
The spec allows /metrics to be either unauthenticated or scrape-scoped, while the readiness tables and cross-repo dependency list treat the full health + throughput path as unauthenticated. Pick one deployed contract and document credential provisioning/readiness behavior if auth is required.
🤖 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/specs/deck-ops-cockpit.md` around lines 153 - 160, Resolve the
`/metrics` authentication ambiguity in the deck-ops cockpit specification by
selecting one deployed contract. Update the signal table and related readiness
or cross-repo dependency references consistently, and document credential
provisioning plus readiness behavior if scrape-scoped authentication is
selected.
| - **Endpoint config:** the docket `/mcp` base URL and the sluice base URL are non-secret and can | ||
| live in `Deck.CLI/appsettings.json` / deck app-config with env-override, defaulting to | ||
| `https://sluice.phoenixvc.tech` and the docket Railway `/mcp` URL. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate spec and docket references =="
fd -a 'deck-ops-cockpit.md' . || true
rg -n "DOCKET_MCP_TOKEN|mcp|Docket|Bearer|Authorization|sluice|appsettings" . -S --glob '!**/.git/**' --glob '!node_modules/**' | head -200
echo "== spec context =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
sed -n '180,230p' docs/specs/deck-ops-cockpit.md | cat -n
fiRepository: phoenixvc/deck
Length of output: 13725
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repository files likely containing docket/MCP cost client =="
git ls-files | rg '^(app/src-tauri|Deck\.CLI|docs/specs/07_docket_mcp_server\.md|docs/specs/deck-ops-cockpit\.md)' | sed -n '1,120p'
echo "== cost/docket/mcp token references in tracked files =="
rg -n "DOCKET_MCP_TOKEN|MCP_SECRET|docket .*mcp|/mcp|Authorization: Bearer|Authorization: bearer|requests\.post|client\.post|HttpClient|reqwest|AppSettings|Docket" $(git ls-files | tr '\n' ' ') -S --glob '!*node_modules/**' | sed -n '1,220p'Repository: phoenixvc/deck
Length of output: 5237
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== inspect existing auth/header usage patterns in Rust source =="
rg -n "Authorization|bearer|Bearer|reqwest::Client|allow_redirects|https://|http://" app/src-tauri/src -S --glob '*.rs' | sed -n '1,240p'
echo "== inspect relevant Rust source slices =="
for f in app/src-tauri/src/cosmos.rs app/src-tauri/src/github.rs app/src-tauri/src/utils.rs app/src-tauri/src/config.rs; do
if [ -f "$f" ]; then
echo "--- $f ---"
sed -n '1,260p' "$f" | cat -n
fi
doneRepository: phoenixvc/deck
Length of output: 43998
Do not send the bearer to an arbitrary endpoint.
Endpoint config is allowlisted as non-secret, but the docket /mcp calls still send Authorization: Bearer <DOCKET_MCP_TOKEN>. Validate that the resolved URL uses https and an approved base host before adding the bearer header; reject invalid overrides.
🤖 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/specs/deck-ops-cockpit.md` around lines 209 - 211, Update the docket
/mcp request configuration to validate the resolved endpoint before attaching
the DOCKET_MCP_TOKEN bearer: require HTTPS and an allowlisted base host,
including the configured default and approved override. Reject invalid endpoint
overrides and do not send the Authorization header when validation fails.
| #[tauri::command] pub async fn sluice_health() -> Result<SluiceHealth, String>; // GET /health/readiness | ||
| #[tauri::command] pub async fn sluice_metrics() -> Result<SluiceMetrics, String>; // GET /metrics (Prometheus parse) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Find target file:"
fd -a "deck-ops-cockpit.md" . || true
echo
echo "Target context if found:"
while IFS= read -r f; do
echo "--- $f"
wc -l "$f"
sed -n '200,260p' "$f"
done < <(fd "deck-ops-cockpit.md" .)
echo
echo "Search for health/liveliness/readiness references:"
rg -n "/health/(liveliness|readiness)|sluice_health|liveliness|readiness" . || trueRepository: phoenixvc/deck
Length of output: 299
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Target context:"
wc -l docs/specs/deck-ops-cockpit.md
sed -n '200,260p' docs/specs/deck-ops-cockpit.md
echo
echo "Search health references:"
rg -n "/health/(liveliness|readiness)|sluice_health|liveliness|readiness" docs/specs/deck-ops-cockpit.md . || trueRepository: phoenixvc/deck
Length of output: 5649
Expose sluice_liveliness alongside readiness.
Section 3.2 depends on /health/liveliness, but the cost.rs command plan only maps sluice_health to /health/readiness. Add a liveness command/DTO, or rename/aggregate it with an explicit /health/liveliness target.
🤖 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/specs/deck-ops-cockpit.md` around lines 232 - 233, Update the Section
3.2 command plan around sluice_health to expose a distinct sluice_liveliness
command and corresponding DTO for /health/liveliness, while retaining
sluice_health for /health/readiness; alternatively, explicitly aggregate both
endpoints under the existing command with documented targets.
| ### 5.2 Design against the specced operation-id + status model | ||
|
|
||
| From `BATCH_API_GENERATION_ROUTING.md` (R13, Draft — **not yet built**), the model deck renders | ||
| against: | ||
|
|
||
| - **Enqueue → operation id.** A bulk request returns an **operation id immediately (202)**, exactly | ||
| like the continuity async pattern. `custom_id == BatchGenerationItem.Id`. | ||
| - **Item status ladder:** `Queued → Submitted → Succeeded | Errored | Expired | Failed` (with | ||
| `BatchId msgbatch_…`, `SubmittedAt`, `CompletedAt`, `Attempts`). | ||
| - **Batch status:** `BatchSubmission { BatchId, WindowId (batch-YYYYMMDD), ItemCount, | ||
| ProcessingStatus (in_progress|canceling|ended), Counts { processing, succeeded, errored, | ||
| canceled, expired } }`. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repo files around deck contracts and doc:"
git ls-files | rg '(^docs/specs/deck-ops-cockpit\.md$|BATCH_API_GENERATION_ROUTING\.md$|story_generator\.rs$|deck-contracts|batch|operation)' || true
echo
echo "Target doc section:"
if [ -f docs/specs/deck-ops-cockpit.md ]; then
wc -l docs/specs/deck-ops-cockpit.md
sed -n '300,380p' docs/specs/deck-ops-cockpit.md | cat -n -v
fi
echo
echo "Search BatchOperation and related symbols:"
rg -n "BatchOperation|BatchGenerationItem|BatchSubmission|GeneratorConfig|POST .*202|202|trigger|kill|cancel|idempot" -S . || trueRepository: phoenixvc/deck
Length of output: 19905
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Story generator contract:"
cat -n crates/deck-contracts/src/story_generator.rs | sed -n '1,240p'
echo
echo "Any Batch Generation model refs in repository text only:"
python3 - <<'PY'
import subprocess, re, pathlib
files = subprocess.check_output(['git','ls-files'], text=True).splitlines()
patterns = [
re.compile(r'\b(BatchGenerationItem|BatchSubmission|GeneratorConfig|BatchOperation|BatchEnqueueRequest)\b'),
re.compile(r'\b(POST api/stories/batch|GET api/stories/batch/\{operationId\}|202|idempot|kill|cancel)\b', re.I),
]
for path in files:
text = pathlib.Path(path).read_text(errors='ignore')
hits = [f"{m.group(1)} ({text.count(m.group(1))})" for m in patterns[0].finditer(text) if m.group(1)]
status_hits = set(re.findall(r'(\b(?:POST api/stories/batch|GET api/stories/batch/\{operationId\}|202|idempot|kill|cancel)\b)', text, re.I))
if hits or status_hits:
print(f"--- {path} ---")
for hit in sorted(set(hits)):
print("symbol", hit)
if status_hits:
print("signals", ", ".join(sorted(status_hits)))
print()
PYRepository: phoenixvc/deck
Length of output: 8661
Define the batch command contract before implementation.
POST api/stories/batch and GET api/stories/batch/{operationId} currently return the undefined BatchOperation. Add the exact request/response types; it should not contain both BatchGenerationItem and BatchSubmission, which have different meanings. Reuse GeneratorConfig from crates/deck-contracts/src/story_generator.rs for supported fields, defaults, and validation. Also define the submit-phase trigger contract, kill-switch write semantics, and POST idempotency for custom_id == BatchGenerationItem.Id.
Also applies to: 336-362
🤖 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/specs/deck-ops-cockpit.md` around lines 320 - 331, Define explicit
request and response types for POST api/stories/batch and GET
api/stories/batch/{operationId}, replacing the undefined BatchOperation and
keeping BatchGenerationItem distinct from BatchSubmission. Reuse GeneratorConfig
from story_generator.rs for supported fields, defaults, and validation; document
the submit-phase trigger contract, kill-switch write semantics, and POST
idempotency keyed by custom_id == BatchGenerationItem.Id.
| - **argv-only + minimal capabilities.** New backend commands use `Command::new`/reqwest with no | ||
| shell interpolation; outbound HTTP to sluice/docket/story-gen is added as an explicit Tauri | ||
| capability, not a blanket network grant. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
rg -n 'reqwest|plugin-http|http:default|capabilities' app/src-tauri cratesRepository: phoenixvc/deck
Length of output: 481
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- app/src-tauri/Cargo.toml dependencies/packages ---\n'
cat -n app/src-tauri/Cargo.toml | sed -n '1,80p'
printf '\n--- capabilities/default.json ---\n'
cat -n app/src-tauri/Capabilities/default.json 2>/dev/null || cat -n app/src-tauri/capabilities/default.json | sed -n '1,220p'
printf '\n--- reqwest usage in utils.rs ---\n'
cat -n app/src-tauri/src/utils.rs | sed -n '300,355p'
printf '\n--- reqwest usage in status.rs ---\n'
cat -n app/src-tauri/src/services/status.rs | sed -n '1,90p'
printf '\n--- spec relevant lines ---\n'
cat -n docs/specs/deck-ops-cockpit.md | sed -n '370,405p'
printf '\n--- files cost/story names ---\n'
fd -i 'cost|story_gen|status|utils' app/src-tauri -t fRepository: phoenixvc/deck
Length of output: 243
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- app/src-tauri/Cargo.toml dependencies/packages ---'
cat -n app/src-tauri/Cargo.toml | sed -n '1,80p'
printf '%s\n' ''
printf '%s\n' '--- capabilities/default.json ---'
if [ -f app/src-tauri/Capabilities/default.json ]; then
cat -n app/src-tauri/Capabilities/default.json | sed -n '1,220p'
else
cat -n app/src-tauri/capabilities/default.json | sed -n '1,220p'
fi
printf '%s\n' ''
printf '%s\n' '--- reqwest usage in utils.rs ---'
cat -n app/src-tauri/src/utils.rs | sed -n '300,355p'
printf '%s\n' ''
printf '%s\n' '--- reqwest usage in status.rs ---'
cat -n app/src-tauri/src/services/status.rs | sed -n '1,90p'
printf '%s\n' ''
printf '%s\n' '--- spec relevant lines ---'
cat -n docs/specs/deck-ops-cockpit.md | sed -n '370,405p'
printf '%s\n' ''
printf '%s\n' '--- files cost/story names ---'
fd -i 'cost|story_gen|status|utils' app/src-tauri -t fRepository: phoenixvc/deck
Length of output: 9740
Enforce and allow-list native reqwest destinations.
This app uses native reqwest for command and service-health HTTP, but the Tauri capability is shell/opener/FS focused and has no HTTP plugin permissions. Add native allow-list checks in the Rust commands: require HTTPS and only permit configured sluice/docket/story-gen hosts, including rejected danger_accept_invalid_certs(true) in check_service_health.
🤖 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/specs/deck-ops-cockpit.md` around lines 390 - 392, Update the Rust
command and service-health HTTP paths using reqwest to enforce HTTPS and allow
only the configured sluice, docket, and story-gen hosts. Reject any destination
outside that host allow-list, and ensure check_service_health does not enable
danger_accept_invalid_certs(true); preserve the existing Tauri capability scope.
Source: MCP tools
| 1. **docket MCP** (`phoenixvc/docket`) — Phase-1 tools built (`get_burn_total`, | ||
| `get_spend_by_service`, `get_cost_trend`, `get_ai_spend`, `get_spend_by_resource_group`, | ||
| `get_spend_by_region`), deployed on Railway behind `MCP_SECRET`, and **registered in the org | ||
| MCP** (`register_project`). Status: **specced, not built** (spec `07_docket_mcp_server.md`, | ||
| ADR-09; baton `91ca9c86-4057-49ad-8d2e-4744188daee1`). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate file =="
git ls-files | rg 'docs/specs/deck-ops-cockpit\.md|07_docket_mcp_server\.md|ADR-09|baton|docket|cockpit' | head -200
echo
echo "== target excerpt =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
nl -ba docs/specs/deck-ops-cockpit.md | sed -n '405,435p'
else
echo "target file not found"
fi
echo
echo "== search for docket status/status-related terms and baton =="
rg -n "docket|specced, not built|Phase-1|Phase 1|baton|91ca9c86-4057-49ad-8d2e-4744188daee1|register_project|mcp_secret|MCP_SECRET" docs/specs docs 2>/dev/null | head -200Repository: phoenixvc/deck
Length of output: 264
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target excerpt =="
awk 'NR>=405 && NR<=435 {printf "%7d\t%s\n", NR, $0}' docs/specs/deck-ops-cockpit.md
echo
echo "== search for docket references, status, and baton =="
rg -n "docket|specced, not built|Phase-1|Phase 1|baton|91ca9c86-4057-49ad-8d2e-4744188daee1|register_project|MCP_SECRET|07_docket_mcp_server\.md|ADR-09" docs/specs docs 2>/dev/null | head -200 || trueRepository: phoenixvc/deck
Length of output: 19082
Use one status for the docket dependency.
Lines 407 and 422-425 say the docket MCP tools are built, deployed, and registered; line 425 then says its status is “specced, not built.” This contradicts the Facet 1 readiness statement and the build order. Replace the dependency status with one verified status.
🤖 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/specs/deck-ops-cockpit.md` around lines 422 - 426, Update the docket MCP
entry to use a single verified status consistent with the stated built,
deployed, and registered state; remove the contradictory “specced, not built”
wording while preserving the listed tools, deployment details, registration, and
references.
Follow-up to CodeRabbit review on PR #6. Three changes, all current-state accuracy — the design and both decisions are unchanged. - §1.3 claimed outbound HTTP to sluice/docket would be "an explicit capability addition". That is wrong: deck calls out via native reqwest from Rust, not the Tauri HTTP plugin, so capabilities/default.json (shell/opener/dialog/fs only) does not constrain it. The spec's own security posture was resting on a mechanism that does not apply. Now states the real requirement — per-command https + host allowlisting enforced in Rust — and flags that services/status.rs:44 sets danger_accept_invalid_certs(true) for localhost, which the cockpit's clients must not reuse against remote endpoints. - §5.4 introduced a BatchOperation type without noting that crates/deck-contracts/src/story_generator.rs already exists and is the natural home for it. Records that, and that BatchGenerationItem and BatchSubmission must stay distinct per §5.2. - §1.2 fixes MD028 (blank line inside blockquote) introduced by the drift note in the previous commit. Not changed, and left for the owner as review feedback on a Draft spec: the /metrics auth contract, the missing sluice_liveliness command, and the ADR's "omitted without touching the shell" wording vs the four-file recipe (the ADR already books this under Negative/Costs). The reported §7/§8 docket-status contradiction is a misread — §8 lists what must become real, then states current status; the two agree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Lands the detailed spec and ADR that baton task
0e6c0c19— "Deck R13 focus: cost/ops cockpit, Mystira ops tooling, and story-gen batch-run ops" — has been blocked on since 2026-07-21 (NEXT: detailed spec + ADR required before build).Both documents were authored 2026-07-11 and, until this PR, existed only as untracked files in a local working tree. No branch, no remote, no copy anywhere. A
git clean -fdwould have destroyed them.What lands
docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.mddocs/adr/NNNN-*.mdas deck's ADR homedocs/specs/deck-ops-cockpit.mddocs/specs/as the home for deck design specsADR-0001 settles whether deck should reintroduce Mystira-specific surfaces into a shell that was deliberately made generic during the devhub→deck extraction. Decision: deck is a generic panel-host; Mystira ops tooling is hosted as bounded, individually-omissible panel modules on top of it — not folded into the shell, and not built as a separate app. Left at Proposed: nothing has been built against it yet.
The spec covers the three R13 facets — a Dashboard cost/ops section (sluice health + docket spend), the Cosmos Explorer + Migration Manager re-port, and a Service-Manager story-gen batch-run monitor — with per-facet readiness and the cross-repo dependency list.
Re-grounded against
dev@bc0d1c5deck moved after these were written (PR #3 added the Camera panel and
crates/deck-camera; PR #5 added CI). The design and both decisions are unchanged; the current-state evidence was corrected where it had gone stale:AppContent.tsx/AppSidebar.tsxstill imported the removedCosmosExplorer/MigrationManagerand switched on undefinedVIEWSmembers. PR feat(camera): add private local viewer #3 removed that wiring, and PR ci: add GitHub Actions workflow for Rust and UI #5's CI proves the build is green. The finding is kept in corrected form — the extraction is still unfinished, but the surviving evidence is behavioural: threeDashboard.tsxquick-actions callingonNavigate("cosmos")/onNavigate("migration")that fall throughAppContent'sdefault:to the Service Manager, orphanedStatisticsPanel.tsx/ExportPanel.tsxinvoking Cosmos commands whose .NET handlers were stripped, and live Rust + .NET backends with no UI above them. A dated drift note in §1.2 records exactly what changed and why the conclusion still holds.crates/deck-camera, the six CI gates, and cites the Camera panel as the four-file recipe's most recent worked example.main.rs:69,main.rs:42-43,86-90,constants.ts:2-8,Program.cs:126-127);get_cli_executable_path()is inhelpers.rs:111-123, notcli.rs.Claims re-verified as still accurate: the stripped
cosmos.stats/cosmos.export.NET handlers, the present-and-registeredcosmos.rs+MigrationService, the whole DevHub naming residue, and the dangling../adr/0020-*breadcrumb indocs/guides/contracts-migration.mdthat motivates thedocs/adr/placement.Notes for review
docs/adr/,docs/specs/); deck previously had onlydocs/guides/. Rationale for both is in the spec header and ADR §Notes on placement.🤖 Generated with Claude Code
Summary by CodeRabbit