biotonomy 0.1.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/LICENSE +21 -0
- package/README.md +186 -0
- package/bt +5 -0
- package/bt.sh +134 -0
- package/commands/bootstrap.sh +47 -0
- package/commands/compound.sh +37 -0
- package/commands/design.sh +33 -0
- package/commands/fix.sh +70 -0
- package/commands/gates.sh +40 -0
- package/commands/implement.sh +70 -0
- package/commands/pr.sh +265 -0
- package/commands/research.sh +80 -0
- package/commands/reset.sh +37 -0
- package/commands/review.sh +84 -0
- package/commands/spec.sh +196 -0
- package/commands/status.sh +114 -0
- package/hooks/telegram.sh +31 -0
- package/lib/codex.sh +39 -0
- package/lib/env.sh +96 -0
- package/lib/gates.sh +109 -0
- package/lib/log.sh +48 -0
- package/lib/notify.sh +13 -0
- package/lib/path.sh +36 -0
- package/lib/repo.sh +70 -0
- package/lib/state.sh +60 -0
- package/package.json +39 -0
- package/prompts/fix.md +17 -0
- package/prompts/implement.md +19 -0
- package/prompts/research.md +12 -0
- package/prompts/review.md +15 -0
- package/scripts/demo-issue-3-real-loop.sh +221 -0
- package/scripts/gh-pr.sh +118 -0
- package/scripts/lint-shell.sh +41 -0
- package/scripts/verify-pack.mjs +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Archive Technologies, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Biotonomy
|
|
2
|
+
|
|
3
|
+
Biotonomy is a CLI that runs Codex loops (research→implement→review→fix) inside your repo.
|
|
4
|
+
It enforces quality gates (lint/typecheck/test) between stages and records everything as files.
|
|
5
|
+
PR automation is now first-class (`bt pr` / `bt ship`) and keeps deterministic artifacts for every run.
|
|
6
|
+
|
|
7
|
+
Biotonomy is intentionally file-based:
|
|
8
|
+
- project config lives in `.bt.env`
|
|
9
|
+
- ephemeral state lives in `.bt/`
|
|
10
|
+
- feature state lives in `specs/<feature>/`
|
|
11
|
+
|
|
12
|
+
## The Codex Loop
|
|
13
|
+
|
|
14
|
+
For a feature folder `specs/<feature>/`, the loop is:
|
|
15
|
+
|
|
16
|
+
1. `bt spec <feature>`: create `SPEC.md` (or `bt spec <issue#>` to pull from GitHub via `gh`)
|
|
17
|
+
2. `bt research <feature>`: Codex writes `RESEARCH.md` (Codex required)
|
|
18
|
+
3. `bt implement <feature>`: Codex applies code changes + Biotonomy runs quality gates
|
|
19
|
+
4. `bt review <feature>`: Codex reviews into `REVIEW.md` (writes a stub if Codex is missing)
|
|
20
|
+
5. `bt fix <feature>`: Codex applies targeted fixes + Biotonomy runs quality gates
|
|
21
|
+
|
|
22
|
+
Supporting commands:
|
|
23
|
+
- `bt status`: summarize story status from `SPEC.md` plus latest `gates.json` (if present)
|
|
24
|
+
- `bt gates [<feature>]`: run gates and write `gates.json` (feature-local or global)
|
|
25
|
+
- `bt reset`: delete `.bt/` and `specs/**/.lock` (does not modify your git working tree)
|
|
26
|
+
|
|
27
|
+
## Ship Archie (Walkthrough)
|
|
28
|
+
|
|
29
|
+
This is the intended "ship a feature" path. Some steps are still manual; each TODO points at the tracking issue.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 0) Install
|
|
33
|
+
npm install -g biotonomy
|
|
34
|
+
|
|
35
|
+
# 1) Initialize the repo for Biotonomy (creates .bt.env, specs/, .bt/)
|
|
36
|
+
bt bootstrap
|
|
37
|
+
|
|
38
|
+
# 2) Create a spec (local feature name)
|
|
39
|
+
bt spec archie
|
|
40
|
+
|
|
41
|
+
# (Optional) If "Archie" is a GitHub issue:
|
|
42
|
+
# bt spec 123 # pulls issue title/body via `gh` into specs/issue-123/SPEC.md
|
|
43
|
+
|
|
44
|
+
# 3) Research (requires Codex; see Issue #3 for the end-to-end loop/demo harness)
|
|
45
|
+
bt research archie
|
|
46
|
+
|
|
47
|
+
# 4) Implement (runs gates; if Codex is unavailable this records history and still runs gates)
|
|
48
|
+
bt implement archie
|
|
49
|
+
|
|
50
|
+
# 5) Review (writes specs/archie/REVIEW.md; stub output if Codex is unavailable)
|
|
51
|
+
bt review archie
|
|
52
|
+
|
|
53
|
+
# 6) Fix until review is clean (gates are re-run)
|
|
54
|
+
bt fix archie
|
|
55
|
+
|
|
56
|
+
# 7) Check progress at any time
|
|
57
|
+
bt status
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Tracked work (open issues):
|
|
61
|
+
- Core loop expansion (`bt loop` style driver and polish): [Issue #10](https://github.com/archive-dot-com/biotonomy/issues/10), [Issue #3](https://github.com/archive-dot-com/biotonomy/issues/3)
|
|
62
|
+
- Release readiness and publish workflow (`npm i -g biotonomy`): [Issue #7](https://github.com/archive-dot-com/biotonomy/issues/7)
|
|
63
|
+
- Docs refresh for Archie walkthrough and current commands: [Issue #8](https://github.com/archive-dot-com/biotonomy/issues/8), [Issue #1](https://github.com/archive-dot-com/biotonomy/issues/1)
|
|
64
|
+
- Reliability hardening and bugfixes: [Issues #13-#17](https://github.com/archive-dot-com/biotonomy/issues)
|
|
65
|
+
|
|
66
|
+
## Artifacts And Layout
|
|
67
|
+
|
|
68
|
+
Biotonomy is minimal bash plus prompt templates:
|
|
69
|
+
- `bt.sh`: CLI entrypoint and router
|
|
70
|
+
- `commands/*.sh`: command implementations
|
|
71
|
+
- `lib/*.sh`: shared helpers (env loading, state paths, notifications, gates, Codex exec)
|
|
72
|
+
- `prompts/*.md`: prompt templates for Codex stages
|
|
73
|
+
- `hooks/*`: example notification hooks
|
|
74
|
+
|
|
75
|
+
On disk, expect:
|
|
76
|
+
- `.bt.env`: project config (parsed as `KEY=VALUE` without `source` / without executing code)
|
|
77
|
+
- `.bt/`: ephemeral state (locks/caches; safe to delete via `bt reset`)
|
|
78
|
+
- `specs/<feature>/SPEC.md`: plan and story statuses (parseable; created by `bt spec`)
|
|
79
|
+
- `specs/<feature>/RESEARCH.md`: research notes (`bt research`)
|
|
80
|
+
- `specs/<feature>/REVIEW.md`: review verdict + findings (`bt review`)
|
|
81
|
+
- `specs/<feature>/gates.json`: latest gate results when running `bt gates <feature>`
|
|
82
|
+
- `specs/<feature>/progress.txt`: timestamped progress log
|
|
83
|
+
- `specs/<feature>/history/*.md`: append-only run history for each stage
|
|
84
|
+
- `specs/<feature>/.artifacts/*`: captured stderr from Codex/gh for debugging/repro
|
|
85
|
+
|
|
86
|
+
## Quality Gates
|
|
87
|
+
|
|
88
|
+
Stages that run gates:
|
|
89
|
+
- `bt implement <feature>`
|
|
90
|
+
- `bt fix <feature>`
|
|
91
|
+
- `bt gates [<feature>]`
|
|
92
|
+
|
|
93
|
+
Gate configuration:
|
|
94
|
+
- Override per-project in `.bt.env` via `BT_GATE_LINT`, `BT_GATE_TYPECHECK`, `BT_GATE_TEST`
|
|
95
|
+
- If unset, Biotonomy tries simple auto-detection (npm/yarn/pnpm/Makefile)
|
|
96
|
+
|
|
97
|
+
## PR Automation (Opt-In Today)
|
|
98
|
+
|
|
99
|
+
There is currently a safe helper script (defaults to `--dry-run`) that uses `git` and `gh`:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm run pr:open -- archie --dry-run
|
|
103
|
+
npm run pr:open -- archie --run
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
It determines the branch from `specs/<feature>/SPEC.md` frontmatter (`branch:`) when present, otherwise uses `feat/<feature>`.
|
|
107
|
+
The planned end state is a first-class `bt pr ...` flow. Tracked in [Issue #8](https://github.com/archive-dot-com/biotonomy/issues/8).
|
|
108
|
+
|
|
109
|
+
## Demos
|
|
110
|
+
|
|
111
|
+
### Issue #3 Real Loop (End-to-End, Deterministic)
|
|
112
|
+
|
|
113
|
+
This repo includes an end-to-end "real loop" runner that:
|
|
114
|
+
- runs the actual `bt.sh` entrypoint
|
|
115
|
+
- uses a deterministic workspace
|
|
116
|
+
- stubs `gh` and `codex` so it is reproducible offline
|
|
117
|
+
- writes a scrubbed transcript + snapshot under `specs/issue-3-real-loop/`
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm install
|
|
121
|
+
npm run demo
|
|
122
|
+
|
|
123
|
+
ls -R specs/issue-3-real-loop
|
|
124
|
+
sed -n '1,120p' specs/issue-3-real-loop/transcript.txt
|
|
125
|
+
sed -n '1,120p' specs/issue-3-real-loop/snapshot.txt
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Install
|
|
129
|
+
|
|
130
|
+
Global install:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npm install -g biotonomy
|
|
134
|
+
bt --help
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Local (repo) usage:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npx biotonomy --help
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Targeting A Repo From Anywhere
|
|
144
|
+
|
|
145
|
+
By default, `bt` uses your current working directory as the project root.
|
|
146
|
+
|
|
147
|
+
To run against a different repo, use `--target <path>` (sets `BT_TARGET_DIR` for that invocation):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
bt --target /path/to/repo bootstrap
|
|
151
|
+
bt --target /path/to/repo status
|
|
152
|
+
bt --target /path/to/repo spec archie
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
You can also set `BT_TARGET_DIR` in the environment (same behavior):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
BT_TARGET_DIR=/path/to/repo bt status
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Status (v0.1.0)
|
|
162
|
+
|
|
163
|
+
Implemented today:
|
|
164
|
+
- File-based loop artifacts: `.bt.env`, `.bt/`, `specs/<feature>/...`
|
|
165
|
+
- `bt bootstrap`, `bt spec <feature>`, `bt status`, `bt gates`, `bt reset`
|
|
166
|
+
- `bt review` produces `REVIEW.md` even without Codex (stub output + required `Verdict:` line)
|
|
167
|
+
- `bt implement` and `bt fix` always run quality gates and record history; if Codex is missing they behave as stubs (no code changes)
|
|
168
|
+
- `bt research` requires Codex (it dies early if `codex` is not available)
|
|
169
|
+
- Opt-in PR helper (`npm run pr:open`) with `--dry-run` by default
|
|
170
|
+
|
|
171
|
+
In progress (tracked in open issues):
|
|
172
|
+
- [Issue #10](https://github.com/archive-dot-com/biotonomy/issues/10): add a first-class loop driver (implement→review→fix until APPROVE + gates pass)
|
|
173
|
+
- [Issue #3](https://github.com/archive-dot-com/biotonomy/issues/3): complete Codex-native loop ergonomics
|
|
174
|
+
- [Issue #7](https://github.com/archive-dot-com/biotonomy/issues/7): publish workflow + npm readiness
|
|
175
|
+
- [Issue #8](https://github.com/archive-dot-com/biotonomy/issues/8): docs rewrite around Codex loop + Archie walkthrough
|
|
176
|
+
- [Issue #12](https://github.com/archive-dot-com/biotonomy/issues/12): close stale “already done” tracker issues
|
|
177
|
+
- [Issues #13-#17](https://github.com/archive-dot-com/biotonomy/issues): active bugfix queue
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
npm test
|
|
183
|
+
npm run lint
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Lint uses `shellcheck` if it is installed; otherwise it skips with a warning (CI installs shellcheck and runs strict).
|
package/bt
ADDED
package/bt.sh
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
BT_VERSION="0.1.0"
|
|
5
|
+
|
|
6
|
+
bt_script_dir() {
|
|
7
|
+
local src="${BASH_SOURCE[0]}"
|
|
8
|
+
while [ -h "$src" ]; do
|
|
9
|
+
local dir
|
|
10
|
+
dir="$(cd -P "$(dirname "$src")" && pwd)"
|
|
11
|
+
src="$(readlink "$src")"
|
|
12
|
+
[[ "$src" != /* ]] && src="$dir/$src"
|
|
13
|
+
done
|
|
14
|
+
cd -P "$(dirname "$src")" && pwd
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
BT_ROOT="$(bt_script_dir)"
|
|
18
|
+
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
source "$BT_ROOT/lib/log.sh"
|
|
21
|
+
# shellcheck source=/dev/null
|
|
22
|
+
source "$BT_ROOT/lib/path.sh"
|
|
23
|
+
# shellcheck source=/dev/null
|
|
24
|
+
source "$BT_ROOT/lib/env.sh"
|
|
25
|
+
# shellcheck source=/dev/null
|
|
26
|
+
source "$BT_ROOT/lib/repo.sh"
|
|
27
|
+
# shellcheck source=/dev/null
|
|
28
|
+
source "$BT_ROOT/lib/notify.sh"
|
|
29
|
+
# shellcheck source=/dev/null
|
|
30
|
+
source "$BT_ROOT/lib/codex.sh"
|
|
31
|
+
# shellcheck source=/dev/null
|
|
32
|
+
source "$BT_ROOT/lib/state.sh"
|
|
33
|
+
# shellcheck source=/dev/null
|
|
34
|
+
source "$BT_ROOT/lib/gates.sh"
|
|
35
|
+
|
|
36
|
+
bt_usage() {
|
|
37
|
+
cat <<EOF
|
|
38
|
+
biotonomy (bt) v$BT_VERSION
|
|
39
|
+
|
|
40
|
+
Usage:
|
|
41
|
+
bt [--target <path>] <command> [args]
|
|
42
|
+
|
|
43
|
+
Commands:
|
|
44
|
+
bootstrap spec research implement review fix compound design status gates reset pr ship
|
|
45
|
+
|
|
46
|
+
Global options:
|
|
47
|
+
-h, --help Show help
|
|
48
|
+
--target <p> Operate on target project root for this invocation (sets BT_TARGET_DIR)
|
|
49
|
+
BT_ENV_FILE Explicit path to a .bt.env (otherwise read ./.bt.env)
|
|
50
|
+
BT_TARGET_DIR Operate on this repo dir (sets BT_PROJECT_ROOT); env falls back to \$BT_TARGET_DIR/.bt.env
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
bt bootstrap
|
|
54
|
+
bt spec 123
|
|
55
|
+
bt status
|
|
56
|
+
bt --target /path/to/repo status
|
|
57
|
+
EOF
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
bt_dispatch() {
|
|
61
|
+
# Global argv parsing (kept intentionally small; this is bash, not a full CLI framework).
|
|
62
|
+
# We support:
|
|
63
|
+
# - bt --target <path> <command> ...
|
|
64
|
+
# - bt <command> ... --target <path> ...
|
|
65
|
+
# - bt --target=<path> <command> ...
|
|
66
|
+
local rest=()
|
|
67
|
+
local target_arg=""
|
|
68
|
+
while [[ $# -gt 0 ]]; do
|
|
69
|
+
case "${1:-}" in
|
|
70
|
+
--target)
|
|
71
|
+
[[ $# -ge 2 ]] || bt_die "--target requires a value"
|
|
72
|
+
target_arg="${2:-}"
|
|
73
|
+
shift 2
|
|
74
|
+
;;
|
|
75
|
+
--target=*)
|
|
76
|
+
target_arg="${1#--target=}"
|
|
77
|
+
shift
|
|
78
|
+
;;
|
|
79
|
+
*)
|
|
80
|
+
rest+=("$1")
|
|
81
|
+
shift
|
|
82
|
+
;;
|
|
83
|
+
esac
|
|
84
|
+
done
|
|
85
|
+
|
|
86
|
+
if [[ -n "$target_arg" ]]; then
|
|
87
|
+
export BT_TARGET_DIR="$target_arg"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
set -- "${rest[@]}"
|
|
91
|
+
|
|
92
|
+
local cmd="${1:-help}"
|
|
93
|
+
shift || true
|
|
94
|
+
|
|
95
|
+
case "$cmd" in
|
|
96
|
+
-h|--help|help) bt_usage; return 0 ;;
|
|
97
|
+
esac
|
|
98
|
+
|
|
99
|
+
bt_env_load || true
|
|
100
|
+
|
|
101
|
+
case "$cmd" in
|
|
102
|
+
bootstrap|spec|research|implement|review|fix|compound|design|status|gates|reset|pr|ship) ;;
|
|
103
|
+
*)
|
|
104
|
+
bt_err "unknown command: $cmd"
|
|
105
|
+
bt_usage >&2
|
|
106
|
+
return 2
|
|
107
|
+
;;
|
|
108
|
+
esac
|
|
109
|
+
|
|
110
|
+
local cmd_file="$BT_ROOT/commands/$cmd.sh"
|
|
111
|
+
if [[ "$cmd" == "ship" ]]; then
|
|
112
|
+
cmd_file="$BT_ROOT/commands/pr.sh"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [[ ! -f "$cmd_file" ]]; then
|
|
116
|
+
bt_die "missing command implementation: $cmd_file"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# shellcheck source=/dev/null
|
|
120
|
+
source "$cmd_file"
|
|
121
|
+
|
|
122
|
+
local fn="bt_cmd_$cmd"
|
|
123
|
+
if [[ "$cmd" == "ship" ]]; then
|
|
124
|
+
fn="bt_cmd_pr"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if ! declare -F "$fn" >/dev/null 2>&1; then
|
|
128
|
+
bt_die "command function not found: $fn (in $cmd_file)"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
"$fn" "$@"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
bt_dispatch "$@"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
bt_cmd_bootstrap() {
|
|
5
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
6
|
+
cat <<'EOF'
|
|
7
|
+
Usage:
|
|
8
|
+
bt bootstrap
|
|
9
|
+
|
|
10
|
+
Creates a project-local `.bt.env` and scaffolds required folders (`specs/`, `.bt/`).
|
|
11
|
+
EOF
|
|
12
|
+
return 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Operate within the effective project root (BT_TARGET_DIR if set).
|
|
16
|
+
local root="${BT_PROJECT_ROOT:-$PWD}"
|
|
17
|
+
|
|
18
|
+
local env_path="$root/.bt.env"
|
|
19
|
+
if [[ -f "$env_path" ]]; then
|
|
20
|
+
bt_info "found existing .bt.env"
|
|
21
|
+
else
|
|
22
|
+
cat >"$env_path" <<'EOF'
|
|
23
|
+
# Biotonomy project config (loaded by bt)
|
|
24
|
+
|
|
25
|
+
# Where feature state lives.
|
|
26
|
+
BT_SPECS_DIR=specs
|
|
27
|
+
|
|
28
|
+
# Where ephemeral state lives (locks, caches, etc).
|
|
29
|
+
BT_STATE_DIR=.bt
|
|
30
|
+
|
|
31
|
+
# Optional: point this at an executable script to receive notifications.
|
|
32
|
+
# Example: BT_NOTIFY_HOOK=./hooks/telegram.sh
|
|
33
|
+
BT_NOTIFY_HOOK=
|
|
34
|
+
|
|
35
|
+
# Optional: override quality gates (commands). Empty means "auto-detect" (future).
|
|
36
|
+
BT_GATE_LINT=
|
|
37
|
+
BT_GATE_TYPECHECK=
|
|
38
|
+
BT_GATE_TEST=
|
|
39
|
+
EOF
|
|
40
|
+
bt_info "wrote $env_path"
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
mkdir -p "$root/specs" "$root/.bt" "$root/hooks"
|
|
44
|
+
bt_info "ensured dirs: specs/ .bt/ hooks/"
|
|
45
|
+
|
|
46
|
+
bt_notify "bt bootstrap complete in $root"
|
|
47
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# shellcheck source=/dev/null
|
|
5
|
+
source "$BT_ROOT/lib/state.sh"
|
|
6
|
+
|
|
7
|
+
bt_cmd_compound() {
|
|
8
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
9
|
+
cat <<'EOF'
|
|
10
|
+
Usage:
|
|
11
|
+
bt compound <feature>
|
|
12
|
+
|
|
13
|
+
Stubbed in v0.1.0: writes a learnings file under `learnings/`.
|
|
14
|
+
EOF
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
bt_env_load || true
|
|
19
|
+
bt_ensure_dirs
|
|
20
|
+
|
|
21
|
+
local feature
|
|
22
|
+
feature="$(bt_require_feature "${1:-}")"
|
|
23
|
+
|
|
24
|
+
mkdir -p "$BT_PROJECT_ROOT/learnings"
|
|
25
|
+
local out="$BT_PROJECT_ROOT/learnings/$feature.md"
|
|
26
|
+
cat >"$out" <<EOF
|
|
27
|
+
# Learnings: $feature
|
|
28
|
+
|
|
29
|
+
This is a v0.1.0 stub.
|
|
30
|
+
EOF
|
|
31
|
+
|
|
32
|
+
bt_progress_append "$feature" "compound stub wrote learnings/$feature.md"
|
|
33
|
+
bt_history_write "$feature" "compound" "Wrote learnings for $feature."
|
|
34
|
+
bt_info "wrote $out"
|
|
35
|
+
bt_notify "bt compound complete for $feature"
|
|
36
|
+
}
|
|
37
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# shellcheck source=/dev/null
|
|
5
|
+
source "$BT_ROOT/lib/state.sh"
|
|
6
|
+
|
|
7
|
+
bt_cmd_design() {
|
|
8
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
9
|
+
cat <<'EOF'
|
|
10
|
+
Usage:
|
|
11
|
+
bt design <feature>
|
|
12
|
+
|
|
13
|
+
Stubbed in v0.1.0: records a design iteration marker in history/progress.
|
|
14
|
+
EOF
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
bt_env_load || true
|
|
19
|
+
bt_ensure_dirs
|
|
20
|
+
|
|
21
|
+
local feature
|
|
22
|
+
feature="$(bt_require_feature "${1:-}")"
|
|
23
|
+
|
|
24
|
+
local dir
|
|
25
|
+
dir="$(bt_feature_dir "$feature")"
|
|
26
|
+
mkdir -p "$dir/history"
|
|
27
|
+
|
|
28
|
+
bt_progress_append "$feature" "design stub iteration"
|
|
29
|
+
bt_history_write "$feature" "design" "Design iteration placeholder for $feature."
|
|
30
|
+
bt_info "design stub recorded for $feature"
|
|
31
|
+
bt_notify "bt design stub ran for $feature"
|
|
32
|
+
}
|
|
33
|
+
|
package/commands/fix.sh
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# shellcheck source=/dev/null
|
|
5
|
+
source "$BT_ROOT/lib/state.sh"
|
|
6
|
+
|
|
7
|
+
bt_cmd_fix() {
|
|
8
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
9
|
+
cat <<'EOF'
|
|
10
|
+
Usage:
|
|
11
|
+
bt fix <feature>
|
|
12
|
+
|
|
13
|
+
Runs Codex in full-auto using prompts/fix.md, then runs quality gates.
|
|
14
|
+
EOF
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
bt_env_load || true
|
|
19
|
+
bt_ensure_dirs
|
|
20
|
+
|
|
21
|
+
local feature
|
|
22
|
+
feature="$(bt_require_feature "${1:-}")"
|
|
23
|
+
|
|
24
|
+
local dir
|
|
25
|
+
dir="$(bt_feature_dir "$feature")"
|
|
26
|
+
[[ -d "$dir" ]] || bt_die "missing feature dir: $dir (run: bt spec ...)"
|
|
27
|
+
|
|
28
|
+
bt_progress_append "$feature" "fix: bt fix $feature (starting)"
|
|
29
|
+
|
|
30
|
+
local codex_ec=0
|
|
31
|
+
if bt_codex_available; then
|
|
32
|
+
bt_info "running codex (full-auto) using prompts/fix.md"
|
|
33
|
+
local artifacts_dir codex_logf
|
|
34
|
+
artifacts_dir="$dir/.artifacts"
|
|
35
|
+
mkdir -p "$artifacts_dir"
|
|
36
|
+
codex_logf="$artifacts_dir/codex-fix.log"
|
|
37
|
+
: >"$codex_logf"
|
|
38
|
+
if ! BT_FEATURE="$feature" BT_CODEX_LOG_FILE="$codex_logf" bt_codex_exec_full_auto "$BT_ROOT/prompts/fix.md"; then
|
|
39
|
+
codex_ec=$?
|
|
40
|
+
bt_warn "codex exited non-zero (fix): $codex_ec"
|
|
41
|
+
fi
|
|
42
|
+
else
|
|
43
|
+
codex_ec=127
|
|
44
|
+
bt_warn "codex unavailable; fix is a v0.1.0 stub"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
bt_info "running quality gates"
|
|
48
|
+
local gates_ok=1
|
|
49
|
+
if ! bt_run_gates; then
|
|
50
|
+
gates_ok=0
|
|
51
|
+
bt_progress_append "$feature" "quality gates failed"
|
|
52
|
+
bt_notify "bt fix gates FAILED for $feature"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
local h
|
|
56
|
+
h="$(bt_history_write "$feature" "fix" "$(cat <<EOF
|
|
57
|
+
# Fix Run: $feature
|
|
58
|
+
|
|
59
|
+
- when: $(date +'%Y-%m-%d %H:%M:%S')
|
|
60
|
+
- bt_cmd: bt fix $feature
|
|
61
|
+
- prompt: prompts/fix.md
|
|
62
|
+
- codex_exit: $codex_ec
|
|
63
|
+
- gates: $([[ "$gates_ok" == "1" ]] && echo PASS || echo FAIL)
|
|
64
|
+
EOF
|
|
65
|
+
)")"
|
|
66
|
+
bt_info "wrote history: $h"
|
|
67
|
+
bt_notify "bt fix complete for $feature"
|
|
68
|
+
|
|
69
|
+
[[ "$gates_ok" == "1" ]] || return 1
|
|
70
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
bt_cmd_gates() {
|
|
5
|
+
local usage="Usage: bt gates [<feature>]
|
|
6
|
+
|
|
7
|
+
Runs project quality gates (lint, typecheck, test) as configured or auto-detected.
|
|
8
|
+
If <feature> is provided, writes results to specs/<feature>/gates.json.
|
|
9
|
+
Otherwise, writes to \$BT_PROJECT_ROOT/\$BT_STATE_DIR/state/gates.json."
|
|
10
|
+
|
|
11
|
+
local feature=""
|
|
12
|
+
if [[ $# -gt 0 ]]; then
|
|
13
|
+
case "$1" in
|
|
14
|
+
-h|--help) echo "$usage"; return 0 ;;
|
|
15
|
+
-*) bt_err "Unknown argument: $1"; echo "$usage"; return 1 ;;
|
|
16
|
+
*) feature="$(bt_require_feature "$1")" ;;
|
|
17
|
+
esac
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
local json_out
|
|
21
|
+
local exit_code=0
|
|
22
|
+
|
|
23
|
+
# bt_run_gates outputs the JSON to stdout, and exits with non-zero if any gate failed.
|
|
24
|
+
if ! json_out="$(bt_run_gates)"; then
|
|
25
|
+
exit_code=1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
local out_dir
|
|
29
|
+
if [[ -n "$feature" ]]; then
|
|
30
|
+
out_dir="$(bt_feature_dir "$feature")"
|
|
31
|
+
else
|
|
32
|
+
out_dir="$BT_PROJECT_ROOT/$BT_STATE_DIR/state"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
mkdir -p "$out_dir"
|
|
36
|
+
printf '%s\n' "$json_out" > "$out_dir/gates.json"
|
|
37
|
+
bt_info "Gate results saved to $out_dir/gates.json"
|
|
38
|
+
|
|
39
|
+
return "$exit_code"
|
|
40
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# shellcheck source=/dev/null
|
|
5
|
+
source "$BT_ROOT/lib/state.sh"
|
|
6
|
+
|
|
7
|
+
bt_cmd_implement() {
|
|
8
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
9
|
+
cat <<'EOF'
|
|
10
|
+
Usage:
|
|
11
|
+
bt implement <feature>
|
|
12
|
+
|
|
13
|
+
Runs Codex in full-auto using prompts/implement.md, then runs quality gates.
|
|
14
|
+
EOF
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
bt_env_load || true
|
|
19
|
+
bt_ensure_dirs
|
|
20
|
+
|
|
21
|
+
local feature
|
|
22
|
+
feature="$(bt_require_feature "${1:-}")"
|
|
23
|
+
|
|
24
|
+
local dir
|
|
25
|
+
dir="$(bt_feature_dir "$feature")"
|
|
26
|
+
[[ -d "$dir" ]] || bt_die "missing feature dir: $dir (run: bt spec ...)"
|
|
27
|
+
|
|
28
|
+
bt_progress_append "$feature" "implement: bt implement $feature (starting)"
|
|
29
|
+
|
|
30
|
+
local codex_ec=0
|
|
31
|
+
if bt_codex_available; then
|
|
32
|
+
bt_info "running codex (full-auto) using prompts/implement.md"
|
|
33
|
+
local artifacts_dir codex_logf
|
|
34
|
+
artifacts_dir="$dir/.artifacts"
|
|
35
|
+
mkdir -p "$artifacts_dir"
|
|
36
|
+
codex_logf="$artifacts_dir/codex-implement.log"
|
|
37
|
+
: >"$codex_logf"
|
|
38
|
+
if ! BT_FEATURE="$feature" BT_CODEX_LOG_FILE="$codex_logf" bt_codex_exec_full_auto "$BT_ROOT/prompts/implement.md"; then
|
|
39
|
+
codex_ec=$?
|
|
40
|
+
bt_warn "codex exited non-zero (implement): $codex_ec"
|
|
41
|
+
fi
|
|
42
|
+
else
|
|
43
|
+
codex_ec=127
|
|
44
|
+
bt_warn "codex unavailable; implement is a v0.1.0 stub"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
bt_info "running quality gates"
|
|
48
|
+
local gates_ok=1
|
|
49
|
+
if ! bt_run_gates; then
|
|
50
|
+
gates_ok=0
|
|
51
|
+
bt_progress_append "$feature" "quality gates failed"
|
|
52
|
+
bt_notify "bt implement gates FAILED for $feature"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
local h
|
|
56
|
+
h="$(bt_history_write "$feature" "implement" "$(cat <<EOF
|
|
57
|
+
# Implement Run: $feature
|
|
58
|
+
|
|
59
|
+
- when: $(date +'%Y-%m-%d %H:%M:%S')
|
|
60
|
+
- bt_cmd: bt implement $feature
|
|
61
|
+
- prompt: prompts/implement.md
|
|
62
|
+
- codex_exit: $codex_ec
|
|
63
|
+
- gates: $([[ "$gates_ok" == "1" ]] && echo PASS || echo FAIL)
|
|
64
|
+
EOF
|
|
65
|
+
)")"
|
|
66
|
+
bt_info "wrote history: $h"
|
|
67
|
+
bt_notify "bt implement complete for $feature"
|
|
68
|
+
|
|
69
|
+
[[ "$gates_ok" == "1" ]] || return 1
|
|
70
|
+
}
|