Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
23 changes: 17 additions & 6 deletions .ai/allowlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,33 @@
"codex_reasoning_effort": "medium",
"models": {
"planner": "gpt-6-astra",
"plan-reviewer-a": "claude-opus-5",
"plan-reviewer-a": "claude-opus-5-5",
"plan-reviewer-b": "gpt-6-astra",
"arbiter": "claude-opus-5",
"arbiter": "claude-opus-5-5",
"builder": "gpt-6-astra",
Comment thread
KjellKod marked this conversation as resolved.
Outdated
"code-reviewer-a": "claude-opus-5",
"code-reviewer-a": "claude-opus-5-5",
"code-reviewer-b": "gpt-6-astra",
"review-arbiter": "claude-opus-5",
"review-arbiter": "claude-opus-5-5",
"fixer": "gpt-6-astra"
},
"effort": {
"planner": "high",
"plan-reviewer-a": "medium",
"plan-reviewer-b": "medium",
"arbiter": "high",
"builder": "high",
"code-reviewer-a": "high",
"code-reviewer-b": "high",
"review-arbiter": "high",
"fixer": "medium"
},
"quest_startup": {
"branch_mode": "branch",
"branch_prefix": "quest/",
"worktree_root": ".worktrees/quest"
},
"quest_id_format": "slug-first",
"review_mode": "full",
"review_mode": "auto",
"fast_review_thresholds": {
"max_files": 5,
"max_loc": 300
Expand Down Expand Up @@ -253,7 +264,7 @@
"require_approval_before_commit": true,
"require_approval_before_push": true,
"require_approval_before_delete": true,
"max_plan_iterations": 4,
"max_plan_iterations": 3,
"max_fix_iterations": 3
}
}
1 change: 1 addition & 0 deletions .ai/quest.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ When a role invocation fails (missing/unparsable handoff), Quest uses a three-ti
The Creator controls quest permissions via `.ai/allowlist.json`:
- `auto_approve_phases` — which phases need human approval
- `models` — default role model map (`planner`, `plan-reviewer-a`, `plan-reviewer-b`, `builder`, `code-reviewer-a`, `code-reviewer-b`, `arbiter`, `fixer`)
- `effort` — reasoning effort per role, applied on whichever runtime the role's model selects. Run `scripts/quest_sync_model_defaults.py` after editing `models` or `effort`; the generator is what keeps the four dispatch surfaces in step.
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
- `review_mode` — `auto` (default), `fast`, or `full` for Codex reviews
- `fast_review_thresholds` — file/LOC thresholds for auto fast mode

Expand Down
13 changes: 12 additions & 1 deletion .ai/schemas/allowlist.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,18 @@
"codex_reasoning_effort": {
"type": "string",
"enum": ["low", "medium", "high", "xhigh", "max", "ultra"],
"description": "Reasoning effort pinned for Codex roles in new quests. Must be supported by the selected model and dispatch surface."
"description": "Legacy fallback: reasoning effort for Codex roles absent from the per-role `effort` map. New quests should use `effort`."
},
"effort": {
"type": "object",
"propertyNames": {
"enum": ["planner", "plan-reviewer-a", "plan-reviewer-b", "arbiter", "builder", "code-reviewer-a", "code-reviewer-b", "review-arbiter", "fixer"]
},
"additionalProperties": {
"type": "string",
"enum": ["low", "medium", "high", "xhigh", "max", "ultra"]
},
"description": "Reasoning effort per role, applied on whichever runtime the role's model selects. `ultra` is Codex-only and blocks a Claude-backed role at dispatch."
},
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
"models": {
"type": "object",
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/arbiter.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: arbiter
description: Gatekeeper for plan quality. Synthesizes reviews, filters noise, decides if plan is ready for implementation.
tools: Read, Glob, Grep, Write
model: inherit
effort: high
Comment thread
KjellKod marked this conversation as resolved.
Outdated
---

You are the Arbiter Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: builder
description: Implements approved plans. Writes code, runs tests, produces PR description.
tools: Read, Glob, Grep, Write, Edit, Bash
model: inherit
effort: high
Comment thread
KjellKod marked this conversation as resolved.
Outdated
---

You are the Builder Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: code-reviewer
description: Reviews code changes for correctness, quality, security, and adherence to project patterns.
tools: Read, Glob, Grep, Write
model: inherit
effort: high
Comment thread
KjellKod marked this conversation as resolved.
Outdated
---

You are the Code Review Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/fixer.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: fixer
description: Fixes issues identified by code review. Applies targeted fixes and re-runs tests.
tools: Read, Glob, Grep, Write, Edit, Bash
model: inherit
effort: medium
---

You are the Fixer Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/plan-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: plan-reviewer
description: Reviews implementation plans for feasibility, completeness, and alignment with acceptance criteria.
tools: Read, Glob, Grep, Write
model: inherit
effort: medium
---

You are a Plan Review Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/planner.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: planner
description: Creates and refines implementation plans from quest briefs. Writes plans to .quest/ folder.
tools: Read, Glob, Grep, Write, Edit, Bash
model: inherit
effort: high
---

You are the Planner Agent in a quest orchestration system.
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/review-arbiter.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: review-arbiter
description: Impartial judge for the code-review phase. Adjudicates the two code-reviewer slot findings against the diff and emits the canonical review_findings.json.
tools: Read, Glob, Grep, Write
model: inherit
effort: high
Comment thread
KjellKod marked this conversation as resolved.
Outdated
---

You are the Review Arbiter Agent in a quest orchestration system.
Expand Down
8 changes: 4 additions & 4 deletions .opencode/opencode.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"plan-reviewer-a": {
"description": "Reviews implementation plans (Reviewer A - local subagent)",
"mode": "subagent",
"model": "opencode/claude-opus-5",
"model": "opencode/claude-opus-5-5",
"prompt": "{file:agents/plan-reviewer.md}",
"permission": {
"edit": {
Expand All @@ -67,7 +67,7 @@
"arbiter": {
"description": "Synthesizes dual reviews, renders APPROVE or ITERATE verdict",
"mode": "subagent",
"model": "opencode/claude-opus-5",
"model": "opencode/claude-opus-5-5",
"prompt": "{file:agents/arbiter.md}",
"permission": {
"edit": {
Expand Down Expand Up @@ -105,7 +105,7 @@
"code-reviewer-a": {
"description": "Reviews code changes (Reviewer A - local subagent)",
"mode": "subagent",
"model": "opencode/claude-opus-5",
"model": "opencode/claude-opus-5-5",
"prompt": "{file:agents/code-reviewer.md}",
"permission": {
"edit": {
Expand Down Expand Up @@ -141,7 +141,7 @@
"review-arbiter": {
"description": "Impartial judge for the code-review phase; adjudicates A/B findings against the diff and emits canonical review_findings.json",
"mode": "subagent",
"model": "opencode/claude-opus-5",
"model": "opencode/claude-opus-5-5",
"prompt": "{file:agents/review-arbiter.md}",
"permission": {
"edit": {
Expand Down
5 changes: 3 additions & 2 deletions .skills/quest/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ Before creating the quest folder, present the routing classification to the user
- `claude_transport_resolved`: the `transport` field from the Step 2b preflight result (Codex-led sessions; `null` otherwise)
- `claude_transport_downgraded`: compatibility field; write `false` for new runs (Codex-led preflight also emits `false`)
- `codex_auth_mode`: persist the resolved Step 2b `checks.codex_auth_mode`, not a later allowlist re-read; pass it as `codex_auth_mode` to `write_default_from_allowlist`. In Codex-led startup retain the explicitly resolved mode for any later Claude-led resume; native Codex dispatch continues using the host identity.
- `codex_reasoning_effort`: copy the optional allowlist value verbatim and pass it to `write_default_from_allowlist`; validate with `validate_codex_reasoning_effort`. Omit it for older allowlists with no setting. Show the selected effort beside the model table before accepting defaults.
- `effort`: `.ai/allowlist.json` `.effort` passed verbatim to `write_default_from_allowlist`, which fills omitted roles from the shipped `DEFAULT_EFFORT`. Show the per-role effort beside the model table before accepting defaults.
- `codex_reasoning_effort`: legacy fallback for allowlists with no `.effort` map — copy the optional value verbatim and pass it through; validate with `validate_codex_reasoning_effort`. Omit it when unset.
- `source: "default"`
- `overridden_roles: []`
- `preflight_validated_at: <ISO8601 now>`
Expand Down Expand Up @@ -271,7 +272,7 @@ Before creating the quest folder, present the routing classification to the user
- `models`: merged block (all 9 keys present; unused-in-mode roles still carry the default value)
- `claude_role_transport` / `claude_transport_resolved`: same sourcing as the Y path above; `claude_transport_downgraded: false` for compatibility
- `codex_auth_mode`: same resolved Step 2b mode as the Y path; pass it to `write_orchestration_json`.
- `codex_reasoning_effort`: same allowlist sourcing as the Y path; pass it to `write_orchestration_json`. Model-only overrides do not change effort; validate model support before dispatch.
- `effort` / `codex_reasoning_effort`: same allowlist sourcing as the Y path; pass both to `write_orchestration_json`. Model-only overrides do not change effort; validate model support before dispatch.
- `source: "overridden"`
- `overridden_roles`: list of role names that were actually overridden
- `preflight_validated_at: <ISO8601 now>`
Expand Down
8 changes: 4 additions & 4 deletions .skills/quest/delegation/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ Quest dispatch separates **runtime** from **entrypoint**:
| Orchestrator | Selected role runtime | Entrypoint | Rule |
|--------------|-----------------------|------------|------|
| Codex-led | Codex | local Codex subagent (the `spawn_agent` tool family — versioned namespace such as `multi_agent_v2` varies by Codex CLI release — or repo-supported equivalent) | Use the saved model and Codex effort according to the explicit-selection contract below. Do not use Codex MCP. |
| Codex-led | Claude | `python3 scripts/quest_claude_runner.py` when `claude_transport_available` is true | The runner owns the transport underneath: background-agent (`scripts/quest_claude_bg_run.py`, `claude --bg`, subscription billing) when preflight proved it, or the bridge (`scripts/quest_claude_bridge.py`, `claude --print`) only when bridge was explicitly configured/selected. Pass `--model <models.<role> from .quest/<id>/orchestration.json>` and `--transport <claude_transport_resolved from orchestration.json>`. The exact `claude` model sentinel means use the Claude CLI/account default and must not be sent to the CLI as `--model claude`; concrete configured model strings pass through unchanged. Block with transport guidance if unavailable and no explicit Codex fallback exists. |
| Codex-led | Claude | `python3 scripts/quest_claude_runner.py` when `claude_transport_available` is true | The runner owns the transport underneath: background-agent (`scripts/quest_claude_bg_run.py`, `claude --bg`, subscription billing) when preflight proved it, or the bridge (`scripts/quest_claude_bridge.py`, `claude --print`) only when bridge was explicitly configured/selected. Pass `--model <models.<role> from .quest/<id>/orchestration.json>` and `--transport <claude_transport_resolved from orchestration.json>`. The runner resolves `effort.<role>` from the same saved file and passes `claude --effort`; do not pass `--effort` yourself unless deliberately overriding the saved config. The exact `claude` model sentinel means use the Claude CLI/account default and must not be sent to the CLI as `--model claude`; concrete configured model strings pass through unchanged. Block with transport guidance if unavailable and no explicit Codex fallback exists. |
| Claude-led | Codex | `python3 <installation-root>/scripts/quest_codex_runner.py role` when `codex_available` is true | The runner launches installed `codex exec`, reads saved model, effort and auth, and validates current-attempt artifacts. |
| Claude-led | Claude | native `Task(...)` | Use the orchestrator's native Claude task path. |
| Claude-led | Claude | native `Task(...)` | Use the orchestrator's native Claude task path. Native tasks cannot read `orchestration.json`, so do not try to pass effort here; the only available control is the subagent's `effort:` frontmatter, generated from the allowlist by `scripts/quest_sync_model_defaults.py`. **Unverified:** on Claude Code 2.1.280 that key could not be shown to change behavior (an invalid value raises no warning, and low-vs-max showed no token separation), unlike `claude --effort`, which measurably does. Treat effort on this path as best-effort; route through the runner when it must be guaranteed. |
| Either orchestrator | Antigravity | `python3 scripts/quest_antigravity_runner.py` when `antigravity_available` is true | Selected by Gemini-family model IDs. Antigravity is never an orchestrator, only ever a dispatched runtime, so one runner serves both session types — there is no MCP path and no transport choice. Pass `--model <models.<role> from .quest/<id>/orchestration.json>`; the exact `gemini` sentinel means use the agy default model and must not be sent to the CLI as `--model gemini`. **Always pass `--add-dir` covering the quest directory** — see the Antigravity containment rule below. Block with the preflight `warning` lines if unavailable. |

**Explicit model and effort selection:** Before every Codex role dispatch, read `models.<role>` and optional `codex_reasoning_effort` from the active quest's `orchestration.json`. Do not substitute defaults from this skill, the GPT skill, or the current allowlist. For local subagents, pass the exact `model` and, when set, `reasoning_effort` through the tool's exposed controls. This repository configuration authorizes explicit selection. When the tool requires a fresh or bounded context fork for overrides, use that mode and include the role instructions and artifact paths in the prompt. If the controls are unavailable, inherit only after verifying the parent matches the saved model and any pinned effort; otherwise stop and report the mismatch. Never substitute MCP or nested `codex exec` for Codex-led dispatch.
**Explicit model and effort selection:** Before every Codex role dispatch, read `models.<role>` and `effort.<role>` from the active quest's `orchestration.json` (quests written before the per-role map fall back to the legacy scalar `codex_reasoning_effort`). Do not substitute defaults from this skill, the GPT skill, or the current allowlist. For local subagents, pass the exact `model` and, when set, `reasoning_effort` through the tool's exposed controls. This repository configuration authorizes explicit selection. When the tool requires a fresh or bounded context fork for overrides, use that mode and include the role instructions and artifact paths in the prompt. If the controls are unavailable, inherit only after verifying the parent matches the saved model and any pinned effort; otherwise stop and report the mismatch. Never substitute MCP or nested `codex exec` for Codex-led dispatch.

For Claude-led Codex calls, use the installed runner's `role` mode. It reads `models.<role>`, optional `codex_reasoning_effort` and `codex_auth_mode` (legacy default `cached`) from the saved orchestration file. Do not pass model, effort or auth overrides in role mode. Unsupported settings block dispatch. Log requested settings separately from effective settings; effective values require runtime metadata, otherwise record `unknown`.
For Claude-led Codex calls, use the installed runner's `role` mode. It reads `models.<role>`, `effort.<role>` (falling back to the legacy `codex_reasoning_effort`) and `codex_auth_mode` (legacy default `cached`) from the saved orchestration file. Do not pass model, effort or auth overrides in role mode. Unsupported settings block dispatch. Log requested settings separately from effective settings; effective values require runtime metadata, otherwise record `unknown`.

**Orchestration violation:** A Codex-led attempt to dispatch another Codex role through MCP or nested `codex exec` is an entrypoint violation. Use local Codex subagents with the saved model and effort. Missing native controls or mismatched parent settings block, with no CLI/MCP substitution or saved-setting rewrite.

Expand Down
10 changes: 10 additions & 0 deletions scripts/quest_claude_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
default="",
help="Optional Claude model override (passed through if provided)",
)
parser.add_argument(
"--effort",
default="",
choices=["", "low", "medium", "high", "xhigh", "max"],
help="Optional reasoning effort; empty uses the CLI/session default",
)
parser.add_argument(
"--system-prompt",
default="",
Expand Down Expand Up @@ -160,13 +166,16 @@ def run_claude(
add_dirs: list[str],
allowed_tools: str,
disallowed_tools: str,
effort: str = "",
) -> dict[str, Any]:
cmd = ["claude", "--print", prompt, "--output-format", output_format]
# `claude` is the runtime-family sentinel meaning account-default model —
# never a CLI model name (defense-in-depth mirroring the bg runner; the
# quest layer normalizes it away, but direct callers reach here unfiltered).
if model and model != "claude":
cmd.extend(["--model", model])
if effort:
Comment thread
KjellKod marked this conversation as resolved.
cmd.extend(["--effort", effort])
if system_prompt:
cmd.extend(["--system-prompt", system_prompt])
if append_system_prompt:
Expand Down Expand Up @@ -240,6 +249,7 @@ def main(argv: list[str] | None = None) -> int:
output_format=args.output_format,
timeout=args.timeout,
model=args.model,
effort=args.effort,
system_prompt=args.system_prompt,
append_system_prompt=args.append_system_prompt,
permission_mode=args.permission_mode,
Expand Down
34 changes: 34 additions & 0 deletions scripts/quest_claude_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pathlib import Path

from quest_runtime.artifacts import expected_artifacts_for_role
from quest_runtime.orchestration import effort_for_role
from quest_runtime.claude_runner import (
DEFAULT_BG_RUNNER_SCRIPT,
DEFAULT_BRIDGE_SCRIPT,
Expand Down Expand Up @@ -79,6 +80,14 @@ def parse_args() -> argparse.Namespace:
default=1800.0,
help="Command timeout seconds (default: 1800)",
)
parser.add_argument(
"--effort",
choices=["low", "medium", "high", "xhigh", "max"],
help=(
"Reasoning effort. Omit to resolve effort.<agent> from the quest's "
"orchestration.json (the normal path); pass only to override it."
),
)
parser.add_argument("--permission-mode", default="bypassPermissions")
parser.add_argument(
"--transport",
Expand Down Expand Up @@ -127,6 +136,27 @@ def parse_args() -> argparse.Namespace:
return args


def _resolve_effort(quest_dir: str, agent: str, override: str | None) -> str | None:
"""Effort for this dispatch: explicit flag, else the saved per-role map.

Resolving from orchestration.json here (rather than trusting the
orchestrator to pass it) mirrors Codex role mode and keeps the saved quest
config authoritative. A quest with no orchestration.json yet resolves to
None, which leaves the CLI default in place.
"""
if override:
return override
try:
saved = json.loads(
(Path(quest_dir) / "orchestration.json").read_text(encoding="utf-8")
)
except (OSError, json.JSONDecodeError):
return None
if not isinstance(saved, dict):
return None
return effort_for_role(saved, agent)
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.


def main() -> int:
args = parse_args()
transport = resolve_claude_transport(args.transport)
Expand All @@ -149,6 +179,9 @@ def main() -> int:
agent=args.agent,
artifact_subset=args.artifact_subset,
)
effort = _resolve_effort(
args.quest_dir, args.agent, getattr(args, "effort", None)
)
except ValueError as exc:
payload = {
"exit_code": 1,
Expand Down Expand Up @@ -184,6 +217,7 @@ def main() -> int:
handoff_file=args.handoff_file,
bridge_script=resolve_path(args.cwd, args.bridge_script),
model=args.model,
effort=effort,
timeout=args.timeout,
permission_mode=args.permission_mode,
artifact_paths=artifact_paths,
Expand Down
Loading
Loading