slopie 1.6.2 → 1.7.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../core/src/analytics/native-pool.ts", "../../core/src/analytics/native-stream.ts", "../../core/src/parser/content.ts", "../../core/src/markers.ts", "../../core/src/memory/source-identity.ts", "../../core/src/analytics/source.ts", "../../core/src/redact.ts", "../../core/src/theme.ts", "../../core/src/redact-rules.ts", "../../core/src/redact-elide.ts", "../../core/src/analytics/native-metadata-projection.ts", "../../core/src/analytics/native-usage.ts", "../../core/src/ignore.ts", "../src/audit-native-worker.ts"],
4
+ "sourcesContent": ["import {Worker,parentPort} from 'node:worker_threads';\nimport {serialize,deserialize} from 'node:v8';\nimport {createHash} from 'node:crypto';\nimport {streamNativeFacts,type StreamedNative} from './native-stream.js';\nimport {sourceId} from '../memory/source-identity.js';\nimport {isIgnoredProject} from '../ignore.js';\nexport interface NativeScanPolicy {authorityCommitment:string;ignoredProjects:readonly string[];forgottenSourceIds:readonly string[];project:string|null;eventFrom:string|null;asOf:string|null;}\nexport interface NativeScanJob {jobId:string;ordinal:number;file:string;harness:'claude'|'codex'|'pi';bytes:number;stamp:{dev:string;ino:string;size:number;mtimeNs:string;ctimeNs:string};maxBytes:number;maxRecords?:number;maxPromptBytes:number;policy:NativeScanPolicy;}\nexport interface NativeScanExecutor {scan(job:NativeScanJob,signal:AbortSignal):Promise<StreamedNative>;close():Promise<void>;}\nconst PROTOCOL='audit-native-v1',FRAME=1024*1024;\nconst code=(error:unknown)=>error instanceof Error&&/^(?:[a-z][a-z0-9_]{0,95})$/.test(error.message)?error.message:'native_worker_failed';\ninterface Pending {job:NativeScanJob;signal:AbortSignal;resolve:(v:StreamedNative)=>void;reject:(e:Error)=>void;remove:()=>void;}\ninterface Slot {worker:Worker;ready:boolean;pending:Pending|null;frames:Buffer[];bytes:number;next:number;}\n/** Two owned parser threads; policy authority and ordered aggregation stay in the caller. */\nexport function createNativeScanPool(entry:URL|string,options:{workers?:1|2;maxActiveBytes?:number;maxResultBytes?:number;maxRssBytes?:number}={}):NativeScanExecutor {\n const count=options.workers??2,maxActive=options.maxActiveBytes??256*1024*1024,maxResult=options.maxResultBytes??256*1024*1024,maxRss=options.maxRssBytes??1280*1024*1024;if(![1,2].includes(count)||![maxActive,maxResult,maxRss].every(n=>Number.isSafeInteger(n)&&n>0))throw new Error('native_pool_options_invalid');\n const slots:Slot[]=[],queue:Pending[]=[];let closed=false,failure:string|null=null,activeBytes=0;const terminations:Promise<unknown>[]=[];\n const rejectAll=(reason:string)=>{if(closed)return;failure=reason;closed=true;for(const pending of queue.splice(0)){pending.remove();pending.reject(new Error(reason));}for(const slot of slots){const pending=slot.pending;slot.pending=null;slot.frames=[];if(pending){pending.remove();pending.reject(new Error(reason));}terminations.push(slot.worker.terminate().catch(()=>undefined));}activeBytes=0;clearInterval(monitor);};\n const dispatch=()=>{if(closed)return;for(const slot of slots){if(!slot.ready||slot.pending||!queue.length)continue;const next=queue[0]!;if(next.signal.aborted){queue.shift();next.remove();next.reject(new Error('cancelled'));continue;}if(activeBytes>0&&activeBytes+next.job.bytes>maxActive)continue;queue.shift();slot.pending=next;slot.frames=[];slot.bytes=0;slot.next=0;activeBytes+=next.job.bytes;slot.worker.postMessage({protocol:PROTOCOL,kind:'scan',job:next.job,maxResultBytes:maxResult});}};\n const monitor=setInterval(()=>{if(!closed&&process.memoryUsage().rss>maxRss)rejectAll('native_pool_memory_limit');},250);monitor.unref();\n for(let i=0;i<count;i++){\n const worker=new Worker(entry,{resourceLimits:{maxOldGenerationSizeMb:384},stdout:true,stderr:true}),slot:Slot={worker,ready:false,pending:null,frames:[],bytes:0,next:0};slots.push(slot);worker.stdout?.resume();worker.stderr?.resume();\n worker.on('message',(message:unknown)=>{if(closed||!message||typeof message!=='object')return;const m=message as Record<string,unknown>;if(m.protocol!==PROTOCOL){rejectAll('native_worker_protocol_invalid');return;}if(m.kind==='ready'){slot.ready=true;dispatch();return;}const pending=slot.pending;if(!pending||m.jobId!==pending.job.jobId)return;\n if(m.kind==='frame'){if(m.sequence!==slot.next++||!(m.data instanceof Uint8Array)||m.data.byteLength>FRAME||slot.bytes+m.data.byteLength>maxResult){rejectAll('native_pool_result_bytes_limit');return;}const bytes=Buffer.from(m.data.buffer,m.data.byteOffset,m.data.byteLength);slot.frames.push(bytes);slot.bytes+=bytes.length;return;}\n if(m.kind==='result'||m.kind==='error'){slot.pending=null;activeBytes-=pending.job.bytes;pending.remove();if(m.kind==='error'){slot.frames=[];pending.reject(new Error(typeof m.code==='string'&&/^[a-z][a-z0-9_]{0,95}$/.test(m.code)?m.code:'native_worker_failed'));dispatch();return;}\n try{if(m.authorityCommitment!==pending.job.policy.authorityCommitment||m.bytes!==slot.bytes||typeof m.hash!=='string')throw new Error('native_worker_result_invalid');const buffer=Buffer.concat(slot.frames,slot.bytes);slot.frames=[];if(createHash('sha256').update(buffer).digest('hex')!==m.hash)throw new Error('native_worker_result_invalid');const result=deserialize(buffer) as StreamedNative;if(!result||!Array.isArray(result.usage)||!Array.isArray(result.language)||!Array.isArray(result.facts?.events)||result.bytes!==pending.job.bytes||typeof result.hash!=='string')throw new Error('native_worker_result_invalid');if(pending.signal.aborted)throw new Error('cancelled');pending.resolve(result);}catch(error){pending.reject(new Error(code(error)));}dispatch();\n }\n });worker.on('error',()=>rejectAll('native_worker_failed'));worker.on('exit',()=>{if(!closed)rejectAll('native_worker_exited');});\n }\n return {scan(job,signal){if(!closed&&process.memoryUsage().rss>maxRss)rejectAll('native_pool_memory_limit');if(closed)return Promise.reject(new Error(failure??'native_pool_closed'));if(!Number.isSafeInteger(job.bytes)||job.bytes<0||job.bytes>job.maxBytes)return Promise.reject(new Error('native_usage_total_bytes_limit'));return new Promise((resolve,reject)=>{const abort=()=>rejectAll('cancelled'),pending:Pending={job,signal,resolve,reject,remove:()=>signal.removeEventListener('abort',abort)};signal.addEventListener('abort',abort,{once:true});if(signal.aborted){abort();reject(new Error('cancelled'));return;}queue.push(pending);dispatch();});},async close(){rejectAll('native_pool_closed');await Promise.allSettled(terminations);}};\n}\n/** Minimal published sidecar: no catalogue, semantic provider, UI or database work. */\nexport function runNativeScanWorker():void {\n if(!parentPort)throw new Error('native_worker_requires_port');const port=parentPort;let busy=false;\n port.on('message',async(message:{protocol?:string;kind?:string;job?:NativeScanJob;maxResultBytes?:number})=>{if(message.protocol!==PROTOCOL||message.kind!=='scan'||!message.job||busy)return;busy=true;const job=message.job;\n try{const policy=job.policy,forgotten=new Set(policy.forgottenSourceIds),accept=(project:string|null,time:string|null)=>!(project&&isIgnoredProject(project,policy.ignoredProjects))&&(!policy.project||project===policy.project)&&(!policy.eventFrom||time!==null&&time>=policy.eventFrom)&&(!policy.asOf||time!==null&&time<=policy.asOf);\n const snapshot=await streamNativeFacts(job.file,job.harness,{signal:new AbortController().signal,maxBytes:job.maxBytes,maxRecords:job.maxRecords,maxPromptBytes:job.maxPromptBytes,captureBytes:0,captureFileBytes:job.bytes,expectedIdentity:{dev:job.stamp.dev,ino:job.stamp.ino},sourceAllowed:(id,project)=>!forgotten.has(sourceId(job.harness,id))&&!(project&&isIgnoredProject(project,policy.ignoredProjects)),accept});\n const buffer=serialize(snapshot);if(buffer.length>(message.maxResultBytes??256*1024*1024))throw new Error('native_pool_result_bytes_limit');const hash=createHash('sha256').update(buffer).digest('hex');let sequence=0;for(let at=0;at<buffer.length;at+=FRAME){const chunk=Uint8Array.from(buffer.subarray(at,at+FRAME));port.postMessage({protocol:PROTOCOL,kind:'frame',jobId:job.jobId,sequence:sequence++,data:chunk},[chunk.buffer]);}port.postMessage({protocol:PROTOCOL,kind:'result',jobId:job.jobId,authorityCommitment:policy.authorityCommitment,bytes:buffer.length,hash});\n }catch(error){port.postMessage({protocol:PROTOCOL,kind:'error',jobId:job.jobId,code:code(error)});}finally{busy=false;}\n });port.postMessage({protocol:PROTOCOL,kind:'ready'});\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport {createHash} from 'node:crypto';\nimport {extractTypedText,extractTextFromContent,isRecord} from '../parser/content.js';\nimport {hasExclusionMarker} from '../markers.js';\nimport {sourceId} from '../memory/source-identity.js';\nimport {clean,clock,digest,type NativeEvent,type NativeFacts} from './source.js';\nimport {NativeMetadataProjection} from './native-metadata-projection.js';\nimport {createNativeUsageAccumulator} from './native-usage.js';\nimport type {AuditHarness} from './contracts.js';\nimport type {RecordedInference,ContextRecord} from './launch-contracts.js';\nexport interface StreamedNative {facts:NativeFacts;usage:RecordedInference[];language:ContextRecord[];hash:string;bytes:number;stamp:{dev:string;ino:string;size:number;mtimeNs:string;ctimeNs:string};counts:{observed:number;excluded:number;deduplicated:number};}\n/** Full native inference metadata and observed role inputs; no assistant/tool bodies retained. */\nexport async function streamNativeFacts(file:string,harness:Exclude<AuditHarness,'opencode'>,options:{signal:AbortSignal;maxBytes:number;maxRecords?:number;maxPromptBytes?:number;captureBytes?:number;captureFileBytes?:number;expectedIdentity?:{dev:string;ino:string};sourceAllowed?:(nativeId:string,project:string|null)=>boolean;accept:(project:string|null,eventAt:string|null)=>boolean}):Promise<StreamedNative>{\n const before=fs.statSync(file,{bigint:true}),captureSize=options.captureFileBytes??Number(before.size);if(!before.isFile()||!Number.isSafeInteger(captureSize)||captureSize<0||captureSize>options.maxBytes)throw new Error('native_usage_bytes_limit');if(before.size<BigInt(captureSize)||options.expectedIdentity&&(String(before.dev)!==options.expectedIdentity.dev||String(before.ino)!==options.expectedIdentity.ino))throw new Error('source_changed');\n let nativeId=path.basename(file,'.jsonl'),project:string|null=null,parent:string|null=null,records=0,offset=0,promptBytes=0,maintenance=false,programmatic=false,currentModel:string|null=null,currentProvider:string|null=null;const events:NativeEvent[]=[],language:ContextRecord[]=[],gaps=new Set<string>(),seen=new Set<string>(),hash=createHash('sha256');let usage:ReturnType<typeof createNativeUsageAccumulator>|null=null;\n let held:Buffer[]=[],heldBytes=0,projection:NativeMetadataProjection|null=null,projected=false;const turnLimit=options.captureBytes??0,turns:{lines:string[];bytes:number;prefix:string}[]= [];let turnLines:string[]=[],turnBytes=0,turnPrefix='',keptBytes=0,capturedRecords=0,scopeUncertain=false;const finishTurn=()=>{if(!turnLines.length){if(turnLimit>0&&turnBytes>0)gaps.add('context_turn_oversize');turnBytes=0;return;}if(turnBytes+Buffer.byteLength(turnPrefix)<=turnLimit){turns.push({lines:turnLines,bytes:turnBytes,prefix:turnPrefix});keptBytes+=turnBytes;while(turns.length>1&&keptBytes+Buffer.byteLength(turns[0]!.prefix)>turnLimit)keptBytes-=turns.shift()!.bytes;}else gaps.add('context_turn_oversize');turnLines=[];turnBytes=0;};\n const process=(raw:Buffer,end:number)=>{if(++records>(options.maxRecords??1000000)){gaps.add('native_usage_records_limit');return;}const line=raw.toString('utf8');let r:Record<string,unknown>;try{const parsed=JSON.parse(line);if(!isRecord(parsed))return;r=parsed;}catch{gaps.add('malformed_record');return;}\n if(r.entrypoint==='sdk-ts'||r.originator==='codex_exec')programmatic=true;\n const p=isRecord(r.payload)?r.payload:r;if(p.originator==='codex_exec'||p.source==='exec')programmatic=true;const m=isRecord(r.message)?r.message:{};if(typeof r.cwd==='string')project=r.cwd;if(typeof p.cwd==='string')project=p.cwd;\n if(harness==='claude'&&typeof r.sessionId==='string'){if(file.includes(`${path.sep}subagents${path.sep}`)||r.isSidechain===true){parent=r.sessionId;nativeId=`${parent}:${path.basename(file,'.jsonl')}`;}else nativeId=r.sessionId;}\n if(harness==='codex'&&r.type==='session_meta'){nativeId=typeof p.id==='string'?p.id:typeof p.session_id==='string'?p.session_id:nativeId;const source=isRecord(p.source)?p.source:{},sub=isRecord(source.subagent)?source.subagent:{},spawn=isRecord(sub.thread_spawn)?sub.thread_spawn:{};if(typeof spawn.parent_thread_id==='string')parent=spawn.parent_thread_id;}\n if(harness==='pi'&&r.type==='session'){if(typeof r.id==='string')nativeId=r.id;if(typeof r.parentSessionId==='string')parent=r.parentSessionId;}\n if(r.type==='turn_context'||r.type==='session_meta'||r.type==='model_change'){currentModel=typeof p.model==='string'?p.model:typeof r.modelId==='string'?r.modelId:currentModel;currentProvider=typeof p.model_provider==='string'?p.model_provider:typeof r.provider==='string'?r.provider:currentProvider;}\n if(scopeUncertain&&project!==null&&(harness==='claude'&&typeof r.sessionId==='string'||harness==='codex'&&r.type==='session_meta'&&(typeof p.id==='string'||typeof p.session_id==='string')||harness==='pi'&&r.type==='session'&&typeof r.id==='string'))scopeUncertain=false;\n if(options.sourceAllowed&&!options.sourceAllowed(nativeId,project))throw new Error('native_source_policy_excluded');\n if(hasExclusionMarker(extractTypedText(m.content))||typeof p.message==='string'&&hasExclusionMarker(p.message))maintenance=true;\n const isInput=harness==='claude'&&r.type==='user'&&m.role==='user'&&!(Array.isArray(m.content)&&m.content.some(b=>isRecord(b)&&b.type==='tool_result'))||harness==='codex'&&r.type==='event_msg'&&p.type==='user_message'||harness==='pi'&&r.type==='message'&&m.role==='user';\n if(isInput){finishTurn();turnPrefix=JSON.stringify({type:'turn_context',payload:{cwd:project,model:currentModel,model_provider:currentProvider}})+'\\n';}\n if(projected&&turnLimit>0){turnLines=[];turnBytes=turnLimit+1;gaps.add('context_turn_oversize');}\n if(turnLimit>0&&!projected&&turnBytes<=turnLimit){const recordKey=typeof r.uuid==='string'?r.uuid:typeof r.id==='string'?r.id:typeof p.id==='string'?p.id:`record:${records}`;const encoded=JSON.stringify({...r,_auditRecordKey:recordKey})+'\\n';turnBytes+=Buffer.byteLength(encoded);if(turnBytes<=turnLimit)turnLines.push(encoded);else if(turnLines.length)turnLines=[];}\n if(!usage)usage=createNativeUsageAccumulator(harness,sourceId(harness,nativeId),{maxRecords:1000000,acceptRecord:(_r,scope)=>!maintenance&&!scopeUncertain&&options.accept(scope.project,scope.eventAt)});usage.pushRecord(r,{rawStart:offset,rawEnd:end});if(scopeUncertain)return;\n let text='',identity='',origin:NativeEvent['origin']='unknown',eligible=false,excluded:string|null=null;const time=clock(r.timestamp),key=typeof r.uuid==='string'?r.uuid:typeof r.id==='string'?r.id:typeof p.id==='string'?p.id:`record:${records}`;\n if(harness==='claude'&&r.type==='user'&&m.role==='user'){if(Array.isArray(m.content)&&m.content.some(b=>isRecord(b)&&b.type==='tool_result'))return;text=extractTypedText(m.content);identity=typeof r.promptId==='string'?`prompt:${r.promptId}`:`record:${key}`;origin=typeof r.promptId==='string'?'claude_prompt_id':'unknown';eligible=typeof r.promptId==='string'&&!programmatic;}\n else if(harness==='codex'&&r.type==='event_msg'&&p.type==='user_message'){text=typeof p.message==='string'?p.message:'';identity=`marker:${offset}`;origin=programmatic?'unknown':'codex_human_marker';eligible=!programmatic;}\n else if(harness==='pi'&&r.type==='message'&&m.role==='user'){text=extractTypedText(m.content);identity=`node:${key}`;origin='pi_user_projection';}\n else{const info=isRecord(p.info)?p.info:{};const observedModel=typeof m.model==='string'?m.model:typeof p.model==='string'?p.model:typeof r.model==='string'?r.model:typeof info.model==='string'?info.model:currentModel,observedProvider=typeof m.provider==='string'?m.provider:typeof p.model_provider==='string'?p.model_provider:typeof p.provider==='string'?p.provider:typeof r.provider==='string'?r.provider:currentProvider;if((m.role==='assistant'||harness==='codex'&&(r.type==='event_msg'&&p.type==='token_count'||r.type==='response_item'&&p.type==='message'&&p.role==='assistant'))&&observedModel!=='<synthetic>'&&r.isSynthetic!==true&&options.accept(project,time))language.push({id:`metadata:${records}`,conversationId:sourceId(harness,nativeId),parentId:parent,harness,eventAt:time,project,role:'assistant',text:'',model:observedModel==='codex-auto-review'?null:observedModel,provider:observedProvider,directUser:false,route:null});return;}\n if(!text.trim()&&!projected)return;if(hasExclusionMarker(text)){maintenance=true;excluded='maintenance_exclusion_marker';}else if(r.isMeta===true||r.isSynthetic===true||m.isSynthetic===true)excluded='declared_meta_or_synthetic_input';else if(parent&&events.length===0)excluded='child_initialization';else if(typeof r.session_id==='string'&&r.session_id!==nativeId)excluded='inherited_identity_unverified';\n if(seen.has(identity))return;seen.add(identity);if(!options.accept(project,time))return;const redacted=clean(text);if(promptBytes+Buffer.byteLength(redacted)>(options.maxPromptBytes??64*1024*1024)){gaps.add('native_input_text_limit');return;}promptBytes+=Buffer.byteLength(redacted);\n language.push({id:digest(`${sourceId(harness,nativeId)}:${identity}`).slice(0,32),conversationId:sourceId(harness,nativeId),parentId:parent,harness,eventAt:time,project,role:'user',text:'',model:null,provider:null,directUser:excluded===null&&parent===null,route:null});\n const proofRecord={...r};delete proofRecord.sessionId;delete proofRecord.session_id;delete proofRecord.promptId;const stable=(value:unknown):unknown=>Array.isArray(value)?value.map(stable):isRecord(value)?Object.fromEntries(Object.keys(value).sort().map(k=>[k,stable(value[k])])):value;\n events.push({key,rawStart:offset,rawEnd:end,role:'user',text:redacted,eventAt:time,project,origin,eligible:eligible&&excluded===null&&parent===null,languageEligible:parent===null&&!projected,excluded,identity,observed:excluded===null,...(harness==='claude'&&typeof r.uuid==='string'?{nativeRecordId:r.uuid,recordCommitment:digest(JSON.stringify(stable(proofRecord)))}:{}),...(harness==='claude'&&typeof r.session_id==='string'&&r.session_id!==nativeId?{declaredOrigin:r.session_id}:{})});\n };\n const finishLine=(end:number)=>{if(projection){const result=projection.finish();projection=null;gaps.add('native_record_body_omitted');if(result.exclusionMarker)maintenance=true;if(result.record){projected=true;process(Buffer.from(JSON.stringify(result.record)),end);projected=false;}else{turnLines=[];turnBytes=turnLimit+1;records++;gaps.add(result.code??'native_metadata_invalid');gaps.add('native_scope_record_unavailable');usage?.invalidateContext();scopeUncertain=true;project=null;currentModel=null;currentProvider=null;}}else process(held.length===1?held[0]!:Buffer.concat(held,heldBytes),end);held=[];heldBytes=0;offset=end;};\n const stream=fs.createReadStream(file,{highWaterMark:64*1024,...(captureSize>0?{end:captureSize-1}:{})});try{let consumed=0;for await(const chunk of captureSize===0?[]:stream){if(options.signal.aborted){stream.destroy();throw new Error('cancelled');}const bytes=chunk as Buffer;hash.update(bytes);let at=0;while(at<bytes.length){const newline=bytes.indexOf(10,at),end=newline<0?bytes.length:newline,part=bytes.subarray(at,end);if(projection)projection.push(part);else if(heldBytes+part.length>8*1024*1024){projection=new NativeMetadataProjection(undefined,harness);for(const piece of held)projection.push(piece);projection.push(part);held=[];heldBytes=0;}else{held.push(part);heldBytes+=part.length;}if(newline<0)break;finishLine(consumed+newline+1);at=newline+1;}consumed+=bytes.length;}}finally{stream.destroy();}\n if(heldBytes||projection)gaps.add('unfinished_tail');const after=fs.statSync(file,{bigint:true});if(before.dev!==after.dev||before.ino!==after.ino||after.size<BigInt(captureSize))throw new Error('source_changed');if(BigInt(captureSize)!==after.size||before.mtimeNs!==after.mtimeNs||before.ctimeNs!==after.ctimeNs){const verify=createHash('sha256'),fd=fs.openSync(file,'r'),buffer=Buffer.allocUnsafe(65536);try{let at=0;while(at<captureSize){const n=fs.readSync(fd,buffer,0,Math.min(buffer.length,captureSize-at),at);if(!n)throw new Error('source_changed');verify.update(buffer.subarray(0,n));at+=n;}}finally{fs.closeSync(fd);}if(verify.digest('hex')!==hash.copy().digest('hex'))throw new Error('source_changed');gaps.add('native_appended_after_capture');}\n if(maintenance){gaps.add('maintenance_source_excluded');for(const event of events){event.observed=false;event.eligible=false;event.excluded='maintenance_exclusion_marker';}}\n const artifactHash=hash.digest('hex'),acc=usage as ReturnType<typeof createNativeUsageAccumulator>|null,all=acc?.records()??[];finishTurn();const captured=Buffer.from((turns[0]?.prefix??'')+turns.flatMap(t=>t.lines).join(''));capturedRecords=turns.reduce((n,t)=>n+t.lines.length,0);if(turnLimit>0&&capturedRecords<records)gaps.add('context_capture_partial');return {facts:{nativeId,project,parent,child:parent!==null,title:null,events,gaps:[...gaps],hash:artifactHash,consumed:offset,bytes:captured},usage:maintenance?[]:all,language:maintenance?[]:language,hash:artifactHash,bytes:captureSize,stamp:{dev:String(after.dev),ino:String(after.ino),size:Number(after.size),mtimeNs:String(after.mtimeNs),ctimeNs:String(after.ctimeNs)},counts:maintenance?{observed:acc?.counts().observed??0,excluded:acc?.counts().observed??0,deduplicated:0}:acc?.counts()??{observed:0,excluded:0,deduplicated:0}};\n}\n", "/**\n * Content-block helpers.\n *\n * Ported from obra/episodic-memory@1075769 `src/parser.ts`\n * (MIT, (c) 2025 Jesse Vincent) \u2014 `extractTextFromContent`, `safeParseJson`\n * and `stringifyToolOutput` are upstream's, near-verbatim; the strict-mode\n * guards and `filesTouched` are potsherd's.\n *\n * Every harness writes an assistant turn as either a plain string or an array\n * of typed blocks. This module is the only place that knows the block shapes.\n */\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Join every `text` field in a content array. Upstream filters on the presence\n * of a string `text`, which is deliberately loose: it picks up `text`,\n * `input_text` and `output_text` blocks alike, and that is what codex needs.\n */\nexport function extractTextFromContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .filter((block): block is Record<string, unknown> => isRecord(block) && typeof block.text === 'string')\n .map((block) => block.text as string)\n .join('\\n');\n}\n\n/** Text blocks only \u2014 used for the claude path, where `type` is reliable. */\nexport function extractTypedText(content: unknown, blockType = 'text'): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .filter((b): b is Record<string, unknown> => isRecord(b) && b.type === blockType && typeof b.text === 'string')\n .map((b) => b.text as string)\n .join('\\n');\n}\n\nexport function safeParseJson(value: string): unknown {\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return value;\n }\n}\n\nexport function stringifyToolOutput(output: unknown): string | undefined {\n if (output === undefined || output === null) return undefined;\n if (typeof output === 'string') return output;\n const text = extractTextFromContent(output);\n if (text.trim()) return text;\n try {\n return JSON.stringify(output);\n } catch {\n return undefined;\n }\n}\n\n/**\n * `Exchange.toolCalls[].input` is a string in `03` \u00A72 (it goes straight into a\n * TEXT column and through the redactor), so structured inputs are stringified\n * here once rather than at every call site.\n */\nexport function stringifyToolInput(input: unknown): string {\n if (input === undefined || input === null) return '';\n if (typeof input === 'string') return input;\n try {\n return JSON.stringify(input);\n } catch {\n return String(input);\n }\n}\n\n/**\n * The tool-input keys that name a file. `03` \u00A72 asks for `filesTouched`\n * \"parsed from Edit/Write/Read tool inputs\"; matching on the key rather than\n * the tool name survives new tools and harness-specific tool naming.\n */\nconst FILE_KEYS = ['file_path', 'filePath', 'notebook_path', 'notebookPath', 'path'] as const;\n\n/** Absolute-ish paths named by a tool input, in first-seen order. */\nexport function filesFromToolInput(input: unknown): string[] {\n if (!isRecord(input)) return [];\n const out: string[] = [];\n for (const key of FILE_KEYS) {\n const value = input[key];\n if (typeof value === 'string' && value.trim()) out.push(value);\n }\n // MultiEdit and friends nest one level: { edits: [{ file_path }] }.\n for (const value of Object.values(input)) {\n if (!Array.isArray(value)) continue;\n for (const item of value) {\n for (const f of filesFromToolInput(item)) out.push(f);\n }\n }\n return out;\n}\n\n/** Dedup preserving order \u2014 `filesTouched` is a set, but a stable one. */\nexport function uniq(values: readonly string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const v of values) {\n if (seen.has(v)) continue;\n seen.add(v);\n out.push(v);\n }\n return out;\n}\n", "/**\n * Opt-out markers: text that means \"do not index this conversation\".\n *\n * Ported from obra/episodic-memory@1075769 `src/constants.ts` (the summarizer\n * content marker, verbatim) and `src/sync.ts:7-11` (the exclusion list)\n * (MIT, (c) 2025 Jesse Vincent).\n *\n * Two of the three markers are upstream's own product strings and are kept\n * **verbatim on purpose**: a user who has been running episodic-memory has\n * these markers sitting in real transcripts already, and potsherd must honour\n * the opt-out they represent rather than re-indexing what they excluded.\n * potsherd's own marker is added alongside.\n */\n\n/** Upstream's summarizer prompt contains this, so its own runs never index. */\nexport const SUMMARIZER_CONTEXT_MARKER =\n 'Context: This summary will be shown in a list to help users and Claude choose which conversations are relevant';\n\n/** potsherd's equivalent, for the card writer in phase 2. */\nexport const POTSHERD_CARD_MARKER =\n '<INSTRUCTIONS-TO-POTSHERD>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-POTSHERD>';\n\nexport const EXCLUSION_MARKERS: readonly string[] = [\n '<INSTRUCTIONS-TO-EPISODIC-MEMORY>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-EPISODIC-MEMORY>',\n 'Only use NO_INSIGHTS_FOUND',\n SUMMARIZER_CONTEXT_MARKER,\n POTSHERD_CARD_MARKER,\n];\n\n/** True when a transcript's text opts out of indexing. */\nexport function hasExclusionMarker(text: string): boolean {\n return EXCLUSION_MARKERS.some((marker) => text.includes(marker));\n}\n", "import {createHash} from 'node:crypto';\n/** Stable native source identity, shared with memory without loading its database graph. */\nexport function sourceId(harness:string,nativeSessionId:string):string{return createHash('sha256').update(`source/v1\\0${harness}\\0${nativeSessionId}`).digest('hex');}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport {createHash} from 'node:crypto';\nimport {readJsonlLines,parseJsonLine} from '../parser/jsonl.js';\nimport {isRecord,extractTypedText,extractTextFromContent} from '../parser/content.js';\nimport {redact} from '../redact.js';\nimport {elideBinary} from '../redact-elide.js';\nimport {hasExclusionMarker} from '../markers.js';\nimport type {AuditHarness} from './contracts.js';\n\nexport const digest=(value:string|Buffer):string=>createHash('sha256').update(value).digest('hex');\nexport const clean=(text:string):string=>redact(elideBinary(text)).text;\nexport const clock=(value:unknown):string|null=>typeof value==='string'&&Number.isFinite(Date.parse(value))?new Date(value).toISOString():null;\nexport interface NativeEvent {observed?:boolean;languageEligible?:boolean;key:string;rawStart:number;rawEnd:number;role:'user';text:string;eventAt:string|null;project:string|null;origin:'claude_prompt_id'|'codex_human_marker'|'pi_user_projection'|'opencode_user_projection'|'unknown';eligible:boolean;excluded:string|null;identity:string;evidenceStart?:number;nativeRecordId?:string;recordCommitment?:string;declaredOrigin?:string;}\nexport interface NativeFacts {nativeId:string;project:string|null;parent:string|null;child:boolean;title:string|null;events:NativeEvent[];gaps:string[];hash:string;consumed:number;bytes:Buffer;}\n\n/** A size check and a bounded fd read, with identity rechecked after reading. */\nexport function boundedBytes(file:string,max:number):Buffer {\n const fd=fs.openSync(file,'r');\n try{const before=fs.fstatSync(fd);if(!before.isFile()||before.size>max)throw new Error('source_bytes_limit');\n const bytes=Buffer.alloc(before.size);let offset=0;\n while(offset<bytes.length){const n=fs.readSync(fd,bytes,offset,bytes.length-offset,offset);if(!n)throw new Error('source_changed');offset+=n;}\n const after=fs.fstatSync(fd);if(before.size!==after.size||before.mtimeMs!==after.mtimeMs||before.ctimeMs!==after.ctimeMs||before.dev!==after.dev||before.ino!==after.ino)throw new Error('source_changed');\n return bytes;\n }finally{fs.closeSync(fd);}\n}\n\n/** Bounded entry iteration: no adapter discover() array or symlink traversal. */\nexport async function* walk(root:string,maxEntries:number,signal:AbortSignal,maxDepth=8):AsyncGenerator<string> {\n let visited=0;\n async function* visit(dir:string,depth:number):AsyncGenerator<string>{\n if(signal.aborted)return;if(depth>maxDepth)throw new Error('discovery_depth_limit');\n let handle:fs.Dir;try{handle=await fs.promises.opendir(dir);}catch(error){if((error as NodeJS.ErrnoException).code==='ENOENT')return;throw new Error('source_root_unreadable');}\n try{for await(const item of handle){if(signal.aborted)return;if(++visited>maxEntries)throw new Error('discovery_entries_limit');\n const file=path.join(dir,item.name);if(item.isDirectory())yield* visit(file,depth+1);else if(item.isFile())yield file;\n }}finally{try{await handle.close();}catch{/* async iteration already closes it */}}\n }\n yield* visit(root,0);\n}\n\n/** Shares the established JSONL reader and exact content extractors; no exchange folding. */\nexport async function nativeFacts(file:string,harness:Exclude<AuditHarness,'opencode'>,bytes:Buffer,maxRecords:number):Promise<NativeFacts>{\n const events:NativeEvent[]=[];const gaps=new Set<string>();let project:string|null=null,parent:string|null=null,title:string|null=null;\n let nativeId=path.basename(file,'.jsonl'),consumed=0,records=0,turn:string|null=null,programmatic=false;\n const identity=new Map<string,string>();\n const responses:{text:string;cleanText:string;turn:string|null;start:number;end:number;key:string;time:string|null;project:string|null}[]=[];\n const markers:{event:NativeEvent;turn:string|null}[]=[];\n const put=(event:NativeEvent)=>{const previous=identity.get(event.identity);if(previous!==undefined){if(previous!==event.text)gaps.add('native_event_identity_conflict');return;}identity.set(event.identity,event.text);events.push(event);};\n for await(const line of readJsonlLines(file,{snapshot:bytes})){\n if(!line.terminated){gaps.add('unfinished_tail');break;}if(++records>maxRecords){gaps.add('source_records_limit');break;}consumed=line.end;\n const r=parseJsonLine(line.text);if(!isRecord(r)){if(line.text.trim())gaps.add('malformed_record');continue;}\n const p=isRecord(r.payload)?r.payload:r,m=isRecord(r.message)?r.message:{};\n if(typeof r.cwd==='string')project=r.cwd;if(typeof p.cwd==='string')project=p.cwd;\n const key=typeof r.uuid==='string'?r.uuid:typeof p.id==='string'?p.id:`record:${line.lineNumber}`;\n const at=clock(r.timestamp);const base={key,rawStart:line.start,rawEnd:line.end,role:'user' as const,eventAt:at,project};\n const maintenance=(text:string)=>hasExclusionMarker(text);\n if(harness==='claude'){\n if(typeof r.sessionId==='string'&&!file.includes(`${path.sep}subagents${path.sep}`))nativeId=r.sessionId;\n if(typeof r.entrypoint==='string'){if(r.entrypoint==='sdk-ts')programmatic=true;else if(['cli','desktop','vscode'].includes(r.entrypoint))programmatic=false;}\n if(file.includes(`${path.sep}subagents${path.sep}`)||r.isSidechain===true){parent=typeof r.sessionId==='string'?r.sessionId:parent;}\n if(r.type==='ai-title'&&typeof r.aiTitle==='string')title=clean(r.aiTitle);\n if(r.type!=='user'||m.role!=='user'){\n if(m.role==='user'){const text=extractTypedText(m.content);if(text.trim()){gaps.add('unsupported_user_container');put({...base,text:clean(text),origin:'unknown',eligible:false,excluded:'unsupported_user_container',identity:`record:${key}`});}}\n continue;\n }\n const text=extractTypedText(m.content);if(!text.trim())continue;\n const results=Array.isArray(m.content)&&m.content.some(b=>isRecord(b)&&b.type==='tool_result');\n const native=typeof r.promptId==='string'&&r.promptId.length>0&&!results;\n const explicitMeta=r.isMeta===true||r.isSynthetic===true;\n const declared=typeof r.session_id==='string'&&r.session_id!==nativeId?r.session_id:undefined;\n const recordCopy={...r};delete recordCopy.sessionId;delete recordCopy.session_id;delete recordCopy.promptId;\n const stable=(value:unknown):unknown=>Array.isArray(value)?value.map(stable):isRecord(value)?Object.fromEntries(Object.keys(value).sort().map(k=>[k,stable(value[k])])):value;\n const excluded=parent&&events.length===0?'child_initialization':maintenance(text)?'maintenance_exclusion_marker':results?'tool_result':explicitMeta?'declared_meta_or_synthetic_input':declared?'inherited_identity_unverified':programmatic?'programmatic_origin_unattested':native?null:'injected_or_origin_unknown';\n if(programmatic&&!parent&&excluded!=='maintenance_exclusion_marker')gaps.add('human_attestation_unavailable');if(explicitMeta&&!parent)gaps.add('explicit_meta_or_synthetic_origin_unattested');\n put({...base,observed:!results&&!explicitMeta&&!maintenance(text)&&!declared&&!(parent&&events.length===0),text:clean(text),origin:native&&!declared&&!programmatic&&!explicitMeta?'claude_prompt_id':'unknown',eligible:native&&excluded===null,excluded,identity:native&&!explicitMeta?`prompt:${r.promptId}`:`record:${key}`,...(typeof r.uuid==='string'&&r.uuid.length>0?{nativeRecordId:r.uuid,recordCommitment:digest(JSON.stringify(stable(recordCopy)))}:{}),...(declared?{declaredOrigin:declared}:{})});\n }else if(harness==='codex'){\n if(r.type==='session_meta'){\n nativeId=typeof p.session_id==='string'?p.session_id:typeof p.id==='string'?p.id:nativeId;\n if(p.originator==='codex_exec'||p.source==='exec')programmatic=true;\n const source=isRecord(p.source)?p.source:{},sub=isRecord(source.subagent)?source.subagent:{},spawn=isRecord(sub.thread_spawn)?sub.thread_spawn:{};\n if(typeof spawn.parent_thread_id==='string')parent=spawn.parent_thread_id;\n }\n if(typeof p.turn_id==='string')turn=p.turn_id;\n if(r.type==='response_item'&&p.type==='message'&&p.role==='user'){\n const text=extractTextFromContent(p.content);if(text.trim())responses.push({text,cleanText:clean(text),turn,start:line.start,end:line.end,key,time:at,project});\n }\n if(r.type!=='response_item'&&r.type!=='event_msg'&&p.role==='user'){\n const text=extractTextFromContent(p.content);if(text.trim()){gaps.add('unsupported_user_container');put({...base,text:clean(text),origin:'unknown',eligible:false,excluded:'unsupported_user_container',identity:`record:${key}`});}\n }\n if(r.type!=='event_msg')continue;\n const item=isRecord(p.item)?p.item:{};\n const text=p.type==='user_message'&&typeof p.message==='string'?p.message:p.type==='item_completed'&&item.type==='UserMessage'?extractTextFromContent(item.content):'';\n if(!text.trim())continue;\n const id=typeof item.id==='string'?`item:${item.id}`:`marker:${line.start}`;\n const excluded=parent&&events.length===0?'child_initialization':maintenance(text)?'maintenance_exclusion_marker':programmatic?'programmatic_origin_unattested':null;\n if(programmatic&&!parent&&excluded!=='maintenance_exclusion_marker')gaps.add('human_attestation_unavailable');\n const event:NativeEvent={...base,observed:excluded===null||excluded==='programmatic_origin_unattested',text:clean(text),origin:programmatic?'unknown':'codex_human_marker',eligible:excluded===null,excluded,identity:id};\n const before=events.length;put(event);if(events.length>before)markers.push({event,turn});\n }else{\n if(r.type==='session'){if(typeof r.id==='string')nativeId=r.id;if(typeof r.cwd==='string')project=r.cwd;if(typeof r.parentSessionId==='string')parent=r.parentSessionId;continue;}\n if(r.type!=='message'||m.role!=='user')continue;const text=extractTypedText(m.content);if(!text.trim())continue;\n put({...base,observed:r.isMeta!==true&&r.isSynthetic!==true&&!maintenance(text),text:clean(text),origin:'pi_user_projection',eligible:false,excluded:'projection_origin_unverified',identity:`node:${typeof r.id==='string'?r.id:key}`});gaps.add('pi_exchange_projection_fidelity');\n }\n }\n if(harness==='codex'){\n // Markers are the count authority. Pair only unique text candidates inside the\n // explicit turn or nearest marker window; a same-text injection remains ambiguous.\n const used=new Set<number>();\n for(let i=0;i<markers.length;i++){const marker=markers[i]!,prev=markers[i-1]?.event.rawStart??0,next=markers[i+1]?.event.rawStart??consumed;\n const matches=responses.filter(r=>!used.has(r.start)&&r.cleanText.trim()===marker.event.text.trim()&&(marker.turn!==null?r.turn===marker.turn:r.start>=prev&&r.start<=next));\n if(matches.length===1){const response=matches[0]!;used.add(response.start);marker.event.evidenceStart=response.start;}else if(matches.length>1)gaps.add('codex_response_pair_ambiguous');\n }\n for(const response of responses){if(used.has(response.start))continue;const matches=markers.some(m=>m.event.text.trim()===response.cleanText.trim());\n events.push({key:response.key,rawStart:response.start,rawEnd:response.end,role:'user',text:response.cleanText,eventAt:response.time,project:response.project,origin:'unknown',eligible:false,excluded:matches?'unpaired_user_response':'human_marker_missing',identity:`response:${response.start}`});\n if(!markers.length)gaps.add('codex_human_marker_missing');\n }\n }\n if(parent&&harness==='claude')nativeId=`${parent}:${path.basename(file,'.jsonl')}`;\n if(parent){for(const event of events)event.eligible=false;}\n if(harness==='pi')gaps.add('pi_exchange_projection_fidelity');\n const complete=bytes.subarray(0,consumed);return {nativeId,project,parent,child:parent!==null,title,events,gaps:[...gaps],hash:digest(complete),consumed,bytes:complete};\n}\n", "import { createHash } from 'node:crypto';\nimport type { Exchange, ExchangeToolCall } from './adapters/types.js';\nimport { Theme } from './theme.js';\nimport type { Row } from './render.js';\nimport * as fmt from './format.js';\nimport {\n ALLOW_SPANS,\n RULES,\n SECRET_TYPES,\n type Rule,\n type SecretType,\n} from './redact-rules.js';\n\nexport type { SecretType } from './redact-rules.js';\n// The pre-redaction pass. Not redaction \u2014 it removes binary bulk that carries\n// no meaning for retrieval \u2014 but it runs immediately before this module on the\n// same strings, so it is re-exported here and the two are read together.\nexport {\n elideBinary,\n elideExchange,\n emptyElisions,\n addElisions,\n MIN_PAYLOAD,\n ELISION_RE,\n type Elisions,\n} from './redact-elide.js';\nexport {\n RULES,\n SECRET_TYPES,\n shannonEntropy,\n ENTROPY_MIN_LENGTH,\n ENTROPY_THRESHOLD,\n nameLooksLikeSecret,\n valueLooksLikeSecret,\n type Rule,\n} from './redact-rules.js';\n\n/**\n * L2 \u2014 redaction. `plans/03-ARCHITECTURE.md` \u00A75 and \u00A711.\n *\n * This module decides whether a user's secrets can ever leave their machine.\n * Nothing downstream of it \u2014 the index, cards, ask, graft \u2014 is allowed to see\n * an unredacted string, and every string that reaches a model passes through\n * here first. A false negative is a leaked credential; a false positive is one\n * unreadable token in a search result. The rules are tuned accordingly.\n *\n * Pure and synchronous by contract: no I/O, no network, no module state that\n * survives a call. It runs over the whole corpus at index time, so it also has\n * to be fast \u2014 see `tests/redact.test.ts` for the measured 10 MB throughput.\n *\n * ## The mask\n *\n * \u2039redacted:<type>:<sha8>\u203A e.g. \u2039redacted:aws:cccc2222\u203A\n *\n * `sha8` is the first 8 hex characters of sha256(secret), so the *same* secret\n * always produces the *same* mask: the index stays searchable by shape (\"that\n * session where the same aws key appeared\") and never by value. Two different\n * secrets colliding needs a 32-bit sha256 prefix collision.\n *\n * The guillemets are deliberate: `\u2039` U+2039 and `\u203A` U+203A cannot appear in a\n * shell token, a json key or a base64 blob, so the mask can never be confused\n * for content and can never be pasted back into a command by accident.\n *\n * fts5 tokenisation, measured against the bundled sqlite (default `unicode61`\n * tokenizer): `\u2039redacted:aws:cccc2222\u203A` indexes as the three tokens\n * `redacted`, `aws`, `cccc2222` \u2014 both guillemets and both colons are\n * separators. So `find \"cccc2222\"` locates every exchange that leaked that one\n * secret, `find \"redacted AND aws\"` locates every exchange that leaked an aws\n * key, and the phrase query `\"redacted:aws:cccc2222\"` also works. The mask\n * costs three tokens per hit in the index and nothing else.\n *\n * ## What redaction does NOT touch\n *\n * The archive copy (L3) is byte-exact and unredacted: it is the user's own file\n * on the user's own disk. Only the *index* is redacted. There is no\n * `--no-redact` flag (`03` \u00A711) and adding one is not a feature request.\n */\n\n/** A masked secret. `sha8` identifies it without revealing it. */\nexport interface RedactionHit {\n type: SecretType;\n /** Rule id that claimed it \u2014 `doctor` and false-positive triage. */\n rule: string;\n /** First 8 hex chars of sha256(secret). */\n sha8: string;\n /** Offset of the secret in the *input* text. */\n start: number;\n /** Length of the secret in the input text. */\n length: number;\n}\n\nexport interface RedactionResult {\n text: string;\n hits: RedactionHit[];\n}\n\n/** Counts by type, for `doctor`. */\nexport interface RedactionCounts {\n total: number;\n byType: Record<SecretType, number>;\n}\n\nconst OPEN = '\u2039';\nconst CLOSE = '\u203A';\n\n/** Matches potsherd's own mask, so a second pass recognises its output. */\nexport const MASK_RE = new RegExp(`${OPEN}redacted:[a-z-]+:[0-9a-f]{8}${CLOSE}`, 'g');\n\n/** The first 8 hex characters of sha256(secret). */\nexport function secretDigest(secret: string): string {\n return createHash('sha256').update(secret, 'utf8').digest('hex').slice(0, 8);\n}\n\n/** `\u2039redacted:aws:cccc2222\u203A` */\nexport function maskFor(type: SecretType, secret: string): string {\n return `${OPEN}redacted:${type}:${secretDigest(secret)}${CLOSE}`;\n}\n\n/** Does this text already contain a potsherd mask? */\nexport function containsMask(text: string): boolean {\n return new RegExp(MASK_RE.source).test(text);\n}\n\ninterface Span {\n start: number;\n end: number;\n}\n\n/**\n * Mask every secret in `text`.\n *\n * Rules are applied in `RULES` order and the first rule to claim a span keeps\n * it, which is why the table is ordered specific \u2192 generic \u2192 entropy: a jwt is\n * reported as a jwt and not as three high-entropy tokens, and the base64 body\n * of a private key is reported as one private key and not as forty.\n *\n * Idempotent: existing masks are protected spans, so `redact(redact(x).text)`\n * returns the same text with no further hits.\n */\nexport function redact(text: string): RedactionResult {\n if (typeof text !== 'string' || text.length === 0) return { text: text ?? '', hits: [] };\n\n // Claimed characters. One byte per input character: an O(1) overlap test that\n // stays honest when 40 rules each propose overlapping spans.\n const claimed = new Uint8Array(text.length);\n const spans: Array<Span & { rule: Rule; value: string }> = [];\n\n // Allowlisted regions (data URIs, SRI hashes) and this module's own masks are\n // claimed before any rule runs, so nothing can match inside them.\n for (const span of protectedSpans(text)) claim(claimed, span);\n\n for (const rule of RULES) {\n for (const m of rule.scan(text)) {\n if (m.start < 0 || m.end > text.length || m.end <= m.start) continue;\n if (isClaimed(claimed, m)) continue;\n claim(claimed, m);\n spans.push({ start: m.start, end: m.end, rule, value: m.value });\n }\n }\n\n if (spans.length === 0) return { text, hits: [] };\n spans.sort((a, b) => a.start - b.start);\n\n const out: string[] = [];\n const hits: RedactionHit[] = [];\n let cursor = 0;\n for (const s of spans) {\n out.push(text.slice(cursor, s.start));\n const sha8 = secretDigest(s.value);\n out.push(`${OPEN}redacted:${s.rule.type}:${sha8}${CLOSE}`);\n hits.push({ type: s.rule.type, rule: s.rule.id, sha8, start: s.start, length: s.end - s.start });\n cursor = s.end;\n }\n out.push(text.slice(cursor));\n return { text: out.join(''), hits };\n}\n\n/** Just the text, for the many callers that do not care what was masked. */\nexport function redactText(text: string): string {\n return redact(text).text;\n}\n\n/**\n * Redact one exchange in place of its unredacted self: `user_text`,\n * `assistant_text` and every `tool_calls.input` / `.result` (`03` \u00A75). Returns\n * a new object; the input is never mutated, because the caller may still be\n * writing the byte-exact archive copy from it.\n */\nexport function redactExchange(ex: Exchange): { exchange: Exchange; hits: RedactionHit[] } {\n const hits: RedactionHit[] = [];\n const one = (s: string): string => {\n const r = redact(s);\n if (r.hits.length) hits.push(...r.hits);\n return r.text;\n };\n\n const userText = one(ex.userText);\n const assistantText = one(ex.assistantText);\n const toolCalls: ExchangeToolCall[] = ex.toolCalls.map((tc) => {\n const next: ExchangeToolCall = { ...tc, input: one(tc.input) };\n if (tc.result !== undefined) next.result = one(tc.result);\n return next;\n });\n\n return {\n exchange: { ...ex, userText, assistantText, toolCalls, redacted: ex.redacted || hits.length > 0 },\n hits,\n };\n}\n\n// ---------------------------------------------------------------- counting\n\nexport function emptyCounts(): RedactionCounts {\n const byType = {} as Record<SecretType, number>;\n for (const t of SECRET_TYPES) byType[t] = 0;\n return { total: 0, byType };\n}\n\n/** Tally hits by type. `doctor` sums these across the whole index. */\nexport function tally(hits: Iterable<RedactionHit>, into: RedactionCounts = emptyCounts()): RedactionCounts {\n for (const h of hits) {\n into.byType[h.type] = (into.byType[h.type] ?? 0) + 1;\n into.total++;\n }\n return into;\n}\n\nexport function addCounts(a: RedactionCounts, b: RedactionCounts): RedactionCounts {\n const out = emptyCounts();\n out.total = a.total + b.total;\n for (const t of SECRET_TYPES) out.byType[t] = (a.byType[t] ?? 0) + (b.byType[t] ?? 0);\n return out;\n}\n\n/** `{ total, aws: 3, jwt: 12 }` \u2014 the `--json` shape for `doctor`. */\nexport function countsJson(c: RedactionCounts): Record<string, number> {\n const out: Record<string, number> = { total: c.total };\n for (const t of SECRET_TYPES) if ((c.byType[t] ?? 0) > 0) out[t] = c.byType[t] ?? 0;\n return out;\n}\n\n/**\n * The `doctor` line (`03` \u00A75: \"`potsherd doctor` reports redaction counts by\n * type\"), in the house style of `render.ts`:\n *\n * secrets masked 1,284 jwt 512 \u00B7 entropy 402 \u00B7 aws 12\n *\n * The note lists types by count, biggest first, and elides rather than wraps \u2014\n * `render.ts` never wraps a row. Wired into the doctor card by T1.5; kept here\n * so the counts and the way they are said stay in one file.\n */\nexport function redactionRow(\n c: RedactionCounts,\n t: Theme = new Theme(),\n noteWidth = 43,\n): Row {\n const parts = SECRET_TYPES.filter((k) => (c.byType[k] ?? 0) > 0)\n .sort((a, b) => (c.byType[b] ?? 0) - (c.byType[a] ?? 0))\n .map((k) => `${k} ${fmt.num(c.byType[k] ?? 0)}`);\n const note = parts.length === 0\n ? 'nothing matched \u2014 index holds no secrets'\n : fmt.joinFit(parts, noteWidth, ` ${t.mid} `, t.ellip);\n return {\n label: 'secrets masked',\n value: fmt.num(c.total),\n note,\n tone: c.total > 0 ? 'ok' : 'dim',\n };\n}\n\n/** One plain line, for logs and for `doctor` in a non-card context. */\nexport function redactionLine(c: RedactionCounts, t: Theme = new Theme()): string {\n const row = redactionRow(c, t, Math.max(20, t.width - 30));\n return `${row.label.padEnd(22)}${(row.value ?? '').padStart(7)} ${t.dim(row.note ?? '')}`;\n}\n\n// ---------------------------------------------------------------- internals\n\nfunction protectedSpans(text: string): Span[] {\n const spans: Span[] = [];\n const patterns = [MASK_RE, ...ALLOW_SPANS];\n for (const p of patterns) {\n const rx = new RegExp(p.source, p.flags.includes('g') ? p.flags : p.flags + 'g');\n let m: RegExpExecArray | null;\n while ((m = rx.exec(text)) !== null) {\n if (m[0].length === 0) { rx.lastIndex++; continue; }\n spans.push({ start: m.index, end: m.index + m[0].length });\n }\n }\n return spans;\n}\n\nfunction isClaimed(claimed: Uint8Array, s: Span): boolean {\n for (let i = s.start; i < s.end; i++) if (claimed[i]) return true;\n return false;\n}\n\nfunction claim(claimed: Uint8Array, s: Span): void {\n const end = Math.min(s.end, claimed.length);\n for (let i = Math.max(0, s.start); i < end; i++) claimed[i] = 1;\n}\n\n/** Legacy projections have no immutable text-hash contract; mask on public read.\n * Canonical evidence/notes must instead refuse an unsafe old immutable value.\n */\nexport function redactLegacyProjection<T>(value:T):T{\n const visit=(input:unknown):{value:unknown;changed:boolean}=>{\n if(typeof input==='string'){const clean=redact(input).text;return {value:clean,changed:clean!==input};}\n if(Array.isArray(input)){const items=input.map(visit);return {value:items.map(item=>item.value),changed:items.some(item=>item.changed)};}\n if(input&&typeof input==='object'&&Object.getPrototypeOf(input)===Object.prototype){const output:Record<string,unknown>={};let changed=false;for(const [key,child] of Object.entries(input)){const result=visit(child);output[key]=result.value;changed ||= result.changed;}if(changed){if('redacted' in output)output.redacted=true;if('text' in output&&'match' in output)output.match=null;output.redactionRefreshed=true;}return {value:output,changed};}\n return {value:input,changed:false};\n };return visit(value).value as T;\n}\n", "import process from 'node:process';\n\n/**\n * The terminal design system, in code (plans/05-SHAREABLE-EXPERIENCE.md).\n *\n * Rules this module enforces so no verb can break them:\n * - never more than three colours on screen: accent, warn, ok. Everything\n * else is `dim` or default.\n * - NO_COLOR and --no-color are honoured; a non-TTY stdout is never coloured.\n * - --ascii replaces every non-ASCII glyph, so the output survives a terminal\n * with no unicode font and a screenshot taken on Windows. Two mechanisms,\n * because one was demonstrably forgettable: {@link Theme.g} picks the\n * fallback where the glyph is chosen, and {@link Theme.asciiLine} folds\n * whatever still got through \u2014 an em dash typed into a note, a `\u00B7` an\n * adapter wrote, an emoji in someone's own prompt. `render.ts` runs every\n * line it emits through the fold, so no verb can opt out by forgetting.\n */\n\nexport interface ThemeOptions {\n color?: boolean;\n ascii?: boolean;\n width?: number;\n}\n\nconst CSI = '\\u001b[';\n\nexport class Theme {\n readonly color: boolean;\n readonly ascii: boolean;\n readonly width: number;\n\n constructor(opts: ThemeOptions = {}) {\n this.color = opts.color ?? detectColor();\n this.ascii = opts.ascii ?? detectAscii();\n this.width = opts.width ?? detectWidth();\n }\n\n private wrap(code: string, s: string): string {\n return this.color ? `${CSI}${code}m${s}${CSI}0m` : s;\n }\n\n /** The single most important number on the screen. Exactly one per card. */\n accent(s: string): string { return this.wrap('38;5;209', s); }\n /** Urgency: something is about to be lost. */\n warn(s: string): string { return this.wrap('38;5;214', s); }\n /** Done, saved, safe. */\n ok(s: string): string { return this.wrap('38;5;71', s); }\n /** Secondary text: units, notes, sources. */\n dim(s: string): string { return this.wrap('2', s); }\n bold(s: string): string { return this.wrap('1', s); }\n\n /** Pick a glyph, with an ASCII fallback for --ascii / non-unicode terminals. */\n g(unicode: string, fallback: string): string {\n return this.ascii ? fallback : unicode;\n }\n\n get arrow(): string { return this.g('\u2192', '->'); }\n get mid(): string { return this.g('\u00B7', '.'); }\n get sep(): string { return this.g('\u00B7', '|'); }\n get ellip(): string { return this.g('\u2026', '...'); }\n get star(): string { return this.g('\u2605', '*'); }\n get le(): string { return this.g('\u2264', '<='); }\n get bullet(): string { return this.g('\u2022', '-'); }\n /** The em dash that stands in for \"no number here\". */\n get dash(): string { return this.g('\u2014', '-'); }\n\n /**\n * Fold one rendered line to pure ASCII, when `--ascii` is on.\n *\n * Applied at the very end, after the line has been fitted to the terminal\n * width, so **every substitution is exactly one character wide or narrower**.\n * That is the whole design constraint: `\u2026` \u2192 `...` here would push a line\n * that just fitted 80 columns to 82. The three-character ellipsis comes from\n * {@link ellip}, which the width arithmetic sees; this is only the net.\n */\n asciiLine(s: string): string {\n return this.ascii ? toAscii(s) : s;\n }\n\n /** Visible width, ignoring ANSI escapes. */\n static len(s: string): number {\n return stripAnsi(s).length;\n }\n}\n\n/**\n * The glyphs the design system uses, and their one-character ASCII stand-ins.\n * Anything not listed is decomposed (`\u00E9` \u2192 `e`) and, failing that, becomes a\n * single `?` \u2014 never silently dropped, because a vanished character is a\n * vanished fact.\n */\nconst ASCII_FOLD: Record<string, string> = {\n '\u2026': '.', '\u00B7': '.', '\u2022': '*', '\u2027': '.', '\u2219': '.',\n '\u2014': '-', '\u2013': '-', '\u2012': '-', '\u2212': '-', '\u2015': '-',\n '\u2192': '>', '\u21D2': '>', '\u2190': '<', '\u21D0': '<', '\u2191': '^', '\u2193': 'v',\n '\u2264': '<', '\u2265': '>', '\u2260': '!', '\u00B1': '~', '\u00D7': 'x', '\u00F7': '/',\n '\u2605': '*', '\u2606': '*', '\u2713': 'v', '\u2714': 'v', '\u2717': 'x', '\u2718': 'x',\n '\u2039': '<', '\u203A': '>', '\u00AB': '<', '\u00BB': '>',\n '\u201C': '\"', '\u201D': '\"', '\u201E': '\"', '\u2018': \"'\", '\u2019': \"'\", '\u201A': \"'\",\n '\u2588': '#', '\u2587': '#', '\u2593': '#', '\u2592': '+', '\u2591': '.', '\u25A0': '#', '\u25A1': '.',\n '\u2502': '|', '\u2500': '-', '\u250C': '+', '\u2510': '+', '\u2514': '+', '\u2518': '+', '\u251C': '+',\n '\u2524': '+', '\u252C': '+', '\u2534': '+', '\u253C': '+', '\u00B0': 'o', '\u00A7': 'S', '\u00B6': 'P',\n '\\u00a0': ' ', '\\u2007': ' ', '\\u2009': ' ', '\\u202f': ' ', '\\ufeff': '',\n};\n\n/**\n * Every non-ASCII code point replaced by one that is, without ever making the\n * string longer (measured in characters, which is what a terminal column is).\n * Surrogate pairs count as the one character they display as.\n */\nexport function toAscii(s: string): string {\n // eslint-disable-next-line no-control-regex\n if (!/[^\\x00-\\x7F]/.test(s)) return s;\n let out = '';\n for (const ch of s) {\n if (ch.charCodeAt(0) < 128 && ch.length === 1) { out += ch; continue; }\n const mapped = ASCII_FOLD[ch];\n if (mapped !== undefined) { out += mapped; continue; }\n // `\u00E9` is `e` plus a combining acute; drop the accent and keep the letter.\n const bare = ch.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n // eslint-disable-next-line no-control-regex\n out += bare.length === 1 && !/[^\\x00-\\x7F]/.test(bare) ? bare : '?';\n }\n return out;\n}\n\nconst ANSI_RE = new RegExp('\\\\u001b\\\\[[0-9;]*m', 'g');\n\nexport function stripAnsi(s: string): string {\n return s.replace(ANSI_RE, '');\n}\n\nfunction detectColor(): boolean {\n if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== '') return false;\n if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0') return true;\n if (process.env.TERM === 'dumb') return false;\n return Boolean(process.stdout.isTTY);\n}\n\nfunction detectAscii(): boolean {\n if (process.env.POTSHERD_ASCII === '1') return true;\n const enc = `${process.env.LC_ALL ?? process.env.LC_CTYPE ?? process.env.LANG ?? ''}`;\n if (enc && !/utf-?8/i.test(enc)) return true;\n return false;\n}\n\nfunction detectWidth(): number {\n const cols = process.stdout.columns;\n if (!cols || cols < 40) return 80;\n return Math.min(cols, 100);\n}\n", "/**\n * L2 redaction \u2014 the rule table.\n *\n * ## Provenance (read this before adding a rule)\n *\n * `plans/03-ARCHITECTURE.md` \u00A75 and the reuse table in\n * `plans/02-STRATEGY-AND-VIRALITY.md` are explicit: **port rules, do not write\n * regexes from memory**. Every pattern below is a port of a published,\n * MIT-licensed detection rule, and each rule names its upstream rule id in\n * `source` and in the comment above it.\n *\n * Upstreams:\n *\n * gitleaks \u2014 https://github.com/gitleaks/gitleaks\n * rule pack: `cmd/generate/config/rules/*.go`, published as\n * `config/gitleaks.toml`.\n * Copyright (c) 2019 Zachary Rice. Licensed under the MIT License.\n *\n * secretlint \u2014 https://github.com/secretlint/secretlint\n * rule pack: `@secretlint/secretlint-rule-preset-recommend`, which bundles\n * `-rule-aws`, `-rule-gcp`, `-rule-github`, `-rule-slack`, `-rule-npm`,\n * `-rule-privatekey`, `-rule-basicauth`, `-rule-sendgrid`, `-rule-shopify`.\n * Copyright (c) 2020 Secretlint. Licensed under the MIT License.\n *\n * Neither project's *runtime* is a dependency. secretlint's engine is async,\n * plugin-loading and file-oriented; this module has to be pure, synchronous and\n * cheap enough to run over the whole corpus during `potsherd index`. What is\n * taken is the rule knowledge \u2014 the part that must not be invented. See\n * the header of every rule below. The `NOTICE` entry for both packs lands with\n * T1.5, when this module is first wired into the index.\n *\n * ## What a rule is\n *\n * A scanner over a string returning the spans to mask, a `type` that appears in\n * the mask, and a stable `id`. Rules are applied in array order and the first\n * rule to claim a span wins (see `redact.ts`), so the order here is the\n * precedence order: key material, vendor tokens, credentials in urls, the\n * generic `KEY=` assignment, entropy last.\n *\n * `type` deliberately names a *family* (`aws`, `github`) and not the rule\n * (`aws-access-key-id`): it is user-visible inside the mask, so it stays short,\n * stable and legible in a search result. The rule id rides along on the hit,\n * for `doctor` and for debugging a false positive.\n */\n\n/** The family name that appears in `\u2039redacted:<type>:<sha8>\u203A`. */\nexport type SecretType =\n | 'aws'\n | 'gcp'\n | 'github'\n | 'slack'\n | 'stripe'\n | 'openai'\n | 'anthropic'\n | 'npm'\n | 'jwt'\n | 'private-key'\n | 'basic-auth'\n | 'generic'\n | 'entropy';\n\n/** Every type, in the order `doctor` reports them. */\nexport const SECRET_TYPES: readonly SecretType[] = [\n 'aws',\n 'gcp',\n 'github',\n 'slack',\n 'stripe',\n 'openai',\n 'anthropic',\n 'npm',\n 'jwt',\n 'private-key',\n 'basic-auth',\n 'generic',\n 'entropy',\n] as const;\n\n/** One span of text a rule wants masked. */\nexport interface RuleMatch {\n start: number;\n end: number;\n value: string;\n}\n\nexport interface Rule {\n /** Stable id, reported on the hit and used in tests. */\n id: string;\n type: SecretType;\n /** Upstream rule this was ported from, with its licence. */\n source: string;\n /** Pure: same input, same output, no state carried between calls. */\n scan(text: string): RuleMatch[];\n}\n\n// ---------------------------------------------------------------- entropy\n\n/**\n * Shannon entropy in bits per character. `03` \u00A75 fixes the threshold at 4.5\n * over tokens of \u2265 20 characters.\n *\n * Worth knowing before either number is tuned: entropy measured on a sample of\n * length n cannot exceed log2(n), so a 20-character token can never reach 4.5\n * (log2(20) = 4.32) and nothing shorter than 23 characters can trip this rule\n * at all. That is why 40-char hex git shas (alphabet cap 4.0) and uuids pass\n * through untouched \u2014 the threshold in `03` is self-limiting by design.\n */\nexport function shannonEntropy(s: string): number {\n const n = s.length;\n if (n === 0) return 0;\n const counts = new Map<string, number>();\n for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1);\n let h = 0;\n for (const c of counts.values()) {\n const p = c / n;\n h -= p * Math.log2(p);\n }\n return h;\n}\n\nexport const ENTROPY_MIN_LENGTH = 20;\nexport const ENTROPY_THRESHOLD = 4.5;\n\n// ---------------------------------------------------------------- allowlists\n\n/**\n * Spans that are never a secret and must not be scanned at all. Ported in\n * spirit from gitleaks' `[[rules.allowlist]] regexes` and secretlint's `allows`\n * option (both MIT).\n *\n * A base64 data URI is the worst false positive in a coding transcript: an\n * inlined PNG is tens of kilobytes of maximum-entropy base64 that no rule could\n * tell from a key. It is excluded by construction rather than by lowering a\n * threshold that would then start missing real keys.\n */\nexport const ALLOW_SPANS: RegExp[] = [\n // data: URIs \u2014 `data:image/png;base64,iVBORw0KGgo\u2026`\n /\\bdata:[a-zA-Z0-9!#$&^_.+-]*(?:\\/[a-zA-Z0-9!#$&^_.+-]*)?(?:;[a-zA-Z0-9-]+=[^;,\\s]*)*;base64,[A-Za-z0-9+/=]{20,}(?:\\s+[A-Za-z0-9+/=]{20,})*/g,\n // Subresource Integrity \u2014 `integrity=\"sha384-oqVuAfXRKap7fdgcCY5uykM6+R9\u2026\"`\n /\\bsha(?:256|384|512)-[A-Za-z0-9+/]{20,}={0,3}/g,\n];\n\nconst UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\nconst HEX_RE = /^[0-9a-fA-F]+$/;\nconst NUMERIC_RE = /^[0-9_+-]+$/;\n\n// -------------------------------------------------- entropy-rule exclusions\n//\n// Each of these answers a false-positive class *measured* on the reference\n// corpus by `scripts/redaction-benchmark.mjs`, and each is named and commented\n// so a future reader can audit \u2014 or delete \u2014 one of them on its own merits.\n//\n// The load-bearing property of all of them: they apply **only to a bare token\n// the entropy rule found lying in the text with no context**. A value that is\n// assigned to a secret-named key, sent in an `Authorization` header or put in\n// a url's userinfo is claimed by a rule that runs earlier and never consults\n// this list. So \"exclude uuids\" cannot let `API_KEY=<uuid>` through, and\n// \"exclude `toolu_\u2026`\" cannot let `ANTHROPIC_API_KEY=toolu_\u2026` through. Both are\n// planted cases in `tests/fixtures/secrets/planted.jsonl`.\n\n/**\n * **E1 \u2014 minted object ids.** Model apis and agent harnesses stamp every\n * message, request, tool use and run with a random id under a fixed prefix.\n * They are the densest high-entropy shape in an agent transcript by an order\n * of magnitude \u2014 `toolu_014ZfaccgxvcYNpcTLq8qvkR` and its kin \u2014 and none of\n * them is a credential: they are handed out in api *responses*, they appear in\n * public logs, and they authorise nothing.\n *\n * Prefixes, and who mints them:\n * toolu_ srvtoolu_ msg_ req_ anthropic messages api\n * chatcmpl- fc_ call_ run_ step_\n * thread_ asst_ resp_ evt_ openai\n * exec- exec_ agent- sess_ session_ agent harnesses (claude code, codex)\n * task_ job_ turn_ conv_ snapshot- harness bookkeeping\n *\n * Deliberately *not* here: `sk_`, `rk_`, `ghp_`, `xoxb-`, `npm_`, `AKIA`,\n * `sk-ant-`, `tvly-` \u2014 every one of those prefixes means the opposite.\n */\nconst MINTED_ID_RE =\n /^(?:toolu|srvtoolu|msg|req|resp|call|fc|run|step|thread|asst|evt|sess|session|exec|job|task|turn|conv|agent|snapshot|chatcmpl)[-_]/i;\n\n/**\n * **E5 \u2014 ULIDs.** 26 characters of Crockford base32, the first 10 encoding a\n * millisecond timestamp. log2(26) = 4.70, so a ULID can and does clear the 4.5\n * bar. Sortable ids, not secrets; the alphabet excludes I, L, O and U on\n * purpose, which is what makes the shape recognisable.\n */\nconst ULID_RE = /^[0-7][0-9ABCDEFGHJKMNPQRSTVWXYZ]{25}$/;\n\n/**\n * **E6 \u2014 prose wearing a token's clothes.** The single largest surviving false\n * positive on the reference corpus once images were elided: url slugs.\n *\n * \u2026%2Fy-combinator_reducto-has-just-raised-a-75m-series-b-activity-7383909473913880576-ba7M\n *\n * That is 87 characters over a wide alphabet, so its Shannon entropy is 4.9 \u2014\n * comfortably \"random\" by the measure in `03` \u00A75 \u2014 and it is a LinkedIn\n * permalink. Shannon entropy on a single short sample cannot tell *random*\n * from *varied*, and English is very varied.\n *\n * What separates them is **runs**. A base64 or base62 credential draws each\n * character independently, so a run of 7 consecutive same-case letters has\n * probability \u2248 (26/64)^7 \u2248 1 in 900 per position; two disjoint such runs in\n * one 40-character token is well under 1%. English words are nothing but such\n * runs \u2014 `combinator`, `activity`, `whatsapp`, `killmonger`.\n *\n * So: two runs of \u2265 7 same-case letters, or one run of \u2265 12, and the token is\n * text. Both numbers were checked against the corpus rather than chosen: at\n * \u2265 7/\u00D72 every tavily key, every planted secret and every base64 fixture value\n * survives (their longest same-case run is 4), and the slug class disappears.\n */\nconst SAMECASE_RUN_MIN = 7;\nconst SAMECASE_RUNS_NEEDED = 2;\nconst SAMECASE_RUN_ALONE = 12;\n\nfunction looksLikeProse(token: string): boolean {\n let long = 0;\n for (const run of token.match(/[a-z]+|[A-Z]+/g) ?? []) {\n if (run.length >= SAMECASE_RUN_ALONE) return true;\n if (run.length >= SAMECASE_RUN_MIN) long += 1;\n }\n return long >= SAMECASE_RUNS_NEEDED;\n}\n\n/**\n * **E7 \u2014 alphabet constants.** `0123456789ABCDEFGHJKMNPQRSTVWXYZ` is the\n * Crockford base32 table; every base32/base58/base62 encoder in every codebase\n * declares one, and with no repeated character it scores a perfect log2(n)\n * entropy \u2014 the highest possible.\n *\n * The test is exactly \"no character occurs twice\". Drawing 24 characters from\n * a 62-character alphabet without a single repeat happens with probability\n * \u2248 1%, and from base64url's 64 with probability \u2248 1.4%; combined with the\n * 24-character floor and with the fact that a credential in any real context\n * is claimed by an earlier rule, this is a safe trade for a class that is\n * otherwise permanently unmaskable-looking.\n */\nfunction looksLikeAlphabetConstant(token: string): boolean {\n return token.length >= 24 && new Set(token).size === token.length;\n}\n\n/**\n * Placeholder values. Ported from gitleaks' `stopwords` list and secretlint's\n * dummy-value handling, trimmed to the ones that actually occur in coding\n * transcripts. A value matching this is documentation, not a credential.\n */\nconst PLACEHOLDER_RE =\n /(?:^|[^a-z0-9])(?:x{3,}|your|my[-_]?(?:key|token|secret|pass)|example|sample|dummy|fake|mock|placeholder|change[-_]?(?:me|it|this)|replace[-_]?me|insert|todo|fixme|redacted|hidden|omitted|elided|not[-_]?real|no[-_]?such|hunter2|password|passwd|secret|token|apikey|api[-_]key|abcdef|123456|s3cret|letmein|foobar|lorem|ipsum)(?:$|[^a-z0-9])/i;\n\n/** `${VAR}`, `{{var}}`, `%(var)s`, `<%= x %>`, `<your-key>`, `$VAR` \u2026 */\nconst INTERPOLATION_RE = /\\$\\{|\\{\\{|%\\(|<%|^\\$[A-Za-z_(]|^<|^\\{|\\}$|^%[A-Za-z(]/;\n\n/** A reference to a value rather than the value: `process.env.X`, `cfg.token`. */\nconst REFERENCE_RE =\n /^(?:process\\.env|import\\.meta\\.env|os\\.environ|System\\.getenv|Deno\\.env|env|ENV|config|conf|cfg|settings|opts|options|args|argv|params|props|state|data|input|payload|body|req|res|ctx|context|self|this|that|obj|row|item|user|account|creds|credentials|secrets|vault|store|keychain)\\b\\s*[.[(]/;\n\n/** A bare word with no digits \u2014 `hashedPassword`, `MY_SECRET`, `undefined`. */\nconst WORDY_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z_$]*$/;\n\n/**\n * A dotted identifier chain \u2014 `crypto.randomBytes`, `formData.password`,\n * `settings.auth.token`. Code reaching for a value, not the value. Base64,\n * base64url and hex credentials never contain a `.`, and the ones that do\n * (jwts) have a rule of their own that runs first.\n */\nconst DOTTED_CHAIN_RE = /^[A-Za-z_$][A-Za-z0-9_$]*(?:\\.[A-Za-z_$][A-Za-z0-9_$]*)+$/;\n\n/** A url or a filesystem path, not a credential. */\nconst PATHISH_RE = /^(?:[a-z][a-z0-9+.-]*:\\/\\/|\\.{0,2}\\/|~\\/|[A-Za-z]:\\\\)/;\n\n/** Syntax that means the capture ran into code, not into a credential. */\nconst CODEY_RE = /[<>{}[\\]()|\\\\;,&?!*\"'`]/;\n\n/** The mask itself, so a second pass recognises its own output. */\nexport const MASK_FRAGMENT_RE = /\u2039redacted:/;\n\n/** English words ending in a keyword that never name a secret. */\nconst NAME_STOPWORDS = new Set([\n 'monkey',\n 'donkey',\n 'turkey',\n 'whiskey',\n 'jockey',\n 'hockey',\n 'lackey',\n 'mickey',\n 'malarkey',\n 'hotkey',\n 'sortkey',\n 'oauth',\n]);\n\n/**\n * Does this identifier name a secret? `apiKey`, `AWS_SECRET_ACCESS_KEY`,\n * `db.password`, `client_secret` yes; `tokenizer`, `keyboard`, `monkey` no.\n *\n * Ported from the keyword half of gitleaks' `generic-api-key` and tightened:\n * that rule allows the keyword anywhere inside a 50-character identifier, which\n * flags every `tokenizer:` and `keyboardShortcut:` line in a transcript. Here\n * the keyword has to be the identifier's last segment, splitting on `_ - . $`\n * and on camelCase humps.\n */\nexport function nameLooksLikeSecret(name: string): boolean {\n const segments = name\n .split(/[^A-Za-z0-9]+/)\n .flatMap((part) => part.split(/(?<=[a-z0-9])(?=[A-Z])/))\n .filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) return false;\n const lower = last.toLowerCase();\n if (NAME_STOPWORDS.has(lower)) return false;\n return /(?:key|token|secret|password|passwd|pwd|credential|auth)s?$/.test(lower);\n}\n\n/**\n * Is this assignment's value plausibly a real credential?\n *\n * The generic `KEY=` rule is where false positives come from, because every\n * codebase assigns to something called `token`. Everything rejected here is\n * something transcripts are full of: env lookups, template interpolations,\n * references to another variable, documentation placeholders, type\n * annotations, version numbers, paths.\n */\nexport function valueLooksLikeSecret(value: string): boolean {\n const v = value.trim();\n if (v.length < 10 || v.length > 200) return false;\n if (/\\s/.test(v)) return false;\n if (MASK_FRAGMENT_RE.test(v)) return false;\n if (CODEY_RE.test(v)) return false;\n if (INTERPOLATION_RE.test(v)) return false;\n if (REFERENCE_RE.test(v)) return false;\n if (DOTTED_CHAIN_RE.test(v)) return false;\n if (PATHISH_RE.test(v)) return false;\n if (NUMERIC_RE.test(v)) return false;\n if (PLACEHOLDER_RE.test(v)) return false;\n // A bare word with no digits is a variable name or a sentence fragment, not\n // a 32-character credential.\n if (WORDY_IDENTIFIER_RE.test(v) && shannonEntropy(v) < 4.0) return false;\n // Filler: `****`, `------`, `0000000000`.\n if (new Set(v).size <= 2) return false;\n // gitleaks' generic-api-key requires 3.5 bits on the captured value. 3.2\n // here: potsherd masks a token in an index rather than failing a build, so a\n // marginal hit costs one unreadable word in a search result and a marginal\n // miss costs a leaked credential.\n if (shannonEntropy(v) < 3.2) return false;\n return true;\n}\n\n/**\n * Entropy-rule allowlist: shapes that are high-entropy but never secret.\n *\n * Every `return false` is an exclusion rule with a letter, defined above with\n * the class it was measured against. Read the block comment there before\n * adding, removing or relaxing one.\n *\n * This is consulted **only** by the bare-token entropy rule. It is not part of\n * `valueLooksLikeSecret`, so nothing here can excuse a value that appears in a\n * credential-shaped position.\n */\nexport function entropyCandidateAllowed(token: string): boolean {\n if (token.length < ENTROPY_MIN_LENGTH) return false;\n // E2 \u2014 uuids. Session ids, request ids, trace ids. Capped at 4.0 bits by\n // their alphabet anyway; excluded explicitly so the intent is readable.\n if (UUID_RE.test(token)) return false;\n // E2b \u2014 a uuid under a prefix: `exec-<uuid>`, `agent-<uuid>`, `snapshot-\u2026`.\n if (UUID_RE.test(token.replace(/^[A-Za-z][A-Za-z0-9]{0,15}[-_]/, ''))) return false;\n // E3 \u2014 hex digests: git sha1s, sha256 sums, md5s, content hashes.\n if (HEX_RE.test(token)) return false;\n // E4 \u2014 a hex digest under a prefix (`sha256-\u2026` without the SRI base64 body,\n // `blake3-\u2026`, `md5-\u2026`). The base64 SRI form is an ALLOW_SPAN, above.\n if (/^(?:sha1|sha256|sha384|sha512|md5|blake3|crc32|xxh64)[-_:]/i.test(token)) return false;\n if (NUMERIC_RE.test(token)) return false;\n if (MASK_FRAGMENT_RE.test(token)) return false;\n if (PLACEHOLDER_RE.test(token)) return false;\n if (MINTED_ID_RE.test(token)) return false; // E1\n if (ULID_RE.test(token)) return false; // E5\n if (looksLikeProse(token)) return false; // E6\n if (looksLikeAlphabetConstant(token)) return false; // E7\n return true;\n}\n\n// ---------------------------------------------------------------- machinery\n\ninterface RegexRuleOptions {\n /** Capture group holding the bytes to mask. 0 = the whole match. */\n group?: number;\n /** Reject a candidate; returning false leaves the text untouched. */\n validate?: (value: string, m: RegExpExecArray) => boolean;\n}\n\n/** Build a scanning rule from one global regex. */\nfunction regexRule(\n id: string,\n type: SecretType,\n source: string,\n re: RegExp,\n opts: RegexRuleOptions = {},\n): Rule {\n const group = opts.group ?? 0;\n return {\n id,\n type,\n source,\n scan(text: string): RuleMatch[] {\n const out: RuleMatch[] = [];\n // A fresh regex per scan: a module-level `lastIndex` is shared state and\n // this module promises purity.\n const rx = new RegExp(re.source, re.flags.includes('g') ? re.flags : re.flags + 'g');\n let m: RegExpExecArray | null;\n while ((m = rx.exec(text)) !== null) {\n if (m[0].length === 0) { rx.lastIndex++; continue; }\n const value = group === 0 ? m[0] : m[group];\n if (value === undefined || value.length === 0) continue;\n if (opts.validate && !opts.validate(value, m)) continue;\n const offset = group === 0 ? 0 : m[0].indexOf(value);\n if (offset < 0) continue;\n out.push({ start: m.index + offset, end: m.index + offset + value.length, value });\n }\n return out;\n },\n };\n}\n\n// ---------------------------------------------------------------- the rules\n\n/**\n * The generic `(KEY|TOKEN|SECRET|PASSWORD)\\s*[=:]` rule from `03` \u00A75, given the\n * shape of gitleaks' `generic-api-key`.\n *\n * It is written as a scanner rather than one regex for two reasons. Speed: a\n * pattern of the form `identifier{0,48}(keyword)[:=]` has to be retried at\n * every letter of a 10 MB corpus, while anchoring on the literal keyword lets\n * the engine skip. Correctness: only the *value* is masked, never the name, so\n * `TOKEN=\u2039redacted:generic:\u2026\u203A` still tells a reader which variable leaked.\n */\nconst GENERIC_ANCHOR =\n /(?:key|token|secret|password|passwd|pwd|credential|auth)s?[\"']?[ \\t]*(?::=|=>|[:=])/gi;\n\nconst GENERIC_VALUE =\n // The bare alternative stops at a backslash on purpose: transcripts carry\n // json-escaped text, where `TOKEN=abc\\nNEXT=\u2026` is one line and the `\\n` is\n // two literal characters. Without this the capture swallows the rest of the\n // record and the value is thrown out as code.\n /[ \\t]*(?:\"([^\"\\r\\n]{10,200})\"|'([^'\\r\\n]{10,200})'|`([^`\\r\\n]{10,200})`|([^\\s\"'`,;)\\](}>\\\\]{10,200}))/y;\n\nconst NAME_CHAR_RE = /[A-Za-z0-9_$.-]/;\n\nconst genericAssignmentRule: Rule = {\n id: 'generic-assignment',\n type: 'generic',\n source: '03 \u00A75, given the shape of gitleaks generic-api-key (MIT)',\n scan(text: string): RuleMatch[] {\n const out: RuleMatch[] = [];\n const anchor = new RegExp(GENERIC_ANCHOR.source, GENERIC_ANCHOR.flags);\n let m: RegExpExecArray | null;\n while ((m = anchor.exec(text)) !== null) {\n const opEnd = m.index + m[0].length;\n const opLen = /(?::=|=>)$/.test(m[0]) ? 2 : 1;\n const before = text[opEnd - opLen - 1] ?? '';\n // `==`, `===`, `!=`, `<=`, `>=`, `+=` are comparisons and compound\n // assignment, not `TOKEN=\u2026`.\n if (text[opEnd] === '=' || (opLen === 1 && /[!<>+\\-*/%&|^=]/.test(before))) continue;\n\n // Walk back over the identifier the keyword ends: `AWS_SECRET_ACCESS_KEY`.\n const keywordEnd = m.index + m[0].replace(/[\"']?[ \\t]*(?::=|=>|[:=])$/, '').length;\n let nameStart = m.index;\n while (nameStart > 0 && NAME_CHAR_RE.test(text[nameStart - 1] ?? '')) nameStart--;\n const name = text.slice(nameStart, keywordEnd);\n if (!nameLooksLikeSecret(name)) continue;\n\n GENERIC_VALUE.lastIndex = opEnd;\n const v = GENERIC_VALUE.exec(text);\n if (!v) continue;\n const value = v[1] ?? v[2] ?? v[3] ?? v[4];\n if (value === undefined || !valueLooksLikeSecret(value)) continue;\n const start = v.index + v[0].lastIndexOf(value);\n out.push({ start, end: start + value.length, value });\n anchor.lastIndex = start + value.length;\n }\n return out;\n },\n};\n\n/** Explicit socket-auth command arguments are credential context, not hashes. */\nconst socketAuthRule:Rule={\n id:'socket-auth-argument',type:'generic',source:'03 \u00A75 credential context',\n scan(text:string):RuleMatch[]{const out:RuleMatch[]=[];const anchor=/(?:^|[\\s\"'`])--socket-auth[\"']?(?:[ \\t]*=[ \\t]*|[ \\t]+)/gi;let match:RegExpExecArray|null;\n while((match=anchor.exec(text))!==null){GENERIC_VALUE.lastIndex=anchor.lastIndex;const found=GENERIC_VALUE.exec(text);if(!found)continue;const value=found[1]??found[2]??found[3]??found[4];if(value===undefined||!valueLooksLikeSecret(value))continue;const start=found.index+found[0].lastIndexOf(value);out.push({start,end:start+value.length,value});anchor.lastIndex=start+value.length;}\n return out;}\n};\n\n/**\n * `Authorization: Bearer <token>` \u2014 a credential *context* rather than a\n * credential *shape*.\n *\n * The rule exists to make the entropy exclusions above safe to hold. They all\n * assume that a value in a position that shouts \"credential\" is claimed by an\n * earlier rule; `KEY=`, `?token=` and `https://user:pw@` were already covered,\n * and the http authorization header was the hole. It matters more now than it\n * did before T1.4b: a `Bearer toolu_\u2026`-shaped token is excluded by E1 as a\n * bare token, and must not be excluded here.\n *\n * The name is not masked, only the credential, so a redacted transcript still\n * says which scheme was used.\n */\nconst BEARER_RE =\n /(?:^|[^A-Za-z0-9_-])(?:Bearer|Token|ApiKey|Api-Key|Basic|DPoP)[ \\t]+([A-Za-z0-9+/._~-]{16,512}={0,2})/g;\n\nconst bearerRule: Rule = regexRule(\n 'authorization-bearer',\n 'generic',\n '03 \u00A75 (credential context), given the shape of gitleaks generic-api-key (MIT)',\n BEARER_RE,\n {\n group: 1,\n // Same value screen as the `KEY=` rule: `Bearer ${token}`, `Bearer <TOKEN>`\n // and `Bearer your-token-here` are documentation, not credentials.\n validate: (value) => valueLooksLikeSecret(value),\n },\n);\n\n/**\n * The entropy rule from `03` \u00A75 \u2014 \u2265 4.5 bits over tokens of \u2265 20 characters \u2014\n * written as a scanner rather than as one regex.\n *\n * `03` fixes the threshold and the length floor and both are honoured\n * unchanged. What T1.4b changed is **what counts as a token**, because that\n * was never specified and the naive reading was doing the damage:\n *\n * 1. `=` is base64 *padding*, so it is only a token character at the end.\n * Before, `ANTHROPIC_VERTEX_PROJECT_ID=example-project` was one\n * \"token\" \u2014 a variable glued to its value \u2014 and scored 4.7.\n * 2. `/` and `.` remain separators, so a long path or a dotted hostname is\n * not one token. (Unchanged from T1.4; the reasoning is that a real\n * base64 secret containing `/` still leaves a \u2265 23-character run, and 23\n * is the shortest string that can reach 4.5 bits at all.)\n * 3. Transcripts are json-inside-json, so the text often carries a *literal*\n * backslash-n where a newline belongs. `\\ntvly-dev-\u2026` used to yield the\n * token `ntvly-dev-\u2026` \u2014 the same secret with a different first character,\n * and therefore a different sha8 and a different mask. Escape residue is\n * trimmed, which is a correctness fix for the \"same secret, same mask\"\n * guarantee and not only a cosmetic one.\n * 4. Percent-escape residue (`%2F` leaving `2F\u2026`) and leading/trailing\n * separators are trimmed for the same reason.\n *\n * Shape exclusions live in {@link entropyCandidateAllowed}.\n */\nconst ENTROPY_TOKEN = /[A-Za-z0-9+_-]{20,}={0,2}/g;\n\n/** Characters a `\\x` json escape leaves glued to the front of a token. */\nconst ESCAPE_LETTERS = 'ntrbfv';\n\nconst highEntropyRule: Rule = {\n id: 'high-entropy-token',\n type: 'entropy',\n source: '03 \u00A75 (4.5 bits / 20 chars) + gitleaks entropy allowlists (MIT)',\n scan(text: string): RuleMatch[] {\n const out: RuleMatch[] = [];\n const rx = new RegExp(ENTROPY_TOKEN.source, ENTROPY_TOKEN.flags);\n let m: RegExpExecArray | null;\n while ((m = rx.exec(text)) !== null) {\n let start = m.index;\n let value = m[0];\n // `\\n`, `\\t`, `\\r` written literally by an outer json encoder.\n if (start > 0 && text[start - 1] === '\\\\' && ESCAPE_LETTERS.includes(value[0] ?? '')) {\n start += 1;\n value = value.slice(1);\n }\n // `%2F`, `%3D` \u2014 the `%` is a separator, but the two hex digits that\n // complete the escape are not part of the token that follows it.\n if (start > 0 && text[start - 1] === '%' && /^[0-9A-Fa-f]{2}/.test(value)) {\n start += 2;\n value = value.slice(2);\n }\n // Leading and trailing separators belong to the surrounding text.\n const lead = value.length - value.replace(/^[-_+]+/, '').length;\n start += lead;\n value = value.slice(lead).replace(/[-_+]+$/, '');\n\n if (value.length < ENTROPY_MIN_LENGTH) continue;\n if (!entropyCandidateAllowed(value)) continue;\n if (shannonEntropy(value) < ENTROPY_THRESHOLD) continue;\n out.push({ start, end: start + value.length, value });\n }\n return out;\n },\n};\n\nexport const RULES: Rule[] = [\n // ---- key material ------------------------------------------------------\n regexRule(\n // gitleaks `private-key`; secretlint `@secretlint/secretlint-rule-privatekey`.\n // The whole block is masked, header to footer: the base64 body alone would\n // otherwise be shredded into a dozen separate entropy hits.\n 'private-key-block',\n 'private-key',\n 'gitleaks private-key / secretlint-rule-privatekey (MIT)',\n /-----BEGIN[ A-Z0-9]{0,40}PRIVATE KEY(?: BLOCK)?-----[\\s\\S]{0,200000}?-----END[ A-Z0-9]{0,40}PRIVATE KEY(?: BLOCK)?-----/g,\n ),\n regexRule(\n // gitleaks `private-key`, unterminated variant: a transcript often quotes\n // the header and the first body lines and then elides the rest.\n //\n // The body is taken line by line and only where a line is \u2265 20 characters\n // of pure base64, so an unterminated header followed by prose masks the\n // header alone instead of swallowing the sentence after it. The separator\n // class carries the backslash so json-escaped `\\n` works, and it is\n // disjoint from the base64 class, which is what keeps this linear.\n 'private-key-header',\n 'private-key',\n 'gitleaks private-key (MIT)',\n /-----BEGIN[ A-Z0-9]{0,40}PRIVATE KEY(?: BLOCK)?-----(?:[\\r\\n \\t\\\\]+[A-Za-z0-9+/=]{20,})*/g,\n ),\n regexRule(\n // gitleaks `jwt`: three base64url segments, the first two starting `ey`\n // (the base64 of `{\"`). Session transcripts are full of these.\n 'jwt',\n 'jwt',\n 'gitleaks jwt (MIT)',\n /\\bey[A-Za-z0-9_-]{17,}\\.ey[A-Za-z0-9_-]{17,}\\.[A-Za-z0-9_-]{10,}={0,2}/g,\n ),\n\n // ---- vendor tokens -----------------------------------------------------\n regexRule(\n // gitleaks `aws-access-token`; secretlint-rule-aws `AWSAccessKeyID`.\n 'aws-access-key-id',\n 'aws',\n 'gitleaks aws-access-token / secretlint-rule-aws (MIT)',\n /\\b(?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}\\b/g,\n ),\n regexRule(\n // secretlint-rule-aws `AWSSecretAccessKey`: a 40-character base64 value\n // bound to an AWS-flavoured name. Typed `aws` and placed before the generic\n // rule so `doctor` reports it as what it is.\n 'aws-secret-access-key',\n 'aws',\n 'secretlint-rule-aws AWSSecretAccessKey (MIT)',\n /aws[_.-]?(?:secret|access)[_.-]?(?:access[_.-]?)?key(?:[_.-]?id)?[\"'\\s]{0,4}[:=][\"'\\s]{0,4}([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi,\n { group: 1 },\n ),\n regexRule(\n // gitleaks `gcp-api-key`; secretlint-rule-gcp `GCPApiKey`.\n 'gcp-api-key',\n 'gcp',\n 'gitleaks gcp-api-key / secretlint-rule-gcp (MIT)',\n /\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n ),\n regexRule(\n // gitleaks `gcp-oauth-client-secret`.\n 'gcp-oauth-client-secret',\n 'gcp',\n 'gitleaks gcp-oauth-client-secret (MIT)',\n /\\bGOCSPX-[a-zA-Z0-9_-]{28}\\b/g,\n ),\n regexRule(\n // gitleaks `github-pat` / `-oauth` / `-app-token` / `-refresh-token`;\n // secretlint-rule-github. ghp_ user, gho_ oauth, ghu_/ghs_ app, ghr_ refresh.\n 'github-token',\n 'github',\n 'gitleaks github-pat / secretlint-rule-github (MIT)',\n /\\bgh[pousr]_[A-Za-z0-9]{36,255}\\b/g,\n ),\n regexRule(\n // gitleaks `github-fine-grained-pat`.\n 'github-fine-grained-pat',\n 'github',\n 'gitleaks github-fine-grained-pat (MIT)',\n /\\bgithub_pat_[0-9a-zA-Z_]{82}\\b/g,\n ),\n regexRule(\n // gitleaks `slack-bot-token` / `-user-token` / `-app-token`;\n // secretlint-rule-slack.\n 'slack-token',\n 'slack',\n 'gitleaks slack-bot-token / secretlint-rule-slack (MIT)',\n /\\bxox[abprs]-[0-9a-zA-Z-]{10,72}\\b/g,\n ),\n regexRule(\n // gitleaks `slack-webhook-url`; secretlint-rule-slack `SlackWebhook`.\n 'slack-webhook',\n 'slack',\n 'gitleaks slack-webhook-url (MIT)',\n /https:\\/\\/hooks\\.slack\\.com\\/(?:services|workflows|triggers)\\/[A-Za-z0-9+/]{6,}\\/[A-Za-z0-9+/]{6,}\\/[A-Za-z0-9+/]{6,}/g,\n ),\n regexRule(\n // gitleaks `stripe-access-token`. `pk_` publishable keys are public by\n // design and are deliberately not matched.\n 'stripe-key',\n 'stripe',\n 'gitleaks stripe-access-token (MIT)',\n /\\b(?:sk|rk)_(?:test|live|prod)_[A-Za-z0-9]{10,99}\\b/g,\n ),\n regexRule(\n // gitleaks `anthropic-api-key`. Must precede the openai rules: both start\n // `sk-`, and whichever rule claims the span first wins.\n 'anthropic-api-key',\n 'anthropic',\n 'gitleaks anthropic-api-key (MIT)',\n /\\bsk-ant-(?:api|admin)[0-9]{2}-[A-Za-z0-9_-]{80,120}\\b/g,\n ),\n regexRule(\n // gitleaks `openai-api-key`: the `T3BlbkFJ` infix is the base64 of\n // \"OpenAI\" and is what makes this rule safe to run over prose.\n 'openai-api-key-project',\n 'openai',\n 'gitleaks openai-api-key (MIT)',\n /\\bsk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{20,}T3BlbkFJ[A-Za-z0-9_-]{20,}\\b/g,\n ),\n regexRule(\n // gitleaks `openai-api-key`, legacy 48-character form with no infix.\n 'openai-api-key-legacy',\n 'openai',\n 'gitleaks openai-api-key (MIT)',\n /\\bsk-[A-Za-z0-9]{48}\\b/g,\n ),\n regexRule(\n // gitleaks `npm-access-token`; secretlint-rule-npm.\n 'npm-access-token',\n 'npm',\n 'gitleaks npm-access-token / secretlint-rule-npm (MIT)',\n /\\bnpm_[A-Za-z0-9]{36}\\b/g,\n ),\n\n // ---- credentials in urls -----------------------------------------------\n regexRule(\n // gitleaks `authenticated-url`; secretlint `-rule-basicauth`. Only the\n // password is masked: `postgres://app:\u2039redacted:basic-auth:\u2026\u203A@db:5432/x`\n // still says which host and which user, which is the point of an index that\n // stays searchable by shape.\n 'basic-auth-url',\n 'basic-auth',\n 'gitleaks authenticated-url / secretlint-rule-basicauth (MIT)',\n // The user half is `{0,64}`: `redis://:hunter2@host` has an empty user and\n // is exactly as leaked as the two-part form.\n /\\b[a-zA-Z][a-zA-Z0-9+.-]{1,20}:\\/\\/[^\\s:@/]{0,64}:([^\\s:@/]{1,128})@/g,\n {\n group: 1,\n validate: (value) => {\n if (INTERPOLATION_RE.test(value)) return false;\n if (PLACEHOLDER_RE.test(value)) return false;\n if (MASK_FRAGMENT_RE.test(value)) return false;\n if (/^(?:pass|pw|user|admin|root|test|guest|\\*+|x+|\\d{1,4})$/i.test(value)) return false;\n return true;\n },\n },\n ),\n\n // ---- credential context (03 \u00A75) ----------------------------------------\n bearerRule,\n genericAssignmentRule,\n socketAuthRule,\n\n // ---- entropy (03 \u00A75) ---------------------------------------------------\n // Last, so that anything a named rule understands is reported under its real\n // type and a bare token is the fallback rather than the default.\n highEntropyRule,\n];\n", "/**\n * Binary elision \u2014 the pass that runs **before** the redactor.\n *\n * ## Why this exists\n *\n * T1.4 landed the redactor and `potsherd index --full` promptly reported\n * *165,088 secrets masked* over 1,406 exchanges. Measuring where they were\n * (`scripts/redaction-benchmark.mjs`) settled it: 98.6% were in `tool_calls`,\n * and the single worst tool call was a **589 KB base64 JPEG** pasted into a\n * `Read` result, which alone produced 5,660 entropy hits.\n *\n * That is not a miscalibrated entropy rule. It is a picture. No secret scanner\n * ever written can look at 589 KB of base64 and tell you which 40 characters\n * of it are a credential, because none of them are \u2014 it is a JPEG. The fix is\n * not to make the detector blinder; it is to stop feeding it images.\n *\n * The codex adapter already established the convention for exactly this\n * problem (`adapters/codex.ts`, \"Trap 3\"): a binary payload becomes a short\n * marker, `\u2039elided:image/png:109362 bytes\u203A`. Its regex only recognises\n * `data:\u2026;base64,\u2026` URIs, which is the shape codex writes. Claude Code writes\n * the Anthropic content-block shape instead \u2014\n *\n * [{\"type\":\"image\",\"source\":{\"type\":\"base64\",\"data\":\"/9j/4AAQ\u2026\",\"media_type\":\"image/jpeg\"}}]\n *\n * \u2014 which that regex never sees. This module generalises the convention to\n * both shapes, plus to a bare base64 run that announces itself with a file\n * magic, and is called from `ingest.ts` on the way into the store, before\n * `redactExchange`.\n *\n * ## Why it is safe to run before redaction\n *\n * Every shape elided here is identified by something a *credential never has*:\n * a `data:` URI scheme, an image content-block wrapper, or the base64 of a\n * file-format magic number. A 40-character AWS secret is not a JPEG header,\n * and the {@link MIN_PAYLOAD} floor of 512 base64 characters is far above any\n * credential that has ever been issued. PEM private-key bodies are longer than\n * that but begin `MII\u2026` / `b3Blb\u2026` and carry a `-----BEGIN` header, so they\n * match no magic here and reach the redactor intact \u2014 `tests/redact.test.ts`\n * holds that case.\n *\n * The marker uses the same guillemets as the mask (`\u2039` U+2039, `\u203A` U+203A) and\n * for the same reason: those characters cannot occur in base64, in a shell\n * token or in a json key, so an elision can never be confused for content and\n * a second pass recognises its own output.\n *\n * Elision is **not** redaction and does not pretend to be. It removes bulk\n * that carries no meaning for retrieval; the redactor still runs afterwards\n * over everything that survives, and there is still no `--no-redact` flag.\n */\n\nimport type { Exchange, ExchangeToolCall } from './adapters/types.js';\n\n/** What one pass threw away, so a caller can say it out loud. */\nexport interface Elisions {\n /** Binary payloads replaced by a marker. */\n binaryParts: number;\n /** Characters dropped. */\n charsElided: number;\n}\n\nexport function emptyElisions(): Elisions {\n return { binaryParts: 0, charsElided: 0 };\n}\n\nexport function addElisions(a: Elisions, b: Elisions): Elisions {\n return {\n binaryParts: a.binaryParts + b.binaryParts,\n charsElided: a.charsElided + b.charsElided,\n };\n}\n\n/**\n * The shortest base64 run this module will elide, in characters. 512 base64\n * characters is 384 bytes.\n *\n * Chosen to sit far above every credential shape in `redact-rules.ts` \u2014 the\n * longest is an anthropic key at ~120 characters \u2014 so raising this floor can\n * never be the reason a secret is missed. A \"binary payload\" smaller than this\n * is not worth a marker anyway.\n */\nexport const MIN_PAYLOAD = 512;\n\n/** Matches this module's own marker, so a second pass is a no-op. */\nexport const ELISION_RE = /\u2039elided:[^\u203A]{1,120}\u203A/g;\n\n/**\n * base64 of the first bytes of a file format, longest prefix first.\n *\n * A base64 payload that starts with one of these *is* that file: base64 is a\n * fixed 3-bytes-to-4-characters encoding with no header of its own, so the\n * leading characters are a faithful transcription of the leading bytes, which\n * for every format below is a magic number the format spec mandates.\n *\n * Only formats that actually turn up pasted into an agent transcript are here.\n * Adding one is cheap; guessing one is not, so each names the bytes it encodes.\n */\nconst BASE64_MAGIC: Array<[prefix: string, mime: string, bytes: string]> = [\n ['iVBORw0KGgo', 'image/png', '89 50 4E 47 0D 0A 1A 0A'],\n ['/9j/', 'image/jpeg', 'FF D8 FF (JFIF/Exif SOI)'],\n ['R0lGODdh', 'image/gif', 'GIF87a'],\n ['R0lGODlh', 'image/gif', 'GIF89a'],\n ['Qk0', 'image/bmp', '42 4D (\"BM\")'],\n ['SUkqAA', 'image/tiff', '49 49 2A 00 (little-endian TIFF)'],\n ['TU0AK', 'image/tiff', '4D 4D 00 2A (big-endian TIFF)'],\n ['AAABAA', 'image/x-icon', '00 00 01 00 (ICO)'],\n ['UklGR', 'application/octet-stream', '52 49 46 46 (\"RIFF\" \u2014 webp/wav/avi)'],\n ['JVBERi0', 'application/pdf', '25 50 44 46 2D (\"%PDF-\")'],\n ['UEsDB', 'application/zip', '50 4B 03 04 (\"PK\\\\x03\\\\x04\" \u2014 zip/docx/xlsx)'],\n ['H4sI', 'application/gzip', '1F 8B 08'],\n ['SUQz', 'audio/mpeg', '49 44 33 (\"ID3\")'],\n ['T2dnU', 'application/ogg', '4F 67 67 53 (\"OggS\")'],\n ['d09GRg', 'font/woff', '77 4F 46 46 (\"wOFF\")'],\n ['d09GMg', 'font/woff2', '77 4F 46 32 (\"wOF2\")'],\n ['AAEAAA', 'font/ttf', '00 01 00 00 (TrueType)'],\n ['T1RUTw', 'font/otf', '4F 54 54 4F (\"OTTO\")'],\n];\n\n/** A payload character: base64, plus the `\\/` a json encoder writes for `/`. */\nconst B64_RUN = `(?:[A-Za-z0-9+/=]|\\\\\\\\/)`;\n\n/**\n * A payload, possibly hard-wrapped.\n *\n * Whitespace is tolerated *only between two long chunks*. Allowing it as a\n * plain payload character is the obvious way to write this and it is wrong:\n * `<900 characters of png>\\ndone` is then a single run, and the elision eats\n * the word after the payload. Requiring a continuation to be \u2265 40 characters\n * means prose on the next line ends the run instead of joining it.\n */\nconst B64_BODY = `${B64_RUN}{40,}(?:[\\\\r\\\\n \\\\t]+${B64_RUN}{40,})*`;\n\n/**\n * `data:image/png;base64,\u2026` \u2014 the shape the codex adapter already elides,\n * kept identical here so the two passes agree and the second is a no-op.\n */\nconst DATA_URI = new RegExp(\n `data:([a-zA-Z0-9.+-]+/[a-zA-Z0-9.+-]+)?(?:;[a-zA-Z0-9.+=-]+)*;base64,${B64_BODY}`,\n 'g',\n);\n\n/**\n * The Anthropic / OpenAI image **content block**, as the parser stringifies it\n * into `tool_calls.result`:\n *\n * {\"type\":\"image\",\"source\":{\"type\":\"base64\",\"data\":\"/9j/4AAQ\u2026\",\"media_type\":\"image/jpeg\"}}\n *\n * `media_type` may sit either side of `data` (both orders occur in the real\n * corpus), so the mime is recovered by a second look rather than by trying to\n * write one regex that matches both. The payload key is the union of the keys\n * the shapes in the wild use: `data` (anthropic), `image_data`, `b64_json`\n * (openai images), `base64`.\n *\n * The `\"base64\"` / `media_type` context is *required*: without it this would\n * be \"elide any long string called data\", which would swallow a base64\n * credential posted in a json body. That case is a planted fixture.\n */\nconst CONTENT_BLOCK = new RegExp(\n `\"(?:data|image_data|b64_json|base64)\"\\\\s*:\\\\s*\"(${B64_BODY})\"`,\n 'g',\n);\n\n/** `\"media_type\":\"image/jpeg\"`, `\"mimeType\": \"image/png\"`, `\"type\":\"base64\"`. */\nconst MEDIA_HINT = /\"(?:media_?type|mime_?type|mimeType)\"\\s*:\\s*\"([a-zA-Z0-9.+-]+\\/[a-zA-Z0-9.+-]+)\"|\"type\"\\s*:\\s*\"base64\"/gi;\n\n/** How far either side of a payload a media hint still counts as its own. */\nconst HINT_WINDOW = 200;\n\n/**\n * A bare base64 run that announces itself with a file magic \u2014 a payload pasted\n * without any wrapper at all, which is what `cat image.png | base64` in a Bash\n * tool result looks like.\n *\n * Anchored on the magic prefixes rather than on \"any base64 character\", which\n * is not a nicety: a `{512,}` quantifier over an unanchored character class\n * is retried at every letter of the corpus, and the corpus is 78 MB. With the\n * literal prefixes up front the engine skips to the next possible start.\n */\nconst MAGIC_PREFIXES = BASE64_MAGIC.map(([p]) => p.replace(/[.*+?^${}()|[\\]\\\\/]/g, '\\\\$&')).join('|');\nconst BARE_RUN = new RegExp(\n `(?<![A-Za-z0-9+/=])(?:${MAGIC_PREFIXES})${B64_BODY}`,\n 'g',\n);\n\ninterface Span {\n start: number;\n end: number;\n mime: string;\n}\n\n/** Strip json escapes and whitespace to get at the payload's real leading bytes. */\nfunction magicOf(payload: string): string | undefined {\n const head = payload.slice(0, 32).replace(/\\\\\\//g, '/').replace(/\\s+/g, '');\n for (const [prefix, mime] of BASE64_MAGIC) if (head.startsWith(prefix)) return mime;\n return undefined;\n}\n\n/** The mime named nearest to `[start,end)`, if the window holds a hint. */\nfunction mimeNear(text: string, start: number, end: number): string | undefined {\n const from = Math.max(0, start - HINT_WINDOW);\n const window = text.slice(from, start) + text.slice(end, Math.min(text.length, end + HINT_WINDOW));\n const rx = new RegExp(MEDIA_HINT.source, MEDIA_HINT.flags);\n let m: RegExpExecArray | null;\n let sawBase64 = false;\n while ((m = rx.exec(window)) !== null) {\n if (m[1]) return m[1];\n sawBase64 = true;\n }\n return sawBase64 ? 'application/octet-stream' : undefined;\n}\n\nfunction collect(re: RegExp, text: string, group: number, decide: (payload: string, start: number, end: number) => string | undefined, out: Span[]): void {\n const rx = new RegExp(re.source, re.flags);\n let m: RegExpExecArray | null;\n while ((m = rx.exec(text)) !== null) {\n const payload = group === 0 ? m[0] : m[group];\n if (payload === undefined || payload.length === 0) { rx.lastIndex += 1; continue; }\n const start = m.index + (group === 0 ? 0 : m[0].indexOf(payload));\n const end = start + payload.length;\n const mime = decide(payload, start, end);\n if (mime === undefined) continue;\n out.push({ start, end, mime });\n }\n}\n\n/**\n * Replace every binary payload in `text` with `\u2039elided:<mime>:<n> bytes\u203A`.\n *\n * Idempotent: the marker contains no base64 run of its own, so a second call\n * finds nothing and returns the same string.\n */\nexport function elideBinary(text: string, tally: Elisions = emptyElisions()): string {\n if (typeof text !== 'string' || text.length < MIN_PAYLOAD) return text ?? '';\n // Cheap reject. Every shape below needs a long unbroken base64 run, and\n // that needs at least this much alphabet. Skipping here is what keeps the\n // pass off the 99% of transcript text that is prose and code.\n if (!/[A-Za-z0-9+/]{64}/.test(text)) return text;\n\n const spans: Span[] = [];\n // The regexes only require 40 payload characters so that a hard-wrapped\n // payload still matches as one run; the MIN_PAYLOAD floor is applied here,\n // to the whole run.\n const big = (payload: string) => payload.length >= MIN_PAYLOAD;\n // 1. data: URIs \u2014 mime is in the URI itself.\n collect(DATA_URI, text, 0, (payload) => {\n if (!big(payload)) return undefined;\n const m = /^data:([a-zA-Z0-9.+-]+\\/[a-zA-Z0-9.+-]+)?/.exec(payload);\n return m?.[1] ?? 'application/octet-stream';\n }, spans);\n // 2. image content blocks \u2014 the wrapper must say `base64` or name a mime,\n // otherwise a long value that merely happens to be called `data` is left\n // for the redactor to judge.\n collect(CONTENT_BLOCK, text, 1, (payload, start, end) => {\n if (!big(payload)) return undefined;\n const hint = mimeNear(text, start, end);\n if (hint === undefined) return undefined;\n return magicOf(payload) ?? hint;\n }, spans);\n // 3. bare runs that carry a file magic.\n collect(BARE_RUN, text, 0, (payload) => (big(payload) ? magicOf(payload) : undefined), spans);\n\n if (spans.length === 0) return text;\n\n // First span wins on overlap: a data: URI inside a content block is elided\n // once, as the URI, not twice.\n spans.sort((a, b) => a.start - b.start || b.end - a.end);\n const out: string[] = [];\n let cursor = 0;\n for (const s of spans) {\n if (s.start < cursor) continue;\n out.push(text.slice(cursor, s.start));\n const n = s.end - s.start;\n out.push(`\u2039elided:${s.mime}:${n} bytes\u203A`);\n tally.binaryParts += 1;\n tally.charsElided += n;\n cursor = s.end;\n }\n out.push(text.slice(cursor));\n return out.join('');\n}\n\n/**\n * {@link elideBinary} over every field of an exchange that `03` \u00A75 redacts.\n * Returns a new object; the input is never mutated, because the caller may\n * still be writing the byte-exact archive copy from it.\n */\nexport function elideExchange(ex: Exchange): { exchange: Exchange; elisions: Elisions } {\n const elisions = emptyElisions();\n const one = (s: string): string => elideBinary(s, elisions);\n\n const userText = one(ex.userText);\n const assistantText = one(ex.assistantText);\n const toolCalls: ExchangeToolCall[] = ex.toolCalls.map((tc) => {\n const next: ExchangeToolCall = { ...tc, input: one(tc.input) };\n if (tc.result !== undefined) next.result = one(tc.result);\n return next;\n });\n\n if (elisions.binaryParts === 0) return { exchange: ex, elisions };\n return { exchange: { ...ex, userText, assistantText, toolCalls }, elisions };\n}\n", "import {StringDecoder} from 'node:string_decoder';\nimport {EXCLUSION_MARKERS} from '../markers.js';\ntype ImageBody={frame:Frame;chunks:string[];bytes:number;overflow:boolean};\ntype Frame={path:string[];omitImage:boolean;array:boolean;state:'key'|'keyRequired'|'colon'|'value'|'valueRequired'|'comma';key:string|null;keep:boolean;value:Record<string,unknown>|unknown[]|null};\n/** Validates one complete JSON record while omitting body values, with bounded retained metadata. */\nexport class NativeMetadataProjection {\n private readonly decoder=new StringDecoder('utf8');private frames:Frame[]=[];private root:unknown;private done=false;private mode:'idle'|'string'|'number'|'literal'='idle';private token='';private isKey=false;private keep=false;private escape=false;private unicode='';private markerTail='';private retained=0;private error:string|null=null;private marker=false;private scanString=false;private scanEscape=false;private scanUnicode='';private scanTail='';\n // Defer the producer check until the whole record is known, retaining unknown values only within the shared metadata budget.\n private imageBodies:ImageBody[]=[];private imageCandidate:ImageBody|null=null;private imageBytes=0;\n private trimImages():void{for(let i=this.imageBodies.length-1;i>=0&&this.retained+this.imageBytes>this.maxBytes;i--){const body=this.imageBodies[i]!;this.imageBytes-=body.bytes;body.chunks=[];body.bytes=0;body.overflow=true;}}\n constructor(private readonly maxBytes=8*1024*1024,private readonly harness:string|null=null){}\n private fail(code='native_metadata_invalid'):void{this.error??=code;}\n private add(c:string):void{if(this.keep||this.isKey){this.retained+=Buffer.byteLength(JSON.stringify(c))-2;if(this.retained>this.maxBytes||this.isKey&&this.token.length>32768){this.fail('native_metadata_bytes_limit');return;}this.token+=c;this.trimImages();}if(this.imageCandidate&&!this.imageCandidate.overflow){const bytes=Buffer.byteLength(JSON.stringify(c))-2;this.imageCandidate.bytes+=bytes;this.imageBytes+=bytes;this.imageCandidate.chunks.push(c);this.trimImages();}const searchable=this.markerTail+c;if(EXCLUSION_MARKERS.some(m=>searchable.includes(m)))this.marker=true;this.markerTail=searchable.slice(-256);}\n private expectedValue():boolean{const f=this.frames.at(-1);return f?f.state==='value'||f.state==='valueRequired':!this.done;}\n private imageBody(f:Frame):boolean{return this.harness==='codex'&&f.key==='image_url'&&f.path.length===3&&f.path[0]==='payload'&&f.path[1]==='output'&&f.path[2]==='[]';}\n private retainValue():boolean{const f=this.frames.at(-1);return !f||f.keep&&!(f.key==='content'||f.key==='text'||f.omitImage);}\n private accept(value:unknown):void{if(this.retainValue()){this.retained+=16;this.trimImages();if(this.retained>this.maxBytes){this.fail('native_metadata_bytes_limit');return;}}const f=this.frames.at(-1);if(!f){if(this.done){this.fail();return;}this.root=value;this.done=true;return;}if(f.state!=='value'&&f.state!=='valueRequired'){this.fail();return;}if(f.keep){if(f.array)(f.value as unknown[]).push(value);else if(f.key!==null&&this.retainValue())Object.defineProperty(f.value!,f.key,{value,writable:true,enumerable:true,configurable:true});}f.key=null;f.omitImage=false;f.state='comma';}\n private scalarEnd():void{if(this.mode==='number'){if(!/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(this.token)){this.fail();return;}this.accept(this.keep?Number(this.token):null);}else if(this.mode==='literal'){if(!['true','false','null'].includes(this.token)){this.fail();return;}this.accept(this.keep?JSON.parse(this.token):null);}this.mode='idle';this.token='';}\n private char(c:string):void{\n if(this.error)return;\n if(this.mode==='string'){\n if(this.unicode){if(!/[0-9a-f]/i.test(c)){this.fail();return;}this.unicode+=c;if(this.unicode.length===5){this.add(String.fromCharCode(parseInt(this.unicode.slice(1),16)));this.unicode='';}return;}\n if(this.escape){this.escape=false;if(c==='u'){this.unicode='u';return;}const decoded:Record<string,string>={'\"':'\"','\\\\':'\\\\','/':'/','b':'\\b','f':'\\f','n':'\\n','r':'\\r','t':'\\t'};if(!(c in decoded)){this.fail();return;}this.add(decoded[c]!);return;}\n if(c==='\\\\'){this.escape=true;return;}if(c==='\"'){if(this.isKey){const f=this.frames.at(-1)!;f.key=this.token;f.state='colon';}else this.accept(this.keep?this.token:null);this.mode='idle';this.token='';this.imageCandidate=null;this.markerTail='';return;}if(c.charCodeAt(0)<32){this.fail();return;}this.add(c);return;\n }\n if(this.mode==='number'||this.mode==='literal'){const allowed=this.mode==='number'?/[0-9eE+.-]/:/[a-z]/;if(allowed.test(c)){if(this.token.length>=256){this.fail('native_metadata_scalar_limit');return;}this.token+=c;return;}this.scalarEnd();if(this.error)return;}\n if(/\\s/.test(c)){if(![' ','\\t','\\r','\\n'].includes(c))this.fail();return;}\n const f=this.frames.at(-1);\n if(c==='\"'){this.isKey=!!f&&!f.array&&(f.state==='key'||f.state==='keyRequired');if(!this.isKey&&!this.expectedValue()){this.fail();return;}if(!this.isKey&&f&&this.imageBody(f)){f.omitImage=true;this.imageCandidate={frame:f,chunks:[],bytes:0,overflow:false};this.imageBodies.push(this.imageCandidate);}this.keep=this.isKey||this.retainValue()&&f?.key!=='message';this.token='';this.markerTail='';this.mode='string';return;}\n if(c==='{'||c==='['){if(!this.expectedValue()||this.frames.length>=128){this.fail('native_metadata_depth_limit');return;}const keep=this.retainValue();this.frames.push({path:f?[...f.path,f.array?'[]':f.key!]:[],omitImage:false,array:c==='[',state:c==='['?'value':'key',key:null,keep,value:keep?(c==='['?[]:{}):null});return;}\n if(c==='}'||c===']'){if(!f||f.array!==(c===']')||!['comma',f.array?'value':'key'].includes(f.state)){this.fail();return;}this.frames.pop();this.accept(f.value);return;}\n if(c===':'){if(!f||f.state!=='colon'){this.fail();return;}f.state='valueRequired';return;}\n if(c===','){if(!f||f.state!=='comma'){this.fail();return;}f.state=f.array?'valueRequired':'keyRequired';return;}\n if(!this.expectedValue()){this.fail();return;}this.keep=this.retainValue();this.token=c;if(c==='-'||/[0-9]/.test(c))this.mode='number';else if(/[tfn]/.test(c))this.mode='literal';else this.fail();\n }\n private scanMarkers(text:string):void{const special=/[\"\\\\]/g;let at=0;const add=(value:string)=>{const combined=this.scanTail+value;if(EXCLUSION_MARKERS.some(m=>combined.includes(m)))this.marker=true;this.scanTail=combined.slice(-256);};while(at<text.length){if(this.scanString&&!this.scanEscape&&!this.scanUnicode){special.lastIndex=at;const hit=special.exec(text),end=hit?.index??text.length;add(text.slice(at,end));at=end;if(at>=text.length)break;}const c=text[at++]!;if(this.scanUnicode){this.scanUnicode+=c;if(this.scanUnicode.length===5){if(/^u[0-9a-f]{4}$/i.test(this.scanUnicode))add(String.fromCharCode(parseInt(this.scanUnicode.slice(1),16)));this.scanUnicode='';}continue;}if(this.scanEscape){this.scanEscape=false;if(c==='u')this.scanUnicode='u';else add(({n:'\\n',r:'\\r',t:'\\t'} as Record<string,string>)[c]??c);continue;}if(c==='\"'){this.scanString=!this.scanString;this.scanTail='';}else if(this.scanString&&c==='\\\\')this.scanEscape=true;}}\n push(bytes:Buffer):void{const text=this.decoder.write(bytes);this.scanMarkers(text);const special=/[\"\\\\\\x00-\\x1f]/g;let at=0;while(at<text.length&&!this.error){if(this.mode==='string'&&!this.escape&&!this.unicode){special.lastIndex=at;const hit=special.exec(text),end=hit?.index??text.length;if(end>at)this.add(text.slice(at,end));at=end;if(at>=text.length)break;}this.char(text[at++]!);}}\n finish():{record:Record<string,unknown>|null;code:string|null;exclusionMarker:boolean}{for(const c of this.decoder.end())this.char(c);if(this.mode==='number'||this.mode==='literal')this.scalarEnd();if(this.mode!=='idle'||this.frames.length||!this.done)this.fail();if(!this.error&&(!this.root||typeof this.root!=='object'||Array.isArray(this.root)))this.fail();if(!this.error&&this.imageBodies.length){const root=this.root as Record<string,unknown>,payload=root.payload as Record<string,unknown>|undefined;for(const body of this.imageBodies){if(root.type==='response_item'&&(payload?.type==='custom_tool_call_output'||payload?.type==='function_call_output')&&(body.frame.value as Record<string,unknown>|null)?.type==='input_image')continue;if(body.overflow)this.fail('native_metadata_bytes_limit');else Object.defineProperty(body.frame.value!,'image_url',{value:body.chunks.join(''),writable:true,enumerable:true,configurable:true});}}if(!this.error&&Buffer.byteLength(JSON.stringify(this.root))>this.maxBytes)this.fail('native_metadata_bytes_limit');return {record:this.error?null:this.root as Record<string,unknown>,code:this.error,exclusionMarker:this.marker};}\n}\n", "import {createHash} from 'node:crypto';\nimport type {AuditHarness} from './contracts.js';\nimport type {RecordedInference} from './launch-contracts.js';\n\ntype R=Record<string,unknown>;\nconst obj=(v:unknown):R=>v!==null&&typeof v==='object'&&!Array.isArray(v)?v as R:{};\nconst str=(...v:unknown[]):string|null=>v.find(x=>typeof x==='string'&&x.length>0) as string|undefined??null;\nconst num=(v:unknown):number|null=>typeof v==='number'&&Number.isSafeInteger(v)&&v>=0?v:null;\nconst cost=(v:unknown):number|null=>typeof v==='number'&&Number.isFinite(v)&&v>=0?v:null;\nconst hash=(v:string)=>createHash('sha256').update(v).digest('hex');\nconst at=(v:unknown):string|null=>typeof v==='number'&&Number.isFinite(v)&&Math.abs(v)<8.64e15?new Date(v).toISOString():typeof v==='string'&&Number.isFinite(Date.parse(v))?new Date(v).toISOString():null;\nexport interface UsageRecordScope {key:string;rawStart:number;rawEnd:number;eventAt:string|null;project:string|null;}\nexport interface NativeUsageOptions {project?:string|null;maxRecords?:number;acceptRecord?:(record:R,scope:UsageRecordScope)=>boolean;}\n/** Reads only the caller's bounded frozen bytes. Excluded records still advance native counters. */\nexport interface NativeUsageAccumulator {invalidateContext():void;pushLine(line:string):void;pushRecord(record:R,position?:{rawStart:number;rawEnd:number}):void;records():RecordedInference[];counts():{observed:number;excluded:number;deduplicated:number};}\n/** Stateful per-record extraction lets full usage stream independently of context captures. */\nexport function createNativeUsageAccumulator(harness:AuditHarness,conversationId:string,options:NativeUsageOptions={}):NativeUsageAccumulator {\n let observed=0,excluded=0;\n const records=new Map<string,RecordedInference>();let project=options.project??null,model:string|null=null,provider:string|null=null,session=conversationId,offset=0,seq=0;\n let previous:R|null=null;const seenTotals=new Set<string>();\n const identities=new Map<string,{models:Set<string>;providers:Set<string>}>();\n const score=(v:RecordedInference)=> (v.inputTokens??0)+(v.outputTokens??0)+(v.cacheReadTokens??0)+Math.max(v.cacheWriteTokens??0,(v.cacheWrite5mTokens??0)+(v.cacheWrite1hTokens??0))+(v.reasoningTokens??0);\n const put=(r:RecordedInference)=>{const old=records.get(r.id),identity=identities.get(r.id)??{models:new Set<string>(),providers:new Set<string>()};if(r.model!==null)identity.models.add(r.model);if(r.provider!==null)identity.providers.add(r.provider);identities.set(r.id,identity);const chosen=!old||score(r)>score(old)?r:old;const conflict=identity.models.size>1||identity.providers.size>1;records.set(r.id,conflict?{...chosen,model:null,provider:null,gaps:[...new Set([...chosen.gaps,'response_identity_model_conflict'])]}:chosen);};\n const pushRecord=(record:R,position?:{rawStart:number;rawEnd:number}):void=>{\n const start=position?.rawStart??offset;if(position)offset=position.rawEnd;if(++seq>(options.maxRecords??100_000))return;let r=record;\n if(harness==='opencode'){r={...r,...obj(r.message)};const wrapped=r.data??r.content;if(typeof wrapped==='string'){try{r={...r,...obj(JSON.parse(wrapped))};}catch{/* unsupported projection remains unknown */}}else if(wrapped&&typeof wrapped==='object')r={...r,...obj(wrapped)};}\n const p=obj(r.payload),m=obj(r.message);\n project=str(r.cwd,p.cwd,r.directory)??project;if(harness==='claude')session=str(r.sessionId)??session;if(harness==='pi'&&r.type==='session')session=str(r.id)??session;\n if(harness==='codex'&&(r.type==='session_meta'||r.type==='turn_context')){session=str(p.session_id,p.id)??session;model=str(p.model)??model;provider=str(p.model_provider,p.provider)??provider;return;}\n const eventAt=at(r.timestamp)??at(m.timestamp)??at(obj(r.time).created);const key=str(r.uuid,r.id,p.id,m.id)??`record:${seq}`;\n const accepted=options.acceptRecord?.(r,{key,rawStart:start,rawEnd:offset,eventAt,project})??true;\n let input:number|null=null,output:number|null=null,read:number|null=null,write:number|null=null,reasoning:number|null=null,reported:number|null=null;\n let observedModel:string|null=null,observedProvider:string|null=null,id:string,basis:string,includesCache=false,includesReasoning=true;const gaps:string[]=[];\n if(harness==='codex'){\n if(r.type!=='event_msg'||p.type!=='token_count')return;const info=obj(p.info),last=obj(info.last_token_usage),total=obj(info.total_token_usage);if(!Object.keys(last).length&&!Object.keys(total).length)return;observed++;\n const previousTotal=previous;previous=Object.keys(total).length?total:previous;\n const signature=Object.keys(total).length?JSON.stringify([session,total.input_tokens,total.output_tokens,total.cached_input_tokens,total.reasoning_output_tokens]):null;\n if(signature&&seenTotals.has(signature))return;if(signature)seenTotals.add(signature);\n const delta=(field:string):number|null=>{const current=num(total[field]),prev=num(previousTotal?.[field]);return current===null||prev===null||current<prev?null:current-prev;};\n const firstComplete=previousTotal===null&&num(last.input_tokens)!==null&&last.input_tokens===total.input_tokens&&last.output_tokens===total.output_tokens;\n const bucket=(field:string)=>num(last[field])??delta(field)??(firstComplete?num(total[field]):null);\n input=bucket('input_tokens');output=bucket('output_tokens');read=bucket('cached_input_tokens');write=bucket('cache_write_input_tokens');reasoning=bucket('reasoning_output_tokens');\n if(!Object.keys(last).length&&previousTotal===null)gaps.push('cumulative_baseline_unknown');\n if(previousTotal&&Object.keys(total).length&&['input_tokens','output_tokens'].some(k=>num(total[k])!==null&&num(previousTotal[k])!==null&&(num(total[k]) as number)<(num(previousTotal[k]) as number)))gaps.push('cumulative_counter_reset');\n observedModel=str(p.model,info.model)??model;observedProvider=str(p.model_provider,p.provider,info.provider)??provider;\n includesCache=true;basis='codex_last_response_with_cumulative_dedup';id=`codex:${hash(JSON.stringify([session,str(p.response_id,info.response_id)??signature??[eventAt,last]]))}`;\n // Absent optional cache-write means zero in Codex's native usage schema.\n write=write??0;\n }else if(harness==='claude'){\n if(r.type!=='assistant'||m.role!=='assistant')return;const u=obj(m.usage);input=num(u.input_tokens);output=num(u.output_tokens);read=num(u.cache_read_input_tokens)??(input!==null?0:null);write=num(u.cache_creation_input_tokens)??(input!==null?0:null);reasoning=num(u.reasoning_tokens);const duration=obj(u.cache_creation);const five=num(duration.ephemeral_5m_input_tokens),hour=num(duration.ephemeral_1h_input_tokens);if(five!==null&&hour!==null&&write!==null&&five+hour!==write)gaps.push('cache_write_duration_conflict');\n if(hour!==null&&hour>0&&(five===null||write===null||five+hour!==write))gaps.push('cache_write_duration_unknown');\n observedModel=str(m.model,r.model);observedProvider=str(m.provider,r.provider,r.modelProvider);reported=cost(r.costUSD)??cost(m.costUSD);basis='claude_response_usage';id=`claude:${hash(JSON.stringify([str(m.id,r.uuid)??key,str(r.requestId)??[session,eventAt]]))}`;\n }else if(harness==='pi'){\n if(r.type!=='message'||m.role!=='assistant')return;const u=obj(m.usage);input=num(u.input);output=num(u.output);read=num(u.cacheRead)??(input!==null?0:null);write=num(u.cacheWrite)??(input!==null?0:null);reasoning=num(u.reasoning);reported=cost(obj(u.cost).total);observedModel=str(m.model);observedProvider=str(m.provider);basis='pi_response_usage';id=`pi:${hash(JSON.stringify([session,str(r.id)??key,eventAt]))}`;\n }else{\n if(r.role!=='assistant')return;const u=obj(r.tokens),cache=obj(u.cache);input=num(u.input);output=num(u.output);read=num(cache.read)??(input!==null?0:null);write=num(cache.write)??(input!==null?0:null);reasoning=num(u.reasoning);reported=cost(r.cost);observedModel=str(r.modelID,obj(r.model).modelID,obj(r.model).id,r.model);observedProvider=str(r.providerID,obj(r.model).providerID,r.provider);basis='opencode_response_tokens';includesReasoning=false;id=`opencode:${str(r.id)??hash(JSON.stringify([conversationId,key,eventAt]))}`;\n }\n if(observedModel==='codex-auto-review'){observedModel=null;gaps.push('workflow_model_identity_unavailable');}\n if(harness!=='codex')observed++;if(r.isSynthetic===true||r.isMeta===true||m.isSynthetic===true||observedModel==='<synthetic>'){excluded++;return;}if(!accepted){excluded++;return;}if(!observedModel)gaps.push('model_unrecorded');if(!observedProvider)gaps.push('provider_unrecorded');if(input===null||output===null)gaps.push('usage_partial');\n if(includesCache&&read===null)gaps.push('cache_inclusion_unknown');\n if(includesCache&&input!==null&&read!==null&&write!==null&&read+write>input)gaps.push('cache_exceeds_input');\n if(includesReasoning&&output!==null&&reasoning!==null&&reasoning>output)gaps.push('reasoning_exceeds_output');\n put({id,conversationId,harness,eventAt,project,provider:observedProvider,model:observedModel,canonicalModel:null,inputTokens:input,outputTokens:output,cacheReadTokens:read,cacheWriteTokens:write,reasoningTokens:reasoning,inputIncludesCache:includesCache,outputIncludesReasoning:includesReasoning,reportedCostUsd:reported,basis,gaps,...(harness==='claude'?{cacheWrite5mTokens:num(obj(obj(m.usage).cache_creation).ephemeral_5m_input_tokens),cacheWrite1hTokens:num(obj(obj(m.usage).cache_creation).ephemeral_1h_input_tokens)}:{})});\n };\n const pushLine=(line:string):void=>{const start=offset;offset+=Buffer.byteLength(line)+1;if(!line.trim())return;let r:R;try{r=obj(JSON.parse(line));}catch{seq++;return;}pushRecord(r,{rawStart:start,rawEnd:offset});};\n return {pushRecord,invalidateContext:()=>{project=null;model=null;provider=null;previous=null;},pushLine,records:()=>[...records.values()],counts:()=>({observed,excluded,deduplicated:Math.max(0,observed-excluded-records.size)})};\n}\nexport function extractNativeUsageWithCounts(bytes:Buffer|string,harness:AuditHarness,conversationId:string,options:NativeUsageOptions={}):{usage:RecordedInference[];counts:{observed:number;excluded:number;deduplicated:number}}{\n const text=Buffer.isBuffer(bytes)?bytes.toString('utf8'):bytes,acc=createNativeUsageAccumulator(harness,conversationId,options);\n const lines=text.trimStart().startsWith('[')?(()=>{try{return (JSON.parse(text) as unknown[]).map(x=>JSON.stringify(x));}catch{return [];}})():text.split('\\n');for(const line of lines)acc.pushLine(line);return {usage:acc.records(),counts:acc.counts()};\n}\n\nexport function extractNativeUsage(bytes:Buffer|string,harness:AuditHarness,conversationId:string,options:NativeUsageOptions={}):RecordedInference[]{return extractNativeUsageWithCounts(bytes,harness,conversationId,options).usage;}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Db } from './db.js';\nimport { configPath, expandTilde, potsherdDir } from './paths.js';\nimport type { SearchFilters } from './search/filters.js';\n\n/**\n * The ignore list: projects you do not want in `ls`, `find`, `ask` or `stats`.\n *\n * **Why it exists.** On the reference machine 9 of the top 15 `ls` rows are\n * potsherd's own worker and sdk sessions, and `find pgbouncer` returns\n * potsherd's own test sessions before the user's. Every user who builds\n * potsherd from a checkout hits a milder version of that, and every developer\n * running agents across many repos hits it whatever they build. The archive is\n * not wrong \u2014 it is complete, and completeness is what buries the answer.\n *\n * **Three rules this module is built to keep.**\n *\n * 1. **Nothing is ignored by default.** There is no shipped list, no\n * \"this looks like a build directory\" heuristic, and no auto-detection.\n * The user names what they ignore, with `potsherd ignore <project>`, and\n * `potsherd unignore <project>` takes it back. A tool that decided on its\n * own which of your work did not count would be making a claim about your\n * history it has no standing to make.\n *\n * 2. **An ignore list is never silent.** Every surface that drops rows says\n * so and says how many \u2014 `ls`, `find` and `stats` each print one line\n * naming the count and the flag that undoes it. A filter the user cannot\n * see is a claim about their archive the product cannot support: \"you\n * have 12 sessions about pgbouncer\" is a different sentence from \"you\n * have 12 sessions about pgbouncer, outside the projects you told me to\n * skip\". `doctor` prints the whole list, always.\n *\n * 3. **Ignoring is a view, not a deletion.** `index` keeps indexing\n * everything, `rescue` keeps rescuing everything, `show <id>` still shows\n * an ignored session, and `--all` brings every row back on the surfaces\n * that hide them. Nothing here ever deletes a row or skips a file.\n *\n * **Storage** is `~/.potsherd/config.json`, whose path `paths.configPath()`\n * has always resolved. The file is potsherd's own \u2014 the first thing potsherd\n * writes there that a user is expected to edit \u2014 so the writer preserves every\n * key it does not own and the reader survives a file that has been hand-edited\n * into nonsense.\n */\n\n/** The key this module owns inside `config.json`. Everything else is left alone. */\nexport const IGNORE_KEY = 'ignore';\n\nexport interface IgnoreConfig {\n /** The list as stored, in the order it was written. */\n list: string[];\n /** Every other key in the file, preserved across writes. */\n rest: Record<string, unknown>;\n /**\n * Set when the file exists and could not be understood. The list is then\n * empty \u2014 but `doctor` says the file is unreadable rather than reporting an\n * empty list, because \"you ignore nothing\" and \"I could not read your\n * settings\" are different facts and only one of them is actionable.\n */\n error?: string;\n /** The file this came from, whether or not it exists. */\n file: string;\n}\n\n/**\n * Read `<root>/config.json`.\n *\n * A missing file is not an error: it is the normal state of a fresh install\n * and means an empty list. A malformed one is reported rather than repaired \u2014\n * this file belongs to the user once they have opened it.\n */\nexport function readIgnoreConfig(root: string = potsherdDir()): IgnoreConfig {\n const file = configPath(root);\n let text: string;\n try {\n text = fs.readFileSync(file, 'utf8');\n } catch {\n return { list: [], rest: {}, file };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return { list: [], rest: {}, file, error: 'config.json is not valid JSON' };\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return { list: [], rest: {}, file, error: 'config.json is not a JSON object' };\n }\n const record = parsed as Record<string, unknown>;\n const { [IGNORE_KEY]: raw, ...rest } = record;\n if (raw === undefined) return { list: [], rest, file };\n if (!Array.isArray(raw)) {\n return { list: [], rest, file, error: `config.json \"${IGNORE_KEY}\" is not an array` };\n }\n const list: string[] = [];\n for (const value of raw) {\n if (typeof value !== 'string') continue;\n const entry = normalizeIgnoreEntry(value);\n if (entry && !list.some((e) => sameEntry(e, entry))) list.push(entry);\n }\n return { list, rest, file };\n}\n\n/** Just the list. The shape every caller inside the engine wants. */\nexport function readIgnoreList(root: string = potsherdDir()): string[] {\n return readIgnoreConfig(root).list;\n}\n\n/**\n * Write the list back, preserving every other key.\n *\n * Written to a sibling temp file and renamed, so a crash mid-write leaves the\n * old config rather than half of a new one, and created 0600 because\n * `~/.potsherd` holds copies of transcripts and this file sits beside them.\n */\nexport function writeIgnoreList(root: string, list: readonly string[]): string[] {\n const current = readIgnoreConfig(root);\n const clean: string[] = [];\n for (const value of list) {\n const entry = normalizeIgnoreEntry(value);\n if (entry && !clean.some((e) => sameEntry(e, entry))) clean.push(entry);\n }\n const next = { ...current.rest, [IGNORE_KEY]: clean };\n const file = current.file;\n fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n const tmp = `${file}.tmp-${String(process.pid)}`;\n fs.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\\n`, { mode: 0o600 });\n fs.renameSync(tmp, file);\n return clean;\n}\n\nexport interface IgnoreChange {\n /** The list after the change. */\n list: string[];\n /** The entry as it was stored or removed, normalised. */\n entry: string;\n /** False when the entry was already there (`ignore`) or absent (`unignore`). */\n changed: boolean;\n}\n\n/** `potsherd ignore <project>`. Idempotent, and says so rather than pretending. */\nexport function addIgnored(root: string, project: string): IgnoreChange {\n const entry = normalizeIgnoreEntry(project);\n if (!entry) throw new Error('an ignore entry needs at least one character that is not a slash');\n const before = readIgnoreList(root);\n if (before.some((e) => sameEntry(e, entry))) return { list: before, entry, changed: false };\n const list = writeIgnoreList(root, [...before, entry]);\n return { list, entry, changed: true };\n}\n\n/** `potsherd unignore <project>`. */\nexport function removeIgnored(root: string, project: string): IgnoreChange {\n const entry = normalizeIgnoreEntry(project);\n if (!entry) throw new Error('an ignore entry needs at least one character that is not a slash');\n const before = readIgnoreList(root);\n if (!before.some((e) => sameEntry(e, entry))) return { list: before, entry, changed: false };\n const list = writeIgnoreList(\n root,\n before.filter((e) => !sameEntry(e, entry)),\n );\n return { list, entry, changed: true };\n}\n\n/**\n * What the user typed, as it will be stored.\n *\n * `~` is expanded because a stored `~/code/potsherd` would never match a\n * project recorded as `/Users/me/code/potsherd`, and a trailing slash is\n * dropped because `potsherd/` and `potsherd` are the same directory to\n * everyone except a string comparison.\n */\nexport function normalizeIgnoreEntry(value: string): string {\n const trimmed = expandTilde(value.trim());\n return trimmed.replace(/[\\\\/]+$/, '');\n}\n\nfunction fold(value: string): string {\n return value.replace(/\\\\/g, '/').replace(/\\/+$/, '').toLowerCase();\n}\n\nfunction sameEntry(a: string, b: string): boolean {\n return fold(a) === fold(b);\n}\n\n/**\n * Does this entry name this project?\n *\n * Two forms, and the difference is whether the user typed a slash.\n *\n * `potsherd` a **path segment**. Matches\n * `/Users/me/randomness/potsherd` and everything\n * under it, including\n * `/Users/me/randomness/potsherd/wt/w3-ignore`.\n * It does **not** match `potsherd-notes`: the\n * segment must be the whole segment, or `ignore\n * core` would hide `core-app` and the user would\n * have no way to tell it had.\n *\n * `~/randomness/potsherd` a **path**. Matches that directory and its\n * descendants, and nothing else. This is the form\n * to reach for when the same directory name\n * appears in two places and only one of them is\n * noise.\n *\n * The segment form is the default because it is the one that works: potsherd's\n * own sessions on the reference machine are spread across the checkout, six\n * git worktrees and a `.claude/worktrees/agent-*` directory, and a rule that\n * matched only the exact path the user typed would hide one of eight.\n */\nexport function matchesIgnoreEntry(project: string | null | undefined, entry: string): boolean {\n if (!project) return false;\n const p = fold(project);\n const e = fold(entry);\n if (!p || !e) return false;\n if (p === e) return true;\n if (e.includes('/')) return p.startsWith(`${e}/`);\n return p.split('/').filter(Boolean).includes(e);\n}\n\n/** True when any entry in the list names this project. */\nexport function isIgnoredProject(\n project: string | null | undefined,\n entries: readonly string[],\n): boolean {\n return entries.some((entry) => matchesIgnoreEntry(project, entry));\n}\n\n/**\n * `<root>` for an open database, so a core function that was handed only a\n * `Db` can still find the config beside it.\n *\n * This matters because `ask` reaches `recall` without passing a root through\n * every layer, and an ignore list `ls` honours but `ask` does not would be\n * worse than no ignore list at all. `PRAGMA database_list` names the file the\n * connection actually opened \u2014 not the file some caller believes it opened \u2014\n * so a test pointing at a temp directory and a user pointing at `~/.potsherd`\n * are answered the same way. An in-memory database has no file and returns\n * null, which is the honest answer: it has no config.\n */\nexport function rootForDb(db: Db): string | null {\n try {\n const rows = db.prepare('PRAGMA database_list').all() as {\n name?: string;\n file?: string;\n }[];\n const main = rows.find((r) => r.name === 'main') ?? rows[0];\n const file = main?.file;\n if (!file) return null;\n return path.dirname(file);\n } catch {\n return null;\n }\n}\n\n/**\n * The project values **in this index** that the list names.\n *\n * The predicate is a rule about paths; SQL needs a set of literals. Resolving\n * the rule against the projects that actually exist gives both \u2014 a bound\n * `NOT IN (?, ?)` that any of the three filter builders can carry, and the\n * exact list of what is being hidden, which is what the surfaces print.\n */\nexport function ignoredProjectsInIndex(db: Db, entries: readonly string[]): string[] {\n if (entries.length === 0) return [];\n let rows: { project: string | null }[] = [];\n try {\n rows = db\n .prepare(\n `SELECT DISTINCT project FROM (\n SELECT project FROM sessions WHERE project IS NOT NULL\n UNION\n SELECT project FROM ghosts WHERE project IS NOT NULL\n )`,\n )\n .all() as { project: string | null }[];\n } catch {\n return [];\n }\n const out: string[] = [];\n for (const r of rows) {\n if (r.project && isIgnoredProject(r.project, entries)) out.push(r.project);\n }\n return out.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n}\n\nexport interface IgnoreOptions {\n /** `--all`: show everything. The list is read but not applied. */\n all?: boolean;\n /** potsherd root. Falls back to the database's own directory. */\n root?: string;\n /** Entries to use instead of reading the config. Tests, and `--json` echo. */\n entries?: readonly string[];\n}\n\nexport interface IgnoreApplication {\n /** The filters to run, with `excludeProjects` set when the list applies. */\n filters: SearchFilters;\n /** What the config holds, whether or not it was applied. */\n entries: string[];\n /** The project values excluded from this query. Empty when nothing applied. */\n projects: string[];\n /** True when rows were actually excluded. */\n applied: boolean;\n /** Why not, when `applied` is false and `entries` is not empty. */\n reason?: 'all' | 'named-project' | 'no-match';\n}\n\n/**\n * Fold the ignore list into a set of filters, once, at the top of a verb.\n *\n * Two things deliberately switch it off:\n *\n * **`--all`.** The escape hatch every surface names on screen.\n *\n * **`--project X`.** Naming a project *is* asking for it. Hiding the rows\n * someone has just asked for by name, and printing \"12 hidden\" under an\n * empty table, is the ignore list arguing with its user.\n */\nexport function applyIgnore(\n db: Db,\n filters: SearchFilters = {},\n options: IgnoreOptions = {},\n): IgnoreApplication {\n const root = options.root ?? rootForDb(db) ?? undefined;\n const entries = [...(options.entries ?? readIgnoreList(root ?? potsherdDir()))];\n if (entries.length === 0) return { filters, entries, projects: [], applied: false };\n if (options.all) return { filters, entries, projects: [], applied: false, reason: 'all' };\n if (filters.project) {\n return { filters, entries, projects: [], applied: false, reason: 'named-project' };\n }\n const projects = ignoredProjectsInIndex(db, entries);\n if (projects.length === 0) {\n return { filters, entries, projects: [], applied: false, reason: 'no-match' };\n }\n return { filters: { ...filters, excludeProjects: projects }, entries, projects, applied: true };\n}\n\n/**\n * What a surface reports about the rows it dropped.\n *\n * Carried on `ListResult`, `RecallResult` and `StatsReport` so the renderers\n * and `--json` read one shape, and so a `--json` consumer can tell \"no\n * results\" apart from \"no results outside your ignore list\".\n */\nexport interface IgnoreReport {\n /** The list as configured. */\n entries: string[];\n /** The project values actually excluded. */\n projects: string[];\n /**\n * How much the list cost, **in the units the surface reporting it uses**,\n * and 0 whenever the list did not apply.\n *\n * `ls` rows dropped from *this* listing \u2014 the ones that matched every\n * other filter and lost only on their project.\n * `find` sessions in the ignored projects that were not searched.\n * `stats` sessions and ghosts left out of the counts.\n *\n * Each surface names its unit on screen; they are not interchangeable and\n * nothing should add them together.\n */\n hidden: number;\n}\n\n/**\n * Sessions and ghosts belonging to the ignored projects, for the surfaces that\n * report what they did not look at rather than what they dropped.\n *\n * Top-level sessions only: a subagent transcript is not a row anybody counts,\n * and `197 sessions not searched` on a machine with 30 conversations would be\n * a true number that misinforms every reader of it.\n */\nexport function countIgnoredSessions(db: Db, projects: readonly string[]): number {\n if (projects.length === 0) return 0;\n const marks = projects.map(() => '?').join(', ');\n try {\n const row = db\n .prepare(\n `SELECT (SELECT COUNT(*) FROM sessions\n WHERE is_sidechain = 0 AND project IN (${marks}))\n + (SELECT COUNT(*) FROM ghosts WHERE project IN (${marks})) AS n`,\n )\n .get(...projects, ...projects) as { n: number };\n return row?.n ?? 0;\n } catch {\n return 0;\n }\n}\n\nexport function emptyIgnoreReport(entries: readonly string[] = []): IgnoreReport {\n return { entries: [...entries], projects: [], hidden: 0 };\n}\n", "import {runNativeScanWorker} from '../../core/src/analytics/native-pool.js';\nrunNativeScanWorker();\n"],
5
+ "mappings": "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",
6
+ "names": ["createHash", "createHash", "createHash", "createHash", "createHash", "createHash", "code", "f", "at", "createHash", "num", "hash", "createHash", "process", "at", "hash", "createHash", "at"]
7
+ }