easy-coding-harness 0.5.3 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-coding-harness",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "CLI scaffold for installing Easy Coding harness files into agent-native directories.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -162,7 +162,7 @@ agent must be able to see what was generated and on what evidence.
162
162
  - TEST_STRATEGY.md (skeleton for the chosen framework)
163
163
  3. **Skip ABSTRACT.md** — no architecture exists yet. Note in init_log:
164
164
  "ABSTRACT pending; ec-memory backfills after the first substantive task." (ec-memory
165
- detects the missing file during MEMORY_LONG and generates it from the then-current code.)
165
+ detects the missing file during MEMORY and generates it from the then-current code.)
166
166
  4. Memory migration probe and memory init, same as iterative steps 5-7.
167
167
  5. Recommend: design first with `{{skill_trigger}}ec-brainstorming`, then build via
168
168
  `{{skill_trigger}}ec-workflow`.
@@ -42,10 +42,12 @@ analysis, workflow operation). The CLI never analyzes the project.
42
42
 
43
43
  ## Workflow state machine
44
44
 
45
- 8 stages + 2 terminals, owned by ec-workflow:
46
- `INIT → ANALYSIS → WAITING_CONFIRM → IMPLEMENT → REVIEW → VERIFICATION → MEMORY_SHORT
47
- MEMORY_LONG → COMPLETE`, plus `CLOSED` (user abort, no memory flow). WAITING_CONFIRM and
48
- VERIFICATION are hard gates. The active task pointer lives in `sessions/{ppid}.json`;
45
+ 6 work stages + 2 terminals, owned by ec-workflow:
46
+ `INIT → ANALYSIS → IMPLEMENT → REVIEW → VERIFICATION → MEMORY COMPLETE`, plus `CLOSED`
47
+ (user abort, no memory flow). Every legal stage edge records `task.json.pending_transition`
48
+ and requires explicit user confirmation by default. VERIFICATION remains the fresh-evidence
49
+ hard gate, and MEMORY keeps the conditional long-memory threshold gate. The active task
50
+ pointer lives in `sessions/{ppid}.json`;
49
51
  when the task reaches `COMPLETE` or `CLOSED`, the state API clears `current_task` so the
50
52
  session returns to Ready. Each task's stage persists in its `task.json`. Hooks inject the
51
53
  session and task state as breadcrumbs so every reply can render the status line.
@@ -57,7 +59,8 @@ stage in `task.json`; no data is lost. Each task folder is self-contained.
57
59
 
58
60
  ## Task persistence
59
61
 
60
- Each task is a folder. `task.json` is metadata; `dev-spec.md` is the human-readable plan;
62
+ Each task is a folder. `task.json` is metadata, including the current stage and any
63
+ `pending_transition`; `dev-spec.md` is the human-readable plan;
61
64
  `execution.jsonl` is an append-only plan-and-log (one `plan` record, then `dispatch`/`result`
62
65
  /`review`/`verify`/`handoff` records). Because plan and log live on disk, not in an agent's
63
66
  context window, a task survives session end and agent switches with zero information loss.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ec-analysis
3
- description: ANALYSIS-stage skill. Use when ec-workflow enters ANALYSIS. Creates the dev-spec skeleton FIRST (template-first), then fills incrementally — producing the narrative plan, execution plan (execution.jsonl), and test strategy. Ends in WAITING_CONFIRM. Grounds every conclusion in real code, never restates the requirement.
3
+ description: ANALYSIS-stage skill. Use when ec-workflow enters ANALYSIS. Creates the dev-spec skeleton FIRST (template-first), then fills incrementally — producing the narrative plan, execution plan (execution.jsonl), and test strategy. Ends by requesting the confirmed edge to IMPLEMENT. Grounds every conclusion in real code, never restates the requirement.
4
4
  ---
5
5
 
6
6
  > **SKELETON FIRST — your first two tool calls MUST be: (1) Read `.easy-coding/templates/dev-spec-skeleton.md`, (2) Write its EXACT content to the task's dev-spec.md. No exceptions. Do not analyze or think before the skeleton file exists on disk.**
@@ -42,8 +42,8 @@ Communicate with the user in the user's language.
42
42
  which subset this round?" as an explicit item in 待用户决策 for the user to decide. Never
43
43
  make a scope-narrowing decision yourself and present it as settled. Never fabricate a
44
44
  premise such as "the user already fixed scope X in INIT" or "auto_mode already selected Y"
45
- to justify narrowing — `auto_mode` only waives the WAITING_CONFIRM confirmation step and
46
- carries NO scope or delivery-form decision whatsoever.
45
+ to justify narrowing — `auto_mode` only waives stage-boundary prompts under an explicit
46
+ autonomous user request and carries NO scope or delivery-form decision whatsoever.
47
47
  6. **改动范围 lists ONLY real project code.** The 改动范围 table carries only changes to real
48
48
  project source/config files. Any harness artifact under `.easy-coding/` (dev-spec.md,
49
49
  execution.jsonl, test-strategy.md, memory files, generated reports, etc.) is FORBIDDEN in
@@ -218,7 +218,8 @@ VERIFICATION baseline).
218
218
 
219
219
  > 修订同样受 HARD RULE 5/6 约束:用户的修订诉求若是扩大或细化代码改动,不得借机把任务降级为"出报告";范围收窄仍须作为 待用户决策 项由用户确认。
220
220
 
221
- On user revision request at WAITING_CONFIRM, do NOT reply with only a change summary.
221
+ On user revision or Other feedback while ANALYSIS has a pending transition, first cancel the
222
+ pending edge. Do NOT reply with only a change summary.
222
223
  Re-output the COMPLETE revised dev-spec.md:
223
224
 
224
225
  1. Prepend a `### 修订摘要` listing each user request and its impact on the plan. If the
@@ -227,11 +228,11 @@ Re-output the COMPLETE revised dev-spec.md:
227
228
  sections), incorporating all revisions.
228
229
  3. Overwrite the `plan` record in execution.jsonl with the new strategy.
229
230
  4. Update test-strategy.md if test scope changed.
230
- 5. Re-enter WAITING_CONFIRM and wait for explicit user confirmation.
231
+ 5. Request ANALYSIS -> IMPLEMENT again and present the standard confirmation/handoff/Other gate.
231
232
 
232
233
  ## End state
233
234
 
234
235
  Read dev-spec.md back from disk and output the COMPLETE content as your reply to the user —
235
- not a summary, not a different format, not a table you invented. Then set stage to
236
- WAITING_CONFIRM and hand control back to ec-workflow. Never start implementing from this
237
- skill.
236
+ not a summary, not a different format, not a table you invented. Then ask ec-workflow to
237
+ record `pending_transition: ANALYSIS -> IMPLEMENT`, present the standard boundary choices,
238
+ and stop. Never start implementing from this skill.
@@ -66,7 +66,8 @@ After saving the design doc, ask the user: "Design confirmed. Start a task based
66
66
  design now?" Offer two options:
67
67
 
68
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.
69
+ task prompt. ec-workflow will create the task and enter INIT. After INIT completes, it
70
+ presents the standard confirmation/handoff/Other gate before entering ANALYSIS.
70
71
  ec-analysis will discover the design doc in `.easy-coding/spec/` and use it as input.
71
72
  2. **Later** — tell the user the design is saved and they can run
72
73
  `{{skill_trigger}}ec-workflow` whenever ready.
@@ -46,8 +46,8 @@ EVERY STRATEGY = MANDATORY SUB-AGENT DISPATCH. NO EXCEPTIONS.
46
46
 
47
47
  You MUST dispatch sub-agents using {{sub_agent_dispatch}} for every unit, whatever the
48
48
  strategy. You are FORBIDDEN from implementing any unit yourself in the main agent. Doing the
49
- work inline instead of dispatching is a protocol violation equivalent to skipping
50
- WAITING_CONFIRM.
49
+ work inline instead of dispatching is a protocol violation equivalent to bypassing the
50
+ ANALYSIS -> IMPLEMENT confirmation gate.
51
51
 
52
52
  Self-check before writing ANY implementation code:
53
53
  - Am I about to write implementation code in the main agent? → STOP. Dispatch a sub-agent.
@@ -107,8 +107,9 @@ let sub-agents re-dispatch each other.
107
107
 
108
108
  ## End state
109
109
 
110
- All units done and self-audited → hand back to ec-workflow to advance to REVIEW. If you
111
- hit something that invalidates the plan, return to ANALYSIS instead of improvising.
110
+ All units done and self-audited → hand back to ec-workflow to request IMPLEMENT -> REVIEW and
111
+ wait at the standard confirmation/handoff/Other gate. If something invalidates the plan,
112
+ request IMPLEMENT -> ANALYSIS and wait at the same gate instead of improvising.
112
113
 
113
114
  ## Self-check gates (before handing back)
114
115
 
@@ -1,18 +1,18 @@
1
1
  ---
2
2
  name: ec-memory
3
- description: MEMORY_SHORT and MEMORY_LONG stage skill — part of the archive flow, triggered only after user acceptance. Use when ec-workflow enters the memory stages. Writes schema-v2 short memory with a sliding window, distills long memory into BUSINESS/TECHNICAL with conflict resolution, and backfills ABSTRACT on architecture changes.
3
+ description: MEMORY-stage skill — part of the archive flow, triggered only after user acceptance and a confirmed stage edge. Writes one schema-v2 short memory, then runs the authoritative conditional long-memory gate, performs optional distillation, and requests COMPLETE.
4
4
  ---
5
5
 
6
6
  # ec-memory — archive what was learned
7
7
 
8
- ec-workflow dispatches you during MEMORY_SHORT and MEMORY_LONG, which run only after the
9
- user accepts the task. Inputs: the task's `dev-spec.md`, `execution.jsonl` (the `result` and
8
+ ec-workflow dispatches you during MEMORY, which runs only after the user accepts the task and
9
+ confirms entry. Inputs: the task's `dev-spec.md`, `execution.jsonl` (the `result` and
10
10
  `verify` records are precise source material), the changed-files list, existing memory files.
11
11
 
12
12
  Communicate with the user in the user's language. Memory file content follows the project's
13
13
  recorded comment/doc language.
14
14
 
15
- ## MEMORY_SHORT — write one short memory entry
15
+ ## Step 1 — write one short memory entry
16
16
 
17
17
  Create one file under `.easy-coding/memory/short/` following the format in
18
18
  `.easy-coding/memory/SHORT_MEMORY_TEMPLATE.md`. File naming convention:
@@ -23,6 +23,7 @@ Frontmatter (all fields required):
23
23
  ---
24
24
  memory_schema: 2
25
25
  id: SM-{YYYYMMDD}-{NN}
26
+ source_task: {current task id, exact}
26
27
  date: {YYYY-MM-DD}
27
28
  task_type: {feature | bugfix | refactor | perf | doc | workflow}
28
29
  project_mode: {startup | iteration}
@@ -45,6 +46,13 @@ conversation. Refer to SHORT_MEMORY_TEMPLATE.md for the complete section format.
45
46
 
46
47
  If the task was cross-repo, record the repo names involved and the collaboration reason.
47
48
 
49
+ After the file is successfully written, record the checkpoint immediately:
50
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py memory-short-complete --session-file <P> --file "<relative-short-memory-path>" --agent <agent-id>`.
51
+ Use the returned `status_context` as authoritative. On resume, if `memory_progress` already
52
+ shows `short_memory_written:true`, do not create a duplicate entry; continue from Step 2.
53
+ The state API validates `memory_schema: 2`, requires `source_task` to equal the current task id,
54
+ and fingerprints the file. Do not reuse an older task's memory file as this checkpoint.
55
+
48
56
  ## Supermodule memory routing
49
57
 
50
58
  If the current project config contains `supermodule.role: super-parent`, archive memory by
@@ -67,26 +75,27 @@ create a new one instead. Short memories serve as both a recent-detail sliding w
67
75
  distillation buffer for long-term memory.
68
76
 
69
77
  **Sliding window (informational):** The short memory directory has a soft cap defined by
70
- `memory.short_term_max` (default 10). MEMORY_SHORT only WRITES one entry per completed task
71
- it never counts, trims, or triggers distillation. Trimming is exclusively MEMORY_LONG's
72
- responsibility and only runs when the threshold is exceeded.
78
+ `memory.short_term_max` (default 10). Step 1 only writes and checkpoints one entry per
79
+ completed task. It never decides whether to distill.
73
80
 
74
- ## MEMORY_LONGdistill durable knowledge (CONDITIONAL)
81
+ ## Step 2 run the long-memory gate (CONDITIONAL)
75
82
 
76
83
  <HARD-GATE>
77
- MEMORY_LONG IS CONTROLLED BY THE STATE API `memory_long` INSTRUCTION.
84
+ LONG-MEMORY WORK IS CONTROLLED BY THE STATE API `memory` INSTRUCTION.
78
85
 
79
86
  Before performing ANY distillation work:
80
- 1. Read the `memory_long` object returned by the state API transition to MEMORY_LONG.
81
- If it is not visible in context, re-run the same transition command for MEMORY_LONG to
82
- re-emit the snapshot, then use that `memory_long` object.
83
- 2. Treat `memory_long.action` as authoritative. Do NOT recount short memories yourself and
87
+ 1. After Step 1 is checkpointed, call
88
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py memory-instruction --session-file <P>`.
89
+ This ordering is mandatory: the current task's short entry must be counted first.
90
+ The first successful call is frozen in `memory_progress.instruction`; resumed work reuses
91
+ the same action and trim count even after consumed short files are deleted.
92
+ 2. Treat the returned `memory.action` as authoritative. Do NOT recount short memories yourself and
84
93
  do NOT override the state API instruction with prompt reasoning.
85
- 3. If `action == "no-op"`: output "MEMORY_LONG: no-op (short memory count = {short_count},
86
- threshold = {short_term_max})" and immediately hand back to ec-workflow to advance to
87
- COMPLETE. Do NOT read long memory files, do NOT attempt distillation, do NOT modify any file.
88
- 4. If `action == "distill"`: distill exactly the older `trim_count` short-memory entries
89
- and keep the latest `short_term_keep` entries.
94
+ 3. If `action == "no-op"`: output "MEMORY: long-memory no-op (short memory count =
95
+ {short_count}, threshold = {short_term_max})". Do NOT read or modify long memory files.
96
+ 4. If `action == "distill"`: treat `memory.candidate_files` and `memory.kept_files` as the
97
+ frozen authoritative sets. Distill and delete exactly `candidate_files`; preserve every
98
+ `kept_files` entry. Do not rebuild either set from the live directory.
90
99
 
91
100
  This gate is absolute. Even a single short memory entry below threshold does NOT trigger
92
101
  long-term compression regardless of any other signal.
@@ -100,8 +109,8 @@ Three-file long memory:
100
109
  - `TECHNICAL.md` — architecture decisions, implementation patterns, gotchas.
101
110
 
102
111
  Distillation steps:
103
- 1. Use `memory_long.short_term_keep` and `memory_long.trim_count`. Keep the latest
104
- `short_term_keep` entries; the older `trim_count` entries become distillation candidates.
112
+ 1. Use `memory.candidate_files` and `memory.kept_files`; their sizes correspond to
113
+ `memory.trim_count` and the retained window calculated at instruction time.
105
114
  2. Read the `target_long` of candidate short memories; route to business/technical.
106
115
  3. **Progressive loading** — read only the existing long entries matching this round's
107
116
  domain/tags/related_files. No unbounded whole-repo memory scan.
@@ -116,6 +125,19 @@ Distillation steps:
116
125
  This is sliding-window consumption after successful distillation, not destructive
117
126
  deletion of durable long-term knowledge.
118
127
 
128
+ After either branch succeeds, record completion with the same authoritative action:
129
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py memory-complete --session-file <P> --action <no-op|distill> --agent <agent-id>`.
130
+ The state API rejects an action that disagrees with the current threshold calculation.
131
+ For `distill`, it also rejects completion while any frozen candidate still exists or any
132
+ frozen retained file is missing. A candidate checkpoint may disappear only because it is
133
+ explicitly listed in `candidate_files`.
134
+
135
+ ## Step 3 — request COMPLETE
136
+
137
+ Only after `memory_progress.completed:true`, hand control to ec-workflow to request
138
+ MEMORY -> COMPLETE. Present the standard confirmation/handoff/Other gate and stop. Do not
139
+ mark the task COMPLETE automatically.
140
+
119
141
  ## ABSTRACT backfill / update
120
142
 
121
143
  While distilling technical memory, if you detect an architecture change — module added or
@@ -30,9 +30,9 @@ result. No finding without a location.
30
30
 
31
31
  ## Verdict (exactly one)
32
32
 
33
- - `accept` — all dimensions pass. Advance to VERIFICATION.
33
+ - `accept` — all dimensions pass. Request REVIEW -> VERIFICATION.
34
34
  - `fix` — problems found, fixable within the current plan. Auto-fix via sub-agents (see below).
35
- - `replan` — the plan itself is flawed (wrong approach, missing design). Return to ANALYSIS.
35
+ - `replan` — the plan itself is flawed (wrong approach, missing design). Request REVIEW -> ANALYSIS.
36
36
  - `blocked` — external blocker (missing dependency, environment). Pause and report.
37
37
 
38
38
  ## Auto-fix flow (on `fix` verdict)
@@ -46,7 +46,7 @@ defects, not design decisions.
46
46
  ONLY escalate to the user when:
47
47
  - The fix requires a DESIGN CHOICE (two equally valid approaches, ambiguous requirement)
48
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
49
+ - The finding contradicts something the user explicitly confirmed at a stage boundary
50
50
  </HARD-GATE>
51
51
 
52
52
  Fix dispatch flow:
@@ -88,3 +88,6 @@ Platform spawn rule: {{platform_spawn_instruction}}
88
88
  Append `review` records to execution.jsonl, one per dimension:
89
89
  `{"type":"review","dimension":"correctness","findings":[{"file":"...","line":42,"issue":"...","severity":"warn"}]}`.
90
90
  Then state the verdict and hand back to ec-workflow.
91
+ For `accept` or `replan`, ec-workflow records the corresponding pending transition and presents
92
+ the standard confirmation/handoff/Other gate. A `fix` round stays inside REVIEW and therefore
93
+ does not create a status transition unless the outcome changes.
@@ -24,7 +24,7 @@ when you recognize abandonment intent in the user's message.
24
24
  clears session `current_task` so the next hook injection returns to Ready.
25
25
  Use the returned `status_context` as the authoritative status source for the rest of the
26
26
  current turn.
27
- 4. **No memory flow.** Do not run MEMORY_SHORT/LONG. An incomplete task's memory is dirty data.
27
+ 4. **No memory flow.** Do not run MEMORY. An incomplete task's memory is dirty data.
28
28
  5. **Linked tasks.** If the task has `spawned_from` or `spawned_tasks`, note the closure fact
29
29
  on the relation so a future agent understands the chain.
30
30
  6. Optionally append a closure note to `execution.jsonl` if there is context worth keeping for
@@ -54,7 +54,8 @@ Append one `verify` record per check:
54
54
 
55
55
  - All three pass AND coverage satisfied → present the verification result; wait for user
56
56
  acceptance. Do NOT archive yet.
57
- - Any failure → append the failing `verify` record, summarize failures, return to IMPLEMENT.
57
+ - Any failure → append the failing `verify` record, summarize failures, request
58
+ VERIFICATION -> IMPLEMENT, and wait at the standard confirmation/handoff/Other gate.
58
59
 
59
60
  ## 4. User acceptance and repair loop
60
61
 
@@ -62,9 +63,10 @@ After a green gate, present an acceptance summary: what changed (files + summari
62
63
  verification results (lint/type/test), and the coverage status. Then the user takes time to
63
64
  test manually. Their response routes:
64
65
 
65
- - **"accepted"** → trigger the archive flow (section 5).
66
+ - **"accepted"** → request VERIFICATION -> MEMORY and present the standard boundary gate.
66
67
  - **"problem here"** → scope judgment against the dev-spec:
67
- - in scope → return to IMPLEMENT to fix → re-REVIEW → re-VERIFICATION.
68
+ - in scope → request VERIFICATION -> IMPLEMENT, then re-REVIEW → re-VERIFICATION after
69
+ the user confirms each stage edge.
68
70
  - out of scope → propose a new task (`spawned_from` = current task id); the current task
69
71
  may archive now (if already satisfactory) or stay suspended.
70
72
  - **"cancel"** → ec-task-close.
@@ -72,21 +74,14 @@ test manually. Their response routes:
72
74
  Repair sizing: a trivial tweak is fixed and re-verified inside VERIFICATION; a logic/structure
73
75
  change formally returns to IMPLEMENT and re-walks REVIEW → VERIFICATION.
74
76
 
75
- ## 5. Archive flow (only after acceptance)
76
-
77
- Runs automatically once the user accepts:
78
- 1. MEMORY_SHORT call
79
- `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py transition --session-file <P> --stage MEMORY_SHORT --agent <agent-id>`,
80
- use the returned `status_context` as the latest status source, then hand control to
81
- ec-memory to write the short memory entry.
82
- 2. MEMORY_LONG — after MEMORY_SHORT returns, call
83
- `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py transition --session-file <P> --stage MEMORY_LONG --agent <agent-id>`,
84
- use the returned `status_context` and `memory_long` object as authoritative, then hand
85
- control to ec-memory to distill long memory or perform its no-op gate.
86
- 3. COMPLETE — after MEMORY_LONG returns, call
87
- `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py transition --session-file <P> --stage COMPLETE --agent <agent-id>`,
88
- which clears session `current_task` for the completed task. Use the returned
89
- `status_context`, then output the task summary (what was done, files changed, key
90
- decisions).
91
-
92
- Hand control back to ec-workflow at each transition; ec-workflow owns the stage writes.
77
+ ## 5. Archive entry (only after acceptance)
78
+
79
+ Acceptance does not mutate the stage directly. Hand control to ec-workflow to call
80
+ `request-transition --stage MEMORY`, then present:
81
+ 1. Confirm entering MEMORY
82
+ 2. Hand off to another agent
83
+ 3. Other (native free-form Other, or the third text option)
84
+
85
+ Only after confirmation may ec-workflow consume the pending edge and dispatch ec-memory.
86
+ ec-memory owns both short-memory creation and the conditional long-memory gate inside the
87
+ single MEMORY stage. It later requests MEMORY -> COMPLETE and waits for a separate confirmation.
@@ -65,27 +65,24 @@ replies are English.
65
65
  ## State machine
66
66
 
67
67
  ```
68
- INIT -> ANALYSIS -> WAITING_CONFIRM -> IMPLEMENT -> REVIEW -> VERIFICATION
69
- ^ ^ |
70
- | +---- repair loop -----+
71
- +--- revision ---+ |
72
- [user acceptance]
73
- |
74
- MEMORY_SHORT -> MEMORY_LONG -> COMPLETE
68
+ INIT -> ANALYSIS -> IMPLEMENT -> REVIEW -> VERIFICATION -> MEMORY -> COMPLETE
69
+ ^ ^ | |
70
+ +-- replan ---+ +--- fix -----+
71
+ ^ |
72
+ +------- repair ----------+
73
+ every edge --[explicit user confirmation by default]--> target stage
75
74
  any stage --[user abort via ec-task-close]--> CLOSED
76
75
  ```
77
76
 
78
77
  | Stage | Owner skill | What happens | Exit condition |
79
78
  |---|---|---|---|
80
- | INIT | ec-workflow | collect context, settle scope AND delivery form (change code vs. produce a document) | task understood |
81
- | ANALYSIS | ec-analysis | dev-spec + execution plan + test strategy | analysis presented |
82
- | WAITING_CONFIRM | ec-workflow | blocking gate; user reviews the plan | explicit user confirmation |
83
- | IMPLEMENT | ec-implementing | code changes per confirmed plan | all units done |
84
- | REVIEW | ec-reviewing | multi-dimension code review | verdict = accept |
85
- | VERIFICATION | ec-verification | hard gate: lint/typecheck/test + coverage | all pass AND user accepts |
86
- | MEMORY_SHORT | ec-memory | archive: short memory entry | written |
87
- | MEMORY_LONG | ec-memory | archive: long memory distillation (conditional — no-op when short memory is under threshold) | state API `memory_long` instruction handled |
88
- | COMPLETE | ec-workflow | clear current_task, set task status, summary | terminal |
79
+ | INIT | ec-workflow | collect context, settle scope AND delivery form (change code vs. produce a document) | work complete; request ANALYSIS |
80
+ | ANALYSIS | ec-analysis | dev-spec + execution plan + test strategy | analysis presented; request IMPLEMENT |
81
+ | IMPLEMENT | ec-implementing | code changes per confirmed plan | all units done; request REVIEW |
82
+ | REVIEW | ec-reviewing | multi-dimension code review | verdict selects a legal target; request it |
83
+ | VERIFICATION | ec-verification | hard gate: lint/typecheck/test + coverage | result selects MEMORY or IMPLEMENT; request it |
84
+ | MEMORY | ec-memory | write short memory, then run the conditional long-memory gate | memory work complete; request COMPLETE |
85
+ | COMPLETE | ec-workflow | clear current_task, set task status, summary | terminal after user confirms entry |
89
86
  | CLOSED | ec-task-close | user abort; no memory flow | terminal |
90
87
 
91
88
  > **INIT delivery-form rule.** When creating the task, `type` and `title` must faithfully
@@ -111,14 +108,31 @@ routing matches, and switching happens again.
111
108
  ## Transition rules (hard)
112
109
 
113
110
  - **Never skip a stage.** ANALYSIS cannot jump to VERIFICATION; IMPLEMENT cannot start before
114
- WAITING_CONFIRM passes. No exception for "simple" tasks — simple tasks have short analyses,
115
- not skipped ones.
116
- - **State before action.** Every stage advance is a two-step protocol: first persist the
117
- next stage through the state API, then run that stage's real work. Do not start analysis,
118
- implementation, review, verification, memory writing, closeout, or task switching while
111
+ the ANALYSIS -> IMPLEMENT confirmation gate passes. No exception for "simple" tasks —
112
+ simple tasks have short analyses, not skipped ones.
113
+ - **Every stage edge is a confirmation gate by default.** Stage completion does NOT change
114
+ `task.json.status`. It records a `pending_transition` through the state API, presents the
115
+ standard choices below, and stops. This applies to forward edges, repair/replan edges, and
116
+ MEMORY -> COMPLETE. Task creation entering INIT and the separately confirmed ec-task-close
117
+ flow do not add a redundant second prompt.
118
+ - **Native choice first (hard requirement).** After `request-transition` succeeds, you MUST
119
+ prefer the agent/platform's native user-choice tool whenever one is available. Do not render
120
+ a plain-text numbered list on a platform that can present selectable options and a free-form
121
+ Other input. Offer exactly these business branches through that native UI:
122
+ 1. Confirm entering/returning to `<target-stage>` (recommended)
123
+ 2. Hand off to another agent
124
+ 3. Other — use the native tool's built-in free-form Other input.
125
+ Plain-text numbered choices are fallback only: use them only when no native user-choice tool
126
+ exists. The runtime hook never mutates workflow state from user-prompt text. Native choice
127
+ results, numbered fallback replies, and every natural-language reply must be interpreted by
128
+ you against the current task and stored target before calling `confirm-transition` explicitly.
129
+ On Other feedback, cancel the pending edge before revising work or requesting a different
130
+ legal target. Never interpret silence, enthusiasm, or topic changes as confirmation.
131
+ - **State before action.** Every confirmed stage advance is a two-step protocol: first consume
132
+ the pending edge through `confirm-transition`, then run that stage's real work. Do not start
133
+ analysis, implementation, review, verification, memory writing, or closeout while
119
134
  `task.json.status` still names the previous stage. After every state API call, treat the
120
- returned snapshot/read-after-write state as authoritative for the next action and for the
121
- status line.
135
+ returned snapshot/read-after-write state as authoritative for the next action and status line.
122
136
  - **ANALYSIS entry gate.** When entering ANALYSIS, your FIRST TWO tool calls must be:
123
137
  (1) Read `.easy-coding/templates/dev-spec-skeleton.md`, then (2) Write its exact content
124
138
  to the task's dev-spec.md. This is a mechanical copy, not a generation task. Do not read
@@ -128,51 +142,45 @@ routing matches, and switching happens again.
128
142
  Additionally, ANALYSIS must stay faithful to the user's delivery form — it may NOT downgrade
129
143
  a code task to a report-only task — and the 改动范围 table must list only real project code,
130
144
  never `.easy-coding/` harness artifacts (ec-analysis HARD RULES 5 and 6).
131
- - **WAITING_CONFIRM is a real gate.** Proceed only on explicit user confirmation of BOTH the
132
- analysis conclusion and the test strategy. Silence, enthusiasm, or a topic change is not
133
- confirmation. Sole exception: `behavior.auto_mode: true` in `.easy-coding/config.yaml`
134
- AND the user asked for autonomous execution. `auto_mode` ONLY waives this confirmation step;
135
- it carries NO scope or delivery-form decision. Never cite `auto_mode` (or "the user already
136
- decided in INIT") to justify narrowing scope or downgrading a code task to a report.
137
- On confirmation, the harness hook may have already advanced the task to IMPLEMENT before
138
- this reply is generated. If the breadcrumb/state is still WAITING_CONFIRM, call the state
139
- API to transition to IMPLEMENT immediately; only after the read-after-write state says
140
- IMPLEMENT may you dispatch ec-implementing.
141
- - **On every transition** call the state API immediately (not at turn end):
142
- `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py transition --session-file <P> --stage <STAGE> --agent <agent-id>`.
145
+ - **Autonomous exception.** `behavior.auto_mode: true` in `.easy-coding/config.yaml` only
146
+ waives stage-boundary prompts when the user explicitly requested autonomous execution.
147
+ It carries NO scope or delivery-form decision. Never cite `auto_mode` to narrow scope,
148
+ downgrade a code task, or bypass a blocker that needs a real user decision.
149
+ - **At stage completion** request the legal target immediately (not at turn end):
150
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py request-transition --session-file <P> --stage <STAGE> --agent <agent-id> --reason "<why this edge is ready>"`.
151
+ This writes only `pending_transition`; it does not change the stage.
152
+ - **On user confirmation** read the current task's pending edge and call:
153
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py confirm-transition --session-file <P> --stage <STAGE> --agent <agent-id>`.
154
+ Only after the read-after-write status names the target stage may its action start.
155
+ - **On Other feedback or a changed outcome** call:
156
+ `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py cancel-transition --session-file <P> --agent <agent-id>`
157
+ before revising the current stage or requesting a different target.
143
158
  Do not hand-edit `status`, `stage_history`, `last_agent`, `current_task`, or session files.
144
159
  The command returns `status_line` and `status_context`; after any state-changing command,
145
160
  discard older hook-injected status text and use this returned context as the authoritative
146
161
  status source for the rest of the current turn.
147
- If the target stage is already present because a hook preflight completed it, do not issue a
148
- duplicate transition; use the latest snapshot and continue with the target stage's action.
149
162
  - **Hook enforcement.** The `inject-workflow-state` hook validates every stage transition
150
163
  against the state machine. If you see `[ILLEGAL-TRANSITION:...]` in the injected context,
151
164
  you MUST revert the task's status to the previous valid stage and explain why the
152
165
  transition was rejected. Do not proceed with an illegal stage.
153
- - **Repair loop sizing** (user acceptance window after VERIFICATION): a trivial tweak
154
- (one-line style fix, copy text) is fixed inside VERIFICATION and re-verified; a logic or
155
- structure change formally returns to IMPLEMENT and re-walks REVIEW VERIFICATION.
166
+ - **Repair loop sizing** (after VERIFICATION): a trivial tweak may be fixed inside
167
+ VERIFICATION and re-verified without a status change; a logic or structure change requests
168
+ VERIFICATION -> IMPLEMENT and waits at the standard confirmation gate before re-walking
169
+ REVIEW -> VERIFICATION.
156
170
  - **Scope guard** (repair loop): if the user's fix request falls outside the dev-spec scope
157
171
  (features or files absent from the change-scope table), say so explicitly and propose a
158
172
  new task with `spawned_from` set to the current task id. Never silently absorb scope creep.
159
173
  - **Task switching is allowed at any stage.** The suspended task retains its stage in
160
174
  task.json. Do not run memory flows for suspended tasks — only completed tasks get archived.
161
175
  - **Archive only after user acceptance.** VERIFICATION passing does not complete the task.
162
- After the user accepts, call state API transitions in order:
163
- MEMORY_SHORT MEMORY_LONG COMPLETE. Do not jump directly from VERIFICATION to COMPLETE.
164
- For each archive step, transition first and run the corresponding action second:
165
- after MEMORY_SHORT is persisted, write the short memory; after MEMORY_LONG is persisted,
166
- handle the `memory_long` instruction; after COMPLETE is persisted, produce the final summary.
167
- At each transition, use the state API's returned `status_context` as the latest status
168
- source before running the next action.
169
- When transitioning to MEMORY_LONG, pass the state API snapshot to ec-memory and treat its
170
- `memory_long` object as authoritative: `action == "no-op"` advances to COMPLETE without
171
- reading or writing long memory; `action == "distill"` runs distillation for `trim_count`
172
- older short-memory entries.
173
- - **COMPLETE closeout:** call the state API with `--stage COMPLETE`. The state API clears
174
- session `current_task` for terminal tasks, so the next hook injection returns to Ready.
175
- Then output a summary (what was done, files changed, key decisions).
176
+ A green gate requests VERIFICATION -> MEMORY and presents the standard choices. After the
177
+ user confirms, MEMORY writes one short entry first, records it through `memory-short-complete`,
178
+ then asks the state API for the authoritative `memory` instruction. `action == "no-op"`
179
+ skips long-memory reads/writes; `action == "distill"` processes exactly `trim_count` older
180
+ entries. Only after `memory-complete` may ec-memory request MEMORY -> COMPLETE.
181
+ - **COMPLETE closeout:** COMPLETE is also a confirmed edge. Once the user confirms it, the
182
+ state API clears session `current_task`, so the next hook injection returns to Ready. Then
183
+ output a summary (what was done, files changed, key decisions).
176
184
 
177
185
  ## Resume and handoff
178
186
 
@@ -186,16 +194,15 @@ Resuming an active task (whether from session restart, claim, handoff, or task s
186
194
  records tell you exactly where work stopped.
187
195
  3. If the task was claimed from another agent, read the latest `handoff` record first for the
188
196
  fast summary and tell the user which previous agent handed it off.
189
- 4. Tell the user what is being resumed and from which stage, then continue.
197
+ 4. If `pending_transition` exists, do not rerun the completed stage action. Re-present the
198
+ standard confirmation/handoff/Other choices for its stored target.
199
+ 5. Otherwise tell the user what is being resumed and from which stage, then continue.
190
200
 
191
201
  After a task switch, the same resume flow applies — the only difference is that `current_task`
192
202
  was just changed by the switching procedure rather than being loaded from a prior session.
193
203
 
194
- Offering handoff — at WAITING_CONFIRM, after presenting the plan, offer exactly:
195
- 1. Start implementation
196
- 2. Write handoff and stop
197
- 3. Revise the plan
198
- On option 2, call:
204
+ Offering handoff — every pending stage edge includes the standard handoff option. On that
205
+ option, call:
199
206
  `{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py handoff-task --session-file <P> --agent <agent-id> --summary "<dense context: plan shape, key decisions, user emphases>"`.
200
207
 
201
208
  The handoff record is target-less:
@@ -204,8 +211,9 @@ It records who handed the task off, not who will take it next. Do not ask the us
204
211
  the next agent, and do not invent or store a next-agent field. After writing handoff, stop
205
212
  owning the task; another agent can use ec-task-management or ec-workflow to claim it.
206
213
 
207
- Handoff is also legal at any other stage boundary on user request. The harness never switches
208
- agents by itself; the next agent claims the task explicitly.
214
+ Handoff preserves `pending_transition`, so the next agent resumes the same completed boundary
215
+ without rerunning stage work. The harness never switches agents by itself; the next agent
216
+ claims the task explicitly.
209
217
 
210
218
  ## Status line
211
219
 
@@ -35,16 +35,20 @@ First run `ec-init`; daily work goes through `ec-workflow`.
35
35
 
36
36
  ## Workflow discipline
37
37
 
38
- - Stages do not skip. WAITING_CONFIRM is a real gate implement only after the user confirms
39
- the plan and test strategy (unless `behavior.auto_mode` is on and the user asked for it).
38
+ - Stages do not skip. Every legal stage edge uses `pending_transition` and requires explicit
39
+ user confirmation by default. At each boundary, use the agent's native user-choice tool
40
+ whenever available to offer: confirm target stage, hand off to another agent, or its
41
+ free-form Other input. Plain-text numbered choices are fallback only. `auto_mode` only
42
+ waives prompts when configured and explicitly requested by the user; it never changes scope
43
+ or delivery form.
40
44
  - ANALYSIS must follow template-first: read `.easy-coding/templates/dev-spec-skeleton.md` then
41
45
  write its exact content to the task's dev-spec.md as the FIRST tool calls, then fill sections
42
46
  incrementally via edits. Reply to the user with the complete dev-spec.md content — never a
43
47
  summary table or custom format.
44
48
  - VERIFICATION is a hard gate: lint + typecheck + test must pass on fresh evidence, and
45
49
  coverage must match the test strategy, before a task can complete.
46
- - Archive (memory flow) runs only after explicit user acceptance — an unaccepted task's
47
- memory is dirty data.
50
+ - MEMORY combines short-memory creation and the conditional long-memory gate. Archive runs
51
+ only after explicit user acceptance — an unaccepted task's memory is dirty data.
48
52
  - NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.
49
53
  - All cross-platform modules (skills, hooks, references) must use universal agent protocols.
50
54
  Do not rely on any specific agent's proprietary conventions unless the module is explicitly
@@ -54,8 +58,8 @@ First run `ec-init`; daily work goes through `ec-workflow`.
54
58
  ## Runtime contract
55
59
 
56
60
  - Workflow state operations go through `{{platform_config_dir}}/hooks/easy_coding_state.py`;
57
- do not hand-edit session files, `current_task`, task `status`, `stage_history`, or
58
- `last_agent`.
61
+ do not hand-edit session files, `current_task`, task `status`, `stage_history`,
62
+ `pending_transition`, `memory_progress`, or `last_agent`.
59
63
  - The hook injects `[easy-coding:session-file:P]`; pass that path to the state script with
60
64
  `--session-file <P>` when changing the current task or stage.
61
65
  - Workflow session files live at `{{workflow_state_path}}`; the CLI only installs files and