Repository navigation
feat: stop TUI browsers from silently skipping the agent-facing surface #360
Description
Activity
- addedenhancementNew feature or requestNew feature or requestpriority/nextQueued after current focusQueued after current focustech-debtRefactoring / maintainabilityRefactoring / maintainability
on Sep 13, 2026 @Unic-bot: assign me
@YoungJinJung has been assigned to this issue.
- added a commit that references this issue
on Sep 14, 2026 Progress on the checklist.
- Parity test with a documented exemption map — test: guard agent surface parity #361
- Every current gap recorded as an exemption entry (7 mapped + 31 exempt = 38 catalog features)
- Agent surface documented as a wiring step —
CLAUDE.md,AGENTS.md, both architecture docs - Expose
inspectas the first fill — feat: expose the inspector rule packs to automation #363 - Remaining fills
Two things worth recording while they are fresh.
Inspector sits outside the guard.
grep -c Inspector internal/domain/{model,catalog}.go→ 0. It is a workflow, not a catalog feature, so #361's parity test cannot see it — a green guard does not mean full coverage. #363 pins the boundary withTestSecurityInspectorToolIsReadOnlyAndNotAResourceContractand says so in both architecture docs, but any future non-catalog surface will have the same blind spot.Four exemptions are justified more weakly than they read.
FeatureAutoScalingBrowser,FeatureEventBridgeRules,FeatureLambdaBrowser, andFeatureSQSBrowserall cite mutations as the reason. ButFeatureECSExec— which opens an interactive shell, the most mutation-capable feature in the catalog — is mapped to a read-onlyecs-rolloutcommand. So the read path is separable; the real reason is the trailing "yet". SQS looks like the strongest next candidate: deepest-backlog-first ordering with DLQ relationships is precisely the curated view a raw API bridge cannot reproduce.Suggested order for the rest, by that same criterion — how much a generic AWS API bridge would struggle:
- SQS queue backlogs (join + ordering + DLQ edges)
- ElastiCache (replication-group/cluster join with partial-failure semantics)
- SNS (topic + subscription join; the repository methods already return
([]T, []error, error), which maps straight ontodata/warnings) - CloudFormation and Step Functions (failure-first triage ordering)
Status reconciliation as of 2026-09-15:
- Merged: test: guard agent surface parity #361 added the catalog-to-agent-surface guard and documentation; feat: expose the inspector rule packs to automation #363 exposed the inspector rule packs.
- Open follow-ups: test: validate complete MCP CLI invocations #362 validates complete MCP CLI invocations; feat: expose SQS queues to automation #364 exposes SQS; feat: expose ElastiCache resources to automation #365 exposes ElastiCache; feat: expose SNS topics to automation #366 exposes SNS; feat: expose CloudFormation stacks to automation #367 exposes CloudFormation; feat: expose Step Functions executions to automation #368 exposes Step Functions.
- All six open PR heads have passing hosted checks and have been reviewed at their current SHAs. Each remains REVIEW_REQUIRED / merge-blocked pending an independent approving review, so no review was repeated and no merge was attempted.
- No additional fill was started while these overlapping issue feat: stop TUI browsers from silently skipping the agent-facing surface #360 branches are in flight. The issue should remain open until the accepted follow-ups land and the remaining exemption list is reassessed.
Review-state update as of 2026-09-16: #365, #366, and #368 now have approvals from
youngjinjung-linqon their unchanged heads. The collaborator-permission API reports that account has onlyreadaccess, and GitHub still reportsREVIEW_REQUIRED/BLOCKEDfor all six open follow-ups (#362, #364–#368). Main requires one approving review; an eligible reviewer with write access other than the PR author is still needed.All current hosted checks pass. No new actionable feedback from YoungJinJung is outstanding, and all six heads already have completed code reviews. No duplicate review, additional implementation, or merge was attempted. Issue #360 remains open while the existing follow-ups await eligible approval.
Status reconciliation as of 2026-09-21:
- All six open follow-ups (test: validate complete MCP CLI invocations #362 and feat: expose SQS queues to automation #364–feat: expose Step Functions executions to automation #368) now have an approval from
youngjinjung-linqon their unchanged current heads; test: validate complete MCP CLI invocations #362 and feat: expose SQS queues to automation #364 gained those approvals after the prior issue update. - Hosted checks pass on every current head, and GitHub reports each PR as mergeable but still
REVIEW_REQUIRED/BLOCKED. - The active agent account does not have push access, so its approvals do not satisfy the protected-branch requirement. An eligible reviewer with write access, other than the PR author, is still required.
- No new comments from YoungJinJung request changes, and every current head has already received a complete review. To avoid duplicate review or overlapping implementation, no code changes or merge attempts were made.
Issue #360 remains open while the existing follow-ups await eligible approval.
- All six open follow-ups (test: validate complete MCP CLI invocations #362 and feat: expose SQS queues to automation #364–feat: expose Step Functions executions to automation #368) now have an approval from
State change as of 2026-09-29: PRs #367 and #368 are now reported by GitHub as
CONFLICTING/DIRTYagainstmain. Their head SHAs remain unchanged (2ed37ffandf79d9cb), hosted checks at those heads still pass, and both heads were already fully reviewed, so no duplicate review was performed. Each branch now needs its conflicts with currentmainresolved and validation rerun before an eligible approval or merge can proceed.All five fills from the suggested order are merged: SQS #364, ElastiCache #365, SNS #366, CloudFormation #367, Step Functions #368. The invocation guard #362 landed too.
Coverage on
c38984b, counted by parsingagent_surface_test.gowithgo/astrather than grepping — a line count was off by one on each map and I did not want to report a number I had not verified:before this pass now mapped 7 12 exempt 31 26 catalog features 38 38 No feature appears in both maps; the two sets partition the catalog exactly.
unic resourcesnow exposes:alarms,backup-vaults,cloudformation-stacks,cloudtrail-events,ec2-instances,ecs-rollout,elasticache-resources,elb-target-health,rds-instances,sns-topics,sqs-queues,step-function-executions.Two things worth recording from the merge itself
Every one of these conflicted once the previous had landed, all in the same four places —
resources.go,resources_operations.go,server.go,agent_surface_test.go. That is inherent to five parallel branches editing the same registries, not a problem with any of them, but it is why merging them serially took longer than reviewing them.While resolving #368 I found it had introduced a generic
resourceTimeJSONwhile #367 had already landedcloudFormationTimeJSONdoing exactly the same thing. I unified on the generic name rather than keeping two identical helpers. Worth knowing that the branches were written in parallel against a main that did not yet have each other's work, so this kind of near-duplicate is likely in anything still outstanding.One README line was also changed permanently: the "the server provides ... including
list_X" sentence named one example tool, which made it conflict on every single fill. The example is gone — the command list directly above already enumerates them.Remaining
26 exemptions, each with a stated reason. The ones I would still question are the value-judgement ones rather than the genuinely-blocked ones (secrets and parameter values needing operator-controlled reveal, SSM session being an interactive shell, reachability analysis creating real resources — those look correctly excluded). Most of the rest say "no curated query is defined yet", which is honest and is exactly what the guard is for: they stay visible instead of being forgotten.
- added a commit that references this issue
on Sep 29, 2026
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 browser — test: guard agent surface parity #361inspectas the first fill, reusing the existing report structs — feat: expose the inspector rule packs to automation #363make testandmake build— verified on mainfbced782eb9772312bc83bb084020783066e24c9(2026-09-29)Current implementation status
The prioritized fills are merged: SQS #364, ElastiCache #365, SNS #366, CloudFormation #367, and Step Functions #368. The catalog guard currently records 12 mapped features and 26 explicit exemptions. Inspector is a separate non-catalog workflow. This issue remains open for incremental fills as demand appears; no additional service contract is selected here.