infernoflow 0.44.7 → 0.44.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.
@@ -1,13 +1,13 @@
1
- import*as l from"node:fs";import*as d from"node:path";import{execSync as I}from"node:child_process";import{readEntries as j,readConfig as _}from"./amp/io.mjs";const y="<!-- infernoflow:start -->",f="<!-- infernoflow:end -->",x=[".cursorrules","CLAUDE.md",d.join(".github","copilot-instructions.md")],b=4,A=5,C=200;function k(e){const n=e&&e.config||{},t=n.injection&&typeof n.injection=="object"?n.injection:{},r=Array.isArray(n.inject)&&!n.inject.includes("all")?n.inject:null;return{maxEntries:Number.isInteger(t.maxEntries)&&t.maxEntries>=0?t.maxEntries:b,maxCommits:Number.isInteger(t.maxCommits)&&t.maxCommits>=0?t.maxCommits:A,maxEntryChars:Number.isInteger(t.maxEntryChars)&&t.maxEntryChars>0?t.maxEntryChars:C,targets:Array.isArray(t.targets)&&t.targets.length?t.targets:r||x,includeProtocol:t.includeProtocol!==!1}}function T(e){if(!l.existsSync(e))return{stripped:!1};const n=l.readFileSync(e,"utf8"),t=n.indexOf(y),r=n.indexOf(f);if(t===-1||r===-1||r<=t)return{stripped:!1};const s=n.slice(0,t).replace(/\s+$/,""),o=n.slice(r+f.length).replace(/^\s+/,""),i=s&&o?s+`
1
+ import*as l from"node:fs";import*as d from"node:path";import{execSync as I}from"node:child_process";import{readEntries as j,readConfig as _}from"./amp/io.mjs";const y="<!-- infernoflow:start -->",f="<!-- infernoflow:end -->",x=[".cursorrules","CLAUDE.md",d.join(".github","copilot-instructions.md")],b=4,A=5,C=200;function v(e){const n=e&&e.config||{},t=n.injection&&typeof n.injection=="object"?n.injection:{},o=Array.isArray(n.inject)&&!n.inject.includes("all")?n.inject:null;return{maxEntries:Number.isInteger(t.maxEntries)&&t.maxEntries>=0?t.maxEntries:b,maxCommits:Number.isInteger(t.maxCommits)&&t.maxCommits>=0?t.maxCommits:A,maxEntryChars:Number.isInteger(t.maxEntryChars)&&t.maxEntryChars>0?t.maxEntryChars:C,targets:Array.isArray(t.targets)&&t.targets.length?t.targets:o||x,includeProtocol:t.includeProtocol!==!1}}function k(e){if(!l.existsSync(e))return{stripped:!1};const n=l.readFileSync(e,"utf8"),t=n.indexOf(y),o=n.indexOf(f);if(t===-1||o===-1||o<=t)return{stripped:!1};const r=n.slice(0,t).replace(/\s+$/,""),s=n.slice(o+f.length).replace(/^\s+/,""),i=r&&s?r+`
2
2
 
3
- `+o:s||o;return l.writeFileSync(e,i?i.replace(/\s*$/,"")+`
4
- `:"","utf8"),{stripped:!0}}function E(){const e=[];return e.push("### Memory protocol \u2014 capture as you go"),e.push(""),e.push("You have the `amp_write` MCP tool. **Use it proactively** (without the user asking) whenever you detect any of these moments. Capture the lesson in one sentence so the next AI session inherits it."),e.push(""),e.push("| When you see\u2026 | Call `amp_write` with\u2026 |"),e.push("|---|---|"),e.push("| User types `!!`, `!!!`, `not working`, `still broken`, `no change`, `same error`, `retry` / `retrying`, repeated frustration | `{type: 'attempt', msg: '<one-line: what was tried and how it failed>', file: '<active file>'}` |"),e.push("| You generate a plan, numbered steps, or `Plan:` / `Approach:` block | `{type: 'note', msg: 'Plan: <one-line summary>', file: '<focus file>'}` |"),e.push("| User picks X over Y, decides an architectural approach, or you both agree on a direction | `{type: 'decision', msg: '<X> chosen over <Y> because <reason>', file: '<file>'}` |"),e.push("| Discovered non-obvious behavior, API quirk, or `aha \u2014 turns out\u2026` moment | `{type: 'gotcha', msg: '<one-line>', file: '<file>', line: <line if known>}` |"),e.push("| User says `switching` / `back to X`, or ~30 min passed without logging | `{type: 'note', msg: 'Session snapshot \u2014 worked on: <X>. Open threads: <Y>.'}` |"),e.push(""),e.push("**Do NOT log:** typos, syntax errors, obvious bugs visible in the code, anything the next AI can infer by re-reading the file."),e.push("**Do log:** anything that taught you something non-derivable from code."),e.push("**Be concise:** entries should be one sentence. Future-you will skim them."),e.join(`
5
- `)}function F(){return[y,"<!-- Auto-managed by infernoflow. Don't edit between these markers. -->","## Project memory (infernoflow)","",E(),"",'_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._',f].join(`
6
- `)}function v(e){const n=e.indexOf("<!-- AMP:START -->"),t=e.indexOf("<!-- AMP:END -->");if(n===-1||t===-1||t<=n)return e;const r=e.slice(0,n).replace(/\s+$/,""),s=e.slice(t+16).replace(/^\s+/,"");return(r?r+(s?`
3
+ `+s:r||s;return l.writeFileSync(e,i?i.replace(/\s*$/,"")+`
4
+ `:"","utf8"),{stripped:!0}}function E(){const e=[];return e.push("### Memory protocol \u2014 capture as you go"),e.push(""),e.push("You have the `amp_write` MCP tool. **Use it proactively** (without the user asking) whenever you detect any of these moments. Capture the lesson in one sentence so the next AI session inherits it."),e.push(""),e.push("**If `amp_write` is not in your visible tools**, your client uses deferred MCP loading \u2014 call your tool-discovery mechanism (Claude Code: `ToolSearch` with query `infernoflow`) to load the `amp_*` tools BEFORE proceeding. Don't silently skip the protocol because the tool isn't visible yet."),e.push(""),e.push("| When you see\u2026 | Call `amp_write` with\u2026 |"),e.push("|---|---|"),e.push("| User types `!!`, `!!!`, `not working`, `still broken`, `no change`, `same error`, `retry` / `retrying`, repeated frustration | `{type: 'attempt', msg: '<one-line: what was tried and how it failed>', file: '<active file>'}` |"),e.push("| You generate a plan, numbered steps, or `Plan:` / `Approach:` block | `{type: 'note', msg: 'Plan: <one-line summary>', file: '<focus file>'}` |"),e.push("| User picks X over Y, decides an architectural approach, or you both agree on a direction | `{type: 'decision', msg: '<X> chosen over <Y> because <reason>', file: '<file>'}` |"),e.push("| Discovered non-obvious behavior, API quirk, or `aha \u2014 turns out\u2026` moment | `{type: 'gotcha', msg: '<one-line>', file: '<file>', line: <line if known>}` |"),e.push("| User says `switching` / `back to X`, or ~30 min passed without logging | `{type: 'note', msg: 'Session snapshot \u2014 worked on: <X>. Open threads: <Y>.'}` |"),e.push(""),e.push("**Do NOT log:** typos, syntax errors, obvious bugs visible in the code, anything the next AI can infer by re-reading the file."),e.push("**Do log:** anything that taught you something non-derivable from code."),e.push("**Be concise:** entries should be one sentence. Future-you will skim them."),e.push("**When you use a \u{1F525} memory entry in your reply, briefly cite it** \u2014 e.g. `\u{1F525} (from infernoflow memory) gotcha at src/api.js:42: ...` \u2014 so the user can see which guidance came from project memory vs. your own inference."),e.join(`
5
+ `)}function T(){return[y,"<!-- Auto-managed by infernoflow. Don't edit between these markers. -->","## Project memory (infernoflow)","",E(),"",'_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._',f].join(`
6
+ `)}function F(e){const n=e.indexOf("<!-- AMP:START -->"),t=e.indexOf("<!-- AMP:END -->");if(n===-1||t===-1||t<=n)return e;const o=e.slice(0,n).replace(/\s+$/,""),r=e.slice(t+16).replace(/^\s+/,"");return(o?o+(r?`
7
7
 
8
- `:""):"")+s}function S(e,n){const t=d.dirname(e);if(l.existsSync(t)||l.mkdirSync(t,{recursive:!0}),!l.existsSync(e))return l.writeFileSync(e,n+`
9
- `,"utf8"),{created:!0,updated:!1};let r=l.readFileSync(e,"utf8");r=v(r);const s=r.indexOf(y),o=r.indexOf(f);if(s===-1||o===-1){const g=n+`
8
+ `:""):"")+r}function S(e,n){const t=d.dirname(e);if(l.existsSync(t)||l.mkdirSync(t,{recursive:!0}),!l.existsSync(e))return l.writeFileSync(e,n+`
9
+ `,"utf8"),{created:!0,updated:!1};let o=l.readFileSync(e,"utf8");o=F(o);const r=o.indexOf(y),s=o.indexOf(f);if(r===-1||s===-1){const g=n+`
10
10
 
11
- `+r;return l.writeFileSync(e,g,"utf8"),{created:!1,updated:!0}}const i=r.slice(0,s),p=r.slice(o+f.length),u=i+n+p;return u===r?{created:!1,updated:!1}:(l.writeFileSync(e,u,"utf8"),{created:!1,updated:!0})}function O(e){const n=F(),t=[];for(const r of x){const s=d.join(e,r);try{const o=S(s,n);t.push({rel:r,...o})}catch(o){t.push({rel:r,error:o.message})}}return t}function D(e){return j(e)}function M(e,n=10){try{return I(`git log --pretty=format:"%h%x09%ad%x09%s" --date=short -n ${n}`,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).split(`
12
- `).filter(Boolean).map(r=>{const[s,o,i]=r.split(" ");return{hash:(s||"").slice(0,7),date:o||"",subject:i||""}})}catch{return[]}}function N(e,n={}){const{maxEntries:t=b,maxCommits:r=A,maxEntryChars:s=C,includeProtocol:o=!0}=n,i=D(e),p=M(e,r);i.sort((c,m)=>{const h=typeof c.ts=="number"?c.ts:Date.parse(c.ts||0);return(typeof m.ts=="number"?m.ts:Date.parse(m.ts||0))-h});const u=i.slice(0,t),g={gotcha:"\u26A0",decision:"\u2713",attempt:"\u2717",note:"\xB7",detection:"\u25CB",pattern:"\u25C7"},a=[];if(a.push(y),a.push("<!-- Auto-managed by infernoflow. Don't edit between these markers. -->"),a.push("## Project memory (infernoflow)"),a.push(""),o&&(a.push(E()),a.push("")),p.length>0){a.push("### Recent commits");for(const c of p)a.push(`- \`${c.hash}\` _${c.date}_ ${c.subject}`);a.push("")}if(u.length>0){a.push("### Recent memory");for(const c of u){const m=c.file?` (\`${c.file}${c.line?":"+c.line:""}\`)`:"",h=(c.msg||c.summary||"").replace(/\n/g," "),w=s&&h.length>s?h.slice(0,s).trimEnd()+"\u2026":h;a.push(`- \u{1F525} ${g[c.type]||"\xB7"} **${c.type||"note"}**${m}: ${w}`)}a.push("")}return i.length===0&&p.length===0&&a.push('_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._'),a.push(f),a.join(`
13
- `)}function P(e){const n=k(_(e)),t=N(e,n),r=i=>String(i).replace(/\\/g,"/"),s=new Set(n.targets.map(r)),o=[];for(const i of x){const p=d.join(e,i);try{if(s.has(r(i))){const u=S(p,t);o.push({rel:i,...u})}else T(p).stripped&&o.push({rel:i,stripped:!0})}catch(u){o.push({rel:i,error:u.message})}}return o}export{P as refreshRuleFilesFromMemory,k as resolveInjectionSettings,O as writeInitRuleFiles};
11
+ `+o;return l.writeFileSync(e,g,"utf8"),{created:!1,updated:!0}}const i=o.slice(0,r),p=o.slice(s+f.length),u=i+n+p;return u===o?{created:!1,updated:!1}:(l.writeFileSync(e,u,"utf8"),{created:!1,updated:!0})}function $(e){const n=T(),t=[];for(const o of x){const r=d.join(e,o);try{const s=S(r,n);t.push({rel:o,...s})}catch(s){t.push({rel:o,error:s.message})}}return t}function D(e){return j(e)}function M(e,n=10){try{return I(`git log --pretty=format:"%h%x09%ad%x09%s" --date=short -n ${n}`,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).split(`
12
+ `).filter(Boolean).map(o=>{const[r,s,i]=o.split(" ");return{hash:(r||"").slice(0,7),date:s||"",subject:i||""}})}catch{return[]}}function R(e,n={}){const{maxEntries:t=b,maxCommits:o=A,maxEntryChars:r=C,includeProtocol:s=!0}=n,i=D(e),p=M(e,o);i.sort((c,m)=>{const h=typeof c.ts=="number"?c.ts:Date.parse(c.ts||0);return(typeof m.ts=="number"?m.ts:Date.parse(m.ts||0))-h});const u=i.slice(0,t),g={gotcha:"\u26A0",decision:"\u2713",attempt:"\u2717",note:"\xB7",detection:"\u25CB",pattern:"\u25C7"},a=[];if(a.push(y),a.push("<!-- Auto-managed by infernoflow. Don't edit between these markers. -->"),a.push("## Project memory (infernoflow)"),a.push(""),s&&(a.push(E()),a.push("")),p.length>0){a.push("### Recent commits");for(const c of p)a.push(`- \`${c.hash}\` _${c.date}_ ${c.subject}`);a.push("")}if(u.length>0){a.push("### Recent memory");for(const c of u){const m=c.file?` (\`${c.file}${c.line?":"+c.line:""}\`)`:"",h=(c.msg||c.summary||"").replace(/\n/g," "),w=r&&h.length>r?h.slice(0,r).trimEnd()+"\u2026":h;a.push(`- \u{1F525} ${g[c.type]||"\xB7"} **${c.type||"note"}**${m}: ${w}`)}a.push("")}return i.length===0&&p.length===0&&a.push('_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._'),a.push(f),a.join(`
13
+ `)}function P(e){const n=v(_(e)),t=R(e,n),o=i=>String(i).replace(/\\/g,"/"),r=new Set(n.targets.map(o)),s=[];for(const i of x){const p=d.join(e,i);try{if(r.has(o(i))){const u=S(p,t);s.push({rel:i,...u})}else k(p).stripped&&s.push({rel:i,stripped:!0})}catch(u){s.push({rel:i,error:u.message})}}return s}export{P as refreshRuleFilesFromMemory,v as resolveInjectionSettings,$ as writeInitRuleFiles};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infernoflow",
3
- "version": "0.44.7",
3
+ "version": "0.44.9",
4
4
  "description": "Persistent memory for AI coding sessions — captures what agents can't infer from code alone. Works with Copilot, Cursor, Claude, and Windsurf.",
5
5
  "type": "module",
6
6
  "bin": {