Idle
Elapsed 0.0s
· ETA to finish —
· healthy
0% · idle
— the bar/ETA track the live SSE heartbeat; if no progress arrives for >4s it flags a
possible stall/crash.
A
Parse
read 10-PAPER.txt
✓
B
Resolve cites
source map
✓
C
Body QC loop
loop ② · multi-viewpoint
✓
D
Figures
loop ③ · author + geometry QC
✓
E
Assemble HTML
cite-style + gate
✓
Ensemble
Laguna·Devstral·Gemma
free jury · 3 models
Sections
7
enforced from config
Figures kept
— / 19
large fonts, 0 hard defects
Citations
—
author-year, STM-only
GPT spend
$0.00
Laguna = free
Status
Idle
—
Press Run pipeline to simulate a full pass. Stages animate through the same
A→E flow the backend executes; the QC, Figures, Citations and Audit tabs fill in as it runs.
Full data flow for advanced users: two engines, one shared
ensemble, and four bounded self-improvement / QC loops (amber ⟲). Each loop stops early on
convergence or an anti-thrash freeze.
Where QC is applied — 4 bounded loops
| # | Loop | Engine · script | Round cap | What it does |
|---|---|---|---|---|
| ① | Draft REFINE | build_research.py | --max-rounds (3) | ensemble judge→correct on prose sections; converges when gain < ε for K rounds |
| ② | Body QC | render_paper.py · run_qc | --qc-rounds (5) | ensemble judge→correct on the whole paper's prose; temperature-rotated (multi-viewpoint) |
| ③ | Figure geometry QC | render_paper.py · author_figures | --qc-rounds, per figure | deterministic geometry lint → LLM fix → re-lint, for EACH figure independently |
| ④ | Format conversion | to_format.py | --passes, per format | convert HTML→docx/pdf, diff against the HTML, fix, repeat |
Is “QC rounds” cumulative? No. --qc-rounds is a per-application cap,
not a total. The same value independently bounds ② the body-QC loop (once over the whole paper) and
③ each figure's geometry-QC loop. Worst-case figure-fix calls ≈ figures × qc-rounds (e.g. 19 × 5),
though every loop stops early on convergence or an anti-thrash freeze, so actual rounds are usually fewer.
Loop ① (draft) uses a separate --max-rounds; loop ④ (conversion) uses a separate
--passes. These are three different knobs in the config.
Judge→correct loop on a working copy. The synthesist temperature rotates each round
(0.2, 0.5, 0.8, 0.4, 0.7) for diverse revisions;
a revision is rejected if it changes the section set or reintroduces symbolic notation.
QC log will stream here on run…
Each figure: draft (varied temperature) → safety/well-formedness gate →
deterministic geometry lint (out-of-bounds = hard drop; small font <14px / text-collision = soft, auto-fixed).
Rendered inline as (Short name, year), external STM only
(internal author corpus dropped). Keys are knowledge-driven from
LTM-citation-style.txt [CITATION-KEYS].
| Key | STM id | Year | In-text |
|---|
These are the ACTUAL long-term knowledge nodes injected into
the pipeline's LLM prompts (drafter, reviser, figure author, citation renderer). The backend serves the
FULL file via GET /api/knowledge/:node; the boxes below show representative
excerpts. Edits + PUT take effect next run and are replicated when you create a
new workspace.
Context injected into every draft / revise prompt
27,695 / 28,000 chars
5 LTM nodes are concatenated (hard cap 28,000). Each large-context
prompt repeats the task ≥4× (task anchoring) so the model stays focused across this context.
These files are the distilled result of the whole 10-PAPER-new.html optimization — not shallow summaries;
the excerpts here are abridged for display only.
LTM-writing-style.txt 198 lines · 12.9 KB — voice, zero-notation, term discipline, section hygiene
Full file loaded via GET /api/knowledge/LTM-writing-style. Excerpt:
LTM-figure-style.txt 135 lines · 8.5 KB — visual-first, LARGE text, geometry QC, artifact hygiene
Full file via GET /api/knowledge/LTM-figure-style. Excerpt:
LTM-citation-style.txt 112 lines · 6.1 KB — author-year, STM-only, [CITATION-KEYS] (44)
Full file via GET /api/knowledge/LTM-citation-style. Excerpt:
LTM-author-voice.txt 80 lines · 8.4 KB — thesis + voice from the internal corpus (informs, not cited)
Full file via GET /api/knowledge/LTM-author-voice. Excerpt:
LTM-paper-profile.txt 79 lines · 5.3 KB — descriptive target template (measured from 10-PAPER-new.html)
Full file via GET /api/knowledge/LTM-paper-profile. Excerpt:
rubrics/RUB-paper.txt 37 lines · 2.0 KB — K1-K6 criteria + house-style gates (regenerated each run)
Seeded from build_research._seed_criteria() each run. Excerpt:
Rendered output preview — the HTML is the primary, high-fidelity source.
DOCX/PDF are derived from it over self-improving conversion passes.
Deterministic invariants checked on every render, compared against the
hand-tuned target 10-PAPER-new.html.
| Invariant / metric | This run | Target | Status |
|---|---|---|---|
| Symbolic notation ($ / greek / LaTeX) | — | 0 | |
| MathJax script present | — | no | |
| "RReferences" artifact | — | none | |
| Numeric superscript citations | — | 0 | |
| Internal-corpus refs (P-/S-) | — | 0 | |
| Author-year citations | — | ~19 | |
| Figures | — | 19 | |
| Section headings (h2) | — | 8 | |
| Word count | — | ~5276 | |
| Well-formed HTML | — | yes |
REST endpoints (thin wrapper)
| Method + path | Purpose |
|---|---|
| GET /api/health | WARP + gateway reachability, ensemble attribution |
| GET /api/config | read search_config.json (ensemble, paper, gate) |
| PUT /api/config | update pool / temperatures / rounds / min+max figures / budget |
| POST /api/workspaces | create a NEW paper dir; replicate KnowledgeRepresentation/ + augment; engine stays shared |
| POST /api/uploads | upload one or more local source papers into a workspace |
| POST /api/runs | start build_research and/or render_paper over the input list |
| GET /api/runs/:id/events | SSE stream: stage, %, ETA, heartbeat, QC rounds, figure results |
| POST /api/convert | HTML → docx/pdf, self-improving over N passes |
| GET /api/runs/:id/output?fmt= | rendered html / docx / pdf |
| GET /api/runs/:id/audit | deterministic invariant report |
| GET /api/knowledge/:node | FULL knowledge node text (writing/figure/citation/author/profile + rubric) |
| PUT /api/knowledge/:node | edit a knowledge node (takes effect next run; replicated to new workspaces) |
POST /api/runs — request body
{
"workspace": "papers-vince/ActionEngram",
"new_workspace": false,
"replicate_knowledge": true,
"augment_knowledge": "",
"inputs": ["KnowledgeRepresentation/10-PAPER.txt"],
"formats": ["html","docx"],
"conversion_passes": 3,
"pool": ["poolside/Laguna-S-2.1"],
"max_rounds": 3, // ① draft REFINE (build_research)
"qc_rounds": 5, // ② body QC + ③ figure QC, per-application
"min_figures": 12, "max_figures": 19,
"qc_temperatures": [0.2,0.5,0.8,0.4,0.7],
"figure_temperatures":[0.3,0.7],
"daily_usd_cap": 15,
"no_qc": false, "no_figures": false, "dry_run": false
}
SSE event shape (drives the progress bar / ETA / stall)
event: stage data: {"stage":"qc","pct":42,"eta_s":95}
event: heartbeat data: {"t":1699,"alive":true}
event: qc data: {"round":2,"temp":0.5,"accept":true,"gain":3}
event: figure data: {"n":7,"title":"Anatomy…","kept":true,"soft":1}
event: convert data: {"fmt":"docx","pass":2,"of":3}
event: done data: {"audit":{"dollar":0,"figs":19,...}}
The client watches heartbeat; if none
arrives for >4s it flags a stall/crash. The wrapper shells out to build_research.py + render_paper.py
(and a to_format.py converter) and tails stdout + 12-QC-LOG.txt; no pipeline
logic is duplicated.