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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-coding-harness",
3
- "version": "0.8.1-beta.0",
3
+ "version": "0.8.1-beta.1",
4
4
  "description": "CLI scaffold for installing Easy Coding harness files into agent-native directories.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,16 +13,6 @@
13
13
  }
14
14
  ],
15
15
  "UserPromptSubmit": [
16
- {
17
- "matcher": "",
18
- "hooks": [
19
- {
20
- "type": "command",
21
- "command": "{{platform_hook_session_start_command}}",
22
- "timeout": 15000
23
- }
24
- ]
25
- },
26
16
  {
27
17
  "matcher": "",
28
18
  "hooks": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "hooks": {
3
- "UserPromptSubmit": [
3
+ "SessionStart": [
4
4
  {
5
5
  "hooks": [
6
6
  {
@@ -9,7 +9,9 @@
9
9
  "timeout": 10
10
10
  }
11
11
  ]
12
- },
12
+ }
13
+ ],
14
+ "UserPromptSubmit": [
13
15
  {
14
16
  "hooks": [
15
17
  {
@@ -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
- ## Entry guard (idempotencyrun first)
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/{ppid}.json`;
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` — ensures the per-session file exists; performs legacy `state.json`
41
- migration; injects resume / init-required / handoff breadcrumbs. Idempotent.
42
- - `inject-workflow-state.py` — injects the `workflow-state` and `current-task` breadcrumbs so
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` also runs on `UserPromptSubmit` before `inject-workflow-state.py`, so
50
- every prompt receives a fresh status context even if the native session event is not surfaced
51
- to the model turn.
52
- - **Codex**: no `SessionStart` and no Agent tool. `session-start.py` and
53
- `inject-workflow-state.py` both hang off `UserPromptSubmit`; `inject-subagent-context.py`
54
- is skipped. Codex hooks also require user-level enablement (`[features] hooks = true`).
55
- - **Qoder**: like Claude Code (has Agent tool + Stop) but uses `UserPromptSubmit` for state
56
- injection. The `.qoder/settings.json` wrapper nests an extra `hooks` array.
57
-
58
- `session-start.py` is designed to be idempotent precisely because Claude/Codex/Qoder can fire it
59
- on `UserPromptSubmit` rather than only a real session-start event repeated calls are safe.
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
- `{NNN}_{YYYYMMDD}_{smart_name}.md`. The entry is immutable after creation.
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: SM-{YYYYMMDD}-{NN}
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
- and fingerprints the file. Do not reuse an older task's memory file as this checkpoint.
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": 5
9
+ "timeout": 10
19
10
  }
20
11
  ]
21
12
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  memory_schema: 2
3
- id: SM-YYYYMMDD-001
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: `{NNN}_{YYYYMMDD}_{smart_name}.md`
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; if date is missing or tied, by filename prefix
30
- > number ascending; then by filename ascending.
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 / 记忆 / 报告等)当作改动对象。本表为空仅允许用于"用户明确要求的无代码交付形态";代码类任务(重构/修复/功能)若此表为空,即为自我降级。