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
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cc",
"version": "1.7.12",
"version": "1.8.0",
"description": "Claude Code Plugin for Codex. Run reviews, tracked tasks, and independent Codex-Claude design or research workflows.",
"author": {
"name": "CBEPX",
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

## [Unreleased]

## v1.8.0

### Added

- Add an explicit native advisor policy: `--advisor inherit|off|<alias-or-id>` for `task`/rescue, `review`, `adversarial-review`, `peer-create` (design and research), and `setup --stop-review-advisor` with workspace `stopReviewAdvisor`. Omission means `inherit`: the plugin adds no flag and no environment change, and a `CLAUDE_CODE_DISABLE_ADVISOR_TOOL` value from the caller stays in effect. `off` sets `CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1` in the Claude Code child environment only. An alias or model ID is passed as native `--advisor` and needs a verified stable CLI 2.1.293 or later (the hidden flag is not read from `--help`). An invalid value, an older CLI, or an unverifiable version is refused before any model turn (`CLAUDE_ADVISOR_INVALID`, `CLAUDE_ADVISOR_UNSUPPORTED`), without a retry, without removing the flag, and with the job reservation released. Task and review requests store a non-default policy (inherit is stored as no policy) and detached workers forward it. `--resume` without the flag keeps the policy of the originating task, selected by owner and Claude session; `--advisor inherit` resets it; a fresh task starts at `inherit`. Peer workflows freeze the policy as the `claude-advisor` manifest entry for memo, critique, and retry, and `--continue` and `--retry` reject `--advisor`. A Stop review with an unsupported or invalid `stopReviewAdvisor` blocks with `blocked_protection_refused`, `claudeInvoked: false`, and an operator handoff. Records, workflows, and configuration written before this change have no policy and mean `inherit`. `setup --check` rejects `--stop-review-advisor` before any side effect. Non-string stored values (task history, Stop configuration, peer manifest) are refused as `CLAUDE_ADVISOR_INVALID`; a resume bound to a workflow selects its originating policy inside that workflow, so the policy survives an explicit owner rebind; `setup` reports an invalid stored value (`stopReviewAdvisor: "invalid"` with `stopReviewAdvisorProblem` and a repair step) and warns when a configured alias or model ID needs a newer CLI. The request is not evidence that an advisor ran.
- Add bounded native advisor telemetry as an `advisor` object: `{ requested, calls, countExact, observedModel, status, diagnostics }`. The object is in `runClaudeTurn` and `runClaudeReview` results, task payloads, and review payloads (`codex.advisor`). It is also in `status`, `result`, peer memo and critique `model` metadata, and the Stop snapshot and history. `requested` is the plugin policy. The other fields are observations. The parser counts distinct `server_tool_use` blocks named `advisor` in full assistant records and in partial `content_block_start` events. It counts one call for the same ID in both forms, and it does not count `advisor_tool_result`. Forwarded subagent records do not count. A missing or malformed ID, or more than 256 IDs, sets `countExact: false` and `status: "incomplete"`, and `calls` is then a lower bound. Zero calls is `not_observed`, not proof that the advisor was disabled. `observedModel` stays `null`, because the native stream does not identify the advisor model. Ordinary `toolUses`, `touchedFiles`, `finalModel`, context-window attribution, and `modelFallbacks` stay primary-only. Rendered task and review output, `status` records, and the job status table show the advisor result in two cases only. The policy is not `inherit`, or the stream showed calls. This keeps default records inside the bounded read view. The peer model table shows it when the object is present. Records written before this change have no `advisor` object and stay readable without migration.

### Changed

- Report the Claude Code authentication check in separate states: authenticated, API key, confirmed logout, timeout, spawn failure, and other probe failure. `getClaudeAuthStatus` adds `state` to its result and keeps `loggedIn`. Only a confirmed logout (`loggedIn: false` in the native JSON, or a not-logged-in message from a failed command) tells the user to run `claude auth login`. A timeout or an unexplained failure says the login state is unknown and points to `claude auth status`. `setup`, `task`, `review`, `adversarial-review`, the Stop review gate, and peer turns use the same states; peer failures record `CLAUDE_AUTH`, `CLAUDE_AUTH_PROBE_TIMEOUT`, `CLAUDE_AUTH_PROBE_FAILED`, or `CLAUDE_UNAVAILABLE`.
- Report a proven organization subscription refusal as `claude_subscription_refused` (peer code `CLAUDE_SUBSCRIPTION_REFUSED`). The signal is the result text of an API-error terminal event, or the stderr of a command that failed before any terminal event. A successful answer that quotes the message stays a success, and a run that ends for another reason (for example max turns or budget) keeps its own category even when its text quotes the message. An unknown required CLI option is reported as `claude_cli_unsupported` (peer code `CLAUDE_CLI_UNSUPPORTED`) without a retry and with every protective flag unchanged.
- Make a refused protected Stop review explicit. The gate stays closed and persists `blocked_protection_refused` with `claudeInvoked: false` and the refusal code. The block text says that retrying the unchanged request cannot resolve the refusal and that the exact blocker goes to the user. A missing Claude Code CLI or an inconclusive login check keeps the existing allow-with-guidance path. The Stop snapshot sets `claudeInvoked: true` only after the Claude process has spawned, so an interrupted or pre-spawn-refused run never claims an invocation.
- Refuse to pin a relative project `Read` or `Edit` rule to a Windows drive, UNC, or backslash checkout path. No Windows runner qualified a conversion, so the review does not start (`PROJECT_SETTINGS_UNSUPPORTED`).
- Tell the forwarding skills and runtimes that a reserved job id belongs to one launch attempt and is spent after a failure, because the companion may already have released it. A retry asks `background-routing-context` for a new id, and the forwarder copies the task text byte for byte.

### Fixed

- Keep private stream payload out of parser diagnostics and progress. A stream line that is not valid JSON now adds `{ code: "INVALID_JSON", length }` to `parseErrors` (or `EVENT_HANDLING_FAILED` for a record that fails later). The entry keeps neither the raw line prefix nor the `JSON.parse` message, because both can contain advisor input, advice, or encrypted content. The unresolved parse error count does not change. Progress events no longer forward the raw native event as `data`. Earlier records keep their stored `parseErrors` entries.
- Supervise the Claude Code child when an `onSpawn` callback throws. `runClaudeTurn` now installs its stream listeners first. If the callback throws, it stops the child process group and sends `SIGKILL` after 5 seconds. It rejects with the original error only after the child closes. The Stop review gate treats its spawn-time diagnostic snapshot as best effort. If that write fails, the gate logs the error and continues the review. The final snapshot still records `claudeInvoked: true` and the review decision. A failed final write still ends the hook with an error.
- Close the descriptor in `exportReadPayload` when `fstat` fails after the exclusive open (#54). The output file stays because its identity was never read. Cleanup after a write failure still deletes only a path that matches the created file.
- Test-only (#57): make the stdio SIGTERM-escalation test wait for fixture readiness, then fire the probe's own timers in order. Production probe deadlines do not change (the default stays `options.timeoutMs ?? 5000`; 1000 ms is the test's explicit argument). The test keeps its SIGTERM-ignored and SIGKILL-reaped proofs and now stops the started probe and fixture when readiness fails.

## v1.7.12

### Changed
Expand Down
Loading
Loading