AI Flow
Public Made by Adomby adom
Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board.
main
| Name | Last updated |
|---|---|
| screenshots | |
| favicon.svg | |
| index.html | |
| README.md | |
| sample-timeline.json |
Flow timeline
A live, single-file dashboard for an adom-aiflow run. It shows every step of the flow on one path, where the AI is right now, how many steps are left, a check mark on every finished step, and a purple arc for every time a later step sent the AI back to rework an earlier one. Built for a Hydrogen webview beside the AI chat (about 700 to 900 px wide), and it switches to a horizontal layout above 1700 px.
Run it
Serve this folder and have the flow write timeline.json next to index.html:
cp sample-timeline.json timeline.json # or let adom-aiflow write it
python3 -m http.server 8790
Open index.html in a Hydrogen webview. The page fetches timeline.json (a relative URL, so it works behind a proxy path) every second and animates changes: a step turning done, the current-step marker gliding, a new loop arc drawing itself. ?src=other.json reads a different relative file.
If the file is missing or invalid the page shows "Waiting for the flow to start". After the first good read, a missing or half-written file keeps the last picture and the header says "Reconnecting". Write the file atomically (write a temp file, then rename) to avoid half-written reads.
timeline.json
{
"title": "12 V to 5 V, 1 A buck converter",
"label": "12 V to 5 V, 1 A buck converter",
"engine": "Fusion",
"board": "buck-12v5v.brd",
"aiThread": "astra",
"runFolder": "buck-run-3",
"runDir": "/home/adom/runs/buck-run-3",
"finish": "Gerbers, BOM and CPL exported",
"updated": "2026-10-07T14:02:11Z",
"current": "routing",
"steps": [
{"name": "routing", "title": "Routing", "does": "what the AI is doing in this step",
"phase": "Board", "status": "current", "visits": 2, "minutes": 6.0}
],
"loops": [
{"from": "fields", "to": "placement", "why": "why the AI went back", "at": "2026-10-07T13:40:00Z"}
]
}
stepsis the ordered path.statusistodo,current,doneorredo(was done, a loop back reopened it).currentat the top level wins over a step's own status.phasegroups consecutive steps (Plan, Circuit, Library, Board, Analysis, Deliver).visitsabove 1 shows an "x2" style badge.minutesis AI time on that step, summed in the header.loopsare in time order; the last one is the "latest" loop shown in the callout.fromis the later step that found the problem,tois the earlier step the AI went back to. When writing a loop, also set the steps fromtoonward toredo.- "Step N of M" is the current step's position; "to go" counts
todoplusredosteps. When every step isdone(andcurrentis null) the finish line lights up. titleis the run's label (requirements title, spec title, project page, original board stem, brief, run folder; never a hash). The line under it showsboard,engine,AI thread: <aiThread>andrunFolder; it never wraps: the thread ellipsizes, then the run folder, the lane and the board are dropped in that order.- Unknown fields are ignored, so the schema can grow.
Design notes
Adom brand palette only: teal #00b8b1 for done marks, progress and the current step, purple #8c6bf7 for loop backs and rework, the signature gradient on the finish line once reached. Familjen Grotesk for display, DM Sans for body (Satoshi if installed), JetBrains Mono for numbers. Icons are white line drawings. Tooltips (600 ms hover, tap on touch) clamp to the viewport. Motion is turned off under prefers-reduced-motion.
window.flowTimeline.state() returns what is on screen, for scripted checks.
Project overview and contributions
The timeline leads the dashboard, immediately below its compact progress header.
The supporting overview follows the timeline with the active task and completed workflow steps. Without an image,
it shows stage-specific guidance for intake, requirements, sourcing, schematic and
simulation; it never waits for a board or invents design evidence. A saved schematic,
simulation plot or board image can be supplied in presentation.json beside the page:
{"image":"project-view.png","alt":"Saved schematic","caption":"Schematic review · saved 2026-10-09"}
For an early-stage run, omit image and supply title and summary for the real project brief or requirements. Optional projectTitle supplies a human-readable project name. These are presentation text, never gate evidence.
Only same-origin PNG/JPEG/WebP assets are accepted. Label the capture and date accurately; a static capture is not a live 3D viewer. Missing/failed assets retain the stage overview. The presentation file is preserved when CLI commands refresh the timeline.
The community card links to the public MIT license, source and pull requests. Its prompt helps users contribute through their AI; follow the root skill's contribution guidance.
The optional presentation arrives with timeline SSE state; static exports use polling. Changed captions and saved images appear without navigation. A missing/malformed file or failed image preserves the last good presentation; a valid object without image clears the image. For an overwritten image with otherwise identical metadata, change an imageRevision field to trigger a reload. Presentation text never changes engineering gate evidence.
Live updates
GET events streams state over SSE, with current-state replay, proxy padding and 15-second heartbeats. GET state reads the current timeline/presentation. POST state accepts { "aiThread": "load design", "presentation": { "caption": "Thermal open" } } as JSON. Only presentation strings are accepted; workflow acceptance remains derived from the run. The CLI exposes this as timeline present --json <JSON>. Keep the existing webview open. Offline/static copies fall back to polling.
Event-driven dashboard state (0.1.90)
The server uses one native filesystem watcher per run and a shared state cache. CLI presentation controls notify SSE clients immediately; external timeline/presentation edits trigger native filesystem notifications, including atomic replacements. Idle SSE connections do not poll or reread state files. The 15-second heartbeat only writes a connection comment. Native watcher failures are reported rather than silently falling back to server-side polling. /health reports stateSource, stateFileReads, and watcherError for verification. Keep the existing webview open during server upgrades; SSE reconnects automatically.
Hands-on AI Flow (handson.rs, docs/hands-on.md)
timeline.json carries handsOn:
{"state": "planning|active|off", "profile": "noah-flow", "profileName": "Noah flow",
"plan": {"steps": {"placement": {"mode": "checkin"}, "routing": {"mode": "human"}}, "fallback": "auto", "notify": "hydrogen", "screen": "hands-off"},
"waiting": {"kind": "plan|checkin|human", "step": "placement", "summary": "..."},
"verdicts": {"placement": {"visit": 1, "verdict": "approved", "quote": "...", "by": "dashboard"}},
"profiles": [{"slug": "noah-flow", "name": "Noah flow", "default": true, "steps": {}}], "modes": [...]}
Each step also has a mode.
The page shows:
- The planner (state planning, or Change). Four choices per step (1 AI, 2 Check in, 3 Me, 4 Custom with instructions), "start from" a saved profile, notify and screen choices, save as a named flow, and "use it for my next boards".
- A review or "your turn" card while a check-in or human step is open.
- A one-line summary with Change.
- A mode chip on each step row.
- A "Want a say in each step?" card when the run is not hands-on.
Answers go to POST handson (relative URL) with Content-Type: application/json and X-Aiflow-Handson: 1. The body is one of:
{"action":"plan","plan":{...,"saveAs":"Noah flow","makeDefault":true}}{"action":"approved"|"changes"|"done","step":"placement","note":"..."}
The server queues it in handson-inbox.json; the CLI applies it. The page never changes run.json or a gate.
Last route and checks that need a look (issue #141, attention.rs)
Every command that ends with findings (FINDINGS, or an OK after NOTE lines) or an error is kept in run.json checks, keyed by the command's name (route, gate, land route, analyze current), with the step it was charged to, a count and its first lines. It stays until that same command ends cleanly again; it is a suggestion, never a block. The ledger gets a command-outcome event for every command (outcome: ok, findings or error). route keeps lastRoute (connections routed and unrouted, nets unrouted, vias, warnings, the route-quality headline) and gate keeps lastGate (new DRC errors, unconnected); a new board does not remove them, they are labelled with the board revision they were measured on.
timeline.json carries them:
{"steps": [{"name": "routing", "status": "current", "attention": {"kind": "findings|error", "count": 2, "items": [ /* checks on this step */ ]}}],
"route": {"route": {"routed": 2, "connections": 3, "unrouted": 1, "netsUnrouted": ["C"], "vias": 0, "warnings": [], "routeQuality": "...",
"onCurrentBoard": false, "measuredOn": "measured on the previous board (board-0.kicad_pcb, revision 1; the board is now revision 2): ..."},
"gate": {"newErrors": 0, "unconnected": 1, "onCurrentBoard": true, "measuredOn": "..."}},
"checks": [{"key": "route", "step": "routing", "kind": "findings", "count": 1, "lines": ["routing closed 1 connection(s) short ..."], "suggestion": "...", "at": "..."}]}
The page shows a "needs a look · N" (or "error") chip on the step row, the lines in the step's tooltip, and a card with the last route's numbers and the open checks. status prints the same as text.