infernoflow 0.12.0 → 0.13.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/dist/bin/infernoflow.mjs
CHANGED
|
@@ -31,6 +31,7 @@ const COMMAND_DESCRIPTIONS = {
|
|
|
31
31
|
"generate-skills": "Generate personalised Cursor rules + skill files from your developer profile",
|
|
32
32
|
synthesize: "Auto-detect workflow patterns and synthesize reusable skills + agents",
|
|
33
33
|
agent: "Manage and run auto-synthesized agents (list | run | show | delete)",
|
|
34
|
+
version: "Smart semver bump recommendation based on capability changes (--apply to write)",
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const COMMAND_HANDLERS = {
|
|
@@ -55,6 +56,7 @@ const COMMAND_HANDLERS = {
|
|
|
55
56
|
"generate-skills": async (args) => (await import("../lib/commands/generateSkills.mjs")).generateSkillsCommand(args),
|
|
56
57
|
synthesize: async (args) => (await import("../lib/commands/synthesize.mjs")).synthesizeCommand(args),
|
|
57
58
|
agent: async (args) => (await import("../lib/commands/agent.mjs")).agentCommand(args),
|
|
59
|
+
version: async (args) => (await import("../lib/commands/version.mjs")).versionCommand(args),
|
|
58
60
|
};
|
|
59
61
|
|
|
60
62
|
function formatCommandsHelp() {
|
|
@@ -160,6 +162,11 @@ ${formatCommandsHelp()}
|
|
|
160
162
|
--response <json|@file> Provide AI response directly (use with --json)
|
|
161
163
|
--apply Apply the response changes when using --json --response
|
|
162
164
|
|
|
165
|
+
${bold("version options:")}
|
|
166
|
+
--ref <tag|commit> Compare against a specific ref (default: last git tag)
|
|
167
|
+
--apply Write recommended version bump to package.json
|
|
168
|
+
--json Machine-readable output
|
|
169
|
+
|
|
163
170
|
${bold("Machine output:")}
|
|
164
171
|
${gray("status --json")}
|
|
165
172
|
${gray("check --json")}
|
|
@@ -169,6 +176,8 @@ ${formatCommandsHelp()}
|
|
|
169
176
|
${gray('run "task" --json')}
|
|
170
177
|
${gray('suggest "what changed" --json')}
|
|
171
178
|
${gray('suggest "what changed" --json --response \'{"newCapabilities":[...]}\' --apply')}
|
|
179
|
+
${gray("version --json")}
|
|
180
|
+
${gray("version --apply")}
|
|
172
181
|
`;
|
|
173
182
|
|
|
174
183
|
// ── Silent behavior observation ───────────────────────────────────────────
|
|
@@ -119,9 +119,9 @@ export async function publishCommand(rawArgs) {
|
|
|
119
119
|
const yes = args.includes("--yes") || args.includes("-y");
|
|
120
120
|
|
|
121
121
|
const bumpIdx = args.indexOf("--bump");
|
|
122
|
-
|
|
122
|
+
let bumpType = bumpIdx !== -1 ? (args[bumpIdx + 1] || "patch") : null;
|
|
123
123
|
|
|
124
|
-
if (!["patch", "minor", "major"].includes(bumpType)) {
|
|
124
|
+
if (bumpType && !["patch", "minor", "major"].includes(bumpType)) {
|
|
125
125
|
console.error(` Invalid --bump value: ${bumpType}. Must be patch, minor, or major.`);
|
|
126
126
|
process.exit(1);
|
|
127
127
|
}
|
|
@@ -136,6 +136,29 @@ export async function publishCommand(rawArgs) {
|
|
|
136
136
|
const pkgPath = path.join(PKG_ROOT, "package.json");
|
|
137
137
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
138
138
|
const oldVersion = pkg.version;
|
|
139
|
+
|
|
140
|
+
// ── Auto-detect bump type from capability diff if not specified ───────────
|
|
141
|
+
if (!bumpType) {
|
|
142
|
+
try {
|
|
143
|
+
const { versionCommand: _vc, ...versionModule } = await import("./version.mjs");
|
|
144
|
+
// Use the JSON output to get the recommendation
|
|
145
|
+
const { execSync: _exec } = await import("node:child_process");
|
|
146
|
+
const result = _exec("node " + JSON.stringify(path.join(PKG_ROOT, "bin", "infernoflow.mjs")) + " version --json", {
|
|
147
|
+
cwd: PKG_ROOT, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"],
|
|
148
|
+
});
|
|
149
|
+
const parsed = JSON.parse(result);
|
|
150
|
+
if (parsed.bump && parsed.bump !== "none") {
|
|
151
|
+
bumpType = parsed.bump;
|
|
152
|
+
info(`Auto-detected bump type: ${bold(cyan(bumpType))} (from capability diff)`);
|
|
153
|
+
} else {
|
|
154
|
+
bumpType = "patch";
|
|
155
|
+
info(`No capability changes detected — defaulting to ${bold("patch")}`);
|
|
156
|
+
}
|
|
157
|
+
} catch {
|
|
158
|
+
bumpType = "patch";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
139
162
|
const newVersion = bumpVersion(oldVersion, bumpType);
|
|
140
163
|
|
|
141
164
|
console.log();
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* infernoflow version
|
|
3
|
+
*
|
|
4
|
+
* Smart semver bump recommendation based on capability changes since the last
|
|
5
|
+
* git tag (or a custom ref).
|
|
6
|
+
*
|
|
7
|
+
* Classification rules:
|
|
8
|
+
* MAJOR — any capability was REMOVED (breaking: callers lose functionality)
|
|
9
|
+
* MINOR — capabilities were ADDED (non-breaking: new surface area)
|
|
10
|
+
* PATCH — only metadata changed (title / description / status edits)
|
|
11
|
+
* NONE — no capability changes at all
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* infernoflow version # recommend bump type + show next version
|
|
15
|
+
* infernoflow version --apply # apply recommended bump to package.json
|
|
16
|
+
* infernoflow version --ref v1.2.3 # compare against a specific ref
|
|
17
|
+
* infernoflow version --json # machine-readable output
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import * as fs from "node:fs";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
import { execSync } from "node:child_process";
|
|
23
|
+
import { header, ok, warn, info, bold, cyan, gray, green, red, yellow, done } from "../ui/output.mjs";
|
|
24
|
+
|
|
25
|
+
// ── git helpers (shared with diff.mjs) ───────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
function capture(cmd, cwd) {
|
|
28
|
+
try {
|
|
29
|
+
return execSync(cmd, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function lastTag(cwd) {
|
|
36
|
+
return capture("git describe --tags --abbrev=0", cwd) || null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function fileAtRef(ref, relPath, cwd) {
|
|
40
|
+
return capture(`git show "${ref}:${relPath}"`, cwd);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── capability helpers ────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
function parseCaps(jsonText) {
|
|
46
|
+
if (!jsonText) return null;
|
|
47
|
+
try {
|
|
48
|
+
const obj = JSON.parse(jsonText);
|
|
49
|
+
const raw = obj.capabilities || [];
|
|
50
|
+
return raw.map(c => {
|
|
51
|
+
if (typeof c === "string") return { id: c, title: c };
|
|
52
|
+
return { id: c.id || c, title: c.title || c.id || String(c), status: c.status };
|
|
53
|
+
});
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function loadCapsFromDisk(infernoDir) {
|
|
60
|
+
const capsPath = path.join(infernoDir, "capabilities.json");
|
|
61
|
+
const contractPath = path.join(infernoDir, "contract.json");
|
|
62
|
+
if (fs.existsSync(capsPath)) return parseCaps(fs.readFileSync(capsPath, "utf8"));
|
|
63
|
+
if (fs.existsSync(contractPath)) return parseCaps(fs.readFileSync(contractPath, "utf8"));
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function loadCapsAtRef(ref, infernoRelDir, cwd) {
|
|
68
|
+
const capsJson = fileAtRef(ref, `${infernoRelDir}/capabilities.json`, cwd);
|
|
69
|
+
if (capsJson) return parseCaps(capsJson);
|
|
70
|
+
const contractJson = fileAtRef(ref, `${infernoRelDir}/contract.json`, cwd);
|
|
71
|
+
return parseCaps(contractJson);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function diffCaps(before, after) {
|
|
75
|
+
const beforeMap = new Map(before.map(c => [c.id, c]));
|
|
76
|
+
const afterMap = new Map(after.map(c => [c.id, c]));
|
|
77
|
+
|
|
78
|
+
const added = after.filter(c => !beforeMap.has(c.id));
|
|
79
|
+
const removed = before.filter(c => !afterMap.has(c.id));
|
|
80
|
+
|
|
81
|
+
const changed = [];
|
|
82
|
+
for (const c of after) {
|
|
83
|
+
const old = beforeMap.get(c.id);
|
|
84
|
+
if (!old) continue;
|
|
85
|
+
const changes = [];
|
|
86
|
+
if (old.title !== c.title) changes.push({ field: "title", from: old.title, to: c.title });
|
|
87
|
+
if ((old.status || "") !== (c.status || "")) changes.push({ field: "status", from: old.status || "—", to: c.status || "—" });
|
|
88
|
+
if (changes.length) changed.push({ id: c.id, changes });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { added, removed, changed };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── semver helpers ────────────────────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
function classifyBump(diff) {
|
|
97
|
+
if (diff.removed.length > 0) return "major";
|
|
98
|
+
if (diff.added.length > 0) return "minor";
|
|
99
|
+
if (diff.changed.length > 0) return "patch";
|
|
100
|
+
return "none";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function applyBump(version, type) {
|
|
104
|
+
const parts = (version || "0.0.0").split(".").map(Number);
|
|
105
|
+
if (type === "major") { parts[0]++; parts[1] = 0; parts[2] = 0; }
|
|
106
|
+
else if (type === "minor") { parts[1]++; parts[2] = 0; }
|
|
107
|
+
else if (type === "patch") { parts[2]++; }
|
|
108
|
+
return parts.join(".");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function readPackageVersion(cwd) {
|
|
112
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
113
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
114
|
+
try {
|
|
115
|
+
return JSON.parse(fs.readFileSync(pkgPath, "utf8")).version || null;
|
|
116
|
+
} catch { return null; }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function writePackageVersion(cwd, newVersion) {
|
|
120
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
121
|
+
const raw = fs.readFileSync(pkgPath, "utf8");
|
|
122
|
+
const data = JSON.parse(raw);
|
|
123
|
+
data.version = newVersion;
|
|
124
|
+
fs.writeFileSync(pkgPath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ── reason builder ────────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
function buildReason(type, diff, ref) {
|
|
130
|
+
const lines = [];
|
|
131
|
+
if (type === "major") {
|
|
132
|
+
lines.push(`${diff.removed.length} capability removed — breaking change`);
|
|
133
|
+
for (const c of diff.removed.slice(0, 3)) lines.push(` - ${c.id}: ${c.title}`);
|
|
134
|
+
if (diff.removed.length > 3) lines.push(` … and ${diff.removed.length - 3} more`);
|
|
135
|
+
} else if (type === "minor") {
|
|
136
|
+
lines.push(`${diff.added.length} new capability added`);
|
|
137
|
+
for (const c of diff.added.slice(0, 3)) lines.push(` + ${c.id}: ${c.title}`);
|
|
138
|
+
if (diff.added.length > 3) lines.push(` … and ${diff.added.length - 3} more`);
|
|
139
|
+
} else if (type === "patch") {
|
|
140
|
+
lines.push(`${diff.changed.length} capability metadata updated`);
|
|
141
|
+
} else {
|
|
142
|
+
lines.push(`No capability changes since ${ref}`);
|
|
143
|
+
}
|
|
144
|
+
return lines;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ── MCP-compatible JSON output ────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
function emitJson(payload) {
|
|
150
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ── main command ──────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
export async function versionCommand(rawArgs) {
|
|
156
|
+
const args = rawArgs.slice(1);
|
|
157
|
+
const asJson = args.includes("--json");
|
|
158
|
+
const apply = args.includes("--apply");
|
|
159
|
+
|
|
160
|
+
const refIdx = args.indexOf("--ref");
|
|
161
|
+
let ref = refIdx !== -1 ? args[refIdx + 1] : null;
|
|
162
|
+
|
|
163
|
+
const cwd = process.cwd();
|
|
164
|
+
const infernoDir = path.join(cwd, "inferno");
|
|
165
|
+
|
|
166
|
+
if (!asJson) header("infernoflow version");
|
|
167
|
+
|
|
168
|
+
// ── Validate ───────────────────────────────────────────────────────────────
|
|
169
|
+
if (!fs.existsSync(infernoDir)) {
|
|
170
|
+
if (asJson) { emitJson({ ok: false, error: "inferno_not_found" }); process.exit(1); }
|
|
171
|
+
warn("inferno/ not found — run: infernoflow init");
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ── Resolve ref ────────────────────────────────────────────────────────────
|
|
176
|
+
if (!ref) {
|
|
177
|
+
ref = lastTag(cwd);
|
|
178
|
+
if (!ref) {
|
|
179
|
+
const parentExists = capture("git rev-parse HEAD~1", cwd);
|
|
180
|
+
ref = parentExists ? "HEAD~1" : null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!ref) {
|
|
185
|
+
const currentVersion = readPackageVersion(cwd) || "0.0.0";
|
|
186
|
+
if (asJson) {
|
|
187
|
+
emitJson({ ok: true, bump: "minor", current: currentVersion, next: applyBump(currentVersion, "minor"), reason: ["No git history — defaulting to minor for first release"], ref: null });
|
|
188
|
+
} else {
|
|
189
|
+
info("No git history found — defaulting to minor for first release");
|
|
190
|
+
ok(`Recommended: ${bold(cyan("minor"))} → ${bold(applyBump(currentVersion, "minor"))}`);
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ── Load capabilities ──────────────────────────────────────────────────────
|
|
196
|
+
const current = loadCapsFromDisk(infernoDir);
|
|
197
|
+
const previous = loadCapsAtRef(ref, "inferno", cwd);
|
|
198
|
+
|
|
199
|
+
if (!current) {
|
|
200
|
+
if (asJson) { emitJson({ ok: false, error: "no_capabilities" }); process.exit(1); }
|
|
201
|
+
warn("No capabilities.json or contract.json found");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// If no previous snapshot, treat all current caps as new → minor
|
|
206
|
+
const prevCaps = previous || [];
|
|
207
|
+
const diff = diffCaps(prevCaps, current);
|
|
208
|
+
const bump = classifyBump(diff);
|
|
209
|
+
|
|
210
|
+
const currentVersion = readPackageVersion(cwd) || "0.0.0";
|
|
211
|
+
const nextVersion = bump === "none" ? currentVersion : applyBump(currentVersion, bump);
|
|
212
|
+
const reason = buildReason(bump, diff, ref);
|
|
213
|
+
|
|
214
|
+
// ── JSON output ────────────────────────────────────────────────────────────
|
|
215
|
+
if (asJson) {
|
|
216
|
+
emitJson({
|
|
217
|
+
ok: true,
|
|
218
|
+
bump,
|
|
219
|
+
current: currentVersion,
|
|
220
|
+
next: nextVersion,
|
|
221
|
+
ref,
|
|
222
|
+
reason,
|
|
223
|
+
diff: {
|
|
224
|
+
added: diff.added.length,
|
|
225
|
+
removed: diff.removed.length,
|
|
226
|
+
changed: diff.changed.length,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ── Human output ──────────────────────────────────────────────────────────
|
|
233
|
+
const bumpColor = bump === "major" ? red
|
|
234
|
+
: bump === "minor" ? green
|
|
235
|
+
: bump === "patch" ? yellow
|
|
236
|
+
: gray;
|
|
237
|
+
|
|
238
|
+
console.log();
|
|
239
|
+
console.log(` Current version ${bold(currentVersion)} ${gray("(" + ref + ")")}`);
|
|
240
|
+
console.log();
|
|
241
|
+
|
|
242
|
+
if (bump === "none") {
|
|
243
|
+
ok(`No capability changes — version stays at ${bold(currentVersion)}`);
|
|
244
|
+
} else {
|
|
245
|
+
console.log(` ${bold("Recommended bump:")} ${bumpColor(bold(bump.toUpperCase()))}`);
|
|
246
|
+
console.log();
|
|
247
|
+
for (const line of reason) {
|
|
248
|
+
const prefix = line.startsWith(" +") ? green(" +")
|
|
249
|
+
: line.startsWith(" -") ? red(" -")
|
|
250
|
+
: line.startsWith(" …") ? gray(" …")
|
|
251
|
+
: " ";
|
|
252
|
+
const text = line.replace(/^\s+[+\-…]\s?/, "");
|
|
253
|
+
if (line.startsWith(" ") && !line.startsWith(" …")) {
|
|
254
|
+
console.log(` ${line.trim()}`);
|
|
255
|
+
} else {
|
|
256
|
+
console.log(` ${gray(line)}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
console.log();
|
|
260
|
+
console.log(` ${bold(currentVersion)} → ${bumpColor(bold(nextVersion))}`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ── Apply ──────────────────────────────────────────────────────────────────
|
|
264
|
+
if (apply && bump !== "none") {
|
|
265
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
266
|
+
if (!fs.existsSync(pkgPath)) {
|
|
267
|
+
warn("No package.json found — skipping --apply");
|
|
268
|
+
} else {
|
|
269
|
+
writePackageVersion(cwd, nextVersion);
|
|
270
|
+
console.log();
|
|
271
|
+
done(`package.json updated → ${bold(nextVersion)}`);
|
|
272
|
+
}
|
|
273
|
+
} else if (apply && bump === "none") {
|
|
274
|
+
console.log();
|
|
275
|
+
info("No changes to apply — version unchanged");
|
|
276
|
+
} else if (bump !== "none") {
|
|
277
|
+
console.log();
|
|
278
|
+
info(`Run ${cyan("infernoflow version --apply")} to write ${nextVersion} to package.json`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
console.log();
|
|
282
|
+
}
|
|
@@ -68,6 +68,14 @@ const TOOLS = [
|
|
|
68
68
|
description: "Execute a saved workflow agent by name. Check infernoflow_agent_list first. Can replace multi-step manual workflows with one call.",
|
|
69
69
|
inputSchema: { type: "object", properties: { name: { type: "string", description: "Agent name to run" } }, required: ["name"] }
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: "infernoflow_version",
|
|
73
|
+
description: "Get the recommended semver bump (major/minor/patch) based on capability changes since the last git tag. CALL THIS AUTOMATICALLY when the developer asks about releasing, bumping version, or publishing. Returns bump type and next version number. Pass apply:true to write the bump to package.json.",
|
|
74
|
+
inputSchema: { type: "object", properties: {
|
|
75
|
+
apply: { type: "boolean", description: "If true, write the recommended version to package.json" },
|
|
76
|
+
ref: { type: "string", description: "Compare against a specific git ref (default: last tag)" }
|
|
77
|
+
}}
|
|
78
|
+
},
|
|
71
79
|
{
|
|
72
80
|
name: "infernoflow_run",
|
|
73
81
|
description: "Generate a full infernoflow task prompt. Use infernoflow_implement instead for most cases — it's simpler. Use this for complex multi-step flows.",
|
|
@@ -576,6 +584,11 @@ function handleTool(id, name, input) {
|
|
|
576
584
|
text = listAgents();
|
|
577
585
|
} else if (name === "infernoflow_agent_run") {
|
|
578
586
|
text = runAgent(input.name);
|
|
587
|
+
} else if (name === "infernoflow_version") {
|
|
588
|
+
const parts = ["version", "--json"];
|
|
589
|
+
if (input.ref) parts.push(`--ref "${input.ref}"`);
|
|
590
|
+
if (input.apply) parts.push("--apply");
|
|
591
|
+
text = runCmd(parts.join(" "));
|
|
579
592
|
} else { return sendError(id, -32601, `Unknown tool: ${name}`); }
|
|
580
593
|
sendResult(id, { content: [{ type: "text", text: text || "(no output)" }] });
|
|
581
594
|
} catch (err) { sendError(id, -32000, err.message); }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infernoflow",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The forge for liquid code
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "The forge for liquid code - keep capabilities, contracts, and docs in sync.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"infernoflow": "dist/bin/infernoflow.mjs"
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"test": "node scripts/smoke.mjs && node scripts/json-smoke.mjs && node scripts/json-negative-smoke.mjs && node scripts/implement-smoke.mjs && node scripts/adopt-smoke.mjs && node scripts/pr-impact-smoke.mjs && node scripts/sync-smoke.mjs && node scripts/run-smoke.mjs",
|
|
21
21
|
"test:help": "node bin/infernoflow.mjs --help",
|
|
22
22
|
"build": "node build.mjs",
|
|
23
|
-
"prepublishOnly": "node build.mjs"
|
|
23
|
+
"prepublishOnly": "node build.mjs",
|
|
24
|
+
"inferno:promote-draft": "node scripts/inferno-promote-draft.mjs"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"cli",
|
|
@@ -45,4 +46,4 @@
|
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"esbuild": "^0.28.0"
|
|
47
48
|
}
|
|
48
|
-
}
|
|
49
|
+
}
|