@caupulican/pi-adaptative 0.81.2 → 0.81.4
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/CHANGELOG.md +32 -0
- package/dist/core/agent-session.d.ts +2 -23
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +139 -147
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +2 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +3 -0
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/billing-failover-controller.d.ts +38 -0
- package/dist/core/billing-failover-controller.d.ts.map +1 -0
- package/dist/core/billing-failover-controller.js +78 -0
- package/dist/core/billing-failover-controller.js.map +1 -0
- package/dist/core/billing-failover.d.ts +25 -0
- package/dist/core/billing-failover.d.ts.map +1 -0
- package/dist/core/billing-failover.js +21 -0
- package/dist/core/billing-failover.js.map +1 -0
- package/dist/core/compaction-support.d.ts +10 -1
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +68 -9
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +1 -0
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +51 -14
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +9 -9
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/failure-corpus.d.ts +49 -0
- package/dist/core/failure-corpus.d.ts.map +1 -0
- package/dist/core/failure-corpus.js +61 -0
- package/dist/core/failure-corpus.js.map +1 -0
- package/dist/core/model-router/config-diagnostics.d.ts +1 -1
- package/dist/core/model-router/config-diagnostics.d.ts.map +1 -1
- package/dist/core/model-router/config-diagnostics.js +29 -1
- package/dist/core/model-router/config-diagnostics.js.map +1 -1
- package/dist/core/model-router/fitness-gate.d.ts +25 -0
- package/dist/core/model-router/fitness-gate.d.ts.map +1 -0
- package/dist/core/model-router/fitness-gate.js +34 -0
- package/dist/core/model-router/fitness-gate.js.map +1 -0
- package/dist/core/model-router/status.d.ts +29 -1
- package/dist/core/model-router/status.d.ts.map +1 -1
- package/dist/core/model-router/status.js +31 -4
- package/dist/core/model-router/status.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +10 -1
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +110 -27
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
- package/dist/core/models/default-model-suggestions.js +18 -0
- package/dist/core/models/default-model-suggestions.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +16 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +88 -1
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +44 -0
- package/dist/core/scout-controller.d.ts.map +1 -0
- package/dist/core/scout-controller.js +165 -0
- package/dist/core/scout-controller.js.map +1 -0
- package/dist/core/settings-manager.d.ts +17 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +47 -3
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +6 -8
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/context-scout.d.ts +19 -0
- package/dist/core/tools/context-scout.d.ts.map +1 -0
- package/dist/core/tools/context-scout.js +47 -0
- package/dist/core/tools/context-scout.js.map +1 -0
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.js +5 -0
- package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +77 -7
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +13 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts +5 -2
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +129 -1
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +16 -0
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +32 -0
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/docs/bug-ledger.md +113 -0
- package/docs/index.md +1 -0
- package/docs/models.md +9 -0
- package/docs/providers.md +14 -0
- package/docs/scout.md +73 -0
- package/docs/settings.md +16 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Bug Ledger — pi-adaptative (SHARED · Claude + agy + codex)
|
|
2
|
+
|
|
3
|
+
**Standing rule (Cau, mandatory):** while reviewing, building, or hunting ANYTHING, if you find a bug —
|
|
4
|
+
**even one unrelated to the task at hand or to what was asked** — you MUST log it here. Never discard it,
|
|
5
|
+
never stay silent, never "fix-and-forget" without recording it. Drive-by discoveries count. Unrelated
|
|
6
|
+
counts. If unsure whether it's a bug, log it as `suspected`.
|
|
7
|
+
|
|
8
|
+
Unversioned (`.git/info/exclude`) working doc. One row per bug. Keep it append-only except for status
|
|
9
|
+
updates. Sign the "Found by" column.
|
|
10
|
+
|
|
11
|
+
## Severity
|
|
12
|
+
- **critical** — data loss, crash/hang, security, or breaks a core flow (boot, shutdown, send/receive).
|
|
13
|
+
- **high** — wrong behavior on a common path; silent incorrect results.
|
|
14
|
+
- **medium** — wrong behavior on an edge/uncommon path; degraded UX.
|
|
15
|
+
- **low** — cosmetic, minor, or theoretical.
|
|
16
|
+
|
|
17
|
+
## Status
|
|
18
|
+
`open` · `investigating` · `fix-proposed` · `fixed` · `wontfix (with reason)` · `not-a-bug (with reason)`
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Ledger
|
|
23
|
+
|
|
24
|
+
| # | Severity | Area | Location (file:line) | Description | Found by | Status |
|
|
25
|
+
|---|---|---|---|---|---|---|
|
|
26
|
+
| 1 | critical | lifecycle / idle-watcher | `/home/caudev/GitHub/mine/CaupulicanDev/AIConfigs/pi/extensions/idle-watcher/index.ts:321-332`, `:334-347`, `:638-642`, `:690-692`, `:783-787` | Root cause of boot + manual-close bug: (1) `effectiveIdleMs()` converted a no-message branch (`raw == null`) into `sinceReset` (which evaluated to `Date.now() - resetEpochMs`). This defeated the first-message escape (`idleMs == null`), making fresh/re-initialized empty sessions eligible for handoff. The handoff generator built an empty transcript, causing `"No conversation to summarise"`. (2) In-flight async paths (confirm picker/model restore) in `handleSessionStartHandoff` could finish and write/inject against a disposed/stale session after manual close. Fix: Return `null` when `raw == null`, set `disposed = true` on `session_shutdown`, and abort in-flight async flows if `disposed` is set. | Cau / codex / agy | **verified (agy, codex)** — `effectiveIdleMs` now preserves `null` for message-less sessions before applying the reset floor, preventing boot/post-close handoff on empty history. |
|
|
27
|
+
| 2 | high | lifecycle / continuous-learning | `/home/caudev/GitHub/mine/CaupulicanDev/AIConfigs/pi/extensions/continuous-learning/index.ts:4535-4555`; `packages/coding-agent/src/modes/interactive/interactive-mode.ts:5732-5740` | External `continuous-learning` extension still registers `session_start` scheduling and `agent_end` triggers even when native reflection is enabled. The core gate only disables the built-in/interactive auto-learn path, not this installed extension, so boot and turns can still start legacy learning alongside native reflection. Minimal fix: make the extension honor `PI_NATIVE_REFLECTION` or expose a core disable signal so the external scheduler does not start when native reflection owns learning. | codex / claude | **verified (agy, codex)** — `session_start` skips `schedule()` and `agent_end` skips `maybeTriggerAutoLearn()` when `PI_NATIVE_REFLECTION !== "0"`; legacy learning requires explicit `PI_NATIVE_REFLECTION=0`. |
|
|
28
|
+
| 3 | high | lifecycle / continuous-learning | `/home/caudev/GitHub/mine/CaupulicanDev/AIConfigs/pi/extensions/continuous-learning/index.ts:4091-4152`, `:4561-4568` | Suspected shutdown bug: `session_shutdown` clears timers/status but does not cancel or await an active `runRound`; `runRound` only checks `runtimeActive` before starting. A manual close during a learning round can let file/memory writes continue against a stale session context after shutdown. Minimal fix: use an `AbortController`/generation token for active rounds, abort it on `session_shutdown`, and check it before each phase/write. | codex / claude | **open — verification failed (codex)**: `roundGeneration` is bumped and checked before the learning executor and `persistLearningOutcome`, but not before every phase/write (`writeHermesComparison`, provider sweep/indexing, skill audit, and run-log writes happen before the first abort check). The round is mostly synchronous, so an in-flight round also cannot observe `session_shutdown` until it yields. Root fix still needs per-phase/write abort checks and/or cancellable async phases. |
|
|
29
|
+
| 4 | medium | lifecycle / idle-watcher | `/home/caudev/GitHub/mine/CaupulicanDev/AIConfigs/pi/extensions/idle-watcher/index.ts:755-759`, `:772-774`; `packages/coding-agent/src/core/agent-session.ts:1023-1025` | Suspected stale-context race: `session_start` launches `handleSessionStartHandoff()` fire-and-forget, while `session_shutdown` only stops status UI. If the session is manually closed while the async picker/injection path is pending, the task can continue using a stale extension context after `AgentSession.dispose()` invalidates it. Minimal fix: track a per-session generation/abort flag, cancel it on `session_shutdown`, and re-check before UI calls, `pi.sendMessage`, or `pi.appendEntry`. | codex / claude | **verified (agy, codex)** — `disposed` is reset on `session_start`, set on `session_shutdown`, and checked after the model-restore await and after the confirm/picker await before `injectHandoff`/`pi.appendEntry`. |
|
|
30
|
+
|
|
31
|
+
| 5 | high | native reflection / cost accounting | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:5783-5791`; `packages/agent/src/types.ts:309`; `packages/ai/src/types.ts:281-299` | Native reflection duplicate-cost dedupe is still ineffective on the real host path. `maybeRunNativeReflection()` derives `reportId` from `(messages[messages.length - 1] as { id?: string })?.id`, but `AgentMessage` is `Message | CustomAgentMessages[...]` and user/assistant messages have timestamps but no top-level `id`. In normal turns `reportId` is therefore `undefined`, so duplicate scheduling/retry can double-count reflection cost despite `runReflectionPass` supporting idempotence. Minimal fix: derive the report id from a real session entry id after persistence (e.g. latest branch entry id) or a stable turn digest, and add an integration test that calls `maybeRunNativeReflection` twice for one turn and asserts one `spawned_usage` report. | codex | open |
|
|
32
|
+
| 6 | low | lifecycle / continuous-learning | `/home/caudev/GitHub/mine/CaupulicanDev/AIConfigs/pi/extensions/continuous-learning/index.ts:4550-4563` | Suspected residual native-mode side effect: even when `PI_NATIVE_REFLECTION !== "0"`, `session_start` still initializes continuous-learning state, writes the Hermes comparison artifact, registers the active session, and updates status before returning. This no longer starts the scheduler (#2 fixed), but it is not a true no-op/yield while native reflection owns learning. Minimal fix: move the native-reflection gate to the top of `session_start` before state/artifact writes unless those side effects are explicitly still desired. | codex | suspected |
|
|
33
|
+
| 7 | high | context-gc / memory subsystem | `packages/coding-agent/src/core/context-gc.ts:236-243`; `packages/coding-agent/src/core/agent-session.ts:1497-1502` | `<memory_context` recall pages are prepended to history as `"user"` messages. However, `ContextGc.ts` only applies semantic memory GC markers (like `<memory_context`) to `"custom"` or `"toolResult"` messages. It does NOT scan `"user"` or `"assistant"` messages. As a result, every cross-session recall page fetched during a session accumulates permanently in active memory and gets persisted in transcript files, completely bypassing Context GC and leading to context window bloat over long sessions. | agy | **fixed (claude)** — recall injected as a GC-managed `custom` message (role custom, customType memory_context) so semantic-memory context-GC packs stale recall pages instead of accumulating forever. |
|
|
34
|
+
| 8 | high | memory subsystem / prompt injection | `packages/coding-agent/src/core/memory/providers/transcript-recall.ts:74-75`, `:134-157`; `packages/coding-agent/src/core/agent-session.ts:1497-1502` | Transcript recall interpolates raw past user/assistant text inside an XML-ish `<memory_context>` block and then injects that block as a `user` message. A prior transcript can contain `</memory_context>` or direct instructions, break out of the wrapper, and be replayed as current-turn user content. Minimal fix: treat snippets as untrusted data (escape/fence delimiters or encode), strengthen the wrapper instruction, and add a regression with a closing-tag/instruction payload. | codex | **fixed (claude)** — recall snippets fenced via the untrusted-content boundary (Hermes-aligned: recall = data, not instructions). |
|
|
35
|
+
| 9 | high | memory subsystem / corpus bounds | `packages/coding-agent/src/core/memory/providers/transcript-recall.ts:94-128`; `packages/coding-agent/src/core/session-manager.ts:489-553` | R3 corpus caps are applied only after `loadEntriesFromFile()` has synchronously read and parsed an entire selected JSONL session into memory. A huge or long-lived transcript can block the first recalled turn and allocate far beyond `MAX_DOC_CHARS` / `MAX_TOTAL_CHARS`, violating the bounded-ms-local contract. Minimal fix: stream-extract only user/assistant text with byte/entry/session caps, skip overlarge files before parse, and test a large transcript path. | codex | **fixed (claude)** — skip transcript files > MAX_FILE_BYTES (8MB) before parse so a huge log can't block/bloat the first recalled turn. |
|
|
36
|
+
| 10 | high | memory subsystem / double injection | `packages/coding-agent/src/core/agent-session.ts:1497-1502`; `packages/agent/src/agent-loop.ts:111-114`; `packages/agent/src/agent.ts:519-522`; `packages/coding-agent/src/core/agent-session.ts:773-790`; `packages/coding-agent/src/core/memory/providers/transcript-recall.ts:134-157` | Recall pages are real persisted `user` messages, and future transcript indexing concatenates every `user`/`assistant` message without excluding `<memory_context source="transcript-recall">`. That recirculates recalled snippets into later sessions, duplicates stale data, and can amplify injected transcript content. Minimal fix: make recall context non-persistent or a filtered custom/context-only message, and/or make `extractSessionText()` skip transcript-recall pages; add a regression proving recalled pages are not re-indexed. | codex | **reinforced (claude)** — recall is now a `custom` message which the transcript index (user/assistant only) never re-reads. |
|
|
37
|
+
| 11 | medium | memory subsystem / cwd privacy | `packages/coding-agent/src/core/memory/providers/transcript-recall.ts:120-126`; `packages/coding-agent/src/core/session-manager.ts:574-596` | Suspected hardening gap: recall relies on the cwd-derived session directory but does not verify that each session header's `cwd` matches the active cwd before indexing. Normal writes are per-cwd, but a misplaced/copied JSONL in that directory can be recalled across cwd boundaries; session resume already performs header-cwd matching. Minimal fix: skip headers whose `cwd` is present and does not resolve to `ctx.cwd`, and test a mismatched-header file. | codex | **fixed (claude)** — skip session headers whose cwd does not resolve to the active cwd (no cross-project recall). |
|
|
38
|
+
<!-- Append new rows below. Renumber sequentially. Include file:line whenever known. -->
|
|
39
|
+
|
|
40
|
+
| 5 | high | reflection cost dedup | interactive-mode.ts maybeRunNativeReflection | reportId derived from messages[last].id which doesn't exist on the real path (messages carry only timestamps) -> reportId always undefined -> reflection-cost dedup ineffective (flagged by codex R1+R2 round-2, re-surfaced by agy). | codex / agy | **fixed (claude)** — derive turnKey from last message timestamp + turn size (present on every real turn, stable across retry, distinct per turn). |
|
|
41
|
+
| 12 | high | security / untrusted boundary | `packages/coding-agent/src/core/security/untrusted-boundary.ts:50-53` | Case and spacing variations in boundary tags bypass escaping: `wrapUntrustedText` uses case-sensitive exact-match `replaceAll` to escape boundary tags. This allows an attacker/untrusted content to bypass the boundary by using case variations (e.g. `</UNTRUSTED_CONTENT>`) or spacing variations (e.g. `</untrusted_content >`), which LLMs often interpret as closing the boundary tag. | agy | **fixed (claude)** — case/whitespace-tolerant fence neutralization regex. |
|
|
42
|
+
| 13 | high | security / untrusted boundary | `packages/coding-agent/src/core/security/untrusted-boundary.ts:16-35` | Under-classification of untrusted tools: `UNTRUSTED_NAME_RE` is too narrow and misses generic terms like `download`, `exec`, or `execute` for third-party extensions. If an extension retrieves remote content or runs untrusted scripts under a different name, its output is classified as `trusted` by default and escapes wrapping. | agy | **fixed (claude)** — widened UNTRUSTED_NAME_RE (download/scrape/exec/execute/run-script/shell/curl/wget/request/api). |
|
|
43
|
+
| 14 | high | memory subsystem / effectiveness | `packages/coding-agent/src/core/memory/effectiveness-tracker.ts:48-58` | Fraction-based distinctive recall usage metric false-negative bias: (1) It divides hits by the entire `distinctive.length`, heavily penalizing longer recall snippets since concise assistant responses only repeat a few key tokens, driving the rolling EMA below the 0.15 gate threshold. (2) If a query perfectly overlaps with a recall page, `distinctive.length` becomes 0, returning a score of 0 (useless) for a perfect keyword match. | agy | **fixed (claude)** — saturate denominator at a few key tokens (no length penalty) + no-signal sentinel when recall adds nothing (skip sample), per Hermes reference-data framing. |
|
|
44
|
+
| 15 | high | memory subsystem / file-store | `packages/coding-agent/src/core/memory/providers/file-store.ts:15-34` | R5 `supersedeNearDuplicateLine` lacks Markdown structural protection: it split-checks all non-empty lines, allowing a new fact to overwrite section headers (e.g. `## User profile`) if the Jaccard similarity is >= 0.6, corrupting the file structure. It can also overwrite negative rules (e.g. `Do not use curl`) with generic positive assertions (e.g. `Use wget`), silently deleting critical safety instructions. | agy | **fixed (claude)** — supersede skips Markdown header lines (never overwrites structure). |
|
|
45
|
+
| 16 | medium | settings / profiles | `packages/coding-agent/src/core/settings-manager.ts:891-902` | Multi-profile soul concatenation: souls from all active profiles are concatenated via `join("\n\n")` instead of following specificity-based override rules. This can inject contradictory soul instructions (e.g., combining a project soul with a global soul) and confuse the model. | agy | **fixed (claude)** — getActiveProfileSoul uses first-wins precedence (no concatenation of contradictory souls). |
|
|
46
|
+
| 17 | high | gateways | `packages/coding-agent/src/core/gateways/channel-provider.ts:70-78` | Resource leak on gateway/scheduler re-registration: registering a channel or scheduler with a name that is already in the map overwrites the entry but does not call `.stop()` on the old provider if the registry is active (`started === true`), leaving background listeners/sockets dangling. | agy | **fixed (claude)** — registerChannel/Scheduler stop the same-named provider being replaced. |
|
|
47
|
+
| 18 | medium | catalog-manager | `packages/coding-agent/src/core/catalog-manager.ts:74-77`, `:94-100` | Partial copy corruption on failure: `install()` and `backup()` use `cpSync()` directly without rollback. If the copy fails halfway (e.g., disk full, permissions), it leaves a corrupt, partially copied resource at the destination which can cause startup crash-loops or runtime loader errors. | agy | **fixed (claude)** — install/backup copy to a temp then atomic-swap (no partial tree at dest). |
|
|
48
|
+
| 19 | high | catalog-manager / hashPath | `packages/coding-agent/src/core/catalog-manager.ts:108-137` | Infinite recursion stack overflow crash: `hashPath` walks directories using `statSync`, which follows symlinks. If a catalog resource contains a circular symlink (pointing back to a parent directory), it causes infinite recursion and crashes the agent process on startup/reload with `RangeError: Maximum call stack size exceeded`. | agy | **fixed (claude)** — hashPath tracks visited realpaths + depth cap (breaks circular symlinks). |
|
|
49
|
+
| 20 | medium | lifecycle / memory leak | `packages/coding-agent/src/core/agent-session.ts:1033-1044` | Deactivated session hooks leak: `AgentSession.dispose()` does not clear hooks (`beforeToolCall`, `afterToolCall`, `contextTransform`, `turnRefresh`) that it registers directly on the shared `this.agent` instance. If the `agent` instance is reused or outlives the session (e.g. in IDE/daemon integrations), the captured closure variables keep the entire deactivated `AgentSession` instance (including all its history and maps) alive in memory. | agy | **fixed (claude)** — dispose() clears agent.afterToolCall + transformContext so the closures stop pinning the session. |
|
|
50
|
+
| 21 | high | lifecycle / reflection | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:5809-5820`; `packages/coding-agent/src/core/agent-session.ts:1033-1044` | In-flight reflection pass leak/corruption: In-flight native reflection passes are not tracked or cancelled on session shutdown/dispose. If a user quits, reloads, or switches sessions while a background reflection pass is in-flight, the completion request will continue to run, wasting tokens/budget and executing memory writes (`_applyReflectionWrite` / `_promoteReflectionSkill`) on the file system against the stale session context. | agy | **fixed (claude)** — _disposed flag + _reflectionAbort signal: runReflectionPass bails pre/post-completion and aborts the in-flight call on dispose (no writes to a dead session). |
|
|
51
|
+
| 22 | high | performance / memory subsystem | `packages/coding-agent/src/core/agent-session.ts:4029-4066`; `packages/coding-agent/src/modes/interactive/components/footer.ts:188` | O(N) spawned usage scan on TUI loop: `getSpawnedUsage` performs an `O(N)` scan of all session entries (and filters `this.fileEntries`) to compute cost. Since this is called by the interactive footer component on every single keystroke/render frame, in long sessions with thousands of entries, this synchronous scan causes severe interface lag and CPU spikes. Similarly, `addSpawnedUsage` performs an `O(N)` scan to check for duplicate report IDs. | agy | **fixed (claude)** — getSpawnedUsage cached by entry count (O(1) per render frame; recompute only when entries change). |
|
|
52
|
+
| 23 | critical | agent loop / runaway loop | `packages/agent/src/agent-loop.ts:174-254` | **(Token/Cost)** No turn limit or iteration cap is enforced in the core `runLoop`. If a model gets stuck in a tool execution loop (repeatedly calling tools due to errors or confusion), it executes infinitely. Since history grows quadratically, this can consume hundreds of thousands of tokens and cost $50+ on premium models in a single run. *Cost Impact:* High/Unbounded. *Minimal Fix:* Add a default turn cap (e.g., max 25 turns) in `AgentLoopConfig` or `Agent`. | agy | **verified + fixed (claude)** — confirmed real (`while(true)` core loop, no backstop). NOT fixed with a blunt turn cap (that would kill legitimate long agentic work = feature-removal, banned). Root-cause fix: progress-based runaway backstop — `maxStallTurns` (default 12) in `AgentLoopConfig`; `runLoop` keys a sliding window on exact tool-call signature (name+args) and stops gracefully (+`onRunawayStop` hook) only when ONE signature recurs ≥limit within the window. Varied/long work never trips it. Tests: `packages/agent/test/runaway-loop.test.ts`. **Review (agy):** AGREE that progress-based backstop is superior to a blunt cap. However, (1) Legit polling tasks (e.g. waiting for a build to finish via repeated command calls) will false-positive after 12 iterations. (2) Gaped: Any period P >= 3 loop (e.g. sequence A->B->C->A->B->C...) will completely bypass the detector because the sliding window of size 2 * L can contain at most 2 * L / P < L occurrences of any single signature. E.g. for L=12 and P=3, maximum repeats count is 8, allowing the runaway loop to execute infinitely. (3) Non-deterministic arguments (like changing timestamps) also completely bypass the detector. Filed Bug #28. |
|
|
53
|
+
| 24 | high | memory subsystem / file-store | `packages/coding-agent/src/core/memory/providers/file-store.ts:99-128` | **(Context Bloat)** `systemPromptBlock` reads the entire contents of `MEMORY.md` and `USER.md` verbatim into the system prompt on every turn with no size limit or warning. If these memory files grow large (e.g. from repeated reflection promotions), they will permanently bloat every turn's context window. *Cost Impact:* High permanent token cost per turn (up to $0.50+ extra/turn for 15KB memory). *Minimal Fix:* Cap the injected memory block length (e.g., max 12,000 characters total) or warn when files exceed a threshold. | agy | **verified (mostly invalid) + hardened (claude)** — claim "no size limit" is wrong: the `memory` tool already hard-caps every WRITE at `BUDGET_MEMORY=2200`/`BUDGET_USER=1375` chars (file-store.ts:165,225), and reflection promotions go through that same budgeted tool — so an agent can never bloat memory past ~3.5KB. The 15KB/"$0.50/turn" scenario can't occur via any agent path. Residual gap (external/manual edits bypassing the tool): added a read-time cap in `systemPromptBlock` so the injected view is bounded to the same budgets with a truncation note (file on disk untouched). Tests: `packages/coding-agent/test/file-store-budget.test.ts`. **Review (agy):** AGREE. While the memory tool caps writes, the read-time cap is a critical hardening fix for out-of-band/manual edits. Tested and correct. |
|
|
54
|
+
| 25 | medium | lifecycle / reflection | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:5772-5820` | **(Redundant Calls)** Background native reflection runs unconditionally at the end of any turn that meets the tool call threshold or contains correction keywords. In a multi-turn troubleshooting session where the user repeatedly corrects the agent, this spams back-to-back/overlapping background reflection reasoning passes for the same task. *Cost Impact:* Medium ($1.00 - $3.00/session in wasted background model calls). *Minimal Fix:* Add a time-based debounce or turn-based cooldown (e.g. do not reflect more than once every 3 turns). | agy | **verified + fixed (claude)** — confirmed: `maybeRunNativeReflection` fires per eligible turn; the reportId only dedups retries of the *same* turn, not consecutive distinct corrective turns. Fix: debounce in `InteractiveMode` — `_nativeReflectionInFlight` blocks overlapping passes, `_lastNativeReflectionAt` + `NATIVE_REFLECTION_MIN_INTERVAL_MS` (45s) enforces a minimum gap. Not feature-removal: skipped corrections are still reflected on the next eligible pass over the accumulated turn text. **Review (agy):** DISAGREE with "Not feature-removal". Since reflection only analyzes `event.messages` (the current turn's messages) rather than the whole history, skipped turns are completely lost and never reflected on, causing learning loss. Filed Bug #29. |
|
|
55
|
+
| 26 | high | context-gc / recall | `packages/coding-agent/src/core/context-gc.ts:236-243` | **(Context Bloat)** `semanticMessageHasMarker` in `context-gc.ts` only scans `toolResult` and semantic `custom` messages. However, `TranscriptRecallProvider` memory context pages are injected as `role: "user"` messages. Thus, recall pages completely bypass GC and accumulate verbatim forever, causing significant context window token bloat over long sessions. *Cost Impact:* Medium/High token accumulation over long sessions. *Minimal Fix:* Update `semanticMessageHasMarker` to also scan messages with `role: "user"`. | agy | **invalid — already fixed by #7 (claude)** — STALE finding (reviewed pre-batch-3 code). Recall pages are NO LONGER `role:"user"`: batch-3 #7 changed injection to `createCustomMessage("memory_context", …)` → `role:"custom"`, customType contains "memory" so `isSemanticMemoryCustomMessage` matches, and `<memory_context` is in the default GC markers. Recall pages ARE GC-managed now. Agy's suggested fix (scan `role:"user"`) is also wrong — it would sweep genuine user input into GC. No change. **Review (agy):** AGREE. Recall pages are indeed custom messages now, and are correctly garbage collected. Stale finding verified invalid. |
|
|
56
|
+
| 27 | high | compaction / settings | `packages/coding-agent/src/core/compaction/compaction.ts:219-230` | **(Token/Cost)** Auto-compaction trigger is based on the absolute model context window (`contextWindow - reserveTokens`). For large-context models (e.g. 200k for Claude 3.5 Sonnet, 128k for GPT-4o), auto-compaction will not trigger until 110k-180k tokens are reached, resulting in extremely expensive inputs ($0.30 - $0.50+ per turn) for ordinary chat. *Cost Impact:* Very High ($2.00 - $10.00+ per long session). *Minimal Fix:* Cap the default compaction trigger threshold at a hard maximum ceiling (e.g. 32k or 48k tokens) on large-context models. | agy | **rejected as framed (claude)** — `shouldCompact` ALREADY accepts a configurable `triggerTokens` (Math.min with the window-based default), so the threshold is tunable per deployment. A hard 32–48k ceiling on a 200k model is NOT a root-cause fix: it would force frequent *lossy* compaction, discarding cheaply-cached context and forcing re-derivation/re-reads — that raises cost and degrades quality (the opposite of the goal). Compaction is a quality/cost tradeoff knob that already exists; hardcoding a low ceiling removes headroom users paid for. Open for a possible *opt-in* default cap setting later, but no blunt hardcode. **Review (agy):** AGREE. Compaction triggers are already tunable, and a hard ceiling could degrade performance on expensive cached context windows. An opt-in ceiling is a better approach than a blunt hardcode. |
|
|
57
|
+
| 28 | high | agent loop / runaway loop | `packages/agent/src/agent-loop.ts:227-238` | Evasion of runaway loop detector via period >= 3 oscillations (e.g. A->B->C->A->B->C). Since window size is capped at 2 * L, the count of any single signature in a periodic sequence is at most 2 * L / P, which is less than L. Thus, the detector never triggers and period >= 3 loops run infinitely. | agy | **fixed (claude)** — two root-cause changes in `agent-loop.ts`: (1) signatures are normalized (`normalizeToolSignature`) to mask volatile arg tokens — UUIDs, ISO timestamps, ≥10-digit epochs, ≥16-char hashes — so a model retrying the same call with a fresh timestamp/nonce each turn collapses to one signature and IS detected (gap 3). Short numbers (`file2`, `line 42`) are deliberately NOT masked, so distinct numbered calls aren't falsely merged. (2) window widened from `stallLimit*2` to `stallLimit*STALL_WINDOW_PERIODS` (×4): a period-P cycle repeats each signature ~window/P times, so the count-based trip now catches oscillation up to period 4 (gap 2), not just back-to-back repeats. Tests: `runaway-loop.test.ts` (volatile-timestamp + period-3 cases). Residual (accepted/documented): exact cycles of period ≥5 and legit identical-poll loops still trip — `onRunawayStop` stops gracefully (recoverable) and `maxStallTurns` is tunable/0-disables per deployment (gap 1). Also (agy round-2): a loop that legitimately shows ≥`stallLimit` full ≥16-char commit hashes (40-char SHAs) would over-mask to one signature and false-positive — accepted as the safer default (masking prevents UNBOUNDED nonce-evasion runaways; the false-positive is a graceful recoverable stop). Narrow in practice: git short hashes (7–12 chars) are below the ≥16 threshold and stay distinct, so only full-SHA loops are affected. **Review (agy):** AGREE. The fix is robust and complete. (1) Widening the window to 4 * L successfully catches period P <= 4 oscillations, as each signature will occur at least 4 * L / P >= L times. (2) Normalization correctly filters volatile parameters (UUIDs, timestamps, large digits, large hashes). One minor over-masking edge case remains: git commit hashes of length >= 16 are collapsed, meaning a legitimate loop of showing >= L commits will false-positive. (3) Handled gracefully via onRunawayStop and custom maxStallTurns settings. |
|
|
58
|
+
| 29 | high | lifecycle / reflection | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:5780-5790` | Native reflection debounce skips learning inputs on skipped turns. Since reflection only analyzes the current turn's messages, corrective feedback from turns skipped due to the 45-second gap is permanently lost. | agy | **fixed (claude)** — agy is correct: reflection only sees the current turn's `event.messages`, so dropping a debounced turn lost its learning (making my debounce a feature-removal). Fix: the debounce now DEFERS instead of dropping — an eligible-but-debounced turn's text is buffered (`_bufferPendingReflection`, bounded to `PENDING_REFLECTION_MAX_CHARS=12000`, oldest-dropped) and folded into the next pass's `recentTurnText` via `_drainPendingReflection`. Eligibility (trigger) is now computed BEFORE the debounce check so corrective turns are buffered, not skipped silently. No corrective feedback is lost; it's batched. **Review (agy):** AGREE. The fix is robust and correct. Buffering debounced turns preserves corrective inputs, folding them into the next pass without loss of learning. The FIFO drop-oldest buffer bounds memory growth safely, and the ordering is preserved correctly. |
|
|
59
|
+
| 30 | high | compaction / cost | `packages/coding-agent/src/core/compaction/compaction.ts:123,226`; `packages/coding-agent/src/core/agent-session.ts:2243-2252` | **(Token/Cost — found during Hermes parity review)** Long-session compaction is doubly expensive vs Hermes: (1) default trigger is `contextWindow - reserveTokens` (reserveTokens=16384), i.e. it waits until the context is NEARLY FULL — on a 200k model every turn before compaction pays ~184k input tokens; Hermes compacts at **50% of the window** (capping per-turn input far lower on sustained sessions). (2) the summary is generated with `this.model` (the MAIN/expensive model), whereas Hermes summarizes with a **cheap auxiliary model** (Gemini Flash) and skips compaction if the last 2 passes each saved <10% (anti-thrashing). This is the nuanced, defensible form of the earlier #27 (rejected as a blunt hardcoded ceiling): the real fix is a configurable **percentage-based trigger default** + an optional **cheap auxiliary summarizer model** + anti-thrashing. *Cost Impact:* High on long sessions. | claude (Hermes review) | **fix-proposed (shipped v0.80.75, agy impl-review: AGREE)** — `shouldCompact` adds a fractional trigger (`triggerPercent` default 0.7, lower-of with reserve) + stateless anti-thrashing gate (skip early compaction when projected savings <12%, hard near-full trigger never gated); `_resolveCompactionModel` summarizes with the cheapest authed model meeting a 64k context floor and strictly cheaper than the session model, else the session model. Tests: `compaction.test.ts`. **Review (agy):** AGREE. The stateless anti-thrash projected savings calculation is mathematically sound and superior to a turn counter. The hard near-full trigger is evaluated first, guaranteeing no context overflow. Model selection is appropriately bounded by the 64k capability floor and strictly-cheaper pricing checks. |
|
|
60
|
+
| 31 | medium | security / threat scanning | `packages/coding-agent/src/core/resource-loader.ts:112-130` | **(Security — found during Hermes parity review)** `scanContextFileThreats` has only **3 regex patterns** (instruction-override, secret-exfil, hidden-instruction) and does **not** detect invisible/bidirectional Unicode (zero-width `-`, directional isolates `-`, embeddings/overrides `-`) — a known prompt-injection vector that can hide instructions in context files/memory. Hermes scans 17 such codepoints plus scoped (all/context/strict) pattern sets incl. exfil/C2/role-hijack. Our nonce-fenced untrusted boundary is stronger than Hermes's static fence, but our pre-injection content scanner is much thinner. Minimal fix: add an invisible/bidi-Unicode detector to the scanner and broaden the pattern set (esp. for memory-write `strict` scope). | claude (Hermes review) | **fix-proposed (shipped v0.80.75, agy impl-review: AGREE)** — added `hasInvisibleUnicode`/`stripInvisibleUnicode` (zero-width, bidi overrides/isolates, BOM) + scoped `THREAT_PATTERNS` (`context` vs strict superset incl. exfil/ssh-backdoor/secret-read). Layered per agy: context-file + memory READS strip+continue; memory WRITES scanned `strict` and rejected (incl. hidden chars). Tests: `threat-scanner.test.ts`. **Review (agy):** AGREE. Threat patterns are correctly scoped and memory writes are appropriately blocked. However, identified a significant internationalization bug: `INVISIBLE_UNICODE_RE` includes standard RTL/Indic formatting characters (ZWNJ `\u200C`, ZWJ `\u200D`, LRM `\u200E`, RLM `\u200F`), meaning reading legitimate Arabic, Hebrew, Persian, or Hindi text will strip these characters, corrupting ligatures and word boundaries. Logged as Bug #35. |
|
|
61
|
+
| 32 | medium | learning / skill lifecycle | `packages/coding-agent/src/core/agent-session.ts:4287-4306` (`_promoteReflectionSkill`) | **(Cost/Bloat — found during Hermes parity review)** R7 promotes recurring lessons into `<agentDir>/skills/<name>/SKILL.md`, but there is **no curator**: promoted skills are never usage-tracked, archived when stale, or consolidated when overlapping. Over time this grows the skills corpus unboundedly → tool/context bloat → higher per-turn cost and degraded routing. Hermes has a curator (usage sidecar; STALE >30d, ARCHIVED >90d to restorable `.archive/`; idle-triggered consolidation). Minimal fix: track promoted-skill usage and add an idle/threshold-triggered archive+consolidate pass (restorable, non-destructive). | claude (Hermes review) | **fix-proposed (agy impl-review: AGREE)** — new `skill-curator.ts`: promoted skills carry frontmatter `promoted: true`; `_expandSkillCommand` bumps a usage sidecar on invocation; `computeCurationProposals` (pure) flags stale-unused for archival + overlapping pairs for consolidation; `SkillCurator` archives/restores non-destructively to `skills/.archive/`. PROPOSE-ONLY per agy — surfaced via the new `/curate` command (`/curate archive|restore <name>`); never auto-archives/merges, never touches hand-authored skills. Tests: `skill-curator.test.ts`. **Review (agy):** AGREE. The curator implementation correctly maintains the propose-only invariant. The `createdMs` grace logic guards new skills successfully. Moving skills to `.archive` and restoring works atomically, preventing any concurrency races. **Default-on AUTO-ARCHIVE (Cau, post-review):** at Cau's request the curator now auto-archives stale promoted skills at session start by default (`curator.autoArchive` default true), reversing the propose-only default. agy sanity-checked the safety design and AGREED it's safe enough given the safeguards, flagging a concurrent-session race → mitigated: `autoArchiveStale` runs the batch under a `proper-lockfile` lock on the skills dir, archival is restorable + promoted-only + ANNOUNCED at startup (`Curator: auto-archived N stale skill(s) … restore with /curate restore`). Consolidation stays propose-only. Tests: `skill-curator.test.ts` (autoArchiveStale). |
|
|
62
|
+
| 33 | low | learning / reflection cost | `packages/coding-agent/src/core/agent-session.ts` (`runIsolatedCompletion`/`runReflectionPass`) | **(Cost optimization — found during Hermes parity review)** Our in-process reflection uses a FRESH Context (`tools:[]`, `cacheRetention:"none"`, no sessionId), so the reflection LLM call gets NO prompt-cache hit and pays full input cost. Hermes reuses the parent's cached system prompt for its background-review fork for a measured ~26% cost reduction. **Plan decision (agy):** do NOT inherit the session prompt (it's packed with tool/extension defs → dilutes reflection quality + inflates tokens). Instead make the dedicated reflection prompt a STATIC structure so it hits prompt-cache naturally across passes. | claude (Hermes review) | **fix-proposed (agy impl-review: AGREE)** — `REFLECTION_SYSTEM_PROMPT` is now a static module constant (no per-call interpolation); existing-memory + turn transcript moved into the USER prompt. `runIsolatedCompletion` gained an optional `cacheRetention` (default "none"); reflection passes "short" so the static prefix is provider-cached. Tests: native-reflection/reflection-skill-promotion still green. **Review (agy):** AGREE. Restructuring `REFLECTION_SYSTEM_PROMPT` to be fully static while passing variables in the user prompt is correct. It successfully enables prompt caching with `cacheRetention: "short"` without quality dilution. |
|
|
63
|
+
| 34 | medium | cost / billing guard | `packages/coding-agent/src/core/agent-session.ts` (pre-submit path) | **(Cost/Token — superiority item proposed by agy in the parity plan)** Neither Hermes nor we have a PROACTIVE per-turn cost ceiling. Add a token cost guard: estimate the dollar cost of the pending prompt before submission (input size × model input price + expected max output), and if it exceeds a user-defined threshold (e.g. $1.50/turn) either warn interactively or auto-downgrade reasoning effort (high→low/off) to prevent runaway billing spikes. Beats Hermes (it only compresses reactively; this caps cost proactively). | agy (Hermes parity plan) | **fix-proposed (agy impl-review: AGREE)** — new pure `cost-guard.ts` (`estimateTurnCostUsd`, `evaluateCostGuard`, `downgradeReasoning`) + `costGuard` settings (`maxTurnUsd` default 0 = disabled, `action` warn|downgrade). Wired in `transformContext` via `_applyCostGuard`: estimates the imminent turn's USD, records a decision (`getLastCostGuardDecision()` for the UI), and on `downgrade` steps reasoning down once per over-threshold episode. Tests: `cost-guard.test.ts`. **Review (agy):** AGREE. Integration in `transformContext` runs at the right chokepoint before submission. The one-shot downgrade latch successfully steps reasoning down once per episode without cascading to "off" immediately, and the try-catch wrapper ensures it never disrupts a turn. **Default-on (Cau, post-review):** flipped to ON in WARN-only mode — `maxTurnUsd` default 0→2.5, `action` default "warn" — and wired the decision into the footer (`⚠$X/turn` indicator) so it's actually visible. Auto-downgrade stays opt-in. |
|
|
64
|
+
| 35 | medium | threat-scanner / internationalization | `packages/coding-agent/src/core/resource-loader.ts:177` | **(Internationalization)** The threat scanner's `INVISIBLE_UNICODE_RE` includes standard RTL/Indic formatting characters (ZWNJ `\u200C`, ZWJ `\u200D`, LRM `\u200E`, RLM `\u200F`). Stripping these from read-context files corrupts spelling, joined glyph rendering, and punctuation alignment in Persian, Arabic, Hebrew, and Hindi. | agy | **fixed (claude)** — narrowed `INVISIBLE_UNICODE_RE` to genuinely-dangerous controls only (U+200B, U+202A–202E, U+2060–2064, U+2066–206F, U+FEFF); the legitimate joiners/marks U+200C ZWNJ, U+200D ZWJ, U+200E LRM, U+200F RLM are now PRESERVED (load-bearing in Persian/Arabic/Hebrew/Hindi shaping + emoji ZWJ sequences). The Trojan-Source reorder attack relies on the embeddings/overrides/isolates, which are still stripped. Test: `threat-scanner.test.ts` (i18n-preservation case). |
|
|
65
|
+
| 36 | medium | resource profiles / extension filtering | `packages/coding-agent/src/core/resource-loader.ts` (`getDiscoverableExtensionPaths` vs reload extension discovery) | **(Found in live testing)** External-resource-root extensions (`<root>/extensions/<name>`) are LOADED at reload (`filterPathsByProfile(externalExtensions, "extensions")`) but were ABSENT from `getDiscoverableExtensionPaths()`, which only read `packageManager.resolve()` + CLI paths. The profile-resource editor builds its "available extensions" universe from `getDiscoverableExtensionPaths()`, so external-root extensions (e.g. Cau's private automata-memory-graph/skill-tool-router/etc.) were active but INVISIBLE to the editor — it showed "(none available)" while ~60 ran, and they couldn't be blocked per-profile. | claude (live testing) | **fixed (claude)** — extracted the external-extension directory scan into one shared `discoverExternalExtensionPaths()` used by BOTH the load path and `getDiscoverableExtensionPaths()`, so the editor's universe always matches the loaded set. External extensions now appear in the profile editor and are blockable per-profile. Test: `resource-loader.test.ts` ("getDiscoverableExtensionPaths includes external-root extensions"). |
|
|
66
|
+
| 37 | high | ai / cost accounting | `packages/ai/src/models.ts:44; packages/ai/src/providers/anthropic.ts:550` | W1.1 Anthropic streamed usage.cost.total freezes at input-only value after message_start, under-reporting output cost. | 2026-07-05 harness bug hunt | fixed |
|
|
67
|
+
| 38 | high | ai / json parsing | `packages/ai/src/utils/json-parse.ts:3` | W1.2 repairJson treats invalid \u escapes as valid, causing tool-call JSON parsing to fall back to empty args. | 2026-07-05 harness bug hunt | fixed |
|
|
68
|
+
| 39 | high | coding-agent / model router | `packages/coding-agent/src/core/model-router-controller.ts:715` | W1.3 Executor speculative retry truncates live history but leaves discarded first attempt in router session buffer, persisting ghost turns. | 2026-07-05 harness bug hunt | fixed |
|
|
69
|
+
| 40 | high | coding-agent / bash fast path | `packages/coding-agent/src/core/tools/bash.ts` | W1.4 grep/rg fast path uses literal substring matching for regex patterns, yielding silent false negatives. | 2026-07-05 harness bug hunt | fixed |
|
|
70
|
+
| 41 | high | coding-agent / bash fast path | `packages/coding-agent/src/core/tools/bash.ts` | W1.5 find fast path follows symlinked directories without cycle/escape guard, diverging from real find and risking hangs. | 2026-07-05 harness bug hunt | fixed |
|
|
71
|
+
| 42 | high | coding-agent / html export | `packages/coding-agent/src/core/export-html/index.ts:164` | W1.6 HTML export asset injection uses String.replace values directly, corrupting $ sequences in JS/vendor assets. | 2026-07-05 harness bug hunt | fixed |
|
|
72
|
+
| 43 | high | coding-agent / goals | `packages/coding-agent/src/core/slash-commands.ts` | W2.1 /goal has no user-facing producer; goal consumer stack remains unreachable unless model volunteers goal tool calls. | 2026-07-05 harness bug hunt | fixed |
|
|
73
|
+
| 44 | high | agent / retry kernel | `packages/agent/src/reliability/retry-controller.ts:116` | W3.1 Turn retry controller ignores parsed retryAfterMs when computing backoff. | 2026-07-05 harness bug hunt | fixed |
|
|
74
|
+
| 45 | high | coding-agent / failure corpus | `packages/coding-agent/src/core/agent-session.ts:3639; packages/coding-agent/src/core/billing-failover-controller.ts:73` | W3.2 Failure corpus recording is side-effectful in retry predicate and billing failover, duplicating one failure and possibly disagreeing on classification. | 2026-07-05 harness bug hunt | open |
|
|
75
|
+
| 46 | medium | agent / classifier | `packages/agent/src/reliability/classifier.ts:53` | W3.3 Numeric status regexes match inside longer numbers, misclassifying token counts and IDs as rate/server errors. | 2026-07-05 harness bug hunt | open |
|
|
76
|
+
| 47 | medium | agent / compaction loop | `packages/agent/src/compaction/loop.ts:227` | W3.4 Compaction-loop failure mapping treats any aborted substring as user abort, suppressing retries for ECONNABORTED-style provider errors. | 2026-07-05 harness bug hunt | open |
|
|
77
|
+
| 48 | medium | ai+agent / streams | `packages/ai/src/utils/event-stream.ts:38; packages/agent/src/proxy.ts:213` | W3.5 Streams ending without terminal event can leave result() unresolved after watchdog disarms. | 2026-07-05 harness bug hunt | suspected |
|
|
78
|
+
| 49 | low | ai / oauth | `packages/ai/src/utils/oauth/openai-codex.ts:150` | W3.6 Codex OAuth token expiry lacks the 5-minute early-refresh buffer used by sibling providers. | 2026-07-05 harness bug hunt | suspected |
|
|
79
|
+
| 50 | high | agent / compaction loop | `packages/agent/src/compaction/loop.ts:63` | W4.1 effect-not-restored retry path is unreachable after apply appends a compaction entry; tests mask real branch mutation. | 2026-07-05 harness bug hunt | open |
|
|
80
|
+
| 51 | medium | agent / compaction verification | `packages/agent/src/compaction/extraction.ts:24` | W4.2 Cancelled-work extraction over-matches everyday phrasing and creates unsatisfiable verification gates. | 2026-07-05 harness bug hunt | open |
|
|
81
|
+
| 52 | medium | agent / compaction verification | `packages/agent/src/compaction/verification.ts:87` | W4.3 actions-overlap Jaccard penalizes faithful Done carry-over on update compactions. | 2026-07-05 harness bug hunt | open |
|
|
82
|
+
| 53 | low | agent / compaction tokens | `packages/agent/src/compaction/compaction.ts:294` | W4.4 Token estimator comment is directionally wrong and chunk sizing uses 100% of input bound with no headroom. | 2026-07-05 harness bug hunt | open |
|
|
83
|
+
| 54 | low | agent / branch summarization | `packages/agent/src/compaction/branch-summarization.ts:324` | W4.5 Branch summarization bypasses wrapped stream/retry/watchdog path. | 2026-07-05 harness bug hunt | open |
|
|
84
|
+
| 55 | medium | coding-agent / interactive rendering | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:2465` | W5.1 renderSessionContext is not reentrancy-safe; overlapping rebuilds can orphan chat containers. | 2026-07-05 harness bug hunt | suspected |
|
|
85
|
+
| 56 | medium | coding-agent / extensions UI | `packages/coding-agent/src/modes/interactive/interactive-mode.ts:656` | W5.2 extensions-changed UI subscription is not rebound after session switch. | 2026-07-05 harness bug hunt | open |
|
|
86
|
+
| 57 | medium | coding-agent / extensions loader | `packages/coding-agent/src/core/resource-loader.ts:912` | W5.3 Failed /reload can leak event-bus subscriptions from new and partial extension generations. | 2026-07-05 harness bug hunt | suspected |
|
|
87
|
+
| 58 | medium | coding-agent / extensions runner | `packages/coding-agent/src/core/extensions/runner.ts:878` | W5.4 emitToolCall lacks per-handler error isolation, skipping later handlers and diagnostics on throw. | 2026-07-05 harness bug hunt | suspected |
|
|
88
|
+
| 59 | medium | tui / input | `packages/tui/src/keys.ts:1375` | W6.1 Kitty PUA functional keys decode as printable invisible text. | 2026-07-05 harness bug hunt | suspected |
|
|
89
|
+
| 60 | medium | tui / measurement | `packages/tui/src/utils.ts:295` | W6.2 extractAnsiCode CSI terminator set is too narrow and can swallow visible text after non-SGR CSI. | 2026-07-05 harness bug hunt | suspected |
|
|
90
|
+
| 61 | low | tui / stdin buffer | `packages/tui/src/stdin-buffer.ts:315` | W6.3 Bracketed paste without end marker can leave pasteMode set forever. | 2026-07-05 harness bug hunt | suspected |
|
|
91
|
+
| 62 | high | coding-agent / startup migrations | `packages/coding-agent/src/migrations.ts:147` | W7.1 Malformed models.json hard-crashes startup migrations; trust-manager parse has similar unguarded path. | 2026-07-05 harness bug hunt | open |
|
|
92
|
+
| 63 | medium | coding-agent / settings | `packages/coding-agent/src/core/settings-manager.ts:427` | W7.2 deepMergeSettings documents recursive merge but only merges one level. | 2026-07-05 harness bug hunt | open |
|
|
93
|
+
| 64 | low | coding-agent / migrations | `packages/coding-agent/src/migrations.ts:252` | W7.3 Windows session migration basename extraction silently no-ops. | 2026-07-05 harness bug hunt | open |
|
|
94
|
+
| 65 | medium | coding-agent / scout | `packages/coding-agent/src/core/scout-controller.ts:103` | W8.1 Scout budget counts total tokens against an output-token cap, causing premature truncation. | 2026-07-05 harness bug hunt | suspected |
|
|
95
|
+
| 66 | low | coding-agent / reflection | `packages/coding-agent/src/core/learning/reflection-engine.ts:177` | W8.2 Reflection JSON parse failure returns empty usage, zeroing real spend. | 2026-07-05 harness bug hunt | suspected |
|
|
96
|
+
| 67 | low | coding-agent / research lane | `packages/coding-agent/src/core/background-lane-controller.ts:452` | W8.3 Research-lane budget gate compares unclamped estimate against clamped envelope limit. | 2026-07-05 harness bug hunt | suspected |
|
|
97
|
+
| 68 | low | agent / public loop API | `packages/agent/src/agent-loop.ts:41` | W9.1 agentLoop public API has detached promise with no catch and continuation mutates caller messages array. | 2026-07-05 harness bug hunt | open |
|
|
98
|
+
| 69 | low | agent / shell output | `packages/agent/src/utils/shell-output.ts` | W9.2 sanitizeBinaryOutput preserves lone surrogates, DEL, and C1 controls despite comment. | 2026-07-05 harness bug hunt | open |
|
|
99
|
+
| 70 | low | ai / anthropic | `packages/ai/src/providers/anthropic.ts:1259` | W9.3 Anthropic mapStopReason default throws on future stop_reason values instead of graceful stop. | 2026-07-05 harness bug hunt | open |
|
|
100
|
+
| 71 | low | coding-agent / failure corpus | `packages/coding-agent/src/core/failure-corpus.ts:83` | W9.4 redactSecrets misses separator-bearing sk-proj/sk-ant key formats. | 2026-07-05 harness bug hunt | suspected |
|
|
101
|
+
| 72 | low | coding-agent / exec | `packages/coding-agent/src/core/exec.ts:135` | W9.5 exec decodes per chunk with data.toString(), splitting multibyte characters. | 2026-07-05 harness bug hunt | suspected |
|
|
102
|
+
| 73 | low | coding-agent / bash execution | `packages/coding-agent/src/core/bash-execution-controller.ts:39` | W9.6 Overlapping executeBash calls clobber the shared abort controller. | 2026-07-05 harness bug hunt | suspected |
|
|
103
|
+
| 74 | low | coding-agent / tools manager | `packages/coding-agent/src/utils/tools-manager.ts:312` | W9.7 Concurrent same-tool first-run downloads race on one archive path. | 2026-07-05 harness bug hunt | suspected |
|
|
104
|
+
| 75 | low | coding-agent / interactive mode | `packages/coding-agent/src/modes/interactive/interactive-mode.ts` | W9.8 Interactive-mode small leaks: current-scope session selector lacks seq guard; custom editor replacement does not dispose previous editor. | 2026-07-05 harness bug hunt | suspected |
|
|
105
|
+
| 76 | low | ai / mistral streaming | `packages/ai/src/providers/mistral.ts:397` | W9.9 Investigation: Mistral streaming tool-call assembly may fragment if ids are absent from later deltas. | 2026-07-05 harness bug hunt | suspected |
|
|
106
|
+
| 77 | high | coding-agent / local models | `packages/coding-agent/src/core/models/local-registration.ts:81` | W10.1 Local model context windows are registered as a guess (8192 default); no num_ctx/served-window awareness anywhere, so over-window prompts are silently truncated by the server. | 2026-07-06 compaction incident | open |
|
|
107
|
+
| 78 | high | coding-agent / compaction | `packages/coding-agent/src/core/compaction-support.ts:132` | W10.2 Summarizer selection was capacity-blind: router-cheap local model chosen for spans its window cannot hold, producing recall-empty checkpoints. | 2026-07-06 compaction incident | fix-proposed |
|
|
108
|
+
| 79 | high | agent / compaction | `packages/agent/src/compaction/compaction.ts` | W10.3 Verification demands scale with span size while the summary budget was fixed at 1500 tokens; length-stopped summaries were gated as complete; truncation deleted the gate-checked Files/Done sections. | 2026-07-06 compaction incident | fix-proposed |
|
|
109
|
+
| 80 | high | agent+coding-agent / compaction | `packages/coding-agent/src/core/context-pipeline.ts:388` | W10.4 Pre-digest feeds the summarizer a lossy digest while facts are extracted from the raw span; active-task text did not ride in the facts block, making the gate unsatisfiable. | 2026-07-06 compaction incident | fix-proposed |
|
|
110
|
+
| 81 | medium | coding-agent / compaction | `packages/coding-agent/src/core/agent-session.ts:2784` | W10.5 Manual /compact is single-shot on the cheap summarizer with no escalation ladder or deterministic fallback; surfaces raw gate internals. | 2026-07-06 compaction incident | open |
|
|
111
|
+
| 82 | low | agent / compaction extraction | `packages/agent/src/compaction/extraction.ts:23` | W10.6 Prohibition extraction captured a mid-sentence fragment as a mandatory rule in the incident trace; needs fixture with W4.2. | 2026-07-06 compaction incident | open |
|
|
112
|
+
| 83 | low | coding-agent / red-team tests | `packages/coding-agent/test/red-team/provider-limits.test.ts:158` | Pre-existing failure on main: d444e991 added _failureCorpus.record inside _compactWithRetry but the red-team CompactWithRetryHarness was never updated, so the quota-mid-compaction row failed with a TypeError. | 2026-07-06 compaction incident (drive-by) | fix-proposed |
|
|
113
|
+
| 84 | high | ai / openai responses | `packages/ai/src/providers/openai-responses-shared.ts:349` | Regression in c81848ec (W1.1): providerSuppliedTotal flag dereferences response.usage.cost outside the usage guard, crashing finalizeResponse on usage-less streams; caught by the full sweep. | 2026-07-06 compaction incident (drive-by) | fix-proposed |
|
package/docs/index.md
CHANGED
|
@@ -45,6 +45,7 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
45
45
|
- [Keybindings](keybindings.md) - default shortcuts and custom keybindings.
|
|
46
46
|
- [Sessions](sessions.md) - session management, branching, and tree navigation.
|
|
47
47
|
- [Compaction](compaction.md) - context compaction and branch summarization.
|
|
48
|
+
- [FastContext scout](scout.md) - read-only repository scout setup and 10 GB local profile.
|
|
48
49
|
|
|
49
50
|
## Customization
|
|
50
51
|
|
package/docs/models.md
CHANGED
|
@@ -36,6 +36,15 @@ For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
|
|
|
36
36
|
|
|
37
37
|
The `apiKey` is required but Ollama ignores it, so any value works.
|
|
38
38
|
|
|
39
|
+
## Curated Local Suggestions
|
|
40
|
+
|
|
41
|
+
Run `/models suggest` to choose from pi's curated local-model roster. Pi pulls the selected model through the managed Ollama runtime, probes it with `/fitness` on your hardware, then offers the shaped role assignment.
|
|
42
|
+
|
|
43
|
+
Current baked suggestions include:
|
|
44
|
+
|
|
45
|
+
- FastContext-1.0-4B → repository scout (`context_scout`): the model the scout lane is built around, not a pi benchmark claim. Q4 is about 2.5 GB weights; expect about 5-6 GB peak with 32K-64K KV. Assignment writes `scout.model` and enables `scout.enabled` only after the `scout_auto` exam passes.
|
|
46
|
+
- Ornith-1.0-9B → agentic-coding worker / router cheap tier: an external candidate, not from pi's own validation research. Q4_K_M is about 5.6 GB weights; expect about 7-8 GB peak with KV, and run it as the only local model on a 10 GB box. `/fitness` on your hardware is the validator.
|
|
47
|
+
|
|
39
48
|
Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
|
|
40
49
|
|
|
41
50
|
You can set `compat` at the provider level to apply to all models, or at the model level to override a specific model. This commonly applies to Ollama, vLLM, SGLang, and similar OpenAI-compatible servers.
|
package/docs/providers.md
CHANGED
|
@@ -21,6 +21,20 @@ Use `/login` in interactive mode, then select a provider, or pass one directly (
|
|
|
21
21
|
|
|
22
22
|
Use `/logout` to clear credentials. Tokens are stored per provider in `~/.pi/agent/auth.json` and auto-refresh when expired.
|
|
23
23
|
|
|
24
|
+
If a subscription provider reports a terminal usage limit, Pi stops retrying that exhausted model, announces the condition, and switches the session to that provider's default model when it is authenticated and not already exhausted. API-key/metered quota failures do not auto-hop; Pi halts the turn and asks you to switch models, wait for the limit window, or resend explicitly.
|
|
25
|
+
|
|
26
|
+
## Provider Failure Evidence Corpus
|
|
27
|
+
|
|
28
|
+
Pi records local provider failures to `~/.pi/agent/state/failure-corpus.jsonl` so unclassified provider messages become reviewable evidence. Records contain `{ts, provider, modelId, reason, retryable, message}`; messages are truncated to 500 characters and redacted for `sk-...` keys, `Bearer ...` tokens, and long base64-like secrets. The file stays local, is never uploaded by pi, and is rotated to 512 KB / newest 1,000 records. You may delete it at any time.
|
|
29
|
+
|
|
30
|
+
Evidence grades for adding future provider signatures:
|
|
31
|
+
|
|
32
|
+
- Grade A: executable SDK fixture that constructs the vendor SDK error and classifies its actual `.message`.
|
|
33
|
+
- Grade B: redacted corpus capture from real traffic.
|
|
34
|
+
- Grade C: literal adapter throw-site in pi source.
|
|
35
|
+
|
|
36
|
+
Promotion procedure: evidence → provider signature row with source/grade → paired fixture tests with and without provider context → red-team ledger closure. Documentation memory alone is not admissible evidence.
|
|
37
|
+
|
|
24
38
|
## Running Multiple Providers at Once
|
|
25
39
|
|
|
26
40
|
Pi does not keep a single global active provider for running agents. Each Pi process/session has its own selected model, and `auth.json` can hold credentials for many providers at the same time. After logging in to both subscription providers, start separate terminals with explicit provider or model selection:
|
package/docs/scout.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# FastContext scout
|
|
2
|
+
|
|
3
|
+
Pi can delegate broad repository exploration to a bounded read-only scout through the `context_scout` tool. The scout runs a fresh subagent with only `read`, `grep`, and `find`, then returns a short summary plus validated `file:line` citations. Treat scout output like other tool output: use it as evidence, then read the cited ranges yourself before editing.
|
|
4
|
+
|
|
5
|
+
## Install the reference local model
|
|
6
|
+
|
|
7
|
+
One-step path: run `/models suggest`, choose `FastContext-1.0-4B`, let pi pull and probe it, then confirm the scout role. The assignment writes `scout.model` and sets `scout.enabled = true` only after the `scout_auto` exam passes.
|
|
8
|
+
|
|
9
|
+
Manual fallback: pull the verified Q4 GGUF tag:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
ollama pull hf.co/KikoCis/FastContext-1.0-4B-longctx-imatrix-GGUF:fastcontext4b.Q4_K_M.imx.gguf
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The Hugging Face repository also exposes `fastcontext4b.IQ3_M.imx.gguf`; use the Q4 tag above unless you need the smaller IQ3 quant.
|
|
16
|
+
|
|
17
|
+
After pulling manually:
|
|
18
|
+
|
|
19
|
+
1. Start pi in the target repo.
|
|
20
|
+
2. Run `/models` and confirm the Ollama model appears.
|
|
21
|
+
3. Run `/fitness` against the model before assigning it to `scout.model` or a router tier.
|
|
22
|
+
4. Only assign it if the tool-calls and research-lane probe surfaces pass. Pi's model-adoption gates refuse all-lanes-failed probes automatically.
|
|
23
|
+
|
|
24
|
+
Enable the tool with settings after the probe passes:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"scout": {
|
|
29
|
+
"enabled": true,
|
|
30
|
+
"model": "ollama/hf.co/KikoCis/FastContext-1.0-4B-longctx-imatrix-GGUF:fastcontext4b.Q4_K_M.imx.gguf"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`"model": "auto"` looks for an installed model whose provider/name/id contains `fastcontext`, then requires a host-local `/fitness` report that passes both `research` and `toolCall`. If no model resolves, the model is unprobed, or the required lanes failed, `context_scout` returns `scout unavailable: <cause>` instead of failing the main turn. An explicit `scout.model` pattern is a user choice and resolves without this auto-selection proof gate; scout output is still validated at runtime through citation checks.
|
|
36
|
+
|
|
37
|
+
## 10 GB reference profile
|
|
38
|
+
|
|
39
|
+
A practical 10 GB RAM layout:
|
|
40
|
+
|
|
41
|
+
- FastContext Q4 weights: about 2.5 GB.
|
|
42
|
+
- 32K-64K KV cache: about 1-2 GB.
|
|
43
|
+
- Pi process: about 0.5 GB.
|
|
44
|
+
- Main model: cloud-hosted, or a local Qwen3-4B-Instruct-2507 Q4 model (about 2.5 GB more).
|
|
45
|
+
|
|
46
|
+
Expected peak for scout + pi is roughly 5-6 GB; adding a local 4B main model still fits on a 10 GB machine. Pi warns when a chosen local model's installed size exceeds about 90% of RAM.
|
|
47
|
+
|
|
48
|
+
## Qwen3 chat-template caveat
|
|
49
|
+
|
|
50
|
+
Ollama derives the chat template from the GGUF. Verify tool calling with `/fitness` before trusting the scout. If the probe shows tool-call failures, create a Modelfile with an explicit Qwen3 template and probe that model instead:
|
|
51
|
+
|
|
52
|
+
```modelfile
|
|
53
|
+
FROM hf.co/KikoCis/FastContext-1.0-4B-longctx-imatrix-GGUF:fastcontext4b.Q4_K_M.imx.gguf
|
|
54
|
+
TEMPLATE """{{- if .System }}<|im_start|>system
|
|
55
|
+
{{ .System }}<|im_end|>
|
|
56
|
+
{{ end }}{{- range .Messages }}<|im_start|>{{ .Role }}
|
|
57
|
+
{{ .Content }}<|im_end|>
|
|
58
|
+
{{ end }}<|im_start|>assistant
|
|
59
|
+
"""
|
|
60
|
+
PARAMETER temperature 0
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
ollama create fastcontext-qwen3-tools -f Modelfile
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Probe `ollama/fastcontext-qwen3-tools` with `/fitness` before assigning it.
|
|
70
|
+
|
|
71
|
+
## Router cheap-tier recipe
|
|
72
|
+
|
|
73
|
+
FastContext is a scout, not a solver. With `modelRouter.fitnessGate` enabled, a FastContext-shaped report that passes `research` + `toolCall` but fails `worker` remains eligible for the cheap tier and is structurally excluded from medium/expensive solver tiers. Mutating turns must still escalate out of the cheap tier before write/edit/bash changes; keep the medium or expensive tier on a solver model.
|
package/docs/settings.md
CHANGED
|
@@ -116,18 +116,30 @@ Hard stops still require explicit foreground approval even in `full`: publishing
|
|
|
116
116
|
|
|
117
117
|
| Setting | Type | Default | Description |
|
|
118
118
|
|---------|------|---------|-------------|
|
|
119
|
-
| `modelRouter.enabled` | boolean | `false` | Enable deterministic cheap/expensive model routing |
|
|
119
|
+
| `modelRouter.enabled` | boolean | `false` | Enable deterministic cheap/medium/expensive model routing |
|
|
120
|
+
| `modelRouter.fitnessGate` | boolean | `false` | Opt-in subtractive gate: when a tier model has a host-local failed probe for its router lanes, skip or fall back instead of routing to it; unprobed tier models still route |
|
|
120
121
|
| `modelRouter.cheapModel` | string | - | Model pattern for read-only, research, explanation, and question turns |
|
|
121
|
-
| `modelRouter.
|
|
122
|
+
| `modelRouter.mediumModel` | string | - | Model pattern for scoped implementation/planning turns |
|
|
123
|
+
| `modelRouter.expensiveModel` | string | - | Model pattern for high-impact, modify, implementation, and escalated tool-heavy turns |
|
|
122
124
|
| `modelRouter.learningModel` | string | `"active"` | Model pattern for background reflection, learn, and skill-creator work; `"active"` uses the current session model |
|
|
125
|
+
| `failover.subscriptionHop` | boolean | `true` | Allow subscription/OAuth quota failures to switch once to an authenticated provider default; metered/API-key quota failures always halt for explicit user choice |
|
|
123
126
|
|
|
124
|
-
Use `/settings` → **Model Router** to configure these fields globally or for the current project's `.pi/settings.json`. `/session` and `/usage` show the active router state and
|
|
127
|
+
Use `/settings` → **Model Router** to configure these fields globally or for the current project's `.pi/settings.json`. `/session` and `/usage` show the active router state, diagnostics, and per-tier fitness when the gate is enabled. Profile files can also include a `modelRouter` block so a situation can carry its own cheap, medium, expensive, and learning/reflection models together with its model, thinking level, soul, and resource filters.
|
|
128
|
+
|
|
129
|
+
Fitness applicability is intentionally split by autonomy level:
|
|
130
|
+
|
|
131
|
+
- Class A autonomous adoption requires proof on this host: executor direct uses `toolCall`, curation uses `digest`, and scout `"auto"` uses `research` + `toolCall`.
|
|
132
|
+
- Class B routed turns are subtractive and opt-in via `modelRouter.fitnessGate`: cheap uses `research` + `toolCall`; medium/expensive use `worker` + `toolCall`; the routing judge uses parsed `judge` output. Unprobed tier models pass.
|
|
133
|
+
- Compaction summarizer auto-selection is always-on subtractive composition: when `compaction.model` is `auto`, a router cheap model with a probed failed `digest` lane falls back to the session model; unprobed cheap models still pass, and exhausted explicit/cheap summarizers fall back visibly.
|
|
134
|
+
- Class C explicit user choices are sovereign: explicit `/model` and explicit `scout.model` patterns are not router-gated, except for the existing all-lanes-failed adoption backstop and runtime output checks.
|
|
125
135
|
|
|
126
136
|
```json
|
|
127
137
|
{
|
|
128
138
|
"modelRouter": {
|
|
129
139
|
"enabled": true,
|
|
140
|
+
"fitnessGate": true,
|
|
130
141
|
"cheapModel": "openrouter/google/gemini-flash-latest",
|
|
142
|
+
"mediumModel": "anthropic/claude-sonnet-4-5",
|
|
131
143
|
"expensiveModel": "openai-codex/gpt-5.5",
|
|
132
144
|
"learningModel": "anthropic/claude-haiku-4-5"
|
|
133
145
|
}
|
|
@@ -177,6 +189,7 @@ When enabled, Auto Learn keeps a small shared state file for visibility/cooldown
|
|
|
177
189
|
| Setting | Type | Default | Description |
|
|
178
190
|
|---------|------|---------|-------------|
|
|
179
191
|
| `compaction.enabled` | boolean | `true` | Enable auto-compaction |
|
|
192
|
+
| `compaction.model` | string | `"auto"` | Summarizer model pattern. `auto` follows router cheap when available, but always consults exhausted-provider state and the subtractive `digest` fitness surface before falling back visibly to the session model. |
|
|
180
193
|
| `compaction.reserveTokens` | number | `16384` | Tokens reserved for LLM response |
|
|
181
194
|
| `compaction.keepRecentTokens` | number | `20000` | Recent tokens to keep (not summarized) |
|
|
182
195
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.4",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.4",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "^0.0.26"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-with-deps",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-with-deps",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.4",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|
|
@@ -26,7 +26,7 @@ if (process.env.MY_ANTHROPIC_KEY) {
|
|
|
26
26
|
// Model registry with no custom models.json
|
|
27
27
|
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
28
28
|
|
|
29
|
-
const model = getModel("anthropic", "claude-sonnet-4-
|
|
29
|
+
const model = getModel("anthropic", "claude-sonnet-4-5");
|
|
30
30
|
if (!model) throw new Error("Model not found");
|
|
31
31
|
|
|
32
32
|
// In-memory settings with overrides
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caupulican/pi-adaptative",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@caupulican/pi-adaptative",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.4",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@caupulican/pi-agent-core": "^0.81.
|
|
13
|
-
"@caupulican/pi-ai": "^0.81.
|
|
14
|
-
"@caupulican/pi-tui": "^0.81.
|
|
12
|
+
"@caupulican/pi-agent-core": "^0.81.4",
|
|
13
|
+
"@caupulican/pi-ai": "^0.81.4",
|
|
14
|
+
"@caupulican/pi-tui": "^0.81.4",
|
|
15
15
|
"@ff-labs/fff-node": "0.9.6",
|
|
16
16
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
17
17
|
"chalk": "5.6.2",
|
|
@@ -475,11 +475,11 @@
|
|
|
475
475
|
}
|
|
476
476
|
},
|
|
477
477
|
"node_modules/@caupulican/pi-agent-core": {
|
|
478
|
-
"version": "0.81.
|
|
479
|
-
"resolved": "https://registry.npmjs.org/@caupulican/pi-agent-core/-/pi-agent-core-0.81.
|
|
478
|
+
"version": "0.81.4",
|
|
479
|
+
"resolved": "https://registry.npmjs.org/@caupulican/pi-agent-core/-/pi-agent-core-0.81.4.tgz",
|
|
480
480
|
"license": "MIT",
|
|
481
481
|
"dependencies": {
|
|
482
|
-
"@caupulican/pi-ai": "^0.81.
|
|
482
|
+
"@caupulican/pi-ai": "^0.81.4",
|
|
483
483
|
"ignore": "7.0.5",
|
|
484
484
|
"typebox": "1.1.38",
|
|
485
485
|
"yaml": "2.9.0"
|
|
@@ -489,8 +489,8 @@
|
|
|
489
489
|
}
|
|
490
490
|
},
|
|
491
491
|
"node_modules/@caupulican/pi-ai": {
|
|
492
|
-
"version": "0.81.
|
|
493
|
-
"resolved": "https://registry.npmjs.org/@caupulican/pi-ai/-/pi-ai-0.81.
|
|
492
|
+
"version": "0.81.4",
|
|
493
|
+
"resolved": "https://registry.npmjs.org/@caupulican/pi-ai/-/pi-ai-0.81.4.tgz",
|
|
494
494
|
"license": "MIT",
|
|
495
495
|
"dependencies": {
|
|
496
496
|
"@anthropic-ai/sdk": "0.91.1",
|
|
@@ -512,8 +512,8 @@
|
|
|
512
512
|
}
|
|
513
513
|
},
|
|
514
514
|
"node_modules/@caupulican/pi-tui": {
|
|
515
|
-
"version": "0.81.
|
|
516
|
-
"resolved": "https://registry.npmjs.org/@caupulican/pi-tui/-/pi-tui-0.81.
|
|
515
|
+
"version": "0.81.4",
|
|
516
|
+
"resolved": "https://registry.npmjs.org/@caupulican/pi-tui/-/pi-tui-0.81.4.tgz",
|
|
517
517
|
"license": "MIT",
|
|
518
518
|
"dependencies": {
|
|
519
519
|
"get-east-asian-width": "1.6.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caupulican/pi-adaptative",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.4",
|
|
4
4
|
"description": "Adaptive fork of Pi coding agent for self-evolving agent harness experiments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@caupulican/pi-agent-core": "^0.81.
|
|
45
|
-
"@caupulican/pi-ai": "^0.81.
|
|
46
|
-
"@caupulican/pi-tui": "^0.81.
|
|
44
|
+
"@caupulican/pi-agent-core": "^0.81.4",
|
|
45
|
+
"@caupulican/pi-ai": "^0.81.4",
|
|
46
|
+
"@caupulican/pi-tui": "^0.81.4",
|
|
47
47
|
"@ff-labs/fff-node": "0.9.6",
|
|
48
48
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
49
49
|
"chalk": "5.6.2",
|