feat(studio-cp,oab-mcp): k8s roster observe + runtime_context dispatch - #149
Merged
Conversation
studio#146 slice 2 of 4. Builds the k8s counterpart to the ECS read-model
(observe_services/observe_deployment/build_deployment), producing the same
runtime-agnostic Deployment/InstancePhase shape via slice 1's K8sDriver
instead of EcsDriver:
- studio-cp: observe_k8s_services (list OAB-managed Deployments in a
namespace, via the `oab/name` label) and observe_k8s_deployment (one
Deployment's replica counters + per-Pod phase, mapping a live Pod's
phase/readiness/CrashLoopBackOff onto the canonical 6-state).
- oab-mcp: deploy_list/deploy_get/runtime_context now dispatch on a named
fleet's runtime — k8s calls the new studio-cp functions (and the
already-existing observe_k8s_identity for runtime_context), ecs is
unchanged. `target()` itself and every other tool (scale/delete/apply/
provision/events) stay ecs-only on purpose — this only touches the three
calls that are actually runtime-aware now.
Fleet-membership matching note: a k8s Deployment's own on-cluster resource
name is `oab-{slug(name)}` (k8s_driver.rs, no namespace embedded), but
fleets.toml's `members` stores `oab-{namespace}-{name}` (deploy.ts writes
this uniformly for both runtimes) — observe_k8s_services/
observe_k8s_deployment reconstruct the latter from the Deployment's
`oab/name` label so FleetBinding::includes matches correctly.
🤖 Generated with Claude Code
2 tasks
brettchien
added a commit
that referenced
this pull request
Sep 7, 2026
…ge commands (#150) studio#146 slice 3 of 4. `deploy_list` and `runtime_context` (the two Tauri bridge commands backing the console's roster/identity reads) gain an optional `fleet: Option<String>` parameter, forwarded to the underlying `deploy_list`/`deploy_get`/`runtime_context` MCP tool calls alongside `cluster`. This is what a k8s-runtime fleet's roster/identity needs to reach oab-mcp's new k8s dispatch (studio#146 slice 2, PR #149) — `cluster` alone has no k8s equivalent to resolve against. No Rust compile-time dependency on slice 2 — the MCP call is JSON/string dispatched, not typed, so this only needs the tool arg *contract* (stable, defined in #149) not its merge. `fleet` is a new trailing optional parameter on two already-registered `#[tauri::command]`s, so no `generate_handler!` change is needed, and existing callers that omit it keep their exact current (cluster-only) behavior — nothing in the console passes `fleet` yet, that's slice 4. Per studio-tauri-bridge-layer-gotcha: this layer has no local build signal in this sandbox (`studio-desktop` isn't a workspace member, needs macOS/GTK system libs this environment doesn't have) — reviewed by hand against the surrounding bridge functions' existing pattern (the `params["provider"] = json!(p)` idiom `deploy_provision_agent`'s bridge already uses), only `bundle-macos` CI verifies it actually builds. 🤖 Generated with Claude Code
4 tasks
brettchien
added a commit
that referenced
this pull request
Sep 7, 2026
…151) studio#146 slice 4 of 4 (final slice) — the console-side fix for the originally-reported bug: clicking a k8s-runtime fleet in the Fleets panel now actually opens Fleet detail and loads its roster, instead of `selectFleet` showing an info toast and refusing to switch. - `source.ts`: `listDeployments`/`runtimeContext` gain an optional `fleet` param, forwarded to the Tauri bridge (#150) alongside `cluster`. - `main.ts`: `selectFleet` branches on `fleet.runtime` instead of declining for k8s — `activeCluster` becomes an unused "" sentinel for a k8s fleet (reads now go by `fleet` name, which oab-mcp resolves to the bound context/namespace, #149), and the header label shows `context/namespace` instead of a cluster. `tick()` now always passes `activeFleet` as `fleet` to `listDeployments` (a no-op for the no-fleet-selected case, and for an ecs fleet this only makes oab-mcp's existing member-side filtering redundant with the console's own `filterByMembers` — same result, not a behavior change). - `types.ts`: `RuntimeContext.cluster` is `string | null` now (`null` for a k8s-runtime fleet, with `context`/`namespace` set instead); `FleetBinding` gained optional `context`/`namespace` fields alongside the existing `profile`/`region`. `runtimeContext()` itself has no console call site yet (true before this change too) — this is type-contract parity with oab-mcp's tool, not new UI. **Not in scope** (matches the issue body): start/stop (scale) for a k8s roster row isn't wired — `scale()` still calls `scaleDeployment` without a `fleet` arg, so it'll hit the ecs-only `deploy_scale` path and fail with a clear error toast (not silently) if attempted against a k8s deployment. That's a separate action-surface follow-up, not blocking this read-only roster view. ## Test plan - `npm test`: 107/107 passing (no new tests — this is control-flow wiring over already-tested pure functions; `filterByMembers`/ `serviceName` already have k8s-shaped-data coverage from the delete-fleet/ member-name-preview work). - `npm run typecheck`: clean. - `npm run build`: clean. - Manual: no live k8s cluster in this sandbox to exercise end-to-end — same caveat #149 already carries. 🤖 Generated with Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
studio#146 slice 2 of 4 (k8s fleet roster/observe UI). Builds on slice 1 (#148, merged) to add the actual k8s observe path, and wires
oab-mcpto dispatch to it for a k8s-runtime fleet.crates/studio-cp— the k8s counterpart to the existing ECS read-model (observe_services/observe_deployment/build_deployment):observe_k8s_services(context, namespace): lists OAB-managed Deployments (oab/namelabel present) in a namespace — the k8s counterpart toobserve_services.observe_k8s_deployment(context, namespace, service): one Deployment's replica counters + per-Pod phase, listing its Pods by the Deployment's own selector and mapping each throughagent_lifecycle::k8s::K8sDriver(from feat(agent-lifecycle): k8s RuntimeDriver — projects Pod state onto the 6-state model #148) — sameDeployment/InstancePhaseoutput type ECS produces, no new console-facing shape.Readycondition, whether a readiness probe is declared, and CrashLoopBackOff from container statuses — the native signalsK8sDriver::projectexpects.crates/oab-mcp—deploy_list/deploy_get/runtime_contextnow check the named fleet'sruntimeand branch to the k8s path (the new studio-cp functions, and the already-existingobserve_k8s_identityforruntime_context) before falling through to the existing ECS logic.target()itself is untouched and still rejects k8s fleets — every other tool (scale/delete/apply/provision/events) has no k8s dispatch yet and should keep erroring loudly rather than silently acting against an empty cluster string. Tool descriptions updated to mention k8s support where applicable.A naming wrinkle worth flagging explicitly: a k8s Deployment's own on-cluster resource name is
oab-{slug(name)}(k8s_driver.rs'sk8s_deployment_name, no namespace embedded — namespace is a first-class k8s field there). Butfleets.toml'smembersarray storesoab-{namespace}-{name}(console/src/deploy.ts'sservice = oab-${namespace}-${name}, written unconditionally for both runtimes).observe_k8s_services/observe_k8s_deploymentreconstruct the fleets.toml form from the Deployment'soab/namelabel (whichk8s_driver.rs::build_deploymentsets to the original, un-slugified agent name) rather than using the on-cluster resource name, soFleetBinding::includesmatches the same way it does for ECS's full-vs-short dual match. Flagging this because it's exactly the kind of naming mismatch that reads as "roster shows nothing" if missed.runtime_context's k8s response shape:clusterisnull,context/namespaceare set instead of it — noting this for whoever picks up slice 4 (console read-path wiring), since that's the exact JSON shape it'll need to branch on.Test plan
cargo test -p studio-cp --lib— 35/35 passing (no regressions; the new k8s observe functions need a live cluster so aren't unit-tested here, same asobserve_k8s_identity/list_namespacesbefore them)cargo test -p oab-mcp --lib— 3/3 passing (incl.catalog_advertises_the_named_tools, unaffected by the description-only tool-schema edits)cargo check -p studio-cp -p oab-mcp— cleanaws-sdk-ec2OOM'd the sandbox's default test-profile debuginfo; worked around locally withCARGO_PROFILE_TEST_DEBUG=0, not something to carry into the PR itself)deploy_list/deploy_get/runtime_contextagainst a real k8s-runtime fleet — no live cluster available in this sandbox🤖 Generated with Claude Code