Commit Graph

36 Commits

Author SHA1 Message Date
Ran Shem Tov 61eed4a4ad fix(showcase): harden CrewAI D6 parity on a3 2026-08-07 17:50:13 +03:00
Mike Ryan 98711fbefb fix(showcase): stage Angular artifacts in deployment images 2026-07-23 09:46:29 -07:00
Mike Ryan 637845bb7c feat(showcase): checkpoint 3 - shared build and proof pair 2026-07-23 07:14:55 -07:00
Jordan Ritter 85d2128da7 fix(showcase): accept --isolate <name> regardless of slug order and reject an empty value
--isolate <name> <slug> (name before slug) mis-parsed the name as the
slug, then died "Unexpected argument"; a bare --isolate= silently
fell through to auto-pick. Defer the ambiguous post---isolate token to
pending_iso_name and resolve it after the parse loop (slug present =>
token was the name; no slug => token was the slug); reject an empty
--isolate= loudly; --isolate=<name> (non-numeric) now binds an explicit
isolate name. The --isolate=<N> numeric pin is unchanged.
2026-06-26 13:38:30 -07:00
Jordan Ritter 8c8ead1a02 fix(showcase): propagate _slot_offset_ports failure so the port-conflict guard fails loudly on a bad slot
_slot_ports_free consumed _slot_offset_ports via process substitution
(done < <(...)), so a die on an out-of-range/non-numeric slot exited only
the subshell — the loop read zero ports, any_held stayed 0, and the
function returned 0 ("all free"), silently defeating the port-conflict
guard for a bad slot. Capture into a variable with || die so the failure
propagates to the caller. Real-surface bats prove a bad slot now fails
loudly while valid-slot free/held behavior is unchanged.
2026-06-26 13:38:29 -07:00
Jordan Ritter 7b5d47e125 feat(showcase): add 'showcase reap' subcommand to tear down leaked isolated stacks
Dry-run by default (lists the plan, changes nothing); --force executes,
--all ignores TTL/keep, --include-live opts into reaping a live-owner
target, <name|slot> targets one. Identifies harness-owned projects via
the slot-record / run-dir / showcase-iso<N> / self-id-label union, and
never touches the base 'showcase' stack or BuildKit resources. Real
docker bats prove dry-run/--force/--all + the base/buildkit guards.
2026-06-26 12:54:56 -07:00
Jordan Ritter 42e17cf6c3 fix(showcase): reconcile slot liveness against container state, add kept-stack TTL + reap self-id label
A --keep'd isolated stack whose owning process had exited (but whose
containers kept running) was classified 'live' forever and never reaped,
leaking Docker stacks indefinitely. Introduce a start-time-verified
_owner_liveness probe and a new 'kept' state, an ISOLATE_KEEP_TTL (4h,
SHOWCASE_ISOLATE_KEEP_TTL-overridable) that flips an over-age kept slot
to 'stale' so the sweep reclaims it, a com.copilotkit.showcase.isolate
self-id label stamped by apply_isolation, a 'slots --reapable' filter,
and a macOS lsof COMMAND-truncation fix in the own-project port filter.
Real-surface bats cover the liveness false-positive and TTL reaping.
2026-06-26 12:54:55 -07:00
Jordan Ritter 1f36894bc5 feat(showcase): emit CVDIAG backend boundaries agent-side for strands-typescript
Emit CVDIAG backend boundary markers from the agent process for strands-typescript (byteLength fix on sseChunkByteLength), enable the emitter in docker-compose.local.yml, vendor src/cvdiag, and exclude tests from tsconfig.
2026-06-26 10:48:43 -07:00
Jordan Ritter 2efc99fa5b fix(cvdiag): bundle a concrete writer-role PB writer into TS integration backends (auth-with-password→Bearer fetch) so backend events persist; was a type-only no-op seam 2026-06-21 12:49:05 -07:00
Jordan Ritter 0a826bf17f fix(cvdiag): re-stage TS cvdiag emitter from canonical — staged copies were stale (leaked sk-ant-/colon-less URL userinfo + half-missing emit.ts) (M6) 2026-06-19 12:33:00 -07:00
Jordan Ritter 8b86e9a877 feat(cvdiag): wire --ab-report subcommand into cvdiag CLI 2026-06-18 15:11:38 -07:00
Jordan Ritter ca84419656 feat(cvdiag): showcase cvdiag CLI — timeline/classify/replay/purge (L2-B) 2026-06-18 15:01:04 -07:00
Jordan Ritter 8118ff1dea feat(cvdiag): backend 11-boundary instrumentation for 4 TS integrations (L1-E) 2026-06-18 14:27:25 -07:00
Jordan Ritter dc72e9cac8 feat(cvdiag): Python _shared bootstrap module + 12-integration reachability wiring (L0-C) 2026-06-18 14:06:57 -07:00
Jordan Ritter 709787e872 feat(cvdiag): schema foundation + emitter + edge-header filter (L0-A) 2026-06-18 13:52:49 -07:00
Jordan Ritter ce2d2bcd91 feat(showcase): support --isolate=<N> CLI form as sugar over SHOWCASE_ISO_SLOT
Adds a sugar form of the --isolate flag that pins the isolation slot
directly from the command line:

    bin/showcase test agno --d5 --isolate=9
    # equivalent to:
    SHOWCASE_ISO_SLOT=9 bin/showcase test agno --d5 --isolate

The arg parser splits --isolate=<N> into setting use_isolate=true plus
exporting SHOWCASE_ISO_SLOT=<N>; the existing picker
(_claim_isolate_slot in _common.sh) handles all validation — positive
integer, slot 0 reserved, 1<=N<=ISOLATE_MAX_SLOT, port probe, liveness.
No validation logic is duplicated.

Tests:
- replays the parser branch and verifies SHOWCASE_ISO_SLOT export +
  picker pinning
- drives the picker's reserved-slot (N=0) and out-of-range (N=99)
  rejections through the arg form to pin the parser->env->picker wiring
- drift guard: sources the REAL cmd-test.sh, stubs apply_isolation, and
  snapshots SHOWCASE_ISO_SLOT to catch any future regression of the
  parser branch

Help text and TESTING.md updated in a follow-up commit.
2026-06-18 10:38:55 -07:00
Jordan Ritter ec33db8249 feat(showcase): add bin/showcase slots inspector subcommand 2026-06-17 16:44:18 -07:00
Jordan Ritter cb197773ee feat(showcase): rewrite --isolate slot picker with pinned slots, port probe, and slot 0 reservation
- Centralize ISOLATE_MAX_SLOT=45 constant
- Add helpers: _slot_offset_ports, _slot_liveness, _slot_ports_free, _slot_state
- Rewrite _claim_isolate_slot to reserve slot 0, honor SHOWCASE_ISO_SLOT, port-probe via lsof
- Document benign mkdir/rmdir race in auto-pick path
- Shift dashboard host port 3200 → 3210 in apply_isolation / restore_isolation
- Pass slot entry path + project to _reap_isolate_slot in pinned-path retry
- _slot_state reports offset=0 for the base stack (slot 0)
- _slot_state degrades gracefully to ports=? when lsof is missing
2026-06-17 16:44:12 -07:00
Jordan Ritter edc77f8090 fix(showcase/harness): pass slug via env var to python rewriter instead of bash interpolation
The python rewriter in apply_isolation previously interpolated $slug
directly into the inline python source via bash. A slug containing a
single quote would break the python literal. Internal-tool risk only
(slug is developer-typed), but cheap to harden.

Pass slug via SHOWCASE_ISO_SLUG env var and read os.environ.get(...)
inside the python heredoc. Defense-in-depth; no behavior change for
valid slugs.
2026-06-15 11:16:24 -07:00
Jordan Ritter 5e641d88c9 fix(showcase/harness): override LOCAL_SERVICES_JSON in --isolate generator to target the requested slug
The persistent stack's docker-compose.local.yml hardcodes LOCAL_SERVICES_JSON
to the langgraph-python sample for fast N=1 local demos. When --isolate
spawns an iso1 stack with a different slug (e.g. ms-agent-python), the
iso1 harness container inherited that hardcoded value, causing
discovery.railway-services.local-injection to enumerate the wrong service
(showcase-langgraph-python instead of showcase-<requested-slug>). The iso1
probe then targeted the wrong container, broke red-green verification, and
left D5 cells unwritten.

Inject a per-slug LOCAL_SERVICES_JSON override into the iso1 compose
generator so iso1 always probes the slug passed via --isolate.
2026-06-15 10:38:06 -07:00
Jordan Ritter 171943469a fix(showcase): guard reaper against reserved 'showcase' record + isolate review fixes
Cross-session review fixes for the --isolate machinery (one concern:
source + test + docs).

1) Reaper reserved-name guard (critical): _reap_isolate_slot trusted
   slot records — a record naming 'showcase' (corrupt, or written by an
   older CLI version before apply_isolation reserved the name) passes
   the charset regex, so the reap ran `docker compose -p showcase down
   --remove-orphans --volumes` against the LIVE default stack,
   destroying the PocketBase named volume. The reserved name now gets
   the same treatment as the path-traversal guard: warn (naming the
   record and why it is dangerous) and leave the slot intact for manual
   inspection — no compose-down, no state removal.

   Call-site enumeration: _reap_isolate_slot's sole caller is
   _sweep_isolate_slots, at 3 sites (dead-PID reap, project-recorded/
   no-owner reap, age-fallback reap), all passing
   "$slot_entry" "$slot_proj" — all three flow through the new guard
   identically.

   Red-green: the new bats test ("a slot whose project record reads the
   RESERVED 'showcase' is left intact...") was run against the UNFIXED
   code first and FAILED — the sweep logged "Attempting to reclaim
   stale slot 0 (project showcase has no live containers and no
   recorded owner)" and reaped the slot. It passes with the guard.

2) .iso-bak restore race: two concurrent runs can both see a stale
   backup; the loser's mv is the FINAL command of its `[ -f ] && mv`
   AND-list, so its failure trips set -e and kills the CLI pre-claim
   with a raw error. Both mv's now carry `2>/dev/null || true` — the
   survivor's restore wins, the loser proceeds with restored originals.

3) Keep-test absence regexes greped only the `--project-name <name>
   down` spelling; the reaper's own downs use `-p <name> down`, so a
   keep-branch regression via the -p form passed undetected. Both keep
   absence assertions now match `(--project-name|-p) <name> down`.
   Mutation-verified: a temporary -p-form compose-down added to the
   keep branch made BOTH broadened tests FAIL; reverted, suite green.
   (All other absence assertions use the word-matched generic
   `compose ... down` regex, which already covers both spellings.)

4) RUNBOOK.md/DEBUGGING.md contradicted shipped code: the manual
   teardown was quoted without --volumes plus notes claiming
   `down --remove-orphans` leaves named volumes (the shipped survival
   notice and every teardown path include --volumes), and the name rule
   was documented as `[a-z0-9_-]+` (actual: starts with [a-z0-9], then
   [a-z0-9_-], uppercase normalized with a warn, 'showcase' reserved).
   Both updated to the shipped semantics; the now-redundant separate
   `down --volumes` snippets removed.

Verification: full `bats showcase/scripts/__tests__/` green (60 tests);
shellcheck on _common.sh shows no new warnings vs baseline
(pre-existing SC2034/SC2115 only, line-shifted).
2026-06-10 08:58:28 -07:00
Jordan Ritter f2ed2b28ef fix(showcase): harden isolate state machine — --keep wiring, default-stack guards, registry concurrency
- ISOLATE_KEEP promoted to a global so --keep survives cmd_test return
  into the trap scope
- early-die and default-stack protection: failed --isolate setup no
  longer tears down the default stack; half-initialized state is
  cleaned up on the way out
- liveness/PID/age reaping signals with a sweep lock: heartbeat
  updates, own-pid lock release, tombstones, and a claim-then-verify
  duplicate-name guard close slot-registry races (TOCTOU, lock
  takeover, reap order)
- teardown robustness: --volumes on every compose down, failed-down
  runs preserve state for diagnosis, reap remnants get a compose-down,
  path-traversal guard, uniform rm guards under set -e
- name validation: --isolate names must start with a lowercase letter
  or digit; reserved name 'showcase' rejected (it aliases the default
  stack)
- fail-loud warning before pre-down of an existing stack; help text
  updated

Result of an 8-round, 7-agent code-review loop with red-green
verified fixes.
2026-06-09 18:17:55 -07:00
Jordan Ritter da504c147c fix(showcase): honor --keep on the isolate teardown path
Previously the EXIT-trap restore_isolation always tore down the isolated
stack, ignoring --keep. Now restore_isolation reads a keep flag (set in
cmd-test.sh when --keep is parsed): when kept it skips compose down, the run-dir
removal, and the slot release, and instead prints a survival notice with the
project, slot, the three offset host ports, and the exact manual teardown
command. The kept stack's live containers keep its slot from being reaped.
2026-06-09 12:52:33 -07:00
Jordan Ritter 1d31c2782b feat(showcase): reap stale isolate slots by compose-project liveness
Persist the compose project name into each claimed slot dir, and at claim time
reap any slot whose recorded project has no live containers (queried via
docker ps --filter label=com.docker.compose.project). This correctly leaves a
--keep'd stack's slot alone since its containers are still up. The existing
PID/age heuristics remain as a fallback for slots predating the project file.
2026-06-09 12:52:12 -07:00
Jordan Ritter 887191db95 refactor(showcase): migrate isolate runtime state to XDG_STATE_HOME
Move the --isolate slot registry and per-run scratch dir off /tmp (wiped on
reboot, world-writable) to $XDG_STATE_HOME/copilotkit/showcase (slots/ and
runs/<name>). The run dir is now keyed by the finalized project name instead
of the PID so a kept run is locatable for manual teardown. Adds a bats suite
covering the new state-base helper and run-dir location.
2026-06-09 12:51:53 -07:00
Jordan Ritter 5812739b5e feat(showcase): drive bin/showcase test d5/d6 through the fleet control-plane + add dev hot-reload mode
Make the showcase dev tool faithful to staging by construction. Two changes:

1. `showcase test --d5/--d6` now drives the fleet CONTROL-PLANE (producer ->
   probe_jobs queue -> worker -> result-aggregator) instead of the legacy
   in-process runLevel() driver. The new cli/control-plane-run.ts replicates
   the deep/full producer tick exactly as runControlPlane wires it
   (createE2eDeepServiceEnumerator / createServiceEnumerator over
   createJobProducer + createFleetQueueClient), enqueues one operator-triggered
   tick, and polls local PocketBase for the run's terminal cells. The running
   worker fleet claims + runs the driver + the aggregator writes the d5/d6
   status cells, so the dev tool exercises the IDENTICAL wiring + concurrency
   as staging. The old in-process path stays available behind `--direct`.

2. `showcase up --dev` adds a docker-compose.dev.yml overlay that bind-mounts
   each integration's source and overrides the run command with a stack-aware
   hot-reload entrypoint (shared/dev/dev-entrypoint.sh: uvicorn --reload for
   FastAPI agents, langgraph dev for graphs, next dev for the frontend). Edit a
   source file and the component reloads in place with no image rebuild. The
   built-image mode remains the faithful/staging-equivalent default.
2026-06-06 00:06:29 -07:00
Jordan Ritter 84b0035d1d feat(showcase): wire fleet roles into the showcase CLI and local compose 2026-06-05 10:38:41 -07:00
Jordan Ritter 671cc6ae1d feat(showcase/harness): support concurrent --isolate runs
- scripts/cli/_common.sh apply_isolation rewrites compose-file relative
  paths to absolute (build/context/dockerfile/volumes/env_file), enforces
  the docker compose [a-z0-9_-] project-name rule (normalize-with-warn or
  hard fail), and exports SHOWCASE_COMPOSE_FILE / SHOWCASE_INFRA_PORT_OFFSET
  plus offset host URLs (AIMOCK_URL_LOCAL / DASHBOARD_URL_LOCAL /
  POCKETBASE_URL_LOCAL) so the TS harness CLI talks to THIS project's
  aimock instead of the default :4010
- harness/src/cli/{aimock-rebuild,config,doctor,lifecycle}.ts honor the
  new env vars; lifecycle picks up the offset infra port for health
  probes so concurrent stacks no longer report each other's services as
  healthy
- Commit a generated harness/package-lock.json (new file) so npm ci
  resolves deterministically
2026-05-29 16:15:47 -07:00
Jordan Ritter 781ed8b045 chore(showcase): D6 scripts, fixture tests, and docs
Add fixture analysis/split/merge scripts for the D6 restructure,
update aimock fixture collision detection tests for the new directory
layout, update GOTCHAS.md and QA-COVERAGE.md with D6 notes, and
add --d6 flag support to the showcase test CLI.
2026-05-26 11:26:37 -07:00
Jordan Ritter d49dcc4fc9 fix(showcase): add --project-name to isolated compose commands
The COMPOSE_CMD in apply_isolation was missing --project-name, so Docker
Compose would infer the project name from the directory and collide with
the base showcase stack (and other isolated runs). Adding --project-name
ensures containers, networks, and volumes are fully scoped to the
isolation slot.
2026-05-01 00:09:30 -07:00
Jordan Ritter 7e4dad042c fix(showcase): temp overlay isolation + slot-based port allocation
apply_isolation previously mutated docker-compose.local.yml and
local-ports.json in-place with .iso-bak backups. If the process crashed
the originals stayed corrupted with +200 port offsets, breaking all
subsequent showcase commands.

Now writes modified copies to a temp directory and overrides
COMPOSE_FILE/PORTS_FILE shell variables so downstream code reads from
the overlay. Originals are never touched. restore_isolation just removes
the temp dir.

Also replaces hardcoded +200 port offset with atomic mkdir-based slot
allocation. Two parallel --isolate runs now get different port ranges
(slot 0 = +200, slot 1 = +400, etc.) instead of colliding on the same
ports. Container names include the slot number for collision-free Docker
naming. Stale slots from crashed runs are reclaimed via PID liveness
checks and a 2-hour age fallback.

TS harness files (config.ts, lifecycle.ts, doctor.ts) honor
LOCAL_PORTS_FILE env var so they read offset ports from the temp overlay.
2026-05-01 00:08:16 -07:00
Jordan Ritter f9578b2ab7 feat(showcase): add --isolate flag for parallel-safe local testing
When passed to `showcase test`, creates an isolated Docker Compose
project with offset ports (+200) and renamed containers, allowing
multiple agents/sessions to run showcase tests simultaneously without
container conflicts.

Usage:
  showcase test agno --d5 --isolate           # auto-names isolate-<PID>
  showcase test agno --d5 --isolate d5verify  # explicit name
2026-04-30 16:31:12 -07:00
Jordan Ritter 5abf0409a8 fix(showcase): D5 test infrastructure and CLI improvements
- Rewrite cmd-test.sh to use harness CLI for D5 probes
- Add run-e2e-with-aimock.sh helper (removed stale version)
- Update fail-baseline hash for D5 coverage
- Fix provider base URLs in .env.example
- Update local-ports.json for spring-ai
- Remove eval tier system (superseded by D5 depth probes)
- Add D5 debugging runbook
2026-04-29 19:40:10 -07:00
Jordan Ritter 2cb4e26469 feat(showcase): add aimock-rebuild, diff-logs, doctor, and fixtures CLI commands
cmd-aimock-rebuild: full rebuild-redeploy cycle with Depot bypass and
  health check timeout.
cmd-diff-logs: time-windowed container logs with --since last-test
  integration.
cmd-doctor: 10 diagnostic checks (Docker, Depot, ports, stale images,
  env vars, compose config, aimock health, disk, network, DNS).
cmd-fixtures: jq-based fixture validation (syntax, duplicates,
  turnIndex gaps, empty responses, orphaned sub-agent references).
2026-04-28 22:29:34 -07:00
Jordan Ritter 75504f900b feat(showcase): add logs, test, and recreate CLI commands
cmd-logs: container log tailing with --grep, --since, -n, --no-follow.
cmd-test: probe runner with --d5/--d6 filtering, --cycle for aimock log
  dump on failure, --timeout forwarding, .last-test-ts marker.
cmd-recreate: force-recreate with optional --build, routes aimock to
  its dedicated compose file.
2026-04-28 22:29:27 -07:00
Jordan Ritter 58b423d167 feat(showcase): add unified CLI dispatcher and shared utilities
bin/showcase auto-discovers cmd-*.sh plugins, routes built-in commands
(up/down/build/ps/ports), and provides stage_shared/restore_symlinks
for Docker Compose volume management.

_common.sh provides shared variables (SHOWCASE_ROOT, COMPOSE_CMD,
COMPOSE_FILE), output helpers (die/info/warn/success), and container
utilities (slug_to_container, slug_to_port, wait_healthy).
2026-04-28 22:29:21 -07:00