review(dash): pre-claim independent ground truth baseline — 432 run dirs/308 parseable/124 unparseable, bluesky-pds=8 runs w/ mixed numeric+named ids (timestamp-sort trap), per-recipe counts, break-test plan
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
76
machine-docs/REVIEW-dash.md
Normal file
76
machine-docs/REVIEW-dash.md
Normal file
@ -0,0 +1,76 @@
|
||||
# REVIEW-dash — Adversary verdicts for phase `dash` (per-recipe run history fix)
|
||||
|
||||
SSOT: /srv/cc-ci/cc-ci-plan/plan-phase-dash-recipe-history.md
|
||||
Gates: M1 (fix implemented + locally verified), M2 (deployed + verified live).
|
||||
|
||||
---
|
||||
|
||||
## Pre-claim independent ground truth (Adversary, @2026-06-17T16:20Z, cold)
|
||||
|
||||
Gathered directly from the host (`ssh cc-ci`), BEFORE any Builder claim — this is my own
|
||||
baseline to verify the fix against, not the Builder's narrative.
|
||||
|
||||
**Run artifacts on host `/var/lib/cc-ci-runs`:**
|
||||
- **432** run dirs total; **308** have a parseable `results.json`; **124** dirs have NO
|
||||
parseable `results.json` (in-flight / failed-early — contain only `junit/`, `screenshot.png`,
|
||||
`abra/`). The fix MUST skip these 124 gracefully (no 500).
|
||||
- `results.json` schema 2 keys: `customization, finished, flags, level, lint, pr, recipe, ref,
|
||||
results, run_id, rungs, schema, screenshot, skips, stages, summary_card, version`.
|
||||
Fields the history needs ARE present: `recipe`, `version`, `level`, `ref`, `finished` (epoch
|
||||
float timestamp), `run_id`. Status is derivable from `results`/`rungs` (per-stage pass/fail).
|
||||
|
||||
**Per-recipe run counts (from parseable results.json):**
|
||||
```
|
||||
33 plausible 24 ghost 9 mailu 6 cryptpad
|
||||
33 custom-html 24 custom-html-tiny 8 lasuite-drive 3 drone
|
||||
28 immich 15 mattermost-lts 8 lasuite-docs 3 custom-html-rst-bad
|
||||
25 discourse 12 uptime-kuma 8 gitea
|
||||
24 (ghost) 12 mumble 8 bluesky-pds
|
||||
11 matrix-synapse 7 custom-html-bkp-bad
|
||||
10 lasuite-meet 6 keycloak
|
||||
9 n8n 6 hedgedoc
|
||||
```
|
||||
- `bluesky-pds` (named M2 target) → **8 runs**. `plausible`/`custom-html` → 33 (exceed a 30 cap →
|
||||
good cap test). A ~30 display cap should show 8 for bluesky-pds, 30 for plausible/custom-html.
|
||||
|
||||
**bluesky-pds runs — newest-first BY `finished` timestamp (the correct order):**
|
||||
```
|
||||
run_id ref level finished
|
||||
753 dcf933813df9 5 1781663348
|
||||
556 f7b6c8dfb81c 5 1781301301
|
||||
435 f7b6c8dfb81c 5 1781192858
|
||||
427 f7b6c8dfb81c 5 1781178768
|
||||
423 f7b6c8dfb81c 0 1781178063
|
||||
ab-bluesky-pds-oldmain b2d86efba3f1 0 1781126338
|
||||
m2rr-bluesky-pds b2d86efba3f1 0 1781123524
|
||||
m2r-bluesky-pds b2d86efba3f1 0 1781121610
|
||||
```
|
||||
**ADVERSARIAL TRAP TO CHECK:** run ids are MIXED numeric (753,556,…) AND named
|
||||
(`m2rr-bluesky-pds`, `ab-bluesky-pds-oldmain`). Sorting by `int(run_id)` would crash or misorder
|
||||
the named runs; sorting lexically would put `9...` after `7...` wrongly and scatter named ones.
|
||||
**Only a `finished`-timestamp sort yields the correct newest-first order.** I will verify the
|
||||
deployed page matches the timestamp order above, and that 423 (older, finished 1781178063) sorts
|
||||
BELOW 427 (1781178768) even though 423<427 numerically-close — and that the named runs land in
|
||||
their timestamp positions, not bunched at top/bottom.
|
||||
|
||||
**Current (buggy) code (`dashboard/dashboard.py`):** `history_for(recipe)` returns
|
||||
`[_build_row(b) for b in _custom_recipe_builds() …]`; `_custom_recipe_builds` fetches a single
|
||||
Drone page `…/builds?per_page=100`. So history is capped at whatever recipe runs fall in the
|
||||
latest-100 Drone window → most recipes show 1 row. Confirmed root cause matches plan §1.
|
||||
|
||||
**Things I will break-test on the fix:**
|
||||
1. Count + order per recipe match the host artifacts (esp. bluesky-pds 8, timestamp order above).
|
||||
2. The 124 unparseable dirs don't 500 and don't appear as garbage rows.
|
||||
3. Path-traversal guard + `/recipe/<name>` validation preserved (try `/recipe/../..`,
|
||||
`/recipe/foo%2f..`, arg injection in recipe name).
|
||||
4. Overview (`/`), `/badge/<recipe>.svg`, `/runs/<id>/<file>` unchanged.
|
||||
5. stdlib-only (no new imports/deps); mount stays read-only.
|
||||
6. Display cap actually bounds (plausible/custom-html show cap, not 33) AND newest are kept
|
||||
(not oldest) when capped.
|
||||
7. Run links resolve — for named run ids too (no Drone build number for m2r*/ab-*).
|
||||
|
||||
---
|
||||
|
||||
## Verdicts
|
||||
|
||||
(none yet — awaiting Builder M1 claim in STATUS-dash.md)
|
||||
Reference in New Issue
Block a user