Merge remote-tracking branch 'origin/codex/package-readme-limitations-audit-20260712' into codex/model-experience-readmes-20260712
# Conflicts: # docs/cookbook/adding-a-package.md # docs/rfc/INDEX.md # package.json # packages/AGENTS.md # packages/bash/bash-sandbox/README.md # packages/sandbox/sandbox-local/README.md # packages/sandbox/sandbox/README.md # packages/session-persistence/session-persistence-sqlite/README.md # packages/support/acp-snapshot/README.md # packages/ui/app-boot/README.md # packages/ui/user-approval/README.md # packages/workflow/tool-workflow/README.md
This commit is contained in:
@@ -35,6 +35,7 @@ Declaration-merged into `SessionEventMap` (log-only, like `compact/*` — NOT a
|
||||
|
||||
Like every event they must sit inside an open turn. The mid-turn points (`PreToolUse`/`PostToolUse`/`UserPromptSubmit`/`Stop`) fire inside the loop's open turn by construction; `SessionStart` gets no `hook/*` record (its injected `context/message` is the durable evidence) — see the hooks RFC.
|
||||
|
||||
## Input rewrite is parsed but not honored
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
`HookOutput.updatedInput` carries a hook's requested tool-input rewrite (CC `updatedInput`), but the harness does not honor it yet — input rewrite is a deferred consistency-design problem ([the pre-tool-input-rewrite RFC](../../../docs/rfc/proposed/feature/2026-06-30-pre-tool-input-rewrite.md)). A bridge logs + warns when a hook sets it. See `src/types.ts` for the full contracts.
|
||||
- **`HookOutput.updatedInput` is parsed but not honored** — input rewrite is a deferred consistency-design problem ([the pre-tool-input-rewrite RFC](../../../docs/rfc/proposed/feature/2026-06-30-pre-tool-input-rewrite.md)); a bridge logs + warns when a hook sets it. See `src/types.ts` for the full contracts.
|
||||
- **An invalid matcher regex matches nothing, silently** — `matchesMatcher` never throws; surfacing the error needs a diagnostic-returning variant or parse-time validation (`TODO(matcher-diagnostics)`).
|
||||
|
||||
@@ -57,8 +57,11 @@ The matcher subject is the tool name (`PreToolUse`/`PostToolUse`), the session s
|
||||
|
||||
Injected context carries an explicit `{ kind: 'plugin', plugin: 'hooks-claude' }` source. `agent.inject()` defaults a missing source to `{ kind: 'user' }`, which would mislabel plugin context as a user prompt — so the bridge always names itself.
|
||||
|
||||
## Deferred (faithful-but-degraded)
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **`updatedInput` (tool-input rewrite)** is logged + warned, **not honored** — input rewrite is a deferred consistency-design problem ([the pre-tool-input-rewrite RFC](../../../docs/rfc/proposed/feature/2026-06-30-pre-tool-input-rewrite.md)).
|
||||
- **`systemMessage`** (a hook's user-facing warning) is logged + warned, **not surfaced** — there is no user-message channel on these seams yet (only model-facing `additionalContext`). The shared merge collects it; the bridge does not yet render it.
|
||||
- **Stop loop-guard.** CC breaks an infinite force-continue with `stop_hook_active` (true once a Stop hook has fired this run) plus a max-consecutive cap; both are deferred (`TODO(stop-loop-guard)`). Today `stop_hook_active` is always `false`, so a Stop hook that unconditionally blocks would force-continue every step — a hook author must self-limit until the guard lands.
|
||||
- **`{"continue": false}` is recorded, not enforced** — the merge computes the `stop`/`stopReason` outcome and the `hook/result` event records decision `stop`, but the run is not halted (`TODO(hook-continue-false)`).
|
||||
- **`SessionStart` cannot gate the first turn** — `agent/session-start` is a synchronous emit, so a hook's injected context lands best-effort before turn 1 (`TODO(session-start-gating)`).
|
||||
- **Hook config is process-level** — one `configPath` parsed at load for the whole process; per-session discovery of a project-local config is deferred (`TODO(per-session-hook-config)`).
|
||||
|
||||
@@ -61,8 +61,10 @@ A tool call's payload carries the real `tool_name` (the same value the matcher t
|
||||
|
||||
Injected context carries an explicit `{ kind: 'plugin', plugin: 'hooks-codex' }` source (`agent.inject()` would otherwise default it to `{ kind: 'user' }`).
|
||||
|
||||
## Deferred
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
**Stop loop-guard** (`TODO(stop-loop-guard)`): as in CC, a Stop hook that unconditionally blocks would force-continue every step (`stop_hook_active` is always `false` here); the loop-guard is deferred. A hook author must self-limit until it lands.
|
||||
|
||||
**`systemMessage`**: a hook's user-facing warning is logged + warned, not surfaced — there is no user-message channel on these seams yet (only model-facing `additionalContext`).
|
||||
- **Stop loop-guard** (`TODO(stop-loop-guard)`) — as in CC, a Stop hook that unconditionally blocks would force-continue every step (`stop_hook_active` is always `false` here); the loop-guard is deferred, and a hook author must self-limit until it lands.
|
||||
- **`systemMessage`** — a hook's user-facing warning is logged + warned, not surfaced; there is no user-message channel on these seams yet (only model-facing `additionalContext`).
|
||||
- **`{"continue": false}` is recorded, not enforced** — the `hook/result` event records decision `stop`, but the run is not halted (`TODO(hook-continue-false)`).
|
||||
- **`SessionStart` cannot gate the first turn** — `agent/session-start` is a synchronous emit with a detached continuation, so a hook's injected context lands best-effort before turn 1 (`TODO(session-start-gating)`).
|
||||
- **Hook config is process-level** — one `configPath` parsed at load for the whole process; per-session discovery of a project-local config is deferred (`TODO(per-session-hook-config)`).
|
||||
|
||||
Reference in New Issue
Block a user