Spaces:
Running on Zero
Running on Zero
fix: make example notes builder-facing
Browse filesCo-authored-by: Codex <noreply@openai.com>
- README.md +1 -1
- hackathon_advisor/field_notes.py +8 -8
- static/app.js +1 -1
- tests/test_app.py +3 -1
- tests/test_field_notes.py +6 -1
- tests/test_frontend_copy.py +2 -0
README.md
CHANGED
|
@@ -66,7 +66,7 @@ is intentionally kept out of the main user workflow.
|
|
| 66 |
## Field Notes Artifact
|
| 67 |
|
| 68 |
The `field_notes` Gradio API endpoint and `Notes` button export a Markdown build note from the exact session state:
|
| 69 |
-
builder profile, selected goals, idea board, cited Spaces, latest build plan,
|
| 70 |
keeps the note tied to auditable app evidence instead of a separate hand-written summary.
|
| 71 |
|
| 72 |
## Chapter Artifact
|
|
|
|
| 66 |
## Field Notes Artifact
|
| 67 |
|
| 68 |
The `field_notes` Gradio API endpoint and `Notes` button export a Markdown build note from the exact session state:
|
| 69 |
+
builder profile, selected goals, idea board, cited Spaces, latest build plan, advisor actions, and the share caption. This
|
| 70 |
keeps the note tied to auditable app evidence instead of a separate hand-written summary.
|
| 71 |
|
| 72 |
## Chapter Artifact
|
hackathon_advisor/field_notes.py
CHANGED
|
@@ -53,12 +53,12 @@ def build_field_notes_markdown(session: dict[str, Any], metadata: dict[str, Any]
|
|
| 53 |
else:
|
| 54 |
lines.append("No build plan has been generated yet.")
|
| 55 |
|
| 56 |
-
lines.extend(["", "##
|
| 57 |
if trace:
|
| 58 |
for index, event in enumerate(trace, start=1):
|
| 59 |
-
lines.extend(
|
| 60 |
else:
|
| 61 |
-
lines.append("No
|
| 62 |
|
| 63 |
wood_map = last_artifact.get("wood_map") if isinstance(last_artifact.get("wood_map"), dict) else {}
|
| 64 |
if wood_map:
|
|
@@ -122,14 +122,14 @@ def _idea_section(index: int, idea: dict[str, Any]) -> list[str]:
|
|
| 122 |
return lines
|
| 123 |
|
| 124 |
|
| 125 |
-
def
|
| 126 |
tools = _list_of_dicts(event.get("tools"))
|
| 127 |
-
|
| 128 |
lines = [
|
| 129 |
-
f"###
|
| 130 |
"",
|
| 131 |
f"- Input: {_clean(event.get('input'))}",
|
| 132 |
-
f"-
|
| 133 |
]
|
| 134 |
verdict = _clean(event.get("verdict"))
|
| 135 |
overall = event.get("overall")
|
|
@@ -141,7 +141,7 @@ def _trace_section(index: int, event: dict[str, Any]) -> list[str]:
|
|
| 141 |
resolution = event.get("tool_resolution") if isinstance(event.get("tool_resolution"), dict) else {}
|
| 142 |
call = resolution.get("call") if isinstance(resolution.get("call"), dict) else {}
|
| 143 |
if call:
|
| 144 |
-
lines.append(f"-
|
| 145 |
lines.append("")
|
| 146 |
return lines
|
| 147 |
|
|
|
|
| 53 |
else:
|
| 54 |
lines.append("No build plan has been generated yet.")
|
| 55 |
|
| 56 |
+
lines.extend(["", "## Session Decisions", ""])
|
| 57 |
if trace:
|
| 58 |
for index, event in enumerate(trace, start=1):
|
| 59 |
+
lines.extend(_decision_section(index, event))
|
| 60 |
else:
|
| 61 |
+
lines.append("No session decisions were recorded.")
|
| 62 |
|
| 63 |
wood_map = last_artifact.get("wood_map") if isinstance(last_artifact.get("wood_map"), dict) else {}
|
| 64 |
if wood_map:
|
|
|
|
| 122 |
return lines
|
| 123 |
|
| 124 |
|
| 125 |
+
def _decision_section(index: int, event: dict[str, Any]) -> list[str]:
|
| 126 |
tools = _list_of_dicts(event.get("tools"))
|
| 127 |
+
action_names = " -> ".join(_clean(tool.get("name")) for tool in tools if tool.get("name")) or "reply"
|
| 128 |
lines = [
|
| 129 |
+
f"### Decision {index}",
|
| 130 |
"",
|
| 131 |
f"- Input: {_clean(event.get('input'))}",
|
| 132 |
+
f"- Advisor actions: {action_names}",
|
| 133 |
]
|
| 134 |
verdict = _clean(event.get("verdict"))
|
| 135 |
overall = event.get("overall")
|
|
|
|
| 141 |
resolution = event.get("tool_resolution") if isinstance(event.get("tool_resolution"), dict) else {}
|
| 142 |
call = resolution.get("call") if isinstance(resolution.get("call"), dict) else {}
|
| 143 |
if call:
|
| 144 |
+
lines.append(f"- Recorded action: `{_clean(call.get('name'))}`")
|
| 145 |
lines.append("")
|
| 146 |
return lines
|
| 147 |
|
static/app.js
CHANGED
|
@@ -385,7 +385,7 @@ function applyDemoSession(data) {
|
|
| 385 |
session.profile = session.profile || {};
|
| 386 |
session.goals = Array.isArray(session.goals) ? session.goals : [];
|
| 387 |
session.last_response = data.response || session.last_response || "";
|
| 388 |
-
session.ui_status =
|
| 389 |
currentArtifact = data.artifact || session.last_artifact || null;
|
| 390 |
ink.textContent = data.response || "Example session loaded.";
|
| 391 |
ink.classList.remove("thinking");
|
|
|
|
| 385 |
session.profile = session.profile || {};
|
| 386 |
session.goals = Array.isArray(session.goals) ? session.goals : [];
|
| 387 |
session.last_response = data.response || session.last_response || "";
|
| 388 |
+
session.ui_status = "Example idea board loaded with a plan and share page.";
|
| 389 |
currentArtifact = data.artifact || session.last_artifact || null;
|
| 390 |
ink.textContent = data.response || "Example session loaded.";
|
| 391 |
ink.classList.remove("thinking");
|
tests/test_app.py
CHANGED
|
@@ -73,7 +73,9 @@ def test_field_notes_endpoint_exports_markdown() -> None:
|
|
| 73 |
assert "Skills: frontend" in payload
|
| 74 |
assert "Goals: Build notes" in payload
|
| 75 |
assert "Targets: Field Notes" not in payload
|
| 76 |
-
assert "##
|
|
|
|
|
|
|
| 77 |
assert "Write build notes from the exact decisions" in payload
|
| 78 |
|
| 79 |
|
|
|
|
| 73 |
assert "Skills: frontend" in payload
|
| 74 |
assert "Goals: Build notes" in payload
|
| 75 |
assert "Targets: Field Notes" not in payload
|
| 76 |
+
assert "## Session Decisions" in payload
|
| 77 |
+
assert "## Turn Trace" not in payload
|
| 78 |
+
assert "Planner call" not in payload
|
| 79 |
assert "Write build notes from the exact decisions" in payload
|
| 80 |
|
| 81 |
|
tests/test_field_notes.py
CHANGED
|
@@ -31,8 +31,13 @@ def test_field_notes_markdown_contains_session_decisions() -> None:
|
|
| 31 |
assert "A local-first archive cartographer for family photos" in markdown
|
| 32 |
assert "## Build Plan" in markdown
|
| 33 |
assert "Write build notes from the exact decisions" in markdown
|
|
|
|
|
|
|
|
|
|
| 34 |
assert "Closest cited Spaces" in markdown
|
| 35 |
assert "Page " in markdown
|
| 36 |
assert "## Wood Map" in markdown
|
| 37 |
assert "echo score" in markdown
|
| 38 |
-
assert "
|
|
|
|
|
|
|
|
|
| 31 |
assert "A local-first archive cartographer for family photos" in markdown
|
| 32 |
assert "## Build Plan" in markdown
|
| 33 |
assert "Write build notes from the exact decisions" in markdown
|
| 34 |
+
assert "## Session Decisions" in markdown
|
| 35 |
+
assert "### Decision 2" in markdown
|
| 36 |
+
assert "Recorded action: `make_plan`" in markdown
|
| 37 |
assert "Closest cited Spaces" in markdown
|
| 38 |
assert "Page " in markdown
|
| 39 |
assert "## Wood Map" in markdown
|
| 40 |
assert "echo score" in markdown
|
| 41 |
+
assert "## Turn Trace" not in markdown
|
| 42 |
+
assert "Planner call" not in markdown
|
| 43 |
+
assert "tool trace" not in markdown.lower()
|
tests/test_frontend_copy.py
CHANGED
|
@@ -10,6 +10,7 @@ def test_main_interface_copy_is_builder_facing() -> None:
|
|
| 10 |
assert "Closest project echoes" in html
|
| 11 |
assert "Press Plan to draft build steps for the selected idea." in app_js
|
| 12 |
assert "Loading an example idea board." in app_js
|
|
|
|
| 13 |
assert "/api/artifact.png" in app_js
|
| 14 |
assert "renderArtifactCanvas" not in app_js
|
| 15 |
assert "canvas.toDataURL" not in app_js
|
|
@@ -25,6 +26,7 @@ def test_main_interface_copy_is_builder_facing() -> None:
|
|
| 25 |
"Still riffling the inked pages.",
|
| 26 |
"YOU VS THE WOOD",
|
| 27 |
"current Wood",
|
|
|
|
| 28 |
]
|
| 29 |
for phrase in stale_jargon:
|
| 30 |
assert phrase not in combined
|
|
|
|
| 10 |
assert "Closest project echoes" in html
|
| 11 |
assert "Press Plan to draft build steps for the selected idea." in app_js
|
| 12 |
assert "Loading an example idea board." in app_js
|
| 13 |
+
assert "Example idea board loaded with a plan and share page." in app_js
|
| 14 |
assert "/api/artifact.png" in app_js
|
| 15 |
assert "renderArtifactCanvas" not in app_js
|
| 16 |
assert "canvas.toDataURL" not in app_js
|
|
|
|
| 26 |
"Still riffling the inked pages.",
|
| 27 |
"YOU VS THE WOOD",
|
| 28 |
"current Wood",
|
| 29 |
+
"advisor turns",
|
| 30 |
]
|
| 31 |
for phrase in stale_jargon:
|
| 32 |
assert phrase not in combined
|