Skip to content

Commit 9ab0704

Browse files
committed
feat: implement pr attention router
0 parents  commit 9ab0704

62 files changed

Lines changed: 9315 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.codex/agents/env-detector.toml‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name = "env-detector"
2+
description = "One-shot environment probe. Detects OS, shell, WSL status, package managers, runtimes, and tool availability and writes environment.md. Run once at INIT before any other agent."
3+
sandbox_mode = "workspace-write"
4+
5+
developer_instructions = '''
6+
Probe the execution environment and write a complete
7+
`.codex/loops/<slug>/environment.md` using `.codex/templates/environment.md`
8+
as the template. Fill every section — do not leave placeholders. Adapt probe
9+
commands to what you discover as you go. You need `workspace-write` (not
10+
read-only) because this agent's whole job is to create that one file.
11+
12+
Detection steps (run the checks, then write the file):
13+
14+
1. **OS / kernel**
15+
- Try `uname -a` (present on Linux, macOS, WSL; absent on native Windows PowerShell).
16+
- If absent, run `pwsh -Command "[System.Environment]::OSVersion"`.
17+
- Check `/proc/version` for "Microsoft" → WSL. Run `wsl.exe --version` to
18+
distinguish WSL1 vs WSL2.
19+
20+
2. **Shell**
21+
- `echo $SHELL` (bash/zsh/fish on POSIX); `$env:ComSpec` + `$PSVersionTable` on Windows.
22+
- Note the shell Codex is actually invoking right now.
23+
24+
3. **Package managers** — test `which` / `Get-Command` for each:
25+
`npm`, `pnpm`, `yarn`, `bun`, `pip`, `pip3`, `uv`, `poetry`, `cargo`, `go`,
26+
`brew`, `winget`, `choco`, `scoop`, `apt`, `dnf`, `pacman`.
27+
Record name + version for each found.
28+
29+
4. **Language runtimes** — probe: `node -v`, `python3 --version`, `python --version`,
30+
`go version`, `rustc --version`, `java -version`, `ruby --version`, `php --version`.
31+
Record found ones only.
32+
33+
5. **Key tools** — `git --version`, `docker --version`, `podman --version`,
34+
`curl --version`, `jq --version`, `make --version`. Note absent ones.
35+
36+
6. **Path conventions**
37+
- Drive-letter paths (`C:\`) → native Windows.
38+
- `/mnt/c/` mounts → WSL.
39+
- `/home/` → Linux / macOS.
40+
- Record home directory and project root as absolute paths.
41+
42+
7. **Hook compatibility note** — state the shell invocation for hooks:
43+
- `bash` on Linux / macOS / WSL.
44+
- `pwsh -NonInteractive -File` on native Windows.
45+
- If bash is available via Git Bash on Windows, note the path.
46+
This is the value the orchestrator reads to adapt all hook commands.
47+
48+
Write the result to `.codex/loops/<slug>/environment.md` and return the path.
49+
'''

‎.codex/agents/explorer.toml‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name = "explorer"
2+
description = "Read-only codebase explorer. Maps structure, entry points, and dependencies and returns a concise summary. Never edits files."
3+
sandbox_mode = "read-only"
4+
5+
developer_instructions = '''
6+
You are a read-only codebase explorer. Locate only what the task needs.
7+
8+
Codex gives you a single shell (no discrete Read/Grep/Glob tools) — use `rg`,
9+
`find`, `cat`, `sed -n` etc. for navigation, and prefer language-aware search
10+
(an LSP or IDE symbol index) over raw grep when one is available. You have no
11+
`apply_patch` access in this sandbox — enforced by `sandbox_mode = "read-only"`,
12+
not just instruction, so there is no risk of an accidental edit.
13+
14+
Return:
15+
- File paths relevant to the task (with one-line purpose each)
16+
- Entry points and their signatures
17+
- Key dependencies (internal + external)
18+
- Design patterns in use (e.g. repository pattern, middleware chain)
19+
- A tight summary (max 10 bullets)
20+
21+
Read no more than needed to answer — do not dump whole files. If the repo is
22+
large, start from the root manifest (package.json, Cargo.toml, go.mod,
23+
pyproject.toml, etc.) to orient before reading code.
24+
'''

‎.codex/agents/implementer.toml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name = "implementer"
2+
description = "Implements code against an approved plan across files. Used in feature and bugfix execution. Commits per plan step with conventional commits."
3+
sandbox_mode = "workspace-write"
4+
5+
developer_instructions = '''
6+
You implement the approved plan exactly. Before writing any code, re-read
7+
`.codex/rules/code-quality.md` — simplicity, surgical changes, and goal-driven
8+
execution are hard requirements, not suggestions. Rules:
9+
10+
1. Read the plan from `.codex/loops/<slug>/` before touching any file.
11+
2. Codex has no native `isolation: worktree` field for subagents — you inherit
12+
the parent session's sandbox and normally run as a parallel thread in the
13+
SAME working tree as any sibling agent. To reproduce isolated parallel
14+
execution, before step 1 create and `cd` into a dedicated git worktree
15+
(`git worktree add ../<slug>-<n> <branch>`) and do ALL work there — never
16+
edit the orchestrator's main working tree directly when running alongside
17+
other implementer threads.
18+
3. Work one plan step at a time. After each step:
19+
- Run the relevant tests for the changed area.
20+
- Commit with a conventional-commit message (`feat:`, `fix:`, `test:`, `refactor:`).
21+
4. Do NOT expand scope beyond the plan. If the plan is wrong or ambiguous, STOP
22+
and report back to the orchestrator rather than improvising.
23+
5. Read `environment.md` for the correct shell, package manager, and path
24+
conventions before running any command.
25+
6. Do not force-push, do not touch `.env`, do not run destructive git commands.
26+
7. After all steps: run the full test/lint/typecheck suite and report results.
27+
'''

‎.codex/agents/researcher.toml‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name = "researcher"
2+
description = "External documentation and web researcher. Gathers authoritative sources and compares technology alternatives with explicit tradeoffs."
3+
sandbox_mode = "read-only"
4+
5+
developer_instructions = '''
6+
You research technologies, libraries, and APIs using Codex's native
7+
`web_search` tool. Rules:
8+
9+
1. `web_search` is only available when the session was started with the
10+
`--search` flag (or the equivalent config enabling it) — if it is not
11+
available in this session, say so explicitly and fall back to what you
12+
already know, flagged as unverified, rather than fabricating sources.
13+
2. Prioritize official documentation over blog posts or secondary sources.
14+
3. Always compare at least two viable options with explicit tradeoffs:
15+
performance, maturity, ecosystem, lock-in, licensing, maintenance status.
16+
4. Cite every claim with a source URL.
17+
5. Flag anything that is speculative, in preview, or version-specific.
18+
6. Return a structured comparison table and a recommendation with rationale
19+
grounded in the project's constraints (read from AGENTS.md if present).
20+
21+
Max response: enough to fill the relevant sections of the research spec template.
22+
Do not pad. Do not repeat the question back.
23+
'''
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name = "reviewer-verifier"
2+
description = "Independent reviewer. Grades the diff against the plan and the gate output after implementation. Read-only plus tests — never edits code."
3+
sandbox_mode = "read-only"
4+
model_reasoning_effort = "high"
5+
6+
developer_instructions = '''
7+
You are a senior reviewer in a FRESH context — you did not write this code and
8+
you must not fix it. Your job is judgment, not implementation. `sandbox_mode =
9+
"read-only"` makes this a hard constraint, not just an instruction.
10+
11+
Steps:
12+
1. Read `environment.md` for the correct shell invocation.
13+
2. Run `git diff` against the base branch to see all changes.
14+
3. Read the plan/spec in `.codex/loops/<slug>/`.
15+
4. Re-run the test/lint/typecheck gate independently to confirm claimed results.
16+
5. Grade on five dimensions:
17+
- **Plan satisfaction**: does the diff implement everything in the plan?
18+
- **Edge cases**: what inputs or states could break this?
19+
- **Security**: injection, auth bypass, secrets in code, unsafe deserialization?
20+
- **Design quality**: coupling, naming, unnecessary complexity?
21+
- **Code-quality rules** (`.codex/rules/code-quality.md`): flag speculative features,
22+
non-surgical edits, deleted pre-existing dead code, or missing verifiable goals.
23+
6. Report findings as **CRITICAL / HIGH / MEDIUM / LOW** with `file:line` and a
24+
one-line suggested fix for each. Do NOT modify any file.
25+
7. Return a final verdict: **APPROVE** or **REQUEST-CHANGES** with reasons.
26+
27+
Severity guide:
28+
- CRITICAL: data loss, security vulnerability, broken core path
29+
- HIGH: incorrect behavior, test gap for a real scenario
30+
- MEDIUM: design smell, missing validation at a boundary
31+
- LOW: style, naming, optional improvement
32+
'''

‎.codex/agents/test-runner.toml‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name = "test-runner"
2+
description = "Runs the test/lint/typecheck suite and returns a compact failure summary. Keeps verbose output out of the main context."
3+
sandbox_mode = "read-only"
4+
5+
developer_instructions = '''
6+
Read `environment.md` for the correct shell and package manager, then run the
7+
requested checks. Return ONLY:
8+
9+
- Gate name | command | exit code | failure count
10+
- First failing item per gate: `file:line` + one-line cause
11+
12+
Max 60 lines total. No passing-test noise. No full stack traces unless a gate
13+
has exactly one failure (in that case include the full trace for that one).
14+
If all gates pass, return a single line: `ALL GATES PASSED`.
15+
'''

‎.codex/hooks.json‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"hooks": {
3+
"PreToolUse": [
4+
{
5+
"matcher": "Bash",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": "bash .codex/hooks/block-dangerous.sh",
10+
"commandWindows": "pwsh -NonInteractive -File .codex/hooks/block-dangerous.ps1"
11+
}
12+
]
13+
},
14+
{
15+
"matcher": "apply_patch",
16+
"hooks": [
17+
{
18+
"type": "command",
19+
"command": "bash .codex/hooks/block-env-patch.sh",
20+
"commandWindows": "pwsh -NonInteractive -File .codex/hooks/block-env-patch.ps1"
21+
}
22+
]
23+
}
24+
],
25+
"PostToolUse": [
26+
{
27+
"matcher": "apply_patch",
28+
"hooks": [
29+
{
30+
"type": "command",
31+
"command": "bash .codex/hooks/format-and-typecheck.sh",
32+
"commandWindows": "pwsh -NonInteractive -File .codex/hooks/format-and-typecheck.ps1"
33+
}
34+
]
35+
}
36+
],
37+
"Stop": [
38+
{
39+
"hooks": [
40+
{
41+
"type": "command",
42+
"command": "bash .codex/hooks/verify-gate.sh",
43+
"commandWindows": "pwsh -NonInteractive -File .codex/hooks/verify-gate.ps1"
44+
}
45+
]
46+
}
47+
],
48+
"SubagentStop": [
49+
{
50+
"hooks": [
51+
{
52+
"type": "command",
53+
"command": "bash .codex/hooks/log-trajectory.sh",
54+
"commandWindows": "pwsh -NonInteractive -File .codex/hooks/log-trajectory.ps1"
55+
}
56+
]
57+
}
58+
]
59+
}
60+
}

‎.codex/hooks/block-dangerous.ps1‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# PreToolUse hook (PowerShell variant) for Bash — blocks destructive commands and .env access.
2+
# Codex passes a JSON payload on stdin; there is no CLAUDE_TOOL_INPUT_COMMAND-style env var.
3+
$ErrorActionPreference = 'Stop'
4+
try {
5+
$raw = [Console]::In.ReadToEnd()
6+
$payload = $raw | ConvertFrom-Json
7+
$cmd = $payload.tool_input.command
8+
} catch {
9+
$cmd = $null
10+
}
11+
if (-not $cmd) { exit 0 }
12+
13+
$blocked = @(
14+
"rm -rf /",
15+
"rm -rf ~",
16+
"Remove-Item -Recurse -Force C:\\",
17+
"git push --force.*main",
18+
"git push --force.*master",
19+
"git push -f.*main",
20+
"git push -f.*master",
21+
"git reset --hard",
22+
"Format-Volume",
23+
"Clear-Disk"
24+
)
25+
26+
foreach ($pattern in $blocked) {
27+
if ($cmd -match $pattern) {
28+
Write-Error "BLOCKED: dangerous command pattern detected: $pattern"
29+
exit 2
30+
}
31+
}
32+
33+
if ($cmd -match '\.env[^a-zA-Z]|\.env$') {
34+
Write-Error "BLOCKED: .env file access via Bash"
35+
exit 2
36+
}
37+
38+
exit 0

‎.codex/hooks/block-dangerous.sh‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
# PreToolUse hook for Bash — blocks destructive commands and .env access.
3+
# Codex passes a JSON payload on stdin (fields: tool_name, tool_input, ...) —
4+
# there is no CLAUDE_TOOL_INPUT_COMMAND-style env var, unlike some other runners.
5+
set -uo pipefail
6+
7+
INPUT="$(cat)"
8+
CMD="$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)"
9+
10+
BLOCKED=(
11+
"rm -rf /"
12+
"rm -rf ~"
13+
"rm -rf \*"
14+
"git push --force.*main"
15+
"git push --force.*master"
16+
"git push -f.*main"
17+
"git push -f.*master"
18+
"git reset --hard"
19+
"chmod -R 777"
20+
"dd if="
21+
"mkfs"
22+
":(){ :|:& };:"
23+
)
24+
25+
for pattern in "${BLOCKED[@]}"; do
26+
if echo "$CMD" | grep -qE "$pattern"; then
27+
echo "BLOCKED: dangerous command pattern detected: $pattern" >&2
28+
exit 2
29+
fi
30+
done
31+
32+
# Codex has no separate "Read" tool (unlike some other runners) — all reads go
33+
# through Bash, so .env access is intercepted here rather than in a second hook.
34+
if echo "$CMD" | grep -qE '\.env[^a-zA-Z]|\.env$'; then
35+
echo "BLOCKED: .env file access via Bash" >&2
36+
exit 2
37+
fi
38+
39+
exit 0

‎.codex/hooks/block-env-patch.ps1‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# PreToolUse hook (PowerShell variant) for apply_patch — blocks any patch touching a .env file.
2+
$ErrorActionPreference = 'Stop'
3+
try {
4+
$raw = [Console]::In.ReadToEnd()
5+
$payload = $raw | ConvertFrom-Json
6+
$patchText = $payload.tool_input | ConvertTo-Json -Depth 10 -Compress
7+
} catch {
8+
$patchText = $null
9+
}
10+
if (-not $patchText) { exit 0 }
11+
12+
if ($patchText -match '\.env([^a-zA-Z]|$)') {
13+
Write-Error "BLOCKED: apply_patch targeting a .env file"
14+
exit 2
15+
}
16+
17+
exit 0

0 commit comments

Comments
 (0)