@mindrian_os/install 1.13.0-beta.16 → 1.13.0-beta.17
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/plugin.json +1 -1
- package/CHANGELOG.md +10 -0
- package/commands/file-meeting.md +2 -0
- package/commands/grade.md +2 -0
- package/commands/mva-brief.md +56 -0
- package/commands/mva-option.md +89 -0
- package/commands/new-project.md +2 -0
- package/commands/onboard.md +2 -0
- package/hooks/hooks.json +9 -0
- package/lib/agents/mva/brain-classic-traps.cjs +77 -0
- package/lib/agents/mva/brain-cross-domain.cjs +79 -0
- package/lib/agents/mva/brain-similar-ventures.cjs +93 -0
- package/lib/agents/mva/dashboard-graph-neighborhood.cjs +72 -0
- package/lib/agents/mva/index.cjs +42 -0
- package/lib/agents/mva/six-hats-red-black.cjs +137 -0
- package/lib/agents/mva/tavily-funding-scan.cjs +147 -0
- package/lib/agents/mva/test-all-six-agents.cjs +467 -0
- package/lib/conversation/operator.cjs +64 -0
- package/lib/conversation/operator.test.cjs +160 -0
- package/lib/core/mva-agent-contract.cjs +170 -0
- package/lib/core/mva-agent-contract.test.cjs +169 -0
- package/lib/core/mva-budget.cjs +75 -0
- package/lib/core/mva-budget.test.cjs +68 -0
- package/lib/core/mva-classifier.cjs +370 -0
- package/lib/core/mva-classifier.test.cjs +248 -0
- package/lib/core/mva-deck-builder.cjs +452 -0
- package/lib/core/mva-deck-builder.test.cjs +287 -0
- package/lib/core/mva-detect.smoke.test.cjs +197 -0
- package/lib/core/mva-dispatcher.cjs +110 -0
- package/lib/core/mva-dispatcher.test.cjs +216 -0
- package/lib/core/mva-option-router.cjs +292 -0
- package/lib/core/mva-option-router.test.cjs +483 -0
- package/lib/core/mva-orchestrator.cjs +324 -0
- package/lib/core/mva-orchestrator.test.cjs +908 -0
- package/lib/core/mva-progressive-renderer.cjs +194 -0
- package/lib/core/mva-progressive-renderer.test.cjs +157 -0
- package/lib/core/mva-rule-linter.cjs +213 -0
- package/lib/core/mva-rule-linter.test.cjs +336 -0
- package/lib/core/mva-state.cjs +159 -0
- package/lib/core/mva-telemetry.cjs +170 -0
- package/lib/core/mva-telemetry.test.cjs +196 -0
- package/lib/core/mva-vercel-deploy.cjs +168 -0
- package/lib/core/mva-vercel-deploy.test.cjs +239 -0
- package/lib/core/navigation/dashboard-helpers.cjs +145 -0
- package/lib/core/navigation.cjs +11 -0
- package/lib/core/resolve-vercel-key.cjs +107 -0
- package/lib/core/resolve-vercel-key.test.cjs +137 -0
- package/lib/memory/run-feynman-tests.cjs +27 -0
- package/package.json +1 -1
- package/skills/mva-pipeline/SKILL.md +129 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
*
|
|
4
|
+
* Phase 118-03 Plan 03 Task 2 -- mva-orchestrator.
|
|
5
|
+
*
|
|
6
|
+
* Top-level controller for the 30-Second MVA pipeline.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. readPending() from Plan 118-00 state. If null, nothing to do.
|
|
10
|
+
* 2. If hebrew_refusal:true (per LD1), render bilingual refusal, markComplete,
|
|
11
|
+
* return. NO dispatcher invocation. NO state.json manifest write.
|
|
12
|
+
* 3. markRunning, emit mva_pipeline_started.
|
|
13
|
+
* 4. For each AgentResult yielded by dispatch(ALL_AGENTS, sha256):
|
|
14
|
+
* render block + emit mva_agent_returned (with duration_ms).
|
|
15
|
+
* 5. If all agents non-ok: append sharp-question fallback +
|
|
16
|
+
* emit mva_pipeline_failed.
|
|
17
|
+
* 6. Else: append footer.
|
|
18
|
+
* 7. emit mva_brief_rendered (with total_duration_ms, NOT duration_ms).
|
|
19
|
+
* 8. Atomically write ~/.mindrian/mva/state.json (CRITICAL-3 wire).
|
|
20
|
+
* 9. markComplete.
|
|
21
|
+
*
|
|
22
|
+
* Canon Part 8 invariants:
|
|
23
|
+
* - The orchestrator only ever reads sentence_sha256 from pending (not raw).
|
|
24
|
+
* - It NEVER reads .sentence / .prompt / .raw_sentence / .raw_text.
|
|
25
|
+
* - It writes ONLY sha-keyed / scalar telemetry.
|
|
26
|
+
*
|
|
27
|
+
* Em-dash discipline: this module emits no rendered strings directly; it
|
|
28
|
+
* only joins blocks returned by the renderer (which is em-dash-free).
|
|
29
|
+
*
|
|
30
|
+
* Pure CJS, node built-ins only.
|
|
31
|
+
*/
|
|
32
|
+
'use strict';
|
|
33
|
+
|
|
34
|
+
const fs = require('node:fs');
|
|
35
|
+
const path = require('node:path');
|
|
36
|
+
const os = require('node:os');
|
|
37
|
+
|
|
38
|
+
const mvaState = require('./mva-state.cjs');
|
|
39
|
+
const renderer = require('./mva-progressive-renderer.cjs');
|
|
40
|
+
const telemetry = require('./mva-telemetry.cjs');
|
|
41
|
+
const { dispatch } = require('./mva-dispatcher.cjs');
|
|
42
|
+
|
|
43
|
+
// Plan 118-02 sibling ships lib/agents/mva/index.cjs with the ALL_AGENTS
|
|
44
|
+
// export. Plan 118-03 ships in parallel; we lazy-load the agents module so
|
|
45
|
+
// our test suite (which mocks the agents via require.cache injection) is not
|
|
46
|
+
// blocked on the sibling's file landing first. At runtime in production both
|
|
47
|
+
// plans have landed -- the require always succeeds.
|
|
48
|
+
function _loadAgents() {
|
|
49
|
+
try {
|
|
50
|
+
return require('../agents/mva/index.cjs').ALL_AGENTS || [];
|
|
51
|
+
} catch (_e) {
|
|
52
|
+
// Sibling hasn't shipped yet OR (under tests) the mock didn't install.
|
|
53
|
+
// Returning [] makes dispatch yield zero results, which the orchestrator
|
|
54
|
+
// then treats as all-fail (renders sharp-question fallback).
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---------- Shape documentation ----------
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* OUTCOME_SHAPE -- the return shape of runPipeline.
|
|
63
|
+
*
|
|
64
|
+
* {
|
|
65
|
+
* results: Array<AgentResult>, // empty on Hebrew refusal / no-pending
|
|
66
|
+
* rendered: string, // the joined text block sent to user
|
|
67
|
+
* footer_data: { ok, failed, sha256 } | null // null on Hebrew/no-pending
|
|
68
|
+
* }
|
|
69
|
+
*/
|
|
70
|
+
const OUTCOME_SHAPE = Object.freeze({
|
|
71
|
+
results: 'AgentResult[]',
|
|
72
|
+
rendered: 'string',
|
|
73
|
+
footer_data: '{ ok, failed, sha256 } | null'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ---------- Helpers ----------
|
|
77
|
+
|
|
78
|
+
function _homeDir() {
|
|
79
|
+
return process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function _mvaDir() {
|
|
83
|
+
return path.join(_homeDir(), '.mindrian', 'mva');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Atomic state.json manifest write per CRITICAL-3 wire. Best-effort: failures
|
|
88
|
+
* are swallowed because the MVA brief was already rendered to the user.
|
|
89
|
+
* Plan 118-05's resolveCurrentSha8() handles missing-file gracefully.
|
|
90
|
+
*
|
|
91
|
+
* Plan 118-04 extension: accepts an optional `vercel_url` so the manifest
|
|
92
|
+
* carries the real deploy URL once Plan 118-04's deployDeck returns. When
|
|
93
|
+
* called without vercel_url (or with null), the field stays null -- Plan
|
|
94
|
+
* 118-04 then overwrites the manifest after deploy.
|
|
95
|
+
*/
|
|
96
|
+
function _writeStateManifest(pending, vercel_url) {
|
|
97
|
+
try {
|
|
98
|
+
const dir = _mvaDir();
|
|
99
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
100
|
+
const manifest = {
|
|
101
|
+
current_sha8: pending.sentence_sha256.slice(0, 8),
|
|
102
|
+
current_sha256: pending.sentence_sha256,
|
|
103
|
+
rendered_at_ms: Date.now(),
|
|
104
|
+
vercel_url: (typeof vercel_url === 'string' && vercel_url.length > 0) ? vercel_url : null
|
|
105
|
+
};
|
|
106
|
+
const finalPath = path.join(dir, 'state.json');
|
|
107
|
+
const tmpPath = finalPath + '.tmp.' + process.pid + '.' + Math.random().toString(36).slice(2, 10);
|
|
108
|
+
fs.writeFileSync(tmpPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
109
|
+
fs.renameSync(tmpPath, finalPath);
|
|
110
|
+
} catch (_e) {
|
|
111
|
+
// Best-effort. Manifest is for Plan 118-05's auto-discovery convenience;
|
|
112
|
+
// the rendered brief is already in the user's scrollback.
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Side-file write for Plan 118-05 option-2 consumption. The structured deck
|
|
118
|
+
* data lands at ~/.mindrian/mva/briefs/<sha8>.json so option 2 (Build a room
|
|
119
|
+
* around this) can read it without re-running the pipeline.
|
|
120
|
+
*
|
|
121
|
+
* Best-effort: failures swallowed (the rendered brief is already in scrollback).
|
|
122
|
+
*/
|
|
123
|
+
function _writeSideFile(pending, results) {
|
|
124
|
+
try {
|
|
125
|
+
const sha8 = pending.sentence_sha256.slice(0, 8);
|
|
126
|
+
const briefsDir = path.join(_mvaDir(), 'briefs');
|
|
127
|
+
fs.mkdirSync(briefsDir, { recursive: true });
|
|
128
|
+
const sideFilePath = path.join(briefsDir, sha8 + '.json');
|
|
129
|
+
const payload = {
|
|
130
|
+
sha256: pending.sentence_sha256,
|
|
131
|
+
sha8,
|
|
132
|
+
timestamp: new Date().toISOString(),
|
|
133
|
+
results,
|
|
134
|
+
};
|
|
135
|
+
const tmpPath = sideFilePath + '.tmp.' + process.pid + '.' + Math.random().toString(36).slice(2, 10);
|
|
136
|
+
fs.writeFileSync(tmpPath, JSON.stringify(payload, null, 2), 'utf8');
|
|
137
|
+
fs.renameSync(tmpPath, sideFilePath);
|
|
138
|
+
} catch (_e) {
|
|
139
|
+
// Best-effort.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ---------- Public runPipeline ----------
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* runPipeline -- end-to-end controller.
|
|
147
|
+
*
|
|
148
|
+
* @param {object} [opts] Reserved for future use. Honored: none in v1.13.0.
|
|
149
|
+
* @returns {Promise<{ results: Array, rendered: string, footer_data: object|null }>}
|
|
150
|
+
*/
|
|
151
|
+
async function runPipeline(opts) {
|
|
152
|
+
void opts; // reserved
|
|
153
|
+
|
|
154
|
+
const pending = mvaState.readPending();
|
|
155
|
+
if (!pending) {
|
|
156
|
+
return { results: [], rendered: '', footer_data: null };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Hebrew short-circuit (LD1). DO NOT fire the dispatcher.
|
|
160
|
+
if (pending.hebrew_refusal) {
|
|
161
|
+
const out = renderer.renderHebrewRefusal();
|
|
162
|
+
mvaState.markComplete();
|
|
163
|
+
return { results: [], rendered: out, footer_data: null };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
mvaState.markRunning();
|
|
167
|
+
|
|
168
|
+
// Sanity: pending.sentence_sha256 is the only sentence-derived identifier
|
|
169
|
+
// we consume. We pass it to the dispatcher and to telemetry. Nothing else
|
|
170
|
+
// from `pending` flows downstream (Canon Part 8 invariant).
|
|
171
|
+
const sha256 = pending.sentence_sha256;
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
telemetry.emit('mva_pipeline_started', { sentence_sha256: sha256 });
|
|
175
|
+
} catch (_e) { /* validation errors swallowed -- best-effort telemetry */ }
|
|
176
|
+
|
|
177
|
+
const t0 = Date.now();
|
|
178
|
+
const blocks = [renderer.renderHeader(sha256.slice(0, 8))];
|
|
179
|
+
const results = [];
|
|
180
|
+
let okCount = 0;
|
|
181
|
+
let failedCount = 0;
|
|
182
|
+
|
|
183
|
+
const agents = _loadAgents();
|
|
184
|
+
for await (const result of dispatch(agents, sha256)) {
|
|
185
|
+
results.push(result);
|
|
186
|
+
blocks.push(renderer.renderAgentResult(result));
|
|
187
|
+
if (result.status === 'ok') {
|
|
188
|
+
okCount += 1;
|
|
189
|
+
} else {
|
|
190
|
+
failedCount += 1;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const payload = {
|
|
194
|
+
sentence_sha256: sha256,
|
|
195
|
+
agent_id: String(result.agent_id || '').slice(0, 64),
|
|
196
|
+
duration_ms: result.duration_ms | 0,
|
|
197
|
+
status: result.status
|
|
198
|
+
};
|
|
199
|
+
if (result.error) {
|
|
200
|
+
payload.error_short = String(result.error).slice(0, 60);
|
|
201
|
+
}
|
|
202
|
+
telemetry.emit('mva_agent_returned', payload);
|
|
203
|
+
} catch (_e) { /* best-effort */ }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const totalDuration = Date.now() - t0;
|
|
207
|
+
|
|
208
|
+
// Plan 118-04: build deck + deploy to Vercel. Skip on all-fail (sharp-question
|
|
209
|
+
// path doesn't need a deck URL; the user gets a focused question instead).
|
|
210
|
+
// Best-effort: deploy failures are absorbed; the rendered terminal output
|
|
211
|
+
// is the primary reward surface.
|
|
212
|
+
let deck_url = null;
|
|
213
|
+
let deploy_duration_ms = 0;
|
|
214
|
+
|
|
215
|
+
if (okCount > 0) {
|
|
216
|
+
// Lazy-require deck-builder + vercel-deploy so the orchestrator can be
|
|
217
|
+
// unit-tested without these modules (and so failures in those modules
|
|
218
|
+
// never break orchestrator load).
|
|
219
|
+
let buildDeck, deployDeck;
|
|
220
|
+
try {
|
|
221
|
+
({ buildDeck } = require('./mva-deck-builder.cjs'));
|
|
222
|
+
({ deployDeck } = require('./mva-vercel-deploy.cjs'));
|
|
223
|
+
} catch (_e) {
|
|
224
|
+
buildDeck = null; deployDeck = null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (typeof buildDeck === 'function' && typeof deployDeck === 'function') {
|
|
228
|
+
try {
|
|
229
|
+
const interimOutcome = {
|
|
230
|
+
results,
|
|
231
|
+
rendered: blocks.join(''),
|
|
232
|
+
footer_data: { ok: okCount, failed: failedCount, sha256 }
|
|
233
|
+
};
|
|
234
|
+
const html = buildDeck(interimOutcome);
|
|
235
|
+
const sha8 = sha256.slice(0, 8);
|
|
236
|
+
const deployResult = await deployDeck(html, sha8);
|
|
237
|
+
deploy_duration_ms = deployResult.deploy_duration_ms | 0;
|
|
238
|
+
|
|
239
|
+
if (deployResult.url) {
|
|
240
|
+
deck_url = deployResult.url;
|
|
241
|
+
try {
|
|
242
|
+
telemetry.emit('mva_brief_deployed', {
|
|
243
|
+
sentence_sha256: sha256,
|
|
244
|
+
vercel_subdomain_hash: sha8,
|
|
245
|
+
deploy_duration_ms,
|
|
246
|
+
status: 'ok'
|
|
247
|
+
});
|
|
248
|
+
} catch (_e) { /* best-effort */ }
|
|
249
|
+
} else if (deployResult.fallback_path) {
|
|
250
|
+
deck_url = 'file://' + deployResult.fallback_path;
|
|
251
|
+
try {
|
|
252
|
+
telemetry.emit('mva_brief_deployed', {
|
|
253
|
+
sentence_sha256: sha256,
|
|
254
|
+
vercel_subdomain_hash: sha8,
|
|
255
|
+
deploy_duration_ms,
|
|
256
|
+
status: 'fallback'
|
|
257
|
+
});
|
|
258
|
+
} catch (_e) { /* best-effort */ }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Side-file for Plan 118-05 option-2 consumption.
|
|
262
|
+
_writeSideFile(pending, results);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
// Deploy/build exception is non-fatal -- the terminal output already worked.
|
|
265
|
+
try {
|
|
266
|
+
telemetry.emit('mva_brief_deployed', {
|
|
267
|
+
sentence_sha256: sha256,
|
|
268
|
+
vercel_subdomain_hash: sha256.slice(0, 8),
|
|
269
|
+
deploy_duration_ms,
|
|
270
|
+
status: 'error',
|
|
271
|
+
error_short: String((e && e.message) || e).slice(0, 60)
|
|
272
|
+
});
|
|
273
|
+
} catch (_e) { /* best-effort */ }
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Push the URL line BEFORE the 3-option footer (Test 14 render-order invariant).
|
|
279
|
+
if (deck_url) {
|
|
280
|
+
blocks.push('\n Your Feynman deck: ' + deck_url + '\n');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (okCount === 0) {
|
|
284
|
+
blocks.push(renderer.renderSharpQuestionFallback());
|
|
285
|
+
try {
|
|
286
|
+
telemetry.emit('mva_pipeline_failed', {
|
|
287
|
+
sentence_sha256: sha256,
|
|
288
|
+
total_duration_ms: totalDuration
|
|
289
|
+
});
|
|
290
|
+
} catch (_e) { /* best-effort */ }
|
|
291
|
+
} else {
|
|
292
|
+
blocks.push(renderer.renderFooter());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// mva_brief_rendered fires on EVERY rendered path (even all-fail), so the
|
|
296
|
+
// total_duration_ms invariant (Plan 118-06 Dror harness Test 1) holds.
|
|
297
|
+
try {
|
|
298
|
+
telemetry.emit('mva_brief_rendered', {
|
|
299
|
+
sentence_sha256: sha256,
|
|
300
|
+
total_duration_ms: totalDuration, // NOT duration_ms (per WARN-2)
|
|
301
|
+
agent_count_ok: okCount,
|
|
302
|
+
agent_count_failed: failedCount
|
|
303
|
+
});
|
|
304
|
+
} catch (_e) { /* best-effort */ }
|
|
305
|
+
|
|
306
|
+
// CRITICAL-3 wire: atomic state.json manifest after mva_brief_rendered.
|
|
307
|
+
// Only on the rendered path (not on Hebrew short-circuit which returned earlier).
|
|
308
|
+
// Plan 118-04 carries the deck_url into the manifest atomically.
|
|
309
|
+
_writeStateManifest(pending, deck_url);
|
|
310
|
+
|
|
311
|
+
mvaState.markComplete();
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
results: results,
|
|
315
|
+
rendered: blocks.join(''),
|
|
316
|
+
footer_data: { ok: okCount, failed: failedCount, sha256: sha256 },
|
|
317
|
+
deck_url: deck_url // Plan 118-04: null on Hebrew/all-fail/build-error; string otherwise
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
module.exports = {
|
|
322
|
+
runPipeline,
|
|
323
|
+
OUTCOME_SHAPE,
|
|
324
|
+
};
|