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.
- package/CHANGELOG.md +14 -0
- package/bin/installer-core.js +3 -3
- package/bin/wizard/setup-wizard.js +1 -1
- package/package.json +20 -4
- package/.forge/org/CONVENTIONS.md +0 -0
- package/.forge/org/ORG.md +0 -0
- package/.forge/org/SECURITY.md +0 -0
- package/.forge/org/TOOLS.md +0 -0
- package/.forge/personas/analyst.md +0 -0
- package/.forge/personas/architect.md +0 -0
- package/.forge/personas/debug-specialist.md +0 -0
- package/.forge/personas/developer.md +0 -26
- package/.forge/personas/qa-engineer.md +0 -0
- package/.forge/personas/release-manager.md +0 -0
- package/.forge/personas/security-reviewer.md +0 -33
- package/.forge/personas/tech-writer.md +0 -0
- package/.forge/skills/api-design/SKILL.md +0 -0
- package/.forge/skills/code-quality/SKILL.md +0 -0
- package/.forge/skills/documentation/SKILL.md +0 -0
- package/.forge/skills/security-review/SKILL.md +0 -23
- package/.forge/skills/testing-standards/SKILL.md +0 -27
- package/.github/workflows/mindforge-ci.yml +0 -224
- package/.gitlab-ci-mindforge.yml +0 -18
- package/eslint.config.mjs +0 -31
- package/implementation-roadmap/day-1-imp/DAY1-HARDEN.md +0 -823
- package/implementation-roadmap/day-1-imp/DAY1-IMPLEMENT.md +0 -2459
- package/implementation-roadmap/day-1-imp/DAY1-REVIEW.md +0 -288
- package/implementation-roadmap/day-2-imp/DAY2-HARDEN.md +0 -954
- package/implementation-roadmap/day-2-imp/DAY2-IMPLEMENT.md +0 -2347
- package/implementation-roadmap/day-2-imp/DAY2-REVIEW.md +0 -422
- package/implementation-roadmap/day-3-imp/DAY3-HARDEN.md +0 -870
- package/implementation-roadmap/day-3-imp/DAY3-IMPLEMENT.md +0 -2798
- package/implementation-roadmap/day-3-imp/DAY3-REVIEW.md +0 -484
- package/implementation-roadmap/day-4-imp/DAY4-HARDEN.md +0 -1087
- package/implementation-roadmap/day-4-imp/DAY4-IMPLEMENT.md +0 -2874
- package/implementation-roadmap/day-4-imp/DAY4-REVIEW.md +0 -386
- package/implementation-roadmap/day-5-imp/DAY5-HARDEN.md +0 -1078
- package/implementation-roadmap/day-5-imp/DAY5-IMPLEMENT.md +0 -3151
- package/implementation-roadmap/day-5-imp/DAY5-REVIEW.md +0 -345
- package/implementation-roadmap/day-6-imp/DAY6-COMPLETE.md +0 -3919
- package/implementation-roadmap/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +0 -4513
- package/sdk/README.md +0 -69
- package/sdk/eslint.config.mjs +0 -34
- package/sdk/package-lock.json +0 -1507
- package/sdk/package.json +0 -30
- package/sdk/src/client.ts +0 -133
- package/sdk/src/commands.ts +0 -63
- package/sdk/src/events.ts +0 -166
- package/sdk/src/index.ts +0 -22
- package/sdk/src/types.ts +0 -87
- package/sdk/tsconfig.json +0 -13
- package/tests/audit.test.js +0 -206
- package/tests/ci-mode.test.js +0 -162
- package/tests/compaction.test.js +0 -161
- package/tests/distribution.test.js +0 -205
- package/tests/e2e.test.js +0 -618
- package/tests/governance.test.js +0 -130
- package/tests/install.test.js +0 -209
- package/tests/integrations.test.js +0 -128
- package/tests/intelligence.test.js +0 -117
- package/tests/metrics.test.js +0 -96
- package/tests/migration.test.js +0 -309
- package/tests/production.test.js +0 -416
- package/tests/sdk.test.js +0 -200
- package/tests/skills-platform.test.js +0 -403
- 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
|
-
}
|
package/sdk/src/commands.ts
DELETED
|
@@ -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