specline 1.4.0 → 2.0.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.
Files changed (75) hide show
  1. package/README.md +132 -125
  2. package/adapters/claude/deploy.json +12 -0
  3. package/adapters/claude/hooks/hooks.json +12 -0
  4. package/adapters/claude/hooks.json +12 -0
  5. package/adapters/claude/orchestration.md +17 -0
  6. package/adapters/codex/agent.toml.hbs +7 -0
  7. package/adapters/codex/deploy.json +12 -0
  8. package/adapters/codex/hooks.json +12 -0
  9. package/adapters/codex/orchestration.md +18 -0
  10. package/adapters/cursor/deploy.json +12 -0
  11. package/adapters/cursor/hooks.json +9 -0
  12. package/adapters/cursor/orchestration.md +17 -0
  13. package/adapters/opencode/deploy.json +12 -0
  14. package/adapters/opencode/orchestration.md +18 -0
  15. package/adapters/opencode/plugin.js +10 -0
  16. package/cli.mjs +161 -558
  17. package/core/agents/specline-backend-dev.yaml +45 -0
  18. package/core/agents/specline-code-reviewer.yaml +67 -0
  19. package/core/agents/specline-config-dev.yaml +50 -0
  20. package/core/agents/specline-config-reviewer.yaml +70 -0
  21. package/core/agents/specline-explore-assistant.yaml +79 -0
  22. package/core/agents/specline-frontend-dev.yaml +45 -0
  23. package/core/agents/specline-spec-creator.yaml +58 -0
  24. package/core/agents/specline-spec-reviewer.yaml +58 -0
  25. package/core/agents/specline-test-runner.yaml +62 -0
  26. package/core/agents/specline-test-writer.yaml +67 -0
  27. package/core/bootstrap/using-specline.md +14 -0
  28. package/core/gates/pipeline-gate-checks/a1-covers-ref.sh +125 -0
  29. package/core/gates/pipeline-gate-checks/a2-a3-reverse.sh +171 -0
  30. package/core/gates/pipeline-gate-checks/c1-exception.sh +71 -0
  31. package/core/gates/pipeline-gate-checks/c2-vague.sh +60 -0
  32. package/core/gates/pipeline-gate-checks/common.sh +68 -0
  33. package/core/gates/pipeline-gate-checks/d1-cycle.sh +149 -0
  34. package/core/gates/pipeline-gate-checks/d3-type-file.sh +260 -0
  35. package/core/gates/pipeline-gate.sh +1456 -0
  36. package/core/hooks/session-start.sh +259 -0
  37. package/core/skills/specline-apply-change/SKILL.md +197 -0
  38. package/core/skills/specline-archive-change/SKILL.md +173 -0
  39. package/core/skills/specline-explore/SKILL.md +504 -0
  40. package/core/skills/specline-knowledge/SKILL.md +539 -0
  41. package/core/skills/specline-pipeline/SKILL.md +604 -0
  42. package/core/skills/specline-pipeline/references/error-recovery-details.md +49 -0
  43. package/core/skills/specline-pipeline/references/event-log-spec.md +59 -0
  44. package/core/skills/specline-pipeline/references/pipeline-state-schema.md +87 -0
  45. package/core/skills/specline-pipeline/templates/subagent-prompts.md +397 -0
  46. package/core/skills/specline-propose/SKILL.md +186 -0
  47. package/core/skills/specline-quickfix/SKILL.md +289 -0
  48. package/core/templates/AGENTS.md.hbs +5 -0
  49. package/core/templates/specline/config.yaml +15 -0
  50. package/lib/deploy-claude.mjs +80 -0
  51. package/lib/deploy-codex.mjs +77 -0
  52. package/lib/deploy-opencode.mjs +93 -0
  53. package/lib/deploy.mjs +668 -0
  54. package/lib/gate.mjs +103 -0
  55. package/lib/hash.mjs +13 -0
  56. package/lib/hook.mjs +105 -0
  57. package/lib/init.mjs +122 -0
  58. package/lib/lock.mjs +99 -0
  59. package/lib/merge.mjs +184 -0
  60. package/lib/paths.mjs +40 -0
  61. package/lib/platforms.mjs +74 -0
  62. package/lib/render-agents.mjs +88 -0
  63. package/lib/render.mjs +126 -0
  64. package/lib/sync.mjs +253 -0
  65. package/lib/tty-select.mjs +89 -0
  66. package/package.json +4 -1
  67. package/templates/.cursor/README.md +18 -0
  68. package/templates/.cursor/agents/specline-code-reviewer.md +18 -2
  69. package/templates/.cursor/agents/specline-spec-creator.md +51 -2
  70. package/templates/.cursor/agents/specline-test-runner.md +10 -1
  71. package/templates/.cursor/agents/specline-test-writer.md +58 -7
  72. package/templates/.cursor/hooks/specline-pipeline-gate-checks/a2-a3-reverse.sh +1 -1
  73. package/templates/.cursor/hooks/specline-pipeline-gate.sh +118 -0
  74. package/templates/.cursor/skills/specline-pipeline/SKILL.md +10 -4
  75. package/templates/.cursor/skills/specline-propose/SKILL.md +3 -3
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env bash
2
+ # specline-session-start.sh — sessionStart Hook (Pipeline Session Binding)
3
+ #
4
+ # 新会话启动时:
5
+ # 1. 清理过期绑定(7 天未更新)
6
+ # 2. 检查当前 session 是否已有绑定
7
+ # 3. 有绑定且 pipeline 仍活跃 → 使用已有绑定,注入上下文
8
+ # 4. 有绑定但 pipeline 已失效 → 清理脏数据,重新扫描
9
+ # 5. 无绑定 → 透明放行(echo '{}')——不自动绑定,避免跨窗口污染
10
+ #
11
+ # Input (stdin JSON):
12
+ # { "session_id": "...", "is_background_agent": bool, ... }
13
+ #
14
+ # Output (stdout JSON):
15
+ # { "additional_context": "<pipeline 上下文>" } 或 {}(无活跃 pipeline)
16
+
17
+ set -euo pipefail
18
+
19
+ # ============================================================================
20
+ # Input
21
+ # ============================================================================
22
+
23
+ input=$(cat)
24
+
25
+ # 跳过 background agent(子 Agent 不需要 pipeline 上下文)
26
+ is_bg=$(echo "$input" | jq -r '.is_background_agent // false')
27
+ if [ "$is_bg" = "true" ]; then
28
+ echo '{}'
29
+ exit 0
30
+ fi
31
+
32
+ session_id=$(echo "$input" | jq -r '.session_id // empty')
33
+ if [ -z "$session_id" ]; then
34
+ echo '{}'
35
+ exit 0
36
+ fi
37
+
38
+ # ============================================================================
39
+ # Paths
40
+ # ============================================================================
41
+
42
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
43
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
44
+ BINDINGS_FILE="$PROJECT_ROOT/specline/.pipeline-sessions.json"
45
+ CHANGES_DIR="$PROJECT_ROOT/specline/changes"
46
+
47
+ # ============================================================================
48
+ # Helper Functions
49
+ # ============================================================================
50
+
51
+ # init_bindings_file — ensure bindings file exists with a valid JSON object
52
+ init_bindings_file() {
53
+ if [ ! -f "$BINDINGS_FILE" ]; then
54
+ mkdir -p "$(dirname "$BINDINGS_FILE")"
55
+ echo '{}' > "$BINDINGS_FILE"
56
+ fi
57
+
58
+ # Validate it's readable JSON; reset if corrupted
59
+ if ! jq empty "$BINDINGS_FILE" 2>/dev/null; then
60
+ echo '{}' > "$BINDINGS_FILE"
61
+ fi
62
+ }
63
+
64
+ # clean_expired_bindings — remove bindings where bound_at > 7 days ago
65
+ # Uses ISO-8601 lexical comparison: works on both macOS and Linux
66
+ clean_expired_bindings() {
67
+ [ -f "$BINDINGS_FILE" ] || return 0
68
+
69
+ local cutoff_date
70
+ # macOS date, fallback to Linux date
71
+ cutoff_date=$(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || \
72
+ date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null)
73
+
74
+ if [ -z "$cutoff_date" ]; then
75
+ return 0 # Cannot determine cutoff, skip cleanup
76
+ fi
77
+
78
+ local tmp_file="${BINDINGS_FILE}.tmp"
79
+ # Keep only entries whose bound_at is >= cutoff (i.e. within the last 7 days)
80
+ jq --arg cutoff "$cutoff_date" \
81
+ 'with_entries(select(.value.bound_at >= $cutoff))' \
82
+ "$BINDINGS_FILE" > "$tmp_file" 2>/dev/null && \
83
+ mv "$tmp_file" "$BINDINGS_FILE" 2>/dev/null || true
84
+ }
85
+
86
+ # is_pipeline_active — check if a pipeline's state file exists and is not archived
87
+ # Returns 0 (active) or 1 (inactive)
88
+ is_pipeline_active() {
89
+ local change_name="$1"
90
+ local state_file="$CHANGES_DIR/$change_name/.pipeline-state.json"
91
+
92
+ [ -f "$state_file" ] || return 1
93
+
94
+ local phase
95
+ phase=$(jq -r '.current_phase // "unknown"' "$state_file" 2>/dev/null)
96
+ [ "$phase" != "archive" ] || return 1
97
+
98
+ return 0
99
+ }
100
+
101
+ # scan_active_pipelines — scan changes/ (excluding archive/) for active pipelines
102
+ # Output: one line per pipeline: change_name|phase|state_file_path
103
+ scan_active_pipelines() {
104
+ if [ ! -d "$CHANGES_DIR" ]; then
105
+ return 0
106
+ fi
107
+
108
+ for state_file in "$CHANGES_DIR"/*/.pipeline-state.json; do
109
+ [ -f "$state_file" ] || continue
110
+
111
+ # Exclude archive/
112
+ case "$state_file" in
113
+ */archive/*) continue ;;
114
+ esac
115
+
116
+ local change_name phase
117
+ change_name=$(jq -r '.change_name // ""' "$state_file" 2>/dev/null)
118
+ phase=$(jq -r '.current_phase // ""' "$state_file" 2>/dev/null)
119
+
120
+ [ -n "$change_name" ] || continue
121
+ [ "$phase" != "archive" ] || continue
122
+
123
+ printf '%s|%s|%s\n' "$change_name" "$phase" "$state_file"
124
+ done
125
+ }
126
+
127
+ # phase_constraints — output constraint text for a given phase (to stdout)
128
+ phase_constraints() {
129
+ local phase="$1"
130
+ case "$phase" in
131
+ spec)
132
+ printf '%s\n' "- 只能通过 specline-spec-creator / specline-spec-reviewer 子 Agent 工作"
133
+ printf '%s\n' "- 禁止编辑任何应用代码文件(.ts/.tsx/.py/.go 等)"
134
+ printf '%s\n' "- 规划文件生成后需运行 Spec Gate"
135
+ ;;
136
+ coding)
137
+ printf '%s\n' "- 编码必须通过子 Agent:specline-frontend-dev / specline-backend-dev / specline-config-dev"
138
+ printf '%s\n' "- 禁止直接编辑应用代码文件"
139
+ printf '%s\n' "- 每批次任务完成后运行 Build Gate"
140
+ printf '%s\n' "- 每个 Task 完成后更新 tasks.md 的 checkbox"
141
+ ;;
142
+ code_review)
143
+ printf '%s\n' "- 只能运行 specline-code-reviewer + Lint Gate"
144
+ printf '%s\n' "- 如需修复代码,通过子 Agent 完成"
145
+ ;;
146
+ test)
147
+ printf '%s\n' "- 运行测试 Gate 链:unit → integration → e2e"
148
+ printf '%s\n' "- 测试失败时通过 specline-test-runner 分析原因"
149
+ printf '%s\n' "- 代码修复通过子 Agent,测试修复通过 specline-test-writer"
150
+ ;;
151
+ *)
152
+ printf '%s\n' "- 遵循 specline-pipeline SKILL 的当前阶段约束"
153
+ ;;
154
+ esac
155
+ }
156
+
157
+ # build_context — generate a JSON-escaped additional_context string for a bound pipeline
158
+ build_context() {
159
+ local change_name="$1"
160
+ local phase="$2"
161
+ local state_file="$3"
162
+
163
+ {
164
+ printf '🚨 **Specline Pipeline 运行中**\n\n'
165
+ printf '**当前变更**: %s\n' "$change_name"
166
+ printf '**当前阶段**: %s\n' "$phase"
167
+
168
+ # Task progress for coding phase
169
+ if [ "$phase" = "coding" ] && [ -f "$state_file" ]; then
170
+ local completed total
171
+ completed=$(jq -r '[.phases.coding.tasks[]? | select(.status == "completed")] | length' "$state_file" 2>/dev/null || printf '0')
172
+ total=$(jq -r '[.phases.coding.tasks[]?] | length' "$state_file" 2>/dev/null || printf '0')
173
+ if [ "$total" != "0" ]; then
174
+ printf '**任务进度**: %s/%s 完成\n' "$completed" "$total"
175
+ fi
176
+ fi
177
+
178
+ printf '\n**阶段约束**:\n'
179
+ phase_constraints "$phase"
180
+ printf '\n'
181
+ printf '**重要**: 你是 Specline Pipeline 编排者。上述约束具有最高优先级,必须在每个操作前检查是否符合当前阶段要求。'
182
+ } | jq -Rs '.'
183
+ }
184
+
185
+ # phase_constraint_table — static phase constraint reference table (markdown)
186
+ phase_constraint_table() {
187
+ cat << 'TABLEEOF'
188
+ | 阶段 | 约束 |
189
+ |------|------|
190
+ | spec | 只能通过 specline-spec-creator/specline-spec-reviewer 子 Agent 工作,禁止编辑代码 |
191
+ | coding | 必须通过子 Agent 编码,批次完成后运行 Build Gate,更新 tasks.md |
192
+ | code_review | 只能运行 specline-code-reviewer + Lint Gate |
193
+ | test | 运行测试 Gate 链:unit → integration → e2e |
194
+ TABLEEOF
195
+ }
196
+
197
+ # write_binding — write a session_id → change_name binding to .pipeline-sessions.json
198
+ write_binding() {
199
+ local sid="$1"
200
+ local change="$2"
201
+
202
+ local now_iso
203
+ now_iso=$(date -u +%Y-%m-%dT%H:%M:%SZ)
204
+
205
+ local tmp_file="${BINDINGS_FILE}.tmp"
206
+ jq --arg sid "$sid" --arg change "$change" --arg now "$now_iso" \
207
+ '.[$sid] = {"change": $change, "bound_at": $now}' \
208
+ "$BINDINGS_FILE" > "$tmp_file" 2>/dev/null && \
209
+ mv "$tmp_file" "$BINDINGS_FILE" 2>/dev/null || true
210
+ }
211
+
212
+ # delete_binding — remove a session_id entry from .pipeline-sessions.json
213
+ delete_binding() {
214
+ local session_id="$1"
215
+
216
+ [ -f "$BINDINGS_FILE" ] || return 0
217
+
218
+ local tmp_file="${BINDINGS_FILE}.tmp"
219
+ jq --arg sid "$session_id" 'del(.[$sid])' "$BINDINGS_FILE" > "$tmp_file" 2>/dev/null && \
220
+ mv "$tmp_file" "$BINDINGS_FILE" 2>/dev/null || true
221
+ }
222
+
223
+ # ============================================================================
224
+ # Main Logic
225
+ # ============================================================================
226
+
227
+ init_bindings_file
228
+
229
+ # 1. Clean expired bindings (bound_at > 7 days ago)
230
+ clean_expired_bindings
231
+
232
+ # 2. Check existing binding for this session
233
+ existing_change=""
234
+ if [ -f "$BINDINGS_FILE" ]; then
235
+ existing_change=$(jq -r --arg sid "$session_id" '.[$sid].change // empty' "$BINDINGS_FILE" 2>/dev/null)
236
+ fi
237
+
238
+ if [ -n "$existing_change" ]; then
239
+ if is_pipeline_active "$existing_change"; then
240
+ # Binding is still valid — use it
241
+ state_file="$CHANGES_DIR/$existing_change/.pipeline-state.json"
242
+ phase=$(jq -r '.current_phase // "unknown"' "$state_file" 2>/dev/null)
243
+
244
+ ctx_json=$(build_context "$existing_change" "$phase" "$state_file")
245
+
246
+ printf '{\n "additional_context": %s\n}\n' "$ctx_json"
247
+ exit 0
248
+ else
249
+ # Dirty data: pipeline archived or deleted — clean up and rescan
250
+ delete_binding "$session_id"
251
+ fi
252
+ fi
253
+
254
+
255
+ # 3. No (valid) binding → transparent pass-through
256
+ # 不再自动绑定或注入任何 pipeline 上下文,避免跨窗口污染。
257
+ # 用户需通过 /specline-pipeline --change <name> 显式绑定。
258
+ echo '{}'
259
+ exit 0
@@ -0,0 +1,197 @@
1
+ ---
2
+ name: specline-apply-change
3
+ description: Implement tasks from a Specline change. Use when the user wants to start implementing, continue implementation, or work through tasks.
4
+ license: MIT
5
+ compatibility: Compatible with specline.
6
+ metadata:
7
+ author: specline
8
+ version: "1.0"
9
+ generatedBy: "1.3.1"
10
+ ---
11
+
12
+ Implement tasks from a Specline change.
13
+
14
+ **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
15
+
16
+ ## 速览 (Layer 1)
17
+
18
+ > **一句话**:实现 Specline change 中的编码任务。
19
+ > **入口**:`/specline-apply-change [change-name]` 或直接说「继续实现」
20
+ > **流程**:选 change → 读上下文 → 逐任务实现 → 标记完成
21
+
22
+ > ⚠️ **人机门禁策略感知**:当调用方传递了 `HUMAN_GATE_POLICY=minimal` 或 `HUMAN_GATE_POLICY=none` 上下文时,本 Skill 内所有的 {{CONFIRM}} 交互应自动采用默认安全选项:
23
+ > - change 选择 → 若上下文中已有 change name,直接使用;否则取第一个活跃 change
24
+ > - 其他 {{CONFIRM}} 交互 → 自动采用默认安全选项继续,不暂停等待人工输入
25
+
26
+ **Fluid Workflow Integration**
27
+
28
+ This skill supports the "actions on a change" model:
29
+ - **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions
30
+ - **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly
31
+
32
+ **开始前请确认:**
33
+ - [ ] Change 已选中(`/specline-pipeline --change <name>`)
34
+ - [ ] 已读取 proposal.md(知道做什么)
35
+ - [ ] 已读取 spec.md(知道需求和场景)
36
+ - [ ] 已读取 design.md(知道技术决策)
37
+ - [ ] 已读取 tasks.md(知道实现清单)
38
+
39
+ ## 详细步骤 — Happy Path (Layer 2)
40
+
41
+ **Steps**
42
+
43
+ 1. **Select the change**
44
+
45
+ If a name is provided, use it. Otherwise:
46
+ - Infer from conversation context if the user mentioned a change
47
+ - Auto-select if only one active change exists
48
+ - If ambiguous, run `specline gate list --json` to get available changes and use {{CONFIRM}} to let the user select
49
+
50
+ Always announce: "Using change: <name>" and how to override (e.g., `/specline-pipeline --change <other>`).
51
+
52
+ 2. **Check status to understand the schema**
53
+ ```bash
54
+ specline gate artifacts --change "<name>" --json
55
+ ```
56
+ Parse the JSON to understand:
57
+ - `schemaName`: The workflow being used (e.g., "spec-driven")
58
+ - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
59
+
60
+ 3. **Read context files**
61
+
62
+ Read the planning files at `specline/changes/<name>/`:
63
+ - `proposal.md` — what & why
64
+ - `specs/<capability>/spec.md` — requirements & scenarios
65
+ - `design.md` — architecture & decisions
66
+ - `tasks.md` — implementation checklist
67
+
68
+ Check task completion: count `- [ ]` (incomplete) vs `- [x]` (complete).
69
+
70
+ 4. **Show current progress**
71
+
72
+ Display:
73
+ - Progress: "N/M tasks complete"
74
+ - Remaining tasks overview
75
+
76
+ 5. **Implement tasks (loop until done or blocked)**
77
+
78
+ For each pending task:
79
+ - Show which task is being worked on
80
+ - Make the code changes required
81
+ - Keep changes minimal and focused
82
+ - Mark task complete in the tasks file: `- [ ]` → `- [x]`
83
+ - Continue to next task
84
+
85
+ **Pause if:**
86
+ - Task is unclear → ask for clarification
87
+ - Implementation reveals a design issue → suggest updating artifacts
88
+ - Error or blocker encountered → report and wait for guidance
89
+ - User interrupts
90
+
91
+ 6. **On completion or pause, show status**
92
+
93
+ Display:
94
+ - Tasks completed this session
95
+ - Overall progress: "N/M tasks complete"
96
+ - If all done: suggest archive
97
+ - If paused: explain why and wait for guidance
98
+
99
+ ## 输出模板 & 高级话题 (Layer 3)
100
+
101
+ ### 输出模板
102
+
103
+ **Output During Implementation**
104
+
105
+ ```
106
+ ## Implementing: <change-name> (schema: <schema-name>)
107
+
108
+ Working on task 3/7: <task description>
109
+ [...implementation happening...]
110
+ ✓ Task complete
111
+
112
+ Working on task 4/7: <task description>
113
+ [...implementation happening...]
114
+ ✓ Task complete
115
+ ```
116
+
117
+ **Output On Completion**
118
+
119
+ ```
120
+ ## Implementation Complete
121
+
122
+ **Change:** <change-name>
123
+ **Schema:** <schema-name>
124
+ **Progress:** 7/7 tasks complete ✓
125
+
126
+ ### Completed This Session
127
+ - [x] Task 1
128
+ - [x] Task 2
129
+ ...
130
+
131
+ All tasks complete! Ready to archive this change.
132
+ ```
133
+
134
+ **Output On Pause (Issue Encountered)**
135
+
136
+ ```
137
+ ## Implementation Paused
138
+
139
+ **Change:** <change-name>
140
+ **Schema:** <schema-name>
141
+ **Progress:** 4/7 tasks complete
142
+
143
+ ### Issue Encountered
144
+ <description of the issue>
145
+
146
+ **Options:**
147
+ 1. <option 1>
148
+ 2. <option 2>
149
+ 3. Other approach
150
+
151
+ What would you like to do?
152
+ ```
153
+
154
+ ### Guardrails
155
+ - Keep going through tasks until done or blocked
156
+ - Always read context files before starting (from the apply instructions output)
157
+ - If task is ambiguous, pause and ask before implementing
158
+ - If implementation reveals issues, pause and suggest artifact updates
159
+ - Keep code changes minimal and scoped to each task
160
+ - Update task checkbox immediately after completing each task
161
+ - Pause on errors, blockers, or unclear requirements - don't guess
162
+ - Use contextFiles from CLI output, don't assume specific file names
163
+ - **Hook blocked → no silent fallback**: If this skill is invoked because a coding subagent (specline-frontend-dev / specline-backend-dev) was blocked by a hook, you MUST first notify the user of the blocking cause and attempt diagnosis. Do not silently execute tasks that should have been handled by the blocked subagent. Reference the Hook Blocking Resolution Protocol in the specline-pipeline skill.
164
+
165
+ ---
166
+
167
+ ## Anti-Rationalization 表格
168
+
169
+ 逐任务实现时,Agent 容易偏离规范:
170
+
171
+ | 借口 | 现实 |
172
+ |------|------|
173
+ | "不用读 Spec/Design/Tasks,我理解需求" | 记忆不可靠。实现前读上下文文件是防止方向偏离的最便宜保险。 |
174
+ | "顺便把这个相邻函数也重构了" | Scope Discipline 是 Core Behaviors。越界修改让 Code Review 和回溯都变困难。 |
175
+ | "checkbox 我最后一起标记" | Checkbox 是断点续跑的唯一信号源。不及时标记意味着下次恢复时状态丢失。 |
176
+ | "这个任务没有测试也没关系,下一个任务会补" | 每个 Testable=true 的任务必须产出测试。推迟 = 不写。 |
177
+ | "tasks.md 的 Covers 追溯链我不用管,代码写对就行" | Covers 链是 Spec → Code 的可追溯纽带。不维护它,Code Review 和测试失败定位都失去锚点。 |
178
+
179
+ ## Verification Checklist
180
+
181
+ 每完成一个任务后自查,全部完成后终查:
182
+
183
+ - [ ] 开始前已读 proposal.md / spec.md / design.md / tasks.md
184
+ - [ ] 每个任务的实现范围未超出 Files 声明
185
+ - [ ] 每个 Testable=true 的任务产出了测试文件(在 tests/unit/ 或 tests/models/)
186
+ - [ ] tasks.md 中每个已完成任务的 `[ ]` 已改为 `[x]`
187
+ - [ ] task-{id}-result.json 已写入 .tmp/ 目录
188
+ - [ ] 本 session 修改的文件与 tasks.md 的 Files 声明一致
189
+ - [ ] 未修改其他任务负责的文件
190
+
191
+ ### 暂停场景处理
192
+
193
+ 当实现过程中出现以下情况时,暂停并等待用户指引:
194
+ - 任务描述不清晰 → 请求用户澄清
195
+ - 实现中暴露出设计问题 → 建议更新 Artifact(proposal / spec / design / tasks)
196
+ - 遇到错误或阻塞 → 报告具体问题并等待指导
197
+ - 用户主动中断 → 记录当前进度,下次可从断点继续
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: specline-archive-change
3
+ description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
4
+ license: MIT
5
+ compatibility: Compatible with specline.
6
+ metadata:
7
+ author: specline
8
+ version: "1.0"
9
+ generatedBy: "1.3.1"
10
+ ---
11
+
12
+ ## TL;DR (Layer 1)
13
+
14
+ > **一句话**:归档已完成的 Specline change。
15
+ > **入口**:`/specline-archive-change [change-name]`
16
+ > **流程**:选 change → 检查完成度 → Delta spec sync 决策 → 移动目录 → 完成
17
+
18
+ ### 归档前后目录结构变化
19
+
20
+ ```
21
+ 归档前 (活跃、可修改) 归档后 (只读、可追溯)
22
+
23
+ specline/changes/ specline/changes/
24
+ ├── my-change/ ──▶ ├── archive/
25
+ │ ├── proposal.md │ └── 2026-06-01-my-change/
26
+ │ ├── design.md │ ├── proposal.md
27
+ │ ├── tasks.md │ ├── design.md
28
+ │ └── specs/ │ ├── tasks.md
29
+ │ └── specs/
30
+ ```
31
+
32
+ **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
33
+
34
+ ---
35
+
36
+ ## Steps (Layer 2 — Happy Path)
37
+
38
+ 1. **If no change name provided, prompt for selection**
39
+
40
+ Run `specline gate list --json` to get available changes. Use {{CONFIRM}} to let the user select.
41
+
42
+ Show only active changes (not already archived).
43
+ Include the schema used for each change if available.
44
+
45
+ **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
46
+
47
+ 2. **Check artifact completion status**
48
+
49
+ Run `specline gate artifacts --change "<name>" --json` to check artifact completion.
50
+
51
+ Parse the JSON to understand:
52
+ - `schemaName`: The workflow being used
53
+ - `artifacts`: List of artifacts with their status (`done` or other)
54
+
55
+ **If any artifacts are not `done`:**
56
+ - Display warning listing incomplete artifacts
57
+ - Use {{CONFIRM}} to confirm user wants to proceed
58
+ - Proceed if user confirms
59
+
60
+ 3. **Check task completion status**
61
+
62
+ Read the tasks file (typically `tasks.md`) to check for incomplete tasks.
63
+
64
+ Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).
65
+
66
+ **If incomplete tasks found:**
67
+ - Display warning showing count of incomplete tasks
68
+ - Use {{CONFIRM}} to confirm user wants to proceed
69
+ - Proceed if user confirms
70
+
71
+ **If no tasks file exists:** Proceed without task-related warning.
72
+
73
+ 4. **Assess delta spec sync state**
74
+
75
+ **决策流程:**
76
+
77
+ ```
78
+ Delta specs 存在?
79
+ ├── 否 → 直接归档
80
+ └── 是 → 比较 delta spec 与 main spec
81
+ ├── 无差异 → 「已同步」→ 直接归档
82
+ └── 有差异 → 展示变更摘要 → 询问用户
83
+ ├── 同步 → 执行 sync → 归档
84
+ └── 跳过 → 归档
85
+ ```
86
+
87
+ Check for delta specs at `specline/changes/<name>/specs/`. If none exist, proceed without sync prompt.
88
+
89
+ **If delta specs exist:**
90
+ - Compare each delta spec with its corresponding main spec at `specline/specs/<capability>/spec.md`
91
+ - Determine what changes would be applied (adds, modifications, removals, renames)
92
+ - Show a combined summary before prompting
93
+
94
+ **Prompt options:**
95
+ - If changes needed: "Sync now (recommended)", "Archive without syncing"
96
+ - If already synced: "Archive now", "Sync anyway", "Cancel"
97
+
98
+ If user chooses sync, {{DISPATCH}},role="general-purpose",prompt: "Use Skill tool to invoke specline-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>". Proceed to archive regardless of choice.
99
+
100
+ 5. **Perform the archive**
101
+
102
+ Create the archive directory if it doesn't exist:
103
+ ```bash
104
+ mkdir -p specline/changes/archive
105
+ ```
106
+
107
+ Generate target name using current date: `YYYY-MM-DD-<change-name>`
108
+
109
+ **Check if target already exists:**
110
+ - If yes: Fail with error, suggest renaming existing archive or using different date
111
+ - If no: Move the change directory to archive
112
+
113
+ ```bash
114
+ specline gate archive --execute --change <name>
115
+ ```
116
+
117
+ 6. **Display summary**
118
+
119
+ Show archive completion summary including:
120
+ - Change name
121
+ - Schema that was used
122
+ - Archive location
123
+ - Whether specs were synced (if applicable)
124
+ - Note about any warnings (incomplete artifacts/tasks)
125
+
126
+ ### Output On Success
127
+
128
+ ```
129
+ ## Archive Complete
130
+
131
+ **Change:** <change-name>
132
+ **Schema:** <schema-name>
133
+ **Archived to:** specline/changes/archive/YYYY-MM-DD-<name>/
134
+ **Specs:** ✓ Synced to main specs (or "No delta specs" or "Sync skipped")
135
+
136
+ All artifacts complete. All tasks complete.
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Guardrails (Layer 3 — 高级话题)
142
+
143
+ - Always prompt for change selection if not provided
144
+ - Use artifact graph (specline gate artifacts --json) for completion checking
145
+ - Don't block archive on warnings - just inform and confirm
146
+ - Preserve .specline.yaml when moving to archive (it moves with the directory)
147
+ - Show clear summary of what happened
148
+ - If sync is requested, use specline-sync-specs approach (agent-driven)
149
+ - If delta specs exist, always run the sync assessment and show the combined summary before prompting
150
+
151
+ ---
152
+
153
+ ## Anti-Rationalization 表格
154
+
155
+ 归档是流水线的最后一步,松懈的代价是污染长期记录:
156
+
157
+ | 借口 | 现实 |
158
+ |------|------|
159
+ | "不用检查完成度,反正用户说可以归档了" | 用户说可以不代表真的可以。Artifact 和 task 完成度检查是归档前的最后防线。 |
160
+ | "Delta spec 不用同步,下次再说" | 未同步的 Delta spec 意味着 spec 与代码脱节。归档后几乎不会再有人回来补。 |
161
+ | "归档就是移动目录,不需要通知用户" | 归档改变了 change 的可见性和可修改性。用户需要知道发生了什么。 |
162
+ | "警告不用管,自动继续就行" | 警告(artifact 不完整、task 未完成)是信号。归档时应确认而非忽略。 |
163
+
164
+ ## Verification Checklist
165
+
166
+ 归档前自查:
167
+
168
+ - [ ] Artifact 完成度已检查(`specline gate artifacts --json`)
169
+ - [ ] Task 完成度已检查(tasks.md checkbox 状态)
170
+ - [ ] 任何警告/不完整项已向用户确认
171
+ - [ ] Delta spec sync 决策已完成(存在则展示摘要→询问;不存在则跳过)
172
+ - [ ] 归档目录已创建(`specline/changes/archive/YYYY-MM-DD-<name>/`)
173
+ - [ ] 归档摘要已展示给用户