@pennixrv/trellis 0.7.0-beta.46 → 0.7.0-beta.48
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/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/backup.d.ts +20 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +122 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/channel/rm.d.ts.map +1 -1
- package/dist/commands/channel/rm.js +203 -91
- package/dist/commands/channel/rm.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +10 -4
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/workflow.js +1 -1
- package/dist/commands/workflow.js.map +1 -1
- package/dist/migrations/manifests/0.7.0-beta.47.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.48.json +9 -0
- package/dist/templates/codex/hooks/session-start.py +6 -6
- package/dist/templates/copilot/hooks/session-start.py +6 -6
- package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/backend/error-handling.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/index.md.txt +19 -19
- package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +25 -25
- package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/index.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/state-management.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/type-safety.md.txt +22 -22
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +80 -85
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +164 -209
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +161 -185
- package/dist/templates/markdown/spec/guides/index.md.txt +51 -51
- package/dist/templates/markdown/workspace-index.md +44 -44
- package/dist/templates/opencode/lib/session-utils.js +2 -2
- package/dist/templates/shared-hooks/session-start.py +7 -7
- package/dist/templates/trellis/scripts/add_session.py +35 -32
- package/dist/templates/trellis/scripts/common/developer.py +18 -18
- package/dist/templates/trellis/scripts/common/task_store.py +11 -11
- package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -3
- package/dist/templates/trellis/workflow.md +403 -458
- package/package.json +2 -2
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
# Thinking Guides
|
|
1
|
+
# 思考指南(Thinking Guides)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **目的(Purpose)**:扩展思考,发现可能遗漏的因素。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Why Thinking Guides
|
|
7
|
+
## 为什么需要思考指南(Why Thinking Guides?)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**大多数错误和技术债务来自“没有想到”,而不是能力不足:**
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
- 没有思考层边界会发生什么 → 出现跨层错误
|
|
12
|
+
- 没有注意代码模式重复 → 到处产生重复代码
|
|
13
|
+
- 没有考虑边界情况 → 出现运行时错误
|
|
14
|
+
- 没有考虑未来维护者 → 代码难以阅读
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
这些指南帮助你在编码前**提出正确的问题**。
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Available Guides
|
|
20
|
+
## 可用指南(Available Guides)
|
|
21
21
|
|
|
22
|
-
| Guide | Purpose | When to Use |
|
|
22
|
+
| 指南(Guide) | 目的(Purpose) | 使用时机(When to Use) |
|
|
23
23
|
|-------|---------|-------------|
|
|
24
|
-
| [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md) |
|
|
25
|
-
| [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md) |
|
|
24
|
+
| [代码复用思考指南(Code Reuse Thinking Guide)](./code-reuse-thinking-guide.md) | 识别模式并减少重复 | 发现重复模式时 |
|
|
25
|
+
| [跨层思考指南(Cross-Layer Thinking Guide)](./cross-layer-thinking-guide.md) | 梳理跨层数据流 | 功能跨越多个层时 |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## Quick Reference: Thinking Triggers
|
|
29
|
+
## 快速参考:思考触发条件(Quick Reference: Thinking Triggers)
|
|
30
30
|
|
|
31
|
-
### When to Think About Cross-Layer Issues
|
|
31
|
+
### 何时思考跨层问题(When to Think About Cross-Layer Issues)
|
|
32
32
|
|
|
33
|
-
- [ ]
|
|
34
|
-
- [ ]
|
|
35
|
-
- [ ]
|
|
36
|
-
- [ ]
|
|
37
|
-
- [ ]
|
|
38
|
-
- [ ] UI
|
|
33
|
+
- [ ] 功能涉及三个或更多层(API、Service、Component、Database)
|
|
34
|
+
- [ ] 数据格式在层之间发生变化
|
|
35
|
+
- [ ] 多个消费者需要同一份数据
|
|
36
|
+
- [ ] 不确定某段逻辑应放在哪里
|
|
37
|
+
- [ ] 正在增加事件类型、JSONL 记录、RPC 载荷或配置字段
|
|
38
|
+
- [ ] UI/命令代码开始直接断言原始载荷字段
|
|
39
39
|
|
|
40
|
-
→
|
|
40
|
+
→ 阅读 [跨层思考指南(Cross-Layer Thinking Guide)](./cross-layer-thinking-guide.md)
|
|
41
41
|
|
|
42
|
-
### When to Think About Code Reuse
|
|
42
|
+
### 何时思考代码复用(When to Think About Code Reuse)
|
|
43
43
|
|
|
44
|
-
- [ ]
|
|
45
|
-
- [ ]
|
|
46
|
-
- [ ]
|
|
47
|
-
- [ ]
|
|
48
|
-
- [ ]
|
|
49
|
-
- [ ]
|
|
50
|
-
- [ ]
|
|
44
|
+
- [ ] 正在编写与已有代码相似的代码
|
|
45
|
+
- [ ] 看到同一模式重复三次或更多
|
|
46
|
+
- [ ] 正在多个位置增加新字段
|
|
47
|
+
- [ ] **正在修改任意常量或配置**
|
|
48
|
+
- [ ] **正在创建新的工具/辅助函数** ← 先搜索!
|
|
49
|
+
- [ ] 两个文件使用本地断言读取同一个无类型载荷字段
|
|
50
|
+
- [ ] 多个分支根据 `kind` / `action` 更新同一派生状态
|
|
51
51
|
|
|
52
|
-
→
|
|
52
|
+
→ 阅读 [代码复用思考指南(Code Reuse Thinking Guide)](./code-reuse-thinking-guide.md)
|
|
53
53
|
|
|
54
|
-
### When Verifying AI Cross-Review Results
|
|
54
|
+
### 核验 AI 交叉审查结果时(When Verifying AI Cross-Review Results)
|
|
55
55
|
|
|
56
|
-
- [ ]
|
|
57
|
-
- [ ]
|
|
58
|
-
- [ ]
|
|
59
|
-
- [ ]
|
|
56
|
+
- [ ] 审查者声称“用户输入可能恶意” → 检查实际数据来源(内部 manifest?用户配置?外部 API?)
|
|
57
|
+
- [ ] 审查者指出“缺少校验” → 数据是否来自可信内部来源?
|
|
58
|
+
- [ ] 审查者说“行为发生变化” → 阅读代码注释,确认是否属于有意设计。
|
|
59
|
+
- [ ] 审查者在测试中指出“错误” → 在脑中删除被测功能,测试是否仍然通过?如果是 → 这是同义反复测试
|
|
60
60
|
|
|
61
|
-
**
|
|
62
|
-
1.
|
|
63
|
-
2.
|
|
64
|
-
3.
|
|
61
|
+
**AI 审查者常见的误报模式**:
|
|
62
|
+
1. **信任边界混淆**:将内部数据(打包的 JSON manifest)当作不可信外部输入
|
|
63
|
+
2. **忽略设计注释**:将代码注释中记录的有意行为标记为错误
|
|
64
|
+
3. **误读变量**:不追踪变量的实际定义(例如 Map 以路径而不是名称为键)
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
**核验规则**:每个 CRITICAL/WARNING 发现都必须对照实际代码核验后再排序。
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
|
-
## Pre-Modification Rule
|
|
70
|
+
## 修改前规则(Pre-Modification Rule,CRITICAL)
|
|
71
71
|
|
|
72
|
-
>
|
|
72
|
+
> **修改任何值之前,始终先搜索!**
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
75
|
# Search for the value you're about to change
|
|
76
76
|
grep -r "value_to_change" .
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
这一习惯可以预防大多数“忘记更新 X”的错误。
|
|
80
80
|
|
|
81
81
|
---
|
|
82
82
|
|
|
83
|
-
## How to Use This Directory
|
|
83
|
+
## 如何使用本目录(How to Use This Directory)
|
|
84
84
|
|
|
85
|
-
1.
|
|
86
|
-
2.
|
|
87
|
-
3.
|
|
85
|
+
1. **编码前**:浏览相关思考指南
|
|
86
|
+
2. **编码中**:如果某处感觉重复或复杂,查阅这些指南
|
|
87
|
+
3. **出现错误后**:将新经验加入相关指南,从错误中学习
|
|
88
88
|
|
|
89
89
|
---
|
|
90
90
|
|
|
91
|
-
## Contributing
|
|
91
|
+
## 贡献(Contributing)
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
发现新的“没有想到”时刻?将它加入相关指南。
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
**核心原则(Core Principle)**:30 分钟的思考可以节省 3 小时的调试时间。
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# Workspace Index
|
|
1
|
+
# 工作区索引(Workspace Index)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 记录所有开发者的 AI Agent 工作记录。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Overview
|
|
7
|
+
## 概览(Overview)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
本目录跟踪本项目所有使用 AI Agent 的开发者记录。
|
|
10
10
|
|
|
11
|
-
### File Structure
|
|
11
|
+
### 文件结构(File Structure)
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
workspace/
|
|
@@ -23,98 +23,98 @@ workspace/
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
## Active Developers
|
|
26
|
+
## 活跃开发者(Active Developers)
|
|
27
27
|
|
|
28
|
-
| Developer | Last Active | Sessions | Active File |
|
|
28
|
+
| 开发者(Developer) | 最近活动(Last Active) | 会话(Sessions) | 活动文件(Active File) |
|
|
29
29
|
|-----------|-------------|----------|-------------|
|
|
30
|
-
|
|
|
30
|
+
| (暂无) | - | - | - |
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
## Getting Started
|
|
34
|
+
## 开始使用(Getting Started)
|
|
35
35
|
|
|
36
|
-
### For New Developers
|
|
36
|
+
### 新开发者(For New Developers)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
运行初始化脚本:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
python3 ./.trellis/scripts/init_developer.py <your-name>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
1.
|
|
46
|
-
2.
|
|
47
|
-
3.
|
|
48
|
-
4.
|
|
44
|
+
此命令将:
|
|
45
|
+
1. 创建身份文件(由 git 忽略)
|
|
46
|
+
2. 创建进度目录
|
|
47
|
+
3. 创建个人索引
|
|
48
|
+
4. 创建初始日志文件
|
|
49
49
|
|
|
50
|
-
### For Returning Developers
|
|
50
|
+
### 已有开发者(For Returning Developers)
|
|
51
51
|
|
|
52
|
-
1.
|
|
52
|
+
1. 获取开发者名称:
|
|
53
53
|
```bash
|
|
54
54
|
python3 ./.trellis/scripts/get_developer.py
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
2.
|
|
57
|
+
2. 阅读个人索引:
|
|
58
58
|
```bash
|
|
59
59
|
cat .trellis/workspace/$(python3 ./.trellis/scripts/get_developer.py)/index.md
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
---
|
|
63
63
|
|
|
64
|
-
## Guidelines
|
|
64
|
+
## 指南(Guidelines)
|
|
65
65
|
|
|
66
|
-
### Journal File Rules
|
|
66
|
+
### 日志文件规则(Journal File Rules)
|
|
67
67
|
|
|
68
|
-
- **
|
|
69
|
-
-
|
|
70
|
-
-
|
|
68
|
+
- 每个日志文件最多 **2000 行**
|
|
69
|
+
- 达到上限后创建 `journal-{N+1}.md`
|
|
70
|
+
- 创建新文件时更新个人 `index.md`
|
|
71
71
|
|
|
72
|
-
### Session Record Format
|
|
72
|
+
### 会话记录格式(Session Record Format)
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
- Summary
|
|
76
|
-
- Branch
|
|
77
|
-
- Main Changes
|
|
78
|
-
- Git Commits
|
|
79
|
-
- Next Steps
|
|
74
|
+
每个会话应包含:
|
|
75
|
+
- 摘要(Summary):一行描述
|
|
76
|
+
- 分支(Branch):工作的分支
|
|
77
|
+
- 主要变更(Main Changes):修改内容
|
|
78
|
+
- Git 提交(Git Commits):提交哈希和消息
|
|
79
|
+
- 下一步(Next Steps):后续工作
|
|
80
80
|
|
|
81
81
|
---
|
|
82
82
|
|
|
83
|
-
## Session Template
|
|
83
|
+
## 会话模板(Session Template)
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
记录会话时使用以下模板:
|
|
86
86
|
|
|
87
87
|
```markdown
|
|
88
|
-
## Session {N}
|
|
88
|
+
## 会话(Session) {N}:{Title}
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
**日期(Date)**: YYYY-MM-DD
|
|
91
|
+
**任务(Task)**: {task-name}
|
|
92
|
+
**分支(Branch)**: `{branch-name}`
|
|
93
93
|
|
|
94
|
-
### Summary
|
|
94
|
+
### 摘要(Summary)
|
|
95
95
|
|
|
96
96
|
{One-line summary}
|
|
97
97
|
|
|
98
|
-
### Main Changes
|
|
98
|
+
### 主要变更(Main Changes)
|
|
99
99
|
|
|
100
100
|
- {Change 1}
|
|
101
101
|
- {Change 2}
|
|
102
102
|
|
|
103
|
-
### Git Commits
|
|
103
|
+
### Git 提交(Git Commits)
|
|
104
104
|
|
|
105
105
|
| Hash | Message |
|
|
106
106
|
|------|---------|
|
|
107
107
|
| `abc1234` | {commit message} |
|
|
108
108
|
|
|
109
|
-
### Testing
|
|
109
|
+
### 测试(Testing)
|
|
110
110
|
|
|
111
111
|
- [OK] {Test result}
|
|
112
112
|
|
|
113
|
-
### Status
|
|
113
|
+
### 状态(Status)
|
|
114
114
|
|
|
115
115
|
[OK] **Completed** / # **In Progress** / [P] **Blocked**
|
|
116
116
|
|
|
117
|
-
### Next Steps
|
|
117
|
+
### 下一步(Next Steps)
|
|
118
118
|
|
|
119
119
|
- {Next step 1}
|
|
120
120
|
- {Next step 2}
|
|
@@ -122,4 +122,4 @@ Use this template when recording sessions:
|
|
|
122
122
|
|
|
123
123
|
---
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
**语言(Language)**:所有文档默认使用**简体中文**。
|
|
@@ -402,9 +402,9 @@ Trellis compact SessionStart context. Use it to orient the session; load details
|
|
|
402
402
|
let rangeEnd = allLines.length
|
|
403
403
|
for (let i = 0; i < allLines.length; i++) {
|
|
404
404
|
const stripped = allLines[i].trim()
|
|
405
|
-
if (rangeStart === -1 && stripped === "## Phase Index") {
|
|
405
|
+
if (rangeStart === -1 && (stripped === "## 阶段索引(Phase Index)" || stripped === "## Phase Index")) {
|
|
406
406
|
rangeStart = i
|
|
407
|
-
} else if (rangeStart !== -1 && stripped === "## Phase 1: Plan") {
|
|
407
|
+
} else if (rangeStart !== -1 && (stripped === "## 阶段一:规划(Phase 1: Plan)" || stripped === "## Phase 1: Plan")) {
|
|
408
408
|
rangeEnd = i
|
|
409
409
|
break
|
|
410
410
|
}
|
|
@@ -754,24 +754,24 @@ def _build_compact_current_state(
|
|
|
754
754
|
return "\n".join(lines)
|
|
755
755
|
|
|
756
756
|
|
|
757
|
-
def _extract_range(content: str, start_header: str, end_header: str) -> str:
|
|
757
|
+
def _extract_range(content: str, start_header: tuple[str, ...], end_header: tuple[str, ...]) -> str:
|
|
758
758
|
"""Extract lines starting at `## start_header` up to (but excluding) `## end_header`.
|
|
759
759
|
|
|
760
|
-
|
|
760
|
+
Parameters contain accepted full header lines WITHOUT the `## ` prefix.
|
|
761
761
|
Returns empty string if start header is not found.
|
|
762
762
|
End header missing → extracts to end of file.
|
|
763
763
|
"""
|
|
764
764
|
lines = content.splitlines()
|
|
765
765
|
start: int | None = None
|
|
766
766
|
end: int = len(lines)
|
|
767
|
-
|
|
768
|
-
|
|
767
|
+
start_matches = {f"## {header}" for header in start_header}
|
|
768
|
+
end_matches = {f"## {header}" for header in end_header}
|
|
769
769
|
for i, line in enumerate(lines):
|
|
770
770
|
stripped = line.strip()
|
|
771
|
-
if start is None and stripped
|
|
771
|
+
if start is None and stripped in start_matches:
|
|
772
772
|
start = i
|
|
773
773
|
continue
|
|
774
|
-
if start is not None and stripped
|
|
774
|
+
if start is not None and stripped in end_matches:
|
|
775
775
|
end = i
|
|
776
776
|
break
|
|
777
777
|
if start is None:
|
|
@@ -833,7 +833,7 @@ def _build_workflow_overview(workflow_path: Path) -> str:
|
|
|
833
833
|
"",
|
|
834
834
|
]
|
|
835
835
|
|
|
836
|
-
phases = _extract_range(content, "Phase Index", "Phase 1: Plan")
|
|
836
|
+
phases = _extract_range(content, ("阶段索引(Phase Index)", "Phase Index"), ("阶段一:规划(Phase 1: Plan)", "Phase 1: Plan"))
|
|
837
837
|
if phases:
|
|
838
838
|
out_lines.append(_strip_breadcrumb_tag_blocks(phases).rstrip())
|
|
839
839
|
|
|
@@ -97,8 +97,8 @@ MARKER_PREFIX = "<!-- trellis-session:"
|
|
|
97
97
|
# fingerprint mixed in the calendar date; see compute_record_fingerprint.
|
|
98
98
|
MARKER_VERSION = 2
|
|
99
99
|
LEGACY_MARKER_RE = re.compile(r"^<!-- trellis-session: fp=([0-9a-f]{16}) -->$")
|
|
100
|
-
ENTRY_DATE_RE = re.compile(r"^\*\*Date\*\*: (\d{4}-\d{2}-\d{2})\s*$")
|
|
101
|
-
SESSION_HEADING_RE = re.compile(r"^## Session (\d+)
|
|
100
|
+
ENTRY_DATE_RE = re.compile(r"^\*\*(?:Date|日期(Date))\*\*: (\d{4}-\d{2}-\d{2})\s*$")
|
|
101
|
+
SESSION_HEADING_RE = re.compile(r"^## (?:Session|会话(Session)) (\d+)(?::|:)", re.MULTILINE)
|
|
102
102
|
|
|
103
103
|
# Recording states, in the order the operation walks them.
|
|
104
104
|
STATE_ABSENT = "absent"
|
|
@@ -170,7 +170,7 @@ def _max_session_in_index(content: str) -> int:
|
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def _max_session_in_journal(content: str) -> int:
|
|
173
|
-
"""Highest
|
|
173
|
+
"""Highest old or new session heading in a journal body (0 when none)."""
|
|
174
174
|
numbers = [int(m.group(1)) for m in SESSION_HEADING_RE.finditer(content)]
|
|
175
175
|
return max(numbers) if numbers else 0
|
|
176
176
|
|
|
@@ -195,7 +195,7 @@ def count_journal_files(dev_dir: Path, active_num: int) -> str:
|
|
|
195
195
|
for f in files:
|
|
196
196
|
filename = f.name
|
|
197
197
|
lines = len(f.read_text(encoding="utf-8").splitlines())
|
|
198
|
-
status = "Active" if filename == active_file else "Archived"
|
|
198
|
+
status = "活动(Active)" if filename == active_file else "归档(Archived)"
|
|
199
199
|
result_lines.append(f"| `{filename}` | ~{lines} | {status} |")
|
|
200
200
|
|
|
201
201
|
return "\n".join(result_lines)
|
|
@@ -301,10 +301,10 @@ def create_new_journal_file(
|
|
|
301
301
|
prev_num = num - 1
|
|
302
302
|
new_file = dev_dir / f"{FILE_JOURNAL_PREFIX}{num}.md"
|
|
303
303
|
|
|
304
|
-
content = f"""# Journal
|
|
304
|
+
content = f"""# 日志(Journal)- {developer}(第 {num} 部分)
|
|
305
305
|
|
|
306
|
-
>
|
|
307
|
-
> Started
|
|
306
|
+
> 续接自 `{FILE_JOURNAL_PREFIX}{prev_num}.md`(约 {max_lines} 行时归档)
|
|
307
|
+
> 开始日期(Started): {today}
|
|
308
308
|
|
|
309
309
|
---
|
|
310
310
|
|
|
@@ -615,7 +615,7 @@ def _max_session_across_refs(repo_root: Path, refs: list[str], dev_rel: str) ->
|
|
|
615
615
|
"-h",
|
|
616
616
|
"-E",
|
|
617
617
|
"-e",
|
|
618
|
-
r"^## Session [0-9]
|
|
618
|
+
r"^## (Session [0-9]+:|会话(Session) [0-9]+:)",
|
|
619
619
|
"-e",
|
|
620
620
|
r"Total Sessions",
|
|
621
621
|
]
|
|
@@ -629,7 +629,7 @@ def _max_session_across_refs(repo_root: Path, refs: list[str], dev_rel: str) ->
|
|
|
629
629
|
|
|
630
630
|
# `git grep` prefixes each hit with `<rev>:<path>:`, so the numbers are
|
|
631
631
|
# matched anywhere in the line rather than anchored.
|
|
632
|
-
numbers = [int(m.group(1)) for m in re.finditer(r"## Session (\d+)
|
|
632
|
+
numbers = [int(m.group(1)) for m in re.finditer(r"## (?:Session|会话(Session)) (\d+)(?::|:)", out)]
|
|
633
633
|
numbers += [
|
|
634
634
|
int(m.group(1)) for m in re.finditer(r"Total Sessions[^\d]{0,8}(\d+)", out)
|
|
635
635
|
]
|
|
@@ -843,7 +843,7 @@ def classify_record(
|
|
|
843
843
|
if session_num is None:
|
|
844
844
|
return "", None, None, (
|
|
845
845
|
f"{journal_file.name} carries this record's marker without a "
|
|
846
|
-
"
|
|
846
|
+
"session heading above it. The pending record is malformed; "
|
|
847
847
|
"repair it by hand before retrying."
|
|
848
848
|
)
|
|
849
849
|
|
|
@@ -884,9 +884,9 @@ def _render_bullet_section(header: str, items: list[str], bullet_prefix: str = "
|
|
|
884
884
|
def _render_main_changes(changes: list[str], extra_content: str | None) -> str:
|
|
885
885
|
"""Render the Main Changes section from --change bullets or freeform content."""
|
|
886
886
|
if changes:
|
|
887
|
-
return _render_bullet_section("Main Changes", changes)
|
|
887
|
+
return _render_bullet_section("主要变更(Main Changes)", changes)
|
|
888
888
|
if extra_content:
|
|
889
|
-
return f"\n\n### Main Changes
|
|
889
|
+
return f"\n\n### 主要变更(Main Changes)\n\n{extra_content}"
|
|
890
890
|
return ""
|
|
891
891
|
|
|
892
892
|
|
|
@@ -906,39 +906,39 @@ def generate_session_content(
|
|
|
906
906
|
) -> str:
|
|
907
907
|
"""Generate session content."""
|
|
908
908
|
if evidence:
|
|
909
|
-
commit_table = """| Hash | Message |
|
|
909
|
+
commit_table = """| 哈希(Hash) | 消息(Message) |
|
|
910
910
|
|------|---------|"""
|
|
911
911
|
for oid, subject in evidence:
|
|
912
912
|
commit_table += f"\n| `{oid}` | {escape_markdown_cell(subject)} |"
|
|
913
913
|
else:
|
|
914
|
-
commit_table = "
|
|
914
|
+
commit_table = "(无提交——规划会话)"
|
|
915
915
|
|
|
916
|
-
package_line = f"\n
|
|
917
|
-
branch_line = f"\n
|
|
916
|
+
package_line = f"\n**包(Package)**: {package}" if package else ""
|
|
917
|
+
branch_line = f"\n**分支(Branch)**: `{branch}`" if branch else ""
|
|
918
918
|
|
|
919
919
|
main_changes_section = _render_main_changes(changes or [], extra_content)
|
|
920
|
-
testing_section = _render_bullet_section("Testing", tests or [], bullet_prefix="- [OK] ")
|
|
921
|
-
next_steps_section = _render_bullet_section("Next Steps", next_steps or [])
|
|
920
|
+
testing_section = _render_bullet_section("测试(Testing)", tests or [], bullet_prefix="- [OK] ")
|
|
921
|
+
next_steps_section = _render_bullet_section("下一步(Next Steps)", next_steps or [])
|
|
922
922
|
|
|
923
923
|
return f"""
|
|
924
924
|
|
|
925
|
-
## Session {session_num}
|
|
925
|
+
## 会话(Session) {session_num}:{title}
|
|
926
926
|
{marker}
|
|
927
927
|
|
|
928
|
-
|
|
929
|
-
|
|
928
|
+
**日期(Date)**: {today}
|
|
929
|
+
**任务(Task)**: {title}{package_line}{branch_line}
|
|
930
930
|
|
|
931
|
-
### Summary
|
|
931
|
+
### 摘要(Summary)
|
|
932
932
|
|
|
933
933
|
{summary}{main_changes_section}
|
|
934
934
|
|
|
935
|
-
### Git Commits
|
|
935
|
+
### Git 提交(Git Commits)
|
|
936
936
|
|
|
937
937
|
{commit_table}{testing_section}
|
|
938
938
|
|
|
939
|
-
### Status
|
|
939
|
+
### 状态(Status)
|
|
940
940
|
|
|
941
|
-
[OK]
|
|
941
|
+
[OK] **已完成(Completed)**{next_steps_section}
|
|
942
942
|
"""
|
|
943
943
|
|
|
944
944
|
|
|
@@ -992,9 +992,9 @@ def update_index(
|
|
|
992
992
|
if "@@@auto:current-status" in line:
|
|
993
993
|
new_lines.append(line)
|
|
994
994
|
in_current_status = True
|
|
995
|
-
new_lines.append(f"-
|
|
996
|
-
new_lines.append(f"-
|
|
997
|
-
new_lines.append(f"-
|
|
995
|
+
new_lines.append(f"- **活动文件(Active File)**: `{active_file}`")
|
|
996
|
+
new_lines.append(f"- **会话总数(Total Sessions)**: {new_session}")
|
|
997
|
+
new_lines.append(f"- **最近活动(Last Active)**: {today}")
|
|
998
998
|
continue
|
|
999
999
|
|
|
1000
1000
|
if "@@@/auto:current-status" in line:
|
|
@@ -1005,7 +1005,7 @@ def update_index(
|
|
|
1005
1005
|
if "@@@auto:active-documents" in line:
|
|
1006
1006
|
new_lines.append(line)
|
|
1007
1007
|
in_active_documents = True
|
|
1008
|
-
new_lines.append("| File | Lines | Status |")
|
|
1008
|
+
new_lines.append("| 文件(File) | 行数(Lines) | 状态(Status) |")
|
|
1009
1009
|
new_lines.append("|------|-------|--------|")
|
|
1010
1010
|
new_lines.append(files_table)
|
|
1011
1011
|
continue
|
|
@@ -1038,13 +1038,16 @@ def update_index(
|
|
|
1038
1038
|
r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*Branch\s*\|\s*Base Branch\s*\|\s*$",
|
|
1039
1039
|
line,
|
|
1040
1040
|
):
|
|
1041
|
-
new_lines.append("| # | Date | Title | Commits | Branch |")
|
|
1041
|
+
new_lines.append("| # | 日期(Date) | 标题(Title) | 提交(Commits) | 分支(Branch) |")
|
|
1042
1042
|
continue
|
|
1043
1043
|
if re.match(r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*Branch\s*\|\s*$", line):
|
|
1044
|
-
new_lines.append("| # | Date | Title | Commits | Branch |")
|
|
1044
|
+
new_lines.append("| # | 日期(Date) | 标题(Title) | 提交(Commits) | 分支(Branch) |")
|
|
1045
|
+
continue
|
|
1046
|
+
if re.match(r"^\|\s*#\s*\|\s*日期(Date)\s*\|\s*标题(Title)\s*\|\s*提交(Commits)\s*\|\s*分支(Branch)\s*\|\s*$", line):
|
|
1047
|
+
new_lines.append("| # | 日期(Date) | 标题(Title) | 提交(Commits) | 分支(Branch) |")
|
|
1045
1048
|
continue
|
|
1046
1049
|
if re.match(r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*$", line):
|
|
1047
|
-
new_lines.append("| # | Date | Title | Commits | Branch |")
|
|
1050
|
+
new_lines.append("| # | 日期(Date) | 标题(Title) | 提交(Commits) | 分支(Branch) |")
|
|
1048
1051
|
continue
|
|
1049
1052
|
if re.match(r"^\|[-| ]+\|\s*$", line) and not header_written:
|
|
1050
1053
|
new_lines.append("|---|------|-------|---------|--------|")
|
|
@@ -78,10 +78,10 @@ def init_developer(name: str, repo_root: Path | None = None) -> bool:
|
|
|
78
78
|
journal_file = workspace_dir / f"{FILE_JOURNAL_PREFIX}1.md"
|
|
79
79
|
if not journal_file.exists():
|
|
80
80
|
today = datetime.now().strftime("%Y-%m-%d")
|
|
81
|
-
journal_content = f"""# Journal
|
|
81
|
+
journal_content = f"""# 日志(Journal)- {name}(第 1 部分)
|
|
82
82
|
|
|
83
|
-
> AI
|
|
84
|
-
> Started
|
|
83
|
+
> AI 开发会话日志
|
|
84
|
+
> 开始日期(Started): {today}
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
@@ -95,46 +95,46 @@ def init_developer(name: str, repo_root: Path | None = None) -> bool:
|
|
|
95
95
|
# Create index.md with markers for auto-update
|
|
96
96
|
index_file = workspace_dir / "index.md"
|
|
97
97
|
if not index_file.exists():
|
|
98
|
-
index_content = f"""# Workspace Index
|
|
98
|
+
index_content = f"""# 工作区索引(Workspace Index)- {name}
|
|
99
99
|
|
|
100
|
-
>
|
|
100
|
+
> AI 开发会话跟踪日志。
|
|
101
101
|
|
|
102
102
|
---
|
|
103
103
|
|
|
104
|
-
## Current Status
|
|
104
|
+
## 当前状态(Current Status)
|
|
105
105
|
|
|
106
106
|
<!-- @@@auto:current-status -->
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
107
|
+
- **活动文件(Active File)**: `journal-1.md`
|
|
108
|
+
- **会话总数(Total Sessions)**: 0
|
|
109
|
+
- **最近活动(Last Active)**: -
|
|
110
110
|
<!-- @@@/auto:current-status -->
|
|
111
111
|
|
|
112
112
|
---
|
|
113
113
|
|
|
114
|
-
## Active Documents
|
|
114
|
+
## 活动文档(Active Documents)
|
|
115
115
|
|
|
116
116
|
<!-- @@@auto:active-documents -->
|
|
117
|
-
| File | Lines | Status |
|
|
117
|
+
| 文件(File) | 行数(Lines) | 状态(Status) |
|
|
118
118
|
|------|-------|--------|
|
|
119
|
-
| `journal-1.md` | ~0 | Active |
|
|
119
|
+
| `journal-1.md` | ~0 | 活动(Active) |
|
|
120
120
|
<!-- @@@/auto:active-documents -->
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
|
124
|
-
## Session History
|
|
124
|
+
## 会话历史(Session History)
|
|
125
125
|
|
|
126
126
|
<!-- @@@auto:session-history -->
|
|
127
|
-
| # | Date | Title | Commits | Branch |
|
|
127
|
+
| # | 日期(Date) | 标题(Title) | 提交(Commits) | 分支(Branch) |
|
|
128
128
|
|---|------|-------|---------|--------|
|
|
129
129
|
<!-- @@@/auto:session-history -->
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
-
## Notes
|
|
133
|
+
## 备注(Notes)
|
|
134
134
|
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
135
|
+
- 会话会追加到日志文件
|
|
136
|
+
- 当前日志超过 2000 行时创建新的日志文件
|
|
137
|
+
- 使用 `add_session.py` 记录会话
|
|
138
138
|
"""
|
|
139
139
|
try:
|
|
140
140
|
index_file.write_text(index_content, encoding="utf-8")
|
|
@@ -306,27 +306,27 @@ def _parse_meta_pairs(pairs: list[str] | None) -> dict[str, str] | None:
|
|
|
306
306
|
|
|
307
307
|
def _default_prd_content(title: str, description: str | None = None) -> str:
|
|
308
308
|
"""Return the default PRD skeleton created with every task."""
|
|
309
|
-
goal = (description or "").strip() or "
|
|
310
|
-
heading = title.strip() or "
|
|
309
|
+
goal = (description or "").strip() or "待填写。"
|
|
310
|
+
heading = title.strip() or "未命名任务"
|
|
311
311
|
return f"""# {heading}
|
|
312
312
|
|
|
313
|
-
## Goal
|
|
313
|
+
## 目标(Goal)
|
|
314
314
|
|
|
315
315
|
{goal}
|
|
316
316
|
|
|
317
|
-
## Requirements
|
|
317
|
+
## 需求(Requirements)
|
|
318
318
|
|
|
319
|
-
-
|
|
319
|
+
- 待填写
|
|
320
320
|
|
|
321
|
-
## Acceptance Criteria
|
|
321
|
+
## 验收标准(Acceptance Criteria)
|
|
322
322
|
|
|
323
|
-
- [ ]
|
|
323
|
+
- [ ] 待填写
|
|
324
324
|
|
|
325
|
-
## Notes
|
|
325
|
+
## 备注(Notes)
|
|
326
326
|
|
|
327
|
-
-
|
|
328
|
-
-
|
|
329
|
-
-
|
|
327
|
+
- 让 `prd.md` 聚焦需求、约束和验收标准。
|
|
328
|
+
- 轻量任务可以只保留 PRD。
|
|
329
|
+
- 复杂任务在 `task.py start` 前增加 `design.md` 记录技术设计,增加 `implement.md` 记录执行计划。
|
|
330
330
|
"""
|
|
331
331
|
|
|
332
332
|
|