easy-coding-harness 0.8.1-beta.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 +8 -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-memory/SKILL.md +8 -3
- 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.
|
|
@@ -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
|
|
|
@@ -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 / 记忆 / 报告等)当作改动对象。本表为空仅允许用于"用户明确要求的无代码交付形态";代码类任务(重构/修复/功能)若此表为空,即为自我降级。
|