Simplify context display to type-only legend with color dots

Changes:
- Updated legend to show only observation types (bugfix, feature, refactor, change, discovery, decision)
- Mapped each type to a color dot emoji (🔴 bugfix, 🟢 feature, 🔵 refactor,  change, 🟡 discovery, 🟤 decision)
- Removed concept-based filtering and icon selection
- Simplified progressive disclosure instructions to reference types instead of concepts
- All observations now shown in timeline (no concept filtering)

Technical details:
- Modified: src/hooks/context-hook.ts:203-207 (legend)
- Modified: src/hooks/context-hook.ts:210-223 (progressive disclosure text)
- Modified: src/hooks/context-hook.ts:344-369 (icon mapping switched from concepts to types)
- Modified: src/hooks/context-hook.ts:168-173 (removed concept filtering)
- Rebuilt: plugin/scripts/context-hook.js

Rationale: Types are mutually exclusive and core to categorization, while concepts are multi-select metadata better accessed through MCP search tools. This simplifies the display and reduces visual noise.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-11-03 14:25:35 -05:00
parent 02130c49d1
commit c6bf72ca72
6 changed files with 128 additions and 177 deletions
+13 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import G from"path";import{stdin as P}from"process";import ce from"better-sqlite3";import{join as E,dirname as ne,basename as Se}from"path";import{homedir as j}from"os";import{existsSync as Ie,mkdirSync as ie}from"fs";import{fileURLToPath as oe}from"url";function ae(){return typeof __dirname<"u"?__dirname:ne(oe(import.meta.url))}var de=ae(),N=process.env.CLAUDE_MEM_DATA_DIR||E(j(),".claude-mem"),U=process.env.CLAUDE_CONFIG_DIR||E(j(),".claude"),ve=E(N,"archives"),Ae=E(N,"logs"),ye=E(N,"trash"),Ce=E(N,"backups"),De=E(N,"settings.json"),Y=E(N,"claude-mem.db"),ke=E(N,"vector-db"),xe=E(U,"settings.json"),we=E(U,"commands"),Ue=E(U,"CLAUDE.md");function V(a){ie(a,{recursive:!0})}function K(){return E(de,"..","..")}var $=(i=>(i[i.DEBUG=0]="DEBUG",i[i.INFO=1]="INFO",i[i.WARN=2]="WARN",i[i.ERROR=3]="ERROR",i[i.SILENT=4]="SILENT",i))($||{}),M=class{level;useColor;constructor(){let e=process.env.CLAUDE_MEM_LOG_LEVEL?.toUpperCase()||"INFO";this.level=$[e]??1,this.useColor=process.stdout.isTTY??!1}correlationId(e,t){return`obs-${e}-${t}`}sessionId(e){return`session-${e}`}formatData(e){if(e==null)return"";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="object"){if(e instanceof Error)return this.level===0?`${e.message}
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?JSON.stringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;try{let s=typeof t=="string"?JSON.parse(t):t;if(e==="Bash"&&s.command){let r=s.command.length>50?s.command.substring(0,50)+"...":s.command;return`${e}(${r})`}if(e==="Read"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}if(e==="Edit"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}if(e==="Write"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}return e}catch{return e}}log(e,t,s,r,i){if(e<this.level)return;let d=new Date().toISOString().replace("T"," ").substring(0,23),p=$[e].padEnd(5),u=t.padEnd(6),R="";r?.correlationId?R=`[${r.correlationId}] `:r?.sessionId&&(R=`[session-${r.sessionId}] `);let g="";i!=null&&(this.level===0&&typeof i=="object"?g=`
`+JSON.stringify(i,null,2):g=" "+this.formatData(i));let n="";if(r){let{sessionId:h,sdkSessionId:k,correlationId:L,...C}=r;Object.keys(C).length>0&&(n=` {${Object.entries(C).map(([c,m])=>`${c}=${m}`).join(", ")}}`)}let I=`[${d}] [${p}] [${u}] ${R}${s}${n}${g}`;e===3?console.error(I):console.log(I)}debug(e,t,s,r){this.log(0,e,t,s,r)}info(e,t,s,r){this.log(1,e,t,s,r)}warn(e,t,s,r){this.log(2,e,t,s,r)}error(e,t,s,r){this.log(3,e,t,s,r)}dataIn(e,t,s,r){this.info(e,`\u2192 ${t}`,s,r)}dataOut(e,t,s,r){this.info(e,`\u2190 ${t}`,s,r)}success(e,t,s,r){this.info(e,`\u2713 ${t}`,s,r)}failure(e,t,s,r){this.error(e,`\u2717 ${t}`,s,r)}timing(e,t,s,r){this.info(e,`\u23F1 ${t}`,r,{duration:`${s}ms`})}},q=new M;var D=class{db;constructor(){V(N),this.db=new ce(Y),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.initializeSchema(),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields(),this.makeObservationsTextNullable(),this.createUserPromptsTable()}initializeSchema(){try{this.db.exec(`
import F from"path";import{stdin as X}from"process";import ae from"better-sqlite3";import{join as T,dirname as te,basename as be}from"path";import{homedir as W}from"os";import{existsSync as Oe,mkdirSync as re}from"fs";import{fileURLToPath as ne}from"url";function ie(){return typeof __dirname<"u"?__dirname:te(ne(import.meta.url))}var oe=ie(),b=process.env.CLAUDE_MEM_DATA_DIR||T(W(),".claude-mem"),x=process.env.CLAUDE_CONFIG_DIR||T(W(),".claude"),Le=T(b,"archives"),ve=T(b,"logs"),Ae=T(b,"trash"),ye=T(b,"backups"),Ce=T(b,"settings.json"),H=T(b,"claude-mem.db"),De=T(b,"vector-db"),ke=T(x,"settings.json"),xe=T(x,"commands"),Ue=T(x,"CLAUDE.md");function j(a){re(a,{recursive:!0})}function Y(){return T(oe,"..","..")}var U=(i=>(i[i.DEBUG=0]="DEBUG",i[i.INFO=1]="INFO",i[i.WARN=2]="WARN",i[i.ERROR=3]="ERROR",i[i.SILENT=4]="SILENT",i))(U||{}),$=class{level;useColor;constructor(){let e=process.env.CLAUDE_MEM_LOG_LEVEL?.toUpperCase()||"INFO";this.level=U[e]??1,this.useColor=process.stdout.isTTY??!1}correlationId(e,t){return`obs-${e}-${t}`}sessionId(e){return`session-${e}`}formatData(e){if(e==null)return"";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="object"){if(e instanceof Error)return this.level===0?`${e.message}
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?JSON.stringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;try{let s=typeof t=="string"?JSON.parse(t):t;if(e==="Bash"&&s.command){let r=s.command.length>50?s.command.substring(0,50)+"...":s.command;return`${e}(${r})`}if(e==="Read"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}if(e==="Edit"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}if(e==="Write"&&s.file_path){let r=s.file_path.split("/").pop()||s.file_path;return`${e}(${r})`}return e}catch{return e}}log(e,t,s,r,i){if(e<this.level)return;let d=new Date().toISOString().replace("T"," ").substring(0,23),p=U[e].padEnd(5),u=t.padEnd(6),S="";r?.correlationId?S=`[${r.correlationId}] `:r?.sessionId&&(S=`[session-${r.sessionId}] `);let h="";i!=null&&(this.level===0&&typeof i=="object"?h=`
`+JSON.stringify(i,null,2):h=" "+this.formatData(i));let n="";if(r){let{sessionId:P,sdkSessionId:C,correlationId:R,...A}=r;Object.keys(A).length>0&&(n=` {${Object.entries(A).map(([c,l])=>`${c}=${l}`).join(", ")}}`)}let v=`[${d}] [${p}] [${u}] ${S}${s}${n}${h}`;e===3?console.error(v):console.log(v)}debug(e,t,s,r){this.log(0,e,t,s,r)}info(e,t,s,r){this.log(1,e,t,s,r)}warn(e,t,s,r){this.log(2,e,t,s,r)}error(e,t,s,r){this.log(3,e,t,s,r)}dataIn(e,t,s,r){this.info(e,`\u2192 ${t}`,s,r)}dataOut(e,t,s,r){this.info(e,`\u2190 ${t}`,s,r)}success(e,t,s,r){this.info(e,`\u2713 ${t}`,s,r)}failure(e,t,s,r){this.error(e,`\u2717 ${t}`,s,r)}timing(e,t,s,r){this.info(e,`\u23F1 ${t}`,r,{duration:`${s}ms`})}},V=new $;var y=class{db;constructor(){j(b),this.db=new ae(H),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.initializeSchema(),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields(),this.makeObservationsTextNullable(),this.createUserPromptsTable()}initializeSchema(){try{this.db.exec(`
CREATE TABLE IF NOT EXISTS schema_versions (
id INTEGER PRIMARY KEY,
version INTEGER UNIQUE NOT NULL,
@@ -265,7 +265,7 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
UPDATE sdk_sessions
SET sdk_session_id = ?
WHERE id = ? AND sdk_session_id IS NULL
`).run(t,e).changes===0?(q.debug("DB","sdk_session_id already set, skipping update",{sessionId:e,sdkSessionId:t}),!1):!0}setWorkerPort(e,t){this.db.prepare(`
`).run(t,e).changes===0?(V.debug("DB","sdk_session_id already set, skipping update",{sessionId:e,sdkSessionId:t}),!1):!0}setWorkerPort(e,t){this.db.prepare(`
UPDATE sdk_sessions
SET worker_port = ?
WHERE id = ?
@@ -284,23 +284,23 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
INSERT INTO sdk_sessions
(claude_session_id, sdk_session_id, project, started_at, started_at_epoch, status)
VALUES (?, ?, ?, ?, ?, 'active')
`).run(e,e,t,i.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`));let g=this.db.prepare(`
`).run(e,e,t,i.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`));let h=this.db.prepare(`
INSERT INTO observations
(sdk_session_id, project, type, title, subtitle, facts, narrative, concepts,
files_read, files_modified, prompt_number, created_at, created_at_epoch)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(e,t,s.type,s.title,s.subtitle,JSON.stringify(s.facts),s.narrative,JSON.stringify(s.concepts),JSON.stringify(s.files_read),JSON.stringify(s.files_modified),r||null,i.toISOString(),d);return{id:Number(g.lastInsertRowid),createdAtEpoch:d}}storeSummary(e,t,s,r){let i=new Date,d=i.getTime();this.db.prepare(`
`).run(e,t,s.type,s.title,s.subtitle,JSON.stringify(s.facts),s.narrative,JSON.stringify(s.concepts),JSON.stringify(s.files_read),JSON.stringify(s.files_modified),r||null,i.toISOString(),d);return{id:Number(h.lastInsertRowid),createdAtEpoch:d}}storeSummary(e,t,s,r){let i=new Date,d=i.getTime();this.db.prepare(`
SELECT id FROM sdk_sessions WHERE sdk_session_id = ?
`).get(e)||(this.db.prepare(`
INSERT INTO sdk_sessions
(claude_session_id, sdk_session_id, project, started_at, started_at_epoch, status)
VALUES (?, ?, ?, ?, ?, 'active')
`).run(e,e,t,i.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`));let g=this.db.prepare(`
`).run(e,e,t,i.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`));let h=this.db.prepare(`
INSERT INTO session_summaries
(sdk_session_id, project, request, investigated, learned, completed,
next_steps, notes, prompt_number, created_at, created_at_epoch)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(e,t,s.request,s.investigated,s.learned,s.completed,s.next_steps,s.notes,r||null,i.toISOString(),d);return{id:Number(g.lastInsertRowid),createdAtEpoch:d}}markSessionCompleted(e){let t=new Date,s=t.getTime();this.db.prepare(`
`).run(e,t,s.request,s.investigated,s.learned,s.completed,s.next_steps,s.notes,r||null,i.toISOString(),d);return{id:Number(h.lastInsertRowid),createdAtEpoch:d}}markSessionCompleted(e){let t=new Date,s=t.getTime();this.db.prepare(`
UPDATE sdk_sessions
SET status = 'completed', completed_at = ?, completed_at_epoch = ?
WHERE id = ?
@@ -312,7 +312,7 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
UPDATE sdk_sessions
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
WHERE status = 'active'
`).run(e.toISOString(),t).changes}close(){this.db.close()}};import X from"path";import{existsSync as F}from"fs";import{spawn as pe}from"child_process";var ue=parseInt(process.env.CLAUDE_MEM_WORKER_PORT||"37777",10),le=`http://127.0.0.1:${ue}/health`;async function J(){try{return(await fetch(le,{signal:AbortSignal.timeout(500)})).ok}catch{return!1}}async function Q(){try{if(await J())return!0;console.error("[claude-mem] Worker not responding, starting...");let a=K(),e=X.join(a,"plugin","scripts","worker-service.cjs");if(!F(e))return console.error(`[claude-mem] Worker service not found at ${e}`),!1;let t=X.join(a,"ecosystem.config.cjs"),s=X.join(a,"node_modules",".bin","pm2");if(!F(s))throw new Error(`PM2 binary not found at ${s}. This is a bundled dependency - try running: npm install`);if(!F(t))throw new Error(`PM2 ecosystem config not found at ${t}. Plugin installation may be corrupted.`);let r=pe(s,["start",t],{detached:!0,stdio:"ignore",cwd:a});r.on("error",i=>{throw new Error(`Failed to spawn PM2: ${i.message}`)}),r.unref(),console.error("[claude-mem] Worker started with PM2");for(let i=0;i<3;i++)if(await new Promise(d=>setTimeout(d,500)),await J())return console.error("[claude-mem] Worker is healthy"),!0;return console.error("[claude-mem] Worker failed to become healthy after startup"),!1}catch(a){return console.error(`[claude-mem] Failed to start worker: ${a.message}`),!1}}var me=parseInt(process.env.CLAUDE_MEM_CONTEXT_OBSERVATIONS||"50",10),z=10,o={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"};function B(a){if(!a)return[];let e=JSON.parse(a);return Array.isArray(e)?e:[]}function _e(a){return new Date(a).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0})}function Ee(a){return new Date(a).toLocaleString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0})}function Te(a){return new Date(a).toLocaleString("en-US",{month:"short",day:"numeric",year:"numeric"})}function he(a){return a?Math.ceil(a.length/4):0}function ge(a,e){return G.isAbsolute(a)?G.relative(e,a):a}function Z(a,e=!1,t=!1){Q();let s=a?.cwd??process.cwd(),r=s?G.basename(s):"unknown-project",i=new D,d=i.db.prepare(`
`).run(e.toISOString(),t).changes}close(){this.db.close()}};import w from"path";import{existsSync as M}from"fs";import{spawn as de}from"child_process";var ce=parseInt(process.env.CLAUDE_MEM_WORKER_PORT||"37777",10),pe=`http://127.0.0.1:${ce}/health`;async function K(){try{return(await fetch(pe,{signal:AbortSignal.timeout(500)})).ok}catch{return!1}}async function q(){try{if(await K())return!0;console.error("[claude-mem] Worker not responding, starting...");let a=Y(),e=w.join(a,"plugin","scripts","worker-service.cjs");if(!M(e))return console.error(`[claude-mem] Worker service not found at ${e}`),!1;let t=w.join(a,"ecosystem.config.cjs"),s=w.join(a,"node_modules",".bin","pm2");if(!M(s))throw new Error(`PM2 binary not found at ${s}. This is a bundled dependency - try running: npm install`);if(!M(t))throw new Error(`PM2 ecosystem config not found at ${t}. Plugin installation may be corrupted.`);let r=de(s,["start",t],{detached:!0,stdio:"ignore",cwd:a});r.on("error",i=>{throw new Error(`Failed to spawn PM2: ${i.message}`)}),r.unref(),console.error("[claude-mem] Worker started with PM2");for(let i=0;i<3;i++)if(await new Promise(d=>setTimeout(d,500)),await K())return console.error("[claude-mem] Worker is healthy"),!0;return console.error("[claude-mem] Worker failed to become healthy after startup"),!1}catch(a){return console.error(`[claude-mem] Failed to start worker: ${a.message}`),!1}}var ue=parseInt(process.env.CLAUDE_MEM_CONTEXT_OBSERVATIONS||"50",10),J=10,o={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"};function me(a){if(!a)return[];let e=JSON.parse(a);return Array.isArray(e)?e:[]}function le(a){return new Date(a).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0})}function _e(a){return new Date(a).toLocaleString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0})}function Ee(a){return new Date(a).toLocaleString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Te(a){return a?Math.ceil(a.length/4):0}function he(a,e){return F.isAbsolute(a)?F.relative(e,a):a}function Q(a,e=!1,t=!1){q();let s=a?.cwd??process.cwd(),r=s?F.basename(s):"unknown-project",i=new y,d=i.db.prepare(`
SELECT
id, sdk_session_id, type, title, subtitle, narrative,
facts, concepts, files_read, files_modified,
@@ -321,18 +321,18 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
WHERE project = ?
ORDER BY created_at_epoch DESC
LIMIT ?
`).all(r,me),p=i.db.prepare(`
`).all(r,ue),p=i.db.prepare(`
SELECT id, sdk_session_id, request, completed, next_steps, created_at, created_at_epoch
FROM session_summaries
WHERE project = ?
ORDER BY created_at_epoch DESC
LIMIT ?
`).all(r,z+1);if(d.length===0&&p.length===0)return i.close(),e?`
`).all(r,J+1);if(d.length===0&&p.length===0)return i.close(),e?`
${o.bright}${o.cyan}\u{1F4DD} [${r}] recent context${o.reset}
${o.gray}${"\u2500".repeat(60)}${o.reset}
${o.dim}No previous sessions found for this project yet.${o.reset}
`:`# [${r}] recent context
No previous sessions found for this project yet.`;let u=d,R=p.slice(0,z),g=u.filter(I=>{let h=B(I.concepts);return h.includes("what-changed")||h.includes("how-it-works")||h.includes("problem-solution")||h.includes("gotcha")||h.includes("discovery")||h.includes("why-it-exists")||h.includes("decision")||h.includes("trade-off")}),n=[];if(e?(n.push(""),n.push(`${o.bright}${o.cyan}\u{1F4DD} [${r}] recent context${o.reset}`),n.push(`${o.gray}${"\u2500".repeat(60)}${o.reset}`),n.push("")):(n.push(`# [${r}] recent context`),n.push("")),g.length>0){e?(n.push(`${o.dim}Legend: \u{1F3AF} session-request | \u{1F534} gotcha | \u{1F7E1} problem-solution | \u{1F535} how-it-works | \u{1F7E2} what-changed | \u{1F7E3} discovery | \u{1F7E0} why-it-exists | \u{1F7E4} decision | \u2696\uFE0F trade-off${o.reset}`),n.push("")):(n.push("**Legend:** \u{1F3AF} session-request | \u{1F534} gotcha | \u{1F7E1} problem-solution | \u{1F535} how-it-works | \u{1F7E2} what-changed | \u{1F7E3} discovery | \u{1F7E0} why-it-exists | \u{1F7E4} decision | \u2696\uFE0F trade-off"),n.push("")),e?(n.push(`${o.dim}\u{1F4A1} Progressive Disclosure: This index shows WHAT exists (titles) and retrieval COST (token counts).${o.reset}`),n.push(`${o.dim} \u2192 Use MCP search tools to fetch full observation details on-demand (Layer 2)${o.reset}`),n.push(`${o.dim} \u2192 Prefer searching observations over re-reading code for past decisions and learnings${o.reset}`),n.push(`${o.dim} \u2192 Critical types (\u{1F534} gotcha, \u{1F7E4} decision, \u2696\uFE0F trade-off) often worth fetching immediately${o.reset}`),n.push("")):(n.push("\u{1F4A1} **Progressive Disclosure:** This index shows WHAT exists (titles) and retrieval COST (token counts)."),n.push("- Use MCP search tools to fetch full observation details on-demand (Layer 2)"),n.push("- Prefer searching observations over re-reading code for past decisions and learnings"),n.push("- Critical types (\u{1F534} gotcha, \u{1F7E4} decision, \u2696\uFE0F trade-off) often worth fetching immediately"),n.push(""));let I=p[0]?.id,h=R.map((c,m)=>{let l=m===0?null:p[m+1];return{...c,displayEpoch:l?l.created_at_epoch:c.created_at_epoch,displayTime:l?l.created_at:c.created_at,isMostRecent:c.id===I}}),k=[...g.map(c=>({type:"observation",data:c})),...h.map(c=>({type:"summary",data:c}))];k.sort((c,m)=>{let l=c.type==="observation"?c.data.created_at_epoch:c.data.displayEpoch,O=m.type==="observation"?m.data.created_at_epoch:m.data.displayEpoch;return l-O});let L=new Map;for(let c of k){let m=c.type==="observation"?c.data.created_at:c.data.displayTime,l=Te(m);L.has(l)||L.set(l,[]),L.get(l).push(c)}let C=Array.from(L.entries()).sort((c,m)=>{let l=new Date(c[0]).getTime(),O=new Date(m[0]).getTime();return l-O});for(let[c,m]of C){e?(n.push(`${o.bright}${o.cyan}${c}${o.reset}`),n.push("")):(n.push(`### ${c}`),n.push(""));let l=null,O="",v=!1;for(let x of m)if(x.type==="summary"){v&&(n.push(""),v=!1,l=null,O="");let _=x.data,A=`${_.request||"Session started"} (${_e(_.displayTime)})`,S=_.isMostRecent?"":`claude-mem://session-summary/${_.id}`;if(e){let T=S?`${o.dim}[${S}]${o.reset}`:"";n.push(`\u{1F3AF} ${o.yellow}#S${_.id}${o.reset} ${A} ${T}`)}else{let T=S?` [\u2192](${S})`:"";n.push(`**\u{1F3AF} #S${_.id}** ${A}${T}`)}n.push("")}else{let _=x.data,A=B(_.files_modified),S=A.length>0?ge(A[0],s):"General";S!==l&&(v&&n.push(""),e?n.push(`${o.dim}${S}${o.reset}`):n.push(`**${S}**`),e||(n.push("| ID | Time | T | Title | Tokens |"),n.push("|----|------|---|-------|--------|")),l=S,v=!0,O="");let T=B(_.concepts),b="\u2022";T.includes("gotcha")?b="\u{1F534}":T.includes("decision")?b="\u{1F7E4}":T.includes("trade-off")?b="\u2696\uFE0F":T.includes("problem-solution")?b="\u{1F7E1}":T.includes("discovery")?b="\u{1F7E3}":T.includes("why-it-exists")?b="\u{1F7E0}":T.includes("how-it-works")?b="\u{1F535}":T.includes("what-changed")&&(b="\u{1F7E2}");let y=Ee(_.created_at),W=_.title||"Untitled",w=he(_.narrative),H=y!==O,se=H?y:"";if(O=y,e){let te=H?`${o.dim}${y}${o.reset}`:" ".repeat(y.length),re=w>0?`${o.dim}(~${w}t)${o.reset}`:"";n.push(` ${o.dim}#${_.id}${o.reset} ${te} ${b} ${W} ${re}`)}else n.push(`| #${_.id} | ${se||"\u2033"} | ${b} | ${W} | ~${w} |`)}v&&n.push("")}let f=p[0];f&&(f.completed||f.next_steps)&&(f.completed&&(e?n.push(`${o.green}Completed:${o.reset} ${f.completed}`):n.push(`**Completed**: ${f.completed}`),n.push("")),f.next_steps&&(e?n.push(`${o.magenta}Next Steps:${o.reset} ${f.next_steps}`):n.push(`**Next Steps**: ${f.next_steps}`),n.push(""))),e?n.push(`${o.dim}Use claude-mem MCP search to access records with the given ID${o.reset}`):n.push("*Use claude-mem MCP search to access records with the given ID*")}return i.close(),n.join(`
`).trimEnd()}var ee=process.argv.includes("--index"),fe=process.argv.includes("--colors");if(P.isTTY||fe){let a=Z(void 0,!0,ee);console.log(a),process.exit(0)}else{let a="";P.on("data",e=>a+=e),P.on("end",()=>{let e=a.trim()?JSON.parse(a):void 0,s={hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:Z(e,!1,ee)}};console.log(JSON.stringify(s)),process.exit(0)})}
No previous sessions found for this project yet.`;let u=d,S=p.slice(0,J),h=u,n=[];if(e?(n.push(""),n.push(`${o.bright}${o.cyan}\u{1F4DD} [${r}] recent context${o.reset}`),n.push(`${o.gray}${"\u2500".repeat(60)}${o.reset}`),n.push("")):(n.push(`# [${r}] recent context`),n.push("")),h.length>0){e?(n.push(`${o.dim}Legend: \u{1F3AF} session-request | \u{1F534} bugfix | \u{1F7E2} feature | \u{1F535} refactor | \u26AA change | \u{1F7E1} discovery | \u{1F7E4} decision${o.reset}`),n.push("")):(n.push("**Legend:** \u{1F3AF} session-request | \u{1F534} bugfix | \u{1F7E2} feature | \u{1F535} refactor | \u26AA change | \u{1F7E1} discovery | \u{1F7E4} decision"),n.push("")),e?(n.push(`${o.dim}\u{1F4A1} Progressive Disclosure: This index shows WHAT exists (titles) and retrieval COST (token counts).${o.reset}`),n.push(`${o.dim} \u2192 Use MCP search tools to fetch full observation details on-demand (Layer 2)${o.reset}`),n.push(`${o.dim} \u2192 Prefer searching observations over re-reading code for past decisions and learnings${o.reset}`),n.push(`${o.dim} \u2192 Critical types (\u{1F534} bugfix, \u{1F7E4} decision) often worth fetching immediately${o.reset}`),n.push("")):(n.push("\u{1F4A1} **Progressive Disclosure:** This index shows WHAT exists (titles) and retrieval COST (token counts)."),n.push("- Use MCP search tools to fetch full observation details on-demand (Layer 2)"),n.push("- Prefer searching observations over re-reading code for past decisions and learnings"),n.push("- Critical types (\u{1F534} bugfix, \u{1F7E4} decision) often worth fetching immediately"),n.push(""));let v=p[0]?.id,P=S.map((c,l)=>{let m=l===0?null:p[l+1];return{...c,displayEpoch:m?m.created_at_epoch:c.created_at_epoch,displayTime:m?m.created_at:c.created_at,isMostRecent:c.id===v}}),C=[...h.map(c=>({type:"observation",data:c})),...P.map(c=>({type:"summary",data:c}))];C.sort((c,l)=>{let m=c.type==="observation"?c.data.created_at_epoch:c.data.displayEpoch,N=l.type==="observation"?l.data.created_at_epoch:l.data.displayEpoch;return m-N});let R=new Map;for(let c of C){let l=c.type==="observation"?c.data.created_at:c.data.displayTime,m=Ee(l);R.has(m)||R.set(m,[]),R.get(m).push(c)}let A=Array.from(R.entries()).sort((c,l)=>{let m=new Date(c[0]).getTime(),N=new Date(l[0]).getTime();return m-N});for(let[c,l]of A){e?(n.push(`${o.bright}${o.cyan}${c}${o.reset}`),n.push("")):(n.push(`### ${c}`),n.push(""));let m=null,N="",O=!1;for(let D of l)if(D.type==="summary"){O&&(n.push(""),O=!1,m=null,N="");let _=D.data,I=`${_.request||"Session started"} (${le(_.displayTime)})`,f=_.isMostRecent?"":`claude-mem://session-summary/${_.id}`;if(e){let E=f?`${o.dim}[${f}]${o.reset}`:"";n.push(`\u{1F3AF} ${o.yellow}#S${_.id}${o.reset} ${I} ${E}`)}else{let E=f?` [\u2192](${f})`:"";n.push(`**\u{1F3AF} #S${_.id}** ${I}${E}`)}n.push("")}else{let _=D.data,I=me(_.files_modified),f=I.length>0?he(I[0],s):"General";f!==m&&(O&&n.push(""),e?n.push(`${o.dim}${f}${o.reset}`):n.push(`**${f}**`),e||(n.push("| ID | Time | T | Title | Tokens |"),n.push("|----|------|---|-------|--------|")),m=f,O=!0,N="");let E="\u2022";switch(_.type){case"bugfix":E="\u{1F534}";break;case"feature":E="\u{1F7E2}";break;case"refactor":E="\u{1F535}";break;case"change":E="\u26AA";break;case"discovery":E="\u{1F7E1}";break;case"decision":E="\u{1F7E4}";break;default:E="\u2022"}let L=_e(_.created_at),B=_.title||"Untitled",k=Te(_.narrative),G=L!==N,Z=G?L:"";if(N=L,e){let ee=G?`${o.dim}${L}${o.reset}`:" ".repeat(L.length),se=k>0?`${o.dim}(~${k}t)${o.reset}`:"";n.push(` ${o.dim}#${_.id}${o.reset} ${ee} ${E} ${B} ${se}`)}else n.push(`| #${_.id} | ${Z||"\u2033"} | ${E} | ${B} | ~${k} |`)}O&&n.push("")}let g=p[0];g&&(g.completed||g.next_steps)&&(g.completed&&(e?n.push(`${o.green}Completed:${o.reset} ${g.completed}`):n.push(`**Completed**: ${g.completed}`),n.push("")),g.next_steps&&(e?n.push(`${o.magenta}Next Steps:${o.reset} ${g.next_steps}`):n.push(`**Next Steps**: ${g.next_steps}`),n.push(""))),e?n.push(`${o.dim}Use claude-mem MCP search to access records with the given ID${o.reset}`):n.push("*Use claude-mem MCP search to access records with the given ID*")}return i.close(),n.join(`
`).trimEnd()}var z=process.argv.includes("--index"),ge=process.argv.includes("--colors");if(X.isTTY||ge){let a=Q(void 0,!0,z);console.log(a),process.exit(0)}else{let a="";X.on("data",e=>a+=e),X.on("end",()=>{let e=a.trim()?JSON.parse(a):void 0,s={hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:Q(e,!1,z)}};console.log(JSON.stringify(s)),process.exit(0)})}