bmad-module-ultracode-goal 0.5.0 → 1.0.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.
Files changed (50) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +9 -8
  3. package/docs/_internal/RELEASING.md +4 -1
  4. package/docs/_internal/STABILITY.md +20 -6
  5. package/docs/architecture.md +18 -12
  6. package/docs/comparison.md +40 -38
  7. package/docs/cross-session-recall.md +1 -1
  8. package/docs/gate-model.md +4 -2
  9. package/docs/getting-started.md +27 -7
  10. package/docs/health-check.md +2 -2
  11. package/docs/how-it-works.md +45 -11
  12. package/docs/index.md +1 -1
  13. package/docs/parallel-mode.md +5 -5
  14. package/docs/troubleshooting.md +5 -5
  15. package/docs/why-ultracode-goal.md +5 -5
  16. package/package.json +14 -9
  17. package/skills/ultracode-goal/SKILL.md +9 -3
  18. package/skills/ultracode-goal/assets/execute-epic.workflow.js +3 -2
  19. package/skills/ultracode-goal/assets/module-help.csv +3 -1
  20. package/skills/ultracode-goal/assets/module-setup.md +1 -1
  21. package/skills/ultracode-goal/customize.toml +26 -2
  22. package/skills/ultracode-goal/references/define-done.md +3 -1
  23. package/skills/ultracode-goal/references/execute.md +62 -8
  24. package/skills/ultracode-goal/references/finalize.md +72 -5
  25. package/skills/ultracode-goal/references/gate.md +7 -5
  26. package/skills/ultracode-goal/references/health-check.md +21 -1
  27. package/skills/ultracode-goal/references/ingest-and-scope.md +6 -4
  28. package/skills/ultracode-goal/references/preflight.md +33 -6
  29. package/skills/ultracode-goal/scripts/drive_epic.py +896 -0
  30. package/skills/ultracode-goal/scripts/formalize_check.py +129 -0
  31. package/skills/ultracode-goal/scripts/gate_eval.py +65 -9
  32. package/skills/ultracode-goal/scripts/gate_trail.py +555 -0
  33. package/skills/ultracode-goal/scripts/headless_envelope.py +116 -8
  34. package/skills/ultracode-goal/scripts/health_check_fp.py +42 -6
  35. package/skills/ultracode-goal/scripts/hooks/budget_stop.py +28 -37
  36. package/skills/ultracode-goal/scripts/hooks/guard_pretooluse.py +526 -15
  37. package/skills/ultracode-goal/scripts/red_ids.py +302 -0
  38. package/skills/ultracode-goal/scripts/status_render.py +471 -0
  39. package/skills/ultracode-goal/skills/ucg-resolve/SKILL.md +225 -0
  40. package/skills/ultracode-goal/skills/ucg-status/SKILL.md +136 -0
  41. package/tools/cli/commands/status.js +109 -2
  42. package/tools/cli/lib/ide-skills.js +1 -1
  43. package/tools/cli/lib/installer.js +20 -8
  44. package/tools/cli/lib/skill-parity.js +165 -0
  45. package/tools/ucg-npx-wrapper.js +0 -0
  46. package/tools/validate-docs-links.js +502 -0
  47. package/tools/validate-fixtures.js +161 -0
  48. package/website/README.md +1 -1
  49. package/website/astro.config.mjs +1 -1
  50. package/website/src/rehype-markdown-links.js +147 -70
@@ -19,7 +19,7 @@
19
19
  "name": "bmad-module-ultracode-goal",
20
20
  "source": "./",
21
21
  "description": "Supercharges BMAD with Claude Code Goal Mode, Auto Mode, and Auto Memory: autonomous Epic execution to a machine-checked, TEA-gated Definition-of-Done. Execute Epics. Accumulate Knowledge. Deliver Outcomes.",
22
- "version": "0.5.0",
22
+ "version": "1.0.0",
23
23
  "author": {
24
24
  "name": "Armel"
25
25
  },
package/README.md CHANGED
@@ -6,17 +6,17 @@
6
6
 
7
7
  **Run a BMAD Epic autonomously to a machine-checked Definition-of-Done.**
8
8
 
9
- [![Requires Claude Code](https://img.shields.io/badge/requires-Claude%20Code-D97757?logo=claude&logoColor=white)](https://www.anthropic.com/claude-code)
9
+ [![Requires Claude Code](https://img.shields.io/badge/requires-Claude%20Code-D97757?logo=claude&logoColor=white)](https://claude.com/product/claude-code)
10
10
  [![Quality & Validation](https://github.com/armelhbobdad/bmad-module-ultracode-goal/actions/workflows/quality.yaml/badge.svg)](https://github.com/armelhbobdad/bmad-module-ultracode-goal/actions/workflows/quality.yaml)
11
11
  [![npm](https://img.shields.io/npm/v/bmad-module-ultracode-goal)](https://www.npmjs.com/package/bmad-module-ultracode-goal)
12
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/MIT)
13
13
  [![BMAD Module](https://img.shields.io/badge/BMAD-module-blue)](https://github.com/bmad-code-org/BMAD-METHOD)
14
14
  [![Python Version](https://img.shields.io/badge/python-%3E%3D3.10-blue?logo=python&logoColor=white)](https://www.python.org)
15
15
  [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=uv)](https://docs.astral.sh/uv/)
16
16
  [![Docs](https://img.shields.io/badge/docs-online-green)](https://armelhbobdad.github.io/bmad-module-ultracode-goal/)
17
17
  [![GitHub stars](https://img.shields.io/github/stars/armelhbobdad/bmad-module-ultracode-goal?style=social)](https://github.com/armelhbobdad/bmad-module-ultracode-goal/stargazers)
18
18
 
19
- **Built for [Claude Code](https://www.anthropic.com/claude-code), and only Claude Code.** UCG composes `/goal`, Auto Mode, Auto Memory, and runtime hooks; the autonomous run itself requires Claude Code.
19
+ **Built for [Claude Code](https://claude.com/product/claude-code), and only Claude Code.** UCG composes `/goal`, Auto Mode, Auto Memory, and runtime hooks; the autonomous run itself requires Claude Code.
20
20
 
21
21
  _UCG is a standalone [BMAD](https://github.com/bmad-code-org/BMAD-METHOD) module that delivers a BMAD Epic end to end without a babysitter. It preflights to a remediated green light, turns acceptance criteria into executable tests with the Test Architect (TEA), and advances a story only when a deterministic script reads `PASS` from TEA's gate artifact, not when the model decides it feels done._
22
22
 
@@ -61,7 +61,7 @@ The `gate_status` comes straight from TEA's artifact: `gate_eval.py` never re-de
61
61
 
62
62
  ## Install
63
63
 
64
- Requires [Claude Code](https://www.anthropic.com/claude-code) (the runtime UCG conducts), [Node.js](https://nodejs.org/) >= 22, [Python](https://www.python.org/) >= 3.10, [uv](https://docs.astral.sh/uv/), plus `git` and `gh` on PATH.
64
+ Requires [Claude Code](https://claude.com/product/claude-code) (the runtime UCG conducts), [Node.js](https://nodejs.org/) >= 22, [Python](https://www.python.org/) >= 3.10, [uv](https://docs.astral.sh/uv/), plus `git` and `gh` on PATH.
65
65
 
66
66
  ```bash
67
67
  npx bmad-module-ultracode-goal install
@@ -80,6 +80,7 @@ Invoke the skill in natural language: "run this epic autonomously," "execute thi
80
80
  - `--yes`: skip Stage 1's open-floor invite and the launch confirm. It **never** skips the hard preflight gate.
81
81
  - `-H`: headless: run non-interactively and emit the five-key status JSON at every exit point.
82
82
  - `--retro`: run the close-out retrospective (interactive runs offer it anyway; headless runs it only when this flag is passed).
83
+ - `--max-stories N`: drive at most **N** stories in this invocation, then finish normally through the report and the terminal JSON. It bounds the work, not the scope: the Epic's in-scope set is untouched, so the next invocation resumes where this one stopped. `scripts/drive_epic.py` uses it to run one story per process, so a long Epic's context dies with each story.
83
84
 
84
85
  See [How It Works](./docs/how-it-works.md) for the full six-stage walkthrough, routing conditions, and the headless contract.
85
86
 
@@ -97,13 +98,13 @@ A skeptical reader is probably already running one of these. Here is the honest
97
98
 
98
99
  The alternatives aren't bad; they solve different problems. **UCG solves exactly one: advancing an epic only when a deterministic script confirms the gate passed, and giving you the verdict JSON to check it yourself.**
99
100
 
100
- UCG's closest peer is [bmad-auto](https://github.com/bmad-code-org/bmad-auto) (published under the bmad-code-org org), which makes the opposite architectural bet (a deterministic Python loop driving any CLI from outside the agent). For an honest, side-by-side look at where each one wins, see [UCG vs bmad-auto](https://armelhbobdad.github.io/bmad-module-ultracode-goal/comparison/).
101
+ UCG's closest peer is [bmad-loop](https://github.com/bmad-code-org/bmad-loop) (formerly bmad-auto, published under the bmad-code-org org), which makes the opposite architectural bet (a deterministic Python loop driving any CLI from outside the agent). For a side-by-side look at where each one wins, see [UCG vs bmad-loop](https://armelhbobdad.github.io/bmad-module-ultracode-goal/comparison/).
101
102
 
102
103
  ## Verifying
103
104
 
104
105
  You don't have to take the gate's word for it. The deterministic pieces ship with a test suite, and you can run the evaluator on a real artifact yourself.
105
106
 
106
- Run the Python suite (318 tests across the preflight, gate, hook, readiness, memory, and customization scripts):
107
+ Run the Python suite (600+ tests across the preflight, gate, hook, readiness, memory, and customization scripts):
107
108
 
108
109
  ```bash
109
110
  uv run --with pytest pytest skills/ultracode-goal/scripts/tests/ -v
@@ -148,8 +149,8 @@ UCG is a conductor over primitives it does not replace. It builds on:
148
149
  | Tool | Role in UCG |
149
150
  | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
150
151
  | [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) | The epic toolbox UCG orchestrates (sprint planning, story creation, dev, review) |
151
- | [TEA Test Architect](https://github.com/bmad-code-org/BMAD-METHOD) | Machine-checked quality gates: test-design, ATDD, NFR, trace; the gate artifact |
152
- | [Claude Code](https://www.anthropic.com/claude-code) | `/goal`, Auto Mode, Auto Memory, hooks, and git worktrees, the primitives UCG composes |
152
+ | [TEA Test Architect](https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise) | Machine-checked quality gates: test-design, ATDD, NFR, trace; the gate artifact |
153
+ | [Claude Code](https://claude.com/product/claude-code) | `/goal`, Auto Mode, Auto Memory, hooks, and git worktrees, the primitives UCG composes |
153
154
 
154
155
  ## Contributing
155
156
 
@@ -51,7 +51,7 @@ These must exist before the first `main`-dispatch release. Order matters.
51
51
 
52
52
  ### 1. Required-check contexts must exist
53
53
 
54
- Branch-protection rulesets can only require status checks that have reported at least once. Open any PR (or dispatch `quality.yaml` manually) so these seven contexts exist:
54
+ Branch-protection rulesets can only require status checks that have reported at least once. Open any PR (or dispatch `quality.yaml` manually) so these eight contexts exist:
55
55
 
56
56
  ```text
57
57
  prettier
@@ -61,8 +61,11 @@ validate (ubuntu-latest)
61
61
  validate (windows-latest)
62
62
  python (ubuntu-latest)
63
63
  python (windows-latest)
64
+ docs-links
64
65
  ```
65
66
 
67
+ This list is the setup seed, not the source of truth: the ruleset is. Whenever `quality.yaml` gains or renames a job, add the new context to the ruleset as well, or `main` silently loses that protection while every release still passes (the wait-for-checks step below reads the ruleset, so it waits only on what the ruleset names).
68
+
66
69
  ### 2. Main-branch ruleset
67
70
 
68
71
  Create a ruleset on `main` requiring the seven contexts above, with `bypass_actors` = Admin RepositoryRole, `bypass_mode: pull_request`. Then record its id in the repo variable the workflow reads:
@@ -20,11 +20,13 @@ The installer CLI is invoked via `npx bmad-module-ultracode-goal <subcommand>`.
20
20
 
21
21
  ### The `[workflow]` customize.toml keys
22
22
 
23
- The keys in the shipped `[workflow]` block of `customize.toml` (including `persistent_facts`, `tea_config_path`, `trace_output_dir`, `implementation_artifacts`, `deferred_work_path`, `epic_branch_prefix`, `protected_branches`, `max_turns_per_story`, `story_token_budget`, `parallel_max_concurrency`, `allowlist_commands`, and `on_epic_complete`) are the supported override surface. Teams and users override them in `_bmad/custom/ultracode-goal.toml` (and `.user.toml`) with base → team → user resolution (scalars override, tables deep-merge, arrays append). Renaming or removing a key, or changing how it resolves, is a contract change. See [architecture](../architecture.md).
23
+ The keys in the shipped `[workflow]` block of `customize.toml` (including `persistent_facts`, `tea_config_path`, `trace_output_dir`, `implementation_artifacts`, `deferred_work_path`, `epic_branch_prefix`, `protected_branches`, `max_turns_per_story`, `story_token_budget` (**deprecated, no-op**), `parallel_max_concurrency`, `allowlist_commands`, `on_epic_complete`, and `on_escalation`) are the supported override surface. Teams and users override them in `_bmad/custom/ultracode-goal.toml` (and `.user.toml`) with base → team → user resolution (scalars override, tables deep-merge, arrays append). Renaming or removing a key, or changing how it resolves, is a contract change. See [architecture](../architecture.md).
24
+
25
+ `story_token_budget` is **deprecated** as of the deprecation note in `CHANGELOG.md`: it is still shipped, still accepted, and still resolves, so existing overrides keep working and nothing errors. It is a no-op; no layer reads it any more. The runaway bound is turns only, via `max_turns_per_story`. The key stays enumerated here (and stays in `customize.toml`) precisely because removing it would be the contract break this section forbids.
24
26
 
25
27
  ### The headless five-key JSON emit shape
26
28
 
27
- Every headless (`-H`) exit point emits one object with exactly these five keys, always present, `null` when an artifact was not produced, `reason` carrying a one-line cause only when blocked:
29
+ Every headless (`-H`) exit point emits one object with exactly these five keys, always present, `null` when an artifact was not produced, plus a conditional sixth, `reason`, carrying a one-line cause only when blocked. A **complete** emit omits `reason` entirely; it is not present-and-`null`, so read it only when `status` is `blocked`:
28
30
 
29
31
  ```json
30
32
  {"status": "complete|blocked",
@@ -32,10 +34,21 @@ Every headless (`-H`) exit point emits one object with exactly these five keys,
32
34
  "decision_log": "<path>",
33
35
  "report": "<path or null>",
34
36
  "deferred_work": "<path or null>",
35
- "reason": "<one line when blocked, else null>"}
37
+ "reason": "<one line, present only when blocked; omitted on a complete emit>"}
36
38
  ```
37
39
 
38
- An automator parses this one schema regardless of where the run stopped. Changing a key name, adding or removing a key, or changing the `null`-when-absent guarantee is a contract change.
40
+ An automator parses this one schema regardless of where the run stopped. Changing a key name, adding or removing a key, changing the `null`-when-absent guarantee, or making `reason` present on a complete emit is a contract change.
41
+
42
+ ### The headless result file
43
+
44
+ A headless run writes that same object to `{workflow.implementation_artifacts}/run-result.json`, byte-identical to what it emitted on stdout, so an automator reads a pinned file path instead of scraping a transcript. Covered:
45
+
46
+ - **The path**: the basename `run-result.json` directly inside the resolved `{workflow.implementation_artifacts}`, with no run-id suffix and no subdirectory.
47
+ - **The contents**: the headless five-key emit shape above, unchanged.
48
+
49
+ - **The guarantee**: once a headless run resolves `{workflow.implementation_artifacts}` it clears any prior `run-result.json`, before any stage work. From that point on the file's presence means **this** run reached a terminal. The guarantee is scoped to that moment, so a consumer should still prefer a parseable stdout envelope when the file is absent.
50
+
51
+ Four documented exceptions, none of which is a contract break: a block that fires **before** `{workflow.implementation_artifacts}` resolves (the "not a BMAD project" stop) neither writes nor clears, so it leaves the stdout envelope as its sole output and is the one case where a prior run's file can survive; a terminal whose best-effort write failed leaves no file while still printing its envelope; a headless run that has not yet reached a terminal (still running, crashed, or killed) has no file, because startup cleared any prior one; and an **attended** run writes no file at all and clears none. The file is overwrite-in-place, so it carries no cross-run history, and under the experimental `--parallel` mode each worktree agent sees its own artifacts path, so no single `run-result.json` describes a fan-out run.
39
52
 
40
53
  ### The skill name and invocation phrases
41
54
 
@@ -45,8 +58,9 @@ The skill name `ultracode-goal` and its documented invocation phrases ("run an e
45
58
 
46
59
  `scripts/gate_eval.py` is the deterministic completion authority. Covered:
47
60
 
48
- - **CLI flags**: `--trace-output` (required), `--profile` (`light` | `production`, required), `--nfr`, `--test-review` (production only).
61
+ - **CLI flags**: `--trace-output` (required), `--profile` (`light` | `production`, required), `--story`, `--nfr`, `--test-review` (production only).
49
62
  - **Verdict vocabulary**: the `verdict` values `advance` / `defer` / `reloop` / `escalate`, and the `gate_status` values `PASS` / `CONCERNS` / `FAIL` / `WAIVED` / `NOT_EVALUATED`, plus the mapping between them. See the [gate model](../gate-model.md).
63
+ - **`--story` fail-closed resolution**: when `--story` matches no artifact in a trace dir whose reports or gate-decision files are named per story, the result is `NOT_EVALUATED` (so, `escalate`), never a fallback to another story's gate. A trace dir whose candidates are all generically named (`trace.md`, `gate-decision.json`) still resolves unscoped. Which file the resolver picks, and how it decides that a name carries a story id, are internal.
50
64
 
51
65
  The contractual mapping each `gate_status` resolves to:
52
66
 
@@ -71,7 +85,7 @@ Everything not enumerated above is `@internal` and may change in any `0.x` relea
71
85
  - **Reference file structure**: the `references/*.md` stage files' internal structure, step ordering, prose, and section headings. The stage *names* are referenced by the health-check fingerprint (see below) but the file contents are an authoring surface.
72
86
  - **Script internals**: the internal functions, regexes, and intermediate behavior of `preflight_check.py`, `gate_eval.py`, `health_check_fp.py`, and the hook scripts. The covered surface is `gate_eval.py`'s CLI and verdict vocabulary above; everything else (the `preflight_check.py` JSON shape, the fingerprint tuple format, the hook env-var names) is internal and may change.
73
87
  - **The experimental `--parallel` workflow**: `assets/execute-epic.workflow.js`, the `/ultracode-goal-execute` registration, its args binding, its return shape, and `parallel_max_concurrency`'s runtime behavior are explicitly experimental and excluded from the contract. See [parallel mode](../parallel-mode.md).
74
- - **`_bmad-output/` artifact layout**: run folders, the decision log, `run-report.md`, `run-status.json`, the deferred-work ledger, and the improvement queue are run outputs, not a downstream-consumable schema. The headless emit shape (covered above) is the supported way to locate these paths programmatically.
88
+ - **`_bmad-output/` artifact layout**, with one exception: run folders, the decision log, `run-report.md`, `run-status.json`, the deferred-work ledger, and the improvement queue are run outputs, not a downstream-consumable schema. **`run-result.json` is the exception and is covered** (see [the headless result file](#the-headless-result-file)); it is the one artifact in that tree an automator may pin against. The headless emit shape (covered above) is the supported way to locate the rest of these paths programmatically.
75
89
 
76
90
  ## SemVer note
77
91
 
@@ -17,24 +17,24 @@ Because it is a conductor, the truth of "is this done" lives in the artifacts it
17
17
 
18
18
  ## The three enforcement layers
19
19
 
20
- These are the module's non-negotiables. Each exists because the documented mechanics make the intuitive shortcut wrong (see [why](why-ultracode-goal.md)).
20
+ These are the module's non-negotiables. Each exists because the documented mechanics make the intuitive shortcut wrong (see [why](./why-ultracode-goal.md)).
21
21
 
22
22
  ### 1. Deterministic gate truth
23
23
 
24
- `scripts/gate_eval.py` reads TEA's `gate-decision.json` and maps its gate status to a routing verdict (`PASS`/`WAIVED` → advance, `CONCERNS` → defer, `FAIL` → reloop, `NOT_EVALUATED` → escalate). It never re-derives TEA's thresholds and never reads the transcript. The `/goal` evaluator that drives execution can only see what the run surfaces, it cannot open the gate file, so it is structurally incapable of being the completion authority. The script is. In production, two extra signals can only downgrade an `advance`, never lift a lower verdict. See the [gate model](gate-model.md) for the full mapping diagram, thresholds, and the fail-closed contract.
24
+ `scripts/gate_eval.py` reads TEA's `gate-decision.json` and maps its gate status to a routing verdict (`PASS`/`WAIVED` → advance, `CONCERNS` → defer, `FAIL` → reloop, `NOT_EVALUATED` → escalate). It never re-derives TEA's thresholds and never reads the transcript. The `/goal` evaluator that drives execution can only see what the run surfaces, it cannot open the gate file, so it is structurally incapable of being the completion authority. The script is. In production, two extra signals can only downgrade an `advance`, never lift a lower verdict. See the [gate model](./gate-model.md) for the full mapping diagram, thresholds, and the fail-closed contract.
25
25
 
26
26
  ### 2. Hooks as invariants
27
27
 
28
- Two invariants must hold for every commit, and neither can live in memory, which is context the model may or may not weigh:
28
+ A set of invariants must hold before the runtime lets a tool call through, and none of them can live in memory, which is context the model may or may not weigh:
29
29
 
30
- - **`scripts/hooks/guard_pretooluse.py`** (PreToolUse): inspects each `git commit`/`git push`. It denies the command on a protected branch, and denies a `git commit` when no tests-ran marker (`<impl-artifacts>/.tests-ran-<story_id>`) exists for the current story. It returns a `deny` decision in the hook JSON and also exits 2 with the reason on stderr so older clients that ignore the JSON still block.
31
- - **`scripts/hooks/budget_stop.py`** (Stop): counts turns and accumulated tokens for the current story against `max_turns_per_story` / `story_token_budget`. On overrun it writes an escalation marker and surfaces a message, then **lets the stop proceed**. Its documented limitation: a Stop hook fires only when Claude is already trying to stop, so it cannot interrupt a `/goal` condition mid-turn. The in-condition "stop after N turns" clause and the gate's re-loop budget are the real bounds; this hook is the third, defensive layer.
30
+ - **`scripts/hooks/guard_pretooluse.py`** (PreToolUse): inspects each `git commit`/`git push` and enforces six invariants. It denies the command on a protected branch; denies a `git commit` when no tests-ran marker (`<impl-artifacts>/.tests-ran-<story_id>`) exists for the current story; denies it when that marker's `baseline=<sha>` does not match the SHA the story recorded at start; denies it when the staged index is empty or unreadable; and denies it, when armed with `ULTRACODE_TEST_ARTIFACTS`, while the staged content of a checklist-enumerated acceptance test still contains `test.skip(`. A sixth invariant is not about git at all: it runs for every tool call, and while a run is active it denies claude-mem MCP calls and filesystem reach into `.claude-mem` unless the Cross-Session Recall latch is green. It returns a `deny` decision in the hook JSON and also exits 2 with the reason on stderr so older clients that ignore the JSON still block. The marker, freshness, staged-index, and recall-latch checks fail **closed**, denying on an input they cannot read. Two do not: the protected-branch check fails **open** when `git rev-parse` cannot report a branch, and the un-skip proof is out of scope entirely when `ULTRACODE_TEST_ARTIFACTS` is unset. The protected-branch check is also scoped to the **session's** working directory rather than the repository the command names, so it denies a `git commit`/`git push` aimed at another checkout whenever the session's own repo is on a protected branch.
31
+ - **`scripts/hooks/budget_stop.py`** (Stop): counts turns for the current story against `max_turns_per_story`. On overrun it writes an escalation marker and surfaces a message, then **lets the stop proceed**. Its documented limitation: a Stop hook fires only when Claude is already trying to stop, so it cannot interrupt a `/goal` condition mid-turn. The in-condition "stop after N turns" clause and the gate's re-loop budget are the real bounds; this hook is the third, defensive layer.
32
32
 
33
- Both hooks read their config from env first (so the conductor injects per-run values) and fall back to hardcoded defaults (`main`/`master`, `25`, `1_500_000`, `ultracode/epic-`). Because of that fallback, a `customize.toml` override **silently no-ops at the enforcement layer** unless the conductor passes it through the hook env, so preflight injects `ULTRACODE_PROTECTED_BRANCHES`, `ULTRACODE_IMPL_ARTIFACTS`, `ULTRACODE_MAX_TURNS`, `ULTRACODE_TOKEN_BUDGET`, and `ULTRACODE_EPIC_BRANCH_PREFIX`.
33
+ Both hooks read their config from env first (so the conductor injects per-run values) and fall back to hardcoded defaults (`main`/`master`, `25`, `ultracode/epic-`). Because of that fallback, a `customize.toml` override **silently no-ops at the enforcement layer** unless the conductor passes it through the hook env, so preflight injects `ULTRACODE_PROTECTED_BRANCHES`, `ULTRACODE_IMPL_ARTIFACTS`, `ULTRACODE_MAX_TURNS`, `ULTRACODE_EPIC_BRANCH_PREFIX`, and `ULTRACODE_TEST_ARTIFACTS`.
34
34
 
35
35
  ### 3. Budget enforcement
36
36
 
37
- A runaway story is bounded by three layers in order of authority: the **in-condition** "…or stop after N turns" clause inside the `/goal` condition (the real in-loop bound), the **gate re-loop budget** (a `reloop` that would exceed `max_turns_per_story` or `story_token_budget` becomes `escalate`), and the **Stop hook** as the defensive backstop described above. Rollback is git, not `/rewind` (an Epic branch off a protected branch, one commit per green story, worktree isolation under `--parallel`) because `/rewind` checkpoints miss the Bash-driven changes that make up the run.
37
+ A runaway story is bounded by three layers in order of authority: the **in-condition** "…or stop after N turns" clause inside the `/goal` condition (the real in-loop bound), the **gate re-loop budget** (a `reloop` that would exceed `max_turns_per_story` becomes `escalate`), and the **Stop hook** as the defensive backstop described above. Rollback is git, not `/rewind` (an Epic branch off a protected branch, one commit per green story, worktree isolation under `--parallel`) because `/rewind` checkpoints miss the Bash-driven changes that make up the run.
38
38
 
39
39
  ## File layout
40
40
 
@@ -56,7 +56,11 @@ skills/ultracode-goal/
56
56
  ├── scripts/ # Deterministic truth (run via `uv`)
57
57
  │ ├── preflight_check.py # mechanical preflight facts + blocker budget
58
58
  │ ├── gate_eval.py # gate status -> verdict (the completion authority)
59
+ │ ├── gate_trail.py # per-story evidence trail (gate-trail.md) at finalize
59
60
  │ ├── formalize_check.py # readiness kernel behind the /ucg-formalize gate
61
+ │ ├── status_render.py # read-side render behind /ucg-status
62
+ │ ├── red_ids.py # preflight-RED identity (the resolve join key)
63
+ │ ├── drive_epic.py # one `claude -p` per story (--max-stories work bound)
60
64
  │ ├── headless_envelope.py # the one five-key headless-envelope adapter
61
65
  │ ├── health_check_fp.py # health-check fingerprint + seen-cache plumbing
62
66
  │ ├── mem_observation.py # Cross-Session Recall write path (build/spill/drain)
@@ -67,16 +71,18 @@ skills/ultracode-goal/
67
71
  │ ├── lib/mem_common.py # shared Cross-Session Recall primitives
68
72
  │ └── hooks/
69
73
  │ ├── guard_pretooluse.py # commit invariants (PreToolUse)
70
- │ └── budget_stop.py # turn/token budget (Stop)
74
+ │ └── budget_stop.py # turn budget (Stop)
71
75
  ├── skills/
72
- └── ucg-formalize/ # Standalone readiness gate
76
+ ├── ucg-formalize/ # Standalone readiness gate
77
+ │ ├── ucg-resolve/ # Decide-surface for a blocked or escalated run
78
+ │ └── ucg-status/ # Read-only status view over a run
73
79
  └── assets/
74
80
  ├── execute-epic.workflow.js # EXPERIMENTAL --parallel worktree fan-out
75
81
  ├── module.yaml · module-setup.md · module-help.csv # install metadata
76
82
  └── ucg-awareness/ # shift-left planning customization fragments
77
83
  ```
78
84
 
79
- `SKILL.md` carries the routing and the contract; the `references/*.md` files carry each stage's procedure and testable routing conditions; the `scripts/*.py` files carry the deterministic facts the model cannot fudge (the gate, preflight, readiness kernel, hooks, and the install-time/recall plumbing); the `skills/ucg-formalize/` subskill is the standalone readiness gate; and the `assets/` hold the experimental `--parallel` workflow plus install metadata and the planning-customization fragments. See [how it works](how-it-works.md) for the stages and [parallel mode](parallel-mode.md) for the workflow asset.
85
+ `SKILL.md` carries the routing and the contract; the `references/*.md` files carry each stage's procedure and testable routing conditions; the `scripts/*.py` files carry the deterministic facts the model cannot fudge (the gate, preflight, readiness kernel, hooks, and the install-time/recall plumbing); the `skills/` subskills are the operator-facing surfaces (`ucg-formalize` the standalone readiness gate, `ucg-resolve` the decide-surface for a stopped run, `ucg-status` the read-only run view); and the `assets/` hold the experimental `--parallel` workflow plus install metadata and the planning-customization fragments. See [how it works](./how-it-works.md) for the stages and [parallel mode](./parallel-mode.md) for the workflow asset.
80
86
 
81
87
  ## Customization resolution
82
88
 
@@ -86,7 +92,7 @@ Configuration resolves in three layers, base → team → user, via `resolve_cus
86
92
  2. **Team**: `{project-root}/_bmad/custom/ultracode-goal.toml`.
87
93
  3. **User**: `{project-root}/_bmad/custom/ultracode-goal.user.toml`.
88
94
 
89
- Merge semantics: **scalars override**, **tables deep-merge**, **arrays append**. At activation the skill runs `resolve_customization.py --skill {skill-root} --key workflow`; if that fails, it resolves the three files itself in the same order. The shipped base layer defines the run's knobs: the TEA/artifact paths (`tea_config_path`, `trace_output_dir`, `implementation_artifacts`, `deferred_work_path`), the git guardrails (`epic_branch_prefix`, `protected_branches`), the budgets (`max_turns_per_story`, `story_token_budget`), the experimental `parallel_max_concurrency`, the `allowlist_commands`, and the `on_epic_complete` hook. Teams and users override without editing the shipped file. Remember that a budget or branch override only reaches the *enforcement* layer because preflight threads it into the hook env (see layer 2 above).
95
+ Merge semantics: **scalars override**, **tables deep-merge**, **arrays append**. At activation the skill runs `resolve_customization.py --skill {skill-root} --key workflow`; if that fails, it resolves the three files itself in the same order. The shipped base layer defines the run's knobs: the TEA/artifact paths (`tea_config_path`, `trace_output_dir`, `implementation_artifacts`, `deferred_work_path`), the git guardrails (`epic_branch_prefix`, `protected_branches`), the turn budget (`max_turns_per_story`; `story_token_budget` remains as a deprecated no-op key), the experimental `parallel_max_concurrency`, the `allowlist_commands`, and the `on_epic_complete` hook. Teams and users override without editing the shipped file. Remember that a budget or branch override only reaches the *enforcement* layer because preflight threads it into the hook env (see layer 2 above).
90
96
 
91
97
  The three TOML layers merge once, but a branch or budget value then travels two ways: the conductor reads it directly, while the hooks only see it if preflight re-injects it as env:
92
98
 
@@ -108,4 +114,4 @@ flowchart LR
108
114
 
109
115
  ## Why the hooks live in settings.local.json
110
116
 
111
- The PreToolUse and Stop hooks are auto-merged into `{project-root}/.claude/settings.local.json` (machine-local, gitignored, honored after the workspace trust dialog), not into a committed settings file or memory. The reasoning: these hooks are **enforcement, not context**. A committed hook would impose this module's commit guard on every contributor and every unrelated session in the repo; a hook in memory would not block a commit at all. The machine-local file scopes enforcement to the machine actually running the unattended Epic, and the gitignore keeps it out of shared history. The skill re-merges them every run (idempotently) and asserts they are active before the run goes unattended; it does not assume a prior run left them in place. Because the file is machine-local and executes on your machine, review what is merged; see [SECURITY.md](../SECURITY.md).
117
+ The PreToolUse and Stop hooks are auto-merged into `{project-root}/.claude/settings.local.json` (machine-local, gitignored, honored after the workspace trust dialog), not into a committed settings file or memory. The reasoning: these hooks are **enforcement, not context**. A committed hook would impose this module's commit guard on every contributor and every unrelated session in the repo; a hook in memory would not block a commit at all. The machine-local file scopes enforcement to the machine actually running the unattended Epic, and the gitignore keeps it out of shared history. The skill re-merges them every run (idempotently) and asserts they are active before the run goes unattended; it does not assume a prior run left them in place. Because the file is machine-local and executes on your machine, review what is merged; see [SECURITY.md](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/SECURITY.md).
@@ -1,81 +1,83 @@
1
1
  ---
2
- title: UCG vs bmad-auto
3
- description: An honest, side-by-side comparison of UltraCode Goal and bmad-code-org's bmad-auto orchestrator, including where bmad-auto is the better choice and which to reach for when.
2
+ title: UCG vs bmad-loop
3
+ description: An honest, side-by-side comparison of UltraCode Goal and bmad-code-org's bmad-loop orchestrator (formerly bmad-auto), including where bmad-loop is the better choice and which to reach for when.
4
4
  ---
5
5
 
6
- Both UltraCode Goal (UCG) and [bmad-auto](https://github.com/bmad-code-org/bmad-auto) automate the BMAD implementation phase without a babysitter. They are siblings, not clones: they make opposite bets on where the control loop lives and how completion is judged. This page compares them honestly, including the places where bmad-auto is the better tool.
6
+ Both UltraCode Goal (UCG) and [bmad-loop](https://github.com/bmad-code-org/bmad-loop) (formerly bmad-auto; renamed at v0.8.0) automate the BMAD implementation phase without a babysitter. They are siblings, not clones: they make opposite bets on where the control loop lives and how completion is judged. This page compares them honestly, including the places where bmad-loop is the better tool.
7
7
 
8
- Snapshot: UCG v0.4.0 and bmad-auto v0.7.4, both as of 2026-06-28. Both projects are young and moving fast, so treat every line below as a point-in-time reading and verify the current state for yourself (links at the bottom).
8
+ Snapshot: UCG v0.5.1 and bmad-loop v0.9.0, as of 2026-07-28, both released versions. Both projects are young and moving fast. bmad-loop's v0.9.0 (released 2026-07-21) shipped everything the previous snapshot listed as unreleased work on main: a `stories.yaml` planning mode with per-story checkpoints, patch-restore escalation recovery, a pluggable multiplexer-backend registry, the extra adversarial review hunters, and the integrity fixes to its verify gate. It also added a graceful stop that finishes the in-flight item before ending a run, an active-agent indicator in the dashboard, an OpenCode adapter driven over HTTP rather than tmux, and stable, schema-versioned `--json` documents for `status`, `list`, `validate`, `decisions`, `clean`, and `cleanup`. Roughly half its commands are machine-readable now, with the rest tracked upstream, so scripting it no longer means scraping the human text. Treat every line below as a point-in-time reading and verify the current state for yourself (links at the bottom).
9
9
 
10
10
  ## The one difference everything else follows from
11
11
 
12
- bmad-auto puts the control loop in **plain Python, outside the agent**. A deterministic orchestrator picks the next story, spawns a fresh, disposable coding-agent session (over tmux) for each step, watches structured hook events the session writes, and decides retries, gates, and completion in code. No LLM sits in the control loop.
12
+ bmad-loop puts the control loop in **plain Python, outside the agent**. A deterministic orchestrator picks the next story, spawns a fresh, disposable coding-agent session (over tmux) for each step, watches structured hook events the session writes, and decides retries, gates, and completion in code. No LLM sits in the control loop.
13
13
 
14
- UCG puts the control loop **inside Claude Code**. The run is a Claude Code skill that composes `/goal`, Auto Mode, runtime hooks, and dynamic workflows. The per-story loop is paced by Claude Code's `/goal` evaluator (an LLM), while the binding completion verdict is a deterministic script (`gate_eval.py`) that reads the Test Architect's gate artifact.
14
+ UCG puts the control loop **inside Claude Code**. The run is a Claude Code skill that composes `/goal`, Auto Mode, runtime hooks, and dynamic workflows. The per-story loop is paced by Claude Code's `/goal` evaluator (an LLM), while the binding completion verdict is a deterministic script (`gate_eval.py`) that reads the Test Architect's (TEA) gate artifact.
15
15
 
16
- The consequence cascades: bmad-auto is a tool you run beside any supported agent; UCG is a capability that lives within one specific agent.
16
+ The consequence cascades: bmad-loop is a tool you run beside any supported agent; UCG is a capability that lives within one specific agent.
17
17
 
18
18
  ## At a glance
19
19
 
20
- | Dimension | bmad-auto | UltraCode Goal (UCG) |
20
+ | Dimension | bmad-loop | UltraCode Goal (UCG) |
21
21
  |---|---|---|
22
- | Runtime | External Python process plus tmux; Linux, macOS, or WSL | A skill inside Claude Code; no external process, no tmux |
22
+ | Runtime | External Python process plus tmux; Linux, macOS, or WSL (native Windows is planned) | A skill inside Claude Code; no daemon, no tmux; runs anywhere Claude Code runs. One optional exception: a small driver script that runs one session per story on long Epics |
23
23
  | Control loop | Deterministic Python, no LLM in the loop | LLM-paced `/goal` spine with a deterministic completion gate |
24
- | Agent / CLI | claude, codex, gemini, copilot (mix per stage) | Claude Code only |
25
- | Scope | Implementation phase: `ready-for-dev` stories through dev, review, verify, commit | Whole Epic: planning-readiness preflight, ATDD test generation, execute, TEA gate, finalize |
26
- | Completion authority | On-disk artifact checks plus your test and lint commands | TEA quality gate (`gate-decision.json`: P0/P1/overall, NFR, test-review) read by `gate_eval.py` |
27
- | Test strategy | Your `[verify].commands` plus adversarial review hunters | ATDD: acceptance criteria become executable red-phase tests driven to green; TEA traceability |
28
- | Pre-launch gate | `validate` (config, git, tmux, CLI, hooks) | `validate` plus a semantic scan that refuses to launch on an undecided product or architecture decision |
29
- | Observability | Rich Textual TUI: dashboard, attach to live sessions, journal, token totals | Files: `.decision-log.md`, a `run-status.json` heartbeat, a transcript ticker, the `/workflows` view |
24
+ | Agent / CLI | claude, codex, gemini, copilot, antigravity, opencode (mix per stage) | Claude Code only |
25
+ | Scope | Implementation phase: `backlog` and `ready-for-dev` stories through dev, review, verify, commit | Whole Epic: planning-readiness preflight, ATDD (acceptance-test-driven development) test generation, execute, TEA gate, finalize |
26
+ | Completion authority | Checks on the spec and result artifacts, a proof-of-work diff, and your test and lint commands; opt-in TEA gate steps via a bundled plugin (advisory by default) | TEA quality gate: `gate-decision.json` (P0/P1/overall), combined in the default profile with NFR and test-review artifacts, read fail-closed by `gate_eval.py` |
27
+ | Test strategy | Your `[verify].commands` plus adversarial review hunters; opt-in TEA test-design and ATDD workflows via the bundled plugin | ATDD: acceptance criteria become executable red-phase tests driven to green; TEA traceability |
28
+ | Pre-launch gate | `validate` (config, sprint-status, git, multiplexer, CLI, hooks, base skills) | A mechanical preflight script plus a readiness check and a semantic scan that refuse to launch on an undecided product or architecture decision |
29
+ | Observability | A live terminal dashboard (built with Textual): runs table, attach to live sessions, journal, cost-weighted token totals | Files: `.decision-log.md`, a `run-status.json` heartbeat, a transcript ticker, the `/workflows` view |
30
30
  | Deferred work | A triage-and-execute **sweep** engine plus a decisions workflow | An append-only ledger surfaced at finalize; no execute engine |
31
- | Escalation | Typed (CRITICAL / PREFERENCE) plus an interactive resolve agent | An escalate verdict and a blocked headless envelope; resume from the decision log |
32
- | Isolation | Opt-in git worktree per story or bundle, merged back locally | Sequential by default; an experimental `--parallel` worktree fan-out |
33
- | Extensibility | A plugin system plus a Unity game-engine plugin | `customize.toml` knobs and planning-shaping fragments |
31
+ | Escalation | Typed (CRITICAL / PREFERENCE) plus an interactive resolve agent | An escalate verdict and a machine-readable blocked report (the headless envelope); resume from the decision log |
32
+ | Isolation | In place by default; opt-in git worktree per story or bundle, merged back locally | None by default (stories run sequentially in one session); an experimental `--parallel` mode fans stories out into git worktrees |
33
+ | Extensibility | A plugin system (observe, veto, mutate) with bundled TEA and Unity plugins | `customize.toml` knobs and planning-shaping fragments |
34
34
  | Self-improvement | Not shipped | A health check that files deduplicated GitHub issues about its own friction |
35
- | Maturity | First-party (bmad-code-org); v0.7.4; rich docs; CI + test suite | Community module; v0.4.0; docs site; CI + test suite |
35
+ | Maturity | First-party (bmad-code-org); v0.9.0; rich docs; CI + test suite | Community module; v0.5.1; docs site; CI + test suite |
36
36
  | License | MIT | MIT |
37
37
 
38
- ## Where bmad-auto is stronger
38
+ ## Where bmad-loop is stronger
39
39
 
40
40
  This is a genuinely strong tool; pretending otherwise would make this page useless.
41
41
 
42
- 1. **A deterministic control loop.** Story selection, retry budgets, gates, and completion checks are ordinary Python, so they are debuggable, reproducible, and cost no tokens. UCG's `/goal` pacing is LLM-driven and only its final completion gate is deterministic. If you want zero LLM judgment in the orchestration itself, bmad-auto is the cleaner model.
43
- 2. **Agent portability.** It drives claude, codex, gemini, or GitHub Copilot CLI, and can run dev on one model and review on another via per-stage profiles. UCG is deliberately Claude Code only.
44
- 3. **Observability and control.** A live Textual TUI gives you a runs dashboard, a sprint tree, the deferred-work ledger, per-story token totals, attach-to-session, and a policy editor. UCG's window into a run is files and the transcript.
45
- 4. **A deferred-work engine, not just a ledger.** `bmad-auto sweep` triages the ledger against the real code, bundles cohesive work, executes it, and has a decisions workflow for the human calls. UCG appends to a ledger and surfaces it at the end; acting on it is manual.
46
- 5. **Extensibility and reach.** A real plugin system (observe, veto, mutate the cycle) and a Unity game-engine integration. UCG exposes configuration knobs, not a plugin API.
47
- 6. **Operational maturity.** Disk reclamation (clean and archive, retention windows, worktree teardown), cost-weighted token budgets that discount cache reads, an adapter-authoring path for new CLIs, and the backing of the bmad-code-org org.
42
+ 1. **A deterministic control loop.** Story selection, retry budgets, gates, and completion checks are ordinary Python, so they are debuggable, reproducible, and cost no tokens. UCG's `/goal` pacing is LLM-driven; its deterministic pieces (the per-story and epic-level gate reads, the preflight scripts, the commit-guard and budget hooks) bound the loop rather than run it. If you want zero LLM judgment in the orchestration itself, bmad-loop is the cleaner model.
43
+ 2. **Agent portability.** It drives claude, codex, gemini, GitHub Copilot CLI, antigravity, or OpenCode, and can run dev on one model and review on another via per-stage profiles. UCG is deliberately Claude Code only.
44
+ 3. **Observability and control.** A live terminal UI (built with Textual) gives you a runs dashboard, a sprint tree, the deferred-work ledger, per-story token totals, attach-to-session, and a policy editor. UCG's window into a run is files and the transcript.
45
+ 4. **A deferred-work engine, not just a ledger.** `bmad-loop sweep` triages the ledger against the real code, bundles cohesive work, executes it, and has a decisions workflow for the human calls. UCG appends to a ledger and surfaces it at the end; acting on it is manual.
46
+ 5. **Extensibility and reach.** It has a real plugin system (observe, veto, mutate the cycle) with bundled plugins: a TEA plugin that can add Test Architect workflows to its pipeline, and a Unity game-engine integration. UCG exposes configuration knobs, not a plugin API.
47
+ 6. **Operational maturity.** It ships disk reclamation (clean and archive, retention windows, worktree teardown), cost-weighted token budgets that discount cache reads, and an adapter-authoring path for new CLIs, and it carries the backing of the bmad-code-org org.
48
48
 
49
49
  ## Where UCG is stronger
50
50
 
51
- 1. **Completion gated on formal traceability, not on build-and-review alone.** UCG's completion authority is the Test Architect's gate: a traceability matrix that holds acceptance criteria to hard thresholds (P0 = 100%, P1 >= 90%, overall >= 80%), ANDed in production with an NFR assessment and a test-review score. bmad-auto's gate is strict but differently shaped: your test and lint commands, a non-empty diff, an independent baseline-commit check, the spec marked done, and two adversarial review hunters. What UCG adds is the requirement that every acceptance criterion is demonstrably traced to a passing test at those thresholds, which bmad-auto does not compute.
52
- 2. **ATDD-first.** UCG turns each story's acceptance criteria into executable, red-phase (`test.skip`) tests before any code is written, then drives them to green. The acceptance tests are a first-class generated artifact, not a by-product. bmad-auto relies on the dev skill's own implementation plus the test commands you supply.
53
- 3. **A planning-readiness gate that can refuse to launch.** UCG's preflight hands a read of the PRD, architecture, and stories to a throwaway subagent that hunts undecided product or architecture decisions, PRD-versus-architecture contradictions, and an undefinable "done". Any such RED stops the run rather than letting an unattended agent guess. bmad-auto's preflight is mechanical (config, git, tmux, CLI, hooks); it assumes the sprint's stories are already ready to build.
54
- 4. **No moving parts outside the agent.** UCG is a skill: no external daemon, no tmux, no separate process to attach to. For a Claude Code user that is a smaller operational surface, and it is also exactly why UCG cannot run anywhere else.
51
+ 1. **The TEA gate is the default, binding completion authority, not an opt-in layer.** UCG's completion authority is the Test Architect's gate: a traceability matrix that holds acceptance criteria to hard thresholds (P0 coverage at 100%, P1 at 90% or above, overall at 80% or above). UCG's default profile combines that verdict with an NFR (non-functional requirements) assessment and a test-review score, and `gate_eval.py` reads the result fail-closed: a missing or unreadable signal downgrades the verdict, never upgrades it. Since v0.5.0 the default sequential path also re-runs the full test, lint, and build suite on each story's committed HEAD before advancing, so a story that is green pre-commit but red once its new files are tracked cannot slip through to the gate.
52
+
53
+ bmad-loop can reach similar territory, but differently. Its default gate is checks on the spec and result artifacts, a proof-of-work diff (the commit must contain real changes since the story's baseline), and your test and lint commands; its bundled TEA plugin can add trace, NFR, and test-review steps before every commit. That plugin is opt-in, its gate steps ship advisory (non-blocking), and they fail open when an artifact is missing or unparseable. That gap narrowed in v0.9.0: at v0.8.1 bmad-loop's independent baseline-commit cross-check could not actually fire, because it read a spec key the dev skill does not write, so a spec claiming a stale or foreign baseline sailed through; v0.9.0 fixed it to accept either key and re-cut the test fixture that had been fabricating the missing one. The advisory-by-default and fail-open-on-missing-artifact properties of the TEA plugin's gate steps are unchanged. If you want acceptance-criterion-to-test traceability enforced by default, fail-closed, with nothing to configure, that is UCG's defining bet.
54
+ 2. **ATDD-first.** UCG turns each story's acceptance criteria into executable acceptance tests (scaffolded as red-phase `test.skip` placeholders) before any code is written, then un-skips them and drives them to green. The acceptance tests are a first-class generated artifact, not a by-product. One scope note: TEA's ATDD generator targets web and E2E stacks; on a non-web stack UCG's preflight steers the run to `--light`, where the story's acceptance criteria (not generated tests) are the trace oracle, or you author the acceptance tests in the stack's own harness. bmad-loop's default pipeline relies on whatever tests the dev skill writes while implementing, plus the test commands you supply; TEA test generation exists there only as an opt-in plugin step that runs after dev, not as the default path.
55
+ 3. **A planning-readiness gate that can refuse to launch.** UCG's preflight hands the PRD, the architecture, and the stories to a throwaway subagent that hunts for undecided product or architecture decisions, contradictions between the PRD and the architecture, and any story whose "done" cannot be pinned down. The scan grades what it finds, and any RED verdict stops the run rather than letting an unattended agent guess. That scan is itself LLM judgment, the very thing bmad-loop keeps out of its loop; the difference is that it can only block a launch, never pass one. bmad-loop's preflight is mechanical (config, sprint-status, git, multiplexer, CLI, hooks, skill presence); it assumes the sprint's stories are already ready to build.
56
+ 4. **Almost no moving parts outside the agent.** UCG is a skill: no daemon, no tmux, no session to attach to. For a Claude Code user that is a smaller operational surface, and it is also exactly why UCG cannot run anywhere else. The one qualifier, added honestly: a long Epic accumulates every story's transcript in one session, so UCG ships an optional driver script that spawns one `claude -p` per story under a `--max-stories` work bound. Use it and you are running a loop outside the agent after all, which is bmad-loop's model in miniature. The difference is that it is opt-in and about 600 lines, where bmad-loop's orchestrator is the product; skip it and the skill still runs standalone.
55
57
  5. **A self-improvement loop.** UCG's finalize step can file deduplicated GitHub issues about friction in its own workflow, so the tool reports its own rough edges.
56
58
 
57
59
  ## What they share
58
60
 
59
- - A deterministic completion authority the model cannot talk its way past: bmad-auto's on-disk artifact and command checks plus its baseline-commit "lie detector"; UCG's TEA gate read.
61
+ - A deterministic completion authority the model cannot talk its way past: bmad-loop's artifact, diff, and command checks; UCG's TEA gate read (on UCG's non-web `--light` path the trace artifacts are agent-authored under strict honesty rules, so the guarantee there is procedural rather than mechanical).
60
62
  - Fresh-context review separated from implementation, to kill self-review anchoring bias.
61
63
  - Adversarial review passes, bounded so they cannot oscillate forever.
62
64
  - Optional git worktree isolation.
63
- - Resumable runs and per-story token budgets.
65
+ - Resumable runs with a per-story budget: bmad-loop's is a cost-weighted token ceiling that discounts cache reads; UCG's is a turn cap, encoded in the `/goal` condition and enforced at the gate (a re-loop that would exceed the budget escalates instead).
64
66
  - `sprint-status.yaml` as planning truth, owned by the BMAD skills; both build on BMAD-METHOD.
65
67
 
66
68
  ## Which to reach for
67
69
 
68
- Choose **bmad-auto** if you use codex, gemini, or GitHub Copilot CLI (or want to mix models per stage), you want a code-only orchestrator you can step through and debug, you want a live dashboard and attach-to-session control, you have a backlog of deferred work to triage and sweep, you need plugin extensibility or game-engine support, or you want the tool published under the bmad-code-org org.
70
+ Choose **bmad-loop** if you use codex, gemini, or GitHub Copilot CLI (or want to mix models per stage), you want a code-only orchestrator you can step through and debug, you want a live dashboard and attach-to-session control, you have a backlog of deferred work to triage and sweep, you need plugin extensibility or game-engine support, or you prefer a first-party tool maintained under the bmad-code-org org.
69
71
 
70
- Choose **UCG** if you are on Claude Code, you want completion judged by the Test Architect's traceability thresholds (every acceptance criterion traced to a passing test) rather than by build-and-review checks, you want acceptance criteria compiled into executable tests up front, you want a run that refuses to start while a product or architecture decision is still undecided, or you want a single skill with no external process to operate.
72
+ Choose **UCG** if you are on Claude Code and any of these fit: you want the Test Architect's gate as the default, binding, fail-closed completion authority (every P0 criterion traced to a passing test, with P1 at 90% or above and overall at 80% or above) rather than an opt-in layer; you want acceptance criteria compiled into executable tests up front; you want a run that refuses to start while a product or architecture decision is still undecided; or you want a single skill with nothing to operate beside it (with the optional per-story driver above as the one exception, for Epics long enough that one session's context becomes the problem).
71
73
 
72
- They are not mutually exclusive. Both read the same `sprint-status.yaml` and BMAD artifacts, so you can plan and gate an Epic UCG's way and grind a deferred-work backlog bmad-auto's way in the same project.
74
+ They are not mutually exclusive. Both read the same `sprint-status.yaml` and BMAD artifacts, so you can plan and gate an Epic UCG's way and grind a deferred-work backlog bmad-loop's way in the same project.
73
75
 
74
76
  ## Verify this yourself
75
77
 
76
78
  Both tools change weekly, so re-check before you rely on anything above:
77
79
 
78
- - bmad-auto: its [README](https://github.com/bmad-code-org/bmad-auto), [docs/FEATURES.md](https://github.com/bmad-code-org/bmad-auto/blob/main/docs/FEATURES.md), and [docs/ROADMAP.md](https://github.com/bmad-code-org/bmad-auto/blob/main/docs/ROADMAP.md).
79
- - UCG: [How It Works](how-it-works.md) and the [Gate Model](gate-model.md).
80
+ - bmad-loop: its [README](https://github.com/bmad-code-org/bmad-loop), [docs/FEATURES.md](https://github.com/bmad-code-org/bmad-loop/blob/main/docs/FEATURES.md), and [docs/ROADMAP.md](https://github.com/bmad-code-org/bmad-loop/blob/main/docs/ROADMAP.md).
81
+ - UCG: [How It Works](./how-it-works.md) and the [Gate Model](./gate-model.md).
80
82
 
81
- This snapshot was taken on 2026-06-28 against bmad-auto v0.7.4 and UCG v0.4.0.
83
+ This snapshot was re-cut on 2026-07-28 against bmad-loop v0.9.0 (released 2026-07-21) and UCG v0.5.1; the previous cut (2026-07-12) read bmad-loop v0.8.1, and the one before it (2026-06-28, bmad-auto v0.7.4 and UCG v0.4.0) predates the rename.
@@ -57,7 +57,7 @@ What the sanitizer **does** before any advisory is surfaced:
57
57
  What it honestly does **not** do:
58
58
 
59
59
  - It is **not** a complete secret scrubber: redaction is high-precision pattern matching, not a guarantee that nothing sensitive ever survives.
60
- - It does **not** vote. Advisories carry only a mechanical `recurred` field (`yes`/`no`/`unknown`); there are no LLM self-grades, and nothing recall surfaces is ever an input to `gate_eval.py`. The gate reads TEA's `gate-decision.json` and only that. See the [gate model](gate-model.md).
60
+ - It does **not** vote. Advisories carry only a mechanical `recurred` field (`yes`/`no`/`unknown`); there are no LLM self-grades, and nothing recall surfaces is ever an input to `gate_eval.py`. The gate reads TEA's `gate-decision.json` and only that. See the [gate model](./gate-model.md).
61
61
  - It does **not** keep working when claude-mem looks wrong. If the capability contract fails (a missing tool, a malformed probe, a breaking schema change) the latch records recall as absent and the hook denies claude-mem calls for the run. Fail closed, never fail open.
62
62
 
63
63
  ## Turning it on
@@ -3,7 +3,7 @@ title: Gate Model
3
3
  description: How gate_eval.py turns TEA's gate-decision.json into a fail-closed advance, defer, reloop, or escalate verdict.
4
4
  ---
5
5
 
6
- Completion in UltraCode Goal is decided by a deterministic artifact read, not by judgment. `scripts/gate_eval.py` reads TEA's `gate-decision.json` and returns a routing verdict the skill executes. This page documents the verdict mapping, the production AND, the thresholds, the fail-closed contract, and why the `/goal` evaluator alone is insufficient, all traced to [`../skills/ultracode-goal/scripts/gate_eval.py`](../skills/ultracode-goal/scripts/gate_eval.py).
6
+ Completion in UltraCode Goal is decided by a deterministic artifact read, not by judgment. `scripts/gate_eval.py` reads TEA's `gate-decision.json` and returns a routing verdict the skill executes. This page documents the verdict mapping, the production AND, the thresholds, the fail-closed contract, and why the `/goal` evaluator alone is insufficient, all traced to [`../skills/ultracode-goal/scripts/gate_eval.py`](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/skills/ultracode-goal/scripts/gate_eval.py).
7
7
 
8
8
  ## What the gate reads
9
9
 
@@ -13,6 +13,8 @@ The script resolves the gate artifact from the trace output directory:
13
13
  2. If that slim file is absent, it falls back to the always-written `e2e-trace-summary.json` and lifts the gate fields from it. **The slim file's absence is normal, not a failure**: TEA only writes it when the run is gate-eligible and the decision is PASS/CONCERNS/FAIL/WAIVED.
14
14
  3. If neither file is present, or the run carries no gate fields, `gate_status` is `NOT_EVALUATED`.
15
15
 
16
+ **`--story` scopes that resolution, and fails closed when it matches nothing.** Because one run gates many stories, the trace directory usually names its artifacts per story (`trace-2-1.md`, `gate-decision-4.json`). Passing `--story <id>` selects that story's artifacts. If the directory is named per story and the id matches none of them, the script does **not** fall back to an unscoped read: it returns `NOT_EVALUATED` with a reason naming the absent story, which routes to `escalate`. That matters because the fallback used to fire, so a story that produced no trace artifacts at all silently resolved a *neighbouring* story's decision and could report `PASS` / `advance` having been evaluated by nothing. The documented single-story fallback is untouched: a directory whose candidates are all generically named (`trace.md`, `gate-decision.json`) still resolves unscoped, so a single-story trace directory behaves exactly as it always did. The Epic-level gate is not that case: it passes the epic's own id via `--story` and matches it against trailing name components, so epic `4` resolves `gate-decision-4.json` and never its child story `4-1`, and an epic with no artifact of its own escalates rather than borrowing one.
17
+
16
18
  The script never re-derives TEA's thresholds; it reads `gate_status` as given by the trace workflow.
17
19
 
18
20
  How the script resolves an artifact into a `gate_status`:
@@ -148,4 +150,4 @@ The same `PASS` gate, but with a test review scoring 74, downgrades to `reloop`;
148
150
 
149
151
  ## Why the `/goal` evaluator alone is insufficient
150
152
 
151
- The `/goal` loop that drives Execute ends with an evaluator confirming the success condition, but that evaluator only sees the transcript. It cannot open `gate-decision.json`. So it can confirm "the tests I was shown printed green" but not "TEA's deterministic gate read PASS against the traceability matrix and the NFR thresholds." Letting it be the completion authority would let the run grade itself from its own notes. `gate_eval.py` reads the file the model cannot author, which is exactly why it, and not the transcript evaluator, decides. See [why](why-ultracode-goal.md) and the routing detail in [`references/gate.md`](../skills/ultracode-goal/references/gate.md).
153
+ The `/goal` loop that drives Execute ends with an evaluator confirming the success condition, but that evaluator only sees the transcript. It cannot open `gate-decision.json`. So it can confirm "the tests I was shown printed green" but not "TEA's deterministic gate read PASS against the traceability matrix and the NFR thresholds." Letting it be the completion authority would let the run grade itself from its own notes. `gate_eval.py` reads the file the model cannot author, which is exactly why it, and not the transcript evaluator, decides. See [why](./why-ultracode-goal.md) and the routing detail in [`references/gate.md`](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/skills/ultracode-goal/references/gate.md).
@@ -11,15 +11,16 @@ UltraCode Goal conducts BMAD and TEA skills and runs deterministic Python under
11
11
 
12
12
  | Tool | Required for | Install |
13
13
  |------|--------------|---------|
14
- | Claude Code | **The runtime: non-negotiable.** UCG composes `/goal`, Auto Mode, Auto Memory, and runtime hooks, which only exist in Claude Code; the autonomous run cannot execute anywhere else | <https://www.anthropic.com/claude-code> |
14
+ | Claude Code | **The runtime: non-negotiable.** UCG composes `/goal`, Auto Mode, Auto Memory, and runtime hooks, which only exist in Claude Code; the autonomous run cannot execute anywhere else | <https://claude.com/product/claude-code> |
15
15
  | Node.js >= 22 | Installation, `npx` commands | <https://nodejs.org> |
16
16
  | Python >= 3.10 | The deterministic gate, preflight, and hook scripts (run via `uv`) | <https://www.python.org> |
17
17
  | `uv` | Running the module's Python scripts with automatic dependency management | <https://docs.astral.sh/uv/> |
18
18
  | `git` | Epic-branch isolation and per-story commits (the real rollback) | <https://git-scm.com> |
19
- | `gh` (GitHub CLI) | Submitting or queuing [health-check](health-check.md) findings | <https://cli.github.com> |
20
- | A BMAD project with an Epic | The unit of delivery: a `_bmad/` install, a `sprint-status.yaml`, and at least one Epic with stories | see [bmad-method.org](https://docs.bmad-method.org) |
19
+ | `gh` (GitHub CLI) | Submitting or queuing [health-check](./health-check.md) findings | <https://cli.github.com> |
20
+ | A BMAD project with an Epic | The unit of delivery: a `_bmad/` install, a `sprint-status.yaml`, and at least one Epic with stories | see [docs.bmad-method.org](https://docs.bmad-method.org) |
21
+ | TEA (Test Architect) | **The gate: non-negotiable.** UCG invokes the `bmad-testarch-*` skills to produce the `gate-decision.json` that `gate_eval.py` reads. Required in both profiles: `--light` still runs test-design and trace | <https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise> |
21
22
 
22
- The run also depends on recent Claude Code primitives: `/goal`, dynamic workflows, and Auto Memory. The preflight script version-gates these and reports a mechanical blocker if the installed Claude Code is below the minimum any of them needs (see [troubleshooting](troubleshooting.md)).
23
+ The run also depends on recent Claude Code primitives: `/goal`, dynamic workflows, and Auto Memory. The preflight script version-gates these and reports a mechanical blocker if the installed Claude Code is below the minimum any of them needs (see [troubleshooting](./troubleshooting.md)).
23
24
 
24
25
  ## Install
25
26
 
@@ -37,18 +38,37 @@ Invoke the skill with one of its trigger phrases ("run an epic autonomously", "e
37
38
  2. **Preflight runs.** Stage 2 is the autonomy gate. It runs a mechanical check (`preflight_check.py`), auto-remediates the fixable ambers (scaffolding the test framework, generating missing acceptance criteria, pre-creating TEA output dirs, and so on), then adds a semantic scan for undecided product or architecture decisions the script cannot see. The run launches **only** when the post-remediation intervention budget is zero and the semantic scan found no red blocker. A single undecided architecture decision stops the run here rather than letting an unattended run guess it.
38
39
  3. **The launch briefing.** On an attended run, before the first unattended action the skill prints a one-screen briefing: what is about to run, the worst-case turn envelope, the autonomy line ("from here I will not ask you anything"), the kill switch (Ctrl-C, or delete the Epic branch; `/rewind` will not help), and where to watch (the run's `.decision-log.md` and `run-status.json`). One soft confirm crosses the line.
39
40
 
40
- From there the run is autonomous: it defines done with TEA, executes each story to a green commit, gates each one deterministically, and finalizes with a run report and the deferred-work ledger. See [how it works](how-it-works.md) for the full stage-by-stage narration and the routing diagram.
41
+ From there the run is autonomous: it defines done with TEA, executes each story to a green commit, gates each one deterministically, and finalizes with a run report and the deferred-work ledger. See [how it works](./how-it-works.md) for the full stage-by-stage narration and the routing diagram.
41
42
 
42
43
  ## Run-mode flags
43
44
 
44
45
  | Flag | Effect |
45
46
  |------|--------|
46
47
  | `--light` | Trace-only gate. Downscopes from the full TEA chain to `bmad-testarch-trace` plus `gate_eval.py --profile light`: no NFR/test-review AND. |
47
- | `--parallel` | Experimental worktree fan-out. Each story runs isolated in its own worktree; no mid-run input. The sequential `/goal` spine is the default and recommended path; see [parallel mode](parallel-mode.md). |
48
+ | `--parallel` | Experimental worktree fan-out. Each story runs isolated in its own worktree; no mid-run input. The sequential `/goal` spine is the default and recommended path; see [parallel mode](./parallel-mode.md). |
48
49
  | `--yes` | Skips Stage 1's open-floor invite and the launch confirm. The launch briefing still prints. **Never** skips the hard preflight gate. |
49
50
  | `-H` | Headless. Runs non-interactively, never prompts (an unresolvable secret becomes a red blocker, not a question), and emits one JSON object at every exit point. |
50
51
  | `--retro` | Runs the close-out retrospective (`bmad-retrospective`). Interactive runs offer it at Epic close anyway; headless runs it only when `--retro` is passed. |
52
+ | `--max-stories N` | Bounds this **invocation** to N stories, then finalizes normally (report, ledger, terminal JSON). It is a work bound, not a scope narrowing: in-scope stays every not-`done` story, so the next invocation resumes at the story this one stopped before. No Epic-level gate is authored while stories remain. See [one story per process](#one-story-per-process). |
53
+
54
+ ## One story per process
55
+
56
+ A headless run drives every remaining story in one Claude Code session, and that session's context only grows: by the fifth story it carries four stories of transcript it will never need again. `scripts/drive_epic.py` moves that boundary into the process table. It spawns one `claude -p` per story under `--max-stories 1`, so each story's context dies with the process that held it:
57
+
58
+ ```bash
59
+ uv run .claude/skills/ultracode-goal/scripts/drive_epic.py \
60
+ --epic 7 \
61
+ --impl-artifacts _bmad-output/implementation-artifacts \
62
+ --profile light \
63
+ --dry-run
64
+ ```
65
+
66
+ Run it from your project root. The path above is the Claude Code skill copy the installer writes; the module copy under your resolved UCG folder (`_bmad/ucg/ultracode-goal/scripts/drive_epic.py` by default) is the same file, and in a clone of this repository it is `skills/ultracode-goal/scripts/drive_epic.py`.
67
+
68
+ Drop `--dry-run` to actually spawn. Point `--impl-artifacts` at the directory holding your `sprint-status.yaml`; the driver refuses to start if it is not there, since that is the sprint plan it reads. That directory also has to be the one your config resolves `implementation_artifacts` to, because the spawned session writes its terminal `run-result.json` where the config says, not where the driver was pointed. The driver cannot check that half for you: it would have to re-implement the skill's own config resolution to do it.
69
+
70
+ The driver is read-only on your tree with exactly one exception: it deletes the pinned `run-result.json` before each spawn, so the file's presence means *that* spawn reached a terminal. It stops on anything it cannot verify, and says why: no readable terminal, a `blocked` envelope (with the reason), a status it does not recognize, a `complete` whose story did not reach `done`, or a session that outran `--session-timeout` (2 hours by default; `0` disables it). Useful flags: `--limit N` caps how many sessions it spawns, `--permission-mode` defaults to `acceptEdits` and refuses `bypassPermissions` unless you also pass `--allow-full-autonomy`, and `--skill-command` overrides the invocation string for a plugin-marketplace install (`/bmad-module-ultracode-goal:ultracode-goal`).
51
71
 
52
72
  ## Hook security
53
73
 
54
- At preflight the skill auto-merges its **PreToolUse** guard and **Stop** budget hook into `.claude/settings.local.json`, a machine-local, gitignored file, honored after the workspace trust dialog. These hooks are the enforcement layer that blocks a commit on a protected branch and bounds a runaway story; they are not shared into the repo. Because they execute on your machine, review what gets merged: see [SECURITY.md](../SECURITY.md) for the hook-security model and what to check before granting trust.
74
+ At preflight the skill auto-merges its **PreToolUse** guard and **Stop** budget hook into `.claude/settings.local.json`, a machine-local, gitignored file, honored after the workspace trust dialog. These hooks are the enforcement layer that blocks a commit on a protected branch and bounds a runaway story; they are not shared into the repo. Because they execute on your machine, review what gets merged: see [SECURITY.md](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/SECURITY.md) for the hook-security model and what to check before granting trust.
@@ -3,7 +3,7 @@ title: Health Check
3
3
  description: "The Finalize self-improvement reflection: what it computes locally, what leaves your machine and only after approval, how it dedups, and how to turn it off."
4
4
  ---
5
5
 
6
- Every UltraCode Goal run that reaches Finalize ends with a health check: a brief self-improvement reflection that audits the run for friction, gaps, or bugs in *this module* and, when it finds something, offers to file a structured GitHub issue. The expected outcome is **zero findings**: a clean run exits in a line. This page covers exactly what it sends, the privacy model, how it dedups, and how to turn it off. The deterministic fingerprint and seen-cache plumbing is [`../skills/ultracode-goal/scripts/health_check_fp.py`](../skills/ultracode-goal/scripts/health_check_fp.py).
6
+ Every UltraCode Goal run that reaches Finalize ends with a health check: a brief self-improvement reflection that audits the run for friction, gaps, or bugs in *this module* and, when it finds something, offers to file a structured GitHub issue. The expected outcome is **zero findings**: a clean run exits in a line. This page covers exactly what it sends, the privacy model, how it dedups, and how to turn it off. The deterministic fingerprint and seen-cache plumbing is [`../skills/ultracode-goal/scripts/health_check_fp.py`](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/skills/ultracode-goal/scripts/health_check_fp.py).
7
7
 
8
8
  ## What it is, and when it runs
9
9
 
@@ -87,7 +87,7 @@ The `step_file` component is always the source-repo form `skills/ultracode-goal/
87
87
 
88
88
  Dedup runs at three levels:
89
89
 
90
- 1. **Machine-global seen-cache** at the configured `health_check_seen_cache` (by default `~/.ultracode-goal/health-check-seen.json`): the `seen` / `record` subcommands check and atomically merge-write this cache (a missing, empty, or corrupt cache is treated as empty, never a crash). Each record carries the issue URL, the action taken (`created` / `reacted` / `commented` / `queued`), and the date.
90
+ 1. **Machine-global seen-cache** at the configured `health_check_seen_cache` (by default `~/.ultracode-goal/health-check-seen.json`): the `seen` / `record` subcommands check and atomically merge-write this cache (a missing, empty, or corrupt cache is treated as empty, never a crash). Each record carries the issue URL, the action taken (`created` / `reacted` / `commented` / `queued` / `resolved`), and the date. Only the first four suppress a later sighting. `resolved` records that a finding was fixed, and deliberately does **not** suppress: a fresh sighting of a fixed defect is a regression rather than a duplicate, so it is reported and linked back to the original. An unrecognized action does not suppress either, on the same reasoning: a duplicate report is closed automatically, whereas a silenced regression is caught by nothing. The cache is machine-local, so where a record carries a real issue URL the shared source of truth is that issue's own state, which the check consults in preference to the local record. Only a *completed* close, or a merged pull request, counts as a fix there: an issue closed as *not planned* keeps the local verdict, because that is how the dedup Action closes a duplicate and how a wontfix is closed, and neither is a fix.
91
91
  2. **Remote search**: before filing, the existing issues are searched so a finding already filed by another machine is not duplicated.
92
92
  3. **Server-side**: a repository Action closes duplicates and upvotes the canonical issue, so even a race between two machines converges on one issue.
93
93