Skip to content

Trajectory evaluation, CI, unit tests, MCP eval server, measured palette + cold start - #1

Closed
ashiksharonm wants to merge 13 commits into
mainfrom
improve/2026-10-audit
Closed

ashiksharonm wants to merge 13 commits into
mainfrom
improve/2026-10-audit

Conversation

@ashiksharonm

@ashiksharonm ashiksharonm commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Summary

Turns Rewind from "fork and compare agent runs" into "fork, compare, and grade agent runs", and fixes the audit findings (no CI, no unit tests, unbacked palette claim, undocumented cold start, no trace fixture).

  • test: vitest unit tests for engine fork semantics (buildMessages, parent never mutated, parallel tool groups, reroll truncation, every edit type, validation).
  • ci: GitHub Actions: install → typecheck server + web → unit tests → eval reproducibility → palette drift check → build → boot server (simulated) → HTTP smoke → MCP smoke.
  • feat(eval): trajectory evaluator (server/src/eval/): exact / in_order / any_order matching (parallel groups unordered), tool-call precision/recall/F1 with exact/subset/ignore argument matching (max bipartite matching), efficiency + budgets, tool errors / retries / redundant calls, forbidden tools, outcome checks, and a timeline diff with improved/regressed verdicts + pass flip.
  • feat(eval): npm run eval: 7 deterministic scenarios on the simulated agent via the real MCP tools server (3 forks, 2 negative controls), committed to eval/results/; npm run eval:trace scores exported traces offline; recorded simulated trace fixture.
  • feat(api): POST /api/runs/:id/evaluate, POST /api/compare, GET /api/eval/scenarios (zod-validated; regex checks rejected over HTTP to avoid ReDoS).
  • feat(mcp): server/src/mcp/rewind-server.ts: Rewind as an MCP server (list_runs, get_run, fork_run, evaluate_run, compare_runs, list_eval_scenarios).
  • feat(web): eval panel on the compare view (screenshot in README, captured with headless Chromium).
  • fix(a11y): scripts/palette-check.mjs computes WCAG contrast + CVD separation → docs/palette-report.md. --critical failed 4.5:1 as text (3.62:1) and was lightened to #ea5a5a (5.07:1).
  • docs: README rewrite (pitch, mermaid architecture, eval section, measured cold start, test matrix, limitations).

Before / after

Metric Before After Source
Unit tests 0 34 passing npm test
HTTP smoke checks 29 (manual, needs server) 33, run in CI npm run smoke
MCP smoke checks 0 4, run in CI npm run smoke:mcp
CI none .github/workflows/ci.yml —
Eval scenarios, verdict as expected n/a 7/7 eval/results/summary.md
Palette pairs meeting WCAG threshold unmeasured ("validated") 22/22 (after --critical fix; 21/22 before) docs/palette-report.md
Render cold start undocumented 32.7 s cold, 0.86 s warm (measured 2026-10-05) docs/render-cold-start.txt

Reproduce

npm ci && npm run typecheck && npm test
npm run eval && git diff --exit-code eval/results
npm run check:palette
npm run build && REWIND_MODE=simulated REWIND_AUTOSEED=0 npm start &
npm run smoke && npm run smoke:mcp

Test output (local, Apple M5, macOS, Node 24.18)

  • npm test: 34 passed (engine 11, trajectory 21, fixture 2)
  • npm run smoke: 33 passed, 0 failed
  • npm run smoke:mcp: 4/4
  • npm run eval: 7/7 verdicts as expected; output byte-identical across two runs

Not done / limitations

  • No live Claude trace or results: no ANTHROPIC_API_KEY was available. Every eval number comes from the scripted simulated agent and describes the evaluator, not an LLM.
  • Outcome checks are string-based (no LLM-as-judge).
  • docs/compare.png predates the eval panel (the panel has its own screenshot).
  • Cold start was measured once from a single client; it will vary.

ashiksharonm and others added 13 commits July 18, 2026 22:05
Time-machine debugging for agents: every run (model turns + MCP tool
calls) is recorded as a replayable trace. Fork any step — edit a tool
result, reroll a model turn, or rewrite the prompt — re-execute the
future, and compare timelines side by side.

- Node 24 + Express + node:sqlite trace store
- Real MCP toolchain (stdio server + client, 4 deterministic demo tools)
- Claude API agent loop (claude-opus-4-8) with simulated fallback mode
- React + Vite UI: dashboard, trace timeline, fork dialog, compare view
- 29-check smoke suite, Dockerfile, Render blueprint
Added live URL to README and updated formatting.
Covers buildMessages (parallel tool groups, error flags, no-prompt guard),
recording, and every fork edit type: tool_result (whole parallel group kept,
parent never mutated, ids re-keyed), reroll truncation, prompt edit, and
validation errors. Root 'npm test' now runs unit tests; the HTTP smoke suite
moves to 'npm run smoke'.
Pure scoring over recorded steps: exact / in_order / any_order trajectory
matching (parallel tool groups treated as unordered), tool-call precision,
recall and F1 via maximum bipartite matching with exact/subset/ignore
argument matching, efficiency and budget checks, tool errors, retries,
redundant calls, forbidden tools, and final-answer outcome checks.
diffEvaluations labels each metric improved/regressed between two
timelines. Covered by 21 unit tests.
npm run eval records 7 scenarios on the simulated agent through the real
MCP tools server (3 of them forks: edited tool result, reroll, prompt
edit), scores them, and writes eval/results/scenarios.json + summary.md.
Two negative controls (exact-mode mismatch, an unknown-city agent bug)
must fail; the script exits non-zero if any verdict disagrees with its
expectation. Also adds npm run eval:trace for scoring exported traces
offline, and a recorded simulated trace fixture with tests.
POST /api/runs/:id/evaluate scores a run against a spec, another run's
trajectory (referenceRunId), or reference-free. POST /api/compare scores
two timelines under one spec and returns the per-metric diff. GET
/api/eval/scenarios lists the shipped scenario specs. Specs are validated
with zod; regex outcome checks are rejected over HTTP to avoid ReDoS on
the public demo. Smoke suite grows to 33 checks.
server/src/mcp/rewind-server.ts is a stdio MCP server over a Rewind
instance's HTTP API with list_runs, get_run, fork_run, evaluate_run,
compare_runs and list_eval_scenarios. scripts/mcp-smoke.mjs drives it with
the official SDK client; CI runs it plus an eval reproducibility check.
Scores both timelines under one spec (A's own tool calls by default, or any
shipped scenario, or hand-edited JSON) and shows each metric for A and B
with its delta and an improved/regressed verdict, plus the pass flip and
per-run findings (missing/unexpected calls, failed outcome checks).
Screenshot captured with headless Chromium against a local server.
scripts/palette-check.mjs reads the :root tokens and writes
docs/palette-report.{json,md}: WCAG 2.x contrast for every text/status token
(4.5:1) and chart token (3:1) on both surfaces, plus CIE76 separation of
the chart series and verdict colors under simulated protanopia,
deuteranopia and tritanopia (Machado 2009). --critical failed 4.5:1 as
text (3.62:1) and is lightened to #ea5a5a (5.07:1). CI fails if the
report drifts from the stylesheet.
Pitch, eval panel screenshot, mermaid architecture, eval spec and metrics,
scenario results table (from eval/results), MCP server config, measured
Render cold start (raw output committed), test matrix, measured palette
report, and an honest limitations section.
The simulated agent used toLocaleString() with the host locale, so the same
run produced '3,16,800 JPY' on an en-IN machine and '316,800 JPY' on CI —
traces were not reproducible across hosts. Caught by the CI eval
reproducibility check. Regenerates eval results and the trace fixture.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant