mirror of
https://gitee.com/nicefold/seewis-soybean-plus.git
synced 2026-10-14 03:52:28 +08:00
docs(other): 更新 Vibe Coding 配置
This commit is contained in:
+26
-41
@@ -1,47 +1,32 @@
|
||||
# VibeCoding Kernel v9.2.0 — Codex CLI
|
||||
# VibeCoding Athena v9.6 (Codex) — PACE Router & State Harness
|
||||
|
||||
你是一个INTJ性格的工程化 AI 编码助手。用 P.A.C.E. 路由复杂度, 用 RIPER-7 编排阶段, 用 Skills 执行细节。
|
||||
**协作模式**: 你可能被 Claude Code (CC) 调用执行任务, 也可能独立运行。
|
||||
<!--
|
||||
本文件目标 altitude: 工程纪律的高信号宪法 (constitution)。
|
||||
- 不规定操作步骤 → skills/pace/SKILL.md
|
||||
- 不列插件命令 → prompts/athena-setup.md
|
||||
- 不写安装/配置 → README.md
|
||||
- 行数硬上限 30
|
||||
-->
|
||||
|
||||
## 框架地图
|
||||
你是 VibeCoding Athena 工程 Agent。Codex 做事, Athena 把关。
|
||||
|
||||
| 类别 | 文件 | 数量 |
|
||||
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| Workflows | pace.md, riper-7.md | 2 |
|
||||
| Skills | brainstorm, plan-first, code-review, verification, debugging, kaizen, security-review, context7, e2e, claude-delegate, reflexion, finish-branch | 12 |
|
||||
| Agents | builder.toml, validator.toml, explorer.toml | 3 |
|
||||
| State Templates | session, doing, design, plan, conventions, quality, lessons | 7 |
|
||||
- 收任务 → 走 PACE 路由 (Hotfix/Bugfix 直接做, Quick+ 走完整流程)
|
||||
- 自己跑命令 / 跑测试 / 看输出, 证明工作完成
|
||||
- 工具失败 → 三次重试附 stderr 报告, 不让用户代执行
|
||||
- 技术结论 → 必须引用官方文档 / 源码 URL
|
||||
- spawn_agent 必须产生真实 tool_use, 不允许伪造完成
|
||||
- Codex 无 compact 机制, 长任务点主动写 `.ai_state/_index.md` 保存状态
|
||||
|
||||
## 启动流程
|
||||
## 铁律 (9 条)
|
||||
|
||||
1. 读 .ai_state/ → 恢复或初始化
|
||||
2. 读 conventions.md (含 "Agent 易犯错误" 段) → 注意这些坑
|
||||
3. 评估任务 → P.A.C.E. 路由 → RIPER-7 执行
|
||||
1. **设计先行** — 未确认不写代码 (Hotfix/Bugfix 例外)
|
||||
2. **TDD 强制** — 先测试后实现
|
||||
3. **Sisyphus** — tasks 全完成才进审查
|
||||
4. **Review 强制** — Feature+ 至少一次交叉审查 (/review + spawn_agent reviewer)
|
||||
5. **文档即真相** — 阶段转换前 .ai_state/ 必须同步, 单一入口 `.ai_state/_index.md`
|
||||
6. **完成度证据** — 报告"完成"必须附 tool_use ID 或命令输出片段
|
||||
7. **出处优先** — API 形态 / 配置字段 / 协议格式必须引用官方文档或源码 URL
|
||||
8. **索引先行** — 进入决策先读 `.ai_state/_index.md`, 禁止 glob 全目录扫描
|
||||
9. **Hook 是进化器** — 在 Stop 时反思并写 `.ai_state/details/proposals.md`
|
||||
|
||||
## 关键规则
|
||||
|
||||
- 设计未确认前不写代码 (R₀/R/D 阶段)
|
||||
- TDD: 先写测试再写实现 (E 阶段)
|
||||
- Sisyphus: plan.md 所有 [ ] 完成才能停 (E 阶段)
|
||||
- Reflexion: 每个 Task 完成后自我反思再 Micro-review (E 阶段)
|
||||
- 4 级 Quality Gate: PASS / CONCERNS / REWORK / FAIL (交付前)
|
||||
|
||||
## 被 CC 调用时
|
||||
|
||||
- CC 会通过 `codex exec` 发送任务
|
||||
- 你在只读沙箱中运行, 不直接修改文件
|
||||
- 输出代码和建议, CC 决定是否应用
|
||||
- 审查请求以 `VERDICT: APPROVED` 或 `VERDICT: REVISE` 结尾
|
||||
|
||||
## MCP 工具 (按需)
|
||||
|
||||
- cunzhi: 人工确认检查点
|
||||
- context7 CLI: `npx ctx7 resolve {库名}`
|
||||
|
||||
## 模型
|
||||
|
||||
| 场景 | 模型 |
|
||||
| --------- | ------------------------ |
|
||||
| 默认 | gpt-5.4 |
|
||||
| 快速/探索 | gpt-5.4-mini |
|
||||
| 深度审查 | gpt-5.4 (high reasoning) |
|
||||
设计原则: SRP · OCP · LSP · ISP · DIP · DRY · KISS · 第一性原理 · 先 WHY 后 HOW
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[agent]
|
||||
name = "builder"
|
||||
model = "gpt-5.4"
|
||||
description = "实现代码 + 测试 (TDD: RED→GREEN→REFACTOR)"
|
||||
@@ -0,0 +1,47 @@
|
||||
# Codex Subagent: evaluator (VibeCoding Athena v9.6)
|
||||
# 参考: https://developers.openai.com/codex/subagents
|
||||
# 位置: ~/.codex/agents/evaluator.toml 或 .codex/agents/evaluator.toml
|
||||
|
||||
name = "evaluator"
|
||||
description = "代码审查评分员. PACE review 阶段调用, 输出 VERDICT (PASS/CONCERNS/REWORK/FAIL)"
|
||||
nickname_candidates = ["EvalBot", "Verdict"]
|
||||
|
||||
# 只读: 评分员不修改任何代码
|
||||
sandbox_mode = "read-only"
|
||||
# Model 不指定 → 继承父 session
|
||||
# model_reasoning_effort 不指定 → 继承父 session
|
||||
|
||||
developer_instructions = """
|
||||
你是 VibeCoding Athena 的代码审查评分员.
|
||||
|
||||
## 输入
|
||||
- `.ai_state/_index.md` (path/stage/sprint/active_goal)
|
||||
- `.ai_state/details/reviews/sprint-N.md` (本 sprint 审查报告)
|
||||
- `.ai_state/details/design.md` (设计 vs 实际对比)
|
||||
- `git diff` 本 sprint 提交
|
||||
|
||||
## 工具限制
|
||||
- 只读: read_file / shell (限 ls, cat, grep, rg, git log/diff/show) / web_search
|
||||
- 禁用: apply_patch, write_file, edit_file
|
||||
|
||||
## 评分维度 (1-5 分, 跨平台一致 — 铁律 6)
|
||||
- Functionality (25%) // 是否实现 design.md 中所有 MUST 项
|
||||
- Spec Compliance (25%) // 是否符合 design.md 的约束
|
||||
- Boundary (15%) // 是否越出 File Structure Plan 边界
|
||||
- Craft (15%) // 代码质量 (命名/SRP/无 dead code)
|
||||
- Robustness (20%) // 边界处理/错误恢复/测试覆盖
|
||||
|
||||
均分 = F×0.25 + SC×0.25 + B×0.15 + C×0.15 + R×0.20
|
||||
|
||||
## VERDICT 规则
|
||||
- 均分 ≥ 4.0 且所有维度 ≥ 3 → PASS
|
||||
- 均分 ≥ 3.0 但某维度 = 2 → CONCERNS
|
||||
- 均分 < 3.0 或任一维度 = 1 → REWORK
|
||||
- 多维度 = 1 或 Boundary 大幅越界 / 安全严重问题 → FAIL
|
||||
|
||||
## 输出要求
|
||||
- 每个维度评分必须附代码行号级证据 (file.ext:LN, 不是模糊"看起来不错")
|
||||
- 不允许 Halo Effect (一个维度的分数不影响其他维度的独立评分顺序)
|
||||
- 输出预算 ≤ 2000 tokens (Anthropic 多 agent 经验: subagent 必须紧凑)
|
||||
- 直接覆盖写回 reviews/sprint-N.md 的 "## Step 6" 段和 "## VERDICT:" 段
|
||||
"""
|
||||
@@ -1,4 +0,0 @@
|
||||
[agent]
|
||||
name = "explorer"
|
||||
model = "gpt-5.4-mini"
|
||||
description = "代码库调研 + 文档查询 (只读)"
|
||||
@@ -0,0 +1,62 @@
|
||||
# Codex Subagent: generator (VibeCoding Athena v9.6)
|
||||
# 参考: https://developers.openai.com/codex/subagents
|
||||
# 位置: ~/.codex/agents/generator.toml 或 .codex/agents/generator.toml
|
||||
|
||||
name = "generator"
|
||||
description = "代码实现者. 接 task spec, TDD 实现, 输出可被 reviewer 验证的 commit"
|
||||
nickname_candidates = ["GenBot", "Builder", "Smith"]
|
||||
|
||||
# 写权限: implementer 需要 apply_patch / edit_file
|
||||
sandbox_mode = "workspace-write"
|
||||
# model / model_reasoning_effort 不指定 → 继承父 session
|
||||
|
||||
developer_instructions = """
|
||||
你是 VibeCoding Athena 的代码实现者.
|
||||
|
||||
## 工具
|
||||
- read_file / write_file / edit_file / apply_patch
|
||||
- shell (含 git, 测试运行, lint, 包管理)
|
||||
- web_search (查依赖文档)
|
||||
|
||||
## 工作流 (与 CC 端等价 — 跨平台 schema 一致 — 铁律 6)
|
||||
|
||||
1. Get-bearings (R₀):
|
||||
- 读 `.ai_state/_index.md`
|
||||
- 读 design.md 对应模块段
|
||||
- 读 tasks-current.md 当前 task 的 Boundary/Depends
|
||||
2. TDD 强制 (铁律 2):
|
||||
- 先写测试 → 跑测试 (RED) → 实现 → 跑测试 (GREEN)
|
||||
3. Boundary 守则:
|
||||
- 仅修改 task 的 Boundary 标注的文件
|
||||
- 越界 → 停, 报告主 agent (可能需要升路径)
|
||||
4. 跑 lint_cmd → 失败修复
|
||||
5. 更新文档:
|
||||
- tasks-current.md 勾选 ([ ] → [x])
|
||||
- progress.md 追加一行 (YYYY-MM-DD HH:MM [path/stage/sprint] Task N done)
|
||||
- design.md 不动 (除非发现 design 错; 那种情况报告主 agent 不要自己改)
|
||||
6. Commit:
|
||||
- `git add -p` 仅添加 Boundary 内文件
|
||||
- `git commit -m "<task short summary>"`
|
||||
7. 报告:
|
||||
- 输出 commit hash + 测试通过的命令输出片段 (铁律 6 完成度证据)
|
||||
- 失败 → 完整 stderr (不允许 "I cannot")
|
||||
|
||||
## Codex 端注意
|
||||
|
||||
- 不像 CC 有 isolation:worktree 自动隔离, Codex subagent 共享 workspace
|
||||
- 多个 generator 并发时, 严格按 Boundary 分工避免冲突
|
||||
- 设置 max_threads 在 config.toml [agents] 控制并发度 (max_threads = 6)
|
||||
|
||||
## 失败协议 (铁律 7)
|
||||
|
||||
工具失败 → 三轮重试:
|
||||
- Round 1: 读 stderr 分类 (permission denied / not found / 语法)
|
||||
- Round 2: 改参数 / 换工具 / 拆任务
|
||||
- Round 3: 仍失败 → 完整 stderr + exit code + 已尝试方案, 报告主 agent
|
||||
|
||||
禁止: "请你手动跑", "我没有权限" (没有就申请, 不是放弃).
|
||||
|
||||
## 输出预算
|
||||
|
||||
≤ 2000 tokens. 详细日志写文件不写回主 agent.
|
||||
"""
|
||||
@@ -0,0 +1,62 @@
|
||||
# Codex Subagent: reviewer (VibeCoding Athena v9.6)
|
||||
# 参考: https://developers.openai.com/codex/subagents
|
||||
# 位置: ~/.codex/agents/reviewer.toml 或 .codex/agents/reviewer.toml
|
||||
|
||||
name = "reviewer"
|
||||
description = "代码审查员. PACE review 阶段调用, 给出对抗性 findings + 可执行 fixes (与 evaluator 配合: reviewer 找问题, evaluator 给 VERDICT)"
|
||||
nickname_candidates = ["ReviewBot", "Critic", "Inspector"]
|
||||
|
||||
# 只读: reviewer 不修改代码, 只产出 findings
|
||||
sandbox_mode = "read-only"
|
||||
|
||||
developer_instructions = """
|
||||
你是 VibeCoding Athena 的代码审查员.
|
||||
|
||||
## 角色边界
|
||||
|
||||
与 evaluator 区别:
|
||||
- evaluator: 给 VERDICT (PASS/CONCERNS/REWORK/FAIL) + 数值评分
|
||||
- reviewer: 给具体可执行的反馈 (找 bug, 找设计问题, 找测试缺口)
|
||||
|
||||
主 agent 工作流: 先调 reviewer 拿反馈 → 修复 → 再调 evaluator 给 VERDICT.
|
||||
|
||||
## 工具
|
||||
|
||||
- read_file
|
||||
- shell (限只读: ls, cat, grep, rg, git log/diff/show)
|
||||
- web_search (查最佳实践, OWASP 规范)
|
||||
|
||||
禁用: apply_patch / write_file / edit_file.
|
||||
|
||||
## 审查重点 (与 CC 端 /codex:review 行为对齐)
|
||||
|
||||
1. Bug: 边界用例, 错误处理, race condition
|
||||
2. 设计: 是否违反 design.md, SOLID, KISS
|
||||
3. 测试: 覆盖率, 是否测了 happy path 没测 error path
|
||||
4. 安全: 输入验证, 注入风险, 密钥处理
|
||||
5. 性能: 明显的 N+1, 同步阻塞, 内存泄漏
|
||||
|
||||
## 输出
|
||||
|
||||
写入 `.ai_state/details/reviews/sprint-N.md` 的 "## Step 2/3" 段:
|
||||
|
||||
```
|
||||
### Reviewer (Codex subagent)
|
||||
|
||||
**job_id**: <Codex subagent job id, 铁律 6 完成度证据>
|
||||
|
||||
**Findings**:
|
||||
- [HIGH] file.ext:LN — <描述>
|
||||
- [MEDIUM] file.ext:LN — <描述>
|
||||
- [LOW] file.ext:LN — <描述>
|
||||
|
||||
**Suggested fixes**:
|
||||
- ...
|
||||
```
|
||||
|
||||
每个 finding 必须有 file:line 锚点 (no 模糊"代码可以更好").
|
||||
|
||||
## 输出预算
|
||||
|
||||
≤ 2000 tokens.
|
||||
"""
|
||||
@@ -1,4 +0,0 @@
|
||||
[agent]
|
||||
name = "validator"
|
||||
model = "gpt-5.4"
|
||||
description = "代码审查 + Plan Review"
|
||||
+92
-62
@@ -1,85 +1,115 @@
|
||||
# VibeCoding Kernel v9.2.0 — Codex CLI Config
|
||||
model_provider = "custom"
|
||||
model = "gpt-5.4"
|
||||
# VibeCoding Athena v9.6 · Codex Configuration
|
||||
|
||||
project_root_markers = [".git", ".hg", ".sl"]
|
||||
project_doc_max_bytes = 65536
|
||||
|
||||
model = "gpt-5.5"
|
||||
model_reasoning_effort = "xhigh"
|
||||
|
||||
windows_wsl_setup_acknowledged = true
|
||||
model_context_window = 1000000
|
||||
model_auto_compact_token_limit = 900000
|
||||
web_search = "live"
|
||||
suppress_unstable_features_warning = true
|
||||
|
||||
# 危险,可开启 和下面的二选一,上面的代表绝对信任
|
||||
# approval_policy = "never" # untrusted|on-request|never
|
||||
# sandbox_mode = "danger-full-access" # read-only|workspace-write|danger-full-access
|
||||
|
||||
approval_policy = "never"
|
||||
sandbox_mode = "workspace-write"
|
||||
approval_policy = "on-request"
|
||||
sandbox_mode = "workspace-write"
|
||||
|
||||
[sandbox_workspace_write]
|
||||
network_access = true # npm install / pip install 需要网络
|
||||
|
||||
# Web Search
|
||||
web_search = "live"
|
||||
network_access = false
|
||||
|
||||
[features]
|
||||
multi_agent = true # stable; 多代理编排
|
||||
collaboration_modes = true # stable; 协作模式
|
||||
shell_snapshot = true # beta; 加速重复命令
|
||||
unified_exec = true # beta; PTY-backed 执行
|
||||
shell_tool = true # stable; 默认 shell 工具
|
||||
apply_patch_freeform = true # experimental; 自由 patch
|
||||
undo = true # 回滚 Codex 改动;
|
||||
hooks = true
|
||||
multi_agent = true
|
||||
shell_tool = true
|
||||
shell_snapshot = true
|
||||
unified_exec = true
|
||||
apply_patch_freeform = true
|
||||
undo = true
|
||||
memories = true
|
||||
|
||||
[tui]
|
||||
notifications = true
|
||||
animations = true
|
||||
[memories]
|
||||
generate_memories = true
|
||||
use_memories = true
|
||||
disable_on_external_context = true
|
||||
|
||||
[profiles.ci]
|
||||
approval_policy = "never"
|
||||
sandbox_mode = "workspace-write"
|
||||
[[hooks.SessionStart]]
|
||||
matcher = "^(startup|resume|clear)$"
|
||||
[[hooks.SessionStart.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/session-start.py\""
|
||||
timeout = 10
|
||||
statusMessage = "Loading Athena context"
|
||||
|
||||
[profiles.review]
|
||||
model = "gpt-5.4"
|
||||
approval_policy = "on-request"
|
||||
[[hooks.UserPromptSubmit]]
|
||||
[[hooks.UserPromptSubmit.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/user-prompt-submit.py\""
|
||||
timeout = 5
|
||||
statusMessage = "Athena pre-check"
|
||||
|
||||
[profiles.dev]
|
||||
model = "gpt-5.4"
|
||||
approval_policy = "on-request"
|
||||
sandbox_mode = "workspace-write"
|
||||
[[hooks.PreToolUse]]
|
||||
matcher = "^Bash$"
|
||||
[[hooks.PreToolUse.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/pre-bash-guard.py\""
|
||||
timeout = 10
|
||||
statusMessage = "Checking Bash command"
|
||||
|
||||
[[hooks.PostToolUse]]
|
||||
[[hooks.PostToolUse.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/index-updater.py\""
|
||||
timeout = 10
|
||||
|
||||
[[hooks.PostToolUse]]
|
||||
[[hooks.PostToolUse.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/subagent-retry.py\""
|
||||
timeout = 10
|
||||
|
||||
[[hooks.Stop]]
|
||||
[[hooks.Stop.hooks]]
|
||||
type = "command"
|
||||
command = "python3 \"./.codex/hooks/delivery-gate.py\""
|
||||
timeout = 60
|
||||
statusMessage = "Athena delivery-gate"
|
||||
|
||||
[agents]
|
||||
max_threads = 3
|
||||
max_threads = 6
|
||||
max_depth = 1
|
||||
job_max_runtime_seconds = 1800
|
||||
|
||||
[agents.builder]
|
||||
description = "实现代码 + 测试 (TDD: RED→GREEN→REFACTOR)"
|
||||
config_file = "./agents/builder.toml"
|
||||
[[skills.config]]
|
||||
name = "pace"
|
||||
enabled = true
|
||||
|
||||
[agents.validator]
|
||||
description = "代码审查 + Plan Review"
|
||||
config_file = "./agents/validator.toml"
|
||||
[[skills.config]]
|
||||
name = "compound"
|
||||
enabled = true
|
||||
|
||||
[agents.explorer]
|
||||
description = "代码库调研 + 文档查询 (只读)"
|
||||
config_file = "./agents/explorer.toml"
|
||||
[[skills.config]]
|
||||
name = "context7"
|
||||
enabled = true
|
||||
|
||||
[model_providers.custom]
|
||||
name = "custom"
|
||||
wire_api = "responses"
|
||||
requires_openai_auth = true
|
||||
[[skills.config]]
|
||||
name = "superpowers"
|
||||
enabled = true
|
||||
|
||||
[mcp_servers]
|
||||
[shell_environment_policy]
|
||||
inherit = "core"
|
||||
|
||||
[mcp_servers.mcp-deepwiki]
|
||||
type = "stdio"
|
||||
command = "npx"
|
||||
args = ["-y", "mcp-deepwiki@latest"]
|
||||
[tui.model_availability_nux]
|
||||
"gpt-5.5" = 4
|
||||
|
||||
[mcp_servers."cunzhi"]
|
||||
type = "stdio"
|
||||
command = "寸止"
|
||||
|
||||
[mcp_servers.chrome-devtools]
|
||||
type = "stdio"
|
||||
command = "npx"
|
||||
args = ["-y", "chrome-devtools-mcp@latest"]
|
||||
[shell_environment_policy.set]
|
||||
VIBECODING_VERSION = "9.6.0-codex"
|
||||
|
||||
[mcp_servers.augment-context-engine]
|
||||
type = "stdio"
|
||||
command = "npx"
|
||||
args = ["ace-tool-rs", "--base-url", "https://acemcp.heroman.wtf/relay/", "--token", ""]
|
||||
args = [ "ace-tool-rs", "--base-url", "https://acemcp.heroman.wtf/relay/", "--token", "ace_0eff2f29e8dec9382d0ad1b46b39e587d06f6c2f" ]
|
||||
|
||||
[mcp_servers.augment-context-engine.tools.search_context]
|
||||
approval_mode = "approve"
|
||||
|
||||
[hooks.state]
|
||||
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex Stop hook (delivery-gate) v9.6.
|
||||
|
||||
设计:
|
||||
- Codex 无 /goal autonomous loop → Athena 必须自己判定 VERDICT
|
||||
- Codex 无 Stop hook block-cap 概念, 但保守起见也做内部计数
|
||||
- VERDICT 不符 → 阻断 (decision: block)
|
||||
- CONCERNS → systemMessage 不阻断
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
PROJECT_DIR = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
STATE_DIR = os.path.join(PROJECT_DIR, ".ai_state")
|
||||
INDEX_PATH = os.path.join(STATE_DIR, "_index.md")
|
||||
HOME = os.path.expanduser("~")
|
||||
COUNTER_PATH = os.path.join(HOME, ".codex", "state", "athena-block-counter.json")
|
||||
|
||||
BLOCK_CAP_SAFE = 6
|
||||
|
||||
|
||||
def trace(payload: dict):
|
||||
try:
|
||||
with open(os.path.join(STATE_DIR, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(json.dumps({
|
||||
"ts": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"hook": "delivery-gate",
|
||||
**payload
|
||||
}) + "\n")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
if event.get("stop_hook_active"):
|
||||
sys.exit(0)
|
||||
return
|
||||
if event.get("agent_type") and event["agent_type"] != "main":
|
||||
sys.exit(0)
|
||||
return
|
||||
if not os.path.exists(INDEX_PATH):
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
try:
|
||||
content = open(INDEX_PATH).read()
|
||||
m = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
|
||||
if not m:
|
||||
sys.exit(0)
|
||||
return
|
||||
fm = m.group(1)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
def get_str(key):
|
||||
match = re.search(rf'^ {re.escape(key)}: (.*)$', fm, re.MULTILINE)
|
||||
return match.group(1).strip().strip('"').strip("'") if match else ""
|
||||
|
||||
def get_num(key):
|
||||
match = re.search(rf'^ {re.escape(key)}: (\d+)$', fm, re.MULTILINE)
|
||||
return int(match.group(1)) if match else 0
|
||||
|
||||
path_name = get_str("path")
|
||||
stage = get_str("stage")
|
||||
sprint = get_num("sprint")
|
||||
tasks_pending = get_num("tasks_pending")
|
||||
|
||||
if not sprint or not stage or path_name in ("Hotfix", "Bugfix") or stage != "review":
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
needs_ext = path_name in ("Feature", "Refactor", "System")
|
||||
issues = []
|
||||
|
||||
if tasks_pending > 0:
|
||||
issues.append(f"{tasks_pending} Task 未完成")
|
||||
|
||||
review_file = os.path.join(STATE_DIR, "details", "reviews", f"sprint-{sprint}.md")
|
||||
rc = ""
|
||||
try:
|
||||
rc = open(review_file).read()
|
||||
except Exception:
|
||||
issues.append("审查报告不存在")
|
||||
|
||||
if needs_ext and rc and not re.search(r"reviewer|web_search|/review|spawn_agent", rc, re.IGNORECASE):
|
||||
issues.append("无外部审查记录")
|
||||
if rc and not re.search(r"test|测试|pass|通过|✅", rc, re.IGNORECASE):
|
||||
issues.append("无测试通过记录")
|
||||
|
||||
verdict = ""
|
||||
if rc:
|
||||
vm = re.search(r"VERDICT:\s*(PASS|CONCERNS|REWORK|FAIL)", rc, re.IGNORECASE)
|
||||
if vm:
|
||||
verdict = vm.group(1).upper()
|
||||
if verdict in ("REWORK", "FAIL"):
|
||||
issues.append(f"VERDICT={verdict}")
|
||||
|
||||
if issues:
|
||||
os.makedirs(os.path.dirname(COUNTER_PATH), exist_ok=True)
|
||||
counter = {}
|
||||
try:
|
||||
counter = json.load(open(COUNTER_PATH))
|
||||
except Exception:
|
||||
pass
|
||||
sid = event.get("session_id", "unknown")
|
||||
counter[sid] = counter.get(sid, 0) + 1
|
||||
try:
|
||||
with open(COUNTER_PATH, "w") as f:
|
||||
json.dump(counter, f)
|
||||
except Exception:
|
||||
pass
|
||||
count = counter[sid]
|
||||
|
||||
sys.stderr.write(f"[delivery-gate] block #{count}/{BLOCK_CAP_SAFE} {path_name}/{stage}: {', '.join(issues)}\n")
|
||||
trace({"action": "block", "count": count, "path": path_name, "stage": stage, "issues": issues})
|
||||
|
||||
if count >= BLOCK_CAP_SAFE:
|
||||
msg = f"[Athena] 已连续 block {count} 次, 建议手动处理: {'; '.join(issues)}"
|
||||
print(json.dumps({"systemMessage": msg}))
|
||||
else:
|
||||
print(json.dumps({
|
||||
"decision": "block",
|
||||
"reason": f"[Athena delivery-gate] 阻断:\n" + "\n".join("• " + i for i in issues) + f"\n\n修复后再交付 (block {count}/{BLOCK_CAP_SAFE})."
|
||||
}))
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
# 通过, 重置计数
|
||||
try:
|
||||
counter = json.load(open(COUNTER_PATH))
|
||||
counter.pop(event.get("session_id", ""), None)
|
||||
with open(COUNTER_PATH, "w") as f:
|
||||
json.dump(counter, f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if verdict == "PASS":
|
||||
# 检查 lessons
|
||||
try:
|
||||
lessons = open(os.path.join(STATE_DIR, "details", "lessons.md")).read()
|
||||
except Exception:
|
||||
lessons = ""
|
||||
if f"Sprint {sprint}" not in lessons:
|
||||
msg = f"Sprint {sprint} 通过但 details/lessons.md 无条目, 建议运行 compound skill 沉淀经验"
|
||||
print(json.dumps({"systemMessage": f"[Athena] {msg}"}))
|
||||
trace({"action": "soft-warn", "reason": "no compound", "path": path_name, "sprint": sprint})
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
sys.stderr.write(f"[delivery-gate] PASS {path_name}/{stage}\n")
|
||||
trace({"action": "pass", "path": path_name, "stage": stage, "sprint": sprint, "verdict": verdict})
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex PostToolUse index-updater v9.6.
|
||||
|
||||
设计 (与 CC 等价, schema 跨平台一致 - 铁律 6):
|
||||
- 检测 tool_input.file_path 是否在 .ai_state/details/
|
||||
- 若是 → 重新扫描计算 counts/fingerprints/pointers
|
||||
- 原子写入 _index.md (.tmp + rename)
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
PROJECT_DIR = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
STATE_DIR = os.path.join(PROJECT_DIR, ".ai_state")
|
||||
INDEX_PATH = os.path.join(STATE_DIR, "_index.md")
|
||||
DETAILS_DIR = os.path.join(STATE_DIR, "details")
|
||||
|
||||
|
||||
def read_file_safe(path):
|
||||
try:
|
||||
return open(path).read()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def mtime(path):
|
||||
try:
|
||||
return int(os.path.getmtime(path) * 1000)
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
|
||||
def count_matches(text, pattern):
|
||||
return len(re.findall(pattern, text, re.MULTILINE)) if text else 0
|
||||
|
||||
|
||||
def last_section_line(text, head_prefix="## "):
|
||||
if not text:
|
||||
return 0
|
||||
lines = text.split("\n")
|
||||
for i in range(len(lines) - 1, -1, -1):
|
||||
if lines[i].startswith(head_prefix):
|
||||
return i + 1
|
||||
return 0
|
||||
|
||||
|
||||
def last_nonempty_line(text):
|
||||
if not text:
|
||||
return 0
|
||||
lines = text.split("\n")
|
||||
for i in range(len(lines) - 1, -1, -1):
|
||||
s = lines[i].strip()
|
||||
if s and not s.startswith("<!--") and not s.startswith("-->") and not s.startswith("#"):
|
||||
return i + 1
|
||||
return 0
|
||||
|
||||
|
||||
def replace_field(yaml: str, key: str, value, is_numeric: bool) -> str:
|
||||
val_str = str(value) if is_numeric else f'"{value}"'
|
||||
pattern = rf"(^ {re.escape(key)}: ).*$"
|
||||
if re.search(pattern, yaml, re.MULTILINE):
|
||||
return re.sub(pattern, rf"\g<1>{val_str}", yaml, count=1, flags=re.MULTILINE)
|
||||
return yaml
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
file_path = (event.get("tool_input") or {}).get("file_path", "")
|
||||
if not file_path or ".ai_state/details/" not in file_path:
|
||||
sys.exit(0)
|
||||
return
|
||||
if not os.path.exists(INDEX_PATH):
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
try:
|
||||
content = open(INDEX_PATH).read()
|
||||
m = re.match(r"^---\n(.*?)\n---\n(.*)$", content, re.DOTALL)
|
||||
if not m:
|
||||
sys.stderr.write("[index-updater] frontmatter parse failed\n")
|
||||
sys.exit(0)
|
||||
return
|
||||
fm, body = m.group(1), m.group(2)
|
||||
|
||||
tasks_text = read_file_safe(os.path.join(DETAILS_DIR, "tasks-current.md"))
|
||||
progress_text = read_file_safe(os.path.join(DETAILS_DIR, "progress.md"))
|
||||
lessons_text = read_file_safe(os.path.join(DETAILS_DIR, "lessons.md"))
|
||||
proposals_text = read_file_safe(os.path.join(DETAILS_DIR, "proposals.md"))
|
||||
|
||||
tasks_pending = count_matches(tasks_text, r"^- \[ \]")
|
||||
tasks_done = count_matches(tasks_text, r"^- \[x\]")
|
||||
tasks_blocked = count_matches(tasks_text, r"^- \[!\]")
|
||||
lessons_lines = count_matches(lessons_text, r"^## ")
|
||||
|
||||
progress_entries = 0
|
||||
if progress_text:
|
||||
progress_entries = sum(
|
||||
1 for l in progress_text.split("\n")
|
||||
if l.strip() and not l.startswith("<!--") and not l.startswith("-->") and not l.startswith("#")
|
||||
)
|
||||
|
||||
reviews_count = 0
|
||||
latest_review = ""
|
||||
try:
|
||||
files = [f for f in os.listdir(os.path.join(DETAILS_DIR, "reviews")) if re.match(r"^sprint-\d+\.md$", f)]
|
||||
reviews_count = len(files)
|
||||
if files:
|
||||
files.sort(key=lambda f: int(re.search(r"\d+", f).group()))
|
||||
latest_review = f"details/reviews/{files[-1]}"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
latest_progress = f"details/progress.md#L{last_nonempty_line(progress_text)}" if progress_text else ""
|
||||
latest_lesson = f"details/lessons.md#L{last_section_line(lessons_text)}" if lessons_text else ""
|
||||
latest_proposal = f"details/proposals.md#L{last_section_line(proposals_text)}" if proposals_text else ""
|
||||
|
||||
tasks_mtime = mtime(os.path.join(DETAILS_DIR, "tasks-current.md"))
|
||||
design_mtime = mtime(os.path.join(DETAILS_DIR, "design.md"))
|
||||
progress_mtime = mtime(os.path.join(DETAILS_DIR, "progress.md"))
|
||||
lessons_mtime = mtime(os.path.join(DETAILS_DIR, "lessons.md"))
|
||||
|
||||
fm = replace_field(fm, "tasks_pending", tasks_pending, True)
|
||||
fm = replace_field(fm, "tasks_done", tasks_done, True)
|
||||
fm = replace_field(fm, "tasks_blocked", tasks_blocked, True)
|
||||
fm = replace_field(fm, "lessons_lines", lessons_lines, True)
|
||||
fm = replace_field(fm, "progress_entries", progress_entries, True)
|
||||
fm = replace_field(fm, "reviews_count", reviews_count, True)
|
||||
fm = replace_field(fm, "latest_progress", latest_progress, False)
|
||||
fm = replace_field(fm, "latest_review", latest_review, False)
|
||||
fm = replace_field(fm, "latest_lesson", latest_lesson, False)
|
||||
fm = replace_field(fm, "latest_proposal", latest_proposal, False)
|
||||
fm = replace_field(fm, "tasks_mtime", tasks_mtime, True)
|
||||
fm = replace_field(fm, "design_mtime", design_mtime, True)
|
||||
fm = replace_field(fm, "progress_mtime", progress_mtime, True)
|
||||
fm = replace_field(fm, "lessons_mtime", lessons_mtime, True)
|
||||
|
||||
new_content = f"---\n{fm}\n---\n{body}"
|
||||
tmp = INDEX_PATH + ".tmp"
|
||||
with open(tmp, "w") as f:
|
||||
f.write(new_content)
|
||||
os.rename(tmp, INDEX_PATH)
|
||||
sys.stderr.write(f"[index-updater] _index.md updated (pending={tasks_pending} done={tasks_done})\n")
|
||||
|
||||
with open(os.path.join(STATE_DIR, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(json.dumps({
|
||||
"ts": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"hook": "index-updater",
|
||||
"tasks_pending": tasks_pending,
|
||||
"tasks_done": tasks_done,
|
||||
"lessons_lines": lessons_lines,
|
||||
}) + "\n")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"[index-updater] failed: {e}\n")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex PreToolUse Bash guard v9.6.
|
||||
|
||||
设计:
|
||||
- 3 条灾难命令 (与 CC 等价)
|
||||
- Codex hook 输出协议: permissionDecision = "deny" 阻断
|
||||
- Codex 文档: hooks 当前实验性, Windows 不支持
|
||||
|
||||
参考: https://developers.openai.com/codex/hooks
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
import os
|
||||
|
||||
DANGER_PATTERNS = [
|
||||
(re.compile(r"rm\s+-[rRf]+\s+(/(\s|\*|;|&|\||$)|~/?\s|~\s|~$)"), "禁止删除系统/用户根目录"),
|
||||
(re.compile(r"(curl|wget)\s+[^|]*\|\s*(bash|sh|zsh|fish|ksh)"), "禁止管道执行远程脚本"),
|
||||
(re.compile(r"\bmkfs\.|dd\s+if=.*of=/dev/sd|>\s*/dev/sd[a-z]"), "禁止格式化磁盘/写设备"),
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
cmd = (event.get("tool_input") or {}).get("command", "")
|
||||
if not cmd:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
for pat, reason in DANGER_PATTERNS:
|
||||
if pat.search(cmd):
|
||||
sys.stderr.write(f"[bash-guard] deny: {reason} ({cmd[:60]})\n")
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": f"Athena bash-guard 阻断: {reason}"
|
||||
}
|
||||
}))
|
||||
try:
|
||||
project_dir = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
state_dir = os.path.join(project_dir, ".ai_state")
|
||||
with open(os.path.join(state_dir, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(json.dumps({
|
||||
"ts": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"hook": "pre-bash-guard",
|
||||
"action": "deny",
|
||||
"reason": reason
|
||||
}) + "\n")
|
||||
except Exception:
|
||||
pass
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex SessionStart hook v9.6.
|
||||
|
||||
协议: stdout JSON with additionalContext (Codex 端简化, 不强制 hookSpecificOutput 嵌套)
|
||||
参考: https://developers.openai.com/codex/hooks
|
||||
|
||||
设计 (铁律 8 索引先行, 同 CC):
|
||||
- 唯一 IO: read .ai_state/_index.md frontmatter
|
||||
- 注入 context-essentials.md (静态文本)
|
||||
- 注入 _index.md 关键字段摘要
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
PROJECT_DIR = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
STATE_DIR = os.path.join(PROJECT_DIR, ".ai_state")
|
||||
INDEX_PATH = os.path.join(STATE_DIR, "_index.md")
|
||||
|
||||
HOME = os.path.expanduser("~")
|
||||
PROJECT_ESSENTIALS = os.path.join(PROJECT_DIR, ".codex", "skills", "pace", "context-essentials.md")
|
||||
GLOBAL_ESSENTIALS = os.path.join(HOME, ".codex", "skills", "pace", "context-essentials.md")
|
||||
|
||||
|
||||
def trace(payload: dict):
|
||||
try:
|
||||
line = json.dumps({"ts": datetime.datetime.utcnow().isoformat() + "Z", "hook": "session-start", **payload}) + "\n"
|
||||
with open(os.path.join(STATE_DIR, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(line)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def read_file_safe(path: str) -> str:
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
return f.read().strip()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def get_frontmatter(content: str) -> str:
|
||||
m = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
|
||||
return m.group(1) if m else ""
|
||||
|
||||
|
||||
def get_str(fm: str, key: str) -> str:
|
||||
m = re.search(rf"^ {re.escape(key)}: (.*)$", fm, re.MULTILINE)
|
||||
if not m:
|
||||
return ""
|
||||
val = m.group(1).strip()
|
||||
return val.strip('"').strip("'")
|
||||
|
||||
|
||||
def get_num(fm: str, key: str) -> int:
|
||||
m = re.search(rf"^ {re.escape(key)}: (\d+)$", fm, re.MULTILINE)
|
||||
return int(m.group(1)) if m else 0
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
event = {}
|
||||
source = event.get("source", "unknown")
|
||||
|
||||
lines = []
|
||||
|
||||
# 1. 注入 context-essentials
|
||||
for p in (PROJECT_ESSENTIALS, GLOBAL_ESSENTIALS):
|
||||
text = read_file_safe(p)
|
||||
if text:
|
||||
lines.append(text)
|
||||
break
|
||||
if not lines:
|
||||
lines.append("[VibeCoding Athena Codex v9.6] TDD · Review · Sisyphus · 索引先行")
|
||||
|
||||
# 2. 注入 _index.md frontmatter 摘要
|
||||
if os.path.exists(INDEX_PATH):
|
||||
try:
|
||||
content = open(INDEX_PATH).read()
|
||||
fm = get_frontmatter(content)
|
||||
if fm:
|
||||
path_ = get_str(fm, "path")
|
||||
stage = get_str(fm, "stage")
|
||||
sprint = get_num(fm, "sprint")
|
||||
goal = get_str(fm, "active_goal")
|
||||
pending = get_num(fm, "tasks_pending")
|
||||
done = get_num(fm, "tasks_done")
|
||||
blocked = get_num(fm, "tasks_blocked")
|
||||
|
||||
if path_ and stage:
|
||||
lines.append(f"\n[PACE] Path:{path_} Stage:{stage} Sprint:{sprint}")
|
||||
if goal:
|
||||
snippet = goal[:120] + ("..." if len(goal) > 120 else "")
|
||||
lines.append(f"[/goal active (CC only)] {snippet}")
|
||||
if pending + done + blocked > 0:
|
||||
lines.append(f"[任务] {done} 完成 {pending} 待办 {blocked} 阻塞 (详见 details/tasks-current.md)")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"[session-start] _index.md parse failed: {e}\n")
|
||||
|
||||
additional_context = "\n".join(lines)
|
||||
sys.stderr.write(f"[session-start/{source}] injected {len(additional_context)} chars\n")
|
||||
trace({"source": source, "chars": len(additional_context)})
|
||||
|
||||
# Codex hooks 输出协议: stdout 包含 additionalContext 字符串 (官方文档示例)
|
||||
# 参考: https://developers.openai.com/codex/hooks 中 SessionStart 段
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": additional_context
|
||||
}
|
||||
}))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex PostToolUse subagent-retry v9.6.
|
||||
|
||||
设计 (与 CC 等价):
|
||||
- 检测 spawn_agent 返回的内容是否含放弃信号词
|
||||
- 注入 systemMessage 提示主 agent 重试或接管
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
import os
|
||||
|
||||
GIVEUP_PATTERNS = [
|
||||
re.compile(r"我(无法|不能|没法|无能力|不具备能力)"),
|
||||
re.compile(r"I (cannot|can't|am not able to|don't have access)", re.IGNORECASE),
|
||||
re.compile(r"no (capability|access|permission) to", re.IGNORECASE),
|
||||
re.compile(r"unable to (read|write|execute|access)", re.IGNORECASE),
|
||||
re.compile(r"tool not available", re.IGNORECASE),
|
||||
re.compile(r"(请|你)(自己|手动|帮我)?(运行|执行|跑)"),
|
||||
re.compile(r"please run (this|the command) (yourself|manually)", re.IGNORECASE),
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
if event.get("tool_name") not in ("Task", "spawn_agent"):
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
response = event.get("tool_response") or {}
|
||||
text = ""
|
||||
if isinstance(response.get("content"), str):
|
||||
text = response["content"]
|
||||
elif isinstance(response.get("content"), list):
|
||||
text = "\n".join(c.get("text", "") for c in response["content"] if isinstance(c, dict))
|
||||
else:
|
||||
text = json.dumps(response)
|
||||
|
||||
for pat in GIVEUP_PATTERNS:
|
||||
if pat.search(text):
|
||||
sys.stderr.write(f"[subagent-retry] giveup detected: {pat.pattern[:50]}\n")
|
||||
subagent = (event.get("tool_input") or {}).get("subagent_type") or (event.get("tool_input") or {}).get("agent_type") or "subagent"
|
||||
msg = f"[Athena subagent-retry] {subagent} 返回了放弃信号. 协议: 1) 再尝试一次, 用不同参数或拆分任务 2) 仍失败则主 agent 接管, 不要让用户代执行 (铁律 6 完成度证据)"
|
||||
print(json.dumps({"systemMessage": msg}))
|
||||
|
||||
try:
|
||||
project_dir = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
state_dir = os.path.join(project_dir, ".ai_state")
|
||||
with open(os.path.join(state_dir, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(json.dumps({
|
||||
"ts": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"hook": "subagent-retry",
|
||||
"subagent": subagent
|
||||
}) + "\n")
|
||||
except Exception:
|
||||
pass
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VibeCoding Athena Codex UserPromptSubmit hook v9.6.
|
||||
|
||||
仅在用户 prompt 看起来是"开发请求" 时, 提示当前 PACE 状态, 帮助 model 路由.
|
||||
不强制添加任何内容, 单纯增强 context.
|
||||
|
||||
参考: https://developers.openai.com/codex/hooks
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
PROJECT_DIR = os.environ.get("CODEX_PROJECT_DIR") or os.getcwd()
|
||||
STATE_DIR = os.path.join(PROJECT_DIR, ".ai_state")
|
||||
INDEX_PATH = os.path.join(STATE_DIR, "_index.md")
|
||||
|
||||
DEV_KEYWORDS = re.compile(
|
||||
r"(实现|开发|新增|加上|做|搭|跑|写|改|修|fix|implement|build|add|create|refactor|review|test|debug)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
event = json.loads(raw)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
prompt = event.get("prompt") or event.get("user_prompt") or ""
|
||||
if not DEV_KEYWORDS.search(prompt):
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
if not os.path.exists(INDEX_PATH):
|
||||
sys.exit(0)
|
||||
return
|
||||
|
||||
try:
|
||||
content = open(INDEX_PATH).read()
|
||||
m = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
|
||||
if not m:
|
||||
sys.exit(0)
|
||||
return
|
||||
fm = m.group(1)
|
||||
path_m = re.search(r'^ path: "([^"]*)"$', fm, re.MULTILINE)
|
||||
stage_m = re.search(r'^ stage: "([^"]*)"$', fm, re.MULTILINE)
|
||||
path_val = path_m.group(1) if path_m else ""
|
||||
stage_val = stage_m.group(1) if stage_m else ""
|
||||
|
||||
if path_val and stage_val:
|
||||
msg = f"[Athena] 当前 PACE 状态: {path_val}/{stage_val}. 如果是延续任务, 请走 pace skill 既有流程; 如果是新任务, 评估是否升路径."
|
||||
sys.stderr.write(msg + "\n")
|
||||
print(json.dumps({"systemMessage": msg}))
|
||||
|
||||
try:
|
||||
line = json.dumps({
|
||||
"ts": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"hook": "user-prompt-submit",
|
||||
"path": path_val, "stage": stage_val
|
||||
}) + "\n"
|
||||
with open(os.path.join(STATE_DIR, "hook-trace.jsonl"), "a") as f:
|
||||
f.write(line)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"[user-prompt-submit] failed: {e}\n")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,24 @@
|
||||
# /athena-dev (Codex) — 主入口
|
||||
|
||||
`.ai_state/` 不存在 → 提示 `/athena-init` 并停。
|
||||
`schema_version` != "9.6" → 提示 `/athena-migrate` 并停。
|
||||
|
||||
## Get-bearings (R₀, just-in-time, 铁律 8)
|
||||
|
||||
1. **必读**: `.ai_state/_index.md`
|
||||
2. **按需**: stage=impl/review → 按 pointers.latest_progress 读 progress.md 尾部
|
||||
3. **按需**: 任务命中 lessons 主题 → pointers.latest_lesson 跳段
|
||||
4. **按需**: `git log --oneline -10`
|
||||
5. **按需**: impl/review 阶段 → `bash .ai_state/init.sh`
|
||||
|
||||
文件大就用 head/tail/grep。**禁止 glob 整个 .ai_state/**。
|
||||
|
||||
## Dispatch
|
||||
|
||||
有进行中的 stage → 从当前阶段继续 (参考 `~/.codex/skills/pace/SKILL.md`)。
|
||||
新需求 → 触发 pace skill 路由, 需求: $ARGUMENTS。
|
||||
|
||||
Codex 端特别注意:
|
||||
- **无 /goal** → delivery-gate hook 兜底判定
|
||||
- **无 /batch** → 多任务用 spawn_agent (config.toml [agents] 配置)
|
||||
- **无 compact 生命周期** → 长任务点主动写 `.ai_state/_index.md` 保存
|
||||
@@ -0,0 +1,67 @@
|
||||
# /athena-init (Codex) — 项目初始化
|
||||
|
||||
# 描述
|
||||
> 项目初始化。每个新项目首次使用 Athena 时运行。
|
||||
# end
|
||||
|
||||
参考: <https://developers.openai.com/codex/concepts/customization>
|
||||
|
||||
`.ai_state/_index.md` 已存在 → 提示用户用 `/athena-migrate` 升级或确认覆盖。
|
||||
|
||||
## 1. 项目扫描
|
||||
|
||||
```bash
|
||||
ls package.json pyproject.toml Cargo.toml go.mod build.gradle pom.xml 2>/dev/null
|
||||
cat package.json 2>/dev/null | grep -A5 '"scripts"'
|
||||
ls jest.config* vitest.config* pytest.ini .eslintrc* ruff.toml biome.json 2>/dev/null
|
||||
```
|
||||
|
||||
## 2. 创建 .ai_state/ (v9.6 schema)
|
||||
|
||||
```bash
|
||||
mkdir -p .ai_state/details/reviews .ai_state/details/tasks-archive
|
||||
```
|
||||
|
||||
## 3. 拷贝模板
|
||||
|
||||
从 `~/.codex/skills/pace/templates/` 复制:
|
||||
- `_index.md` → `.ai_state/_index.md`
|
||||
- 所有 `details/*.md`
|
||||
- `init.sh`
|
||||
|
||||
## 4. 填充 _index.md frontmatter
|
||||
|
||||
把扫描结果写入: tech_stack, test_cmd, build_cmd, lint_cmd, dev_cmd
|
||||
|
||||
平台特征 (`codex --version` 输出):
|
||||
- `cx_version`
|
||||
- `goal_supported`: Codex 当前**没有原生 /goal** → false
|
||||
- `batch_supported`: Codex subagent (max_threads in [agents]) 部分支持 → 视 max_threads 而定
|
||||
- `background_supported`: false (Codex 无 /background)
|
||||
- `session_memory_active`: false (Codex 无 ~/.claude/projects/ 等价物)
|
||||
- `cross_session_memory`: "none"
|
||||
|
||||
## 5. 生成 init.sh
|
||||
|
||||
根据扫描结果定制 `.ai_state/init.sh`. `chmod +x`.
|
||||
|
||||
## 6. .gitignore
|
||||
|
||||
```bash
|
||||
grep -q '.ai_state' .gitignore 2>/dev/null || echo '.ai_state/' >> .gitignore
|
||||
```
|
||||
|
||||
## 7. Git commit
|
||||
|
||||
```bash
|
||||
git add .ai_state/ .gitignore
|
||||
git commit -m "athena: project initialized (v9.6 schema, Codex)"
|
||||
```
|
||||
|
||||
## 8. 验证
|
||||
|
||||
```bash
|
||||
bash .ai_state/init.sh
|
||||
```
|
||||
|
||||
告知用户: "Athena (Codex 版) 已就绪。用 `/athena-dev <需求>` 开始, 或 `/athena-status` 看面板。"
|
||||
@@ -0,0 +1,155 @@
|
||||
# /athena-migrate (Codex) — v9.5 → v9.6 迁移
|
||||
|
||||
参考 CC 版 `~/.claude/skills/athena-migrate/SKILL.md`. 算法一致 (因为 schema 跨平台相同, 这是铁律 6).
|
||||
|
||||
Codex 端差异:
|
||||
- 用 python3 替代 node 生成 `_index.md` (Codex 默认有 python3)
|
||||
- 检测 `cx_version` 写入 `platform_features.cx_version`, **不写** cc_version
|
||||
|
||||
## 备份脚本
|
||||
|
||||
```bash
|
||||
mkdir -p .ai_state/.legacy-v9.5
|
||||
cp -r .ai_state/{tasks.md,design.md,progress.md,lessons.md,handoff.md,project.json,reviews,hook-trace.jsonl} .ai_state/.legacy-v9.5/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
## 创建 details/
|
||||
|
||||
```bash
|
||||
mkdir -p .ai_state/details/reviews .ai_state/details/tasks-archive
|
||||
```
|
||||
|
||||
## 平移
|
||||
|
||||
```bash
|
||||
[ -f .ai_state/tasks.md ] && mv .ai_state/tasks.md .ai_state/details/tasks-current.md
|
||||
for f in design.md progress.md lessons.md handoff.md; do
|
||||
[ -f .ai_state/$f ] && mv .ai_state/$f .ai_state/details/$f
|
||||
done
|
||||
[ -d .ai_state/reviews ] && mv .ai_state/reviews .ai_state/details/reviews
|
||||
[ -f .ai_state/compact-snapshot.json ] && rm .ai_state/compact-snapshot.json # Codex 无 compact 也能有的旧文件
|
||||
```
|
||||
|
||||
## 生成 _index.md (python3)
|
||||
|
||||
```bash
|
||||
python3 << 'PY'
|
||||
import json, os, re, sys
|
||||
|
||||
proj = {}
|
||||
try:
|
||||
with open('.ai_state/.legacy-v9.5/project.json') as f:
|
||||
proj = json.load(f)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def count_match(path, pattern):
|
||||
try:
|
||||
with open(path) as f:
|
||||
return len(re.findall(pattern, f.read(), re.MULTILINE))
|
||||
except FileNotFoundError:
|
||||
return 0
|
||||
|
||||
def last_section_line(path, head_prefix='## '):
|
||||
try:
|
||||
lines = open(path).read().split('\n')
|
||||
for i in range(len(lines) - 1, -1, -1):
|
||||
if lines[i].startswith(head_prefix):
|
||||
return i + 1
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return 0
|
||||
|
||||
def last_nonempty_line(path):
|
||||
try:
|
||||
lines = open(path).read().split('\n')
|
||||
for i in range(len(lines) - 1, -1, -1):
|
||||
stripped = lines[i].strip()
|
||||
if stripped and not stripped.startswith('<!--') and not stripped.startswith('#'):
|
||||
return i + 1
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return 0
|
||||
|
||||
tasks_pending = count_match('.ai_state/details/tasks-current.md', r'^- \[ \]')
|
||||
tasks_done = count_match('.ai_state/details/tasks-current.md', r'^- \[x\]')
|
||||
progress_n = last_nonempty_line('.ai_state/details/progress.md')
|
||||
lessons_lines = count_match('.ai_state/details/lessons.md', r'^## ')
|
||||
latest_lesson_line = last_section_line('.ai_state/details/lessons.md')
|
||||
|
||||
reviews = []
|
||||
try:
|
||||
reviews = [f for f in os.listdir('.ai_state/details/reviews') if re.match(r'^sprint-\d+\.md$', f)]
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
reviews_count = len(reviews)
|
||||
latest_review = ''
|
||||
if reviews:
|
||||
latest_review = 'details/reviews/' + sorted(reviews, key=lambda f: int(re.search(r'\d+', f).group()))[-1]
|
||||
|
||||
content = f'''---
|
||||
schema_version: "9.6"
|
||||
athena_version: "9.6.0"
|
||||
project:
|
||||
path: "{proj.get('path','')}"
|
||||
stage: "{proj.get('stage','')}"
|
||||
sprint: {proj.get('sprint', 0)}
|
||||
active_goal: ""
|
||||
counts:
|
||||
tasks_pending: {tasks_pending}
|
||||
tasks_done: {tasks_done}
|
||||
tasks_blocked: 0
|
||||
lessons_lines: {lessons_lines}
|
||||
progress_entries: {progress_n}
|
||||
reviews_count: {reviews_count}
|
||||
pointers:
|
||||
latest_progress: "{('details/progress.md#L' + str(progress_n)) if progress_n else ''}"
|
||||
latest_review: "{latest_review}"
|
||||
latest_lesson: "{('details/lessons.md#L' + str(latest_lesson_line)) if latest_lesson_line else ''}"
|
||||
latest_proposal: ""
|
||||
fingerprints:
|
||||
tasks_mtime: 0
|
||||
design_mtime: 0
|
||||
progress_mtime: 0
|
||||
lessons_mtime: 0
|
||||
platform_features:
|
||||
cc_version: ""
|
||||
cx_version: ""
|
||||
goal_supported: false
|
||||
batch_supported: false
|
||||
background_supported: false
|
||||
session_memory_active: false
|
||||
cross_session_memory: "none"
|
||||
gotchas: {json.dumps(proj.get('gotchas', []))}
|
||||
conventions: {json.dumps(proj.get('conventions', []))}
|
||||
tech_stack: "{proj.get('tech_stack','')}"
|
||||
test_cmd: "{proj.get('test_cmd','')}"
|
||||
build_cmd: "{proj.get('build_cmd','')}"
|
||||
lint_cmd: "{proj.get('lint_cmd','')}"
|
||||
dev_cmd: "{proj.get('dev_cmd','')}"
|
||||
---
|
||||
|
||||
# 项目状态索引 (v9.6 migrated from v9.5.5)
|
||||
|
||||
## 最近活动
|
||||
|
||||
## 当前阻塞
|
||||
|
||||
## 下一动作 (PACE 建议)
|
||||
|
||||
## 反思建议 (Hook 沉淀)
|
||||
'''
|
||||
|
||||
with open('.ai_state/_index.md', 'w') as f:
|
||||
f.write(content)
|
||||
print('[migrate] _index.md generated')
|
||||
PY
|
||||
```
|
||||
|
||||
## 收尾
|
||||
|
||||
```bash
|
||||
touch .ai_state/details/next.md .ai_state/details/proposals.md
|
||||
git add .ai_state/
|
||||
git commit -m "athena: migrate state to v9.6 schema (codex)"
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
# /athena-preferences (Codex)
|
||||
|
||||
## 设计原则 (同 CC 版)
|
||||
|
||||
Athena 不造私有偏好文件。所有写入都是 Codex 原生位置:
|
||||
|
||||
| 偏好类型 | Codex 落点 |
|
||||
|---|---|
|
||||
| 工具偏好 (pnpm/vitest) | `~/.codex/AGENTS.md` "## Tool Preferences" 段 |
|
||||
| 风格偏好 (Linus 模式等) | `~/.codex/AGENTS.md` |
|
||||
|
||||
**Codex 没有 CC 风格的 permissions.allow/deny.** Codex 用:
|
||||
- `approval_policy` (on-request / never / on-failure / untrusted) — 顶层
|
||||
- `sandbox_mode` (workspace-write / read-only / danger-full-access)
|
||||
- `[shell_environment_policy]` 控制环境
|
||||
|
||||
参考: <https://developers.openai.com/codex/config-reference>
|
||||
|
||||
所以 `/athena:remember-allow|deny` 在 Codex 上**部分语义不可映射**, 当前实现:
|
||||
- `/athena:remember-tool <key>=<value>` → 写 `~/.codex/AGENTS.md` "## Tool Preferences"
|
||||
- `/athena:show-preferences` → cat ~/.codex/AGENTS.md
|
||||
- `/athena:remember-allow|deny` → 提示用户在 `~/.codex/config.toml` 改 `approval_policy` 或 `sandbox_mode`, **不自动改** (那是 critical 配置)
|
||||
|
||||
## 子命令 (Codex)
|
||||
|
||||
### `/athena:remember-tool <key>=<value>`
|
||||
|
||||
```bash
|
||||
GLOBAL_AGENTS_MD="$HOME/.codex/AGENTS.md"
|
||||
mkdir -p "$(dirname "$GLOBAL_AGENTS_MD")"
|
||||
|
||||
# 创建文件 / 找到 Tool Preferences 段 / 追加
|
||||
python3 << PY
|
||||
import os, re
|
||||
p = os.path.expanduser("~/.codex/AGENTS.md")
|
||||
try:
|
||||
content = open(p).read()
|
||||
except FileNotFoundError:
|
||||
content = ""
|
||||
|
||||
section = "## Tool Preferences"
|
||||
arg = "$ARGUMENTS" # 由 Codex 替换
|
||||
|
||||
if section not in content:
|
||||
if content and not content.endswith("\n"):
|
||||
content += "\n"
|
||||
content += "\n" + section + "\n\n- " + arg + "\n"
|
||||
else:
|
||||
# 在 section 后追加一行 (避免重复)
|
||||
if "- " + arg in content:
|
||||
print(f"⚠️ 已存在: {arg}")
|
||||
exit(0)
|
||||
content = re.sub(r"(" + re.escape(section) + r"\n+)", r"\g<1>- " + arg + "\n", content, count=1)
|
||||
|
||||
open(p, "w").write(content)
|
||||
print(f"✓ 已加入 ~/.codex/AGENTS.md Tool Preferences: {arg}")
|
||||
PY
|
||||
```
|
||||
|
||||
### `/athena:show-preferences`
|
||||
|
||||
```bash
|
||||
echo "=== ~/.codex/AGENTS.md (Tool Preferences) ==="
|
||||
sed -n '/^## Tool Preferences/,/^## /p' ~/.codex/AGENTS.md 2>/dev/null | head -30
|
||||
|
||||
echo ""
|
||||
echo "=== ~/.codex/config.toml (approvals / sandbox) ==="
|
||||
grep -E "^(approval_policy|sandbox_mode)" ~/.codex/config.toml 2>/dev/null
|
||||
```
|
||||
|
||||
### `/athena:remember-allow|deny <pattern>`
|
||||
|
||||
不自动写, 仅提示:
|
||||
```
|
||||
⚠️ Codex 没有 permissions.allow/deny 概念.
|
||||
等价配置在 ~/.codex/config.toml:
|
||||
- approval_policy: on-request | never | on-failure | untrusted
|
||||
- sandbox_mode: read-only | workspace-write | danger-full-access
|
||||
请用编辑器手改这两个字段, 不通过 Athena 自动改 (critical config).
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
# /athena-review (Codex)
|
||||
|
||||
有 `.ai_state/_index.md` → 按当前 Path 触发 pace skill 审查阶段。
|
||||
无 → 快速审查 (Codex 内置 /review)。
|
||||
|
||||
焦点: $ARGUMENTS
|
||||
|
||||
Codex 端可用工具:
|
||||
- `/review` (Codex 内置)
|
||||
- `spawn_agent reviewer` (从 ~/.codex/agents/reviewer.toml 调度)
|
||||
- `web_search` 查最佳实践
|
||||
- 不可: /codex:review (那是 CC 侧反向调用)
|
||||
@@ -0,0 +1,98 @@
|
||||
# /athena-setup (Codex)
|
||||
|
||||
参考: <https://developers.openai.com/codex/config-basic>
|
||||
|
||||
## Step 0: Codex 版本
|
||||
|
||||
```bash
|
||||
codex --version
|
||||
```
|
||||
|
||||
要求 ≥ v0.124 (hooks stable). v0.129+ 解锁 /hooks TUI menu.
|
||||
|
||||
写入 `_index.md.platform_features.cx_version`.
|
||||
|
||||
## Step 1: 验证 config.toml
|
||||
|
||||
`~/.codex/config.toml` 应包含 (从 cx/.codex/config.toml 拷贝):
|
||||
|
||||
- `model = "gpt-5.5"`
|
||||
- `[features] hooks = true` (规范名, 非 deprecated codex_hooks)
|
||||
- `[[hooks.SessionStart]]`, `[[hooks.PreToolUse]]`, `[[hooks.PostToolUse]]`, `[[hooks.Stop]]`
|
||||
- `[agents] max_threads = 6`
|
||||
- `[[skills.config]]` 包含 pace / compound / context7 / superpowers
|
||||
|
||||
```bash
|
||||
codex check config 2>&1 | head -20
|
||||
```
|
||||
|
||||
## Step 2: 部署 hooks
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/hooks
|
||||
cp cx/.codex/hooks/*.py ~/.codex/hooks/
|
||||
chmod +x ~/.codex/hooks/*.py
|
||||
```
|
||||
|
||||
Codex hook 列表 (Python, 6 个):
|
||||
- session-start.py
|
||||
- user-prompt-submit.py
|
||||
- pre-bash-guard.py
|
||||
- index-updater.py
|
||||
- subagent-retry.py
|
||||
- delivery-gate.py
|
||||
|
||||
⚠️ Codex hooks 当前 Windows 不支持 (官方限制, 参考 <https://developers.openai.com/codex/hooks>)
|
||||
|
||||
## Step 3: 部署 skills
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/skills/pace ~/.codex/skills/compound
|
||||
cp -r cx/.codex/skills/pace/* ~/.codex/skills/pace/
|
||||
cp -r cx/.codex/skills/compound/* ~/.codex/skills/compound/
|
||||
```
|
||||
|
||||
## Step 4: 部署 prompts (slash commands)
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/prompts
|
||||
cp cx/.codex/prompts/*.md ~/.codex/prompts/
|
||||
```
|
||||
|
||||
## Step 5: 部署 subagents (单 TOML 文件, 非子目录)
|
||||
|
||||
参考: <https://developers.openai.com/codex/subagents>
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/agents
|
||||
cp cx/.codex/agents/*.toml ~/.codex/agents/
|
||||
```
|
||||
|
||||
部署后:
|
||||
- `~/.codex/agents/evaluator.toml` — 评分员 (read-only)
|
||||
- `~/.codex/agents/generator.toml` — 实现者 (workspace-write)
|
||||
- `~/.codex/agents/reviewer.toml` — 审查员 (read-only)
|
||||
|
||||
验证:
|
||||
```bash
|
||||
codex /agents 2>&1 | head -20
|
||||
# 应列出 evaluator, generator, reviewer 三个 custom agent
|
||||
```
|
||||
|
||||
## Step 6: 跨项目记忆 (推荐)
|
||||
|
||||
Codex 暂无 claude-mem 等价物。推荐:
|
||||
- 用 `~/.codex/AGENTS.md` 全局 "## Tool Preferences" 段做轻量记忆
|
||||
- 多项目用同一 ~/.codex/AGENTS.md (跨项目人工同步)
|
||||
|
||||
## Step 7: 验证
|
||||
|
||||
```bash
|
||||
codex --version # ≥ 0.124
|
||||
ls ~/.codex/hooks/*.py | wc -l # 应 = 6
|
||||
ls ~/.codex/prompts/*.md # 7 个 athena-* prompt
|
||||
codex /hooks 2>&1 | head # v0.129+ TUI 显示 hook 树
|
||||
cat .ai_state/_index.md | head -5 # schema_version: "9.6"
|
||||
```
|
||||
|
||||
通过 → "Codex 端 Athena 已就绪。"
|
||||
@@ -0,0 +1,32 @@
|
||||
# /athena-status (Codex)
|
||||
|
||||
参考 CC 版 (~/.claude/skills/athena-status/SKILL.md). 等价实现, 差异:
|
||||
|
||||
| 字段 | CC 端 | CX 端 |
|
||||
|------|-------|-------|
|
||||
| goal_supported | CC v2.1.139+ | **始终 false** (Codex 无 /goal) |
|
||||
| batch_supported | CC v2.1.121+ | 视 [agents] max_threads 而定 |
|
||||
| background_supported | CC v2.1.139+ | **始终 false** (Codex 无 /background) |
|
||||
| session_memory_active | ~/.claude/projects/ | **始终 false** (Codex 无等价) |
|
||||
|
||||
## 收集顺序 (同 CC 版)
|
||||
|
||||
1. PACE 状态 (从 `.ai_state/_index.md` frontmatter)
|
||||
2. Sprint 进度 (counts 段)
|
||||
3. Hook 触发记录 (`tail -50 .ai_state/hook-trace.jsonl`)
|
||||
4. Lessons 统计
|
||||
5. Platform 健康 (Codex 特定)
|
||||
6. Plugin 状态: CX 无插件生态, 仅显示 `codex --version`, `codex /hooks` 输出, `codex /skills`
|
||||
|
||||
## Codex 特有显示
|
||||
|
||||
```
|
||||
[Codex Hooks]
|
||||
/hooks tui: v0.129+
|
||||
hooks 配置文件: ~/.codex/hooks.json, ~/.codex/config.toml [[hooks.*]]
|
||||
Windows 支持: 否 (官方限制)
|
||||
|
||||
[Codex Subagents]
|
||||
config.toml [agents].max_threads: <从 config 读>
|
||||
available roles: evaluator, generator, reviewer
|
||||
```
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
name: brainstorm
|
||||
description: R₀ 苏格拉底式需求精炼
|
||||
---
|
||||
# Brainstorm (R₀ 需求精炼)
|
||||
|
||||
Path B+ 任务在写代码前**必须**激活。
|
||||
|
||||
## 流程
|
||||
### 0. 自主调研 (提问前)
|
||||
- 搜索项目中与需求相关的现有代码
|
||||
- 读 .ai_state/lessons.md + conventions.md
|
||||
→ 基于调研结果准备更有深度的问题
|
||||
|
||||
### 1. 访谈 (苏格拉底式)
|
||||
- 一次只问一个问题, 优先选择题
|
||||
- 覆盖: 目标、场景、边界、非功能需求
|
||||
- YAGNI: 主动砍不必要的功能
|
||||
|
||||
### 2. 提出 2-3 方案
|
||||
- 每方案: 架构 + 优劣 + 复杂度
|
||||
- context7 验证可行性
|
||||
|
||||
### 3. 确认 → .ai_state/design.md
|
||||
铁律: 设计未确认前不写代码
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
name: claude-delegate
|
||||
description: 接收 CC 派发任务 + 反向调用 CC
|
||||
---
|
||||
# Claude Delegate
|
||||
|
||||
## 当被 CC 调用时
|
||||
- CC 通过 codex exec 发送任务
|
||||
- 你在只读沙箱, 输出代码和建议
|
||||
- 审查请求: 以 `VERDICT: APPROVED` 或 `VERDICT: REVISE` 结尾
|
||||
|
||||
## 反向调用 CC (独立运行时)
|
||||
如需 Claude 视角:
|
||||
```bash
|
||||
# 如果有 claude CLI
|
||||
claude -p "审查以下代码: {code}"
|
||||
```
|
||||
如不可用 → 用 validator agent 自审
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
name: code-review
|
||||
description: T 阶段代码审查
|
||||
---
|
||||
# Code Review
|
||||
|
||||
## 审查清单
|
||||
1. Spec 合规: 每个 MUST 实现?
|
||||
2. TDD: 源码有对应测试?
|
||||
3. 边界: 空输入/超长/并发/错误路径?
|
||||
4. 安全: 无硬编码密钥, 输入已验证
|
||||
5. 可读: 函数 < 50 行, 注释说 WHY, 严格类型
|
||||
6. 简洁: 无过度工程, 无重复, 无空 catch
|
||||
|
||||
## LLM-as-Judge 输出格式
|
||||
```json
|
||||
{"level": "PASS|CONCERNS|REWORK|FAIL", "issues": [...], "summary": "..."}
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: compound
|
||||
description: >
|
||||
Sprint Quality Gate 通过后触发。提炼本 Sprint 学到的为结构化条目追加 lessons.md。
|
||||
effort: xhigh
|
||||
---
|
||||
|
||||
# /compound — 经验沉淀
|
||||
|
||||
Gate PASS 后触发 (或用户显式 `/compound`).
|
||||
|
||||
## 输入
|
||||
|
||||
- `.ai_state/details/reviews/sprint-N.md` (审查报告)
|
||||
- `git diff` (本 Sprint 所有变更)
|
||||
- `.ai_state/details/tasks-current.md` (完成项)
|
||||
- `.ai_state/details/design.md` (设计 vs 实际实现对比)
|
||||
|
||||
## 提炼方法
|
||||
|
||||
从以上输入找**真实发现**, 不写仪式性废话。每 Sprint 0-N 条不强制。
|
||||
|
||||
- **Pattern**: 什么解法有效且可复用? (带代码行号 / 文件路径)
|
||||
- **Pitfall**: 什么坑踩过? 未来同类场景要提前避开
|
||||
- **Constraint**: 发现的新约束 (依赖版本、环境、性能边界、API 限制)
|
||||
|
||||
没发现可提炼的 → 不写, 直接告知用户 "no new lesson". **不允许编造**.
|
||||
|
||||
## 输出 (项目级)
|
||||
|
||||
追加到 `.ai_state/details/lessons.md` (append-only, 不修改历史).
|
||||
|
||||
格式见 `pace/templates/details/lessons.md`. **Athena 不做跨项目知识管理**——需要的话装 claude-mem 或 superpowers。
|
||||
|
||||
写入后同步更新 `_index.md`:
|
||||
- `counts.lessons_lines` += 新增条目数 (按 `## ` 头计)
|
||||
- `pointers.latest_lesson` = `details/lessons.md#L<新条目行号>`
|
||||
- `fingerprints.lessons_mtime` = 当前时间戳
|
||||
|
||||
## 自检
|
||||
|
||||
写入后读回验证:
|
||||
1. 条目有具体的文件/行号/版本引用 (不只是"要注意 X")
|
||||
2. 一句话标题能让下次 R₀ 快速扫描命中
|
||||
3. Pattern/Pitfall/Constraint 三段不强制全有, 但至少有一段
|
||||
|
||||
写完告知用户: "Lessons updated. Next sprint R₀ 会自动读取 (按 _index.md.pointers.latest_lesson 跳转)."
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: context7
|
||||
description: 库文档查询
|
||||
---
|
||||
# Context7
|
||||
|
||||
1. 优先: `npx ctx7 resolve {库名}`
|
||||
2. 备选: web search
|
||||
3. 缓存: 查过的结论写入当前笔记
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: debugging
|
||||
description: 系统化调试 4 阶段
|
||||
---
|
||||
# Systematic Debugging
|
||||
|
||||
必须按 4 阶段执行, 禁止跳步:
|
||||
|
||||
## 1. 复现 — 最小用例, 记录输入/期望/实际
|
||||
## 2. 定位 — 从错误点向上追溯, 用证据不用直觉
|
||||
## 3. 修复 — 只改根因, 有对应测试, 禁止 as any / 空 catch
|
||||
## 4. 验证 — 复现通过 + 全量无回归 + Reflexion: 值得记录?
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: e2e
|
||||
description: 端到端测试
|
||||
---
|
||||
# E2E Testing
|
||||
|
||||
前置: 有 E2E 框架 (Playwright/Cypress) 且 Path C+ 或用户要求
|
||||
流程: 基于验收标准写用例 → 运行 → 结果入 quality.md
|
||||
无框架: 手动验证清单
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
name: finish-branch
|
||||
description: V 阶段分支收尾
|
||||
---
|
||||
# Finish Branch
|
||||
|
||||
V 阶段 kaizen 后, 交付确认前。
|
||||
|
||||
## 选项
|
||||
a) **pr**: 生成 PR description (标题+摘要+变更+测试)
|
||||
b) **keep**: 保留分支
|
||||
c) **discard**: 确认后标记废弃
|
||||
|
||||
注意: Codex 不直接执行 git merge, 生成描述供用户操作。
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: kaizen
|
||||
description: V 阶段回顾
|
||||
---
|
||||
# Kaizen
|
||||
|
||||
## 流程
|
||||
1. 回顾: 好的保持, 差的改进, 模式性错误?
|
||||
2. 更新 lessons.md
|
||||
3. 更新 conventions.md "## Agent 易犯错误" (如发现模式性错误)
|
||||
4. 摘要给用户
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
name: pace
|
||||
description: >
|
||||
工作流路由器 (Codex 版). 收到开发任务时触发. 按任务复杂度路由到 6 条路径.
|
||||
effort: high
|
||||
---
|
||||
|
||||
# PACE — 6 路径路由器 (v9.6 Codex)
|
||||
|
||||
首先读 `.ai_state/_index.md` (铁律 8 索引先行). 有 stage → 从当前阶段继续.
|
||||
.ai_state/ 不存在 → 提示 `/athena-init`.
|
||||
|
||||
## 路由 (同 CC)
|
||||
|
||||
```
|
||||
┌─ 1行/配置 ──────→ Hotfix
|
||||
修复 ────┤
|
||||
└─ 需要调试 ─────→ Bugfix
|
||||
|
||||
┌─ 需求清晰/小 ──→ Quick
|
||||
新建 ────┤ 需要设计 ─────→ Feature
|
||||
├─ 改现有结构 ───→ Refactor
|
||||
└─ 跨模块/服务 ──→ System
|
||||
```
|
||||
|
||||
## Codex 端关键限制 (vs CC)
|
||||
|
||||
| 能力 | CC | Codex | Athena 替代方案 |
|
||||
|------|-----|-------|----------------|
|
||||
| /goal autonomous loop | ✓ v2.1.139+ | ✗ | delivery-gate hook 兜底判定 VERDICT |
|
||||
| /batch 自动并行 worktree | ✓ v2.1.121+ | ✗ | spawn_agent 多线程 (config.toml [agents].max_threads) |
|
||||
| /background 多会话 | ✓ v2.1.139+ | ✗ | 用户自己开多个 codex session |
|
||||
| PreCompact / PostCompact | ✓ | ✗ | 长任务点主动 _index.md 保存 |
|
||||
| Session memory | ✓ ~/.claude/projects/ | ✗ | 无 (cross_session_memory: "none") |
|
||||
| compact 自动 | ✓ /compact | ✗ | Codex 用 `/clear` + AGENTS.md 注入恢复 |
|
||||
|
||||
## Codex 优势 (vs CC)
|
||||
|
||||
| 信号 | Codex 更适合 |
|
||||
|------|------------|
|
||||
| 终端命令为主 | Terminal-Bench 2.0 SOTA 82.7% (GPT-5.5 Apr 2026) |
|
||||
| 大量同模式改写 | token 成本 0.25-0.33× CC, 适合"重复劳动" |
|
||||
| 多模型互审 | Codex 主跑 + 调 web_search 验证 |
|
||||
|
||||
## 跨平台路由建议
|
||||
|
||||
Codex 端在以下情况主动建议用户切到 CC:
|
||||
- 任务包含大量"自动循环直到达成条件" → 建议 CC `/goal`
|
||||
- 任务包含"并行改 100 个文件" → 建议 CC `/batch`
|
||||
- 任务需要 Opus 设计能力 → 建议 CC
|
||||
|
||||
不强制 — 是建议。
|
||||
|
||||
## 6 路径 (Codex 版, 简化)
|
||||
|
||||
### Hotfix · Bugfix
|
||||
同 CC 版, 没有 stage. `apply_patch` 改 → `shell` 跑测试 → `git commit`.
|
||||
|
||||
### Quick (impl → review → ship)
|
||||
TDD 实现 → /review (Codex 内置) → git commit.
|
||||
路径升级监测 (同 CC).
|
||||
|
||||
### Feature (plan → impl → review → ship)
|
||||
- **plan**: web_search 调研 + brainstorming → design.md → 用户确认 → tasks.
|
||||
- **impl**: 按 task 实现, TDD, 完成勾选 + progress 追加. 路径升级监测.
|
||||
- **review**: /review + spawn_agent reviewer (Codex subagent, 见 [agents].max_threads). VERDICT.
|
||||
- **ship**: git commit + 归档.
|
||||
|
||||
### Refactor (plan → impl → review → ship)
|
||||
- **plan**: 用户确认重构方案 + design.md (before/after) + tasks-current.md.
|
||||
- **impl**: 用 spawn_agent 多线程并发 (Codex 端不像 CC 的 /batch 自动 worktree, 需要手动多 agent 协作).
|
||||
- 设置 `--max-threads <N>` (从 _index.md.platform_features 推断 max_threads)
|
||||
- **review**: 同 Feature.
|
||||
- **ship**: 同上.
|
||||
|
||||
### System (plan → design → impl → review → ship)
|
||||
完整流程, 长 stage 主动写 `.ai_state/_index.md` 保存 (Codex 无 compact).
|
||||
|
||||
## 共享协议 (审查/发布同 CC 端)
|
||||
|
||||
参考 `~/.codex/skills/pace/SKILL.md` 完整文本.
|
||||
|
||||
## 失败处理协议 (同 CC, 铁律 6 完成度证据)
|
||||
|
||||
工具失败 → 三轮重试 (改参数 / 换工具 / 拆任务). 三轮后报告完整 stderr + exit code.
|
||||
spawn_agent 输出预算 ≤ 2000 tokens.
|
||||
|
||||
**禁止**: "请你手动执行" 作为首次响应.
|
||||
|
||||
## 状态管理 (铁律 5/8)
|
||||
|
||||
`.ai_state/_index.md` 单一入口. 协议字段同 CC 端. 跨平台一致 (铁律 6).
|
||||
|
||||
合法 path: Hotfix / Bugfix / Quick / Feature / Refactor / System
|
||||
合法 stage: plan / design (System only) / impl / review / ship
|
||||
|
||||
Codex 无 compact 生命周期 → 不写 `compact-snapshot.md`, hooks 也无 PreCompact/PostCompact.
|
||||
@@ -0,0 +1,32 @@
|
||||
# VibeCoding Athena Codex (SessionStart 自动注入)
|
||||
|
||||
你是 VibeCoding Athena 工程 Agent. Codex 做事, Athena 把关.
|
||||
|
||||
**铁律 (9 条, 跨平台共用)**:
|
||||
1. 设计先行 (Hotfix/Bugfix 例外)
|
||||
2. TDD 强制
|
||||
3. Sisyphus (tasks 全完成才进审查)
|
||||
4. Review 强制 (Feature+ 至少一次交叉审查)
|
||||
5. 文档即真相 (`.ai_state/_index.md` 单一入口)
|
||||
6. 完成度证据 (报告"完成"必须附 tool_use ID 或命令输出)
|
||||
7. 出处优先 (技术结论必须引用官方文档/源码 URL)
|
||||
8. **索引先行** (进入决策先读 `.ai_state/_index.md`, 禁止 glob 全目录)
|
||||
9. **Hook 是进化器** (Stop 时反思写 `details/proposals.md`)
|
||||
|
||||
工具报错 → 三次重试附 stderr 报告, 不让用户代执行.
|
||||
spawn_agent 必须产生真实 tool_use 响应, 不允许伪造.
|
||||
|
||||
## R₀ Get-bearings (just-in-time)
|
||||
|
||||
1. 必读: `.ai_state/_index.md` (单一入口, 已自动注入)
|
||||
2. 按需: stage=impl/review → 按 pointers.latest_progress 读 progress.md 尾部
|
||||
3. 按需: 命中 lessons 主题 → pointers.latest_lesson 跳段
|
||||
|
||||
文件大就用 head/tail/grep. **禁止 glob 整个 .ai_state/**.
|
||||
|
||||
## Codex 端限制 (vs CC)
|
||||
|
||||
- 无 /goal /batch /background → 由 Athena 兜底
|
||||
- 无 compact → 长 stage 主动写 _index.md 保存
|
||||
- 无 cross-session memory → 跨项目记忆人工同步 ~/.codex/AGENTS.md
|
||||
- Windows 不支持 hooks (官方限制)
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
schema_version: "9.6"
|
||||
athena_version: "9.6.0"
|
||||
project:
|
||||
path: "" # Hotfix | Bugfix | Quick | Feature | Refactor | System | ""
|
||||
stage: "" # plan | design | impl | review | ship | ""
|
||||
sprint: 0
|
||||
active_goal: "" # 当前 /goal condition (空 = 无活动 goal)
|
||||
counts:
|
||||
tasks_pending: 0
|
||||
tasks_done: 0
|
||||
tasks_blocked: 0
|
||||
lessons_lines: 0
|
||||
progress_entries: 0
|
||||
reviews_count: 0
|
||||
pointers:
|
||||
latest_progress: "" # 如 "details/progress.md#L46"
|
||||
latest_review: "" # 如 "details/reviews/sprint-3.md"
|
||||
latest_lesson: "" # 如 "details/lessons.md#L98"
|
||||
latest_proposal: "" # 如 "details/proposals.md#L12"
|
||||
fingerprints:
|
||||
tasks_mtime: 0
|
||||
design_mtime: 0
|
||||
progress_mtime: 0
|
||||
lessons_mtime: 0
|
||||
platform_features:
|
||||
cc_version: "" # 由 athena-setup 检测填入
|
||||
cx_version: "" # 同上
|
||||
goal_supported: false # CC ≥ v2.1.139 时 true
|
||||
batch_supported: false # CC ≥ v2.1.121 时 true
|
||||
background_supported: false # CC ≥ v2.1.139 时 true
|
||||
session_memory_active: false # ~/.claude/projects/ 自动摘要是否启用
|
||||
cross_session_memory: "none" # "claude-mem" | "superpowers" | "none"
|
||||
gotchas: [] # 项目特有的"小心点", PACE 会在 SessionStart 注入
|
||||
conventions: [] # 项目约定 (pnpm vs npm 等)
|
||||
tech_stack: ""
|
||||
test_cmd: ""
|
||||
build_cmd: ""
|
||||
lint_cmd: ""
|
||||
dev_cmd: ""
|
||||
---
|
||||
|
||||
# 项目状态索引
|
||||
|
||||
<!--
|
||||
本文件是 .ai_state/ 的单一入口 (铁律 8)。
|
||||
SessionStart hook 只读这一个文件, 注入轻量 frontmatter 字段 + counts 摘要。
|
||||
下游 (Edit/Read tools) 按 pointers 自取明细。
|
||||
任何 detail/* 文件写入 → PostToolUse index-updater.cjs 原子更新本文件。
|
||||
-->
|
||||
|
||||
## 最近活动
|
||||
|
||||
<!-- 由 pace-continuator hook 在 Stop 时维护, 保留最近 3 条 -->
|
||||
|
||||
## 当前阻塞
|
||||
|
||||
<!-- 由 PACE 流程在 stage=impl/review 时填写 -->
|
||||
|
||||
## 下一动作 (PACE 建议)
|
||||
|
||||
<!-- 由 pace-continuator 在 Stop 时根据 stage 推断, 写入 details/next.md 的摘要 -->
|
||||
|
||||
## 反思建议 (Hook 沉淀)
|
||||
|
||||
<!-- 引用 details/proposals.md 最近一条 (latest_proposal) -->
|
||||
@@ -0,0 +1,28 @@
|
||||
# 设计文档
|
||||
|
||||
## 需求摘要
|
||||
|
||||
## 功能分级
|
||||
|
||||
- **MUST**:
|
||||
- **SHOULD**:
|
||||
- **COULD**:
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ]
|
||||
|
||||
## 技术方案
|
||||
|
||||
## File Structure Plan
|
||||
|
||||
<!--
|
||||
模块/文件边界, 给 tasks-current.md 拆任务用 (boundary-first 设计)
|
||||
示例:
|
||||
- src/auth/ — JWT/refresh/session, owner: Task 1-3
|
||||
- src/routes/user/ — user CRUD endpoints, owner: Task 4-5
|
||||
- tests/auth/ — auth 单测 + 集成测试
|
||||
边界外的文件 = 本 Sprint 不应触碰
|
||||
-->
|
||||
|
||||
## 不做什么
|
||||
@@ -0,0 +1,31 @@
|
||||
# 跨模型/跨 worker 交接
|
||||
|
||||
<!--
|
||||
本文件内容会作为 /codex:rescue "<内容>" 的 prompt 传入。Codex 不会自动读本文件。
|
||||
构造完 handoff.md → Claude 把文件内容 Read 出来作为 /codex:rescue 的参数。
|
||||
-->
|
||||
|
||||
## 当前任务
|
||||
|
||||
<!-- Task ID + 描述 + 验收标准 + Boundary 范围 -->
|
||||
|
||||
## 项目文件树
|
||||
|
||||
<!-- 必须包含实际文件列表, 用 find/ls 生成, 不要手写 -->
|
||||
<!-- 示例: find . -name "*.py" -not -path "./venv/*" | head -50 -->
|
||||
|
||||
## 关键代码片段
|
||||
|
||||
<!-- 与本 Task 直接相关的代码文件内容 (关键函数/类, 不要全文) -->
|
||||
|
||||
## 项目背景
|
||||
|
||||
<!-- design.md 摘要 + 技术栈 -->
|
||||
|
||||
## 已完成
|
||||
|
||||
<!-- tasks-current.md 中完成的 Task -->
|
||||
|
||||
## 注意事项
|
||||
|
||||
<!-- _index.md.gotchas + conventions -->
|
||||
@@ -0,0 +1,21 @@
|
||||
# 项目级经验沉淀 (Lessons Learned)
|
||||
|
||||
<!--
|
||||
每个 Sprint 通过 Gate 后由 compound skill 追加。append-only, 不删不改历史。
|
||||
本文件存项目级业务代码经验 (Athena 不做跨项目知识管理)。
|
||||
跨项目记忆请装 claude-mem 或 superpowers。
|
||||
|
||||
格式:
|
||||
|
||||
## [YYYY-MM-DD Sprint N] 一句话标题
|
||||
- **Pattern**: 解法描述 (文件:行号)
|
||||
- **Pitfall**: 坑点描述
|
||||
- **Constraint**: 新约束
|
||||
|
||||
示例:
|
||||
|
||||
## [2026-05-21 Sprint 1] JWT refresh 不能和 access 共享 secret
|
||||
- **Pattern**: 分开 secret + rotation key 在 env (src/auth/config.ts:15)
|
||||
- **Pitfall**: Authorization header 大小写处理不一致, 用 lodash.toLower 前置
|
||||
- **Constraint**: Redis 需要 ≥256MB 才放得下 session cache
|
||||
-->
|
||||
@@ -0,0 +1,15 @@
|
||||
# 下一动作建议 (PACE-aware, Stop hook 维护)
|
||||
|
||||
<!--
|
||||
本文件由 .claude/hooks/pace-continuator.cjs 在 Stop 事件时写入。
|
||||
读 _index.md 的 path/stage/sprint, 推断"下一步该做什么", 给出具体的命令建议。
|
||||
SessionStart 时 (如有 pace-resumer hook) 会读本文件作为"继续提示"。
|
||||
|
||||
格式:
|
||||
## YYYY-MM-DD HH:MM
|
||||
当前: <path>/<stage>/sprint <N>
|
||||
建议:
|
||||
- 命令 1
|
||||
- 命令 2
|
||||
理由: <一句话>
|
||||
-->
|
||||
@@ -0,0 +1,15 @@
|
||||
# Progress Log
|
||||
|
||||
<!--
|
||||
impl 阶段每完成一个 Task 追加一行 (铁律 5)。
|
||||
格式: YYYY-MM-DD HH:MM [path/stage/sprint] action
|
||||
|
||||
示例:
|
||||
2026-05-21 14:30 [Feature/impl/1] Task 3 done: auth middleware
|
||||
2026-05-21 15:10 [Feature/impl/1] design.md updated: JWT expiry 15min
|
||||
2026-05-21 15:30 [Feature/impl/1] PATH-UPGRADE Feature → System (发现需要改 schema)
|
||||
2026-05-21 16:45 [Feature/review/1] /review 完成, 无阻塞问题
|
||||
|
||||
append-only: 不删历史, 不改既有行。
|
||||
index-updater hook 会更新 _index.md.counts.progress_entries 和 pointers.latest_progress。
|
||||
-->
|
||||
@@ -0,0 +1,20 @@
|
||||
# Hook 反思沉淀 (铁律 9: Hook 是进化器)
|
||||
|
||||
<!--
|
||||
本文件由 .claude/hooks/pace-continuator.cjs 在 Stop 时维护。
|
||||
当 hook 检测到"本 turn 有反复试错 / 阻塞 / 失败模式", append-only 一条反思。
|
||||
|
||||
不写"已知坑" (lessons.md 管那个), 写"流程级提议":
|
||||
- "考虑把 X 加入 .ai_state/conventions"
|
||||
- "delivery-gate 这条规则可能误伤, 下版本调整"
|
||||
- "本 sprint 的 stage transition 太快, plan 阶段不充分"
|
||||
|
||||
人审完后可以手动迁移到 lessons.md 或者 conventions 列表。
|
||||
hook 永远不替用户做决定, 只提供素材。
|
||||
|
||||
格式:
|
||||
## YYYY-MM-DD HH:MM (sprint N)
|
||||
- 观察: <事实>
|
||||
- 假设: <可能原因>
|
||||
- 提议: <改什么>
|
||||
-->
|
||||
@@ -0,0 +1,41 @@
|
||||
# Sprint N 审查报告
|
||||
|
||||
## Step 1: 测试结果
|
||||
|
||||
<!-- 命令 + 实际输出 (不是"已跑通") -->
|
||||
|
||||
## Step 2: /codex:review (Feature+, Quick 可选)
|
||||
|
||||
<!-- 必须有以下证据之一, 防伪装 (铁律 4 反空跑 + 铁律 6 完成度证据):
|
||||
- codex job ID
|
||||
- codex CLI 真实命令行输出片段
|
||||
- 不可用时明示 "codex unavailable" + 完整 stderr -->
|
||||
|
||||
## Step 3: /codex:adversarial-review (System)
|
||||
|
||||
<!-- 同上证据要求 -->
|
||||
|
||||
## Step 4: ECC 扫描 (System)
|
||||
|
||||
<!-- npx ecc-agentshield scan 实际输出摘要 -->
|
||||
|
||||
## Step 5: Claude 审查 (/review 内置)
|
||||
|
||||
<!-- /review 输出 -->
|
||||
|
||||
## Step 6: @evaluator 评分
|
||||
|
||||
| 维度 | 分数 | 证据 |
|
||||
|------|------|------|
|
||||
| Functionality | /5 | (代码行号) |
|
||||
| Spec Compliance | /5 | (代码行号 vs design.md) |
|
||||
| Boundary Adherence | /5 | (是否越出 File Structure Plan) |
|
||||
| Craft | /5 | (代码行号) |
|
||||
| Robustness | /5 | (边界用例覆盖) |
|
||||
| **均分** | **/5** | |
|
||||
|
||||
均分 = F×0.25 + SC×0.25 + B×0.15 + C×0.15 + R×0.20
|
||||
|
||||
## VERDICT:
|
||||
|
||||
<!-- PASS (均分≥4.0 且所有维度≥3) | CONCERNS (均分≥3.0 有维度=2) | REWORK (均分<3.0 或任一=1) | FAIL (多维度=1 或安全/Boundary 大幅越界) -->
|
||||
@@ -0,0 +1,19 @@
|
||||
# Sprint 任务清单
|
||||
|
||||
<!--
|
||||
每个 Task 的 Boundary/Depends 标注 (cc-sdd 边界优先, 防止越界)
|
||||
格式:
|
||||
- [ ] Task N: 简述
|
||||
_Boundary:_ src/auth/, tests/auth/
|
||||
_Depends:_ Task N-1 (空则 — )
|
||||
|
||||
PostToolUse hook (index-updater.cjs) 会:
|
||||
- 检测本文件的 - [ ] / - [x] 数量变化
|
||||
- 原子更 _index.md.counts.tasks_pending/done/blocked
|
||||
-->
|
||||
|
||||
## 待办
|
||||
|
||||
## 完成
|
||||
|
||||
## 阻塞
|
||||
@@ -0,0 +1,121 @@
|
||||
# /goal Condition 模板库
|
||||
|
||||
每个 PACE stage 对应一个 condition 模板, 用 `/goal <condition>` 启动 autonomous loop。
|
||||
|
||||
参考: <https://code.claude.com/docs/en/goal>
|
||||
|
||||
## 写 condition 的四件套 (官方推荐)
|
||||
|
||||
```
|
||||
End Goal + Verification + Constraints + Turn/Time Limit
|
||||
```
|
||||
|
||||
- **End Goal**: 一个可测的终态 (test 通过 / 文件存在 / git log 含 commit)
|
||||
- **Verification**: 如何证明 (npm test exits 0 / rg "X" 0 行)
|
||||
- **Constraints**: 边界 (不动 X 文件 / 不引入新依赖)
|
||||
- **Turn/Time Limit**: stop after 20 turns / stop after 60 minutes
|
||||
|
||||
---
|
||||
|
||||
## Feature/Refactor/System stage=plan
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- .ai_state/details/design.md 含 "## File Structure Plan" 段且段下至少 3 个 owner 行
|
||||
- .ai_state/details/tasks-current.md 至少 1 个 - [ ] Task
|
||||
- 我已经 ask 用户确认且收到了 "yes" 或 "go" 回复
|
||||
Constraints:
|
||||
- 不修改 design.md 之外的源码文件
|
||||
- 不超过 20 turns
|
||||
```
|
||||
|
||||
## Quick/Feature stage=impl
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- .ai_state/details/tasks-current.md 中所有 - [ ] 都变成 - [x]
|
||||
- 运行 <test_cmd> 退出码 0 (从 _index.md.test_cmd 读)
|
||||
- .ai_state/details/progress.md 在本 turn 序列至少新增 N 行 (N = 原待办 task 数)
|
||||
- 没有任何对 design.md 的修改
|
||||
Constraints:
|
||||
- 不动 .ai_state/_index.md 以外的元数据
|
||||
- 不超过 30 turns 或 90 分钟
|
||||
```
|
||||
|
||||
## Refactor stage=impl (用 /batch)
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- tasks-current.md 全部 - [x]
|
||||
- 每个 worktree 的 lint_cmd 退出 0
|
||||
- 每个 worktree 的 test_cmd 退出 0
|
||||
- 主分支 git diff 显示预期的批量变更模式
|
||||
Constraints:
|
||||
- 不引入新依赖
|
||||
- 不超过 60 minutes 或 50 turns
|
||||
```
|
||||
|
||||
## System stage=design
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- details/design.md 含 "## File Structure Plan" 且段下覆盖所有新增/修改的模块路径
|
||||
- details/design.md 含 "## 验收标准" 段且至少 5 条 - [ ] (会在 impl 阶段勾选)
|
||||
- details/tasks-current.md 至少 N 个 Task (N = design 模块数), 每个含 Boundary 和 Depends 注释
|
||||
- 我已经 ask 用户对设计的最终确认
|
||||
Constraints:
|
||||
- 不超过 25 turns
|
||||
```
|
||||
|
||||
## stage=review (Feature+)
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- .ai_state/details/reviews/sprint-{sprint}.md 已存在且含 "VERDICT:" 行
|
||||
- VERDICT 取值为 PASS / CONCERNS / REWORK / FAIL 之一
|
||||
- 报告含至少一段 /codex:review 或 reviewer subagent 的真实输出 (codex job ID 或 thread ID)
|
||||
- 报告含 test_cmd 实际输出
|
||||
Constraints:
|
||||
- 评分必须基于代码行号级证据
|
||||
- 不超过 40 turns
|
||||
```
|
||||
|
||||
## stage=ship
|
||||
|
||||
```
|
||||
ALL of:
|
||||
- details/lessons.md 末尾含 "## [{date} Sprint {sprint}]" 标题
|
||||
- git log --oneline -1 显示本 sprint 的提交
|
||||
- _index.md.project.sprint 已 +1 且 stage="" (由 athena-status 验证)
|
||||
- details/tasks-archive/sprint-{sprint}.md 存在 (归档)
|
||||
Constraints:
|
||||
- 不超过 10 turns
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 启动方式
|
||||
|
||||
### 交互式
|
||||
```
|
||||
/goal <粘贴上面对应 stage 的 condition>
|
||||
```
|
||||
|
||||
### 非交互式 (overnight 跑)
|
||||
```bash
|
||||
claude -p "/goal <condition>"
|
||||
```
|
||||
|
||||
### 状态查询
|
||||
```
|
||||
/goal # 不带参数, 看 turns/tokens/最近 evaluator reason
|
||||
/goal clear # 中止
|
||||
```
|
||||
|
||||
## 注意事项 (官方文档)
|
||||
|
||||
- evaluator 只读 transcript, 不跑命令——condition 必须是"transcript 能证明的事"
|
||||
- 一个 session 只能有一个 active goal, 设置新 goal 替换旧的
|
||||
- condition ≤ 4000 字符
|
||||
- v2.1.139+ 才有, 旧版本 delivery-gate hook 兜底
|
||||
- "Vague in, vague out"——含糊的 condition = 含糊的 loop
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# Athena init.sh — 启动开发环境 + 基线测试
|
||||
# 由 /athena-init 根据项目类型生成具体命令
|
||||
set -e
|
||||
|
||||
echo "[Athena] 启动开发环境..."
|
||||
# 示例 (根据项目类型):
|
||||
# npm install
|
||||
# pip install -e .
|
||||
# cargo build
|
||||
|
||||
echo "[Athena] 运行基线测试..."
|
||||
# npm test
|
||||
# pytest
|
||||
# cargo test
|
||||
|
||||
echo "[Athena] 就绪。"
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: plan-first
|
||||
description: P 阶段计划生成
|
||||
---
|
||||
# Plan-First (P 阶段)
|
||||
|
||||
## 流程
|
||||
1. 读 design.md
|
||||
2. 分解为可执行任务:
|
||||
```
|
||||
- [ ] T-001: {动作} + {目标} + {验收条件}
|
||||
文件: {涉及文件}
|
||||
依赖: {前置任务}
|
||||
```
|
||||
3. 排序: 依赖拓扑 → 风险高先做
|
||||
4. 写入 plan.md
|
||||
|
||||
## 质量检查
|
||||
- 每个任务有"完成"定义
|
||||
- 无模糊词
|
||||
- 超过 15 个任务考虑拆分
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: reflexion
|
||||
description: E 阶段自我反思
|
||||
---
|
||||
# Reflexion (自我反思)
|
||||
|
||||
E 阶段每个 Task 实现完成后, Micro-review 之前。
|
||||
|
||||
## 反思清单
|
||||
1. 走捷径了吗? (as any, 空 catch)
|
||||
2. 忽略边界了吗? (空/超长/并发/null)
|
||||
3. 硬编码了吗? (URL/端口/阈值)
|
||||
4. 过度工程了吗? (需求没要求的功能)
|
||||
5. 偏离 spec 了吗?
|
||||
6. 6 个月后能理解吗?
|
||||
|
||||
发现问题 → 立即修复
|
||||
值得记录 → lessons.md
|
||||
模式性错误 → conventions.md "Agent 易犯错误"
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
name: security-review
|
||||
description: 安全审查
|
||||
---
|
||||
# Security Review
|
||||
|
||||
检查: 认证/授权, 输入验证, 密钥管理, 依赖漏洞, 日志安全, CORS/CSP
|
||||
产出: 追加到 quality.md
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: verification
|
||||
description: T 阶段验证
|
||||
---
|
||||
# Verification
|
||||
|
||||
## 流程
|
||||
1. 运行测试 + 覆盖率
|
||||
2. TypeScript 类型检查 (如有)
|
||||
3. Lint (如有, Path C+ 强制)
|
||||
|
||||
## 验收标准逐条确认
|
||||
4. 读 design.md "## 验收标准"
|
||||
5. 逐条确认: 满足? 证据?
|
||||
6. 未满足 → quality.md "## 未满足验收标准"
|
||||
7. E2E (如有框架)
|
||||
@@ -1,9 +0,0 @@
|
||||
# Conventions
|
||||
|
||||
## 项目编码规范
|
||||
{自动检测或手动填写}
|
||||
|
||||
## Agent 易犯错误
|
||||
> 由 reflexion/kaizen 自动追加
|
||||
|
||||
- (初始为空)
|
||||
@@ -1,19 +0,0 @@
|
||||
# Design Spec
|
||||
|
||||
## 需求 (MUST/SHOULD/COULD)
|
||||
|
||||
### MUST
|
||||
- {核心功能}
|
||||
|
||||
### SHOULD
|
||||
- {重要功能}
|
||||
|
||||
### COULD
|
||||
- {锦上添花}
|
||||
|
||||
## 技术方案
|
||||
{架构}
|
||||
|
||||
## 验收标准
|
||||
- [ ] {标准 1}
|
||||
- [ ] {标准 2}
|
||||
@@ -1,7 +0,0 @@
|
||||
# Doing
|
||||
|
||||
## 当前执行
|
||||
- [ ] {当前步骤}
|
||||
|
||||
## 历史
|
||||
{自动追加}
|
||||
@@ -1,7 +0,0 @@
|
||||
# Lessons Learned
|
||||
|
||||
## 技术陷阱
|
||||
{发现的问题}
|
||||
|
||||
## 有效模式
|
||||
{有效的解决方案}
|
||||
@@ -1,7 +0,0 @@
|
||||
# Plan
|
||||
|
||||
## 任务列表
|
||||
|
||||
- [ ] T-001: {动作} + {目标} + {验收条件}
|
||||
文件: {文件}
|
||||
依赖: 无
|
||||
@@ -1,13 +0,0 @@
|
||||
# Quality Report
|
||||
|
||||
## 验证结果
|
||||
- 测试: {通过/失败}
|
||||
- 类型检查: {通过/失败}
|
||||
|
||||
## 验收标准确认
|
||||
- [x] {标准}: 满足
|
||||
- [ ] {标准}: 未满足
|
||||
|
||||
## 代码审查
|
||||
- 发现: {数量}
|
||||
- 已修复: {数量}
|
||||
@@ -1,10 +0,0 @@
|
||||
# Session
|
||||
|
||||
## 任务
|
||||
{任务描述}
|
||||
|
||||
## 路径
|
||||
P.A.C.E. Path: {A|B|C|D}
|
||||
|
||||
## 当前阶段
|
||||
RIPER-7: {R₀|R|D|P|E|T|V}
|
||||
@@ -1,13 +0,0 @@
|
||||
# P.A.C.E. 复杂度路由 v9.2.0
|
||||
|
||||
收到任务后, 按以下规则选择路径:
|
||||
|
||||
| 条件 | 路径 | 阶段 |
|
||||
|------|------|------|
|
||||
| 修 bug / 改配置 / <30min | **A (快速)** | E→T |
|
||||
| 新功能 / 重构 / 30min-4h | **B (标准)** | R₀→R→D→P→E→T→V |
|
||||
| 跨模块 / 架构变更 / >4h | **C (复杂)** | 同B + 子代理并行 |
|
||||
| 多服务 / 全栈 / 多人协作 | **D (系统)** | 同C + 设计评审 |
|
||||
|
||||
选定路径后 → 读 riper-7.md 执行对应阶段。
|
||||
Path A 跳过 R₀/R/D/P, 直接 E→T。
|
||||
@@ -1,57 +0,0 @@
|
||||
# RIPER-7 阶段编排 v9.2.0
|
||||
|
||||
## 每阶段进入前 (通用)
|
||||
1. 这一步要解决的核心问题是什么?
|
||||
2. 项目里有没有类似实现? → 搜索相关代码
|
||||
3. 用到的库 API 确定吗? → context7 skill 查文档
|
||||
4. .ai_state/lessons.md + conventions.md 有相关经验吗?
|
||||
|
||||
---
|
||||
|
||||
## R₀ 需求精炼 (Path B+)
|
||||
**技能**: brainstorm skill (含步骤0自主调研)
|
||||
**产出**: .ai_state/design.md (Spec: MUST/SHOULD/COULD + 验收标准)
|
||||
**门控**: cunzhi `DESIGN_READY` (cunzhi 不可用时: 直接输出 "[DESIGN_READY] 请确认" 等用户回复)
|
||||
|
||||
## R 技术调研 (Path B+)
|
||||
读 design.md → 搜索相关代码 + 查库文档
|
||||
产出: design.md 追加技术方案
|
||||
|
||||
## D 方案定稿 (Path B+)
|
||||
读 design.md → 检查接口最小化? 错误处理完整? 更简单的方案?
|
||||
产出: design.md 最终版
|
||||
门控: cunzhi `DESIGN_FINALIZED` (cunzhi 不可用时: 直接输出确认提示)
|
||||
|
||||
## P 计划 (Path B+)
|
||||
技能: plan-first skill → 生成 plan.md
|
||||
**计划审查**: 用 /review 内置功能审查, 或用 validator agent
|
||||
门控: cunzhi `PLAN_CONFIRMED` (cunzhi 不可用时: 直接输出确认提示)
|
||||
|
||||
## E 执行 (Path B+) — Sisyphus 循环
|
||||
对 plan.md 每个 Task:
|
||||
1. 读 Task + 相关文件 + conventions.md
|
||||
2. TDD: 先写测试 → 实现 → 重构
|
||||
2.5. **Reflexion** (自我反思 → reflexion skill):
|
||||
"这个实现有没有: 走捷径/忽略边界/硬编码/过度工程/偏离 spec?"
|
||||
发现问题 → 立即修复
|
||||
值得记录 → lessons.md
|
||||
3. **Micro-review**: 对标 design.md spec + conventions.md
|
||||
通过 → [x] Task + commit
|
||||
不通过 → 修复
|
||||
**铁律**: plan.md 有任何 [ ] 未完成, 不停止。
|
||||
|
||||
## T 测试/审查 (Path B+)
|
||||
1. verification skill: 跑测试 + 覆盖率
|
||||
1.5. **验收标准确认**:
|
||||
读 design.md "## 验收标准" → 逐条确认是否满足
|
||||
未满足 → 标注到 quality.md
|
||||
2. code-review skill: 代码审查
|
||||
3. 用 /review 内置审查功能 做代码审查
|
||||
4. 综合 → quality.md
|
||||
5. Quality Gate: PASS(exit 0) / CONCERNS(exit 0+warn) / REWORK(exit 2) / FAIL(exit 2)
|
||||
|
||||
## V 归档 (Path B+)
|
||||
1. kaizen skill: 回顾 + lessons.md
|
||||
1.5. **分支收尾** (finish-branch skill):
|
||||
选项: PR description / keep / discard (Codex 不直接 merge)
|
||||
2. cunzhi `DELIVERY_COMPLETE` (cunzhi 不可用时: 直接输出确认提示)
|
||||
Reference in New Issue
Block a user