fix(harness): populate retrievalConfig from memory strategy namespaces#1374
fix(harness): populate retrievalConfig from memory strategy namespaces#1374padmak30 wants to merge 3 commits into
Conversation
Without retrievalConfig in the CreateHarness payload, the harness runtime had no instruction to retrieve from any namespace at inference time — so long-term memory was written correctly but never read back. mapMemory now accepts the resolved Memory spec and derives retrievalConfig by collecting namespaces from all strategies. computeHarnessHash now includes the Memory spec so that changes to strategy namespaces in agentcore.json trigger a redeploy even when harness.json is unchanged.
|
Claude Security Review: no high-confidence findings. (run) |
Coverage Report
|
agentcore-cli-automation
left a comment
There was a problem hiding this comment.
Thanks for tackling this! The core fix — populating retrievalConfig from the memory's strategy namespaces and including the memory spec in the harness config hash — is on the right track and matches what the runtime needs.
A couple of things to consider before merging:
- EPISODIC
reflectionNamespacesare excluded fromretrievalConfig. This may leave the issue partially unresolved for users with EPISODIC strategies (see inline comment). - No test coverage for the redeploy-on-namespace-change behavior that the PR description calls out as a primary fix (see inline comment on
harness-deployer.ts).
Minor: the memorySpec lookup in harness-deployer.ts only matches by memory.name, so harnesses that reference memory by arn won't get a retrievalConfig derived. This is probably acceptable as a known limitation (we can't introspect external memories), but worth confirming the intent.
buildRetrievalConfig now flattens reflectionNamespaces alongside namespaces for EPISODIC strategies, so cross-session reflection summaries stored at the parent namespace path are retrieved at inference time. Also adds a unit test asserting that mutating strategies[*].namespaces in agentcore.json produces a different configHash and triggers a harness update rather than being silently skipped.
|
Claude Security Review: no high-confidence findings. (run) |
|
|
||
| const deployedResources = deployedState.targets?.[targetName]?.resources; | ||
| const existingHarness = deployedHarnesses[entry.name]; | ||
| const memorySpec = projectSpec.memories?.find(m => m.name === harnessSpec.memory?.name); |
There was a problem hiding this comment.
Minor / low priority — flagging for awareness rather than as a blocker.
The spec lookup keys solely on harnessSpec.memory?.name. HarnessMemoryRefSchema (src/schema/schemas/primitives/harness.ts:188) makes both name and arn optional, and mapMemory already has an if (memory.arn) branch (harness-mapper.ts:280). For an arn-only ref, find(m => m.name === undefined) returns undefined and the harness ships without retrievalConfig.
That said, no CLI surface produces this shape — agentcore add harness always writes { name: ... }, and there's no --memory-arn flag. The only way to land here is hand-editing harness.json. So this is theoretical for any first-party flow.
Two reasonable resolutions:
- Tighten
HarnessMemoryRefSchemato requirename(drop thearnbranch inmapMemoryalong with it), so the schema reflects what the tooling actually supports. - Leave as-is and add a test asserting that the arn-only branch intentionally omits
retrievalConfig, so a future contributor doesn't read it as a regression.
Either is fine — feel free to defer or close as out-of-scope.
Includes EPISODIC reflectionNamespaces in the retrieval config so the harness runtime searches all relevant memory namespaces at inference time. Also incorporates memorySpec into the deploy hash so namespace changes trigger a harness update. Cherry-picked from #1374.
…refs When a harness references memory by ARN only (no name field), the previous lookup returned undefined, silently omitting retrievalConfig and excluding the memory from the configHash. resolveMemorySpec now walks deployedResources.memories to match by ARN and find the corresponding projectSpec memory, so name-less refs that point at a CLI-managed memory get the same treatment as name-based refs. HarnessMemoryRef is exported from the schema barrel so it can be used as the explicit parameter type on resolveMemorySpec. Adds unit tests for both the ARN-match path and the intentional undefined fallback for genuinely external memories.
|
Claude Security Review: no high-confidence findings. (run) |
* feat: implement compile-time feature flag for preview/GA branch consolidation Replace the dual-branch (main/preview) workflow with a single branch using a compile-time __PREVIEW__ constant. esbuild's define block replaces the constant at build time, enabling dead code elimination for GA builds while keeping all harness/preview code in the same source tree. Key changes: - Add src/cli/feature-flags.ts with isPreviewEnabled() wrapper - Configure esbuild define block and vitest define for __PREVIEW__ - Gate harness commands (add tool, remove tool/harness) behind isPreviewEnabled() - Gate harness UI screens and create flow behind the flag - Add globalThis shim in index.ts for tsx dev mode - Update bundle.mjs to produce dual tarballs (GA + preview) - Support ESBUILD_OUTFILE env var for isolated test builds - Port all harness-related source files from preview branch - Add preview-flag.test.ts verifying dead code elimination * fix: remove unnecessary quotes around __PREVIEW__ key in esbuild config Prettier requires unquoted object keys when valid identifiers. * fix: skip harness integration and e2e tests in GA builds Harness features are gated behind BUILD_PREVIEW=1 and eliminated from GA bundles. Integration and e2e tests that exercise harness commands must skip when running against the default (GA) build. * fix: gate harness options in invoke/create commands and fix remove memory cleanup - Wrap harness-related CLI options in invoke command behind isPreviewEnabled() so they don't leak into GA build's --help output - Wrap harness-related CLI options in create command behind isPreviewEnabled() - Fix remove harness leaving orphaned memory entries in agentcore.json - Fix deploy preflight rejecting harness-only projects - Add integration test for harness re-add after removal * fix: auto-deploy harness in TUI dev mode before invoking The TUI path for `agentcore dev` skipped deployment, going straight to the invoke screen. This caused "No deployed targets found" errors for users who hadn't manually run `agentcore deploy`. Now uses the existing useDevDeploy hook to deploy before transitioning to harness invoke mode. * fix: use queueMicrotask for deploy-to-harness transition in TUI dev The derived effectiveMode approach didn't trigger re-renders, leaving the deploy screen stuck after completion. Switch to queueMicrotask + setMode (matching the preview branch pattern) so the transition fires correctly. Also handles browser mode by calling onLaunchBrowser after deploy. * fix: match preview branch deploy UI and persist deployHash - Deploy screen in TUI dev mode now matches preview branch: shows "Deploying project resources..." with DeployStatus CFN messages, filters redundant step, yellow error text, and log path link. - Persist deployHash in deployed-state.json after successful deploys so canSkipDeploy can detect unchanged projects and skip re-deploy. * fix: align harness UX with preview branch - InvokeScreen: Ctrl+N for new session (was bare N), hint messages rendered in gray, context-sensitive "Loading..."/"Thinking..." label, directional scroll arrows instead of numeric range - DevScreen: disable keyboard input while exiting (!isExiting guard) - deploy/actions: imperative harness teardown before stack destroy (gated behind isPreviewEnabled) so harnesses aren't orphaned - browser-mode: resolve harness traces via resolveAgentOrHarness instead of ignoring harnessName parameter - resolve-agent: add resolveHarness and resolveAgentOrHarness helpers * fix: hint message render order and harness/runtime disambiguation - isHint check now comes after isExec (matching preview branch) so exec messages always render as magenta, not gray - When a project has both runtimes and harnesses and no flag is given, show a clear error listing both --runtime and --harness options * fix: route harness invocations and show deploy box in dev mode The browser in `agentcore dev` could not invoke harnesses because the /invocations POST handler never checked for harnessName in the request body. Add early routing to handleHarnessInvocation when present. The deploy progress box was missing because useDevDeploy did not pass verbose: true or onResourceEvent to handleDeploy, so the switchableIoHost was never created and CloudFormation messages never reached the TUI. Constraint: handleHarnessInvocation handler already existed but was unreachable Rejected: Adding a separate /harness-invocations endpoint | breaks frontend contract Confidence: high Scope-risk: narrow * fix: serve harness info in status API and fix deploy message flow The browser frontend could not discover harnesses because /api/status did not include harness data or selectedHarness in its response. The deploy box was still not showing because switchableIoHost was only created with verbose:true, but preview also creates it when onDeployMessage is provided. Also wire onDeployMessage into the setOnMessage callback so both callbacks receive deploy events. Constraint: frontend polls /api/status to discover available targets Rejected: Separate /api/harnesses endpoint | adds complexity for no benefit Confidence: high Scope-risk: narrow * fix: include harnesses in /api/resources response for browser UI The frontend Agent Inspector crashes with "Cannot read properties of undefined (reading 'find')" when switching to a harness because the /api/resources endpoint was missing the harnesses array entirely. Constraint: Frontend expects harnesses array with deploymentStatus and deployed fields Confidence: high Scope-risk: narrow * test: add unit tests for harness invocation and status handlers Covers validation, routing, SSE streaming, error handling, and the harness fields added to /api/status response. Confidence: high Scope-risk: narrow * test: add unit tests for resolve-agent, change-detection, and harness-mapper Cover the untested middle-layer logic that routes invocations, decides whether deploys can be skipped, and maps harness specs to API payloads. Confidence: high Scope-risk: narrow * fix: adjust preview-flag DCE test for keepNames compatibility The keepNames:true esbuild option (added for better error stacks) preserves class/function name strings even in dead code paths. Adjust assertions to check for harness-only module markers that are fully tree-shaken, rather than name strings that survive. Confidence: high Scope-risk: narrow * fix: pass structured DeployMessage through to TUI instead of plain strings The dev deploy hook was re-wrapping string messages into DeployMessage objects with hardcoded values. Now the real message (with actual level, code, timestamp) flows through directly from CDK. * fix(harness): populate retrievalConfig from memory strategy namespaces Includes EPISODIC reflectionNamespaces in the retrieval config so the harness runtime searches all relevant memory namespaces at inference time. Also incorporates memorySpec into the deploy hash so namespace changes trigger a harness update. Cherry-picked from #1374. * fix: rewrite dev command to resolve merge conflict with telemetry refactor The merge conflict resolution left duplicated code blocks and mismatched braces. Rebuilt from main's withCommandRunTelemetry+recorder pattern and re-applied preview feature flag gates (harness support, skip-deploy, TUI picker). * fix: address PR review feedback from jariy17 - Remove unnecessary `as unknown as` cast in agentcore-control.ts (SDK already has IndexedKey type) - Optimize preview build to only re-run esbuild (not full tsc + assets) - Delete dead code: poll.ts and its test (nothing imports it) - Error when harness enters FAILED state after create/update instead of silently returning success - Add unit tests for harness-deployer (create, update, skip, teardown, FAILED status, role resolution, retry, polling) * fix: update release workflows for single-branch preview model - release.yml: set BUILD_PREVIEW=1 for preview builds - release-main-and-preview.yml: rewrite as single-PR flow using preview-version.json for the preview version track (no separate preview branch needed) - Remove sync-preview.yml (no preview branch to sync) - Update preview-version.json to match current npm state (1.0.0-preview.9) Constraint: preview and GA are both built from main, differentiated by BUILD_PREVIEW env var at esbuild time Confidence: high Scope-risk: narrow * feat: add release_target input to select main, preview, or both Allows running the release workflow for just main-only, preview-only, or both together. Jobs are conditionally skipped based on the selection. Confidence: high Scope-risk: narrow * fix: use github.ref_name for release branch selection Allows triggering the release workflow from any branch via the GitHub UI branch selector, instead of hardcoding main. Confidence: high Scope-risk: narrow * chore: remove unused BUILD_PREVIEW env from release.yml Preview releases are handled by release-main-and-preview.yml. Confidence: high Scope-risk: narrow
Description
Without retrievalConfig in the CreateHarness payload, the harness runtime had no instruction to retrieve from any namespace at inference time — so long-term memory was written correctly but never read back.
mapMemory now accepts the resolved Memory spec and derives retrievalConfig by collecting namespaces from all strategies.
computeHarnessHash now includes the Memory spec so that changes to strategy namespaces in agentcore.json trigger a redeploy even when harness.json is unchanged.
Related Issue
Closes # #1097
Type of Change
Testing
How have you tested the change?
npm run test:unitandnpm run test:integnpm run typechecknpm run lintsrc/assets/, I rannpm run test:update-snapshotsand committed the updated snapshotsChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.