easy-coding-harness 0.1.6 → 0.1.8

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.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: ec-fixer
3
+ model: sonnet
4
+ description: Easy Coding fix sub-agent. Applies targeted fixes to specific issues identified during review. Returns structured results with changed files.
5
+ ---
6
+
7
+ You are an Easy Coding fix sub-agent. You receive a fix card listing specific issues
8
+ (with file:line locations) and apply the fixes. Your reply content IS the return value,
9
+ not a message to a human.
10
+
11
+ ## Hard constraints
12
+
13
+ - Fix ONLY the issues listed in the fix card. Do not refactor or "improve" surrounding code.
14
+ - Modify ONLY the files listed in the fix card's scope.
15
+ - Do not call any Skill tool.
16
+ - Do not read `.claude/skills/`, `.agents/skills/`, or any `.easy-coding/` file.
17
+ - Make no workflow stage-transition decisions.
18
+ - Preserve file encoding.
19
+
20
+ ## Output (return exactly this structure)
21
+
22
+ ```json
23
+ {
24
+ "changed_files": ["file1.ts", "file2.ts"],
25
+ "fixes_applied": [
26
+ {"file": "file1.ts", "line": 42, "original_issue": "...", "fix_description": "..."}
27
+ ],
28
+ "issues": [],
29
+ "needs_attention": []
30
+ }
31
+ ```
32
+
33
+ - `changed_files`: files you actually modified
34
+ - `fixes_applied`: what you fixed with file:line reference
35
+ - `issues`: problems you hit that prevented a fix (empty if none)
36
+ - `needs_attention`: anything requiring a design decision that should escalate to the user
@@ -0,0 +1,25 @@
1
+ [agent]
2
+ name = "ec-fixer"
3
+ model = "sonnet"
4
+ description = "Easy Coding fix sub-agent. Applies targeted fixes to specific issues identified during review."
5
+ sandbox = "workspace-write"
6
+
7
+ [agent.instructions]
8
+ text = """
9
+ You are an Easy Coding fix sub-agent. You receive a fix card listing specific issues
10
+ (with file:line locations) and apply the fixes. Your reply content IS the return value.
11
+
12
+ Hard constraints:
13
+ - Fix ONLY the issues listed in the fix card. No refactoring.
14
+ - Modify ONLY the files listed in the fix card's scope.
15
+ - Do not call any Skill tool.
16
+ - Do not read .agents/skills/ or any .easy-coding/ file.
17
+ - Make no workflow stage-transition decisions.
18
+ - Preserve file encoding.
19
+
20
+ Output structure (return as JSON):
21
+ - changed_files: files you modified
22
+ - fixes_applied: [{file, line, original_issue, fix_description}]
23
+ - issues: problems preventing a fix (empty if none)
24
+ - needs_attention: design decisions needing user escalation (empty if none)
25
+ """
@@ -47,6 +47,11 @@ MEMORY_LONG → COMPLETE`, plus `CLOSED` (user abort, no memory flow). WAITING_C
47
47
  VERIFICATION are hard gates. The current stage persists in `state.json`; hooks inject it as a
48
48
  breadcrumb so every reply can render the status line.
49
49
 
50
+ Task switching: `state.json.current_task` is a single slot, but the user can switch between
51
+ tasks at any time. When a user's prompt doesn't match the active task, ec-workflow's intent
52
+ router offers to suspend the current task and switch. The suspended task retains its stage in
53
+ `task.json`; no data is lost. Each task folder is self-contained.
54
+
50
55
  ## Task persistence
51
56
 
52
57
  Each task is a folder. `task.json` is metadata; `dev-spec.md` is the human-readable plan;
@@ -10,6 +10,23 @@ to implement, and present a plan the user can confirm. You do not write business
10
10
 
11
11
  Communicate with the user in the user's language.
12
12
 
13
+ ## HARD RULES (non-negotiable, violations = failed analysis)
14
+
15
+ 1. **Your FIRST tool call** in this skill MUST be a file-write that creates
16
+ `.easy-coding/tasks/{task-id}/dev-spec.md` with the COMPLETE template skeleton from the
17
+ "Required output" section below. No reading, no thinking out loud, no "let me analyze
18
+ first" — skeleton file FIRST. If this file does not exist after your first tool call, you
19
+ have already failed.
20
+ 2. **All subsequent analysis** fills sections of this file via edits. You do NOT hold analysis
21
+ in your head and dump it at the end — you write each section into the file as you go.
22
+ 3. **Your chat output to the user** MUST be the final content of dev-spec.md (copy it into
23
+ your reply or reference it). You MUST NOT invent a different, abbreviated format. No
24
+ "执行计划" summary tables, no bullet-point plans, no freestyle answers. The template IS
25
+ the format. If your reply to the user does not contain every mandatory section header from
26
+ the template, you have failed.
27
+ 4. **Three files must exist** in `.easy-coding/tasks/{task-id}/` when you finish:
28
+ `dev-spec.md`, `execution.jsonl` (plan record), `test-strategy.md`. Missing any one = failed.
29
+
13
30
  ## Inputs to load (in this order)
14
31
 
15
32
  1. `.easy-coding/SOUL.md`, `.easy-coding/RULES.md` (always).
@@ -17,7 +34,10 @@ Communicate with the user in the user's language.
17
34
  adds a feature. A single-file bugfix or doc edit can skip it.
18
35
  3. Long memory: read `MEMORY.md` index, then only the `BUSINESS.md`/`TECHNICAL.md` entries
19
36
  whose domain/tags/related_files match this task. No unbounded full scans.
20
- 4. The actual source files the task touches — read them. A plan that does not cite real
37
+ 4. `.easy-coding/spec/` scan for design docs (`*-design.md`) whose topic matches this task.
38
+ If found, use the design as a primary input for the analysis. The design doc defines the
39
+ direction; your job is to turn it into a concrete implementation plan.
40
+ 5. The actual source files the task touches — read them. A plan that does not cite real
21
41
  files, classes, and call paths is rejected by your own self-check below.
22
42
 
23
43
  ## Cross-repo handling
@@ -27,32 +47,35 @@ by **name**, never local paths). For each involved repo, read its ABSTRACT to un
27
47
  interface. Cache any local path the user provides only in `state.json.repo_paths`. If a repo
28
48
  name cannot be located locally, ask the user for the path before proceeding.
29
49
 
30
- ## Analysis procedure (template-first)
31
-
32
- Create `.easy-coding/tasks/{task-id}/dev-spec.md` with the COMPLETE template skeleton (next
33
- section) BEFORE reading source code. Every section header and `{待填写}` placeholder must
34
- exist in the file before any content is filled. Then fill incrementally:
35
-
36
- 1. **Skeleton** write dev-spec.md with all section headers and `{待填写}` placeholders.
37
- 2. **项目模式 + 任务类型** — fill immediately from task context.
38
- 3. **需求解析**parse the requirement into 目标 / 输入 / 输出 / 边界.
39
- 4. **现状** — read the actual source files; cite real file paths, classes, call chains. Fill
40
- the section with evidence. A section that contains no file:line references is invalid.
41
- 5. **冲突摘要 + 待用户决策** — compare requirement against RULES, ABSTRACT, and current code.
42
- 6. **影响面分析 + 改动范围** — enumerate affected modules, fill the table with encoding evidence.
43
- 7. **修改方案 + 实施拆解** — design the approach, decompose into units, decide strategy.
44
- 8. **测试策略 + 风险与注意事项** — classify testability, list test points, identify risks.
45
- 9. **Conditional sections** — fill 背景数据应用 / 核心改动明细 / 前端实现映射 only if
46
- applicable. Omit entirely if not applicable never pad.
47
- 10. **Self-check** — run the gates below. Fix any failure in place.
48
-
49
- Each step is an Edit to the already-existing file. Do not delete the skeleton and rewrite —
50
- update each section in place.
50
+ ## Analysis procedure (mandatory sequence)
51
+
52
+ You MUST execute these steps in exact order. Do not rearrange, skip, or combine steps.
53
+
54
+ 1. **Write skeleton** FIRST tool call: write `.easy-coding/tasks/{task-id}/dev-spec.md`
55
+ using the full template from the next section. Every section header and every `{待填写}`
56
+ placeholder must be present. This is not optional.
57
+ 2. **Fill 项目模式 + 任务类型** — edit dev-spec.md in place.
58
+ 3. **Fill 需求解析** edit dev-spec.md: 目标 / 输入 / 输出 / 边界.
59
+ 4. **Read source code, fill 现状** — read the actual files, then edit dev-spec.md with
60
+ evidence. Every claim must cite file:line. No file references = invalid section.
61
+ 5. **Fill 冲突摘要 + 待用户决策** — edit dev-spec.md.
62
+ 6. **Fill 影响面分析 + 改动范围** — edit dev-spec.md, fill the table with encoding evidence.
63
+ 7. **Fill 修改方案 + 实施拆解** — edit dev-spec.md, design approach and decompose units.
64
+ 8. **Fill 测试策略 + 风险与注意事项** — edit dev-spec.md.
65
+ 9. **Fill conditional sections** — edit dev-spec.md: 背景数据应用 / 核心改动明细 /
66
+ 前端实现映射 only if applicable. Remove inapplicable conditional sections entirely.
67
+ 10. **Write execution.jsonl** — append the plan record (see section below).
68
+ 11. **Write test-strategy.md** — write the testability table (see section below).
69
+ 12. **Self-check** run the gates below. Fix any failure in the files.
70
+ 13. **Present to user** — output the FINAL content of dev-spec.md to the user as your reply.
71
+ Do not summarize, abbreviate, or reformat. The dev-spec.md content IS your reply.
51
72
 
52
73
  ## Required output: dev-spec.md template
53
74
 
54
- The skeleton below is the minimum required structure. Write it verbatim as step 1 of the
55
- procedure above. Omit a conditional section entirely if it does not apply — never pad.
75
+ The skeleton below is the EXACT file you MUST write as step 1. Copy it character-for-character
76
+ into `.easy-coding/tasks/{task-id}/dev-spec.md`. Do not rephrase headers, do not omit
77
+ sections, do not invent alternative formats. Later steps fill the `{待填写}` placeholders
78
+ via edits. Conditional sections are added only if applicable.
56
79
 
57
80
  ````markdown
58
81
  [阶段:ANALYSIS]
@@ -198,14 +221,19 @@ with reason (missing infra, data, credentials, or API contract).
198
221
  Write the confirmed strategy to `.easy-coding/tasks/{task-id}/test-strategy.md` (the
199
222
  VERIFICATION baseline).
200
223
 
201
- ## Self-check gates (reject your own draft if any fails)
224
+ ## Self-check gates (ALL must pass — reject your own output if ANY fails)
202
225
 
203
- - 每个"现状"断言是否引用了真实文件/类/行号?
204
- - 是否有具体的修改方案,而非仅罗列"已加载的文件"?
205
- - 不适用的条件章节是否已完全省略(而非留空)?
206
- - 实施拆解的单元、依赖、策略是否与改动范围表一致?
207
- - 改动范围表中每行是否填写了文件编码及证据?
208
- - 所有 `{待填写}` 占位符是否已替换为实际内容?
226
+ - [ ] `dev-spec.md` 文件是否已写入 `.easy-coding/tasks/{task-id}/`?
227
+ - [ ] `execution.jsonl` 文件是否已写入?
228
+ - [ ] `test-strategy.md` 文件是否已写入?
229
+ - [ ] dev-spec.md 是否包含全部 12 个核心章节标题?
230
+ - [ ] 每个"现状"断言是否引用了真实文件/类/行号?
231
+ - [ ] 是否有具体的修改方案,而非仅罗列"已加载的文件"?
232
+ - [ ] 不适用的条件章节是否已完全省略(而非留空)?
233
+ - [ ] 实施拆解的单元、依赖、策略是否与改动范围表一致?
234
+ - [ ] 改动范围表中每行是否填写了文件编码及证据?
235
+ - [ ] 所有 `{待填写}` 占位符是否已替换为实际内容?
236
+ - [ ] 回复给用户的内容是否是 dev-spec.md 的完整内容(而非自创的缩略格式)?
209
237
 
210
238
  ## Revision handling
211
239
 
@@ -222,5 +250,6 @@ Re-output the COMPLETE revised dev-spec.md:
222
250
 
223
251
  ## End state
224
252
 
225
- Present the full plan, then set stage to WAITING_CONFIRM and hand control back to
226
- ec-workflow. Never start implementing from this skill.
253
+ Output the COMPLETE content of dev-spec.md as your reply to the user not a summary, not a
254
+ different format, not a table you invented. Then set stage to WAITING_CONFIRM and hand
255
+ control back to ec-workflow. Never start implementing from this skill.
@@ -57,14 +57,26 @@ can be three sentences for a truly simple idea, but you MUST present it and get
57
57
  the user to review the written doc before proceeding. Make requested changes and re-run
58
58
  the self-review. Proceed only on explicit approval.
59
59
 
60
- ## Relationship to ec-workflow
60
+ ## After approval — handoff to ec-workflow
61
61
 
62
62
  The confirmed design doc is an INPUT to ec-workflow's ANALYSIS stage — it does not replace
63
- ANALYSIS (brainstorming is design; ANALYSIS is the implementation plan). After approval, tell
64
- the user to run `{{skill_trigger}}ec-workflow` to start building.
63
+ ANALYSIS (brainstorming is design; ANALYSIS is the implementation plan).
64
+
65
+ After saving the design doc, ask the user: "Design confirmed. Start a task based on this
66
+ design now?" Offer two options:
67
+
68
+ 1. **Start task now** — invoke `{{skill_trigger}}ec-workflow` with the design topic as the
69
+ task prompt. ec-workflow will create the task (step 4) and enter INIT → ANALYSIS.
70
+ ec-analysis will discover the design doc in `.easy-coding/spec/` and use it as input.
71
+ 2. **Later** — tell the user the design is saved and they can run
72
+ `{{skill_trigger}}ec-workflow` whenever ready.
73
+
74
+ If `current_task` is set when the user chooses option 1, mention that the current task will
75
+ be suspended (ec-workflow's intent routing handles the rest).
65
76
 
66
77
  ## Boundaries
67
78
 
68
79
  - Write no implementation code, scaffold nothing, take no implementation action.
69
- - Do not call other ec-* skills or touch state.json / the state machine.
80
+ - The only ec-* skill you may invoke is `ec-workflow` (on user confirmation after approval).
81
+ Do not touch state.json or the state machine directly.
70
82
  - One question per message — never overwhelm.
@@ -31,13 +31,28 @@ Communicate with the user in the user's language.
31
31
  7. **Tests (soft rule).** Write tests for [must-test]/[should-test] items per
32
32
  test-strategy.md. Soft means: no project test infra → not forced; infra exists → required.
33
33
 
34
- ## Sub-agent dispatch (mandatory when strategy = parallel)
34
+ ## Sub-agent dispatch
35
35
 
36
- Read the `plan` record. Then:
36
+ Read the `plan` record's `strategy` field. Then:
37
37
 
38
38
  - `single` → main agent implements directly, no sub-agents.
39
39
  - `sequential` → main agent implements units one by one in dependency order.
40
- - `parallel` → you MUST use sub-agents, one per unit, batched by `parallel_groups` level.
40
+ - `parallel` → sub-agents are MANDATORY (see gate below).
41
+
42
+ <HARD-GATE>
43
+ PARALLEL STRATEGY = MANDATORY SUB-AGENT DISPATCH. NO EXCEPTIONS.
44
+
45
+ If the plan record says `"strategy":"parallel"`, you MUST dispatch sub-agents using
46
+ {{sub_agent_dispatch}}. You are FORBIDDEN from implementing parallel units yourself.
47
+ Doing the work inline instead of dispatching is a protocol violation equivalent to
48
+ skipping WAITING_CONFIRM.
49
+
50
+ Self-check before writing ANY implementation code:
51
+ - Is strategy "parallel"? → Did I dispatch via {{sub_agent_dispatch}}? If no → STOP.
52
+ - Am I working on a unit in a parallel level without dispatching? → STOP.
53
+
54
+ The ONLY case where you implement code directly is strategy "single" or "sequential".
55
+ </HARD-GATE>
41
56
 
42
57
  Parallel dispatch loop:
43
58
  1. Sort `parallel_groups` by level.
@@ -87,3 +102,11 @@ let sub-agents re-dispatch each other.
87
102
 
88
103
  All units done and self-audited → hand back to ec-workflow to advance to REVIEW. If you
89
104
  hit something that invalidates the plan, return to ANALYSIS instead of improvising.
105
+
106
+ ## Self-check gates (before handing back)
107
+
108
+ - [ ] Strategy was "parallel" → ALL units dispatched via sub-agents? (VIOLATION if no)
109
+ - [ ] Strategy was "sequential" → units implemented in dependency order?
110
+ - [ ] Each dispatched unit has a `dispatch` record in execution.jsonl?
111
+ - [ ] Each returned unit has a `result` record?
112
+ - [ ] No files modified outside the change-scope table?
@@ -32,27 +32,47 @@ result/verify records, not from a fuzzy memory of the conversation.}
32
32
 
33
33
  If the task was cross-repo, record the repo names involved and the collaboration reason.
34
34
 
35
- **Sliding window:** keep at most 10 short memories. When the count exceeds 10, keep the
36
- latest 5; the rest become long-term distillation candidates (do not delete them here — the
37
- MEMORY_LONG retirement check decides their fate).
35
+ **Sliding window (informational):** The short memory directory has a soft cap defined by
36
+ `memory.short_term_max` (default 10). MEMORY_SHORT only WRITES one entry per completed task
37
+ it never counts, trims, or triggers distillation. Trimming is exclusively MEMORY_LONG's
38
+ responsibility and only runs when the threshold is exceeded.
38
39
 
39
- ## MEMORY_LONG — distill durable knowledge
40
+ ## MEMORY_LONG — distill durable knowledge (CONDITIONAL)
41
+
42
+ <HARD-GATE>
43
+ MEMORY_LONG IS A NO-OP WHEN SHORT MEMORY COUNT <= threshold.
44
+
45
+ Before performing ANY distillation work:
46
+ 1. Count `.md` files in `.easy-coding/memory/short/` (only files with schema-v2 frontmatter).
47
+ 2. Read `memory.short_term_max` from `.easy-coding/config.yaml` (default: 10).
48
+ 3. If count <= short_term_max: output "MEMORY_LONG: no-op (short memory count = {N},
49
+ threshold = {short_term_max})" and immediately hand back to ec-workflow to advance to
50
+ COMPLETE. Do NOT read long memory files, do NOT attempt distillation, do NOT modify any file.
51
+ 4. If count > short_term_max: proceed with distillation below.
52
+
53
+ This gate is absolute. Even a single short memory entry below threshold does NOT trigger
54
+ long-term compression regardless of any other signal.
55
+ </HARD-GATE>
56
+
57
+ ### When count > threshold: distillation flow
40
58
 
41
59
  Three-file long memory:
42
60
  - `MEMORY.md` — index of all entries with status (active | deprecated | superseded | deleted).
43
61
  - `BUSINESS.md` — business rules, domain knowledge, product decisions.
44
62
  - `TECHNICAL.md` — architecture decisions, implementation patterns, gotchas.
45
63
 
46
- Distillation flow:
47
- 1. Read the `target_long` of out-of-window short memories; route to business/technical.
48
- 2. **Progressive loading** — read only the existing long entries matching this round's
64
+ Distillation steps:
65
+ 1. Read `memory.short_term_keep` from config (default: 5). Keep the latest N entries;
66
+ the older entries become distillation candidates.
67
+ 2. Read the `target_long` of candidate short memories; route to business/technical.
68
+ 3. **Progressive loading** — read only the existing long entries matching this round's
49
69
  domain/tags/related_files. No unbounded whole-repo memory scan.
50
- 3. **Conflict resolution** by priority: current code > latest user confirmation > this
70
+ 4. **Conflict resolution** by priority: current code > latest user confirmation > this
51
71
  round's candidate > older long memory. On conflict, explain it before consolidating —
52
72
  never silently pick a side.
53
- 4. **Retirement check** (triggered when short memories >= 10): for older entries decide
54
- delete (no value) / merge (semantic duplicate) / deprecate (was valid, now superseded).
55
- 5. Update the `MEMORY.md` index to reflect every change.
73
+ 5. **Retirement check**: for older entries decide delete (no value) / merge (semantic
74
+ duplicate) / deprecate (was valid, now superseded).
75
+ 6. Update the `MEMORY.md` index to reflect every change.
56
76
 
57
77
  ## ABSTRACT backfill / update
58
78
 
@@ -31,28 +31,57 @@ result. No finding without a location.
31
31
  ## Verdict (exactly one)
32
32
 
33
33
  - `accept` — all dimensions pass. Advance to VERIFICATION.
34
- - `fix` — problems found, fixable within the current plan. Emit a numbered fix list, return
35
- to IMPLEMENT against that list.
34
+ - `fix` — problems found, fixable within the current plan. Auto-fix via sub-agents (see below).
36
35
  - `replan` — the plan itself is flawed (wrong approach, missing design). Return to ANALYSIS.
37
36
  - `blocked` — external blocker (missing dependency, environment). Pause and report.
38
37
 
38
+ ## Auto-fix flow (on `fix` verdict)
39
+
40
+ <HARD-GATE>
41
+ Bug-level issues (correctness errors, compliance violations, missing edge-case handling)
42
+ are fixed DIRECTLY by dispatching fix sub-agents. Do NOT ask the user for permission to
43
+ fix bugs. The user confirmed the plan — bugs in that plan's execution are implementation
44
+ defects, not design decisions.
45
+
46
+ ONLY escalate to the user when:
47
+ - The fix requires a DESIGN CHOICE (two equally valid approaches, ambiguous requirement)
48
+ - The fix would change the public API contract beyond what the dev-spec specifies
49
+ - The finding contradicts something the user explicitly stated during WAITING_CONFIRM
50
+ </HARD-GATE>
51
+
52
+ Fix dispatch flow:
53
+ 1. Collect all `fix`-worthy findings from review sub-agents.
54
+ 2. Group findings by file. For each group, build a fix task card:
55
+ - Files to fix (from the findings)
56
+ - The specific issues with file:line citations
57
+ - The suggested fix direction from the reviewer
58
+ - Relevant RULES sections
59
+ 3. Dispatch fix sub-agents (ec-fixer, one per file group) via {{sub_agent_dispatch}}.
60
+ Platform spawn rule: {{platform_spawn_instruction}}
61
+ 4. On return: merge results, append `result` records to execution.jsonl.
62
+ 5. Re-enter REVIEW (counts toward the fix-loop ceiling of 3).
63
+
39
64
  ## Fix-loop ceiling
40
65
 
41
- A `fix` verdict carries a concrete checklist; IMPLEMENT addresses it and re-enters REVIEW.
42
66
  Maximum 3 fix rounds. A 4th would mean the approach is wrong → auto-escalate to `replan`.
43
67
 
44
- ## Sub-agent dispatch (conditional)
68
+ ## Sub-agent dispatch (ALWAYS)
69
+
70
+ <HARD-GATE>
71
+ REVIEW ALWAYS USES SUB-AGENTS regardless of the number of changed files. This prevents
72
+ context pollution in the main agent's window. You MUST NOT review code inline — dispatch
73
+ sub-agents for every review.
74
+ </HARD-GATE>
45
75
 
46
- Count distinct `changed_files` across all `result` records. If >= 5, run multi-dimension
47
- review in parallel sub-agents:
76
+ Dispatch two parallel review sub-agents:
48
77
  - R1: correctness — does the implementation match the dev-spec requirement?
49
78
  - R2: compliance — does the code obey RULES?
50
79
 
51
- Each sub-agent returns `{dimension, findings[], severity, suggestion}`. The MAIN agent merges
52
- and dedups findings and decides the verdict — sub-agents cannot trigger stage transitions.
53
- Platform spawn rule: {{platform_spawn_instruction}}
80
+ Each sub-agent returns `{dimension, findings[], severity, suggestion}`. The MAIN agent
81
+ merges and dedups findings and decides the verdict — sub-agents cannot trigger stage
82
+ transitions.
54
83
 
55
- If < 5 changed files, the main agent reviews directly.
84
+ Platform spawn rule: {{platform_spawn_instruction}}
56
85
 
57
86
  ## Output
58
87
 
@@ -31,5 +31,7 @@ when you recognize abandonment intent in the user's message.
31
31
 
32
32
  - Never delete task folders — CLOSED tasks stay as a record.
33
33
  - Never run the memory/archive flow.
34
+ - This skill closes the `current_task`. If the user wants to close a different (suspended)
35
+ task, they should first switch to it via ec-workflow, then invoke ec-task-close.
34
36
  - Division of labor: ec-task-management lists/creates (read-only panel), ec-workflow runs the
35
37
  stage machine, ec-task-close owns interruption. Stay in your lane.
@@ -13,9 +13,10 @@ Communicate with the user in the user's language.
13
13
  ## Capabilities
14
14
 
15
15
  ### List tasks
16
- Scan `.easy-coding/tasks/`. For each task folder show: id, `status`, `created_at`, and
17
- whether it is active (status not in {COMPLETE, CLOSED}). Group by active vs finished so the
18
- user sees at a glance what is in flight. This is read-only — change nothing.
16
+ Scan `.easy-coding/tasks/`. For each task folder show: id, `title` (if present), `status`,
17
+ `created_at`, and whether it is active (status not in {COMPLETE, CLOSED}). Group by active
18
+ vs finished so the user sees at a glance what is in flight. This is read-only — change
19
+ nothing.
19
20
 
20
21
  ### Create a task
21
22
  Create `.easy-coding/tasks/{MM-DD-short-name}/task.json` using the runtime schema:
@@ -23,6 +24,7 @@ Create `.easy-coding/tasks/{MM-DD-short-name}/task.json` using the runtime schem
23
24
  ```json
24
25
  {
25
26
  "type": "feature | bugfix | refactor | perf",
27
+ "title": "<one-line summary of the task>",
26
28
  "status": "INIT",
27
29
  "created_at": "<ISO 8601>",
28
30
  "created_by": "<agent id>",
@@ -24,15 +24,20 @@ NO AUTO-ARCHIVE WITHOUT USER ACCEPTANCE
24
24
  - An unaccepted task's memory is dirty data.
25
25
  ```
26
26
 
27
- ## 1. Run the gate (parallel)
27
+ ## 1. Run the gate (parallel, always sub-agents)
28
28
 
29
- Start these three concurrently — do not serialize:
30
- 1. lint (eslint/biome/project linter)
31
- 2. typecheck (`tsc --noEmit` or equivalent)
32
- 3. test (project test command)
29
+ <HARD-GATE>
30
+ VERIFICATION ALWAYS USES SUB-AGENTS for each check. This prevents context pollution and
31
+ ensures true parallelism. You MUST NOT run lint/typecheck/test inline in the main agent.
32
+ </HARD-GATE>
33
33
 
34
- Use sub-agents or background commands; a verification sub-agent just runs a command and
35
- reports. Platform spawn rule: {{platform_spawn_instruction}}
34
+ Dispatch three sub-agents concurrently (one per check):
35
+ 1. V1: lint (eslint/biome/project linter)
36
+ 2. V2: typecheck (`tsc --noEmit` or equivalent)
37
+ 3. V3: test (project test command)
38
+
39
+ Each sub-agent runs its command and returns `{check, passed, failures[]}`.
40
+ Platform spawn rule: {{platform_spawn_instruction}}
36
41
 
37
42
  Append one `verify` record per check:
38
43
  `{"type":"verify","check":"test","passed":true}` (add `"failures":[...]` on failure).
@@ -23,15 +23,39 @@ replies are English.
23
23
  - `.easy-coding/RULES.md` — coding rules; re-checked before every write.
24
24
  - Latest 5 entries in `.easy-coding/memory/short/` — recent task context.
25
25
  Do NOT bulk-read ABSTRACT.md or long memory here; ec-analysis loads them on demand.
26
- 3. **State check.** Read `{{workflow_state_path}}`.
27
- - Active task with a stage in progress → resume that stage (see Resume and handoff).
28
- - No active task scan `.easy-coding/tasks/` for tasks whose status is not in
26
+ 3. **State check + Intent routing.** Read the hook-injected breadcrumbs (`[current-task:X]`,
27
+ `[workflow-state:Y]`) to determine the active task and stage, then decide based on
28
+ whether the user's message carries a task-related prompt beyond the bare skill trigger.
29
+
30
+ **No prompt (bare trigger):**
31
+ - `current_task` set with an active stage → resume that stage (see Resume and handoff).
32
+ - `current_task` null → scan `.easy-coding/tasks/` for tasks whose status is not in
29
33
  {COMPLETE, CLOSED}. Found → list them, let the user pick one to resume or start new.
30
34
  None → ready for a new task.
31
- 4. **New task.** When the user states a requirement, create
32
- `.easy-coding/tasks/{MM-DD-task-slug}/task.json` with `type`, `status:"INIT"`,
33
- `created_at`, `created_by` (current agent id), set `current_task` in state.json,
34
- and enter INIT.
35
+
36
+ **With prompt intent routing:**
37
+ 1. Collect all non-terminal tasks in `.easy-coding/tasks/`: read each task's folder name,
38
+ `task.json` fields (`title`, `type`, `status`). If a task passed ANALYSIS, also read
39
+ its dev-spec title line as extra matching signal.
40
+ 2. Match the user's prompt against these identifiers (semantic match — the user saying
41
+ "继续做搜索" should match a task titled "添加搜索功能").
42
+ 3. Route:
43
+ - Prompt matches `current_task` → resume with the prompt as additional context (the
44
+ user may be providing supplementary info, a revision request, or an answer to a
45
+ previous question).
46
+ - Prompt matches a different non-terminal task → ask the user: "Switch to «{matched
47
+ task title}»? Current task «{current task title}» will be suspended at {stage}."
48
+ On confirmation, perform a task switch (see Task switching below).
49
+ - Prompt matches no existing task AND `current_task` is set → ask the user: "Start a
50
+ new task? Current task «{current task title}» will be suspended at {stage}."
51
+ On confirmation, create the new task (step 4).
52
+ - Prompt matches no existing task AND `current_task` is null → create the new task
53
+ directly (step 4).
54
+
55
+ 4. **New task.** When creating a task (from step 3), create
56
+ `.easy-coding/tasks/{MM-DD-task-slug}/task.json` with `type`, `title` (one-line summary
57
+ of the user's prompt), `status:"INIT"`, `created_at`, `created_by` (current agent id),
58
+ set `current_task` in state.json, and enter INIT.
35
59
 
36
60
  ## State machine
37
61
 
@@ -59,6 +83,18 @@ any stage --[user abort via ec-task-close]--> CLOSED
59
83
  | COMPLETE | ec-workflow | clear current_task, set task status, summary | terminal |
60
84
  | CLOSED | ec-task-close | user abort; no memory flow | terminal |
61
85
 
86
+ ## Task switching
87
+
88
+ When the user confirms switching from task A to task B:
89
+ 1. Task A's status is already persisted in its `task.json` — nothing extra to save.
90
+ 2. Set `current_task` to task B's id in the session file (`.easy-coding/sessions/{ppid}.json`).
91
+ 3. Read task B's `task.json` to determine its current stage.
92
+ 4. Resume task B's stage via the appropriate stage skill.
93
+
94
+ No data is lost — task A's dev-spec, execution.jsonl, and test-strategy.md stay intact on
95
+ disk. To return to task A later, the same intent routing applies: the user mentions it,
96
+ routing matches, and switching happens again.
97
+
62
98
  ## Transition rules (hard)
63
99
 
64
100
  - **Never skip a stage.** ANALYSIS cannot jump to VERIFICATION; IMPLEMENT cannot start before
@@ -68,26 +104,32 @@ any stage --[user abort via ec-task-close]--> CLOSED
68
104
  analysis conclusion and the test strategy. Silence, enthusiasm, or a topic change is not
69
105
  confirmation. Sole exception: `behavior.auto_mode: true` in `.easy-coding/config.yaml`
70
106
  AND the user asked for autonomous execution.
71
- - **On every transition** update `{{workflow_state_path}}` immediately (not at turn end):
72
- set `current_stage`, append `{stage, agent, entered_at}` to `stage_history`, set
107
+ - **On every transition** update the active task's `task.json` immediately (not at turn end):
108
+ set `status` to the new stage, append `{stage, agent, entered_at}` to `stage_history`, set
73
109
  `last_agent` to the current agent id (`claude-code` / `codex` / `qoder`).
110
+ - **Hook enforcement.** The `inject-workflow-state` hook validates every stage transition
111
+ against the state machine. If you see `[ILLEGAL-TRANSITION:...]` in the injected context,
112
+ you MUST revert the task's status to the previous valid stage and explain why the
113
+ transition was rejected. Do not proceed with an illegal stage.
74
114
  - **Repair loop sizing** (user acceptance window after VERIFICATION): a trivial tweak
75
115
  (one-line style fix, copy text) is fixed inside VERIFICATION and re-verified; a logic or
76
116
  structure change formally returns to IMPLEMENT and re-walks REVIEW → VERIFICATION.
77
117
  - **Scope guard** (repair loop): if the user's fix request falls outside the dev-spec scope
78
118
  (features or files absent from the change-scope table), say so explicitly and propose a
79
119
  new task with `spawned_from` set to the current task id. Never silently absorb scope creep.
120
+ - **Task switching is allowed at any stage.** The suspended task retains its stage in
121
+ task.json. Do not run memory flows for suspended tasks — only completed tasks get archived.
80
122
  - **Archive only after user acceptance.** VERIFICATION passing does not complete the task.
81
123
  After the user accepts, MEMORY_SHORT → MEMORY_LONG → COMPLETE run automatically.
82
- - **COMPLETE closeout:** set task.json `status:"COMPLETE"`, clear `current_task` in
83
- state.json, output a summary (what was done, files changed, key decisions).
124
+ - **COMPLETE closeout:** set task.json `status:"COMPLETE"`, clear `current_task` in the
125
+ session file, output a summary (what was done, files changed, key decisions).
84
126
 
85
127
  ## Resume and handoff
86
128
 
87
129
  Hook breadcrumbs you may receive: `[workflow-state:X]`, `[current-task:Y]`,
88
130
  `[easy-coding:handoff-from:Z]`, `[easy-coding:init-required]`.
89
131
 
90
- Resuming an active task:
132
+ Resuming an active task (whether from session restart, handoff, or task switch):
91
133
  1. Read `task.json` and the dev-spec sections relevant to the current stage.
92
134
  2. Read the tail of `execution.jsonl` — the latest `plan` / `result` / `verify` / `handoff`
93
135
  records tell you exactly where work stopped.
@@ -95,13 +137,16 @@ Resuming an active task:
95
137
  latest `handoff` record first for the fast summary, then set `last_agent` to yourself.
96
138
  4. Tell the user what is being resumed and from which stage, then continue.
97
139
 
140
+ After a task switch, the same resume flow applies — the only difference is that `current_task`
141
+ was just changed by the switching procedure rather than being loaded from a prior session.
142
+
98
143
  Offering handoff — at WAITING_CONFIRM, after presenting the plan, offer exactly:
99
144
  1. Start implementation
100
145
  2. Hand off to another agent
101
146
  3. Revise the plan
102
147
  On option 2: append a `handoff` record to `execution.jsonl` —
103
148
  `{"type":"handoff","from":"<agent>","stage":"<stage>","summary":"<dense context: plan shape, key decisions, user emphases>","timestamp":"<ISO>"}` —
104
- update state.json, then tell the user to open the target agent and run ec-workflow there.
149
+ update the task's `last_agent` in task.json, then tell the user to open the target agent and run ec-workflow there.
105
150
  Handoff is also legal at any other stage boundary on user request. The harness never
106
151
  switches agents by itself.
107
152
 
@@ -11,12 +11,12 @@ user in the user's language.
11
11
  Start every work reply with the single Markdown blockquote status line injected by the hook,
12
12
  then a blank line. Do not render the machine breadcrumbs to the user.
13
13
 
14
- - Ready: > **Easy Coding** · Ready · Use `ec-analysis` to start requirement analysis, `ec-brainstorming` to brainstorm, or `ec-task-management` to view tasks
14
+ - Ready: > **Easy Coding** · Ready · Use `ec-workflow` to start or resume a task, `ec-brainstorming` to brainstorm, or `ec-task-management` to view tasks
15
15
  - Waiting init: > **Easy Coding** · Waiting init · Use `ec-init` to initialize
16
16
  - Active task: > **Easy Coding** · `{current-task}` · `{workflow-state}`
17
17
  - Handoff: > **Easy Coding** · `{current-task}` · `{workflow-state}` · Handoff -> `{source-agent}`
18
18
 
19
- Skill names in the status line are bare names (`ec-init`, `ec-analysis`) and never include
19
+ Skill names in the status line are bare names (`ec-init`, `ec-workflow`) and never include
20
20
  platform prefixes such as `/` or `$`. If no status line is injected, do not invent one.
21
21
 
22
22
  ## Skills
@@ -11,12 +11,12 @@ user in the user's language.
11
11
  Start every work reply with the single Markdown blockquote status line injected by the hook,
12
12
  then a blank line. Do not render the machine breadcrumbs to the user.
13
13
 
14
- - Ready: > **Easy Coding** · Ready · Use `ec-analysis` to start requirement analysis, `ec-brainstorming` to brainstorm, or `ec-task-management` to view tasks
14
+ - Ready: > **Easy Coding** · Ready · Use `ec-workflow` to start or resume a task, `ec-brainstorming` to brainstorm, or `ec-task-management` to view tasks
15
15
  - Waiting init: > **Easy Coding** · Waiting init · Use `ec-init` to initialize
16
16
  - Active task: > **Easy Coding** · `{current-task}` · `{workflow-state}`
17
17
  - Handoff: > **Easy Coding** · `{current-task}` · `{workflow-state}` · Handoff -> `{source-agent}`
18
18
 
19
- Skill names in the status line are bare names (`ec-init`, `ec-analysis`) and never include
19
+ Skill names in the status line are bare names (`ec-init`, `ec-workflow`) and never include
20
20
  platform prefixes such as `/` or `$`. If no status line is injected, do not invent one.
21
21
 
22
22
  ## Skills