Skip to content

feat(tui): open a Linked Resources screen on bare project status - #2215

Draft
AlexanderRichey wants to merge 2 commits into
refactorfrom
project-status-tui
Draft

feat(tui): open a Linked Resources screen on bare project status#2215
AlexanderRichey wants to merge 2 commits into
refactorfrom
project-status-tui

Conversation

@AlexanderRichey

@AlexanderRichey AlexanderRichey commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

What

agentcore project status was headless-only. A bare invocation in a terminal now opens an interactive Linked Resources screen; any user-supplied flag, --json, or a non-TTY invocation keeps producing exactly the current headless JSON report.

  • Grouped by agent: each entry in spec.runtimes (code agents) and spec.harnesses (managed harness agents) is a top-level group holding the agent's deployed Runtime/Harness and its linked Memories. Resources not attributable to an agent (gateways, credentials, config bundles, …) stay visible under a shared project group, with the resolver's nested children (gateway → targets, policy engine → policies, payment manager → connectors) carried through.
  • Selection forwards to detail pages: enter on a deployed Runtime, Harness, Memory, Gateway, or Gateway Target opens its existing detail screen. Local-only rows are dimmed, annotated local-only, and non-selectable; deployed types without a detail screen explain themselves instead of navigating.
  • Escape returns to the project menu from the status screen, and from a detail page back to the status screen (plain router history).

Design decisions

  • Memory ↔ agent rule (commented on buildStatusNodes): every declared memory groups under every runtime agent, because the CDK L3 injects a MEMORY_<NAME>_ID env var for each declared memory into every runtime. A harness's memory ref lives in its own harness.json, not in the project spec the report is built from, so harness groups list the harness itself and unclaimed memories fall back to the shared group.
  • Region: detail screens read the AWS region off the launch context — the ambient region, not necessarily where the project's target is deployed. The status screen links to detail pages with ?region=<target region>, and the detail screens resolve their CoreOptions through a shared useCoreOpts hook: a truthy region in the query string wins, otherwise the context's region applies as before. History-back naturally restores the previous screen, so escape works at every level, and the override is visible in the route itself.
  • TreeView: the vendored (previously unused) TreeView is used for the grouped view, extended with a focusMarker prop (the selection style the rest of the TUI uses instead of inverse video) and per-node muted annotations; icons are off so it matches the existing visual language.

status joins the project router's supportedTuiCommands, so the agentcore project menu lists it above the "command line only" divider, and the route is mounted in Root.tsx.

Testing

  • 21 tests in src/handlers/project/status/: screen tests via renderScreen (grouping, shared group, local-only skipping, forwarding to Runtime/Memory/Harness detail with region assertions, escape at each level, hint rows, collapse/expand, error state, empty project, outside-a-project guidance) plus handler tests pinning the TTY/non-TTY/--json/explicit-flag dispatch.
  • Full suite: 2,979 pass, 0 fail; coverage 97.5% lines (new screen 100%); tsc, oxlint, prettier --check clean.
  • Live E2E: scaffolded a project with runtime myFirstAgent + myFirstAgentMemory + an added harness, deployed to us-west-2 with ambient region us-east-1 (the mismatch case), and drove the real TUI in a PTY: the tree grouped the memory under the agent, enter landed on live Runtime (READY), Memory (ACTIVE), and Harness (READY) detail pages fetched in us-west-2, and escape walked back cleanly. Headless --json verified unchanged; stack torn down afterwards (DELETE_COMPLETE, no StatusE2E resources remain).

🤖 Generated with Claude Code

https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2

A bare `agentcore project status` in a terminal now opens an interactive
Linked Resources view: each agent the project declares (spec.runtimes and
spec.harnesses) is a top-level group holding its deployed Runtime/Harness
and linked Memories, with everything unattributable kept visible under a
shared "project" group. Enter on a deployed Runtime, Harness, Memory,
Gateway, or Gateway Target forwards to its existing detail page;
local-only rows are dimmed and non-selectable. Any user-supplied flag,
--json, or a non-TTY invocation keeps the headless JSON report unchanged.

Detail screens fetch in the region pinned on their context, which is the
ambient one — not necessarily the project target's. Root now scopes the
context per navigation from { state: { region } }, so the status screen
lands detail pages in the target's region while history-back restores the
launch context (escape keeps working at every level).

The vendored TreeView gains a focusMarker prop (the ❯ selection style the
rest of the TUI uses) and per-node annotations; `status` joins the project
router's supported TUI commands so the menu lists it as interactive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2
@github-actions github-actions Bot added the size/xl PR size: XL label Sep 4, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Sep 4, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 4, 2026

@agentcore-devx-automation agentcore-devx-automation Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgentCore Harness Review

Verdict: Changes requested

Nice piece of work overall — the grouping logic is clearly documented, TreeView gets a small, principled extension, and the dispatch/test coverage for TTY vs. non-TTY is thorough. One substantive issue about the region-forwarding mechanism, plus a couple of smaller things.

Region drops on forward navigation from a detail screen

src/components/Root.tsx (AppRoutes, ~lines 146–153) resolves the effective region from location.state.region for every route, and src/handlers/project/status/screen.tsx:1786 seeds that state when opening a detail page. Because state is per-history-entry, that works for the initial status → detail hop and for esc back — but any further forward navigation from the detail screen re-enters AppRoutes with a location.state that doesn't carry region, so the destination silently falls back to the launch (ambient) region:

  • src/handlers/runtime/get/screen.tsx:66 — the "endpoints", "versions", and "detail (json)" actions call navigate(action.to(runtimeId), { state: … }) without region. Only the invoke action sets state at all, and even then it's { returnOnEscape: true }, not { region }.
  • src/handlers/memory/get/screen.tsx:71 and src/handlers/harness/get/screen.tsx:78 — action onSelect handlers call navigate(action.to(id)) with no state at all.
  • src/handlers/gateway/target/get/… — same shape.

So the concrete case is: on a project deployed to us-west-2 with ambient region us-east-1, status → runtime detail fetches in us-west-2 (correct, and covered by a test), but then picking "endpoints" / "versions" / "invoke" / "json" from that page fetches in us-east-1 and the user sees "not found" or gets pointed at the wrong resource. Same for memory→segments/…, harness→endpoints/versions/etc., gateway→targets.

A few options for the author:

  1. Have every detail screen that owns an action list forward the current region from its location.state onto its navigate({ state }) calls. Simple and localized, but easy to forget for future screens.
  2. Persist the region higher up (e.g. a small "session region" ref/context set by the status screen when it forwards, cleared when the user leaves via the project menu), so downstream screens don't have to plumb state.
  3. Encode the region in the URL for the detail routes that need it and read it from useParams (route-first approach — no reliance on history state at all).

Whichever direction is chosen, please add a screen test that drills at least one level past the detail page (e.g. status → runtime detail → endpoints list) and asserts the region on the resulting core-client call.

Minor

  • src/handlers/project/status/screen.tsx:1734 — the description string passed to ProjectGate ("the project's linked resources on target default") hardcodes default, but the TARGET_NAME = "default" constant is right above; consider interpolating it so the two can't drift. The Layout render below already uses status.data.target.name for the same string, so the gate/loading path is the only inconsistency. Not blocking.
  • src/handlers/project/status/screen.tsx:1685 — every memory in spec.memories is claimed by every runtime agent, but claim() still calls claimed.add on each pass. That's fine functionally (Set dedupes), but the intent — "a memory is claimed once it appears under any runtime" — is worth a one-liner comment for the next reader; the neighboring block-comment already explains the why of the grouping rule but not this detail.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Sep 4, 2026
@codecov-commenter

codecov-commenter commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.06%. Comparing base (97d3d9a) to head (7d70a78).
⚠️ Report is 1 commits behind head on refactor.

Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2215      +/-   ##
============================================
- Coverage     97.07%   97.06%   -0.02%     
============================================
  Files           544      547       +3     
  Lines         37866    38215     +349     
============================================
+ Hits          36760    37093     +333     
- Misses         1106     1122      +16     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

… state

The cross-region link from project status to a detail page now travels as
?region= on the detail route, resolved by a useCoreOpts hook the detail
screens share: a truthy region in the query string wins, otherwise the
context's ambient region applies as before. This drops the AppRoutes
wrapper from Root (and the whole-file re-indent it caused) — Root gains
only the status route — and makes the override visible in the route
itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2
@github-actions github-actions Bot added size/l PR size: L and removed size/xl PR size: XL size/l PR size: L labels Sep 4, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 4, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants