@caupulican/pi-agent-core 0.81.39 → 0.81.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +77 -89
- package/dist/agent-loop.js.map +1 -1
- package/dist/compaction/branch-summarization.d.ts +4 -2
- package/dist/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/compaction/branch-summarization.js +4 -0
- package/dist/compaction/branch-summarization.js.map +1 -1
- package/dist/compaction/compaction.d.ts +32 -1
- package/dist/compaction/compaction.d.ts.map +1 -1
- package/dist/compaction/compaction.js +172 -101
- package/dist/compaction/compaction.js.map +1 -1
- package/dist/compaction/extraction.d.ts.map +1 -1
- package/dist/compaction/extraction.js +1 -1
- package/dist/compaction/extraction.js.map +1 -1
- package/dist/compaction/loop.d.ts +1 -1
- package/dist/compaction/loop.d.ts.map +1 -1
- package/dist/compaction/loop.js +24 -7
- package/dist/compaction/loop.js.map +1 -1
- package/dist/compaction/utils.d.ts.map +1 -1
- package/dist/compaction/utils.js +3 -1
- package/dist/compaction/utils.js.map +1 -1
- package/dist/compaction/verification.d.ts +11 -0
- package/dist/compaction/verification.d.ts.map +1 -1
- package/dist/compaction/verification.js +93 -11
- package/dist/compaction/verification.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +1 -0
- package/dist/proxy.js.map +1 -1
- package/dist/reliability/classifier.d.ts.map +1 -1
- package/dist/reliability/classifier.js +3 -3
- package/dist/reliability/classifier.js.map +1 -1
- package/dist/session/session-manager.d.ts +18 -6
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +68 -61
- package/dist/session/session-manager.js.map +1 -1
- package/dist/tool-failure-memory.d.ts +35 -0
- package/dist/tool-failure-memory.d.ts.map +1 -0
- package/dist/tool-failure-memory.js +290 -0
- package/dist/tool-failure-memory.js.map +1 -0
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/usage.d.ts +5 -0
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +32 -0
- package/dist/usage.js.map +1 -1
- package/dist/uuid.d.ts +1 -1
- package/dist/uuid.d.ts.map +1 -1
- package/dist/uuid.js +1 -49
- package/dist/uuid.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/compaction/utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared utilities for compaction and branch summarization.\n */\n\nimport type { Message } from \"@caupulican/pi-ai\";\nimport type { AgentMessage } from \"../types.ts\";\n\n// ============================================================================\n// File Operation Tracking\n// ============================================================================\n\nexport interface FileOperations {\n\tread: Set<string>;\n\twritten: Set<string>;\n\tedited: Set<string>;\n}\n\nexport function createFileOps(): FileOperations {\n\treturn {\n\t\tread: new Set(),\n\t\twritten: new Set(),\n\t\tedited: new Set(),\n\t};\n}\n\n/**\n * Extract file operations from tool calls in an assistant message.\n */\nexport function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void {\n\tif (message.role !== \"assistant\") return;\n\tif (!(\"content\" in message) || !Array.isArray(message.content)) return;\n\n\tfor (const block of message.content) {\n\t\tif (typeof block !== \"object\" || block === null) continue;\n\t\tif (!(\"type\" in block) || block.type !== \"toolCall\") continue;\n\t\tif (!(\"arguments\" in block) || !(\"name\" in block)) continue;\n\n\t\tconst args = block.arguments as Record<string, unknown> | undefined;\n\t\tif (!args) continue;\n\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tif (!path) continue;\n\n\t\tswitch (block.name) {\n\t\t\tcase \"read\":\n\t\t\t\tfileOps.read.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"write\":\n\t\t\t\tfileOps.written.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"edit\":\n\t\t\t\tfileOps.edited.add(path);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Compute final file lists from file operations.\n * Returns readFiles (files only read, not modified) and modifiedFiles.\n */\nexport function computeFileLists(fileOps: FileOperations): { readFiles: string[]; modifiedFiles: string[] } {\n\tconst modified = new Set([...fileOps.edited, ...fileOps.written]);\n\tconst readOnly = [...fileOps.read].filter((f) => !modified.has(f)).sort();\n\tconst modifiedFiles = [...modified].sort();\n\treturn { readFiles: readOnly, modifiedFiles };\n}\n\n/**\n * Format file operations as XML tags for summary.\n */\nexport function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string {\n\tconst sections: string[] = [];\n\tif (readFiles.length > 0) {\n\t\tsections.push(`<read-files>\\n${readFiles.join(\"\\n\")}\\n</read-files>`);\n\t}\n\tif (modifiedFiles.length > 0) {\n\t\tsections.push(`<modified-files>\\n${modifiedFiles.join(\"\\n\")}\\n</modified-files>`);\n\t}\n\tif (sections.length === 0) return \"\";\n\treturn `\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Message Serialization\n// ============================================================================\n\n/** Maximum characters for a tool result in serialized summaries. */\nconst TOOL_RESULT_MAX_CHARS = 2000;\n/** Maximum characters for non-gated assistant thinking in serialized summaries. */\nconst ASSISTANT_THINKING_MAX_CHARS = 2000;\n\n/**\n * Truncate text to a maximum character length for summarization.\n * Keeps the beginning and appends a truncation marker.\n */\nfunction truncateForSummary(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\tconst truncatedChars = text.length - maxChars;\n\treturn `${text.slice(0, maxChars)}\\n\\n[... ${truncatedChars} more characters truncated]`;\n}\n\n/**\n * Serialize LLM messages to text for summarization.\n * This prevents the model from treating it as a conversation to continue.\n * Call convertToLlm() first to handle custom message types.\n *\n * Tool results are truncated to keep the summarization request within\n * reasonable token budgets. Full content is not needed for summarization.\n */\nexport function serializeConversation(messages: Message[]): string {\n\tconst parts: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tconst content =\n\t\t\t\ttypeof msg.content === \"string\"\n\t\t\t\t\t? msg.content\n\t\t\t\t\t: msg.content\n\t\t\t\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t\tif (content) parts.push(`[User]: ${content}`);\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tconst thinkingParts: string[] = [];\n\t\t\tconst toolCalls: string[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tthinkingParts.push(block.thinking);\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tconst args = block.arguments as Record<string, unknown>;\n\t\t\t\t\tconst argsStr = Object.entries(args)\n\t\t\t\t\t\t.map(([k, v]) => `${k}=${JSON.stringify(v)}`)\n\t\t\t\t\t\t.join(\", \");\n\t\t\t\t\ttoolCalls.push(`${block.name}(${argsStr})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (thinkingParts.length > 0) {\n\t\t\t\tparts.push(\n\t\t\t\t\t`[Assistant thinking]: ${truncateForSummary(thinkingParts.join(\"\\n\"), ASSISTANT_THINKING_MAX_CHARS)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (textParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant]: ${textParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tparts.push(`[Assistant tool calls]: ${toolCalls.join(\"; \")}`);\n\t\t\t}\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst content = msg.content\n\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t.map((c) => c.text)\n\t\t\t\t.join(\"\");\n\t\t\tif (content) {\n\t\t\t\tparts.push(`[Tool result]: ${truncateForSummary(content, TOOL_RESULT_MAX_CHARS)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ============================================================================\n// Summarization System Prompt\n// ============================================================================\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context checkpointer. Input: a serialized agent conversation. Output: ONLY the checkpoint, exactly in the format below. No preamble. No commentary. Same language as the user. Never include secrets/keys/tokens — write [REDACTED].\n\nRULES:\n- Recent turns weigh heaviest. Old turns contribute only rules, decisions, and file knowledge.\n- ## Active Task: the user's most recent UNFULFILLED input, near-verbatim. A question awaiting an answer IS an active task. If the user's last signal cancels earlier work (stop/undo/never mind), record the cancellation and DROP the cancelled work everywhere.\n- ### Mandatory Rules: every user prohibition (\"do not X\", \"never Y\", \"stop doing Z\") as one bullet each, imperative, with source turn if known. PRESERVE existing rules verbatim. A user-corrected mistake appears ONLY here as \"DO NOT <mistake>\" — the mistaken work itself must not survive.\n- ## Working Set: the currently active/recent files — path — why they matter.\n- ## Files: bare paths only; modified files must all appear, read files should be recalled when relevant.\n- ## Open Problems: unresolved errors only — command/operation plus first error line. Drop resolved/transient errors.\n- ## Done: numbered caveman log — \"N. VERB target — outcome\". Exact paths, commands, line numbers, error strings.\n- Do NOT carry resolved/transient errors, superseded approaches, or file contents. Record paths and intent, never bodies.\n- Sections with nothing: write \"(none)\".\n\nEXAMPLE INPUT (excerpt):\n[user]: add retry to the fetcher, and do not touch the legacy client\n[assistant]: (edits src/fetcher.ts, adds retry loop)\n[tool write src/fetcher.ts]: ok\n[tool bash npm test]: 2 failed: fetcher.test.ts\n[assistant]: (tries wrapping legacy client instead)\n[user]: no — stop changing the legacy client, I said don't touch it. Fix the two tests instead.\n\nEXAMPLE OUTPUT:\n## Active Task\nUser: \"Fix the two failing tests\" (fetcher.test.ts) — retry work continues, legacy-client changes cancelled.\n\n### Mandatory Rules\n- DO NOT touch the legacy client (user, twice)\n\n## Working Set\n- test/fetcher.test.ts — 2 failing, current focus\n- src/fetcher.ts — retry loop added\n\n## Files\n- src/fetcher.ts\n- test/fetcher.test.ts\n\n## Open Problems\n- TEST npm test: 2 failed: fetcher.test.ts\n\n## Done\n1. EDIT src/fetcher.ts — added retry loop\n2. TEST npm test — 2 failed: fetcher.test.ts\n\n## Key Decisions\n(none)\n\n## Constraints & Preferences\n(none)\n\n## Critical Context\n(none)\n\nNote what the example TEACHES (not just shows): the legacy-client wrapping attempt (cancelled work) appears nowhere except as the DO-NOT rule; the Active Task is the tail, near-verbatim; Done lines are caveman-format.`;\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/compaction/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,MAAM,UAAU,aAAa,GAAmB;IAC/C,OAAO;QACN,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;AAAA,CACF;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAqB,EAAE,OAAuB,EAAQ;IAC/F,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO;IACzC,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO;IAEvE,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC1D,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QAC9D,IAAI,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;YAAE,SAAS;QAE5D,MAAM,IAAI,GAAG,KAAK,CAAC,SAAgD,CAAC;QACpE,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,MAAM;gBACV,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACvB,MAAM;YACP,KAAK,OAAO;gBACX,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,MAAM;YACP,KAAK,MAAM;gBACV,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACzB,MAAM;QACR,CAAC;IACF,CAAC;AAAA,CACD;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAuB,EAAoD;IAC3G,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1E,MAAM,aAAa,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AAAA,CAC9C;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAmB,EAAE,aAAuB,EAAU;IAC1F,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,qBAAqB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAAA,CACtC;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E,oEAAoE;AACpE,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,mFAAmF;AACnF,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAC1C,gFAAgF;AAChF,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAE3C;;;GAGG;AACH,SAAS,kBAAkB,CAAC,IAAY,EAAE,QAAgB,EAAU;IACnE,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;IAC9C,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,YAAY,cAAc,6BAA6B,CAAC;AAAA,CACzF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAmB,EAAU;IAClE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,OAAO,GACZ,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC9B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,GAAG,CAAC,OAAO;qBACV,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;qBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;qBAClB,IAAI,CAAC,EAAE,CAAC,CAAC;YACd,IAAI,OAAO;gBAAE,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACrC,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,MAAM,aAAa,GAAa,EAAE,CAAC;YACnC,MAAM,SAAS,GAAa,EAAE,CAAC;YAE/B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC3B,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5B,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACtC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAoC,CAAC;oBACxD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;yBAClC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;yBAC5C,IAAI,CAAC,IAAI,CAAC,CAAC;oBACb,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,kBAAkB,CAAC,OAAO,EAAE,6BAA6B,CAAC,GAAG,CAAC,CAAC;gBAChG,CAAC;YACF,CAAC;YAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CACT,yBAAyB,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,4BAA4B,CAAC,EAAE,CACrG,CAAC;YACH,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,2BAA2B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC;QACF,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO;iBACzB,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,CAAC,EAAE,CAAC,CAAC;YACX,IAAI,OAAO,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,kBAAkB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,CAAC,EAAE,CAAC,CAAC;YACpF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC1B;AAED,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0NAoD+K,CAAC","sourcesContent":["/**\n * Shared utilities for compaction and branch summarization.\n */\n\nimport type { Message } from \"@caupulican/pi-ai\";\nimport type { AgentMessage } from \"../types.ts\";\n\n// ============================================================================\n// File Operation Tracking\n// ============================================================================\n\nexport interface FileOperations {\n\tread: Set<string>;\n\twritten: Set<string>;\n\tedited: Set<string>;\n}\n\nexport function createFileOps(): FileOperations {\n\treturn {\n\t\tread: new Set(),\n\t\twritten: new Set(),\n\t\tedited: new Set(),\n\t};\n}\n\n/**\n * Extract file operations from tool calls in an assistant message.\n */\nexport function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void {\n\tif (message.role !== \"assistant\") return;\n\tif (!(\"content\" in message) || !Array.isArray(message.content)) return;\n\n\tfor (const block of message.content) {\n\t\tif (typeof block !== \"object\" || block === null) continue;\n\t\tif (!(\"type\" in block) || block.type !== \"toolCall\") continue;\n\t\tif (!(\"arguments\" in block) || !(\"name\" in block)) continue;\n\n\t\tconst args = block.arguments as Record<string, unknown> | undefined;\n\t\tif (!args) continue;\n\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tif (!path) continue;\n\n\t\tswitch (block.name) {\n\t\t\tcase \"read\":\n\t\t\t\tfileOps.read.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"write\":\n\t\t\t\tfileOps.written.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"edit\":\n\t\t\t\tfileOps.edited.add(path);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Compute final file lists from file operations.\n * Returns readFiles (files only read, not modified) and modifiedFiles.\n */\nexport function computeFileLists(fileOps: FileOperations): { readFiles: string[]; modifiedFiles: string[] } {\n\tconst modified = new Set([...fileOps.edited, ...fileOps.written]);\n\tconst readOnly = [...fileOps.read].filter((f) => !modified.has(f)).sort();\n\tconst modifiedFiles = [...modified].sort();\n\treturn { readFiles: readOnly, modifiedFiles };\n}\n\n/**\n * Format file operations as XML tags for summary.\n */\nexport function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string {\n\tconst sections: string[] = [];\n\tif (readFiles.length > 0) {\n\t\tsections.push(`<read-files>\\n${readFiles.join(\"\\n\")}\\n</read-files>`);\n\t}\n\tif (modifiedFiles.length > 0) {\n\t\tsections.push(`<modified-files>\\n${modifiedFiles.join(\"\\n\")}\\n</modified-files>`);\n\t}\n\tif (sections.length === 0) return \"\";\n\treturn `\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Message Serialization\n// ============================================================================\n\n/** Maximum characters for a tool result in serialized summaries. */\nconst TOOL_RESULT_MAX_CHARS = 2000;\n/** Maximum characters for non-gated assistant thinking in serialized summaries. */\nconst ASSISTANT_THINKING_MAX_CHARS = 2000;\n/** Maximum characters for one tool call's arguments in serialized summaries. */\nconst TOOL_CALL_ARGUMENTS_MAX_CHARS = 2000;\n\n/**\n * Truncate text to a maximum character length for summarization.\n * Keeps the beginning and appends a truncation marker.\n */\nfunction truncateForSummary(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\tconst truncatedChars = text.length - maxChars;\n\treturn `${text.slice(0, maxChars)}\\n\\n[... ${truncatedChars} more characters truncated]`;\n}\n\n/**\n * Serialize LLM messages to text for summarization.\n * This prevents the model from treating it as a conversation to continue.\n * Call convertToLlm() first to handle custom message types.\n *\n * Tool results are truncated to keep the summarization request within\n * reasonable token budgets. Full content is not needed for summarization.\n */\nexport function serializeConversation(messages: Message[]): string {\n\tconst parts: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tconst content =\n\t\t\t\ttypeof msg.content === \"string\"\n\t\t\t\t\t? msg.content\n\t\t\t\t\t: msg.content\n\t\t\t\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t\tif (content) parts.push(`[User]: ${content}`);\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tconst thinkingParts: string[] = [];\n\t\t\tconst toolCalls: string[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tthinkingParts.push(block.thinking);\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tconst args = block.arguments as Record<string, unknown>;\n\t\t\t\t\tconst argsStr = Object.entries(args)\n\t\t\t\t\t\t.map(([k, v]) => `${k}=${JSON.stringify(v)}`)\n\t\t\t\t\t\t.join(\", \");\n\t\t\t\t\ttoolCalls.push(`${block.name}(${truncateForSummary(argsStr, TOOL_CALL_ARGUMENTS_MAX_CHARS)})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (thinkingParts.length > 0) {\n\t\t\t\tparts.push(\n\t\t\t\t\t`[Assistant thinking]: ${truncateForSummary(thinkingParts.join(\"\\n\"), ASSISTANT_THINKING_MAX_CHARS)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (textParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant]: ${textParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tparts.push(`[Assistant tool calls]: ${toolCalls.join(\"; \")}`);\n\t\t\t}\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst content = msg.content\n\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t.map((c) => c.text)\n\t\t\t\t.join(\"\");\n\t\t\tif (content) {\n\t\t\t\tparts.push(`[Tool result]: ${truncateForSummary(content, TOOL_RESULT_MAX_CHARS)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ============================================================================\n// Summarization System Prompt\n// ============================================================================\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context checkpointer. Input: a serialized agent conversation. Output: ONLY the checkpoint, exactly in the format below. No preamble. No commentary. Same language as the user. Never include secrets/keys/tokens — write [REDACTED].\n\nRULES:\n- Recent turns weigh heaviest. Old turns contribute only rules, decisions, and file knowledge.\n- ## Active Task: the user's most recent UNFULFILLED input, near-verbatim. A question awaiting an answer IS an active task. If the user's last signal cancels earlier work (stop/undo/never mind), record the cancellation and DROP the cancelled work everywhere.\n- ### Mandatory Rules: every user prohibition (\"do not X\", \"never Y\", \"stop doing Z\") as one bullet each, imperative, with source turn if known. PRESERVE existing rules verbatim. A user-corrected mistake appears ONLY here as \"DO NOT <mistake>\" — the mistaken work itself must not survive.\n- ## Working Set: the currently active/recent files — path — why they matter.\n- ## Files: bare paths only; modified files must all appear, read files should be recalled when relevant.\n- ## Open Problems: unresolved errors only — command/operation plus first error line. Drop resolved/transient errors.\n- ## Done: numbered caveman log — \"N. VERB target — outcome\". Exact paths, commands, line numbers, error strings.\n- Do NOT carry resolved/transient errors, superseded approaches, or file contents. Record paths and intent, never bodies.\n- Sections with nothing: write \"(none)\".\n\nEXAMPLE INPUT (excerpt):\n[user]: add retry to the fetcher, and do not touch the legacy client\n[assistant]: (edits src/fetcher.ts, adds retry loop)\n[tool write src/fetcher.ts]: ok\n[tool bash npm test]: 2 failed: fetcher.test.ts\n[assistant]: (tries wrapping legacy client instead)\n[user]: no — stop changing the legacy client, I said don't touch it. Fix the two tests instead.\n\nEXAMPLE OUTPUT:\n## Active Task\nUser: \"Fix the two failing tests\" (fetcher.test.ts) — retry work continues, legacy-client changes cancelled.\n\n### Mandatory Rules\n- DO NOT touch the legacy client (user, twice)\n\n## Working Set\n- test/fetcher.test.ts — 2 failing, current focus\n- src/fetcher.ts — retry loop added\n\n## Files\n- src/fetcher.ts\n- test/fetcher.test.ts\n\n## Open Problems\n- TEST npm test: 2 failed: fetcher.test.ts\n\n## Done\n1. EDIT src/fetcher.ts — added retry loop\n2. TEST npm test — 2 failed: fetcher.test.ts\n\n## Key Decisions\n(none)\n\n## Constraints & Preferences\n(none)\n\n## Critical Context\n(none)\n\nNote what the example TEACHES (not just shows): the legacy-client wrapping attempt (cancelled work) appears nowhere except as the DO-NOT rule; the Active Task is the tail, near-verbatim; Done lines are caveman-format.`;\n"]}
|
|
@@ -2,11 +2,21 @@ import { type CompactionFacts } from "./extraction.ts";
|
|
|
2
2
|
export interface VerificationFailure {
|
|
3
3
|
check: string;
|
|
4
4
|
detail: string;
|
|
5
|
+
score?: number;
|
|
6
|
+
threshold?: number;
|
|
7
|
+
comparator?: "minimum" | "maximum";
|
|
8
|
+
matched?: number;
|
|
9
|
+
demanded?: number;
|
|
5
10
|
}
|
|
6
11
|
export interface VerificationReport {
|
|
7
12
|
ok: boolean;
|
|
8
13
|
failures: VerificationFailure[];
|
|
9
14
|
}
|
|
15
|
+
/** A failed verification attempt with its structured reports preserved for the retry ladder. */
|
|
16
|
+
export declare class CompactionVerificationError extends Error {
|
|
17
|
+
readonly reports: VerificationReport[];
|
|
18
|
+
constructor(reports: readonly VerificationReport[]);
|
|
19
|
+
}
|
|
10
20
|
export interface DeterministicGapFillResult {
|
|
11
21
|
summary: string;
|
|
12
22
|
verification: VerificationReport;
|
|
@@ -22,6 +32,7 @@ export declare function verifySummary(summary: string, facts: CompactionFacts):
|
|
|
22
32
|
export declare function isCompactionSummaryStructurallyUsable(summary: string): boolean;
|
|
23
33
|
export declare function deterministicallyFillSummaryGaps(summary: string, facts: CompactionFacts): DeterministicGapFillResult;
|
|
24
34
|
export declare function buildRetryPrompt(report: VerificationReport, previousAttempt?: string): string;
|
|
35
|
+
export declare function formatVerificationReports(reports: readonly VerificationReport[]): string;
|
|
25
36
|
export declare function tokenSet(text: string): Set<string>;
|
|
26
37
|
export declare function containment(needle: Set<string>, hay: Set<string>): number;
|
|
27
38
|
export declare function jaccard(a: Set<string>, b: Set<string>): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../../src/compaction/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErF,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,iCAAiC,MAAM,CAAC;AACrD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAM,CAAC;AA+BhD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,kBAAkB,CA0GzF;AAED,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAU9E;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,0BAA0B,CA8FpH;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7F;AA0GD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAQlD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAWzE;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAY9D","sourcesContent":["import { ACTIVE_TASK_SOURCE_MAX_CHARS, type CompactionFacts } from \"./extraction.ts\";\n\nexport interface VerificationFailure {\n\tcheck: string;\n\tdetail: string;\n}\n\nexport interface VerificationReport {\n\tok: boolean;\n\tfailures: VerificationFailure[];\n}\n\nexport interface DeterministicGapFillResult {\n\tsummary: string;\n\tverification: VerificationReport;\n\tchanged: boolean;\n}\n\nexport const FILES_READ_RECALL_THRESHOLD = 0.8;\nexport const ACTIVE_TASK_CONTAINMENT_THRESHOLD = 0.9;\nexport const MANDATORY_RULES_RECALL_THRESHOLD = 0.7;\nexport const CANCELLED_WORK_DROPPED_THRESHOLD = 0.1;\nexport const ACTIONS_RECALL_THRESHOLD = 0.6;\nexport const OPEN_ERRORS_RECALL_THRESHOLD = 0.7;\n\nconst SECTION_FILES = \"files\";\nconst SECTION_WORKING_SET = \"working set\";\nconst SECTION_OPEN_PROBLEMS = \"open problems\";\nconst SECTION_DONE = \"done\";\nconst SECTION_ACTIVE_TASK = \"active task\";\nconst SECTION_MANDATORY_RULES = \"mandatory rules\";\nconst SECTION_KEY_DECISIONS = \"key decisions\";\nconst SECTION_CONSTRAINTS = \"constraints & preferences\";\nconst SECTION_CRITICAL_CONTEXT = \"critical context\";\n\ninterface ParsedSummarySection {\n\theading: string;\n\tnormalized: string;\n\tlevel: \"##\" | \"###\";\n\tlines: string[];\n}\n\nconst REQUIRED_SUMMARY_SECTIONS: Array<{ heading: string; normalized: string; level: \"##\" | \"###\" }> = [\n\t{ heading: \"Active Task\", normalized: SECTION_ACTIVE_TASK, level: \"##\" },\n\t{ heading: \"Mandatory Rules\", normalized: SECTION_MANDATORY_RULES, level: \"###\" },\n\t{ heading: \"Working Set\", normalized: SECTION_WORKING_SET, level: \"##\" },\n\t{ heading: \"Files\", normalized: SECTION_FILES, level: \"##\" },\n\t{ heading: \"Open Problems\", normalized: SECTION_OPEN_PROBLEMS, level: \"##\" },\n\t{ heading: \"Done\", normalized: SECTION_DONE, level: \"##\" },\n\t{ heading: \"Key Decisions\", normalized: SECTION_KEY_DECISIONS, level: \"##\" },\n\t{ heading: \"Constraints & Preferences\", normalized: SECTION_CONSTRAINTS, level: \"##\" },\n\t{ heading: \"Critical Context\", normalized: SECTION_CRITICAL_CONTEXT, level: \"##\" },\n];\n\nexport function verifySummary(summary: string, facts: CompactionFacts): VerificationReport {\n\tif (factsAreEmpty(facts)) {\n\t\treturn { ok: true, failures: [] };\n\t}\n\n\tconst sections = extractSections(summary);\n\tconst failures: VerificationFailure[] = [];\n\tconst filesSection = sections[SECTION_FILES] ?? \"\";\n\tconst workingSetSection = sections[SECTION_WORKING_SET] ?? \"\";\n\tconst openProblemsSection = sections[SECTION_OPEN_PROBLEMS] ?? \"\";\n\tconst doneSection = sections[SECTION_DONE] ?? \"\";\n\tconst activeTaskSection = sections[SECTION_ACTIVE_TASK] ?? \"\";\n\tconst mandatoryRulesSection = sections[SECTION_MANDATORY_RULES] ?? \"\";\n\n\tconst modifiedFiles = facts.files.filter((file) => file.kind !== \"read\");\n\tconst missingModifiedFiles = modifiedFiles.map((file) => file.path).filter((path) => !filesSection.includes(path));\n\tif (missingModifiedFiles.length > 0) {\n\t\tfailures.push({\n\t\t\tcheck: \"files-modified-recall\",\n\t\t\tdetail: `Missing modified/created files in ## Files: ${missingModifiedFiles.join(\", \")}`,\n\t\t});\n\t}\n\n\tconst workingSetPaths = facts.workingSet.map((file) => file.path);\n\tconst missingWorkingSetPaths = workingSetPaths.filter((path) => !workingSetSection.includes(path));\n\tif (missingWorkingSetPaths.length > 0) {\n\t\tfailures.push({\n\t\t\tcheck: \"working-set-recall\",\n\t\t\tdetail: `Missing working-set files in ## Working Set: ${missingWorkingSetPaths.join(\", \")}`,\n\t\t});\n\t}\n\n\tconst readPaths = facts.files.filter((file) => file.kind === \"read\").map((file) => file.path);\n\tif (readPaths.length > 0) {\n\t\tconst score = containment(tokenSet(readPaths.join(\"\\n\")), tokenSet(filesSection));\n\t\tif (score < FILES_READ_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"files-read-recall\",\n\t\t\t\tdetail: `Read file recall ${formatScore(score)} below ${FILES_READ_RECALL_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.activeTaskSource) {\n\t\tconst score = containment(\n\t\t\ttokenSet(facts.activeTaskSource.slice(0, ACTIVE_TASK_SOURCE_MAX_CHARS)),\n\t\t\ttokenSet(activeTaskSection),\n\t\t);\n\t\tif (score < ACTIVE_TASK_CONTAINMENT_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"active-task-containment\",\n\t\t\t\tdetail: `Active task containment ${formatScore(score)} below ${ACTIVE_TASK_CONTAINMENT_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const prohibition of facts.prohibitions) {\n\t\tconst score = containment(tokenSet(prohibition), tokenSet(mandatoryRulesSection));\n\t\tif (score < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"mandatory-rules-recall\",\n\t\t\t\tdetail: `Missing mandatory rule: ${prohibition}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.cancelledText) {\n\t\tconst summaryOutsideMandatoryRules = removeSection(summary, SECTION_MANDATORY_RULES);\n\t\t// File paths from the facts are REQUIRED elsewhere (files-modified/read-recall demand them\n\t\t// in ## Files), so counting them as cancelled-work leakage would make the two gates\n\t\t// unsatisfiable together whenever a reversal message references a touched file.\n\t\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\t\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\t\tconst score = containment(cancelledTokens, tokenSet(summaryOutsideMandatoryRules));\n\t\tif (score > CANCELLED_WORK_DROPPED_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"cancelled-work-dropped\",\n\t\t\t\tdetail: `Cancelled work leakage ${formatScore(score)} above ${CANCELLED_WORK_DROPPED_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const error of facts.errorFacts) {\n\t\tconst score = containment(tokenSet(`${error.operation}: ${error.error}`), tokenSet(openProblemsSection));\n\t\tif (score < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"open-errors-recall\",\n\t\t\t\tdetail: `Open error recall ${formatScore(score)} below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.actions.length > 0) {\n\t\t// Asymmetric on purpose: the update path carries prior ## Done items forward (bounded), so a\n\t\t// symmetric overlap metric would punish faithful carry-over — the gate demands only that the\n\t\t// NEW span's actions are recalled in ## Done, however much history rides alongside them.\n\t\tconst score = containment(tokenSet(facts.actions.join(\"\\n\")), tokenSet(doneSection));\n\t\tif (score < ACTIONS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"actions-recall\",\n\t\t\t\tdetail: `New-action recall in ## Done ${formatScore(score)} below ${ACTIONS_RECALL_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { ok: failures.length === 0, failures };\n}\n\nexport function isCompactionSummaryStructurallyUsable(summary: string): boolean {\n\tif (summary.trim().length === 0) return false;\n\tconst sections = extractSections(summary);\n\treturn (\n\t\tsections[SECTION_ACTIVE_TASK] !== undefined ||\n\t\tsections[SECTION_FILES] !== undefined ||\n\t\tsections[SECTION_DONE] !== undefined ||\n\t\tsections[SECTION_WORKING_SET] !== undefined ||\n\t\tsections[SECTION_OPEN_PROBLEMS] !== undefined\n\t);\n}\n\nexport function deterministicallyFillSummaryGaps(summary: string, facts: CompactionFacts): DeterministicGapFillResult {\n\tif (!isCompactionSummaryStructurallyUsable(summary)) {\n\t\treturn { summary, verification: verifySummary(summary, facts), changed: false };\n\t}\n\n\tconst sections = parseSummarySections(summary);\n\tconst sectionByName = new Map<string, ParsedSummarySection>();\n\tconst extraSections: ParsedSummarySection[] = [];\n\tfor (const section of sections) {\n\t\tif (REQUIRED_SUMMARY_SECTIONS.some((required) => required.normalized === section.normalized)) {\n\t\t\tconst existing = sectionByName.get(section.normalized);\n\t\t\tif (existing) {\n\t\t\t\texisting.lines.push(...section.lines);\n\t\t\t} else {\n\t\t\t\tsectionByName.set(section.normalized, section);\n\t\t\t}\n\t\t} else {\n\t\t\textraSections.push(section);\n\t\t}\n\t}\n\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tif (!sectionByName.has(required.normalized)) {\n\t\t\tsectionByName.set(required.normalized, {\n\t\t\t\theading: required.heading,\n\t\t\t\tnormalized: required.normalized,\n\t\t\t\tlevel: required.level,\n\t\t\t\tlines: [\"(none)\"],\n\t\t\t});\n\t\t}\n\t}\n\n\tremoveCancelledWorkLines(sectionByName, facts);\n\n\tif (facts.activeTaskSource) {\n\t\tconst activeTask = sectionByName.get(SECTION_ACTIVE_TASK)!;\n\t\tif (\n\t\t\tcontainment(tokenSet(facts.activeTaskSource), tokenSetFromLines(activeTask.lines)) <\n\t\t\tACTIVE_TASK_CONTAINMENT_THRESHOLD\n\t\t) {\n\t\t\tappendContentLine(activeTask.lines, `User: ${facts.activeTaskSource}`);\n\t\t}\n\t}\n\n\tconst mandatoryRules = sectionByName.get(SECTION_MANDATORY_RULES)!;\n\tfor (const rule of facts.prohibitions) {\n\t\tif (containment(tokenSet(rule), tokenSetFromLines(mandatoryRules.lines)) < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(mandatoryRules.lines, `- ${rule}`);\n\t\t}\n\t}\n\n\tconst workingSet = sectionByName.get(SECTION_WORKING_SET)!;\n\tfor (const file of facts.workingSet) {\n\t\tif (!sectionLinesContain(workingSet.lines, file.path)) {\n\t\t\tappendContentLine(workingSet.lines, `- ${file.path} — ${file.note || file.kind}`);\n\t\t}\n\t}\n\n\tconst files = sectionByName.get(SECTION_FILES)!;\n\tfor (const file of facts.files) {\n\t\tif (!sectionLinesContain(files.lines, file.path)) {\n\t\t\tappendContentLine(files.lines, `- ${file.path}`);\n\t\t}\n\t}\n\n\tconst openProblems = sectionByName.get(SECTION_OPEN_PROBLEMS)!;\n\tfor (const error of facts.errorFacts) {\n\t\tconst required = `${error.operation}: ${error.error}`;\n\t\tif (containment(tokenSet(required), tokenSetFromLines(openProblems.lines)) < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(openProblems.lines, `- ${required}`);\n\t\t}\n\t}\n\n\tconst done = sectionByName.get(SECTION_DONE)!;\n\tif (\n\t\tfacts.actions.length > 0 &&\n\t\tcontainment(tokenSet(facts.actions.join(\"\\n\")), tokenSetFromLines(done.lines)) < ACTIONS_RECALL_THRESHOLD\n\t) {\n\t\tlet nextNumber = findNextDoneNumber(done.lines);\n\t\tfor (const action of facts.actions) {\n\t\t\tif (sectionLinesContain(done.lines, action)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tappendContentLine(done.lines, `${nextNumber}. ${action}`);\n\t\t\tnextNumber++;\n\t\t}\n\t}\n\n\tconst filledSummary = renderSummarySections(sectionByName, extraSections);\n\treturn {\n\t\tsummary: filledSummary,\n\t\tverification: verifySummary(filledSummary, facts),\n\t\tchanged: filledSummary !== summary,\n\t};\n}\n\nexport function buildRetryPrompt(report: VerificationReport, previousAttempt?: string): string {\n\tconst failures = report.failures.map((failure) => `${failure.check}: ${failure.detail}`).join(\"; \");\n\tconst previous = previousAttempt ? `\\n\\n<previous-attempt>\\n${previousAttempt}\\n</previous-attempt>` : \"\";\n\treturn `Your previous checkpoint failed verification: ${failures}. Fix ONLY these omissions.${previous}`;\n}\n\nfunction parseSummarySections(summary: string): ParsedSummarySection[] {\n\tconst sections: ParsedSummarySection[] = [];\n\tlet current: ParsedSummarySection | undefined;\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tcurrent = {\n\t\t\t\theading: match[2],\n\t\t\t\tnormalized: normalizeHeading(match[2]),\n\t\t\t\tlevel: match[1] as \"##\" | \"###\",\n\t\t\t\tlines: [],\n\t\t\t};\n\t\t\tsections.push(current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tcurrent.lines.push(line);\n\t\t}\n\t}\n\n\treturn sections;\n}\n\nfunction renderSummarySections(\n\tsectionByName: Map<string, ParsedSummarySection>,\n\textraSections: ParsedSummarySection[],\n): string {\n\tconst rendered: string[] = [];\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tconst section = sectionByName.get(required.normalized)!;\n\t\trendered.push(`${required.level} ${required.heading}`);\n\t\tconst body = normalizeSectionLines(section.lines);\n\t\trendered.push(...body);\n\t\trendered.push(\"\");\n\t}\n\tfor (const section of extraSections) {\n\t\trendered.push(`${section.level} ${section.heading}`);\n\t\trendered.push(...normalizeSectionLines(section.lines));\n\t\trendered.push(\"\");\n\t}\n\treturn rendered.join(\"\\n\").trimEnd();\n}\n\nfunction normalizeSectionLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim() === \"\") start++;\n\twhile (end > start && lines[end - 1].trim() === \"\") end--;\n\tif (start === end) return [\"(none)\"];\n\treturn lines.slice(start, end).map((line) => line.trimEnd());\n}\n\nfunction sectionLinesContain(lines: readonly string[], value: string): boolean {\n\treturn lines.some((line) => line.includes(value));\n}\n\nfunction tokenSetFromLines(lines: readonly string[]): Set<string> {\n\tconst tokens = new Set<string>();\n\tfor (const line of lines) {\n\t\tfor (const token of tokenSet(line)) tokens.add(token);\n\t}\n\treturn tokens;\n}\n\nfunction appendContentLine(lines: string[], line: string): void {\n\tconst normalized = normalizeSectionLines(lines).filter((existing) => existing.trim() !== \"(none)\");\n\tnormalized.push(line);\n\tlines.length = 0;\n\tlines.push(...normalized);\n}\n\nfunction findNextDoneNumber(lines: string[]): number {\n\tlet max = 0;\n\tfor (const line of lines) {\n\t\tconst match = /^\\s*(\\d+)\\./.exec(line);\n\t\tif (!match) continue;\n\t\tmax = Math.max(max, Number(match[1]));\n\t}\n\treturn max + 1;\n}\n\nfunction removeCancelledWorkLines(sectionByName: Map<string, ParsedSummarySection>, facts: CompactionFacts): void {\n\tif (!facts.cancelledText) return;\n\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\tif (cancelledTokens.size === 0) return;\n\n\tfor (const section of sectionByName.values()) {\n\t\tif (section.normalized === SECTION_MANDATORY_RULES) continue;\n\t\tsection.lines = section.lines.filter((line) => !lineShouldBeDroppedAsCancelledWork(line, cancelledTokens));\n\t}\n}\n\nfunction lineShouldBeDroppedAsCancelledWork(line: string, cancelledTokens: Set<string>): boolean {\n\tconst lineTokens = tokenSet(line);\n\tif (lineTokens.size === 0) return false;\n\tlet overlap = 0;\n\tfor (const token of lineTokens) {\n\t\tif (cancelledTokens.has(token)) overlap++;\n\t}\n\treturn overlap >= 2 && overlap / lineTokens.size >= 0.6;\n}\n\nexport function tokenSet(text: string): Set<string> {\n\treturn new Set(\n\t\ttext\n\t\t\t.toLowerCase()\n\t\t\t.split(/[^a-z0-9_./-]+/)\n\t\t\t.map((token) => token.trim())\n\t\t\t.filter((token) => token.length >= 3),\n\t);\n}\n\nexport function containment(needle: Set<string>, hay: Set<string>): number {\n\tif (needle.size === 0) {\n\t\treturn 1;\n\t}\n\tlet hits = 0;\n\tfor (const token of needle) {\n\t\tif (hay.has(token)) {\n\t\t\thits += 1;\n\t\t}\n\t}\n\treturn hits / needle.size;\n}\n\nexport function jaccard(a: Set<string>, b: Set<string>): number {\n\tif (a.size === 0 && b.size === 0) {\n\t\treturn 1;\n\t}\n\tlet intersection = 0;\n\tfor (const token of a) {\n\t\tif (b.has(token)) {\n\t\t\tintersection += 1;\n\t\t}\n\t}\n\tconst union = new Set([...a, ...b]).size;\n\treturn union === 0 ? 1 : intersection / union;\n}\n\nfunction factsAreEmpty(facts: CompactionFacts): boolean {\n\treturn (\n\t\tfacts.files.length === 0 &&\n\t\tfacts.workingSet.length === 0 &&\n\t\tfacts.actions.length === 0 &&\n\t\tfacts.errorFacts.length === 0 &&\n\t\tfacts.prohibitions.length === 0 &&\n\t\tfacts.cancelledText === \"\" &&\n\t\tfacts.activeTaskSource === \"\"\n\t);\n}\n\nfunction extractSections(summary: string): Record<string, string> {\n\tconst sections: Record<string, string> = {};\n\tlet current: string | undefined;\n\tlet bucket: string[] = [];\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tsections[current] = bucket.join(\"\\n\").trim();\n\t\t}\n\t\tbucket = [];\n\t};\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tflush();\n\t\t\tcurrent = normalizeHeading(match[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tbucket.push(line);\n\t\t}\n\t}\n\tflush();\n\treturn sections;\n}\n\nfunction removeSection(summary: string, heading: string): string {\n\tconst normalizedHeading = normalizeHeading(heading);\n\tconst kept: string[] = [];\n\tlet skipping = false;\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tskipping = normalizeHeading(match[1]) === normalizedHeading;\n\t\t\tif (skipping) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!skipping) {\n\t\t\tkept.push(line);\n\t\t}\n\t}\n\treturn kept.join(\"\\n\");\n}\n\nfunction normalizeHeading(heading: string): string {\n\treturn heading.trim().toLowerCase();\n}\n\nfunction formatScore(score: number): string {\n\treturn score.toFixed(2);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../../src/compaction/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErF,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,gGAAgG;AAChG,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAEvC,YAAY,OAAO,EAAE,SAAS,kBAAkB,EAAE,EAOjD;CACD;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,iCAAiC,MAAM,CAAC;AACrD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,4BAA4B,MAAM,CAAC;AA+BhD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,kBAAkB,CAsJzF;AAED,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAU9E;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,0BAA0B,CA8FpH;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7F;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAKxF;AA0HD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAQlD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAWzE;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAY9D","sourcesContent":["import { ACTIVE_TASK_SOURCE_MAX_CHARS, type CompactionFacts } from \"./extraction.ts\";\n\nexport interface VerificationFailure {\n\tcheck: string;\n\tdetail: string;\n\tscore?: number;\n\tthreshold?: number;\n\tcomparator?: \"minimum\" | \"maximum\";\n\tmatched?: number;\n\tdemanded?: number;\n}\n\nexport interface VerificationReport {\n\tok: boolean;\n\tfailures: VerificationFailure[];\n}\n\n/** A failed verification attempt with its structured reports preserved for the retry ladder. */\nexport class CompactionVerificationError extends Error {\n\treadonly reports: VerificationReport[];\n\n\tconstructor(reports: readonly VerificationReport[]) {\n\t\tsuper(`gate-failed: ${formatVerificationReports(reports)}`);\n\t\tthis.name = \"CompactionVerificationError\";\n\t\tthis.reports = reports.map((report) => ({\n\t\t\tok: report.ok,\n\t\t\tfailures: report.failures.map((failure) => ({ ...failure })),\n\t\t}));\n\t}\n}\n\nexport interface DeterministicGapFillResult {\n\tsummary: string;\n\tverification: VerificationReport;\n\tchanged: boolean;\n}\n\nexport const FILES_READ_RECALL_THRESHOLD = 0.8;\nexport const ACTIVE_TASK_CONTAINMENT_THRESHOLD = 0.9;\nexport const MANDATORY_RULES_RECALL_THRESHOLD = 0.7;\nexport const CANCELLED_WORK_DROPPED_THRESHOLD = 0.1;\nexport const ACTIONS_RECALL_THRESHOLD = 0.6;\nexport const OPEN_ERRORS_RECALL_THRESHOLD = 0.7;\n\nconst SECTION_FILES = \"files\";\nconst SECTION_WORKING_SET = \"working set\";\nconst SECTION_OPEN_PROBLEMS = \"open problems\";\nconst SECTION_DONE = \"done\";\nconst SECTION_ACTIVE_TASK = \"active task\";\nconst SECTION_MANDATORY_RULES = \"mandatory rules\";\nconst SECTION_KEY_DECISIONS = \"key decisions\";\nconst SECTION_CONSTRAINTS = \"constraints & preferences\";\nconst SECTION_CRITICAL_CONTEXT = \"critical context\";\n\ninterface ParsedSummarySection {\n\theading: string;\n\tnormalized: string;\n\tlevel: \"##\" | \"###\";\n\tlines: string[];\n}\n\nconst REQUIRED_SUMMARY_SECTIONS: Array<{ heading: string; normalized: string; level: \"##\" | \"###\" }> = [\n\t{ heading: \"Active Task\", normalized: SECTION_ACTIVE_TASK, level: \"##\" },\n\t{ heading: \"Mandatory Rules\", normalized: SECTION_MANDATORY_RULES, level: \"###\" },\n\t{ heading: \"Working Set\", normalized: SECTION_WORKING_SET, level: \"##\" },\n\t{ heading: \"Files\", normalized: SECTION_FILES, level: \"##\" },\n\t{ heading: \"Open Problems\", normalized: SECTION_OPEN_PROBLEMS, level: \"##\" },\n\t{ heading: \"Done\", normalized: SECTION_DONE, level: \"##\" },\n\t{ heading: \"Key Decisions\", normalized: SECTION_KEY_DECISIONS, level: \"##\" },\n\t{ heading: \"Constraints & Preferences\", normalized: SECTION_CONSTRAINTS, level: \"##\" },\n\t{ heading: \"Critical Context\", normalized: SECTION_CRITICAL_CONTEXT, level: \"##\" },\n];\n\nexport function verifySummary(summary: string, facts: CompactionFacts): VerificationReport {\n\tif (factsAreEmpty(facts)) {\n\t\treturn { ok: true, failures: [] };\n\t}\n\n\tconst sections = extractSections(summary);\n\tconst failures: VerificationFailure[] = [];\n\tconst filesSection = sections[SECTION_FILES] ?? \"\";\n\tconst workingSetSection = sections[SECTION_WORKING_SET] ?? \"\";\n\tconst openProblemsSection = sections[SECTION_OPEN_PROBLEMS] ?? \"\";\n\tconst doneSection = sections[SECTION_DONE] ?? \"\";\n\tconst activeTaskSection = sections[SECTION_ACTIVE_TASK] ?? \"\";\n\tconst mandatoryRulesSection = sections[SECTION_MANDATORY_RULES] ?? \"\";\n\n\tconst modifiedFiles = facts.files.filter((file) => file.kind !== \"read\");\n\tconst missingModifiedFiles = modifiedFiles\n\t\t.map((file) => file.path)\n\t\t.filter((path) => !sectionContainsExactPath(filesSection, path));\n\tif (missingModifiedFiles.length > 0) {\n\t\tconst matched = modifiedFiles.length - missingModifiedFiles.length;\n\t\tfailures.push({\n\t\t\tcheck: \"files-modified-recall\",\n\t\t\tdetail: `Modified/created file recall ${formatScore(matched / modifiedFiles.length)} (${matched}/${modifiedFiles.length} exact paths); missing: ${formatMissingValues(missingModifiedFiles)}`,\n\t\t\tscore: matched / modifiedFiles.length,\n\t\t\tthreshold: 1,\n\t\t\tcomparator: \"minimum\",\n\t\t\tmatched,\n\t\t\tdemanded: modifiedFiles.length,\n\t\t});\n\t}\n\n\tconst workingSetPaths = facts.workingSet.map((file) => file.path);\n\tconst missingWorkingSetPaths = workingSetPaths.filter((path) => !sectionContainsExactPath(workingSetSection, path));\n\tif (missingWorkingSetPaths.length > 0) {\n\t\tconst matched = workingSetPaths.length - missingWorkingSetPaths.length;\n\t\tfailures.push({\n\t\t\tcheck: \"working-set-recall\",\n\t\t\tdetail: `Working-set recall ${formatScore(matched / workingSetPaths.length)} (${matched}/${workingSetPaths.length} exact paths); missing: ${formatMissingValues(missingWorkingSetPaths)}`,\n\t\t\tscore: matched / workingSetPaths.length,\n\t\t\tthreshold: 1,\n\t\t\tcomparator: \"minimum\",\n\t\t\tmatched,\n\t\t\tdemanded: workingSetPaths.length,\n\t\t});\n\t}\n\n\tconst readPaths = facts.files.filter((file) => file.kind === \"read\").map((file) => file.path);\n\tif (readPaths.length > 0) {\n\t\t// Paths are atomic identities. A global token bag over-credits shared directory prefixes and\n\t\t// makes the score impossible to interpret as \"how many files survived\".\n\t\tconst missingReadPaths = readPaths.filter((path) => !sectionContainsExactPath(filesSection, path));\n\t\tconst matched = readPaths.length - missingReadPaths.length;\n\t\tconst score = matched / readPaths.length;\n\t\tif (score < FILES_READ_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"files-read-recall\",\n\t\t\t\tdetail: `Read file recall ${formatScore(score)} (${matched}/${readPaths.length} exact paths) below ${FILES_READ_RECALL_THRESHOLD}; missing: ${formatMissingValues(missingReadPaths)}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: FILES_READ_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t\tmatched,\n\t\t\t\tdemanded: readPaths.length,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.activeTaskSource) {\n\t\tconst score = containment(\n\t\t\ttokenSet(facts.activeTaskSource.slice(0, ACTIVE_TASK_SOURCE_MAX_CHARS)),\n\t\t\ttokenSet(activeTaskSection),\n\t\t);\n\t\tif (score < ACTIVE_TASK_CONTAINMENT_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"active-task-containment\",\n\t\t\t\tdetail: `Active task containment ${formatScore(score)} below ${ACTIVE_TASK_CONTAINMENT_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: ACTIVE_TASK_CONTAINMENT_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const prohibition of facts.prohibitions) {\n\t\tconst score = containment(tokenSet(prohibition), tokenSet(mandatoryRulesSection));\n\t\tif (score < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"mandatory-rules-recall\",\n\t\t\t\tdetail: `Mandatory rule recall ${formatScore(score)} below ${MANDATORY_RULES_RECALL_THRESHOLD}: ${prohibition}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: MANDATORY_RULES_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.cancelledText) {\n\t\tconst summaryOutsideMandatoryRules = removeSection(summary, SECTION_MANDATORY_RULES);\n\t\t// File paths from the facts are REQUIRED elsewhere (files-modified/read-recall demand them\n\t\t// in ## Files), so counting them as cancelled-work leakage would make the two gates\n\t\t// unsatisfiable together whenever a reversal message references a touched file.\n\t\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\t\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\t\tconst score = containment(cancelledTokens, tokenSet(summaryOutsideMandatoryRules));\n\t\tif (score > CANCELLED_WORK_DROPPED_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"cancelled-work-dropped\",\n\t\t\t\tdetail: `Cancelled work leakage ${formatScore(score)} above ${CANCELLED_WORK_DROPPED_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: CANCELLED_WORK_DROPPED_THRESHOLD,\n\t\t\t\tcomparator: \"maximum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const error of facts.errorFacts) {\n\t\t// Command strings can be much longer than their failure signal. Weight the operation and the\n\t\t// error identity equally so command flags cannot drown out a faithfully preserved failure (or\n\t\t// let a generic error phrase hide a missing operation).\n\t\tconst openProblemTokens = tokenSet(openProblemsSection);\n\t\tconst operationScore = containment(tokenSet(error.operation), openProblemTokens);\n\t\tconst errorScore = containment(tokenSet(error.error), openProblemTokens);\n\t\tconst score = (operationScore + errorScore) / 2;\n\t\tif (score < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"open-errors-recall\",\n\t\t\t\tdetail: `Open error recall ${formatScore(score)} (operation ${formatScore(operationScore)}, error ${formatScore(errorScore)}) below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: OPEN_ERRORS_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.actions.length > 0) {\n\t\t// Asymmetric on purpose: the update path carries prior ## Done items forward (bounded), so a\n\t\t// symmetric overlap metric would punish faithful carry-over — the gate demands only that the\n\t\t// NEW span's actions are recalled in ## Done, however much history rides alongside them.\n\t\tconst score = containment(tokenSet(facts.actions.join(\"\\n\")), tokenSet(doneSection));\n\t\tif (score < ACTIONS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"actions-recall\",\n\t\t\t\tdetail: `New-action recall in ## Done ${formatScore(score)} below ${ACTIONS_RECALL_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: ACTIONS_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { ok: failures.length === 0, failures };\n}\n\nexport function isCompactionSummaryStructurallyUsable(summary: string): boolean {\n\tif (summary.trim().length === 0) return false;\n\tconst sections = extractSections(summary);\n\treturn (\n\t\tsections[SECTION_ACTIVE_TASK] !== undefined ||\n\t\tsections[SECTION_FILES] !== undefined ||\n\t\tsections[SECTION_DONE] !== undefined ||\n\t\tsections[SECTION_WORKING_SET] !== undefined ||\n\t\tsections[SECTION_OPEN_PROBLEMS] !== undefined\n\t);\n}\n\nexport function deterministicallyFillSummaryGaps(summary: string, facts: CompactionFacts): DeterministicGapFillResult {\n\tif (!isCompactionSummaryStructurallyUsable(summary)) {\n\t\treturn { summary, verification: verifySummary(summary, facts), changed: false };\n\t}\n\n\tconst sections = parseSummarySections(summary);\n\tconst sectionByName = new Map<string, ParsedSummarySection>();\n\tconst extraSections: ParsedSummarySection[] = [];\n\tfor (const section of sections) {\n\t\tif (REQUIRED_SUMMARY_SECTIONS.some((required) => required.normalized === section.normalized)) {\n\t\t\tconst existing = sectionByName.get(section.normalized);\n\t\t\tif (existing) {\n\t\t\t\texisting.lines.push(...section.lines);\n\t\t\t} else {\n\t\t\t\tsectionByName.set(section.normalized, section);\n\t\t\t}\n\t\t} else {\n\t\t\textraSections.push(section);\n\t\t}\n\t}\n\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tif (!sectionByName.has(required.normalized)) {\n\t\t\tsectionByName.set(required.normalized, {\n\t\t\t\theading: required.heading,\n\t\t\t\tnormalized: required.normalized,\n\t\t\t\tlevel: required.level,\n\t\t\t\tlines: [\"(none)\"],\n\t\t\t});\n\t\t}\n\t}\n\n\tremoveCancelledWorkLines(sectionByName, facts);\n\n\tif (facts.activeTaskSource) {\n\t\tconst activeTask = sectionByName.get(SECTION_ACTIVE_TASK)!;\n\t\tif (\n\t\t\tcontainment(tokenSet(facts.activeTaskSource), tokenSetFromLines(activeTask.lines)) <\n\t\t\tACTIVE_TASK_CONTAINMENT_THRESHOLD\n\t\t) {\n\t\t\tappendContentLine(activeTask.lines, `User: ${facts.activeTaskSource}`);\n\t\t}\n\t}\n\n\tconst mandatoryRules = sectionByName.get(SECTION_MANDATORY_RULES)!;\n\tfor (const rule of facts.prohibitions) {\n\t\tif (containment(tokenSet(rule), tokenSetFromLines(mandatoryRules.lines)) < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(mandatoryRules.lines, `- ${rule}`);\n\t\t}\n\t}\n\n\tconst workingSet = sectionByName.get(SECTION_WORKING_SET)!;\n\tfor (const file of facts.workingSet) {\n\t\tif (!sectionContainsExactPath(workingSet.lines.join(\"\\n\"), file.path)) {\n\t\t\tappendContentLine(workingSet.lines, `- ${file.path} — ${file.note || file.kind}`);\n\t\t}\n\t}\n\n\tconst files = sectionByName.get(SECTION_FILES)!;\n\tfor (const file of facts.files) {\n\t\tif (!sectionContainsExactPath(files.lines.join(\"\\n\"), file.path)) {\n\t\t\tappendContentLine(files.lines, `- ${file.path}`);\n\t\t}\n\t}\n\n\tconst openProblems = sectionByName.get(SECTION_OPEN_PROBLEMS)!;\n\tfor (const error of facts.errorFacts) {\n\t\tconst required = `${error.operation}: ${error.error}`;\n\t\tif (containment(tokenSet(required), tokenSetFromLines(openProblems.lines)) < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(openProblems.lines, `- ${required}`);\n\t\t}\n\t}\n\n\tconst done = sectionByName.get(SECTION_DONE)!;\n\tif (\n\t\tfacts.actions.length > 0 &&\n\t\tcontainment(tokenSet(facts.actions.join(\"\\n\")), tokenSetFromLines(done.lines)) < ACTIONS_RECALL_THRESHOLD\n\t) {\n\t\tlet nextNumber = findNextDoneNumber(done.lines);\n\t\tfor (const action of facts.actions) {\n\t\t\tif (sectionLinesContain(done.lines, action)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tappendContentLine(done.lines, `${nextNumber}. ${action}`);\n\t\t\tnextNumber++;\n\t\t}\n\t}\n\n\tconst filledSummary = renderSummarySections(sectionByName, extraSections);\n\treturn {\n\t\tsummary: filledSummary,\n\t\tverification: verifySummary(filledSummary, facts),\n\t\tchanged: filledSummary !== summary,\n\t};\n}\n\nexport function buildRetryPrompt(report: VerificationReport, previousAttempt?: string): string {\n\tconst failures = report.failures.map((failure) => `${failure.check}: ${failure.detail}`).join(\"; \");\n\tconst previous = previousAttempt ? `\\n\\n<previous-attempt>\\n${previousAttempt}\\n</previous-attempt>` : \"\";\n\treturn `Your previous checkpoint failed verification: ${failures}. Fix ONLY these omissions.${previous}`;\n}\n\nexport function formatVerificationReports(reports: readonly VerificationReport[]): string {\n\treturn reports\n\t\t.flatMap((report) => report.failures)\n\t\t.map((failure) => `${failure.check}: ${failure.detail}`)\n\t\t.join(\", \");\n}\n\nfunction parseSummarySections(summary: string): ParsedSummarySection[] {\n\tconst sections: ParsedSummarySection[] = [];\n\tlet current: ParsedSummarySection | undefined;\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tcurrent = {\n\t\t\t\theading: match[2],\n\t\t\t\tnormalized: normalizeHeading(match[2]),\n\t\t\t\tlevel: match[1] as \"##\" | \"###\",\n\t\t\t\tlines: [],\n\t\t\t};\n\t\t\tsections.push(current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tcurrent.lines.push(line);\n\t\t}\n\t}\n\n\treturn sections;\n}\n\nfunction renderSummarySections(\n\tsectionByName: Map<string, ParsedSummarySection>,\n\textraSections: ParsedSummarySection[],\n): string {\n\tconst rendered: string[] = [];\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tconst section = sectionByName.get(required.normalized)!;\n\t\trendered.push(`${required.level} ${required.heading}`);\n\t\tconst body = normalizeSectionLines(section.lines);\n\t\trendered.push(...body);\n\t\trendered.push(\"\");\n\t}\n\tfor (const section of extraSections) {\n\t\trendered.push(`${section.level} ${section.heading}`);\n\t\trendered.push(...normalizeSectionLines(section.lines));\n\t\trendered.push(\"\");\n\t}\n\treturn rendered.join(\"\\n\").trimEnd();\n}\n\nfunction normalizeSectionLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim() === \"\") start++;\n\twhile (end > start && lines[end - 1].trim() === \"\") end--;\n\tif (start === end) return [\"(none)\"];\n\treturn lines.slice(start, end).map((line) => line.trimEnd());\n}\n\nfunction sectionLinesContain(lines: readonly string[], value: string): boolean {\n\treturn lines.some((line) => line.includes(value));\n}\n\nfunction sectionContainsExactPath(section: string, path: string): boolean {\n\tlet fromIndex = 0;\n\twhile (fromIndex <= section.length - path.length) {\n\t\tconst index = section.indexOf(path, fromIndex);\n\t\tif (index < 0) return false;\n\t\tconst before = index > 0 ? section[index - 1] : undefined;\n\t\tconst afterIndex = index + path.length;\n\t\tconst after = afterIndex < section.length ? section[afterIndex] : undefined;\n\t\tconst boundary = (character: string | undefined): boolean =>\n\t\t\tcharacter === undefined || /[\\s`'\"()[\\]{}<>,:;|—]/.test(character);\n\t\tif (boundary(before) && boundary(after)) return true;\n\t\tfromIndex = index + 1;\n\t}\n\treturn false;\n}\n\nfunction tokenSetFromLines(lines: readonly string[]): Set<string> {\n\tconst tokens = new Set<string>();\n\tfor (const line of lines) {\n\t\tfor (const token of tokenSet(line)) tokens.add(token);\n\t}\n\treturn tokens;\n}\n\nfunction appendContentLine(lines: string[], line: string): void {\n\tconst normalized = normalizeSectionLines(lines).filter((existing) => existing.trim() !== \"(none)\");\n\tnormalized.push(line);\n\tlines.length = 0;\n\tlines.push(...normalized);\n}\n\nfunction findNextDoneNumber(lines: string[]): number {\n\tlet max = 0;\n\tfor (const line of lines) {\n\t\tconst match = /^\\s*(\\d+)\\./.exec(line);\n\t\tif (!match) continue;\n\t\tmax = Math.max(max, Number(match[1]));\n\t}\n\treturn max + 1;\n}\n\nfunction removeCancelledWorkLines(sectionByName: Map<string, ParsedSummarySection>, facts: CompactionFacts): void {\n\tif (!facts.cancelledText) return;\n\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\tif (cancelledTokens.size === 0) return;\n\n\tfor (const section of sectionByName.values()) {\n\t\tif (section.normalized === SECTION_MANDATORY_RULES) continue;\n\t\tsection.lines = section.lines.filter((line) => !lineShouldBeDroppedAsCancelledWork(line, cancelledTokens));\n\t}\n}\n\nfunction lineShouldBeDroppedAsCancelledWork(line: string, cancelledTokens: Set<string>): boolean {\n\tconst lineTokens = tokenSet(line);\n\tif (lineTokens.size === 0) return false;\n\tlet overlap = 0;\n\tfor (const token of lineTokens) {\n\t\tif (cancelledTokens.has(token)) overlap++;\n\t}\n\treturn overlap >= 2 && overlap / lineTokens.size >= 0.6;\n}\n\nexport function tokenSet(text: string): Set<string> {\n\treturn new Set(\n\t\ttext\n\t\t\t.toLowerCase()\n\t\t\t.split(/[^a-z0-9_./-]+/)\n\t\t\t.map((token) => token.trim())\n\t\t\t.filter((token) => token.length >= 3),\n\t);\n}\n\nexport function containment(needle: Set<string>, hay: Set<string>): number {\n\tif (needle.size === 0) {\n\t\treturn 1;\n\t}\n\tlet hits = 0;\n\tfor (const token of needle) {\n\t\tif (hay.has(token)) {\n\t\t\thits += 1;\n\t\t}\n\t}\n\treturn hits / needle.size;\n}\n\nexport function jaccard(a: Set<string>, b: Set<string>): number {\n\tif (a.size === 0 && b.size === 0) {\n\t\treturn 1;\n\t}\n\tlet intersection = 0;\n\tfor (const token of a) {\n\t\tif (b.has(token)) {\n\t\t\tintersection += 1;\n\t\t}\n\t}\n\tconst union = new Set([...a, ...b]).size;\n\treturn union === 0 ? 1 : intersection / union;\n}\n\nfunction factsAreEmpty(facts: CompactionFacts): boolean {\n\treturn (\n\t\tfacts.files.length === 0 &&\n\t\tfacts.workingSet.length === 0 &&\n\t\tfacts.actions.length === 0 &&\n\t\tfacts.errorFacts.length === 0 &&\n\t\tfacts.prohibitions.length === 0 &&\n\t\tfacts.cancelledText === \"\" &&\n\t\tfacts.activeTaskSource === \"\"\n\t);\n}\n\nfunction extractSections(summary: string): Record<string, string> {\n\tconst sections: Record<string, string> = {};\n\tlet current: string | undefined;\n\tlet bucket: string[] = [];\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tsections[current] = bucket.join(\"\\n\").trim();\n\t\t}\n\t\tbucket = [];\n\t};\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tflush();\n\t\t\tcurrent = normalizeHeading(match[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tbucket.push(line);\n\t\t}\n\t}\n\tflush();\n\treturn sections;\n}\n\nfunction removeSection(summary: string, heading: string): string {\n\tconst normalizedHeading = normalizeHeading(heading);\n\tconst kept: string[] = [];\n\tlet skipping = false;\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tskipping = normalizeHeading(match[1]) === normalizedHeading;\n\t\t\tif (skipping) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!skipping) {\n\t\t\tkept.push(line);\n\t\t}\n\t}\n\treturn kept.join(\"\\n\");\n}\n\nfunction normalizeHeading(heading: string): string {\n\treturn heading.trim().toLowerCase();\n}\n\nfunction formatScore(score: number): string {\n\treturn score.toFixed(2);\n}\n\nfunction formatMissingValues(values: readonly string[]): string {\n\tconst visible = values.slice(0, 5).join(\", \");\n\treturn values.length > 5 ? `${visible} (+${values.length - 5} more)` : visible;\n}\n"]}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { ACTIVE_TASK_SOURCE_MAX_CHARS } from "./extraction.js";
|
|
2
|
+
/** A failed verification attempt with its structured reports preserved for the retry ladder. */
|
|
3
|
+
export class CompactionVerificationError extends Error {
|
|
4
|
+
reports;
|
|
5
|
+
constructor(reports) {
|
|
6
|
+
super(`gate-failed: ${formatVerificationReports(reports)}`);
|
|
7
|
+
this.name = "CompactionVerificationError";
|
|
8
|
+
this.reports = reports.map((report) => ({
|
|
9
|
+
ok: report.ok,
|
|
10
|
+
failures: report.failures.map((failure) => ({ ...failure })),
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
2
14
|
export const FILES_READ_RECALL_THRESHOLD = 0.8;
|
|
3
15
|
export const ACTIVE_TASK_CONTAINMENT_THRESHOLD = 0.9;
|
|
4
16
|
export const MANDATORY_RULES_RECALL_THRESHOLD = 0.7;
|
|
@@ -38,28 +50,51 @@ export function verifySummary(summary, facts) {
|
|
|
38
50
|
const activeTaskSection = sections[SECTION_ACTIVE_TASK] ?? "";
|
|
39
51
|
const mandatoryRulesSection = sections[SECTION_MANDATORY_RULES] ?? "";
|
|
40
52
|
const modifiedFiles = facts.files.filter((file) => file.kind !== "read");
|
|
41
|
-
const missingModifiedFiles = modifiedFiles
|
|
53
|
+
const missingModifiedFiles = modifiedFiles
|
|
54
|
+
.map((file) => file.path)
|
|
55
|
+
.filter((path) => !sectionContainsExactPath(filesSection, path));
|
|
42
56
|
if (missingModifiedFiles.length > 0) {
|
|
57
|
+
const matched = modifiedFiles.length - missingModifiedFiles.length;
|
|
43
58
|
failures.push({
|
|
44
59
|
check: "files-modified-recall",
|
|
45
|
-
detail: `
|
|
60
|
+
detail: `Modified/created file recall ${formatScore(matched / modifiedFiles.length)} (${matched}/${modifiedFiles.length} exact paths); missing: ${formatMissingValues(missingModifiedFiles)}`,
|
|
61
|
+
score: matched / modifiedFiles.length,
|
|
62
|
+
threshold: 1,
|
|
63
|
+
comparator: "minimum",
|
|
64
|
+
matched,
|
|
65
|
+
demanded: modifiedFiles.length,
|
|
46
66
|
});
|
|
47
67
|
}
|
|
48
68
|
const workingSetPaths = facts.workingSet.map((file) => file.path);
|
|
49
|
-
const missingWorkingSetPaths = workingSetPaths.filter((path) => !workingSetSection
|
|
69
|
+
const missingWorkingSetPaths = workingSetPaths.filter((path) => !sectionContainsExactPath(workingSetSection, path));
|
|
50
70
|
if (missingWorkingSetPaths.length > 0) {
|
|
71
|
+
const matched = workingSetPaths.length - missingWorkingSetPaths.length;
|
|
51
72
|
failures.push({
|
|
52
73
|
check: "working-set-recall",
|
|
53
|
-
detail: `
|
|
74
|
+
detail: `Working-set recall ${formatScore(matched / workingSetPaths.length)} (${matched}/${workingSetPaths.length} exact paths); missing: ${formatMissingValues(missingWorkingSetPaths)}`,
|
|
75
|
+
score: matched / workingSetPaths.length,
|
|
76
|
+
threshold: 1,
|
|
77
|
+
comparator: "minimum",
|
|
78
|
+
matched,
|
|
79
|
+
demanded: workingSetPaths.length,
|
|
54
80
|
});
|
|
55
81
|
}
|
|
56
82
|
const readPaths = facts.files.filter((file) => file.kind === "read").map((file) => file.path);
|
|
57
83
|
if (readPaths.length > 0) {
|
|
58
|
-
|
|
84
|
+
// Paths are atomic identities. A global token bag over-credits shared directory prefixes and
|
|
85
|
+
// makes the score impossible to interpret as "how many files survived".
|
|
86
|
+
const missingReadPaths = readPaths.filter((path) => !sectionContainsExactPath(filesSection, path));
|
|
87
|
+
const matched = readPaths.length - missingReadPaths.length;
|
|
88
|
+
const score = matched / readPaths.length;
|
|
59
89
|
if (score < FILES_READ_RECALL_THRESHOLD) {
|
|
60
90
|
failures.push({
|
|
61
91
|
check: "files-read-recall",
|
|
62
|
-
detail: `Read file recall ${formatScore(score)} below ${FILES_READ_RECALL_THRESHOLD}`,
|
|
92
|
+
detail: `Read file recall ${formatScore(score)} (${matched}/${readPaths.length} exact paths) below ${FILES_READ_RECALL_THRESHOLD}; missing: ${formatMissingValues(missingReadPaths)}`,
|
|
93
|
+
score,
|
|
94
|
+
threshold: FILES_READ_RECALL_THRESHOLD,
|
|
95
|
+
comparator: "minimum",
|
|
96
|
+
matched,
|
|
97
|
+
demanded: readPaths.length,
|
|
63
98
|
});
|
|
64
99
|
}
|
|
65
100
|
}
|
|
@@ -69,6 +104,9 @@ export function verifySummary(summary, facts) {
|
|
|
69
104
|
failures.push({
|
|
70
105
|
check: "active-task-containment",
|
|
71
106
|
detail: `Active task containment ${formatScore(score)} below ${ACTIVE_TASK_CONTAINMENT_THRESHOLD}`,
|
|
107
|
+
score,
|
|
108
|
+
threshold: ACTIVE_TASK_CONTAINMENT_THRESHOLD,
|
|
109
|
+
comparator: "minimum",
|
|
72
110
|
});
|
|
73
111
|
}
|
|
74
112
|
}
|
|
@@ -77,7 +115,10 @@ export function verifySummary(summary, facts) {
|
|
|
77
115
|
if (score < MANDATORY_RULES_RECALL_THRESHOLD) {
|
|
78
116
|
failures.push({
|
|
79
117
|
check: "mandatory-rules-recall",
|
|
80
|
-
detail: `
|
|
118
|
+
detail: `Mandatory rule recall ${formatScore(score)} below ${MANDATORY_RULES_RECALL_THRESHOLD}: ${prohibition}`,
|
|
119
|
+
score,
|
|
120
|
+
threshold: MANDATORY_RULES_RECALL_THRESHOLD,
|
|
121
|
+
comparator: "minimum",
|
|
81
122
|
});
|
|
82
123
|
}
|
|
83
124
|
}
|
|
@@ -93,15 +134,27 @@ export function verifySummary(summary, facts) {
|
|
|
93
134
|
failures.push({
|
|
94
135
|
check: "cancelled-work-dropped",
|
|
95
136
|
detail: `Cancelled work leakage ${formatScore(score)} above ${CANCELLED_WORK_DROPPED_THRESHOLD}`,
|
|
137
|
+
score,
|
|
138
|
+
threshold: CANCELLED_WORK_DROPPED_THRESHOLD,
|
|
139
|
+
comparator: "maximum",
|
|
96
140
|
});
|
|
97
141
|
}
|
|
98
142
|
}
|
|
99
143
|
for (const error of facts.errorFacts) {
|
|
100
|
-
|
|
144
|
+
// Command strings can be much longer than their failure signal. Weight the operation and the
|
|
145
|
+
// error identity equally so command flags cannot drown out a faithfully preserved failure (or
|
|
146
|
+
// let a generic error phrase hide a missing operation).
|
|
147
|
+
const openProblemTokens = tokenSet(openProblemsSection);
|
|
148
|
+
const operationScore = containment(tokenSet(error.operation), openProblemTokens);
|
|
149
|
+
const errorScore = containment(tokenSet(error.error), openProblemTokens);
|
|
150
|
+
const score = (operationScore + errorScore) / 2;
|
|
101
151
|
if (score < OPEN_ERRORS_RECALL_THRESHOLD) {
|
|
102
152
|
failures.push({
|
|
103
153
|
check: "open-errors-recall",
|
|
104
|
-
detail: `Open error recall ${formatScore(score)} below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,
|
|
154
|
+
detail: `Open error recall ${formatScore(score)} (operation ${formatScore(operationScore)}, error ${formatScore(errorScore)}) below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,
|
|
155
|
+
score,
|
|
156
|
+
threshold: OPEN_ERRORS_RECALL_THRESHOLD,
|
|
157
|
+
comparator: "minimum",
|
|
105
158
|
});
|
|
106
159
|
}
|
|
107
160
|
}
|
|
@@ -114,6 +167,9 @@ export function verifySummary(summary, facts) {
|
|
|
114
167
|
failures.push({
|
|
115
168
|
check: "actions-recall",
|
|
116
169
|
detail: `New-action recall in ## Done ${formatScore(score)} below ${ACTIONS_RECALL_THRESHOLD}`,
|
|
170
|
+
score,
|
|
171
|
+
threshold: ACTIONS_RECALL_THRESHOLD,
|
|
172
|
+
comparator: "minimum",
|
|
117
173
|
});
|
|
118
174
|
}
|
|
119
175
|
}
|
|
@@ -176,13 +232,13 @@ export function deterministicallyFillSummaryGaps(summary, facts) {
|
|
|
176
232
|
}
|
|
177
233
|
const workingSet = sectionByName.get(SECTION_WORKING_SET);
|
|
178
234
|
for (const file of facts.workingSet) {
|
|
179
|
-
if (!
|
|
235
|
+
if (!sectionContainsExactPath(workingSet.lines.join("\n"), file.path)) {
|
|
180
236
|
appendContentLine(workingSet.lines, `- ${file.path} — ${file.note || file.kind}`);
|
|
181
237
|
}
|
|
182
238
|
}
|
|
183
239
|
const files = sectionByName.get(SECTION_FILES);
|
|
184
240
|
for (const file of facts.files) {
|
|
185
|
-
if (!
|
|
241
|
+
if (!sectionContainsExactPath(files.lines.join("\n"), file.path)) {
|
|
186
242
|
appendContentLine(files.lines, `- ${file.path}`);
|
|
187
243
|
}
|
|
188
244
|
}
|
|
@@ -217,6 +273,12 @@ export function buildRetryPrompt(report, previousAttempt) {
|
|
|
217
273
|
const previous = previousAttempt ? `\n\n<previous-attempt>\n${previousAttempt}\n</previous-attempt>` : "";
|
|
218
274
|
return `Your previous checkpoint failed verification: ${failures}. Fix ONLY these omissions.${previous}`;
|
|
219
275
|
}
|
|
276
|
+
export function formatVerificationReports(reports) {
|
|
277
|
+
return reports
|
|
278
|
+
.flatMap((report) => report.failures)
|
|
279
|
+
.map((failure) => `${failure.check}: ${failure.detail}`)
|
|
280
|
+
.join(", ");
|
|
281
|
+
}
|
|
220
282
|
function parseSummarySections(summary) {
|
|
221
283
|
const sections = [];
|
|
222
284
|
let current;
|
|
@@ -268,6 +330,22 @@ function normalizeSectionLines(lines) {
|
|
|
268
330
|
function sectionLinesContain(lines, value) {
|
|
269
331
|
return lines.some((line) => line.includes(value));
|
|
270
332
|
}
|
|
333
|
+
function sectionContainsExactPath(section, path) {
|
|
334
|
+
let fromIndex = 0;
|
|
335
|
+
while (fromIndex <= section.length - path.length) {
|
|
336
|
+
const index = section.indexOf(path, fromIndex);
|
|
337
|
+
if (index < 0)
|
|
338
|
+
return false;
|
|
339
|
+
const before = index > 0 ? section[index - 1] : undefined;
|
|
340
|
+
const afterIndex = index + path.length;
|
|
341
|
+
const after = afterIndex < section.length ? section[afterIndex] : undefined;
|
|
342
|
+
const boundary = (character) => character === undefined || /[\s`'"()[\]{}<>,:;|—]/.test(character);
|
|
343
|
+
if (boundary(before) && boundary(after))
|
|
344
|
+
return true;
|
|
345
|
+
fromIndex = index + 1;
|
|
346
|
+
}
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
271
349
|
function tokenSetFromLines(lines) {
|
|
272
350
|
const tokens = new Set();
|
|
273
351
|
for (const line of lines) {
|
|
@@ -405,4 +483,8 @@ function normalizeHeading(heading) {
|
|
|
405
483
|
function formatScore(score) {
|
|
406
484
|
return score.toFixed(2);
|
|
407
485
|
}
|
|
486
|
+
function formatMissingValues(values) {
|
|
487
|
+
const visible = values.slice(0, 5).join(", ");
|
|
488
|
+
return values.length > 5 ? `${visible} (+${values.length - 5} more)` : visible;
|
|
489
|
+
}
|
|
408
490
|
//# sourceMappingURL=verification.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/compaction/verification.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTIVE_TASK_SOURCE_MAX_CHARS, type CompactionFacts } from \"./extraction.ts\";\n\nexport interface VerificationFailure {\n\tcheck: string;\n\tdetail: string;\n}\n\nexport interface VerificationReport {\n\tok: boolean;\n\tfailures: VerificationFailure[];\n}\n\nexport interface DeterministicGapFillResult {\n\tsummary: string;\n\tverification: VerificationReport;\n\tchanged: boolean;\n}\n\nexport const FILES_READ_RECALL_THRESHOLD = 0.8;\nexport const ACTIVE_TASK_CONTAINMENT_THRESHOLD = 0.9;\nexport const MANDATORY_RULES_RECALL_THRESHOLD = 0.7;\nexport const CANCELLED_WORK_DROPPED_THRESHOLD = 0.1;\nexport const ACTIONS_RECALL_THRESHOLD = 0.6;\nexport const OPEN_ERRORS_RECALL_THRESHOLD = 0.7;\n\nconst SECTION_FILES = \"files\";\nconst SECTION_WORKING_SET = \"working set\";\nconst SECTION_OPEN_PROBLEMS = \"open problems\";\nconst SECTION_DONE = \"done\";\nconst SECTION_ACTIVE_TASK = \"active task\";\nconst SECTION_MANDATORY_RULES = \"mandatory rules\";\nconst SECTION_KEY_DECISIONS = \"key decisions\";\nconst SECTION_CONSTRAINTS = \"constraints & preferences\";\nconst SECTION_CRITICAL_CONTEXT = \"critical context\";\n\ninterface ParsedSummarySection {\n\theading: string;\n\tnormalized: string;\n\tlevel: \"##\" | \"###\";\n\tlines: string[];\n}\n\nconst REQUIRED_SUMMARY_SECTIONS: Array<{ heading: string; normalized: string; level: \"##\" | \"###\" }> = [\n\t{ heading: \"Active Task\", normalized: SECTION_ACTIVE_TASK, level: \"##\" },\n\t{ heading: \"Mandatory Rules\", normalized: SECTION_MANDATORY_RULES, level: \"###\" },\n\t{ heading: \"Working Set\", normalized: SECTION_WORKING_SET, level: \"##\" },\n\t{ heading: \"Files\", normalized: SECTION_FILES, level: \"##\" },\n\t{ heading: \"Open Problems\", normalized: SECTION_OPEN_PROBLEMS, level: \"##\" },\n\t{ heading: \"Done\", normalized: SECTION_DONE, level: \"##\" },\n\t{ heading: \"Key Decisions\", normalized: SECTION_KEY_DECISIONS, level: \"##\" },\n\t{ heading: \"Constraints & Preferences\", normalized: SECTION_CONSTRAINTS, level: \"##\" },\n\t{ heading: \"Critical Context\", normalized: SECTION_CRITICAL_CONTEXT, level: \"##\" },\n];\n\nexport function verifySummary(summary: string, facts: CompactionFacts): VerificationReport {\n\tif (factsAreEmpty(facts)) {\n\t\treturn { ok: true, failures: [] };\n\t}\n\n\tconst sections = extractSections(summary);\n\tconst failures: VerificationFailure[] = [];\n\tconst filesSection = sections[SECTION_FILES] ?? \"\";\n\tconst workingSetSection = sections[SECTION_WORKING_SET] ?? \"\";\n\tconst openProblemsSection = sections[SECTION_OPEN_PROBLEMS] ?? \"\";\n\tconst doneSection = sections[SECTION_DONE] ?? \"\";\n\tconst activeTaskSection = sections[SECTION_ACTIVE_TASK] ?? \"\";\n\tconst mandatoryRulesSection = sections[SECTION_MANDATORY_RULES] ?? \"\";\n\n\tconst modifiedFiles = facts.files.filter((file) => file.kind !== \"read\");\n\tconst missingModifiedFiles = modifiedFiles.map((file) => file.path).filter((path) => !filesSection.includes(path));\n\tif (missingModifiedFiles.length > 0) {\n\t\tfailures.push({\n\t\t\tcheck: \"files-modified-recall\",\n\t\t\tdetail: `Missing modified/created files in ## Files: ${missingModifiedFiles.join(\", \")}`,\n\t\t});\n\t}\n\n\tconst workingSetPaths = facts.workingSet.map((file) => file.path);\n\tconst missingWorkingSetPaths = workingSetPaths.filter((path) => !workingSetSection.includes(path));\n\tif (missingWorkingSetPaths.length > 0) {\n\t\tfailures.push({\n\t\t\tcheck: \"working-set-recall\",\n\t\t\tdetail: `Missing working-set files in ## Working Set: ${missingWorkingSetPaths.join(\", \")}`,\n\t\t});\n\t}\n\n\tconst readPaths = facts.files.filter((file) => file.kind === \"read\").map((file) => file.path);\n\tif (readPaths.length > 0) {\n\t\tconst score = containment(tokenSet(readPaths.join(\"\\n\")), tokenSet(filesSection));\n\t\tif (score < FILES_READ_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"files-read-recall\",\n\t\t\t\tdetail: `Read file recall ${formatScore(score)} below ${FILES_READ_RECALL_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.activeTaskSource) {\n\t\tconst score = containment(\n\t\t\ttokenSet(facts.activeTaskSource.slice(0, ACTIVE_TASK_SOURCE_MAX_CHARS)),\n\t\t\ttokenSet(activeTaskSection),\n\t\t);\n\t\tif (score < ACTIVE_TASK_CONTAINMENT_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"active-task-containment\",\n\t\t\t\tdetail: `Active task containment ${formatScore(score)} below ${ACTIVE_TASK_CONTAINMENT_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const prohibition of facts.prohibitions) {\n\t\tconst score = containment(tokenSet(prohibition), tokenSet(mandatoryRulesSection));\n\t\tif (score < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"mandatory-rules-recall\",\n\t\t\t\tdetail: `Missing mandatory rule: ${prohibition}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.cancelledText) {\n\t\tconst summaryOutsideMandatoryRules = removeSection(summary, SECTION_MANDATORY_RULES);\n\t\t// File paths from the facts are REQUIRED elsewhere (files-modified/read-recall demand them\n\t\t// in ## Files), so counting them as cancelled-work leakage would make the two gates\n\t\t// unsatisfiable together whenever a reversal message references a touched file.\n\t\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\t\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\t\tconst score = containment(cancelledTokens, tokenSet(summaryOutsideMandatoryRules));\n\t\tif (score > CANCELLED_WORK_DROPPED_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"cancelled-work-dropped\",\n\t\t\t\tdetail: `Cancelled work leakage ${formatScore(score)} above ${CANCELLED_WORK_DROPPED_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const error of facts.errorFacts) {\n\t\tconst score = containment(tokenSet(`${error.operation}: ${error.error}`), tokenSet(openProblemsSection));\n\t\tif (score < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"open-errors-recall\",\n\t\t\t\tdetail: `Open error recall ${formatScore(score)} below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.actions.length > 0) {\n\t\t// Asymmetric on purpose: the update path carries prior ## Done items forward (bounded), so a\n\t\t// symmetric overlap metric would punish faithful carry-over — the gate demands only that the\n\t\t// NEW span's actions are recalled in ## Done, however much history rides alongside them.\n\t\tconst score = containment(tokenSet(facts.actions.join(\"\\n\")), tokenSet(doneSection));\n\t\tif (score < ACTIONS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"actions-recall\",\n\t\t\t\tdetail: `New-action recall in ## Done ${formatScore(score)} below ${ACTIONS_RECALL_THRESHOLD}`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { ok: failures.length === 0, failures };\n}\n\nexport function isCompactionSummaryStructurallyUsable(summary: string): boolean {\n\tif (summary.trim().length === 0) return false;\n\tconst sections = extractSections(summary);\n\treturn (\n\t\tsections[SECTION_ACTIVE_TASK] !== undefined ||\n\t\tsections[SECTION_FILES] !== undefined ||\n\t\tsections[SECTION_DONE] !== undefined ||\n\t\tsections[SECTION_WORKING_SET] !== undefined ||\n\t\tsections[SECTION_OPEN_PROBLEMS] !== undefined\n\t);\n}\n\nexport function deterministicallyFillSummaryGaps(summary: string, facts: CompactionFacts): DeterministicGapFillResult {\n\tif (!isCompactionSummaryStructurallyUsable(summary)) {\n\t\treturn { summary, verification: verifySummary(summary, facts), changed: false };\n\t}\n\n\tconst sections = parseSummarySections(summary);\n\tconst sectionByName = new Map<string, ParsedSummarySection>();\n\tconst extraSections: ParsedSummarySection[] = [];\n\tfor (const section of sections) {\n\t\tif (REQUIRED_SUMMARY_SECTIONS.some((required) => required.normalized === section.normalized)) {\n\t\t\tconst existing = sectionByName.get(section.normalized);\n\t\t\tif (existing) {\n\t\t\t\texisting.lines.push(...section.lines);\n\t\t\t} else {\n\t\t\t\tsectionByName.set(section.normalized, section);\n\t\t\t}\n\t\t} else {\n\t\t\textraSections.push(section);\n\t\t}\n\t}\n\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tif (!sectionByName.has(required.normalized)) {\n\t\t\tsectionByName.set(required.normalized, {\n\t\t\t\theading: required.heading,\n\t\t\t\tnormalized: required.normalized,\n\t\t\t\tlevel: required.level,\n\t\t\t\tlines: [\"(none)\"],\n\t\t\t});\n\t\t}\n\t}\n\n\tremoveCancelledWorkLines(sectionByName, facts);\n\n\tif (facts.activeTaskSource) {\n\t\tconst activeTask = sectionByName.get(SECTION_ACTIVE_TASK)!;\n\t\tif (\n\t\t\tcontainment(tokenSet(facts.activeTaskSource), tokenSetFromLines(activeTask.lines)) <\n\t\t\tACTIVE_TASK_CONTAINMENT_THRESHOLD\n\t\t) {\n\t\t\tappendContentLine(activeTask.lines, `User: ${facts.activeTaskSource}`);\n\t\t}\n\t}\n\n\tconst mandatoryRules = sectionByName.get(SECTION_MANDATORY_RULES)!;\n\tfor (const rule of facts.prohibitions) {\n\t\tif (containment(tokenSet(rule), tokenSetFromLines(mandatoryRules.lines)) < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(mandatoryRules.lines, `- ${rule}`);\n\t\t}\n\t}\n\n\tconst workingSet = sectionByName.get(SECTION_WORKING_SET)!;\n\tfor (const file of facts.workingSet) {\n\t\tif (!sectionLinesContain(workingSet.lines, file.path)) {\n\t\t\tappendContentLine(workingSet.lines, `- ${file.path} — ${file.note || file.kind}`);\n\t\t}\n\t}\n\n\tconst files = sectionByName.get(SECTION_FILES)!;\n\tfor (const file of facts.files) {\n\t\tif (!sectionLinesContain(files.lines, file.path)) {\n\t\t\tappendContentLine(files.lines, `- ${file.path}`);\n\t\t}\n\t}\n\n\tconst openProblems = sectionByName.get(SECTION_OPEN_PROBLEMS)!;\n\tfor (const error of facts.errorFacts) {\n\t\tconst required = `${error.operation}: ${error.error}`;\n\t\tif (containment(tokenSet(required), tokenSetFromLines(openProblems.lines)) < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(openProblems.lines, `- ${required}`);\n\t\t}\n\t}\n\n\tconst done = sectionByName.get(SECTION_DONE)!;\n\tif (\n\t\tfacts.actions.length > 0 &&\n\t\tcontainment(tokenSet(facts.actions.join(\"\\n\")), tokenSetFromLines(done.lines)) < ACTIONS_RECALL_THRESHOLD\n\t) {\n\t\tlet nextNumber = findNextDoneNumber(done.lines);\n\t\tfor (const action of facts.actions) {\n\t\t\tif (sectionLinesContain(done.lines, action)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tappendContentLine(done.lines, `${nextNumber}. ${action}`);\n\t\t\tnextNumber++;\n\t\t}\n\t}\n\n\tconst filledSummary = renderSummarySections(sectionByName, extraSections);\n\treturn {\n\t\tsummary: filledSummary,\n\t\tverification: verifySummary(filledSummary, facts),\n\t\tchanged: filledSummary !== summary,\n\t};\n}\n\nexport function buildRetryPrompt(report: VerificationReport, previousAttempt?: string): string {\n\tconst failures = report.failures.map((failure) => `${failure.check}: ${failure.detail}`).join(\"; \");\n\tconst previous = previousAttempt ? `\\n\\n<previous-attempt>\\n${previousAttempt}\\n</previous-attempt>` : \"\";\n\treturn `Your previous checkpoint failed verification: ${failures}. Fix ONLY these omissions.${previous}`;\n}\n\nfunction parseSummarySections(summary: string): ParsedSummarySection[] {\n\tconst sections: ParsedSummarySection[] = [];\n\tlet current: ParsedSummarySection | undefined;\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tcurrent = {\n\t\t\t\theading: match[2],\n\t\t\t\tnormalized: normalizeHeading(match[2]),\n\t\t\t\tlevel: match[1] as \"##\" | \"###\",\n\t\t\t\tlines: [],\n\t\t\t};\n\t\t\tsections.push(current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tcurrent.lines.push(line);\n\t\t}\n\t}\n\n\treturn sections;\n}\n\nfunction renderSummarySections(\n\tsectionByName: Map<string, ParsedSummarySection>,\n\textraSections: ParsedSummarySection[],\n): string {\n\tconst rendered: string[] = [];\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tconst section = sectionByName.get(required.normalized)!;\n\t\trendered.push(`${required.level} ${required.heading}`);\n\t\tconst body = normalizeSectionLines(section.lines);\n\t\trendered.push(...body);\n\t\trendered.push(\"\");\n\t}\n\tfor (const section of extraSections) {\n\t\trendered.push(`${section.level} ${section.heading}`);\n\t\trendered.push(...normalizeSectionLines(section.lines));\n\t\trendered.push(\"\");\n\t}\n\treturn rendered.join(\"\\n\").trimEnd();\n}\n\nfunction normalizeSectionLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim() === \"\") start++;\n\twhile (end > start && lines[end - 1].trim() === \"\") end--;\n\tif (start === end) return [\"(none)\"];\n\treturn lines.slice(start, end).map((line) => line.trimEnd());\n}\n\nfunction sectionLinesContain(lines: readonly string[], value: string): boolean {\n\treturn lines.some((line) => line.includes(value));\n}\n\nfunction tokenSetFromLines(lines: readonly string[]): Set<string> {\n\tconst tokens = new Set<string>();\n\tfor (const line of lines) {\n\t\tfor (const token of tokenSet(line)) tokens.add(token);\n\t}\n\treturn tokens;\n}\n\nfunction appendContentLine(lines: string[], line: string): void {\n\tconst normalized = normalizeSectionLines(lines).filter((existing) => existing.trim() !== \"(none)\");\n\tnormalized.push(line);\n\tlines.length = 0;\n\tlines.push(...normalized);\n}\n\nfunction findNextDoneNumber(lines: string[]): number {\n\tlet max = 0;\n\tfor (const line of lines) {\n\t\tconst match = /^\\s*(\\d+)\\./.exec(line);\n\t\tif (!match) continue;\n\t\tmax = Math.max(max, Number(match[1]));\n\t}\n\treturn max + 1;\n}\n\nfunction removeCancelledWorkLines(sectionByName: Map<string, ParsedSummarySection>, facts: CompactionFacts): void {\n\tif (!facts.cancelledText) return;\n\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\tif (cancelledTokens.size === 0) return;\n\n\tfor (const section of sectionByName.values()) {\n\t\tif (section.normalized === SECTION_MANDATORY_RULES) continue;\n\t\tsection.lines = section.lines.filter((line) => !lineShouldBeDroppedAsCancelledWork(line, cancelledTokens));\n\t}\n}\n\nfunction lineShouldBeDroppedAsCancelledWork(line: string, cancelledTokens: Set<string>): boolean {\n\tconst lineTokens = tokenSet(line);\n\tif (lineTokens.size === 0) return false;\n\tlet overlap = 0;\n\tfor (const token of lineTokens) {\n\t\tif (cancelledTokens.has(token)) overlap++;\n\t}\n\treturn overlap >= 2 && overlap / lineTokens.size >= 0.6;\n}\n\nexport function tokenSet(text: string): Set<string> {\n\treturn new Set(\n\t\ttext\n\t\t\t.toLowerCase()\n\t\t\t.split(/[^a-z0-9_./-]+/)\n\t\t\t.map((token) => token.trim())\n\t\t\t.filter((token) => token.length >= 3),\n\t);\n}\n\nexport function containment(needle: Set<string>, hay: Set<string>): number {\n\tif (needle.size === 0) {\n\t\treturn 1;\n\t}\n\tlet hits = 0;\n\tfor (const token of needle) {\n\t\tif (hay.has(token)) {\n\t\t\thits += 1;\n\t\t}\n\t}\n\treturn hits / needle.size;\n}\n\nexport function jaccard(a: Set<string>, b: Set<string>): number {\n\tif (a.size === 0 && b.size === 0) {\n\t\treturn 1;\n\t}\n\tlet intersection = 0;\n\tfor (const token of a) {\n\t\tif (b.has(token)) {\n\t\t\tintersection += 1;\n\t\t}\n\t}\n\tconst union = new Set([...a, ...b]).size;\n\treturn union === 0 ? 1 : intersection / union;\n}\n\nfunction factsAreEmpty(facts: CompactionFacts): boolean {\n\treturn (\n\t\tfacts.files.length === 0 &&\n\t\tfacts.workingSet.length === 0 &&\n\t\tfacts.actions.length === 0 &&\n\t\tfacts.errorFacts.length === 0 &&\n\t\tfacts.prohibitions.length === 0 &&\n\t\tfacts.cancelledText === \"\" &&\n\t\tfacts.activeTaskSource === \"\"\n\t);\n}\n\nfunction extractSections(summary: string): Record<string, string> {\n\tconst sections: Record<string, string> = {};\n\tlet current: string | undefined;\n\tlet bucket: string[] = [];\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tsections[current] = bucket.join(\"\\n\").trim();\n\t\t}\n\t\tbucket = [];\n\t};\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tflush();\n\t\t\tcurrent = normalizeHeading(match[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tbucket.push(line);\n\t\t}\n\t}\n\tflush();\n\treturn sections;\n}\n\nfunction removeSection(summary: string, heading: string): string {\n\tconst normalizedHeading = normalizeHeading(heading);\n\tconst kept: string[] = [];\n\tlet skipping = false;\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tskipping = normalizeHeading(match[1]) === normalizedHeading;\n\t\t\tif (skipping) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!skipping) {\n\t\t\tkept.push(line);\n\t\t}\n\t}\n\treturn kept.join(\"\\n\");\n}\n\nfunction normalizeHeading(heading: string): string {\n\treturn heading.trim().toLowerCase();\n}\n\nfunction formatScore(score: number): string {\n\treturn score.toFixed(2);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/compaction/verification.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTIVE_TASK_SOURCE_MAX_CHARS, type CompactionFacts } from \"./extraction.ts\";\n\nexport interface VerificationFailure {\n\tcheck: string;\n\tdetail: string;\n\tscore?: number;\n\tthreshold?: number;\n\tcomparator?: \"minimum\" | \"maximum\";\n\tmatched?: number;\n\tdemanded?: number;\n}\n\nexport interface VerificationReport {\n\tok: boolean;\n\tfailures: VerificationFailure[];\n}\n\n/** A failed verification attempt with its structured reports preserved for the retry ladder. */\nexport class CompactionVerificationError extends Error {\n\treadonly reports: VerificationReport[];\n\n\tconstructor(reports: readonly VerificationReport[]) {\n\t\tsuper(`gate-failed: ${formatVerificationReports(reports)}`);\n\t\tthis.name = \"CompactionVerificationError\";\n\t\tthis.reports = reports.map((report) => ({\n\t\t\tok: report.ok,\n\t\t\tfailures: report.failures.map((failure) => ({ ...failure })),\n\t\t}));\n\t}\n}\n\nexport interface DeterministicGapFillResult {\n\tsummary: string;\n\tverification: VerificationReport;\n\tchanged: boolean;\n}\n\nexport const FILES_READ_RECALL_THRESHOLD = 0.8;\nexport const ACTIVE_TASK_CONTAINMENT_THRESHOLD = 0.9;\nexport const MANDATORY_RULES_RECALL_THRESHOLD = 0.7;\nexport const CANCELLED_WORK_DROPPED_THRESHOLD = 0.1;\nexport const ACTIONS_RECALL_THRESHOLD = 0.6;\nexport const OPEN_ERRORS_RECALL_THRESHOLD = 0.7;\n\nconst SECTION_FILES = \"files\";\nconst SECTION_WORKING_SET = \"working set\";\nconst SECTION_OPEN_PROBLEMS = \"open problems\";\nconst SECTION_DONE = \"done\";\nconst SECTION_ACTIVE_TASK = \"active task\";\nconst SECTION_MANDATORY_RULES = \"mandatory rules\";\nconst SECTION_KEY_DECISIONS = \"key decisions\";\nconst SECTION_CONSTRAINTS = \"constraints & preferences\";\nconst SECTION_CRITICAL_CONTEXT = \"critical context\";\n\ninterface ParsedSummarySection {\n\theading: string;\n\tnormalized: string;\n\tlevel: \"##\" | \"###\";\n\tlines: string[];\n}\n\nconst REQUIRED_SUMMARY_SECTIONS: Array<{ heading: string; normalized: string; level: \"##\" | \"###\" }> = [\n\t{ heading: \"Active Task\", normalized: SECTION_ACTIVE_TASK, level: \"##\" },\n\t{ heading: \"Mandatory Rules\", normalized: SECTION_MANDATORY_RULES, level: \"###\" },\n\t{ heading: \"Working Set\", normalized: SECTION_WORKING_SET, level: \"##\" },\n\t{ heading: \"Files\", normalized: SECTION_FILES, level: \"##\" },\n\t{ heading: \"Open Problems\", normalized: SECTION_OPEN_PROBLEMS, level: \"##\" },\n\t{ heading: \"Done\", normalized: SECTION_DONE, level: \"##\" },\n\t{ heading: \"Key Decisions\", normalized: SECTION_KEY_DECISIONS, level: \"##\" },\n\t{ heading: \"Constraints & Preferences\", normalized: SECTION_CONSTRAINTS, level: \"##\" },\n\t{ heading: \"Critical Context\", normalized: SECTION_CRITICAL_CONTEXT, level: \"##\" },\n];\n\nexport function verifySummary(summary: string, facts: CompactionFacts): VerificationReport {\n\tif (factsAreEmpty(facts)) {\n\t\treturn { ok: true, failures: [] };\n\t}\n\n\tconst sections = extractSections(summary);\n\tconst failures: VerificationFailure[] = [];\n\tconst filesSection = sections[SECTION_FILES] ?? \"\";\n\tconst workingSetSection = sections[SECTION_WORKING_SET] ?? \"\";\n\tconst openProblemsSection = sections[SECTION_OPEN_PROBLEMS] ?? \"\";\n\tconst doneSection = sections[SECTION_DONE] ?? \"\";\n\tconst activeTaskSection = sections[SECTION_ACTIVE_TASK] ?? \"\";\n\tconst mandatoryRulesSection = sections[SECTION_MANDATORY_RULES] ?? \"\";\n\n\tconst modifiedFiles = facts.files.filter((file) => file.kind !== \"read\");\n\tconst missingModifiedFiles = modifiedFiles\n\t\t.map((file) => file.path)\n\t\t.filter((path) => !sectionContainsExactPath(filesSection, path));\n\tif (missingModifiedFiles.length > 0) {\n\t\tconst matched = modifiedFiles.length - missingModifiedFiles.length;\n\t\tfailures.push({\n\t\t\tcheck: \"files-modified-recall\",\n\t\t\tdetail: `Modified/created file recall ${formatScore(matched / modifiedFiles.length)} (${matched}/${modifiedFiles.length} exact paths); missing: ${formatMissingValues(missingModifiedFiles)}`,\n\t\t\tscore: matched / modifiedFiles.length,\n\t\t\tthreshold: 1,\n\t\t\tcomparator: \"minimum\",\n\t\t\tmatched,\n\t\t\tdemanded: modifiedFiles.length,\n\t\t});\n\t}\n\n\tconst workingSetPaths = facts.workingSet.map((file) => file.path);\n\tconst missingWorkingSetPaths = workingSetPaths.filter((path) => !sectionContainsExactPath(workingSetSection, path));\n\tif (missingWorkingSetPaths.length > 0) {\n\t\tconst matched = workingSetPaths.length - missingWorkingSetPaths.length;\n\t\tfailures.push({\n\t\t\tcheck: \"working-set-recall\",\n\t\t\tdetail: `Working-set recall ${formatScore(matched / workingSetPaths.length)} (${matched}/${workingSetPaths.length} exact paths); missing: ${formatMissingValues(missingWorkingSetPaths)}`,\n\t\t\tscore: matched / workingSetPaths.length,\n\t\t\tthreshold: 1,\n\t\t\tcomparator: \"minimum\",\n\t\t\tmatched,\n\t\t\tdemanded: workingSetPaths.length,\n\t\t});\n\t}\n\n\tconst readPaths = facts.files.filter((file) => file.kind === \"read\").map((file) => file.path);\n\tif (readPaths.length > 0) {\n\t\t// Paths are atomic identities. A global token bag over-credits shared directory prefixes and\n\t\t// makes the score impossible to interpret as \"how many files survived\".\n\t\tconst missingReadPaths = readPaths.filter((path) => !sectionContainsExactPath(filesSection, path));\n\t\tconst matched = readPaths.length - missingReadPaths.length;\n\t\tconst score = matched / readPaths.length;\n\t\tif (score < FILES_READ_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"files-read-recall\",\n\t\t\t\tdetail: `Read file recall ${formatScore(score)} (${matched}/${readPaths.length} exact paths) below ${FILES_READ_RECALL_THRESHOLD}; missing: ${formatMissingValues(missingReadPaths)}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: FILES_READ_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t\tmatched,\n\t\t\t\tdemanded: readPaths.length,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.activeTaskSource) {\n\t\tconst score = containment(\n\t\t\ttokenSet(facts.activeTaskSource.slice(0, ACTIVE_TASK_SOURCE_MAX_CHARS)),\n\t\t\ttokenSet(activeTaskSection),\n\t\t);\n\t\tif (score < ACTIVE_TASK_CONTAINMENT_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"active-task-containment\",\n\t\t\t\tdetail: `Active task containment ${formatScore(score)} below ${ACTIVE_TASK_CONTAINMENT_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: ACTIVE_TASK_CONTAINMENT_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const prohibition of facts.prohibitions) {\n\t\tconst score = containment(tokenSet(prohibition), tokenSet(mandatoryRulesSection));\n\t\tif (score < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"mandatory-rules-recall\",\n\t\t\t\tdetail: `Mandatory rule recall ${formatScore(score)} below ${MANDATORY_RULES_RECALL_THRESHOLD}: ${prohibition}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: MANDATORY_RULES_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.cancelledText) {\n\t\tconst summaryOutsideMandatoryRules = removeSection(summary, SECTION_MANDATORY_RULES);\n\t\t// File paths from the facts are REQUIRED elsewhere (files-modified/read-recall demand them\n\t\t// in ## Files), so counting them as cancelled-work leakage would make the two gates\n\t\t// unsatisfiable together whenever a reversal message references a touched file.\n\t\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\t\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\t\tconst score = containment(cancelledTokens, tokenSet(summaryOutsideMandatoryRules));\n\t\tif (score > CANCELLED_WORK_DROPPED_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"cancelled-work-dropped\",\n\t\t\t\tdetail: `Cancelled work leakage ${formatScore(score)} above ${CANCELLED_WORK_DROPPED_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: CANCELLED_WORK_DROPPED_THRESHOLD,\n\t\t\t\tcomparator: \"maximum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const error of facts.errorFacts) {\n\t\t// Command strings can be much longer than their failure signal. Weight the operation and the\n\t\t// error identity equally so command flags cannot drown out a faithfully preserved failure (or\n\t\t// let a generic error phrase hide a missing operation).\n\t\tconst openProblemTokens = tokenSet(openProblemsSection);\n\t\tconst operationScore = containment(tokenSet(error.operation), openProblemTokens);\n\t\tconst errorScore = containment(tokenSet(error.error), openProblemTokens);\n\t\tconst score = (operationScore + errorScore) / 2;\n\t\tif (score < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"open-errors-recall\",\n\t\t\t\tdetail: `Open error recall ${formatScore(score)} (operation ${formatScore(operationScore)}, error ${formatScore(errorScore)}) below ${OPEN_ERRORS_RECALL_THRESHOLD}: ${error.operation}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: OPEN_ERRORS_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (facts.actions.length > 0) {\n\t\t// Asymmetric on purpose: the update path carries prior ## Done items forward (bounded), so a\n\t\t// symmetric overlap metric would punish faithful carry-over — the gate demands only that the\n\t\t// NEW span's actions are recalled in ## Done, however much history rides alongside them.\n\t\tconst score = containment(tokenSet(facts.actions.join(\"\\n\")), tokenSet(doneSection));\n\t\tif (score < ACTIONS_RECALL_THRESHOLD) {\n\t\t\tfailures.push({\n\t\t\t\tcheck: \"actions-recall\",\n\t\t\t\tdetail: `New-action recall in ## Done ${formatScore(score)} below ${ACTIONS_RECALL_THRESHOLD}`,\n\t\t\t\tscore,\n\t\t\t\tthreshold: ACTIONS_RECALL_THRESHOLD,\n\t\t\t\tcomparator: \"minimum\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { ok: failures.length === 0, failures };\n}\n\nexport function isCompactionSummaryStructurallyUsable(summary: string): boolean {\n\tif (summary.trim().length === 0) return false;\n\tconst sections = extractSections(summary);\n\treturn (\n\t\tsections[SECTION_ACTIVE_TASK] !== undefined ||\n\t\tsections[SECTION_FILES] !== undefined ||\n\t\tsections[SECTION_DONE] !== undefined ||\n\t\tsections[SECTION_WORKING_SET] !== undefined ||\n\t\tsections[SECTION_OPEN_PROBLEMS] !== undefined\n\t);\n}\n\nexport function deterministicallyFillSummaryGaps(summary: string, facts: CompactionFacts): DeterministicGapFillResult {\n\tif (!isCompactionSummaryStructurallyUsable(summary)) {\n\t\treturn { summary, verification: verifySummary(summary, facts), changed: false };\n\t}\n\n\tconst sections = parseSummarySections(summary);\n\tconst sectionByName = new Map<string, ParsedSummarySection>();\n\tconst extraSections: ParsedSummarySection[] = [];\n\tfor (const section of sections) {\n\t\tif (REQUIRED_SUMMARY_SECTIONS.some((required) => required.normalized === section.normalized)) {\n\t\t\tconst existing = sectionByName.get(section.normalized);\n\t\t\tif (existing) {\n\t\t\t\texisting.lines.push(...section.lines);\n\t\t\t} else {\n\t\t\t\tsectionByName.set(section.normalized, section);\n\t\t\t}\n\t\t} else {\n\t\t\textraSections.push(section);\n\t\t}\n\t}\n\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tif (!sectionByName.has(required.normalized)) {\n\t\t\tsectionByName.set(required.normalized, {\n\t\t\t\theading: required.heading,\n\t\t\t\tnormalized: required.normalized,\n\t\t\t\tlevel: required.level,\n\t\t\t\tlines: [\"(none)\"],\n\t\t\t});\n\t\t}\n\t}\n\n\tremoveCancelledWorkLines(sectionByName, facts);\n\n\tif (facts.activeTaskSource) {\n\t\tconst activeTask = sectionByName.get(SECTION_ACTIVE_TASK)!;\n\t\tif (\n\t\t\tcontainment(tokenSet(facts.activeTaskSource), tokenSetFromLines(activeTask.lines)) <\n\t\t\tACTIVE_TASK_CONTAINMENT_THRESHOLD\n\t\t) {\n\t\t\tappendContentLine(activeTask.lines, `User: ${facts.activeTaskSource}`);\n\t\t}\n\t}\n\n\tconst mandatoryRules = sectionByName.get(SECTION_MANDATORY_RULES)!;\n\tfor (const rule of facts.prohibitions) {\n\t\tif (containment(tokenSet(rule), tokenSetFromLines(mandatoryRules.lines)) < MANDATORY_RULES_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(mandatoryRules.lines, `- ${rule}`);\n\t\t}\n\t}\n\n\tconst workingSet = sectionByName.get(SECTION_WORKING_SET)!;\n\tfor (const file of facts.workingSet) {\n\t\tif (!sectionContainsExactPath(workingSet.lines.join(\"\\n\"), file.path)) {\n\t\t\tappendContentLine(workingSet.lines, `- ${file.path} — ${file.note || file.kind}`);\n\t\t}\n\t}\n\n\tconst files = sectionByName.get(SECTION_FILES)!;\n\tfor (const file of facts.files) {\n\t\tif (!sectionContainsExactPath(files.lines.join(\"\\n\"), file.path)) {\n\t\t\tappendContentLine(files.lines, `- ${file.path}`);\n\t\t}\n\t}\n\n\tconst openProblems = sectionByName.get(SECTION_OPEN_PROBLEMS)!;\n\tfor (const error of facts.errorFacts) {\n\t\tconst required = `${error.operation}: ${error.error}`;\n\t\tif (containment(tokenSet(required), tokenSetFromLines(openProblems.lines)) < OPEN_ERRORS_RECALL_THRESHOLD) {\n\t\t\tappendContentLine(openProblems.lines, `- ${required}`);\n\t\t}\n\t}\n\n\tconst done = sectionByName.get(SECTION_DONE)!;\n\tif (\n\t\tfacts.actions.length > 0 &&\n\t\tcontainment(tokenSet(facts.actions.join(\"\\n\")), tokenSetFromLines(done.lines)) < ACTIONS_RECALL_THRESHOLD\n\t) {\n\t\tlet nextNumber = findNextDoneNumber(done.lines);\n\t\tfor (const action of facts.actions) {\n\t\t\tif (sectionLinesContain(done.lines, action)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tappendContentLine(done.lines, `${nextNumber}. ${action}`);\n\t\t\tnextNumber++;\n\t\t}\n\t}\n\n\tconst filledSummary = renderSummarySections(sectionByName, extraSections);\n\treturn {\n\t\tsummary: filledSummary,\n\t\tverification: verifySummary(filledSummary, facts),\n\t\tchanged: filledSummary !== summary,\n\t};\n}\n\nexport function buildRetryPrompt(report: VerificationReport, previousAttempt?: string): string {\n\tconst failures = report.failures.map((failure) => `${failure.check}: ${failure.detail}`).join(\"; \");\n\tconst previous = previousAttempt ? `\\n\\n<previous-attempt>\\n${previousAttempt}\\n</previous-attempt>` : \"\";\n\treturn `Your previous checkpoint failed verification: ${failures}. Fix ONLY these omissions.${previous}`;\n}\n\nexport function formatVerificationReports(reports: readonly VerificationReport[]): string {\n\treturn reports\n\t\t.flatMap((report) => report.failures)\n\t\t.map((failure) => `${failure.check}: ${failure.detail}`)\n\t\t.join(\", \");\n}\n\nfunction parseSummarySections(summary: string): ParsedSummarySection[] {\n\tconst sections: ParsedSummarySection[] = [];\n\tlet current: ParsedSummarySection | undefined;\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tcurrent = {\n\t\t\t\theading: match[2],\n\t\t\t\tnormalized: normalizeHeading(match[2]),\n\t\t\t\tlevel: match[1] as \"##\" | \"###\",\n\t\t\t\tlines: [],\n\t\t\t};\n\t\t\tsections.push(current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tcurrent.lines.push(line);\n\t\t}\n\t}\n\n\treturn sections;\n}\n\nfunction renderSummarySections(\n\tsectionByName: Map<string, ParsedSummarySection>,\n\textraSections: ParsedSummarySection[],\n): string {\n\tconst rendered: string[] = [];\n\tfor (const required of REQUIRED_SUMMARY_SECTIONS) {\n\t\tconst section = sectionByName.get(required.normalized)!;\n\t\trendered.push(`${required.level} ${required.heading}`);\n\t\tconst body = normalizeSectionLines(section.lines);\n\t\trendered.push(...body);\n\t\trendered.push(\"\");\n\t}\n\tfor (const section of extraSections) {\n\t\trendered.push(`${section.level} ${section.heading}`);\n\t\trendered.push(...normalizeSectionLines(section.lines));\n\t\trendered.push(\"\");\n\t}\n\treturn rendered.join(\"\\n\").trimEnd();\n}\n\nfunction normalizeSectionLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim() === \"\") start++;\n\twhile (end > start && lines[end - 1].trim() === \"\") end--;\n\tif (start === end) return [\"(none)\"];\n\treturn lines.slice(start, end).map((line) => line.trimEnd());\n}\n\nfunction sectionLinesContain(lines: readonly string[], value: string): boolean {\n\treturn lines.some((line) => line.includes(value));\n}\n\nfunction sectionContainsExactPath(section: string, path: string): boolean {\n\tlet fromIndex = 0;\n\twhile (fromIndex <= section.length - path.length) {\n\t\tconst index = section.indexOf(path, fromIndex);\n\t\tif (index < 0) return false;\n\t\tconst before = index > 0 ? section[index - 1] : undefined;\n\t\tconst afterIndex = index + path.length;\n\t\tconst after = afterIndex < section.length ? section[afterIndex] : undefined;\n\t\tconst boundary = (character: string | undefined): boolean =>\n\t\t\tcharacter === undefined || /[\\s`'\"()[\\]{}<>,:;|—]/.test(character);\n\t\tif (boundary(before) && boundary(after)) return true;\n\t\tfromIndex = index + 1;\n\t}\n\treturn false;\n}\n\nfunction tokenSetFromLines(lines: readonly string[]): Set<string> {\n\tconst tokens = new Set<string>();\n\tfor (const line of lines) {\n\t\tfor (const token of tokenSet(line)) tokens.add(token);\n\t}\n\treturn tokens;\n}\n\nfunction appendContentLine(lines: string[], line: string): void {\n\tconst normalized = normalizeSectionLines(lines).filter((existing) => existing.trim() !== \"(none)\");\n\tnormalized.push(line);\n\tlines.length = 0;\n\tlines.push(...normalized);\n}\n\nfunction findNextDoneNumber(lines: string[]): number {\n\tlet max = 0;\n\tfor (const line of lines) {\n\t\tconst match = /^\\s*(\\d+)\\./.exec(line);\n\t\tif (!match) continue;\n\t\tmax = Math.max(max, Number(match[1]));\n\t}\n\treturn max + 1;\n}\n\nfunction removeCancelledWorkLines(sectionByName: Map<string, ParsedSummarySection>, facts: CompactionFacts): void {\n\tif (!facts.cancelledText) return;\n\tconst factPathTokens = tokenSet(facts.files.map((file) => file.path).join(\"\\n\"));\n\tconst cancelledTokens = new Set([...tokenSet(facts.cancelledText)].filter((token) => !factPathTokens.has(token)));\n\tif (cancelledTokens.size === 0) return;\n\n\tfor (const section of sectionByName.values()) {\n\t\tif (section.normalized === SECTION_MANDATORY_RULES) continue;\n\t\tsection.lines = section.lines.filter((line) => !lineShouldBeDroppedAsCancelledWork(line, cancelledTokens));\n\t}\n}\n\nfunction lineShouldBeDroppedAsCancelledWork(line: string, cancelledTokens: Set<string>): boolean {\n\tconst lineTokens = tokenSet(line);\n\tif (lineTokens.size === 0) return false;\n\tlet overlap = 0;\n\tfor (const token of lineTokens) {\n\t\tif (cancelledTokens.has(token)) overlap++;\n\t}\n\treturn overlap >= 2 && overlap / lineTokens.size >= 0.6;\n}\n\nexport function tokenSet(text: string): Set<string> {\n\treturn new Set(\n\t\ttext\n\t\t\t.toLowerCase()\n\t\t\t.split(/[^a-z0-9_./-]+/)\n\t\t\t.map((token) => token.trim())\n\t\t\t.filter((token) => token.length >= 3),\n\t);\n}\n\nexport function containment(needle: Set<string>, hay: Set<string>): number {\n\tif (needle.size === 0) {\n\t\treturn 1;\n\t}\n\tlet hits = 0;\n\tfor (const token of needle) {\n\t\tif (hay.has(token)) {\n\t\t\thits += 1;\n\t\t}\n\t}\n\treturn hits / needle.size;\n}\n\nexport function jaccard(a: Set<string>, b: Set<string>): number {\n\tif (a.size === 0 && b.size === 0) {\n\t\treturn 1;\n\t}\n\tlet intersection = 0;\n\tfor (const token of a) {\n\t\tif (b.has(token)) {\n\t\t\tintersection += 1;\n\t\t}\n\t}\n\tconst union = new Set([...a, ...b]).size;\n\treturn union === 0 ? 1 : intersection / union;\n}\n\nfunction factsAreEmpty(facts: CompactionFacts): boolean {\n\treturn (\n\t\tfacts.files.length === 0 &&\n\t\tfacts.workingSet.length === 0 &&\n\t\tfacts.actions.length === 0 &&\n\t\tfacts.errorFacts.length === 0 &&\n\t\tfacts.prohibitions.length === 0 &&\n\t\tfacts.cancelledText === \"\" &&\n\t\tfacts.activeTaskSource === \"\"\n\t);\n}\n\nfunction extractSections(summary: string): Record<string, string> {\n\tconst sections: Record<string, string> = {};\n\tlet current: string | undefined;\n\tlet bucket: string[] = [];\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tsections[current] = bucket.join(\"\\n\").trim();\n\t\t}\n\t\tbucket = [];\n\t};\n\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tflush();\n\t\t\tcurrent = normalizeHeading(match[1]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (current) {\n\t\t\tbucket.push(line);\n\t\t}\n\t}\n\tflush();\n\treturn sections;\n}\n\nfunction removeSection(summary: string, heading: string): string {\n\tconst normalizedHeading = normalizeHeading(heading);\n\tconst kept: string[] = [];\n\tlet skipping = false;\n\tfor (const line of summary.split(/\\r?\\n/)) {\n\t\tconst match = /^(?:##|###)\\s+(.+?)\\s*$/.exec(line);\n\t\tif (match) {\n\t\t\tskipping = normalizeHeading(match[1]) === normalizedHeading;\n\t\t\tif (skipping) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!skipping) {\n\t\t\tkept.push(line);\n\t\t}\n\t}\n\treturn kept.join(\"\\n\");\n}\n\nfunction normalizeHeading(heading: string): string {\n\treturn heading.trim().toLowerCase();\n}\n\nfunction formatScore(score: number): string {\n\treturn score.toFixed(2);\n}\n\nfunction formatMissingValues(values: readonly string[]): string {\n\tconst visible = values.slice(0, 5).join(\", \");\n\treturn values.length > 5 ? `${visible} (+${values.length - 5} more)` : visible;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export * from "./messages.ts";
|
|
|
4
4
|
export * from "./proxy.ts";
|
|
5
5
|
export * from "./reliability/index.ts";
|
|
6
6
|
export * from "./session/message-retention.ts";
|
|
7
|
+
export * from "./tool-failure-memory.ts";
|
|
7
8
|
export * from "./types.ts";
|
|
9
|
+
export * from "./usage.ts";
|
|
8
10
|
export * from "./utils/shell-output.ts";
|
|
9
11
|
export { uuidv7 } from "./uuid.ts";
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAEhC,cAAc,eAAe,CAAC;AAE9B,cAAc,YAAY,CAAC;AAE3B,cAAc,wBAAwB,CAAC;AAEvC,cAAc,gCAAgC,CAAC;AAE/C,cAAc,YAAY,CAAC;AAE3B,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\n// Custom message types + LLM transformer\nexport * from \"./messages.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Reliability kernel\nexport * from \"./reliability/index.ts\";\n// Session message retention (pure)\nexport * from \"./session/message-retention.ts\";\n// Types\nexport * from \"./types.ts\";\n// Shell output utilities\nexport * from \"./utils/shell-output.ts\";\nexport { uuidv7 } from \"./uuid.ts\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAEhC,cAAc,eAAe,CAAC;AAE9B,cAAc,YAAY,CAAC;AAE3B,cAAc,wBAAwB,CAAC;AAEvC,cAAc,gCAAgC,CAAC;AAE/C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAE3B,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\n// Custom message types + LLM transformer\nexport * from \"./messages.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Reliability kernel\nexport * from \"./reliability/index.ts\";\n// Session message retention (pure)\nexport * from \"./session/message-retention.ts\";\n// Provider-neutral failed tool-call context boundary\nexport * from \"./tool-failure-memory.ts\";\n// Types\nexport * from \"./types.ts\";\nexport * from \"./usage.ts\";\n// Shell output utilities\nexport * from \"./utils/shell-output.ts\";\nexport { uuidv7 } from \"./uuid.ts\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,11 @@ export * from "./proxy.js";
|
|
|
10
10
|
export * from "./reliability/index.js";
|
|
11
11
|
// Session message retention (pure)
|
|
12
12
|
export * from "./session/message-retention.js";
|
|
13
|
+
// Provider-neutral failed tool-call context boundary
|
|
14
|
+
export * from "./tool-failure-memory.js";
|
|
13
15
|
// Types
|
|
14
16
|
export * from "./types.js";
|
|
17
|
+
export * from "./usage.js";
|
|
15
18
|
// Shell output utilities
|
|
16
19
|
export * from "./utils/shell-output.js";
|
|
17
20
|
export { uuidv7 } from "./uuid.js";
|