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.8.1",
"version": "1.9.0",
"description": "Claude Code Plugin for Codex. Run reviews, tracked tasks, and independent Codex-Claude design or research workflows.",
"author": {
"name": "CBEPX",
Expand Down
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# Changelog

## [Unreleased]
## v1.9.0

### Added

- Add a bounded trusted `PostToolUse` dispatcher for fenced automatic research continuation on an existing shared native Codex server, with `--manual-continue` opt-out and explicit unavailable/manual recovery. Store checkpoint/final delivery separately from parent consumption. Preserve legacy/design behavior, current collaboration mode, permissions, ownership and epoch fences. Keep workers inside their sandbox and deliver only stored workflow events after native ancestry checks. Persist native interruption fences and preserve unrelated queued user input. Require separate trust for the new `PostToolUse` and `Interrupt` hooks. Use native WebSocket transport without a separate Codex server or automatic resume.

- Add research search selection with `--search-provider all|native|brave|firecrawl`. The default uses all available selected providers for each participant. Freeze separate Codex and Claude search routes, require result receipts, and retain partial provider failures as gaps. Page reads do not count as native search. Preserve legacy workflow acceptance rules.
- Accept the exact Firecrawl search tool after a read-only schema check. Reject action-bearing schemas and destructive declarations. Do not grant crawl, agent, or script tools.
- Show the optional native Claude login expiry in setup output without storing account fields.

### Fixed

- Classify the observed expired OAuth session terminal error as an authentication failure, including native generic API-error results. Preserve the native terminal category.
- Give Codex research workers one complete memo structure with linked search call and result receipts. Use local correlation labels when the host does not expose native call IDs. Keep worker-reported provenance explicit and reject missing results.
- Require Claude Code 2.1.321 or later for protected reviews after upstream fixes to permissions, sandbox checks, excluded settings sources, and MCP OAuth redirects. Validate the new boolean `permissions.denyInsteadOfPrompting` setting while preserving the plugin's `dontAsk` review policy.

## v1.8.1

Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,15 @@ JSON task and review results keep `requestedModel` as the forwarded alias or ful

For model qualification, compare `--model claude-opus-5-5 --effort medium` against `high` and `xhigh`, and `--model claude-fable-5-1 --effort high` against `xhigh` on identical tasks. Defaults remain unchanged until local quality and latency measurements justify a change. See Anthropic's [Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5) and [Fable 5.1](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1) prompting guides.

Protected reviews require Claude Code 2.1.321 or later. The plugin refuses older or unverified versions before it starts a review.

Scope `auto` (the default) inspects `git status` and chooses between working-tree and branch automatically.

In foreground, review returns the result directly. In background, the plugin uses a Codex built-in subagent, tracks the review as a job, and nudges you to open the result when it completes.

If the diff is too large to inline safely, the review prompt falls back to concise status/stat context and tells Claude to inspect the diff directly with the read-only `mcp__gitReview__diff` tool instead of failing the run.

By default, review runs with only the bundled read-only git MCP. Repeat `--user-mcp-tool <mcp__server__tool>` to opt in specific Claude MCP tools from your user-scope Claude config for a run. Opted-in user MCP tools run as external Claude MCP processes and are auto-approved for that review, so use only trusted tools when reviewing untrusted diffs. Eligibility is based on the server's `readOnlyHint` declaration or the immutable four-ID audited annotationless registry: Context7 `mcp__context7__query-docs` and `mcp__context7__resolve-library-id`, plus Brave `mcp__brave-search__brave_web_search` and `mcp__brave-search__brave_llm_context`. It is not an OS-enforced sandbox. A `destructiveHint` declaration is always vetoed. Project `.mcp.json` server definitions are ignored unless you also pass `--allow-project-mcp-servers`.
By default, review runs with only the bundled read-only git MCP. Repeat `--user-mcp-tool <mcp__server__tool>` to opt in specific Claude MCP tools from your user-scope Claude config for a run. Opted-in user MCP tools run as external Claude MCP processes and are auto-approved for that review, so use only trusted tools when reviewing untrusted diffs. Eligibility is based on the server's `readOnlyHint` declaration or the immutable audited annotationless registry: Context7 `mcp__context7__query-docs` and `mcp__context7__resolve-library-id`, plus Brave `mcp__brave-search__brave_web_search` and `mcp__brave-search__brave_llm_context`, and schema-checked Firecrawl `mcp__firecrawl__firecrawl_search`. It is not an OS-enforced sandbox. A `destructiveHint` declaration is always vetoed. Project `.mcp.json` server definitions are ignored unless you also pass `--allow-project-mcp-servers`.

#### Advisor policy

Expand Down Expand Up @@ -211,15 +213,19 @@ $cc:design --retry <workflow-id>

New workflows default to Claude `fable` with `opus` fallback and inherited Codex model at `xhigh` effort. Use `--model`, `--fallback-model`, `--effort`, `--advisor`, `--codex-model`, or `--codex-effort` to override them. Repeat `--user-mcp-tool <mcp__server__tool>` for explicitly trusted eligible tools; automatic selection is limited to the smallest relevant eligible set exposed to the active Codex turn. Eligibility records whether trust came from `readOnlyHint` or the audited registry, but does not independently enforce server behavior. Project MCP servers still require `--allow-project-mcp-servers`.

Only the two Brave IDs in that four-ID registry — `mcp__brave-search__brave_web_search` and `mcp__brave-search__brave_llm_context` — are Brave web-evidence tools; other Brave IDs are not eligible through the registry. A Brave event counts as Claude web evidence only when that exact ID is also in the workflow's frozen selected-tool manifest. The manifest records the selected ID and trust basis, not the provider's behavior: an `@latest` Brave server can still change a tool behind the same ID. Pin a server version when that drift is unacceptable.
For legacy workflows, only the two Brave IDs in that registry — `mcp__brave-search__brave_web_search` and `mcp__brave-search__brave_llm_context` — are Brave web-evidence tools; other Brave IDs are not eligible through the registry. A Brave event counts as Claude web evidence only when that exact ID is also in the workflow's frozen selected-tool manifest. The manifest records the selected ID and trust basis, not the provider's behavior: an `@latest` Brave server can still change a tool behind the same ID. Pin a server version when that drift is unacceptable.

Selected MCP search servers are external trusted processes/services, not an OS sandbox. Their query or context input can disclose the brief and research terms to the provider; do not send secrets or sensitive material through either tool. The workflow never persists raw MCP configuration or credentials, but that does not remove this upstream disclosure risk.

Selected Brave MCP servers are external trusted processes/services, not an OS sandbox. Their query or context input can disclose the brief and research terms to the provider; do not send secrets or sensitive material through either tool. The workflow never persists raw MCP configuration or credentials, but that does not remove this upstream disclosure risk.
New research workflows use `--search-provider all` by default. Each participant uses every available selected search provider: native search, Brave, and Firecrawl. Use `--search-provider native|brave|firecrawl` to select one provider; it must be available to both participants. Search tools are frozen separately for Codex and Claude. Page readers do not count as search. Each selected provider must be attempted, and each participant needs at least one successful search result. Partial provider failures remain explicit gaps. Claude receipts come from its native stream; Codex worker receipts remain worker-reported evidence and do not bind citations to provider responses. Workflows created before this policy retain their previous evidence rules.

The stored and rendered workflow shows independent branch states, requested/final models and fallback events, source/tool evidence counts, selected public tool IDs and reasons, checkpoint or final result, and the exact continue/retry command. Raw MCP configuration, environment variables, headers, and credentials are never persisted or rendered. Claude receives no Bash, write, or Agent capability, and only selected MCP servers enter its strict runtime config. Peer turns also require the platform filesystem sandbox, deny unsandboxed commands and reads of canonical Codex/Claude state, persist no Claude transcript, and expose only content-free phase/tool/model-fallback progress before reveal. Native Windows peer execution is unsupported and isolation failures stop with `PEER_ISOLATION_UNAVAILABLE`.

Attempt leases are single-use secrets sent through stdin, while durable state keeps only their digests. A Claude-first memo remains process-local until Codex seals its independent memo. That wait has one absolute 30-minute deadline; retry keeps a committed waiter only while its current linked job is alive, rotates only unfinished reservations, and never rewrites completed payloads. A lost, terminal, or reaped worker becomes retryable, while unresolved process cancellation stays terminal as `cancel_failed`.

At the checkpoint, inspect the aggregate result and either continue with feedback or retry only failed/missing work. Continuation may run from a new Codex session: ownership is rebound explicitly, and critique starts a fresh ephemeral Claude turn from the frozen brief, memos, and feedback. SessionEnd marks unfinished work retryable after identity-checked linked-process cleanup; unresolved cancellation remains `cancel_failed`.
New research continues from its checkpoint through critique and synthesis when enabled, trusted research `PostToolUse` and `Interrupt` hooks qualify its parent on an existing compatible shared Codex server. The initial launch returns in background. The final event returns the parent to analysis and planning. Use `--manual-continue` for a checkpoint stop. Old workflows and design remain manual. If native continuation is unavailable, the workflow reports the reason and exact manual recovery command. The dispatcher delivers only stored workflow events; sandboxed workers do not access the privileged control socket. An interruption records a durable parent fence and removes only matching research events from the native queue. New hook trust and activation require a separate setup step. Native continuation needs built-in WebSocket support (standard in Node 22 and later). It does not start a Codex server, change permissions, or authorize implementation.

For manual workflows, inspect the checkpoint and either continue with feedback or retry only failed/missing work. Continuation may run from a new Codex session: ownership is rebound explicitly, and critique starts a fresh ephemeral Claude turn from the frozen brief, memos, and feedback. SessionEnd marks unfinished work retryable after identity-checked linked-process cleanup; unresolved cancellation remains `cancel_failed`.

### `$cc:adversarial-review`

Expand Down Expand Up @@ -525,7 +531,7 @@ node scripts/qualify-peer-live.mjs --live verify \

Installed mode compares file bytes and the entry set under the shipped paths against an exact local Git tag. Extra files, directories, and symlinks under those paths fail the check. To check candidate source, use `--mode candidate` with a full 40-character commit ID. Neither mode binds a workflow to the checked runtime or proves artifact publication, installation activation, or a client restart. The release checklist above still applies.

The gate checks pinned Draft-07 schemas, frozen manifests, memo citations, native model metadata, and both exact Brave calls in the Claude memo. Use a full Claude model ID. Aliases do not pass qualification. The memo and critique must report that exact model without fallback. The gate checks critique content and allowed tools through the existing peer contract. A candidate's memo and critique must report the frozen advisor policy with an exact, consistent count. An incomplete observation or an `off` policy with observed calls fails. Zero advisor calls mean `not_observed`. The supported stream does not identify the advisor model, so `observedModel` must remain `null`. A requested Fable model is not proof of its invocation.
The gate checks pinned Draft-07 schemas, frozen manifests, memo citations, native model metadata, and successful per-provider search receipts for new research workflows. Legacy qualification still requires both exact Brave calls in the Claude memo. Use a full Claude model ID. Aliases do not pass qualification. The memo and critique must report that exact model without fallback. The gate checks critique content and allowed tools through the existing peer contract. A candidate's memo and critique must report the frozen advisor policy with an exact, consistent count. An incomplete observation or an `off` policy with observed calls fails. Zero advisor calls mean `not_observed`. The supported stream does not identify the advisor model, so `observedModel` must remain `null`. A requested Fable model is not proof of its invocation.

The workspace inventory includes ignored files, modes, empty directories, and symlink targets. The inventory does not follow symlinks or cover Git metadata outside the linked worktree. The report records `workspaceEntriesUnchanged` and excludes memo text and advisor payload. Both memos and the critique must complete on their first attempt. Failed or incomplete workflows, failed branch attempt history, memo or critique retries, and model fallbacks do not pass this gate.

Expand Down
45 changes: 45 additions & 0 deletions docs/superpowers/plans/2026-11-09-research-modernization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Research modernization implementation plan

Approved scope: diagnostics, current Claude CLI compatibility, multiple search providers, and background research continuation.
Tracking: https://github.com/CBEPX/cc-plugin-codex/issues/27. Base: v1.8.1 at `95cc226`.

## Constraints

- Use RED/GREEN regression tests and independent Codex review. Do not invoke Claude while its quota is unavailable.
- Preserve exact MCP selection, sandbox protections, ownership, epoch fences, and cancellation.
- Keep model, effort, and advisor defaults unchanged. Do not log in or refresh credentials automatically.
- Keep release, installation, hook trust, and shared-runtime migration as separate gates.
- Preserve a resumable handoff and release the claim on a requested pause. The original 10:15 MSK stop was completed; later work resumes only on the user's explicit instruction.

## Task 1: Diagnostics and compatibility

- Reproduce expired OAuth session classification, then classify the proven failure as authentication. Successful quoted text remains successful.
- Require Claude CLI 2.1.314 or later for protected reviews. Refuse an older or unknown version before launch.
- Accept boolean `permissions.denyInsteadOfPrompting` under forced `dontAsk`. Preserve other project restrictions and reject invalid types.
- Show `loginExpiresAt` in setup when the native CLI provides it.
- Test MCP name boundaries and new task events without assuming an upstream failure.

## Task 2: Search providers

- Add `research --search-provider all|brave|firecrawl|native`, default `all`.
- Discover routes separately for each participant and freeze selected exact tool IDs.
- Use all available selected searches. Continue after a partial provider failure with explicit gaps. Require at least one successful search.
- Separate search coverage from page reading. Verify tool results, not only tool calls or model claims.
- Preserve explicit pins and `--no-auto-tools`. Do not add Firecrawl autonomous agents, crawls, browser interaction, or Alexandria.
- Update qualification, worker prompts, and public reads together. Preserve legacy workflows.

## Task 3: Background continuation

- New research proceeds from memos through critique and synthesis to a parent planning turn. `--manual-continue` preserves the checkpoint stop.
- Old workflows remain manual. Design behavior is unchanged.
- Deliver compact fenced checkpoint/final events to the exact parent thread on its existing shared native Codex server.
- Use the existing native queue without resume or context overrides. A bounded trusted `PostToolUse` dispatcher delivers saved events; sandboxed workers do not access the privileged server socket. Qualify the exact parent before enabling delivery. Do not spawn a separate Codex server to deliver an event.
- Distinguish queue acceptance, turn start, and parent consumption. Duplicate delivery cannot start a stage twice.
- Preserve Plan Mode, current user steering, permissions, cancellation, rebind, and SessionEnd behavior.
- Test real parent wake in an isolated profile with fake Claude/MCP before separately migrating any intended task session.

## Verification

Run targeted regressions, `npm run check`, and required mutation gates without reducing thresholds.
Require changed-behavior E2E before commit or PR creation. Preserve any blocked live gate explicitly.
No release, installation, authentication changes, other-session restart, or runtime activation is implied by passing local tests.
25 changes: 25 additions & 0 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,31 @@
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_DATA}/runtime/hook-launcher.mjs\" research-continuation",
"timeout": 8,
"statusMessage": "Delivering research continuation"
}
]
}
],
"Interrupt": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_DATA}/runtime/hook-launcher.mjs\" research-continuation",
"timeout": 3,
"statusMessage": "Pausing research continuation"
}
]
}
]
}
}
19 changes: 19 additions & 0 deletions hooks/research-continuation-hook.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env node
/**
* Copyright 2026 Sendbird, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import { readHookInput } from "./lib/hook-input.mjs";
import { dispatchResearchContinuations, pauseResearchContinuations } from "../scripts/lib/research-continuation.mjs";

try {
const input = readHookInput();
if (input.hook_event_name === "Interrupt") {
await pauseResearchContinuations({ cwd: input.cwd, sessionId: input.session_id });
} else if (input.hook_event_name === "PostToolUse" && input.tool_name === "Bash" &&
/\b(session-routing-context|peer-create|peer-checkpoint|peer-final|peer-status)\b/.test(input.tool_input?.command ?? "")) {
const receipts = await dispatchResearchContinuations({ cwd: input.cwd, sessionId: input.session_id });
if (receipts.length) console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: "PostToolUse",
additionalContext: "Research continuation dispatcher receipts: " + JSON.stringify(receipts) } }));
}
} catch { /* Hook failure preserves the native tool result and manual continuation. */ }
Loading
Loading