@caupulican/pi-agent-core 0.81.39 → 0.81.40
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/dist/compaction/compaction.d.ts +13 -0
- package/dist/compaction/compaction.d.ts.map +1 -1
- package/dist/compaction/compaction.js +114 -78
- 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 +14 -2
- package/dist/compaction/loop.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/session/session-manager.d.ts +11 -3
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +64 -59
- package/dist/session/session-manager.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extraction.js","sourceRoot":"","sources":["../../src/compaction/extraction.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionEntry } from \"../session/session-manager.ts\";\nimport type { AgentMessage } from \"../types.ts\";\n\nexport interface CompactionFileFact {\n\tpath: string;\n\tkind: \"modified\" | \"created\" | \"read\";\n\tnote: string;\n}\n\nexport interface CompactionErrorFact {\n\toperation: string;\n\terror: string;\n}\n\nexport interface CompactionDelegatedWorkerFact {\n\t/** Worker-authored text is evidence for the parent, never a verified decision or completion claim. */\n\ttrust: \"UNTRUSTED\";\n\ttask: string;\n\tsummary: string;\n}\n\nexport interface CompactionFacts {\n\tfiles: CompactionFileFact[];\n\tworkingSet: CompactionFileFact[];\n\tactions: string[];\n\terrorFacts: CompactionErrorFact[];\n\tprohibitions: string[];\n\tcancelledText: string;\n\tactiveTaskSource: string;\n\t/** Latest-first worker evidence retained only by deterministic checkpoints. */\n\tdelegatedWorkerFacts?: CompactionDelegatedWorkerFact[];\n}\n\ninterface ToolCallFact {\n\tid: string | undefined;\n\tname: string;\n\tpath: string | undefined;\n\tbaseKind: \"modified\" | \"created\" | \"read\" | null;\n\tfinalKind: \"modified\" | \"created\" | \"read\" | null;\n\tverb: string;\n\tresolved: boolean;\n\tfailed: boolean;\n}\n\nconst PROHIBITION_PATTERN = /\\b(do not|don't|never|stop (?:doing|using|changing)|no more)\\b/i;\n// Deliberately narrow: a bare \"stop\" (\"stop the server and rerun\") is everyday phrasing, not a\n// reversal of the prior work — matching it marked whole turns cancelled and made the\n// cancelled-work gate fight the recall gates (2026-07-06 incident).\nconst REVERSAL_PATTERN =\n\t/\\b(undo|revert|roll back|never mind|scrap that|forget (?:it|that)|stop (?:that|this|it|everything|working on))\\b/i;\n\n/** User messages longer than this are documents/pastes, not spoken prohibitions. */\nconst PROHIBITION_SOURCE_MAX_CHARS = 1_500;\n/** Upper bound on gate-demanded rules; most recent win (same bounding rationale as Done carry-over). */\nconst MAX_PROHIBITIONS = 8;\n/** Upper bound on gate-demanded actions; mirrors the prompt's \"15 most recent Done items\" rule. */\nconst MAX_ACTIONS = 15;\nconst MAX_WORKING_SET_FILES = 8;\nconst MAX_ERROR_FACTS = 5;\nconst ERROR_LINE_MAX_CHARS = 160;\nconst COMMAND_PREFIX_MAX_CHARS = 80;\nconst MAX_DELEGATED_WORKER_FACTS = 4;\nconst DELEGATED_WORKER_TASK_MAX_CHARS = 240;\nconst DELEGATED_WORKER_SUMMARY_MAX_CHARS = 600;\n/** Shared clamp for the active-task text because verification can only demand what the prompt receives. */\nexport const ACTIVE_TASK_SOURCE_MAX_CHARS = 4_000;\n\nconst FILE_KIND_PRIORITY: Record<NonNullable<ToolCallFact[\"finalKind\"]>, number> = {\n\tread: 1,\n\tcreated: 2,\n\tmodified: 3,\n};\n\nconst TOOL_KIND_BY_NAME: Record<string, \"modified\" | \"created\" | \"read\" | null> = {\n\tread: \"read\",\n\tgrep: \"read\",\n\tfind: \"read\",\n\twrite: \"modified\",\n\tedit: \"modified\",\n\tbash: null,\n};\n\nconst TOOL_VERB_BY_NAME: Record<string, string> = {\n\twrite: \"WRITE\",\n\tedit: \"EDIT\",\n\tbash: \"RUN\",\n\tread: \"READ\",\n\tgrep: \"READ\",\n\tfind: \"READ\",\n};\n\nfunction messageToText(message: AgentMessage): string {\n\tconst rawContent = (message as { content?: unknown }).content;\n\tif (typeof rawContent === \"string\") {\n\t\treturn rawContent;\n\t}\n\tif (!Array.isArray(rawContent)) {\n\t\treturn \"\";\n\t}\n\n\tconst parts: string[] = [];\n\tfor (const block of rawContent) {\n\t\tif (!block || typeof block !== \"object\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((block as { type?: unknown }).type === \"text\" && typeof (block as { text?: unknown }).text === \"string\") {\n\t\t\tparts.push((block as { text: string }).text);\n\t\t}\n\t}\n\treturn (parts.length === 1 ? parts[0] : parts.join(\" \")).trim();\n}\n\nfunction assistantToolCallTarget(name: string, rawArgs: unknown): string | undefined {\n\tif (!rawArgs || typeof rawArgs !== \"object\") {\n\t\treturn undefined;\n\t}\n\tconst args = rawArgs as Record<string, unknown>;\n\n\tif (\n\t\t(name === \"read\" || name === \"grep\" || name === \"find\" || name === \"write\" || name === \"edit\") &&\n\t\ttypeof args.path === \"string\" &&\n\t\targs.path.length > 0\n\t) {\n\t\treturn args.path;\n\t}\n\n\tif (name === \"bash\" && typeof args.command === \"string\" && args.command.length > 0) {\n\t\treturn args.command;\n\t}\n\n\treturn undefined;\n}\n\nfunction clampText(text: string, maxLen: number): string {\n\treturn text.length > maxLen ? text.slice(0, maxLen) : text;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction normalizeDelegatedWorkerText(text: string, maxLen: number): string {\n\tlet normalized = \"\";\n\tfor (const match of text.matchAll(/\\S+/g)) {\n\t\tconst separator = normalized.length > 0 ? \" \" : \"\";\n\t\tconst remaining = maxLen - normalized.length - separator.length;\n\t\tif (remaining <= 0) break;\n\t\tnormalized += `${separator}${match[0].slice(0, remaining)}`;\n\t\tif (match[0].length >= remaining) break;\n\t}\n\treturn normalized;\n}\n\nfunction extractDelegatedWorkerFact(entry: SessionEntry): CompactionDelegatedWorkerFact | undefined {\n\tif (entry.type !== \"custom\" || entry.customType !== \"worker_result\" || !isPlainRecord(entry.data)) {\n\t\treturn undefined;\n\t}\n\tif (entry.data.version !== 1 || !isPlainRecord(entry.data.result)) return undefined;\n\n\tconst result = entry.data.result;\n\tif (typeof result.requestId !== \"string\" || typeof result.summary !== \"string\") return undefined;\n\tif (typeof result.status !== \"string\" || ![\"completed\", \"blocked\", \"failed\", \"cancelled\"].includes(result.status)) {\n\t\treturn undefined;\n\t}\n\tif (!Array.isArray(result.changedFiles) || !result.changedFiles.every((file) => typeof file === \"string\")) {\n\t\treturn undefined;\n\t}\n\n\tconst request = entry.data.request;\n\tconst instructions =\n\t\tisPlainRecord(request) && typeof request.instructions === \"string\" ? request.instructions : undefined;\n\tconst task = normalizeDelegatedWorkerText(\n\t\tinstructions ?? `Worker request ${result.requestId}`,\n\t\tDELEGATED_WORKER_TASK_MAX_CHARS,\n\t);\n\tconst summary = normalizeDelegatedWorkerText(result.summary, DELEGATED_WORKER_SUMMARY_MAX_CHARS);\n\n\treturn {\n\t\ttrust: \"UNTRUSTED\",\n\t\ttask: task || \"(empty task)\",\n\t\tsummary: summary || \"(empty summary)\",\n\t};\n}\n\nfunction extractDelegatedWorkerFacts(\n\tentries: readonly SessionEntry[],\n\tstart: number,\n\tend: number,\n): CompactionDelegatedWorkerFact[] {\n\tconst facts: CompactionDelegatedWorkerFact[] = [];\n\tfor (let i = end - 1; i >= start && facts.length < MAX_DELEGATED_WORKER_FACTS; i--) {\n\t\tconst fact = extractDelegatedWorkerFact(entries[i]);\n\t\tif (fact) facts.push(fact);\n\t}\n\treturn facts;\n}\n\nfunction appearsCreated(message: AgentMessage): boolean {\n\tif (message.role !== \"toolResult\") {\n\t\treturn false;\n\t}\n\n\tconst text = messageToText(message).toLowerCase();\n\tif (/(\\bnew file\\b|\\bcreated\\b|\\bcreated file\\b)/.test(text)) {\n\t\treturn true;\n\t}\n\n\tconst details = (message as { details?: unknown }).details;\n\tif (!details || typeof details !== \"object\") {\n\t\treturn false;\n\t}\n\n\tif (typeof (details as { created?: unknown }).created === \"boolean\") {\n\t\treturn (details as { created: boolean }).created;\n\t}\n\tif (typeof (details as { isCreated?: unknown }).isCreated === \"boolean\") {\n\t\treturn (details as { isCreated: boolean }).isCreated;\n\t}\n\tif (typeof (details as { isNewFile?: unknown }).isNewFile === \"boolean\") {\n\t\treturn (details as { isNewFile: boolean }).isNewFile;\n\t}\n\n\treturn false;\n}\n\nfunction splitSentenceLines(text: string): string[] {\n\treturn text\n\t\t.split(/(?<=[.!?])\\s+|\\n+/)\n\t\t.map((line) => line.trim().replace(/[.!?]+$/, \"\"))\n\t\t.filter(Boolean);\n}\n\nfunction getMessageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tswitch (entry.type) {\n\t\tcase \"message\":\n\t\t\treturn entry.message;\n\t\tcase \"custom_message\":\n\t\t\treturn {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: entry.customType,\n\t\t\t\tcontent: entry.content,\n\t\t\t\tdetails: entry.details,\n\t\t\t\tdisplay: entry.display,\n\t\t\t\ttimestamp: new Date(entry.timestamp).getTime(),\n\t\t\t};\n\t\tcase \"branch_summary\":\n\t\t\treturn {\n\t\t\t\trole: \"branchSummary\",\n\t\t\t\tsummary: entry.summary,\n\t\t\t\tfromId: entry.fromId,\n\t\t\t\ttimestamp: new Date(entry.timestamp).getTime(),\n\t\t\t};\n\t\tcase \"compaction\":\n\t\t\treturn undefined;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction isToolCallBlock(block: unknown): block is { type: \"toolCall\"; id?: string; name: string; arguments: unknown } {\n\tif (!block || typeof block !== \"object\") {\n\t\treturn false;\n\t}\n\tif ((block as { type?: unknown }).type !== \"toolCall\") {\n\t\treturn false;\n\t}\n\tif (typeof (block as { name?: unknown }).name !== \"string\") {\n\t\treturn false;\n\t}\n\tif (!(block as { arguments?: unknown }).arguments) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nfunction toolCallVerb(name: string): string {\n\treturn TOOL_VERB_BY_NAME[name] ?? name.toUpperCase();\n}\n\nfunction isHarnessPlumbingTarget(target: string | undefined): boolean {\n\tif (!target) return false;\n\treturn (\n\t\ttarget.includes(\"/.pi/agent/context-gc/\") ||\n\t\ttarget.includes(\"~/.pi/agent/context-gc/\") ||\n\t\t/\\/tmp\\/pi-bash-[^\\s]+\\.log\\b/.test(target)\n\t);\n}\n\nfunction normalizeOperationTarget(toolName: string, path: string | undefined): string {\n\tif (!path) return \"(unknown)\";\n\tif (toolName !== \"bash\") return path;\n\treturn clampText(path.replace(/\\s+/g, \" \").trim(), COMMAND_PREFIX_MAX_CHARS);\n}\n\nfunction operationKey(toolName: string, path: string | undefined): string {\n\treturn `${toolName}:${normalizeOperationTarget(toolName, path)}`;\n}\n\nfunction operationLabel(toolName: string, path: string | undefined): string {\n\treturn `${toolCallVerb(toolName)} ${normalizeOperationTarget(toolName, path)}`;\n}\n\nfunction resultExitCode(message: AgentMessage): number | undefined {\n\tconst details = (message as { details?: unknown }).details;\n\tif (!details || typeof details !== \"object\") return undefined;\n\tconst raw = (details as { exitCode?: unknown }).exitCode;\n\tif (typeof raw === \"number\" && Number.isFinite(raw)) return raw;\n\tif (typeof raw === \"string\" && /^\\d+$/.test(raw)) return Number(raw);\n\treturn undefined;\n}\n\nfunction isOutcomeBearingTool(toolName: string | undefined): boolean {\n\treturn toolName === \"bash\";\n}\n\nfunction isOpenProblemTool(toolName: string | undefined): boolean {\n\treturn toolName === \"bash\" || toolName === \"edit\" || toolName === \"write\";\n}\n\nfunction failureSignalLine(text: string): string | undefined {\n\treturn text\n\t\t.split(/\\r?\\n/)\n\t\t.map((part) => part.trim())\n\t\t.find((line) => /exited with code [1-9]\\d*/i.test(line) || /^(error|fatal|✗|FAIL)\\b/i.test(line));\n}\n\nfunction firstErrorLine(text: string): string {\n\tconst line =\n\t\tfailureSignalLine(text) ??\n\t\ttext\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((part) => part.trim())\n\t\t\t.find(Boolean);\n\treturn clampText(line ?? \"failed\", ERROR_LINE_MAX_CHARS);\n}\n\nfunction isFailureToolResult(message: AgentMessage, text: string): boolean {\n\tif (message.role !== \"toolResult\") return false;\n\tif ((message as { isError?: unknown }).isError === true) return true;\n\tconst exitCode = resultExitCode(message);\n\tif (exitCode !== undefined) return exitCode !== 0;\n\tconst toolName = (message as { toolName?: unknown }).toolName;\n\treturn typeof toolName === \"string\" && isOutcomeBearingTool(toolName) && failureSignalLine(text) !== undefined;\n}\n\nexport function extractCompactionFacts(entries: SessionEntry[], start: number, end: number): CompactionFacts {\n\tconst rangeStart = Math.max(0, start);\n\tconst rangeEnd = Math.min(entries.length, Math.max(rangeStart, end));\n\n\tif (rangeStart >= rangeEnd) {\n\t\treturn {\n\t\t\tfiles: [],\n\t\t\tworkingSet: [],\n\t\t\tactions: [],\n\t\t\terrorFacts: [],\n\t\t\tprohibitions: [],\n\t\t\tcancelledText: \"\",\n\t\t\tactiveTaskSource: \"\",\n\t\t\tdelegatedWorkerFacts: [],\n\t\t};\n\t}\n\tconst delegatedWorkerFacts = extractDelegatedWorkerFacts(entries, rangeStart, rangeEnd);\n\n\tconst filesByPath = new Map<string, CompactionFileFact & { lastTouch: number }>();\n\tconst filesNotes = new Map<string, string>();\n\tconst seenProhibitions = new Set<string>();\n\tconst actionFacts: ToolCallFact[] = [];\n\tconst pendingById = new Map<string, number[]>();\n\tconst pendingByOrder: number[] = [];\n\n\tconst actions: string[] = [];\n\tconst openErrors = new Map<string, CompactionErrorFact & { lastTouch: number }>();\n\tconst prohibitions: string[] = [];\n\tlet activeTaskSource = \"\";\n\tconst cancelledParts: string[] = [];\n\tconst sinceLastUser: string[] = [];\n\n\tfor (let i = rangeStart; i < rangeEnd; i++) {\n\t\tconst message = getMessageFromEntry(entries[i]);\n\t\tif (!message) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (message.role === \"user\") {\n\t\t\tconst userText = messageToText(message);\n\t\t\tif (REVERSAL_PATTERN.test(userText)) {\n\t\t\t\tcancelledParts.push(...sinceLastUser);\n\t\t\t}\n\t\t\tsinceLastUser.length = 0;\n\n\t\t\tif (userText) {\n\t\t\t\tactiveTaskSource = clampText(userText, ACTIVE_TASK_SOURCE_MAX_CHARS);\n\t\t\t\t// Mandatory Rules exist for SPOKEN durable prohibitions (\"do not touch X\"), not for\n\t\t\t\t// documents. A long pasted text (plan, instruction file) can contain dozens of\n\t\t\t\t// \"never/do not\" lines; harvesting them makes the verification gate demand the\n\t\t\t\t// checkpoint reproduce the document (2026-07-06 field incident: 13 fragment rules\n\t\t\t\t// extracted from one pasted instruction). Documents live on disk; skip them here.\n\t\t\t\tif (userText.length <= PROHIBITION_SOURCE_MAX_CHARS) {\n\t\t\t\t\tfor (const sentence of splitSentenceLines(userText)) {\n\t\t\t\t\t\tif (!PROHIBITION_PATTERN.test(sentence)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst normalized = clampText(sentence, 160);\n\t\t\t\t\t\tconst dedupeKey = normalized.toLowerCase();\n\t\t\t\t\t\tif (!seenProhibitions.has(dedupeKey)) {\n\t\t\t\t\t\t\tseenProhibitions.add(dedupeKey);\n\t\t\t\t\t\t\tprohibitions.push(normalized);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (message.role === \"assistant\" || message.role === \"toolResult\") {\n\t\t\tconst messageText = messageToText(message);\n\t\t\tif (messageText) {\n\t\t\t\tsinceLastUser.push(messageText);\n\t\t\t}\n\t\t}\n\n\t\tif (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\tfor (const block of message.content) {\n\t\t\t\tif (!isToolCallBlock(block)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst name = block.name;\n\t\t\t\tconst verb = toolCallVerb(name);\n\t\t\t\tconst path = assistantToolCallTarget(name, block.arguments);\n\t\t\t\tconst baseKind = TOOL_KIND_BY_NAME[name] ?? null;\n\t\t\t\tconst fact: ToolCallFact = {\n\t\t\t\t\tid: block.id,\n\t\t\t\t\tname,\n\t\t\t\t\tpath,\n\t\t\t\t\tbaseKind,\n\t\t\t\t\tfinalKind: baseKind,\n\t\t\t\t\tverb,\n\t\t\t\t\tresolved: false,\n\t\t\t\t\tfailed: false,\n\t\t\t\t};\n\t\t\t\tactionFacts.push(fact);\n\t\t\t\tconst index = actionFacts.length - 1;\n\t\t\t\tpendingByOrder.push(index);\n\t\t\t\tif (fact.id) {\n\t\t\t\t\tconst bucket = pendingById.get(fact.id) ?? [];\n\t\t\t\t\tbucket.push(index);\n\t\t\t\t\tpendingById.set(fact.id, bucket);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (message.role === \"toolResult\") {\n\t\t\tconst toolCallId = (message as { toolCallId?: string }).toolCallId;\n\t\t\tconst toolName = (message as { toolName?: string }).toolName;\n\t\t\tlet matchedIndex: number | undefined;\n\n\t\t\tif (toolCallId) {\n\t\t\t\tconst bucket = pendingById.get(toolCallId);\n\t\t\t\tif (bucket && bucket.length > 0) {\n\t\t\t\t\tmatchedIndex = bucket.shift();\n\t\t\t\t\tif (bucket.length === 0) {\n\t\t\t\t\t\tpendingById.delete(toolCallId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matchedIndex === undefined && toolName) {\n\t\t\t\tfor (const index of pendingByOrder) {\n\t\t\t\t\tconst candidate = actionFacts[index];\n\t\t\t\t\tif (!candidate.resolved && candidate.name === toolName) {\n\t\t\t\t\t\tmatchedIndex = index;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matchedIndex !== undefined) {\n\t\t\t\tconst fact = actionFacts[matchedIndex];\n\t\t\t\tconst resultText = messageToText(message);\n\t\t\t\tconst failed = isFailureToolResult(message, resultText);\n\t\t\t\tfact.resolved = true;\n\t\t\t\tfact.failed = failed;\n\t\t\t\tif (!failed && fact.baseKind === \"modified\" && appearsCreated(message)) {\n\t\t\t\t\tfact.finalKind = \"created\";\n\t\t\t\t}\n\n\t\t\t\tif (!failed && fact.path && fact.finalKind && !isHarnessPlumbingTarget(fact.path)) {\n\t\t\t\t\tconst existing = filesByPath.get(fact.path);\n\t\t\t\t\tconst nextKind = fact.finalKind;\n\t\t\t\t\tconst note = fact.verb;\n\t\t\t\t\tif (!existing || FILE_KIND_PRIORITY[nextKind] > FILE_KIND_PRIORITY[existing.kind]) {\n\t\t\t\t\t\tfilesByPath.set(fact.path, { path: fact.path, kind: nextKind, note, lastTouch: i });\n\t\t\t\t\t} else if (existing.kind === nextKind) {\n\t\t\t\t\t\texisting.note = note;\n\t\t\t\t\t\texisting.lastTouch = i;\n\t\t\t\t\t} else {\n\t\t\t\t\t\texisting.lastTouch = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst key = operationKey(fact.name, fact.path);\n\t\t\t\tif (failed && isOpenProblemTool(fact.name)) {\n\t\t\t\t\topenErrors.set(key, {\n\t\t\t\t\t\toperation: operationLabel(fact.name, fact.path),\n\t\t\t\t\t\terror: firstErrorLine(resultText),\n\t\t\t\t\t\tlastTouch: i,\n\t\t\t\t\t});\n\t\t\t\t} else if (!failed) {\n\t\t\t\t\topenErrors.delete(key);\n\t\t\t\t}\n\n\t\t\t\tconst pendingPos = pendingByOrder.indexOf(matchedIndex);\n\t\t\t\tif (pendingPos >= 0) {\n\t\t\t\t\tpendingByOrder.splice(pendingPos, 1);\n\t\t\t\t}\n\t\t\t\tif (toolCallId) {\n\t\t\t\t\tconst bucket = pendingById.get(toolCallId);\n\t\t\t\t\tif (bucket) {\n\t\t\t\t\t\tconst pos = bucket.indexOf(matchedIndex);\n\t\t\t\t\t\tif (pos >= 0) {\n\t\t\t\t\t\t\tbucket.splice(pos, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (bucket.length === 0) {\n\t\t\t\t\t\t\tpendingById.delete(toolCallId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const action of actionFacts) {\n\t\tif (isHarnessPlumbingTarget(action.path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (action.resolved && action.failed && action.name !== \"bash\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif ((!action.resolved || !action.failed) && action.finalKind && action.path && !filesByPath.has(action.path)) {\n\t\t\tfilesByPath.set(action.path, {\n\t\t\t\tpath: action.path,\n\t\t\t\tkind: action.finalKind,\n\t\t\t\tnote: action.verb,\n\t\t\t\tlastTouch: actionFacts.indexOf(action),\n\t\t\t});\n\t\t}\n\n\t\tactions.push(`${action.verb} ${action.path ?? \"(unknown)\"}`);\n\t}\n\n\tfor (const file of filesByPath.values()) {\n\t\tif (!file.note && filesNotes.has(file.path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (file.note && filesNotes.get(file.path) === file.note) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (file.note) {\n\t\t\tfilesNotes.set(file.path, file.note);\n\t\t}\n\t}\n\n\tfor (const file of filesByPath.values()) {\n\t\tconst suffix = filesNotes.get(file.path);\n\t\tif (suffix) {\n\t\t\tfile.note = suffix;\n\t\t}\n\t}\n\n\tconst files = Array.from(filesByPath.values())\n\t\t.sort(\n\t\t\t(a, b) =>\n\t\t\t\tb.lastTouch - a.lastTouch ||\n\t\t\t\tFILE_KIND_PRIORITY[b.kind] - FILE_KIND_PRIORITY[a.kind] ||\n\t\t\t\ta.path.localeCompare(b.path),\n\t\t)\n\t\t.map(({ lastTouch: _lastTouch, ...file }) => file);\n\n\treturn {\n\t\tfiles,\n\t\tworkingSet: files.slice(0, MAX_WORKING_SET_FILES),\n\t\tactions: dedupeMostRecent(actions).slice(-MAX_ACTIONS),\n\t\terrorFacts: Array.from(openErrors.values())\n\t\t\t.sort((a, b) => a.lastTouch - b.lastTouch)\n\t\t\t.slice(-MAX_ERROR_FACTS)\n\t\t\t.map(({ lastTouch: _lastTouch, ...error }) => error),\n\t\tprohibitions: prohibitions.slice(-MAX_PROHIBITIONS),\n\t\tcancelledText: cancelledParts.join(\"\\n\"),\n\t\tactiveTaskSource,\n\t\tdelegatedWorkerFacts,\n\t};\n}\n\nfunction dedupeMostRecent(values: string[]): string[] {\n\tconst seen = new Set<string>();\n\tconst kept: string[] = [];\n\tfor (let i = values.length - 1; i >= 0; i--) {\n\t\tconst value = values[i];\n\t\tif (seen.has(value)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(value);\n\t\tkept.push(value);\n\t}\n\treturn kept.reverse();\n}\n\nexport function renderFactsBlock(facts: CompactionFacts): string {\n\tconst lines: string[] = [\"verification demands:\"];\n\tlines.push(\"files-modified-recall (must appear in ## Files):\");\n\tfor (const file of facts.files.filter((file) => file.kind !== \"read\")) {\n\t\tlines.push(file.path);\n\t}\n\tlines.push(\"files-read-recall (must appear in ## Files, containment threshold applies):\");\n\tfor (const file of facts.files.filter((file) => file.kind === \"read\")) {\n\t\tlines.push(file.path);\n\t}\n\tlines.push(\"working-set-recall (must appear in ## Working Set):\");\n\tfor (const file of facts.workingSet) {\n\t\tlines.push(`${file.path} — ${file.note || file.kind}`);\n\t}\n\tlines.push(\"open-errors-recall (must appear in ## Open Problems):\");\n\tfor (const error of facts.errorFacts) {\n\t\tlines.push(`${error.operation}: ${error.error}`);\n\t}\n\tlines.push(\"actions-recall (must appear in ## Done):\");\n\tfor (const action of facts.actions) {\n\t\tlines.push(action);\n\t}\n\tlines.push(\"mandatory-rules-recall (must appear in ### Mandatory Rules):\");\n\tfor (const prohibition of facts.prohibitions) {\n\t\tlines.push(prohibition);\n\t}\n\t// The active-task gate demands near-verbatim recall of this text, but the conversation the\n\t// summarizer sees may be pre-digested or truncated — the facts block is the one channel\n\t// guaranteed to reach the prompt, so the gated text must ride in it (bounded).\n\tlines.push(\"active-task-containment (must appear in ## Active Task):\");\n\tif (facts.activeTaskSource) {\n\t\tlines.push(clampText(facts.activeTaskSource, ACTIVE_TASK_SOURCE_MAX_CHARS));\n\t}\n\tlines.push(\"cancelled-work-dropped (must NOT appear outside ### Mandatory Rules):\");\n\tif (facts.cancelledText) {\n\t\tlines.push(facts.cancelledText);\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"extraction.js","sourceRoot":"","sources":["../../src/compaction/extraction.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionEntry } from \"../session/session-manager.ts\";\nimport type { AgentMessage } from \"../types.ts\";\n\nexport interface CompactionFileFact {\n\tpath: string;\n\tkind: \"modified\" | \"created\" | \"read\";\n\tnote: string;\n}\n\nexport interface CompactionErrorFact {\n\toperation: string;\n\terror: string;\n}\n\nexport interface CompactionDelegatedWorkerFact {\n\t/** Worker-authored text is evidence for the parent, never a verified decision or completion claim. */\n\ttrust: \"UNTRUSTED\";\n\ttask: string;\n\tsummary: string;\n}\n\nexport interface CompactionFacts {\n\tfiles: CompactionFileFact[];\n\tworkingSet: CompactionFileFact[];\n\tactions: string[];\n\terrorFacts: CompactionErrorFact[];\n\tprohibitions: string[];\n\tcancelledText: string;\n\tactiveTaskSource: string;\n\t/** Latest-first worker evidence retained only by deterministic checkpoints. */\n\tdelegatedWorkerFacts?: CompactionDelegatedWorkerFact[];\n}\n\ninterface ToolCallFact {\n\tid: string | undefined;\n\tname: string;\n\tpath: string | undefined;\n\tbaseKind: \"modified\" | \"created\" | \"read\" | null;\n\tfinalKind: \"modified\" | \"created\" | \"read\" | null;\n\tverb: string;\n\tresolved: boolean;\n\tfailed: boolean;\n}\n\nconst PROHIBITION_PATTERN = /\\b(do not|don't|never|stop (?:doing|using|changing)|no more)\\b/i;\n// Deliberately narrow: a bare \"stop\" (\"stop the server and rerun\") is everyday phrasing, not a\n// reversal of the prior work — matching it marked whole turns cancelled and made the\n// cancelled-work gate fight the recall gates (2026-07-06 incident).\nconst REVERSAL_PATTERN =\n\t/\\b(undo|revert|roll back|never mind|scrap that|forget (?:it|that)|stop (?:that|this|it|everything|working on))\\b/i;\n\n/** User messages longer than this are documents/pastes, not spoken prohibitions. */\nconst PROHIBITION_SOURCE_MAX_CHARS = 1_500;\n/** Upper bound on gate-demanded rules; most recent win (same bounding rationale as Done carry-over). */\nconst MAX_PROHIBITIONS = 8;\n/** Upper bound on gate-demanded actions; mirrors the prompt's \"15 most recent Done items\" rule. */\nconst MAX_ACTIONS = 15;\nconst MAX_WORKING_SET_FILES = 8;\nconst MAX_ERROR_FACTS = 5;\nconst ERROR_LINE_MAX_CHARS = 160;\nconst COMMAND_PREFIX_MAX_CHARS = 80;\nconst MAX_DELEGATED_WORKER_FACTS = 4;\nconst DELEGATED_WORKER_TASK_MAX_CHARS = 240;\nconst DELEGATED_WORKER_SUMMARY_MAX_CHARS = 600;\n/** Shared clamp for the active-task text because verification can only demand what the prompt receives. */\nexport const ACTIVE_TASK_SOURCE_MAX_CHARS = 4_000;\n\nconst FILE_KIND_PRIORITY: Record<NonNullable<ToolCallFact[\"finalKind\"]>, number> = {\n\tread: 1,\n\tcreated: 2,\n\tmodified: 3,\n};\n\nconst TOOL_KIND_BY_NAME: Record<string, \"modified\" | \"created\" | \"read\" | null> = {\n\tread: \"read\",\n\tgrep: \"read\",\n\tfind: \"read\",\n\twrite: \"modified\",\n\tedit: \"modified\",\n\tbash: null,\n};\n\nconst TOOL_VERB_BY_NAME: Record<string, string> = {\n\twrite: \"WRITE\",\n\tedit: \"EDIT\",\n\tbash: \"RUN\",\n\tread: \"READ\",\n\tgrep: \"READ\",\n\tfind: \"READ\",\n};\n\nfunction messageToText(message: AgentMessage): string {\n\tconst rawContent = (message as { content?: unknown }).content;\n\tif (typeof rawContent === \"string\") {\n\t\treturn rawContent;\n\t}\n\tif (!Array.isArray(rawContent)) {\n\t\treturn \"\";\n\t}\n\n\tconst parts: string[] = [];\n\tfor (const block of rawContent) {\n\t\tif (!block || typeof block !== \"object\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((block as { type?: unknown }).type === \"text\" && typeof (block as { text?: unknown }).text === \"string\") {\n\t\t\tparts.push((block as { text: string }).text);\n\t\t}\n\t}\n\treturn (parts.length === 1 ? parts[0] : parts.join(\" \")).trim();\n}\n\nfunction assistantToolCallTarget(name: string, rawArgs: unknown): string | undefined {\n\tif (!rawArgs || typeof rawArgs !== \"object\") {\n\t\treturn undefined;\n\t}\n\tconst args = rawArgs as Record<string, unknown>;\n\n\tif (\n\t\t(name === \"read\" || name === \"grep\" || name === \"find\" || name === \"write\" || name === \"edit\") &&\n\t\ttypeof args.path === \"string\" &&\n\t\targs.path.length > 0\n\t) {\n\t\treturn args.path;\n\t}\n\n\tif (name === \"bash\" && typeof args.command === \"string\" && args.command.length > 0) {\n\t\treturn args.command;\n\t}\n\n\treturn undefined;\n}\n\nfunction clampText(text: string, maxLen: number): string {\n\treturn text.length > maxLen ? text.slice(0, maxLen) : text;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction normalizeDelegatedWorkerText(text: string, maxLen: number): string {\n\tlet normalized = \"\";\n\tfor (const match of text.matchAll(/\\S+/g)) {\n\t\tconst separator = normalized.length > 0 ? \" \" : \"\";\n\t\tconst remaining = maxLen - normalized.length - separator.length;\n\t\tif (remaining <= 0) break;\n\t\tnormalized += `${separator}${match[0].slice(0, remaining)}`;\n\t\tif (match[0].length >= remaining) break;\n\t}\n\treturn normalized;\n}\n\nfunction extractDelegatedWorkerFact(entry: SessionEntry): CompactionDelegatedWorkerFact | undefined {\n\tif (entry.type !== \"custom\" || entry.customType !== \"worker_result\" || !isPlainRecord(entry.data)) {\n\t\treturn undefined;\n\t}\n\tif (entry.data.version !== 1 || !isPlainRecord(entry.data.result)) return undefined;\n\n\tconst result = entry.data.result;\n\tif (typeof result.requestId !== \"string\" || typeof result.summary !== \"string\") return undefined;\n\tif (typeof result.status !== \"string\" || ![\"completed\", \"blocked\", \"failed\", \"cancelled\"].includes(result.status)) {\n\t\treturn undefined;\n\t}\n\tif (!Array.isArray(result.changedFiles) || !result.changedFiles.every((file) => typeof file === \"string\")) {\n\t\treturn undefined;\n\t}\n\n\tconst request = entry.data.request;\n\tconst instructions =\n\t\tisPlainRecord(request) && typeof request.instructions === \"string\" ? request.instructions : undefined;\n\tconst task = normalizeDelegatedWorkerText(\n\t\tinstructions ?? `Worker request ${result.requestId}`,\n\t\tDELEGATED_WORKER_TASK_MAX_CHARS,\n\t);\n\tconst summary = normalizeDelegatedWorkerText(result.summary, DELEGATED_WORKER_SUMMARY_MAX_CHARS);\n\n\treturn {\n\t\ttrust: \"UNTRUSTED\",\n\t\ttask: task || \"(empty task)\",\n\t\tsummary: summary || \"(empty summary)\",\n\t};\n}\n\nfunction extractDelegatedWorkerFacts(\n\tentries: readonly SessionEntry[],\n\tstart: number,\n\tend: number,\n): CompactionDelegatedWorkerFact[] {\n\tconst facts: CompactionDelegatedWorkerFact[] = [];\n\tfor (let i = end - 1; i >= start && facts.length < MAX_DELEGATED_WORKER_FACTS; i--) {\n\t\tconst fact = extractDelegatedWorkerFact(entries[i]);\n\t\tif (fact) facts.push(fact);\n\t}\n\treturn facts;\n}\n\nfunction appearsCreated(message: AgentMessage): boolean {\n\tif (message.role !== \"toolResult\") {\n\t\treturn false;\n\t}\n\n\tconst text = messageToText(message).toLowerCase();\n\tif (/(\\bnew file\\b|\\bcreated\\b|\\bcreated file\\b)/.test(text)) {\n\t\treturn true;\n\t}\n\n\tconst details = (message as { details?: unknown }).details;\n\tif (!details || typeof details !== \"object\") {\n\t\treturn false;\n\t}\n\n\tif (typeof (details as { created?: unknown }).created === \"boolean\") {\n\t\treturn (details as { created: boolean }).created;\n\t}\n\tif (typeof (details as { isCreated?: unknown }).isCreated === \"boolean\") {\n\t\treturn (details as { isCreated: boolean }).isCreated;\n\t}\n\tif (typeof (details as { isNewFile?: unknown }).isNewFile === \"boolean\") {\n\t\treturn (details as { isNewFile: boolean }).isNewFile;\n\t}\n\n\treturn false;\n}\n\nfunction splitSentenceLines(text: string): string[] {\n\treturn text\n\t\t.split(/(?<=[.!?])\\s+|\\n+/)\n\t\t.map((line) => line.trim().replace(/[.!?]+$/, \"\"))\n\t\t.filter(Boolean);\n}\n\nfunction getMessageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tswitch (entry.type) {\n\t\tcase \"message\":\n\t\t\treturn entry.message;\n\t\tcase \"custom_message\":\n\t\t\treturn {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: entry.customType,\n\t\t\t\tcontent: entry.content,\n\t\t\t\tdetails: entry.details,\n\t\t\t\tdisplay: entry.display,\n\t\t\t\ttimestamp: new Date(entry.timestamp).getTime(),\n\t\t\t};\n\t\tcase \"branch_summary\":\n\t\t\treturn {\n\t\t\t\trole: \"branchSummary\",\n\t\t\t\tsummary: entry.summary,\n\t\t\t\tfromId: entry.fromId,\n\t\t\t\ttimestamp: new Date(entry.timestamp).getTime(),\n\t\t\t};\n\t\tcase \"compaction\":\n\t\t\treturn undefined;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction isToolCallBlock(block: unknown): block is { type: \"toolCall\"; id?: string; name: string; arguments: unknown } {\n\tif (!block || typeof block !== \"object\") {\n\t\treturn false;\n\t}\n\tif ((block as { type?: unknown }).type !== \"toolCall\") {\n\t\treturn false;\n\t}\n\tif (typeof (block as { name?: unknown }).name !== \"string\") {\n\t\treturn false;\n\t}\n\tif (!(block as { arguments?: unknown }).arguments) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nfunction toolCallVerb(name: string): string {\n\treturn TOOL_VERB_BY_NAME[name] ?? name.toUpperCase();\n}\n\nfunction isHarnessPlumbingTarget(target: string | undefined): boolean {\n\tif (!target) return false;\n\treturn (\n\t\ttarget.includes(\"/.pi/agent/context-gc/\") ||\n\t\ttarget.includes(\"~/.pi/agent/context-gc/\") ||\n\t\t/\\/tmp\\/pi-bash-[^\\s]+\\.log\\b/.test(target)\n\t);\n}\n\nfunction normalizeOperationTarget(toolName: string, path: string | undefined): string {\n\tif (!path) return \"(unknown)\";\n\tif (toolName !== \"bash\") return path;\n\treturn clampText(path.replace(/\\s+/g, \" \").trim(), COMMAND_PREFIX_MAX_CHARS);\n}\n\nfunction operationKey(toolName: string, path: string | undefined): string {\n\treturn `${toolName}:${normalizeOperationTarget(toolName, path)}`;\n}\n\nfunction operationLabel(toolName: string, path: string | undefined): string {\n\treturn `${toolCallVerb(toolName)} ${normalizeOperationTarget(toolName, path)}`;\n}\n\nfunction resultExitCode(message: AgentMessage): number | undefined {\n\tconst details = (message as { details?: unknown }).details;\n\tif (!details || typeof details !== \"object\") return undefined;\n\tconst raw = (details as { exitCode?: unknown }).exitCode;\n\tif (typeof raw === \"number\" && Number.isFinite(raw)) return raw;\n\tif (typeof raw === \"string\" && /^\\d+$/.test(raw)) return Number(raw);\n\treturn undefined;\n}\n\nfunction isOutcomeBearingTool(toolName: string | undefined): boolean {\n\treturn toolName === \"bash\";\n}\n\nfunction isOpenProblemTool(toolName: string | undefined): boolean {\n\treturn toolName === \"bash\" || toolName === \"edit\" || toolName === \"write\";\n}\n\nfunction failureSignalLine(text: string): string | undefined {\n\treturn text\n\t\t.split(/\\r?\\n/)\n\t\t.map((part) => part.trim())\n\t\t.find((line) => /exited with code [1-9]\\d*/i.test(line) || /^(error|fatal|✗|FAIL)\\b/i.test(line));\n}\n\nfunction firstErrorLine(text: string): string {\n\tconst line =\n\t\tfailureSignalLine(text) ??\n\t\ttext\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((part) => part.trim())\n\t\t\t.find(Boolean);\n\treturn clampText(line ?? \"failed\", ERROR_LINE_MAX_CHARS);\n}\n\nfunction isFailureToolResult(message: AgentMessage, text: string): boolean {\n\tif (message.role !== \"toolResult\") return false;\n\tif ((message as { isError?: unknown }).isError === true) return true;\n\tconst exitCode = resultExitCode(message);\n\tif (exitCode !== undefined) return exitCode !== 0;\n\tconst toolName = (message as { toolName?: unknown }).toolName;\n\treturn typeof toolName === \"string\" && isOutcomeBearingTool(toolName) && failureSignalLine(text) !== undefined;\n}\n\nexport function extractCompactionFacts(entries: SessionEntry[], start: number, end: number): CompactionFacts {\n\tconst rangeStart = Math.max(0, start);\n\tconst rangeEnd = Math.min(entries.length, Math.max(rangeStart, end));\n\n\tif (rangeStart >= rangeEnd) {\n\t\treturn {\n\t\t\tfiles: [],\n\t\t\tworkingSet: [],\n\t\t\tactions: [],\n\t\t\terrorFacts: [],\n\t\t\tprohibitions: [],\n\t\t\tcancelledText: \"\",\n\t\t\tactiveTaskSource: \"\",\n\t\t\tdelegatedWorkerFacts: [],\n\t\t};\n\t}\n\tconst delegatedWorkerFacts = extractDelegatedWorkerFacts(entries, rangeStart, rangeEnd);\n\n\tconst filesByPath = new Map<string, CompactionFileFact & { lastTouch: number }>();\n\tconst filesNotes = new Map<string, string>();\n\tconst seenProhibitions = new Set<string>();\n\tconst actionFacts: ToolCallFact[] = [];\n\tconst pendingById = new Map<string, number[]>();\n\tconst pendingByOrder: number[] = [];\n\n\tconst actions: string[] = [];\n\tconst openErrors = new Map<string, CompactionErrorFact & { lastTouch: number }>();\n\tconst prohibitions: string[] = [];\n\tlet activeTaskSource = \"\";\n\tconst cancelledParts: string[] = [];\n\tconst sinceLastUser: string[] = [];\n\n\tfor (let i = rangeStart; i < rangeEnd; i++) {\n\t\tconst message = getMessageFromEntry(entries[i]);\n\t\tif (!message) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (message.role === \"user\") {\n\t\t\tconst userText = messageToText(message);\n\t\t\tif (REVERSAL_PATTERN.test(userText)) {\n\t\t\t\tcancelledParts.push(...sinceLastUser);\n\t\t\t}\n\t\t\tsinceLastUser.length = 0;\n\n\t\t\tif (userText) {\n\t\t\t\tactiveTaskSource = clampText(userText, ACTIVE_TASK_SOURCE_MAX_CHARS);\n\t\t\t\t// Mandatory Rules exist for SPOKEN durable prohibitions (\"do not touch X\"), not for\n\t\t\t\t// documents. A long pasted text (plan, instruction file) can contain dozens of\n\t\t\t\t// \"never/do not\" lines; harvesting them makes the verification gate demand the\n\t\t\t\t// checkpoint reproduce the document (2026-07-06 field incident: 13 fragment rules\n\t\t\t\t// extracted from one pasted instruction). Documents live on disk; skip them here.\n\t\t\t\tif (userText.length <= PROHIBITION_SOURCE_MAX_CHARS) {\n\t\t\t\t\tfor (const sentence of splitSentenceLines(userText)) {\n\t\t\t\t\t\tif (!PROHIBITION_PATTERN.test(sentence)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst normalized = clampText(sentence, 160);\n\t\t\t\t\t\tconst dedupeKey = normalized.toLowerCase();\n\t\t\t\t\t\tif (!seenProhibitions.has(dedupeKey)) {\n\t\t\t\t\t\t\tseenProhibitions.add(dedupeKey);\n\t\t\t\t\t\t\tprohibitions.push(normalized);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (message.role === \"assistant\" || message.role === \"toolResult\") {\n\t\t\tconst messageText = messageToText(message);\n\t\t\tif (messageText) {\n\t\t\t\tsinceLastUser.push(messageText);\n\t\t\t}\n\t\t}\n\n\t\tif (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\tfor (const block of message.content) {\n\t\t\t\tif (!isToolCallBlock(block)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst name = block.name;\n\t\t\t\tconst verb = toolCallVerb(name);\n\t\t\t\tconst path = assistantToolCallTarget(name, block.arguments);\n\t\t\t\tconst baseKind = TOOL_KIND_BY_NAME[name] ?? null;\n\t\t\t\tconst fact: ToolCallFact = {\n\t\t\t\t\tid: block.id,\n\t\t\t\t\tname,\n\t\t\t\t\tpath,\n\t\t\t\t\tbaseKind,\n\t\t\t\t\tfinalKind: baseKind,\n\t\t\t\t\tverb,\n\t\t\t\t\tresolved: false,\n\t\t\t\t\tfailed: false,\n\t\t\t\t};\n\t\t\t\tactionFacts.push(fact);\n\t\t\t\tconst index = actionFacts.length - 1;\n\t\t\t\tpendingByOrder.push(index);\n\t\t\t\tif (fact.id) {\n\t\t\t\t\tconst bucket = pendingById.get(fact.id) ?? [];\n\t\t\t\t\tbucket.push(index);\n\t\t\t\t\tpendingById.set(fact.id, bucket);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (message.role === \"toolResult\") {\n\t\t\tconst toolCallId = (message as { toolCallId?: string }).toolCallId;\n\t\t\tconst toolName = (message as { toolName?: string }).toolName;\n\t\t\tlet matchedIndex: number | undefined;\n\n\t\t\tif (toolCallId) {\n\t\t\t\tconst bucket = pendingById.get(toolCallId);\n\t\t\t\tif (bucket && bucket.length > 0) {\n\t\t\t\t\tmatchedIndex = bucket.shift();\n\t\t\t\t\tif (bucket.length === 0) {\n\t\t\t\t\t\tpendingById.delete(toolCallId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matchedIndex === undefined && toolName) {\n\t\t\t\tfor (const index of pendingByOrder) {\n\t\t\t\t\tconst candidate = actionFacts[index];\n\t\t\t\t\tif (!candidate.resolved && candidate.name === toolName) {\n\t\t\t\t\t\tmatchedIndex = index;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matchedIndex !== undefined) {\n\t\t\t\tconst fact = actionFacts[matchedIndex];\n\t\t\t\tconst resultText = messageToText(message);\n\t\t\t\tconst failed = isFailureToolResult(message, resultText);\n\t\t\t\tfact.resolved = true;\n\t\t\t\tfact.failed = failed;\n\t\t\t\tif (!failed && fact.baseKind === \"modified\" && appearsCreated(message)) {\n\t\t\t\t\tfact.finalKind = \"created\";\n\t\t\t\t}\n\n\t\t\t\tif (!failed && fact.path && fact.finalKind && !isHarnessPlumbingTarget(fact.path)) {\n\t\t\t\t\tconst existing = filesByPath.get(fact.path);\n\t\t\t\t\tconst nextKind = fact.finalKind;\n\t\t\t\t\tconst note = fact.verb;\n\t\t\t\t\tif (!existing || FILE_KIND_PRIORITY[nextKind] > FILE_KIND_PRIORITY[existing.kind]) {\n\t\t\t\t\t\tfilesByPath.set(fact.path, { path: fact.path, kind: nextKind, note, lastTouch: i });\n\t\t\t\t\t} else if (existing.kind === nextKind) {\n\t\t\t\t\t\texisting.note = note;\n\t\t\t\t\t\texisting.lastTouch = i;\n\t\t\t\t\t} else {\n\t\t\t\t\t\texisting.lastTouch = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst key = operationKey(fact.name, fact.path);\n\t\t\t\tif (failed && isOpenProblemTool(fact.name)) {\n\t\t\t\t\topenErrors.set(key, {\n\t\t\t\t\t\toperation: operationLabel(fact.name, fact.path),\n\t\t\t\t\t\terror: firstErrorLine(resultText),\n\t\t\t\t\t\tlastTouch: i,\n\t\t\t\t\t});\n\t\t\t\t} else if (!failed) {\n\t\t\t\t\topenErrors.delete(key);\n\t\t\t\t}\n\n\t\t\t\tconst pendingPos = pendingByOrder.indexOf(matchedIndex);\n\t\t\t\tif (pendingPos >= 0) {\n\t\t\t\t\tpendingByOrder.splice(pendingPos, 1);\n\t\t\t\t}\n\t\t\t\tif (toolCallId) {\n\t\t\t\t\tconst bucket = pendingById.get(toolCallId);\n\t\t\t\t\tif (bucket) {\n\t\t\t\t\t\tconst pos = bucket.indexOf(matchedIndex);\n\t\t\t\t\t\tif (pos >= 0) {\n\t\t\t\t\t\t\tbucket.splice(pos, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (bucket.length === 0) {\n\t\t\t\t\t\t\tpendingById.delete(toolCallId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const action of actionFacts) {\n\t\tif (isHarnessPlumbingTarget(action.path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (action.resolved && action.failed && action.name !== \"bash\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif ((!action.resolved || !action.failed) && action.finalKind && action.path && !filesByPath.has(action.path)) {\n\t\t\tfilesByPath.set(action.path, {\n\t\t\t\tpath: action.path,\n\t\t\t\tkind: action.finalKind,\n\t\t\t\tnote: action.verb,\n\t\t\t\tlastTouch: actionFacts.indexOf(action),\n\t\t\t});\n\t\t}\n\n\t\tactions.push(`${action.verb} ${action.path ?? \"(unknown)\"}`);\n\t}\n\n\tfor (const file of filesByPath.values()) {\n\t\tif (!file.note && filesNotes.has(file.path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (file.note && filesNotes.get(file.path) === file.note) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (file.note) {\n\t\t\tfilesNotes.set(file.path, file.note);\n\t\t}\n\t}\n\n\tfor (const file of filesByPath.values()) {\n\t\tconst suffix = filesNotes.get(file.path);\n\t\tif (suffix) {\n\t\t\tfile.note = suffix;\n\t\t}\n\t}\n\n\tconst files = Array.from(filesByPath.values())\n\t\t.sort(\n\t\t\t(a, b) =>\n\t\t\t\tb.lastTouch - a.lastTouch ||\n\t\t\t\tFILE_KIND_PRIORITY[b.kind] - FILE_KIND_PRIORITY[a.kind] ||\n\t\t\t\ta.path.localeCompare(b.path),\n\t\t)\n\t\t.map(({ lastTouch: _lastTouch, ...file }) => file);\n\n\treturn {\n\t\tfiles,\n\t\tworkingSet: files.slice(0, MAX_WORKING_SET_FILES),\n\t\tactions: dedupeMostRecent(actions).slice(-MAX_ACTIONS),\n\t\terrorFacts: Array.from(openErrors.values())\n\t\t\t.sort((a, b) => a.lastTouch - b.lastTouch)\n\t\t\t.slice(-MAX_ERROR_FACTS)\n\t\t\t.map(({ lastTouch: _lastTouch, ...error }) => error),\n\t\tprohibitions: prohibitions.slice(-MAX_PROHIBITIONS),\n\t\tcancelledText: cancelledParts.join(\"\\n\"),\n\t\tactiveTaskSource,\n\t\tdelegatedWorkerFacts,\n\t};\n}\n\nfunction dedupeMostRecent(values: string[]): string[] {\n\tconst seen = new Set<string>();\n\tconst kept: string[] = [];\n\tfor (let i = values.length - 1; i >= 0; i--) {\n\t\tconst value = values[i];\n\t\tif (seen.has(value)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(value);\n\t\tkept.push(value);\n\t}\n\treturn kept.reverse();\n}\n\nexport function renderFactsBlock(facts: CompactionFacts): string {\n\tconst lines: string[] = [\"verification demands:\"];\n\tlines.push(\"files-modified-recall (must appear in ## Files):\");\n\tfor (const file of facts.files.filter((file) => file.kind !== \"read\")) {\n\t\tlines.push(file.path);\n\t}\n\tlines.push(\"files-read-recall (must appear as exact paths in ## Files, path recall threshold applies):\");\n\tfor (const file of facts.files.filter((file) => file.kind === \"read\")) {\n\t\tlines.push(file.path);\n\t}\n\tlines.push(\"working-set-recall (must appear in ## Working Set):\");\n\tfor (const file of facts.workingSet) {\n\t\tlines.push(`${file.path} — ${file.note || file.kind}`);\n\t}\n\tlines.push(\"open-errors-recall (must appear in ## Open Problems):\");\n\tfor (const error of facts.errorFacts) {\n\t\tlines.push(`${error.operation}: ${error.error}`);\n\t}\n\tlines.push(\"actions-recall (must appear in ## Done):\");\n\tfor (const action of facts.actions) {\n\t\tlines.push(action);\n\t}\n\tlines.push(\"mandatory-rules-recall (must appear in ### Mandatory Rules):\");\n\tfor (const prohibition of facts.prohibitions) {\n\t\tlines.push(prohibition);\n\t}\n\t// The active-task gate demands near-verbatim recall of this text, but the conversation the\n\t// summarizer sees may be pre-digested or truncated — the facts block is the one channel\n\t// guaranteed to reach the prompt, so the gated text must ride in it (bounded).\n\tlines.push(\"active-task-containment (must appear in ## Active Task):\");\n\tif (facts.activeTaskSource) {\n\t\tlines.push(clampText(facts.activeTaskSource, ACTIVE_TASK_SOURCE_MAX_CHARS));\n\t}\n\tlines.push(\"cancelled-work-dropped (must NOT appear outside ### Mandatory Rules):\");\n\tif (facts.cancelledText) {\n\t\tlines.push(facts.cancelledText);\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Model } from "@caupulican/pi-ai";
|
|
2
2
|
import type { SessionEntry } from "../session/session-manager.ts";
|
|
3
|
-
import type
|
|
3
|
+
import { type CompactionResult } from "./compaction.ts";
|
|
4
4
|
export interface CompactionCycleParams {
|
|
5
5
|
modelTier: "cheap" | "session";
|
|
6
6
|
keepRecentTokens: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/compaction/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,MAAM,CAAC;IAC7B,SAAS,IAAI,YAAY,EAAE,CAAC;IAC5B,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1F,kBAAkB,CACjB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IACzC,4BAA4B,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,GAAG;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC;IACrG,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtD,YAAY,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1F,uBAAuB,CAAC,IAAI,MAAM,CAAC;IACnC,qBAAqB,CAAC,IAAI,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMtD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA6IhG","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { SessionEntry } from \"../session/session-manager.ts\";\nimport type { CompactionResult } from \"./compaction.ts\";\n\nexport interface CompactionCycleParams {\n\tmodelTier: \"cheap\" | \"session\";\n\tkeepRecentTokens: number;\n\tchunked: boolean;\n\tdeterministicOnly: boolean;\n}\n\nexport interface ModelAndAuth {\n\tmodel: Model<any>;\n\tapiKey?: string;\n\theaders?: Record<string, string>;\n\tfailure?: string;\n}\n\nexport interface CompactionLoopDeps {\n\tmeasureLiveTokens(): number;\n\tshouldCompact(tokens: number): boolean;\n\tgetPostApplyMargin(): number;\n\tgetBranch(): SessionEntry[];\n\tresolveModelAndAuth(modelTier: CompactionCycleParams[\"modelTier\"]): Promise<ModelAndAuth>;\n\tsummarizeAndVerify(\n\t\tparams: CompactionCycleParams,\n\t\tmodel: Model<any>,\n\t\tapiKey: string | undefined,\n\t\theaders: Record<string, string> | undefined,\n\t\tbranch: SessionEntry[],\n\t): Promise<{ result: CompactionResult }>;\n\tbuildDeterministicCheckpoint(): Promise<{ result: CompactionResult }> | { result: CompactionResult };\n\tapply(result: CompactionResult): Promise<void> | void;\n\tonTransition(info: { cycle: number; from: string; cause: string; detail?: string }): void;\n\tgetBaseKeepRecentTokens?(): number;\n\tverifyPostApplyEffect?(): boolean;\n\tsignal?: AbortSignal;\n}\n\nexport type CompactionLoopOutcome =\n\t| { kind: \"success\"; result: CompactionResult; cycles: number }\n\t| { kind: \"skip\"; reason: string }\n\t| { kind: \"failed\"; reason: string; cycles: number };\n\nconst MAX_CYCLES = 4;\nconst MAX_LLM_CYCLES = 3;\nconst DEFAULT_KEEP_RECENT = 20_000;\n\nexport async function runCompactionLoop(deps: CompactionLoopDeps): Promise<CompactionLoopOutcome> {\n\tlet lastCause = \"start\";\n\tlet lastParams: CompactionCycleParams | undefined;\n\tlet lastObservedTokens: number | undefined;\n\tlet appliedResult: CompactionResult | undefined;\n\tlet lastModelKey: string | undefined;\n\tlet ownTrailingCompactionId: string | undefined;\n\tlet ownTrailingCompactionNeedsRetry = false;\n\tlet baseKeepRecent = deps.getBaseKeepRecentTokens ? deps.getBaseKeepRecentTokens() : DEFAULT_KEEP_RECENT;\n\tif (!Number.isFinite(baseKeepRecent) || baseKeepRecent <= 0) {\n\t\tbaseKeepRecent = DEFAULT_KEEP_RECENT;\n\t}\n\n\tfor (let cycle = 1; cycle <= MAX_CYCLES; cycle++) {\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t}\n\n\t\tconst branch = deps.getBranch();\n\t\tconst trailingEntry = branch[branch.length - 1];\n\t\tif (branch.length > 0 && trailingEntry?.type === \"compaction\") {\n\t\t\tif (appliedResult && trailingEntry.id === ownTrailingCompactionId) {\n\t\t\t\tif (!ownTrailingCompactionNeedsRetry) return { kind: \"success\", result: appliedResult, cycles: cycle - 1 };\n\t\t\t} else {\n\t\t\t\treturn { kind: \"skip\", reason: \"already compacted\" };\n\t\t\t}\n\t\t}\n\n\t\tconst observedTokens = deps.measureLiveTokens();\n\t\tif (cycle === 1 && !deps.shouldCompact(observedTokens)) {\n\t\t\treturn {\n\t\t\t\tkind: \"skip\",\n\t\t\t\treason:\n\t\t\t\t\tbranch.length > 0 && branch[branch.length - 1]?.type === \"compaction\"\n\t\t\t\t\t\t? \"already compacted\"\n\t\t\t\t\t\t: \"within threshold\",\n\t\t\t};\n\t\t}\n\n\t\tconst selectedParams = selectCycleParams(cycle, lastCause, lastParams, baseKeepRecent);\n\t\tlet params = enforceMonotonicProgress(selectedParams, lastParams, observedTokens, lastObservedTokens, lastCause);\n\t\tlastObservedTokens = observedTokens;\n\n\t\tif (params.deterministicOnly || cycle > MAX_LLM_CYCLES) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst { result } = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\tawait deps.apply(result);\n\t\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t\t} catch (error) {\n\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(error).cause, cycles: cycle };\n\t\t\t}\n\t\t}\n\n\t\tlet modelInfo: ModelAndAuth;\n\t\ttry {\n\t\t\tmodelInfo = await deps.resolveModelAndAuth(params.modelTier);\n\t\t} catch {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tif (modelInfo.failure) {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tconst currentModelKey = modelKey(modelInfo.model);\n\t\tif (\n\t\t\t(lastCause === \"gate-failed\" || lastCause === \"length-stop\") &&\n\t\t\tlastParams &&\n\t\t\tparams.modelTier !== lastParams.modelTier &&\n\t\t\tlastModelKey === currentModelKey\n\t\t) {\n\t\t\tparams = { ...params, modelTier: lastParams.modelTier };\n\t\t}\n\t\tlastParams = params;\n\t\tlastModelKey = currentModelKey;\n\n\t\tlet result: CompactionResult;\n\t\ttry {\n\t\t\t({ result } = await deps.summarizeAndVerify(\n\t\t\t\tparams,\n\t\t\t\tmodelInfo.model,\n\t\t\t\tmodelInfo.apiKey,\n\t\t\t\tmodelInfo.headers,\n\t\t\t\tbranch,\n\t\t\t));\n\t\t} catch (error) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t\t}\n\t\t\tconst failure = mapFailureCause(error);\n\t\t\tlastCause = failure.cause;\n\t\t\tif (lastCause === \"aborted\") {\n\t\t\t\treturn { kind: \"failed\", reason: lastCause, cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"provider-failure\") {\n\t\t\t\treturn { kind: \"failed\", reason: error instanceof Error ? error.message : String(error), cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"deterministic-required\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst { result: deterministicResult } = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\t\tawait deps.apply(deterministicResult);\n\t\t\t\t\treturn { kind: \"success\", result: deterministicResult, cycles: cycle };\n\t\t\t\t} catch (deterministicError) {\n\t\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(deterministicError).cause, cycles: cycle };\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step3\", cause: lastCause, detail: failure.detail });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t}\n\t\tawait deps.apply(result);\n\t\tappliedResult = result;\n\t\tconst branchAfterApply = deps.getBranch();\n\t\tconst trailingAfterApply = branchAfterApply[branchAfterApply.length - 1];\n\t\townTrailingCompactionId = trailingAfterApply?.type === \"compaction\" ? trailingAfterApply.id : undefined;\n\n\t\tif (deps.verifyPostApplyEffect?.() === false) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\tconst measuredAfter = deps.measureLiveTokens();\n\t\tif (!deps.shouldCompact(measuredAfter + deps.getPostApplyMargin())) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\townTrailingCompactionNeedsRetry = true;\n\t\tlastCause = \"effect-not-restored\";\n\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step5\", cause: lastCause });\n\t}\n\n\treturn { kind: \"failed\", reason: \"exhausted-compaction-cycles\", cycles: MAX_CYCLES };\n}\n\nfunction selectCycleParams(\n\tcycle: number,\n\tcause: string,\n\tlastParams: CompactionCycleParams | undefined,\n\tbaseKeepRecent: number,\n): CompactionCycleParams {\n\tif (cycle >= MAX_CYCLES) {\n\t\treturn {\n\t\t\tmodelTier: lastParams?.modelTier ?? \"session\",\n\t\t\tkeepRecentTokens: Math.max(1, Math.floor((lastParams?.keepRecentTokens ?? baseKeepRecent) / 2)),\n\t\t\tchunked: true,\n\t\t\tdeterministicOnly: true,\n\t\t};\n\t}\n\n\tif (!lastParams) {\n\t\treturn {\n\t\t\tmodelTier: \"cheap\",\n\t\t\tkeepRecentTokens: Math.max(1, baseKeepRecent),\n\t\t\tchunked: false,\n\t\t\tdeterministicOnly: false,\n\t\t};\n\t}\n\n\tconst params: CompactionCycleParams = {\n\t\t...lastParams,\n\t\tdeterministicOnly: false,\n\t};\n\n\tif (cause === \"gate-failed\" || cause === \"auth-failed\" || cause === \"length-stop\") {\n\t\tparams.modelTier = \"session\";\n\t} else if (cause === \"input-overflow\") {\n\t\tparams.chunked = true;\n\t} else if (cause === \"effect-not-restored\") {\n\t\tparams.chunked = true;\n\t\tparams.keepRecentTokens = Math.max(1, Math.floor(lastParams.keepRecentTokens / 2));\n\t}\n\n\treturn params;\n}\n\nfunction enforceMonotonicProgress(\n\tparams: CompactionCycleParams,\n\tlastParams: CompactionCycleParams | undefined,\n\tobservedTokens: number,\n\tlastObservedTokens: number | undefined,\n\tlastCause: string,\n): CompactionCycleParams {\n\tif (\n\t\t!lastParams ||\n\t\tparams.deterministicOnly ||\n\t\t(lastObservedTokens !== undefined && observedTokens < lastObservedTokens)\n\t) {\n\t\treturn params;\n\t}\n\tif (!sameParams(params, lastParams)) {\n\t\treturn params;\n\t}\n\tif (lastCause === \"gate-failed\") {\n\t\treturn params;\n\t}\n\n\tconst keepRecentTokens = Math.max(1, Math.floor(params.keepRecentTokens / 2));\n\tif (keepRecentTokens !== params.keepRecentTokens) {\n\t\treturn { ...params, chunked: true, keepRecentTokens };\n\t}\n\tif (!params.chunked) {\n\t\treturn { ...params, chunked: true };\n\t}\n\treturn { ...params, modelTier: params.modelTier === \"cheap\" ? \"session\" : \"cheap\" };\n}\n\nfunction modelKey(model: Model<any>): string {\n\treturn `${model.provider}:${model.id}:${model.api}:${model.baseUrl ?? \"\"}`;\n}\n\nfunction sameParams(a: CompactionCycleParams, b: CompactionCycleParams): boolean {\n\treturn (\n\t\ta.modelTier === b.modelTier &&\n\t\ta.keepRecentTokens === b.keepRecentTokens &&\n\t\ta.chunked === b.chunked &&\n\t\ta.deterministicOnly === b.deterministicOnly\n\t);\n}\n\nfunction mapFailureCause(error: unknown): { cause: string; detail?: string } {\n\tconst message = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n\tif (message.includes(\"gate-failed\")) return { cause: \"gate-failed\", detail: boundedDetail(message) };\n\tif (message.includes(\"summary-demand-exceeds-reserve\"))\n\t\treturn { cause: \"deterministic-required\", detail: boundedDetail(message) };\n\tif (message.includes(\"input-overflow\")) return { cause: \"input-overflow\", detail: boundedDetail(message) };\n\t// A length-stopped summary lost gated sections; escalating the tier buys a larger output cap.\n\tif (message.includes(\"summary-length-stop\")) return { cause: \"length-stop\", detail: boundedDetail(message) };\n\tif (\n\t\t/stream stalled|overloaded|rate.?limit|too many requests|service.?unavailable|server.?error|network.?error|fetch failed|timeout|timed out/i.test(\n\t\t\tmessage,\n\t\t)\n\t)\n\t\treturn { cause: \"provider-failure\", detail: boundedDetail(message) };\n\tif (message.includes(\"auto-compaction-cancelled\")) return { cause: \"aborted\", detail: boundedDetail(message) };\n\tif (message.includes(\"auth\") || message.includes(\"api key\") || message.includes(\"not compacted\"))\n\t\treturn { cause: \"auth-failed\", detail: boundedDetail(message) };\n\treturn { cause: \"unknown-failure\", detail: boundedDetail(message) };\n}\n\nfunction boundedDetail(message: string): string | undefined {\n\tif (!message) return undefined;\n\treturn message.length > 500 ? `${message.slice(0, 500)}…` : message;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/compaction/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,KAAK,gBAAgB,EAAsC,MAAM,iBAAiB,CAAC;AAG5F,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,MAAM,CAAC;IAC7B,SAAS,IAAI,YAAY,EAAE,CAAC;IAC5B,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1F,kBAAkB,CACjB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IACzC,4BAA4B,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,GAAG;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC;IACrG,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtD,YAAY,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1F,uBAAuB,CAAC,IAAI,MAAM,CAAC;IACnC,qBAAqB,CAAC,IAAI,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMtD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAuJhG","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { SessionEntry } from \"../session/session-manager.ts\";\nimport { type CompactionResult, mergeCompactionVerificationReports } from \"./compaction.ts\";\nimport { CompactionVerificationError, type VerificationReport } from \"./verification.ts\";\n\nexport interface CompactionCycleParams {\n\tmodelTier: \"cheap\" | \"session\";\n\tkeepRecentTokens: number;\n\tchunked: boolean;\n\tdeterministicOnly: boolean;\n}\n\nexport interface ModelAndAuth {\n\tmodel: Model<any>;\n\tapiKey?: string;\n\theaders?: Record<string, string>;\n\tfailure?: string;\n}\n\nexport interface CompactionLoopDeps {\n\tmeasureLiveTokens(): number;\n\tshouldCompact(tokens: number): boolean;\n\tgetPostApplyMargin(): number;\n\tgetBranch(): SessionEntry[];\n\tresolveModelAndAuth(modelTier: CompactionCycleParams[\"modelTier\"]): Promise<ModelAndAuth>;\n\tsummarizeAndVerify(\n\t\tparams: CompactionCycleParams,\n\t\tmodel: Model<any>,\n\t\tapiKey: string | undefined,\n\t\theaders: Record<string, string> | undefined,\n\t\tbranch: SessionEntry[],\n\t): Promise<{ result: CompactionResult }>;\n\tbuildDeterministicCheckpoint(): Promise<{ result: CompactionResult }> | { result: CompactionResult };\n\tapply(result: CompactionResult): Promise<void> | void;\n\tonTransition(info: { cycle: number; from: string; cause: string; detail?: string }): void;\n\tgetBaseKeepRecentTokens?(): number;\n\tverifyPostApplyEffect?(): boolean;\n\tsignal?: AbortSignal;\n}\n\nexport type CompactionLoopOutcome =\n\t| { kind: \"success\"; result: CompactionResult; cycles: number }\n\t| { kind: \"skip\"; reason: string }\n\t| { kind: \"failed\"; reason: string; cycles: number };\n\nconst MAX_CYCLES = 4;\nconst MAX_LLM_CYCLES = 3;\nconst DEFAULT_KEEP_RECENT = 20_000;\n\nexport async function runCompactionLoop(deps: CompactionLoopDeps): Promise<CompactionLoopOutcome> {\n\tlet lastCause = \"start\";\n\tlet lastParams: CompactionCycleParams | undefined;\n\tlet lastObservedTokens: number | undefined;\n\tlet appliedResult: CompactionResult | undefined;\n\tlet lastModelKey: string | undefined;\n\tlet ownTrailingCompactionId: string | undefined;\n\tlet ownTrailingCompactionNeedsRetry = false;\n\tconst pendingVerificationReports: VerificationReport[] = [];\n\tlet baseKeepRecent = deps.getBaseKeepRecentTokens ? deps.getBaseKeepRecentTokens() : DEFAULT_KEEP_RECENT;\n\tif (!Number.isFinite(baseKeepRecent) || baseKeepRecent <= 0) {\n\t\tbaseKeepRecent = DEFAULT_KEEP_RECENT;\n\t}\n\n\tfor (let cycle = 1; cycle <= MAX_CYCLES; cycle++) {\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t}\n\n\t\tconst branch = deps.getBranch();\n\t\tconst trailingEntry = branch[branch.length - 1];\n\t\tif (branch.length > 0 && trailingEntry?.type === \"compaction\") {\n\t\t\tif (appliedResult && trailingEntry.id === ownTrailingCompactionId) {\n\t\t\t\tif (!ownTrailingCompactionNeedsRetry) return { kind: \"success\", result: appliedResult, cycles: cycle - 1 };\n\t\t\t} else {\n\t\t\t\treturn { kind: \"skip\", reason: \"already compacted\" };\n\t\t\t}\n\t\t}\n\n\t\tconst observedTokens = deps.measureLiveTokens();\n\t\tif (cycle === 1 && !deps.shouldCompact(observedTokens)) {\n\t\t\treturn {\n\t\t\t\tkind: \"skip\",\n\t\t\t\treason:\n\t\t\t\t\tbranch.length > 0 && branch[branch.length - 1]?.type === \"compaction\"\n\t\t\t\t\t\t? \"already compacted\"\n\t\t\t\t\t\t: \"within threshold\",\n\t\t\t};\n\t\t}\n\n\t\tconst selectedParams = selectCycleParams(cycle, lastCause, lastParams, baseKeepRecent);\n\t\tlet params = enforceMonotonicProgress(selectedParams, lastParams, observedTokens, lastObservedTokens, lastCause);\n\t\tlastObservedTokens = observedTokens;\n\n\t\tif (params.deterministicOnly || cycle > MAX_LLM_CYCLES) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst built = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\tconst result = mergeCompactionVerificationReports(built.result, pendingVerificationReports);\n\t\t\t\tpendingVerificationReports.length = 0;\n\t\t\t\tawait deps.apply(result);\n\t\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t\t} catch (error) {\n\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(error).cause, cycles: cycle };\n\t\t\t}\n\t\t}\n\n\t\tlet modelInfo: ModelAndAuth;\n\t\ttry {\n\t\t\tmodelInfo = await deps.resolveModelAndAuth(params.modelTier);\n\t\t} catch {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tif (modelInfo.failure) {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tconst currentModelKey = modelKey(modelInfo.model);\n\t\tif (\n\t\t\t(lastCause === \"gate-failed\" || lastCause === \"length-stop\") &&\n\t\t\tlastParams &&\n\t\t\tparams.modelTier !== lastParams.modelTier &&\n\t\t\tlastModelKey === currentModelKey\n\t\t) {\n\t\t\tparams = { ...params, modelTier: lastParams.modelTier };\n\t\t}\n\t\tlastParams = params;\n\t\tlastModelKey = currentModelKey;\n\n\t\tlet result: CompactionResult;\n\t\ttry {\n\t\t\t({ result } = await deps.summarizeAndVerify(\n\t\t\t\tparams,\n\t\t\t\tmodelInfo.model,\n\t\t\t\tmodelInfo.apiKey,\n\t\t\t\tmodelInfo.headers,\n\t\t\t\tbranch,\n\t\t\t));\n\t\t} catch (error) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t\t}\n\t\t\tif (error instanceof CompactionVerificationError) {\n\t\t\t\tpendingVerificationReports.push(...error.reports);\n\t\t\t}\n\t\t\tconst failure = mapFailureCause(error);\n\t\t\tlastCause = failure.cause;\n\t\t\tif (lastCause === \"aborted\") {\n\t\t\t\treturn { kind: \"failed\", reason: lastCause, cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"provider-failure\") {\n\t\t\t\treturn { kind: \"failed\", reason: error instanceof Error ? error.message : String(error), cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"deterministic-required\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst built = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\t\tconst deterministicResult = mergeCompactionVerificationReports(built.result, pendingVerificationReports);\n\t\t\t\t\tpendingVerificationReports.length = 0;\n\t\t\t\t\tawait deps.apply(deterministicResult);\n\t\t\t\t\treturn { kind: \"success\", result: deterministicResult, cycles: cycle };\n\t\t\t\t} catch (deterministicError) {\n\t\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(deterministicError).cause, cycles: cycle };\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step3\", cause: lastCause, detail: failure.detail });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t}\n\t\tmergeCompactionVerificationReports(result, pendingVerificationReports);\n\t\tpendingVerificationReports.length = 0;\n\t\tawait deps.apply(result);\n\t\tappliedResult = result;\n\t\tconst branchAfterApply = deps.getBranch();\n\t\tconst trailingAfterApply = branchAfterApply[branchAfterApply.length - 1];\n\t\townTrailingCompactionId = trailingAfterApply?.type === \"compaction\" ? trailingAfterApply.id : undefined;\n\n\t\tif (deps.verifyPostApplyEffect?.() === false) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\tconst measuredAfter = deps.measureLiveTokens();\n\t\tif (!deps.shouldCompact(measuredAfter + deps.getPostApplyMargin())) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\townTrailingCompactionNeedsRetry = true;\n\t\tlastCause = \"effect-not-restored\";\n\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step5\", cause: lastCause });\n\t}\n\n\treturn { kind: \"failed\", reason: \"exhausted-compaction-cycles\", cycles: MAX_CYCLES };\n}\n\nfunction selectCycleParams(\n\tcycle: number,\n\tcause: string,\n\tlastParams: CompactionCycleParams | undefined,\n\tbaseKeepRecent: number,\n): CompactionCycleParams {\n\tif (cycle >= MAX_CYCLES) {\n\t\treturn {\n\t\t\tmodelTier: lastParams?.modelTier ?? \"session\",\n\t\t\tkeepRecentTokens: Math.max(1, Math.floor((lastParams?.keepRecentTokens ?? baseKeepRecent) / 2)),\n\t\t\tchunked: true,\n\t\t\tdeterministicOnly: true,\n\t\t};\n\t}\n\n\tif (!lastParams) {\n\t\treturn {\n\t\t\tmodelTier: \"cheap\",\n\t\t\tkeepRecentTokens: Math.max(1, baseKeepRecent),\n\t\t\tchunked: false,\n\t\t\tdeterministicOnly: false,\n\t\t};\n\t}\n\n\tconst params: CompactionCycleParams = {\n\t\t...lastParams,\n\t\tdeterministicOnly: false,\n\t};\n\n\tif (cause === \"gate-failed\" || cause === \"auth-failed\" || cause === \"length-stop\") {\n\t\tparams.modelTier = \"session\";\n\t} else if (cause === \"input-overflow\") {\n\t\tparams.chunked = true;\n\t} else if (cause === \"effect-not-restored\") {\n\t\tparams.chunked = true;\n\t\tparams.keepRecentTokens = Math.max(1, Math.floor(lastParams.keepRecentTokens / 2));\n\t}\n\n\treturn params;\n}\n\nfunction enforceMonotonicProgress(\n\tparams: CompactionCycleParams,\n\tlastParams: CompactionCycleParams | undefined,\n\tobservedTokens: number,\n\tlastObservedTokens: number | undefined,\n\tlastCause: string,\n): CompactionCycleParams {\n\tif (\n\t\t!lastParams ||\n\t\tparams.deterministicOnly ||\n\t\t(lastObservedTokens !== undefined && observedTokens < lastObservedTokens)\n\t) {\n\t\treturn params;\n\t}\n\tif (!sameParams(params, lastParams)) {\n\t\treturn params;\n\t}\n\tif (lastCause === \"gate-failed\") {\n\t\treturn params;\n\t}\n\n\tconst keepRecentTokens = Math.max(1, Math.floor(params.keepRecentTokens / 2));\n\tif (keepRecentTokens !== params.keepRecentTokens) {\n\t\treturn { ...params, chunked: true, keepRecentTokens };\n\t}\n\tif (!params.chunked) {\n\t\treturn { ...params, chunked: true };\n\t}\n\treturn { ...params, modelTier: params.modelTier === \"cheap\" ? \"session\" : \"cheap\" };\n}\n\nfunction modelKey(model: Model<any>): string {\n\treturn `${model.provider}:${model.id}:${model.api}:${model.baseUrl ?? \"\"}`;\n}\n\nfunction sameParams(a: CompactionCycleParams, b: CompactionCycleParams): boolean {\n\treturn (\n\t\ta.modelTier === b.modelTier &&\n\t\ta.keepRecentTokens === b.keepRecentTokens &&\n\t\ta.chunked === b.chunked &&\n\t\ta.deterministicOnly === b.deterministicOnly\n\t);\n}\n\nfunction mapFailureCause(error: unknown): { cause: string; detail?: string } {\n\tconst message = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n\tif (message.includes(\"gate-failed\")) return { cause: \"gate-failed\", detail: boundedDetail(message) };\n\tif (message.includes(\"summary-demand-exceeds-reserve\"))\n\t\treturn { cause: \"deterministic-required\", detail: boundedDetail(message) };\n\tif (message.includes(\"input-overflow\")) return { cause: \"input-overflow\", detail: boundedDetail(message) };\n\t// A length-stopped summary lost gated sections; escalating the tier buys a larger output cap.\n\tif (message.includes(\"summary-length-stop\")) return { cause: \"length-stop\", detail: boundedDetail(message) };\n\tif (\n\t\t/stream stalled|overloaded|rate.?limit|too many requests|service.?unavailable|server.?error|network.?error|fetch failed|timeout|timed out/i.test(\n\t\t\tmessage,\n\t\t)\n\t)\n\t\treturn { cause: \"provider-failure\", detail: boundedDetail(message) };\n\tif (message.includes(\"auto-compaction-cancelled\")) return { cause: \"aborted\", detail: boundedDetail(message) };\n\tif (message.includes(\"auth\") || message.includes(\"api key\") || message.includes(\"not compacted\"))\n\t\treturn { cause: \"auth-failed\", detail: boundedDetail(message) };\n\treturn { cause: \"unknown-failure\", detail: boundedDetail(message) };\n}\n\nfunction boundedDetail(message: string): string | undefined {\n\tif (!message) return undefined;\n\treturn message.length > 500 ? `${message.slice(0, 500)}…` : message;\n}\n"]}
|
package/dist/compaction/loop.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { mergeCompactionVerificationReports } from "./compaction.js";
|
|
2
|
+
import { CompactionVerificationError } from "./verification.js";
|
|
1
3
|
const MAX_CYCLES = 4;
|
|
2
4
|
const MAX_LLM_CYCLES = 3;
|
|
3
5
|
const DEFAULT_KEEP_RECENT = 20_000;
|
|
@@ -9,6 +11,7 @@ export async function runCompactionLoop(deps) {
|
|
|
9
11
|
let lastModelKey;
|
|
10
12
|
let ownTrailingCompactionId;
|
|
11
13
|
let ownTrailingCompactionNeedsRetry = false;
|
|
14
|
+
const pendingVerificationReports = [];
|
|
12
15
|
let baseKeepRecent = deps.getBaseKeepRecentTokens ? deps.getBaseKeepRecentTokens() : DEFAULT_KEEP_RECENT;
|
|
13
16
|
if (!Number.isFinite(baseKeepRecent) || baseKeepRecent <= 0) {
|
|
14
17
|
baseKeepRecent = DEFAULT_KEEP_RECENT;
|
|
@@ -45,7 +48,9 @@ export async function runCompactionLoop(deps) {
|
|
|
45
48
|
return { kind: "failed", reason: "aborted", cycles: cycle - 1 };
|
|
46
49
|
}
|
|
47
50
|
try {
|
|
48
|
-
const
|
|
51
|
+
const built = await Promise.resolve(deps.buildDeterministicCheckpoint());
|
|
52
|
+
const result = mergeCompactionVerificationReports(built.result, pendingVerificationReports);
|
|
53
|
+
pendingVerificationReports.length = 0;
|
|
49
54
|
await deps.apply(result);
|
|
50
55
|
return { kind: "success", result, cycles: cycle };
|
|
51
56
|
}
|
|
@@ -84,6 +89,9 @@ export async function runCompactionLoop(deps) {
|
|
|
84
89
|
if (deps.signal?.aborted) {
|
|
85
90
|
return { kind: "failed", reason: "aborted", cycles: cycle };
|
|
86
91
|
}
|
|
92
|
+
if (error instanceof CompactionVerificationError) {
|
|
93
|
+
pendingVerificationReports.push(...error.reports);
|
|
94
|
+
}
|
|
87
95
|
const failure = mapFailureCause(error);
|
|
88
96
|
lastCause = failure.cause;
|
|
89
97
|
if (lastCause === "aborted") {
|
|
@@ -94,7 +102,9 @@ export async function runCompactionLoop(deps) {
|
|
|
94
102
|
}
|
|
95
103
|
if (lastCause === "deterministic-required") {
|
|
96
104
|
try {
|
|
97
|
-
const
|
|
105
|
+
const built = await Promise.resolve(deps.buildDeterministicCheckpoint());
|
|
106
|
+
const deterministicResult = mergeCompactionVerificationReports(built.result, pendingVerificationReports);
|
|
107
|
+
pendingVerificationReports.length = 0;
|
|
98
108
|
await deps.apply(deterministicResult);
|
|
99
109
|
return { kind: "success", result: deterministicResult, cycles: cycle };
|
|
100
110
|
}
|
|
@@ -108,6 +118,8 @@ export async function runCompactionLoop(deps) {
|
|
|
108
118
|
if (deps.signal?.aborted) {
|
|
109
119
|
return { kind: "failed", reason: "aborted", cycles: cycle };
|
|
110
120
|
}
|
|
121
|
+
mergeCompactionVerificationReports(result, pendingVerificationReports);
|
|
122
|
+
pendingVerificationReports.length = 0;
|
|
111
123
|
await deps.apply(result);
|
|
112
124
|
appliedResult = result;
|
|
113
125
|
const branchAfterApply = deps.getBranch();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/compaction/loop.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { SessionEntry } from \"../session/session-manager.ts\";\nimport type { CompactionResult } from \"./compaction.ts\";\n\nexport interface CompactionCycleParams {\n\tmodelTier: \"cheap\" | \"session\";\n\tkeepRecentTokens: number;\n\tchunked: boolean;\n\tdeterministicOnly: boolean;\n}\n\nexport interface ModelAndAuth {\n\tmodel: Model<any>;\n\tapiKey?: string;\n\theaders?: Record<string, string>;\n\tfailure?: string;\n}\n\nexport interface CompactionLoopDeps {\n\tmeasureLiveTokens(): number;\n\tshouldCompact(tokens: number): boolean;\n\tgetPostApplyMargin(): number;\n\tgetBranch(): SessionEntry[];\n\tresolveModelAndAuth(modelTier: CompactionCycleParams[\"modelTier\"]): Promise<ModelAndAuth>;\n\tsummarizeAndVerify(\n\t\tparams: CompactionCycleParams,\n\t\tmodel: Model<any>,\n\t\tapiKey: string | undefined,\n\t\theaders: Record<string, string> | undefined,\n\t\tbranch: SessionEntry[],\n\t): Promise<{ result: CompactionResult }>;\n\tbuildDeterministicCheckpoint(): Promise<{ result: CompactionResult }> | { result: CompactionResult };\n\tapply(result: CompactionResult): Promise<void> | void;\n\tonTransition(info: { cycle: number; from: string; cause: string; detail?: string }): void;\n\tgetBaseKeepRecentTokens?(): number;\n\tverifyPostApplyEffect?(): boolean;\n\tsignal?: AbortSignal;\n}\n\nexport type CompactionLoopOutcome =\n\t| { kind: \"success\"; result: CompactionResult; cycles: number }\n\t| { kind: \"skip\"; reason: string }\n\t| { kind: \"failed\"; reason: string; cycles: number };\n\nconst MAX_CYCLES = 4;\nconst MAX_LLM_CYCLES = 3;\nconst DEFAULT_KEEP_RECENT = 20_000;\n\nexport async function runCompactionLoop(deps: CompactionLoopDeps): Promise<CompactionLoopOutcome> {\n\tlet lastCause = \"start\";\n\tlet lastParams: CompactionCycleParams | undefined;\n\tlet lastObservedTokens: number | undefined;\n\tlet appliedResult: CompactionResult | undefined;\n\tlet lastModelKey: string | undefined;\n\tlet ownTrailingCompactionId: string | undefined;\n\tlet ownTrailingCompactionNeedsRetry = false;\n\tlet baseKeepRecent = deps.getBaseKeepRecentTokens ? deps.getBaseKeepRecentTokens() : DEFAULT_KEEP_RECENT;\n\tif (!Number.isFinite(baseKeepRecent) || baseKeepRecent <= 0) {\n\t\tbaseKeepRecent = DEFAULT_KEEP_RECENT;\n\t}\n\n\tfor (let cycle = 1; cycle <= MAX_CYCLES; cycle++) {\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t}\n\n\t\tconst branch = deps.getBranch();\n\t\tconst trailingEntry = branch[branch.length - 1];\n\t\tif (branch.length > 0 && trailingEntry?.type === \"compaction\") {\n\t\t\tif (appliedResult && trailingEntry.id === ownTrailingCompactionId) {\n\t\t\t\tif (!ownTrailingCompactionNeedsRetry) return { kind: \"success\", result: appliedResult, cycles: cycle - 1 };\n\t\t\t} else {\n\t\t\t\treturn { kind: \"skip\", reason: \"already compacted\" };\n\t\t\t}\n\t\t}\n\n\t\tconst observedTokens = deps.measureLiveTokens();\n\t\tif (cycle === 1 && !deps.shouldCompact(observedTokens)) {\n\t\t\treturn {\n\t\t\t\tkind: \"skip\",\n\t\t\t\treason:\n\t\t\t\t\tbranch.length > 0 && branch[branch.length - 1]?.type === \"compaction\"\n\t\t\t\t\t\t? \"already compacted\"\n\t\t\t\t\t\t: \"within threshold\",\n\t\t\t};\n\t\t}\n\n\t\tconst selectedParams = selectCycleParams(cycle, lastCause, lastParams, baseKeepRecent);\n\t\tlet params = enforceMonotonicProgress(selectedParams, lastParams, observedTokens, lastObservedTokens, lastCause);\n\t\tlastObservedTokens = observedTokens;\n\n\t\tif (params.deterministicOnly || cycle > MAX_LLM_CYCLES) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst { result } = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\tawait deps.apply(result);\n\t\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t\t} catch (error) {\n\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(error).cause, cycles: cycle };\n\t\t\t}\n\t\t}\n\n\t\tlet modelInfo: ModelAndAuth;\n\t\ttry {\n\t\t\tmodelInfo = await deps.resolveModelAndAuth(params.modelTier);\n\t\t} catch {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tif (modelInfo.failure) {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tconst currentModelKey = modelKey(modelInfo.model);\n\t\tif (\n\t\t\t(lastCause === \"gate-failed\" || lastCause === \"length-stop\") &&\n\t\t\tlastParams &&\n\t\t\tparams.modelTier !== lastParams.modelTier &&\n\t\t\tlastModelKey === currentModelKey\n\t\t) {\n\t\t\tparams = { ...params, modelTier: lastParams.modelTier };\n\t\t}\n\t\tlastParams = params;\n\t\tlastModelKey = currentModelKey;\n\n\t\tlet result: CompactionResult;\n\t\ttry {\n\t\t\t({ result } = await deps.summarizeAndVerify(\n\t\t\t\tparams,\n\t\t\t\tmodelInfo.model,\n\t\t\t\tmodelInfo.apiKey,\n\t\t\t\tmodelInfo.headers,\n\t\t\t\tbranch,\n\t\t\t));\n\t\t} catch (error) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t\t}\n\t\t\tconst failure = mapFailureCause(error);\n\t\t\tlastCause = failure.cause;\n\t\t\tif (lastCause === \"aborted\") {\n\t\t\t\treturn { kind: \"failed\", reason: lastCause, cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"provider-failure\") {\n\t\t\t\treturn { kind: \"failed\", reason: error instanceof Error ? error.message : String(error), cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"deterministic-required\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst { result: deterministicResult } = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\t\tawait deps.apply(deterministicResult);\n\t\t\t\t\treturn { kind: \"success\", result: deterministicResult, cycles: cycle };\n\t\t\t\t} catch (deterministicError) {\n\t\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(deterministicError).cause, cycles: cycle };\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step3\", cause: lastCause, detail: failure.detail });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t}\n\t\tawait deps.apply(result);\n\t\tappliedResult = result;\n\t\tconst branchAfterApply = deps.getBranch();\n\t\tconst trailingAfterApply = branchAfterApply[branchAfterApply.length - 1];\n\t\townTrailingCompactionId = trailingAfterApply?.type === \"compaction\" ? trailingAfterApply.id : undefined;\n\n\t\tif (deps.verifyPostApplyEffect?.() === false) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\tconst measuredAfter = deps.measureLiveTokens();\n\t\tif (!deps.shouldCompact(measuredAfter + deps.getPostApplyMargin())) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\townTrailingCompactionNeedsRetry = true;\n\t\tlastCause = \"effect-not-restored\";\n\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step5\", cause: lastCause });\n\t}\n\n\treturn { kind: \"failed\", reason: \"exhausted-compaction-cycles\", cycles: MAX_CYCLES };\n}\n\nfunction selectCycleParams(\n\tcycle: number,\n\tcause: string,\n\tlastParams: CompactionCycleParams | undefined,\n\tbaseKeepRecent: number,\n): CompactionCycleParams {\n\tif (cycle >= MAX_CYCLES) {\n\t\treturn {\n\t\t\tmodelTier: lastParams?.modelTier ?? \"session\",\n\t\t\tkeepRecentTokens: Math.max(1, Math.floor((lastParams?.keepRecentTokens ?? baseKeepRecent) / 2)),\n\t\t\tchunked: true,\n\t\t\tdeterministicOnly: true,\n\t\t};\n\t}\n\n\tif (!lastParams) {\n\t\treturn {\n\t\t\tmodelTier: \"cheap\",\n\t\t\tkeepRecentTokens: Math.max(1, baseKeepRecent),\n\t\t\tchunked: false,\n\t\t\tdeterministicOnly: false,\n\t\t};\n\t}\n\n\tconst params: CompactionCycleParams = {\n\t\t...lastParams,\n\t\tdeterministicOnly: false,\n\t};\n\n\tif (cause === \"gate-failed\" || cause === \"auth-failed\" || cause === \"length-stop\") {\n\t\tparams.modelTier = \"session\";\n\t} else if (cause === \"input-overflow\") {\n\t\tparams.chunked = true;\n\t} else if (cause === \"effect-not-restored\") {\n\t\tparams.chunked = true;\n\t\tparams.keepRecentTokens = Math.max(1, Math.floor(lastParams.keepRecentTokens / 2));\n\t}\n\n\treturn params;\n}\n\nfunction enforceMonotonicProgress(\n\tparams: CompactionCycleParams,\n\tlastParams: CompactionCycleParams | undefined,\n\tobservedTokens: number,\n\tlastObservedTokens: number | undefined,\n\tlastCause: string,\n): CompactionCycleParams {\n\tif (\n\t\t!lastParams ||\n\t\tparams.deterministicOnly ||\n\t\t(lastObservedTokens !== undefined && observedTokens < lastObservedTokens)\n\t) {\n\t\treturn params;\n\t}\n\tif (!sameParams(params, lastParams)) {\n\t\treturn params;\n\t}\n\tif (lastCause === \"gate-failed\") {\n\t\treturn params;\n\t}\n\n\tconst keepRecentTokens = Math.max(1, Math.floor(params.keepRecentTokens / 2));\n\tif (keepRecentTokens !== params.keepRecentTokens) {\n\t\treturn { ...params, chunked: true, keepRecentTokens };\n\t}\n\tif (!params.chunked) {\n\t\treturn { ...params, chunked: true };\n\t}\n\treturn { ...params, modelTier: params.modelTier === \"cheap\" ? \"session\" : \"cheap\" };\n}\n\nfunction modelKey(model: Model<any>): string {\n\treturn `${model.provider}:${model.id}:${model.api}:${model.baseUrl ?? \"\"}`;\n}\n\nfunction sameParams(a: CompactionCycleParams, b: CompactionCycleParams): boolean {\n\treturn (\n\t\ta.modelTier === b.modelTier &&\n\t\ta.keepRecentTokens === b.keepRecentTokens &&\n\t\ta.chunked === b.chunked &&\n\t\ta.deterministicOnly === b.deterministicOnly\n\t);\n}\n\nfunction mapFailureCause(error: unknown): { cause: string; detail?: string } {\n\tconst message = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n\tif (message.includes(\"gate-failed\")) return { cause: \"gate-failed\", detail: boundedDetail(message) };\n\tif (message.includes(\"summary-demand-exceeds-reserve\"))\n\t\treturn { cause: \"deterministic-required\", detail: boundedDetail(message) };\n\tif (message.includes(\"input-overflow\")) return { cause: \"input-overflow\", detail: boundedDetail(message) };\n\t// A length-stopped summary lost gated sections; escalating the tier buys a larger output cap.\n\tif (message.includes(\"summary-length-stop\")) return { cause: \"length-stop\", detail: boundedDetail(message) };\n\tif (\n\t\t/stream stalled|overloaded|rate.?limit|too many requests|service.?unavailable|server.?error|network.?error|fetch failed|timeout|timed out/i.test(\n\t\t\tmessage,\n\t\t)\n\t)\n\t\treturn { cause: \"provider-failure\", detail: boundedDetail(message) };\n\tif (message.includes(\"auto-compaction-cancelled\")) return { cause: \"aborted\", detail: boundedDetail(message) };\n\tif (message.includes(\"auth\") || message.includes(\"api key\") || message.includes(\"not compacted\"))\n\t\treturn { cause: \"auth-failed\", detail: boundedDetail(message) };\n\treturn { cause: \"unknown-failure\", detail: boundedDetail(message) };\n}\n\nfunction boundedDetail(message: string): string | undefined {\n\tif (!message) return undefined;\n\treturn message.length > 500 ? `${message.slice(0, 500)}…` : message;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/compaction/loop.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { SessionEntry } from \"../session/session-manager.ts\";\nimport { type CompactionResult, mergeCompactionVerificationReports } from \"./compaction.ts\";\nimport { CompactionVerificationError, type VerificationReport } from \"./verification.ts\";\n\nexport interface CompactionCycleParams {\n\tmodelTier: \"cheap\" | \"session\";\n\tkeepRecentTokens: number;\n\tchunked: boolean;\n\tdeterministicOnly: boolean;\n}\n\nexport interface ModelAndAuth {\n\tmodel: Model<any>;\n\tapiKey?: string;\n\theaders?: Record<string, string>;\n\tfailure?: string;\n}\n\nexport interface CompactionLoopDeps {\n\tmeasureLiveTokens(): number;\n\tshouldCompact(tokens: number): boolean;\n\tgetPostApplyMargin(): number;\n\tgetBranch(): SessionEntry[];\n\tresolveModelAndAuth(modelTier: CompactionCycleParams[\"modelTier\"]): Promise<ModelAndAuth>;\n\tsummarizeAndVerify(\n\t\tparams: CompactionCycleParams,\n\t\tmodel: Model<any>,\n\t\tapiKey: string | undefined,\n\t\theaders: Record<string, string> | undefined,\n\t\tbranch: SessionEntry[],\n\t): Promise<{ result: CompactionResult }>;\n\tbuildDeterministicCheckpoint(): Promise<{ result: CompactionResult }> | { result: CompactionResult };\n\tapply(result: CompactionResult): Promise<void> | void;\n\tonTransition(info: { cycle: number; from: string; cause: string; detail?: string }): void;\n\tgetBaseKeepRecentTokens?(): number;\n\tverifyPostApplyEffect?(): boolean;\n\tsignal?: AbortSignal;\n}\n\nexport type CompactionLoopOutcome =\n\t| { kind: \"success\"; result: CompactionResult; cycles: number }\n\t| { kind: \"skip\"; reason: string }\n\t| { kind: \"failed\"; reason: string; cycles: number };\n\nconst MAX_CYCLES = 4;\nconst MAX_LLM_CYCLES = 3;\nconst DEFAULT_KEEP_RECENT = 20_000;\n\nexport async function runCompactionLoop(deps: CompactionLoopDeps): Promise<CompactionLoopOutcome> {\n\tlet lastCause = \"start\";\n\tlet lastParams: CompactionCycleParams | undefined;\n\tlet lastObservedTokens: number | undefined;\n\tlet appliedResult: CompactionResult | undefined;\n\tlet lastModelKey: string | undefined;\n\tlet ownTrailingCompactionId: string | undefined;\n\tlet ownTrailingCompactionNeedsRetry = false;\n\tconst pendingVerificationReports: VerificationReport[] = [];\n\tlet baseKeepRecent = deps.getBaseKeepRecentTokens ? deps.getBaseKeepRecentTokens() : DEFAULT_KEEP_RECENT;\n\tif (!Number.isFinite(baseKeepRecent) || baseKeepRecent <= 0) {\n\t\tbaseKeepRecent = DEFAULT_KEEP_RECENT;\n\t}\n\n\tfor (let cycle = 1; cycle <= MAX_CYCLES; cycle++) {\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t}\n\n\t\tconst branch = deps.getBranch();\n\t\tconst trailingEntry = branch[branch.length - 1];\n\t\tif (branch.length > 0 && trailingEntry?.type === \"compaction\") {\n\t\t\tif (appliedResult && trailingEntry.id === ownTrailingCompactionId) {\n\t\t\t\tif (!ownTrailingCompactionNeedsRetry) return { kind: \"success\", result: appliedResult, cycles: cycle - 1 };\n\t\t\t} else {\n\t\t\t\treturn { kind: \"skip\", reason: \"already compacted\" };\n\t\t\t}\n\t\t}\n\n\t\tconst observedTokens = deps.measureLiveTokens();\n\t\tif (cycle === 1 && !deps.shouldCompact(observedTokens)) {\n\t\t\treturn {\n\t\t\t\tkind: \"skip\",\n\t\t\t\treason:\n\t\t\t\t\tbranch.length > 0 && branch[branch.length - 1]?.type === \"compaction\"\n\t\t\t\t\t\t? \"already compacted\"\n\t\t\t\t\t\t: \"within threshold\",\n\t\t\t};\n\t\t}\n\n\t\tconst selectedParams = selectCycleParams(cycle, lastCause, lastParams, baseKeepRecent);\n\t\tlet params = enforceMonotonicProgress(selectedParams, lastParams, observedTokens, lastObservedTokens, lastCause);\n\t\tlastObservedTokens = observedTokens;\n\n\t\tif (params.deterministicOnly || cycle > MAX_LLM_CYCLES) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle - 1 };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst built = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\tconst result = mergeCompactionVerificationReports(built.result, pendingVerificationReports);\n\t\t\t\tpendingVerificationReports.length = 0;\n\t\t\t\tawait deps.apply(result);\n\t\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t\t} catch (error) {\n\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(error).cause, cycles: cycle };\n\t\t\t}\n\t\t}\n\n\t\tlet modelInfo: ModelAndAuth;\n\t\ttry {\n\t\t\tmodelInfo = await deps.resolveModelAndAuth(params.modelTier);\n\t\t} catch {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tif (modelInfo.failure) {\n\t\t\tlastCause = \"auth-failed\";\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step0\", cause: lastCause });\n\t\t\tcontinue;\n\t\t}\n\t\tconst currentModelKey = modelKey(modelInfo.model);\n\t\tif (\n\t\t\t(lastCause === \"gate-failed\" || lastCause === \"length-stop\") &&\n\t\t\tlastParams &&\n\t\t\tparams.modelTier !== lastParams.modelTier &&\n\t\t\tlastModelKey === currentModelKey\n\t\t) {\n\t\t\tparams = { ...params, modelTier: lastParams.modelTier };\n\t\t}\n\t\tlastParams = params;\n\t\tlastModelKey = currentModelKey;\n\n\t\tlet result: CompactionResult;\n\t\ttry {\n\t\t\t({ result } = await deps.summarizeAndVerify(\n\t\t\t\tparams,\n\t\t\t\tmodelInfo.model,\n\t\t\t\tmodelInfo.apiKey,\n\t\t\t\tmodelInfo.headers,\n\t\t\t\tbranch,\n\t\t\t));\n\t\t} catch (error) {\n\t\t\tif (deps.signal?.aborted) {\n\t\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t\t}\n\t\t\tif (error instanceof CompactionVerificationError) {\n\t\t\t\tpendingVerificationReports.push(...error.reports);\n\t\t\t}\n\t\t\tconst failure = mapFailureCause(error);\n\t\t\tlastCause = failure.cause;\n\t\t\tif (lastCause === \"aborted\") {\n\t\t\t\treturn { kind: \"failed\", reason: lastCause, cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"provider-failure\") {\n\t\t\t\treturn { kind: \"failed\", reason: error instanceof Error ? error.message : String(error), cycles: cycle };\n\t\t\t}\n\t\t\tif (lastCause === \"deterministic-required\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst built = await Promise.resolve(deps.buildDeterministicCheckpoint());\n\t\t\t\t\tconst deterministicResult = mergeCompactionVerificationReports(built.result, pendingVerificationReports);\n\t\t\t\t\tpendingVerificationReports.length = 0;\n\t\t\t\t\tawait deps.apply(deterministicResult);\n\t\t\t\t\treturn { kind: \"success\", result: deterministicResult, cycles: cycle };\n\t\t\t\t} catch (deterministicError) {\n\t\t\t\t\treturn { kind: \"failed\", reason: mapFailureCause(deterministicError).cause, cycles: cycle };\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step3\", cause: lastCause, detail: failure.detail });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (deps.signal?.aborted) {\n\t\t\treturn { kind: \"failed\", reason: \"aborted\", cycles: cycle };\n\t\t}\n\t\tmergeCompactionVerificationReports(result, pendingVerificationReports);\n\t\tpendingVerificationReports.length = 0;\n\t\tawait deps.apply(result);\n\t\tappliedResult = result;\n\t\tconst branchAfterApply = deps.getBranch();\n\t\tconst trailingAfterApply = branchAfterApply[branchAfterApply.length - 1];\n\t\townTrailingCompactionId = trailingAfterApply?.type === \"compaction\" ? trailingAfterApply.id : undefined;\n\n\t\tif (deps.verifyPostApplyEffect?.() === false) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\tconst measuredAfter = deps.measureLiveTokens();\n\t\tif (!deps.shouldCompact(measuredAfter + deps.getPostApplyMargin())) {\n\t\t\townTrailingCompactionNeedsRetry = false;\n\t\t\treturn { kind: \"success\", result, cycles: cycle };\n\t\t}\n\n\t\townTrailingCompactionNeedsRetry = true;\n\t\tlastCause = \"effect-not-restored\";\n\t\tdeps.onTransition({ cycle: cycle + 1, from: \"step5\", cause: lastCause });\n\t}\n\n\treturn { kind: \"failed\", reason: \"exhausted-compaction-cycles\", cycles: MAX_CYCLES };\n}\n\nfunction selectCycleParams(\n\tcycle: number,\n\tcause: string,\n\tlastParams: CompactionCycleParams | undefined,\n\tbaseKeepRecent: number,\n): CompactionCycleParams {\n\tif (cycle >= MAX_CYCLES) {\n\t\treturn {\n\t\t\tmodelTier: lastParams?.modelTier ?? \"session\",\n\t\t\tkeepRecentTokens: Math.max(1, Math.floor((lastParams?.keepRecentTokens ?? baseKeepRecent) / 2)),\n\t\t\tchunked: true,\n\t\t\tdeterministicOnly: true,\n\t\t};\n\t}\n\n\tif (!lastParams) {\n\t\treturn {\n\t\t\tmodelTier: \"cheap\",\n\t\t\tkeepRecentTokens: Math.max(1, baseKeepRecent),\n\t\t\tchunked: false,\n\t\t\tdeterministicOnly: false,\n\t\t};\n\t}\n\n\tconst params: CompactionCycleParams = {\n\t\t...lastParams,\n\t\tdeterministicOnly: false,\n\t};\n\n\tif (cause === \"gate-failed\" || cause === \"auth-failed\" || cause === \"length-stop\") {\n\t\tparams.modelTier = \"session\";\n\t} else if (cause === \"input-overflow\") {\n\t\tparams.chunked = true;\n\t} else if (cause === \"effect-not-restored\") {\n\t\tparams.chunked = true;\n\t\tparams.keepRecentTokens = Math.max(1, Math.floor(lastParams.keepRecentTokens / 2));\n\t}\n\n\treturn params;\n}\n\nfunction enforceMonotonicProgress(\n\tparams: CompactionCycleParams,\n\tlastParams: CompactionCycleParams | undefined,\n\tobservedTokens: number,\n\tlastObservedTokens: number | undefined,\n\tlastCause: string,\n): CompactionCycleParams {\n\tif (\n\t\t!lastParams ||\n\t\tparams.deterministicOnly ||\n\t\t(lastObservedTokens !== undefined && observedTokens < lastObservedTokens)\n\t) {\n\t\treturn params;\n\t}\n\tif (!sameParams(params, lastParams)) {\n\t\treturn params;\n\t}\n\tif (lastCause === \"gate-failed\") {\n\t\treturn params;\n\t}\n\n\tconst keepRecentTokens = Math.max(1, Math.floor(params.keepRecentTokens / 2));\n\tif (keepRecentTokens !== params.keepRecentTokens) {\n\t\treturn { ...params, chunked: true, keepRecentTokens };\n\t}\n\tif (!params.chunked) {\n\t\treturn { ...params, chunked: true };\n\t}\n\treturn { ...params, modelTier: params.modelTier === \"cheap\" ? \"session\" : \"cheap\" };\n}\n\nfunction modelKey(model: Model<any>): string {\n\treturn `${model.provider}:${model.id}:${model.api}:${model.baseUrl ?? \"\"}`;\n}\n\nfunction sameParams(a: CompactionCycleParams, b: CompactionCycleParams): boolean {\n\treturn (\n\t\ta.modelTier === b.modelTier &&\n\t\ta.keepRecentTokens === b.keepRecentTokens &&\n\t\ta.chunked === b.chunked &&\n\t\ta.deterministicOnly === b.deterministicOnly\n\t);\n}\n\nfunction mapFailureCause(error: unknown): { cause: string; detail?: string } {\n\tconst message = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n\tif (message.includes(\"gate-failed\")) return { cause: \"gate-failed\", detail: boundedDetail(message) };\n\tif (message.includes(\"summary-demand-exceeds-reserve\"))\n\t\treturn { cause: \"deterministic-required\", detail: boundedDetail(message) };\n\tif (message.includes(\"input-overflow\")) return { cause: \"input-overflow\", detail: boundedDetail(message) };\n\t// A length-stopped summary lost gated sections; escalating the tier buys a larger output cap.\n\tif (message.includes(\"summary-length-stop\")) return { cause: \"length-stop\", detail: boundedDetail(message) };\n\tif (\n\t\t/stream stalled|overloaded|rate.?limit|too many requests|service.?unavailable|server.?error|network.?error|fetch failed|timeout|timed out/i.test(\n\t\t\tmessage,\n\t\t)\n\t)\n\t\treturn { cause: \"provider-failure\", detail: boundedDetail(message) };\n\tif (message.includes(\"auto-compaction-cancelled\")) return { cause: \"aborted\", detail: boundedDetail(message) };\n\tif (message.includes(\"auth\") || message.includes(\"api key\") || message.includes(\"not compacted\"))\n\t\treturn { cause: \"auth-failed\", detail: boundedDetail(message) };\n\treturn { cause: \"unknown-failure\", detail: boundedDetail(message) };\n}\n\nfunction boundedDetail(message: string): string | undefined {\n\tif (!message) return undefined;\n\treturn message.length > 500 ? `${message.slice(0, 500)}…` : message;\n}\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"]}
|