Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable AgentTape changes are documented here.

## 0.4.1 - 2026-08-25

- Cover all 11 current Codex hook events, including prompts, compaction, and subagent lifecycle events.
- Preserve event ordering when hook processes write concurrently.
- Recover real Bash exit status from the current Codex transcript when `PostToolUse` omits it.
- Redact prompt and lifecycle details, omit transcript paths, and shorten home-directory paths in portable tapes.
- Add a capture verifier and a directory-level regression command used by CI.
- Expand the capture skill into the complete inspect, fork, save, and offline-test workflow.

## 0.4.0 - 2026-08-23

- Add `rate_limited` (HTTP 429) structural failure injection with configurable `retryAfterSeconds`.
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ save assertions → run offline in CI
## Why AgentTape

- **Failure artifact, not another dashboard.** A `.tape` is portable evidence you can inspect, review, share, and commit with a bug fix.
- **Codex-native capture.** Bundled hooks record supported lifecycle, permission, and tool events after the user reviews and trusts them—no application instrumentation required.
- **Codex-native capture.** Bundled hooks cover the 11 current Codex lifecycle, prompt, compaction, subagent, permission, and local tool events after the user reviews and trusts them—no application instrumentation required.
- **Local and privacy-conscious.** Runtime captures stay inside the active project, and common secret-bearing fields are recursively redacted before export.
- **Controlled failure injection.** Fork recorded evidence with permission-denied, timeout, rate-limited, malformed-JSON, or truncated-response results.
- **Offline regression tests.** Structural replay and assertions use captured evidence with zero model calls and zero live tool calls.
Expand Down Expand Up @@ -61,12 +61,13 @@ AgentTape exposes four MCP tools:
Run a saved regression locally or in CI:

```bash
node plugins/agenttape/scripts/agenttape.mjs test \
tests/agenttape/fixture_permission_denied-timeout.tape
node plugins/agenttape/scripts/agenttape.mjs test tests/agenttape
```

Passing assertions exit with code `0`. Validation or assertion failures exit nonzero, and captured comparison values are omitted from failure output.

The repository CI runs the same directory command through `npm run test:tapes`, so every reviewed `.tape` added under `tests/agenttape/` becomes an offline regression automatically.

## What a `.tape` captures

Tape v1 keeps the evidence needed for structural debugging:
Expand Down
21 changes: 11 additions & 10 deletions docs/DEVELOPMENT_STATUS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# AgentTape 开发状态

更新时间:2026-08-23
版本状态:0.4.0 / 已公开发布并完成 Git marketplace 实机验收
当前里程碑:扩展故障注入与顺序断言能力
更新时间:2026-08-25
版本状态:0.4.1 / 已完成真实捕获、CI 闭环和 Git marketplace 实机验收
当前里程碑:让真实 Codex 失败稳定变成可提交的离线回归

## 一句话状态

Expand All @@ -12,19 +12,20 @@ AgentTape 已完成本地“捕获 → 检查 → 分叉 → 注入 → 结构

| 领域 | 状态 | 已验证事实 |
| --- | --- | --- |
| Hooks recorder / redaction | 完成 | 支持本地 Codex 生命周期、权限和工具事件,输出 redacted tape v1 |
| Hooks recorder / redaction | 完成 | 覆盖当前 11 类 Codex Hook;真实 Bash 退出码、提示词脱敏和 24 路并发写入均已验证 |
| Tape schema / fixtures | 完成 | JSON Schema、validator、3 个合成 fixture |
| Bundled stdio MCP | 完成 | `list_tapes`、`inspect_tape`、`fork_run`、`save_regression` |
| Structural replay | 完成 | 5 种 recorded-result injection(含 rate_limited 429),0 model calls / 0 live tools |
| Assertions / CLI | 完成 | 7 类断言(含 tool_order 时序断言);通过为 0,失败为非零且 diff 脱敏 |
| Assertions / CLI | 完成 | 7 类断言(含 tool_order);`test tests/agenttape` 批量执行全部已保存回归 |
| Repository marketplace | 完成 | marketplace 名为 `agenttape`,插件源为 `./plugins/agenttape` |
| Plugin validation | 完成 | 当前 Codex 插件校验器、单测和重新安装后的实机 MCP 调用通过 |
| Open-source metadata | 完成 | MIT、README、SECURITY、CONTRIBUTING、Code of Conduct、Changelog |
| Public GitHub release | 完成 | `jiangkoumo/agenttape`、`v0.4.0` Release 和公共 GitHub Actions 均已验证 |
| Public GitHub release | 完成 | `jiangkoumo/agenttape`、`v0.4.1` Release 和公共 GitHub Actions 均已验证 |

## 关键验证证据

- UI 从合成的 permission-denied tape 加载工具失败,并可生成 timeout 分支。
- 真实 Codex CLI 项目执行 `npm test` 并退出 7;capture 状态为 failed,5 个实际 Hook 事件连续,伪密钥未出现在 tape 中。
- 同一真实 capture 经 `list_tapes → inspect_tape → fork_run → save_regression` 保存后,由目录级 runner 输出 `PASS 1/1 regression tapes`。
- 保存后的回归由 CLI 执行:`PASS tape_regression_9f680719a4a7 4/4 assertions`。
- 从公开 GitHub `v0.3.1` 全新安装后,只读 Codex 进程经工具搜索实机调用 `agenttape/list_tapes`,返回 `tape_fixture_permission_denied`。
- MCP 路径遍历、符号链接、超大文件、无效 schema、重复写入和覆盖请求均有拒绝测试。
Expand Down Expand Up @@ -55,10 +56,10 @@ record-hook.mjs

1. 公共仓库 `github.com/jiangkoumo/agenttape` 已创建并推送。
2. GitHub Actions 的 `plugin-release` 和 `optional-surfaces` 检查均通过。
3. 带注释的 `v0.3.1` 标签和 GitHub Release 已发布。
4. 已从公共标签运行 `codex plugin marketplace add jiangkoumo/agenttape --ref v0.3.1` 并安装 `agenttape@agenttape`。
3. 带注释的 `v0.4.1` 标签和 GitHub Release 已发布。
4. 已从公共标签运行 `codex plugin marketplace add jiangkoumo/agenttape --ref v0.4.1` 并安装 `agenttape@agenttape`。
5. GitHub 安装的插件已在新只读 Codex 进程中完成 `list_tapes` MCP 实机调用。

`v0.3.0` 首次发布缺少被 Git 跟踪的预构建 MCP bundle;`v0.3.1` 已修复,并在 CI 中新增 bundle 跟踪检查以防回归。
0.4.1 的完整验收证据见 [`V0_4_1_VALIDATION.md`](./V0_4_1_VALIDATION.md)。下一阶段不再继续堆网站功能,而是选择 2–3 个真实 Codex 工程积累 regression fixture,并根据实际失败类型扩展断言和 replay 边界。

Branch Canvas 托管和远程 HTTP MCP 保留为可选后续方向,不计入上述完成条件。
15 changes: 9 additions & 6 deletions docs/HANDOFF.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# AgentTape 项目交接

更新时间:2026-08-23
当前阶段:0.4.0 开源 Codex 插件已发布
更新时间:2026-08-25
当前阶段:0.4.1 开源 Codex 插件已完成真实项目和 CI 闭环验收

## 正式产品

- Codex 插件:`plugins/agenttape/`。
- Git marketplace:`.agents/plugins/marketplace.json`,公开名称为 `agenttape`。
- Hooks recorder、redaction、tape v1 schema、validator 和合成 fixtures。
- 覆盖当前 11 类 Codex Hook 的 recorder、redaction、tape v1 schema、validator 和 fixtures。
- Bundled stdio MCP:`list_tapes`、`inspect_tape`、`fork_run`、`save_regression`。
- Structural replay、5 种 injection、7 类 assertion runner 和 CLI exit semantics。
- MIT License、开源贡献规范、安全政策和 GitHub Actions。
Expand All @@ -19,6 +19,7 @@ Branch Canvas、Sites 构建适配和远程 HTTP MCP 是可选开发组件。它
```bash
npm ci
npm run test:plugin-release
npm run test:tapes
npm run build:plugin
git diff --check
```
Expand All @@ -38,7 +39,7 @@ git diff --check
## 已完成发布

- 公共仓库:`https://github.com/jiangkoumo/agenttape`
- 当前正式版:`v0.4.0`
- 当前正式版:`v0.4.1`
- 安装源:`codex plugin marketplace add jiangkoumo/agenttape`
- 插件安装:`codex plugin add agenttape@agenttape`
- 公共 CI、GitHub Release、隔离安装和真实 Codex MCP 调用均已通过。
Expand All @@ -47,6 +48,8 @@ git diff --check

## 后续方向

1. 收集真实 Codex 项目的 capture 与回归测试反馈。
2. 扩展受支持的 Hook 事件和结构化 replay 断言,同时保持 tape v1 向后兼容。
1. 在 2–3 个真实 Codex 工程中积累经过人工检查的 regression fixture,优先覆盖权限、超时和外部 API 失败。
2. 根据真实 fixture 扩展结构化 replay 断言,同时保持 tape v1 向后兼容。
3. Branch Canvas、Sites 和远程 HTTP MCP 仅在有明确需求时继续,不作为本地插件安装依赖。

0.4.1 的实际 Bash 退出 7、脱敏、MCP 分叉保存和离线 CI 证据见 [`V0_4_1_VALIDATION.md`](./V0_4_1_VALIDATION.md)。
76 changes: 76 additions & 0 deletions docs/V0_4_1_VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# AgentTape 0.4.1 验收记录

验收日期:2026-08-25

## 目标

本次补丁完成三个可验证目标:覆盖 Codex 当前 11 类 Hook;在真实 Codex 项目中验证失败捕获与脱敏;让保存到 `tests/agenttape/` 的回归文件由本地和 CI 使用同一条命令执行。

## Hook 覆盖

插件现在注册:

- 会话:`SessionStart`、`SessionEnd`
- 提示与压缩:`UserPromptSubmit`、`PreCompact`、`PostCompact`
- 工具与权限:`PreToolUse`、`PostToolUse`、`PermissionRequest`
- 子 Agent:`SubagentStart`、`SubagentStop`
- 回合结束:`Stop`

事件详情统一经过递归脱敏。主 transcript 和子 Agent transcript 的本地路径不写入 tape;只保留是否可用。并发 Hook 写入通过项目内运行时锁串行化,测试覆盖 24 个同时写入者,最终序号连续且无丢失。

## 真实 Codex 项目验证

验证环境:Codex CLI 0.149.0、Node.js 项目、隔离的临时 Git 仓库。

真实任务要求 Codex 执行一个退出码为 7 的 `npm test`。验证中发现,当前 Codex 的 Bash `PostToolUse.tool_response` 只包含输出文本,不包含退出码;AgentTape 因此增加了 transcript 证据回退,只提取匹配 `tool_use_id` 的 `status` 和 `exit_code`,不复制 transcript 内容或路径。

最终捕获结果:

```text
status: failed
events: SessionStart → UserPromptSubmit → PreToolUse → PostToolUse → Stop
failed tool calls: 1
failure: Codex recorded tool exit code 7
redaction marker: present
obvious unredacted secret pattern: false
```

验证命令:

```bash
node plugins/agenttape/scripts/verify-capture.mjs \
--root <real-project> \
--must-fail \
--require-redaction \
--require-event SessionStart \
--require-event UserPromptSubmit \
--require-event PreToolUse \
--require-event PostToolUse \
--require-event Stop
```

验证时使用的是专门构造的伪密钥。验证器确认 `.tape` 中存在脱敏标记,并且没有残留常见的未脱敏 API key 或 Bearer token 模式。该检查不能证明任意自由文本中绝对没有敏感信息,公开分享前仍需人工检查。

## 失败到 CI 的闭环

同一个真实捕获依次通过插件自己的 MCP 工具完成:

1. `list_tapes` 找到失败 tape。
2. `inspect_tape` 确认 Bash 退出码 7、覆盖边界和脱敏状态。
3. `fork_run` 在序号 3 后将序号 4 的结果替换为 timeout;证据为 0 次模型调用、0 次真实工具调用。
4. `save_regression` 写入 `tests/agenttape/real-bash-exit-timeout.tape`,包含 4 条断言。
5. 目录级 runner 输出:

```text
PASS tape_regression_60468d473ef9 4/4 assertions
PASS 1/1 regression tapes
```

仓库通过 `npm run test:tapes` 执行相同的目录级命令。新增的 `.tape` 文件不需要再单独修改 CI 配置。

## 边界

- Hosted tools 不在 Codex 本地 Hook 覆盖范围内。
- Transcript 回退只读取当前会话、当前工具调用的状态和退出码,并限制读取文件尾部大小;它不会把 transcript 作为 artifact 保存。
- Structural replay 在注入的工具结果处停止,不生成新的下游模型推理。
- 以上验证证明当前范围内的结构化捕获和回归流程可用,不代表 bit-exact、完整或 hermetic replay。
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agenttape",
"version": "0.4.0",
"version": "0.4.1",
"description": "Local-first Codex plugin for redacted failure traces and offline regression tests.",
"private": true,
"license": "MIT",
Expand All @@ -14,7 +14,7 @@
"homepage": "https://github.com/jiangkoumo/agenttape#readme",
"type": "module",
"scripts": {
"test": "npm run test:release && npm run test:plugin && npm run test:mcp && npm run test:http-mcp && npm run test:api && npm run test:demo && npm run test:replay && npm run test:regression && npm run test:sites",
"test": "npm run test:release && npm run test:plugin && npm run test:mcp && npm run test:http-mcp && npm run test:api && npm run test:demo && npm run test:replay && npm run test:regression && npm run test:tapes && npm run test:sites",
"dev": "node scripts/run-vite.mjs",
"build": "npm run build:mcp && npm run build:demo && node scripts/run-vite.mjs build && node scripts/prepare-sites-build.mjs && npm run build:http-mcp",
"build:plugin": "npm run build:mcp",
Expand All @@ -31,9 +31,11 @@
"test:demo": "npm run build:demo && node --test tests/demo-data.test.mjs",
"test:replay": "node --test tests/structural-replay.test.mjs",
"test:regression": "node --test tests/assertion-runner.test.mjs",
"test:tapes": "node plugins/agenttape/scripts/agenttape.mjs test tests/agenttape",
"verify:capture": "node plugins/agenttape/scripts/verify-capture.mjs",
"test:sites": "node --test tests/sites-worker.test.mjs",
"test:release": "node --test tests/release-metadata.test.mjs",
"test:plugin-release": "npm run test:release && npm run test:plugin && npm run test:mcp && npm run test:replay && npm run test:regression",
"test:plugin-release": "npm run test:release && npm run test:plugin && npm run test:mcp && npm run test:replay && npm run test:regression && npm run test:tapes",
"deploy:http-mcp": "wrangler deploy",
"verify:http-mcp": "node scripts/verify-remote-mcp.mjs"
},
Expand Down
2 changes: 1 addition & 1 deletion plugins/agenttape/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agenttape",
"version": "0.4.0",
"version": "0.4.1",
"description": "Capture Codex tool traces and turn failures as portable .tape evidence.",
"author": {
"name": "jiangkoumo",
Expand Down
12 changes: 7 additions & 5 deletions plugins/agenttape/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# AgentTape Plugin

AgentTape 0.4.0 is an open-source, local-first Codex plugin that records supported lifecycle and tool events, marks explicit tool failures, emits a redacted version 1 `.tape`, and turns deterministic structural branches into executable regressions. It does not require a hosted service.
AgentTape is an open-source, local-first Codex plugin that records supported lifecycle and tool events, marks explicit tool failures, emits a redacted version 1 `.tape`, and turns deterministic structural branches into executable regressions. It does not require a hosted service.

Install it from the repository marketplace with `codex plugin marketplace add jiangkoumo/agenttape`, followed by `codex plugin add agenttape@agenttape`.

## Included

- Codex hooks for `SessionStart`, `PreToolUse`, `PostToolUse`, `PermissionRequest`, `Stop`, and `SessionEnd`.
- Codex hooks for `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SubagentStart`, `SubagentStop`, and `Stop`.
- Recursive redaction for common secret-bearing fields.
- Serialized runtime writes so concurrent hooks preserve one complete event sequence.
- Per-turn captures under `.agent-tape/tapes/`.
- The `capture-failure` skill and offline `agenttape.mjs` CLI.
- Version 1 JSON Schema and fixed permission-denied, timeout, and malformed-JSON fixtures.
- Bundled stdio MCP tools: `list_tapes`, `inspect_tape`, `fork_run`, and `save_regression`.
- Recorded-result substitution for four supported failure conditions.
- Assertions for field equality, tool presence/absence, retry limits, final status, and replay confidence.
- Recorded-result substitution for five supported failure conditions.
- Assertions for field equality, tool presence/absence, tool order, retry limits, final status, and replay confidence.

## Storage

Expand All @@ -32,7 +33,8 @@ Intentional regression artifacts are written under `tests/agenttape/` and can be
```bash
node scripts/agenttape.mjs list --json
node scripts/agenttape.mjs validate fixtures/permission-denied.tape
node scripts/agenttape.mjs test fixtures/permission-denied.tape
node scripts/agenttape.mjs test tests/agenttape
node scripts/verify-capture.mjs --must-fail --require-redaction --require-event PostToolUse
```

## MCP behavior
Expand Down
2 changes: 1 addition & 1 deletion plugins/agenttape/dist/mcp-server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22818,7 +22818,7 @@ async function activeWorkspaceRoot(configuredRoot, requestedRoot, extra, server)
}
function createAgentTapeServer({ workspaceRoot } = {}) {
const server = new McpServer(
{ name: "agenttape", version: "0.4.0" },
{ name: "agenttape", version: "0.4.1" },
{
instructions: "Read AgentTape captures from the active workspace. The server resolves the workspace from MCP roots or the Codex environment; pass workspaceRoot only when the host cannot expose it. Inspect a tape before making claims about failures or replay confidence. Hosted tools outside local hook coverage may be absent."
}
Expand Down
50 changes: 50 additions & 0 deletions plugins/agenttape/hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/scripts/record-hook.mjs\""
}
]
}
],
"PreToolUse": [
{
"hooks": [
Expand Down Expand Up @@ -40,6 +50,46 @@
]
}
],
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/scripts/record-hook.mjs\""
}
]
}
],
"PostCompact": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/scripts/record-hook.mjs\""
}
]
}
],
"SubagentStart": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/scripts/record-hook.mjs\""
}
]
}
],
"SubagentStop": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/scripts/record-hook.mjs\""
}
]
}
],
"Stop": [
{
"hooks": [
Expand Down
2 changes: 1 addition & 1 deletion plugins/agenttape/mcp/remote-server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function registerTool(server, name, config, handler, successText) {

export function createRemoteAgentTapeServer() {
const server = new McpServer(
{ name: "agenttape-remote", version: "0.4.0" },
{ name: "agenttape-remote", version: "0.4.1" },
{
instructions: "Process only a redacted AgentTape v1 document explicitly supplied by the caller. This stateless server does not read local files, retain tapes, call models, or call live tools. Structural replay stops at the injected tool result.",
},
Expand Down
2 changes: 1 addition & 1 deletion plugins/agenttape/mcp/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async function activeWorkspaceRoot(configuredRoot, requestedRoot, extra, server)

export function createAgentTapeServer({ workspaceRoot } = {}) {
const server = new McpServer(
{ name: "agenttape", version: "0.4.0" },
{ name: "agenttape", version: "0.4.1" },
{
instructions: "Read AgentTape captures from the active workspace. The server resolves the workspace from MCP roots or the Codex environment; pass workspaceRoot only when the host cannot expose it. Inspect a tape before making claims about failures or replay confidence. Hosted tools outside local hook coverage may be absent.",
},
Expand Down
Loading
Loading