diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..fca421eb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - run: pip install ruff + - run: ruff check . + + typecheck: + name: Type Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - run: pip install pyright pyyaml anthropic mcp pytest + - run: pyright + + test: + name: Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - run: pip install pytest pyyaml anthropic + - run: pytest plugins/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a26fca5..18607554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### code v1.2.1 + +#### Changed +- `plan-agent` now verifies Codex findings against the codebase before acting -- rejects findings that don't hold up with evidence, writes a revision summary for cross-round context +- `codex-review` skill accepts `--revisions-file` parameter, injecting Claude's revision summary into Codex's prompt on rounds > 1 so rejected findings are not re-raised + +#### Fixed +- Fixed `plan-with-codex` resume path triggering a redundant user review checkpoint when the user had already confirmed by choosing "resume with existing plan" + ### code v1.2.0 #### Added diff --git a/plugins/code/.claude-plugin/plugin.json b/plugins/code/.claude-plugin/plugin.json index 2548bb66..525d490d 100644 --- a/plugins/code/.claude-plugin/plugin.json +++ b/plugins/code/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "code", "description": "Code and planning framework plugin", - "version": "1.2.0", + "version": "1.2.1", "author": { "name": "ClosedLoop", "email": "support@closedloop.ai" diff --git a/plugins/code/README.md b/plugins/code/README.md index e42af853..9b4cc451 100644 --- a/plugins/code/README.md +++ b/plugins/code/README.md @@ -300,9 +300,9 @@ Implements the validation loop for agents registered in `loop-agents.json`. When Injects tool-specific learnings just before tool execution. Filters `org-patterns.toon` by tool type (Bash patterns get build/test tags; Write/Edit patterns get language-specific tags based on file extension). Injects up to 10 matching patterns as `additionalContext`. Also auto-allows tool calls targeting `.closedloop-ai/` workspace paths without prompting. -### `plan-review.sh` (PostToolUse on ExitPlanMode) +### `plan-review.sh` (not currently registered in `hooks.json`) -Triggers when Claude exits plan mode to get a second opinion via Codex. Extracts plan content from `tool_response.plan`, sends it to Codex (`gpt-5.3-codex-spark`) for review, and injects the feedback as `additionalContext` so Claude sees Codex's concerns inline. Exits silently if no plan content is present or Codex returns empty. Debug logs kept in `.closedloop-ai/plan-review-logs/` (max 15 files). +Triggers when Claude exits plan mode to get a second opinion via Codex. Extracts plan content from `tool_response.plan`, sends it to Codex (`gpt-5.3-codex-spark`) for review, and injects the feedback as `additionalContext` so Claude sees Codex's concerns inline. Exits silently if no plan content is present or Codex returns empty. Debug logs kept in `.closedloop-ai/plan-review-logs/` (max 15 files). This script exists in `hooks/` but is not wired into `hooks.json` -- it would require a PostToolUse entry matching ExitPlanMode to activate. ### `validate-plan.sh` (validation script, not a hook directly) diff --git a/plugins/code/agents/plan-agent.md b/plugins/code/agents/plan-agent.md index 0db21173..f53ef481 100644 --- a/plugins/code/agents/plan-agent.md +++ b/plugins/code/agents/plan-agent.md @@ -88,7 +88,21 @@ Structure plans with these sections: When given feedback to address: 1. Read the current plan file and the feedback file -2. Address ALL concerns raised in the feedback -3. If you disagree with a point, note your reasoning in the plan but still consider the underlying concern -4. If the reviewer proposed a concrete fix, adopt it directly unless you have a strong reason not to +2. **Verify each finding against the codebase before acting on it.** Use `Grep`, `Glob`, and `Read` to check whether the reviewer's claims are accurate (e.g., does the file/function they reference actually exist? Is the behavior they describe real?). Reviewers can hallucinate or misunderstand the codebase. +3. For verified findings: address the concern. If the reviewer proposed a concrete fix, adopt it directly unless you have a strong reason not to. +4. For findings that don't hold up: reject them with a brief explanation and evidence (e.g., "Finding 2 claims X is missing, but `path/to/file:42` already implements it"). 5. Write the updated plan back to the same file path using the `Write` tool +6. **If a revisions file path was provided**, write a revision summary to it. Format: + +```markdown +## Round N Revisions + +### Accepted +- **Finding 1** (title): [what changed in the plan] +- **Finding 3** (title): [what changed in the plan] + +### Rejected +- **Finding 2** (title): [why, with evidence -- e.g., "X already exists at `path/to/file:42`"] +``` + +This file is read by the reviewer on the next round so they have full context on what was addressed and what was pushed back on. diff --git a/plugins/code/commands/plan-with-codex.md b/plugins/code/commands/plan-with-codex.md index b561a7d6..6fe3edde 100644 --- a/plugins/code/commands/plan-with-codex.md +++ b/plugins/code/commands/plan-with-codex.md @@ -61,6 +61,7 @@ Arguments: $ARGUMENTS Derive sidecar paths from the plan file stem (e.g., for `debate-plan.md`): - `{stem}.feedback` -- Codex feedback text +- `{stem}.revisions` -- Claude's revision summary (changes made + pushback on rejected findings) - `{stem}.state` -- phase/round/session state - `{stem}.prompt` -- original prompt (plain text) @@ -185,6 +186,7 @@ Activate `code:codex-review` skill and run: bash /scripts/run_codex_review.sh \ --plan-file {plan-file-abs} \ --feedback-file {feedback-file-abs} \ + --revisions-file {revisions-file-abs} \ --round {N} \ --codex-model {codex-model} \ [--session-id {codex_session_id}] \ @@ -213,7 +215,7 @@ Update TodoWrite: "Round {N}/{max}: Revising plan..." Resume the plan-agent: - description: "Revise plan based on Codex feedback" -- prompt: "Revise the plan at {plan-file-abs} based on feedback at {feedback-file-abs}. Address ALL concerns raised." +- prompt: "Revise the plan at {plan-file-abs} based on feedback at {feedback-file-abs}. Verify each finding against the codebase before acting on it -- reject any that don't hold up. After updating the plan, write a revision summary to {revisions-file-abs}." Verify plan was updated. Write state: `ROUND={N+1}, PHASE=codex_review`, preserve current `CODEX_SESSION_ID` and `LOG_ID`. Continue to next round. @@ -226,7 +228,7 @@ Report outcome: Clean up ALL sidecar files (prompt sidecar deleted intentionally to prevent stale intent on future runs): ```bash -rm -f {state_file} {feedback_file} {prompt_file} +rm -f {state_file} {feedback_file} {revisions_file} {prompt_file} ``` Update TodoWrite: mark all remaining items completed. diff --git a/plugins/code/skills/codex-review/SKILL.md b/plugins/code/skills/codex-review/SKILL.md index a99b6b4e..b12f105a 100644 --- a/plugins/code/skills/codex-review/SKILL.md +++ b/plugins/code/skills/codex-review/SKILL.md @@ -24,6 +24,7 @@ The `scripts/` directory is relative to this skill's base directory (shown above bash /scripts/run_codex_review.sh \ --plan-file \ --feedback-file \ + --revisions-file \ --round \ --codex-model \ [--session-id ] \ @@ -34,6 +35,7 @@ bash /scripts/run_codex_review.sh \ |----------|----------|---------|-------------| | `--plan-file` | Yes | -- | Absolute path to the plan file Codex should review | | `--feedback-file` | Yes | -- | Path where full feedback text will be written | +| `--revisions-file` | No | -- | Path to Claude's revision summary (accepted/rejected findings). If present and round > 1, Codex reads it for context. | | `--round` | No | 1 | Current debate round (affects review prompt intro) | | `--codex-model` | No | gpt-5.4 | Codex model to use | | `--session-id` | No | -- | Thread ID from a previous round for session resume | diff --git a/plugins/code/skills/codex-review/scripts/run_codex_review.sh b/plugins/code/skills/codex-review/scripts/run_codex_review.sh index b88002d2..b8d9bb47 100755 --- a/plugins/code/skills/codex-review/scripts/run_codex_review.sh +++ b/plugins/code/skills/codex-review/scripts/run_codex_review.sh @@ -24,6 +24,7 @@ set -euo pipefail PLAN_FILE="" FEEDBACK_FILE="" +REVISIONS_FILE="" ROUND=1 CODEX_MODEL="gpt-5.4" SESSION_ID="" @@ -31,12 +32,13 @@ LOG_ID="" while [[ $# -gt 0 ]]; do case $1 in - --plan-file) PLAN_FILE="$2"; shift 2 ;; - --feedback-file) FEEDBACK_FILE="$2"; shift 2 ;; - --round) ROUND="$2"; shift 2 ;; - --codex-model) CODEX_MODEL="$2"; shift 2 ;; - --session-id) SESSION_ID="$2"; shift 2 ;; - --log-id) LOG_ID="$2"; shift 2 ;; + --plan-file) PLAN_FILE="$2"; shift 2 ;; + --feedback-file) FEEDBACK_FILE="$2"; shift 2 ;; + --revisions-file) REVISIONS_FILE="$2"; shift 2 ;; + --round) ROUND="$2"; shift 2 ;; + --codex-model) CODEX_MODEL="$2"; shift 2 ;; + --session-id) SESSION_ID="$2"; shift 2 ;; + --log-id) LOG_ID="$2"; shift 2 ;; *) echo "Unknown option: $1" >&2 exit 1 @@ -80,14 +82,22 @@ prompt_file="$tmp_dir/prompt.txt" # ── Build the review prompt ────────────────────────────────────────────────── +REVISIONS_BLOCK="" if [[ "$ROUND" -eq 1 ]]; then REVIEW_INTRO="Claude has created an implementation plan. Review it and provide feedback." else REVIEW_INTRO="Claude has addressed your previous feedback and updated the plan. Re-review the plan for remaining issues." + if [[ -n "$REVISIONS_FILE" ]] && [[ -s "$REVISIONS_FILE" ]]; then + REVISIONS_BLOCK=" + +Claude's revision summary (including any findings that were rejected with evidence) is at: ${REVISIONS_FILE} +Read it before reviewing the plan -- if Claude rejected a finding with valid evidence, do not re-raise it." + fi fi cat > "$prompt_file" <