@accidentally-awesome-labs/opencode-bestest 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/VERSION +1 -1
- package/payload/agents/plan-checker.md +3 -2
- package/payload/agents/reviewer.md +4 -0
- package/payload/hooks/session-start.sh +23 -0
- package/payload/scripts/trace.sh +134 -6
- package/payload/skills/bestest-go/SKILL.md +2 -2
- package/payload/skills/build/SKILL.md +3 -3
- package/payload/skills/design/SKILL.md +27 -0
- package/payload/skills/design/references/direction.md +23 -0
- package/payload/skills/design/references/motion.md +33 -0
- package/payload/skills/design/references/review-rules.md +42 -0
- package/payload/skills/interrogate/SKILL.md +2 -2
- package/payload/skills/interrogate/references/challenge-tactics.md +4 -1
- package/payload/skills/plan/SKILL.md +2 -1
- package/payload/skills/ship/SKILL.md +2 -2
- package/payload/skills/using-bestest/references/claude-code.md +1 -1
- package/payload/skills/using-bestest/references/codex.md +1 -1
- package/payload/templates/DESIGN.md +54 -0
- package/payload/templates/DISCOVERED.md +3 -0
- package/payload/templates/PLAN.md +1 -1
- package/payload/templates/SPEC.md +3 -1
- package/payload/templates/UAT.md +3 -1
- package/payload/templates/task-card.md +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accidentally-awesome-labs/opencode-bestest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "OpenCode head for the bestest plugin: guard/lock/syntax enforcement shelling into the shared bash hooks, passive state injection, and an installer for skills/agents/commands.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/payload/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0
|
|
@@ -12,14 +12,15 @@ You are the adversarial checker for a bestest project. You are read-only; you re
|
|
|
12
12
|
- `[Ambiguity]` — a sentence two reasonable builders would implement differently. Quote it; say the two readings.
|
|
13
13
|
- `[Conflict]` — two statements that cannot both hold. Cite both R-IDs/sections.
|
|
14
14
|
- `[Assumption]` — a load-bearing `[assumed]` tag or an untagged claim with no `[user]`/`[cited:]` evidence.
|
|
15
|
-
Check every R-N.M is real EARS (trigger + observable behavior, one sentence, testable), anti-goals ≥3, out_of_scope non-empty, user-facing docs dispositioned (R-IDs or out_of_scope), doneness function falsifiable, autonomy contract present. `deliverable: findings` SPECs: R-IDs are research questions — require a named verdict shape and evidence bar per R-ID instead of EARS. Gaps and Conflicts are freeze-blockers.
|
|
15
|
+
Check every R-N.M is real EARS (trigger + observable behavior, one sentence, testable), anti-goals ≥3, out_of_scope non-empty, user-facing docs dispositioned (R-IDs or out_of_scope), doneness function falsifiable, autonomy contract present. A DESIGN.md beside the SPEC gets graded too: `covers:` R-IDs real; Direction holds a specific reference object (adjectives alone = `[Ambiguity]`), ≥3 banned defaults, a signature element; hex only in Tokens; Motion rows numeric; Do/Don't ≥3 each and testable. An interface-shaped premise with no DESIGN.md is a `[Gap]`. `deliverable: findings` SPECs: R-IDs are research questions — require a named verdict shape and evidence bar per R-ID instead of EARS. Gaps and Conflicts are freeze-blockers.
|
|
16
16
|
|
|
17
17
|
**Plan mode** (given PLAN.md + cards + SPEC): hunt, in order:
|
|
18
18
|
1. R-IDs with no covering card; cards citing phantom R-IDs; orphan cards serving no R-ID.
|
|
19
19
|
2. **Recompute complexity** per card from its own fields (`1 + 2/extra file + 2/verify cmd + 3 if title needs "and" + 2/new interface`); declared < recomputed, or >6 unsplit → blocker.
|
|
20
20
|
3. Zero-context violations: placeholders, "as discussed", missing signatures/paths, a card a fresh stranger couldn't execute.
|
|
21
21
|
4. Assets consumed but never produced (check `blocked_by:` ordering too).
|
|
22
|
-
5. Complexity Justification table: any structure beyond the simplest satisfying design without a row → blocker.
|
|
22
|
+
5. Complexity Justification table: any structure beyond the simplest satisfying design without a row → blocker; a row naming no rejected rung (reuse / stdlib / platform / installed dep) → blocker.
|
|
23
23
|
6. TDD pairing: implementer cards with `may_edit_tests: true`, or no failing-test card ahead of them.
|
|
24
|
+
7. Design cascade: a card advancing a DESIGN.md `covers:` R-ID without `design: .bestest/DESIGN.md`, or any card inventing visual values the contract doesn't define → blocker.
|
|
24
25
|
|
|
25
26
|
Verdict format, both modes: `PASS` or `FAIL` + numbered blockers, each with file/R-ID cite and the one-line fix you'd accept. Nits go in a separate short list — never pad blockers.
|
|
@@ -13,9 +13,13 @@ Inputs: the card, the diff range, the report, SPEC.md, relevant D-IDs.
|
|
|
13
13
|
- **weight ≥ 4 — full adversarial:** actively try to break it. Trace the R-IDs' EARS triggers through the code by hand; probe edge/failure paths the tests skip; check the claim→evidence table by re-running what's cheap; hunt silent contract drift (behavior the SPEC forbids, error paths swallowed, security footguns in the diff).
|
|
14
14
|
- **weight < 4 — blockers-only:** correctness of the R-ID behavior, verify commands genuinely proving it, diff staying inside `files:`. No style opinions.
|
|
15
15
|
|
|
16
|
+
**ui-mode** (design-bearing cards — the dispatch includes the DESIGN.md contract and the ui review-rules): audit the diff against every rule; findings cite rule IDs. Blockers at any weight: raw values where a contract token exists, motion off the contract's Motion table, a report lacking a rendered-output pointer (screenshot/recording) for a visual change. Distinctive is not wrong — block only contract and rule violations; taste is at most a flag.
|
|
17
|
+
|
|
16
18
|
Always check, any weight:
|
|
17
19
|
1. Tests: do they *assert the criterion* or just execute the code? A test the implementation can't fail is a blocker at weight≥4, a flag below.
|
|
18
20
|
2. Report honesty: any claim whose evidence doesn't hold up = blocker, regardless of code quality.
|
|
19
21
|
3. `Bestest-Req:` trailer present and citing the card's R-IDs.
|
|
20
22
|
|
|
21
23
|
Verdict: `APPROVED` or numbered findings, each: severity (blocker/flag), file:line, what breaks, the smallest fix you'd accept. A finding you raised closes only when you re-confirm the fix — say explicitly what you'd need to see. Do not approve out of fatigue; do not block on taste.
|
|
24
|
+
|
|
25
|
+
Close every review with a delete-list: opportunities tagged `[delete]` `[stdlib]` `[native]` `[yagni]` `[shrink]`, one line each, ending `net: −N lines possible` — count N from the diff, never estimate; nothing to shrink = `net: 0`. Delete-tags are flags, not blockers — except an interface or dependency no R-ID needs: that one blocks.
|
|
@@ -17,6 +17,21 @@ hash_stdin() {
|
|
|
17
17
|
# Not a bestest project (or not a repo yet): stay silent.
|
|
18
18
|
[ -d "$b" ] || exit 0
|
|
19
19
|
|
|
20
|
+
# persona -> per-turn one-line minimalism reminder (UserPromptSubmit, both heads).
|
|
21
|
+
# Scoped to P4/quick: where code is written under an active card. At routing
|
|
22
|
+
# moments (done, P0-P3) it stays silent — "minimum that works" next to a fresh
|
|
23
|
+
# user ask out-shouts the router (measured: quick-lane eval 3/3 process-skips).
|
|
24
|
+
# The full stanza rides 'start'; builders get the ladder via the card contract.
|
|
25
|
+
if [ "$mode" = "persona" ]; then
|
|
26
|
+
ph="$(grep -m1 -E '^phase:' "$b/STATE.md" 2>/dev/null | sed -E 's/^phase:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
27
|
+
case "${ph:-}" in
|
|
28
|
+
P4|quick)
|
|
29
|
+
echo "[bestest minimalism reminder — standing plugin behavior] Ladder before new code: delete the need → reuse this repo → stdlib → platform-native → installed dep → minimum that works. Floor: validation, security, error handling, accessibility. The ladder shortens the solution, never the process — the active card and its gates still bind."
|
|
30
|
+
;;
|
|
31
|
+
esac
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
20
35
|
head="$(git -C "$root" rev-parse HEAD 2>/dev/null || echo none)"
|
|
21
36
|
# Hash content, not just the porcelain listing — an edit that keeps the same
|
|
22
37
|
# file list would otherwise slip past the drift check. Exclude our own snapshot
|
|
@@ -32,6 +47,8 @@ fi
|
|
|
32
47
|
|
|
33
48
|
echo "## bestest state (auto-injected — durable source of truth: .bestest/)"
|
|
34
49
|
sed -n '1,60p' "$b/STATE.md"
|
|
50
|
+
echo
|
|
51
|
+
echo "(The plugin: line above is the authoritative root for this project's scripts and templates — trust it as long as that path exists on disk. The live plugin install may sit at a different path; project-local copies are normal, and re-resolution applies only when the recorded path is missing.)"
|
|
35
52
|
|
|
36
53
|
if [ -f "$b/LOCKS" ] && [ -s "$b/LOCKS" ]; then
|
|
37
54
|
echo
|
|
@@ -39,6 +56,12 @@ if [ -f "$b/LOCKS" ] && [ -s "$b/LOCKS" ]; then
|
|
|
39
56
|
cat "$b/LOCKS"
|
|
40
57
|
fi
|
|
41
58
|
|
|
59
|
+
# Minimalism persona: the ladder sentence below must byte-match the builder
|
|
60
|
+
# contract in skills/build/SKILL.md (static-checks rule-copy lint).
|
|
61
|
+
echo
|
|
62
|
+
echo "### minimalism persona (standing plugin behavior, active every response; a one-line reminder repeats per turn during build)"
|
|
63
|
+
echo "Build like the laziest senior dev: before new code, descend the ladder: delete the need → reuse this repo → stdlib → platform-native → installed dep → minimum that works; never simplify away validation, security, error handling, accessibility, or anything explicitly asked. Deliberate ceilings: comment 'bestest-defer: <ceiling> until <trigger>' + a DISCOVERED.md line. The ladder shortens the solution, never the process — lanes, cards, and gates still bind."
|
|
64
|
+
|
|
42
65
|
card="$(grep -m1 -E '^card:' "$b/STATE.md" 2>/dev/null | sed -E 's/^card:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
43
66
|
if [ -n "${card:-}" ] && [ "$card" != "none" ] && [ -f "$root/$card" ]; then
|
|
44
67
|
echo
|
package/payload/scripts/trace.sh
CHANGED
|
@@ -29,6 +29,28 @@ check_discovered() { # every DISCOVERED entry needs a disposition by ship
|
|
|
29
29
|
|| fail "DISCOVERED entry lacks disposition: ${line%%|*}"
|
|
30
30
|
done < <(grep -E '^- ' "$b/DISCOVERED.md")
|
|
31
31
|
}
|
|
32
|
+
check_defers() { # 'bestest-defer: <ceiling> until <trigger>' markers: rot + harvest audit
|
|
33
|
+
if git -C "$root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
34
|
+
hits="$(git -C "$root" grep -In --untracked 'bestest-defer:' -- . ':!.bestest' 2>/dev/null || true)"
|
|
35
|
+
else
|
|
36
|
+
hits="$(grep -rIn --exclude-dir=.git --exclude-dir=.bestest --exclude-dir=node_modules 'bestest-defer:' "$root" 2>/dev/null || true)"
|
|
37
|
+
fi
|
|
38
|
+
[ -n "$hits" ] || return 0
|
|
39
|
+
while IFS= read -r h; do
|
|
40
|
+
[ -n "$h" ] || continue
|
|
41
|
+
loc="$(printf '%s' "$h" | cut -d: -f1,2)"
|
|
42
|
+
body="$(printf '%s' "$h" | sed 's/.*bestest-defer:[[:space:]]*//')"
|
|
43
|
+
case "$body" in
|
|
44
|
+
*' until '*) : ;;
|
|
45
|
+
*) fail "deferral marker without ' until <trigger>' — rot: $loc"; continue ;;
|
|
46
|
+
esac
|
|
47
|
+
ceiling="${body%% until *}"
|
|
48
|
+
grep -qF -- "$ceiling" "$b/DISCOVERED.md" 2>/dev/null \
|
|
49
|
+
|| fail "unharvested deferral marker — add a DISCOVERED.md defer line: $loc"
|
|
50
|
+
done <<DEOF
|
|
51
|
+
$hits
|
|
52
|
+
DEOF
|
|
53
|
+
}
|
|
32
54
|
check_roadmap() { # check_roadmap <1 to also require a verdict on the current milestone's ledger line>
|
|
33
55
|
ms_cur="$(grep -m1 -E '^milestone:' "$b/STATE.md" 2>/dev/null | sed -E 's/^milestone:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
34
56
|
if [ ! -f "$b/ROADMAP.md" ]; then
|
|
@@ -52,12 +74,16 @@ rids="$(grep -oE 'R-[0-9]+\.[0-9]+' "$b/SPEC.md" | sort -u)"
|
|
|
52
74
|
|
|
53
75
|
# --- quick-lane checks (--quick): Q-cards only, then exit --------------------
|
|
54
76
|
if [ "$mode" = "--quick" ]; then
|
|
55
|
-
# tamper canary: the quick lane never amends
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
# tamper canary: the quick lane never amends a frozen artifact (SPEC, DESIGN, …)
|
|
78
|
+
if [ -f "$b/LOCKS" ]; then
|
|
79
|
+
while IFS= read -r hl; do
|
|
80
|
+
[ -n "$hl" ] || continue
|
|
81
|
+
lh="$(printf '%s' "$hl" | awk '{print $2}')"; hp="$(printf '%s' "$hl" | awk '{print $3}')"
|
|
82
|
+
[ -f "$root/$hp" ] || continue
|
|
83
|
+
if command -v sha256sum >/dev/null 2>&1; then ch="$(sha256sum "$root/$hp" | cut -d' ' -f1)"
|
|
84
|
+
else ch="$(shasum -a 256 "$root/$hp" | cut -d' ' -f1)"; fi
|
|
85
|
+
[ "$lh" = "$ch" ] || fail "$hp no longer matches its LOCKS hash — the quick lane never amends frozen artifacts"
|
|
86
|
+
done < <(grep -E '^hash [0-9a-f]+ ' "$b/LOCKS" 2>/dev/null || true)
|
|
61
87
|
fi
|
|
62
88
|
|
|
63
89
|
qcards="$(ls "$b"/plans/Q-*.md 2>/dev/null || true)"
|
|
@@ -274,6 +300,107 @@ fi
|
|
|
274
300
|
# spikes: a spike: block in a research RQ file must carry a disposition: by P3
|
|
275
301
|
check_spikes
|
|
276
302
|
|
|
303
|
+
# --- design-contract checks: active iff .bestest/DESIGN.md exists -------------
|
|
304
|
+
check_design() {
|
|
305
|
+
df="$b/DESIGN.md"
|
|
306
|
+
[ -f "$df" ] || return 0
|
|
307
|
+
|
|
308
|
+
# covers: line names the UI R-IDs this contract governs; each must be real
|
|
309
|
+
drids="$(grep -m1 -E '^covers:' "$df" | grep -oE 'R-[0-9]+\.[0-9]+' || true)"
|
|
310
|
+
if [ -z "$drids" ]; then
|
|
311
|
+
fail "DESIGN.md needs a 'covers:' line naming its UI R-IDs"
|
|
312
|
+
else
|
|
313
|
+
for r in $drids; do
|
|
314
|
+
printf '%s\n' "$rids" | grep -qx "$r" || fail "DESIGN.md covers $r which is not in SPEC.md"
|
|
315
|
+
done
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
# freeze parity: a frozen SPEC demands a frozen design contract
|
|
319
|
+
if grep -qE '^hash [0-9a-f]+ \.bestest/SPEC\.md' "$b/LOCKS" 2>/dev/null; then
|
|
320
|
+
grep -qE '^hash [0-9a-f]+ \.bestest/DESIGN\.md' "$b/LOCKS" 2>/dev/null \
|
|
321
|
+
|| fail "SPEC is frozen but DESIGN.md has no LOCKS hash — freeze the design contract at P2"
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
# every section filled (headers matched verbatim; template guidance is comments)
|
|
325
|
+
for s in Direction Tokens 'Contrast pairs' Components Motion 'Do / Don' Responsive; do
|
|
326
|
+
section_filled "$df" "$s" || fail "DESIGN.md section empty: $s"
|
|
327
|
+
done
|
|
328
|
+
|
|
329
|
+
# token discipline: raw values live only in Tokens/Contrast pairs
|
|
330
|
+
awk '/^## Components/{f=1;next} /^## /{f=0} f' "$df" | grep -qE '#[0-9a-fA-F]{3,8}' \
|
|
331
|
+
&& fail "raw hex in DESIGN.md Components — reference {tokens}; hex lives only in Tokens"
|
|
332
|
+
|
|
333
|
+
# Motion rows: numeric ms + named easing, or an explicit none — never vibes
|
|
334
|
+
while IFS= read -r mrow; do
|
|
335
|
+
[ -n "$mrow" ] || continue
|
|
336
|
+
case "$mrow" in *none*) continue ;; esac
|
|
337
|
+
if ! { printf '%s' "$mrow" | grep -qE '[0-9]+[[:space:]]*ms' \
|
|
338
|
+
&& printf '%s' "$mrow" | grep -qE '(ease|linear|cubic-bezier|spring)'; }; then
|
|
339
|
+
fail "DESIGN.md Motion row lacks numeric ms + named easing (vibes are not a contract): $mrow"
|
|
340
|
+
fi
|
|
341
|
+
done < <(awk '/^## Motion/{f=1;next} /^## /{f=0} f && /^[[:space:]]*\|/' "$df" \
|
|
342
|
+
| grep -vE '^[[:space:]]*\|[-:| ]*$' | grep -vi 'duration')
|
|
343
|
+
|
|
344
|
+
# WCAG contrast on declared pairs (python3 stdlib; SKIP silently degrades)
|
|
345
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
346
|
+
cerr="$(awk '/^## Contrast pairs/{f=1;next} /^## /{f=0} f&&/^[[:space:]]*-/' "$df" | python3 -c '
|
|
347
|
+
import sys, re
|
|
348
|
+
def lum(h):
|
|
349
|
+
h = h.lstrip("#")
|
|
350
|
+
if len(h) == 3: h = "".join(c * 2 for c in h)
|
|
351
|
+
def lin(c):
|
|
352
|
+
c = int(h[c:c+2], 16) / 255.0
|
|
353
|
+
return c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4
|
|
354
|
+
return 0.2126 * lin(0) + 0.7152 * lin(2) + 0.0722 * lin(4)
|
|
355
|
+
for line in sys.stdin:
|
|
356
|
+
m = re.search(r"(#[0-9a-fA-F]{3,6})\s+on\s+(#[0-9a-fA-F]{3,6})", line)
|
|
357
|
+
if not m: continue
|
|
358
|
+
hi, lo = sorted((lum(m.group(1)), lum(m.group(2))), reverse=True)
|
|
359
|
+
ratio = (hi + 0.05) / (lo + 0.05)
|
|
360
|
+
need = 3.0 if "AA-large" in line else 4.5
|
|
361
|
+
if ratio < need:
|
|
362
|
+
print("%s on %s = %.2f (< %.1f)" % (m.group(1), m.group(2), ratio, need))
|
|
363
|
+
' 2>/dev/null || true)"
|
|
364
|
+
while IFS= read -r ce; do
|
|
365
|
+
[ -n "$ce" ] && fail "DESIGN.md contrast pair below WCAG AA: $ce"
|
|
366
|
+
done <<CEOF
|
|
367
|
+
$cerr
|
|
368
|
+
CEOF
|
|
369
|
+
else
|
|
370
|
+
echo "SKIP contrast math (no python3)"
|
|
371
|
+
fi
|
|
372
|
+
|
|
373
|
+
# cascade: each covers: R-ID needs >=1 covering card that carries the contract
|
|
374
|
+
for r in $drids; do
|
|
375
|
+
dcov=no
|
|
376
|
+
for c in $cards; do
|
|
377
|
+
cfm="$(front "$c")"
|
|
378
|
+
if printf '%s' "$cfm" | grep -E '^requirements:' | grep -Eq "$(rid_re "$r")" \
|
|
379
|
+
&& printf '%s' "$cfm" | grep -E '^design:' | grep -q 'DESIGN.md'; then dcov=yes; break; fi
|
|
380
|
+
done
|
|
381
|
+
[ "$dcov" = yes ] || fail "$r is a DESIGN.md covers: R-ID but no covering card carries design: .bestest/DESIGN.md"
|
|
382
|
+
done
|
|
383
|
+
|
|
384
|
+
# --all: covers: R-IDs must show rendered output in UAT, not prose
|
|
385
|
+
if [ "$mode" = "--all" ]; then
|
|
386
|
+
for r in $drids; do
|
|
387
|
+
grep -E "$(rid_re "$r")" "$b/UAT.md" 2>/dev/null | grep -qiE '\.(png|jpe?g|webp|gif|mp4|webm)|screenshot|recording' \
|
|
388
|
+
|| fail "$r is a UI criterion — its UAT evidence must point at rendered output (screenshot/recording)"
|
|
389
|
+
done
|
|
390
|
+
fi
|
|
391
|
+
}
|
|
392
|
+
check_design
|
|
393
|
+
|
|
394
|
+
# any card's design: value must be none or resolve to a file
|
|
395
|
+
for c in $cards; do
|
|
396
|
+
dval="$(front "$c" | grep -E '^design:' | head -1 | sed 's/^design:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]*$//')"
|
|
397
|
+
[ -n "${dval:-}" ] || continue
|
|
398
|
+
case "$dval" in
|
|
399
|
+
none) : ;;
|
|
400
|
+
*) [ -f "$root/$dval" ] || fail "$(basename "$c" .md) design: $dval does not resolve to a file" ;;
|
|
401
|
+
esac
|
|
402
|
+
done
|
|
403
|
+
|
|
277
404
|
# --- full-chain checks (--all) -----------------------------------------------
|
|
278
405
|
if [ "$mode" = "--all" ]; then
|
|
279
406
|
for c in $cards; do
|
|
@@ -309,6 +436,7 @@ if [ "$mode" = "--all" ]; then
|
|
|
309
436
|
done
|
|
310
437
|
|
|
311
438
|
check_discovered
|
|
439
|
+
check_defers
|
|
312
440
|
fi
|
|
313
441
|
|
|
314
442
|
if [ "$fails" -eq 0 ]; then
|
|
@@ -30,8 +30,8 @@ Findings deliverable (`deliverable: findings` in SPEC): P2 freeze → `phase: P5
|
|
|
30
30
|
## Milestone rollover (P5 shipped → next milestone)
|
|
31
31
|
|
|
32
32
|
All via explicit shell gate steps (LOCKS/SPEC are hook-frozen against file edits):
|
|
33
|
-
1. `N` = STATE `milestone:` (default v1). `mkdir -p .bestest/milestones/N` and `git mv` SPEC.md, PLAN.md, UAT.md, RUNBOOK.md, CODEBASE.md, FINDINGS.md, plans/, reports/, research/ (those that exist) into it, plus a `cp` snapshot of the final STATE.md (its gate log is the milestone's ledger). DECISIONS.md, LESSONS.md, DISCOVERED.md, ROADMAP.md stay live — history, debt and direction carry forward.
|
|
34
|
-
2. Rewrite LOCKS dropping
|
|
33
|
+
1. `N` = STATE `milestone:` (default v1). `mkdir -p .bestest/milestones/N` and `git mv` SPEC.md, DESIGN.md, PLAN.md, UAT.md, RUNBOOK.md, CODEBASE.md, FINDINGS.md, plans/, reports/, research/ (those that exist) into it, plus a `cp` snapshot of the final STATE.md (its gate log is the milestone's ledger). DECISIONS.md, LESSONS.md, DISCOVERED.md, ROADMAP.md stay live — history, debt and direction carry forward.
|
|
34
|
+
2. Rewrite LOCKS dropping every `hash` line (archived copies stay frozen); keep every test `glob` — incumbent tests stay immutable.
|
|
35
35
|
3. Fresh STATE.md from the template: `phase: P0`, `milestone: N+1`, same `plugin:` line. Commit `.bestest: roll over N -> N+1`.
|
|
36
36
|
4. Re-enter **interrogate** Stage 0 as brownfield — regenerate CODEBASE.md first (step 1a contract; trace.sh fails a stale one): prior SPEC (`.bestest/milestones/N/SPEC.md`), ROADMAP.md, the DISCOVERED backlog, and LESSONS are the opening context — the new idea is interrogated against what already ships; unshipped R-IDs and deferred DISCOVERED lines must be explicitly re-adopted or cut, never assumed.
|
|
37
37
|
|
|
@@ -9,14 +9,14 @@ You are the **orchestrator**: dispatch, gate, close loops. You do not write prod
|
|
|
9
9
|
|
|
10
10
|
## Dispatch loop
|
|
11
11
|
1. **Pick:** lowest-numbered incomplete card whose `blocked_by:` are all done. Set `card:` + `stage:` + `task_start: $(git rev-parse HEAD)` in STATE.md, mark card `doing`.
|
|
12
|
-
2. **Dispatch a fresh subagent** with: the card, LESSONS.md ("read first, append what you learn"), relevant D-IDs. File handoffs only — builders write code + `.bestest/reports/T-##.md`; they get no chat history.
|
|
13
|
-
3. **Builder contract** (put in the prompt): follow the card exactly; TDD (the failing test exists — make it pass, never edit it);
|
|
12
|
+
2. **Dispatch a fresh subagent** with: the card, LESSONS.md ("read first, append what you learn"), relevant D-IDs, and the file named by the card's `design:` field when not none. File handoffs only — builders write code + `.bestest/reports/T-##.md`; they get no chat history.
|
|
13
|
+
3. **Builder contract** (put in the prompt): follow the card exactly; TDD (the failing test exists — make it pass, never edit it); before new code, descend the ladder: delete the need → reuse this repo → stdlib → platform-native → installed dep → minimum that works; never simplify away validation, security, error handling, accessibility, or anything explicitly asked. A deliberate ceiling gets a code comment `bestest-defer: <ceiling> until <trigger>` plus a Discovered line — never silently. Commit with trailer `Bestest-Req: <R-IDs>`; on any underdetermined point return `BLOCKED: <specific question>` instead of improvising; report claim→evidence + FRICTION (or `None`) + Lessons (the exact LESSONS.md lines appended, or `None`) + Discovered.
|
|
14
14
|
4. **Gate mechanically** (never trust the report):
|
|
15
15
|
- Re-run every `verify:` command yourself; paste output.
|
|
16
16
|
- `git diff --name-only <task_start from STATE.md>..HEAD` ⊆ card `files:` — out-of-scope diffs get reverted or INTERRUPT; locked paths must show zero diff.
|
|
17
17
|
- Report FRICTION and Lessons sections present; Discovered lines actually appended to DISCOVERED.md.
|
|
18
18
|
5. **Close the loop:** FRICTION → patch the *remaining* cards now + append environment facts to LESSONS.md — before the next dispatch, not "later".
|
|
19
|
-
6. **Review** (risk-scaled): dispatch **reviewer** agent — card weight ≥4 → full adversarial pass; weight <4 → blockers-only. A finding closes only *fixed-and-reconfirmed by the reviewer*, or waived as a D-ID with a revisit trigger.
|
|
19
|
+
6. **Review** (risk-scaled): dispatch **reviewer** agent — card weight ≥4 → full adversarial pass; weight <4 → blockers-only. Design-bearing cards add **ui-mode**: the dispatch also includes the contract file and the design skill's `references/review-rules.md`. A finding closes only *fixed-and-reconfirmed by the reviewer*, or waived as a D-ID with a revisit trigger.
|
|
20
20
|
7. Mark done, update STATE.md, commit `.bestest/`, next card.
|
|
21
21
|
|
|
22
22
|
## Interrupt handling
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design
|
|
3
|
+
description: Use when a bestest project has a visible interface — design direction, the frozen DESIGN.md contract, and UI craft rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design
|
|
7
|
+
|
|
8
|
+
Loaded from interrogate Stage 2 when discovery finds an interface surface. Output: `.bestest/DESIGN.md` (template: DESIGN.md), frozen at P2 beside the SPEC. Direction method: `references/direction.md`. Motion values: `references/motion.md`. Rules the reviewer applies in ui-mode: `references/review-rules.md`.
|
|
9
|
+
|
|
10
|
+
## 1. Discovery
|
|
11
|
+
Ask only what research can't derive: platforms and breakpoints · brand constraints (existing tokens, fonts, logo rules) · accessibility floor beyond WCAG AA · motion appetite · the 2–3 screens users live in. **Brownfield:** extract incumbent tokens/components from the codebase first, `[cited:path]` — never re-ask what the stylesheet already answers. **No meaningful visual surface** (CLI, library, service)? Record that as a D-ID and stop — no DESIGN.md, none of the downstream gates activate.
|
|
12
|
+
|
|
13
|
+
## 2. Direction
|
|
14
|
+
Before any token: run `references/direction.md`. Name the 3 nearest default looks and ban them in the contract; pick ONE specific reference object (never adjectives); pick ONE signature element only this product could have. Present direction as a Taste batch — the user vetoes, you decide the rest.
|
|
15
|
+
|
|
16
|
+
## 3. Contract
|
|
17
|
+
Fill `templates/DESIGN.md`, headers verbatim. Discipline trace.sh enforces mechanically: `covers:` names the UI R-IDs · raw hex/px/font values live ONLY in Tokens and Contrast pairs — Components reference `{tokens}` · every Motion row is numeric ms + named easing, values from `references/motion.md` (`none` is an honest row) · every text fg/bg pair declared under Contrast pairs (≥4.5:1, or 3:1 marked `— AA-large`) · Do/Don't ≥3 each, testable phrasing.
|
|
18
|
+
|
|
19
|
+
## 4. Freeze (P2, with the SPEC)
|
|
20
|
+
The plan-checker's spec mode grades the contract alongside the SPEC; blockers block the freeze. Then hash it into LOCKS in the same gate step:
|
|
21
|
+
```bash
|
|
22
|
+
h="$( (command -v sha256sum >/dev/null && sha256sum .bestest/DESIGN.md || shasum -a 256 .bestest/DESIGN.md) | cut -d' ' -f1)" && printf 'hash %s .bestest/DESIGN.md\n' "$h" >> .bestest/LOCKS
|
|
23
|
+
```
|
|
24
|
+
Amendment = D-ID → shell-gate edit → re-hash, exactly like the SPEC. Rollover archives it with the milestone.
|
|
25
|
+
|
|
26
|
+
## 5. Downstream (all trace-checked)
|
|
27
|
+
P3: every card advancing a `covers:` R-ID sets `design: .bestest/DESIGN.md` — the orchestrator hands that file to builder and reviewer with the card. P4: reviewer runs ui-mode on design-bearing cards (contract + `references/review-rules.md`). P5: each `covers:` R-ID's UAT evidence is a screenshot/recording path, not prose — a UI criterion nobody looked at is not accepted.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Direction — escaping the default look
|
|
2
|
+
|
|
3
|
+
Generated design clusters hard around three looks: cream/warm-paper background + high-contrast serif display + terracotta accent · near-black background + one acid-green or vermilion accent · broadsheet layout with hairline rules. They are defaults, not choices. If another system given a similar prompt would produce substantially the same interface, the direction step failed.
|
|
4
|
+
|
|
5
|
+
## Method, in order
|
|
6
|
+
1. **Name the defaults.** Write the 3 most likely default looks for THIS product type — a pattern you haven't named is a pattern you can't avoid. They go in DESIGN.md as banned defaults.
|
|
7
|
+
2. **One specific reference.** A reference object describes a point; adjectives describe a region. "A 1970s graduate lecture handout" beats "clean, modern, trustworthy" — and naming the object names its negatives for free (a handout doesn't glow or use gradients).
|
|
8
|
+
3. **One signature element.** Something that could only exist for this product — a domain-shaped motif, an unexpected but purposeful structural move. "The overall feel" doesn't count; you must be able to point at it.
|
|
9
|
+
4. **Tokens from the world.** 4–6 named colors whose names evoke the reference ("ink", "parchment"). Reading the token list aloud should evoke the product, not a template ("gray-700", "surface-2").
|
|
10
|
+
|
|
11
|
+
## Craft rules (defaults that ARE choices)
|
|
12
|
+
- Hierarchy: ONE focal point per view; weight and color do more hierarchy work than size; trust modest type ratios (1.2–1.333).
|
|
13
|
+
- Color: 60/30/10 distribution; dark-mode surfaces climb roughly +7/+9/+12% lightness per level; borders are low-alpha white, not opaque gray.
|
|
14
|
+
- Shape: inputs sit darker/inset — they receive content; sidebars share the canvas color; nested radii concentric — child ≤ parent, outer = inner + padding.
|
|
15
|
+
- Type and data: tabular numerals for figures; balance-wrapped headings; density is a choice — state it in px, tight or airy, never unexamined.
|
|
16
|
+
- Touch targets ≥44px.
|
|
17
|
+
- **Use what exists:** native element → headless primitive → hand-roll last; hand-rolling owes the full behavior contract (keyboard nav, focus trap and return, ARIA names).
|
|
18
|
+
|
|
19
|
+
## Self-tests before the contract freezes
|
|
20
|
+
- **Swap test:** cover the product name — is the interface still recognizably this product?
|
|
21
|
+
- **Squint test:** blur the view — does exactly one focal point survive?
|
|
22
|
+
- **Token test:** read the token names aloud — world or template?
|
|
23
|
+
- **Signature test:** point at five specific decisions that are yours; vibes don't count.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Motion — the numeric canon
|
|
2
|
+
|
|
3
|
+
Fill the DESIGN.md Motion table from these values; deviations are Taste calls recorded in the contract. When in doubt: less. The remedial step for a bad animation is deletion, not tuning.
|
|
4
|
+
|
|
5
|
+
## When to animate
|
|
6
|
+
- Action fired 100+ times a day (shortcuts, command palette, tab switches): **no animation, ever** — write the row as `none`; that is a contract, not an omission.
|
|
7
|
+
- Never animate keyboard-initiated focus or typing.
|
|
8
|
+
- Tens/day: minimal or none. Occasional (modals, toasts): standard. Rare or first-run: delight allowed.
|
|
9
|
+
|
|
10
|
+
## Durations
|
|
11
|
+
Press feedback 100–160 ms · tooltips 125–200 ms · dropdowns/popovers 150–250 ms · modals/drawers 200–500 ms · everything non-modal under 300 ms. Exits run 60–70% of their enter — leaving should feel faster than arriving. Stagger list entrances 30–50 ms per item.
|
|
12
|
+
|
|
13
|
+
## Easing
|
|
14
|
+
- Entering or exiting the screen → ease-out.
|
|
15
|
+
- Moving on-screen (reorder, resize, reposition) → ease-in-out.
|
|
16
|
+
- Hover, color, opacity → ease.
|
|
17
|
+
- Constant motion (spinners, progress) → linear.
|
|
18
|
+
- **Never ease-in for UI** — it delays movement at the exact moment the user is watching closest.
|
|
19
|
+
|
|
20
|
+
Tokens: `--ease-out: cubic-bezier(0.23, 1, 0.32, 1)` · `--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1)` · `--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1)`.
|
|
21
|
+
|
|
22
|
+
## Physicality
|
|
23
|
+
- Nothing appears from nothing: enter from scale(0.95) + opacity 0, never scale(0).
|
|
24
|
+
- Pressables compress: scale(0.97) on active press.
|
|
25
|
+
- Popovers and menus scale from their trigger (transform-origin at the trigger); centered modals are exempt.
|
|
26
|
+
- State that retargets mid-flight (toasts, toggles, gestures) uses interruptible transitions/springs, never restart-from-zero keyframes.
|
|
27
|
+
|
|
28
|
+
## Performance
|
|
29
|
+
- Animate transform and opacity only; never layout properties (width, height, top, left).
|
|
30
|
+
- Write full transform strings — animation-library shorthand props may bypass hardware acceleration.
|
|
31
|
+
- Never drive child transforms through a parent CSS variable (per-frame recalculation storm).
|
|
32
|
+
- Blur ≤20px.
|
|
33
|
+
- `prefers-reduced-motion`: movement degrades to opacity; never silently remove feedback.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# UI review rules — reviewer ui-mode
|
|
2
|
+
|
|
3
|
+
Audit the diff against every rule; each finding cites its rule ID. Blockers at any weight: raw values where a DESIGN.md token exists, motion off the contract's Motion table, a report with no rendered-output pointer (screenshot/recording) for a visual change. Distinctive is not wrong — block only contract and rule violations; taste is at most a flag. Default to flagging; approval is earned.
|
|
4
|
+
|
|
5
|
+
## Interaction
|
|
6
|
+
- I1 NEVER block paste in inputs or textareas.
|
|
7
|
+
- I2 MUST: hit targets ≥44×44px, or padded to it.
|
|
8
|
+
- I3 MUST: visible focus state on every interactive element; never remove an outline without a replacement.
|
|
9
|
+
- I4 MUST: URL reflects shareable state — filters, tabs, pagination survive reload and share.
|
|
10
|
+
- I5 MUST: no double-submit — disable or make idempotent after first activation.
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
- L1 MUST: flex children that truncate need min-width 0.
|
|
14
|
+
- L2 NEVER: horizontal scroll at a breakpoint DESIGN.md declares.
|
|
15
|
+
- L3 MUST: nested radii concentric — child ≤ parent.
|
|
16
|
+
|
|
17
|
+
## Forms
|
|
18
|
+
- F1 MUST: every input has a label or accessible name.
|
|
19
|
+
- F2 MUST: validate on blur, not per keystroke; error text says how to fix.
|
|
20
|
+
|
|
21
|
+
## Feedback
|
|
22
|
+
- B1 MUST: mutations reflect in under 500 ms or show optimistic/pending state.
|
|
23
|
+
- B2 MUST: destructive actions get confirm or undo.
|
|
24
|
+
- B3 MUST: operations over 300 ms show a loading state; known layouts prefer skeleton over spinner.
|
|
25
|
+
|
|
26
|
+
## Accessibility
|
|
27
|
+
- A1 MUST: text contrast satisfies the DESIGN.md Contrast pairs (4.5:1; 3:1 AA-large); a new fg/bg pair the diff introduces gets declared in the contract, not eyeballed.
|
|
28
|
+
- A2 MUST: modals trap focus and return it on close.
|
|
29
|
+
- A3 MUST: icon-only buttons carry an accessible name.
|
|
30
|
+
- A4 NEVER: emoji as icons.
|
|
31
|
+
|
|
32
|
+
## Motion
|
|
33
|
+
- M1 MUST: every animation in the diff matches a DESIGN.md Motion row (duration + easing); an unlisted animation is an undeclared contract change.
|
|
34
|
+
- M2 NEVER: ease-in on UI; never enter from scale(0); never animate 100+/day actions.
|
|
35
|
+
- M3 MUST: prefers-reduced-motion handled — movement degrades to opacity.
|
|
36
|
+
- M4 MUST: transform/opacity only; no layout-property animation.
|
|
37
|
+
|
|
38
|
+
## Tokens
|
|
39
|
+
- T1 MUST: no raw hex/px/font/duration where a contract token exists — new values are contract amendments, not inline improvisation.
|
|
40
|
+
- T2 MUST: the DESIGN.md signature element survives in the shipped surface; flag a diff that erodes it.
|
|
41
|
+
|
|
42
|
+
Report shape: rule-ID findings first (blockers, then flags), then the standard delete-list.
|
|
@@ -24,7 +24,7 @@ Six forcing questions, strictly one at a time, researching between answers so th
|
|
|
24
24
|
Between questions, search for existing tools that already solve it; present findings before asking the user to justify building. Exit: a written **Premise Verdict** the user confirms — or an honest recommendation to pivot or park. A premise whose deliverable is knowledge, not software: record `deliverable: findings` — question-shaped R-IDs, P3–P4 skipped (research `references/findings.md`).
|
|
25
25
|
|
|
26
26
|
## Stage 2 — Discovery
|
|
27
|
-
Adaptive, domain-specific gray areas across
|
|
27
|
+
Adaptive, domain-specific gray areas across six buckets: users/actors · data & lifecycle · integration surface · failure/abuse · **interface surface** (visible UI → load the **design** skill) · **Anti-Goals (mandatory, ≥3)**. Present options annotated with what research already found ("Postgres and SQLite both fit; SQLite unless you need concurrent writers — you said single user"). Batch related Taste questions; never ask what Stage-3 research can derive.
|
|
28
28
|
|
|
29
29
|
## Stage 3 — Research handoff
|
|
30
30
|
Zero user questions by default. Load the **research** skill: fan-out → primary sources → adversarial verification → cited stack table → SLOPCHECK on every proposed dependency. Output: SPEC §5 rows, all `[cited:URL]`. A question only execution can answer → the research skill's spike protocol (timeboxed, hook-quarantined, disposition-mandatory).
|
|
@@ -46,4 +46,4 @@ Close the stage by writing **SPEC §8 — the doneness function**: the falsifiab
|
|
|
46
46
|
```bash
|
|
47
47
|
mkdir -p .bestest && h="$( (command -v sha256sum >/dev/null && sha256sum .bestest/SPEC.md || shasum -a 256 .bestest/SPEC.md) | cut -d' ' -f1)" && printf 'hash %s .bestest/SPEC.md\nglob <test-glob>\n' "$h" >> .bestest/LOCKS
|
|
48
48
|
```
|
|
49
|
-
Set `spec_hash:` in STATE.md, commit, advance to P3. This is the **last HIGH-touch moment** — everything after runs on the contract.
|
|
49
|
+
UI projects append the DESIGN.md hash line too (design skill §4). Set `spec_hash:` in STATE.md, commit, advance to P3. This is the **last HIGH-touch moment** — everything after runs on the contract.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Challenge tactics (Stage 4)
|
|
2
2
|
|
|
3
|
-
Run all
|
|
3
|
+
Run all six; report what each found, even if "nothing".
|
|
4
4
|
|
|
5
5
|
## 1. Tension naming
|
|
6
6
|
Find pairs of stated goals that pull against each other ("offline-first" vs "always-fresh data"; "zero config" vs "multi-tenant"). Name the tension, state which side the current spec silently picked, make the user pick explicitly. D-ID the resolution.
|
|
@@ -17,5 +17,8 @@ Walk every feature/requirement back to the Premise Verdict. Anything that doesn'
|
|
|
17
17
|
## 5. Alternatives for heavy decisions
|
|
18
18
|
Every weight≥6 decision gets one genuinely different alternative (not a strawman), with the strongest honest case for it in two sentences. If the user's choice survives the strongest opposing case, it's load-tested; if it flips, the challenge just paid for the whole interrogation.
|
|
19
19
|
|
|
20
|
+
## 6. YAGNI ladder on requirements
|
|
21
|
+
For every surviving requirement: what observably breaks if we ship without it? Could reuse, the stdlib, or the platform satisfy it with no new code? "We might need it" becomes Defer with a written reopen trigger. Challenge in-answer ("did X; Y covers it — need full X? say so"), never as a stall. Floor — never cut: validation, security, error handling, accessibility, anything the user explicitly asked for. A requirement is complexity smuggled in as prose; challenge it like code.
|
|
22
|
+
|
|
20
23
|
## SLOPCHECK (dependency vetting, used by Stage 3)
|
|
21
24
|
For each proposed dependency: last release date · open-issue trend · maintainer bus-factor · install weight · license · does the stdlib/platform already do this? Reject any dep that fails two, unless a D-ID records why it's worth it.
|
|
@@ -13,9 +13,10 @@ Input: frozen SPEC. Output: `.bestest/PLAN.md` (template: PLAN.md) and `.bestest
|
|
|
13
13
|
- **TDD pairing:** tests are authored by a card with `may_edit_tests: true`; the implementer card that follows has `false` and makes them pass (the lock-guard hook enforces this physically).
|
|
14
14
|
- **Complexity formula**, computed honestly on every card: `1 + 2/extra file + 2/verify command + 3 if the title needs "and" + 2/new interface`. Over 6 → split before anyone reviews it.
|
|
15
15
|
- Every card: `requirements:` R-IDs (no orphan cards), `files:` blast radius, `verify:` commands a machine can re-run, `blocked_by:` for real order constraints only.
|
|
16
|
+
- **Design-bearing cards:** every card advancing an R-ID named by a DESIGN.md `covers:` line sets `design: .bestest/DESIGN.md` and consumes contract tokens — never invented visual values (`trace.sh --plan` checks the cascade).
|
|
16
17
|
|
|
17
18
|
## Complexity Justification table (in PLAN.md)
|
|
18
|
-
Any design element beyond the simplest thing satisfying the R-IDs gets a row (columns in the PLAN.md template). No row → the plan-checker counts it as a blocker. This is where architecture astronautics goes to die.
|
|
19
|
+
Any design element beyond the simplest thing satisfying the R-IDs gets a row (columns in the PLAN.md template). Each row names the next-simpler rung rejected — reuse in this codebase / stdlib / platform-native / installed dep — "we might need it" is not a justification. No row → the plan-checker counts it as a blocker. This is where architecture astronautics goes to die.
|
|
19
20
|
|
|
20
21
|
## Checker loop (gate)
|
|
21
22
|
1. Dispatch **plan-checker** agent (card mode) with PLAN.md + cards + SPEC.
|
|
@@ -8,13 +8,13 @@ description: Use when a bestest project enters P5 — UAT against every acceptan
|
|
|
8
8
|
Nothing new gets built here; P5 proves what exists and stages it for production. Findings variant (`deliverable: findings`): steps 1–2 run against FINDINGS.md with `trace.sh --findings`; step 5 is `n/a: findings deliverable` — discipline: research `references/findings.md`.
|
|
9
9
|
|
|
10
10
|
## 1. UAT — one question per criterion
|
|
11
|
-
Create `.bestest/UAT.md` (template). For each `R-N.M` in SPEC §2: restate the EARS criterion as a single check the user can answer, attach the evidence pointer (command output, screenshot, URL), walk the user through them **one at a time**. Any fail → back to P4 with a card citing that R-ID; do not negotiate the criterion mid-UAT (that's a SPEC amendment: D-ID + re-hash). One retry per R-ID: a second UAT fail means build and criterion disagree at spec level — INTERRUPT with the exact mismatch: amend (D-ID + re-hash) or mark the row FAIL and carry it into go/no-go as an open risk. Never loop a third time.
|
|
11
|
+
Create `.bestest/UAT.md` (template). For each `R-N.M` in SPEC §2: restate the EARS criterion as a single check the user can answer, attach the evidence pointer (command output, screenshot, URL), walk the user through them **one at a time**. R-IDs named by a DESIGN.md `covers:` line: the evidence must be a screenshot/recording path — `trace.sh --all` fails prose-only UI rows. Any fail → back to P4 with a card citing that R-ID; do not negotiate the criterion mid-UAT (that's a SPEC amendment: D-ID + re-hash). One retry per R-ID: a second UAT fail means build and criterion disagree at spec level — INTERRUPT with the exact mismatch: amend (D-ID + re-hash) or mark the row FAIL and carry it into go/no-go as an open risk. Never loop a third time.
|
|
12
12
|
|
|
13
13
|
## 2. Full-chain audit
|
|
14
14
|
First complete this milestone's ROADMAP.md ledger line with a verdict and refresh its Next-up/Abandoned sections — the audit fails a verdict-less line. Then `"$PLUGIN"/scripts/trace.sh --all` where `PLUGIN` = the `plugin:` line in STATE.md must print PASS — attach output as gate evidence. It enforces: every criterion covered, every done card reported with FRICTION, every R-ID committed with a `Bestest-Req:` trailer and present in UAT.
|
|
15
15
|
|
|
16
16
|
## 3. Disposition DISCOVERED.md — every line
|
|
17
|
-
|
|
17
|
+
First harvest deferral markers: `git grep -n 'bestest-defer:'` — every marker gets a DISCOVERED `defer:` line (grammar in the header); trace.sh --all fails trigger-less and unharvested markers. Then append `| disposition:` to each line. trace.sh fails any bare line. This is where "never dropped" gets cashed.
|
|
18
18
|
|
|
19
19
|
## 4. LESSONS curation
|
|
20
20
|
Compress LESSONS.md: dedupe, drop task-local noise, keep durable environment/codebase facts. Then two promotion offers, each one batch, each the user's call: top project-relevant items → the project memory file; `[env]`/`[tool]` facts that hold beyond this project → the user-level memory file (both per harness map). Never write either silently; declined items stay in LESSONS.md.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
| Concept | Native here |
|
|
4
4
|
|---|---|
|
|
5
5
|
| Router | `/bestest:go`, `/bestest:status` (plugin command stubs → bestest-go/bestest-status skills) |
|
|
6
|
-
| Plugin root | `${CLAUDE_PLUGIN_ROOT}`, pre-rendered inside the command stubs; bootstrap records it as the `plugin:` line in STATE.md |
|
|
6
|
+
| Plugin root | `${CLAUDE_PLUGIN_ROOT}`, pre-rendered inside the command stubs; first-time bootstrap records it as the `plugin:` line in STATE.md — an existing line that resolves on disk wins |
|
|
7
7
|
| Planning mode | plan mode — read-only exploration before mutating anything |
|
|
8
8
|
| Todo tracking | TodoWrite — one entry per gate step or card |
|
|
9
9
|
| Structured user questions | AskUserQuestion — batch weight≥4 decisions into one call |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
| Concept | Native here |
|
|
4
4
|
|---|---|
|
|
5
5
|
| Router | `$bestest-go` / `$bestest-status` skill mentions (or implicit trigger by description) |
|
|
6
|
-
| Plugin root | newest dir from `ls -d ~/.codex/plugins/cache/*/bestest/*` — bootstrap records it as the `plugin:` line in STATE.md (hooks also get `${CLAUDE_PLUGIN_ROOT}` env) |
|
|
6
|
+
| Plugin root | newest dir from `ls -d ~/.codex/plugins/cache/*/bestest/*` — first-time bootstrap records it as the `plugin:` line in STATE.md; an existing line that resolves on disk wins (hooks also get `${CLAUDE_PLUGIN_ROOT}` env) |
|
|
7
7
|
| Planning mode | `/plan` |
|
|
8
8
|
| Todo tracking | built-in plan/update_plan facility |
|
|
9
9
|
| Structured user questions | plain chat — one decision per message, options lettered |
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# DESIGN — <project> visual contract
|
|
2
|
+
<!-- Written by the design skill (P0–P2), frozen at P2: its sha256 joins
|
|
3
|
+
.bestest/LOCKS beside the SPEC hash (lock-guard then blocks edits).
|
|
4
|
+
Amendment = D-ID → shell-gate edit → re-hash, same ceremony as the SPEC.
|
|
5
|
+
trace.sh gates: covers: R-IDs real in SPEC · every section filled · hex
|
|
6
|
+
only in Tokens/Contrast pairs · Motion rows numeric · contrast pairs
|
|
7
|
+
≥4.5:1 (3:1 with "— AA-large") · each covers: R-ID needs a design-bearing
|
|
8
|
+
card (--plan) and rendered UAT evidence (--all).
|
|
9
|
+
Section headers are matched verbatim — do not rename them.
|
|
10
|
+
Guidance lives in comments; leave a section empty until it is real. -->
|
|
11
|
+
covers: <comma-separated R-N.M this contract governs>
|
|
12
|
+
|
|
13
|
+
## Direction
|
|
14
|
+
<!-- - reference: ONE specific object ("a 1970s graduate lecture handout"),
|
|
15
|
+
never adjectives — a reference describes a point, adjectives a region.
|
|
16
|
+
- signature: one element that could only exist for THIS product.
|
|
17
|
+
- banned defaults: >=3 nearest default looks, named and rejected
|
|
18
|
+
(e.g. cream + high-contrast serif + terracotta accent; near-black +
|
|
19
|
+
single acid-green accent; broadsheet hairline rules). -->
|
|
20
|
+
|
|
21
|
+
## Tokens
|
|
22
|
+
<!-- The ONLY home for raw hex/px/font values. 4–6 named colors with roles;
|
|
23
|
+
names evoke the world ("ink", "parchment"), not the template ("gray-700").
|
|
24
|
+
| token | value | role |
|
|
25
|
+
Plus: spacing unit · radius scale (nested: child <= parent; concentric:
|
|
26
|
+
outer = inner + padding) · type family / scale ratio / weights. -->
|
|
27
|
+
|
|
28
|
+
## Contrast pairs
|
|
29
|
+
<!-- Every text-bearing fg/bg pair, one per line, exact grammar:
|
|
30
|
+
- #RRGGBB on #RRGGBB
|
|
31
|
+
- #RRGGBB on #RRGGBB — AA-large (>=24px, or bold >=19px)
|
|
32
|
+
trace.sh computes WCAG ratios from these lines (python3). -->
|
|
33
|
+
|
|
34
|
+
## Components
|
|
35
|
+
<!-- Per-component specs referencing {tokens} only — raw hex here fails trace.
|
|
36
|
+
e.g. button-primary: bg {ink} · text {parchment} · radius {r1} · 36px h
|
|
37
|
+
Component sizes/paddings may cite the spacing unit. -->
|
|
38
|
+
|
|
39
|
+
## Motion
|
|
40
|
+
<!-- One row per animated element; "none" is a valid, honest contract row.
|
|
41
|
+
Keep the header row — trace.sh skips it and the |---| separator, then
|
|
42
|
+
demands numeric ms + a named easing (ease*/linear/cubic-bezier/spring)
|
|
43
|
+
on every other row. Values come from the design skill's motion canon.
|
|
44
|
+
| element | trigger | duration | easing | notes |
|
|
45
|
+
|---|---|---|---|---|
|
|
46
|
+
| modal | open | 240 ms | ease-out | scale 0.95→1 + opacity | -->
|
|
47
|
+
|
|
48
|
+
## Do / Don't
|
|
49
|
+
<!-- >=3 each, testable phrasing ("Don't use bold anywhere; body stays 400/500",
|
|
50
|
+
not "keep it clean"). The plan-checker blocks vibes here. -->
|
|
51
|
+
|
|
52
|
+
## Responsive
|
|
53
|
+
<!-- Breakpoints + what reflows at each; no horizontal scroll at any declared
|
|
54
|
+
breakpoint (review rule). Touch targets >=44px below the pointer break. -->
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# DISCOVERED — out-of-blast-radius work
|
|
2
2
|
<!-- Never fixed silently, never dropped. One line per item, appended when found:
|
|
3
3
|
- <summary> | discovered-from: T-## | blocks: <T-## or none>
|
|
4
|
+
Deliberate ceilings marked in code ('bestest-defer: <ceiling> until <trigger>')
|
|
5
|
+
get a line too — trace.sh --all fails trigger-less or unharvested markers:
|
|
6
|
+
- defer: <ceiling> | discovered-from: T-## | marker: <file>
|
|
4
7
|
At P5 ship every line gains a disposition (trace.sh --all fails bare lines):
|
|
5
8
|
| disposition: fix-now / deferred to <where> / wontfix because <reason>
|
|
6
9
|
Survives milestone rollover; deferred lines seed the next interrogation. -->
|
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
## Complexity justification
|
|
15
15
|
<!-- every design element beyond the simplest thing satisfying the R-IDs gets a
|
|
16
16
|
row — no row means the plan-checker counts it as a blocker:
|
|
17
|
-
| Complexity | Why needed |
|
|
17
|
+
| Complexity | Why needed | Next-simpler rung rejected (reuse / stdlib / platform / installed dep) because |
|
|
18
18
|
|---|---|---| -->
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
<!-- one paragraph: the real problem, for whom, why now, why not an existing tool.
|
|
7
7
|
Every factual claim tagged [user] / [cited:URL] / [assumed].
|
|
8
8
|
Knowledge deliverable, nothing ships: add a 'deliverable: findings' line —
|
|
9
|
-
R-IDs become questions, P3-P4 are skipped (research references/findings.md).
|
|
9
|
+
R-IDs become questions, P3-P4 are skipped (research references/findings.md).
|
|
10
|
+
Visible interface: the design skill produces .bestest/DESIGN.md, frozen
|
|
11
|
+
beside this SPEC; its covers: line names the UI R-IDs from §2. -->
|
|
10
12
|
|
|
11
13
|
## 2. Requirements — EARS acceptance criteria
|
|
12
14
|
<!-- one sentence each, numbered R-N.M, observable behavior only:
|
package/payload/templates/UAT.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# UAT — one question per acceptance criterion
|
|
2
2
|
<!-- Filled at P5. One row per R-N.M from SPEC §2. The user answers the question;
|
|
3
|
-
'pass' requires their yes plus the evidence pointer.
|
|
3
|
+
'pass' requires their yes plus the evidence pointer. R-IDs named by a
|
|
4
|
+
DESIGN.md covers: line need a screenshot/recording path as evidence —
|
|
5
|
+
trace.sh --all fails prose-only UI rows. -->
|
|
4
6
|
|
|
5
7
|
| R-ID | question to user (restates the EARS criterion as a check) | evidence | result |
|
|
6
8
|
|------|-----------------------------------------------------------|----------|--------|
|
|
@@ -8,6 +8,9 @@ weight: 3 # irreversibility x scope; >=4 -> full adversarial revie
|
|
|
8
8
|
complexity: 3 # 1 + 2/extra file + 2/verify cmd + 3 if title needs "and" + 2/new interface; >6 split
|
|
9
9
|
blocked_by: none # comma-separated T-IDs
|
|
10
10
|
may_edit_tests: false # true only on test-author cards (lock-guard enforces)
|
|
11
|
+
design: none # .bestest/DESIGN.md when this card renders human-facing UI —
|
|
12
|
+
# the orchestrator hands that file to builder AND reviewer
|
|
13
|
+
# (ui-mode) with the card; trace.sh checks the cascade
|
|
11
14
|
verify:
|
|
12
15
|
- <command that proves this card done — orchestrator re-runs it>
|
|
13
16
|
---
|