bmad-module-ultracode-goal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +20 -0
- package/.gitattributes +16 -0
- package/.nvmrc +1 -0
- package/LICENSE +27 -0
- package/README.md +200 -0
- package/docs/_internal/RELEASING.md +101 -0
- package/docs/_internal/STABILITY.md +62 -0
- package/docs/architecture.md +77 -0
- package/docs/assets/ucg-logo.svg +73 -0
- package/docs/gate-model.md +109 -0
- package/docs/getting-started.md +51 -0
- package/docs/health-check.md +61 -0
- package/docs/how-it-works.md +73 -0
- package/docs/index.md +25 -0
- package/docs/parallel-mode.md +33 -0
- package/docs/troubleshooting.md +56 -0
- package/docs/why-ultracode-goal.md +34 -0
- package/package.json +100 -0
- package/skills/.gitkeep +0 -0
- package/skills/module.yaml +12 -0
- package/skills/ultracode-goal/SKILL.md +75 -0
- package/skills/ultracode-goal/assets/execute-epic.workflow.js +208 -0
- package/skills/ultracode-goal/customize.toml +47 -0
- package/skills/ultracode-goal/references/define-done.md +41 -0
- package/skills/ultracode-goal/references/execute.md +90 -0
- package/skills/ultracode-goal/references/finalize.md +64 -0
- package/skills/ultracode-goal/references/gate.md +70 -0
- package/skills/ultracode-goal/references/health-check.md +332 -0
- package/skills/ultracode-goal/references/ingest-and-scope.md +46 -0
- package/skills/ultracode-goal/references/preflight.md +100 -0
- package/skills/ultracode-goal/scripts/gate_eval.py +280 -0
- package/skills/ultracode-goal/scripts/health_check_fp.py +196 -0
- package/skills/ultracode-goal/scripts/hooks/budget_stop.py +162 -0
- package/skills/ultracode-goal/scripts/hooks/guard_pretooluse.py +174 -0
- package/skills/ultracode-goal/scripts/preflight_check.py +399 -0
- package/tools/cli/commands/install.js +36 -0
- package/tools/cli/commands/status.js +161 -0
- package/tools/cli/commands/uninstall.js +175 -0
- package/tools/cli/commands/update.js +65 -0
- package/tools/cli/lib/ide-skills.js +218 -0
- package/tools/cli/lib/installer.js +226 -0
- package/tools/cli/lib/manifest.js +100 -0
- package/tools/cli/lib/platform-codes.yaml +223 -0
- package/tools/cli/lib/ui.js +353 -0
- package/tools/cli/lib/version-check.js +86 -0
- package/tools/cli/ucg-cli.js +45 -0
- package/tools/ucg-npx-wrapper.js +36 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bmad-module-ultracode-goal",
|
|
3
|
+
"owner": { "name": "Armel" },
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"homepage": "https://github.com/armelhbobdad/bmad-module-ultracode-goal",
|
|
6
|
+
"repository": "https://github.com/armelhbobdad/bmad-module-ultracode-goal",
|
|
7
|
+
"keywords": ["bmad", "claude-code", "goal-mode", "autonomous-delivery", "test-architect", "quality-gates"],
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "bmad-module-ultracode-goal",
|
|
11
|
+
"source": "./",
|
|
12
|
+
"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.",
|
|
13
|
+
"version": "0.1.0",
|
|
14
|
+
"author": { "name": "Armel" },
|
|
15
|
+
"skills": [
|
|
16
|
+
"./skills/ultracode-goal"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
package/.gitattributes
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Normalize all text files to LF in the repo and on checkout, regardless of
|
|
2
|
+
# the contributor's platform or core.autocrlf setting. UCG runs on Linux,
|
|
3
|
+
# macOS, and Windows (Git Bash / WSL2); LF-everywhere keeps prettier
|
|
4
|
+
# clean and avoids spurious diffs from line-ending churn.
|
|
5
|
+
* text=auto eol=lf
|
|
6
|
+
|
|
7
|
+
# Binary blobs — never touch.
|
|
8
|
+
*.png binary
|
|
9
|
+
*.jpg binary
|
|
10
|
+
*.jpeg binary
|
|
11
|
+
*.gif binary
|
|
12
|
+
*.ico binary
|
|
13
|
+
*.pdf binary
|
|
14
|
+
*.zip binary
|
|
15
|
+
*.gz binary
|
|
16
|
+
*.tgz binary
|
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22
|
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Armel (armelhbobdad)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
TRADEMARK NOTICE:
|
|
24
|
+
BMad™ , BMAD-CORE™ and BMAD-METHOD™ are trademarks of BMad Code, LLC. The use of these
|
|
25
|
+
trademarks in this software does not grant any rights to use the trademarks
|
|
26
|
+
for any other purpose.
|
|
27
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="docs/assets/ucg-logo.svg" alt="UltraCode Goal — six stage nodes orbiting a deterministic gate whose verdict reads PASS" width="190"/>
|
|
4
|
+
|
|
5
|
+
# UltraCode Goal (UCG)
|
|
6
|
+
|
|
7
|
+
**Run a BMAD Epic autonomously to a machine-checked Definition-of-Done.**
|
|
8
|
+
|
|
9
|
+
[](https://www.anthropic.com/claude-code)
|
|
10
|
+
[](https://github.com/armelhbobdad/bmad-module-ultracode-goal/actions/workflows/quality.yaml)
|
|
11
|
+
[](https://www.npmjs.com/package/bmad-module-ultracode-goal)
|
|
12
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
|
+
[](https://github.com/bmad-code-org/BMAD-METHOD)
|
|
14
|
+
[](https://www.python.org)
|
|
15
|
+
[](https://docs.astral.sh/uv/)
|
|
16
|
+
[](./docs/index.md)
|
|
17
|
+
[](https://github.com/armelhbobdad/bmad-module-ultracode-goal/stargazers)
|
|
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, which exist nowhere else. Other editors can hold the skill files; the autonomous run itself requires Claude Code.
|
|
20
|
+
|
|
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
|
+
|
|
23
|
+
**If UCG shipped an epic while you slept, give it a ⭐ — it helps others find this tool.**
|
|
24
|
+
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## The Problem
|
|
30
|
+
|
|
31
|
+
You hand an agent an epic and tell it to "build until done." It runs, it commits, it declares victory. At review time you discover "done" meant "the model felt done." There are four reasons this keeps happening, and each one is a mechanic, not a vibe:
|
|
32
|
+
|
|
33
|
+
- **The `/goal` evaluator only sees the transcript.** It cannot open the gate artifact TEA wrote to disk. So the thing deciding completion is reading a story _about_ the work, not the verdict _on_ the work.
|
|
34
|
+
- **A model grading its own output is the fox auditing the henhouse.** Self-assessment is the weakest possible signal for a release gate, and it is exactly the signal you get by default.
|
|
35
|
+
- **`/rewind` checkpoints miss Bash changes.** Rollback you cannot trust is rollback you do not have.
|
|
36
|
+
- **Memory is context, not enforcement.** Telling the agent "never commit on `main`" in a prompt is a suggestion. An invariant has to be a hook the runtime _executes_, or it is not an invariant.
|
|
37
|
+
|
|
38
|
+
UCG exists because the documented mechanics make the intuitive shortcut wrong.
|
|
39
|
+
|
|
40
|
+
## Before vs After
|
|
41
|
+
|
|
42
|
+
**Before** — you babysit an epic story-by-story, approving each step, or you let an agent run unattended and find out at review time that its definition of "done" was its own opinion of its own work.
|
|
43
|
+
|
|
44
|
+
**After** — the preflight hard-gates the epic to a remediated green light before anything launches. TEA turns each story's acceptance criteria into red-phase tests. The run advances only when `gate_eval.py` reads `PASS` from TEA's deterministic `gate-decision.json`. Completion is a fact on disk, not a feeling in the transcript.
|
|
45
|
+
|
|
46
|
+
That verdict is a small, real JSON object. Here is the actual output of `gate_eval.py` reading a passing gate file (`--profile light`):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"verdict": "advance",
|
|
51
|
+
"gate_status": "PASS",
|
|
52
|
+
"p0_status": "100%",
|
|
53
|
+
"p1_status": "95%",
|
|
54
|
+
"overall_status": "88%",
|
|
55
|
+
"nfr_status": null,
|
|
56
|
+
"review_score": null,
|
|
57
|
+
"reasons": [
|
|
58
|
+
"gate read from gate-decision.json",
|
|
59
|
+
"gate_status PASS -> advance"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The `gate_status` comes straight from TEA's artifact — `gate_eval.py` never re-derives the thresholds; it reads the status as given and maps it to a `verdict` (`PASS`/`WAIVED` → `advance`, `CONCERNS` → `defer`, `FAIL` → `reloop`, `NOT_EVALUATED` → `escalate`). Under `--profile production` the same run additionally ANDs two signals — `nfr_status` and `review_score` populate, and any failure downgrades an otherwise-`advance` verdict to `reloop`. The contract is fail-closed: a missing or unparseable signal counts as a _failing_ one, so prose drift degrades to a conservative re-loop, never a silent false-advance.
|
|
65
|
+
|
|
66
|
+
## Install
|
|
67
|
+
|
|
68
|
+
Requires [Claude Code](https://www.anthropic.com/claude-code) (the runtime UCG conducts — see above), [Node.js](https://nodejs.org/) >= 22, [Python](https://www.python.org/) >= 3.10, [uv](https://docs.astral.sh/uv/) (Python package runner), plus `git` and `gh` on PATH.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npx bmad-module-ultracode-goal install
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You'll be prompted for a project name, your IDEs, and whether to install the learning material.
|
|
75
|
+
|
|
76
|
+
> **Hook security:** UCG installs `PreToolUse`/`Stop` hooks into your machine-local, gitignored `.claude/settings.local.json` at preflight — never into a committed file. They run zero-dependency Python scripts shipped in the skill. See [SECURITY.md](SECURITY.md) for exactly what they execute and how to remove them.
|
|
77
|
+
|
|
78
|
+
UCG is also available through the Claude plugin marketplace as an alternative to the npx installer — see [Getting Started](./docs/getting-started.md) for that path.
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
Invoke the skill in natural language — "run this epic autonomously," "execute this epic," or `ultracode goal`. The conductor ingests the epic, preflights, defines done with TEA, executes, gates, and finalizes. Flags shape the run:
|
|
83
|
+
|
|
84
|
+
- `--light` — run the **trace gate only** (the production default runs the full TEA gate set).
|
|
85
|
+
- `--parallel` — opt into the **experimental** worktree fan-out instead of the sequential `/goal` spine.
|
|
86
|
+
- `--yes` — skip Stage 1's open-floor invite and the launch confirm. It **never** skips the hard preflight gate.
|
|
87
|
+
- `-H` — headless: run non-interactively and emit the five-key status JSON at every exit point.
|
|
88
|
+
- `--retro` — run the close-out retrospective (interactive runs offer it anyway; headless runs it only when this flag is passed).
|
|
89
|
+
|
|
90
|
+
See [How It Works](./docs/how-it-works.md) for the full stage-by-stage walkthrough and headless contract.
|
|
91
|
+
|
|
92
|
+
## Who Is This For?
|
|
93
|
+
|
|
94
|
+
- **Claude Code users running BMAD Epics** who want unattended delivery backed by a real gate, not an optimistic transcript.
|
|
95
|
+
- **Anyone burned by "the agent said it was done"** and who wants completion decided by a file on disk they can read themselves.
|
|
96
|
+
- **Engineers who want rollback they can trust** — every green story is one git commit on an isolated epic branch, not a `/rewind` checkpoint that misses Bash changes.
|
|
97
|
+
|
|
98
|
+
## How UCG Compares
|
|
99
|
+
|
|
100
|
+
A skeptical reader is probably already running one of these. Here is the honest contrast:
|
|
101
|
+
|
|
102
|
+
| | **UltraCode Goal** | Hand-driven `/goal` per story | Plain Auto Mode | CI-only gating |
|
|
103
|
+
| -------------------------- | ---------------------------------------------------- | ------------------------------------ | -------------------------------- | ------------------------------------ |
|
|
104
|
+
| Completion authority | `gate_eval.py` reads TEA's `gate-decision.json` | you, story by story | the model's self-assessment | CI, but only after the agent stops |
|
|
105
|
+
| Preflight autonomy gate | hard-gate to remediated green (intervention budget 0)| ad hoc, per story | none | none — CI runs post-hoc |
|
|
106
|
+
| Invariants enforcement | `PreToolUse` hooks in `settings.local.json` | your attention | prompt text (context, not a gate)| CI checks, after the fact |
|
|
107
|
+
| Rollback | git: epic branch, one commit per green story | manual | `/rewind` (misses Bash changes) | revert after merge |
|
|
108
|
+
| Knowledge capture | Auto Memory + CLAUDE.md split at Finalize | none structured | none structured | none |
|
|
109
|
+
|
|
110
|
+
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.**
|
|
111
|
+
|
|
112
|
+
## How It Works
|
|
113
|
+
|
|
114
|
+
UCG runs six stages in order, each routing by the testable conditions stated in its reference file:
|
|
115
|
+
|
|
116
|
+
1. **Ingest & Scope** — resolve the epic and its artifacts; confirm the profile (production default / `--light`).
|
|
117
|
+
2. **Preflight** — auto-remediate ambers, then hard-gate on red; create the git branch, merge hooks, populate the allowlist.
|
|
118
|
+
3. **Define Done** — TEA test-design plus per-story ATDD turn acceptance criteria into executable, red-phase tests.
|
|
119
|
+
4. **Execute** — the sequential `/goal` spine (default) or the `--parallel` worktree fan-out.
|
|
120
|
+
5. **Gate** — `gate_eval.py` reads TEA's verdict and routes: advance / defer / reloop / escalate.
|
|
121
|
+
6. **Finalize** — Auto Memory capture, optional retrospective, decision-log audit, run report.
|
|
122
|
+
|
|
123
|
+
Three enforcement layers keep the autonomy honest:
|
|
124
|
+
|
|
125
|
+
- **Hooks are the invariants** — `PreToolUse` guards (no commit on a protected branch; no commit before tests ran for the story) live in `settings.local.json`, where the runtime enforces them, not in memory.
|
|
126
|
+
- **`gate_eval.py` is the completion truth** — advancement is decided by reading TEA's gate file, never by the conductor's judgment and never by the `/goal` evaluator alone.
|
|
127
|
+
- **The Stop hook plus the turn cap are the budget** — the in-`/goal`-condition turn cap is the primary runaway guard; the `Stop` hook is a defensive third layer that records overruns against `max_turns_per_story` / `story_token_budget`.
|
|
128
|
+
|
|
129
|
+
## Verifying
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
Run the Python suite (72 tests across the preflight, gate, hook, and fingerprint scripts):
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
uv run --with pytest pytest skills/ultracode-goal/scripts/tests/ -v
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Then inspect any `gate-decision.json` TEA wrote and evaluate it directly:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
uv run skills/ultracode-goal/scripts/gate_eval.py \
|
|
143
|
+
--trace-output path/to/traceability \
|
|
144
|
+
--profile light
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The JSON it prints is the same object UCG routes on — `verdict`, `gate_status`, and the `reasons` trail that explains how it got there. Nothing is hidden behind the model.
|
|
148
|
+
|
|
149
|
+
## Help UCG Improve
|
|
150
|
+
|
|
151
|
+
Every run that reaches Finalize ends with a self-improvement check. When it finds a defect in its own stage references, it can file a GitHub issue — deduplicated by a deterministic fingerprint so re-reporting is safe — with your approval. Headless runs queue findings to a machine-local cache instead of filing live. The fingerprint is install-mode-invariant, so the same defect maps to the same issue whether it surfaced in a dev checkout or an installed tree. **Please let runs finish through Finalize**, or [open an issue](https://github.com/armelhbobdad/bmad-module-ultracode-goal/issues/new/choose) directly. If UCG saved you an afternoon of babysitting, a ⭐ helps others find it.
|
|
152
|
+
|
|
153
|
+
## Learn More
|
|
154
|
+
|
|
155
|
+
The docs are organized into three buckets — **Why** (start here), **Try** (do stuff), and **Reference** (look things up):
|
|
156
|
+
|
|
157
|
+
**Why**
|
|
158
|
+
|
|
159
|
+
- **[Why UltraCode Goal](./docs/why-ultracode-goal.md)** — the problem, the three enforcement layers, and when not to use it.
|
|
160
|
+
|
|
161
|
+
**Try**
|
|
162
|
+
|
|
163
|
+
- **[Getting Started](./docs/getting-started.md)** — install, prerequisites, the flags, and your first autonomous run.
|
|
164
|
+
- **[How It Works](./docs/how-it-works.md)** — the six stages, their routing conditions, and the headless five-key emit.
|
|
165
|
+
- **[Parallel Mode](./docs/parallel-mode.md)** — the experimental worktree fan-out and its known limits.
|
|
166
|
+
|
|
167
|
+
**Reference**
|
|
168
|
+
|
|
169
|
+
- **[Architecture](./docs/architecture.md)** — the conductor model, enforcement layers in depth, and `customize.toml` resolution.
|
|
170
|
+
- **[Gate Model](./docs/gate-model.md)** — how `gate_eval.py` maps `gate_status` to a verdict, and the production AND-signals.
|
|
171
|
+
- **[Health Check](./docs/health-check.md)** — the terminal self-improvement loop: what it sends, privacy, and how to disable it.
|
|
172
|
+
- **[Troubleshooting](./docs/troubleshooting.md)** — real failure modes and their remediations.
|
|
173
|
+
|
|
174
|
+
## Acknowledgements
|
|
175
|
+
|
|
176
|
+
UCG is a conductor over primitives it does not replace. It builds on:
|
|
177
|
+
|
|
178
|
+
| Tool | Role in UCG |
|
|
179
|
+
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
180
|
+
| [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) | The epic toolbox UCG orchestrates (sprint planning, story creation, dev, review) |
|
|
181
|
+
| [TEA Test Architect](https://github.com/bmad-code-org/BMAD-METHOD) | Machine-checked quality gates — test-design, ATDD, NFR, trace; the gate artifact |
|
|
182
|
+
| [Claude Code](https://www.anthropic.com/claude-code) | `/goal`, Auto Mode, Auto Memory, hooks, and git worktrees — the primitives UCG composes |
|
|
183
|
+
|
|
184
|
+
## Contributing
|
|
185
|
+
|
|
186
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
187
|
+
|
|
188
|
+
## Changelog
|
|
189
|
+
|
|
190
|
+
Past releases are documented in [CHANGELOG.md](CHANGELOG.md).
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
**UltraCode Goal (UCG)** — A standalone [BMAD](https://github.com/bmad-code-org/BMAD-METHOD) module for autonomous epic delivery.
|
|
199
|
+
|
|
200
|
+
See [CONTRIBUTORS.md](CONTRIBUTORS.md) for contributor information.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Maintainer runbook for cutting a release of `bmad-module-ultracode-goal`. The canonical release path is [`.github/workflows/release.yaml`](../../.github/workflows/release.yaml) — manual dispatch, OIDC trusted publishing, no token secrets.
|
|
4
|
+
|
|
5
|
+
## How a release works
|
|
6
|
+
|
|
7
|
+
Dispatching `release.yaml` from `main` runs, in order:
|
|
8
|
+
|
|
9
|
+
1. Quality gate (`npm test`) on the release runner.
|
|
10
|
+
2. Version bump (`npm version` — `alpha`/`beta`/`rc` prerelease or `patch`/`minor`/`major`).
|
|
11
|
+
3. Sync `.claude-plugin/marketplace.json` `.plugins[0].version` to the new version (atomic jq edit).
|
|
12
|
+
4. CHANGELOG update via `conventional-changelog-cli`, preamble restored to Keep-a-Changelog shape.
|
|
13
|
+
5. Pre-publish `npm publish --dry-run` (catches package validation failures before anything is pushed).
|
|
14
|
+
6. **PR-auto-merge flow**: the release commit is pushed to a temp branch `release/bot/vX.Y.Z-<run_id>`, a bot PR is opened against `main`, `quality.yaml` is force-dispatched against the temp branch (PR events from `GITHUB_TOKEN` do not fire workflows), the workflow waits for all required status checks, then for maintainer approval (or an admin bypass-merge), then auto-merges with a merge commit.
|
|
15
|
+
7. Tag `vX.Y.Z` anchored on the merge commit.
|
|
16
|
+
8. `npm publish` via OIDC trusted publishing (provenance auto-attached).
|
|
17
|
+
9. GitHub Release created from generated notes.
|
|
18
|
+
|
|
19
|
+
Dispatching from a non-`main` ref skips the PR flow: the tag anchors on the CI-ephemeral commit and `main` is not advanced. This is the expected path for prerelease cuts from feature branches.
|
|
20
|
+
|
|
21
|
+
## One-time setup
|
|
22
|
+
|
|
23
|
+
These must exist before the first `main`-dispatch release. Order matters.
|
|
24
|
+
|
|
25
|
+
### 1. Required-check contexts must exist
|
|
26
|
+
|
|
27
|
+
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:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
prettier
|
|
31
|
+
eslint
|
|
32
|
+
markdownlint
|
|
33
|
+
validate (ubuntu-latest)
|
|
34
|
+
validate (windows-latest)
|
|
35
|
+
python (ubuntu-latest)
|
|
36
|
+
python (windows-latest)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Main-branch ruleset
|
|
40
|
+
|
|
41
|
+
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:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gh api /repos/armelhbobdad/bmad-module-ultracode-goal/rulesets --jq '.[] | {id, name}'
|
|
45
|
+
gh variable set RELEASE_RULESET_ID --body "<id>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The wait-for-checks step fetches the required-context list from this ruleset at run time, so the workflow can never drift from branch protection. It fails fast with a setup hint if the variable is unset.
|
|
49
|
+
|
|
50
|
+
### 3. `release` GitHub Environment
|
|
51
|
+
|
|
52
|
+
Create an Environment named `release` with `armelhbobdad` as a required reviewer. `github-actions[bot]` cannot self-approve; every release run pauses for this approval before any step executes.
|
|
53
|
+
|
|
54
|
+
### 4. npm Trusted Publisher
|
|
55
|
+
|
|
56
|
+
On [npmjs.com](https://www.npmjs.com/) → package settings → Trusted Publisher, register:
|
|
57
|
+
|
|
58
|
+
- Repository: `armelhbobdad/bmad-module-ultracode-goal`
|
|
59
|
+
- Workflow filename: `release.yaml` (character-for-character — renaming the file breaks publishing)
|
|
60
|
+
- Environment: `release`
|
|
61
|
+
|
|
62
|
+
The workflow upgrades npm to ≥ 11.5.1 (the OIDC trusted-publishing floor) and pins `NPM_TOKEN: ""` on both publish steps so a stale runner-env token can never be picked up silently. Note: the very first publish of a brand-new package may need to be performed manually (`npm publish` with a granular token) before Trusted Publisher can be attached to the package — check current npm rules when cutting `0.1.0`.
|
|
63
|
+
|
|
64
|
+
### 5. Auto-merge repo setting
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
gh api --method PATCH /repos/armelhbobdad/bmad-module-ultracode-goal -f allow_auto_merge=true
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Without it, `gh pr merge --auto` in the workflow fails.
|
|
71
|
+
|
|
72
|
+
### 6. Health-check labels
|
|
73
|
+
|
|
74
|
+
The health-check loop's `gh issue create` hard-fails on missing labels (only the per-fingerprint `fp-*` label is guarded with `|| true`). Pre-create the fixed set:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
for L in "health-check:0E8A16" "workflow-improvement:1D76DB" "bug:D73A4A" "friction:FBCA04" "gap:C5DEF5" "duplicate:CFD3D7"; do
|
|
78
|
+
gh label create "${L%%:*}" --repo armelhbobdad/bmad-module-ultracode-goal --color "${L##*:}" 2>/dev/null || true
|
|
79
|
+
done
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Version-coupling invariant
|
|
83
|
+
|
|
84
|
+
`package.json` `version` and `.claude-plugin/marketplace.json` `.plugins[0].version` must always be equal. The release workflow enforces this at release time (step 3); between releases, keep them equal by hand — `npm run test:install` asserts the coupling and fails the quality gate on drift.
|
|
85
|
+
|
|
86
|
+
## Cutting a release
|
|
87
|
+
|
|
88
|
+
1. Confirm `main` is green and the working tree state you want to ship is merged.
|
|
89
|
+
2. Actions → Release → Run workflow → choose the bump type. Prefer an `alpha` for the first cut after any pipeline change — it exercises the full path with a low-stakes version.
|
|
90
|
+
3. Approve the `release` environment run when prompted.
|
|
91
|
+
4. Approve (or admin-merge) the bot PR when checks are green.
|
|
92
|
+
5. After publish, dispatch `install-smoke.yaml` with the new version — it verifies `npx bmad-module-ultracode-goal@<version> --version` on ubuntu/windows/macos.
|
|
93
|
+
|
|
94
|
+
## Rollback playbook
|
|
95
|
+
|
|
96
|
+
npm unpublish is heavily restricted; prefer forward fixes.
|
|
97
|
+
|
|
98
|
+
- **Bad publish, caught quickly:** `npm deprecate bmad-module-ultracode-goal@X.Y.Z "broken — use X.Y.Z+1"`, then cut a patch release.
|
|
99
|
+
- **Bad prerelease tag:** point the dist-tag back: `npm dist-tag add bmad-module-ultracode-goal@<good> alpha`.
|
|
100
|
+
- **Bad git tag (not yet published):** delete the tag (`git push origin :refs/tags/vX.Y.Z`) and the bot PR/branch, then re-dispatch.
|
|
101
|
+
- **Workflow died mid-flow:** the PR (if opened) is left open by design for inspection. Close it, delete the temp branch, fix the cause, re-dispatch — the `run_id`-suffixed branch name prevents collisions on retry.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Stability and Public Contract
|
|
2
|
+
|
|
3
|
+
> **Status:** 0.x — pre-1.0. The surfaces below are the intended public contract at `0.1.0`. Per [Semantic Versioning 2.0.0](https://semver.org/), a `0.x` series makes no stability guarantee across minor versions; this document records what we *try* to hold stable and what is explicitly `@internal`, so a consumer knows which surfaces to pin against and which to treat as free to change.
|
|
4
|
+
|
|
5
|
+
This is the stability posture for `bmad-module-ultracode-goal` at `0.1.0`. It enumerates the surfaces a downstream consumer or automator may reasonably depend on, versus everything else, which is `@internal`.
|
|
6
|
+
|
|
7
|
+
## Public contract at 0.1.0
|
|
8
|
+
|
|
9
|
+
The following surfaces are the intended public contract. We aim not to break them within the `0.x` series without a deprecation note; see [SemVer note](#semver-note).
|
|
10
|
+
|
|
11
|
+
### CLI command surface
|
|
12
|
+
|
|
13
|
+
The installer CLI is invoked via `npx bmad-module-ultracode-goal <subcommand>`. Covered:
|
|
14
|
+
|
|
15
|
+
- **Subcommands**: `install`, `update`, `status`, `uninstall`. Renaming, removing, or changing the semantics of any subcommand is a contract change.
|
|
16
|
+
- **Options**: `-V` / `--version` (prints the installed package version) and `-h` / `--help` (top-level and per-subcommand).
|
|
17
|
+
|
|
18
|
+
### The `[workflow]` customize.toml keys
|
|
19
|
+
|
|
20
|
+
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).
|
|
21
|
+
|
|
22
|
+
### The headless five-key JSON emit shape
|
|
23
|
+
|
|
24
|
+
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:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{"status": "complete|blocked",
|
|
28
|
+
"skill": "ultracode-goal",
|
|
29
|
+
"decision_log": "<path>",
|
|
30
|
+
"report": "<path or null>",
|
|
31
|
+
"deferred_work": "<path or null>",
|
|
32
|
+
"reason": "<one line when blocked, else null>"}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
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.
|
|
36
|
+
|
|
37
|
+
### The skill name and invocation phrases
|
|
38
|
+
|
|
39
|
+
The skill name `ultracode-goal` and its documented invocation phrases — "run an epic autonomously", "execute this epic", "ultracode goal", "autonomously deliver the epic" — are part of the contract. Removing or renaming the skill, or dropping a documented trigger phrase, is a contract change.
|
|
40
|
+
|
|
41
|
+
### gate_eval.py CLI and verdict vocabulary
|
|
42
|
+
|
|
43
|
+
`scripts/gate_eval.py` is the deterministic completion authority. Covered:
|
|
44
|
+
|
|
45
|
+
- **CLI flags**: `--trace-output` (required), `--profile` (`light` | `production`, required), `--nfr`, `--test-review` (production only).
|
|
46
|
+
- **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).
|
|
47
|
+
|
|
48
|
+
The printed JSON object's key set (`verdict`, `gate_status`, `p0_status`, `p1_status`, `overall_status`, `nfr_status`, `review_score`, `reasons`) is the consumable shape; the human-readable `reasons` strings are not contractual wording.
|
|
49
|
+
|
|
50
|
+
## @internal — not covered
|
|
51
|
+
|
|
52
|
+
Everything not enumerated above is `@internal` and may change in any `0.x` release without a deprecation note. Do not pin against:
|
|
53
|
+
|
|
54
|
+
- **Installer library internals** — the implementation behind the CLI subcommands; what is covered is the observable subcommand surface, not how the files get placed.
|
|
55
|
+
- **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.
|
|
56
|
+
- **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.
|
|
57
|
+
- **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).
|
|
58
|
+
- **`_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.
|
|
59
|
+
|
|
60
|
+
## SemVer note
|
|
61
|
+
|
|
62
|
+
This is a `0.x` module: **minor versions may break.** We try to hold the surfaces in [Public contract at 0.1.0](#public-contract-at-010) stable, and the two surfaces an automator is most likely to encode against — the **headless five-key JSON emit shape** and the **`[workflow]` customize.toml keys** — get a deprecation note in `CHANGELOG.md` before changing. `@internal` surfaces change freely. Once the module reaches `1.0.0`, this document is superseded by a full SemVer contract.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
UltraCode Goal is a conductor. It orchestrates the installed BMAD epic toolbox and the TEA gates, composing Claude Code primitives — `/goal`, Auto Mode, Auto Memory, hooks, git/worktree isolation — and replaces none of them. This page covers the conductor model, the three enforcement layers in depth, the file layout, customization resolution, and why the hooks live where they do.
|
|
4
|
+
|
|
5
|
+
## The conductor model
|
|
6
|
+
|
|
7
|
+
The skill owns no implementation logic of its own for building features or running tests. What it owns is the *order*, the *gates*, and the *enforcement*. It delegates:
|
|
8
|
+
|
|
9
|
+
- **Epic toolbox** — `bmad-sprint-planning`, `bmad-create-story`, `bmad-check-implementation-readiness`, `bmad-dev-story`, `bmad-code-review`, `bmad-correct-course`, `bmad-sprint-status`, `bmad-retrospective`.
|
|
10
|
+
- **TEA gates** — `bmad-testarch-framework`, `-ci`, `-test-design`, `-atdd`, `-automate`, `-test-review`, `-nfr`, `-trace`.
|
|
11
|
+
- **Claude Code primitives** — the `/goal` loop drives execution; Auto Mode and ultracode session effort make the unattended run possible; Auto Memory carries learnings forward; hooks enforce invariants; git branches and worktrees provide isolation and rollback.
|
|
12
|
+
|
|
13
|
+
Because it is a conductor, the truth of "is this done" lives in the artifacts its delegates produce, not in the conductor's own reasoning. That is the whole design: the model arranges the work, but a script reads the verdict.
|
|
14
|
+
|
|
15
|
+
## The three enforcement layers
|
|
16
|
+
|
|
17
|
+
These are the module's non-negotiables. Each exists because the documented mechanics make the intuitive shortcut wrong (see [why](why-ultracode-goal.md)).
|
|
18
|
+
|
|
19
|
+
### 1. Deterministic gate truth
|
|
20
|
+
|
|
21
|
+
`scripts/gate_eval.py` reads TEA's `gate-decision.json` and maps its gate status to a routing verdict. 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. See the [gate model](gate-model.md) for the full mapping, thresholds, and the fail-closed contract.
|
|
22
|
+
|
|
23
|
+
### 2. Hooks as invariants
|
|
24
|
+
|
|
25
|
+
Two invariants must hold for every commit, and neither can live in memory, which is context the model may or may not weigh:
|
|
26
|
+
|
|
27
|
+
- **`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.
|
|
28
|
+
- **`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.
|
|
29
|
+
|
|
30
|
+
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`.
|
|
31
|
+
|
|
32
|
+
### 3. Budget enforcement
|
|
33
|
+
|
|
34
|
+
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.
|
|
35
|
+
|
|
36
|
+
## File layout
|
|
37
|
+
|
|
38
|
+
The skill routes from a thin entry point down to just-in-time stage files, deterministic scripts, and an experimental asset:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
skills/ultracode-goal/
|
|
42
|
+
├── SKILL.md # Entry point: overview, conventions, run modes,
|
|
43
|
+
│ # non-negotiables, the 6-stage table, headless contract
|
|
44
|
+
├── customize.toml # Config base layer (the [workflow] block)
|
|
45
|
+
├── references/ # One file per stage, loaded just-in-time
|
|
46
|
+
│ ├── ingest-and-scope.md # Stage 1
|
|
47
|
+
│ ├── preflight.md # Stage 2 (the autonomy gate)
|
|
48
|
+
│ ├── define-done.md # Stage 3
|
|
49
|
+
│ ├── execute.md # Stage 4
|
|
50
|
+
│ ├── gate.md # Stage 5
|
|
51
|
+
│ └── finalize.md # Stage 6
|
|
52
|
+
├── scripts/ # Deterministic truth (run via `uv`)
|
|
53
|
+
│ ├── preflight_check.py # mechanical preflight facts + blocker budget
|
|
54
|
+
│ ├── gate_eval.py # gate status -> verdict (the completion authority)
|
|
55
|
+
│ ├── health_check_fp.py # health-check fingerprint + seen-cache plumbing
|
|
56
|
+
│ └── hooks/
|
|
57
|
+
│ ├── guard_pretooluse.py # commit invariants (PreToolUse)
|
|
58
|
+
│ └── budget_stop.py # turn/token budget (Stop)
|
|
59
|
+
└── assets/
|
|
60
|
+
└── execute-epic.workflow.js # EXPERIMENTAL --parallel worktree fan-out
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`SKILL.md` carries the routing and the contract; the `references/*.md` stage files carry the procedure and the testable routing conditions; the `scripts/*.py` files carry the deterministic facts the model cannot fudge; the `assets/*.js` workflow is the opt-in experimental execution path. See [how it works](how-it-works.md) for the stages and [parallel mode](parallel-mode.md) for the asset.
|
|
64
|
+
|
|
65
|
+
## Customization resolution
|
|
66
|
+
|
|
67
|
+
Configuration resolves in three layers, base → team → user, via `resolve_customization.py`:
|
|
68
|
+
|
|
69
|
+
1. **Base** — `customize.toml` in the skill root (the shipped `[workflow]` block).
|
|
70
|
+
2. **Team** — `{project-root}/_bmad/custom/ultracode-goal.toml`.
|
|
71
|
+
3. **User** — `{project-root}/_bmad/custom/ultracode-goal.user.toml`.
|
|
72
|
+
|
|
73
|
+
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).
|
|
74
|
+
|
|
75
|
+
## Why the hooks live in settings.local.json (decision D6)
|
|
76
|
+
|
|
77
|
+
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).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 480" width="480" height="480" role="img" aria-labelledby="ucgTitle ucgDesc">
|
|
2
|
+
<title id="ucgTitle">UltraCode Goal</title>
|
|
3
|
+
<desc id="ucgDesc">Six stage nodes orbit a hexagonal gate; an autonomous conductor circles them, and the centre verdict reads PASS.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="gateGrad" x1="0" y1="0" x2="1" y2="1">
|
|
6
|
+
<stop offset="0" stop-color="#6366F1"/>
|
|
7
|
+
<stop offset="1" stop-color="#4F46E5"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
|
10
|
+
<stop offset="0" stop-color="#6366F1" stop-opacity="0.16"/>
|
|
11
|
+
<stop offset="1" stop-color="#6366F1" stop-opacity="0"/>
|
|
12
|
+
</radialGradient>
|
|
13
|
+
<path id="orbit" d="M 240 70 A 170 170 0 1 1 239.99 70.0003" fill="none"/>
|
|
14
|
+
</defs>
|
|
15
|
+
|
|
16
|
+
<!-- ambient glow -->
|
|
17
|
+
<circle cx="240" cy="240" r="232" fill="url(#glow)"/>
|
|
18
|
+
|
|
19
|
+
<!-- outer gate frame (hexagon) -->
|
|
20
|
+
<polygon points="240,15 434.9,127.5 434.9,352.5 240,465 45.1,352.5 45.1,127.5"
|
|
21
|
+
fill="none" stroke="url(#gateGrad)" stroke-width="10" stroke-linejoin="round" opacity="0.9"/>
|
|
22
|
+
|
|
23
|
+
<!-- orbit ring -->
|
|
24
|
+
<circle cx="240" cy="240" r="170" fill="none" stroke="#818CF8" stroke-opacity="0.35"
|
|
25
|
+
stroke-width="3" stroke-dasharray="2 12" stroke-linecap="round"/>
|
|
26
|
+
|
|
27
|
+
<!-- six stage nodes (Ingest, Preflight, Define Done, Execute, Gate, Finalize) -->
|
|
28
|
+
<g fill="#818CF8">
|
|
29
|
+
<circle cx="240" cy="70" r="11" opacity="0.5">
|
|
30
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="0s" repeatCount="indefinite"/>
|
|
31
|
+
</circle>
|
|
32
|
+
<circle cx="387.2" cy="155" r="11" opacity="0.5">
|
|
33
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="1.5s" repeatCount="indefinite"/>
|
|
34
|
+
</circle>
|
|
35
|
+
<circle cx="387.2" cy="325" r="11" opacity="0.5">
|
|
36
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="3s" repeatCount="indefinite"/>
|
|
37
|
+
</circle>
|
|
38
|
+
<circle cx="240" cy="410" r="11" opacity="0.5">
|
|
39
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="4.5s" repeatCount="indefinite"/>
|
|
40
|
+
</circle>
|
|
41
|
+
<circle cx="92.8" cy="325" r="11" opacity="0.5">
|
|
42
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="6s" repeatCount="indefinite"/>
|
|
43
|
+
</circle>
|
|
44
|
+
<circle cx="92.8" cy="155" r="11" opacity="0.5">
|
|
45
|
+
<animate attributeName="opacity" values="0.5;1;0.5;0.5" keyTimes="0;0.06;0.14;1" dur="9s" begin="7.5s" repeatCount="indefinite"/>
|
|
46
|
+
</circle>
|
|
47
|
+
</g>
|
|
48
|
+
|
|
49
|
+
<!-- the autonomous conductor, circling the stages -->
|
|
50
|
+
<g>
|
|
51
|
+
<circle r="8" fill="#A5B4FC">
|
|
52
|
+
<animateMotion dur="9s" repeatCount="indefinite">
|
|
53
|
+
<mpath href="#orbit"/>
|
|
54
|
+
</animateMotion>
|
|
55
|
+
</circle>
|
|
56
|
+
<circle r="14" fill="none" stroke="#A5B4FC" stroke-opacity="0.45" stroke-width="2">
|
|
57
|
+
<animateMotion dur="9s" repeatCount="indefinite">
|
|
58
|
+
<mpath href="#orbit"/>
|
|
59
|
+
</animateMotion>
|
|
60
|
+
</circle>
|
|
61
|
+
</g>
|
|
62
|
+
|
|
63
|
+
<!-- inner gate -->
|
|
64
|
+
<polygon points="240,122 342.2,181 342.2,299 240,358 137.8,299 137.8,181"
|
|
65
|
+
fill="url(#gateGrad)" stroke="#4F46E5" stroke-width="4" stroke-linejoin="round"/>
|
|
66
|
+
|
|
67
|
+
<!-- the machine-checked verdict -->
|
|
68
|
+
<path d="M 193 248 L 226 281 L 291 203" fill="none" stroke="#FFFFFF"
|
|
69
|
+
stroke-width="20" stroke-linecap="round" stroke-linejoin="round"
|
|
70
|
+
stroke-dasharray="170" stroke-dashoffset="170">
|
|
71
|
+
<animate attributeName="stroke-dashoffset" from="170" to="0" dur="0.9s" begin="0.5s" fill="freeze"/>
|
|
72
|
+
</path>
|
|
73
|
+
</svg>
|