ly-workflow-codex 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +65 -0
- package/bin/lycx.mjs +2 -0
- package/dist/chunks/legacy-cleanup.mjs +143 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +340 -0
- package/dist/index.d.mts +223 -0
- package/dist/index.d.ts +223 -0
- package/dist/index.mjs +12 -0
- package/dist/shared/ly-workflow-codex.K-E7PMp3.mjs +2068 -0
- package/docs/codex-exec-contract.md +90 -0
- package/package.json +73 -0
- package/templates/prompts/codex/plan-reviewer.md +52 -0
- package/templates/prompts/codex/reviewer.md +58 -0
- package/templates/skills-codex/apply.md +49 -0
- package/templates/skills-codex/archive.md +22 -0
- package/templates/skills-codex/changelog.md +165 -0
- package/templates/skills-codex/clean-branches.md +121 -0
- package/templates/skills-codex/commit.md +126 -0
- package/templates/skills-codex/explore.md +19 -0
- package/templates/skills-codex/init.md +63 -0
- package/templates/skills-codex/propose.md +147 -0
- package/templates/skills-codex/publish.md +388 -0
- package/templates/skills-codex/release.md +317 -0
- package/templates/skills-codex/review-code.md +190 -0
- package/templates/skills-codex/review-plan.md +196 -0
- package/templates/skills-codex/rollback.md +120 -0
- package/templates/skills-codex/worktree.md +159 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
> ⚠️ **DEPRECATED(自本 change `subagent-multi-agent-mode` 起)**:审查/实施已迁移 **subagent 多 Agent 模式**(双审查 subagent + coding subagent,spawn 协议/任务构造/共识与分歧裁决内联写入 `templates/skills-codex/review-plan.md`、`review-code.md`、`apply.md`),**模板不再引用本文档**。本文档仅作历史参考保留——subagent 为宿主原生能力,不再有 shell 调用契约的版本漂移维护面。
|
|
2
|
+
|
|
3
|
+
# codex exec 独立子会话调用契约
|
|
4
|
+
|
|
5
|
+
> 适用范围:`templates/skills-codex/review-plan.md` 与 `templates/skills-codex/review-code.md` 的审查子会话调用。
|
|
6
|
+
> **该契约随 codex CLI 版本漂移,升级 codex 时需复核**(尤其是子命令形态、`--json` 事件名、resume 行为)。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 调用命令形态(首轮)
|
|
11
|
+
|
|
12
|
+
审查在 `codex exec` **独立子会话**中执行(无当前会话上下文),调用方(当前会话)通过 stdin 传入 heredoc(ROLE_FILE + TASK + OUTPUT 格式约束),审查子会话以 agentic 模式运行,具备在 `WORKDIR` 下自主执行 shell 命令、读取文件的能力。
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
WORKDIR=$(pwd)
|
|
16
|
+
cat <<'CODEAGENT_EOF' | codex exec -C "$WORKDIR" --json -m {{REVIEW_MODEL}} -
|
|
17
|
+
ROLE_FILE: ~/.ly/prompts/codex/reviewer.md # review-plan 用 plan-reviewer.md
|
|
18
|
+
<TASK>…</TASK>
|
|
19
|
+
OUTPUT: …
|
|
20
|
+
CODEAGENT_EOF
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
要点:
|
|
24
|
+
|
|
25
|
+
- `-C "$WORKDIR"`:审查子会话的工作目录 = 当前仓库目录。
|
|
26
|
+
- `--json`:输出 JSONL 事件流(每行一个 JSON 事件),供 SESSION_ID 提取。
|
|
27
|
+
- `-m {{REVIEW_MODEL}}`:模型由安装期配置渲染;未配置审查模型时**不带** `-m`(回退当前会话模型)。
|
|
28
|
+
- `ROLE_FILE`:`~/.ly/prompts/codex/` 下的绝对路径,审查子会话先读取该角色词再执行审查,此路径为行为契约不可改。
|
|
29
|
+
- TASK 只传基线引用说明与路径清单,不预先拼贴文件全文(子会话自行读取)。
|
|
30
|
+
|
|
31
|
+
## 2. thread.started / session_id 提取规则
|
|
32
|
+
|
|
33
|
+
`--json` 输出为 JSONL 事件流。取**首个** `thread.started` 事件的 `thread_id` 字段值作为本流程审查会话的 SESSION_ID:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{ "type": "thread.started", "thread_id": "01a09e11-..." }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- resume 参数接受该 UUID;后续轮次 resume 复用,**不因 resume 而更换**。
|
|
40
|
+
- 事件流中没有 `thread.started`/`thread_id` 事件 → 按"未取得 session_id"处理(后续轮次退化为独立调用,见 §3)。
|
|
41
|
+
|
|
42
|
+
## 3. resume 续聊循环(第 2 轮起)
|
|
43
|
+
|
|
44
|
+
从第 2 轮起,命令从 §1 形态改为:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
cat <<'CODEAGENT_EOF' | codex exec -C "$WORKDIR" --json resume <session-id> -
|
|
48
|
+
…增量 TASK…
|
|
49
|
+
CODEAGENT_EOF
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
要点:
|
|
53
|
+
|
|
54
|
+
- **resume 子命令不带 `-m`**(模型沿用首轮会话)。
|
|
55
|
+
- stdin 仍传增量 TASK,构造方式同首轮,只是内容替换为增量传递(上一轮全部 Critical 原文 + 路径清单),不再整段重传基线。
|
|
56
|
+
- 审查子会话在同一会话上下文中复用上一轮记忆(它给的 Critical、已做的修改),会话记忆提供连续性。
|
|
57
|
+
- 每轮的 SESSION_ID 都以本流程**首轮**的为准;未取得 SESSION_ID 时,后续轮次退化为独立调用(命令同首轮),并在本轮报告中如实说明"未启用轮间续聊"。
|
|
58
|
+
- 第 2 轮起的调用由当前会话自动触发,不要求用户手动重新触发命令。
|
|
59
|
+
|
|
60
|
+
## 4. 调用失败处理(独立终止条件)
|
|
61
|
+
|
|
62
|
+
若本次调用超时、非零退出、返回空响应,或返回内容无法解析为 Critical/Warning/Info 格式(也不是明确的"无发现"声明),立即停止循环,报告原始失败信息(退出码/超时说明/原始输出片段),**不得**把失败等同于"本轮无 Critical"或视为清零通过。
|
|
63
|
+
|
|
64
|
+
## 5. 终止条件八条
|
|
65
|
+
|
|
66
|
+
任一命中即停止循环,转报告(不执行任何提交,改动留在工作区);**清零优先于轮数上限**(本轮先判 Critical 是否清零,仅非清零时才检查轮数上限):
|
|
67
|
+
|
|
68
|
+
1. **正常清零**:某一轮审查 Critical 数为 0。
|
|
69
|
+
2. **熔断**:同一个 Critical(文件路径 + 问题类别 + 定位锚点三者共同判定为同一问题)在相邻两轮审查中都被判定为存在,且上一轮当前会话对它是"认可"状态(已尝试修复但没修好)。
|
|
70
|
+
3. **无法安全自动修复**:修复需要产品/业务决策、依赖当前会话不具备的外部凭据、会改变已发布的公开 API/接口契约,或当前会话判断信息不足以给出确定性修复——不得猜测性修改。
|
|
71
|
+
4. **修复后验证失败**:本轮修复后运行项目对应验证命令(测试/类型检查/构建,review-plan 为 `openspec validate`)失败,立即停止,报告改动文件清单与验证失败信息。
|
|
72
|
+
5. **分歧未决**:当前会话对某条 Critical 上一轮判断"不认可"(未修复),下一轮审查子会话仍判定同一问题存在。
|
|
73
|
+
6. **审查对象类型持续系统性误判**:连续 3 轮(含本轮)每一轮的全部 Critical 都被当前会话判定为同一大类系统性误判(理由类别一致,不要求文件/类别/锚点匹配)。
|
|
74
|
+
7. **达到全局轮数上限**(默认 5 轮,独立于 1-6 的判定)。
|
|
75
|
+
8. **审查调用失败**:见 §4(模板中表述为"审查调用失败视为独立终止条件")。
|
|
76
|
+
|
|
77
|
+
触发条件 2-6(或达到轮数上限)时,报告中必须明确指出触发的具体条件、涉及的问题(文件/类别/锚点/判定依据),并说明需要人工介入。"分歧未决"与"审查对象类型持续系统性误判"额外要求并列展示审查子会话每轮的原始发现与当前会话每轮的反驳理由(后者展示连续 3 轮)。
|
|
78
|
+
|
|
79
|
+
## 6. 与审查-修复循环的配合
|
|
80
|
+
|
|
81
|
+
- Critical 判定/修复由当前会话执行:逐条判断认可/不认可,认可才修复,不认可必须写反驳理由,不能沉默跳过。
|
|
82
|
+
- 每轮调用完成后都生成"逐轮执行日志",逐字展示该轮审查子会话返回的原始 Critical/Warning/Info 与当前会话判定,直到循环结束。
|
|
83
|
+
- 循环期间不提交;仅正常清零时对审查目标全部文件(原始改动 + 循环修复)统一提交一次(`--no-commit` 可关闭)。
|
|
84
|
+
|
|
85
|
+
## 7. 升级 codex 时的复核清单
|
|
86
|
+
|
|
87
|
+
- `codex exec` 子命令(`-`/`resume`)形态与 `-C`/`--json`/`-m` 参数是否仍有效。
|
|
88
|
+
- `thread.started` 事件名与 `thread_id` 字段是否变化。
|
|
89
|
+
- `resume` 是否仍不带模型参数、是否仍按 `thread_id` 复用。
|
|
90
|
+
- JSONL 事件流格式(行分隔、字段名)是否变化。
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ly-workflow-codex",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"packageManager": "pnpm@10.17.1",
|
|
6
|
+
"description": "Codex 单 Agent 工作流 —— OpenSpec 生命周期 + 独立审查关卡 + GitFlow 发布管线",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "FE-runner"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/FE-runner/ly-workflow-codex.git"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/FE-runner/ly-workflow-codex/issues"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"codex",
|
|
20
|
+
"openspec",
|
|
21
|
+
"ai",
|
|
22
|
+
"cli",
|
|
23
|
+
"workflow"
|
|
24
|
+
],
|
|
25
|
+
"main": "dist/index.mjs",
|
|
26
|
+
"module": "dist/index.mjs",
|
|
27
|
+
"types": "dist/index.d.mts",
|
|
28
|
+
"bin": {
|
|
29
|
+
"lycx": "bin/lycx.mjs"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin/lycx.mjs",
|
|
33
|
+
"dist",
|
|
34
|
+
"docs/codex-exec-contract.md",
|
|
35
|
+
"templates/prompts/codex/",
|
|
36
|
+
"templates/skills-codex/"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "tsx src/cli.ts",
|
|
43
|
+
"build": "unbuild",
|
|
44
|
+
"start": "node bin/lycx.mjs",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"prepublishOnly": "pnpm build",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"lint": "eslint",
|
|
49
|
+
"lint:fix": "eslint --fix"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"ansis": "^4.1.0",
|
|
53
|
+
"cac": "^6.7.14",
|
|
54
|
+
"fs-extra": "^11.3.2",
|
|
55
|
+
"i18next": "^25.5.2",
|
|
56
|
+
"i18next-fs-backend": "^2.6.0",
|
|
57
|
+
"inquirer": "^12.9.6",
|
|
58
|
+
"ora": "^9.0.0",
|
|
59
|
+
"pathe": "^2.0.3",
|
|
60
|
+
"smol-toml": "^1.4.2"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@antfu/eslint-config": "^5.4.1",
|
|
64
|
+
"@types/fs-extra": "^11.0.4",
|
|
65
|
+
"@types/node": "^22.0.0",
|
|
66
|
+
"@vitest/coverage-v8": "^3.2.7",
|
|
67
|
+
"eslint": "^9.36.0",
|
|
68
|
+
"tsx": "^4.20.5",
|
|
69
|
+
"typescript": "^5.9.2",
|
|
70
|
+
"unbuild": "^3.6.1",
|
|
71
|
+
"vitest": "^3.1.1"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Codex Role: OpenSpec Plan Reviewer
|
|
2
|
+
|
|
3
|
+
> For: @lyx-review-plan
|
|
4
|
+
|
|
5
|
+
You are an OpenSpec plan reviewer. You review **planning documents** (proposal/design/tasks/spec) for a not-yet-implemented or partially-implemented change — not application code.
|
|
6
|
+
|
|
7
|
+
## CRITICAL CONSTRAINTS
|
|
8
|
+
|
|
9
|
+
- **ZERO file system write permission** - READ-ONLY sandbox
|
|
10
|
+
- **审查对象是方案文档本身,不是代码库的实现状态**
|
|
11
|
+
- SHALL NOT 将以下情况作为 Critical 依据(这是方案审查阶段的正常状态,不构成方案缺陷):
|
|
12
|
+
- "代码库尚未实现该方案条目"
|
|
13
|
+
- "`tasks.md` 中某任务未勾选"
|
|
14
|
+
- 任何形式的"这段还没写代码/还没跑起来/还没测试通过"
|
|
15
|
+
- 若你倾向于报告上述类型的问题,先自问:"这是文档本身的逻辑缺陷,还是仅仅因为实施还没开始/没完成?" 后者不报。
|
|
16
|
+
|
|
17
|
+
## Review Checklist(聚焦方案文档本身的逻辑缺陷)
|
|
18
|
+
|
|
19
|
+
### 遗漏与边界
|
|
20
|
+
- [ ] 是否遗漏关键边界情况(并发、失败路径、空输入、权限边界等)
|
|
21
|
+
- [ ] 范围(Impact/Capabilities)是否清晰,是否有遗漏的受影响文件/能力
|
|
22
|
+
|
|
23
|
+
### 文档一致性
|
|
24
|
+
- [ ] `proposal.md`/`design.md`/`tasks.md`/对应 spec 之间是否互相矛盾或脱节
|
|
25
|
+
- [ ] `proposal.md` 的 What Changes 里提到的行为,是否在对应的 spec delta(`specs/**/*.md`)里有对应的 Requirement/Scenario 覆盖——**这是本角色的核心职责之一**:你会收到该 change 的全部 delta spec 文件内容,逐条核对 proposal 的每一项 What Changes 是否能在 spec 里找到对应条目;找不到时才报 Critical,不要因为"spec 写得简略"就报,要确认是"完全未覆盖"
|
|
26
|
+
- [ ] **区分两种"该 change 没有 delta spec 文件"的情形**:(a)`proposal.md` 的 Capabilities 段落中 New/Modified Capabilities 均为空(纯重构/工具/文档类变更)——没有 delta spec 属于正常情况,不报 Critical;(b)Capabilities 段落声明了至少一个 New/Modified Capability,但该 change 目录下完全没有任何 delta spec 文件——必须报 Critical(`openspec validate`/`openspec archive` 只校验"该 change 的 delta 总数是否为 0",不会逐个核对 proposal 声明的每个 capability 是否都有对应 delta spec,也不检查 `skip_specs` 是否被误用,这是唯一能捕捉这类问题的检查点)。判断依据是 proposal 的 Capabilities 段落本身声明了什么,不是"有没有 spec 文件"这个表面现象。
|
|
27
|
+
- [ ] `tasks.md` 的任务拆解是否覆盖了 proposal/design 里描述的全部改动点(拆解不全 ≠ 未实现,是文档本身遗漏了该写的任务)
|
|
28
|
+
|
|
29
|
+
### 风险与决策
|
|
30
|
+
- [ ] 风险点(Risks/Trade-offs)交代是否清晰、是否有明显遗漏
|
|
31
|
+
- [ ] 需要人工决策的开放问题是否已经标注,而不是被隐藏
|
|
32
|
+
|
|
33
|
+
## Response Structure
|
|
34
|
+
|
|
35
|
+
按严重度分三级输出:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
## Critical
|
|
39
|
+
1. [文件相对路径:章节/条目] — <问题描述>
|
|
40
|
+
建议: <具体建议>
|
|
41
|
+
|
|
42
|
+
## Warning
|
|
43
|
+
1. [文件相对路径:章节/条目] — <问题描述>
|
|
44
|
+
建议: <具体建议>
|
|
45
|
+
|
|
46
|
+
## Info
|
|
47
|
+
1. [文件相对路径:章节/条目] — <观察/建议>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
每条发现的"位置"字段必须给出至少一个相对 `WORKDIR` 的可解析文件路径(不能只给章节名而不带文件路径)。若某条发现是跨文件或范围性问题(不存在单一目标文件,例如"proposal 与 tasks 整体范围不一致"),必须列出全部相关文件的路径,不能只取其中一个。
|
|
51
|
+
|
|
52
|
+
若没有任何发现,明确写"未发现问题",不要保持沉默、也不要为了有话说而硬凑 Critical。
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Codex Role: Code Reviewer
|
|
2
|
+
|
|
3
|
+
You are a senior code reviewer specializing in backend code quality, security, and best practices.
|
|
4
|
+
|
|
5
|
+
## CRITICAL CONSTRAINTS
|
|
6
|
+
|
|
7
|
+
- **ZERO file system write permission** - READ-ONLY sandbox
|
|
8
|
+
- **OUTPUT FORMAT**: Structured review with scores (for bugfix validation)
|
|
9
|
+
- **Focus**: Quality, security, performance, maintainability
|
|
10
|
+
|
|
11
|
+
## Review Checklist
|
|
12
|
+
|
|
13
|
+
### Security (Critical)
|
|
14
|
+
- [ ] Input validation and sanitization
|
|
15
|
+
- [ ] SQL injection / command injection prevention
|
|
16
|
+
- [ ] Secrets/credentials not hardcoded
|
|
17
|
+
- [ ] Authentication/authorization checks
|
|
18
|
+
- [ ] Logging without sensitive data exposure
|
|
19
|
+
|
|
20
|
+
### Code Quality
|
|
21
|
+
- [ ] Proper error handling with meaningful messages
|
|
22
|
+
- [ ] No code duplication
|
|
23
|
+
- [ ] Clear naming conventions
|
|
24
|
+
- [ ] Single responsibility principle
|
|
25
|
+
- [ ] Appropriate abstraction level
|
|
26
|
+
|
|
27
|
+
### Performance
|
|
28
|
+
- [ ] Database query efficiency (N+1 problems)
|
|
29
|
+
- [ ] Proper indexing usage
|
|
30
|
+
- [ ] Caching where appropriate
|
|
31
|
+
- [ ] No unnecessary computations
|
|
32
|
+
|
|
33
|
+
### Reliability
|
|
34
|
+
- [ ] Race conditions and concurrency issues
|
|
35
|
+
- [ ] Edge cases handled
|
|
36
|
+
- [ ] Graceful error recovery
|
|
37
|
+
- [ ] Idempotency where needed
|
|
38
|
+
|
|
39
|
+
## Response Structure
|
|
40
|
+
|
|
41
|
+
按严重度分三级输出:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
## Critical
|
|
45
|
+
1. [文件相对路径:行号/函数名] — <问题描述>
|
|
46
|
+
建议: <具体建议>
|
|
47
|
+
|
|
48
|
+
## Warning
|
|
49
|
+
1. [文件相对路径:行号/函数名] — <问题描述>
|
|
50
|
+
建议: <具体建议>
|
|
51
|
+
|
|
52
|
+
## Info
|
|
53
|
+
1. [文件相对路径:行号/函数名] — <观察/建议>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
每条发现的"位置"字段必须给出至少一个相对 `WORKDIR` 的可解析文件路径(不能只给函数名/行号而不带文件路径)。若某条发现涉及跨文件问题(不存在单一目标文件,例如"A 文件的调用方式与 B 文件的签名不一致"),必须列出全部相关文件的路径,不能只给其中一个。
|
|
57
|
+
|
|
58
|
+
若没有任何发现,明确写"未发现问题",不要保持沉默、也不要为了有话说而硬凑 Critical。
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyx-apply
|
|
3
|
+
description: 'coding subagent 实施 tasks(subagent 多 Agent 模式):主会话 spawn coding subagent(fork 当前会话上下文 + 只实施 change 范围),逐任务实施+验证+勾选;结论与改动回传主会话,由主会话确认后统一提交 apply: <change-name>;失败原样呈报转人工(不重试不兜底)'
|
|
4
|
+
argument-hint: '[<change-name>]'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Apply
|
|
8
|
+
|
|
9
|
+
> 调用方式:`@lyx-apply` mention 后跟随的自然语言即参数(如 `@lyx-apply` 带需求描述/选项);无参数时直接 `@lyx-apply`。
|
|
10
|
+
|
|
11
|
+
实施环节由 **coding subagent** 执行(subagent 多 Agent 模式):主会话 spawn 一个 coding subagent,fork 当前会话上下文并在任务中点名"只实施 change 范围";coding subagent 读取 tasks.md 逐任务实施 + 验证 + 勾选后,将改动与结果**回传主会话,不自行 commit**——`apply: <change-name>` 由主会话确认后统一提交,作为 `@lyx-review-code` 的审查对象。失败区分两阶段:**环境级不可用**(宿主无 subagent 能力、初始 spawn 失败)按回退口径回退当前会话直接实施,SHALL NOT 视为业务失败;**实施中/验证失败** SHALL 原样呈报转人工,不自动重试、不切回自实施、不自动兜底。隔离 worktree 的询问/新建统一收敛到 `@lyx-propose` 入口,apply 不触发任何 worktree 询问、不做隔离检测——直接在当前工作目录实施。
|
|
12
|
+
|
|
13
|
+
## 步骤
|
|
14
|
+
|
|
15
|
+
### 1. 确定目标 change 名
|
|
16
|
+
|
|
17
|
+
按固定优先级解析:
|
|
18
|
+
|
|
19
|
+
1. `参数` 中显式且合法的 change 名。
|
|
20
|
+
2. `openspec/changes/` 下唯一未归档的 change。
|
|
21
|
+
3. 无法唯一确定 → 直接询问用户。
|
|
22
|
+
|
|
23
|
+
任一步骤无法唯一确定时,不得继续执行后续步骤。
|
|
24
|
+
|
|
25
|
+
### 2. spawn coding subagent 实施 tasks
|
|
26
|
+
|
|
27
|
+
主会话 spawn 一个 coding subagent(由运行环境的宿主 spawn 能力落实),并给它下述任务指示:
|
|
28
|
+
|
|
29
|
+
1. **模型** = `~/.ly/config.toml` 的 `[codexHost] codingModel`;未配置或空白 → 继承当前会话模型。模型指定只写在任务指示里,由宿主 spawn 能力执行,SHALL NOT 依赖任何 shell 层模型参数。
|
|
30
|
+
2. **fork 当前会话上下文**:coding subagent 以当前会话(含 propose 阶段上下文)fork 启动——关键决策、取舍、已知边界等"软上下文"随 fork 到达实施模型。
|
|
31
|
+
3. **范围点名(只实施 change 范围)**:任务点名"只实施 change 范围"——读取 `openspec/changes/<change-name>/tasks.md`,按需读取同目录 `proposal.md`/`design.md` 及任务引用的上下文文件,理解现有模式;SHALL NOT 改动范围外文件。
|
|
32
|
+
4. **实施规范**(coding subagent 内部执行):
|
|
33
|
+
- 自顶向下逐任务实施,每完成一个任务立即验证:只修改任务列出的文件,不添加任务之外的功能/重构/注释;按 tasks.md 指定的验证方式运行验证(如 typecheck/build/test),失败则修复后重试,每个任务最多 3 次修复尝试;验证通过后,把 tasks.md 中对应条目从 `- [ ]` 改为 `- [x]`,继续下一个任务。
|
|
34
|
+
- 不询问——任务描述有歧义时按最简方案处理,直接落地并在回传结果中说明选择。
|
|
35
|
+
5. **回传不 commit**:coding subagent SHALL NOT 自行执行任何 git commit——实施完成后,将实际改动的文件清单、验证结果与逐任务完成情况回传主会话。
|
|
36
|
+
|
|
37
|
+
**环境级不可用回退**:若当前环境无 subagent spawn 能力或初始 spawn 失败,主会话回退为当前会话直接实施(实施规范同上),并如实报告"已回退,原因:subagent 不可用"——该回退 SHALL NOT 视为业务失败。
|
|
38
|
+
|
|
39
|
+
### 3. 主会话确认并统一提交(全部任务完成时执行)
|
|
40
|
+
|
|
41
|
+
1. 主会话收到 coding subagent 回传的改动与结果后确认;确认时先检查 `git status --porcelain`:若实施前已存在与本次无关的预存改动,`git add` 范围仅限本次实际改动的文件,SHALL NOT 将预存改动一并暂存/提交,并在报告中说明"预存改动未被提交"。
|
|
42
|
+
2. `git add` 本次实际改动的文件后立即 `git commit -m "apply: <change-name>"`。
|
|
43
|
+
3. `apply: <change-name>` commit 即 `@lyx-review-code` 的审查对象。
|
|
44
|
+
4. 无可提交内容(如 tasks 本身无产出、或改动已在审查循环中被提交)则跳过,不创建空 commit。
|
|
45
|
+
5. 若 `git commit` 失败,如实报告 Git 返回的原始错误,不重试不兜底。
|
|
46
|
+
|
|
47
|
+
### 失败处理(未全部完成时执行)
|
|
48
|
+
|
|
49
|
+
**实施中/验证失败**(coding subagent 报告任务未完成或验证失败):主会话原样呈报失败详情转人工,不自动重试、不切回自实施、不 commit、不自动兜底。列出 tasks.md 中仍未勾选的条目,停止执行;改动可能已部分落地在工作区,保留原状,由用户决定后续处理。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyx-archive
|
|
3
|
+
description: '按 opsx:archive 编排流程归档完成的 change,完成后 commit'
|
|
4
|
+
argument-hint: '[<change-name>]'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Archive
|
|
8
|
+
|
|
9
|
+
> 调用方式:`@lyx-archive` mention 后跟随的自然语言即参数(如 `@lyx-archive` 带需求描述/选项);无参数时直接 `@lyx-archive`。
|
|
10
|
+
|
|
11
|
+
按 `@openspec-archive-change skill`(opsx archive 编排 prompt)定义的流程归档指定 change(`参数` 未指定时按 opsx:archive 流程的默认规则确定目标)。
|
|
12
|
+
|
|
13
|
+
## 提交归档改动
|
|
14
|
+
|
|
15
|
+
归档会把 `openspec/changes/<change-name>/` 移动到 `openspec/changes/archive/`,并可能同步更新 `openspec/specs/`。提交涉及的全部文件:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git add -- openspec/
|
|
19
|
+
git commit -m "archive: <change-name>"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
若无可提交内容或 `git commit` 失败,跳过提交,如实报告原始错误,不视为归档失败。
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyx-changelog
|
|
3
|
+
description: 'Keep a Changelog 格式生成 CHANGELOG.md:按 commit 前缀自动分组(Added/Fixed/Changed)'
|
|
4
|
+
argument-hint: '[<版本号>]'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Changelog - 生成 CHANGELOG.md
|
|
8
|
+
|
|
9
|
+
> 调用方式:`@lyx-changelog` mention 后跟随的自然语言即参数(如 `@lyx-changelog` 带需求描述/选项);无参数时直接 `@lyx-changelog`。
|
|
10
|
+
|
|
11
|
+
按 [Keep a Changelog](https://keepachangelog.com) 规范生成/更新 CHANGELOG.md,按 commit 类型分组而非简单罗列 commit message。
|
|
12
|
+
|
|
13
|
+
## 使用方法
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
@lyx-changelog
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
告诉 Codex 要为哪次更新生成 changelog(通常是发版时),自动执行以下步骤。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 步骤一:检查 CHANGELOG 是否存在
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ls CHANGELOG* 2>/dev/null
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **不存在**:询问用户是否需要创建。需要则新建 `CHANGELOG.md`,按下方格式写入首条记录。
|
|
30
|
+
- **存在**:进入步骤二,追加到顶部(保留已有内容,不覆盖历史记录)。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 步骤二:确定上一版本边界
|
|
35
|
+
|
|
36
|
+
优先级从高到低尝试,找到即用,不需要全部执行:
|
|
37
|
+
|
|
38
|
+
**方式 A:git tag**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**方式 B:找上一次改动 `version.sh` 中 VERSION 的 commit**(项目无 tag 时常见)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
PREV_COMMIT=$(git log -2 --format=%H -- version.sh | tail -1)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**方式 C:找上一次改动 `package.json` 中 version 字段的 commit**(Node 项目)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
PREV_COMMIT=$(git log -2 -p --format=%H -- package.json | grep -B5 '"version"' | grep '^[0-9a-f]\{40\}$' | tail -1)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
三种方式取到的边界二选一(哪个存在用哪个,version.sh/package.json 优先于 tag,因为 tag 可能未及时打;实际在方式 A 中 `HEAD^` 已保证取到的是上一个 tag):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
BASE_REF=${PREV_TAG:-${PREV_COMMIT:-}}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 步骤三:收集并分类本次更新的 commit
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# 有边界:收集区间内 commit
|
|
68
|
+
if [ -n "$BASE_REF" ]; then
|
|
69
|
+
RAW=$(git log ${BASE_REF}..HEAD --oneline --no-merges -- | grep -v "bump version")
|
|
70
|
+
else
|
|
71
|
+
RAW=$(git log HEAD --oneline --no-merges -- | grep -v "bump version")
|
|
72
|
+
fi
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 分类规则(Conventional Commits → Keep a Changelog 分组)
|
|
76
|
+
|
|
77
|
+
| commit 前缀 | 分组 |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `feat:`(非 `feat!:`) | **Added** |
|
|
80
|
+
| `fix:` | **Fixed** |
|
|
81
|
+
| `feat!:` 或 body 含 `BREAKING CHANGE:` | **Changed**(标 BREAKING) |
|
|
82
|
+
| `docs:` | **Changed** |
|
|
83
|
+
| `refactor:` / `perf:` / `style:` | **Changed** |
|
|
84
|
+
| `chore:` / `ci:` / `build:` | **Changed** |
|
|
85
|
+
| `revert:` | **Changed** |
|
|
86
|
+
| `test:` | **Changed** |
|
|
87
|
+
| 其他 / 无法识别 | **Changed** |
|
|
88
|
+
|
|
89
|
+
### 分组收集命令
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Added:feat: 开头的 commit(排除 feat!:)
|
|
93
|
+
echo "$RAW" | grep "^[a-f0-9]* feat" | grep -v "feat!:" | grep -v "BREAKING" || true
|
|
94
|
+
|
|
95
|
+
# Fixed:fix: 开头的 commit
|
|
96
|
+
echo "$RAW" | grep "^[a-f0-9]* fix" || true
|
|
97
|
+
|
|
98
|
+
# Changed:其余所有 commit
|
|
99
|
+
echo "$RAW" | grep -v "^[a-f0-9]* feat" | grep -v "^[a-f0-9]* fix" || true
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 步骤四:写入 CHANGELOG.md(Keep a Changelog 格式)
|
|
105
|
+
|
|
106
|
+
在文件顶部插入(保留已有内容,不覆盖历史记录):
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
## [<版本号>] - <日期>
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
- <feat commit 摘要 1>
|
|
113
|
+
- <feat commit 摘要 2>
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
- <fix commit 摘要 1>
|
|
117
|
+
|
|
118
|
+
### Changed
|
|
119
|
+
- <其他 commit 摘要 1>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**格式约定:**
|
|
123
|
+
|
|
124
|
+
- 版本号:`[X.Y.Z]` 方括号包裹,与本次发版的版本号一致
|
|
125
|
+
- 日期:`YYYY-MM-DD`
|
|
126
|
+
- 分组标题按 Keep a Changelog 规范:`Added`(新增功能)、`Fixed`(修复)、`Changed`(其他变更)
|
|
127
|
+
- 没有对应 commit 的分组**省略不写**(如本次无 `feat:` 则不出 `### Added` 段落)
|
|
128
|
+
- 每条去掉 hash,仅保留 message 原文(不改写内容,只分组)
|
|
129
|
+
- 含 `BREAKING CHANGE:` 的条目末尾标注 `**BREAKING**`
|
|
130
|
+
|
|
131
|
+
### 边界处理
|
|
132
|
+
|
|
133
|
+
- **commit 区间为空**(上次 bump 后无 commit):报告 "no commits since last version",不生成版本段落
|
|
134
|
+
- **同一版本号已存在**:警告并询问是覆盖还是跳过
|
|
135
|
+
- **无 CHANGELOG.md**:创建新文件,新条目作为首个版本
|
|
136
|
+
|
|
137
|
+
### 示例输出
|
|
138
|
+
|
|
139
|
+
```markdown
|
|
140
|
+
## [2.0.0] - 2026-09-02
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
- 新增 SemVer 自动推导版本号规则
|
|
144
|
+
- 版本号确认改为建议+确认模式
|
|
145
|
+
|
|
146
|
+
### Fixed
|
|
147
|
+
- 修复 hotfix 场景下版本号漏 bump 的问题
|
|
148
|
+
|
|
149
|
+
### Changed
|
|
150
|
+
- docs: 更新 AGENTS.md 发版规则说明
|
|
151
|
+
- refactor: 统一版本号读取逻辑
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 步骤五:提交变更
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
git add CHANGELOG.md
|
|
160
|
+
git commit -m "docs: update CHANGELOG for v<版本号>"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
**注意:** 本命令只负责生成/更新 CHANGELOG 内容,不负责版本号修改、分支操作、PR 创建——那些属于 `@lyx-release` 的职责。发版流程中,先由 release 完成版本号 bump commit,再触发本命令生成 CHANGELOG。
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyx-clean-branches
|
|
3
|
+
description: '清理 Git 分支:安全清理已合并或过期分支,默认 dry-run 模式'
|
|
4
|
+
argument-hint: '[--stale <days>] [--remote] [--dry-run]'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Clean-Branches - 清理 Git 分支
|
|
8
|
+
|
|
9
|
+
> 调用方式:`@lyx-clean-branches` mention 后跟随的自然语言即参数(如 `@lyx-clean-branches` 带需求描述/选项);无参数时直接 `@lyx-clean-branches`。
|
|
10
|
+
|
|
11
|
+
安全识别并清理已合并或长期未更新的分支。
|
|
12
|
+
|
|
13
|
+
## 使用方法
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
@lyx-clean-branches [options]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 选项
|
|
20
|
+
|
|
21
|
+
| 选项 | 说明 |
|
|
22
|
+
|------|------|
|
|
23
|
+
| `--base <branch>` | 基准分支(默认 main/master) |
|
|
24
|
+
| `--stale <days>` | 清理超过 N 天未更新的分支 |
|
|
25
|
+
| `--remote` | 同时清理远程分支 |
|
|
26
|
+
| `--dry-run` | 只预览,不执行(**默认**) |
|
|
27
|
+
| `--yes` | 跳过确认直接删除 |
|
|
28
|
+
| `--force` | 强制删除未合并分支 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 执行工作流
|
|
33
|
+
|
|
34
|
+
### 🔍 阶段 1:预检
|
|
35
|
+
|
|
36
|
+
`[模式:准备]`
|
|
37
|
+
|
|
38
|
+
1. 同步远端:`git fetch --all --prune`
|
|
39
|
+
2. 读取保护分支配置
|
|
40
|
+
3. 确定基准分支
|
|
41
|
+
|
|
42
|
+
### 📋 阶段 2:分析识别
|
|
43
|
+
|
|
44
|
+
`[模式:分析]`
|
|
45
|
+
|
|
46
|
+
**已合并分支**:
|
|
47
|
+
- 已完全合并到 `--base` 的分支
|
|
48
|
+
|
|
49
|
+
**过期分支**(如指定 `--stale`):
|
|
50
|
+
- 最后提交在 N 天前的分支
|
|
51
|
+
|
|
52
|
+
**排除**:
|
|
53
|
+
- 从待清理列表中移除保护分支
|
|
54
|
+
|
|
55
|
+
### 📊 阶段 3:报告预览
|
|
56
|
+
|
|
57
|
+
`[模式:报告]`
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
## 将要删除的分支
|
|
61
|
+
|
|
62
|
+
### 已合并分支
|
|
63
|
+
- feature/old-feature (合并于 3 天前)
|
|
64
|
+
- bugfix/fixed-issue (合并于 7 天前)
|
|
65
|
+
|
|
66
|
+
### 过期分支
|
|
67
|
+
- experiment/old-test (最后更新 90 天前)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### ✅ 阶段 4:执行清理
|
|
71
|
+
|
|
72
|
+
`[模式:执行]`
|
|
73
|
+
|
|
74
|
+
仅在不带 `--dry-run` 且确认后执行:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 本地分支
|
|
78
|
+
git branch -d <branch>
|
|
79
|
+
|
|
80
|
+
# 远程分支(如果 --remote)
|
|
81
|
+
git push origin --delete <branch>
|
|
82
|
+
|
|
83
|
+
# 强制删除(如果 --force)
|
|
84
|
+
git branch -D <branch>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 保护分支配置
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# 添加保护分支
|
|
93
|
+
git config --add branch.cleanup.protected develop
|
|
94
|
+
git config --add branch.cleanup.protected 'release/*'
|
|
95
|
+
|
|
96
|
+
# 查看保护分支
|
|
97
|
+
git config --get-all branch.cleanup.protected
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 示例
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 预览将清理的分支
|
|
106
|
+
@lyx-clean-branches --dry-run
|
|
107
|
+
|
|
108
|
+
# 清理已合并且超过 90 天未动的分支
|
|
109
|
+
@lyx-clean-branches --stale 90
|
|
110
|
+
|
|
111
|
+
# 清理已合并到 release/v2.1 的分支
|
|
112
|
+
@lyx-clean-branches --base release/v2.1 --remote --yes
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 最佳实践
|
|
116
|
+
|
|
117
|
+
1. **优先 dry-run** – 先预览再执行
|
|
118
|
+
2. **活用 --base** – 适配 release 工作流
|
|
119
|
+
3. **谨慎 --force** – 除非确定无用
|
|
120
|
+
4. **团队协作** – 清理远程分支前先通知
|
|
121
|
+
5. **定期运行** – 每月/季度一次保持清爽
|