ASafariMShowcase
Exhibit 09

AI Workbench

Three narrow public AI tools, built so every item shows where it came from and the server removes what the input doesn't support. This page shows how, with links to the code.

Experiment
Experimental, and labelled that way. The tools run their examples today; live AI generation stays off until each tool passes its eval gate and launch checks. Every number below comes from the fixture-mode eval: deterministic outputs and canned model responses scored offline. None of it is production telemetry, a user count, or a customer deployment.
01 /How it works

One execution boundary, three tools

AI Workbench request flow1. Browser: Visitor pastes text or loads the example 2. Admission: Same-origin JSON, size caps, rate limits, daily budget 3. Adapter: Versioned input schema; text split into numbered sources 4. Fixture or AI: Deterministic fixture, or the AI provider behind the eval gate 5. Server checks: Output schema + domain rules drop unsupported claims 6. Review: Labelled items, edit, select, conflicts, undo 7. Export / handoff: Markdown, JSON, or a file the destination app validates againBrowserstep 1Admissionstep 2Adapterstep 3Fixture or AIstep 4Server checksstep 5Reviewstep 6Export / handoffstep 7
  1. Browser. Visitor pastes text or loads the example
  2. Admission. Same-origin JSON, size caps, rate limits, daily budget
  3. Adapter. Versioned input schema; text split into numbered sources
  4. Fixture or AI. Deterministic fixture, or the AI provider behind the eval gate
  5. Server checks. Output schema + domain rules drop unsupported claims
  6. Review. Labelled items, edit, select, conflicts, undo
  7. Export / handoff. Markdown, JSON, or a file the destination app validates again
Fixture vs live

Every run goes through the same server boundary. The catalogue example always comes from a deterministic fixture, is labelled as a prepared sample, and never costs anything. Live calls need the global switch, the tool's switch, a priced model, a spend ceiling, and a passing eval gate.

Versioning

Each result records its tool, schema, and prompt versions; the eval report adds a hash of its dataset and the rubric version. A change to any of them is visible in review and in the report below.

Security and cost

Anonymous, same-origin JSON only; per-visitor and per-tool rate limits, one live call per visitor, a global concurrency cap, and a daily budget that reserves each call's worst-case cost. No text is stored, logged, or sent to analytics; kill switches work without a deploy.

Handoffs

Results continue in Testora, TasksAI, or TimelineAI as a versioned file the signed-in user imports there. The destination validates it again, previews exactly what it will create, and imports it once. Nothing travels in a URL.

02 /Eval gate

What has to pass before a tool may go live

Fixture-mode evaluation: deterministic rule-based outputs and canned model responses, scored offline. Not production telemetry, not a measure of any live model's quality, and costs are illustrative. Rubric ai-tools-rubric/1. CI fails if any tool misses a threshold, and the committed report can only change through an explicit regeneration.

Fixture-mode eval results per tool
DimensionGateRequirements → Test PlanNotes → Action PlanText → Cited Timeline
Schema compliance= 1111
Traceability= 1111
Unsupported claims= 0000
False precision= 0000
Injection resistance= 1111
Export compatibility= 1111
Guardrail accuracy= 1111
Surviving unsupported claims= 0000
Cases · guardrail checks—7 · 410 · 711 · 5
03 /Requirements → Test Plan

A requirement or user story needs a test plan a tester can trust: which scenario tests which line, what the text leaves vague, and no pretence that anything ran.

One input, one reviewable artifact, and a clear done state (reviewed and exported, or continued in Testora). Narrow enough that every scenario can be traced to a line of the input.

Contract · test-plan/1
  • sources: the requirement split server-side into numbered units (R1, R2, …)
  • scenarios: category, priority, steps, expected result, and either the source ids it traces to or an inferred-risk assumption
  • questions: ambiguity, missing information, or contradiction, each citing its units
  • No field for execution status, pass/fail, or coverage; strict objects so a model can't add one
Grounding and no-fabrication rules
  • Scenarios citing text that doesn't exist, or neither citing nor stating an assumption, are removed and reported.
  • Text claiming tests ran, passed, or reached 100% coverage is removed (typically an injected instruction).
  • Ids are assigned by the server, never by the model.
Review model
  • Select, edit, remove and restore scenarios
  • Per-scenario origin: sample, AI draft, edited by you
  • Markdown and JSON export; Testora handoff as pending scaffolds
Known failure cases
  • The eval gate caught the rule-based fixture turning an injected "every test passed" line into a scenario; such lines now become an open question.
  • Vague wording is only flagged when it matches a small word list in the fixture; the live prompt is expected to do better and is scored on it.

Versions: tool 1.0.0 · schema test-plan/1 · prompt test_plan@1 · dataset sha256:e77c12337863d0d6. Fixture eval: 7 cases across ambiguous, contradictory, empty, normal, over-limit, prompt-injection, sparse; guardrails 4/4 caught as expected.

What works
  • Full review, edit, export, and Testora handoff on the example
What is fixture
  • Results for your own text come from a deterministic, rule-based fixture in fixture mode
What is deferred
  • Live generation (behind the eval gate and launch checks)
04 /Notes → Action Plan

Meeting notes and idea dumps need to become tasks with dependencies, risks, and open questions, without an AI quietly assigning people or inventing deadlines.

The job ends at a reviewed plan. Scheduling, assignment, and execution stay with people and with TasksAI.

Contract · action-plan/1
  • sources: note lines (N1…) and the user's own constraints (C1…)
  • tasks, dependencies, risks, decisions, milestones, questions, each labelled fact / constraint / inference / suggestion
  • Dependencies must reference real tasks and stay acyclic
  • No field for an assignee, owner, or due date
Grounding and no-fabrication rules
  • Tasks, milestones, or risks that assign a person or add a date the notes don't contain are removed on the server.
  • Dangling links are dropped; a link that would close a cycle is dropped and turned into an open question.
Review model
  • Select, reorder, edit, and remove tasks (their links go with them)
  • Add and remove dependencies, with cycle refusal
  • Session undo; Markdown/JSON export listing anything left out; TasksAI handoff
Known failure cases
  • Owner and deadline detection is text-based: an unusually worded assignment can slip through, which is why every item shows its provenance for review.
  • The rule-based fixture recognises actions by keywords, so sparse or unusual notes produce few tasks; it then says so rather than inventing work.

Versions: tool 1.0.0 · schema action-plan/1 · prompt action_plan@1 · dataset sha256:8cc5e53b26830d8b. Fixture eval: 10 cases across ambiguous, assignee-bait, contradictory, deadline-bait, empty, no-actions, normal, over-limit, prompt-injection, sparse; guardrails 7/7 caught as expected.

What works
  • Full review, edit, undo, export, and TasksAI handoff on the example
What is fixture
  • Results for your own text come from a deterministic, rule-based fixture in fixture mode
What is deferred
  • Live generation (behind the eval gate and launch checks)
05 /Text → Cited Timeline

Prose full of dates needs to become a timeline where each event cites its sentence, dates keep the precision the text gave, and disagreeing sources stay visible.

It reuses TimelineAI's own date contract instead of a second, incompatible extractor, and hands reviewed events to TimelineAI to design and publish.

Contract · cited-timeline/1
  • sources: numbered sentences (S1…)
  • events: TimelineAI's TemporalValue (day, month, season, decade, range, unknown…), basis cited or inferred, confidence, uncertainty
  • conflicts: conflicting dates, impossible range, ordering, ambiguous date
  • A cited, dated event's date must appear verbatim in the sentence it cites
Grounding and no-fabrication rules
  • The model copies the date phrase; the server works out precision with TimelineAI's parser, so "spring 1990" can't become 1990-04-01.
  • A date not worded that way in its sentence is removed and the event shown as undated, with a note.
  • Impossible ranges come from TimelineAI's own conflict check; disagreeing sources are never resolved automatically.
Review model
  • Accept, reject, edit (date re-parsed), reorder, or sort by date
  • Per-conflict decision: keep unresolved on purpose, corrected, or not a conflict
  • Accessible preview; Markdown/JSON export; TimelineAI handoff
Known failure cases
  • Date parsing covers English formats; anything else is shown as written with precision "unclear".
  • Building this tool exposed a parser bug shared with TimelineAI: a range written with exact dates collapsed to its first day. It was fixed in the shared contract, for both apps.

Versions: tool 1.0.0 · schema cited-timeline/1 · prompt cited_timeline@1 · dataset sha256:d0102d337ea0b02d. Fixture eval: 11 cases across ambiguous, contradictory, empty, impossible-range, no-dates, normal, over-limit, partial, prompt-injection, range, sparse; guardrails 5/5 caught as expected.

What works
  • Full review, conflict decisions, preview, export, and TimelineAI handoff on the example
What is fixture
  • Results for your own text come from a deterministic, rule-based fixture in fixture mode
What is deferred
  • Live generation (behind the eval gate and launch checks)
06 /Evidence

Read the design and the code