docs: reserve seam for complete capabilities
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/hooks/hooks-codex/README.md
|
||||
README.md: 60dd1d098966aad6ccdb0957ee223b9843db499f
|
||||
README.zh.md: 80162e9fb82eb0f9e358c3d14bd24bf4bfeddaca
|
||||
README.md: f8e0684e0bf4eafadcb31d8c82dde177411db2bf
|
||||
README.zh.md: d278e78204c1bd320980420b506135997cd3a4cc
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
A cordis plugin that runs the supported subset of a user's existing **Codex** hook config on the harness's canonical interception seams. The **Codex dialect** half of the hooks subsystem. The dialect-agnostic primitives come from [`@deepseek-ai/dsh-hook-protocol`](../hook-protocol/README.md); this bridge owns the Codex-shaped payloads, matcher mode, and decision mapping.
|
||||
A cordis plugin that runs the supported subset of a user's existing **Codex** hook config on the harness's canonical interception points. The **Codex dialect** half of the hooks subsystem. The dialect-agnostic primitives come from [`@deepseek-ai/dsh-hook-protocol`](../hook-protocol/README.md); this bridge owns the Codex-shaped payloads, matcher mode, and decision mapping.
|
||||
|
||||
This bridge implements a deliberate subset of Codex's current hook protocol:
|
||||
|
||||
@@ -12,7 +12,7 @@ This bridge implements a deliberate subset of Codex's current hook protocol:
|
||||
- **No Codex plugin env injection and no config-time placeholder substitution** (the command still receives the executor's environment and runs through its shell).
|
||||
- **No pre-tool approval or rewrite path** — a hook can block, but the bridge does not pre-approve or replace tool input.
|
||||
|
||||
A native cordis plugin could do everything this bridge does, more powerfully; the bridge exists only as a compatibility path for the mapped Codex subset (see [the interception-seams Agent Note](../../../.agents/notes/implemented/feature/2026-06-30-interception-seams.md)).
|
||||
A native cordis plugin could do everything this bridge does, more powerfully; the bridge exists only as a compatibility path for the mapped Codex subset (see [the interception extension-points Agent Note](../../../.agents/notes/implemented/feature/2026-06-30-interception-extension-points.md)).
|
||||
|
||||
## Config
|
||||
|
||||
@@ -38,9 +38,9 @@ The config is parsed **once** at load. `configPath` is **process-level** — a r
|
||||
|
||||
The hooks themselves run in the agent's session workspace: for the agent-scoped points the bridge passes the session's `cwd` as the hook process's working directory, so a hook operates in the user's project tree, not the server launch dir.
|
||||
|
||||
## Hook points → seam Decisions
|
||||
## Hook points → typed Decisions
|
||||
|
||||
| Codex hook | Harness seam | Mapping |
|
||||
| Codex hook | Harness point | Mapping |
|
||||
|---|---|---|
|
||||
| `SessionStart` | `agent/session-start` (emit) | a plain-stdout hook's output → additionalContext → `agent.inject()` |
|
||||
| `UserPromptSubmit` | `agent/pre-step` (waterfall) | `block` (exit 2) → `PreStepDecision.reject`; additionalContext-only → delegate via `next()` then append a separately sourced message to a downstream `enter` decision |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
一个 Cordis 插件,在 harness 的规范拦截 seam 上运行用户现有 **Codex** hook 配置的受支持子集。它是 hooks 子系统中采用 **Codex 方言** 的一侧。方言无关原语来自 [`@deepseek-ai/dsh-hook-protocol`](../hook-protocol/README.md);该桥接负责处理 Codex 形状的 payload、matcher 模式和决策映射。
|
||||
一个 Cordis 插件,在 harness 的规范拦截点上运行用户现有 **Codex** hook 配置的受支持子集。它是 hooks 子系统中采用 **Codex 方言** 的一侧。方言无关原语来自 [`@deepseek-ai/dsh-hook-protocol`](../hook-protocol/README.md);该桥接负责处理 Codex 形状的 payload、matcher 模式和决策映射。
|
||||
|
||||
该桥接实现 Codex 当前 hook 协议的一个明确子集:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
- **没有 Codex 插件 env 注入,也没有配置时 placeholder 替换**(命令仍会接收执行器环境,并通过其 shell 运行)。
|
||||
- **没有工具前审批或改写路径**:hook 可以阻塞,但桥接不会预审批或替换工具输入。
|
||||
|
||||
原生 Cordis 插件可以完成此桥接的所有工作,并且功能更强;该桥接只是已映射 Codex 子集的兼容路径(见 [拦截 seam Agent Note](../../../.agents/notes/implemented/feature/2026-06-30-interception-seams.md))。
|
||||
原生 Cordis 插件可以完成此桥接的所有工作,并且功能更强;该桥接只是已映射 Codex 子集的兼容路径(见 [拦截扩展点 Agent Note](../../../.agents/notes/implemented/feature/2026-06-30-interception-extension-points.md))。
|
||||
|
||||
## 配置
|
||||
|
||||
@@ -38,9 +38,9 @@ const config: Config = {
|
||||
|
||||
hook 本身会在 agent(智能体)的会话工作区中运行:对 agent scope 点,桥接会将会话 `cwd` 作为 hook 进程工作目录,因此 hook 作用于用户项目树,而非服务器启动目录。
|
||||
|
||||
## Hook 点 → seam Decision
|
||||
## Hook 点 → 类型化 Decision
|
||||
|
||||
| Codex hook | Harness seam | 映射 |
|
||||
| Codex hook | Harness 点 | 映射 |
|
||||
|---|---|---|
|
||||
| `SessionStart` | `agent/session-start`(emit) | 纯 stdout hook 的输出 → additionalContext → `agent.inject()` |
|
||||
| `UserPromptSubmit` | `agent/pre-step`(waterfall,瀑布式事件) | `block`(退出码 2)→ `PreStepDecision.reject`;仅 additionalContext → 通过 `next()` 委托,再向下游 `enter` 决策追加一条单独标记来源的消息 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Bridge for unmodified Codex command hooks on harness interception seams. It
|
||||
* Bridge for unmodified Codex command hooks on harness interception points. It
|
||||
* supports five points (SessionStart, prompt/tool pre/post, Stop), regex-only
|
||||
* matchers, snake_case payloads without a trailing newline, no hook environment
|
||||
* or command substitution, and no pre-tool approval or rewrite path; only
|
||||
@@ -156,7 +156,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
}
|
||||
outputs.push(output)
|
||||
// Execution and decision mapping remain in each bridge so dialect
|
||||
// differences stay explicit at their owning seam.
|
||||
// differences stay explicit at their owning extension point.
|
||||
/* jscpd:ignore-start */
|
||||
if (output.systemMessage !== undefined) {
|
||||
ctx.logger.warn(`hooks-codex: ${point} hook emitted a systemMessage, which is not yet surfaced (ignored)`)
|
||||
@@ -169,7 +169,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
return mergeHookOutputs(outputs)
|
||||
}
|
||||
|
||||
// TODO(hook-continue-false): `merged.stop` is logged but needs a run-level halt seam.
|
||||
// TODO(hook-continue-false): `merged.stop` is logged but needs a run-level halt mechanism.
|
||||
|
||||
function contextFrom(merged: MergedHookOutcome): UserMessage | undefined {
|
||||
if (merged.additionalContext.length === 0) return undefined
|
||||
@@ -279,7 +279,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
function lastTurn(agent: Agent | undefined): number {
|
||||
if (!agent) return 0
|
||||
const last = [...agent.session.events].findLast(e => e.type === 'turn/start')
|
||||
/* v8 ignore next -- agent-present turnBase callers are tool/stop seams inside an open turn. */
|
||||
/* v8 ignore next -- agent-present turnBase callers are tool/stop extension points inside an open turn. */
|
||||
return last?.type === 'turn/start' ? last.data.turn : 0
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ export function defineCoverageCases(groups: CoverageGroup | readonly CoverageGro
|
||||
})
|
||||
|
||||
it('a {"continue":false} hook is RECORDED as "stop" but does not halt the run (TODO(hook-continue-false))', async () => {
|
||||
// Honoring `continue:false` is deferred — the seams have no hard-halt
|
||||
// Honoring `continue:false` is deferred — the extension points have no hard-halt
|
||||
// primitive. Assert the LOG records the halt request AND that the run is not
|
||||
// actually halted (the tool still runs, the turn completes).
|
||||
const d = dir()
|
||||
|
||||
Reference in New Issue
Block a user