cvpfus Codex commited on
Commit ·
bf25028
1
Parent(s): 084291e
Add curl commands to demo checks
Browse filesCo-authored-by: Codex <codex@openai.com>
- FIELD_NOTES.md +1 -1
- README.md +1 -1
- SUBMISSION.md +1 -1
- app.py +42 -30
- scripts/verify.py +9 -0
- static/app.css +10 -0
- static/app.js +1 -0
FIELD_NOTES.md
CHANGED
|
@@ -28,7 +28,7 @@ The app exposes the same budget through `/api/model-budget`, including numeric `
|
|
| 28 |
|
| 29 |
Runtime setup is also data-backed. `/api/runtime-setup` lists the app command, llama.cpp launch command, model-specific runtime paths, environment values, and fallbacks. The session panel renders a compact version so the demo can distinguish real model wiring from deterministic safety nets.
|
| 30 |
|
| 31 |
-
The judge runbook lives at `/api/demo-script` and is rendered in the session panel with its API evidence checks. It keeps the live presentation repeatable by pairing visible actions with API checks for health, model budget, runtime setup, runtime status, image descriptions, reader narration, and speech.
|
| 32 |
|
| 33 |
Submission readiness lives at `/api/submission-readiness`. It aggregates the demo-critical checks into one payload: model budget, award evidence, custom frontend assets, runtime setup, accessibility audit, image receipts, and executable demo API checks. POST checks must include sample bodies before readiness passes.
|
| 34 |
|
|
|
|
| 28 |
|
| 29 |
Runtime setup is also data-backed. `/api/runtime-setup` lists the app command, llama.cpp launch command, model-specific runtime paths, environment values, and fallbacks. The session panel renders a compact version so the demo can distinguish real model wiring from deterministic safety nets.
|
| 30 |
|
| 31 |
+
The judge runbook lives at `/api/demo-script` and is rendered in the session panel with its API evidence checks. It keeps the live presentation repeatable by pairing visible actions with API checks for health, model budget, runtime setup, runtime status, image descriptions, reader narration, and speech. Each API check includes a curl command for quick reproduction.
|
| 32 |
|
| 33 |
Submission readiness lives at `/api/submission-readiness`. It aggregates the demo-critical checks into one payload: model budget, award evidence, custom frontend assets, runtime setup, accessibility audit, image receipts, and executable demo API checks. POST checks must include sample bodies before readiness passes.
|
| 34 |
|
README.md
CHANGED
|
@@ -75,7 +75,7 @@ The verifier checks syntax, static assets, Space metadata consistency, determini
|
|
| 75 |
|
| 76 |
`/api/runtime-setup` exposes the commands, environment values, and fallback paths used for the model stack so the demo can be reproduced from the same data the UI displays.
|
| 77 |
|
| 78 |
-
`/api/demo-script` exposes a compact judge runbook with the visible actions
|
| 79 |
|
| 80 |
`/api/accessibility-audit` exposes structured evidence for semantic reading order, keyboard navigation, reader cursor state, shortcut safety, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
|
| 81 |
|
|
|
|
| 75 |
|
| 76 |
`/api/runtime-setup` exposes the commands, environment values, and fallback paths used for the model stack so the demo can be reproduced from the same data the UI displays.
|
| 77 |
|
| 78 |
+
`/api/demo-script` exposes a compact judge runbook with the visible actions, API checks, sample bodies, and curl commands that prove the submission claims. The session panel renders those actions and API evidence checks as the Judge Runbook.
|
| 79 |
|
| 80 |
`/api/accessibility-audit` exposes structured evidence for semantic reading order, keyboard navigation, reader cursor state, shortcut safety, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
|
| 81 |
|
SUBMISSION.md
CHANGED
|
@@ -46,7 +46,7 @@ The prototype is designed for a live hackathon demo: every model-facing path has
|
|
| 46 |
- `/api/submission-readiness`: one pass/fail rollup for model budget, award evidence, custom frontend, runtime setup, accessibility, image receipts, and demo API checks.
|
| 47 |
- `/api/evidence-bundle`: copyable JSON bundle containing the core judge evidence receipts.
|
| 48 |
|
| 49 |
-
The
|
| 50 |
|
| 51 |
The accessibility audit also documents two reader-mode details that matter during judging: the active item is exposed as a reader cursor with focus, visible outline, stable id, and `aria-current`; global shortcuts ignore form controls so voice, speed, and auto-advance settings remain usable while reader mode is active.
|
| 52 |
|
|
|
|
| 46 |
- `/api/submission-readiness`: one pass/fail rollup for model budget, award evidence, custom frontend, runtime setup, accessibility, image receipts, and demo API checks.
|
| 47 |
- `/api/evidence-bundle`: copyable JSON bundle containing the core judge evidence receipts.
|
| 48 |
|
| 49 |
+
The checks in `/api/demo-script` include curl commands, and the POST checks include sample JSON bodies for `/api/reader-brain` and `/api/speak`.
|
| 50 |
|
| 51 |
The accessibility audit also documents two reader-mode details that matter during judging: the active item is exposed as a reader cursor with focus, visible outline, stable id, and `aria-current`; global shortcuts ignore form controls so voice, speed, and auto-advance settings remain usable while reader mode is active.
|
| 52 |
|
app.py
CHANGED
|
@@ -213,7 +213,48 @@ def runtime_setup_core() -> dict[str, Any]:
|
|
| 213 |
}
|
| 214 |
|
| 215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
def demo_script_core() -> dict[str, Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
return {
|
| 218 |
"ok": True,
|
| 219 |
"title": "Tiny Narrator judge demo",
|
|
@@ -245,36 +286,7 @@ def demo_script_core() -> dict[str, Any]:
|
|
| 245 |
"evidence": "Tiny Titan, Llama Champion, Off-Brand, and Field Notes evidence is visible.",
|
| 246 |
},
|
| 247 |
],
|
| 248 |
-
"api_checks":
|
| 249 |
-
{"method": "GET", "path": "/api/health", "expect": "custom Gradio Server app and model manifest"},
|
| 250 |
-
{"method": "GET", "path": "/api/model-budget", "expect": "all_models_within_limit is true"},
|
| 251 |
-
{"method": "GET", "path": "/api/runtime-setup", "expect": "llama.cpp, Kokoro, vision, and image paths"},
|
| 252 |
-
{"method": "GET", "path": "/api/runtime-status", "expect": "online or fallback-ready runtime labels"},
|
| 253 |
-
{"method": "GET", "path": "/api/accessibility-audit", "expect": "all reader-mode checks pass"},
|
| 254 |
-
{"method": "GET", "path": "/api/image-descriptions", "expect": "three article image descriptions"},
|
| 255 |
-
{"method": "GET", "path": "/api/submission-readiness", "expect": "all submission readiness checks pass"},
|
| 256 |
-
{
|
| 257 |
-
"method": "POST",
|
| 258 |
-
"path": "/api/reader-brain",
|
| 259 |
-
"expect": "concise narration or fallback narration",
|
| 260 |
-
"sample_body": {
|
| 261 |
-
"node_type": "heading",
|
| 262 |
-
"text": "The model map",
|
| 263 |
-
"position": "item 4 of 10",
|
| 264 |
-
"mode": "narrate",
|
| 265 |
-
},
|
| 266 |
-
},
|
| 267 |
-
{
|
| 268 |
-
"method": "POST",
|
| 269 |
-
"path": "/api/speak",
|
| 270 |
-
"expect": "Kokoro audio or audible browser fallback path",
|
| 271 |
-
"sample_body": {
|
| 272 |
-
"text": "Heading. The model map.",
|
| 273 |
-
"voice": READER_SETTINGS["default_voice"],
|
| 274 |
-
"speed": READER_SETTINGS["default_speed"],
|
| 275 |
-
},
|
| 276 |
-
},
|
| 277 |
-
],
|
| 278 |
}
|
| 279 |
|
| 280 |
|
|
|
|
| 213 |
}
|
| 214 |
|
| 215 |
|
| 216 |
+
def demo_curl_command(check: dict[str, Any]) -> str:
|
| 217 |
+
url = f"http://localhost:7860{check['path']}"
|
| 218 |
+
if check["method"] == "GET":
|
| 219 |
+
return f"curl {url}"
|
| 220 |
+
sample_body = json.dumps(check["sample_body"], separators=(",", ":"))
|
| 221 |
+
return f"curl -X POST {url} -H \"Content-Type: application/json\" -d '{sample_body}'"
|
| 222 |
+
|
| 223 |
+
|
| 224 |
def demo_script_core() -> dict[str, Any]:
|
| 225 |
+
api_checks = [
|
| 226 |
+
{"method": "GET", "path": "/api/health", "expect": "custom Gradio Server app and model manifest"},
|
| 227 |
+
{"method": "GET", "path": "/api/model-budget", "expect": "all_models_within_limit is true"},
|
| 228 |
+
{"method": "GET", "path": "/api/runtime-setup", "expect": "llama.cpp, Kokoro, vision, and image paths"},
|
| 229 |
+
{"method": "GET", "path": "/api/runtime-status", "expect": "online or fallback-ready runtime labels"},
|
| 230 |
+
{"method": "GET", "path": "/api/accessibility-audit", "expect": "all reader-mode checks pass"},
|
| 231 |
+
{"method": "GET", "path": "/api/image-descriptions", "expect": "three article image descriptions"},
|
| 232 |
+
{"method": "GET", "path": "/api/submission-readiness", "expect": "all submission readiness checks pass"},
|
| 233 |
+
{
|
| 234 |
+
"method": "POST",
|
| 235 |
+
"path": "/api/reader-brain",
|
| 236 |
+
"expect": "concise narration or fallback narration",
|
| 237 |
+
"sample_body": {
|
| 238 |
+
"node_type": "heading",
|
| 239 |
+
"text": "The model map",
|
| 240 |
+
"position": "item 4 of 10",
|
| 241 |
+
"mode": "narrate",
|
| 242 |
+
},
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"method": "POST",
|
| 246 |
+
"path": "/api/speak",
|
| 247 |
+
"expect": "Kokoro audio or audible browser fallback path",
|
| 248 |
+
"sample_body": {
|
| 249 |
+
"text": "Heading. The model map.",
|
| 250 |
+
"voice": READER_SETTINGS["default_voice"],
|
| 251 |
+
"speed": READER_SETTINGS["default_speed"],
|
| 252 |
+
},
|
| 253 |
+
},
|
| 254 |
+
]
|
| 255 |
+
for check in api_checks:
|
| 256 |
+
check["curl"] = demo_curl_command(check)
|
| 257 |
+
|
| 258 |
return {
|
| 259 |
"ok": True,
|
| 260 |
"title": "Tiny Narrator judge demo",
|
|
|
|
| 286 |
"evidence": "Tiny Titan, Llama Champion, Off-Brand, and Field Notes evidence is visible.",
|
| 287 |
},
|
| 288 |
],
|
| 289 |
+
"api_checks": api_checks,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
}
|
| 291 |
|
| 292 |
|
scripts/verify.py
CHANGED
|
@@ -45,6 +45,7 @@ def verify_static_assets() -> None:
|
|
| 45 |
assert_true("copyEvidenceButton" in index_html, "Article should expose a copyable evidence bundle button")
|
| 46 |
assert_true("loadDemoScript" in app_js, "Frontend should render the structured demo script")
|
| 47 |
assert_true("payload.api_checks" in app_js, "Frontend should render structured demo API checks")
|
|
|
|
| 48 |
assert_true("/api/evidence-bundle" in app_js, "Frontend should fetch the evidence bundle for copying")
|
| 49 |
assert_true("function haltPlayback" in app_js, "Reader controls should expose a shared playback halt helper")
|
| 50 |
assert_true(
|
|
@@ -344,6 +345,14 @@ def verify_routes() -> None:
|
|
| 344 |
all(item.get("sample_body") for item in demo_payload["api_checks"] if item["method"] == "POST"),
|
| 345 |
"Every POST demo check should include an executable sample body",
|
| 346 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
reader_sample = client.post(reader_check["path"], json=reader_check["sample_body"])
|
| 348 |
assert_true(reader_sample.status_code == 200, "Reader-brain sample payload should be executable")
|
| 349 |
reader_sample_payload = reader_sample.json()
|
|
|
|
| 45 |
assert_true("copyEvidenceButton" in index_html, "Article should expose a copyable evidence bundle button")
|
| 46 |
assert_true("loadDemoScript" in app_js, "Frontend should render the structured demo script")
|
| 47 |
assert_true("payload.api_checks" in app_js, "Frontend should render structured demo API checks")
|
| 48 |
+
assert_true("demo-api-command" in app_js, "Frontend should render copyable demo commands")
|
| 49 |
assert_true("/api/evidence-bundle" in app_js, "Frontend should fetch the evidence bundle for copying")
|
| 50 |
assert_true("function haltPlayback" in app_js, "Reader controls should expose a shared playback halt helper")
|
| 51 |
assert_true(
|
|
|
|
| 345 |
all(item.get("sample_body") for item in demo_payload["api_checks"] if item["method"] == "POST"),
|
| 346 |
"Every POST demo check should include an executable sample body",
|
| 347 |
)
|
| 348 |
+
assert_true(
|
| 349 |
+
all(item["curl"].startswith("curl ") for item in demo_payload["api_checks"]),
|
| 350 |
+
"Every demo API check should include a curl command",
|
| 351 |
+
)
|
| 352 |
+
assert_true(
|
| 353 |
+
"-d '" in reader_check["curl"] and "/api/reader-brain" in reader_check["curl"],
|
| 354 |
+
"Reader-brain curl command should include the sample JSON body",
|
| 355 |
+
)
|
| 356 |
reader_sample = client.post(reader_check["path"], json=reader_check["sample_body"])
|
| 357 |
assert_true(reader_sample.status_code == 200, "Reader-brain sample payload should be executable")
|
| 358 |
reader_sample_payload = reader_sample.json()
|
static/app.css
CHANGED
|
@@ -465,6 +465,16 @@ dd {
|
|
| 465 |
font-size: 0.78rem;
|
| 466 |
}
|
| 467 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
.budget-list {
|
| 469 |
display: grid;
|
| 470 |
gap: 8px;
|
|
|
|
| 465 |
font-size: 0.78rem;
|
| 466 |
}
|
| 467 |
|
| 468 |
+
.demo-api-command {
|
| 469 |
+
grid-column: 1 / -1;
|
| 470 |
+
display: block;
|
| 471 |
+
padding: 8px;
|
| 472 |
+
border-radius: 6px;
|
| 473 |
+
background: #f7f3ee;
|
| 474 |
+
color: var(--ink);
|
| 475 |
+
white-space: normal;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
.budget-list {
|
| 479 |
display: grid;
|
| 480 |
gap: 8px;
|
static/app.js
CHANGED
|
@@ -252,6 +252,7 @@ async function loadDemoScript() {
|
|
| 252 |
<span>${escapeHtml(item.method)}</span>
|
| 253 |
<code>${escapeHtml(item.path)}</code>
|
| 254 |
<p>${escapeHtml(item.expect)}${item.sample_body ? " Sample body included." : ""}</p>
|
|
|
|
| 255 |
</li>
|
| 256 |
`)
|
| 257 |
.join("");
|
|
|
|
| 252 |
<span>${escapeHtml(item.method)}</span>
|
| 253 |
<code>${escapeHtml(item.path)}</code>
|
| 254 |
<p>${escapeHtml(item.expect)}${item.sample_body ? " Sample body included." : ""}</p>
|
| 255 |
+
<code class="demo-api-command">${escapeHtml(item.curl)}</code>
|
| 256 |
</li>
|
| 257 |
`)
|
| 258 |
.join("");
|