godpowers 3.0.1 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +255 -2
- package/README.md +31 -14
- package/RELEASE.md +21 -33
- package/SKILL.md +71 -112
- package/bin/install.js +44 -0
- package/fixtures/gate/harden-pass/.godpowers/state.json +26 -0
- package/lib/README.md +1 -0
- package/lib/artifact-map.js +2 -1
- package/lib/cli-dispatch.js +449 -3
- package/lib/command-families.js +10 -2
- package/lib/evidence/.provenance.json +45 -0
- package/lib/evidence-import.js +147 -0
- package/lib/evidence.js +908 -0
- package/lib/gate.js +26 -15
- package/lib/install-profiles.js +4 -1
- package/lib/installer-args.js +241 -1
- package/lib/quarterback.js +183 -0
- package/lib/surface-profile.js +168 -0
- package/lib/work-report.js +137 -0
- package/package.json +2 -2
- package/references/orchestration/GOD-MODE-RUNBOOK.md +9 -14
- package/references/orchestration/GOD-ORCHESTRATOR-RUNBOOK.md +40 -82
- package/references/shared/DASHBOARD-CONTRACT.md +66 -29
- package/references/shared/README.md +1 -1
- package/routing/god-demo.yaml +35 -0
- package/routing/god-first-run.yaml +34 -0
- package/routing/god-surface.yaml +39 -0
- package/routing/recipes/try-safely.yaml +26 -0
- package/skills/god-agent-audit.md +5 -6
- package/skills/god-archaeology.md +5 -6
- package/skills/god-audit.md +6 -7
- package/skills/god-automation-setup.md +6 -7
- package/skills/god-automation-status.md +6 -7
- package/skills/god-context-scan.md +7 -8
- package/skills/god-demo.md +53 -0
- package/skills/god-design-impact.md +5 -6
- package/skills/god-discuss.md +5 -6
- package/skills/god-docs.md +5 -10
- package/skills/god-doctor.md +8 -9
- package/skills/god-dogfood.md +7 -10
- package/skills/god-explore.md +5 -7
- package/skills/god-first-run.md +64 -0
- package/skills/god-harden.md +5 -2
- package/skills/god-help.md +77 -51
- package/skills/god-hygiene.md +5 -6
- package/skills/god-lifecycle.md +11 -13
- package/skills/god-list-assumptions.md +7 -8
- package/skills/god-locate.md +7 -8
- package/skills/god-map-codebase.md +5 -6
- package/skills/god-migrate.md +6 -15
- package/skills/god-next.md +16 -17
- package/skills/god-preflight.md +7 -8
- package/skills/god-progress.md +7 -8
- package/skills/god-reconcile.md +5 -6
- package/skills/god-reconstruct.md +5 -7
- package/skills/god-refactor.md +6 -7
- package/skills/god-roadmap-check.md +6 -7
- package/skills/god-scan.md +5 -9
- package/skills/god-spike.md +5 -6
- package/skills/god-standards.md +5 -6
- package/skills/god-status.md +12 -10
- package/skills/god-surface.md +61 -0
- package/skills/god-sync.md +4 -8
- package/skills/god-tech-debt.md +5 -6
- package/skills/god-test-runtime.md +4 -8
- package/skills/god-version.md +1 -1
- package/skills/god.md +53 -52
package/lib/cli-dispatch.js
CHANGED
|
@@ -46,7 +46,7 @@ function runDashboardCommand(opts) {
|
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
console.log(dashboard.render(result, { brief: opts.brief }));
|
|
49
|
+
console.log(dashboard.render(result, { brief: opts.brief || !opts.full }));
|
|
50
50
|
if (opts.command === 'next') {
|
|
51
51
|
console.log('');
|
|
52
52
|
console.log('Suggested next command:');
|
|
@@ -65,6 +65,10 @@ function runDogfoodCommand(opts) {
|
|
|
65
65
|
if (result.status !== 'pass') process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function runDemoCommand(opts) {
|
|
69
|
+
return runQuickProofCommand({ ...opts, brief: opts.full ? false : true });
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
function runQuickProofCommand(opts) {
|
|
69
73
|
const quickProof = require('./quick-proof');
|
|
70
74
|
const result = quickProof.compute(opts.project);
|
|
@@ -75,6 +79,37 @@ function runQuickProofCommand(opts) {
|
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
81
|
|
|
82
|
+
function runSurfaceCommand(opts) {
|
|
83
|
+
const path = require('path');
|
|
84
|
+
const surfaceProfile = require('./surface-profile');
|
|
85
|
+
const srcDir = path.resolve(__dirname, '..');
|
|
86
|
+
let applied = [];
|
|
87
|
+
|
|
88
|
+
if (opts.apply) {
|
|
89
|
+
if (opts.json) {
|
|
90
|
+
const originalLog = console.log;
|
|
91
|
+
const originalError = console.error;
|
|
92
|
+
console.log = () => {};
|
|
93
|
+
console.error = () => {};
|
|
94
|
+
try {
|
|
95
|
+
applied = surfaceProfile.apply(srcDir, opts);
|
|
96
|
+
} finally {
|
|
97
|
+
console.log = originalLog;
|
|
98
|
+
console.error = originalError;
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
applied = surfaceProfile.apply(srcDir, opts);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const result = surfaceProfile.plan(srcDir, opts);
|
|
106
|
+
if (opts.json) {
|
|
107
|
+
console.log(JSON.stringify({ ...result, applied }, null, 2));
|
|
108
|
+
} else {
|
|
109
|
+
console.log(surfaceProfile.render(result));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
78
113
|
function runMcpInfoCommand(opts) {
|
|
79
114
|
const mcpInfo = require('./mcp-info');
|
|
80
115
|
const result = mcpInfo.info(opts.project);
|
|
@@ -114,6 +149,395 @@ function runExtensionScaffoldCommand(opts) {
|
|
|
114
149
|
}
|
|
115
150
|
}
|
|
116
151
|
|
|
152
|
+
function verifyFailure(opts, id, reason) {
|
|
153
|
+
return {
|
|
154
|
+
command: 'verify',
|
|
155
|
+
verdict: 'fail',
|
|
156
|
+
project: opts.project,
|
|
157
|
+
kind: null,
|
|
158
|
+
verified: false,
|
|
159
|
+
checks: [{ id, status: 'fail', artifact: '.godpowers/ledger/verifications.jsonl', reason }],
|
|
160
|
+
findings: [{ id, severity: 'error', artifact: '.godpowers/ledger/verifications.jsonl', reason }]
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function relLedger(opts, absPath) {
|
|
165
|
+
const path = require('path');
|
|
166
|
+
return path.relative(opts.project, absPath);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function renderVerify(result) {
|
|
170
|
+
const lines = [];
|
|
171
|
+
lines.push('Godpowers Verify');
|
|
172
|
+
lines.push('');
|
|
173
|
+
if (result.verdict === 'fail' && result.findings && result.findings.length > 0 && !result.record) {
|
|
174
|
+
lines.push('Verdict: fail');
|
|
175
|
+
for (const finding of result.findings) {
|
|
176
|
+
lines.push(`Error: ${finding.reason}`);
|
|
177
|
+
}
|
|
178
|
+
return lines.join('\n');
|
|
179
|
+
}
|
|
180
|
+
const verdictLabel = result.kind === 'attested'
|
|
181
|
+
? 'attested (self-reported, not machine-checked)'
|
|
182
|
+
: result.verdict;
|
|
183
|
+
lines.push(`Verdict: ${verdictLabel}`);
|
|
184
|
+
lines.push(`Command: ${result.commandText ? '`' + result.commandText + '`' : '(none)'}`);
|
|
185
|
+
if (result.substep) lines.push(`Substep: ${result.substep}`);
|
|
186
|
+
if (result.kind === 'executed') {
|
|
187
|
+
lines.push(`Exit: ${result.exitCode} (${result.durationMs} ms)`);
|
|
188
|
+
}
|
|
189
|
+
if (result.claim) lines.push(`Claim: ${result.claim}`);
|
|
190
|
+
lines.push(`Ledger: ${result.ledger}`);
|
|
191
|
+
if (result.rollup) {
|
|
192
|
+
lines.push(result.rollup.applied
|
|
193
|
+
? `Rollup: applied ${result.rollup.substep} verification.commands (${result.rollup.status})`
|
|
194
|
+
: `Rollup: skipped (${result.rollup.reason})`);
|
|
195
|
+
}
|
|
196
|
+
if (result.event) {
|
|
197
|
+
lines.push(result.event.emitted
|
|
198
|
+
? `Event: ${result.event.name} -> runs/${result.event.runId}/events.jsonl`
|
|
199
|
+
: `Event: not emitted (${result.event.error})`);
|
|
200
|
+
}
|
|
201
|
+
if (result.kind === 'executed' && !result.verified && result.diagnostics) {
|
|
202
|
+
lines.push('');
|
|
203
|
+
lines.push('Diagnostics:');
|
|
204
|
+
lines.push(result.diagnostics);
|
|
205
|
+
}
|
|
206
|
+
return lines.join('\n');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function runVerifyCommand(opts) {
|
|
210
|
+
const evidence = require('./evidence');
|
|
211
|
+
|
|
212
|
+
if (opts.attest) {
|
|
213
|
+
if (!opts.claim) {
|
|
214
|
+
const result = verifyFailure(opts, 'claim-required', 'verify --attest requires --claim="<claim>"');
|
|
215
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
216
|
+
else console.log(renderVerify(result));
|
|
217
|
+
process.exitCode = 1;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const outcome = evidence.verifyClaim(opts.claim, opts.evidence, {
|
|
221
|
+
substep: opts.substep || undefined,
|
|
222
|
+
projectRoot: opts.project
|
|
223
|
+
});
|
|
224
|
+
const result = {
|
|
225
|
+
command: 'verify',
|
|
226
|
+
kind: 'attested',
|
|
227
|
+
verdict: 'attested',
|
|
228
|
+
verified: null,
|
|
229
|
+
project: opts.project,
|
|
230
|
+
commandText: null,
|
|
231
|
+
substep: outcome.record.substep,
|
|
232
|
+
claim: outcome.record.claim,
|
|
233
|
+
ledger: relLedger(opts, outcome.ledger),
|
|
234
|
+
rollup: null,
|
|
235
|
+
event: null,
|
|
236
|
+
record: outcome.record
|
|
237
|
+
};
|
|
238
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
239
|
+
else console.log(renderVerify(result));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!opts.verifyCommand) {
|
|
244
|
+
const result = verifyFailure(opts, 'command-required', 'verify requires a command, for example: npx godpowers verify "npm test" --substep tier-2.build');
|
|
245
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
246
|
+
else console.log(renderVerify(result));
|
|
247
|
+
process.exitCode = 1;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!opts.substep) {
|
|
251
|
+
const result = verifyFailure(opts, 'substep-required', 'verify requires --substep=<id>, for example --substep=tier-2.build');
|
|
252
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
253
|
+
else console.log(renderVerify(result));
|
|
254
|
+
process.exitCode = 1;
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const outcome = evidence.verify(opts.verifyCommand, {
|
|
259
|
+
substep: opts.substep,
|
|
260
|
+
claim: opts.claim || undefined,
|
|
261
|
+
timeout: opts.timeout || undefined,
|
|
262
|
+
projectRoot: opts.project
|
|
263
|
+
});
|
|
264
|
+
const result = {
|
|
265
|
+
command: 'verify',
|
|
266
|
+
kind: 'executed',
|
|
267
|
+
verdict: outcome.verified ? 'pass' : 'fail',
|
|
268
|
+
verified: outcome.verified,
|
|
269
|
+
project: opts.project,
|
|
270
|
+
commandText: outcome.record.command,
|
|
271
|
+
substep: outcome.record.substep,
|
|
272
|
+
claim: outcome.record.claim,
|
|
273
|
+
exitCode: outcome.record.exit_code,
|
|
274
|
+
durationMs: Math.max(0, Math.round(outcome.record.duration_seconds * 1000)),
|
|
275
|
+
diagnostics: outcome.rollup && outcome.rollup.applied
|
|
276
|
+
? undefined
|
|
277
|
+
: (outcome.record.stderr_tail || outcome.record.stdout_tail || ''),
|
|
278
|
+
ledger: relLedger(opts, outcome.ledger),
|
|
279
|
+
rollup: outcome.rollup,
|
|
280
|
+
event: outcome.event,
|
|
281
|
+
record: outcome.record
|
|
282
|
+
};
|
|
283
|
+
// Surface diagnostics on failure regardless of rollup state.
|
|
284
|
+
if (!outcome.verified) {
|
|
285
|
+
result.diagnostics = outcome.record.stderr_tail || outcome.record.stdout_tail || `exit ${outcome.record.exit_code}`;
|
|
286
|
+
}
|
|
287
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
288
|
+
else console.log(renderVerify(result));
|
|
289
|
+
if (!outcome.verified) process.exitCode = 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function renderCanClose(result) {
|
|
293
|
+
const lines = [];
|
|
294
|
+
lines.push('Godpowers Can-Close');
|
|
295
|
+
lines.push('');
|
|
296
|
+
lines.push(`Substep: ${result.substep || '(none)'}`);
|
|
297
|
+
lines.push(`Can close: ${result.canClose ? 'yes' : 'no'}`);
|
|
298
|
+
lines.push(`Reason: ${result.reason}`);
|
|
299
|
+
if (result.strategy) lines.push(`Strategy: ${result.strategy}`);
|
|
300
|
+
if (result.wentInFlightAt) lines.push(`In-flight since: ${result.wentInFlightAt}`);
|
|
301
|
+
return lines.join('\n');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function runCanCloseCommand(opts) {
|
|
305
|
+
const evidence = require('./evidence');
|
|
306
|
+
if (!opts.substep) {
|
|
307
|
+
const result = {
|
|
308
|
+
command: 'can-close',
|
|
309
|
+
project: opts.project,
|
|
310
|
+
canClose: false,
|
|
311
|
+
reason: 'substep-required',
|
|
312
|
+
strategy: null,
|
|
313
|
+
substep: null
|
|
314
|
+
};
|
|
315
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
316
|
+
else console.log(`${renderCanClose(result)}\n\nError: can-close requires --substep=<id>, for example --substep=tier-2.build`);
|
|
317
|
+
process.exitCode = 1;
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const verdict = evidence.canClose(opts.substep, { projectRoot: opts.project });
|
|
321
|
+
const result = { command: 'can-close', project: opts.project, ...verdict };
|
|
322
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
323
|
+
else console.log(renderCanClose(result));
|
|
324
|
+
if (!verdict.canClose) process.exitCode = 1;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function renderRoute(result) {
|
|
328
|
+
const lines = [];
|
|
329
|
+
lines.push('Godpowers Route');
|
|
330
|
+
lines.push('');
|
|
331
|
+
lines.push(`Route: ${result.route}`);
|
|
332
|
+
lines.push(`Reason: ${result.reason}`);
|
|
333
|
+
lines.push(`Next command: ${result.nextCommand || '(answer inline)'}`);
|
|
334
|
+
lines.push(`Ceremony: ${result.ceremony}`);
|
|
335
|
+
lines.push(`Verification: ${result.verificationStrategy}`);
|
|
336
|
+
lines.push(`Chat policy: ${result.chatPolicy}`);
|
|
337
|
+
const ev = result.evidence || {};
|
|
338
|
+
lines.push(`Evidence: classification=${ev.classification}, latest verdict=${ev.latestVerdict}, open findings=${ev.openFindings}`);
|
|
339
|
+
return lines.join('\n');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function runRouteCommand(opts) {
|
|
343
|
+
const quarterback = require('./quarterback');
|
|
344
|
+
const result = quarterback.route(opts.routePrompt || '', { projectRoot: opts.project });
|
|
345
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
346
|
+
else console.log(renderRoute(result));
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function runReportCommand(opts) {
|
|
350
|
+
const workReport = require('./work-report');
|
|
351
|
+
const result = workReport.report({
|
|
352
|
+
since: opts.since || 'last',
|
|
353
|
+
peek: opts.peek,
|
|
354
|
+
projectRoot: opts.project
|
|
355
|
+
});
|
|
356
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
357
|
+
else console.log(workReport.render(result));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function runReflectCommand(opts) {
|
|
361
|
+
const evidence = require('./evidence');
|
|
362
|
+
if (!opts.reflectAction) {
|
|
363
|
+
const result = {
|
|
364
|
+
command: 'reflect',
|
|
365
|
+
verdict: 'fail',
|
|
366
|
+
project: opts.project,
|
|
367
|
+
findings: [{ id: 'action-required', severity: 'error', artifact: '.godpowers/ledger/reflections.jsonl', reason: 'reflect requires --action="<what was attempted>"' }]
|
|
368
|
+
};
|
|
369
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
370
|
+
else console.log('Godpowers Reflect\n\nError: reflect requires --action="<what was attempted>"');
|
|
371
|
+
process.exitCode = 1;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const outcome = evidence.reflect({
|
|
375
|
+
action: opts.reflectAction,
|
|
376
|
+
outcome: opts.outcome || undefined,
|
|
377
|
+
observation: opts.observation || undefined,
|
|
378
|
+
rootCause: opts.rootCause || undefined,
|
|
379
|
+
next: opts.nextAction || undefined,
|
|
380
|
+
lesson: opts.lesson || undefined
|
|
381
|
+
}, { substep: opts.substep || undefined, projectRoot: opts.project });
|
|
382
|
+
if (opts.json) {
|
|
383
|
+
console.log(JSON.stringify(outcome, null, 2));
|
|
384
|
+
} else {
|
|
385
|
+
const r = outcome.record;
|
|
386
|
+
const lines = ['Godpowers Reflect', '', `Outcome: ${r.outcome}`, `Action: ${r.action}`];
|
|
387
|
+
if (r.substep) lines.push(`Substep: ${r.substep}`);
|
|
388
|
+
if (r.next) lines.push(`Next: ${r.next}`);
|
|
389
|
+
if (r.lesson) lines.push(`Lesson: ${r.lesson}`);
|
|
390
|
+
lines.push('Recorded to .godpowers/ledger/reflections.jsonl');
|
|
391
|
+
console.log(lines.join('\n'));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function memoryError(opts, reason) {
|
|
396
|
+
if (opts.json) {
|
|
397
|
+
console.log(JSON.stringify({ command: 'memory', verdict: 'fail', project: opts.project, reason }, null, 2));
|
|
398
|
+
} else {
|
|
399
|
+
console.log(`Godpowers Memory\n\nError: ${reason}`);
|
|
400
|
+
}
|
|
401
|
+
process.exitCode = 1;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function runMemoryCommand(opts) {
|
|
405
|
+
const evidence = require('./evidence');
|
|
406
|
+
const action = opts.memoryAction;
|
|
407
|
+
if (!action || !['set', 'get', 'list', 'clear'].includes(action)) {
|
|
408
|
+
return memoryError(opts, 'memory requires an action: set, get, list, or clear');
|
|
409
|
+
}
|
|
410
|
+
const projectRoot = opts.project;
|
|
411
|
+
let result;
|
|
412
|
+
if (action === 'set') {
|
|
413
|
+
if (!opts.memoryKey || opts.memoryValue === null) {
|
|
414
|
+
return memoryError(opts, 'memory set requires a key and value, for example: memory set decision "use postgres"');
|
|
415
|
+
}
|
|
416
|
+
result = evidence.memory.set(opts.memoryKey, opts.memoryValue, { category: opts.category || undefined, projectRoot });
|
|
417
|
+
} else if (action === 'get') {
|
|
418
|
+
if (!opts.memoryKey) return memoryError(opts, 'memory get requires a key');
|
|
419
|
+
result = evidence.memory.get(opts.memoryKey, { projectRoot });
|
|
420
|
+
} else if (action === 'list') {
|
|
421
|
+
result = evidence.memory.list({ category: opts.category || undefined, projectRoot });
|
|
422
|
+
} else {
|
|
423
|
+
result = evidence.memory.clear(opts.memoryKey || undefined, { projectRoot });
|
|
424
|
+
}
|
|
425
|
+
if (opts.json) {
|
|
426
|
+
console.log(JSON.stringify({ command: 'memory', action, result }, null, 2));
|
|
427
|
+
} else {
|
|
428
|
+
const lines = ['Godpowers Memory', '', `Action: ${action}`];
|
|
429
|
+
if (action === 'list') {
|
|
430
|
+
const entries = result || [];
|
|
431
|
+
lines.push(`Entries: ${entries.length}`);
|
|
432
|
+
for (const e of entries) lines.push(` [${e.category}] ${e.key} = ${e.value}`);
|
|
433
|
+
} else if (action === 'get') {
|
|
434
|
+
lines.push(result ? `[${result.category}] ${result.key} = ${result.value}` : '(not found)');
|
|
435
|
+
} else if (action === 'set') {
|
|
436
|
+
lines.push(`Set [${result.category}] ${result.key} = ${result.value}`);
|
|
437
|
+
} else {
|
|
438
|
+
lines.push(`Removed ${result.removed} entr${result.removed === 1 ? 'y' : 'ies'}`);
|
|
439
|
+
}
|
|
440
|
+
console.log(lines.join('\n'));
|
|
441
|
+
}
|
|
442
|
+
if (action === 'get' && !result) process.exitCode = 1;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function runLessonCommand(opts) {
|
|
446
|
+
const evidence = require('./evidence');
|
|
447
|
+
const action = opts.lessonAction;
|
|
448
|
+
if (!action || !['add', 'list'].includes(action)) {
|
|
449
|
+
if (opts.json) console.log(JSON.stringify({ command: 'lesson', verdict: 'fail', reason: 'lesson requires an action: add or list' }, null, 2));
|
|
450
|
+
else console.log('Godpowers Lesson\n\nError: lesson requires an action: add or list');
|
|
451
|
+
process.exitCode = 1;
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const projectRoot = opts.project;
|
|
455
|
+
if (action === 'add') {
|
|
456
|
+
if (!opts.lessonText) {
|
|
457
|
+
if (opts.json) console.log(JSON.stringify({ command: 'lesson', verdict: 'fail', reason: 'lesson add requires the lesson text' }, null, 2));
|
|
458
|
+
else console.log('Godpowers Lesson\n\nError: lesson add requires the lesson text, for example: lesson add "guard inputs before parsing"');
|
|
459
|
+
process.exitCode = 1;
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
const tags = opts.tags ? String(opts.tags).split(',').map((t) => t.trim()).filter(Boolean) : [];
|
|
463
|
+
const record = evidence.lesson.add(opts.lessonText, { tags, scope: opts.scope || undefined, projectRoot });
|
|
464
|
+
if (opts.json) console.log(JSON.stringify({ command: 'lesson', action, result: record }, null, 2));
|
|
465
|
+
else console.log(`Godpowers Lesson\n\nAdded [${record.scope}]${record.tags.length ? ` (${record.tags.join(',')})` : ''}: ${record.lesson}`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const records = evidence.lesson.list({ scope: opts.scope || undefined, projectRoot });
|
|
469
|
+
if (opts.json) {
|
|
470
|
+
console.log(JSON.stringify({ command: 'lesson', action, result: records }, null, 2));
|
|
471
|
+
} else {
|
|
472
|
+
const lines = ['Godpowers Lesson', '', `Lessons: ${records.length}`];
|
|
473
|
+
for (const r of records) lines.push(` [${r.scope}]${r.tags && r.tags.length ? ` (${r.tags.join(',')})` : ''} ${r.lesson}`);
|
|
474
|
+
console.log(lines.join('\n'));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function outcomeError(opts, reason) {
|
|
479
|
+
if (opts.json) console.log(JSON.stringify({ command: 'outcome', verdict: 'fail', reason }, null, 2));
|
|
480
|
+
else console.log(`Godpowers Outcome\n\nError: ${reason}`);
|
|
481
|
+
process.exitCode = 1;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function runOutcomeCommand(opts) {
|
|
485
|
+
const evidence = require('./evidence');
|
|
486
|
+
const action = opts.outcomeAction;
|
|
487
|
+
if (!action || !['start', 'check', 'stop', 'status'].includes(action)) {
|
|
488
|
+
return outcomeError(opts, 'outcome requires an action: start, check, stop, or status');
|
|
489
|
+
}
|
|
490
|
+
if (!opts.outcomeSlug) {
|
|
491
|
+
return outcomeError(opts, `outcome ${action} requires a name, for example: outcome ${action} green-build`);
|
|
492
|
+
}
|
|
493
|
+
const projectRoot = opts.project;
|
|
494
|
+
let payload;
|
|
495
|
+
if (action === 'start') {
|
|
496
|
+
payload = evidence.outcome.start(opts.outcomeSlug, {
|
|
497
|
+
goal: opts.outcomeGoal || undefined,
|
|
498
|
+
verifier: opts.outcomeVerify || undefined,
|
|
499
|
+
budget: opts.budget || undefined,
|
|
500
|
+
substep: opts.substep || undefined,
|
|
501
|
+
projectRoot
|
|
502
|
+
});
|
|
503
|
+
} else if (action === 'check') {
|
|
504
|
+
payload = evidence.outcome.check(opts.outcomeSlug, { projectRoot });
|
|
505
|
+
} else if (action === 'stop') {
|
|
506
|
+
payload = evidence.outcome.stop(opts.outcomeSlug, opts.reason || undefined, { projectRoot });
|
|
507
|
+
} else {
|
|
508
|
+
payload = evidence.outcome.status(opts.outcomeSlug, { projectRoot });
|
|
509
|
+
}
|
|
510
|
+
if (opts.json) {
|
|
511
|
+
console.log(JSON.stringify({ command: 'outcome', action, result: payload }, null, 2));
|
|
512
|
+
} else {
|
|
513
|
+
const lines = ['Godpowers Outcome', '', `Action: ${action}`];
|
|
514
|
+
const goal = payload && (payload.goal || (payload.slug ? payload : null));
|
|
515
|
+
if (goal && goal.slug) {
|
|
516
|
+
lines.push(`Outcome: ${goal.slug}`);
|
|
517
|
+
lines.push(`Status: ${goal.status}`);
|
|
518
|
+
lines.push(`Iterations: ${goal.iterations}/${goal.budget}`);
|
|
519
|
+
}
|
|
520
|
+
if (payload && payload.verified !== undefined) lines.push(`This check: ${payload.verified ? 'verified' : 'unverified'}`);
|
|
521
|
+
if (payload && payload.reason) lines.push(`Note: ${payload.reason}`);
|
|
522
|
+
if (!payload) lines.push('(outcome not found)');
|
|
523
|
+
console.log(lines.join('\n'));
|
|
524
|
+
}
|
|
525
|
+
// A check that did not verify, or a missing outcome, exits non-zero.
|
|
526
|
+
if (action === 'check' && payload && payload.verified === false) process.exitCode = 1;
|
|
527
|
+
if ((action === 'status') && !payload) process.exitCode = 1;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function runImportLedgerCommand(opts) {
|
|
531
|
+
const importer = require('./evidence-import');
|
|
532
|
+
const result = importer.importMythify({
|
|
533
|
+
source: opts.importFrom || undefined,
|
|
534
|
+
projectRoot: opts.project
|
|
535
|
+
});
|
|
536
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
537
|
+
else console.log(importer.render(result));
|
|
538
|
+
if (!result.found) process.exitCode = 1;
|
|
539
|
+
}
|
|
540
|
+
|
|
117
541
|
function runGateCommand(opts) {
|
|
118
542
|
if (!opts.tier) {
|
|
119
543
|
const result = {
|
|
@@ -185,8 +609,19 @@ const COMMAND_RUNNERS = {
|
|
|
185
609
|
'automation-status': runAutomationCommand,
|
|
186
610
|
'automation-setup': runAutomationCommand,
|
|
187
611
|
dogfood: runDogfoodCommand,
|
|
612
|
+
demo: runDemoCommand,
|
|
613
|
+
surface: runSurfaceCommand,
|
|
188
614
|
'extension-scaffold': runExtensionScaffoldCommand,
|
|
189
|
-
gate: runGateCommand
|
|
615
|
+
gate: runGateCommand,
|
|
616
|
+
verify: runVerifyCommand,
|
|
617
|
+
'can-close': runCanCloseCommand,
|
|
618
|
+
route: runRouteCommand,
|
|
619
|
+
report: runReportCommand,
|
|
620
|
+
reflect: runReflectCommand,
|
|
621
|
+
memory: runMemoryCommand,
|
|
622
|
+
lesson: runLessonCommand,
|
|
623
|
+
outcome: runOutcomeCommand,
|
|
624
|
+
'import-ledger': runImportLedgerCommand
|
|
190
625
|
};
|
|
191
626
|
|
|
192
627
|
function runCommand(opts) {
|
|
@@ -204,9 +639,20 @@ module.exports = {
|
|
|
204
639
|
runAutomationCommand,
|
|
205
640
|
runDashboardCommand,
|
|
206
641
|
runDogfoodCommand,
|
|
642
|
+
runDemoCommand,
|
|
207
643
|
runQuickProofCommand,
|
|
644
|
+
runSurfaceCommand,
|
|
208
645
|
runMcpInfoCommand,
|
|
209
646
|
runExtensionScaffoldCommand,
|
|
210
647
|
runGateCommand,
|
|
211
|
-
runStateCommand
|
|
648
|
+
runStateCommand,
|
|
649
|
+
runVerifyCommand,
|
|
650
|
+
runCanCloseCommand,
|
|
651
|
+
runRouteCommand,
|
|
652
|
+
runReportCommand,
|
|
653
|
+
runReflectCommand,
|
|
654
|
+
runMemoryCommand,
|
|
655
|
+
runLessonCommand,
|
|
656
|
+
runOutcomeCommand,
|
|
657
|
+
runImportLedgerCommand
|
|
212
658
|
};
|
package/lib/command-families.js
CHANGED
|
@@ -15,6 +15,8 @@ const COMMAND_FAMILIES = [
|
|
|
15
15
|
purpose: 'Start or import a project.',
|
|
16
16
|
commands: [
|
|
17
17
|
'/god',
|
|
18
|
+
'/god-first-run',
|
|
19
|
+
'/god-demo',
|
|
18
20
|
'/god-init',
|
|
19
21
|
'/god-mode',
|
|
20
22
|
'/god-plan',
|
|
@@ -191,6 +193,7 @@ const COMMAND_FAMILIES = [
|
|
|
191
193
|
purpose: 'Tune settings, budgets, cache, profiles, help, and version info.',
|
|
192
194
|
commands: [
|
|
193
195
|
'/god-settings',
|
|
196
|
+
'/god-surface',
|
|
194
197
|
'/god-set-profile',
|
|
195
198
|
'/god-budget',
|
|
196
199
|
'/god-cost',
|
|
@@ -292,9 +295,14 @@ function familyForCommand(command) {
|
|
|
292
295
|
return COMMAND_FAMILIES.find((family) => family.commands.includes(command)) || null;
|
|
293
296
|
}
|
|
294
297
|
|
|
295
|
-
function renderFamilyCards(
|
|
298
|
+
function renderFamilyCards(
|
|
299
|
+
families = COMMAND_FAMILIES.filter((family) => family.visibility !== 'hidden'),
|
|
300
|
+
opts = {}
|
|
301
|
+
) {
|
|
296
302
|
return families.map((family) => (
|
|
297
|
-
|
|
303
|
+
opts.includeCommands
|
|
304
|
+
? `${family.label}: ${family.purpose} (${family.commands.join(', ')})`
|
|
305
|
+
: `${family.label}: ${family.purpose}`
|
|
298
306
|
));
|
|
299
307
|
}
|
|
300
308
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "mythify-mcp",
|
|
3
|
+
"upstreamRepo": "mythify",
|
|
4
|
+
"upstreamPath": "mcp-server/src/index.js",
|
|
5
|
+
"engine": "verify_run + verify_claim (verification tools)",
|
|
6
|
+
"version": "3.6.3",
|
|
7
|
+
"commit": "7cbd601f9c4d5328a54921a051d450703e44c514",
|
|
8
|
+
"syncedAt": "2026-06-15",
|
|
9
|
+
"adaptations": [
|
|
10
|
+
"verificationStepContext (plan/step_id/step_title/step_status) rebound to substepContext (arc/substep/substep_status)",
|
|
11
|
+
"state dir .mythify/ rebound to .godpowers/ledger/",
|
|
12
|
+
"appendJsonl (fs.appendFileSync) rebound to an atomic read-modify-write append via lib/atomic-write.js",
|
|
13
|
+
"executed verdict additionally rolled up into state.json verification.commands[] via lib/state.js in the Godpowers gate shape",
|
|
14
|
+
"executed verdict additionally emitted as gate.pass / gate.fail to .godpowers/runs/<id>/events.jsonl via lib/events.js",
|
|
15
|
+
"verify_claim exposed as evidence.verifyClaim: attested, verified:null, never rolled up, never emitted"
|
|
16
|
+
],
|
|
17
|
+
"upstreamRecordShape": {
|
|
18
|
+
"executed": [
|
|
19
|
+
"kind",
|
|
20
|
+
"claim",
|
|
21
|
+
"command",
|
|
22
|
+
"exit_code",
|
|
23
|
+
"duration_seconds",
|
|
24
|
+
"stdout_tail",
|
|
25
|
+
"stderr_tail",
|
|
26
|
+
"verified",
|
|
27
|
+
"timestamp",
|
|
28
|
+
"plan",
|
|
29
|
+
"step_id",
|
|
30
|
+
"step_title",
|
|
31
|
+
"step_status"
|
|
32
|
+
],
|
|
33
|
+
"attested": [
|
|
34
|
+
"kind",
|
|
35
|
+
"claim",
|
|
36
|
+
"evidence",
|
|
37
|
+
"verified",
|
|
38
|
+
"timestamp",
|
|
39
|
+
"plan",
|
|
40
|
+
"step_id",
|
|
41
|
+
"step_title",
|
|
42
|
+
"step_status"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|