JacobLinCool Codex commited on
Commit
f61d18a
·
verified ·
1 Parent(s): e0cdb73

refactor: focus app ui on builders

Browse files

Co-authored-by: Codex <noreply@openai.com>

Files changed (3) hide show
  1. README.md +28 -27
  2. static/app.js +28 -22
  3. static/index.html +1 -14
README.md CHANGED
@@ -32,7 +32,7 @@ The current milestone is a deployable, deterministic vertical slice:
32
  - Offline search over project titles, tags, models, and descriptions.
33
  - Jargon correction for hackathon/model terms.
34
  - One-turn advisor loop with overlap citations, whitespace suggestions, scoring, and plans.
35
- - Custom `gradio.Server` frontend with streaming API events.
36
 
37
  See [DESIGN.md](DESIGN.md) for the full product and model plan.
38
 
@@ -60,8 +60,9 @@ source, project order, and digest before the app starts.
60
 
61
  ## Trace Artifact
62
 
63
- The app exposes a `trace_artifact` Gradio API endpoint and a `JSONL` button in the UI. Both emit the same JSONL schema:
64
- a manifest row followed by one row per agent turn. `data/sample_trace.jsonl` is a checked-in, Hub-published sample trace.
 
65
 
66
  ## Field Notes Artifact
67
 
@@ -77,45 +78,45 @@ the private Field Notes artifact.
77
 
78
  ## LoRA Dataset Artifact
79
 
80
- The `lora_dataset` Gradio API endpoint and `LoRA` button export a compact chat JSONL dataset from successful session
81
- turns. Each included turn yields a tool-call example and an advisor-response example for `openbmb/MiniCPM5-1B`, with the
82
- selected targets, parsed XML tool call, tool observations, and score context preserved. This prepares the Well-Tuned
83
- path without claiming that the adapter has already been trained or published.
84
 
85
  ## LoRA Training Kit
86
 
87
- `/api/lora-training-kit.zip` and the `Train` button export a training kit for the deterministic demo session: SFT JSONL,
88
- training recipe, adapter model-card draft, and the exact training command. The included
89
- `scripts/train_minicpm_lora.py` entrypoint supports a dependency-light `--dry-run` validation path and a real
90
- `transformers + PEFT` training path after installing `pip install -e '.[train]'`. The Prize Ledger still marks
91
- Well-Tuned as training-kit-ready until a real adapter is trained and published.
92
 
93
  ## Submission Packet
94
 
95
- The `submission_packet` Gradio API endpoint and `Packet` button export a Markdown submission bundle for the current
96
- session: live links, snapshot provenance, a timed demo script, artifact checklist, Prize Ledger evidence, model budget,
97
- session trace summary, social post draft, and open badge gaps. This keeps the final submission story tied to the same
98
- auditable state as the app instead of a separate hand-curated checklist.
99
 
100
  ## Demo Rehearsal
101
 
102
- `/api/demo-session` and the `Demo` button load a deterministic two-turn rehearsal: a complete project idea, profile,
103
- target badges, score seal, build plan, trace, wood map, and export-ready artifacts. It is built by running the same
104
- advisor engine as a normal user session, so the demo state can be used immediately with JSONL, Notes, Chapter, LoRA,
105
- Packet, and PNG exports.
106
 
107
  ## Demo Evidence Bundle
108
 
109
- `/api/demo-bundle.zip` and the `Bundle` button download a server-built ZIP for the deterministic demo session. The
110
- bundle includes a manifest, demo session JSON, Prize Ledger JSON, trace JSONL, Field Notes, Almanac chapter, LoRA SFT
111
- JSONL, LoRA training kit, Submission Packet, and a PNG export note. This gives judges or collaborators one auditable
112
- package without depending on browser `localStorage`.
113
 
114
  ## Prize Ledger
115
 
116
- `/api/prize-ledger` and the in-app Prize Ledger panel expose submission evidence: the documented model stack, total
117
- parameter budget, Tiny Titan eligibility, runtime backend, and badge readiness. This keeps the demo's prize claims tied
118
- to visible app state rather than hidden notes.
119
 
120
  ## Wood Map
121
 
 
32
  - Offline search over project titles, tags, models, and descriptions.
33
  - Jargon correction for hackathon/model terms.
34
  - One-turn advisor loop with overlap citations, whitespace suggestions, scoring, and plans.
35
+ - Custom `gradio.Server` frontend focused on the builder's idea workflow, with submission evidence kept in API exports.
36
 
37
  See [DESIGN.md](DESIGN.md) for the full product and model plan.
38
 
 
60
 
61
  ## Trace Artifact
62
 
63
+ The app exposes a `trace_artifact` Gradio API endpoint for submission evidence and debugging. It emits a manifest row
64
+ followed by one row per agent turn. `data/sample_trace.jsonl` is a checked-in, Hub-published sample trace. This endpoint
65
+ is intentionally kept out of the main user workflow.
66
 
67
  ## Field Notes Artifact
68
 
 
78
 
79
  ## LoRA Dataset Artifact
80
 
81
+ The `lora_dataset` Gradio API endpoint exports a compact chat JSONL dataset from successful session turns. Each included
82
+ turn yields a tool-call example and an advisor-response example for `openbmb/MiniCPM5-1B`, with the selected targets,
83
+ parsed XML tool call, tool observations, and score context preserved. This prepares the Well-Tuned path without claiming
84
+ that the adapter has already been trained or published.
85
 
86
  ## LoRA Training Kit
87
 
88
+ `/api/lora-training-kit.zip` exports a training kit for the deterministic demo session: SFT JSONL, training recipe,
89
+ adapter model-card draft, and the exact training command. The included `scripts/train_minicpm_lora.py` entrypoint
90
+ supports a dependency-light `--dry-run` validation path and a real `transformers + PEFT` training path after installing
91
+ `pip install -e '.[train]'`. The Prize Ledger still marks Well-Tuned as training-kit-ready until a real adapter is
92
+ trained and published.
93
 
94
  ## Submission Packet
95
 
96
+ The `submission_packet` Gradio API endpoint exports a Markdown submission bundle for the current session: live links,
97
+ snapshot provenance, a timed demo script, artifact checklist, Prize Ledger evidence, model budget, session trace
98
+ summary, social post draft, and open badge gaps. This keeps the final submission story tied to the same auditable state
99
+ as the app instead of a separate hand-curated checklist.
100
 
101
  ## Demo Rehearsal
102
 
103
+ `/api/demo-session` and the `Example` button load a deterministic two-turn sample: a complete project idea, profile,
104
+ target badges, score seal, build plan, trace, and wood map. It is built by running the same advisor engine as a normal
105
+ user session, so the visible app stays focused on the builder's idea while API exports remain available for submission
106
+ evidence.
107
 
108
  ## Demo Evidence Bundle
109
 
110
+ `/api/demo-bundle.zip` downloads a server-built ZIP for the deterministic demo session. The bundle includes a manifest,
111
+ demo session JSON, Prize Ledger JSON, trace JSONL, Field Notes, Almanac chapter, LoRA SFT JSONL, LoRA training kit,
112
+ Submission Packet, and a PNG export note. This gives judges or collaborators one auditable package without depending on
113
+ browser `localStorage`.
114
 
115
  ## Prize Ledger
116
 
117
+ `/api/prize-ledger` exposes submission evidence: the documented model stack, total parameter budget, Tiny Titan
118
+ eligibility, runtime backend, and badge readiness. It is kept as an API artifact rather than a primary in-app panel so
119
+ the user-facing app stays centered on idea evaluation.
120
 
121
  ## Wood Map
122
 
static/app.js CHANGED
@@ -63,7 +63,7 @@ exportButton.addEventListener("click", () => {
63
  exportArtifact(currentArtifact);
64
  });
65
 
66
- exportTraceButton.addEventListener("click", async () => {
67
  await exportTrace();
68
  });
69
 
@@ -75,19 +75,19 @@ exportChapterButton.addEventListener("click", async () => {
75
  await exportChapter();
76
  });
77
 
78
- exportLoraButton.addEventListener("click", async () => {
79
  await exportLoraDataset();
80
  });
81
 
82
- exportTrainKitButton.addEventListener("click", () => {
83
  window.location.assign("/api/lora-training-kit.zip");
84
  });
85
 
86
- exportPacketButton.addEventListener("click", async () => {
87
  await exportSubmissionPacket();
88
  });
89
 
90
- exportBundleButton.addEventListener("click", () => {
91
  window.location.assign("/api/demo-bundle.zip");
92
  });
93
 
@@ -181,7 +181,7 @@ async function loadDemoSession() {
181
  setCommandDisabled(true);
182
  ink.classList.remove("bleed", "gold");
183
  ink.classList.add("thinking");
184
- ink.textContent = "The demo pages are turning.";
185
  corrections.textContent = "";
186
  try {
187
  const response = await fetch("/api/demo-session");
@@ -225,12 +225,12 @@ function applyDemoSession(data) {
225
  renderProjects(data.projects || []);
226
  }
227
  exportButton.disabled = !currentArtifact;
228
- exportTraceButton.disabled = !(session.trace?.length);
229
- exportNotesButton.disabled = !(session.trace?.length);
230
- exportChapterButton.disabled = !(session.ideas?.length);
231
- exportLoraButton.disabled = !(session.trace?.length);
232
- exportPacketButton.disabled = !(session.trace?.length);
233
- corrections.textContent = `demo: ${data.turn_count || 0} recorded turns`;
234
  saveSession();
235
  }
236
 
@@ -263,11 +263,11 @@ function renderRestoredSession(data) {
263
  renderIdeas(session.ideas || []);
264
  renderPlan(session.last_plan || []);
265
  renderTrace(session.trace || []);
266
- exportTraceButton.disabled = !(session.trace?.length);
267
- exportNotesButton.disabled = !(session.trace?.length);
268
- exportChapterButton.disabled = !(session.ideas?.length);
269
- exportLoraButton.disabled = !(session.trace?.length);
270
- exportPacketButton.disabled = !(session.trace?.length);
271
  }
272
 
273
  function readSavedSession() {
@@ -354,6 +354,7 @@ function renderProfile(profile) {
354
  }
355
 
356
  function renderPrizeLedger(ledger) {
 
357
  prizeLedgerEl.innerHTML = "";
358
  if (!ledger) {
359
  prizeLedgerEl.innerHTML = `<div class="empty">No prize ledger loaded.</div>`;
@@ -447,11 +448,11 @@ function handleEvent(event) {
447
  renderWoodMap(event.artifact.wood_map || null);
448
  exportButton.disabled = false;
449
  }
450
- exportTraceButton.disabled = !(session.trace?.length);
451
- exportNotesButton.disabled = !(session.trace?.length);
452
- exportChapterButton.disabled = !(session.ideas?.length);
453
- exportLoraButton.disabled = !(session.trace?.length);
454
- exportPacketButton.disabled = !(session.trace?.length);
455
  saveSession();
456
  }
457
  }
@@ -604,6 +605,7 @@ function renderPlan(steps) {
604
  }
605
 
606
  function renderTrace(trace) {
 
607
  traceEl.innerHTML = "";
608
  if (!trace.length) {
609
  traceEl.innerHTML = `<div class="empty">No tool marks yet.</div>`;
@@ -621,6 +623,10 @@ function renderTrace(trace) {
621
  }
622
  }
623
 
 
 
 
 
624
  function setCommandDisabled(disabled) {
625
  document.querySelectorAll(".command-row button").forEach((button) => {
626
  if (button.id === "export-train-kit") return;
 
63
  exportArtifact(currentArtifact);
64
  });
65
 
66
+ exportTraceButton?.addEventListener("click", async () => {
67
  await exportTrace();
68
  });
69
 
 
75
  await exportChapter();
76
  });
77
 
78
+ exportLoraButton?.addEventListener("click", async () => {
79
  await exportLoraDataset();
80
  });
81
 
82
+ exportTrainKitButton?.addEventListener("click", () => {
83
  window.location.assign("/api/lora-training-kit.zip");
84
  });
85
 
86
+ exportPacketButton?.addEventListener("click", async () => {
87
  await exportSubmissionPacket();
88
  });
89
 
90
+ exportBundleButton?.addEventListener("click", () => {
91
  window.location.assign("/api/demo-bundle.zip");
92
  });
93
 
 
181
  setCommandDisabled(true);
182
  ink.classList.remove("bleed", "gold");
183
  ink.classList.add("thinking");
184
+ ink.textContent = "A sample page is being inked.";
185
  corrections.textContent = "";
186
  try {
187
  const response = await fetch("/api/demo-session");
 
225
  renderProjects(data.projects || []);
226
  }
227
  exportButton.disabled = !currentArtifact;
228
+ setButtonDisabled(exportTraceButton, !(session.trace?.length));
229
+ setButtonDisabled(exportNotesButton, !(session.trace?.length));
230
+ setButtonDisabled(exportChapterButton, !(session.ideas?.length));
231
+ setButtonDisabled(exportLoraButton, !(session.trace?.length));
232
+ setButtonDisabled(exportPacketButton, !(session.trace?.length));
233
+ corrections.textContent = `example loaded: ${data.turn_count || 0} advisor turns`;
234
  saveSession();
235
  }
236
 
 
263
  renderIdeas(session.ideas || []);
264
  renderPlan(session.last_plan || []);
265
  renderTrace(session.trace || []);
266
+ setButtonDisabled(exportTraceButton, !(session.trace?.length));
267
+ setButtonDisabled(exportNotesButton, !(session.trace?.length));
268
+ setButtonDisabled(exportChapterButton, !(session.ideas?.length));
269
+ setButtonDisabled(exportLoraButton, !(session.trace?.length));
270
+ setButtonDisabled(exportPacketButton, !(session.trace?.length));
271
  }
272
 
273
  function readSavedSession() {
 
354
  }
355
 
356
  function renderPrizeLedger(ledger) {
357
+ if (!prizeLedgerEl) return;
358
  prizeLedgerEl.innerHTML = "";
359
  if (!ledger) {
360
  prizeLedgerEl.innerHTML = `<div class="empty">No prize ledger loaded.</div>`;
 
448
  renderWoodMap(event.artifact.wood_map || null);
449
  exportButton.disabled = false;
450
  }
451
+ setButtonDisabled(exportTraceButton, !(session.trace?.length));
452
+ setButtonDisabled(exportNotesButton, !(session.trace?.length));
453
+ setButtonDisabled(exportChapterButton, !(session.ideas?.length));
454
+ setButtonDisabled(exportLoraButton, !(session.trace?.length));
455
+ setButtonDisabled(exportPacketButton, !(session.trace?.length));
456
  saveSession();
457
  }
458
  }
 
605
  }
606
 
607
  function renderTrace(trace) {
608
+ if (!traceEl) return;
609
  traceEl.innerHTML = "";
610
  if (!trace.length) {
611
  traceEl.innerHTML = `<div class="empty">No tool marks yet.</div>`;
 
623
  }
624
  }
625
 
626
+ function setButtonDisabled(button, disabled) {
627
+ if (button) button.disabled = disabled;
628
+ }
629
+
630
  function setCommandDisabled(disabled) {
631
  document.querySelectorAll(".command-row button").forEach((button) => {
632
  if (button.id === "export-train-kit") return;
static/index.html CHANGED
@@ -27,19 +27,14 @@
27
  <button id="submit" type="submit" title="Ink the page">Ink</button>
28
  </form>
29
  <div class="command-row" aria-label="Advisor commands">
30
- <button type="button" id="load-demo" title="Load a complete demo session">Demo</button>
31
  <button type="button" data-command="write bolder and find whitespace" title="Find a gold margin">
32
  Gap
33
  </button>
34
  <button type="button" data-command="make a build plan" title="Draft a build plan">Plan</button>
35
  <button type="button" data-command="compare ideas" title="Compare the idea board">Rank</button>
36
- <button type="button" id="export-trace" title="Export the tool trace" disabled>JSONL</button>
37
  <button type="button" id="export-notes" title="Export Field Notes" disabled>Notes</button>
38
  <button type="button" id="export-chapter" title="Export the Almanac chapter" disabled>Chapter</button>
39
- <button type="button" id="export-lora" title="Export the LoRA SFT dataset" disabled>LoRA</button>
40
- <button type="button" id="export-train-kit" title="Download the LoRA training kit">Train</button>
41
- <button type="button" id="export-packet" title="Export the submission packet" disabled>Packet</button>
42
- <button type="button" id="export-bundle" title="Download the demo evidence bundle">Bundle</button>
43
  <button type="button" id="export-artifact" title="Export the current fate page" disabled>PNG</button>
44
  <button type="button" id="reset-session" title="Clear the saved session">Reset</button>
45
  </div>
@@ -66,10 +61,6 @@
66
  <h2>Profile</h2>
67
  <div id="profile" class="profile-grid"></div>
68
  </article>
69
- <article class="wide-panel">
70
- <h2>Prize Ledger</h2>
71
- <div id="prize-ledger" class="prize-ledger"></div>
72
- </article>
73
  <article>
74
  <h2>Idea Board</h2>
75
  <div id="ideas" class="idea-list"></div>
@@ -86,10 +77,6 @@
86
  <h2>Build Plan</h2>
87
  <ol id="plan" class="plan-list"></ol>
88
  </article>
89
- <article>
90
- <h2>Trace</h2>
91
- <div id="trace" class="trace-list"></div>
92
- </article>
93
  </div>
94
  </section>
95
  </div>
 
27
  <button id="submit" type="submit" title="Ink the page">Ink</button>
28
  </form>
29
  <div class="command-row" aria-label="Advisor commands">
30
+ <button type="button" id="load-demo" title="Load a sample idea">Example</button>
31
  <button type="button" data-command="write bolder and find whitespace" title="Find a gold margin">
32
  Gap
33
  </button>
34
  <button type="button" data-command="make a build plan" title="Draft a build plan">Plan</button>
35
  <button type="button" data-command="compare ideas" title="Compare the idea board">Rank</button>
 
36
  <button type="button" id="export-notes" title="Export Field Notes" disabled>Notes</button>
37
  <button type="button" id="export-chapter" title="Export the Almanac chapter" disabled>Chapter</button>
 
 
 
 
38
  <button type="button" id="export-artifact" title="Export the current fate page" disabled>PNG</button>
39
  <button type="button" id="reset-session" title="Clear the saved session">Reset</button>
40
  </div>
 
61
  <h2>Profile</h2>
62
  <div id="profile" class="profile-grid"></div>
63
  </article>
 
 
 
 
64
  <article>
65
  <h2>Idea Board</h2>
66
  <div id="ideas" class="idea-list"></div>
 
77
  <h2>Build Plan</h2>
78
  <ol id="plan" class="plan-list"></ol>
79
  </article>
 
 
 
 
80
  </div>
81
  </section>
82
  </div>