bmad-module-ultracode-goal 1.0.0 → 1.0.1

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.
@@ -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": "1.0.0",
22
+ "version": "1.0.1",
23
23
  "author": {
24
24
  "name": "Armel"
25
25
  },
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![npm](https://img.shields.io/npm/v/bmad-module-ultracode-goal)](https://www.npmjs.com/package/bmad-module-ultracode-goal)
12
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
- [![Python Version](https://img.shields.io/badge/python-%3E%3D3.10-blue?logo=python&logoColor=white)](https://www.python.org)
14
+ [![Python Version](https://img.shields.io/badge/python-%3E%3D3.11-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)
@@ -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://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.
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.11, [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
@@ -138,6 +138,7 @@ The docs are organized into three buckets: **Why** (start here), **Try** (do stu
138
138
  - **[Gate Model](./docs/gate-model.md)**: how `gate_eval.py` maps `gate_status` to a verdict, and the production AND-signals.
139
139
  - **[Health Check](./docs/health-check.md)**: the terminal self-improvement loop: what it sends, privacy, and how to disable it.
140
140
  - **[Cross-Session Recall](./docs/cross-session-recall.md)**: the optional claude-mem integration: touchpoints, trust model, and how to enable it.
141
+ - **[Knowledge-Graph Refresh](./docs/knowledge-graph-refresh.md)**: the optional graphify integration: preconditions, what it sends where, and what it never touches.
141
142
  - **[Troubleshooting](./docs/troubleshooting.md)**: real failure modes and their remediations.
142
143
 
143
144
  Every run that reaches Finalize ends with a self-improvement check that can file a deduplicated GitHub issue with your approval, so **please let runs finish through Finalize**, or [open an issue](https://github.com/armelhbobdad/bmad-module-ultracode-goal/issues/new/choose) directly. If UCG shipped an epic while you slept, a ⭐ helps others find it.
@@ -88,11 +88,13 @@ skills/ultracode-goal/
88
88
 
89
89
  Configuration resolves in three layers, base → team → user, via `resolve_customization.py`:
90
90
 
91
- 1. **Base**: `customize.toml` in the skill root (the shipped `[workflow]` block).
92
- 2. **Team**: `{project-root}/_bmad/custom/ultracode-goal.toml`.
93
- 3. **User**: `{project-root}/_bmad/custom/ultracode-goal.user.toml`.
91
+ 1. **Base**: `customize.toml` in the skill root (the shipped `[workflow]` block). In an installed project that file is `{project-root}/_bmad/ucg/ultracode-goal/customize.toml`, a verbatim copy of the shipped one; it is the layer to read (every knob is there with its comment), not the layer to edit.
92
+ 2. **Team**: `{project-root}/_bmad/custom/ultracode-goal.toml`, committed.
93
+ 3. **User**: `{project-root}/_bmad/custom/ultracode-goal.user.toml`, gitignored by the `*.user.toml` rule that ships in `_bmad/custom/.gitignore`.
94
94
 
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).
95
+ Neither override file is created by any installer, and a missing one is not an error: the resolver loads it non-required and treats absence as an empty table, so a fresh project resolves the base layer alone. You create them when you first need to override something. Do not mistake them for the `config.toml` and `config.user.toml` already sitting in that directory: those are BMAD's own configuration, and a UCG knob written there resolves to nothing.
96
+
97
+ 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`, the two lifecycle hooks (`on_epic_complete`, `on_escalation`), the [health check](./health-check.md) family (`health_check_repo`, `health_check_seen_cache`, `health_check_queue_path`, `health_check_autosubmit`), and the two optional third-party integrations, both off by default: [`cross_session_recall`](./cross-session-recall.md) and [`graphify_integration`](./knowledge-graph-refresh.md). 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).
96
98
 
97
99
  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:
98
100
 
@@ -5,13 +5,13 @@ description: An honest, side-by-side comparison of UltraCode Goal and bmad-code-
5
5
 
6
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.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).
8
+ Snapshot: UCG v1.0.0 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 four of the five items 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, and the integrity fixes to its verify gate. The fifth was this page's error rather than a gap in the release: those adversarial review layers are BMAD-METHOD's, declared in `bmad-dev-auto` and run against BMAD-METHOD's own review skills, and what v0.9.0 added was a preflight that refuses to start when they are missing. 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 a multiplexer, and stable, schema-versioned `--json` documents for six more commands: `status`, `list`, `validate`, `decisions`, `clean`, and `cleanup`. Eight commands now emit versioned documents, `diagnose` and `probe-adapter` having been converted from a JSON block appended to a text report; most of what is left is action commands with no document to emit. UCG reached v1.0.0 on 2026-07-28. Treat every line below as a point-in-time reading of two *released* versions, and verify the current state for yourself (links at the bottom); both projects' main branches run well ahead of their tags.
9
9
 
10
10
  ## The one difference everything else follows from
11
11
 
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.
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 by default) 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 (TEA) gate artifact.
14
+ UCG puts the control loop **inside Claude Code**. The run is a Claude Code skill that composes `/goal`, Auto Mode, Auto Memory, and runtime hooks; the experimental `--parallel` fan-out additionally uses a dynamic workflow, and degrades to the sequential spine when one is unavailable. 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
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
 
@@ -19,20 +19,20 @@ The consequence cascades: bmad-loop is a tool you run beside any supported agent
19
19
 
20
20
  | Dimension | bmad-loop | UltraCode Goal (UCG) |
21
21
  |---|---|---|
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 |
22
+ | Runtime | External Python process plus a terminal multiplexer, tmux being the bundled default (the OpenCode profile runs over HTTP with no multiplexer window); Linux, macOS, or WSL (native Windows is planned) | A skill inside Claude Code; no daemon, no multiplexer, no session to attach to. Runs wherever Claude Code does, given Python 3.11+, `uv`, and `git`, and a Claude Code new enough for `/goal`, dynamic workflows, and Auto Memory, the three versions preflight pins and refuses to launch below. One optional exception: a ~900-line 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
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 |
25
+ | Scope | Implementation phase: `backlog` and `ready-for-dev` stories from `sprint-status.yaml`, or opt-in from a typed `stories.yaml`, through dev, review, verify, commit | Whole Epic, six stages: ingest and scope, planning-readiness preflight, ATDD (acceptance-test-driven development) test generation, execute, TEA gate, finalize, whose terminal step is a workflow health check that the skill's own table numbers as a seventh stage |
26
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
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
- | 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 machine-readable blocked report (the headless envelope); resume from the decision log |
28
+ | Pre-launch gate | `validate`: 26 registered checks at v0.9.0 (BMAD config, policy, sprint-status, git, multiplexer and process host, CLI binary and profile, hook registration, base skills, stories-mode manifest and dispatch) | 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, an active-agent indicator naming what is driving the current stage, plus schema-versioned `--json` documents for scripted readers | Files plus a read-only renderer: `.decision-log.md`, a `run-status.json` heartbeat on the sequential spine (the `--parallel` fan-out uses the `/workflows` view instead and writes no heartbeat), a transcript ticker that prints each gate verdict, a `gate-trail.md` evidence trail at finalize, and `/ucg-status` to assemble all of it on demand |
30
+ | Deferred work | A triage-and-execute **sweep** engine plus a decisions workflow | A ledger the gate only appends to, surfaced at finalize and readable mid-run through `/ucg-status`, with `/ucg-resolve` able to mark an answered decision row resolved; no execute engine |
31
+ | Escalation | Typed (CRITICAL / PREFERENCE) plus an interactive resolve agent that re-arms the spec and re-applies the saved patch, so review resumes on the restored diff | An `escalate` verdict, a typed `escalation-<story-id>.json` sidecar (`source`, `kind`, `decision_needed`, `evidence`), an `on_escalation` hook, a path-pinned `run-result.json` for every headless terminal exit that got far enough to resolve its artifacts path, not only blocked ones, and `/ucg-resolve` to answer what is pending; resume from the decision log |
32
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 |
33
+ | Extensibility | A plugin system (observe, veto, mutate) with bundled TEA and Unity plugins | `customize.toml` knobs, planning-shaping fragments, and two optional third-party integrations configured there, both off by default and neither able to touch a gate verdict: [claude-mem recall](./cross-session-recall.md) and a [graphify knowledge-graph refresh](./knowledge-graph-refresh.md) |
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.9.0; rich docs; CI + test suite | Community module; v0.5.1; docs site; CI + test suite |
35
+ | Maturity | First-party (bmad-code-org); v0.9.0, whose headline is stable schema-versioned `--json` contracts that evolve additively; rich docs; CI + test suite | Community module; v1.0.0, which binds an already-stated contract (the headless envelope and `gate_eval.py`'s verdict vocabulary were covered at 0.x) under SemVer and adds `run-result.json` to it; docs site; CI + test suite |
36
36
  | License | MIT | MIT |
37
37
 
38
38
  ## Where bmad-loop is stronger
@@ -41,8 +41,8 @@ This is a genuinely strong tool; pretending otherwise would make this page usele
41
41
 
42
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
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.
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 is files, the transcript, and a read-only `/ucg-status` render assembled from those same files: there is still no live view and no session to attach to.
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, surfaces it at the end, and can render it mid-run through `/ucg-status`; acting on it is still manual, and there is no execute engine.
46
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
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
 
@@ -51,27 +51,28 @@ This is a genuinely strong tool; pretending otherwise would make this page usele
51
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
52
 
53
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.
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, about what the generator *emits* rather than what it accepts: the TEA release installed here does detect a backend stack, but its scaffolds are Playwright and TypeScript, and the browser-recording path loads only for a frontend or fullstack project, so a stack with no JS or TS harness still gets nothing runnable. UCG's preflight therefore steers those runs 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; the one way past a RED is an operator recording a `close` for it, since a `defer` does not clear one and an unreadable decisions file clears nothing. 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, and the readiness kernel beside it is deterministic (v1.0.0 closed three fail-opens there, where an Epic with no stories, a story with no acceptance criteria, and a partially seeded story set each used to score `ready`). bmad-loop's preflight is mechanical and assumes the sprint's stories are already ready to build.
56
+ 4. **Almost no moving parts outside the agent.** The autonomous run is a skill: no daemon, no multiplexer, 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. Two qualifiers, added honestly. Three companion skills ship alongside the run and none is required by one: `ucg-formalize` (the standalone readiness gate), `ucg-status` (the read-only run view), and `ucg-resolve` (the decide-surface for a stopped run). And 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; 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 900 lines, where bmad-loop's orchestrator is the product; skip it and the skill still runs standalone, since `--max-stories` is a flag on the skill rather than something the script provides.
57
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.
58
58
 
59
59
  ## What they share
60
60
 
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).
62
- - Fresh-context review separated from implementation, to kill self-review anchoring bias.
63
- - Adversarial review passes, bounded so they cannot oscillate forever.
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 a non-web stack, under either profile, the trace artifacts are agent-authored under strict honesty rules, so the guarantee there is procedural rather than mechanical).
62
+ - Proof that the commit is real work, not a claim about work. bmad-loop cross-checks the diff against the story's baseline commit; UCG enforces the equivalent one layer down, in a `PreToolUse` hook that denies the `git commit` outright unless a tests-ran marker exists whose recorded baseline SHA matches the story's character for character, and unless the staged index is non-empty. On a production run it also refuses a commit whose staged acceptance tests are still skipped, though that check reads `test.skip(` and so does nothing on the non-web stacks the ATDD note above steers to `--light`.
63
+ - Fresh-context review separated from implementation, to kill self-review anchoring bias, on both defaults with a caveat each: bmad-loop's separate session is gated by `review.trigger`, which defaults to `recommended` (set it to `always` for every story), and UCG runs a code-review pass on its production profile but none under `--light`.
64
+ - Adversarial review passes, bounded so they cannot oscillate forever: bmad-loop by `max_review_cycles` (default 3), UCG by `max_turns_per_story`, where a re-loop that would exceed the budget escalates instead.
64
65
  - Optional git worktree isolation.
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).
66
- - `sprint-status.yaml` as planning truth, owned by the BMAD skills; both build on BMAD-METHOD.
66
+ - 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. UCG adds a second axis, `--max-stories N`, a per-invocation work bound whose exhaustion still ends the run `complete` with stories remaining, so that status means "this invocation finished", not "the Epic is done". Note the asymmetry: UCG has no token or cost bound at all, and `story_token_budget` is now a deprecated no-op.
67
+ - `sprint-status.yaml` as the shared planning ledger, and both build on BMAD-METHOD. Neither leaves it write-only to the BMAD skills any more: UCG's gate writes the story's `done` row at the `advance` route, and bmad-loop's orchestrator syncs the board itself.
67
68
 
68
69
  ## Which to reach for
69
70
 
70
71
  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.
71
72
 
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).
73
+ 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 the autonomous run itself to be a single skill with no daemon and no session to attach to (the three optional companion skills and the per-story driver above are all opt-in, and a run needs none of them).
73
74
 
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.
75
+ They are not mutually exclusive. Both read the same `sprint-status.yaml` and BMAD artifacts, so an Epic planned and gated UCG's way is a board bmad-loop can pick up. Their deferred-work ledgers are not interchangeable, though: they share the path but not the schema, since `bmad-loop sweep` parses `### DW-<n>:` sections and UCG never writes one, so a sweep will not see UCG's parked rows.
75
76
 
76
77
  ## Verify this yourself
77
78
 
@@ -80,4 +81,4 @@ Both tools change weekly, so re-check before you rely on anything above:
80
81
  - 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
82
  - UCG: [How It Works](./how-it-works.md) and the [Gate Model](./gate-model.md).
82
83
 
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.
84
+ This snapshot was re-cut on 2026-07-28 against bmad-loop v0.9.0 (released 2026-07-21) and UCG v1.0.0 (released 2026-07-28); the previous cut (2026-07-12) read bmad-loop v0.8.1 and UCG v0.5.1, and the one before it (2026-06-28, bmad-auto v0.7.4 and UCG v0.4.0) predates the rename.
@@ -62,7 +62,7 @@ What it honestly does **not** do:
62
62
 
63
63
  ## Turning it on
64
64
 
65
- Set the knob in your project's `_bmad/custom/ultracode-goal.toml` (the same file the other knobs use):
65
+ Set the knob in your project's `_bmad/custom/ultracode-goal.toml`. **No installer creates that file**, so on most projects you are creating it: `_bmad/custom/` exists already, but the `config.toml` sitting in it belongs to BMAD's own configuration, and putting a UCG knob there does nothing.
66
66
 
67
67
  ```toml
68
68
  [workflow]
@@ -13,7 +13,7 @@ UltraCode Goal conducts BMAD and TEA skills and runs deterministic Python under
13
13
  |------|--------------|---------|
14
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
- | Python >= 3.10 | The deterministic gate, preflight, and hook scripts (run via `uv`) | <https://www.python.org> |
16
+ | Python >= 3.11 | 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
19
  | `gh` (GitHub CLI) | Submitting or queuing [health-check](./health-check.md) findings | <https://cli.github.com> |
@@ -109,7 +109,7 @@ The production AND fails closed: a missing or unparseable `nfr-assessment.md` or
109
109
 
110
110
  ### Stage 6: Finalize
111
111
 
112
- Make the run pay off for the next one. Capture learnings deliberately: machine-local quirks to Auto Memory (`remember X`), team standards to the project's CLAUDE.md or `.claude/rules`. Optionally run the retrospective (`--retro`). Audit every `.decision-log.md` entry into the report, the addendum, or explicit process-noise. Produce a `run-report.md` (Epic, profile, per-story outcomes, the Epic-level gate, budget consumed, learnings, a pointer to the ledger), write the terminal `run-status.json`, surface this Epic's deferred-work ledger heading to the user, and fire the `on_epic_complete` hook **only** when the Epic actually advanced. See [`references/finalize.md`](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/skills/ultracode-goal/references/finalize.md).
112
+ Make the run pay off for the next one. Capture learnings deliberately: machine-local quirks to Auto Memory (`remember X`), team standards to the project's CLAUDE.md or `.claude/rules`. Optionally run the retrospective (`--retro`). Audit every `.decision-log.md` entry into the report, the addendum, or explicit process-noise. Produce a `run-report.md` (Epic, profile, per-story outcomes, the Epic-level gate, budget consumed, learnings, a pointer to the ledger), write the terminal `run-status.json`, surface this Epic's deferred-work ledger heading to the user, and fire the `on_epic_complete` hook **only** when the Epic actually advanced. One optional step also lives here and is off by default: the [knowledge-graph refresh](./knowledge-graph-refresh.md). See [`references/finalize.md`](https://github.com/armelhbobdad/bmad-module-ultracode-goal/blob/main/skills/ultracode-goal/references/finalize.md).
113
113
 
114
114
  ## Production vs. `--light`
115
115
 
package/docs/index.md CHANGED
@@ -63,5 +63,6 @@ The docs split into three buckets: **Why** (start here), **Try** (do stuff), and
63
63
  - [Gate Model](./gate-model.md): how `gate_eval.py` maps `gate_status` to a verdict, the thresholds, and the fail-closed contract.
64
64
  - [Health Check](./health-check.md): the terminal self-improvement reflection: what it sends, the privacy model, and how to disable it.
65
65
  - [Cross-Session Recall](./cross-session-recall.md): the optional claude-mem integration and its trust model.
66
+ - [Knowledge-Graph Refresh](./knowledge-graph-refresh.md): the optional graphify integration, its preconditions, and what it sends where.
66
67
  - [Troubleshooting](./troubleshooting.md): real failure modes and their remediations.
67
68
  - [UCG vs bmad-loop](./comparison.md): a side-by-side comparison with bmad-code-org's bmad-loop orchestrator (formerly bmad-auto).
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: Knowledge-Graph Refresh
3
+ description: The optional graphify integration - UCG refreshes your project's knowledge graph as a run exits, so the next session starts from a current graph. Opt-in, advisory, never in the gate path, off by default.
4
+ ---
5
+
6
+ > **Optional, opt-in, off by default.** The refresh is one time-boxed call on the way out of a run. It can add an artifact to your machine, and it can change nothing else: not the gate verdict, not the recorded run-status, not the headless envelope. When it is off, or when the [graphify](https://github.com/Graphify-Labs/graphify) CLI is absent, the run is byte-for-byte the same as a run without it.
7
+
8
+ ## What it does
9
+
10
+ A knowledge graph of your codebase goes stale the moment a run lands eight stories of new code and the documents that came with them, which is exactly what a UCG run produces. With `graphify_integration = "refresh"`, Stage 6 Finalize spends one incremental, local rebuild, so the next session starts from a current picture instead of a stale one. It refreshes what can be parsed and leaves what needs a model alone; [what it runs](#what-it-runs-and-where-it-writes) draws that line precisely.
11
+
12
+ Finalize is the only call site. No preflight step, no per-story step, and nothing in the gate path calls graphify or reads its output. See [how it works](./how-it-works.md) for where Stage 6 sits.
13
+
14
+ ## What you need
15
+
16
+ The third-party [graphify](https://github.com/Graphify-Labs/graphify) CLI, whose package name is not its command name:
17
+
18
+ ```bash
19
+ uv tool install graphifyy # or: pipx install graphifyy. The command is `graphify`.
20
+ ```
21
+
22
+ > graphify is a third-party tool maintained independently of this module. We don't bundle, endorse, or install it; the refresh simply uses it when you already have it.
23
+
24
+ You also need a graph to refresh, since this step updates one and never builds one. Build it once yourself (`graphify .`, which is the full pipeline and does use an LLM backend), and the run keeps its parsed layer current after that.
25
+
26
+ ## Turning it on
27
+
28
+ Set the knob in your project's `_bmad/custom/ultracode-goal.toml`. **No installer creates that file**, so on most projects you are creating it: `_bmad/custom/` exists already, but the `config.toml` sitting in it belongs to BMAD's own configuration, and putting a UCG knob there does nothing.
29
+
30
+ ```toml
31
+ [workflow]
32
+ # Knowledge-graph refresh: one incremental rebuild as the run exits.
33
+ # Needs the graphify CLI and an existing graphify-out/. Advisory, never gates.
34
+ graphify_integration = "refresh"
35
+ ```
36
+
37
+ The `[workflow]` table header matters: the resolver extracts the `workflow` block from the merged files, so a bare top-level `graphify_integration` line is silently discarded and the feature stays off.
38
+
39
+ ## Three things to know before you turn it on
40
+
41
+ - **The values are `off` and `refresh`, not `on` and `off`.** `cross_session_recall` sits directly above it in the shipped file and takes `on`, so copying that shape here produces `"on"`, which is not a legal value and leaves the step off.
42
+ - **A first-ever enable does nothing, deliberately.** Two preconditions are both required: `graphify` resolves on `PATH`, and a `graphify-out/graph.json` already exists under the project root to update. Refresh means refresh: with no graph there is nothing to update, and building one from nothing walks the whole corpus, which is not something a bounded exit step may do. Build the graph once yourself, and the run keeps its parsed layer current from then on.
43
+ - **Absence is silent, failure is logged.** When either precondition is missing, the run is byte-identical to an `off` run: no probe output, no decision-log line, nothing. When the pass does run and then fails or exceeds its 300 second time box, Finalize logs one `WARN graphify-refresh-failed` line to `.decision-log.md` and moves on. It is never retried.
44
+
45
+ ## What it runs, and where it writes
46
+
47
+ The delegation is exactly one command, `graphify update .`, time-boxed to 300 seconds and never retried. That subcommand re-extracts the graph's **parsed layer** against what is on disk, using tree-sitter: **no LLM call, no API key, no network request, no token spend** at the end of a run you were not watching.
48
+
49
+ The parsed layer is everything graphify has an extractor for: your source code, plus the Markdown family (`.md`, `.mdx`, `.qmd`, `.skill`). So an Epic's new modules and the story and documentation files it wrote are both picked up. What stays as the last full build left it is the **semantic** layer: images, PDFs and papers, and anything an LLM derived from a document. That pass is the one that would send your files to a model provider and spend your API budget, which is exactly what an unattended exit step should not decide to do. Run it yourself, on your own terms, when you want it.
50
+
51
+ One behaviour worth knowing, because it is the opposite of what people expect:
52
+
53
+ - **Deleting code shrinks the graph, and nothing warns.** That is correct: the rebuild accounts for sources that are gone and writes the smaller graph, exit 0.
54
+ - **What graphify refuses is an unexplained loss**, where nodes vanish while their source is still sitting on disk. An Epic that adds a `.gitignore` rule, or otherwise narrows what gets scanned, produces exactly that. Then graphify declines the write, exits non-zero, and you get a `WARN graphify-refresh-failed` line with the graph left intact. Whether to re-run `graphify update . --force` is a decision the run does not make for you.
55
+
56
+ The output is a `graphify-out/` directory at your project root, not in the run folder, so it is not part of the run's evidence and nothing in the gate path reads it. It regenerates on every refresh and holds a `graph.json`, a `graph.html`, a report, and a cache, so **add `graphify-out/` to your `.gitignore`**: UCG commits each green story, and an untracked-but-not-ignored tree at the repo root is exactly what a story commit should never sweep up.
57
+
58
+ ## What it never touches
59
+
60
+ The refresh is advisory in the same sense [Cross-Session Recall](./cross-session-recall.md) is, and the two are independent: either can be on without the other.
61
+
62
+ - The **gate verdict** is `gate_eval.py` reading TEA's `gate-decision.json`, and only that. See the [gate model](./gate-model.md).
63
+ - The **recorded run-status** and the **headless envelope** are identical whether the refresh ran, failed, or never fired.
64
+ - A graphify failure or timeout **never** blocks, re-loops, or escalates a story, and never changes a run's `complete` / `blocked` / `partial-complete` outcome.
65
+
66
+ Verified against graphify 0.9.26 on 2026-07-28. It is a pre-1.0 tool whose CLI surface moves; if the install name, the command name, or the output layout above no longer match what you have, trust `graphify --help`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "bmad-module-ultracode-goal",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "description": "BMAD module — Run a BMAD Epic autonomously to a machine-checked, TEA-gated Definition-of-Done.",
6
6
  "keywords": [
7
7
  "bmad",
@@ -75,8 +75,7 @@ cross_session_recall = "off"
75
75
 
76
76
  # --- Knowledge-graph refresh (optional; runs at Finalize only) ---
77
77
  # Advisory only, never gates. Requires the third-party graphify CLI on PATH and
78
- # a prior graphify-out/manifest.json to increment from; silently inactive
79
- # without either. "off" = never touch it | "refresh" = one incremental,
78
+ # a prior graphify-out/graph.json to update; silently inactive without either. "off" = never touch it | "refresh" = one incremental,
80
79
  # time-boxed rebuild as the run exits, so the next session starts from a
81
80
  # current graph rather than a stale one. Finalize is the only call site: no
82
81
  # preflight step, no per-story step, and no effect on any gate verdict, the
@@ -81,17 +81,21 @@ Resolve the mode exactly as the hooks below resolve theirs:
81
81
 
82
82
  Two values, and no others. `off` is the shipped default and a complete no-op — no probe, no delegation, no decision-log line, no output; there is nothing to read further in this section. `refresh` refreshes the project's knowledge graph on the way out, so the next session starts from a current one instead of a stale one.
83
83
 
84
- **Probe first, and degrade to silence.** Two preconditions, both required: graphify resolves on PATH (`command -v graphify`), and a prior `graphify-out/manifest.json` exists under `{project-root}` to increment from. If either is missing there is nothing to refresh — do nothing, print nothing, and write no `.decision-log.md` entry, so the run stays byte-identical to an `off` run. A "skipped it" log line is exactly the difference that would break that, so do not add one. Absence is silent; failure is logged. They are different events.
84
+ **Probe first, and degrade to silence.** Two preconditions, both required: graphify resolves on PATH (`command -v graphify`), and a prior `graphify-out/graph.json` exists under `{project-root}` to update. If either is missing there is nothing to refresh — do nothing, print nothing, and write no `.decision-log.md` entry, so the run stays byte-identical to an `off` run. A "skipped it" log line is exactly the difference that would break that, so do not add one. Absence is silent; failure is logged. They are different events.
85
85
 
86
- The manifest precondition is not defensive padding. Refresh means refresh: with no manifest there is nothing to increment from, and a cold rebuild walks the whole corpus and spends API budget, which is the opposite of what a bounded step on the way out may do. A first-ever run in this mode therefore refreshes nothing and says nothing.
86
+ The graph precondition is not defensive padding. Refresh means refresh: with no graph there is nothing to update, and building one from nothing walks the whole corpus, which is the opposite of what a bounded step on the way out may do. A first-ever run in this mode therefore refreshes nothing and says nothing.
87
87
 
88
88
  **With both preconditions met, delegate one incremental rebuild from `{project-root}`** — graphify writes `graphify-out/` relative to the current working directory:
89
89
 
90
90
  ```
91
- timeout 300 graphify . --update
91
+ timeout 300 graphify update .
92
92
  ```
93
93
 
94
- `--update` re-extracts only what changed against the recorded manifest, so graphify's own manifest diff *is* the changed-path scoping: the run does not enumerate the Epic's paths, and there is no surface that would accept them. Never a cold full build.
94
+ `graphify update` is the subcommand that re-extracts the graph's **parsed layer** against what is on disk, with no LLM call: no API key, no network, no token spend at the end of an unattended run. Never a cold full build. That layer is everything graphify has a tree-sitter extractor for, which is the source code plus the Markdown family (`.md`, `.mdx`, `.qmd`, `.skill`), so an Epic's new modules *and* the story and doc files it wrote are both picked up. What it does not run is the semantic pass: images, PDFs and papers, and any LLM-derived layer over a document, stay as the last full build left them, because that path spends API budget and a bounded exit step may not take it unattended.
95
+
96
+ Deleting code shrinks the graph, and that is the correct outcome, not a failure: the rebuild accounts for sources that are gone from disk and writes the smaller graph, exit 0, no `WARN`. What graphify refuses is an **unexplained** loss, where nodes disappear but their source is still on disk, which is what an Epic that adds a `.gitignore` rule or otherwise narrows the scan corpus produces. That refusal exits non-zero, so the `WARN` below records it and the graph is left untouched; whether to re-run with `--force` is a decision this step does not get to make.
97
+
98
+ Pass no other flags. Unlike `graphify extract`, this subcommand rejects an unknown option with a usage error instead of ignoring it, so a flag that stops being real fails loudly here rather than silently doing nothing.
95
99
 
96
100
  The delegation is hard time-boxed by the `timeout 300` prefix above and is **not retried**. On a non-zero exit or a timeout, log one `WARN graphify-refresh-failed` line to `.decision-log.md` and move on.
97
101
 
@@ -121,6 +121,7 @@ export default defineConfig({
121
121
  { label: 'Gate Model', slug: 'gate-model' },
122
122
  { label: 'Health Check', slug: 'health-check' },
123
123
  { label: 'Cross-Session Recall', slug: 'cross-session-recall' },
124
+ { label: 'Knowledge-Graph Refresh', slug: 'knowledge-graph-refresh' },
124
125
  { label: 'Troubleshooting', slug: 'troubleshooting' },
125
126
  { label: 'UCG vs bmad-loop', slug: 'comparison' },
126
127
  ],