Skip to content

release: Cortex Agent v1.9.0 - #1

Merged
Kucell merged 29 commits into
mainfrom
codex/release-1.9.0
Jul 31, 2026
Merged

release: Cortex Agent v1.9.0#1
Kucell merged 29 commits into
mainfrom
codex/release-1.9.0

Conversation

@Kucell

@Kucell Kucell commented Jul 31, 2026

Copy link
Copy Markdown
Owner

What changed

  • add Agent Reporter, Governed Launcher and private launch context
  • install Claude Code coordination hooks and lifecycle bridge
  • add fenced lease renewal, heartbeat, terminal recovery and redacted receipts
  • add accepted-persistence handshake to prevent concurrent journal corruption
  • prepare the v1.9.0 package and changelog

Impact

Codex can dispatch one or more Claude Code agents and receive governed progress,
blocked, failed and review notifications in the originating Codex Desktop task.
Critical events remain pending until explicitly acknowledged.

Validation

  • focused coordination and notification tests: 272/272 PASS
  • real dual Claude Agent to Cortex to Codex App Server wakeup: PASS
  • lease release and child receipt verification: PASS
  • independent simple dialog callback to the originating Codex task: PASS
  • local npm pack contents and Volta installation: PASS

Release boundary

This release does not publish to npm. The package was installed locally from the
generated tarball for SamHMI validation.

Kucell added 29 commits July 29, 2026 14:14
… Event Bridge

Implement T-ACN-016 (Operation OP-ACN-CP11-001, lease LEASE-2):

- Agent Reporter: Public Task API lifecycle reports for agent-scoped events
  (accepted, progress, heartbeat, testing, blocked, input_required, failed,
  ready_for_review). Supports standalone (no-op without service) and batch
  reporting via openBatch().

- Governed Launcher: Creates tasks through the Coordination Application
  Service with private launch context (never shared/persisted) and public
  context (slimmed-down for the agent). Creates task.created + task.assigned
  events in a single launch() call.

- Generic Host Event Bridge: Restricted cortex-agent agent report CLI
  command --event-type <type> --task-id <id> [options]. Accepts only
  agent-scoped event types. Validates against the coordination schema.

- Private launch context: Full context held by the launching process, never
  exposed to the agent. Public context is a safe subset.

- 37 focused tests (16 agent-reporter, 12 governed-launcher, 9 host-event-bridge).
  All pass under node:test. No regressions in existing coordination tests.

Boundary: No automatic dispatch/daemon. No credentials. No push/merge.
…Launcher 子进程

1) 删除公共 CLI 与 Host Event Bridge 对 --event-json/raw arbitrary JSON 的
   支持;桥接只映射受限、枚举化的宿主事件字段,拒绝未知/敏感输入。

2) Agent Reporter 从治理启动上下文解析 task、operation、attempt、producer、
   project、ownership、target,禁止 agent 通过 CLI 覆盖 targets/repository/
   sequence/workflowGate/currentState/previousState/permission/ownership/
   Decision/Waitpoint 等;加入长度/秘密过滤和脱敏 receipt。

3) Governed Launcher 实际创建受治理子进程后才提交 accepted;真正的 launch
   failure 稳定上报 failed 而非伪造 accepted;通过私有临时文件给子进程必要
   上下文,公共结果不泄漏私有上下文、prompt、命令、session、token 或绝对
   路径。支持可注入 executor 以便测试,含 worktree/ownership 验证。

4) Stop/exit 0 不得自动 ready/completed;ready 需受限 evidence 引用。

5) 更新/新增测试覆盖这些负面约束和 E2E lifecycle。

测试: 66/66 pass (agent-reporter 34, governed-launcher 17, host-event-bridge 15)
1) agent-reporter: 增加 createAgentReporterFromContext() 从 CORTEX_LAUNCH_CONTEXT
   读取身份,无有效上下文时 fail closed。buildRedactedReceipt 重扫并删除
   敏感字段,敏感内容仅返回 rule IDs。增加 buildRetryDedupKey 实现 hook
   retry 幂等性(稳定 launchId+eventType+deliveryId)。

2) governed-launcher: 默认 executor 改为 defaultExecutor 而非 null,
   可传入受限 agentCommand/agentArgs。真实子进程确认启动后提交
   task.accepted,spawn/early exit 失败按当前状态提交 task.failed 且
   不 fake accepted。私有上下文文件在 child 启动后保留(仅失败时清理),
   保证 child 可读取。返回值/events 不含 prompt/command/context 路径/
   session/token/绝对路径。

3) host-event-bridge: 删除 actor-id/project-id/task-id/kind/session-id/
   correlation-id 等治理参数,所有未知 CLI 参数拒绝。action 限制为
   agent-scoped lifecycle 事件。无有效受治理上下文时 fail closed。
   通过 createAgentReporterFromContext 创建 reporter。

4) cli-contract: 同步更新 agent 命令的 machine contract 描述。

5) 测试:89 个测试全部通过,覆盖无 context 失败、伪造治理参数拒绝、
   敏感内容扫描、幂等去重、context 权限校验、spawn 成功/失败事件完整
   路径、bridge E2E 生命周期。
P-003 §11.1 / §13.5 第三轮阻断性修复:

A. Governed Launcher:
- agentCommand 改为必填,禁止 process.execPath + 空 args fallback
- launch() 改为 async,await executor 确认真实 spawn/alive 后才写 task.accepted
- executor reject/early exit 对已创建的 Task 写 task.failed
- agentCommand/agentArgs 必须传入私有 context
- 公有结果不泄漏 command、args、context path、prompt、session、token 或绝对路径
- 先创建/assign 再验证会失败的 scope,保证 failed 事件可落库

B. Context identity:
- createPrivateLaunchContext 加入不可由 Agent 自选的 producer(targetAgentId、kind=agent)
- createAgentReporterFromContext 使用 targetAgentId 而非 coordinatorId
- input.taskId 不能覆盖 context—必须与 contextTaskId 一致
- 上下文验证 regular file、0600、owner、schema 与必填字段
- CLI 无 context fail closed

C. Hooks/Bridge:
- 公开 agent report 只接受 action + bounded message/evidence ref + delivery id
- 增加 delivery-id 到 RESTRICTED_OPTIONS
- 未知参数拒绝

D. Receipt:
- 只含 eventId、eventType、taskId、projectId、timestamp、state、ok
- 改为 redactedSummary(bounded + scanned)和 artifactSha
- 不再返回 message/evidence,clean 内容也不返回

E. Tests:
- 100 测试全部通过
- 新增真实异步 executor E2E(assert accepted 在 Promise resolved 后)
- 空命令/空 node fallback 被拒绝
- spawn failure/early exit 产生 task.failed
- agentCommand/args 实际到 executor
- target producer 可验证
- input taskId 不能覆盖 context
- receipt 无 message/evidence/path/session/command
- 上下文权限与 schema fail closed
- 跨实例持久化 dedup 测试
Release A 阻断修复 (T-ACN-016 CP-11 第四轮):

1. 启动失败审计加固:
   - 重构 launch() 时序:先 create/assign Task,再执行 worktree/ownership
     validation,确保所有失败都有真实 task.failed event
   - 合约新增 ASSIGNED→FAILED 过渡 (task.failed)
   - assertActorAuthorized 允许 coordinator 在 ASSIGNED 态提交
     task.failed(agent 接受前)
   - 移除所有静默 try/catch,service.submit 失败不再被吞掉
   - 补断言:worktree/ownership 失败后 task.state=FAILED

2. agentCommand 安全校验:
   - validateAgentCommand:拒绝空值/相对路径/process.execPath/
     不可执行文件/命令注入字符;支持 allowedAgentCommands 白名单
   - validateAgentArgs:拒绝非数组/超 64 个/NUL 字符/非字符串
   - 经验证命令/args 仅放入私有 context,公有结果不泄漏
   - 临时可执行 fixture 测试验证

3. 测试覆盖:44 项 governed-launcher、48 项 agent-reporter、
   28 项 host-event-bridge、108 项 contract、10 项 app-service、
   55 项 state = 283 项全通过
ASSIGNED→FAILED 授权收紧:
- 添加 state.createdBy 字段追踪任务创建者 coordinator
- 仅允许创建该任务的 coordinator 在 agent 接受前提交 task.failed
- 第二个 coordinator 的 task.failed 被拒绝(ERR_ACTOR_MISMATCH)
- 增加负面测试、正面测试

命令白名单 fail closed:
- 生产环境:allowedAgentCommands 缺失或空数组时 launch 拒绝
- 仅 testMode: true 时允许跳过白名单(单元测试 opt-in)
- validateAgentCommand 对空白名单显式拒绝
- 覆盖 all 4 场景:缺失/空/白名单有效/非白名单

核验:
- launch config 验证在 task 创建前无任务失败无错误码泄漏
- 所有现有测试通过 testMode: true 适配
…/PostToolUse/Notification/Permission/ReadyForReview/Stop/SubagentStop governance, rate-limiting, redaction, fail-closed

- Claude Code Hook Adapter (lib/coordination/claude-hook-adapter.js):
  - SessionStart → task.accepted (only through real launcher via CORTEX_LAUNCH_CONTEXT)
  - PostToolUse → task.progress (rate-limited 5000ms window, merged within window)
  - Test signal detection → task.testing (npm test, vitest, jest, node --test)
  - Notification/Permission → task.input_required (raw payload stripped)
  - ReadyForReview → task.ready_for_review (only allowed evidence refs)
  - Stop/SubagentStop → NEVER infer completion (coordinator determines terminal state)
  - Redaction: prompt, session, path, command, tool payload, credentials
  - Fail closed: unknown hook names silently ignored

- 58 contract/E2E tests covering all hook handlers, rate limiting, redaction,
  evidence validation, dispatch, edge cases, and fail-closed behavior

- Updated zh/en hook templates with governance adapter documentation

- All existing tests pass (coordination-adapters, etc.)
- git diff --check: clean
…e, hook executable, settings templates, integration tests

Repair following reviewer rejection of commit 1ea13c6 (pure mapping module
with no real hook wiring, no executable, no E2E demonstration).

Changes:
1. Split 709-line claude-hook-adapter.js into 4 files by responsibility:
   - claude-hook-adapter.js — factory + dispatch (slimmed)
   - claude-hook-handlers.js — individual hook handler functions
   - claude-hook-redaction.js — redaction, secret scan, evidence validation
   - claude-hook-rate-limiter.js — rate limiting, progress merging

2. Created bin/cortex-claude-hook — real hook executable entrypoint:
   - Accepts hook name as first argument, bounded stdin JSON (64 KiB max)
   - Derives identity exclusively from CORTEX_LAUNCH_CONTEXT
   - Rejects governance fields (taskId, projectId, actorId, etc.) in stdin
   - Routes through existing redaction/rate-limiter/handlers
   - Returns structured JSON receipt (never leaks prompt/session/path/token)

3. Wired Claude settings/hooks templates in both en/zh:
   - claude-governed-hooks.json — settings.json hooks config for all 6 hook types
   - Uses npx --yes cortex-claude-hook (no hard-coded absolute paths)
   - Updated pre-commit-check.md with hook executable integration docs

4. Fixed SessionStart idempotency:
   - Does NOT independently create task.accepted — launcher already handles it
   - Returns structured event envelope for idempotent reporter route
   - Contract permits only validation + context-derived event building

5. Hook metadata safety:
   - progress/testing/input_required/ready use bounded metadata (≤4000 chars)
   - Stop/SubagentStop never emit terminal events (coordinator decides)
   - Receipt never leaks prompt, session, path, command, payload, token,
     password, apiKey, authorization, arguments, input, output, credential

6. Added 22 integration tests exercising executable against real temp
   coordination service/journal with Notification Pump-compatible state:
   - SessionStart context validation + idempotency
   - PostToolUse progress + long message bounding + test signal + governance
   - Notification/Permission input_required with bounded metadata
   - ReadyForReview evidence filtering
   - Stop/SubagentStop terminal event prohibition
   - Governance field rejection + unknown hook + missing hook name
   - Journal event state (Notification Pump format compatibility)
   - Agent-scoped event submission through service
   - Receipt leak prevention (14 sensitive patterns)

7. Registered cortex-claude-hook in package.json bin entry

Test: 80 tests pass (58 unit + 22 integration), 0 fail
Git: git diff --check produces no whitespace errors
…schemas, templates, tests

Hard blockers fixed:
1. bin/cortex-claude-hook now invokes CoordinationApplicationService to
   write real Journal events (task.progress, task.testing, task.input_required,
   task.ready_for_review) instead of returning adapter-only results
2. Hook templates use 'node node_modules/cortex-agent/bin/cortex-claude-hook'
   instead of 'npx --yes cortex-claude-hook' (offline-safe, no network, no
   unpinned package install)
3. HOOK_ALLOWED_STDIN_FIELDS per hook type rejects unknown fields in stdin
   alongside governance field rejection
4. Error receipts use '[REDACTED]' for all messages; receipts never leak
   prompt/session/path/command/payload/token/credentials
5. SessionStart validates CORTEX_LAUNCH_CONTEXT but does NOT submit
   task.accepted (launcher authoritative — no duplicate)
6. Stop/SubagentStop remain nonterminal (never submit events)
7. previousState read from actual task state in service (not hardcoded)

Tests: 82 total (58 unit + 24 integration), all pass. Integration tests
invoke the actual executable against a temp project with real Journal
and assert event presence, notification pump compatibility, no leakage,
unknown input rejection, and no duplicate accepted.
…nt Reporter bridge, template refactor, process tests

Implement public `cortex-agent hook claude <HookName>` command that routes
hook events through the Agent Reporter (never direct createEvent/submit).

Key changes:
- New lib/coordination/claude-hook-cli.js: bridges hook handlers to Agent
  Reporter for all hook types with proper redaction, dedup, and coordinator
  notification for input/ready events
- Refactored bin/cortex-claude-hook: delegates to claude-hook-cli module
  instead of direct createEvent/service.submit calls
- New hook command in bin/cli.js + lib/commands.js: `cortex-agent hook claude`
  uses .agent-runtime/coordination service root (same as existing commands)
- Updated templates: claude-governed-hooks.json uses `cortex-agent hook claude`
  instead of `node node_modules/cortex-agent/bin/cortex-claude-hook`
- Fixed Agent Reporter producer: removed operationId/operationAttempt from
  producer object (contract only allows actorId, kind, vendor, sessionId)
- Added process tests (claude-hook-cli.test.js): 24 tests for all hook types,
  governance rejection, redacted receipts, Stop nonterminal, SessionStart
  validation, Notification Pump compatibility
- 106 total hook tests pass (82 R2 + 24 R4); 48 agent-reporter tests pass

Safety contract preserved:
- Identity from CORTEX_LAUNCH_CONTEXT only (context-only, never CLI args)
- Governance fields in stdin rejected for all hooks
- SessionStart validates context, never submits (launcher authoritative)
- Stop/SubagentStop: nonterminal, never submit events
- Receipts: only ok/code/eventType/emitted/timestamp; never sensitive data
@Kucell
Kucell merged commit 312004c into main Jul 31, 2026
6 checks passed
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.

1 participant