easy-coding-harness 0.8.0 → 0.8.1-beta.1
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/CHANGELOG.md +14 -0
- package/dist/cli.js +104 -42
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/claude/settings.json +0 -10
- package/templates/codex/hooks.json +4 -2
- package/templates/common/bundled-skills/ec-init/SKILL.md +23 -3
- package/templates/common/bundled-skills/ec-meta/references/local-architecture/README.md +2 -1
- package/templates/common/bundled-skills/ec-meta/references/platform-files/README.md +19 -15
- package/templates/common/skills/ec-analysis/SKILL.md +21 -3
- package/templates/common/skills/ec-memory/SKILL.md +8 -3
- package/templates/common/skills/ec-workflow/SKILL.md +22 -8
- package/templates/main-constraint/AGENTS.md.tpl +10 -0
- package/templates/main-constraint/CLAUDE.md.tpl +10 -0
- package/templates/qoder/settings.json +1 -10
- package/templates/runtime/memory/SHORT_MEMORY_TEMPLATE.md +7 -4
- package/templates/runtime/templates/dev-spec-skeleton.md +1 -1
- package/templates/shared-hooks/easy_coding_state.py +328 -11
- package/templates/shared-hooks/inject-subagent-context.py +19 -3
- package/templates/shared-hooks/inject-workflow-state.py +3 -6
- package/templates/shared-hooks/session-start.py +3 -108
package/package.json
CHANGED
|
@@ -44,10 +44,30 @@ Field whitelist: `mode`, `language`, `test.*`, `build.*`, `lint.*`. Do not inven
|
|
|
44
44
|
top-level keys. Do not copy any CLI-owned field (`harness_version`, `agents`, …) into this
|
|
45
45
|
file.
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Project-init preflight (run first — read-only)
|
|
48
48
|
|
|
49
49
|
1. Read `.easy-coding/tasks/project-init/task.json`.
|
|
50
50
|
- File missing → the CLI never ran. Tell the user to run `easy-coding init` first. Stop.
|
|
51
|
+
- File present → record its `status` for the entry dispatch below, but do not start the
|
|
52
|
+
compliance scan or initialization yet.
|
|
53
|
+
2. Do not call the state API or write any project asset until this file-existence check passes.
|
|
54
|
+
|
|
55
|
+
## Session path resolution (run after preflight — before any project write)
|
|
56
|
+
|
|
57
|
+
Resolve one stable session path `<P>` and reuse it for the entire skill run:
|
|
58
|
+
|
|
59
|
+
1. If hook context contains `[easy-coding:session-file:P]`, use that exact path.
|
|
60
|
+
2. Otherwise run
|
|
61
|
+
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py snapshot --agent <agent-id>`
|
|
62
|
+
and use the returned `session_file` as `<P>`. This is the compatibility path for an explicit
|
|
63
|
+
ec-init invocation before the platform has surfaced hook context.
|
|
64
|
+
3. If snapshot fails or does not return a safe session path, stop before writing any project
|
|
65
|
+
asset and tell the user to enable or approve the platform hooks. Never execute a command with
|
|
66
|
+
the literal placeholder `<P>`.
|
|
67
|
+
|
|
68
|
+
## Entry dispatch (idempotency — run after session resolution)
|
|
69
|
+
|
|
70
|
+
1. Use the `status` read during the project-init preflight.
|
|
51
71
|
- `status == "COMPLETE"` → already initialized. Run the **compliance scan** (see below),
|
|
52
72
|
then exit.
|
|
53
73
|
- `status == "PENDING"` → proceed with full initialization.
|
|
@@ -89,7 +109,7 @@ On decline: exit with the gap list as a reference for the user to address manual
|
|
|
89
109
|
|
|
90
110
|
**Clear upgrade marker:** After the compliance scan completes (whether all checks passed or
|
|
91
111
|
gaps were fixed), run
|
|
92
|
-
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py project-init-complete --agent <agent-id>`.
|
|
112
|
+
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py project-init-complete --session-file <P> --agent <agent-id>`.
|
|
93
113
|
This removes `pending_init_since` and clears the "Waiting init · Upgrade" status line so the
|
|
94
114
|
user is no longer prompted on every session. Use the returned `status_context` as the current
|
|
95
115
|
status source.
|
|
@@ -147,7 +167,7 @@ agent must be able to see what was generated and on what evidence.
|
|
|
147
167
|
Also ensure `SHORT_MEMORY_TEMPLATE.md` exists in `memory/` as format reference. Never write
|
|
148
168
|
fake entries.
|
|
149
169
|
7. **Mark complete** — write the final `init_log` entry, then run
|
|
150
|
-
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py project-init-complete --agent <agent-id>`.
|
|
170
|
+
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py project-init-complete --session-file <P> --agent <agent-id>`.
|
|
151
171
|
Use the returned `status_context`, then tell the user initialization is done and daily work
|
|
152
172
|
goes through `{{skill_trigger}}ec-workflow`.
|
|
153
173
|
|
|
@@ -52,7 +52,8 @@ confirms two critical gates, lite uses the same gates but forces IMPLEMENT -> VE
|
|
|
52
52
|
and auto advances legal edges automatically. Lite never enters REVIEW. VERIFICATION remains
|
|
53
53
|
the code-task fresh-evidence hard gate, and MEMORY keeps the conditional long-memory threshold
|
|
54
54
|
gate. The active task
|
|
55
|
-
pointer lives in `sessions/{
|
|
55
|
+
pointer lives in `sessions/{agent}-{session-id}.json` (with an agent-prefixed PPID fallback only
|
|
56
|
+
when a hook payload has no logical session ID);
|
|
56
57
|
when the task reaches `COMPLETE` or `CLOSED`, the state API clears `current_task` so the
|
|
57
58
|
session returns to Ready. Each task's stage persists in its `task.json`. Hooks inject the
|
|
58
59
|
session and task state as breadcrumbs so every reply can render the status line.
|
|
@@ -37,23 +37,27 @@ Python runtime files are shared verbatim across platforms (only the JSON wrapper
|
|
|
37
37
|
transitions, and task state reads.
|
|
38
38
|
- `easy_coding_status.py` — renders the Markdown status line and machine breadcrumbs from
|
|
39
39
|
state API snapshots.
|
|
40
|
-
- `session-start.py` —
|
|
41
|
-
|
|
42
|
-
- `inject-workflow-state.py` — injects the `workflow-state`
|
|
43
|
-
the status line can render.
|
|
40
|
+
- `session-start.py` — initializes the per-session file on native session-start events and emits
|
|
41
|
+
resume / init-required / handoff breadcrumbs.
|
|
42
|
+
- `inject-workflow-state.py` — idempotently ensures the session and injects the `workflow-state`
|
|
43
|
+
and `current-task` breadcrumbs so the status line can render.
|
|
44
44
|
- `inject-subagent-context.py` — injects the sub-agent guard before an Agent tool call.
|
|
45
45
|
|
|
46
46
|
Wrapper differences:
|
|
47
47
|
|
|
48
48
|
- **Claude Code**: full event set — `SessionStart`, `UserPromptSubmit`, `PreToolUse(Agent)`.
|
|
49
|
-
`session-start.py`
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **Qoder**:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
`session-start.py` owns native session initialization, while `inject-workflow-state.py` is the
|
|
50
|
+
single session writer on each prompt.
|
|
51
|
+
- **Codex**: `session-start.py` runs on `SessionStart`, while
|
|
52
|
+
`inject-workflow-state.py` runs on `UserPromptSubmit`; `inject-subagent-context.py` is
|
|
53
|
+
skipped because Codex has no Agent tool hook. Codex hooks also require user-level enablement
|
|
54
|
+
(`[features] hooks = true`).
|
|
55
|
+
- **Qoder**: has no separate session-start registration, so `inject-workflow-state.py` performs
|
|
56
|
+
idempotent initialization and state injection as the single `UserPromptSubmit` writer. Qoder
|
|
57
|
+
also has Agent tool + Stop hooks, and `.qoder/settings.json` nests an extra `hooks` array.
|
|
58
|
+
|
|
59
|
+
Every session-writing hook resolves the same agent-prefixed logical session key from the hook
|
|
60
|
+
payload, for example `codex-<session-id>.json`. On first use it adopts a legacy `<ppid>.json`
|
|
61
|
+
file when present. A global atomic migration lock ensures only one concurrently starting session
|
|
62
|
+
can claim legacy `state.json`; the winner commits its canonical session before removing the old
|
|
63
|
+
state and releasing the lock.
|
|
@@ -263,11 +263,29 @@ Re-output the COMPLETE revised dev-spec.md:
|
|
|
263
263
|
3. Overwrite the `plan` record in execution.jsonl with the new strategy.
|
|
264
264
|
4. For code tasks, update test-strategy.md if test scope changed. For read-only tasks, keep the
|
|
265
265
|
file absent.
|
|
266
|
-
5. Request ANALYSIS -> IMPLEMENT again and present the
|
|
266
|
+
5. Request ANALYSIS -> IMPLEMENT again and present the complete confirmation/handoff/Other gate
|
|
267
|
+
defined below.
|
|
268
|
+
|
|
269
|
+
## ANALYSIS -> IMPLEMENT choice gate (hard)
|
|
270
|
+
|
|
271
|
+
The same turn that `request-transition` succeeds must invoke the platform's native user-choice
|
|
272
|
+
tool when one is available. The visible branches are:
|
|
273
|
+
|
|
274
|
+
1. Confirm entering IMPLEMENT (recommended)
|
|
275
|
+
2. Hand off to another agent
|
|
276
|
+
3. Other — use the native free-form Other input for revisions or another instruction.
|
|
277
|
+
|
|
278
|
+
If no native choice tool exists, render all three branches as a numbered text fallback. An empty,
|
|
279
|
+
dismissed, timed-out, or unparseable result keeps the task in ANALYSIS with its pending edge and
|
|
280
|
+
may retry the native choice at most once per assistant turn. If that retry also fails, stop the
|
|
281
|
+
current turn and re-present the complete gate on the next user interaction. Never replace the gate
|
|
282
|
+
with only "reply confirm", "confirm execution", or a statement that no valid choice was received,
|
|
283
|
+
and never invoke native choice repeatedly in the same turn. Choosing handoff delegates to
|
|
284
|
+
ec-workflow's existing target-less `handoff-task` flow; do not ask the user to name the next agent.
|
|
267
285
|
|
|
268
286
|
## End state
|
|
269
287
|
|
|
270
288
|
Read dev-spec.md back from disk and output the COMPLETE content as your reply to the user —
|
|
271
|
-
not a summary, not a different format, not a table you invented. Then ask ec-workflow to
|
|
272
|
-
|
|
289
|
+
not a summary, not a different format, not a table you invented. Then ask ec-workflow to record
|
|
290
|
+
`pending_transition: ANALYSIS -> IMPLEMENT`, immediately present the complete choice gate above,
|
|
273
291
|
and stop. Never start implementing from this skill.
|
|
@@ -18,13 +18,17 @@ recorded comment/doc language.
|
|
|
18
18
|
|
|
19
19
|
Create one file under `.easy-coding/memory/short/` following the format in
|
|
20
20
|
`.easy-coding/memory/SHORT_MEMORY_TEMPLATE.md`. File naming convention:
|
|
21
|
-
`{
|
|
21
|
+
`{memory_id}_{YYYYMMDD}_{smart_name}.md`. Generate the id first with
|
|
22
|
+
`{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py memory-new-id --session-file <P> --agent <agent-id>`.
|
|
23
|
+
Use the returned `memory_id` unchanged as both the filename prefix and the frontmatter `id`.
|
|
24
|
+
It uses UUIDv7, so agents never scan the directory or calculate a shared numeric sequence.
|
|
25
|
+
Keep the readable `smart_name` suffix. The entry is immutable after creation.
|
|
22
26
|
Frontmatter (all fields required):
|
|
23
27
|
|
|
24
28
|
```yaml
|
|
25
29
|
---
|
|
26
30
|
memory_schema: 2
|
|
27
|
-
id:
|
|
31
|
+
id: {memory_id returned by memory-new-id, exact}
|
|
28
32
|
source_task: {current task id, exact}
|
|
29
33
|
date: {YYYY-MM-DD}
|
|
30
34
|
task_type: {feature | bugfix | refactor | perf | doc | workflow}
|
|
@@ -53,7 +57,8 @@ After the file is successfully written, record the checkpoint immediately:
|
|
|
53
57
|
Use the returned `status_context` as authoritative. On resume, if `memory_progress` already
|
|
54
58
|
shows `short_memory_written:true`, do not create a duplicate entry; continue from Step 2.
|
|
55
59
|
The state API validates `memory_schema: 2`, requires `source_task` to equal the current task id,
|
|
56
|
-
|
|
60
|
+
requires a UUIDv7 id that exactly matches the filename prefix, and fingerprints the file. Do not
|
|
61
|
+
reuse an older task's memory file as this checkpoint.
|
|
57
62
|
|
|
58
63
|
## Supermodule memory routing
|
|
59
64
|
|
|
@@ -144,11 +144,12 @@ it, routing matches, and switching happens again.
|
|
|
144
144
|
- **Always-automatic mechanical edges.** After INIT work completes, call `auto-transition` for
|
|
145
145
|
ANALYSIS. After `memory-complete`, call `auto-transition` for COMPLETE. These two edges never
|
|
146
146
|
create `pending_transition` in any mode.
|
|
147
|
-
- **Native choice
|
|
148
|
-
call `request-transition`. After it succeeds,
|
|
149
|
-
|
|
150
|
-
a
|
|
151
|
-
|
|
147
|
+
- **Native choice rendering is mandatory (hard requirement).** When the effective mode requires
|
|
148
|
+
confirmation, call `request-transition`. After it succeeds, the boundary is not fully presented
|
|
149
|
+
until the user can actually choose every required business branch. When the agent/platform
|
|
150
|
+
exposes a native user-choice tool, you MUST actually invoke it in the same turn; mentioning the
|
|
151
|
+
tool, recommending a reply, or printing only a confirmation sentence is not a substitute. Offer
|
|
152
|
+
exactly these business branches through that native UI:
|
|
152
153
|
1. Confirm entering/returning to `<target-stage>` (recommended)
|
|
153
154
|
2. Hand off to another agent
|
|
154
155
|
3. Other — use the native tool's built-in free-form Other input.
|
|
@@ -158,9 +159,22 @@ it, routing matches, and switching happens again.
|
|
|
158
159
|
VERIFICATION, cancel that edge, request IMPLEMENT -> VERIFICATION, and immediately confirm it
|
|
159
160
|
because that selection is explicit confirmation of the alternate target.
|
|
160
161
|
Plain-text numbered choices are fallback only: use them only when no native user-choice tool
|
|
161
|
-
exists.
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
exists. An ordinary gate must list all three branches rather than collapsing to "reply confirm":
|
|
163
|
+
`1. Confirm entering/returning to <target-stage> (recommended)`,
|
|
164
|
+
`2. Hand off to another agent`, `3. Other (describe revisions or another instruction)`.
|
|
165
|
+
The code-task IMPLEMENT completion fallback must preserve its special branch set:
|
|
166
|
+
`1. Enter REVIEW (recommended)`, `2. Skip REVIEW and enter VERIFICATION`,
|
|
167
|
+
`3. Hand off to another agent`, `4. Other (describe revisions or another instruction)`.
|
|
168
|
+
An empty, dismissed, timed-out, or unparseable choice result is not confirmation. Preserve the
|
|
169
|
+
pending edge and re-present the complete native choice UI at most once per assistant turn. If
|
|
170
|
+
that retry is also empty, dismissed, timed out, or unparseable, stop the current turn with the
|
|
171
|
+
pending edge intact and re-present the gate on the next user interaction; never call the native
|
|
172
|
+
choice tool repeatedly in the same turn. If native choice is no longer available, render the
|
|
173
|
+
appropriate complete numbered fallback. Never report "no valid choice" and then show only a
|
|
174
|
+
confirmation instruction. The runtime hook never mutates workflow state from user-prompt text.
|
|
175
|
+
Native choice results, numbered fallback replies, and every natural-language reply must be
|
|
176
|
+
interpreted by you against the current task and stored target before calling
|
|
177
|
+
`confirm-transition` explicitly.
|
|
164
178
|
On Other feedback, cancel the pending edge before revising work or requesting a different
|
|
165
179
|
legal target. Never interpret silence, enthusiasm, or topic changes as confirmation.
|
|
166
180
|
- **State before action.** Every confirmation-required stage advance is a two-step protocol: first
|
|
@@ -47,6 +47,16 @@ First run `ec-init`; daily work goes through `ec-workflow`.
|
|
|
47
47
|
- Confirmation-required edges use `pending_transition`; automatic edges use the restricted
|
|
48
48
|
`auto-transition` API. A read-only task creates no test-strategy.md, never enters REVIEW,
|
|
49
49
|
VERIFICATION, or MEMORY, and writes no task memory.
|
|
50
|
+
- A confirmation-required boundary is not fully presented until the user can choose its complete
|
|
51
|
+
business branches. When a native user-choice tool is available, invoke it in the same turn with
|
|
52
|
+
the complete gate. An ordinary gate offers "confirm entering/returning to the target stage"
|
|
53
|
+
(recommended) and "hand off to another agent", with free-form Other for revisions. The special
|
|
54
|
+
approve-mode code IMPLEMENT gate must instead preserve enter REVIEW, skip to VERIFICATION, and
|
|
55
|
+
handoff, with free-form Other. Only when no native choice tool exists may you show the matching
|
|
56
|
+
complete numbered fallback. Empty, dismissed, timed-out, or unparseable results preserve the
|
|
57
|
+
pending edge and may retry native choice at most once per assistant turn; after a failed retry,
|
|
58
|
+
stop the turn and re-present the gate on the next user interaction. Never degrade to only
|
|
59
|
+
"reply confirm" or repeatedly invoke native choice in the same turn.
|
|
50
60
|
- When `[easy-coding:no-harness]` is injected, do not emit an Easy Coding status line and ignore
|
|
51
61
|
only Easy Coding workflow/stage orchestration for this session. Continue honoring every
|
|
52
62
|
non-Easy-Coding skill, hook, and instruction. Do not clear or mutate the suspended task.
|
|
@@ -45,6 +45,16 @@ First run `/ec-init`; daily work goes through `/ec-workflow`.
|
|
|
45
45
|
- Confirmation-required edges use `pending_transition`; automatic edges use the restricted
|
|
46
46
|
`auto-transition` API. A read-only task creates no test-strategy.md, never enters REVIEW,
|
|
47
47
|
VERIFICATION, or MEMORY, and writes no task memory.
|
|
48
|
+
- A confirmation-required boundary is not fully presented until the user can choose its complete
|
|
49
|
+
business branches. When a native user-choice tool is available, invoke it in the same turn with
|
|
50
|
+
the complete gate. An ordinary gate offers "confirm entering/returning to the target stage"
|
|
51
|
+
(recommended) and "hand off to another agent", with free-form Other for revisions. The special
|
|
52
|
+
approve-mode code IMPLEMENT gate must instead preserve enter REVIEW, skip to VERIFICATION, and
|
|
53
|
+
handoff, with free-form Other. Only when no native choice tool exists may you show the matching
|
|
54
|
+
complete numbered fallback. Empty, dismissed, timed-out, or unparseable results preserve the
|
|
55
|
+
pending edge and may retry native choice at most once per assistant turn; after a failed retry,
|
|
56
|
+
stop the turn and re-present the gate on the next user interaction. Never degrade to only
|
|
57
|
+
"reply confirm" or repeatedly invoke native choice in the same turn.
|
|
48
58
|
- When `[easy-coding:no-harness]` is injected, do not emit an Easy Coding status line and ignore
|
|
49
59
|
only Easy Coding workflow/stage orchestration for this session. Continue honoring every
|
|
50
60
|
non-Easy-Coding skill, hook, and instruction. Do not clear or mutate the suspended task.
|
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
3
|
"UserPromptSubmit": [
|
|
4
|
-
{
|
|
5
|
-
"hooks": [
|
|
6
|
-
{
|
|
7
|
-
"type": "command",
|
|
8
|
-
"command": "{{platform_hook_session_start_command}}",
|
|
9
|
-
"timeout": 10
|
|
10
|
-
}
|
|
11
|
-
]
|
|
12
|
-
},
|
|
13
4
|
{
|
|
14
5
|
"hooks": [
|
|
15
6
|
{
|
|
16
7
|
"type": "command",
|
|
17
8
|
"command": "{{platform_hook_inject_workflow_state_command}}",
|
|
18
|
-
"timeout":
|
|
9
|
+
"timeout": 10
|
|
19
10
|
}
|
|
20
11
|
]
|
|
21
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
memory_schema: 2
|
|
3
|
-
id:
|
|
3
|
+
id: {memory_id}
|
|
4
4
|
source_task: MM-DD-task-slug
|
|
5
5
|
date: YYYY-MM-DD
|
|
6
6
|
task_type: feature | bugfix | refactor | perf | doc | workflow
|
|
@@ -20,14 +20,17 @@ target_long: BUSINESS | TECHNICAL | BOTH | NONE
|
|
|
20
20
|
# Short Memory Template
|
|
21
21
|
|
|
22
22
|
> This template defines the format for files under `.easy-coding/memory/short/`.
|
|
23
|
-
> File naming convention: `{
|
|
23
|
+
> File naming convention: `{memory_id}_{YYYYMMDD}_{smart_name}.md`
|
|
24
|
+
> Generate `memory_id` through the state API `memory-new-id` command and use it unchanged as
|
|
25
|
+
> both the filename prefix and this frontmatter `id`. The UUIDv7 id is safe for concurrent agents.
|
|
26
|
+
> Keep `smart_name` as the readable summary suffix.
|
|
24
27
|
> `source_task` must exactly match the current workflow task id from `task.json`.
|
|
25
28
|
> Short memories are immutable after creation — they serve as a sliding window of recent
|
|
26
29
|
> details and a buffer for long-term distillation candidates.
|
|
27
30
|
> When short memories reach the threshold (default 10), the newest 5 are kept as recent
|
|
28
31
|
> context; older entries are distillation candidates for long-term memory.
|
|
29
|
-
> Sorting: by frontmatter `date` ascending
|
|
30
|
-
>
|
|
32
|
+
> Sorting: by frontmatter `date` ascending, then by frontmatter `id`, then by filename. Legacy
|
|
33
|
+
> `SM-YYYYMMDD-NNN` ids sort before UUIDv7 ids on the same date for upgrade compatibility.
|
|
31
34
|
|
|
32
35
|
## Task Summary
|
|
33
36
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- **核心类 / 页面 / 接口**:[[EC_TODO:核心类 / 页面 / 接口]]
|
|
30
30
|
- **数据库变更**:[[EC_TODO:有/无]]
|
|
31
31
|
- **接口变更**:[[EC_TODO:有/无]]
|
|
32
|
-
- **关联历史任务**:[[EC_TODO
|
|
32
|
+
- **关联历史任务**:[[EC_TODO:相关短期记忆 ID;无则“无”]]
|
|
33
33
|
|
|
34
34
|
### 改动范围
|
|
35
35
|
> 只列真实项目源码/配置文件的改动。禁止把 `.easy-coding/` 下的 harness 产物(dev-spec / execution.jsonl / test-strategy / 记忆 / 报告等)当作改动对象。本表为空仅允许用于"用户明确要求的无代码交付形态";代码类任务(重构/修复/功能)若此表为空,即为自我降级。
|