mindforge-cc 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bin/installer-core.js +3 -3
  3. package/bin/wizard/setup-wizard.js +1 -1
  4. package/package.json +20 -4
  5. package/.forge/org/CONVENTIONS.md +0 -0
  6. package/.forge/org/ORG.md +0 -0
  7. package/.forge/org/SECURITY.md +0 -0
  8. package/.forge/org/TOOLS.md +0 -0
  9. package/.forge/personas/analyst.md +0 -0
  10. package/.forge/personas/architect.md +0 -0
  11. package/.forge/personas/debug-specialist.md +0 -0
  12. package/.forge/personas/developer.md +0 -26
  13. package/.forge/personas/qa-engineer.md +0 -0
  14. package/.forge/personas/release-manager.md +0 -0
  15. package/.forge/personas/security-reviewer.md +0 -33
  16. package/.forge/personas/tech-writer.md +0 -0
  17. package/.forge/skills/api-design/SKILL.md +0 -0
  18. package/.forge/skills/code-quality/SKILL.md +0 -0
  19. package/.forge/skills/documentation/SKILL.md +0 -0
  20. package/.forge/skills/security-review/SKILL.md +0 -23
  21. package/.forge/skills/testing-standards/SKILL.md +0 -27
  22. package/.github/workflows/mindforge-ci.yml +0 -224
  23. package/.gitlab-ci-mindforge.yml +0 -18
  24. package/eslint.config.mjs +0 -31
  25. package/implementation-roadmap/day-1-imp/DAY1-HARDEN.md +0 -823
  26. package/implementation-roadmap/day-1-imp/DAY1-IMPLEMENT.md +0 -2459
  27. package/implementation-roadmap/day-1-imp/DAY1-REVIEW.md +0 -288
  28. package/implementation-roadmap/day-2-imp/DAY2-HARDEN.md +0 -954
  29. package/implementation-roadmap/day-2-imp/DAY2-IMPLEMENT.md +0 -2347
  30. package/implementation-roadmap/day-2-imp/DAY2-REVIEW.md +0 -422
  31. package/implementation-roadmap/day-3-imp/DAY3-HARDEN.md +0 -870
  32. package/implementation-roadmap/day-3-imp/DAY3-IMPLEMENT.md +0 -2798
  33. package/implementation-roadmap/day-3-imp/DAY3-REVIEW.md +0 -484
  34. package/implementation-roadmap/day-4-imp/DAY4-HARDEN.md +0 -1087
  35. package/implementation-roadmap/day-4-imp/DAY4-IMPLEMENT.md +0 -2874
  36. package/implementation-roadmap/day-4-imp/DAY4-REVIEW.md +0 -386
  37. package/implementation-roadmap/day-5-imp/DAY5-HARDEN.md +0 -1078
  38. package/implementation-roadmap/day-5-imp/DAY5-IMPLEMENT.md +0 -3151
  39. package/implementation-roadmap/day-5-imp/DAY5-REVIEW.md +0 -345
  40. package/implementation-roadmap/day-6-imp/DAY6-COMPLETE.md +0 -3919
  41. package/implementation-roadmap/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +0 -4513
  42. package/sdk/README.md +0 -69
  43. package/sdk/eslint.config.mjs +0 -34
  44. package/sdk/package-lock.json +0 -1507
  45. package/sdk/package.json +0 -30
  46. package/sdk/src/client.ts +0 -133
  47. package/sdk/src/commands.ts +0 -63
  48. package/sdk/src/events.ts +0 -166
  49. package/sdk/src/index.ts +0 -22
  50. package/sdk/src/types.ts +0 -87
  51. package/sdk/tsconfig.json +0 -13
  52. package/tests/audit.test.js +0 -206
  53. package/tests/ci-mode.test.js +0 -162
  54. package/tests/compaction.test.js +0 -161
  55. package/tests/distribution.test.js +0 -205
  56. package/tests/e2e.test.js +0 -618
  57. package/tests/governance.test.js +0 -130
  58. package/tests/install.test.js +0 -209
  59. package/tests/integrations.test.js +0 -128
  60. package/tests/intelligence.test.js +0 -117
  61. package/tests/metrics.test.js +0 -96
  62. package/tests/migration.test.js +0 -309
  63. package/tests/production.test.js +0 -416
  64. package/tests/sdk.test.js +0 -200
  65. package/tests/skills-platform.test.js +0 -403
  66. package/tests/wave-engine.test.js +0 -338
package/sdk/package.json DELETED
@@ -1,30 +0,0 @@
1
- {
2
- "name": "@mindforge/sdk",
3
- "version": "1.0.0",
4
- "description": "MindForge SDK \u2014 Programmatic API for embedding MindForge in tools",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "tsc",
9
- "test": "node tests/sdk.test.js",
10
- "lint": "eslint ."
11
- },
12
- "keywords": [
13
- "mindforge",
14
- "agentic-framework",
15
- "claude",
16
- "sdk"
17
- ],
18
- "license": "MIT",
19
- "peerDependencies": {
20
- "typescript": ">=5.0.0"
21
- },
22
- "devDependencies": {
23
- "@eslint/js": "^9.0.0",
24
- "@types/node": "^20.0.0",
25
- "eslint": "^9.0.0",
26
- "globals": "^15.0.0",
27
- "typescript": "^5.4.0",
28
- "typescript-eslint": "^8.0.0"
29
- }
30
- }
package/sdk/src/client.ts DELETED
@@ -1,133 +0,0 @@
1
- /**
2
- * MindForge SDK — Main Client
3
- */
4
-
5
- import { EventEmitter } from 'events';
6
- import * as fs from 'fs';
7
- import * as path from 'path';
8
- import type {
9
- MindForgeConfig, HealthReport, AuditLogEntry
10
- } from './types';
11
-
12
- export class MindForgeClient extends EventEmitter {
13
- private config: Required<MindForgeConfig>;
14
- private projectRoot: string;
15
-
16
- constructor(config: MindForgeConfig = {}) {
17
- super();
18
- this.projectRoot = config.projectRoot ?? process.cwd();
19
- this.config = {
20
- projectRoot: this.projectRoot,
21
- apiKey: config.apiKey ?? process.env.ANTHROPIC_API_KEY ?? '',
22
- ciMode: config.ciMode ?? (process.env.CI === 'true'),
23
- outputFormat: config.outputFormat ?? 'json',
24
- taskTimeoutMs: config.taskTimeoutMs ?? 600_000,
25
- };
26
- }
27
- // ── Project state ──────────────────────────────────────────────────────────
28
- isInitialised(): boolean {
29
- return fs.existsSync(path.join(this.projectRoot, '.planning', 'PROJECT.md'));
30
- }
31
-
32
- readState(): Record<string, unknown> | null {
33
- const statePath = path.join(this.projectRoot, '.planning', 'STATE.md');
34
- if (!fs.existsSync(statePath)) return null;
35
- return { raw: fs.readFileSync(statePath, 'utf8') };
36
- }
37
-
38
- readHandoff(): Record<string, unknown> | null {
39
- const handoffPath = path.join(this.projectRoot, '.planning', 'HANDOFF.json');
40
- if (!fs.existsSync(handoffPath)) return null;
41
- try {
42
- return JSON.parse(fs.readFileSync(handoffPath, 'utf8'));
43
- } catch {
44
- return null;
45
- }
46
- }
47
-
48
- // ── Health check ───────────────────────────────────────────────────────────
49
- async health(): Promise<HealthReport> {
50
- const errors: Array<{ category: string; message: string; autoRepairable: boolean }> = [];
51
- const warnings: Array<{ category: string; message: string; autoRepairable: boolean }> = [];
52
- const info: Array<{ category: string; message: string; autoRepairable: boolean }> = [];
53
-
54
- const requiredFiles = [
55
- '.planning/STATE.md',
56
- '.planning/HANDOFF.json',
57
- '.planning/AUDIT.jsonl',
58
- '.mindforge/org/CONVENTIONS.md',
59
- ];
60
-
61
- for (const file of requiredFiles) {
62
- const fullPath = path.join(this.projectRoot, file);
63
- if (!fs.existsSync(fullPath)) {
64
- warnings.push({ category: 'installation', message: `Missing: ${file}`, autoRepairable: false });
65
- }
66
- }
67
-
68
- // Check HANDOFF.json validity
69
- const handoff = this.readHandoff();
70
- if (handoff && !handoff.schema_version) {
71
- errors.push({ category: 'state', message: 'HANDOFF.json missing schema_version field', autoRepairable: false });
72
- }
73
-
74
- // Check AUDIT.jsonl
75
- const auditPath = path.join(this.projectRoot, '.planning', 'AUDIT.jsonl');
76
- if (fs.existsSync(auditPath)) {
77
- const lineCount = fs.readFileSync(auditPath, 'utf8').split('\n').filter(Boolean).length;
78
- if (lineCount > 9000) {
79
- warnings.push({ category: 'audit', message: `AUDIT.jsonl has ${lineCount} lines — archive soon`, autoRepairable: true });
80
- }
81
- info.push({ category: 'audit', message: `AUDIT.jsonl: ${lineCount} entries`, autoRepairable: false });
82
- }
83
-
84
- return {
85
- overallStatus: errors.length > 0 ? 'error' : warnings.length > 0 ? 'warning' : 'healthy',
86
- errors,
87
- warnings,
88
- informational: info,
89
- timestamp: new Date().toISOString(),
90
- };
91
- }
92
-
93
- // ── Audit log reading ──────────────────────────────────────────────────────
94
- readAuditLog(filter?: { event?: string; phase?: number; since?: Date }): AuditLogEntry[] {
95
- const auditPath = path.join(this.projectRoot, '.planning', 'AUDIT.jsonl');
96
- if (!fs.existsSync(auditPath)) return [];
97
-
98
- return fs.readFileSync(auditPath, 'utf8')
99
- .split('\n')
100
- .filter(Boolean)
101
- .map((line: string) => { try { return JSON.parse(line) as AuditLogEntry; } catch { return null; } })
102
- .filter((entry: AuditLogEntry | null): entry is AuditLogEntry => !!entry)
103
- .filter(entry => {
104
- if (filter?.event && entry.event !== filter.event) return false;
105
- if (filter?.phase !== undefined && entry.phase !== filter.phase) return false;
106
- if (filter?.since && new Date(entry.timestamp) < filter.since) return false;
107
- return true;
108
- });
109
- }
110
-
111
- // ── Metrics reading ────────────────────────────────────────────────────────
112
- readSessionMetrics(limit = 10): unknown[] {
113
- const metricsPath = path.join(this.projectRoot, '.mindforge', 'metrics', 'session-quality.jsonl');
114
- if (!fs.existsSync(metricsPath)) return [];
115
-
116
- return fs.readFileSync(metricsPath, 'utf8')
117
- .split('\n')
118
- .filter(Boolean)
119
- .slice(-limit)
120
- .map((line: string) => { try { return JSON.parse(line); } catch { return null; } })
121
- .filter(Boolean);
122
- }
123
-
124
- // ── Config validation ──────────────────────────────────────────────────────
125
- validateConfig(): { valid: boolean; errors: string[]; warnings: string[] } {
126
- const configPath = path.join(this.projectRoot, 'MINDFORGE.md');
127
- if (!fs.existsSync(configPath)) {
128
- return { valid: true, errors: [], warnings: ['MINDFORGE.md not found — using defaults'] };
129
- }
130
- // Full validation via bin/validate-config.js
131
- return { valid: true, errors: [], warnings: [] };
132
- }
133
- }
@@ -1,63 +0,0 @@
1
- /**
2
- * MindForge SDK — Command Builders
3
- * Builds the command strings that can be sent to Claude Code / Antigravity
4
- * via their programmatic APIs.
5
- */
6
-
7
- export interface CommandOptions {
8
- flags?: string[];
9
- args?: string[];
10
- }
11
-
12
- export const commands = {
13
- /**
14
- * Build a /mindforge:health command string
15
- */
16
- health(opts: CommandOptions = {}): string {
17
- const flags = opts.flags?.join(' ') ?? '';
18
- return `/mindforge:health ${flags}`.trim();
19
- },
20
-
21
- /**
22
- * Build a /mindforge:plan-phase command string
23
- */
24
- planPhase(phase: number, opts: CommandOptions = {}): string {
25
- const flags = opts.flags?.join(' ') ?? '';
26
- return `/mindforge:plan-phase ${phase} ${flags}`.trim();
27
- },
28
-
29
- /**
30
- * Build a /mindforge:execute-phase command string
31
- */
32
- executePhase(phase: number, opts: CommandOptions = {}): string {
33
- const flags = opts.flags?.join(' ') ?? '';
34
- return `/mindforge:execute-phase ${phase} ${flags}`.trim();
35
- },
36
-
37
- /**
38
- * Build a /mindforge:security-scan command string
39
- */
40
- securityScan(path?: string, opts: CommandOptions = {}): string {
41
- const flags = opts.flags?.join(' ') ?? '';
42
- return `/mindforge:security-scan ${path ?? ''} ${flags}`.trim();
43
- },
44
-
45
- /**
46
- * Build a /mindforge:audit command string with filters
47
- */
48
- audit(filter: { phase?: number; event?: string; since?: string } = {}): string {
49
- const parts = ['/mindforge:audit'];
50
- if (filter.phase) parts.push(`--phase ${filter.phase}`);
51
- if (filter.event) parts.push(`--event ${filter.event}`);
52
- if (filter.since) parts.push(`--since ${filter.since}`);
53
- return parts.join(' ');
54
- },
55
-
56
- /**
57
- * Build a /mindforge:pr-review command string
58
- */
59
- prReview(opts: CommandOptions = {}): string {
60
- const flags = opts.flags?.join(' ') ?? '';
61
- return `/mindforge:pr-review ${flags}`.trim();
62
- },
63
- };
package/sdk/src/events.ts DELETED
@@ -1,166 +0,0 @@
1
- /**
2
- * MindForge SDK — Server-Sent Events (SSE) stream for real-time progress
3
- * Enables external tools to subscribe to MindForge execution progress.
4
- */
5
-
6
- import * as http from 'http';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
-
10
- interface SSEClient {
11
- id: string;
12
- response: http.ServerResponse;
13
- }
14
-
15
- export class MindForgeEventStream {
16
- private clients: SSEClient[] = [];
17
- private server: http.Server | null = null;
18
- private auditWatcher: fs.FSWatcher | null = null;
19
- private lastAuditLine = 0;
20
-
21
- /**
22
- * Start the SSE server on the given port
23
- */
24
- start(port = 7337): Promise<void> {
25
- return new Promise((resolve, reject) => {
26
- this.server = http.createServer((req, res) => {
27
- if (req.url !== '/events') {
28
- res.writeHead(404);
29
- res.end();
30
- return;
31
- }
32
-
33
- // SECURITY: Only allow connections from localhost
34
- const clientIp = req.socket.remoteAddress;
35
- const isLocalhost = clientIp === '127.0.0.1' ||
36
- clientIp === '::1' ||
37
- clientIp === '::ffff:127.0.0.1';
38
- if (!isLocalhost) {
39
- res.writeHead(403);
40
- res.end('Forbidden: MindForge event stream is localhost-only');
41
- return;
42
- }
43
-
44
- // CORS: Only allow localhost origins (exact match, not wildcard)
45
- const origin = req.headers.origin;
46
- const allowedOriginPattern = /^https?:\/\/localhost(:\d+)?$/;
47
- const corsOrigin = origin && allowedOriginPattern.test(origin)
48
- ? origin
49
- : 'http://localhost';
50
-
51
- res.writeHead(200, {
52
- 'Content-Type': 'text/event-stream',
53
- 'Cache-Control': 'no-cache',
54
- 'Connection': 'keep-alive',
55
- 'Access-Control-Allow-Origin': corsOrigin,
56
- 'X-Content-Type-Options': 'nosniff',
57
- });
58
-
59
- const clientId = Date.now().toString();
60
- this.clients.push({ id: clientId, response: res });
61
-
62
- // Send initial connection event
63
- this.sendEvent(res, 'connected', { clientId, timestamp: new Date().toISOString() });
64
-
65
- // Clean up on disconnect
66
- req.on('close', () => {
67
- this.clients = this.clients.filter(c => c.id !== clientId);
68
- });
69
- });
70
-
71
- // SECURITY: Bind to localhost ONLY — not all interfaces
72
- this.server.listen(port, '127.0.0.1', () => {
73
- console.log(`MindForge event stream: http://localhost:${port}/events (localhost only)`);
74
- resolve();
75
- });
76
-
77
- this.server.on('error', (err: NodeJS.ErrnoException) => {
78
- if (err.code === 'EADDRINUSE') {
79
- reject(new Error(
80
- `Port ${port} is already in use. Use: new MindForgeEventStream().start(${port + 1})`
81
- ));
82
- } else {
83
- reject(err);
84
- }
85
- });
86
- });
87
- }
88
-
89
- /**
90
- * Watch AUDIT.jsonl for new entries and broadcast as SSE events
91
- */
92
- watchAuditLog(projectRoot: string): void {
93
- const auditPath = path.join(projectRoot, '.planning', 'AUDIT.jsonl');
94
-
95
- if (!fs.existsSync(auditPath)) {
96
- // Create the file if it doesn't exist yet
97
- fs.writeFileSync(auditPath, '');
98
- }
99
-
100
- // Set initial line count
101
- const content = fs.readFileSync(auditPath, 'utf8');
102
- this.lastAuditLine = content.split('\n').filter(Boolean).length;
103
-
104
- try {
105
- this.auditWatcher = fs.watch(auditPath, () => {
106
- const lines = fs.readFileSync(auditPath, 'utf8')
107
- .split('\n')
108
- .filter(Boolean);
109
-
110
- // Broadcast new lines
111
- for (let i = this.lastAuditLine; i < lines.length; i++) {
112
- try {
113
- const entry = JSON.parse(lines[i]);
114
- this.broadcast('audit_entry', entry);
115
- } catch {
116
- // Ignore parse errors for incomplete lines
117
- }
118
- }
119
-
120
- this.lastAuditLine = lines.length;
121
- });
122
- } catch (err: unknown) {
123
- if ((err as NodeJS.ErrnoException).code === 'ENOSPC') {
124
- // Linux inotify limit reached — fall back to polling
125
- console.warn('MindForge: inotify limit reached, falling back to 2s polling');
126
- setInterval(() => {
127
- const lines = fs.readFileSync(auditPath, 'utf8').split('\n').filter(Boolean);
128
- for (let i = this.lastAuditLine; i < lines.length; i++) {
129
- try { this.broadcast('audit_entry', JSON.parse(lines[i])); } catch { /* ignore */ }
130
- }
131
- this.lastAuditLine = lines.length;
132
- }, 2000);
133
- } else {
134
- throw err;
135
- }
136
- }
137
- }
138
-
139
- /**
140
- * Broadcast an event to all connected clients
141
- */
142
- broadcast(eventType: string, data: unknown): void {
143
- this.clients.forEach(client => {
144
- this.sendEvent(client.response, eventType, data);
145
- });
146
- }
147
-
148
- private sendEvent(res: http.ServerResponse, type: string, data: unknown): void {
149
- try {
150
- res.write(`event: ${type}\n`);
151
- res.write(`data: ${JSON.stringify(data)}\n\n`);
152
- } catch {
153
- // Client disconnected
154
- }
155
- }
156
-
157
- /**
158
- * Stop the event stream server
159
- */
160
- stop(): void {
161
- this.auditWatcher?.close();
162
- this.server?.close();
163
- this.clients.forEach(c => c.response.end());
164
- this.clients = [];
165
- }
166
- }
package/sdk/src/index.ts DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * MindForge SDK — Public API
3
- * @module @mindforge/sdk
4
- */
5
-
6
- export { MindForgeClient } from './client';
7
- export { MindForgeEventStream } from './events';
8
- export { commands } from './commands';
9
- export type { CommandOptions } from './commands';
10
- export type {
11
- MindForgeConfig,
12
- PhaseResult,
13
- TaskResult,
14
- SecurityFinding,
15
- GateResult,
16
- HealthReport,
17
- HealthIssue,
18
- MindForgeEvent,
19
- AuditLogEntry,
20
- } from './types';
21
-
22
- export const VERSION = '1.0.0';
package/sdk/src/types.ts DELETED
@@ -1,87 +0,0 @@
1
- /**
2
- * MindForge SDK — Type Definitions
3
- */
4
-
5
- export interface MindForgeConfig {
6
- /** Path to the project root (default: cwd) */
7
- projectRoot?: string;
8
- /** Claude API key (default: ANTHROPIC_API_KEY env var) */
9
- apiKey?: string;
10
- /** CI mode — disables interactive features */
11
- ciMode?: boolean;
12
- /** Output format for events */
13
- outputFormat?: 'json' | 'text' | 'github-annotations';
14
- /** Timeout per task in milliseconds (default: 600000 — 10 minutes) */
15
- taskTimeoutMs?: number;
16
- }
17
-
18
- export interface PhaseResult {
19
- phase: number;
20
- status: 'success' | 'failure' | 'warning' | 'skipped';
21
- tasksCompleted: number;
22
- tasksTotal: number;
23
- commits: string[];
24
- securityFindings: SecurityFinding[];
25
- qualityGateResults: GateResult[];
26
- durationMs: number;
27
- errorMessage?: string;
28
- }
29
-
30
- export interface TaskResult {
31
- planId: string;
32
- taskName: string;
33
- status: 'completed' | 'failed' | 'skipped';
34
- commitSha?: string;
35
- verifyOutput?: string;
36
- durationMs: number;
37
- errorMessage?: string;
38
- }
39
-
40
- export interface SecurityFinding {
41
- severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
42
- owaspCategory: string;
43
- file: string;
44
- line: number;
45
- description: string;
46
- remediation: string;
47
- remediated: boolean;
48
- }
49
-
50
- export interface GateResult {
51
- gate: string;
52
- status: 'passed' | 'failed' | 'warning' | 'skipped';
53
- detail?: string;
54
- }
55
-
56
- export interface HealthReport {
57
- overallStatus: 'healthy' | 'warning' | 'error';
58
- errors: HealthIssue[];
59
- warnings: HealthIssue[];
60
- informational: HealthIssue[];
61
- timestamp: string;
62
- }
63
-
64
- export interface HealthIssue {
65
- category: string;
66
- message: string;
67
- autoRepairable: boolean;
68
- fixCommand?: string;
69
- }
70
-
71
- export type MindForgeEvent =
72
- | { type: 'task_started'; phase: number; plan: string; taskName: string }
73
- | { type: 'task_completed'; phase: number; plan: string; commitSha: string }
74
- | { type: 'task_failed'; phase: number; plan: string; error: string }
75
- | { type: 'wave_started'; phase: number; wave: number; taskCount: number }
76
- | { type: 'wave_completed'; phase: number; wave: number }
77
- | { type: 'phase_completed'; phase: number; result: PhaseResult }
78
- | { type: 'security_finding'; finding: SecurityFinding }
79
- | { type: 'gate_result'; gate: GateResult }
80
- | { type: 'log'; level: 'info' | 'warn' | 'error'; message: string };
81
-
82
- export interface AuditLogEntry {
83
- timestamp: string;
84
- event: string;
85
- phase?: number;
86
- [key: string]: unknown;
87
- }
package/sdk/tsconfig.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "CommonJS",
5
- "rootDir": "src",
6
- "outDir": "dist",
7
- "declaration": true,
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true
11
- },
12
- "include": ["src"]
13
- }