helloagents 3.0.37 → 3.0.39

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.37",
3
+ "version": "3.0.39",
4
4
  "description": "HelloAGENTS — The orchestration kernel that makes any AI CLI smarter. Adds intelligent routing, unified QA gates, safety guards, and notifications.",
5
5
  "author": {
6
6
  "name": "HelloWind",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.37",
3
+ "version": "3.0.39",
4
4
  "description": "HelloAGENTS — Quality-driven orchestration kernel for AI CLIs with intelligent routing, unified QA gates, safety guards, and notifications.",
5
5
  "author": {
6
6
  "name": "HelloWind",
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **A workflow layer for AI coding CLIs: skills, project knowledge, delivery checks, safer config writes, and resumable execution.**
10
10
 
11
- [![Version](https://img.shields.io/badge/version-3.0.37-orange.svg)](./package.json)
11
+ [![Version](https://img.shields.io/badge/version-3.0.39-orange.svg)](./package.json)
12
12
  [![npm](https://img.shields.io/npm/v/helloagents.svg)](https://www.npmjs.com/package/helloagents)
13
13
  [![Node](https://img.shields.io/badge/node-%3E%3D18-339933.svg)](./package.json)
14
14
  [![Skills](https://img.shields.io/badge/skills-14-6366f1.svg)](./skills)
@@ -184,12 +184,12 @@ Long tasks need a small recovery snapshot, but one shared state file is not safe
184
184
 
185
185
  HelloAGENTS now resolves the current state file from `state_path`:
186
186
 
187
- - with a stable session id: `.helloagents/sessions/<workspace>/<session>/STATE.md`
188
- - without a stable session id: `.helloagents/sessions/<workspace>/default/STATE.md`
187
+ - with a stable or reusable session id: `.helloagents/sessions/<workspace>/<session>/STATE.md`
188
+ - before a reusable session id is available: `.helloagents/sessions/<workspace>/default/STATE.md`
189
189
 
190
- `<workspace>` is the current Git branch, `detached-<sha>` for a detached HEAD, or `workspace` for non-Git projects. `.helloagents/sessions/active.json` only records the active session index.
190
+ `<workspace>` is the current Git branch, `detached-<sha>` for a detached HEAD, or `workspace` for non-Git projects. `<session>` is the current project-local session token. `.helloagents/sessions/active.json` only keeps the latest active workspace/session mapping plus alias bridges, so the same CLI session stays in one directory and `/resume` can reuse it.
191
191
 
192
- For project-local sessions, HelloAGENTS now only uses stable host identifiers such as `sessionId`, `conversationId`, `threadId`, or `HELLOAGENTS_NOTIFY_SESSION_ID`. It no longer uses terminal/window ids such as `WT_SESSION`, `TERM_SESSION_ID`, or `WINDOWID` to create extra project session directories.
192
+ For project-local sessions, HelloAGENTS first uses stable host identifiers such as `sessionId`, `conversationId`, `threadId`, or `HELLOAGENTS_NOTIFY_SESSION_ID`. If the host only exposes a window or terminal id such as `WT_SESSION`, `TERM_SESSION_ID`, or `WINDOWID`, HelloAGENTS uses it only as a lightweight alias bridge and reuses the mapped session first instead of fanning out duplicate directories. If a session starts before a stable host identifier is available, HelloAGENTS can begin in `default` and keep reusing that same active directory after the same CLI session later exposes a stable identifier, instead of splitting into a second session directory.
193
193
 
194
194
  `STATE.md` records where the current workflow stopped. It is not a universal memory file for every conversation. Codex `/goal` does not replace `state_path`, `turn-state`, or local evidence files; it only handles long-running continuation on the Codex side.
195
195
 
@@ -200,15 +200,17 @@ HelloAGENTS does not treat “tests passed” and “task complete” as the sam
200
200
  Runtime state now stays intentionally small:
201
201
 
202
202
  - `.helloagents/sessions/<workspace>/<session>/STATE.md`
203
+ - `.helloagents/sessions/<workspace>/<session>/runtime.json`
203
204
  - `.helloagents/sessions/active.json`
204
205
  - `.helloagents/sessions/<workspace>/<session>/artifacts/qa-review.json`
205
206
  - `.helloagents/sessions/<workspace>/<session>/artifacts/advisor.json`
206
207
  - `.helloagents/sessions/<workspace>/<session>/artifacts/visual.json`
207
208
  - `.helloagents/sessions/<workspace>/<session>/artifacts/closeout.json`
209
+ - optional `.helloagents/sessions/<workspace>/<session>/events.jsonl`
208
210
  - `~/.codex/.helloagents/notify-state.json` for Codex-native closeout de-duplication only
209
211
 
210
- `turn-state`, route context, and the artifact index are stored inside `STATE.md` metadata instead of a separate `capsule.json`. `events.jsonl` is opt-in trace output, not a default runtime file.
211
- Project-local `STATE.md` is now materialized more lazily, and legacy root-level `.helloagents/artifacts/*.log` files are cleaned up automatically instead of growing as a second history system.
212
+ `STATE.md` only keeps the human-readable recovery snapshot. `runtime.json` is machine-only and keeps the minimal runtime state. `artifacts/*.json` stays limited to structured receipts. `events.jsonl` remains opt-in trace output and stays off by default.
213
+ Project-local `STATE.md` is now materialized more lazily.
212
214
 
213
215
  Standard runtime evidence and transient runtime state now expire after 72 hours. Long-running Codex goal flows still keep their 720-hour upper bound where the workflow explicitly needs it.
214
216
 
@@ -507,6 +509,7 @@ Runtime state and evidence remain local to the working project:
507
509
 
508
510
  - `state_path`
509
511
  - `.helloagents/sessions/active.json`
512
+ - `.helloagents/sessions/<workspace>/<session>/runtime.json`
510
513
  - `.helloagents/sessions/<workspace>/<session>/artifacts/*.json`
511
514
 
512
515
  ### Temporary sessions outside project-local storage
@@ -517,9 +520,9 @@ For read-only work with no local output, if neither the current directory nor it
517
520
  ~/.helloagents/runtime/<scope-key>/
518
521
  ```
519
522
 
520
- This only stores short-lived `STATE.md` and `artifacts/`. Optional `events.jsonl` trace files are only written when trace mode is enabled. It is not project knowledge. Expired transient sessions are removed by TTL cleanup.
523
+ This only stores short-lived `STATE.md`, `runtime.json`, and `artifacts/`. Optional `events.jsonl` trace files are only written when trace mode is enabled. It is not project knowledge. Expired transient sessions are removed by TTL cleanup.
521
524
 
522
- Once the task creates or modifies local files, or otherwise leaves local output in the current project, HelloAGENTS creates the project-local `.helloagents/sessions/.../STATE.md` automatically instead of keeping that task only in the user-level transient runtime.
525
+ Once the task creates or modifies local files, or otherwise leaves local output in the current project, HelloAGENTS creates the project-local `.helloagents/sessions/<workspace>/<session>/STATE.md` automatically instead of keeping that task only in the user-level transient runtime.
523
526
 
524
527
  ### Knowledge creation rules
525
528
 
@@ -657,7 +660,7 @@ Codex is rules-file driven by default.
657
660
  - standby creates `~/.codex/helloagents -> ~/.helloagents/helloagents`
658
661
  - global mode installs the native local-plugin chain, but keeps `~/.helloagents/helloagents` as the single managed runtime source by linking plugin roots, plugin cache, and `~/.codex/helloagents` back to it
659
662
  - for Codex app/plugin discovery, `global` is the native path; `standby` remains the lighter default for explicit project work
660
- - cleanup removes only the HelloAGENTS-managed hook trust entries and legacy managed notify residues, while keeping user-owned hook state untouched
663
+ - cleanup removes only the HelloAGENTS-managed hook trust entries, while keeping user-owned hook state untouched
661
664
  - Codex hooks only synchronize runtime state and enforce Stop gates; they do not inject HelloAGENTS rules or route text through hook output
662
665
  - Codex closeout de-duplicates Stop hooks and native `codex-notify`, so one turn does not notify twice, and clientless delegated child-completion events stay silent when the managed Stop hook is active
663
666
  - `/goal` remains Codex-native. Enable it explicitly with `helloagents codex goals enable` when long-running plan execution is needed
@@ -678,11 +681,11 @@ The current suite covers:
678
681
  - one-shot shell and PowerShell lifecycle dispatch, plus wrapper env cleanup and mode-routing rules for install, update, cleanup, uninstall, and branch switching
679
682
  - Claude, Gemini, and Codex host integration behavior, including global-to-standby cleanup and failed native cleanup tracking
680
683
  - Codex managed `model_instructions_file`, `notify`, `hooks.json`, hook trust state, local plugin, marketplace, and cache behavior
681
- - Codex cleanup of legacy managed notify variants on Windows and canonical managed notify restoration rules
684
+ - Codex cleanup and canonical managed notify restoration rules
682
685
  - Codex `/goal` feature toggles, long-running route context, and goal-aware command contracts
683
686
  - `helloagents doctor`
684
687
  - project storage and `repo-shared` behavior
685
- - session-scoped `state_path`, runtime signals, and evidence
688
+ - workspace-session scoped `state_path`, runtime signals, and evidence
686
689
  - runtime injection, routing, guard, verification, visual evidence, delivery gates, closeout de-duplication, sub-agent wrapper and notification suppression, and successful-mode tracking after native install failures
687
690
  - README and skill contract alignment
688
691
 
package/README_CN.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **面向 AI 编码 CLI 的工作流层:技能、知识库、交付检查、更安全的配置写入,以及可恢复的执行流程。**
10
10
 
11
- [![Version](https://img.shields.io/badge/version-3.0.37-orange.svg)](./package.json)
11
+ [![Version](https://img.shields.io/badge/version-3.0.39-orange.svg)](./package.json)
12
12
  [![npm](https://img.shields.io/npm/v/helloagents.svg)](https://www.npmjs.com/package/helloagents)
13
13
  [![Node](https://img.shields.io/badge/node-%3E%3D18-339933.svg)](./package.json)
14
14
  [![Skills](https://img.shields.io/badge/skills-14-6366f1.svg)](./skills)
@@ -184,12 +184,12 @@ HelloAGENTS 可以在 `.helloagents/` 下创建和维护项目知识库。
184
184
 
185
185
  HelloAGENTS 现在只从 `state_path` 解析当前状态文件:
186
186
 
187
- - 宿主提供稳定会话标识时:`.helloagents/sessions/<workspace>/<session>/STATE.md`
188
- - 宿主未提供稳定会话标识时:`.helloagents/sessions/<workspace>/default/STATE.md`
187
+ - 宿主提供稳定会话标识或可复用会话标识时:`.helloagents/sessions/<workspace>/<session>/STATE.md`
188
+ - 暂时还拿不到可复用会话标识时:`.helloagents/sessions/<workspace>/default/STATE.md`
189
189
 
190
- `<workspace>` 是当前 Git 分支、detached HEAD 的 `detached-<sha>`,或非 Git 项目的 `workspace`。`.helloagents/sessions/active.json` 只记录当前活跃会话索引。
190
+ `<workspace>` 是当前 Git 分支、detached HEAD 的 `detached-<sha>`,或非 Git 项目的 `workspace`。`<session>` 是当前项目本地会话标识。`.helloagents/sessions/active.json` 只保留最近一次活跃的工作区/会话映射和 alias 桥接,这样同一个 CLI 会话会稳定落在同一个目录里,`/resume` 也能复用它。
191
191
 
192
- 对于项目本地会话目录,HelloAGENTS 现在只使用稳定宿主标识,如 `sessionId`、`conversationId`、`threadId` 或 `HELLOAGENTS_NOTIFY_SESSION_ID`。它不再使用 `WT_SESSION`、`TERM_SESSION_ID`、`WINDOWID` 这类终端或窗口标识去额外生成项目会话目录。
192
+ 对于项目本地会话目录,HelloAGENTS 会优先使用稳定宿主标识,如 `sessionId`、`conversationId`、`threadId` 或 `HELLOAGENTS_NOTIFY_SESSION_ID`。如果宿主只能提供 `WT_SESSION`、`TERM_SESSION_ID`、`WINDOWID` 这类窗口或终端标识,HelloAGENTS 只把它们当作轻量 alias 桥接,并优先复用已映射的会话目录,而不是继续分裂出重复目录。如果一个会话启动时还拿不到稳定宿主标识,HelloAGENTS 可以先落到 `default`,等同一个 CLI 会话后续拿到稳定标识时,仍继续复用这个活动目录,而不是再拆出第二个会话目录。
193
193
 
194
194
  `STATE.md` 只记录当前工作流做到哪里,不承担所有对话的统一记忆。Codex `/goal` 也不替代 `state_path`、`turn-state` 或本地证据文件;它只负责 Codex 侧的长程续跑。
195
195
 
@@ -200,15 +200,17 @@ HelloAGENTS 不把“命令通过”和“任务完成”简单画等号。交
200
200
  运行态现在尽量收敛,只保留真正有用的文件:
201
201
 
202
202
  - `.helloagents/sessions/<workspace>/<session>/STATE.md`
203
+ - `.helloagents/sessions/<workspace>/<session>/runtime.json`
203
204
  - `.helloagents/sessions/active.json`
204
205
  - `.helloagents/sessions/<workspace>/<session>/artifacts/qa-review.json`
205
206
  - `.helloagents/sessions/<workspace>/<session>/artifacts/advisor.json`
206
207
  - `.helloagents/sessions/<workspace>/<session>/artifacts/visual.json`
207
208
  - `.helloagents/sessions/<workspace>/<session>/artifacts/closeout.json`
209
+ - 可选 `.helloagents/sessions/<workspace>/<session>/events.jsonl`
208
210
  - 仅用于 Codex 原生收尾去重的 `~/.codex/.helloagents/notify-state.json`
209
211
 
210
- `turn-state`、路由上下文和 artifact 索引都写进 `STATE.md` 的元数据,不再单独生成 `capsule.json`。`events.jsonl` 改为可选 trace 输出,默认不写。
211
- 项目本地 `STATE.md` 现在会更晚创建;旧版残留的项目根 `.helloagents/artifacts/*.log` 也会自动清理,不再继续充当第二套历史系统。
212
+ `STATE.md` 只保留给人看的恢复快照。`runtime.json` 只给机器用,只保存极少量运行态。`artifacts/*.json` 只保留结构化收据。`events.jsonl` 仍是可选 trace 输出,默认不写。
213
+ 项目本地 `STATE.md` 现在会更晚创建。
212
214
 
213
215
  标准运行态证据和临时运行态现在默认 72 小时过期。只有工作流明确需要的长程 Codex goal 链路,才继续保留 720 小时上限。
214
216
 
@@ -511,6 +513,7 @@ Codex 全局模式由 HelloAGENTS 通过本地插件路径自动安装。
511
513
 
512
514
  - `state_path`
513
515
  - `.helloagents/sessions/active.json`
516
+ - `.helloagents/sessions/<workspace>/<session>/runtime.json`
514
517
  - `.helloagents/sessions/<workspace>/<session>/artifacts/*.json`
515
518
 
516
519
  ### 项目本地存储之外的临时会话
@@ -521,9 +524,9 @@ Codex 全局模式由 HelloAGENTS 通过本地插件路径自动安装。
521
524
  ~/.helloagents/runtime/<scope-key>/
522
525
  ```
523
526
 
524
- 这里仅保存短期的 `STATE.md` 和 `artifacts/`。`events.jsonl` 只有在启用 trace 时才会写入,不作为默认运行态文件。它也不属于项目知识库。过期临时会话会按 TTL 清理。
527
+ 这里仅保存短期的 `STATE.md`、`runtime.json` 和 `artifacts/`。`events.jsonl` 只有在启用 trace 时才会写入,不作为默认运行态文件。它也不属于项目知识库。过期临时会话会按 TTL 清理。
525
528
 
526
- 一旦任务会创建或修改本地文件,或会在当前项目留下本地输出,HelloAGENTS 就会自动创建项目本地 `.helloagents/sessions/.../STATE.md`,而不是只停留在用户级临时运行态。
529
+ 一旦任务会创建或修改本地文件,或会在当前项目留下本地输出,HelloAGENTS 就会自动创建项目本地 `.helloagents/sessions/<workspace>/<session>/STATE.md`,而不是只停留在用户级临时运行态。
527
530
 
528
531
  ### 知识创建规则
529
532
 
@@ -661,7 +664,7 @@ Codex 默认走规则文件驱动。
661
664
  - 标准模式创建 `~/.codex/helloagents -> ~/.helloagents/helloagents`
662
665
  - 全局模式安装原生本地插件流程,但仍把 `~/.helloagents/helloagents` 作为唯一受管运行时源;插件根目录、插件缓存和 `~/.codex/helloagents` 都会回链到它
663
666
  - 如果你主要看重 Codex app / 插件发现链路,优先使用 `global`;如果你主要看重更轻量、更显式的项目工作流,保留 `standby`
664
- - 清理时只删除 HelloAGENTS 自己写入的 hook trust 条目和旧式受管 notify 残留,不影响用户已有的 hook 状态
667
+ - 清理时只删除 HelloAGENTS 自己写入的 hook trust 条目,不影响用户已有的 hook 状态
665
668
  - Codex hooks 只做静默运行态同步和 Stop 门禁,不通过 hook 注入 HelloAGENTS 规则或路由说明
666
669
  - Codex 收尾会对 Stop hook 和原生 `codex-notify` 去重,避免同一轮重复通知;受管 Stop hook 生效时,client 为空的委派子任务完成事件也会保持静默
667
670
  - `/goal` 保持 Codex 原生能力;需要长程执行时,用 `helloagents codex goals enable` 显式启用
@@ -682,11 +685,11 @@ npm test
682
685
  - shell 与 PowerShell 一键脚本分发链路,以及包装脚本在安装、更新、清理、卸载和分支切换中的环境清理与模式传递规则
683
686
  - Claude、Gemini、Codex 的宿主集成行为,包括全局切回标准模式的清理和原生清理失败时的模式保留
684
687
  - Codex 受管 `model_instructions_file`、`notify`、`hooks.json`、hook trust 状态、本地插件、marketplace 和缓存行为
685
- - Windows 下 Codex 旧式受管 notify 变体的清理,以及受管 notify 恢复规则
688
+ - Codex 清理链路,以及受管 notify 恢复规则
686
689
  - Codex `/goal` 功能开关、长程路由上下文和 goal 感知命令契约
687
690
  - `helloagents doctor`
688
691
  - 项目存储和 `repo-shared`
689
- - 会话级 `state_path`、运行态信号和证据
692
+ - 工作区+会话级 `state_path`、运行态信号和证据
690
693
  - 运行时注入、选路、Guard、验证、视觉证据、交付门控、收尾去重、子代理外层格式与通知静默保护,以及原生安装失败后的模式记录
691
694
  - README 与 skill 契约一致性
692
695
 
package/bootstrap-lite.md CHANGED
@@ -221,9 +221,9 @@
221
221
  路径: {CWD}/.helloagents/
222
222
  所有文件的创建和更新必须按 templates/ 目录中对应模板的格式执行,不可自由发挥格式。
223
223
  - `.helloagents/` 表示项目本地存储路径,负责知识、方案、状态与运行态;它不再作为项目是否已初始化的判定信号
224
- - `state_path` 指向的状态文件始终保留在项目本地 `.helloagents/sessions/{workspace}/{session}/STATE.md`;当前会话的 `turn-state`、路由上下文和 artifact 索引写入这个文件的元数据,`artifacts/*.json` 仅在需要结构化证据时按需生成,`events.jsonl` 仅在显式 trace 模式下写入
225
- - `state_path` 是状态文件的唯一位置。宿主提供会话标识时,写入 `.helloagents/sessions/{workspace}/{session}/STATE.md`;没有稳定会话标识时,写入 `.helloagents/sessions/{workspace}/default/STATE.md`
226
- - `{workspace}` 为当前 Git 分支、`detached-{sha}` 或非 Git 项目的 `workspace`;`.helloagents/sessions/active.json` 只记录当前活跃会话索引,避免同一会话被拆成多个目录
224
+ - `state_path` 指向的状态文件始终保留在项目本地 `.helloagents/sessions/{workspace}/{session}/STATE.md`;当前会话的 `turn-state`、路由上下文和 artifact 索引写入同目录 `runtime.json`,`artifacts/*.json` 仅在需要结构化证据时按需生成,`events.jsonl` 仅在显式 trace 模式下写入
225
+ - `state_path` 是状态文件的唯一位置。宿主提供稳定会话标识时,写入 `.helloagents/sessions/{workspace}/{session}/STATE.md`;没有稳定或可复用会话标识时,写入 `.helloagents/sessions/{workspace}/default/STATE.md`
226
+ - `{workspace}` 为当前 Git 分支、`detached-{sha}` 或非 Git 项目的 `workspace`;`.helloagents/sessions/active.json` 只记录最近一次活跃的工作区/会话映射与 alias 桥接,避免同一 CLI 会话被拆成多个目录
227
227
  - 若 helloagents.json 中 `project_store_mode = "repo-shared"`,`context.md`、`guidelines.md`、`CHANGELOG.md`、`verify.yaml`、`DESIGN.md`、`modules/`、`plans/`、`archive/` 改按当前上下文中已注入的“当前项目存储”/“项目知识/方案目录”解析;未注入具体路径时,按当前存储模式自行解析,不要假定这些文件一定实际位于当前工作树中
228
228
  templates/ 查找路径(按优先级;首次确定模板根目录后,本会话复用):
229
229
  按上文 `~command` 路由中的相同技能根目录规则确定;确定根目录后读取其中的 `templates/`。
@@ -292,4 +292,3 @@ Tier 3 — 深入特定模块时读取:
292
292
 
293
293
  ### 项目文件
294
294
  根据知识库中的架构描述和模块索引,结合当前任务需求,按需读取相关的项目源码、配置和资源文件。不要一次性读取整个项目,先通过知识库了解项目结构,再有针对性地读取需要的文件。不要把项目级规则文件(`AGENTS.md`、`CLAUDE.md`、`.gemini/GEMINI.md`)当作普通项目文件重复读取。
295
-
package/bootstrap.md CHANGED
@@ -290,9 +290,9 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
290
290
  路径: {CWD}/.helloagents/
291
291
  所有文件的创建和更新必须按 templates/ 目录中对应模板的格式执行,不可自由发挥格式。
292
292
  - `.helloagents/` 表示项目本地存储路径,负责知识、方案、状态与运行态;它不再作为项目是否已初始化的判定信号
293
- - `state_path` 指向的状态文件始终保留在项目本地 `.helloagents/sessions/{workspace}/{session}/STATE.md`;当前会话的 `turn-state`、路由上下文和 artifact 索引写入这个文件的元数据,`artifacts/*.json` 仅在需要结构化证据时按需生成,`events.jsonl` 仅在显式 trace 模式下写入
294
- - `state_path` 是状态文件的唯一位置。宿主提供会话标识时,写入 `.helloagents/sessions/{workspace}/{session}/STATE.md`;没有稳定会话标识时,写入 `.helloagents/sessions/{workspace}/default/STATE.md`
295
- - `{workspace}` 为当前 Git 分支、`detached-{sha}` 或非 Git 项目的 `workspace`;`.helloagents/sessions/active.json` 只记录当前活跃会话索引,避免同一会话被拆成多个目录
293
+ - `state_path` 指向的状态文件始终保留在项目本地 `.helloagents/sessions/{workspace}/{session}/STATE.md`;当前会话的 `turn-state`、路由上下文和 artifact 索引写入同目录 `runtime.json`,`artifacts/*.json` 仅在需要结构化证据时按需生成,`events.jsonl` 仅在显式 trace 模式下写入
294
+ - `state_path` 是状态文件的唯一位置。宿主提供稳定会话标识时,写入 `.helloagents/sessions/{workspace}/{session}/STATE.md`;没有稳定或可复用会话标识时,写入 `.helloagents/sessions/{workspace}/default/STATE.md`
295
+ - `{workspace}` 为当前 Git 分支、`detached-{sha}` 或非 Git 项目的 `workspace`;`.helloagents/sessions/active.json` 只记录最近一次活跃的工作区/会话映射与 alias 桥接,避免同一 CLI 会话被拆成多个目录
296
296
  - 若 helloagents.json 中 `project_store_mode = "repo-shared"`,`context.md`、`guidelines.md`、`CHANGELOG.md`、`verify.yaml`、`DESIGN.md`、`modules/`、`plans/`、`archive/` 改按当前上下文中已注入的“当前项目存储”/“项目知识/方案目录”解析;未注入具体路径时,按当前存储模式自行解析,不要假定这些文件一定实际位于当前工作树中
297
297
  templates/ 查找路径(按优先级;首次确定模板根目录后,本会话复用):
298
298
  按上文相同的技能根目录规则确定;确定根目录后读取其中的 `templates/`。
@@ -361,4 +361,3 @@ Tier 3 — 深入特定模块时读取:
361
361
 
362
362
  ### 项目文件
363
363
  根据知识库中的架构描述和模块索引,结合当前任务需求,按需读取相关的项目源码、配置和资源文件。不要一次性读取整个项目,先通过知识库了解项目结构,再有针对性地读取需要的文件。不要把项目级规则文件(`AGENTS.md`、`CLAUDE.md`、`.gemini/GEMINI.md`)当作普通项目文件重复读取。
364
-
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.37",
3
+ "version": "3.0.39",
4
4
  "description": "Quality-driven orchestration kernel for AI CLIs",
5
5
  "contextFileName": "bootstrap.md",
6
6
  "author": "HelloWind",
package/install.ps1 CHANGED
@@ -124,7 +124,9 @@ switch ($Action) {
124
124
  Invoke-Npm -NpmArgs @("install", "-g", "helloagents")
125
125
  }
126
126
  }
127
- Sync-Hosts
127
+ if ($HasExplicitTarget) {
128
+ Sync-Hosts
129
+ }
128
130
  }
129
131
  "cleanup" {
130
132
  Cleanup-Hosts
package/install.sh CHANGED
@@ -144,7 +144,9 @@ case "$ACTION" in
144
144
  else
145
145
  npm update -g helloagents || npm install -g helloagents
146
146
  fi
147
- sync_hosts
147
+ if [ "$HAS_EXPLICIT_TARGET" -eq 1 ]; then
148
+ sync_hosts
149
+ fi
148
150
  ;;
149
151
  cleanup)
150
152
  cleanup_hosts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.37",
3
+ "version": "3.0.39",
4
4
  "type": "module",
5
5
  "description": "HelloAGENTS — The orchestration kernel that makes any AI CLI smarter. Adds intelligent routing, unified QA gates, safety guards, and notifications.",
6
6
  "author": "HelloWind",
@@ -13,13 +13,8 @@ export const CODEX_MANAGED_TOML_COMMENT = '# helloagents-managed'
13
13
  export const CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH = '~/.codex/AGENTS.md'
14
14
  export const CODEX_MANAGED_NOTIFY_COMMAND = 'helloagents-js'
15
15
  export const CODEX_MANAGED_NOTIFY_VALUE = `["${CODEX_MANAGED_NOTIFY_COMMAND}", "codex-notify"]`
16
- const CODEX_MANAGED_NOTIFY_LEGACY_VALUES = [
17
- `["${CODEX_MANAGED_NOTIFY_COMMAND}.cmd", "codex-notify"]`,
18
- `["${CODEX_MANAGED_NOTIFY_COMMAND}.exe", "codex-notify"]`,
19
- ]
20
16
  export const CODEX_MANAGED_TUI_NOTIFICATIONS_VALUE = '["plan-mode-prompt"]'
21
17
  export const CODEX_HOOKS_FEATURE_KEY = 'hooks'
22
- export const CODEX_LEGACY_HOOKS_FEATURE_KEY = 'codex_hooks'
23
18
  export const CODEX_GOALS_FEATURE_KEY = 'goals'
24
19
  export const CODEX_MANAGED_GOALS_FEATURE_LINE = `${CODEX_GOALS_FEATURE_KEY} = true ${CODEX_MANAGED_TOML_COMMENT}`
25
20
  export const CODEX_MANAGED_GOALS_DISABLED_LINE = `${CODEX_GOALS_FEATURE_KEY} = false ${CODEX_MANAGED_TOML_COMMENT}`
@@ -105,10 +100,6 @@ export function readCodexHooksFeatureLine(text) {
105
100
  return readCodexFeatureLine(text, CODEX_HOOKS_FEATURE_KEY)
106
101
  }
107
102
 
108
- export function readLegacyCodexHooksFeatureLine(text) {
109
- return readCodexFeatureLine(text, CODEX_LEGACY_HOOKS_FEATURE_KEY)
110
- }
111
-
112
103
  export function readCodexGoalsFeatureLine(text) {
113
104
  return readCodexFeatureLine(text, CODEX_GOALS_FEATURE_KEY)
114
105
  }
@@ -146,15 +137,6 @@ export function removeCodexGoalsFeatureConfig(text) {
146
137
  )
147
138
  }
148
139
 
149
- export function removeLegacyManagedCodexHooksFeatureConfig(text) {
150
- return removeTomlSectionLine(
151
- text,
152
- CODEX_FEATURES_HEADER,
153
- CODEX_LEGACY_HOOKS_FEATURE_KEY,
154
- isManagedLegacyCodexHooksFeature,
155
- )
156
- }
157
-
158
140
  export function restoreCodexGoalsFeatureConfig(text, { codexGoalsLine = '' } = {}) {
159
141
  if (!codexGoalsLine) return normalizeToml(text)
160
142
  return upsertTomlSectionLine(
@@ -173,10 +155,7 @@ export function isManagedCodexModelInstruction(line = '') {
173
155
  export function isManagedCodexNotify(line = '') {
174
156
  const value = String(line || '').replace(/\\/g, '/')
175
157
  return value.includes(CODEX_MANAGED_TOML_COMMENT)
176
- && (
177
- value.includes(CODEX_MANAGED_NOTIFY_VALUE)
178
- || CODEX_MANAGED_NOTIFY_LEGACY_VALUES.some((entry) => value.includes(entry))
179
- )
158
+ && value.includes(CODEX_MANAGED_NOTIFY_VALUE)
180
159
  }
181
160
 
182
161
  export function isManagedCodexTuiNotifications(line = '') {
@@ -193,10 +172,6 @@ export function isManagedCodexHooksFeature(line = '') {
193
172
  return isManagedFeatureLine(line, CODEX_HOOKS_FEATURE_KEY)
194
173
  }
195
174
 
196
- export function isManagedLegacyCodexHooksFeature(line = '') {
197
- return isManagedFeatureLine(line, CODEX_LEGACY_HOOKS_FEATURE_KEY)
198
- }
199
-
200
175
  export function isManagedCodexGoalsFeature(line = '') {
201
176
  return isManagedFeatureLine(line, CODEX_GOALS_FEATURE_KEY)
202
177
  }
@@ -17,12 +17,9 @@ import {
17
17
  isManagedCodexGoalsFeature,
18
18
  isManagedCodexModelInstruction,
19
19
  isManagedCodexNotify,
20
- isManagedLegacyCodexHooksFeature,
21
20
  readCodexGoalsFeatureLine,
22
- readLegacyCodexHooksFeatureLine,
23
21
  removeCodexGoalsFeatureConfig,
24
22
  removeCodexManagedTuiConfig,
25
- removeLegacyManagedCodexHooksFeatureConfig,
26
23
  removeCodexPluginConfig,
27
24
  restoreCodexGoalsFeatureConfig,
28
25
  restoreCodexTopLevelConfig,
@@ -156,12 +153,10 @@ function cleanupCodexManagedConfig(configPath, { removePluginConfig = false } =
156
153
  const currentModelInstructions = readTopLevelTomlLine(toml, 'model_instructions_file');
157
154
  const currentNotify = readTopLevelTomlBlock(toml, 'notify');
158
155
  const currentCodexGoalsFeature = readCodexGoalsFeatureLine(toml);
159
- const currentLegacyCodexHooksFeature = readLegacyCodexHooksFeatureLine(toml);
160
156
 
161
157
  const shouldRestoreModelInstructions = isManagedCodexModelInstruction(currentModelInstructions);
162
158
  const shouldRestoreNotify = isManagedCodexNotify(currentNotify);
163
159
  const shouldRestoreCodexGoalsFeature = isManagedCodexGoalsFeature(currentCodexGoalsFeature);
164
- const shouldRemoveLegacyCodexHooksFeature = isManagedLegacyCodexHooksFeature(currentLegacyCodexHooksFeature);
165
160
 
166
161
  if (removePluginConfig) {
167
162
  toml = removeCodexPluginConfig(toml);
@@ -170,9 +165,6 @@ function cleanupCodexManagedConfig(configPath, { removePluginConfig = false } =
170
165
  toml = removeCodexGoalsFeatureConfig(toml);
171
166
  }
172
167
  toml = removeCodexManagedTuiConfig(toml);
173
- if (shouldRemoveLegacyCodexHooksFeature) {
174
- toml = removeLegacyManagedCodexHooksFeatureConfig(toml);
175
- }
176
168
  if (shouldRestoreModelInstructions) {
177
169
  toml = removeTopLevelTomlLines(toml, (line) =>
178
170
  line.startsWith('model_instructions_file =') && isManagedCodexModelInstruction(line)).text;
@@ -220,7 +212,6 @@ export function installCodexStandby(home, pkgRoot) {
220
212
  modelInstructionsPath: CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH,
221
213
  });
222
214
  toml = installCodexManagedTuiConfig(toml);
223
- toml = removeLegacyManagedCodexHooksFeatureConfig(toml);
224
215
  safeWrite(configPath, toml);
225
216
  installCodexStandaloneHooks(home, pkgRoot);
226
217
 
@@ -312,7 +303,6 @@ export function installCodexGlobal(home, pkgRoot) {
312
303
  modelInstructionsPath: CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH,
313
304
  });
314
305
  toml = installCodexManagedTuiConfig(toml);
315
- toml = removeLegacyManagedCodexHooksFeatureConfig(toml);
316
306
  toml = upsertCodexPluginConfig(toml);
317
307
  safeWrite(configPath, toml);
318
308
  installCodexStandaloneHooks(home, pkgRoot);
@@ -9,7 +9,6 @@ import {
9
9
  CODEX_MANAGED_NOTIFY_VALUE,
10
10
  readCodexGoalsFeatureLine,
11
11
  readCodexHooksFeatureLine,
12
- readLegacyCodexHooksFeatureLine,
13
12
  } from './cli-codex-config.mjs'
14
13
  import {
15
14
  buildManagedCodexHookTrustEntries,
@@ -301,8 +300,6 @@ function buildCodexChecks(runtime, settings, trackedMode, detectedMode) {
301
300
  )
302
301
  const hooksFeatureLine = readCodexHooksFeatureLine(codexConfig)
303
302
  const goalsFeatureLine = readCodexGoalsFeatureLine(codexConfig)
304
- const legacyHooksFeatureLine = readLegacyCodexHooksFeatureLine(codexConfig)
305
-
306
303
  return {
307
304
  checks: {
308
305
  carrierMarker: (safeRead(join(codexDir, 'AGENTS.md')) || '').includes('HELLOAGENTS_START'),
@@ -319,10 +316,8 @@ function buildCodexChecks(runtime, settings, trackedMode, detectedMode) {
319
316
  modelInstructionsPathMatch: !!modelInstructionsLine && normalizePath(modelInstructionsLine).includes(`"${CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH}"`),
320
317
  codexNotify: codexConfig.includes('codex-notify'),
321
318
  notifyPathMatch: codexConfig.includes(CODEX_MANAGED_NOTIFY_VALUE),
322
- codexHooksFeature: !/^\s*hooks\s*=\s*false\b/.test(hooksFeatureLine)
323
- && !/^\s*codex_hooks\s*=\s*false\b/.test(legacyHooksFeatureLine),
319
+ codexHooksFeature: !/^\s*hooks\s*=\s*false\b/.test(hooksFeatureLine),
324
320
  codexGoalsFeature: /^\s*goals\s*=\s*true\b/.test(goalsFeatureLine),
325
- legacyCodexHooksFeature: Boolean(legacyHooksFeatureLine),
326
321
  standaloneHooks: JSON.stringify(codexHooks.hooks || {}).includes('helloagents'),
327
322
  standaloneHooksMatch: managedHooksMatch(codexHooks.hooks || {}, expectedHooks),
328
323
  managedHookTrust: expectedHookTrust.every((entry) => managedHookTrust.has(entry.key)),
@@ -369,7 +364,6 @@ export function inspectCodexDoctor(runtime, settings) {
369
364
  if (!checks.pluginVersionMatch && !pluginVersion && detectedMode === 'global') notes.push(runtime.msg('未读到 global 插件根目录版本信息', 'Global plugin root version was not readable'))
370
365
  if (!checks.pluginCacheVersionMatch && !cacheVersion && detectedMode === 'global') notes.push(runtime.msg('未读到 global 插件缓存版本信息', 'Global plugin cache version was not readable'))
371
366
  if (detectedMode !== 'none' && !checks.codexGoalsFeature) notes.push(runtime.msg('Codex /goal 未启用;如需长程执行,可运行 `helloagents codex goals enable`。', 'Codex /goal is not enabled; run `helloagents codex goals enable` if you need long-running goals.'))
372
- if (detectedMode !== 'none' && checks.legacyCodexHooksFeature) notes.push(runtime.msg('检测到旧版 `codex_hooks`;HelloAGENTS 只兼容 Codex 最新版,请移除旧 key。', 'Legacy `codex_hooks` was detected; HelloAGENTS targets latest Codex only, so remove the old key.'))
373
367
  if (!nativeDoctor.available) notes.push(runtime.msg('未检测到原生 `codex doctor`;当前仅检查 HelloAGENTS 受管覆盖层。', 'Native `codex doctor` was not available; only the HelloAGENTS managed overlay was checked.'))
374
368
 
375
369
  const status = summarizeDoctorStatus(issues, { trackedMode, detectedMode })
@@ -349,6 +349,10 @@ function attachTurnSession(payload = {}, cwd = payload.cwd || process.cwd()) {
349
349
  allowPpidFallback: !isProjectRuntimeActive(cwd),
350
350
  });
351
351
  if (!sessionId || payload.sessionId) return payload;
352
+ const aliasSource = String(process.env.HELLOAGENTS_NOTIFY_SESSION_ID || process.env.WT_SESSION || process.env.TERM_SESSION_ID || process.env.WINDOWID || '').trim();
353
+ if (aliasSource) {
354
+ return { ...payload, sessionId, _helloagentsSessionAlias: aliasSource };
355
+ }
352
356
  return { ...payload, sessionId };
353
357
  }
354
358
 
@@ -10,12 +10,10 @@ import {
10
10
  writeJsonFileAtomic,
11
11
  } from './runtime-scope.mjs'
12
12
  import { LONG_RUNNING_TTL_MS } from './runtime-ttl.mjs'
13
- import { readStateDocument } from './state-document.mjs'
13
+ import { looksLikeAutoCreatedState, readStateDocument } from './state-document.mjs'
14
14
 
15
15
  export const PROJECT_SESSION_CLEANUP_COOLDOWN_MS = 10 * 60 * 1000
16
16
  export const PROJECT_SESSION_MAX_AGE_MS = LONG_RUNNING_TTL_MS
17
- const AUTO_CREATED_STATE_MARKER = '由运行时自动创建;后续按实际任务重写'
18
-
19
17
  function removePath(filePath, result, bucket) {
20
18
  try {
21
19
  rmSync(filePath, { recursive: true, force: true })
@@ -25,10 +23,6 @@ function removePath(filePath, result, bucket) {
25
23
  }
26
24
  }
27
25
 
28
- function isDebugLog(entryName = '') {
29
- return /\.log$/i.test(entryName)
30
- }
31
-
32
26
  function isDirectoryEmptyRecursive(dirPath) {
33
27
  const entries = readdirSync(dirPath, { withFileTypes: true })
34
28
  if (entries.length === 0) return true
@@ -38,9 +32,10 @@ function isDirectoryEmptyRecursive(dirPath) {
38
32
  })
39
33
  }
40
34
 
41
- function shouldKeepSession(active, workspace, session) {
35
+ function shouldKeepNestedSession(active, workspace, sessionName) {
42
36
  const activeWorkspace = active.workspace || active.branch || ''
43
- return activeWorkspace === workspace && active.session === session
37
+ const activeSession = active.session || ''
38
+ return activeWorkspace === workspace && activeSession === sessionName
44
39
  }
45
40
 
46
41
  function readCleanupCheckedAt(active) {
@@ -65,9 +60,8 @@ function isAutoCreatedSeedSession(sessionDir) {
65
60
  const statePath = join(sessionDir, 'STATE.md')
66
61
  if (!existsSync(statePath)) return false
67
62
 
68
- const { metadata, body } = readStateDocument(statePath)
69
- if (metadata && typeof metadata === 'object' && Object.keys(metadata).length > 0) return false
70
- return String(body || '').includes(AUTO_CREATED_STATE_MARKER)
63
+ const { body } = readStateDocument(statePath)
64
+ return looksLikeAutoCreatedState(body)
71
65
  }
72
66
 
73
67
  function readSessionStateMtimeMs(sessionDir) {
@@ -94,32 +88,6 @@ function cleanupTransientSessionTemps(sessionsDir, result) {
94
88
  }
95
89
  }
96
90
 
97
- function cleanupLegacyProjectArtifacts(activationDir, result) {
98
- const artifactsDir = join(activationDir, 'artifacts')
99
- if (!existsSync(artifactsDir)) return
100
-
101
- let removableEntries = []
102
- try {
103
- removableEntries = readdirSync(artifactsDir, { withFileTypes: true })
104
- } catch (error) {
105
- result.errors.push(`${artifactsDir}: ${error.message}`)
106
- return
107
- }
108
-
109
- for (const entry of removableEntries) {
110
- if (!entry.isFile() || !isDebugLog(entry.name)) continue
111
- removePath(join(artifactsDir, entry.name), result, 'removedLegacyArtifacts')
112
- }
113
-
114
- try {
115
- if (isDirectoryEmptyRecursive(artifactsDir)) {
116
- removePath(artifactsDir, result, 'removedLegacyArtifacts')
117
- }
118
- } catch (error) {
119
- result.errors.push(`${artifactsDir}: ${error.message}`)
120
- }
121
- }
122
-
123
91
  export function cleanupProjectSessions(cwd, { now = Date.now(), minIntervalMs = 0, maxAgeMs = PROJECT_SESSION_MAX_AGE_MS } = {}) {
124
92
  const projectRoot = getProjectRoot(cwd)
125
93
  const activationDir = getProjectActivationDir(projectRoot)
@@ -133,7 +101,6 @@ export function cleanupProjectSessions(cwd, { now = Date.now(), minIntervalMs =
133
101
  removedNoStateDirs: [],
134
102
  removedSeedDirs: [],
135
103
  removedTempFiles: [],
136
- removedLegacyArtifacts: [],
137
104
  errors: [],
138
105
  skipped: false,
139
106
  }
@@ -152,33 +119,32 @@ export function cleanupProjectSessions(cwd, { now = Date.now(), minIntervalMs =
152
119
  } catch (error) {
153
120
  result.errors.push(`${sessionsDir}: ${error.message}`)
154
121
  }
155
- cleanupLegacyProjectArtifacts(activationDir, result)
156
122
 
157
123
  for (const workspaceEntry of readdirSync(sessionsDir, { withFileTypes: true })) {
158
124
  if (!workspaceEntry.isDirectory()) continue
159
125
  const workspaceDir = join(sessionsDir, workspaceEntry.name)
160
-
161
- for (const sessionEntry of readdirSync(workspaceDir, { withFileTypes: true })) {
162
- if (!sessionEntry.isDirectory()) continue
163
- const sessionDir = join(workspaceDir, sessionEntry.name)
164
- if (shouldKeepSession(active, workspaceEntry.name, sessionEntry.name)) continue
165
-
166
- try {
126
+ try {
127
+ const nestedEntries = readdirSync(workspaceDir, { withFileTypes: true }).filter((entry) => entry.isDirectory())
128
+ for (const nestedEntry of nestedEntries) {
129
+ const sessionDir = join(workspaceDir, nestedEntry.name)
130
+ if (shouldKeepNestedSession(active, workspaceEntry.name, nestedEntry.name)) continue
167
131
  if (isDirectoryEmptyRecursive(sessionDir)) {
168
132
  removePath(sessionDir, result, 'removedEmptyDirs')
169
- } else if (!hasStateSnapshot(sessionDir)) {
133
+ continue
134
+ }
135
+ if (!hasStateSnapshot(sessionDir)) {
170
136
  removePath(sessionDir, result, 'removedNoStateDirs')
171
- } else if (isAutoCreatedSeedSession(sessionDir)) {
137
+ continue
138
+ }
139
+ if (isAutoCreatedSeedSession(sessionDir)) {
172
140
  removePath(sessionDir, result, 'removedSeedDirs')
173
- } else if (isStaleStateSession(sessionDir, now, maxAgeMs)) {
141
+ continue
142
+ }
143
+ if (isStaleStateSession(sessionDir, now, maxAgeMs)) {
174
144
  removePath(sessionDir, result, 'removedInactiveDirs')
175
145
  }
176
- } catch (error) {
177
- result.errors.push(`${sessionDir}: ${error.message}`)
178
146
  }
179
- }
180
147
 
181
- try {
182
148
  if (isDirectoryEmptyRecursive(workspaceDir)) {
183
149
  removePath(workspaceDir, result, 'removedEmptyDirs')
184
150
  }
@@ -114,8 +114,8 @@ export function getProjectSessionStateScope(cwd, options = {}) {
114
114
  const scope = getProjectSessionScope(cwd, normalizeRuntimeOptions(options))
115
115
 
116
116
  return {
117
- stateScope: 'session',
118
- stateSessionToken: scope.session,
117
+ stateScope: 'workspace-session',
118
+ stateSessionToken: scope.session || '',
119
119
  stateSessionMode: scope.sessionMode,
120
120
  stateWorkspace: scope.workspace || scope.branch,
121
121
  sessionDir: scope.sessionDir,
@@ -246,9 +246,6 @@ export function buildProjectStorageHint(cwd, options = {}) {
246
246
  const summary = getProjectStoreSummary(cwd, options)
247
247
  const hints = []
248
248
  hints.push(`当前状态文件写入 \`${summary.promptStatePath}\``)
249
- if (summary.stateSessionMode === 'default') {
250
- hints.push(`当前宿主未提供稳定会话标识,因此使用工作区默认位置 \`${summary.stateSessionToken}\``)
251
- }
252
249
  if (summary.usesSharedStore) {
253
250
  hints.push(`项目存储:\`project_store_mode=repo-shared\`;项目本地存储/会话运行态目录仍是 \`${summary.promptActivationDir}\`,知识库/方案目录改为 \`${summary.promptStoreDir}\``)
254
251
  }
@@ -277,9 +274,6 @@ export function buildProjectStorageBlock(cwd, options = {}) {
277
274
 
278
275
  const explanations = []
279
276
  explanations.push('说明:状态文件只使用 `state_path`。')
280
- if (summary.stateSessionMode === 'default') {
281
- explanations.push('说明:当前宿主未提供稳定会话标识,因此使用工作区默认位置。')
282
- }
283
277
  if (summary.usesSharedStore) {
284
278
  explanations.push('说明:状态文件与会话产物写项目本地存储目录;`context.md`、`guidelines.md`、`DESIGN.md`、`verify.yaml`、`modules/`、`plans/`、`archive/` 写知识库/方案目录。')
285
279
  } else {