@accidentally-awesome-labs/opencode-bestest 0.5.0 → 0.6.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/README.md +2 -2
- package/bin/init.ts +1 -1
- package/opencode-assets/agents/plan-checker.md +1 -18
- package/opencode-assets/agents/researcher.md +1 -10
- package/opencode-assets/agents/reviewer.md +1 -14
- package/package.json +1 -1
- package/payload/VERSION +1 -1
- package/payload/agents/plan-checker.md +1 -1
- package/payload/hooks/lock-guard.sh +9 -4
- package/payload/hooks/session-start.sh +44 -0
- package/payload/scripts/trace.sh +228 -16
- package/payload/skills/bestest-go/SKILL.md +9 -6
- package/payload/skills/bestest-go/references/quick.md +29 -0
- package/payload/skills/bestest-status/SKILL.md +4 -3
- package/payload/skills/build/SKILL.md +6 -6
- package/payload/skills/interrogate/SKILL.md +3 -3
- package/payload/skills/plan/SKILL.md +2 -2
- package/payload/skills/research/SKILL.md +5 -2
- package/payload/skills/research/references/findings.md +20 -0
- package/payload/skills/ship/SKILL.md +5 -5
- package/payload/skills/using-bestest/references/claude-code.md +2 -1
- package/payload/skills/using-bestest/references/codex.md +2 -1
- package/payload/skills/using-bestest/references/opencode.md +2 -1
- package/payload/templates/CODEBASE.md +26 -0
- package/payload/templates/DECISIONS.md +3 -1
- package/payload/templates/DISCOVERED.md +6 -0
- package/payload/templates/FINDINGS.md +14 -0
- package/payload/templates/LESSONS.md +5 -0
- package/payload/templates/PLAN.md +18 -0
- package/payload/templates/ROADMAP.md +21 -0
- package/payload/templates/RQ.md +19 -0
- package/payload/templates/SPEC.md +3 -1
- package/payload/templates/STATE.md +1 -0
- package/payload/templates/quick-card.md +22 -0
- package/payload/templates/report.md +5 -0
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ bunx @accidentally-awesome-labs/opencode-bestest init # or npx
|
|
|
12
12
|
`init` is idempotent (re-run it to update) and supports `--dry-run` and `--global` (skills/agents/commands into `~/.config/opencode/`). It:
|
|
13
13
|
|
|
14
14
|
- copies the lifecycle skills into `.opencode/skills/` (prefixed `bestest-*`)
|
|
15
|
-
- installs the plan-checker / researcher / reviewer agents and `/bestest-go` + `/bestest-status` commands
|
|
16
|
-
- copies the runtime payload (guard scripts, `trace.sh`, templates) to `.opencode/bestest/`
|
|
15
|
+
- installs the plan-checker / researcher / reviewer agents (pointer stubs — their canonical bodies ride the payload, so `--global` installs need a project `init` before the roles resolve) and `/bestest-go` + `/bestest-status` commands
|
|
16
|
+
- copies the runtime payload (guard scripts, `trace.sh`, templates, canonical agent bodies) to `.opencode/bestest/`
|
|
17
17
|
- wires `opencode.json`: the `@accidentally-awesome-labs/opencode-bestest` plugin (enforcement) and an `instructions` entry that passively injects `.bestest/.context.md` — the plugin-maintained digest of STATE + LOCKS + active card + DRIFT notice
|
|
18
18
|
|
|
19
19
|
Then open opencode and run `/bestest-go`.
|
package/bin/init.ts
CHANGED
|
@@ -60,7 +60,7 @@ for (const kind of ["agents", "commands"]) {
|
|
|
60
60
|
|
|
61
61
|
// 4. Runtime payload for project sessions: hooks (shim targets), trace.sh, templates.
|
|
62
62
|
if (!GLOBAL) {
|
|
63
|
-
for (const part of ["hooks", "scripts", "templates"]) {
|
|
63
|
+
for (const part of ["agents", "hooks", "scripts", "templates"]) {
|
|
64
64
|
doCopy(join(src, part), join(cwd, ".opencode", "bestest", part))
|
|
65
65
|
}
|
|
66
66
|
const version = existsSync(join(src, "VERSION")) ? readFileSync(join(src, "VERSION"), "utf8").trim() : "dev"
|
|
@@ -7,21 +7,4 @@ permission:
|
|
|
7
7
|
webfetch: deny
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
**Spec mode** (given SPEC.md): grade completeness, clarity, consistency, measurability, coverage, traceability. Every finding typed and cited:
|
|
13
|
-
- `[Gap]` — something the build will need that no section provides (asset, actor, failure path, data lifecycle).
|
|
14
|
-
- `[Ambiguity]` — a sentence two reasonable builders would implement differently. Quote it; say the two readings.
|
|
15
|
-
- `[Conflict]` — two statements that cannot both hold. Cite both R-IDs/sections.
|
|
16
|
-
- `[Assumption]` — a load-bearing `[assumed]` tag or an untagged claim with no `[user]`/`[cited:]` evidence.
|
|
17
|
-
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. Gaps and Conflicts are freeze-blockers.
|
|
18
|
-
|
|
19
|
-
**Plan mode** (given PLAN.md + cards + SPEC): hunt, in order:
|
|
20
|
-
1. R-IDs with no covering card; cards citing phantom R-IDs; orphan cards serving no R-ID.
|
|
21
|
-
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.
|
|
22
|
-
3. Zero-context violations: placeholders, "as discussed", missing signatures/paths, a card a fresh stranger couldn't execute.
|
|
23
|
-
4. Assets consumed but never produced (check `blocked_by:` ordering too).
|
|
24
|
-
5. Complexity Justification table: any structure beyond the simplest satisfying design without a row → blocker.
|
|
25
|
-
6. TDD pairing: implementer cards with `may_edit_tests: true`, or no failing-test card ahead of them.
|
|
26
|
-
|
|
27
|
-
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.
|
|
10
|
+
Read the file `agents/plan-checker.md` under the bestest plugin root — the `plugin:` line in this project's `.bestest/STATE.md` names that root (this harness: `.opencode/bestest`) — and follow it exactly for the task you were given. You are read-only: never modify any file.
|
|
@@ -8,13 +8,4 @@ permission:
|
|
|
8
8
|
bash: deny
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Method:
|
|
14
|
-
1. Read the RQ file you were given; note the answer shape it needs and which decision it feeds.
|
|
15
|
-
2. Search broadly, then fetch primary sources — official docs, changelogs, pricing pages, GitHub issues/releases — over blogs and search snippets. For version- or price-sensitive facts, find the date on the page.
|
|
16
|
-
For version-sensitive TOOL behavior, docs may describe an unreleased major: prefer running the pinned tool itself (`--help`, a scratch project) over reading about it, and cite the run.
|
|
17
|
-
3. Adversarially check each load-bearing claim: one honest attempt to refute it via a second independent source. Disagreement is a finding — report both sides, don't pick silently.
|
|
18
|
-
4. For dependency candidates, run SLOPCHECK: last release, issue trend, bus factor, install weight, license, "does the platform already do this?".
|
|
19
|
-
|
|
20
|
-
Write findings into the RQ file: each claim on its own line, tagged `[cited:URL]` (the URL you fetched, not the search result), or `[assumed]` if you genuinely could not verify — with what you tried. Finish with a ≤5-line summary: the answer, confidence, and what would change it. Your final message is just the RQ file path and that summary.
|
|
11
|
+
Read the file `agents/researcher.md` under the bestest plugin root — the `plugin:` line in this project's `.bestest/STATE.md` names that root (this harness: `.opencode/bestest`) — and follow it exactly for the research question you were given. Write only into `.bestest/research/`.
|
|
@@ -6,17 +6,4 @@ permission:
|
|
|
6
6
|
webfetch: deny
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Inputs: the card, the diff range, the report, SPEC.md, relevant D-IDs.
|
|
12
|
-
|
|
13
|
-
**Depth is risk-scaled by card `weight:`**
|
|
14
|
-
- **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).
|
|
15
|
-
- **weight < 4 — blockers-only:** correctness of the R-ID behavior, verify commands genuinely proving it, diff staying inside `files:`. No style opinions.
|
|
16
|
-
|
|
17
|
-
Always check, any weight:
|
|
18
|
-
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.
|
|
19
|
-
2. Report honesty: any claim whose evidence doesn't hold up = blocker, regardless of code quality.
|
|
20
|
-
3. `Bestest-Req:` trailer present and citing the card's R-IDs.
|
|
21
|
-
|
|
22
|
-
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.
|
|
9
|
+
Read the file `agents/reviewer.md` under the bestest plugin root — the `plugin:` line in this project's `.bestest/STATE.md` names that root (this harness: `.opencode/bestest`) — and follow it exactly for the card you were given. Read-only on product code: run verify commands, never edit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accidentally-awesome-labs/opencode-bestest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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.6.0
|
|
@@ -12,7 +12,7 @@ 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. 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. `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.
|
|
@@ -95,10 +95,15 @@ esac
|
|
|
95
95
|
may_edit_tests="false"
|
|
96
96
|
card="$(grep -m1 -E '^card:' "$root/.bestest/STATE.md" 2>/dev/null | sed -E 's/^card:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
97
97
|
if [ -n "${card:-}" ] && [ -f "$root/$card" ]; then
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
case "${card##*/}" in
|
|
99
|
+
Q-*) ;; # quick lane: may_edit_tests is always false — a tampered grant must not count
|
|
100
|
+
*)
|
|
101
|
+
# frontmatter only — a mention of may_edit_tests in the card body must not count
|
|
102
|
+
if awk '/^---$/{n++; next} n==1' "$root/$card" | grep -m1 -Eq '^may_edit_tests:[[:space:]]*true'; then
|
|
103
|
+
may_edit_tests="true"
|
|
104
|
+
fi
|
|
105
|
+
;;
|
|
106
|
+
esac
|
|
102
107
|
fi
|
|
103
108
|
|
|
104
109
|
check_one_path() {
|
|
@@ -51,6 +51,12 @@ if [ -f "$b/SPEC.md" ]; then
|
|
|
51
51
|
echo "Autonomy contract in force: SPEC.md section 9 (PROCEED / INTERRUPT / GATED)."
|
|
52
52
|
fi
|
|
53
53
|
|
|
54
|
+
phase_cur="$(grep -m1 -E '^phase:' "$b/STATE.md" 2>/dev/null | sed -E 's/^phase:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
55
|
+
if [ "$phase_cur" = "done" ] || [ "$phase_cur" = "quick" ]; then
|
|
56
|
+
echo
|
|
57
|
+
echo "Post-ship contract: phase is done — this project's audit chain (gate log, Bestest-Req trailers) requires every new change, any size, to land through the quick lane (a Q-card per the router skill's references/quick.md; template and trace.sh --quick under the STATE plugin: root) or a milestone rollover. A direct untracked edit breaks the chain the shipped milestone was accepted on."
|
|
58
|
+
fi
|
|
59
|
+
|
|
54
60
|
if [ -f "$snap" ]; then
|
|
55
61
|
old_head="$(grep -m1 '^HEAD=' "$snap" | cut -d= -f2-)"
|
|
56
62
|
old_dirty="$(grep -m1 '^DIRTY=' "$snap" | cut -d= -f2-)"
|
|
@@ -60,4 +66,42 @@ if [ -f "$snap" ]; then
|
|
|
60
66
|
fi
|
|
61
67
|
fi
|
|
62
68
|
|
|
69
|
+
# STALE-STATE: the injected STATE is only as good as its last rewrite. If product
|
|
70
|
+
# code moved >= STALE_N commits past it, the phase/card/next-action above may lie.
|
|
71
|
+
# Every probe fails silent (no git, never-committed STATE, dirty STATE = just touched).
|
|
72
|
+
STALE_N=5
|
|
73
|
+
state_c="$(git -C "$root" log -1 --format=%H -- .bestest/STATE.md 2>/dev/null || true)"
|
|
74
|
+
state_dirty="$(git -C "$root" status --porcelain -- .bestest/STATE.md 2>/dev/null || true)"
|
|
75
|
+
if [ -n "$state_c" ] && [ -z "$state_dirty" ]; then
|
|
76
|
+
behind="$(git -C "$root" rev-list --count "$state_c..HEAD" -- . ':(exclude).bestest' 2>/dev/null || echo 0)"
|
|
77
|
+
if [ "${behind:-0}" -ge "$STALE_N" ] 2>/dev/null; then
|
|
78
|
+
echo
|
|
79
|
+
echo "STALE-STATE: $behind product commits since STATE.md was last rewritten. The injected phase/card/next-action above may be stale — re-derive them (and Open interrupts) from git log, plans/*.md status, and reports/, rewrite STATE.md, commit, then continue."
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# DECISIONS revisit scan: surface (never act on) waiver/risk lines whose
|
|
84
|
+
# 'revisit' date has arrived. Quieted by an appended 'D-0NN revisited <date>: ...'
|
|
85
|
+
# line — DECISIONS stays append-only. ISO dates compare lexicographically.
|
|
86
|
+
if [ -f "$b/DECISIONS.md" ]; then
|
|
87
|
+
today="$(date +%Y-%m-%d 2>/dev/null || true)"
|
|
88
|
+
if [ -n "$today" ]; then
|
|
89
|
+
due=""
|
|
90
|
+
while IFS= read -r ln; do
|
|
91
|
+
d="$(printf '%s' "$ln" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' | head -1)"
|
|
92
|
+
[ -n "$d" ] || continue
|
|
93
|
+
[ "$d" \> "$today" ] && continue
|
|
94
|
+
did="$(printf '%s' "$ln" | grep -oE '(D|RISK)-[0-9]+' | head -1)"
|
|
95
|
+
if [ -n "$did" ] && grep -i 'revisited' "$b/DECISIONS.md" 2>/dev/null | grep -qE "(^|[^0-9])${did}([^0-9]|$)"; then continue; fi
|
|
96
|
+
due="${due}${ln}
|
|
97
|
+
"
|
|
98
|
+
done < <(grep -iE 'revisit' "$b/DECISIONS.md" 2>/dev/null | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' || true)
|
|
99
|
+
if [ -n "$due" ]; then
|
|
100
|
+
echo
|
|
101
|
+
echo "### DECISIONS revisit due (surface only — no auto-action; quiet each with an appended 'D-0NN revisited $today: <outcome>' line)"
|
|
102
|
+
printf '%s' "$due"
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
fi
|
|
106
|
+
|
|
63
107
|
exit 0
|
package/payload/scripts/trace.sh
CHANGED
|
@@ -12,18 +12,195 @@ b="$root/.bestest"
|
|
|
12
12
|
fails=0
|
|
13
13
|
fail() { fails=$((fails+1)); printf 'FAIL %02d: %s\n' "$fails" "$1"; }
|
|
14
14
|
front() { awk '/^---$/{n++; next} n==1' "$1"; } # frontmatter body of a card
|
|
15
|
+
rid_re() { printf '(^|[^0-9.])%s([^0-9]|$)' "$(printf '%s' "$1" | sed 's/\./\\./g')"; } # R-1.1 must not match R-1.10
|
|
16
|
+
section_filled() { awk -v s="## $2" '$0 ~ "^"s{f=1;next} /^## /{f=0} f&&/^[[:space:]]*<!--/{next} f&&NF{c++} END{exit c?0:1}' "$1"; }
|
|
17
|
+
check_spikes() { # every spike: block in a research RQ file must carry a disposition:
|
|
18
|
+
for rq in "$b"/research/RQ-*.md; do
|
|
19
|
+
[ -f "$rq" ] || continue
|
|
20
|
+
if grep -qE '^spike:' "$rq" && ! grep -qE '^disposition:' "$rq"; then
|
|
21
|
+
fail "$(basename "$rq") has a spike: block without a disposition: line"
|
|
22
|
+
fi
|
|
23
|
+
done
|
|
24
|
+
}
|
|
25
|
+
check_discovered() { # every DISCOVERED entry needs a disposition by ship
|
|
26
|
+
[ -f "$b/DISCOVERED.md" ] || return 0
|
|
27
|
+
while IFS= read -r line; do
|
|
28
|
+
printf '%s' "$line" | grep -q 'disposition:' \
|
|
29
|
+
|| fail "DISCOVERED entry lacks disposition: ${line%%|*}"
|
|
30
|
+
done < <(grep -E '^- ' "$b/DISCOVERED.md")
|
|
31
|
+
}
|
|
32
|
+
check_roadmap() { # check_roadmap <1 to also require a verdict on the current milestone's ledger line>
|
|
33
|
+
ms_cur="$(grep -m1 -E '^milestone:' "$b/STATE.md" 2>/dev/null | sed -E 's/^milestone:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]+$//')"
|
|
34
|
+
if [ ! -f "$b/ROADMAP.md" ]; then
|
|
35
|
+
fail "no $b/ROADMAP.md — copy templates/ROADMAP.md and append this milestone's intent line"
|
|
36
|
+
return 0
|
|
37
|
+
fi
|
|
38
|
+
[ "$(wc -l < "$b/ROADMAP.md" | tr -d ' ')" -le 40 ] || fail "ROADMAP.md exceeds its 40-line cap — compress old ledger lines"
|
|
39
|
+
[ -n "${ms_cur:-}" ] || return 0
|
|
40
|
+
ml="$(grep -E "^[[:space:]]*$ms_cur[[:space:]]*\|" "$b/ROADMAP.md" | head -1)"
|
|
41
|
+
if [ -z "$ml" ]; then
|
|
42
|
+
fail "ROADMAP.md has no ledger line for milestone $ms_cur (append: '$ms_cur | intent: <one clause>')"
|
|
43
|
+
elif [ "$1" = 1 ]; then
|
|
44
|
+
printf '%s' "$ml" | grep -q 'verdict:' || fail "ROADMAP.md ledger line for $ms_cur lacks a verdict — complete it before go/no-go"
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
15
47
|
|
|
16
48
|
[ -f "$b/SPEC.md" ] || { echo "FAIL 01: no $b/SPEC.md — nothing to trace"; exit 1; }
|
|
17
49
|
|
|
18
50
|
rids="$(grep -oE 'R-[0-9]+\.[0-9]+' "$b/SPEC.md" | sort -u)"
|
|
19
51
|
[ -n "$rids" ] || fail "SPEC.md defines no R-N.M acceptance criteria"
|
|
20
52
|
|
|
53
|
+
# --- quick-lane checks (--quick): Q-cards only, then exit --------------------
|
|
54
|
+
if [ "$mode" = "--quick" ]; then
|
|
55
|
+
# tamper canary: the quick lane never amends the SPEC
|
|
56
|
+
lh="$(grep -m1 -E '^hash [0-9a-f]+ \.bestest/SPEC\.md' "$b/LOCKS" 2>/dev/null | awk '{print $2}')"
|
|
57
|
+
if [ -n "${lh:-}" ]; then
|
|
58
|
+
if command -v sha256sum >/dev/null 2>&1; then ch="$(sha256sum "$b/SPEC.md" | cut -d' ' -f1)"
|
|
59
|
+
else ch="$(shasum -a 256 "$b/SPEC.md" | cut -d' ' -f1)"; fi
|
|
60
|
+
[ "$lh" = "$ch" ] || fail "SPEC.md no longer matches its LOCKS hash — the quick lane never amends the SPEC"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
qcards="$(ls "$b"/plans/Q-*.md 2>/dev/null || true)"
|
|
64
|
+
[ -n "$qcards" ] || fail "no quick cards in $b/plans/"
|
|
65
|
+
qn="$(printf '%s\n' "$qcards" | grep -c . || true)"
|
|
66
|
+
[ "$qn" -gt 5 ] && fail "$qn quick cards since last rollover — this is a milestone; run rollover"
|
|
67
|
+
manifests='package.json package-lock.json pnpm-lock.yaml yarn.lock bun.lockb Cargo.toml Cargo.lock go.mod go.sum pyproject.toml requirements.txt requirements-dev.txt Gemfile Gemfile.lock pom.xml build.gradle build.gradle.kts composer.json composer.lock'
|
|
68
|
+
|
|
69
|
+
for qc in $qcards; do
|
|
70
|
+
qid="$(basename "$qc" .md)"
|
|
71
|
+
qfm="$(front "$qc")"
|
|
72
|
+
rlist=""
|
|
73
|
+
|
|
74
|
+
printf '%s' "$qfm" | grep -Eq '^may_edit_tests:[[:space:]]*false' \
|
|
75
|
+
|| fail "$qid may_edit_tests must be false on the quick lane"
|
|
76
|
+
|
|
77
|
+
qfiles="$(printf '%s' "$qfm" | grep -E '^files:' | head -1 | sed 's/^files:[[:space:]]*//; s/[[:space:]]*#.*$//' | tr ',' '\n' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' | grep -v '^$' || true)"
|
|
78
|
+
nq="$(printf '%s\n' "$qfiles" | grep -c . || true)"
|
|
79
|
+
{ [ "$nq" -ge 1 ] && [ "$nq" -le 3 ]; } || fail "$qid files: must list 1-3 paths (found $nq)"
|
|
80
|
+
|
|
81
|
+
qreq="$(printf '%s' "$qfm" | grep -E '^requirements:' | head -1 | sed 's/^requirements:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]*$//')"
|
|
82
|
+
case "$qreq" in
|
|
83
|
+
none|refactor) : ;;
|
|
84
|
+
*) rlist="$(printf '%s' "$qreq" | grep -oE 'R-[0-9]+\.[0-9]+' || true)"
|
|
85
|
+
[ -n "$rlist" ] || fail "$qid requirements: must be none, refactor, or the R-IDs it restores"
|
|
86
|
+
for r in $rlist; do
|
|
87
|
+
printf '%s\n' "$rids" | grep -qx "$r" || fail "$qid cites $r which is not in SPEC.md"
|
|
88
|
+
done ;;
|
|
89
|
+
esac
|
|
90
|
+
|
|
91
|
+
qdid="$(printf '%s' "$qfm" | grep -E '^decision:' | grep -oE 'D-[0-9]+' | head -1)"
|
|
92
|
+
if [ -n "${qdid:-}" ]; then
|
|
93
|
+
grep -q "$qdid" "$b/DECISIONS.md" 2>/dev/null || fail "$qid decision $qdid not found in DECISIONS.md"
|
|
94
|
+
else
|
|
95
|
+
fail "$qid missing decision: D-### field"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
qstart="$(printf '%s' "$qfm" | grep -E '^start:' | head -1 | sed 's/^start:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]*$//')"
|
|
99
|
+
changed=""
|
|
100
|
+
if git -C "$root" rev-parse -q --verify "$qstart^{commit}" >/dev/null 2>&1; then
|
|
101
|
+
changed="$( { git -C "$root" diff --name-only "$qstart"..HEAD; git -C "$root" status --porcelain | awk '{print $NF}'; } 2>/dev/null | grep -v '^\.bestest/' | sort -u || true)"
|
|
102
|
+
while IFS= read -r chp; do
|
|
103
|
+
[ -n "$chp" ] || continue
|
|
104
|
+
printf '%s\n' "$qfiles" | grep -qxF -- "$chp" || fail "$qid touched $chp outside its files: list — escalate (status: escalated + DISCOVERED line)"
|
|
105
|
+
done <<QEOF
|
|
106
|
+
$changed
|
|
107
|
+
QEOF
|
|
108
|
+
else
|
|
109
|
+
fail "$qid start: sha does not resolve"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# neither declared files nor actual changes may hit locked paths or manifests
|
|
113
|
+
for p in $(printf '%s\n%s\n' "$qfiles" "$changed" | grep -v '^$' | sort -u); do
|
|
114
|
+
pb="$(basename "$p")"
|
|
115
|
+
for m in $manifests; do
|
|
116
|
+
[ "$pb" = "$m" ] && fail "$qid touches dependency manifest $p — that is a milestone, not a quick fix"
|
|
117
|
+
done
|
|
118
|
+
[ "$p" = ".bestest/LOCKS" ] && fail "$qid touches the lock registry"
|
|
119
|
+
if [ -f "$b/LOCKS" ]; then
|
|
120
|
+
while IFS= read -r line; do
|
|
121
|
+
kind="${line%% *}"
|
|
122
|
+
case "$kind" in
|
|
123
|
+
hash) hp="$(printf '%s' "$line" | awk '{print $3}')"
|
|
124
|
+
[ "$p" = "$hp" ] && fail "$qid touches hash-locked $p" ;;
|
|
125
|
+
glob) pat="$(printf '%s' "$line" | cut -d' ' -f2-)"
|
|
126
|
+
case "$p" in $pat) fail "$qid touches glob-locked $p — a fix needing test edits is a milestone" ;; esac ;;
|
|
127
|
+
esac
|
|
128
|
+
done < "$b/LOCKS"
|
|
129
|
+
fi
|
|
130
|
+
done
|
|
131
|
+
|
|
132
|
+
qstatus="$(printf '%s' "$qfm" | grep -E '^status:' | head -1 | grep -oE 'doing|done|escalated' | head -1)"
|
|
133
|
+
case "${qstatus:-}" in
|
|
134
|
+
doing) : ;;
|
|
135
|
+
done)
|
|
136
|
+
qrep="$b/reports/$qid.md"
|
|
137
|
+
if [ ! -f "$qrep" ]; then
|
|
138
|
+
fail "$qid is done but report $qrep is missing"
|
|
139
|
+
else
|
|
140
|
+
section_filled "$qrep" FRICTION || fail "$qid report has empty FRICTION section (write 'None' if truly none)"
|
|
141
|
+
section_filled "$qrep" Lessons || fail "$qid report has empty Lessons section (list the LESSONS.md lines appended, or 'None')"
|
|
142
|
+
if [ "$qreq" = refactor ]; then
|
|
143
|
+
section_filled "$qrep" 'Verify output' || fail "$qid refactor card needs the green incumbent-suite run pasted in Verify output"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
git -C "$root" log -E --grep="Bestest-Req:.*$qid([^0-9]|\$)" --oneline -1 2>/dev/null | grep -q . \
|
|
147
|
+
|| fail "$qid has no commit with trailer 'Bestest-Req: $qid'"
|
|
148
|
+
if [ -n "$rlist" ]; then
|
|
149
|
+
for r in $rlist; do
|
|
150
|
+
grep -E "$(rid_re "$r")" "$b/UAT.md" 2>/dev/null | grep -Eq "requick|$qid" \
|
|
151
|
+
|| fail "$r restored by $qid needs a requick row in UAT.md"
|
|
152
|
+
done
|
|
153
|
+
fi
|
|
154
|
+
;;
|
|
155
|
+
escalated)
|
|
156
|
+
grep -q "discovered-from: $qid" "$b/DISCOVERED.md" 2>/dev/null \
|
|
157
|
+
|| fail "$qid escalated without a DISCOVERED.md line (discovered-from: $qid)"
|
|
158
|
+
;;
|
|
159
|
+
*) fail "$qid status must be doing | done | escalated" ;;
|
|
160
|
+
esac
|
|
161
|
+
done
|
|
162
|
+
|
|
163
|
+
if [ "$fails" -eq 0 ]; then
|
|
164
|
+
echo "PASS: $qn quick cards, chain clean (--quick)"
|
|
165
|
+
exit 0
|
|
166
|
+
fi
|
|
167
|
+
exit 1
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# --- findings-terminal checks (--findings): no cards, the deliverable is FINDINGS.md
|
|
171
|
+
if [ "$mode" = "--findings" ]; then
|
|
172
|
+
check_roadmap 1
|
|
173
|
+
check_spikes
|
|
174
|
+
check_discovered
|
|
175
|
+
[ -f "$b/FINDINGS.md" ] || fail "no $b/FINDINGS.md (template: FINDINGS.md)"
|
|
176
|
+
[ -f "$b/UAT.md" ] || fail "no $b/UAT.md"
|
|
177
|
+
for r in $rids; do
|
|
178
|
+
rq_ok=no
|
|
179
|
+
for rq in "$b"/research/RQ-*.md; do
|
|
180
|
+
[ -f "$rq" ] || continue
|
|
181
|
+
if grep -Eq "$(rid_re "$r")" "$rq" && grep -qE '^verdict:' "$rq" && grep -q '\[cited:' "$rq"; then
|
|
182
|
+
rq_ok=yes; break
|
|
183
|
+
fi
|
|
184
|
+
done
|
|
185
|
+
[ "$rq_ok" = yes ] || fail "$r has no research RQ file with a cited verdict"
|
|
186
|
+
if [ -f "$b/FINDINGS.md" ]; then
|
|
187
|
+
grep -Eq "$(rid_re "$r")" "$b/FINDINGS.md" || fail "$r missing from FINDINGS.md"
|
|
188
|
+
fi
|
|
189
|
+
if [ -f "$b/UAT.md" ]; then
|
|
190
|
+
grep -Eq "$(rid_re "$r")" "$b/UAT.md" || fail "$r missing from UAT.md"
|
|
191
|
+
fi
|
|
192
|
+
done
|
|
193
|
+
if [ "$fails" -eq 0 ]; then
|
|
194
|
+
echo "PASS: $(printf '%s\n' "$rids" | grep -c .) findings requirements, chain clean (--findings)"
|
|
195
|
+
exit 0
|
|
196
|
+
fi
|
|
197
|
+
exit 1
|
|
198
|
+
fi
|
|
199
|
+
|
|
21
200
|
cards="$(ls "$b"/plans/T-*.md 2>/dev/null || true)"
|
|
22
201
|
[ -n "$cards" ] || fail "no task cards in $b/plans/"
|
|
23
202
|
|
|
24
203
|
# --- plan-level checks -------------------------------------------------------
|
|
25
|
-
rid_re() { printf '(^|[^0-9.])%s([^0-9]|$)' "$(printf '%s' "$1" | sed 's/\./\\./g')"; } # R-1.1 must not match R-1.10
|
|
26
|
-
|
|
27
204
|
for r in $rids; do
|
|
28
205
|
covered=no
|
|
29
206
|
for c in $cards; do
|
|
@@ -60,13 +237,42 @@ for c in $cards; do
|
|
|
60
237
|
[ "$bigger" -ge 7 ] && fail "$name complexity $bigger >= 7 — split it (target <= 5)"
|
|
61
238
|
done
|
|
62
239
|
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
240
|
+
# ROADMAP: direction artifact — intent line by P3, verdict by P5, 40-line cap
|
|
241
|
+
rv=0; [ "$mode" = "--all" ] && rv=1
|
|
242
|
+
check_roadmap "$rv"
|
|
243
|
+
|
|
244
|
+
# PLAN.md index <-> plans/ card set, both ways (the amendment cascade patches the
|
|
245
|
+
# plan index together with the cards; cuts live in the amendment D-ID, not here)
|
|
246
|
+
if [ -f "$b/PLAN.md" ]; then
|
|
247
|
+
plan_ids="$(grep -oE 'T-[0-9]+' "$b/PLAN.md" | sort -u)"
|
|
248
|
+
for c in $cards; do
|
|
249
|
+
id="$(basename "$c" .md)"
|
|
250
|
+
printf '%s\n' "$plan_ids" | grep -qx "$id" || fail "PLAN.md index missing $id — the amendment cascade patches the plan, not just cards"
|
|
251
|
+
done
|
|
252
|
+
for id in $plan_ids; do
|
|
253
|
+
[ -f "$b/plans/$id.md" ] || fail "PLAN.md cites $id but $b/plans/$id.md does not exist (cuts live in the amendment D-ID; drop them from the index)"
|
|
254
|
+
done
|
|
255
|
+
else
|
|
256
|
+
fail "no $b/PLAN.md (card index + rationale; template: PLAN.md)"
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# CODEBASE.md must postdate the last milestone rollover — it is cited as fact
|
|
260
|
+
# at re-interrogation. Skipped when uncommitted (just regenerated) or pre-rollover.
|
|
261
|
+
if [ -d "$b/milestones" ]; then
|
|
262
|
+
if [ ! -f "$b/CODEBASE.md" ]; then
|
|
263
|
+
fail "no $b/CODEBASE.md after rollover — regenerate it (bestest-go rollover step 4)"
|
|
264
|
+
else
|
|
265
|
+
cb_t="$(git -C "$root" log -1 --format=%ct -- .bestest/CODEBASE.md 2>/dev/null)"
|
|
266
|
+
ms_t="$(git -C "$root" log -1 --format=%ct -- .bestest/milestones 2>/dev/null)"
|
|
267
|
+
cb_dirty="$(git -C "$root" status --porcelain -- .bestest/CODEBASE.md 2>/dev/null)"
|
|
268
|
+
if [ -n "$cb_t" ] && [ -n "$ms_t" ] && [ -z "$cb_dirty" ] && [ "$cb_t" -lt "$ms_t" ]; then
|
|
269
|
+
fail "CODEBASE.md predates the last milestone rollover — regenerate it (bestest-go rollover step 4)"
|
|
270
|
+
fi
|
|
68
271
|
fi
|
|
69
|
-
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
# spikes: a spike: block in a research RQ file must carry a disposition: by P3
|
|
275
|
+
check_spikes
|
|
70
276
|
|
|
71
277
|
# --- full-chain checks (--all) -----------------------------------------------
|
|
72
278
|
if [ "$mode" = "--all" ]; then
|
|
@@ -76,8 +282,19 @@ if [ "$mode" = "--all" ]; then
|
|
|
76
282
|
rep="$b/reports/$id.md"
|
|
77
283
|
if [ ! -f "$rep" ]; then
|
|
78
284
|
fail "$id is done but $rep is missing"
|
|
79
|
-
|
|
80
|
-
|
|
285
|
+
else
|
|
286
|
+
section_filled "$rep" FRICTION \
|
|
287
|
+
|| fail "$id report has empty FRICTION section (write 'None' if truly none)"
|
|
288
|
+
# Lessons propagation: every '- ' line the report claims was appended must
|
|
289
|
+
# actually be in LESSONS.md (substring match survives P5 curation merges).
|
|
290
|
+
if section_filled "$rep" Lessons; then
|
|
291
|
+
while IFS= read -r ln; do
|
|
292
|
+
grep -qF -- "$ln" "$b/LESSONS.md" 2>/dev/null \
|
|
293
|
+
|| fail "$id Lessons line not in LESSONS.md: $ln"
|
|
294
|
+
done < <(awk '/^## Lessons/{f=1;next} /^## /{f=0} f&&/^-[[:space:]]/' "$rep")
|
|
295
|
+
else
|
|
296
|
+
fail "$id report has empty Lessons section (list the LESSONS.md lines appended, or 'None')"
|
|
297
|
+
fi
|
|
81
298
|
fi
|
|
82
299
|
done
|
|
83
300
|
|
|
@@ -91,12 +308,7 @@ if [ "$mode" = "--all" ]; then
|
|
|
91
308
|
fi
|
|
92
309
|
done
|
|
93
310
|
|
|
94
|
-
|
|
95
|
-
while IFS= read -r line; do
|
|
96
|
-
printf '%s' "$line" | grep -q 'disposition:' \
|
|
97
|
-
|| fail "DISCOVERED entry lacks disposition: ${line%%|*}"
|
|
98
|
-
done < <(grep -E '^- ' "$b/DISCOVERED.md")
|
|
99
|
-
fi
|
|
311
|
+
check_discovered
|
|
100
312
|
fi
|
|
101
313
|
|
|
102
314
|
if [ "$fails" -eq 0 ]; then
|
|
@@ -5,11 +5,11 @@ description: Use when routing a bestest project to its lifecycle phase — boots
|
|
|
5
5
|
|
|
6
6
|
# bestest-go — lifecycle router
|
|
7
7
|
|
|
8
|
-
1. Read `.bestest/STATE.md`. If its `plugin:` path is missing on disk (harness switched), re-resolve per the harness map (using-bestest `references/<harness>.md`) and rewrite that line before anything else. If missing: `mkdir -p .bestest/plans .bestest/reports .bestest/research`, copy `templates/STATE.md` from the plugin root into `.bestest
|
|
9
|
-
**Brownfield check** — the repo already contains product code (real source or git history, not scaffolding)? Then before interrogating: (a) dispatch one read-only subagent to write `.bestest/CODEBASE.md
|
|
8
|
+
1. Read `.bestest/STATE.md`. If its `plugin:` path is missing on disk (harness switched), re-resolve per the harness map (using-bestest `references/<harness>.md`) and rewrite that line before anything else. If missing: `mkdir -p .bestest/plans .bestest/reports .bestest/research`, copy `templates/STATE.md`, `ROADMAP.md`, `LESSONS.md` and `DISCOVERED.md` from the plugin root into `.bestest/`, set `phase: P0`, `milestone: v1` and `plugin: <plugin root>` — the absolute directory containing the plugin's `skills/`, `templates/`, `scripts/`; the invoking command passes it pre-rendered where the harness supports that, otherwise resolve per the harness map (using-bestest `references/<harness>.md`). Skills resolve `trace.sh` and templates through this line. Append `.bestest/.session-snapshot` to the project's `.gitignore`, commit.
|
|
9
|
+
**Brownfield check** — the repo already contains product code (real source or git history, not scaffolding)? Then before interrogating: (a) dispatch one read-only subagent to write `.bestest/CODEBASE.md` (template: CODEBASE.md — every claim path-cited, red baseline verbatim); (b) seed `.bestest/LOCKS` via explicit shell commands with one `glob` line per existing test directory — incumbent tests are immutable to implementers from day one; pre-existing failures become RISK entries in DECISIONS.md and no card `verify:` may expect them green — adopting one into scope is a `may_edit_tests: true` card plus a D-ID; (c) interrogation treats CODEBASE.md as context and existing behavior as `[cited:path]` fact, not something to re-ask the user.
|
|
10
10
|
Then load the **interrogate** skill and begin Stage 0 with the user's idea (ask for it if none was given).
|
|
11
11
|
|
|
12
|
-
2. If `phase:
|
|
12
|
+
2. If `phase: quick`: resume the Q-card per `references/quick.md`. If `phase: done` and new work arrives: below-SPEC fixes, shipped-behavior restorations, and ≤3-file behavior-preserving refactors take the quick lane (`references/quick.md`); anything larger runs **Milestone rollover** below.
|
|
13
13
|
|
|
14
14
|
3. Otherwise route on `phase:` — load the named skill and resume exactly at `stage:` / `card:`:
|
|
15
15
|
|
|
@@ -21,17 +21,20 @@ description: Use when routing a bestest project to its lifecycle phase — boots
|
|
|
21
21
|
| P3 | plan | plan-checker PASS (≤3 loops) + `trace.sh --plan` clean + one-screen user approval |
|
|
22
22
|
| P4 | build | every card done: diff-scope clean, verify re-run, review closed |
|
|
23
23
|
| P5 | ship | UAT per R-ID + `trace.sh --all` clean + DISCOVERED dispositioned + user go/no-go |
|
|
24
|
+
| quick | this skill, `references/quick.md` | `trace.sh --quick` PASS → `phase: done`, gate logged |
|
|
25
|
+
|
|
26
|
+
Findings deliverable (`deliverable: findings` in SPEC): P2 freeze → `phase: P5`, skip logged; gate `trace.sh --findings` (research `references/findings.md`).
|
|
24
27
|
|
|
25
28
|
4. On gate pass: update STATE.md (phase, next action, gate log line, and **re-derive Open interrupts from scratch** — an answered interrupt left standing misroutes the next session), commit `.bestest/`, announce the phase transition in one sentence, continue.
|
|
26
29
|
|
|
27
30
|
## Milestone rollover (P5 shipped → next milestone)
|
|
28
31
|
|
|
29
32
|
All via explicit shell gate steps (LOCKS/SPEC are hook-frozen against file edits):
|
|
30
|
-
1. `N` = STATE `milestone:` (default v1). `mkdir -p .bestest/milestones/N` and `git mv` SPEC.md, PLAN.md, UAT.md, RUNBOOK.md, plans/, reports/, research/ 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 stay live — history and
|
|
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.
|
|
31
34
|
2. Rewrite LOCKS dropping the SPEC `hash` line (the archived SPEC keeps its frozen copy); keep every test `glob` — incumbent tests stay immutable.
|
|
32
35
|
3. Fresh STATE.md from the template: `phase: P0`, `milestone: N+1`, same `plugin:` line. Commit `.bestest: roll over N -> N+1`.
|
|
33
|
-
4. Re-enter **interrogate** Stage 0 as brownfield: prior SPEC (`.bestest/milestones/N/SPEC.md`), the DISCOVERED backlog, and LESSONS are the opening context — the new idea is interrogated against what already ships
|
|
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.
|
|
34
37
|
|
|
35
|
-
Amending a frozen SPEC: new D-ID in DECISIONS.md → apply the edit via an explicit shell gate step → re-hash the `hash` line in LOCKS (the lock-guard block message points here). At P3+ the amendment cascades before the next dispatch: cut or patch every card citing a removed/changed R-ID (the amendment D-ID records the cuts), write cards for new R-IDs, re-run plan-checker card mode on touched cards and `trace.sh --plan` — both must pass; done cards citing amended R-IDs get their `verify:` re-run.
|
|
38
|
+
Amending a frozen SPEC: new D-ID in DECISIONS.md → apply the edit via an explicit shell gate step → re-hash the `hash` line in LOCKS (the lock-guard block message points here). At P3+ the amendment cascades before the next dispatch: cut or patch every card citing a removed/changed R-ID plus PLAN.md's index (the amendment D-ID records the cuts), write cards for new R-IDs, re-run plan-checker card mode on touched cards and `trace.sh --plan` — both must pass; done cards citing amended R-IDs get their `verify:` re-run.
|
|
36
39
|
|
|
37
40
|
Never skip a gate because the work "seems obvious" — gates are where the human front-loaded trust.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Quick lane — Q-cards
|
|
2
|
+
|
|
3
|
+
One card, no SPEC/PLAN above it. For work below SPEC visibility: a post-ship defect fix that *restores* shipped behavior, a tiny fix no R-ID describes, or a ≤3-file behavior-preserving refactor. Anything that would alter or create an R-ID's observable behavior is a milestone — never negotiate that boundary.
|
|
4
|
+
|
|
5
|
+
## Entry (only from `phase: done`)
|
|
6
|
+
1. Copy `templates/quick-card.md` (plugin root = the STATE.md `plugin:` line) to `.bestest/plans/Q-##.md`, next free number.
|
|
7
|
+
2. Fill the frontmatter: 1–3 `files:`; `requirements:` = `none`, the R-IDs the fix restores, or `refactor`; `start: $(git rev-parse HEAD)`.
|
|
8
|
+
3. Append the authorizing decision to DECISIONS.md — why this is below SPEC visibility, or which R-ID it restores — and set its D-ID in `decision:`.
|
|
9
|
+
4. Set STATE.md `phase: quick`, `stage: Q-##`, `card: .bestest/plans/Q-##.md`; commit `.bestest/`.
|
|
10
|
+
|
|
11
|
+
## Work rules
|
|
12
|
+
- Read LESSONS.md first; append what you learn. This is the lane's edge: milestone-earned facts serve a five-minute fix.
|
|
13
|
+
- All locks stand: frozen SPEC, test globs (`may_edit_tests` is clamped false on Q-cards — a fix that needs a test edit escalates), destructive-command guard, drift detection.
|
|
14
|
+
- Out-of-scope findings → one DISCOVERED.md line; never fixed here.
|
|
15
|
+
- Commit with trailer `Bestest-Req: Q-##`.
|
|
16
|
+
|
|
17
|
+
## Close — the whole ceremony, keep it minutes
|
|
18
|
+
1. Run every `verify:` command; write `.bestest/reports/Q-##.md` (claim→evidence, verify output, FRICTION, Lessons).
|
|
19
|
+
2. Restored R-IDs: one `requick` row per R-ID in UAT.md. Refactor: paste the green incumbent-suite run in the report's Verify output; no UAT row.
|
|
20
|
+
3. `"$PLUGIN"/scripts/trace.sh --quick` (`PLUGIN` = the `plugin:` line) must print PASS — gate evidence.
|
|
21
|
+
4. Card `status: done`; STATE back to `phase: done`, clear `stage:`/`card:`, gate-log line, commit `.bestest/`.
|
|
22
|
+
|
|
23
|
+
## Escalation — any eligibility breach
|
|
24
|
+
A lock block, a 4th file, a needed test or dependency-manifest edit, R-ID behavior change: set `status: escalated`, append a DISCOVERED.md line (`| discovered-from: Q-##`), offer milestone rollover. The block message is the trigger, not an obstacle to argue with.
|
|
25
|
+
|
|
26
|
+
## Bounds
|
|
27
|
+
- More than 5 Q-cards since the last rollover: trace fails — that backlog is a milestone; roll over.
|
|
28
|
+
- Refactors beyond 3 files are milestones whose SPEC states the preservation invariants as ordinary R-IDs, derived from CODEBASE.md and the prior SPEC.
|
|
29
|
+
- Q-cards and their reports archive with the next rollover like everything else; the counter resets there.
|
|
@@ -9,8 +9,9 @@ Report, compactly, from files only — no edits, no state changes, no "while I'm
|
|
|
9
9
|
|
|
10
10
|
1. `.bestest/STATE.md` — phase, stage, active card, next action, open interrupts.
|
|
11
11
|
2. Gate log — which gates passed, with dates.
|
|
12
|
-
3. Counts: task cards by status (todo/doing/done), DISCOVERED.md lines lacking `disposition:`, open risks in DECISIONS.md.
|
|
13
|
-
4. If P3+: run `"$PLUGIN"/scripts/trace.sh --plan` where `PLUGIN` = the `plugin:` line in STATE.md (read-only) and show PASS or its failure lines. A dead `plugin:` path: report it and point at bestest-go (it re-resolves); do not fix it here.
|
|
14
|
-
5. One line
|
|
12
|
+
3. Counts: task cards by status (todo/doing/done), DISCOVERED.md lines lacking `disposition:`, open risks in DECISIONS.md — list RISK rows and any due `revisit:` dates verbatim.
|
|
13
|
+
4. If P3+: run `"$PLUGIN"/scripts/trace.sh --plan` where `PLUGIN` = the `plugin:` line in STATE.md (read-only) and show PASS or its failure lines (findings projects: `--findings`). A dead `plugin:` path: report it and point at bestest-go (it re-resolves); do not fix it here.
|
|
14
|
+
5. One line from ROADMAP.md: Destination + Next up (absent: say so).
|
|
15
|
+
6. One line: "Next: <the next action verbatim from STATE.md>".
|
|
15
16
|
|
|
16
17
|
If `.bestest/` is missing, say so and point at the **bestest-go** skill.
|
|
@@ -8,13 +8,13 @@ description: Use when a bestest project enters P4 — orchestrate fresh subagent
|
|
|
8
8
|
You are the **orchestrator**: dispatch, gate, close loops. You do not write product code; builders do.
|
|
9
9
|
|
|
10
10
|
## Dispatch loop
|
|
11
|
-
1. **Pick:** lowest-numbered incomplete card whose `blocked_by:` are all done. Set `card:` + `stage:` in STATE.md, mark card `doing
|
|
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
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); commit with trailer `Bestest-Req: <R-IDs>`; on any underdetermined point return `BLOCKED: <specific question>` instead of improvising; report claim→evidence + FRICTION (or `None`) + Discovered.
|
|
13
|
+
3. **Builder contract** (put in the prompt): follow the card exactly; TDD (the failing test exists — make it pass, never edit it); 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
|
-
- `git diff --name-only <
|
|
17
|
-
- Report FRICTION
|
|
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
|
+
- 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
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.
|
|
20
20
|
7. Mark done, update STATE.md, commit `.bestest/`, next card.
|
|
@@ -23,7 +23,7 @@ You are the **orchestrator**: dispatch, gate, close loops. You do not write prod
|
|
|
23
23
|
- `BLOCKED:` from a builder → answer from SPEC/DECISIONS if derivable; else it's a real gap: INTERRUPT the user, record the answer as a D-ID, redispatch.
|
|
24
24
|
- **Loop tripwire:** same command failing 3× with the same error, or two states alternating 3× → stop the lane, record the signature in LESSONS, escalate to **debug** skill.
|
|
25
25
|
- 3 failed fix attempts on one card → debug skill; debug can't crack it → architecture escape: INTERRUPT with a one-paragraph problem statement + 2 options.
|
|
26
|
-
- Out-of-blast-radius discovery → one line in DISCOVERED.md
|
|
27
|
-
- LESSONS.md line format:
|
|
26
|
+
- Out-of-blast-radius discovery → one line in DISCOVERED.md (format in its header). Never fix silently, never drop.
|
|
27
|
+
- LESSONS.md line format: in its header (template: LESSONS.md).
|
|
28
28
|
|
|
29
29
|
Autonomy Contract (SPEC §9) governs everything above; GATED actions stop the line no matter what a card says.
|
|
@@ -21,7 +21,7 @@ Six forcing questions, strictly one at a time, researching between answers so th
|
|
|
21
21
|
5. **Observation** — how will we observe (not hope) that it worked?
|
|
22
22
|
6. **Future-fit** — what changes in 12 months that kills or grows this?
|
|
23
23
|
|
|
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.
|
|
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
27
|
Adaptive, domain-specific gray areas across five buckets: users/actors · data & lifecycle · integration surface · failure/abuse · **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.
|
|
@@ -35,8 +35,8 @@ Now attack the accumulated idea (tactics reference): name tensions between state
|
|
|
35
35
|
## Stage 5 — Scope freeze
|
|
36
36
|
Every candidate requirement gets Include / Defer / Cut / Hold. `out_of_scope` must be non-empty with reasons; Deferred items go to the parking lot. User-facing docs (README, API reference, changelog) get an explicit disposition — Included = R-IDs, else out_of_scope with a reason. Write acceptance criteria in **EARS grammar**, one sentence each, numbered `R-N.M`:
|
|
37
37
|
`WHEN <trigger> [WHILE <state>] THE SYSTEM SHALL <observable behavior>.`
|
|
38
|
-
If a criterion can't be phrased as observable behavior, it isn't a criterion — rework it.
|
|
39
|
-
Close the stage by writing **SPEC §8 — the doneness function**: the falsifiable test the P5 go/no-go will evaluate verbatim.
|
|
38
|
+
If a criterion can't be phrased as observable behavior, it isn't a criterion — rework it. (Findings projects: question R-IDs — grammar in research `references/findings.md`.)
|
|
39
|
+
Close the stage by writing **SPEC §8 — the doneness function**: the falsifiable test the P5 go/no-go will evaluate verbatim — and appending this milestone's intent line to `.bestest/ROADMAP.md` (`trace.sh --plan` fails without it).
|
|
40
40
|
|
|
41
41
|
## Stage 6 — Spec & contract freeze (P2 gate)
|
|
42
42
|
1. **Rubric pass:** dispatch the plan-checker agent in spec mode. Findings come back typed `[Gap]` `[Ambiguity]` `[Conflict]` `[Assumption]` with R-ID cites. Freeze is blocked until every Gap/Conflict is fixed or explicitly accepted as a D-ID.
|
|
@@ -5,7 +5,7 @@ description: Use when a bestest project enters P3 — turn the frozen SPEC into
|
|
|
5
5
|
|
|
6
6
|
# Plan
|
|
7
7
|
|
|
8
|
-
Input: frozen SPEC. Output: `.bestest/PLAN.md` (
|
|
8
|
+
Input: frozen SPEC. Output: `.bestest/PLAN.md` (template: PLAN.md) and `.bestest/plans/T-##.md` cards (template: task-card.md). Assets the build needs (data, fixtures, images, seeds): `references/assets.md`.
|
|
9
9
|
|
|
10
10
|
## Card discipline
|
|
11
11
|
- **Zero-context contract:** a fresh subagent with only the card + LESSONS.md must succeed. Exact paths, signatures, data shapes, D-ID pointers. No placeholders, no "as discussed".
|
|
@@ -15,7 +15,7 @@ Input: frozen SPEC. Output: `.bestest/PLAN.md` (ordered index + rationale) and `
|
|
|
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
16
|
|
|
17
17
|
## Complexity Justification table (in PLAN.md)
|
|
18
|
-
Any design element beyond the simplest thing satisfying the R-IDs gets a row
|
|
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
19
|
|
|
20
20
|
## Checker loop (gate)
|
|
21
21
|
1. Dispatch **plan-checker** agent (card mode) with PLAN.md + cards + SPEC.
|
|
@@ -8,7 +8,7 @@ description: Use when a bestest project needs external facts — P1 stack deriva
|
|
|
8
8
|
Rule zero: **memory is a rumor.** Anything external — API shape, pricing, limit, version, benchmark — is `[assumed]` until a fetched URL says otherwise. `[assumed]` load-bearing claims block the P1 gate.
|
|
9
9
|
|
|
10
10
|
## Loop (per research question)
|
|
11
|
-
1. **Frame** — write `.bestest/research/RQ-<slug>.md
|
|
11
|
+
1. **Frame** — write `.bestest/research/RQ-<slug>.md` (template: RQ.md).
|
|
12
12
|
2. **Fan out** — dispatch researcher agents in parallel, one per RQ (or per candidate for comparisons). Each returns findings with URLs; they write their own RQ file (file handoff, not chat recall).
|
|
13
13
|
3. **Verify adversarially** — for each load-bearing claim, one attempt to refute it: a second independent source, or the primary source read closely (changelogs, pricing pages, GitHub issues beat blog posts). Claims that survive get `[cited:URL]`; claims that don't get flagged to the user or dropped.
|
|
14
14
|
4. **Synthesize** — decision-brief per open decision: options, recommendation, evidence rows. Feed SPEC §5 / DECISIONS.
|
|
@@ -17,7 +17,10 @@ Rule zero: **memory is a rumor.** Anything external — API shape, pricing, limi
|
|
|
17
17
|
Stack is an **output**, never an input. From SPEC constraints (platform, team skills `[user]`, data shape, scale honesty from the Premise) derive candidates → SLOPCHECK every dependency (see interrogate references) → produce the stack decision-brief table, every row cited. Present once, whole, for user approval — that's the single P1 gate.
|
|
18
18
|
|
|
19
19
|
## Spike — when only running code can answer
|
|
20
|
-
A question that survives doc research and only execution can settle: add a `spike:` block to its RQ file (
|
|
20
|
+
A question that survives doc research and only execution can settle: add a `spike:` block to its RQ file (keys in template RQ.md) and set `stage: spike-<slug>` in STATE.md. From then on the lock-guard blocks writes outside `.bestest/` — spike code lives in `.bestest/spikes/<slug>/`, as crude as it likes. Paste run evidence into the RQ as `verdict:`, then disposition — mandatory, trace.sh fails P3 on any bare spike: `discarded` (delete the dir via an explicit shell step) or `promoted` — the finding enters SPEC/DECISIONS as `[cited:<RQ path>]`; cards rebuild it, spike code never ships. Clear `stage:` on exit. Discipline and edge cases: `references/spike.md`.
|
|
21
|
+
|
|
22
|
+
## Research-terminal projects
|
|
23
|
+
`deliverable: findings`: the P1 gate variant and the FINDINGS.md deliverable live in `references/findings.md`.
|
|
21
24
|
|
|
22
25
|
## Citation hygiene
|
|
23
26
|
- Cite the page you actually fetched, not the search snippet.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Research-terminal projects — `deliverable: findings`
|
|
2
|
+
|
|
3
|
+
For premises whose deliverable is knowledge, not software: question in, cited verdict out. Declared in the Premise Verdict (`deliverable: findings`, D-ID recorded). Same lifecycle spine; the router skips P3–P4 after the P2 freeze and logs the skip.
|
|
4
|
+
|
|
5
|
+
## R-ID grammar
|
|
6
|
+
SPEC §2 criteria are questions with a named verdict shape and evidence bar:
|
|
7
|
+
`WHEN research completes THE FINDINGS SHALL state <verdict shape> with <evidence bar>.`
|
|
8
|
+
The observable behavior is the verdict itself — a question that can't name what a usable answer looks like isn't ready to freeze.
|
|
9
|
+
|
|
10
|
+
## P1 gate variant
|
|
11
|
+
The research loop runs unchanged: fan-out, adversarial verification, spikes. The gate: every R-ID's RQ file carries `verdict:` plus at least one `[cited:URL]` (or pasted run evidence for spikes), and every spike is dispositioned. The stack decision-brief approval is replaced by the question-set freeze at P2 — post-freeze question drift is a SPEC amendment (D-ID + re-hash), which is exactly the discipline the freeze buys.
|
|
12
|
+
|
|
13
|
+
## Deliverable
|
|
14
|
+
`.bestest/FINDINGS.md` (template: FINDINGS.md): one section per R-ID — verdict (one paragraph max), confidence plus what-would-change-it, evidence pointers into `research/RQ-*.md`. Ends with a Recommendation and a reopen tripwire. RQ files and FINDINGS stay unfrozen: a P5 UAT fail routes back to the research loop, never to P4.
|
|
15
|
+
|
|
16
|
+
## P5 variant
|
|
17
|
+
Ship runs against FINDINGS.md: UAT walks the user through each R-ID's verdict one at a time; the mechanical gate is `trace.sh --findings` — every R-ID has a cited RQ verdict, a FINDINGS.md section, and a UAT row; spikes and DISCOVERED dispositioned; ROADMAP verdict line present. Runbook is `n/a: findings deliverable` — skip the rollback rehearsal. The doneness function (SPEC §8) is evaluated against FINDINGS.md verbatim. LESSONS curation and the promotion offers run unchanged.
|
|
18
|
+
|
|
19
|
+
## Out of scope
|
|
20
|
+
No post-done citation-freshness monitoring — findings age like any document; the reopen tripwire is the honest boundary. A build project with research questions is just P1 — this lane is only for projects that END at answers.
|
|
@@ -5,19 +5,19 @@ description: Use when a bestest project enters P5 — UAT against every acceptan
|
|
|
5
5
|
|
|
6
6
|
# Ship
|
|
7
7
|
|
|
8
|
-
Nothing new gets built here; P5 proves what exists and stages it for production.
|
|
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
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.
|
|
12
12
|
|
|
13
13
|
## 2. Full-chain audit
|
|
14
|
-
`"$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.
|
|
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
|
-
Append `| disposition:` to each
|
|
17
|
+
Append `| disposition:` to each line (grammar in the DISCOVERED.md header). trace.sh fails any bare line. This is where "never dropped" gets cashed.
|
|
18
18
|
|
|
19
19
|
## 4. LESSONS curation
|
|
20
|
-
Compress LESSONS.md: dedupe, drop task-local noise, keep durable environment/codebase facts.
|
|
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.
|
|
21
21
|
|
|
22
22
|
## 5. Runbook
|
|
23
23
|
Fill `.bestest/RUNBOOK.md` (template) for the actual derived stack. The rollback section requires a **rehearsal transcript** — actually roll back once, paste it. Timeouts, observability floor, negative-path security smoke, restore drill, spend ceiling: each filled or `n/a + reason`.
|
|
@@ -25,4 +25,4 @@ Fill `.bestest/RUNBOOK.md` (template) for the actual derived stack. The rollback
|
|
|
25
25
|
## 6. Go/no-go
|
|
26
26
|
One screen: doneness function (SPEC §8) evaluated verbatim · UAT table · trace PASS · runbook gaps · open risks with tripwires. The user says go or no-go. **Deploy itself is GATED** — even after "go", the deploy command runs only with explicit user approval, per the Autonomy Contract.
|
|
27
27
|
|
|
28
|
-
On "go": log the gate, set `phase: done` in STATE.md, commit. The lifecycle is complete — the router
|
|
28
|
+
On "go": log the gate, set `phase: done` in STATE.md, commit. The lifecycle is complete — new work now routes through the quick lane (small fixes; router `references/quick.md`) or **milestone rollover** (archive to `.bestest/milestones/`, re-enter P0 brownfield).
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
| Subagent dispatch | Task tool; plan-checker / researcher / reviewer ship as plugin agents; parallel dispatch supported |
|
|
11
11
|
| Isolation | git worktrees |
|
|
12
12
|
| Compaction survival | SessionStart hook (matcher startup\|resume\|clear\|compact) re-injects STATE.md lines 1–60 + LOCKS + drift notice |
|
|
13
|
-
|
|
|
13
|
+
| Project memory file (LESSONS promotion) | CLAUDE.md |
|
|
14
|
+
| User-level memory file (cross-project LESSONS) | `~/.claude/CLAUDE.md` |
|
|
14
15
|
| Guarded tools | Bash → guard.sh; Write/Edit/MultiEdit → lock-guard.sh, syntax-check.sh |
|
|
15
16
|
|
|
16
17
|
Everything above is wiring, not behavior: the laws in using-bestest are identical on every harness.
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
| Subagent dispatch | prose-directed dispatch works once roles are registered; **bootstrap extra (gated shell step): copy `adapters/codex/agents/*.toml` from the plugin root into the project's `.codex/agents/`** — plugin-bundled agents don't auto-register; depth 1 |
|
|
11
11
|
| Isolation | separate checkout (no native worktree command) |
|
|
12
12
|
| Compaction survival | SessionStart + PostCompact hooks re-inject STATE.md lines 1–60 + LOCKS + drift notice |
|
|
13
|
-
|
|
|
13
|
+
| Project memory file (LESSONS promotion) | AGENTS.md (32 KiB read cap) |
|
|
14
|
+
| User-level memory file (cross-project LESSONS) | `~/.codex/AGENTS.md` (FACTS.md 2026-07-12) |
|
|
14
15
|
| Guarded tools | shell → guard.sh; apply_patch (file edits) → lock-guard.sh, syntax-check.sh |
|
|
15
16
|
| Hook trust | hooks need a one-time trust review at install; any script update re-flags them — re-trust or they silently stop enforcing |
|
|
16
17
|
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
| Subagent dispatch | task tool with the installed plan-checker / researcher / reviewer agents (`@mention` or prose-directed) |
|
|
12
12
|
| Isolation | git worktrees via your own shell steps |
|
|
13
13
|
| Compaction survival | `opencode.json` instructions loads `.bestest/.context.md` (plugin-maintained digest: STATE.md 1–60 + LOCKS + active card + DRIFT); compaction re-inject rides the plugin |
|
|
14
|
-
|
|
|
14
|
+
| Project memory file (LESSONS promotion) | AGENTS.md |
|
|
15
|
+
| User-level memory file (cross-project LESSONS) | `~/.config/opencode/AGENTS.md` (FACTS.md 2026-07-12) |
|
|
15
16
|
| Guarded tools | bash → guard.sh; write/edit/apply_patch → lock-guard.sh, syntax-check.sh — via the `@accidentally-awesome-labs/opencode-bestest` npm plugin (exit 2 → blocked) |
|
|
16
17
|
| Degraded mode | without the npm plugin there are NO guards, no auto-injection, no drift detection — commands still resume by reading `.bestest/STATE.md` |
|
|
17
18
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# CODEBASE — <repo name>
|
|
2
|
+
<!-- Written by a read-only subagent at brownfield bootstrap; regenerated at each
|
|
3
|
+
milestone rollover. Hard cap 60 lines. Every claim cited to a file path —
|
|
4
|
+
observed fact, not aspiration. -->
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
<!-- top-level dirs and what lives where -->
|
|
8
|
+
|
|
9
|
+
## Entry points
|
|
10
|
+
<!-- binaries, main modules, routes — path-cited -->
|
|
11
|
+
|
|
12
|
+
## Build / run / test
|
|
13
|
+
<!-- exact commands, copy-pasteable -->
|
|
14
|
+
|
|
15
|
+
## Conventions
|
|
16
|
+
<!-- naming, structure, patterns actually observed (path-cited) -->
|
|
17
|
+
|
|
18
|
+
## Integration seams
|
|
19
|
+
<!-- where new code plugs in: interfaces, DI points, extension dirs -->
|
|
20
|
+
|
|
21
|
+
## Deploy surface
|
|
22
|
+
<!-- how it ships today: CI files, Dockerfiles, scripts — or 'none found' -->
|
|
23
|
+
|
|
24
|
+
## Baseline test run
|
|
25
|
+
<!-- exact command + verbatim failure list. Pre-existing failures become RISK
|
|
26
|
+
entries in DECISIONS.md; no card verify: may expect them green. -->
|
|
@@ -8,4 +8,6 @@
|
|
|
8
8
|
<!-- RISK-001 | description | likelihood | blast radius | tripwire that reopens it -->
|
|
9
9
|
|
|
10
10
|
## Review waivers
|
|
11
|
-
<!-- D-0NN | class: Waiver | finding waived | why acceptable | revisit trigger
|
|
11
|
+
<!-- D-0NN | class: Waiver | finding waived | why acceptable | revisit trigger — waivers are decisions, same D-ID sequence.
|
|
12
|
+
Date triggers as 'revisit: YYYY-MM-DD' — session start surfaces due dates until
|
|
13
|
+
you append a 'D-0NN revisited <date>: <outcome>' line (append-only; never rewrite). -->
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# DISCOVERED — out-of-blast-radius work
|
|
2
|
+
<!-- Never fixed silently, never dropped. One line per item, appended when found:
|
|
3
|
+
- <summary> | discovered-from: T-## | blocks: <T-## or none>
|
|
4
|
+
At P5 ship every line gains a disposition (trace.sh --all fails bare lines):
|
|
5
|
+
| disposition: fix-now / deferred to <where> / wontfix because <reason>
|
|
6
|
+
Survives milestone rollover; deferred lines seed the next interrogation. -->
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# FINDINGS — <project name>
|
|
2
|
+
<!-- The deliverable of a research-terminal project (deliverable: findings).
|
|
3
|
+
One section per SPEC R-ID. trace.sh --findings requires every R-ID here,
|
|
4
|
+
each backed by a research/RQ-*.md verdict with citations. Stays unfrozen —
|
|
5
|
+
a UAT fail routes back to the research loop, never to P4. -->
|
|
6
|
+
|
|
7
|
+
## R-N.M — <question, one clause>
|
|
8
|
+
verdict: <the answer, one paragraph max>
|
|
9
|
+
confidence: <high|medium|low> — would change if: <falsifier>
|
|
10
|
+
evidence: <research/RQ-<slug>.md + the load-bearing [cited:URL]s>
|
|
11
|
+
|
|
12
|
+
## Recommendation
|
|
13
|
+
<!-- what to do because of these answers, one paragraph; cite D-IDs -->
|
|
14
|
+
reopen-if: <tripwire that invalidates the recommendation>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# PLAN — <milestone>
|
|
2
|
+
<!-- Written at P3; the amendment cascade patches this file together with the
|
|
3
|
+
cards. trace.sh --plan cross-checks the card index against plans/T-*.md
|
|
4
|
+
both ways: every card indexed, every indexed id has a card file. Cut cards
|
|
5
|
+
are dropped from the index — the cut itself lives in the amendment D-ID. -->
|
|
6
|
+
|
|
7
|
+
## Card index
|
|
8
|
+
<!-- one line per live card, in execution order:
|
|
9
|
+
T-## | <title> | complexity N | blocked_by: <T-## or none> -->
|
|
10
|
+
|
|
11
|
+
## Rationale
|
|
12
|
+
<!-- why this order and these slices; tracer bullet first -->
|
|
13
|
+
|
|
14
|
+
## Complexity justification
|
|
15
|
+
<!-- every design element beyond the simplest thing satisfying the R-IDs gets a
|
|
16
|
+
row — no row means the plan-checker counts it as a blocker:
|
|
17
|
+
| Complexity | Why needed | Simpler alternative rejected because |
|
|
18
|
+
|---|---|---| -->
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ROADMAP — <project name>
|
|
2
|
+
<!-- Direction, never backlog: items live in DISCOVERED.md, scope in the milestone
|
|
3
|
+
SPEC — link, don't copy. Hard cap 40 lines (trace.sh enforces). Never hashed:
|
|
4
|
+
stays editable after the SPEC freeze; survives milestone rollover. -->
|
|
5
|
+
|
|
6
|
+
## Destination
|
|
7
|
+
<!-- 2-3 lines: where the project is going across milestones; what "done for good"
|
|
8
|
+
looks like -->
|
|
9
|
+
|
|
10
|
+
## Milestone ledger
|
|
11
|
+
<!-- one line per milestone, at line start. Intent appended at scope freeze
|
|
12
|
+
(trace --plan gates it); verdict completed at P5 ship (trace --all gates it).
|
|
13
|
+
Compress old lines — detail lives in .bestest/milestones/<N>/.
|
|
14
|
+
vN | intent: <one clause> | verdict: shipped <date> — <one clause outcome> -->
|
|
15
|
+
|
|
16
|
+
## Next up
|
|
17
|
+
<!-- 1-3 lines: the likely next milestone's theme and why-now; point at DISCOVERED
|
|
18
|
+
lines and D-IDs, never copy them -->
|
|
19
|
+
|
|
20
|
+
## Abandoned
|
|
21
|
+
<!-- <direction> — <why> (D-ID) -->
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# RQ — <question slug>
|
|
2
|
+
<!-- One file per research question, written by the researcher agent
|
|
3
|
+
(file handoff, not chat recall). -->
|
|
4
|
+
|
|
5
|
+
question: <the falsifiable question>
|
|
6
|
+
feeds: <which R-ID or decision this answers>
|
|
7
|
+
answer_shape: <what a usable answer looks like>
|
|
8
|
+
|
|
9
|
+
## Findings
|
|
10
|
+
<!-- every external claim [cited:URL] — the page actually fetched, not a search
|
|
11
|
+
snippet; version-sensitive claims name version + date; [assumed] for
|
|
12
|
+
anything no fetched URL confirms -->
|
|
13
|
+
|
|
14
|
+
## Spike
|
|
15
|
+
<!-- only if docs cannot answer (discipline: research references/spike.md).
|
|
16
|
+
Append these as top-level keys, at line start, when the spike opens:
|
|
17
|
+
spike: <falsifiable question> (plus timebox + answer shape)
|
|
18
|
+
verdict: <actual run output, or 'unknown after <timebox>'>
|
|
19
|
+
disposition: discarded | promoted (mandatory — trace.sh fails a bare spike) -->
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## 1. Premise Verdict
|
|
6
6
|
<!-- one paragraph: the real problem, for whom, why now, why not an existing tool.
|
|
7
|
-
Every factual claim tagged [user] / [cited:URL] / [assumed].
|
|
7
|
+
Every factual claim tagged [user] / [cited:URL] / [assumed].
|
|
8
|
+
Knowledge deliverable, nothing ships: add a 'deliverable: findings' line —
|
|
9
|
+
R-IDs become questions, P3-P4 are skipped (research references/findings.md). -->
|
|
8
10
|
|
|
9
11
|
## 2. Requirements — EARS acceptance criteria
|
|
10
12
|
<!-- one sentence each, numbered R-N.M, observable behavior only:
|
|
@@ -8,6 +8,7 @@ milestone: v1 # archived to .bestest/milestones/<milestone>/ at rollover
|
|
|
8
8
|
stage: 0 # interrogation stage 0-6, task id T-## during P4, or spike-<slug> (lock-guard quarantine)
|
|
9
9
|
spec_hash: none # sha256 recorded in .bestest/LOCKS at P2 freeze
|
|
10
10
|
card: none # project-relative path to the active task card (lock-guard reads this)
|
|
11
|
+
task_start: none # HEAD sha at card dispatch — diff-scope gate baseline; survives compaction via re-injection
|
|
11
12
|
|
|
12
13
|
## Now
|
|
13
14
|
- next action: <one imperative sentence — what the very next tool call should do>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: Q-00
|
|
3
|
+
title: <imperative, one clause>
|
|
4
|
+
status: doing # doing | done | escalated
|
|
5
|
+
files: src/example.py # 1-3 paths, comma-separated; a diff outside them = escalate
|
|
6
|
+
requirements: none # none | R-IDs this RESTORES (never alters, never creates) | refactor
|
|
7
|
+
decision: D-000 # DECISIONS.md entry authorizing the quick fix
|
|
8
|
+
start: <sha> # git rev-parse HEAD before the first edit
|
|
9
|
+
may_edit_tests: false # always false on the quick lane (lock-guard clamps it)
|
|
10
|
+
verify:
|
|
11
|
+
- <command proving the fix; refactor: the incumbent test suite>
|
|
12
|
+
---
|
|
13
|
+
## Fix (zero-context contract)
|
|
14
|
+
<!-- symptom, exact paths, expected end state. Read LESSONS.md first; append what
|
|
15
|
+
you learn. TDD locks stand — a fix that needs a test edit escalates. -->
|
|
16
|
+
|
|
17
|
+
## Done means
|
|
18
|
+
<!-- report at .bestest/reports/Q-00.md (FRICTION + Lessons included); commit
|
|
19
|
+
trailer 'Bestest-Req: Q-00'; restored R-IDs get a 'requick' UAT.md row;
|
|
20
|
+
refactor cards paste the green incumbent-suite run in Verify output;
|
|
21
|
+
out-of-scope findings -> DISCOVERED.md, never fixed here.
|
|
22
|
+
trace.sh --quick must PASS before STATE returns to phase: done. -->
|
|
@@ -11,5 +11,10 @@
|
|
|
11
11
|
## FRICTION
|
|
12
12
|
<!-- REQUIRED. Failed commands, backtracking, wrong card assumptions, environment surprises — or exactly 'None'. The orchestrator patches remaining cards + LESSONS.md from this before the next dispatch. -->
|
|
13
13
|
|
|
14
|
+
## Lessons
|
|
15
|
+
<!-- REQUIRED. Each durable FRICTION fact as the exact line appended to LESSONS.md
|
|
16
|
+
('- [env|tool|codebase] <fact> (T-00)') — or exactly 'None'. trace.sh --all
|
|
17
|
+
cross-checks every line here against LESSONS.md. -->
|
|
18
|
+
|
|
14
19
|
## Discovered
|
|
15
20
|
<!-- out-of-blast-radius items appended to DISCOVERED.md this task, or 'None' -->
|