mindforge-cc 1.0.5 → 2.0.0-alpha.6
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/.agent/CLAUDE.md +83 -0
- package/.agent/mindforge/auto.md +22 -0
- package/.agent/mindforge/browse.md +26 -0
- package/.agent/mindforge/costs.md +11 -0
- package/.agent/mindforge/cross-review.md +17 -0
- package/.agent/mindforge/dashboard.md +98 -0
- package/.agent/mindforge/execute-phase.md +5 -3
- package/.agent/mindforge/init-project.md +12 -0
- package/.agent/mindforge/qa.md +16 -0
- package/.agent/mindforge/remember.md +14 -0
- package/.agent/mindforge/research.md +11 -0
- package/.agent/mindforge/steer.md +13 -0
- package/.agent/workflows/publish-release.md +36 -0
- package/.claude/CLAUDE.md +83 -0
- package/.claude/commands/mindforge/auto.md +22 -0
- package/.claude/commands/mindforge/browse.md +26 -0
- package/.claude/commands/mindforge/costs.md +11 -0
- package/.claude/commands/mindforge/cross-review.md +17 -0
- package/.claude/commands/mindforge/dashboard.md +98 -0
- package/.claude/commands/mindforge/execute-phase.md +5 -3
- package/.claude/commands/mindforge/qa.md +16 -0
- package/.claude/commands/mindforge/remember.md +14 -0
- package/.claude/commands/mindforge/research.md +11 -0
- package/.claude/commands/mindforge/steer.md +13 -0
- package/.mindforge/MINDFORGE-V2-SCHEMA.json +47 -0
- package/.mindforge/browser/daemon-protocol.md +24 -0
- package/.mindforge/browser/qa-engine.md +16 -0
- package/.mindforge/browser/session-manager.md +18 -0
- package/.mindforge/browser/visual-verify-spec.md +31 -0
- package/.mindforge/dashboard/api-reference.md +122 -0
- package/.mindforge/dashboard/dashboard-spec.md +96 -0
- package/.mindforge/engine/autonomous/auto-executor.md +266 -0
- package/.mindforge/engine/autonomous/headless-adapter.md +66 -0
- package/.mindforge/engine/autonomous/node-repair.md +190 -0
- package/.mindforge/engine/autonomous/progress-reporter.md +58 -0
- package/.mindforge/engine/autonomous/steering-manager.md +64 -0
- package/.mindforge/engine/autonomous/stuck-detector.md +89 -0
- package/.mindforge/memory/MEMORY-SCHEMA.md +155 -0
- package/.mindforge/memory/decision-library.jsonl +0 -0
- package/.mindforge/memory/engine/capture-protocol.md +36 -0
- package/.mindforge/memory/engine/global-sync-spec.md +42 -0
- package/.mindforge/memory/engine/retrieval-spec.md +44 -0
- package/.mindforge/memory/knowledge-base.jsonl +7 -0
- package/.mindforge/memory/pattern-library.jsonl +1 -0
- package/.mindforge/memory/team-preferences.jsonl +4 -0
- package/.mindforge/models/model-registry.md +48 -0
- package/.mindforge/models/model-router.md +30 -0
- package/.mindforge/personas/research-agent.md +24 -0
- package/.planning/approvals/v2-architecture-approval.json +15 -0
- package/.planning/browser-daemon.log +32 -0
- package/.planning/decisions/ADR-021-autonomy-boundary.md +17 -0
- package/.planning/decisions/ADR-022-node-repair-hierarchy.md +19 -0
- package/.planning/decisions/ADR-023-gate-3-timing.md +15 -0
- package/CHANGELOG.md +81 -0
- package/MINDFORGE.md +26 -3
- package/README.md +70 -18
- package/bin/autonomous/auto-runner.js +95 -0
- package/bin/autonomous/headless.js +36 -0
- package/bin/autonomous/progress-stream.js +49 -0
- package/bin/autonomous/repair-operator.js +213 -0
- package/bin/autonomous/steer.js +71 -0
- package/bin/autonomous/stuck-monitor.js +77 -0
- package/bin/browser/browser-daemon.js +139 -0
- package/bin/browser/daemon-manager.js +91 -0
- package/bin/browser/qa-engine.js +47 -0
- package/bin/browser/qa-report-writer.js +32 -0
- package/bin/browser/regression-writer.js +27 -0
- package/bin/browser/screenshot-store.js +49 -0
- package/bin/browser/session-manager.js +93 -0
- package/bin/browser/visual-verify-executor.js +89 -0
- package/bin/change-classifier.js +86 -0
- package/bin/dashboard/api-router.js +198 -0
- package/bin/dashboard/approval-handler.js +134 -0
- package/bin/dashboard/frontend/index.html +511 -0
- package/bin/dashboard/metrics-aggregator.js +296 -0
- package/bin/dashboard/server.js +135 -0
- package/bin/dashboard/sse-bridge.js +178 -0
- package/bin/dashboard/team-tracker.js +0 -0
- package/bin/governance/approve.js +60 -0
- package/bin/install.js +4 -4
- package/bin/installer-core.js +91 -35
- package/bin/memory/cli.js +99 -0
- package/bin/memory/global-sync.js +107 -0
- package/bin/memory/knowledge-capture.js +278 -0
- package/bin/memory/knowledge-indexer.js +172 -0
- package/bin/memory/knowledge-store.js +319 -0
- package/bin/memory/session-memory-loader.js +137 -0
- package/bin/migrations/0.1.0-to-0.5.0.js +2 -3
- package/bin/migrations/0.5.0-to-0.6.0.js +1 -1
- package/bin/migrations/0.6.0-to-1.0.0.js +3 -3
- package/bin/migrations/migrate.js +15 -11
- package/bin/mindforge-cli.js +87 -0
- package/bin/models/anthropic-provider.js +77 -0
- package/bin/models/cost-tracker.js +118 -0
- package/bin/models/gemini-provider.js +79 -0
- package/bin/models/model-client.js +98 -0
- package/bin/models/model-router.js +111 -0
- package/bin/models/openai-provider.js +78 -0
- package/bin/research/research-engine.js +115 -0
- package/bin/review/cross-review-engine.js +81 -0
- package/bin/review/finding-synthesizer.js +116 -0
- package/bin/review/review-report-writer.js +49 -0
- package/bin/updater/self-update.js +13 -13
- package/bin/wizard/setup-wizard.js +5 -1
- package/docs/adr/ADR-024-browser-localhost-only.md +17 -0
- package/docs/adr/ADR-025-visual-verify-failure-treatment.md +19 -0
- package/docs/adr/ADR-026-session-persistence-security.md +20 -0
- package/docs/architecture/README.md +6 -2
- package/docs/ci-cd.md +92 -0
- package/docs/commands-reference.md +1 -0
- package/docs/feature-dashboard.md +52 -0
- package/docs/publishing-guide.md +43 -0
- package/docs/reference/commands.md +17 -2
- package/docs/reference/sdk-api.md +6 -1
- package/docs/testing-current-version.md +130 -0
- package/docs/user-guide.md +115 -9
- package/docs/usp-features.md +70 -8
- package/docs/workflow-atlas.md +57 -0
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,87 @@
|
|
|
3
3
|
All notable changes to MindForge are documented here.
|
|
4
4
|
Format follows [Keep a Changelog](https://keepachangelog.com).
|
|
5
5
|
|
|
6
|
+
## [2.0.0-alpha.6] — Day 12: Real-time Observability Dashboard — 2026-03-22
|
|
7
|
+
|
|
8
|
+
- [v2.0.0-alpha.6 (2026-03-22)]
|
|
9
|
+
- [NEW] Real-time Dashboard Server (Express + SSE Bridge).
|
|
10
|
+
- [NEW] Premium 5-tab UI: Activity, Metrics, Approvals, Memory, Team.
|
|
11
|
+
- [NEW] Live Data Streaming for Audit Logs, Quality, Costs, and Team Activity.
|
|
12
|
+
- [NEW] Hardened Tier 3 Governance: Mandatory Plan ID typing for sensitive approvals.
|
|
13
|
+
- [NEW] Metrics Aggregator: Multi-source JSONL processing for observability.
|
|
14
|
+
- [NEW] CLI Command: `/mindforge:dashboard` for server lifecycle management.
|
|
15
|
+
- [NEW] ADR-033: Real-time Observability Architecture.
|
|
16
|
+
- [HARDENED] SSE Rotation Detection (Inode-based).
|
|
17
|
+
- [HARDENED] Localhost-only Security Model (Strict CORS/Binding).
|
|
18
|
+
|
|
19
|
+
## [2.0.0-alpha.4] — Day 11: Persistent Knowledge Graph (Long-Term Memory) — 2026-03-22
|
|
20
|
+
|
|
21
|
+
- [v2.0.0-alpha.4 (2026-03-22)]
|
|
22
|
+
- [NEW] Persistent Knowledge Graph for long-term memory across sessions.
|
|
23
|
+
- [NEW] TF-IDF search engine with confidence-based relevance ranking.
|
|
24
|
+
- [NEW] Automated Knowledge Capture from ADRs, Debug Reports, and Retrospectives.
|
|
25
|
+
- [NEW] Global Knowledge Sync for machine-wide insight sharing (`~/.mindforge/global-knowledge-base.jsonl`).
|
|
26
|
+
- [NEW] Skill SDK integration for programmatic memory access.
|
|
27
|
+
- [NEW] Manual memory management command (`/mindforge:remember`).
|
|
28
|
+
- [NEW] Append-only audit-ready storage schema for all knowledge types.
|
|
29
|
+
- [NEW] ADR-030, ADR-031, ADR-032.
|
|
30
|
+
|
|
31
|
+
## [2.0.0-alpha.3] — Day 10: Multi-Model Intelligence Layer — 2026-03-22
|
|
32
|
+
|
|
33
|
+
- [v2.0.0-alpha.3 (2026-03-22)]
|
|
34
|
+
- [NEW] Unified Multi-Model Intelligence Layer (Anthropic, OpenAI, Gemini).
|
|
35
|
+
- [NEW] Dynamic Model Router with Persona and Tier-based logic.
|
|
36
|
+
- [NEW] Real-time Cost Tracking and Daily Budget Enforcement.
|
|
37
|
+
- [NEW] Adversarial Cross-Model Code Review Engine (`/mindforge:cross-review`).
|
|
38
|
+
- [NEW] Deep Research Engine with Gemini 1.5 Pro 1M context support (`/mindforge:research`).
|
|
39
|
+
- [NEW] Model usage and cost reporting (`/mindforge:costs`).
|
|
40
|
+
- [NEW] Secure API handling with SSRF protection and header-based auth.
|
|
41
|
+
- [NEW] ADR-027, ADR-028, ADR-029.
|
|
42
|
+
|
|
43
|
+
## [2.0.0-alpha.2] — Day 9: Visual QA Engine (Browser Runtime Engine) — 2026-03-22
|
|
44
|
+
|
|
45
|
+
- [v2.0.0-alpha.2 (2026-03-22)]
|
|
46
|
+
- [NEW] Persistent Browser Runtime (Playwright-powered Chromium daemon).
|
|
47
|
+
- [NEW] Visual Verification Hook (`<verify-visual>`) in PLAN files.
|
|
48
|
+
- [NEW] Systematic Visual QA Engine (`/mindforge:qa`).
|
|
49
|
+
- [NEW] Persistent Session Management for Browser Control.
|
|
50
|
+
- [NEW] ADR-024, ADR-025, ADR-026.
|
|
51
|
+
|
|
52
|
+
- [v2.0.0-alpha.1 (2026-03-22)]
|
|
53
|
+
- Initial v2 scaffolding.
|
|
54
|
+
|
|
55
|
+
## [2.0.0-alpha.1] — Day 8: Autonomous Execution Engine — 2026-03-22
|
|
56
|
+
|
|
57
|
+
### Added (MindForge v2.0.0-alpha.1)
|
|
58
|
+
**Autonomous execution engine:**
|
|
59
|
+
- `/mindforge:auto` — walk-away autonomous phase/milestone execution
|
|
60
|
+
- `/mindforge:steer` — mid-execution guidance injection from second terminal
|
|
61
|
+
- Node repair operator: RETRY → DECOMPOSE → PRUNE → ESCALATE
|
|
62
|
+
- Stuck detection engine: 5 patterns (S01-S05)
|
|
63
|
+
- Headless CLI mode: `mindforge-cc headless --phase N`
|
|
64
|
+
- `.planning/steering-queue.jsonl` — steering instruction queue
|
|
65
|
+
- `.planning/auto-state.json` — real-time execution state
|
|
66
|
+
|
|
67
|
+
**MINDFORGE.md v2 settings:**
|
|
68
|
+
- AUTO_MODE_DEFAULT_TIMEOUT_MINUTES, AUTO_MODE_UAT
|
|
69
|
+
- AUTO_NODE_REPAIR_BUDGET, AUTO_RETRY_ON_VERIFY_FAIL
|
|
70
|
+
- AUTO_TASK_MAX_TOKENS, AUTO_TASK_TIMEOUT_MINUTES
|
|
71
|
+
- AUTO_PUSH_ON_WAVE_COMPLETE, AUTO_NOTIFY_ON_ESCALATION
|
|
72
|
+
|
|
73
|
+
### Hardened
|
|
74
|
+
- Gate 3 (secret detection) now runs PRE-COMMIT in auto mode
|
|
75
|
+
- Pre-flight dirty check excludes `.planning/` state files
|
|
76
|
+
- DECOMPOSE: dependency chain correctly updated in downstream plans
|
|
77
|
+
- S01 stuck detection requires consecutive failures
|
|
78
|
+
- S03 error normalization preserves module/package names
|
|
79
|
+
- Steering injection guard validates all instructions
|
|
80
|
+
- SIGTERM handler waits for task cleanup before saving state
|
|
81
|
+
|
|
82
|
+
### Architecture Decisions
|
|
83
|
+
- ADR-021: Autonomy Boundary
|
|
84
|
+
- ADR-022: Node Repair Hierarchy
|
|
85
|
+
- ADR-023: Gate 3 Timing
|
|
86
|
+
|
|
6
87
|
## [1.0.5] — v1.0.5 Minimal Install Option — 2026-03-22
|
|
7
88
|
|
|
8
89
|
### Added
|
package/MINDFORGE.md
CHANGED
|
@@ -22,9 +22,9 @@ If a configured model is unavailable, fallback to `inherit` and warn.
|
|
|
22
22
|
|
|
23
23
|
## Project identity
|
|
24
24
|
NAME=MindForge
|
|
25
|
-
VERSION=
|
|
26
|
-
DESCRIPTION=Enterprise agentic framework with
|
|
27
|
-
MINDFORGE_VERSION_REQUIRED=
|
|
25
|
+
VERSION=2.0.0
|
|
26
|
+
DESCRIPTION=Enterprise agentic framework with Multi-Model Intelligence Layer
|
|
27
|
+
MINDFORGE_VERSION_REQUIRED=2.0.0
|
|
28
28
|
|
|
29
29
|
## Model preferences
|
|
30
30
|
PLANNER_MODEL=claude-opus-4-5
|
|
@@ -33,6 +33,15 @@ REVIEWER_MODEL=claude-sonnet-4-5
|
|
|
33
33
|
VERIFIER_MODEL=claude-sonnet-4-5
|
|
34
34
|
SECURITY_MODEL=claude-opus-4-5
|
|
35
35
|
DEBUG_MODEL=claude-opus-4-5
|
|
36
|
+
RESEARCH_MODEL=gemini-1.5-pro
|
|
37
|
+
QA_MODEL=claude-4-5-sonnet
|
|
38
|
+
QUICK_MODEL=claude-4-5-haiku
|
|
39
|
+
|
|
40
|
+
## Cost Management
|
|
41
|
+
MODEL_COST_WARN_USD=1.00
|
|
42
|
+
MODEL_COST_HARD_LIMIT_USD=10.00
|
|
43
|
+
MODEL_PREFER_CHEAP_BELOW_DIFFICULTY=2.0
|
|
44
|
+
REQUIRE_CROSS_REVIEW=false
|
|
36
45
|
|
|
37
46
|
## Execution behavior
|
|
38
47
|
TIER1_AUTO_APPROVE=true
|
|
@@ -59,6 +68,20 @@ DISCUSS_PHASE_REQUIRED_ABOVE_DIFFICULTY=3.5
|
|
|
59
68
|
ANTIPATTERN_SENSITIVITY=standard
|
|
60
69
|
BLOCK_ON_HIGH_ANTIPATTERNS=false
|
|
61
70
|
|
|
71
|
+
## Autonomous mode settings
|
|
72
|
+
AUTO_MODE_DEFAULT_TIMEOUT_MINUTES=120
|
|
73
|
+
AUTO_PUSH_ON_WAVE_COMPLETE=false
|
|
74
|
+
AUTO_NODE_REPAIR_BUDGET=2
|
|
75
|
+
AUTO_PLAN_AMBIGUITY_THRESHOLD=3.5
|
|
76
|
+
SLACK_WEBHOOK_URL=
|
|
77
|
+
|
|
78
|
+
## Browser Runtime
|
|
79
|
+
BROWSER_PORT=7338
|
|
80
|
+
BROWSER_HEADLESS=true
|
|
81
|
+
DEV_SERVER_URL=http://localhost:3000
|
|
82
|
+
AUTO_RUN_QA_AFTER_UI_WAVES=true
|
|
83
|
+
BROWSER_IDLE_TIMEOUT_MINUTES=30
|
|
84
|
+
|
|
62
85
|
## Project-specific agent instructions
|
|
63
86
|
ADDITIONAL_AGENT_INSTRUCTIONS="""
|
|
64
87
|
- Check packages/shared before creating utilities.
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MindForge — Enterprise Agentic Framework (
|
|
1
|
+
# MindForge — Enterprise Agentic Framework (v2.0.0-alpha.6)
|
|
2
2
|
|
|
3
3
|
MindForge turns Claude Code and Antigravity into production-grade engineering
|
|
4
4
|
partners with governance, observability, and a disciplined workflow engine.
|
|
@@ -18,6 +18,11 @@ Decisions get forgotten. MindForge fixes that with:
|
|
|
18
18
|
- **Role personas** — specialised agent modes for each task type
|
|
19
19
|
- **Skills** — just-in-time domain knowledge loaded on demand
|
|
20
20
|
- **Wave execution** — parallelism with dependency safety
|
|
21
|
+
- **Autonomous Engine** — walk-away execution with steerability (v2)
|
|
22
|
+
- **Real-time Dashboard** — web-based observability and governance (v2)
|
|
23
|
+
- **Browser Runtime** — headful/headless visual QA and sessions (v2)
|
|
24
|
+
- **Multi-Model Intelligence** — dynamic routing, adversarial reviews, and deep research (v2)
|
|
25
|
+
- **Persistent Knowledge Graph** — long-term memory across all engineering sessions (v2)
|
|
21
26
|
- **Quality gates** — compliance and security are non-bypassable
|
|
22
27
|
- **Audit trail** — append-only history of every action
|
|
23
28
|
|
|
@@ -35,6 +40,16 @@ npx mindforge-cc@latest --claude --global
|
|
|
35
40
|
npx mindforge-cc@latest --claude --local
|
|
36
41
|
```
|
|
37
42
|
|
|
43
|
+
### Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Install the latest stable version
|
|
47
|
+
npm install -g mindforge-cc
|
|
48
|
+
|
|
49
|
+
# Or try the v2.0.0-alpha (latest features)
|
|
50
|
+
npm install -g mindforge-cc@alpha
|
|
51
|
+
```
|
|
52
|
+
|
|
38
53
|
### Antigravity
|
|
39
54
|
```bash
|
|
40
55
|
npx mindforge-cc@latest --antigravity --global
|
|
@@ -61,18 +76,19 @@ npx mindforge-cc@latest --all --global
|
|
|
61
76
|
|
|
62
77
|
## Verify
|
|
63
78
|
Open Claude Code or Antigravity in your project directory and run:
|
|
64
|
-
```
|
|
79
|
+
```bash
|
|
65
80
|
/mindforge:health
|
|
66
81
|
```
|
|
82
|
+
|
|
67
83
|
If issues are found, run:
|
|
68
|
-
```
|
|
84
|
+
```bash
|
|
69
85
|
/mindforge:health --repair
|
|
70
86
|
```
|
|
71
87
|
|
|
72
88
|
---
|
|
73
89
|
|
|
74
90
|
## Quick start (new project)
|
|
75
|
-
```
|
|
91
|
+
```bash
|
|
76
92
|
/mindforge:init-project
|
|
77
93
|
/mindforge:plan-phase 1
|
|
78
94
|
/mindforge:execute-phase 1
|
|
@@ -81,7 +97,7 @@ If issues are found, run:
|
|
|
81
97
|
```
|
|
82
98
|
|
|
83
99
|
## Quick start (existing codebase)
|
|
84
|
-
```
|
|
100
|
+
```bash
|
|
85
101
|
/mindforge:map-codebase
|
|
86
102
|
/mindforge:plan-phase 1
|
|
87
103
|
```
|
|
@@ -89,7 +105,7 @@ If issues are found, run:
|
|
|
89
105
|
---
|
|
90
106
|
|
|
91
107
|
## Core workflow
|
|
92
|
-
```
|
|
108
|
+
```bash
|
|
93
109
|
/ mindforge:init-project
|
|
94
110
|
→ Requirements interview
|
|
95
111
|
→ Creates PROJECT.md, REQUIREMENTS.md, STATE.md
|
|
@@ -113,12 +129,42 @@ If issues are found, run:
|
|
|
113
129
|
→ Changelog generation
|
|
114
130
|
→ Final quality gates
|
|
115
131
|
→ PR creation
|
|
132
|
+
|
|
133
|
+
/ mindforge:auto --phase 1
|
|
134
|
+
→ Walk-away autonomous execution (v2)
|
|
135
|
+
→ Intelligent stuck detection and node repair
|
|
136
|
+
→ External steering via steering-queue
|
|
137
|
+
|
|
138
|
+
/ mindforge:qa
|
|
139
|
+
→ Systematic visual verification of UI changes (v2)
|
|
140
|
+
→ Automated regression test generation
|
|
141
|
+
→ Persistent browser sessions and daemon
|
|
142
|
+
|
|
143
|
+
/ mindforge:cross-review
|
|
144
|
+
→ Adversarial multi-model code review and synthesis (v2)
|
|
145
|
+
→ Consensus detection and severity normalization
|
|
146
|
+
|
|
147
|
+
/ mindforge:research
|
|
148
|
+
→ Deep research using Gemini 1.5 Pro 1M context (v2)
|
|
149
|
+
→ Codebase-wide context packaging and SSRF protection
|
|
150
|
+
|
|
151
|
+
/ mindforge:costs
|
|
152
|
+
→ Real-time token usage and cost profiling (v2)
|
|
153
|
+
→ Daily budget tracking across all providers
|
|
154
|
+
|
|
155
|
+
/ mindforge:remember
|
|
156
|
+
→ Manual knowledge management and search (v2)
|
|
157
|
+
→ Persistent knowledge graph retrieval and promotion
|
|
158
|
+
|
|
159
|
+
/ mindforge:dashboard
|
|
160
|
+
→ Real-time web observability and governance at localhost:7339 (v2)
|
|
161
|
+
→ Live audit logs, metrics, activity, and team feed
|
|
116
162
|
```
|
|
117
163
|
|
|
118
164
|
---
|
|
119
165
|
|
|
120
166
|
## Updates and migrations
|
|
121
|
-
```
|
|
167
|
+
```bash
|
|
122
168
|
/mindforge:update
|
|
123
169
|
/mindforge:update --apply
|
|
124
170
|
/mindforge:migrate --from v0.6.0 --to v1.0.0
|
|
@@ -169,17 +215,23 @@ See `.mindforge/production/token-optimiser.md`.
|
|
|
169
215
|
|
|
170
216
|
---
|
|
171
217
|
|
|
172
|
-
## What ships in
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
218
|
+
## What ships in v2.0.0-alpha.6
|
|
219
|
+
- **Real-time Dashboard**: `/mindforge:dashboard` and web-based observability.
|
|
220
|
+
- **Persistent Knowledge Graph**: `/mindforge:remember` and long-term memory engine.
|
|
221
|
+
- **Multi-Model Intelligence Layer**: `/mindforge:cross-review`, `/mindforge:research`, and `/mindforge:costs`.
|
|
222
|
+
- **Visual QA Engine**: `/mindforge:qa` and automated regression tests.
|
|
223
|
+
- **Persistent Browser Runtime**: `/mindforge:browse` and Playwright integration.
|
|
224
|
+
- **Autonomous Execution Engine**: `/mindforge:auto` and `/mindforge:steer`.
|
|
225
|
+
- 48+ commands across 10 workflow categories.
|
|
226
|
+
- 12 core skill packs with a three-tier registry.
|
|
227
|
+
- 8 specialised agent personas.
|
|
228
|
+
- Wave-based execution with dependency graph and compaction.
|
|
229
|
+
- Enterprise integrations: Jira, Confluence, Slack, GitHub, GitLab.
|
|
230
|
+
- Three-tier governance with 6 non-bypassable compliance gates.
|
|
231
|
+
- Intelligence layer: health engine, difficulty scoring, anti-pattern detection.
|
|
232
|
+
- Public skills registry and plugin system.
|
|
233
|
+
- @mindforge/sdk with event stream and command builders.
|
|
234
|
+
- 20 test suites, production checklist, and 32 ADRs.
|
|
183
235
|
|
|
184
236
|
---
|
|
185
237
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Auto-Runner Engine
|
|
3
|
+
* The main entry point for /mindforge:auto.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const repairOperator = require('./repair-operator');
|
|
10
|
+
const stuckMonitor = require('./stuck-monitor');
|
|
11
|
+
const steeringManager = require('./steer');
|
|
12
|
+
const progressStream = require('./progress-stream');
|
|
13
|
+
const headlessAdapter = require('./headless');
|
|
14
|
+
|
|
15
|
+
class AutoRunner {
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.phase = options.phase;
|
|
18
|
+
this.isHeadless = options.headless || false;
|
|
19
|
+
this.auditPath = path.join(process.cwd(), '.planning/AUDIT.jsonl');
|
|
20
|
+
this.statePath = path.join(process.cwd(), '.planning/auto-state.json');
|
|
21
|
+
this.monitor = new stuckMonitor(this.auditPath);
|
|
22
|
+
this.isPaused = false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async run() {
|
|
26
|
+
console.log(`🚀 Starting MindForge Autonomous Engine [Phase ${this.phase}]`);
|
|
27
|
+
|
|
28
|
+
if (this.isHeadless) {
|
|
29
|
+
headlessAdapter.setupHeadlessMode(this);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 1. Pre-flight checks
|
|
33
|
+
this.runPreFlight();
|
|
34
|
+
|
|
35
|
+
// 2. Main Wave Loop
|
|
36
|
+
while (await this.hasNextWave()) {
|
|
37
|
+
if (this.isPaused) break;
|
|
38
|
+
await this.executeWave();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.complete();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
runPreFlight() {
|
|
45
|
+
console.log('🔍 Running pre-flight checks...');
|
|
46
|
+
// Real logic would check git status, health, etc.
|
|
47
|
+
this.writeAudit({ event: 'auto_mode_started', phase: this.phase, timestamp: new Date().toISOString() });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async hasNextWave() {
|
|
51
|
+
// Logic to check HANDOFF.json for incomplete waves
|
|
52
|
+
return false; // Placeholder for now
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async executeWave() {
|
|
56
|
+
// Parallel task execution logic...
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async pause() {
|
|
60
|
+
this.isPaused = true;
|
|
61
|
+
this.updateState({ status: 'paused' });
|
|
62
|
+
this.writeAudit({ event: 'auto_mode_paused', timestamp: new Date().toISOString() });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
complete() {
|
|
66
|
+
console.log('✅ Phase complete!');
|
|
67
|
+
const report = progressStream.generateReport(this.auditPath, this.phase);
|
|
68
|
+
fs.writeFileSync(path.join(process.cwd(), `.planning/phases/${this.phase}/AUTONOMOUS-REPORT.md`), report);
|
|
69
|
+
this.writeAudit({ event: 'auto_mode_completed', timestamp: new Date().toISOString() });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
writeAudit(event) {
|
|
73
|
+
if (!event.timestamp) event.timestamp = new Date().toISOString();
|
|
74
|
+
fs.appendFileSync(this.auditPath, JSON.stringify(event) + '\n');
|
|
75
|
+
const result = this.monitor.analyze(event);
|
|
76
|
+
if (result) this.handleStuck(result);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
handleStuck(result) {
|
|
80
|
+
console.error(`🛑 STUCK PATTERN DETECTED: ${result.pattern} - ${result.message}`);
|
|
81
|
+
this.writeAudit({ event: 'auto_mode_escalated', reason: result.message });
|
|
82
|
+
process.exit(10);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
updateState(update) {
|
|
86
|
+
let state = {};
|
|
87
|
+
if (fs.existsSync(this.statePath)) {
|
|
88
|
+
state = JSON.parse(fs.readFileSync(this.statePath, 'utf8'));
|
|
89
|
+
}
|
|
90
|
+
Object.assign(state, update);
|
|
91
|
+
fs.writeFileSync(this.statePath, JSON.stringify(state, null, 2));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = AutoRunner;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Headless Adapter
|
|
3
|
+
* Handles signal management and non-interactive output.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
function setupHeadlessMode(executor) {
|
|
8
|
+
// Disable fancy TTY reporting
|
|
9
|
+
process.env.NO_COLOR = '1';
|
|
10
|
+
process.env.INTERACTIVE = '0';
|
|
11
|
+
|
|
12
|
+
// Hardened signal handling to prevent race conditions during write
|
|
13
|
+
let isShuttingDown = false;
|
|
14
|
+
|
|
15
|
+
async function handleSignal(signal) {
|
|
16
|
+
if (isShuttingDown) return;
|
|
17
|
+
isShuttingDown = true;
|
|
18
|
+
|
|
19
|
+
console.error(`\n⚠️ Received ${signal}. Snapshotting state for resumption...`);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// pause() ensures all state is flushed to disk and current step is stabilized
|
|
23
|
+
await executor.pause();
|
|
24
|
+
console.error('✅ State saved. You can resume with /mindforge:auto --resume');
|
|
25
|
+
process.exit(0);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error('❌ Failed to save state during shutdown:', err.message);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
process.on('SIGTERM', () => handleSignal('SIGTERM'));
|
|
33
|
+
process.on('SIGINT', () => handleSignal('SIGINT'));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { setupHeadlessMode };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Progress Streamer
|
|
3
|
+
* Formats AUDIT events for terminal display and report generation.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate a summary report from an audit file.
|
|
11
|
+
*/
|
|
12
|
+
function generateReport(auditPath, phaseNum) {
|
|
13
|
+
if (!fs.existsSync(auditPath)) return '# No audit log found';
|
|
14
|
+
|
|
15
|
+
const lines = fs.readFileSync(auditPath, 'utf8').split('\n').filter(Boolean);
|
|
16
|
+
const events = lines.map(JSON.parse);
|
|
17
|
+
|
|
18
|
+
let report = `# Autonomous Execution Report — Phase ${phaseNum}\n\n`;
|
|
19
|
+
|
|
20
|
+
const start = events.find(e => e.event === 'auto_mode_started');
|
|
21
|
+
const end = events.find(e => e.event === 'auto_mode_completed' || e.event === 'auto_mode_escalated');
|
|
22
|
+
|
|
23
|
+
report += '## Summary\n';
|
|
24
|
+
report += `- **Status**: ${end ? end.event.replace('auto_mode_', '').toUpperCase() : 'IN PROGRESS'}\n`;
|
|
25
|
+
report += `- **Started**: ${start ? start.timestamp : 'Unknown'}\n`;
|
|
26
|
+
report += `- **Duration**: ${calculateDuration(start, end)}\n`;
|
|
27
|
+
report += `- **Tasks Completed**: ${events.filter(e => e.event === 'task_completed').length}\n\n`;
|
|
28
|
+
|
|
29
|
+
report += '## Audit Log\n';
|
|
30
|
+
events.forEach(e => {
|
|
31
|
+
const time = e.timestamp.split('T')[1].split('.')[0];
|
|
32
|
+
if (e.event === 'task_completed') report += `- [${time}] ✅ Task ${e.plan} completed\n`;
|
|
33
|
+
if (e.event === 'node_repair') report += `- [${time}] 🔧 Repair: ${e.repair_type} on ${e.plan} (${e.repair_outcome})\n`;
|
|
34
|
+
if (e.event === 'stuck_pattern_detected') report += `- [${time}] ⚠️ Stuck Pattern: ${e.pattern} on ${e.file}\n`;
|
|
35
|
+
if (e.event === 'steering_applied') report += `- [${time}] 🚢 Steering: "${e.instruction}"\n`;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return report;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function calculateDuration(start, end) {
|
|
42
|
+
if (!start || !end) return 'Unknown';
|
|
43
|
+
const diff = new Date(end.timestamp) - new Date(start.timestamp);
|
|
44
|
+
const mins = Math.floor(diff / 60000);
|
|
45
|
+
const secs = Math.floor((diff % 60000) / 1000);
|
|
46
|
+
return `${mins}m ${secs}s`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { generateReport };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Node Repair Operator
|
|
3
|
+
* Implements RETRY → DECOMPOSE → PRUNE → ESCALATE decision logic.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Determine the repair strategy for a failed task.
|
|
12
|
+
* @param {object} context - Task context
|
|
13
|
+
* @returns {'RETRY'|'DECOMPOSE'|'PRUNE'|'ESCALATE'}
|
|
14
|
+
*/
|
|
15
|
+
function determineRepairStrategy(context) {
|
|
16
|
+
const {
|
|
17
|
+
planId,
|
|
18
|
+
phase,
|
|
19
|
+
attemptNumber, // 1 = first failure, 2 = retry also failed
|
|
20
|
+
errorOutput,
|
|
21
|
+
isTier3Change,
|
|
22
|
+
isOnCriticalPath, // other plans have this plan as a dependency
|
|
23
|
+
planFilePath,
|
|
24
|
+
repairBudget = 2,
|
|
25
|
+
} = context;
|
|
26
|
+
|
|
27
|
+
// Tier 3 changes ALWAYS escalate — never auto-approve auth/payment/PII
|
|
28
|
+
if (isTier3Change) {
|
|
29
|
+
return 'ESCALATE';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// First failure — always try RETRY first
|
|
33
|
+
if (attemptNumber === 1) {
|
|
34
|
+
return 'RETRY';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Retry also failed — try DECOMPOSE if the plan is decomposable
|
|
38
|
+
if (attemptNumber === 2 && isPlanDecomposable(planFilePath)) {
|
|
39
|
+
return 'DECOMPOSE';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Cannot DECOMPOSE (or decompose also failed) — try PRUNE if not critical path
|
|
43
|
+
if (!isOnCriticalPath) {
|
|
44
|
+
return 'PRUNE';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// On critical path and all repair strategies exhausted — must ESCALATE
|
|
48
|
+
return 'ESCALATE';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if a plan can be split into independent sub-plans.
|
|
53
|
+
*/
|
|
54
|
+
function isPlanDecomposable(planFilePath) {
|
|
55
|
+
if (!fs.existsSync(planFilePath)) return false;
|
|
56
|
+
const content = fs.readFileSync(planFilePath, 'utf8');
|
|
57
|
+
|
|
58
|
+
// Count distinct file domains
|
|
59
|
+
const filesMatch = content.match(/<files>([\s\S]*?)<\/files>/);
|
|
60
|
+
if (!filesMatch) return false;
|
|
61
|
+
const files = filesMatch[1].trim().split('\n').filter(Boolean);
|
|
62
|
+
|
|
63
|
+
// Decomposable if:
|
|
64
|
+
// 1. More than 2 files (enough to split)
|
|
65
|
+
// 2. Files span different directories (different concerns)
|
|
66
|
+
if (files.length <= 1) return false;
|
|
67
|
+
const dirs = new Set(files.map(f => f.trim().split('/').slice(0, 2).join('/')));
|
|
68
|
+
return dirs.size > 1;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate RETRY context injection — adds error details for the retry subagent.
|
|
73
|
+
*/
|
|
74
|
+
function buildRetryContext(errorOutput, attemptNumber) {
|
|
75
|
+
const normalized = errorOutput
|
|
76
|
+
.split('\n')
|
|
77
|
+
.filter(l => /error|FAIL|error/i.test(l))
|
|
78
|
+
.slice(0, 5)
|
|
79
|
+
.join('\n');
|
|
80
|
+
|
|
81
|
+
return `
|
|
82
|
+
[RETRY CONTEXT — attempt ${attemptNumber} of 2]
|
|
83
|
+
Previous attempt failed with:
|
|
84
|
+
${normalized}
|
|
85
|
+
|
|
86
|
+
Instructions:
|
|
87
|
+
- Do NOT repeat the same approach that caused this error
|
|
88
|
+
- Fix the specific error above before implementing new functionality
|
|
89
|
+
- If the error is an import/module error: verify the package is installed
|
|
90
|
+
- If the error is a type error: check the exact type definitions
|
|
91
|
+
- If the error is a test failure: read the test assertion carefully
|
|
92
|
+
`.trim();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Build decomposed sub-plans from a failed plan.
|
|
97
|
+
* Returns two PLAN file contents as strings.
|
|
98
|
+
*/
|
|
99
|
+
function buildDecomposedPlans(planContent, originalPlanId, phase) {
|
|
100
|
+
const xmlMatch = planContent.match(/<task[^>]*>([\s\S]*?)<\/task>/);
|
|
101
|
+
if (!xmlMatch) return null;
|
|
102
|
+
|
|
103
|
+
const name = (planContent.match(/<n>(.*?)<\/n>/) || [])[1] || 'Task';
|
|
104
|
+
const action = (planContent.match(/<action>([\s\S]*?)<\/action>/) || [])[1] || '';
|
|
105
|
+
const filesMatch = planContent.match(/<files>([\s\S]*?)<\/files>/);
|
|
106
|
+
const files = filesMatch ? filesMatch[1].trim().split('\n').filter(Boolean) : [];
|
|
107
|
+
const persona = (planContent.match(/<persona>(.*?)<\/persona>/) || [])[1] || 'developer';
|
|
108
|
+
|
|
109
|
+
const mid = Math.ceil(files.length / 2);
|
|
110
|
+
const filesA = files.slice(0, mid);
|
|
111
|
+
const filesB = files.slice(mid);
|
|
112
|
+
const idA = `${originalPlanId}a`;
|
|
113
|
+
const idB = `${originalPlanId}b`;
|
|
114
|
+
|
|
115
|
+
const planA = `<task type="auto">
|
|
116
|
+
<n>${name} — Part A (Foundation)</n>
|
|
117
|
+
<persona>${persona}</persona>
|
|
118
|
+
<phase>${phase}</phase>
|
|
119
|
+
<plan>${idA}</plan>
|
|
120
|
+
<decomposed_from>${originalPlanId}</decomposed_from>
|
|
121
|
+
<dependencies>${getPlanDependencies(planContent)}</dependencies>
|
|
122
|
+
<files>
|
|
123
|
+
${filesA.map(f => ` ${f.trim()}`).join('\n')}
|
|
124
|
+
</files>
|
|
125
|
+
<action>
|
|
126
|
+
${splitAction(action, 'first_half')}
|
|
127
|
+
</action>
|
|
128
|
+
<verify>Run the tests for the files modified in this sub-task only</verify>
|
|
129
|
+
<done>Part A files exist, compile cleanly, and their specific tests pass</done>
|
|
130
|
+
</task>`;
|
|
131
|
+
|
|
132
|
+
const planB = `<task type="auto">
|
|
133
|
+
<n>${name} — Part B (Integration)</n>
|
|
134
|
+
<persona>${persona}</persona>
|
|
135
|
+
<phase>${phase}</phase>
|
|
136
|
+
<plan>${idB}</plan>
|
|
137
|
+
<decomposed_from>${originalPlanId}</decomposed_from>
|
|
138
|
+
<dependencies>${idA}</dependencies>
|
|
139
|
+
<files>
|
|
140
|
+
${filesB.map(f => ` ${f.trim()}`).join('\n')}
|
|
141
|
+
</files>
|
|
142
|
+
<action>
|
|
143
|
+
${splitAction(action, 'second_half')}
|
|
144
|
+
</action>
|
|
145
|
+
<verify>Run the full test suite for the entire ${name} feature</verify>
|
|
146
|
+
<done>All ${name} functionality working end-to-end</done>
|
|
147
|
+
</task>`;
|
|
148
|
+
|
|
149
|
+
return { planA, planB, idA, idB };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Fix the dependency chain after decomposing a plan.
|
|
154
|
+
* Any plan that depended on the original plan now depends on the second sub-plan.
|
|
155
|
+
*/
|
|
156
|
+
function fixDependencyChain(phaseDir, originalPlanId, newDependentPlanId, phase) {
|
|
157
|
+
const planFiles = fs.readdirSync(phaseDir)
|
|
158
|
+
.filter(f => f.match(new RegExp(`^PLAN-${phase}-\\d`)) && f.endsWith('.md'));
|
|
159
|
+
|
|
160
|
+
let fixed = 0;
|
|
161
|
+
for (const planFile of planFiles) {
|
|
162
|
+
const filePath = path.join(phaseDir, planFile);
|
|
163
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
164
|
+
|
|
165
|
+
// Check if this plan depends on the original decomposed plan
|
|
166
|
+
const depPattern = new RegExp(`<dependencies>([^<]*\\b${originalPlanId}\\b[^<]*)</dependencies>`);
|
|
167
|
+
if (depPattern.test(content)) {
|
|
168
|
+
const updated = content.replace(depPattern, (match, deps) => {
|
|
169
|
+
const newDeps = deps.replace(new RegExp(`\\b${originalPlanId}\\b`, 'g'), newDependentPlanId);
|
|
170
|
+
return `<dependencies>${newDeps}</dependencies>`;
|
|
171
|
+
});
|
|
172
|
+
fs.writeFileSync(filePath, updated);
|
|
173
|
+
fixed++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return fixed;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function getPlanDependencies(planContent) {
|
|
180
|
+
return (planContent.match(/<dependencies>(.*?)<\/dependencies>/) || [])[1] || 'none';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function splitAction(action, half) {
|
|
184
|
+
// Try period-delimited split first
|
|
185
|
+
const periodSplit = action.split(/\.\s+/);
|
|
186
|
+
if (periodSplit.length > 1) {
|
|
187
|
+
const mid = Math.ceil(periodSplit.length / 2);
|
|
188
|
+
return half === 'first_half'
|
|
189
|
+
? periodSplit.slice(0, mid).join('. ').trim()
|
|
190
|
+
: periodSplit.slice(mid).join('. ').trim();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Try newline-bullet split
|
|
194
|
+
const bulletSplit = action.split(/\n-\s+/);
|
|
195
|
+
if (bulletSplit.length > 1) {
|
|
196
|
+
const mid = Math.ceil(bulletSplit.length / 2);
|
|
197
|
+
return half === 'first_half'
|
|
198
|
+
? bulletSplit.slice(0, mid).join('\n- ').trim()
|
|
199
|
+
: bulletSplit.slice(mid).join('\n- ').trim();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Fallback: prefix the whole action with a half indicator
|
|
203
|
+
const prefix = half === 'first_half' ? 'First half of: ' : 'Second half of: ';
|
|
204
|
+
return prefix + action.trim().slice(0, Math.ceil(action.length / 2));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = {
|
|
208
|
+
determineRepairStrategy,
|
|
209
|
+
isPlanDecomposable,
|
|
210
|
+
buildRetryContext,
|
|
211
|
+
buildDecomposedPlans,
|
|
212
|
+
fixDependencyChain,
|
|
213
|
+
};
|