{
  "_comment": "Copy to longhaul.json in pi's agent dir (~/.pi/agent, or PI_CODING_AGENT_DIR). Every key is optional; the defaults are in config.ts. model (omitted here on purpose): provider/model-id to route the narrative call off the session's own model; unset, every session summarizes on its own model, and PI_COMPACT_STATE_MODEL overrides for one invocation. routeProviders: provider names, matched exactly, whose sessions may use that route; every other session summarizes on its own model (none by default, so a model alone routes nothing). localOnlyRoots: directories (absolute, or ~/...; on Windows C:\\... or ~\\... too) whose sessions, and their subdirectories', never use the route, so their conversation stays on the session's own model; only PI_COMPACT_STATE_MODEL beats it, and an entry that cannot match warns. summarizerHeaders: {provider: {header: template}} added to the compaction's own model calls, which pi's before_provider_headers event never sees (e.g. a session-affinity header for a provider that routes by it); {sessionId} is the pi session id, a header the provider already sets wins, empty by default. keptWindowThinking (omitted here on purpose): unset, the kept window's old thinking is left out of requests only on APIs where that is verified (openai-completions); \"keep\" never strips; \"strip\" strips on any API, leaving an active tool turn whole where the API needs its thinking back. caps: hard cap on the rendered state and per-section caps. claimPatterns: leading-token patterns that turn a ledger command into a World claim. rememberPerSpan: accepted longhaul_remember writes per span. coldSliceCaps: command/error records kept per span record. nearDuplicateThreshold: token overlap at or above which a new item is a duplicate. narrativePolicy: retries, chunking, the output budget and the per-request timeout of the narrative call. narrativeMode: single (one diff call) or turns (one section per turn, opt-in); the turns tuning block narrativeTurns is experimental, not part of the versioning contract, and left out here.",
  "routeProviders": [],
  "localOnlyRoots": [],
  "summarizerHeaders": {},
  "caps": { "hardChars": 13500, "objectiveQuoteChars": 600, "corrections": 8, "correctionChars": 300, "decisions": 10, "deadEnds": 10, "itemChars": 300, "workLogLines": 12, "openErrors": 5, "worldChars": 1200, "filesChars": 2500, "learnedChars": 1500 },
  "claimPatterns": [
    { "pattern": "npm test", "kind": "test" }, { "pattern": "node --test", "kind": "test" }, { "pattern": "go test", "kind": "test" },
    { "pattern": "pytest", "kind": "test" }, { "pattern": "cargo test", "kind": "test" }, { "pattern": "make test", "kind": "test" },
    { "pattern": "make check", "kind": "test" }, { "pattern": "cargo build", "kind": "build" }, { "pattern": "make build", "kind": "build" },
    { "pattern": "npm run build", "kind": "build" }, { "pattern": "tsc", "kind": "build" }, { "pattern": "make lint", "kind": "lint" },
    { "pattern": "golangci-lint", "kind": "lint" }, { "pattern": "npm run lint", "kind": "lint" }
  ],
  "rememberPerSpan": 10,
  "coldSliceCaps": { "commands": 200, "errors": 50, "commandChars": 300 },
  "nearDuplicateThreshold": 0.8,
  "narrativePolicy": { "fixableRetries": 1, "maxChunks": 4, "retryNoteChars": 1500, "outputTokens": 3000, "timeoutMs": 1800000 },
  "narrativeMode": "single",
  "routeFailureThreshold": 1,
  "routeCooldownMs": 1800000,
  "routeMaxRetries": 0
}
