Summary
The agent-facing surface (JSON CLI + MCP) covers 6 of 27 catalog services, and nothing prevents that gap from widening. Every browser merged since the MCP work landed has shipped TUI-only, and there is no test that notices.
Evidence
On a563207:
| surface |
count |
| Catalog services / features (TUI) |
27 / 38 |
| Agent-facing resource commands |
6 |
| Parity or coverage test |
none |
The six exposed resources are backup-vaults, alarms, cloudtrail-events, ecs-rollout, elb-target-health, and rds-instances (internal/cli/resources.go, internal/cli/resources_operations.go). The remaining MCP tools — get_capabilities, get_command_schema, get_mcp_capabilities, plan_context_sync — are meta, not resource reads.
Browsers with no agent-facing counterpart include CloudFormation, Step Functions, EventBridge, DynamoDB, Auto Scaling, ElastiCache, KMS, ACM, SQS, S3, Secrets Manager, Route53, IAM, VPC, EKS, ECR, and FIS.
Why this matters now
Adding a browser currently means wiring ~8 TUI touchpoints (catalog.go, model.go, app.go, filter.go, keymap.go, messages.go, feature_submodel.go, screen_views.go). The agent surface is a ninth touchpoint that is easy to miss because nothing fails when you skip it.
Concrete live example: #324 (SNS browser) adds a full TUI browser and no unic resources sns-topics. That was not a deliberate scoping decision — I simply did not know the agent surface existed, because nothing in the build, tests, or docs pointed at it.
Each JSON resource is hand-written — a jsonEnvelope[T] wrapper, a per-resource DTO, and a loadXxx function variable — so the cost is real and the gap will not close by itself.
Proposed change
Two parts, guard first.
1. A parity test with an explicit allowlist. Walk domain.Catalog(), assert each feature either has an agent-facing command or appears in a documented agentSurfaceExempt map with a one-line reason. New browsers then fail the build until the author makes a deliberate call — expose it, or record why not.
This is the high-leverage half: it is small, it prevents recurrence, and it converts an invisible gap into a visible, reviewable list.
2. Fill incrementally, highest value first. Not one PR. Suggested order, by how much a raw AWS API bridge would struggle to reproduce the view:
inspect — RunSecurityScan / RunChecklist already return serializable reports (SecurityScanReport{Findings, ScannerCount, Warnings, ScannedAt}); 10 rule packs behind one call
- ElastiCache, SNS — multi-call joins with partial-failure semantics
- CloudFormation, Step Functions — failure-first triage ordering
- The rest as demand appears
Non-goals
- Exposing all 89 read-only repository methods. The shipped design is ~11 curated tools and that is the right shape; this issue does not propose changing it.
- Widening mutation coverage. The
confirmation gate in internal/cli/mutation.go correctly ports the TUI's type-the-name guard, and new mutations are out of scope here.
Checklist
Summary
The agent-facing surface (JSON CLI + MCP) covers 6 of 27 catalog services, and nothing prevents that gap from widening. Every browser merged since the MCP work landed has shipped TUI-only, and there is no test that notices.
Evidence
On
a563207:The six exposed resources are
backup-vaults,alarms,cloudtrail-events,ecs-rollout,elb-target-health, andrds-instances(internal/cli/resources.go,internal/cli/resources_operations.go). The remaining MCP tools —get_capabilities,get_command_schema,get_mcp_capabilities,plan_context_sync— are meta, not resource reads.Browsers with no agent-facing counterpart include CloudFormation, Step Functions, EventBridge, DynamoDB, Auto Scaling, ElastiCache, KMS, ACM, SQS, S3, Secrets Manager, Route53, IAM, VPC, EKS, ECR, and FIS.
Why this matters now
Adding a browser currently means wiring ~8 TUI touchpoints (
catalog.go,model.go,app.go,filter.go,keymap.go,messages.go,feature_submodel.go,screen_views.go). The agent surface is a ninth touchpoint that is easy to miss because nothing fails when you skip it.Concrete live example: #324 (SNS browser) adds a full TUI browser and no
unic resources sns-topics. That was not a deliberate scoping decision — I simply did not know the agent surface existed, because nothing in the build, tests, or docs pointed at it.Each JSON resource is hand-written — a
jsonEnvelope[T]wrapper, a per-resource DTO, and aloadXxxfunction variable — so the cost is real and the gap will not close by itself.Proposed change
Two parts, guard first.
1. A parity test with an explicit allowlist. Walk
domain.Catalog(), assert each feature either has an agent-facing command or appears in a documentedagentSurfaceExemptmap with a one-line reason. New browsers then fail the build until the author makes a deliberate call — expose it, or record why not.This is the high-leverage half: it is small, it prevents recurrence, and it converts an invisible gap into a visible, reviewable list.
2. Fill incrementally, highest value first. Not one PR. Suggested order, by how much a raw AWS API bridge would struggle to reproduce the view:
inspect—RunSecurityScan/RunChecklistalready return serializable reports (SecurityScanReport{Findings, ScannerCount, Warnings, ScannedAt}); 10 rule packs behind one callNon-goals
confirmationgate ininternal/cli/mutation.gocorrectly ports the TUI's type-the-name guard, and new mutations are out of scope here.Checklist
CLAUDE.md/docs/architecture.*.mdso it is visible when adding a browserinspectas the first fill, reusing the existing report structsmake testandmake build