infernoflow 0.10.18 → 0.10.20
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 +7 -1
- package/dist/bin/infernoflow.mjs +19 -5
- package/dist/lib/commands/diff.mjs +5 -0
- package/dist/lib/commands/publish.mjs +21 -0
- package/package.json +48 -48
package/CHANGELOG.md
CHANGED
package/dist/bin/infernoflow.mjs
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as
|
|
2
|
+
import{readFileSync as m}from"node:fs";import{dirname as d,join as f}from"node:path";import{fileURLToPath as u}from"node:url";import{bold as t,gray as e,red as s}from"../lib/ui/output.mjs";const h=d(u(import.meta.url)),g=JSON.parse(m(f(h,"..","package.json"),"utf8")),r=g.version||"0.0.0",c={publish:"Bump version, update changelog, build, npm publish, git commit + push in one shot",diff:"Show what capabilities changed since the last git tag (or any ref)",setup:"One command to get fully operational \u2014 detects IDE, inits, installs hooks + MCP",init:"Scaffold inferno/ in your project (or adopt existing project)","install-cursor-hooks":"Install Cursor hooks: draft agent replies to inferno/CONTEXT.draft.md","install-vscode-copilot-hooks":"Install VS Code + Copilot agent hooks (Preview): draft to inferno/CONTEXT.draft.md",check:"Validate contract, capabilities, scenarios, changelog",status:"Show contract health at a glance","pr-impact":"Summarize PR impact on capabilities and docs",sync:"Run deterministic inferno sync flow",run:"One-command detect/propose/apply/validate flow","doc-gate":"Fail if code changed but docs were not updated",suggest:"Generate AI prompt + apply capability updates",implement:"Generate code-agent implementation prompt(s)",context:"Generate AI-ready context for new sessions","generate-skills":"Generate personalised Cursor rules + skill files from your developer profile"},l={publish:async o=>(await import("../lib/commands/publish.mjs")).publishCommand(o),diff:async o=>(await import("../lib/commands/diff.mjs")).diffCommand(o),setup:async o=>(await import("../lib/commands/setup.mjs")).setupCommand(o),init:async o=>(await import("../lib/commands/init.mjs")).initCommand(o),"install-cursor-hooks":async o=>(await import("../lib/commands/installCursorHooks.mjs")).installCursorHooksCommand(o),"install-vscode-copilot-hooks":async o=>(await import("../lib/commands/installVsCodeCopilotHooks.mjs")).installVsCodeCopilotHooksCommand(o),check:async o=>(await import("../lib/commands/check.mjs")).checkCommand(o),status:async o=>(await import("../lib/commands/status.mjs")).statusCommand(o),"pr-impact":async o=>(await import("../lib/commands/prImpact.mjs")).prImpactCommand(o),sync:async o=>(await import("../lib/commands/syncAuto.mjs")).syncCommand(o),run:async o=>(await import("../lib/commands/run.mjs")).runCommand(o),suggest:async o=>(await import("../lib/commands/suggest.mjs")).suggestCommand(o),implement:async o=>(await import("../lib/commands/implement.mjs")).implementCommand(o),context:async o=>(await import("../lib/commands/context.mjs")).contextCommand(o),"doc-gate":async o=>(await import("../lib/commands/docGate.mjs")).docGateCommand(o),"generate-skills":async o=>(await import("../lib/commands/generateSkills.mjs")).generateSkillsCommand(o)};function y(){const o=Object.keys(c),a=Math.max(...o.map(i=>i.length),8)+1;return Object.entries(c).map(([i,p])=>` ${i.padEnd(a," ")}${p}`).join(`
|
|
3
3
|
`)}const w=`
|
|
4
|
-
${t("\u{1F525} infernoflow")} ${e("v"+
|
|
4
|
+
${t("\u{1F525} infernoflow")} ${e("v"+r)}
|
|
5
5
|
${e("The forge for liquid code \u2014 keep every AI session in sync")}
|
|
6
6
|
|
|
7
7
|
${t("Usage:")}
|
|
8
8
|
infernoflow <command> [options]
|
|
9
9
|
|
|
10
10
|
${t("Commands:")}
|
|
11
|
-
${
|
|
11
|
+
${y()}
|
|
12
|
+
|
|
13
|
+
${t("diff options:")}
|
|
14
|
+
--ref <tag|commit> Compare against a specific ref (default: last git tag)
|
|
15
|
+
--summary One-liner count only
|
|
16
|
+
--json Machine-readable output
|
|
17
|
+
|
|
18
|
+
${t("publish options:")}
|
|
19
|
+
--bump patch|minor|major Version bump type (default: patch)
|
|
20
|
+
--skip-build Skip the build step
|
|
21
|
+
--skip-tests Skip smoke tests
|
|
22
|
+
--skip-push Commit but don't git push
|
|
23
|
+
--tag Also create a git tag vX.Y.Z
|
|
24
|
+
--dry-run Print all steps without executing
|
|
25
|
+
--yes, -y Non-interactive (skip confirmation prompt)
|
|
12
26
|
|
|
13
27
|
${t("setup options:")}
|
|
14
28
|
--yes, -y Skip prompts (non-interactive)
|
|
@@ -72,7 +86,7 @@ ${g()}
|
|
|
72
86
|
${e("pr-impact --json")}
|
|
73
87
|
${e("sync --auto --json")}
|
|
74
88
|
${e('run "task" --json')}
|
|
75
|
-
`;import*as k from"node:fs";import*as C from"node:path";try{const o=C.join(process.cwd(),"inferno");if(k.existsSync(o)){const{observeCommandStart:
|
|
89
|
+
`;import*as k from"node:fs";import*as C from"node:path";try{const o=C.join(process.cwd(),"inferno");if(k.existsSync(o)){const{observeCommandStart:a}=await import("../lib/learning/observe.mjs"),i=process.argv[2];i&&!i.startsWith("-")&&a(o,i)}}catch{}const[,,n,...b]=process.argv;(!n||n==="--help"||n==="-h")&&(console.log(w),process.exit(0)),(n==="--version"||n==="-v")&&(console.log(r),process.exit(0));const v=Object.keys(l);v.includes(n)||(console.error(s(`
|
|
76
90
|
Unknown command: ${n}`)),console.error(e(`Run: infernoflow --help
|
|
77
|
-
`)),process.exit(1));const $=[n,...
|
|
91
|
+
`)),process.exit(1));const $=[n,...b];l[n]($).catch(o=>{console.error(s(`
|
|
78
92
|
Error: `)+o.message),process.exit(1)});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import*as u from"node:fs";import*as v from"node:path";import{execSync as C}from"node:child_process";import{header as N,ok as J,fail as m,bold as d,cyan as k,gray as c,green as $,red as y,yellow as x}from"../ui/output.mjs";function h(n,e){try{return C(n,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch{return null}}function D(n){const e=h("git describe --tags --abbrev=0",n);return e||null}function j(n,e,o){return h(`git show "${n}:${e}"`,o)}function z(n){return h("git rev-parse --abbrev-ref HEAD",n)||"HEAD"}function O(n,e){const o=h(`git log -1 --format=%ci "${e}"`,n),t=o?o.slice(0,10):null;return t?`${e} ${c("("+t+")")}`:e}function b(n){if(!n)return null;try{return(JSON.parse(n).capabilities||[]).map(t=>typeof t=="string"?{id:t,title:t}:{id:t.id||t,title:t.title||t.id||String(t),since:t.since,status:t.status})}catch{return null}}function _(n,e,o){const t=j(n,`${e}/capabilities.json`,o);if(t)return b(t);const g=j(n,`${e}/contract.json`,o);return b(g)}function E(n){const e=v.join(n,"capabilities.json"),o=v.join(n,"contract.json");return u.existsSync(e)?b(u.readFileSync(e,"utf8")):u.existsSync(o)?b(u.readFileSync(o,"utf8")):null}function R(n,e){const o=new Map(n.map(i=>[i.id,i])),t=new Map(e.map(i=>[i.id,i])),g=e.filter(i=>!o.has(i.id)),s=n.filter(i=>!t.has(i.id)),l=[];for(const i of e){const f=o.get(i.id);if(!f)continue;const a=[];f.title!==i.title&&a.push({field:"title",from:f.title,to:i.title}),f.status!==i.status&&(f.status||i.status)&&a.push({field:"status",from:f.status||"\u2014",to:i.status||"\u2014"}),a.length&&l.push({id:i.id,changes:a})}return{added:g,removed:s,changed:l}}function H(n){if(n.length){console.log(`
|
|
2
|
+
${d($("+ Added"))} ${c("("+n.length+")")}`);for(const e of n){const o=e.since?c(" since "+e.since):"";console.log(` ${$("+")} ${d(e.id)} ${c(e.title)}${o}`)}}}function M(n){if(n.length){console.log(`
|
|
3
|
+
${d(y("- Removed"))} ${c("("+n.length+")")}`);for(const e of n)console.log(` ${y("-")} ${d(e.id)} ${c(e.title)}`)}}function F(n){if(n.length){console.log(`
|
|
4
|
+
${d(x("~ Changed"))} ${c("("+n.length+")")}`);for(const e of n){console.log(` ${x("~")} ${d(e.id)}`);for(const o of e.changes)console.log(` ${c(o.field+":")} ${y(o.from)} \u2192 ${$(o.to)}`)}}}function U(n){n!==0&&console.log(`
|
|
5
|
+
${c(" Unchanged "+n)}`)}function w(n,e){const o=[];n.added.length&&o.push($("+"+n.added.length+" added")),n.removed.length&&o.push(y("-"+n.removed.length+" removed")),n.changed.length&&o.push(x("~"+n.changed.length+" changed")),o.length||o.push(c("no changes")),console.log(` ${o.join(" ")} ${c("vs "+e)}`)}async function G(n){const e=n.slice(1),o=e.includes("--json"),t=e.includes("--summary"),g=e.indexOf("--ref");let s=g!==-1?e[g+1]:null;const l=process.cwd(),i=v.join(l,"inferno"),f="inferno";o||N("diff"),u.existsSync(i)||(o&&(console.log(JSON.stringify({ok:!1,error:"inferno_not_found"})),process.exit(1)),m("inferno/ not found","Run: infernoflow init"),process.exit(1)),s||(s=D(l),s||(h("git rev-parse HEAD~1",l)?s="HEAD~1":(o&&(console.log(JSON.stringify({ok:!1,error:"no_ref",hint:"No git tags found and no parent commit. Use --ref <commit>"})),process.exit(1)),m("No git tags found","Create a tag first: git tag v0.1.0 or use --ref <commit>"),process.exit(1))));const a=E(i);a||(o&&(console.log(JSON.stringify({ok:!1,error:"no_capabilities_found"})),process.exit(1)),m("No capabilities.json or contract.json found in inferno/"),process.exit(1));const p=_(s,f,l);p||(o&&(console.log(JSON.stringify({ok:!1,error:"ref_not_found",ref:s,hint:"Does inferno/capabilities.json exist at that ref?"})),process.exit(1)),m(`Could not read capabilities at ${s}`,"The inferno/ directory may not exist at that ref"),process.exit(1));const r=R(p,a),S=a.length-r.added.length-r.changed.length;if(o){console.log(JSON.stringify({ok:!0,ref:s,current:a.length,previous:p.length,added:r.added,removed:r.removed,changed:r.changed,unchanged:S},null,2));return}const A=O(l,s);if(console.log(),console.log(` Comparing ${d(k("current"))} vs ${d(A)}`),console.log(` ${c(a.length+" capabilities now / "+p.length+" before")}`),t){w(r,s),console.log();return}if(!(r.added.length||r.removed.length||r.changed.length)){console.log(),J("No capability changes since "+s),console.log();return}H(r.added),M(r.removed),F(r.changed),U(S),console.log(),w(r,s),console.log()}export{G as diffCommand};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import*as c from"node:fs";import*as f from"node:path";import{execSync as b}from"node:child_process";import{fileURLToPath as F}from"node:url";import{header as L,ok as o,fail as k,warn as l,info as u,done as O,bold as S,cyan as C,gray as n,green as T}from"../ui/output.mjs";const U=f.dirname(F(import.meta.url)),g=f.resolve(U,"../..");function a(r,i={}){return b(r,{cwd:g,encoding:"utf8",stdio:i.silent?["ignore","pipe","pipe"]:["inherit","inherit","inherit"],...i})}function x(r){return b(r,{cwd:g,encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}function E(r,i){const e=r.split(".").map(Number);return i==="major"?(e[0]++,e[1]=0,e[2]=0):i==="minor"?(e[1]++,e[2]=0):e[2]++,e.join(".")}function h(){return new Date().toISOString().slice(0,10)}function H(r,i){if(!c.existsSync(r))return c.writeFileSync(r,`# Changelog \u2014 infernoflow
|
|
2
|
+
|
|
3
|
+
## ${i} \u2014 ${h()}
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Release ${i}
|
|
7
|
+
`),!0;let e=c.readFileSync(r,"utf8");if(/^## Unreleased/im.test(e))return e=e.replace(/^## Unreleased.*$/im,`## ${i} \u2014 ${h()}`),c.writeFileSync(r,e),!0;const p=/^# .+$/im;return p.test(e)?(e=e.replace(p,y=>`${y}
|
|
8
|
+
|
|
9
|
+
## ${i} \u2014 ${h()}
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Release ${i}
|
|
13
|
+
`),c.writeFileSync(r,e),!0):(c.writeFileSync(r,`## ${i} \u2014 ${h()}
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Release ${i}
|
|
17
|
+
|
|
18
|
+
${e}`),!0)}function _(){try{return x("git status --porcelain").length>0}catch{return!1}}function J(){try{return x("git config user.email"),!0}catch{return!1}}async function M(r){const i=r.slice(1),e=i.includes("--dry-run"),p=i.includes("--skip-build"),y=i.includes("--skip-tests"),A=i.includes("--skip-push"),j=i.includes("--tag"),N=i.includes("--yes")||i.includes("-y"),G=i.indexOf("--bump"),m=G!==-1&&i[G+1]||"patch";["patch","minor","major"].includes(m)||(console.error(` Invalid --bump value: ${m}. Must be patch, minor, or major.`),process.exit(1)),L("infernoflow publish"),e&&l("DRY RUN \u2014 no files will be written, no commands executed");const v=f.join(g,"package.json"),$=JSON.parse(c.readFileSync(v,"utf8")),w=$.version,t=E(w,m);if(console.log(),console.log(` ${n("current")} ${S(w)}`),console.log(` ${n("new ")} ${S(T(t))} ${n("("+m+" bump)")}`),console.log(),!N&&!e){process.stdout.write(` Publish ${S(C("infernoflow@"+t))} to npm? [y/N] `);let s=!1;try{const d=b("bash -c 'read -r ans </dev/tty; echo $ans'",{encoding:"utf8",stdio:["inherit","pipe","inherit"]}).trim().toLowerCase();s=d==="y"||d==="yes"}catch{s=!1}console.log(),s||(console.log(n(` Aborted.
|
|
19
|
+
`)),process.exit(0))}u(`Bumping package.json ${n(w+" \u2192 "+t)}`),e?o(n("[dry] would write package.json")):($.version=t,c.writeFileSync(v,JSON.stringify($,null,4)+`
|
|
20
|
+
`),o("package.json updated"));const R=f.join(g,"CHANGELOG.md");if(u("Updating CHANGELOG.md"),e?o(n("[dry] would update CHANGELOG.md")):(H(R,t),o("CHANGELOG.md updated")),p)l("Skipping build (--skip-build)");else if(u("Running build "+n("node build.mjs")),e)o(n("[dry] would run: node build.mjs"));else try{a("node build.mjs",{silent:!1}),o("Build succeeded")}catch(s){k("Build failed",s.message),process.exit(1)}if(y)l("Skipping tests (--skip-tests)");else if(u("Running smoke tests"),e)o(n("[dry] would run: npm test"));else try{a("npm test",{silent:!1}),o("All smoke tests passed")}catch{k("Smoke tests failed","Fix tests or re-run with --skip-tests"),process.exit(1)}if(u(`Publishing to npm ${n("infernoflow@"+t)}`),e)o(n("[dry] would run: npm publish"));else try{a("npm publish",{silent:!1}),o(`Published infernoflow@${t}`)}catch(s){k("npm publish failed",s.message||"Check npm credentials"),l("Continuing to git commit despite publish failure")}if(u("Committing version bump"),e)o(n(`[dry] would commit: chore: release ${t}`));else try{a(`git add ${["package.json","CHANGELOG.md"].join(" ")}`,{silent:!1});const d=`chore: release ${t}`;a(`git commit -m "${d}"`,{silent:!1}),o(`Committed: ${n(d)}`)}catch(s){l(`Git commit failed: ${s.message}`),l('You can commit manually: git add package.json CHANGELOG.md && git commit -m "chore: release '+t+'"')}if(j)if(u(`Creating git tag ${n("v"+t)}`),e)o(n(`[dry] would tag: v${t}`));else try{a(`git tag v${t}`,{silent:!1}),o(`Tagged v${t}`)}catch(s){l(`Git tag failed: ${s.message}`)}if(A)l("Skipping push (--skip-push)");else if(u("Pushing to origin"),e)o(n("[dry] would run: git push"));else try{const s=j?`git push && git push origin v${t}`:"git push";a(s,{silent:!1}),o("Pushed to origin")}catch(s){l(`Git push failed: ${s.message}`),l("Push manually: git push")}console.log(),e?O(`Dry run complete \u2014 would have published infernoflow@${t}`):(O(`infernoflow@${t} published, committed, and pushed`),console.log(` ${C("npm:")} https://www.npmjs.com/package/infernoflow`),console.log(` ${C("git:")} ${n("chore: release "+t)}
|
|
21
|
+
`))}export{M as publishCommand};
|
package/package.json
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "infernoflow",
|
|
3
|
-
"version": "0.10.
|
|
4
|
-
"description": "The forge for liquid code — keep capabilities, contracts, and docs in sync.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"infernoflow": "dist/bin/infernoflow.mjs"
|
|
8
|
-
},
|
|
9
|
-
"engines": {
|
|
10
|
-
"node": ">=18"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"dist/bin",
|
|
14
|
-
"dist/lib",
|
|
15
|
-
"dist/templates",
|
|
16
|
-
"README.md",
|
|
17
|
-
"CHANGELOG.md"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
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
|
-
"test:help": "node bin/infernoflow.mjs --help",
|
|
22
|
-
"build": "node build.mjs",
|
|
23
|
-
"prepublishOnly": "node build.mjs"
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"cli",
|
|
27
|
-
"capabilities",
|
|
28
|
-
"contract",
|
|
29
|
-
"documentation",
|
|
30
|
-
"ai",
|
|
31
|
-
"liquid-code",
|
|
32
|
-
"dx",
|
|
33
|
-
"developer-tools"
|
|
34
|
-
],
|
|
35
|
-
"author": "infernoflow",
|
|
36
|
-
"license": "MIT",
|
|
37
|
-
"repository": {
|
|
38
|
-
"type": "git",
|
|
39
|
-
"url": "git+https://github.com/ronmiz/infernoflow.git"
|
|
40
|
-
},
|
|
41
|
-
"homepage": "https://github.com/ronmiz/infernoflow#readme",
|
|
42
|
-
"bugs": {
|
|
43
|
-
"url": "https://github.com/ronmiz/infernoflow/issues"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"esbuild": "^0.28.0"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "infernoflow",
|
|
3
|
+
"version": "0.10.20",
|
|
4
|
+
"description": "The forge for liquid code — keep capabilities, contracts, and docs in sync.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"infernoflow": "dist/bin/infernoflow.mjs"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/bin",
|
|
14
|
+
"dist/lib",
|
|
15
|
+
"dist/templates",
|
|
16
|
+
"README.md",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
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
|
+
"test:help": "node bin/infernoflow.mjs --help",
|
|
22
|
+
"build": "node build.mjs",
|
|
23
|
+
"prepublishOnly": "node build.mjs"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"cli",
|
|
27
|
+
"capabilities",
|
|
28
|
+
"contract",
|
|
29
|
+
"documentation",
|
|
30
|
+
"ai",
|
|
31
|
+
"liquid-code",
|
|
32
|
+
"dx",
|
|
33
|
+
"developer-tools"
|
|
34
|
+
],
|
|
35
|
+
"author": "infernoflow",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/ronmiz/infernoflow.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/ronmiz/infernoflow#readme",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/ronmiz/infernoflow/issues"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"esbuild": "^0.28.0"
|
|
47
|
+
}
|
|
48
|
+
}
|