import type { ExtensionFactory } from "@earendil-works/pi-coding-agent"; /** * Structured Forge facts extracted from messagesToSummarize. * All fields are arrays of strings for serialization into the compaction summary. */ export interface ForgeFactSummary { /** FORGE-X-Y / FORGE-X-Y-TN patterns extracted from message text. */ storeIds: string[]; /** Lines containing [x] or [ ] checkbox patterns (Markdown task lists). */ acStateLines: string[]; /** Lines matching → or update-status ... status . */ transitionLines: string[]; /** File refs: engineering/, .forge/, *.ts/*.md/*.cjs/*.json paths. */ fileRefs: string[]; /** Text blocks containing [FRICTION] or type:friction. */ frictionBlocks: string[]; } /** * Options for buildForgeCompactionFactory. */ export interface ForgeCompactionOptions { /** * Absolute path to the project CWD (for warm-tier summary file lookup). * When omitted, warm-tier merge is skipped unless summaryReader is provided. */ cwd?: string; /** * Phase key for summary filename resolution (e.g. "architect/plan"). * When omitted, warm-tier merge is skipped. */ phaseKey?: string; /** * Task/entity ID for summary path resolution (e.g. "FORGE-S30-T09"). * When omitted, warm-tier merge is skipped. */ entityId?: string; /** * Sprint ID for summary path resolution (e.g. "FORGE-S30"). * When omitted, warm-tier merge is skipped. */ sprintId?: string; /** * Injected summary reader (test seam). Receives the resolved summary * file path (empty string when path resolution is skipped) and returns * the raw JSON string or null. Defaults to fs.readFileSync. * Must not throw — return null on any failure. */ summaryReader?: (filePath: string) => string | null; } /** * Extract structured Forge facts from an array of message-like objects. * * Pure function — no fs I/O, no LLM calls, provider-neutral. * Accepts any array (unknown[]) to be safe against varying pi message shapes. * Text content is extracted from `.content[].text` (assistant messages) * and from direct string entries. * * @param messagesToSummarize Array of message-like objects from preparation. * @param extractOpts Optional project-config parameters (FORGE-BUG-043 PR 2): * prefix (store-ID prefix, default "FORGE") and * engineeringPath (file-ref directory, default "engineering"). * Omitting them preserves the historical behaviour exactly. * @returns ForgeFactSummary with all extracted patterns. */ export declare function extractForgeFacts(messagesToSummarize: unknown[], extractOpts?: { prefix?: string; engineeringPath?: string; }): ForgeFactSummary; /** * Build an ExtensionFactory that registers a session_before_compact handler * returning a deterministically-composed CompactionResult. * * The handler: * 1. Validates that event.preparation is present and well-formed. * 2. Extracts Forge facts from event.preparation.messagesToSummarize * (no LLM call, provider-neutral). * 3. Reads the warm-tier {PHASE}-SUMMARY.json if opts provide path context, * or invokes opts.summaryReader("") as a test seam. * 4. Assembles a compact structured summary string. * 5. Returns { compaction: { summary, firstKeptEntryId, tokensBefore } }. * 6. Returns undefined on any error (IL7 — lets pi compact normally). * * Pack 07: reads summary files but never writes .forge/store/. * IL10: no pi-mono edits, no dispatch contract changes. * Wired per-phase by run-task.ts via RunSubagentOptions.extensionFactories. * * Project config (store-ID prefix, paths.engineering) is loaded ONCE here at * factory construction from `/.forge/config.json` — never per * compaction event. Without cwd the historical defaults apply (FORGE-BUG-043 PR 2). * * @param opts ForgeCompactionOptions (default: empty — no warm-tier). * @returns ExtensionFactory for passing to DefaultResourceLoader.extensionFactories. */ export declare function buildForgeCompactionFactory(opts?: ForgeCompactionOptions): ExtensionFactory;