Skip to content

feat(project): imperative harness deployment behind a feature flag - #2216

Draft
AlexanderRichey wants to merge 3 commits into
refactorfrom
feat/imperative-deploy
Draft

feat(project): imperative harness deployment behind a feature flag#2216
AlexanderRichey wants to merge 3 commits into
refactorfrom
feat/imperative-deploy

Conversation

@AlexanderRichey

Copy link
Copy Markdown
Contributor

Summary

This PR adds an imperative deployment path for harness-only projects, entirely behind AGENTCORE_CLI_EXPERIMENTAL_IMPERATIVE_DEPLOY=1. With the flag set, agentcore project deploy in a project that declares only harnesses skips CloudFormation and CDK altogether: it walks a small plan of steps that call the AgentCore control plane directly (CreateHarness/UpdateHarness/GetHarness/DeleteHarness, plus IAM for the default execution role and S3 for a new skills/ directory), polls each harness to READY, and records the result in agentcore/.cli/deployed-state.json. Without the flag, or in a project that declares anything else, nothing changes; the CDK path and its tests are untouched apart from one new state field (deploymentMode: "cdk") it now records. Three commits: the feature-flag client, the imperative deploy on a ported plan engine, and the S3-synced skills/ directory.

How it works

Feature flags. src/featureFlags/ maps a code name (imperativeDeploy) to its environment variable and reads it once at construction through an injected processEnv; a flag is on only when the trimmed value is exactly 1. FeatureFlagsKey joins the root context keys, withFeatureFlags pins an instance at the root for every CLI command and TUI screen, src/index.ts is the one place process.env is passed in, and withLogging writes one debug line naming the enabled flags. TestFeatureFlags and a featureFlags option on renderScreen let tests switch an experiment on.

Plan engine (src/core/plan/). A TypeScript port of the lightpress prototype: a Plan is a polytree of Steps, each with do() (issue one mutating call) and status() (observe through a read call and report NOT_STARTED | WAITING | SUCCESSFUL | FAILED). The engine runs roots concurrently, releases a joined step when its last parent succeeds (in-degree counting), queues children on success, and on the first failure lets in-flight steps finish without scheduling anything new, then throws a ProjectStateError listing every failed step. Validation rejects empty plans, duplicate names, and cycles (DFS colouring). Because every step reads before it writes, a plan is idempotent, self-healing, and resumable with no bookkeeping of its own.

The harness polytree. Per declared harness, ImperativeBackend builds

[execution-role] ─────────────────────────┐
                                          ├──► [put-harness]
[skills-bucket] ──► [sync-skills] ────────┘

with one skills-bucket step shared by every harness of the target, the skills branch present only when the harness has a skills/ directory or had one synced before, and the role step omitted for a user-supplied executionRoleArn. Harnesses recorded in state but no longer declared get independent delete-harness/<name> and delete-skills/<name> roots.

Create / update / remove. Identity is resolved once in preflight: the recorded harnessId, else adoption by name through a paginated ListHarnesses (two matches is an error). put-harness reads NOT_STARTED for a missing or externally deleted harness, WAITING for CREATING/UPDATING, fails with the failureReason and a delete hint on CREATE_FAILED, retries UPDATE_FAILED under the engine's attempt cap, and on READY compares the recorded appliedRequestHash with the hash of the request it would send now (spec → CreateHarnessRequest via harnessRequest.ts, the inverse of mapServiceHarnessToSpec, plus the skills manifest hash). Equal means no call at all; the hash is recorded only after READY is observed. UpdateHarness always sends the spec-owned collections (tools, skills, allowed tools, environment variables) so a removed entry is removed on the service. sync-skills diffs {key → md5} against the bucket's {key → etag} and uploads or deletes only the difference; the execution policy gains a prefix-scoped S3 grant only while the harness has skills. A spec that declares nothing (after project remove all) tears every recorded harness and its objects down after the same --yes confirmation the CDK path asks for; the bucket is never deleted.

Deployed state. deployedState.ts moved from backends/cdk/ to src/core/project/ (the old path re-exports). A target gains deploymentMode: "cdk" | "imperative" and resources.harnesses[name] = { harnessId, harnessArn, executionRoleArn?, appliedRequestHash?, skills?: { bucket, prefix, manifestHash } }. The CDK backend now also records deploymentMode: "cdk"; older state with a stackArn reads as cdk. status and invoke route by the recorded mode, not the flag, so they keep working after the variable is unset.

Mode guard. resolveDeploymentMode picks imperative only when the flag is on and the project is harness-only (or emptied, so a teardown reaches the right backend); otherwise the command prints one stderr line explaining why CDK is used (the TUI shows it as a row). FsProjectManager refuses a deploy whose mode differs from the target's recorded one with a message that says how to switch, so a target is never deployed both ways.

Intentionally unsupported

Rejected in a preflight before any AWS call, listing every offending field: dockerfile (needs the CodeBuild pipeline the CDK path provisions), skills entries of the { "path": … } form (they must be baked into a container image; the skills/ directory is the alternative), skills[].auth.credentialName (use credentialArn), and memory.mode: "existing" referenced by name rather than arn. In skills/: a directory without SKILL.md, a name outside ^[a-z0-9][a-z0-9._-]{0,63}$, a file over 5 GB, or a skill whose URI harness.json already lists. A skills bucket name taken by another account fails with an explanation; there is no override yet.

Two behaviours found during live verification and deliberately mirrored from the CDK construct: an omitted memory is sent as { disabled: {} } (left out, the service auto-provisions a managed memory the default role cannot read, and the first invoke fails), and a managed memory widens the role's memory grant to the harness-named memory the API creates.

Follow-ups

  • A skillsBucket override in aws-targets.json for accounts whose derived bucket name is taken.
  • A parallel-aware progress renderer; today concurrent steps share one linear task list with step-name-prefixed lines.
  • Path-based skills through a container build, and dockerfile support, once a build pipeline exists outside CDK.
  • Moving more resource types (memory, gateway, …) onto the plan engine.
  • Treating a harness in DELETING as WAITING rather than failing, so a redeploy right after an out-of-band delete self-heals without a rerun.

Verification

Hermetic suite. bun run lint:check, bun run format:check, bun run typecheck, bun test, bun run build, and bun install --frozen-lockfile pass at each of the three commits (Node 22 installed so the pre-existing src/io/exec.test.ts cases run). Final run: 3120 tests, 0 failures across 219 files. Line coverage of the new modules: featureFlags/*, plan/*, backends/imperative/*, deployedState.ts, harnessDir.ts, skillsDir.ts, skillsStore.ts, deploymentMode.ts, templates/harnessSkills.ts at 100%; executionRole.tsx at 99.7%. Tests use fakes at the constructor boundaries (an in-memory control plane simulating CREATING → READY, a role provisioner, a skills store) and at the SDK .send() seam (IAM and S3), matching cdk.test.ts.

Live, against us-east-1 in account 501930284170, from source with AGENTCORE_TELEMETRY_DISABLED=1, projects ImpE2ECA1a (commit 2) and ImpE2E9afJ (commit 3):

Commit 1

  • bun run src/index.ts --help works. With the variable =1, ~/.agentcore/logs/output-*.log gained {"msg":"experimental feature flags enabled","featureFlags":["imperativeDeploy"],…}; with =0 or unset, no such line. harness list --region us-east-1 --json still lists harnesses.

Commit 2

  • project create --name ImpE2ECA1a --skip-install --skip-git, then AGENTCORE_CLI_EXPERIMENTAL_IMPERATIVE_DEPLOY=1 project deploy --json: created the default target (aws-targets.json), role AgentCoreHarness-ImpE2ECA1a, and harness ImpE2ECA1a-ukgI8yJJW8, polled to READY (≈2.5 min), printed Deployed project 'ImpE2ECA1a' to target 'default'; outputs carried harness.ImpE2ECA1a.id and .arn; state recorded deploymentMode: "imperative" and the hash.
  • aws bedrock-agentcore-control get-harness: READY, version 1, the scaffolded prompt and global.anthropic.claude-sonnet-4-6; aws iam get-role-policy: AgentCoreHarnessExecutionPolicy with 19 statements.
  • First invoke failed with AccessDeniedException … bedrock-agentcore:ListEvents on memory/ImpE2ECA1a-MnHR2R83Tq: the service had auto-provisioned a managed memory for the omitted memory. Fixed by sending disabled (as CDK does); the next deploy issued exactly one update (version 2, memory: {disabled: {}}, the clear wrappers accepted), and project invoke harness --prompt "Say hello in five words." --json replied Hello there, how are you!.
  • project status --json without the variable: deploymentState: "deployed", id ImpE2ECA1a-ukgI8yJJW8.
  • Unchanged redeploy under a pseudo-TTY: harness version list was ['2','1'] before and after; progress showed execution-role: satisfied and put-harness: satisfied.
  • Edited system-prompt.md (pirate prompt), redeployed: one put-harness: issued, versions ['3','2','1'], get-harness shows the new prompt, invoke replied Ahoy there, matey! Welcome aboard! Arr!.
  • Deploy without the variable: refused with Target 'default' of project 'ImpE2ECA1a' was deployed in imperative mode, but this deploy would run in cdk mode. Set AGENTCORE_CLI_EXPERIMENTAL_IMPERATIVE_DEPLOY=1 …; harness count unchanged.
  • aws-targets.json account edited to 111122223333: Deployment target 'default' expects AWS account 111122223333, but the active credentials belong to 501930284170. after Verifying AWS account, versions unchanged.
  • agentcore harness delete --id ImpE2ECA1a-ukgI8yJJW8, redeploy while still DELETING: failed with the DELETING message (by design); after the delete finished, redeploy recreated ImpE2ECA1a-mxmyhOXapH and state carried the new id.
  • project remove harness --name ImpE2ECA1a then deploy --yes: first attempt exposed that an emptied project resolved to CDK and hit the guard (fixed: emptied projects count as harness-only); then delete-harness/ImpE2ECA1a ran, get-harness returned ResourceNotFoundException, state became {"targets":{}}, and a further deploy reported nothing to remove.

Commit 3

  • Fresh project create --name ImpE2E9afJ: app/ImpE2E9afJ/skills/README.md scaffolded.
  • Added secret-greeting/ (SKILL.md + data/greeting.txt) and release-notes/ (SKILL.md + templates/notes.md), deployed: aws s3api head-bucket found agentcore-skills-501930284170-us-east-1 (it did not exist before), get-public-access-block all four true, aws s3 ls … --recursive listed all four files, get-harness listed both s3 skills, get-role-policy held AgentCoreSkillsRead on …/ImpE2E9afJ/ImpE2E9afJ/skills/* and AgentCoreSkillsList with the s3:prefix condition; state recorded skills: { bucket, prefix, manifestHash }.
  • Invoke "Use your secret-greeting skill: what is the secret greeting?": the transcript shows the skills tool loading .agents/skills/s3/secret-greeting/SKILL.md, file_operations viewing data/greeting.txt, and the reply Purple walrus at dawn. (Later invokes loaded the skill but the model did not always reach for the file tool.)
  • Unchanged redeploy: list-objects-v2 ETags/LastModified identical, harness version still 1, progress sync-skills: satisfied.
  • Changed greeting.txt, redeployed: only that key's ETag/LastModified changed, harness version 2.
  • Removed release-notes/, redeployed: its two objects gone, get-harness lists one s3 skill, version 3.
  • Removed secret-greeting/, redeployed: sync-skills still ran and emptied the prefix, execution-role re-issued and the policy lost both S3 statements, harness version 4 with skills: [], state dropped skills.
  • skills/broken/notes.md without SKILL.md: Harness 'ImpE2E9afJ' has a skill the deploy cannot upload: - 'skills/broken': missing SKILL.md … after the account check and before any mutation (version still 4).
  • Re-added a skill, deployed, then project remove all --yes and deploy --yes: delete-harness and delete-skills ran in parallel, get-harnessResourceNotFoundException, prefix empty, bucket still present, state {"targets":{}}.

Cleanup. Every resource created in this session was removed: both harnesses (via teardown/out-of-band delete), the auto-provisioned memory ImpE2ECA1a-MnHR2R83Tq, roles AgentCoreHarness-ImpE2ECA1a and AgentCoreHarness-ImpE2E9afJ, every object under the test prefixes, and the bucket agentcore-skills-501930284170-us-east-1 (created in this session, empty). list-harnesses, list-roles, list-memories, and list-buckets filtered on the ImpE2E/agentcore-skills prefixes all return nothing; pre-existing resources were not touched.

Reviewer guide

Commit 1 (113d5bf4): src/featureFlags/env.ts, src/middleware/withFeatureFlags.tsx, src/handlers/index.tsx, src/middleware/withLogging.tsx, src/testing/featureFlags.tsx.

Commit 2 (1a113855): src/core/plan/plan.ts (the engine), src/core/project/backends/imperative/index.ts (the backend: harnessSubtree, putHarnessStep, resolveIdentities, recordState, teardown), src/core/project/backends/imperative/harnessRequest.ts (mapping + preflight; see the round-trip test), src/core/project/deployedState.ts, src/core/project/manager.tsx (deploy, guardDeploymentMode, backendForTarget), src/handlers/project/deploymentMode.ts, src/core/executionRole.tsx (ExecutionPolicyOptions, createIamExecutionRoleProvisioner).

Commit 3 (c1eac66f): src/core/project/skillsDir.ts, src/core/skillsStore.ts, src/core/project/backends/imperative/index.ts (syncSkillsStep, skillsBucketStep, removalSteps), src/core/executionRole.tsx (the S3 statements), src/core/project/templates/harnessSkills.ts, README "Experimental features".

🤖 Generated with Claude Code

https://claude.ai/code/session_014D5SZ5sApMQHrwd87VjDar

AlexanderRichey and others added 3 commits September 4, 2026 03:33
… context

Introduces a small feature-flag facility so experimental behavior can ship
behind an explicit switch. The first (and only) flag is
AGENTCORE_CLI_EXPERIMENTAL_IMPERATIVE_DEPLOY, which nothing consumes yet;
the next commit builds the imperative harness deployment on it.

Design:
- src/featureFlags/ declares FEATURE_FLAGS (code name -> env var), the
  consumer-facing FeatureFlags interface, and EnvFeatureFlags, which is
  constructed with an injected processEnv (never process.env directly) and
  reads it once so a flag cannot flip mid-command. The contract is narrow on
  purpose: a flag is on only when the variable's trimmed value is exactly "1".
- FeatureFlagsKey joins the other root context keys; withFeatureFlags pins an
  instance the same way withGlobalConfigAccessor does. createRootHandler
  installs it for every command (CLI and TUI), defaulting to an instance with
  nothing enabled so the ~65 existing test call sites need no change.
  src/index.ts is the one place that passes process.env.
- withLogging writes one debug line naming the enabled flags, only when at
  least one is on, so unflagged runs keep their exact log shape.
- TestFeatureFlags (src/testing/) and a featureFlags option on renderScreen
  let handler and screen tests turn an experiment on.

No behavior changes for users; README gains an "Experimental features"
subsection documenting the =1 contract.

Read first: src/featureFlags/env.ts, src/middleware/withFeatureFlags.tsx,
src/handlers/index.tsx, src/middleware/withLogging.tsx.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D5SZ5sApMQHrwd87VjDar
With AGENTCORE_CLI_EXPERIMENTAL_IMPERATIVE_DEPLOY=1, `project deploy` in a
harness-only project no longer synthesizes and deploys a CloudFormation
stack. It walks a plan of steps that call the AgentCore control plane
directly (CreateHarness/UpdateHarness/GetHarness/DeleteHarness, plus IAM for
the default execution role), polls until each harness is READY, and records
the result in agentcore/.cli/deployed-state.json. Without the flag, or in a
project that declares anything besides harnesses, nothing changes.

Design:
- src/core/plan/: a TypeScript port of the lightpress engine. A Plan is a
  polytree of Steps with do() (issue the mutation) and status() (observe via a
  read call). Roots run concurrently; a joined step runs after its last parent
  (in-degree counting); children are queued on success; after a failure
  in-flight steps finish but nothing new starts, and the error lists every
  failed step. validatePlan rejects empty plans, duplicate names, and cycles
  (DFS colouring rather than the Go visit-count heuristic). Concurrency is a
  Promise.race loop over a set of running steps, bridged to the linear
  ProgressEvent stream through AsyncChannel; every output line is prefixed
  with its step name.
- src/core/project/backends/imperative/: ImperativeBackend implements
  ProjectBackend. Per declared harness the plan is
  [execution-role] -> [put-harness]; a harness recorded in state but no longer
  declared gets a delete-harness root. put-harness resolves the harness id once
  in preflight (state, else adoption by name via a paginated ListHarnesses),
  reads NOT_STARTED for a missing/deleted harness, WAITING for CREATING or
  UPDATING, and on READY compares the recorded appliedRequestHash with the
  hash of the request it would send now, so an unchanged spec issues no call.
  The hash is recorded only after READY is observed. harnessRequest.ts is the
  spec -> CreateHarnessRequest/UpdateHarnessRequest mapping (the inverse of
  mapServiceHarnessToSpec, held together by a round-trip test) plus the
  preflight rejecting dockerfile, path skills, credentialName git auth, and
  by-name memory references. The ExecutionRoleProvisioner interface is
  declared by the backend and implemented over IAM in src/core/executionRole.tsx.
- Deployed state moved to src/core/project/deployedState.ts (the old path
  re-exports). TargetState gains deploymentMode; resources gains a harnesses
  map. The CDK backend now also records deploymentMode: "cdk"; older state with
  a stackArn reads as cdk. FsProjectManager routes deploys by the requested
  mode, refuses a mode that differs from the target's recorded one (the mode
  guard), and routes status/invoke resolution by the recorded mode so they keep
  working after the variable is unset.
- Mode selection lives in src/handlers/project/deploymentMode.ts and is shared
  by the command and the TUI screen; the command prints one stderr line when
  the flag is on but the project is not harness-only, the screen shows it as a
  row.

Deviations from the brief, found during live verification:
- An omitted `memory` in harness.json is sent as { disabled: {} }, as the CDK
  construct does: left out, the service auto-provisions a managed memory named
  after the harness, which the default role policy does not cover, and the
  first invoke fails with AccessDenied on ListEvents. For memory.mode "managed"
  the desired policy widens the memory grant to `memory/<harnessName>-*`
  (ExecutionPolicyOptions on desiredExecutionPolicy/ensureDefaultExecutionRole;
  `harness create` passes nothing and keeps its exact document).
- An emptied project (remove all, or the last harness removed) also resolves
  to imperative mode when the flag is on; otherwise the teardown of an
  imperatively deployed target could never reach its backend.
- ImperativeBackendConfig.executionRoles is required rather than defaulted,
  matching CdkBackendConfig.identity; FsProjectManager takes optional
  harness/executionRoles and falls back to a backend that refuses to run, so
  the existing direct constructions in tests needed no change.
- The two cdk.test.ts assertions on the exact state file gained the mandated
  deploymentMode: "cdk" field; no other expectation changed.
- exportHarness now reads the harness directory through the shared
  readHarnessDirectory, whose last-resort prompt is the scaffold's default
  (no trailing period) rather than the export module's; unreachable for a
  scaffolded harness, which always has system-prompt.md.
- UpdateHarness sends the memory, environmentArtifact and authorizerConfiguration
  wrappers with no value when the spec dropped the field, so the service ends
  up matching the spec; verified against the live service.

Read first: src/core/plan/plan.ts, src/core/project/backends/imperative/index.ts,
src/core/project/backends/imperative/harnessRequest.ts,
src/core/project/deployedState.ts, src/core/project/manager.tsx (deploy,
guardDeploymentMode, backendForTarget), src/handlers/project/deploymentMode.ts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D5SZ5sApMQHrwd87VjDar
A harness directory now carries a skills/ directory next to harness.json and
system-prompt.md: one subdirectory per skill, each with a SKILL.md and whatever
files the skill needs. `project create` and `project add harness` scaffold it
with a README explaining the layout. On an imperative deploy every skill is
uploaded to an S3 bucket the CLI gets-or-creates for the account and region,
and the harness is created/updated with an { s3: { uri } } entry per skill
after whatever harness.json lists. The CDK path ignores the directory.

Design:
- src/core/project/skillsDir.ts discovers skills (immediate subdirectories of
  skills/, walked recursively, junk and dotfiles skipped, MD5 per file) and
  validates them before any AWS call: SKILL.md present, name matches
  ^[a-z0-9][a-z0-9._-]{0,63}$, no file over 5 GB (one PutObject), no duplicate
  of an s3Uri already in harness.json. Bucket agentcore-skills-<account>-<region>,
  prefix <project>/<harness>/skills/, URI s3://<bucket>/<prefix><skill>/.
- SkillsStore is declared by the backend (types.ts) and implemented over
  @aws-sdk/client-s3 in src/core/skillsStore.ts: HeadBucket (404 absent, 403
  forbidden), CreateBucket with LocationConstraint outside us-east-1 and
  BucketAlreadyOwnedByYou as success, PutPublicAccessBlock, paginated
  ListObjectsV2, single PutObject per file (streamed, ContentMD5), DeleteObjects
  in batches of 1000. CoreClient gains an s3() accessor and a createS3Client
  factory like the other clients; fixtureFactories records it too.
- The plan per harness is now the polytree
      [execution-role] ──────────────────────┐
                                             ├──► [put-harness]
      [skills-bucket] ──► [sync-skills] ─────┘
  with one skills-bucket step shared by every harness of the target. The
  skills branch exists when the harness has skills or state records a previous
  sync, so removing the last skill still empties the prefix. sync-skills diffs
  {key -> md5} against {key -> etag} and uploads/deletes only the difference,
  reporting one line per object through a new optional reporter argument the
  engine passes to Step.do. A harness dropped from the spec (and a teardown)
  gets a delete-skills root next to delete-harness; the bucket is never deleted.
- The execution policy gains s3:GetObject on the prefix and a prefix-scoped
  s3:ListBucket only while the harness has skills (ExecutionPolicyOptions
  skillsBucket/skillsPrefix); the role step's desired-document comparison
  means a harness gaining or losing its skills causes exactly one
  PutRolePolicy. A user-supplied executionRoleArn is never touched; the deploy
  prints a reminder of the access the role needs.
- State records { bucket, prefix, manifestHash } under the harness's skills
  after a sync is observed complete. The skills manifest hash is folded into
  the recorded request hash, so a changed skill file (same URIs) still
  triggers one UpdateHarness and a new version; verified live.

Deviations from the brief:
- No skillsBucket override in aws-targets.json; the "forbidden" case fails
  with a message saying so (documented in the README as a follow-up).
- SkillsStore.put takes a { absolutePath, size, md5 } source rather than a
  stream, so the store owns how it reads the file (a node stream, which the
  Node bundle can run) and fakes stay trivial.
- The skills README is an inlined constant (templates/harnessSkills.ts), as
  the harness template inlines its default prompt and has no asset source.
- Two AwsClients test stubs and one gateway test stub gained an s3 member;
  no expectation changed.

Read first: src/core/project/skillsDir.ts, src/core/skillsStore.ts,
src/core/project/backends/imperative/index.ts (harnessSubtree,
syncSkillsStep, removalSteps, recordState), src/core/executionRole.tsx
(ExecutionPolicyOptions), src/core/project/templates/harnessSkills.ts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D5SZ5sApMQHrwd87VjDar
@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
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.20319% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.15%. Comparing base (97d3d9a) to head (c1eac66).
⚠️ Report is 1 commits behind head on refactor.

Files with missing lines Patch % Lines
src/core/project/manager.tsx 83.82% 11 Missing ⚠️
src/core/index.tsx 90.90% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2216      +/-   ##
============================================
+ Coverage     97.07%   97.15%   +0.07%     
============================================
  Files           544      559      +15     
  Lines         37866    39261    +1395     
============================================
+ Hits          36760    38143    +1383     
- Misses         1106     1118      +12     

☔ 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.

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants