infernoflow 0.32.7 → 0.32.9
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/dist/bin/infernoflow.mjs +84 -255
- package/dist/lib/adopters/angular.mjs +1 -128
- package/dist/lib/adopters/css.mjs +1 -111
- package/dist/lib/adopters/react.mjs +1 -104
- package/dist/lib/ai/ideDetection.mjs +1 -31
- package/dist/lib/ai/localProvider.mjs +1 -88
- package/dist/lib/ai/providerRouter.mjs +2 -295
- package/dist/lib/commands/adopt.mjs +20 -869
- package/dist/lib/commands/adoptWizard.mjs +9 -320
- package/dist/lib/commands/agent.mjs +5 -191
- package/dist/lib/commands/ai.mjs +2 -407
- package/dist/lib/commands/audit.mjs +13 -300
- package/dist/lib/commands/changelog.mjs +26 -594
- package/dist/lib/commands/check.mjs +3 -184
- package/dist/lib/commands/ci.mjs +3 -208
- package/dist/lib/commands/claudeMd.mjs +25 -130
- package/dist/lib/commands/cloud.mjs +5 -521
- package/dist/lib/commands/context.mjs +31 -287
- package/dist/lib/commands/coverage.mjs +2 -282
- package/dist/lib/commands/dashboard.mjs +123 -635
- package/dist/lib/commands/demo.mjs +8 -465
- package/dist/lib/commands/diff.mjs +5 -274
- package/dist/lib/commands/docGate.mjs +2 -81
- package/dist/lib/commands/doctor.mjs +3 -321
- package/dist/lib/commands/explain.mjs +8 -438
- package/dist/lib/commands/export.mjs +10 -239
- package/dist/lib/commands/generateSkills.mjs +38 -163
- package/dist/lib/commands/graph.mjs +203 -320
- package/dist/lib/commands/health.mjs +2 -309
- package/dist/lib/commands/impact.mjs +2 -325
- package/dist/lib/commands/implement.mjs +7 -103
- package/dist/lib/commands/init.mjs +23 -475
- package/dist/lib/commands/installCursorHooks.mjs +1 -36
- package/dist/lib/commands/installVsCodeCopilotHooks.mjs +1 -37
- package/dist/lib/commands/link.mjs +2 -342
- package/dist/lib/commands/monorepo.mjs +4 -428
- package/dist/lib/commands/notify.mjs +4 -258
- package/dist/lib/commands/onboard.mjs +4 -296
- package/dist/lib/commands/prComment.mjs +2 -361
- package/dist/lib/commands/prImpact.mjs +2 -157
- package/dist/lib/commands/publish.mjs +15 -316
- package/dist/lib/commands/report.mjs +28 -272
- package/dist/lib/commands/review.mjs +9 -223
- package/dist/lib/commands/run.mjs +8 -336
- package/dist/lib/commands/scaffold.mjs +54 -419
- package/dist/lib/commands/scan.mjs +5 -558
- package/dist/lib/commands/scout.mjs +2 -291
- package/dist/lib/commands/setup.mjs +5 -310
- package/dist/lib/commands/share.mjs +13 -196
- package/dist/lib/commands/snapshot.mjs +3 -383
- package/dist/lib/commands/stability.mjs +2 -293
- package/dist/lib/commands/status.mjs +4 -172
- package/dist/lib/commands/suggest.mjs +21 -563
- package/dist/lib/commands/syncAuto.mjs +1 -96
- package/dist/lib/commands/synthesize.mjs +10 -228
- package/dist/lib/commands/teamSync.mjs +2 -388
- package/dist/lib/commands/test.mjs +6 -363
- package/dist/lib/commands/version.mjs +2 -282
- package/dist/lib/commands/vibe.mjs +7 -357
- package/dist/lib/commands/watch.mjs +4 -203
- package/dist/lib/commands/why.mjs +4 -358
- package/dist/lib/cursorHooksInstall.mjs +1 -60
- package/dist/lib/draftToolingInstall.mjs +7 -68
- package/dist/lib/git/detect-drift.mjs +4 -208
- package/dist/lib/learning/adapt.mjs +6 -101
- package/dist/lib/learning/observe.mjs +1 -119
- package/dist/lib/learning/patternDetector.mjs +1 -298
- package/dist/lib/learning/profile.mjs +2 -279
- package/dist/lib/learning/skillSynthesizer.mjs +24 -145
- package/dist/lib/templates/index.mjs +1 -131
- package/dist/lib/ui/errors.mjs +1 -142
- package/dist/lib/ui/output.mjs +6 -72
- package/dist/lib/ui/prompts.mjs +6 -147
- package/dist/lib/vsCodeCopilotHooksInstall.mjs +1 -42
- package/dist/templates/cursor/inferno-mcp-server.mjs +29 -0
- package/dist/templates/github-app/GITHUB_APP.md +67 -0
- package/dist/templates/github-app/app-manifest.json +20 -0
- package/package.json +1 -1
|
@@ -1,103 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* infernoflow demo
|
|
3
|
-
*
|
|
4
|
-
* A self-contained, narrated walkthrough of infernoflow's core capabilities.
|
|
5
|
-
* Scaffolds a temp sample project, runs the full chain, and shows real output.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* infernoflow demo Run the full interactive demo
|
|
9
|
-
* infernoflow demo --fast Skip pauses (CI/recording mode)
|
|
10
|
-
* infernoflow demo --no-cleanup Keep the temp project after the demo
|
|
11
|
-
*
|
|
12
|
-
* What it demonstrates:
|
|
13
|
-
* 1. Project structure — a mini e-commerce API with real capabilities
|
|
14
|
-
* 2. infernoflow scan — AST analysis: functions, services, throws
|
|
15
|
-
* 3. infernoflow graph — dependency graph
|
|
16
|
-
* 4. infernoflow stability — frozen/stable/experimental breakdown
|
|
17
|
-
* 5. infernoflow impact — blast radius for payment-process
|
|
18
|
-
* 6. infernoflow explain — narrative (structural or AI)
|
|
19
|
-
* 7. infernoflow why — file → capability correlation
|
|
20
|
-
* 8. The money shot: trying to modify a frozen cap and getting warned
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import * as fs from "node:fs";
|
|
24
|
-
import * as path from "node:path";
|
|
25
|
-
import * as os from "node:os";
|
|
26
|
-
import { fileURLToPath } from "node:url";
|
|
27
|
-
import { execSync, spawnSync } from "node:child_process";
|
|
28
|
-
import { bold, cyan, gray, green, yellow, red } from "../ui/output.mjs";
|
|
29
|
-
|
|
30
|
-
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
33
|
-
|
|
34
|
-
async function pause(fast, ms = 900) {
|
|
35
|
-
if (!fast) await sleep(ms);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function hr(char = "─", len = 60) {
|
|
39
|
-
return gray(char.repeat(len));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function run(cmd, cwd) {
|
|
43
|
-
try {
|
|
44
|
-
return spawnSync(cmd, {
|
|
45
|
-
shell: true, cwd, encoding: "utf8", timeout: 30_000,
|
|
46
|
-
});
|
|
47
|
-
} catch { return { stdout: "", stderr: "", status: 1 }; }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ── sample project scaffold ───────────────────────────────────────────────────
|
|
51
|
-
|
|
52
|
-
const SAMPLE_FILES = {
|
|
53
|
-
// Capability definitions
|
|
54
|
-
"inferno/capabilities.json": JSON.stringify([
|
|
55
|
-
{
|
|
56
|
-
id: "user-auth",
|
|
57
|
-
name: "User Authentication",
|
|
58
|
-
description: "Handles login, session management, and token validation",
|
|
59
|
-
stability: "frozen",
|
|
60
|
-
owner: "auth-team",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "payment-process",
|
|
64
|
-
name: "Payment Processing",
|
|
65
|
-
description: "Charges cards via Stripe, handles retries and webhook events",
|
|
66
|
-
stability: "stable",
|
|
67
|
-
owner: "payments-team",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: "order-create",
|
|
71
|
-
name: "Order Creation",
|
|
72
|
-
description: "Validates cart, reserves inventory, creates order records",
|
|
73
|
-
stability: "experimental",
|
|
74
|
-
owner: "core-team",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: "email-notify",
|
|
78
|
-
name: "Email Notifications",
|
|
79
|
-
description: "Sends transactional emails via SendGrid for orders and auth events",
|
|
80
|
-
stability: "experimental",
|
|
81
|
-
owner: "core-team",
|
|
82
|
-
},
|
|
83
|
-
], null, 2),
|
|
84
|
-
|
|
85
|
-
// Dependency graph
|
|
86
|
-
"inferno/graph.json": JSON.stringify({
|
|
87
|
-
deps: {
|
|
88
|
-
"order-create": ["user-auth", "payment-process"],
|
|
89
|
-
"email-notify": ["order-create"],
|
|
90
|
-
"payment-process": ["user-auth"],
|
|
91
|
-
},
|
|
92
|
-
dependents: {
|
|
93
|
-
"user-auth": ["payment-process", "order-create"],
|
|
94
|
-
"payment-process": ["order-create"],
|
|
95
|
-
"order-create": ["email-notify"],
|
|
96
|
-
},
|
|
97
|
-
}, null, 2),
|
|
98
|
-
|
|
99
|
-
// Source files
|
|
100
|
-
"src/auth.js": `// User Authentication
|
|
1
|
+
import*as b from"node:fs";import*as u from"node:path";import*as A from"node:os";import{fileURLToPath as E}from"node:url";import{spawnSync as C}from"node:child_process";import{bold as y,cyan as o,gray as a,green as r,yellow as v,red as h}from"../ui/output.mjs";function T(e){return new Promise(t=>setTimeout(t,e))}async function d(e,t=900){e||await T(t)}function J(e="\u2500",t=60){return a(e.repeat(t))}function q(e,t){try{return C(e,{shell:!0,cwd:t,encoding:"utf8",timeout:3e4})}catch{return{stdout:"",stderr:"",status:1}}}const P={"inferno/capabilities.json":JSON.stringify([{id:"user-auth",name:"User Authentication",description:"Handles login, session management, and token validation",stability:"frozen",owner:"auth-team"},{id:"payment-process",name:"Payment Processing",description:"Charges cards via Stripe, handles retries and webhook events",stability:"stable",owner:"payments-team"},{id:"order-create",name:"Order Creation",description:"Validates cart, reserves inventory, creates order records",stability:"experimental",owner:"core-team"},{id:"email-notify",name:"Email Notifications",description:"Sends transactional emails via SendGrid for orders and auth events",stability:"experimental",owner:"core-team"}],null,2),"inferno/graph.json":JSON.stringify({deps:{"order-create":["user-auth","payment-process"],"email-notify":["order-create"],"payment-process":["user-auth"]},dependents:{"user-auth":["payment-process","order-create"],"payment-process":["order-create"],"order-create":["email-notify"]}},null,2),"src/auth.js":`// User Authentication
|
|
101
2
|
const jwt = require('jsonwebtoken');
|
|
102
3
|
const bcrypt = require('bcrypt');
|
|
103
4
|
|
|
@@ -128,9 +29,7 @@ function validateToken(req, res, next) {
|
|
|
128
29
|
}
|
|
129
30
|
|
|
130
31
|
module.exports = { authenticateUser, validateToken };
|
|
131
|
-
`,
|
|
132
|
-
|
|
133
|
-
"src/payment.js": `// Payment Processing
|
|
32
|
+
`,"src/payment.js":`// Payment Processing
|
|
134
33
|
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
|
|
135
34
|
|
|
136
35
|
/**
|
|
@@ -169,9 +68,7 @@ async function handleWebhook(event) {
|
|
|
169
68
|
}
|
|
170
69
|
|
|
171
70
|
module.exports = { processPayment, handleWebhook };
|
|
172
|
-
`,
|
|
173
|
-
|
|
174
|
-
"src/order.js": `// Order Creation
|
|
71
|
+
`,"src/order.js":`// Order Creation
|
|
175
72
|
const { validateToken } = require('./auth');
|
|
176
73
|
const { processPayment } = require('./payment');
|
|
177
74
|
|
|
@@ -195,9 +92,7 @@ async function createOrder(userId, cart, paymentMethodId) {
|
|
|
195
92
|
}
|
|
196
93
|
|
|
197
94
|
module.exports = { createOrder };
|
|
198
|
-
`,
|
|
199
|
-
|
|
200
|
-
"src/email.js": `// Email Notifications
|
|
95
|
+
`,"src/email.js":`// Email Notifications
|
|
201
96
|
const sgMail = require('@sendgrid/mail');
|
|
202
97
|
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
|
|
203
98
|
|
|
@@ -208,363 +103,11 @@ async function sendOrderConfirmation(order, user) {
|
|
|
208
103
|
await sgMail.send({
|
|
209
104
|
to: user.email,
|
|
210
105
|
from: 'noreply@shop.com',
|
|
211
|
-
subject: \`Order confirmed
|
|
212
|
-
text: \`Your order for
|
|
106
|
+
subject: \`Order confirmed \u2014 #\${order.id}\`,
|
|
107
|
+
text: \`Your order for $\${order.total} has been confirmed.\`,
|
|
213
108
|
});
|
|
214
109
|
}
|
|
215
110
|
|
|
216
111
|
module.exports = { sendOrderConfirmation };
|
|
217
|
-
`,
|
|
218
|
-
|
|
219
|
-
// Scenarios
|
|
220
|
-
"inferno/scenarios/auth-happy-path.json": JSON.stringify({
|
|
221
|
-
scenarioId: "auth-happy-path",
|
|
222
|
-
description: "User logs in with valid credentials and receives a JWT",
|
|
223
|
-
capabilitiesCovered: ["user-auth"],
|
|
224
|
-
steps: [
|
|
225
|
-
"POST /auth/login with valid email + password",
|
|
226
|
-
"Expect 200 with { token: '...' }",
|
|
227
|
-
"Use token in Authorization header for subsequent requests",
|
|
228
|
-
],
|
|
229
|
-
expects: [
|
|
230
|
-
"Token is a valid JWT signed with JWT_SECRET",
|
|
231
|
-
"Token expires in 24 hours",
|
|
232
|
-
],
|
|
233
|
-
}, null, 2),
|
|
234
|
-
|
|
235
|
-
"inferno/scenarios/payment-charge.json": JSON.stringify({
|
|
236
|
-
scenarioId: "payment-charge",
|
|
237
|
-
description: "Successful card charge via Stripe",
|
|
238
|
-
capabilitiesCovered: ["payment-process"],
|
|
239
|
-
steps: [
|
|
240
|
-
"Create order with valid cart",
|
|
241
|
-
"Call processPayment with valid Stripe test PM",
|
|
242
|
-
"Expect payment record in db with status: paid",
|
|
243
|
-
],
|
|
244
|
-
}, null, 2),
|
|
245
|
-
|
|
246
|
-
"package.json": JSON.stringify({
|
|
247
|
-
name: "demo-shop-api",
|
|
248
|
-
version: "1.0.0",
|
|
249
|
-
description: "Demo e-commerce API for infernoflow walkthrough",
|
|
250
|
-
}, null, 2),
|
|
251
|
-
|
|
252
|
-
// Pre-built scan so `why` works without running AST scan
|
|
253
|
-
"inferno/scan.json": JSON.stringify({
|
|
254
|
-
scannedAt: new Date().toISOString(),
|
|
255
|
-
capabilities: [
|
|
256
|
-
{
|
|
257
|
-
id: "user-auth",
|
|
258
|
-
codeAnalysis: {
|
|
259
|
-
sourceFiles: ["src/auth.js"],
|
|
260
|
-
functions: ["authenticateUser", "validateToken"],
|
|
261
|
-
services: [],
|
|
262
|
-
calls: ["db.users.findByEmail", "bcrypt.compare", "jwt.sign", "jwt.verify"],
|
|
263
|
-
throws: ["AuthError"],
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
id: "payment-process",
|
|
268
|
-
codeAnalysis: {
|
|
269
|
-
sourceFiles: ["src/payment.js"],
|
|
270
|
-
functions: ["processPayment", "handleWebhook"],
|
|
271
|
-
services: ["stripe"],
|
|
272
|
-
calls: ["stripe.paymentIntents.create", "db.payments.create", "db.orders.updateStatus"],
|
|
273
|
-
throws: ["PaymentError"],
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
id: "order-create",
|
|
278
|
-
codeAnalysis: {
|
|
279
|
-
sourceFiles: ["src/order.js"],
|
|
280
|
-
functions: ["createOrder"],
|
|
281
|
-
services: [],
|
|
282
|
-
calls: ["db.users.findById", "db.inventory.reserve", "db.orders.create", "processPayment"],
|
|
283
|
-
throws: [],
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
id: "email-notify",
|
|
288
|
-
codeAnalysis: {
|
|
289
|
-
sourceFiles: ["src/email.js"],
|
|
290
|
-
functions: ["sendOrderConfirmation"],
|
|
291
|
-
services: ["sendgrid"],
|
|
292
|
-
calls: ["sgMail.send"],
|
|
293
|
-
throws: [],
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
],
|
|
297
|
-
}, null, 2),
|
|
298
|
-
|
|
299
|
-
// Capability map for file → cap lookups
|
|
300
|
-
"inferno/capability-map.json": JSON.stringify({
|
|
301
|
-
"src/auth.js": ["user-auth"],
|
|
302
|
-
"src/payment.js": ["payment-process"],
|
|
303
|
-
"src/order.js": ["order-create"],
|
|
304
|
-
"src/email.js": ["email-notify"],
|
|
305
|
-
}, null, 2),
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
function scaffoldProject(dir) {
|
|
309
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
310
|
-
for (const [relPath, content] of Object.entries(SAMPLE_FILES)) {
|
|
311
|
-
const full = path.join(dir, relPath);
|
|
312
|
-
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
313
|
-
fs.writeFileSync(full, content);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// ── narrated steps ────────────────────────────────────────────────────────────
|
|
318
|
-
|
|
319
|
-
function header(title) {
|
|
320
|
-
console.log();
|
|
321
|
-
console.log(bold(` ── ${title}`));
|
|
322
|
-
console.log();
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function narrate(text) {
|
|
326
|
-
console.log(` ${gray(text)}`);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function cmd(text) {
|
|
330
|
-
console.log(` ${cyan("$")} ${bold(text)}`);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function out(lines) {
|
|
334
|
-
for (const l of lines) console.log(` ${l}`);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// ── demo runner ───────────────────────────────────────────────────────────────
|
|
338
|
-
|
|
339
|
-
function runInferno(command, args, demoDir, ifBin) {
|
|
340
|
-
const r = spawnSync(process.execPath, [ifBin, command, ...args], {
|
|
341
|
-
cwd: demoDir, encoding: "utf8", timeout: 30_000,
|
|
342
|
-
env: { ...process.env, NO_COLOR: "1" }
|
|
343
|
-
});
|
|
344
|
-
return (r.stdout || "") + (r.stderr || "");
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function printOutput(raw, maxLines = 20) {
|
|
348
|
-
const lines = raw.split("\n").filter(l => l.trim()).slice(0, maxLines);
|
|
349
|
-
for (const l of lines) console.log(` ${gray("│")} ${l}`);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export async function demoCommand(rawArgs) {
|
|
353
|
-
const args = (rawArgs || []).slice(1);
|
|
354
|
-
const fast = args.includes("--fast");
|
|
355
|
-
const noCleanup = args.includes("--no-cleanup");
|
|
356
|
-
|
|
357
|
-
// Find infernoflow bin
|
|
358
|
-
const ifBin = path.resolve(
|
|
359
|
-
path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url)))),
|
|
360
|
-
"bin", "infernoflow.mjs"
|
|
361
|
-
);
|
|
362
|
-
|
|
363
|
-
const demoDir = path.join(os.tmpdir(), `infernoflow-demo-${Date.now()}`);
|
|
364
|
-
|
|
365
|
-
console.clear();
|
|
366
|
-
console.log();
|
|
367
|
-
console.log(bold(" 🔥 infernoflow — interactive demo"));
|
|
368
|
-
console.log(gray(" ─────────────────────────────────────────────────────────────"));
|
|
369
|
-
console.log();
|
|
370
|
-
console.log(gray(" We'll build a mini e-commerce API and show infernoflow's full"));
|
|
371
|
-
console.log(gray(" capability chain — from AST scan to blast radius analysis."));
|
|
372
|
-
console.log();
|
|
373
|
-
if (!fast) {
|
|
374
|
-
console.log(gray(" Press Enter to advance each step, or run with --fast to skip pauses."));
|
|
375
|
-
}
|
|
376
|
-
console.log();
|
|
377
|
-
|
|
378
|
-
// ── Step 1: The project ─────────────────────────────────────────────────────
|
|
379
|
-
await pause(fast, 1200);
|
|
380
|
-
header("Step 1 of 7 — The project");
|
|
381
|
-
narrate("A small e-commerce API: auth, payments, orders, email.");
|
|
382
|
-
narrate(`Scaffolded in: ${demoDir}`);
|
|
383
|
-
console.log();
|
|
384
|
-
|
|
385
|
-
scaffoldProject(demoDir);
|
|
386
|
-
|
|
387
|
-
out([
|
|
388
|
-
`${green("src/")}`,
|
|
389
|
-
` ${cyan("auth.js")} ← user-auth capability`,
|
|
390
|
-
` ${cyan("payment.js")} ← payment-process capability`,
|
|
391
|
-
` ${cyan("order.js")} ← order-create capability`,
|
|
392
|
-
` ${cyan("email.js")} ← email-notify capability`,
|
|
393
|
-
``,
|
|
394
|
-
`${green("inferno/")}`,
|
|
395
|
-
` ${cyan("capabilities.json")} ← 4 capabilities registered`,
|
|
396
|
-
` ${cyan("graph.json")} ← dependency graph`,
|
|
397
|
-
` ${cyan("scenarios/")} ← 2 test scenarios`,
|
|
398
|
-
]);
|
|
399
|
-
|
|
400
|
-
await pause(fast, 1000);
|
|
401
|
-
|
|
402
|
-
// ── Step 2: Stability ───────────────────────────────────────────────────────
|
|
403
|
-
header("Step 2 of 7 — Capability stability");
|
|
404
|
-
cmd("infernoflow stability");
|
|
405
|
-
console.log();
|
|
406
|
-
|
|
407
|
-
const stabOut = runInferno("stability", [], demoDir, ifBin);
|
|
408
|
-
if (stabOut.trim()) {
|
|
409
|
-
printOutput(stabOut, 12);
|
|
410
|
-
} else {
|
|
411
|
-
// Manual fallback display
|
|
412
|
-
out([
|
|
413
|
-
`🧊 ${red("user-auth")} frozen Auth team owns this — no changes without approval`,
|
|
414
|
-
`〰️ ${yellow("payment-process")} stable Stripe integration — additive changes only`,
|
|
415
|
-
`🌊 ${green("order-create")} experimental Free to refactor`,
|
|
416
|
-
`🌊 ${green("email-notify")} experimental Free to refactor`,
|
|
417
|
-
]);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
console.log();
|
|
421
|
-
narrate("user-auth is FROZEN — it's the most critical cap and must never break silently.");
|
|
422
|
-
narrate("payment-process is STABLE — changes must be additive.");
|
|
423
|
-
|
|
424
|
-
await pause(fast, 1000);
|
|
425
|
-
|
|
426
|
-
// ── Step 3: Impact analysis ─────────────────────────────────────────────────
|
|
427
|
-
header("Step 3 of 7 — Blast radius: what breaks if user-auth changes?");
|
|
428
|
-
cmd("infernoflow impact user-auth");
|
|
429
|
-
console.log();
|
|
430
|
-
|
|
431
|
-
const impactOut = runInferno("impact", ["user-auth"], demoDir, ifBin);
|
|
432
|
-
if (impactOut.trim()) {
|
|
433
|
-
printOutput(impactOut, 18);
|
|
434
|
-
} else {
|
|
435
|
-
out([
|
|
436
|
-
`🧊 ${red("user-auth")} → risk: ${red("CRITICAL")}`,
|
|
437
|
-
``,
|
|
438
|
-
` Direct dependents (1):`,
|
|
439
|
-
` payment-process ${yellow("stable")}`,
|
|
440
|
-
``,
|
|
441
|
-
` Transitive dependents (2):`,
|
|
442
|
-
` order-create ${green("experimental")}`,
|
|
443
|
-
` email-notify ${green("experimental")}`,
|
|
444
|
-
``,
|
|
445
|
-
` ${red("CRITICAL")} — frozen capability with dependents.`,
|
|
446
|
-
` Any change risks breaking 3 downstream capabilities.`,
|
|
447
|
-
]);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
console.log();
|
|
451
|
-
narrate("Change user-auth and you risk breaking payments, orders, and email.");
|
|
452
|
-
narrate("This is the blast radius — measured before you write a single line.");
|
|
453
|
-
|
|
454
|
-
await pause(fast, 1200);
|
|
455
|
-
|
|
456
|
-
// ── Step 4: explain ─────────────────────────────────────────────────────────
|
|
457
|
-
header("Step 4 of 7 — What is this capability, exactly?");
|
|
458
|
-
cmd("infernoflow explain user-auth");
|
|
459
|
-
console.log();
|
|
460
|
-
|
|
461
|
-
const explainOut = runInferno("explain", ["user-auth"], demoDir, ifBin);
|
|
462
|
-
if (explainOut.trim()) {
|
|
463
|
-
printOutput(explainOut, 14);
|
|
464
|
-
} else {
|
|
465
|
-
out([
|
|
466
|
-
`🧊 ${red("user-auth")}`,
|
|
467
|
-
` User Authentication`,
|
|
468
|
-
``,
|
|
469
|
-
` Handles login, session management, and token validation.`,
|
|
470
|
-
` This capability is FROZEN — do not modify without explicit instruction.`,
|
|
471
|
-
` payment-process, order-create depend on this capability.`,
|
|
472
|
-
` Before shipping changes, run: auth-happy-path scenario.`,
|
|
473
|
-
``,
|
|
474
|
-
` ${yellow("💡")} For richer AI narratives: infernoflow ai setup`,
|
|
475
|
-
]);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
await pause(fast, 1000);
|
|
479
|
-
|
|
480
|
-
// ── Step 5: why ─────────────────────────────────────────────────────────────
|
|
481
|
-
header("Step 5 of 7 — File → capability correlation");
|
|
482
|
-
cmd("infernoflow why src/payment.js");
|
|
483
|
-
console.log();
|
|
484
|
-
|
|
485
|
-
const whyOut = runInferno("why", ["src/payment.js"], demoDir, ifBin);
|
|
486
|
-
if (whyOut.trim()) {
|
|
487
|
-
printOutput(whyOut, 14);
|
|
488
|
-
} else {
|
|
489
|
-
out([
|
|
490
|
-
` src/payment.js → ${yellow("payment-process")} (stable)`,
|
|
491
|
-
``,
|
|
492
|
-
` Name: Payment Processing`,
|
|
493
|
-
` Description: Charges cards via Stripe, handles retries and webhook events`,
|
|
494
|
-
` Stability: 〰️ stable — additive changes only`,
|
|
495
|
-
``,
|
|
496
|
-
` Scenarios: payment-charge`,
|
|
497
|
-
` Depended on by: order-create (experimental)`,
|
|
498
|
-
]);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
console.log();
|
|
502
|
-
narrate("Any developer can instantly see what capability owns a given file.");
|
|
503
|
-
narrate("No guessing. No digging through wikis.");
|
|
504
|
-
|
|
505
|
-
await pause(fast, 1000);
|
|
506
|
-
|
|
507
|
-
// ── Step 6: test ─────────────────────────────────────────────────────────────
|
|
508
|
-
header("Step 6 of 7 — Run registered scenarios");
|
|
509
|
-
cmd("infernoflow test");
|
|
510
|
-
console.log();
|
|
511
|
-
|
|
512
|
-
const testOut = runInferno("test", [], demoDir, ifBin);
|
|
513
|
-
if (testOut.trim()) {
|
|
514
|
-
printOutput(testOut, 12);
|
|
515
|
-
} else {
|
|
516
|
-
out([
|
|
517
|
-
` ${green("✓")} user-auth [frozen]`,
|
|
518
|
-
` ${green("✓")} auth-happy-path (generated)`,
|
|
519
|
-
``,
|
|
520
|
-
` ${green("✓")} payment-process [stable]`,
|
|
521
|
-
` ${green("✓")} payment-charge (generated)`,
|
|
522
|
-
``,
|
|
523
|
-
` ${green("2")} passed 0 failed 0 skipped`,
|
|
524
|
-
]);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
await pause(fast, 800);
|
|
528
|
-
|
|
529
|
-
// ── Step 7: the money shot ──────────────────────────────────────────────────
|
|
530
|
-
header("Step 7 of 7 — The money shot: CI gate on a frozen capability");
|
|
531
|
-
cmd("infernoflow impact user-auth --check");
|
|
532
|
-
console.log();
|
|
533
|
-
narrate("--check exits with code 1 if risk is HIGH or CRITICAL.");
|
|
534
|
-
narrate("Add this to your CI pipeline before any PR that touches auth.");
|
|
535
|
-
console.log();
|
|
536
|
-
|
|
537
|
-
out([
|
|
538
|
-
` ${red("CRITICAL")} — user-auth is frozen with 3 dependents`,
|
|
539
|
-
` Exit code: 1`,
|
|
540
|
-
``,
|
|
541
|
-
` Your CI pipeline just stopped a risky change from reaching production.`,
|
|
542
|
-
]);
|
|
543
|
-
|
|
544
|
-
await pause(fast, 600);
|
|
545
|
-
|
|
546
|
-
// ── Summary ─────────────────────────────────────────────────────────────────
|
|
547
|
-
console.log();
|
|
548
|
-
console.log(gray(" ─────────────────────────────────────────────────────────────"));
|
|
549
|
-
console.log();
|
|
550
|
-
console.log(bold(" That's infernoflow."));
|
|
551
|
-
console.log();
|
|
552
|
-
console.log(` ${green("✓")} Capability contracts tracked in code, not in Confluence`);
|
|
553
|
-
console.log(` ${green("✓")} Blast radius measured before you change anything`);
|
|
554
|
-
console.log(` ${green("✓")} Every file knows what capability it serves`);
|
|
555
|
-
console.log(` ${green("✓")} CI gates on frozen capabilities — broken things don't ship`);
|
|
556
|
-
console.log(` ${green("✓")} Zero-touch with CLAUDE.md: your AI sessions stay in sync automatically`);
|
|
557
|
-
console.log();
|
|
558
|
-
console.log(` ${bold("Get started:")} ${cyan("npm install -g infernoflow")} → ${cyan("infernoflow setup")}`);
|
|
559
|
-
console.log();
|
|
560
|
-
console.log(gray(" ─────────────────────────────────────────────────────────────"));
|
|
561
|
-
console.log();
|
|
562
|
-
|
|
563
|
-
if (noCleanup) {
|
|
564
|
-
console.log(gray(` Demo project kept at: ${demoDir}`));
|
|
565
|
-
} else {
|
|
566
|
-
try { fs.rmSync(demoDir, { recursive: true, force: true }); } catch {}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
console.log();
|
|
570
|
-
}
|
|
112
|
+
`,"inferno/scenarios/auth-happy-path.json":JSON.stringify({scenarioId:"auth-happy-path",description:"User logs in with valid credentials and receives a JWT",capabilitiesCovered:["user-auth"],steps:["POST /auth/login with valid email + password","Expect 200 with { token: '...' }","Use token in Authorization header for subsequent requests"],expects:["Token is a valid JWT signed with JWT_SECRET","Token expires in 24 hours"]},null,2),"inferno/scenarios/payment-charge.json":JSON.stringify({scenarioId:"payment-charge",description:"Successful card charge via Stripe",capabilitiesCovered:["payment-process"],steps:["Create order with valid cart","Call processPayment with valid Stripe test PM","Expect payment record in db with status: paid"]},null,2),"package.json":JSON.stringify({name:"demo-shop-api",version:"1.0.0",description:"Demo e-commerce API for infernoflow walkthrough"},null,2),"inferno/scan.json":JSON.stringify({scannedAt:new Date().toISOString(),capabilities:[{id:"user-auth",codeAnalysis:{sourceFiles:["src/auth.js"],functions:["authenticateUser","validateToken"],services:[],calls:["db.users.findByEmail","bcrypt.compare","jwt.sign","jwt.verify"],throws:["AuthError"]}},{id:"payment-process",codeAnalysis:{sourceFiles:["src/payment.js"],functions:["processPayment","handleWebhook"],services:["stripe"],calls:["stripe.paymentIntents.create","db.payments.create","db.orders.updateStatus"],throws:["PaymentError"]}},{id:"order-create",codeAnalysis:{sourceFiles:["src/order.js"],functions:["createOrder"],services:[],calls:["db.users.findById","db.inventory.reserve","db.orders.create","processPayment"],throws:[]}},{id:"email-notify",codeAnalysis:{sourceFiles:["src/email.js"],functions:["sendOrderConfirmation"],services:["sendgrid"],calls:["sgMail.send"],throws:[]}}]},null,2),"inferno/capability-map.json":JSON.stringify({"src/auth.js":["user-auth"],"src/payment.js":["payment-process"],"src/order.js":["order-create"],"src/email.js":["email-notify"]},null,2)};function x(e){b.mkdirSync(e,{recursive:!0});for(const[t,n]of Object.entries(P)){const s=u.join(e,t);b.mkdirSync(u.dirname(s),{recursive:!0}),b.writeFileSync(s,n)}}function p(e){console.log(),console.log(y(` \u2500\u2500 ${e}`)),console.log()}function i(e){console.log(` ${a(e)}`)}function f(e){console.log(` ${o("$")} ${y(e)}`)}function m(e){for(const t of e)console.log(` ${t}`)}function g(e,t,n,s){const l=C(process.execPath,[s,e,...t],{cwd:n,encoding:"utf8",timeout:3e4,env:{...process.env,NO_COLOR:"1"}});return(l.stdout||"")+(l.stderr||"")}function w(e,t=20){const n=e.split(`
|
|
113
|
+
`).filter(s=>s.trim()).slice(0,t);for(const s of n)console.log(` ${a("\u2502")} ${s}`)}async function F(e){const t=(e||[]).slice(1),n=t.includes("--fast"),s=t.includes("--no-cleanup"),l=u.resolve(u.dirname(u.dirname(u.dirname(E(import.meta.url)))),"bin","infernoflow.mjs"),c=u.join(A.tmpdir(),`infernoflow-demo-${Date.now()}`);console.clear(),console.log(),console.log(y(" \u{1F525} infernoflow \u2014 interactive demo")),console.log(a(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(),console.log(a(" We'll build a mini e-commerce API and show infernoflow's full")),console.log(a(" capability chain \u2014 from AST scan to blast radius analysis.")),console.log(),n||console.log(a(" Press Enter to advance each step, or run with --fast to skip pauses.")),console.log(),await d(n,1200),p("Step 1 of 7 \u2014 The project"),i("A small e-commerce API: auth, payments, orders, email."),i(`Scaffolded in: ${c}`),console.log(),x(c),m([`${r("src/")}`,` ${o("auth.js")} \u2190 user-auth capability`,` ${o("payment.js")} \u2190 payment-process capability`,` ${o("order.js")} \u2190 order-create capability`,` ${o("email.js")} \u2190 email-notify capability`,"",`${r("inferno/")}`,` ${o("capabilities.json")} \u2190 4 capabilities registered`,` ${o("graph.json")} \u2190 dependency graph`,` ${o("scenarios/")} \u2190 2 test scenarios`]),await d(n,1e3),p("Step 2 of 7 \u2014 Capability stability"),f("infernoflow stability"),console.log();const S=g("stability",[],c,l);S.trim()?w(S,12):m([`\u{1F9CA} ${h("user-auth")} frozen Auth team owns this \u2014 no changes without approval`,`\u3030\uFE0F ${v("payment-process")} stable Stripe integration \u2014 additive changes only`,`\u{1F30A} ${r("order-create")} experimental Free to refactor`,`\u{1F30A} ${r("email-notify")} experimental Free to refactor`]),console.log(),i("user-auth is FROZEN \u2014 it's the most critical cap and must never break silently."),i("payment-process is STABLE \u2014 changes must be additive."),await d(n,1e3),p("Step 3 of 7 \u2014 Blast radius: what breaks if user-auth changes?"),f("infernoflow impact user-auth"),console.log();const $=g("impact",["user-auth"],c,l);$.trim()?w($,18):m([`\u{1F9CA} ${h("user-auth")} \u2192 risk: ${h("CRITICAL")}`,""," Direct dependents (1):",` payment-process ${v("stable")}`,""," Transitive dependents (2):",` order-create ${r("experimental")}`,` email-notify ${r("experimental")}`,"",` ${h("CRITICAL")} \u2014 frozen capability with dependents.`," Any change risks breaking 3 downstream capabilities."]),console.log(),i("Change user-auth and you risk breaking payments, orders, and email."),i("This is the blast radius \u2014 measured before you write a single line."),await d(n,1200),p("Step 4 of 7 \u2014 What is this capability, exactly?"),f("infernoflow explain user-auth"),console.log();const I=g("explain",["user-auth"],c,l);I.trim()?w(I,14):m([`\u{1F9CA} ${h("user-auth")}`," User Authentication",""," Handles login, session management, and token validation."," This capability is FROZEN \u2014 do not modify without explicit instruction."," payment-process, order-create depend on this capability."," Before shipping changes, run: auth-happy-path scenario.","",` ${v("\u{1F4A1}")} For richer AI narratives: infernoflow ai setup`]),await d(n,1e3),p("Step 5 of 7 \u2014 File \u2192 capability correlation"),f("infernoflow why src/payment.js"),console.log();const j=g("why",["src/payment.js"],c,l);j.trim()?w(j,14):m([` src/payment.js \u2192 ${v("payment-process")} (stable)`,""," Name: Payment Processing"," Description: Charges cards via Stripe, handles retries and webhook events"," Stability: \u3030\uFE0F stable \u2014 additive changes only",""," Scenarios: payment-charge"," Depended on by: order-create (experimental)"]),console.log(),i("Any developer can instantly see what capability owns a given file."),i("No guessing. No digging through wikis."),await d(n,1e3),p("Step 6 of 7 \u2014 Run registered scenarios"),f("infernoflow test"),console.log();const k=g("test",[],c,l);if(k.trim()?w(k,12):m([` ${r("\u2713")} user-auth [frozen]`,` ${r("\u2713")} auth-happy-path (generated)`,"",` ${r("\u2713")} payment-process [stable]`,` ${r("\u2713")} payment-charge (generated)`,"",` ${r("2")} passed 0 failed 0 skipped`]),await d(n,800),p("Step 7 of 7 \u2014 The money shot: CI gate on a frozen capability"),f("infernoflow impact user-auth --check"),console.log(),i("--check exits with code 1 if risk is HIGH or CRITICAL."),i("Add this to your CI pipeline before any PR that touches auth."),console.log(),m([` ${h("CRITICAL")} \u2014 user-auth is frozen with 3 dependents`," Exit code: 1",""," Your CI pipeline just stopped a risky change from reaching production."]),await d(n,600),console.log(),console.log(a(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(),console.log(y(" That's infernoflow.")),console.log(),console.log(` ${r("\u2713")} Capability contracts tracked in code, not in Confluence`),console.log(` ${r("\u2713")} Blast radius measured before you change anything`),console.log(` ${r("\u2713")} Every file knows what capability it serves`),console.log(` ${r("\u2713")} CI gates on frozen capabilities \u2014 broken things don't ship`),console.log(` ${r("\u2713")} Zero-touch with CLAUDE.md: your AI sessions stay in sync automatically`),console.log(),console.log(` ${y("Get started:")} ${o("npm install -g infernoflow")} \u2192 ${o("infernoflow setup")}`),console.log(),console.log(a(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(),s)console.log(a(` Demo project kept at: ${c}`));else try{b.rmSync(c,{recursive:!0,force:!0})}catch{}console.log()}export{F as demoCommand};
|