@lmzhen/dsh-evolution-core 0.32.2 → 0.32.4

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.
Files changed (36) hide show
  1. package/README.md +5 -5
  2. package/lib/composition/index.js +2 -2
  3. package/lib/{composition-DSesmTvf.js → composition-3QFfEe56.js} +1 -1
  4. package/lib/{ensure-BuWsjPGD.js → ensure-C2tUoF5U.js} +1 -1
  5. package/lib/{errors-Br2-uUSK.js → errors-DRZ9A187.js} +1 -0
  6. package/lib/index.js +475 -113
  7. package/lib/restrictor.js +1 -1
  8. package/lib/subagent/index.js +1 -1
  9. package/lib/types/errors.d.ts +1 -0
  10. package/lib/types/errors.js +1 -0
  11. package/lib/types/index.d.ts +1 -0
  12. package/lib/types/index.js +1 -0
  13. package/lib/types/mutation-storage-adapter.d.ts +5 -2
  14. package/lib/types/mutation-storage-adapter.js +59 -22
  15. package/lib/types/mutation-unit.d.ts +2 -2
  16. package/lib/types/mutation-unit.js +18 -45
  17. package/lib/types/params.js +1 -1
  18. package/lib/types/platform-services.js +0 -1
  19. package/lib/types/session-projection.d.ts +32 -0
  20. package/lib/types/session-projection.js +51 -3
  21. package/lib/types/skill-reads.d.ts +19 -0
  22. package/lib/types/skill-reads.js +42 -2
  23. package/lib/types/skill-store.js +4 -2
  24. package/lib/types/tool-dispatch.d.ts +16 -0
  25. package/lib/types/tool-dispatch.js +42 -11
  26. package/lib/types/unit-journal.d.ts +5 -3
  27. package/lib/types/unit-journal.js +7 -6
  28. package/lib/types/unit-storage.d.ts +5 -4
  29. package/lib/types/unit-storage.js +8 -8
  30. package/lib/types/unit-transaction.js +5 -7
  31. package/lib/types/write-gates.d.ts +4 -0
  32. package/lib/types/write-gates.js +16 -1
  33. package/lib/types/write-kernel.d.ts +81 -0
  34. package/lib/types/write-kernel.js +155 -0
  35. package/package.json +2 -2
  36. package/persisted-write-inventory.json +1 -10
package/README.md CHANGED
@@ -20,7 +20,7 @@ section, and importing the package root is its only entry.
20
20
  sweeper exists yet). Measured on a 3.6 KB skill written 41 times: a 5.7 KB index over 20 entries and
21
21
  41 blob files totalling 150 KB (41x the live body); unchanged writes add nothing. Plan disk accordingly
22
22
  or remove `.history/blobs` entries by hand.
23
- - Skill-library writes are serialized in-process; cross-process writers to the SAME skill file must go through the single-file paths (`update`, `patch`, `writeSupportFile`). The full concurrency model, its two-phase exceptions and their provenance are in Notes and history.
23
+ - Skill-library writes are serialized **in-process**. The shipped IO backend declares single-process; a second process sharing `DSH_HOME` is unsupported. The full concurrency model, its two-phase exceptions and their provenance are in Notes and history.
24
24
 
25
25
  **Runtime invariant:** No companion is published. The platform auto-assembles nothing and the family mounts no `<pkg>/invariant` cordis row, so a companion here would never execute (v37 S2.1 / I-3).
26
26
 
@@ -44,9 +44,9 @@ section, and importing the package root is its only entry.
44
44
  - `create` is INSIDE the serial chain and, when a transact backend is bound, its exists check runs inside the same per-file transact (v18); `archive`/`consolidate` are rename-based two-phase paths and stay outside the single-file serial chain.
45
45
  - **v18 residual (updated):** `create`, `removeSupportFile` and `setPinned` now run on the serial chain (`removeSupportFile`'s delete also goes through the per-file transact), so the remaining single-file residual is the protection TOCTOU (a marker check outside the transact) and the multi-file two-phase paths `archive`/`consolidate`/`restructure`.
46
46
  - The race needs a concurrent mutator on the SAME skill file/package; the exposure is acknowledged and the protection check is the next candidate (see the v18 optimization plan, E-5).
47
- - When the backend provides `transact` (nodeEvolutionIo and the io adapter do), the constructor binds it BY DEFAULT since 0.3.27: the single-file entry points (`update`, `patch`, `writeSupportFile`, and each per-file piece of `restructure`) run their read→write inside the cross-process lock for every instantiation, so same-file concurrent writes from different processes no longer resolve to last-writer-wins there.
47
+ - The constructor binds the IO backend's `transact` by default since 0.3.27: the single-file entry points (`update`, `patch`, `writeSupportFile`, and each per-file piece of `restructure`) run their read→write inside that transaction. The shipped backend is **single-process**, so this does not protect two processes sharing `DSH_HOME`.
48
48
  - The two-phase paths deliberately stay outside that lock: `create`'s exists probe runs inside the transact when a transact backend is bound (v18), so only a transact-less custom backend can still double-pass the probe across processes; `archive`/`consolidate` are rename-based with best-effort rollback (an archive loser's rollback surfaces the raw failure when the source vanished), and `restructure`'s multi-file swap can expose an interleaved tree to a concurrent reader.
49
- - These residual windows are documented rather than locked: cross-process writers to the SAME skill file should serialize through the single-file paths above.
49
+ - These residual windows are documented rather than locked. The shipped backend is single-process; cross-process writers to the same skill file are unsupported and must not be treated as serialized.
50
50
 
51
51
  ## Events (the family's own, process-local)
52
52
 
@@ -63,7 +63,6 @@ session log made the session unresumable (A-line P0-1), which is why the payload
63
63
  | `evolution/review-completed` | emit (notification) | `evolution-review` after a plugin branch settles |
64
64
  | `evolution/memory-applied` | emit (notification) | `memory` after a memory write |
65
65
  | `evolution/memory-provider-registered` | emit (notification) | `memory` when a provider registers |
66
- | `evolution/approval-decided` | emit (notification) | `evolution-approval` after an approval decision lands |
67
66
 
68
67
  `evolution/plan-applied` is declared for old activity ledgers; `evolution-review` now emits it from a branch review once that branch settles, with real action counts. `reviewMode: "inject"` still emits none by design.
69
68
 
@@ -94,6 +93,7 @@ consumer — so the `@mode` target stays at six (decision 10, provisional: keep)
94
93
  | `E-309` / `E-310` | your write lost a revision race, or the settings service refused it (the reason is included) | re-read with `/evolution params` and retry |
95
94
  | `E-317` | you declined the confirmation the tool asked before creating or deleting a skill (a foreground create or bare delete asks when `skillWriteConfirm` is `ask` or `timeout`; the default `auto` does not ask at all) | nothing was written; repeat the call if you do want it |
96
95
  | `E-318` | a write without a read: the session never loaded that skill, so the write is refused (skills only; the foreground operator session is exempt) | load it with the `skill` tool, then repeat the write |
96
+ | `E-326` | a support-file write without reading THAT file: reading `SKILL.md` is not evidence for `references/x.md` | read the exact support file, then repeat the write |
97
97
  | `E-320` | the profile home is not reported by this host, so the legacy settings document cannot be located | run the command in a session whose profile home is set |
98
98
  | `E-321` | no evolution-io provider is mounted, so the legacy settings document cannot be read | mount the `evolution-io-node` row |
99
99
  | `E-322` | a cross-field parameter constraint would be broken (the field, its floor and the attempted value are included) | raise the value to the named floor, or lower the sibling first |
@@ -101,7 +101,7 @@ consumer — so the `@mode` target stays at six (decision 10, provisional: keep)
101
101
  | `E-324` | a restricted preset could not be created (parent preset read, YAML parse, register, or restrictor mount failed; the reason is included) | run `/evolution doctor` to see the preset id, allow set and failure reason; the review/maintenance channel stays unavailable until it is fixed |
102
102
  | `E-325` | the host data plane is unavailable: no connection service, so panel/approval routes are not registered | use `/evolution pending`, `approve`, `reject` (same service methods) and run `/evolution doctor` |
103
103
  | `E-319` | the confirmation before a create or bare delete went unanswered for `skillWriteConfirmTimeoutSeconds` (`skillWriteConfirm: 'timeout'`), so the write was cancelled | set `skillWriteConfirm` to `auto` (write without asking), keep `ask` (wait until answered), or raise the timeout |
104
- Symptom → next step; the exact text of every code (`E-301`–`E-325`) is stored once in
104
+ Symptom → next step; the exact text of every code (`E-301`–`E-326`) is stored once in
105
105
 
106
106
  ## 单元与撤销(本包负责的契约)
107
107
 
@@ -1,3 +1,3 @@
1
- import { a as entryListSchema, c as MAINTAINER_PRESET_ID, d as RESTRICTED_TOOLS_ROW_ID, f as RESTRICTOR_MODULE, h as restrictedPresetId, i as composeRestrictedPresetDefinition, l as RESTRICTED_PRESET_DELIVERY, m as normalizeAllow, n as ensureRestrictedPreset, o as parsePresetRows, p as REVIEWER_PRESET_ID, r as restrictedPresetState, s as EVOLUTION_PRESET_IDS, t as disposeRestrictedPreset, u as RESTRICTED_PRESET_DISPLAY } from "../ensure-BuWsjPGD.js";
2
- import { C as trimTrailingBlankLines, S as rowSiblingEnd, _ as presetRowId, a as composePresetComposition, b as resolveBasePresetPatch, c as composePresetRow, d as listDirectories, f as loadRowOverrides, g as presetRowBody, h as presetRowBlock, i as basePresetPlugins, l as compositionRowIds, m as presetPatchText, n as AGENT_PRESET_ROOT_HINT, o as composePresetEntry, p as mergePresetRow, r as EMPTY_PATCH_SEED, s as composePresetInsert, t as AGENT_PRESET_PACKAGE, u as denseBlockSequence, v as probeDesktopScope, x as rowBlockSpan, y as removePresetRow } from "../composition-DSesmTvf.js";
1
+ import { a as entryListSchema, c as MAINTAINER_PRESET_ID, d as RESTRICTED_TOOLS_ROW_ID, f as RESTRICTOR_MODULE, h as restrictedPresetId, i as composeRestrictedPresetDefinition, l as RESTRICTED_PRESET_DELIVERY, m as normalizeAllow, n as ensureRestrictedPreset, o as parsePresetRows, p as REVIEWER_PRESET_ID, r as restrictedPresetState, s as EVOLUTION_PRESET_IDS, t as disposeRestrictedPreset, u as RESTRICTED_PRESET_DISPLAY } from "../ensure-C2tUoF5U.js";
2
+ import { C as trimTrailingBlankLines, S as rowSiblingEnd, _ as presetRowId, a as composePresetComposition, b as resolveBasePresetPatch, c as composePresetRow, d as listDirectories, f as loadRowOverrides, g as presetRowBody, h as presetRowBlock, i as basePresetPlugins, l as compositionRowIds, m as presetPatchText, n as AGENT_PRESET_ROOT_HINT, o as composePresetEntry, p as mergePresetRow, r as EMPTY_PATCH_SEED, s as composePresetInsert, t as AGENT_PRESET_PACKAGE, u as denseBlockSequence, v as probeDesktopScope, x as rowBlockSpan, y as removePresetRow } from "../composition-3QFfEe56.js";
3
3
  export { AGENT_PRESET_PACKAGE, AGENT_PRESET_ROOT_HINT, EMPTY_PATCH_SEED, EVOLUTION_PRESET_IDS, MAINTAINER_PRESET_ID, RESTRICTED_PRESET_DELIVERY, RESTRICTED_PRESET_DISPLAY, RESTRICTED_TOOLS_ROW_ID, RESTRICTOR_MODULE, REVIEWER_PRESET_ID, basePresetPlugins, composePresetComposition, composePresetEntry, composePresetInsert, composePresetRow, composeRestrictedPresetDefinition, compositionRowIds, denseBlockSequence, disposeRestrictedPreset, ensureRestrictedPreset, entryListSchema, listDirectories, loadRowOverrides, mergePresetRow, normalizeAllow, parsePresetRows, presetPatchText, presetRowBlock, presetRowBody, presetRowId, probeDesktopScope, removePresetRow, resolveBasePresetPatch, restrictedPresetId, restrictedPresetState, rowBlockSpan, rowSiblingEnd, trimTrailingBlankLines };
@@ -1,4 +1,4 @@
1
- import { _ as scopedPackageName } from "./ensure-BuWsjPGD.js";
1
+ import { _ as scopedPackageName } from "./ensure-C2tUoF5U.js";
2
2
  import { dirname, join } from "node:path";
3
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
@@ -1,4 +1,4 @@
1
- import { n as errorText } from "./errors-Br2-uUSK.js";
1
+ import { n as errorText } from "./errors-DRZ9A187.js";
2
2
  import { dirname, join } from "node:path";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
@@ -36,6 +36,7 @@ const EVOLUTION_ERRORS = Object.freeze({
36
36
  "e-310-the-settings-service-refused": "E-310: 设置服务拒绝了这次写入:%a1% —— 归属插件的规则优先(跨字段成对约束,或只能收紧的上限)。/evolution params 会显示当前值。",
37
37
  "e-317-skill-write-not-confirmed": "E-317: 技能 \"%a1%\" 未被%a2% —— 确认提示被拒绝或关闭,因此没有写入任何内容。每次创建与裸删除都会出现该提示;只有操作者要求时才重复调用。",
38
38
  "e-318-skill-write-without-a-read": "E-318: 本会话没有读取技能 \"%a1%\",因此拒绝这次写入。请先用 `skill` 工具读取它(失败的读取不算),然后重复该写入。",
39
+ "e-326-support-write-without-a-read": "E-326: 本会话没有读取技能 \"%a1%\" 的支撑文件 \"%a2%\",因此拒绝这次写入。只读技能正文不算读过支撑文件;请先读取该文件(失败的读取不算),然后重复该写入。",
39
40
  "e-320-the-profile-home-is-not": "E-320: 本宿主没有报告 profile home,因此无法定位旧设置文档。/evolution migrate 读取 `<profile home>/settings.yaml.imported`;请在由 profile 启动的会话里运行。",
40
41
  "e-322-a-parameter-would-break-a": "E-322: %a1% 至少应为 %a2%,但这次写入把它设成 %a3%。未写入任何内容。",
41
42
  "e-321-no-io-provider-is": "E-321: 没有挂载 evolution-io 提供方,因此无法读取旧设置文档。请挂载 evolution-io 行(evolution-host/evolution-all)后重试。",