app
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
John Lauer
Publish 0.2.56
73fcf19
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
"""Issues #147, #164 and #158 through the CLI: `project-page --results` writes design-review/README.md for
the current board (Fields numbers, the AI's figures, a molecule's contact table, the parts table with
prices) into the page's staging folder or a molecule-publish package folder (--out), records which board
it describes, and prints the push; the run report's header says what finish said (open items, not
cleared for fabrication) instead of a bare "Finished". No CAD, desktop, wiki or dashboard: nothing is pushed.
python3 tests/page-results-workflow.py <adom-aiflow binary>
"""
import json, os, pathlib, subprocess, sys, tempfile
binary = str(pathlib.Path(sys.argv[1]).resolve())
BOARD = '''(kicad_pcb (version 20260206)
(gr_rect (start 98 82) (end 126 102) (layer "Edge.Cuts"))
(footprint "Molecule:MachinePinMediumShort" (layer "F.Cu") (at 100 100) (property "Reference" "MP1") (pad "1" thru_hole circle (at 0 0) (size 1.6 1.6) (drill 1.2) (layers "*.Cu") (net "GND")))
(footprint "Molecule:MachinePinMediumShort" (layer "F.Cu") (at 124 100) (property "Reference" "MP2") (pad "1" thru_hole circle (at 0 0) (size 1.6 1.6) (drill 1.2) (layers "*.Cu") (net "GND")))
(footprint "Molecule:MachinePinMediumShort" (layer "F.Cu") (at 100 84) (property "Reference" "MP3") (pad "1" thru_hole circle (at 0 0) (size 1.6 1.6) (drill 1.2) (layers "*.Cu") (net "GND")))
(footprint "Molecule:MachinePinMediumShort" (layer "F.Cu") (at 124 84) (property "Reference" "MP4") (pad "1" thru_hole circle (at 0 0) (size 1.6 1.6) (drill 1.2) (layers "*.Cu") (net "GND")))
(footprint "Molecule:MachineContactMedium" (layer "F.Cu") (at 100 88) (property "Reference" "MC1") (pad "1" thru_hole circle (at 0 0) (size 1.3 1.3) (drill 0.78) (layers "*.Cu") (net "VIN")))
)
'''
with tempfile.TemporaryDirectory(prefix='aiflow-page-results-') as td:
p = pathlib.Path(td)
env = dict(os.environ, AIFLOW_DASHBOARD='off', AIFLOW_NO_PART_SEARCH='1', AIFLOW_NO_PART_LOOKUP='1')
def call(run, *args):
return subprocess.run([binary, '--run', str(run), '--ai-thread', 'page-results-test', *args], env=env, capture_output=True, text=True, timeout=60)
def data(run): return json.loads((run / 'run.json').read_text())
def put(run, d): (run / 'run.json').write_text(json.dumps(d))
board = p / 'esc.kicad_pcb'; board.write_text(BOARD)
fig = p / 'density.png'; fig.write_bytes(b'\x89PNG fake')
bom = p / 'bom.csv'; bom.write_text('Ref,MPN,Manufacturer,Unit Price,URL\nMC1,MCM-1,Adom,0.50,https://example.com/mcm\n')
req = p / 'requirements.json'; req.write_text(json.dumps({"title": "ESC molecule", "formFactor": {"kind": "molecule", "pin": "MachinePinMediumShort"}}))
# a run on a page, analysed, with one AI figure
run = p / 'run'
r = call(run, 'intake', '--prompt-time', '2026-11-06T10:00:00Z', '--engine', 'test', '--page', 'noah/esc', '--requirements', str(req))
assert r.returncode == 0, r.stdout + r.stderr
d = data(run)
d['boards'] = [str(board)]
d.setdefault('outcomes', {})
d['outcomes']['tour-fields'] = {"nets": [{"net": "VIN", "amps": 3.0, "peakJ": 22.5, "layers": ["F.Cu"]}], "chips": [{"reference": "U1", "watts": 0.8, "riseC": 12.0, "riseMovingC": 7.0}], "heat": {"peakRiseC": 12.0}, "issues": []}
d['outcomes']['analyze-current'] = {"pass": True, "results": [{"net": "VIN", "status": "pass"}]}
d['outcomes']['parts'] = {"pass": True, "bom": str(bom), "parts": [{"mpn": "MCM-1", "manufacturer": "Adom", "refs": ["MC1"], "wiki": "adom/mcm-1"}]}
d.setdefault('outcomeAt', {})['tour-fields'] = '2026-11-06T10:30:00Z'
put(run, d)
with open(run / 'run.jsonl', 'a') as f:
f.write(json.dumps({"event": "artifact", "byAi": True, "kind": "analysis-image", "file": str(fig), "caption": "Current density on VIN", "step": "fields", "t": "2026-11-06T10:31:00Z"}) + "\n")
r = call(run, 'project-page', '--results'); out = r.stdout + r.stderr
assert r.returncode == 0 and 'design review written' in out, out
readme = run / 'page-results' / 'design-review' / 'README.md'
assert readme.is_file(), out
md = readme.read_text()
assert '| VIN | 3.00 | 22.5 | F.Cu |' in md and '| U1 | 0.80 | 12.0 | 7.0 |' in md, md
assert '](design-review/01-density.png)' in md and (run / 'page-results' / 'design-review' / '01-density.png').is_file(), md
# issue #158: the requirements' formFactor makes it a molecule before any spec: the contact table
assert '| MC1 | VIN | MachineContactMedium | (0, 12) |' in md, md
assert '| MCM-1 | Adom |' in md and '[buy](https://example.com/mcm)' in md and '**Board total:** $0.50' in md, md
assert 'adom-wiki repo push noah/esc --files design-review/README.md design-review/01-density.png' in out, out
assert 'interactive schematic' in out, out
o = data(run)['outcomes']['page-results']
assert o['page'] == 'noah/esc' and len(o['boardSha256']) == 64 and o['files'][0] == 'design-review/README.md', o
# into a molecule-publish package folder: the package root is the page root, no push printed
pkg = p / 'pkg'
r = call(run, 'project-page', '--results', '--out', str(pkg)); out = r.stdout + r.stderr
assert r.returncode == 0 and (pkg / 'design-review' / 'README.md').is_file(), out
assert 'molecule-publish package' in out and 'repo push' not in out, out
# issue #147: the run report's header says what finish said
d = data(run); d['clock']['finishTime'] = '2026-11-06T11:00:00Z'; d['summary'] = {"open": ["silkscreen check", "fields issue"]}
d.pop('page', None); put(run, d)
r = call(run, 'report'); out = r.stdout + r.stderr
assert r.returncode == 0, out
rep = (run / 'report' / 'README.md').read_text()
assert 'finish ran with 2 open item(s); not cleared for fabrication' in rep and '**Finished** (board design checks)' not in rep, rep
print('page-results workflow: OK')