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 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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ exec "$SCRIPT_DIR/bt.sh" "$@"
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
+
@@ -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
+ }