Summary:
- Add the repo-local update-harness skill and Claude skill symlink.
- Add a Bun-owned ci command and route GitHub CI through it.
- Tighten generated-doc freshness and workspace inventory generation.
Rationale:
- Keeps the harness upgrade workflow available in-repo for future agents.
- Gives local and hosted CI one shared command instead of duplicated YAML.
- Makes generated inventory depend on tracked files and catches real drift.
Tests:
- bun install --frozen-lockfile
- bun run ci
Co-authored-by: Codex <[email protected]>
## Intent
Fix SYM-34 by making server-managed run executor failures observable outside
SSE subscribers. The controller now writes a structured `run_executor` stderr
line, persists the failure on the run record when a run ID exists, and still
publishes the terminal `run_error` stream event.
## Behavior changes
Failed `agentprobe start-server` runs that reach the executor catch path now
remain visible through `/api/runs/:runId` after the SSE session closes, with
`finalError` populated for the historical run detail. Operators also get a JSON
stderr log line with the run ID, error type, message, and stack.
## Validation
- [x] `./scripts/fast-feedback.sh` passed
- [x] Behavior docs updated (if behavior changed)
- [x] `bun test tests/integration/server/write-control.test.ts` passed
- [x] `bun run typecheck` passed
- [x] `bun run lint` passed
## Screenshots / video
N/A for CLI/server behavior changes.
## Intent
Fix SYM-31 by adding explicit CORS handling for the AgentProbe control-plane API. The server now answers `/api/*` OPTIONS preflights centrally, attaches CORS response headers for allowed origins, and fails closed when operators expose the server externally without an explicit origin allow-list.
## Behavior changes
- `/api/*` OPTIONS preflights return `204` for allow-listed origins with allow-methods, allow-headers, allow-credentials, and max-age headers.
- `/api/*` OPTIONS preflights return `403` for unlisted origins.
- Non-preflight `/api/*` responses echo `Access-Control-Allow-Origin` for allowed origins.
- `AGENTPROBE_SERVER_CORS_ORIGINS` configures comma-separated exact `http://` or `https://` origins.
- `--unsafe-expose` / `AGENTPROBE_SERVER_UNSAFE_EXPOSE=true` now requires `AGENTPROBE_SERVER_CORS_ORIGINS` in addition to an auth token.
## Validation
- [x] `./scripts/fast-feedback.sh` passed on merge head `3774c52`
- [x] Behavior docs updated (if behavior changed)
- `bun test tests/unit/server/config.test.ts tests/integration/server/read-only.test.ts`
- `bun test tests/unit/server tests/integration/server`
- `bun run docs:validate`
- `bun test --timeout 15000` (pre-merge validation on original CORS head)
## Screenshots / video
N/A for CLI/server changes.
Phase 3 of the AgentProbe server: ship historical-run comparison as an API
and dashboard workspace, and introduce the persistence abstraction needed to
back the server with Postgres behind `AGENTPROBE_DB_URL`.
- Persistence contract: new PersistenceRepository interface, URL parser /
redactor, migration dispatcher (per-backend versioned) and a backend factory
that returns SqliteRepository or PostgresRepository. SQLite free-function
exports stay as compat wrappers; all new consumers go through the interface.
- Postgres backend: full DDL with jsonb columns and indexes for server
filters + comparison lookups, migration runner, boot-time schema-version
check that refuses to start when behind, preset/run/comparison reads, and
preset CRUD. Run recorder (writes) is deferred to SYM-25.
- CLI `agentprobe db:migrate`: accepts --db or AGENTPROBE_DB_URL, prints
backend / current / target / applied, fails clearly on unsupported schemes.
- Server config + /readyz + new /api/session expose the backend kind and a
redacted db_url. Postgres URLs are now accepted via --db and env.
- Comparison controller: loads 2–10 runs, chooses alignment (preset snapshot
→ preset id → scenario id → file::id), emits runs, scenarios with per-run
status/score/reason, delta_score, status_change, present_in, and summary
buckets. GET /api/comparisons rejects out-of-range counts with the common
error envelope and sets cache-control: no-store.
- Dashboard /compare workspace: ad-hoc multi-run picker, sticky summary bar,
per-run columns, missing-scenario rows, "only changes" toggle,
?run_ids=…&only=changes deep links, and a "Compare last two runs" CTA on
the preset detail view.
- Docker Compose example documents Postgres as an opt-in service; SQLite on
a named volume remains the default.
- Playbook expansion: Postgres setup/migration/rollback/backup, comparison
semantics, connection errors, and duplicate-scenario-id behaviour.
- Tests: unit coverage for url redaction + parse, migration runner (fresh,
idempotent, upgrade-in-place, unsupported schemes), factory dispatch, and
the comparison controller (alignment, delta/status_change, duplicate ids,
range enforcement, 404 routing). Integration coverage starts a real server
against seeded SQLite runs and exercises the /api/comparisons payload.
Follow-up SYM-25 tracks the buffered async Postgres recorder.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Summary:
- Add authenticated server write routes for starting and cancelling runs,
preset CRUD, preset launch history, and frozen preset snapshots.
- Extend SQLite run history to schema v4 with preset tables, server-run
metadata, cancellation timestamps, and WAL-enabled server connections.
- Teach runSuite to accept prepared file/id scenario selections and a
cooperative AbortSignal while preserving existing CLI and dashboard mode.
- Add dashboard start/preset/cancel views plus Docker and Compose packaging
with a token-protected SQLite volume deployment path.
Rationale:
- Phase 2 needs an operator workflow that can configure a run, save it as a
reusable preset, launch it from the server UI, and observe/cancel progress.
- Scenario references now use file plus id so duplicate ids across scenario
files remain deterministic, and write paths validate boundaries at data-root
and bearer-auth edges.
Tests:
- bun run docs:validate
- bun run test tests/unit/server
- bun run test tests/integration/server
- bun run test:e2e
- bun run dashboard:build
- bun run typecheck
- bun run fast-feedback
- COMPOSE_PROGRESS=plain AGENTPROBE_SERVER_TOKEN=... OPEN_ROUTER_API_KEY=...
docker compose -p agentprobe-sym22 up --build --detach
- curl -fsS http://127.0.0.1:7878/healthz
- curl -fsS -X POST http://127.0.0.1:7878/api/runs ... dry-run payload
- OPEN_ROUTER_API_KEY=... docker compose -p agentprobe-sym22-missing config
exited 1 for missing AGENTPROBE_SERVER_TOKEN
Co-authored-by: Codex <[email protected]>
- Reframe cupel inspiration as design direction (palette, density,
list+detail split), not a visual copy.
- Add cross-file scenario selection, saved presets, and preset-aware
run history.
- Add /compare workspace and /api/comparisons for diffing multiple
runs of the same preset.
- Surface parallel-factor control on the /start run builder.
- Document Postgres backend behind AGENTPROBE_DB_URL for ephemeral
Docker deployments where SQLite-on-volume isn't viable; gated to
Phase 3.
- Fix Dockerfile CMD to match the server's non-loopback security
contract: bake --unsafe-expose into CMD and require
AGENTPROBE_SERVER_TOKEN at boot, failing fast when absent.
- Restructure rollout phases and acceptance criteria accordingly.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>