docs(adr): ADR-2 — Deployment Control Plane (read/write model + MCP) - #4
Merged
Conversation
Consolidates the design decided in the dev thread: - generic glossary (Agent/Instance/Deployment/Fleet/Spec/Status/phase/ AgentState/Discriminators/RuntimeDriver); vendor terms only in drivers. - read model: Spec+Status, phase=AgentState, 6-state<->k8s mapping + traps. - write model: apply() primitive; create/scale/stop are sugar; dry-run/diff. - MCP adapter: server oabctl, tools deploy_list/get/apply/scale/stop. - authorization DEFERRED to ADR-3 (interim: AWS credential ceiling only, documented risk + trusted-callers rule). - non-goals: authz (ADR-3), controller/S3/reconcile (ADR-4), k8s/compose drivers, exec/cp/sync/bootstrap/schedule via MCP. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ish) 1. Deployment.status != AgentState: Instance.status.phase = AgentState; Deployment.status = replica counters (desired/current/ready/available) + Conditions (mirrors k8s). phase is Instance-level only. 2. Write model reaches Paused: add cordon/resume sugar + deploy_cordon/ deploy_resume MCP tools (admission=accepting_work is a Spec field); dry_run is a first-class required param on every write tool. 3. Exposure seam granularity: ServiceStatus must wrap per-Task InstanceStatus; driver aggregates DescribeServices (Deployment counters/rollout) + DescribeTasks (Instance 4-axis -> phase). Deferrals unchanged (authz->ADR-3, controller/S3->ADR-4), reviewers PASS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- D4 (correctness): §4 latch k8s mapping startupProbe -> Ready-first-True (startupProbe fires before Ready; latching there breaks ADR-1 F1's Starting/Unhealthy split). Aligns with §7 ECS lastStatus-ever-RUNNING. - D1: §5 apply framed as on-demand one-shot; continuous reconcile = ADR-4. - D2: split stop (scale->0, reversible, Spec kept) from delete (absence, destructive); §6 adds deploy_delete alongside deploy_stop. - D3: authz interim 'trusted callers' framed as a deployment-time assumption, not a technical control. - D6: glossary config = content referenced by Spec.configRef (not a Spec field). - healthCheck: §7 ECS conformance — task must define a container healthCheck (parallel to compose), else healthStatus UNKNOWN breaks the health axis. - D5 (server name oabctl): dismissed — already decided. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- N1: admission's driver-equivalent is not 'readiness gate' — it is app/CP-level and orthogonal to Ready (ADR-1 F2: accepting_work is CP-controlled, separate from health). Same class of error as D4. - N2: remove raw deploy_apply from the MCP surface — exposing it bypasses the individually-guardable sugar verbs (contradicts the §8 rationale). apply stays the internal primitive; creating a new Spec is a restricted provisioning action, not a first-class operate tool (gating in ADR-3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brettchien
marked this pull request as ready for review
August 8, 2026 16:26
brettchien
pushed a commit
that referenced
this pull request
Aug 13, 2026
…site Address review (Jelly): - #3: add `ServiceStatus::service_name` carrying the raw ECS name verbatim, and query tasks by it instead of `format!`-rebuilding `oab-{ns}-{name}`. The rebuild is wrong for any service that doesn't fit the `oab-<ns>-<name>` shape (the parser falls back to `namespace = "?"`), so this is a correctness fix, not just cleanup. - #4: the resolver (`resolve_service`) now returns the matched service whose `service_name` is passed to `instance_status` with zero further transformation, so the test asserts the exact value the call site queries with — not just an isolated helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brettchien
added a commit
that referenced
this pull request
Aug 13, 2026
…stTasks (#28) * fix(studio-cp): resolve short service name to full ECS name before ListTasks `observe_deployment` accepted either the display short name (`orca`) or the full ECS name (`oab-prod-orca`) when matching a service, then passed the caller's string verbatim to `instance_status`. ECS `ListTasks` filters by `service_name`, which only accepts the full name, so a short name 404s as `ServiceNotFoundException`. The roster / `get_agent_states` path collects short names, so it failed for every agent once credentials resolved to the right account (previously masked by an AccessDenied earlier in the chain). - studio-cp: centralise the short->full mapping (`canonical_service_name` + `find_service`) and query tasks by the resolved full name. - oabctl: harden `instance_status` to fail loud when handed a non-`oab-` name instead of surfacing an opaque ECS `ServiceNotFoundException`. - test: `service_selector_resolves_to_full_ecs_name` guards the short-name path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * review: carry raw ECS service_name; test the observe_deployment call site Address review (Jelly): - #3: add `ServiceStatus::service_name` carrying the raw ECS name verbatim, and query tasks by it instead of `format!`-rebuilding `oab-{ns}-{name}`. The rebuild is wrong for any service that doesn't fit the `oab-<ns>-<name>` shape (the parser falls back to `namespace = "?"`), so this is a correctness fix, not just cleanup. - #4: the resolver (`resolve_service`) now returns the matched service whose `service_name` is passed to `instance_status` with zero further transformation, so the test asserts the exact value the call site queries with — not just an isolated helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Orca (openab agent) <orca@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
Draft ADR-2, consolidating the design we sorted out in the dev thread. Builds on ADR-1.
Scope (this ADR): generic glossary · read model (Spec/Status/phase) · write model (
apply+ intent verbs, dry-run) · MCP adapter (deploy_*).Key decisions baked in:
RuntimeDriver.Status.phase=AgentState(ADR-1's 6 states); 6-state ⇄ k8s mapping + traps.apply(Spec);create/scale/stopare sugar; dry-run/diff.oabctl; toolsdeploy_list/get/apply/scale/stop(nooabctl_prefix).Non-goals (deferred): per-caller authz (ADR-3) · controller/reconcile/S3 state store (ADR-4) · k8s/compose drivers · exec/cp/sync/bootstrap/schedule via MCP.
Docs-only. Ready for review — expecting term/wording nits.