Skip to content

Fix oversized Mainline hook context injection - #203

Merged
catoncat merged 2 commits into
mainline-org:mainfrom
jiangge:feat/pi-hooks
Jul 27, 2026
Merged

Fix oversized Mainline hook context injection#203
catoncat merged 2 commits into
mainline-org:mainfrom
jiangge:feat/pi-hooks

Conversation

@jiangge

@jiangge jiangge commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Prevent oversized Mainline hook context from exhausting model prompts

Summary

  • Replace full session-start status and sync payloads with compact, actionable summaries.
  • Preserve the active intent ID and goal, agent authority boundary, important counts, omitted-item counts, and commands for loading details on demand.
  • Enforce UTF-8-safe renderer budgets of 32 KiB for session-start context and 16 KiB for per-prompt context.
  • Add defensive Pi extension limits for subprocess stdout, individual hook context, and combined injected context.
  • Add regression fixtures containing hundreds of turns, uncovered commits, and proposals without logging omitted content.

The shared renderer change also protects Claude Code, Codex, and Cursor. On the same large repository fixture, all four agents now receive approximately 4 KiB of session-start context instead of approximately 6.7 MB.

Validation

  • go test ./...
  • go vet ./...
  • go test -race ./internal/hooks/...
  • git diff --check
  • End-to-end opencad hook-size verification:
    • Before: approximately 6,728,087 bytes of injected context
    • After: 3,992 bytes
    • Required active-intent, authority, omission-count, and follow-up-command fields remain present

Review notes

The core incident is fixed for every agent using the shared renderer. The Pi extension additionally provides host-side defense in depth. Follow-up hardening opportunities identified during review—avoiding full in-memory serialization before compaction, adding a common host-output boundary for other agents, and bounding Pi stderr—are non-blocking and outside this fix's scope.

Authoritative Mainline intent record

Mainline Intent

Intent: int_5a162dfc
Status: proposed
Title: 限制 Pi hook 上下文注入体积

What changed

将 session-start 的完整 status/sync JSON 改为保留 active intent、authority、计数和下一步命令的紧凑摘要;对大型 turns、uncovered、proposals、suggestions、actionable items 与任意 sync 数组设置条数/字符串限制和 omitted 计数;在通用 renderer 增加 32KiB/16KiB 硬预算,并在 Pi extension 增加 stdout、单段 context、合并 context 三层防御性上限。新增大型 fixture,验证预算、关键信息保留和省略正文不泄露。

Why

Pi 会把 hook 返回的 systemPromptAppend 拼入模型 system prompt。大型 active intent 曾让 session-start 返回约 6.7MB 文本,使空白新会话也超过 1M token 上下文。需要默认按需加载详情,并在 renderer 与宿主 extension 两端建立确定性安全边界。

Decisions

  • session-start 应注入多少 Mainline 状态: 默认注入紧凑、可执行的状态摘要,省略大型历史集合并提供 omitted 数量与 mainline status/preflight/context/show 命令 (agent 仍能看到 active intent id/goal、authority stop line 和关键计数,同时避免把完整 turns、diff/file 列表与 uncovered 详情复制进 system prompt)
    • Rejected: 继续序列化完整 status/sync JSON
    • Rejected: 永久卸载 Pi integration 作为长期方案
  • 上下文预算应在哪一层执行: 通用 dispatcher renderer 和 Pi extension 双层防护 (renderer 负责正常情况下的紧凑语义和确定性预算;Pi extension 可防御旧二进制、未来 renderer 回归或异常超大 stdout)
    • Rejected: 只依赖 Pi extension 最终截断
    • Rejected: 只限制当前 status 数组而不设置最终硬上限
  • 超限时如何退化: 注入短 warning 和按需查询命令,而不是无提示丢弃或保留任意前缀 (让 agent 明确知道详情被省略,并能恢复必要上下文)

Subsystems: hooks dispatcher context renderer, Pi coding-agent extension, hook context regression tests

@catoncat
catoncat merged commit 2b62f2e into mainline-org:main Jul 27, 2026
5 checks passed
@github-actions

Copy link
Copy Markdown

Mainline fork PR import

Status: Mainline fork PR import failed

unknown error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants