@agentxm/workspace-state 0.28.4-bootstrap.0

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 (215) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +11 -0
  3. package/dist/src/index.d.ts +72 -0
  4. package/dist/src/index.js +88 -0
  5. package/dist/src/knowledge/discovery-config.d.ts +12 -0
  6. package/dist/src/knowledge/discovery-config.js +9 -0
  7. package/dist/src/lockfile/accepted-registry-version.d.ts +12 -0
  8. package/dist/src/lockfile/accepted-registry-version.js +13 -0
  9. package/dist/src/lockfile/entry-fields.d.ts +189 -0
  10. package/dist/src/lockfile/entry-fields.js +89 -0
  11. package/dist/src/lockfile/errors.d.ts +48 -0
  12. package/dist/src/lockfile/errors.js +27 -0
  13. package/dist/src/lockfile/index.d.ts +18 -0
  14. package/dist/src/lockfile/index.js +16 -0
  15. package/dist/src/lockfile/lockfile.d.ts +2255 -0
  16. package/dist/src/lockfile/lockfile.js +235 -0
  17. package/dist/src/lockfile/resolved-version.d.ts +4 -0
  18. package/dist/src/lockfile/resolved-version.js +7 -0
  19. package/dist/src/lockfile/schema.d.ts +3062 -0
  20. package/dist/src/lockfile/schema.js +406 -0
  21. package/dist/src/schema/index.d.ts +3 -0
  22. package/dist/src/schema/index.js +2 -0
  23. package/dist/src/schema/read-and-validate-json-file.d.ts +20 -0
  24. package/dist/src/schema/read-and-validate-json-file.js +85 -0
  25. package/dist/src/schema/types.d.ts +26 -0
  26. package/dist/src/schema/types.js +2 -0
  27. package/dist/src/settings/errors.d.ts +22 -0
  28. package/dist/src/settings/errors.js +15 -0
  29. package/dist/src/settings/format-preserving-json.d.ts +40 -0
  30. package/dist/src/settings/format-preserving-json.js +80 -0
  31. package/dist/src/settings/index.d.ts +15 -0
  32. package/dist/src/settings/index.js +14 -0
  33. package/dist/src/settings/schema.d.ts +687 -0
  34. package/dist/src/settings/schema.js +977 -0
  35. package/dist/src/settings/settings.d.ts +38 -0
  36. package/dist/src/settings/settings.js +213 -0
  37. package/dist/src/testing.d.ts +17 -0
  38. package/dist/src/testing.js +17 -0
  39. package/dist/src/utils/atomic-write.d.ts +67 -0
  40. package/dist/src/utils/atomic-write.js +71 -0
  41. package/dist/src/utils/environment.d.ts +16 -0
  42. package/dist/src/utils/environment.js +19 -0
  43. package/dist/src/utils/path-safety.d.ts +25 -0
  44. package/dist/src/utils/path-safety.js +34 -0
  45. package/dist/src/utils/resolve-parent-symlinks.d.ts +16 -0
  46. package/dist/src/utils/resolve-parent-symlinks.js +36 -0
  47. package/dist/src/workspace/accepted-canonical-ref.d.ts +58 -0
  48. package/dist/src/workspace/accepted-canonical-ref.js +229 -0
  49. package/dist/src/workspace/artifact-change.d.ts +14 -0
  50. package/dist/src/workspace/artifact-change.js +18 -0
  51. package/dist/src/workspace/canonical-observation.d.ts +39 -0
  52. package/dist/src/workspace/canonical-observation.js +307 -0
  53. package/dist/src/workspace/configured-agent-outcome.d.ts +22 -0
  54. package/dist/src/workspace/configured-agent-outcome.js +33 -0
  55. package/dist/src/workspace/configured-agent-outcomes-provider.d.ts +50 -0
  56. package/dist/src/workspace/configured-agent-outcomes-provider.js +26 -0
  57. package/dist/src/workspace/configured-agent-outcomes.d.ts +48 -0
  58. package/dist/src/workspace/configured-agent-outcomes.js +113 -0
  59. package/dist/src/workspace/configured-entry-resolution/types.d.ts +32 -0
  60. package/dist/src/workspace/configured-entry-resolution/types.js +2 -0
  61. package/dist/src/workspace/configured-entry-resolution/workspace-ref.d.ts +32 -0
  62. package/dist/src/workspace/configured-entry-resolution/workspace-ref.js +176 -0
  63. package/dist/src/workspace/constants.d.ts +6 -0
  64. package/dist/src/workspace/constants.js +6 -0
  65. package/dist/src/workspace/create-symlink.d.ts +26 -0
  66. package/dist/src/workspace/create-symlink.js +87 -0
  67. package/dist/src/workspace/desired-pack-lock.d.ts +18 -0
  68. package/dist/src/workspace/desired-pack-lock.js +132 -0
  69. package/dist/src/workspace/desired-state-enabled.d.ts +18 -0
  70. package/dist/src/workspace/desired-state-enabled.js +16 -0
  71. package/dist/src/workspace/desired-state-graph.d.ts +114 -0
  72. package/dist/src/workspace/desired-state-graph.js +384 -0
  73. package/dist/src/workspace/desired-state-problem-text.d.ts +6 -0
  74. package/dist/src/workspace/desired-state-problem-text.js +27 -0
  75. package/dist/src/workspace/errors.d.ts +184 -0
  76. package/dist/src/workspace/errors.js +79 -0
  77. package/dist/src/workspace/extension-name.d.ts +28 -0
  78. package/dist/src/workspace/extension-name.js +66 -0
  79. package/dist/src/workspace/extension-paths.d.ts +82 -0
  80. package/dist/src/workspace/extension-paths.js +172 -0
  81. package/dist/src/workspace/footprint-recorder.d.ts +30 -0
  82. package/dist/src/workspace/footprint-recorder.js +32 -0
  83. package/dist/src/workspace/layout.d.ts +43 -0
  84. package/dist/src/workspace/layout.js +164 -0
  85. package/dist/src/workspace/lock-entry-to-ref.d.ts +40 -0
  86. package/dist/src/workspace/lock-entry-to-ref.js +433 -0
  87. package/dist/src/workspace/lock-entry-to-source-params.d.ts +26 -0
  88. package/dist/src/workspace/lock-entry-to-source-params.js +81 -0
  89. package/dist/src/workspace/locked-entries.d.ts +30 -0
  90. package/dist/src/workspace/locked-entries.js +34 -0
  91. package/dist/src/workspace/materialized-file-target.d.ts +14 -0
  92. package/dist/src/workspace/materialized-file-target.js +14 -0
  93. package/dist/src/workspace/materialized-tree.d.ts +23 -0
  94. package/dist/src/workspace/materialized-tree.js +90 -0
  95. package/dist/src/workspace/mcp-entry-semantics.d.ts +31 -0
  96. package/dist/src/workspace/mcp-entry-semantics.js +60 -0
  97. package/dist/src/workspace/observed-installed.d.ts +9 -0
  98. package/dist/src/workspace/observed-installed.js +9 -0
  99. package/dist/src/workspace/pack-manifest-content-identity.d.ts +12 -0
  100. package/dist/src/workspace/pack-manifest-content-identity.js +20 -0
  101. package/dist/src/workspace/pack-paths.d.ts +24 -0
  102. package/dist/src/workspace/pack-paths.js +16 -0
  103. package/dist/src/workspace/package-hash.d.ts +25 -0
  104. package/dist/src/workspace/package-hash.js +45 -0
  105. package/dist/src/workspace/paths.d.ts +24 -0
  106. package/dist/src/workspace/paths.js +52 -0
  107. package/dist/src/workspace/read-model/__fixtures__/builder.d.ts +199 -0
  108. package/dist/src/workspace/read-model/__fixtures__/builder.js +588 -0
  109. package/dist/src/workspace/read-model/__fixtures__/decoders.d.ts +15 -0
  110. package/dist/src/workspace/read-model/__fixtures__/decoders.js +15 -0
  111. package/dist/src/workspace/read-model/__fixtures__/occurrences.d.ts +72 -0
  112. package/dist/src/workspace/read-model/__fixtures__/occurrences.js +134 -0
  113. package/dist/src/workspace/read-model/__fixtures__/scenario-harness.d.ts +99 -0
  114. package/dist/src/workspace/read-model/__fixtures__/scenario-harness.js +142 -0
  115. package/dist/src/workspace/read-model/__fixtures__/test-layer.d.ts +60 -0
  116. package/dist/src/workspace/read-model/__fixtures__/test-layer.js +57 -0
  117. package/dist/src/workspace/read-model/agent-presence.d.ts +32 -0
  118. package/dist/src/workspace/read-model/agent-presence.js +21 -0
  119. package/dist/src/workspace/read-model/agent-root-resolver.d.ts +38 -0
  120. package/dist/src/workspace/read-model/agent-root-resolver.js +35 -0
  121. package/dist/src/workspace/read-model/agents/index.d.ts +38 -0
  122. package/dist/src/workspace/read-model/agents/index.js +45 -0
  123. package/dist/src/workspace/read-model/agents/shared.d.ts +27 -0
  124. package/dist/src/workspace/read-model/agents/shared.js +63 -0
  125. package/dist/src/workspace/read-model/agents/types.d.ts +133 -0
  126. package/dist/src/workspace/read-model/agents/types.js +51 -0
  127. package/dist/src/workspace/read-model/diagnostics.d.ts +18 -0
  128. package/dist/src/workspace/read-model/diagnostics.js +14 -0
  129. package/dist/src/workspace/read-model/discovery/index.d.ts +5 -0
  130. package/dist/src/workspace/read-model/discovery/index.js +5 -0
  131. package/dist/src/workspace/read-model/discovery/plugin-manifests.d.ts +16 -0
  132. package/dist/src/workspace/read-model/discovery/plugin-manifests.js +168 -0
  133. package/dist/src/workspace/read-model/discovery/skills.d.ts +58 -0
  134. package/dist/src/workspace/read-model/discovery/skills.js +263 -0
  135. package/dist/src/workspace/read-model/discovery/subagents.d.ts +37 -0
  136. package/dist/src/workspace/read-model/discovery/subagents.js +48 -0
  137. package/dist/src/workspace/read-model/errors.d.ts +93 -0
  138. package/dist/src/workspace/read-model/errors.js +30 -0
  139. package/dist/src/workspace/read-model/extensions/actual-helpers.d.ts +4 -0
  140. package/dist/src/workspace/read-model/extensions/actual-helpers.js +4 -0
  141. package/dist/src/workspace/read-model/extensions/hook.d.ts +104 -0
  142. package/dist/src/workspace/read-model/extensions/hook.js +119 -0
  143. package/dist/src/workspace/read-model/extensions/index.d.ts +19 -0
  144. package/dist/src/workspace/read-model/extensions/index.js +43 -0
  145. package/dist/src/workspace/read-model/extensions/indexByName.d.ts +31 -0
  146. package/dist/src/workspace/read-model/extensions/indexByName.js +30 -0
  147. package/dist/src/workspace/read-model/extensions/inventory.d.ts +99 -0
  148. package/dist/src/workspace/read-model/extensions/inventory.js +111 -0
  149. package/dist/src/workspace/read-model/extensions/knowledge.d.ts +101 -0
  150. package/dist/src/workspace/read-model/extensions/knowledge.js +121 -0
  151. package/dist/src/workspace/read-model/extensions/mcp-server.d.ts +106 -0
  152. package/dist/src/workspace/read-model/extensions/mcp-server.js +122 -0
  153. package/dist/src/workspace/read-model/extensions/pack.d.ts +104 -0
  154. package/dist/src/workspace/read-model/extensions/pack.js +123 -0
  155. package/dist/src/workspace/read-model/extensions/package-root.d.ts +39 -0
  156. package/dist/src/workspace/read-model/extensions/package-root.js +48 -0
  157. package/dist/src/workspace/read-model/extensions/projection.d.ts +137 -0
  158. package/dist/src/workspace/read-model/extensions/projection.js +180 -0
  159. package/dist/src/workspace/read-model/extensions/rule.d.ts +104 -0
  160. package/dist/src/workspace/read-model/extensions/rule.js +113 -0
  161. package/dist/src/workspace/read-model/extensions/skill.d.ts +170 -0
  162. package/dist/src/workspace/read-model/extensions/skill.js +148 -0
  163. package/dist/src/workspace/read-model/extensions/subagent.d.ts +97 -0
  164. package/dist/src/workspace/read-model/extensions/subagent.js +120 -0
  165. package/dist/src/workspace/read-model/scanners/agent-dir.d.ts +49 -0
  166. package/dist/src/workspace/read-model/scanners/agent-dir.js +180 -0
  167. package/dist/src/workspace/read-model/scanners/agent-root.d.ts +73 -0
  168. package/dist/src/workspace/read-model/scanners/agent-root.js +148 -0
  169. package/dist/src/workspace/read-model/scanners/agent-settings.d.ts +43 -0
  170. package/dist/src/workspace/read-model/scanners/agent-settings.js +54 -0
  171. package/dist/src/workspace/read-model/scanners/canonical-extensions.d.ts +48 -0
  172. package/dist/src/workspace/read-model/scanners/canonical-extensions.js +237 -0
  173. package/dist/src/workspace/read-model/scanners/fs-helpers.d.ts +63 -0
  174. package/dist/src/workspace/read-model/scanners/fs-helpers.js +106 -0
  175. package/dist/src/workspace/read-model/scanners/index.d.ts +15 -0
  176. package/dist/src/workspace/read-model/scanners/index.js +34 -0
  177. package/dist/src/workspace/read-model/scanners/mcp-config.d.ts +47 -0
  178. package/dist/src/workspace/read-model/scanners/mcp-config.js +212 -0
  179. package/dist/src/workspace/read-model/scanners/types.d.ts +170 -0
  180. package/dist/src/workspace/read-model/scanners/types.js +86 -0
  181. package/dist/src/workspace/read-model/service.d.ts +103 -0
  182. package/dist/src/workspace/read-model/service.js +391 -0
  183. package/dist/src/workspace/read-model/state.d.ts +35 -0
  184. package/dist/src/workspace/read-model/state.js +97 -0
  185. package/dist/src/workspace/read-model/types.d.ts +75 -0
  186. package/dist/src/workspace/read-model/types.js +26 -0
  187. package/dist/src/workspace/read-model-record-readers.d.ts +34 -0
  188. package/dist/src/workspace/read-model-record-readers.js +467 -0
  189. package/dist/src/workspace/read-model-record-rows.d.ts +45 -0
  190. package/dist/src/workspace/read-model-record-rows.js +33 -0
  191. package/dist/src/workspace/read-model-record-types.d.ts +45 -0
  192. package/dist/src/workspace/read-model-record-types.js +13 -0
  193. package/dist/src/workspace/remove-if-exists.d.ts +13 -0
  194. package/dist/src/workspace/remove-if-exists.js +26 -0
  195. package/dist/src/workspace/rendered-files.d.ts +53 -0
  196. package/dist/src/workspace/rendered-files.js +50 -0
  197. package/dist/src/workspace/scope-refusal.d.ts +26 -0
  198. package/dist/src/workspace/scope-refusal.js +29 -0
  199. package/dist/src/workspace/service-interface.d.ts +479 -0
  200. package/dist/src/workspace/service-interface.js +27 -0
  201. package/dist/src/workspace/service.d.ts +1665 -0
  202. package/dist/src/workspace/service.js +1263 -0
  203. package/dist/src/workspace/setup-scope-support.d.ts +27 -0
  204. package/dist/src/workspace/setup-scope-support.js +299 -0
  205. package/dist/src/workspace/skill-paths.d.ts +33 -0
  206. package/dist/src/workspace/skill-paths.js +14 -0
  207. package/dist/src/workspace/source-metadata.d.ts +7 -0
  208. package/dist/src/workspace/source-metadata.js +10 -0
  209. package/dist/src/workspace/source-to-lock-entry.d.ts +32 -0
  210. package/dist/src/workspace/source-to-lock-entry.js +68 -0
  211. package/dist/src/workspace/test-stubs.d.ts +144 -0
  212. package/dist/src/workspace/test-stubs.js +412 -0
  213. package/dist/src/workspace/transaction.d.ts +218 -0
  214. package/dist/src/workspace/transaction.js +177 -0
  215. package/package.json +57 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Lockfile module for managing project-root `axm-lock.yaml` or the user-scope
3
+ * `axm-lock.yaml` (YAML format).
4
+ *
5
+ * Provides functions to read, write, and update accepted external resolutions.
6
+ *
7
+ * @experimental This API is unstable and may change without notice.
8
+ * @packageDocumentation
9
+ */
10
+ import { LOCKFILE_NAME } from "@agentxm/extension-model/unstable/workspace-files";
11
+ import * as FileSystem from "effect/FileSystem";
12
+ import * as Path from "effect/Path";
13
+ import * as Effect from "effect/Effect";
14
+ import * as Schema from "effect/Schema";
15
+ import * as Semaphore from "effect/Semaphore";
16
+ import YAML from "yaml";
17
+ import { recordFootprint } from "../workspace/footprint-recorder.js";
18
+ import { sweepStaleAtomicWriteTemps, writeFileAtomic } from "../utils/atomic-write.js";
19
+ import { LockfileValidationError, LockfileWriteError } from "./errors.js";
20
+ import { LOCKFILE_VERSION, LockfileSchema } from "./schema.js";
21
+ // -----------------------------------------------------------------------------
22
+ // Constants
23
+ // -----------------------------------------------------------------------------
24
+ /**
25
+ * Filename for the lockfile.
26
+ *
27
+ * @experimental This API is unstable and may change without notice.
28
+ */
29
+ // eslint-disable-next-line no-restricted-syntax -- Process-owned keys are bounded by lockfiles touched during this one CLI invocation.
30
+ const lockSemaphores = new Map();
31
+ // -----------------------------------------------------------------------------
32
+ // Internal Helpers
33
+ // -----------------------------------------------------------------------------
34
+ const lockfilePathFor = (path, axmDir) => path.join(axmDir, LOCKFILE_NAME);
35
+ const inProcessSemaphoreFor = (key) => {
36
+ const existing = lockSemaphores.get(key);
37
+ if (existing !== undefined)
38
+ return existing;
39
+ const created = Semaphore.makeUnsafe(1);
40
+ lockSemaphores.set(key, created);
41
+ return created;
42
+ };
43
+ const ensureLockfileParent = (lockfilePath) => Effect.gen(function* () {
44
+ const fs = yield* FileSystem.FileSystem;
45
+ const path = yield* Path.Path;
46
+ const parent = path.dirname(lockfilePath);
47
+ yield* fs
48
+ .makeDirectory(parent, { recursive: true })
49
+ .pipe(Effect.mapError((cause) => new LockfileWriteError({ path: parent, step: "mkdir", cause })));
50
+ });
51
+ const encodeLockfileYaml = (lockfilePath, lockfile) => Effect.gen(function* () {
52
+ const encoded = yield* Effect.try({
53
+ try: () => Schema.encodeSync(LockfileSchema)(lockfile),
54
+ catch: (cause) => new LockfileWriteError({ path: lockfilePath, step: "encode", cause }),
55
+ });
56
+ return yield* Effect.try({
57
+ try: () => YAML.stringify(encoded),
58
+ catch: (cause) => new LockfileWriteError({ path: lockfilePath, step: "serialize", cause }),
59
+ });
60
+ });
61
+ const patchOptionalMap = (fresh, base, next) => {
62
+ if (base === undefined && next === undefined)
63
+ return fresh === undefined ? undefined : { ...fresh };
64
+ const patched = { ...(fresh ?? {}) };
65
+ for (const key of Object.keys(base ?? {})) {
66
+ if (!Object.hasOwn(next ?? {}, key)) {
67
+ delete patched[key];
68
+ }
69
+ }
70
+ for (const [key, value] of Object.entries(next ?? {})) {
71
+ patched[key] = value;
72
+ }
73
+ return Object.keys(patched).length === 0 ? undefined : patched;
74
+ };
75
+ const patchRequiredMap = (fresh, base, next) => {
76
+ const patched = { ...fresh };
77
+ for (const key of Object.keys(base)) {
78
+ if (!Object.hasOwn(next, key)) {
79
+ delete patched[key];
80
+ }
81
+ }
82
+ for (const [key, value] of Object.entries(next)) {
83
+ patched[key] = value;
84
+ }
85
+ return patched;
86
+ };
87
+ const applyLockfileSnapshotPatch = (fresh, base, next) => {
88
+ const subagents = patchOptionalMap(fresh.subagents, base.subagents, next.subagents);
89
+ const mcpServers = patchOptionalMap(fresh.mcpServers, base.mcpServers, next.mcpServers);
90
+ const rules = patchOptionalMap(fresh.rules, base.rules, next.rules);
91
+ const hooks = patchOptionalMap(fresh.hooks, base.hooks, next.hooks);
92
+ const knowledge = patchOptionalMap(fresh.knowledge, base.knowledge, next.knowledge);
93
+ const packs = patchOptionalMap(fresh.packs, base.packs, next.packs);
94
+ return {
95
+ lockfileVersion: LOCKFILE_VERSION,
96
+ skills: patchRequiredMap(fresh.skills, base.skills, next.skills),
97
+ ...(subagents !== undefined ? { subagents } : {}),
98
+ ...(mcpServers !== undefined ? { mcpServers } : {}),
99
+ ...(rules !== undefined ? { rules } : {}),
100
+ ...(hooks !== undefined ? { hooks } : {}),
101
+ ...(knowledge !== undefined ? { knowledge } : {}),
102
+ ...(packs !== undefined ? { packs } : {}),
103
+ };
104
+ };
105
+ const readLockfileIfPresent = (lockfilePath) => Effect.gen(function* () {
106
+ const fs = yield* FileSystem.FileSystem;
107
+ const exists = yield* fs
108
+ .exists(lockfilePath)
109
+ .pipe(Effect.mapError((cause) => new LockfileValidationError({ path: lockfilePath, step: "check", cause })));
110
+ if (!exists)
111
+ return undefined;
112
+ const raw = yield* fs
113
+ .readFileString(lockfilePath)
114
+ .pipe(Effect.mapError((cause) => new LockfileValidationError({ path: lockfilePath, step: "read", cause })));
115
+ const parsed = yield* Effect.try({
116
+ try: () => YAML.parse(raw),
117
+ catch: (cause) => new LockfileValidationError({ path: lockfilePath, step: "parse", cause }),
118
+ });
119
+ const decoded = yield* Schema.decodeUnknownEffect(LockfileSchema)(parsed, {
120
+ onExcessProperty: "error",
121
+ }).pipe(Effect.mapError((cause) => new LockfileValidationError({ path: lockfilePath, step: "decode", cause })));
122
+ return decoded;
123
+ });
124
+ const withLockfileLock = (lockfilePath, effect) => Effect.gen(function* () {
125
+ const path = yield* Path.Path;
126
+ const key = path.resolve(lockfilePath);
127
+ const semaphore = inProcessSemaphoreFor(key);
128
+ // Cross-process exclusion belongs to the workspace transaction. This
129
+ // semaphore only serializes multiple updates in one runtime so the
130
+ // read/patch/write helper cannot race with itself.
131
+ return yield* semaphore.withPermits(1)(effect);
132
+ });
133
+ const writeLockfileUnlocked = (lockfilePath, lockfile) => Effect.gen(function* () {
134
+ const fs = yield* FileSystem.FileSystem;
135
+ const yamlContent = yield* encodeLockfileYaml(lockfilePath, lockfile);
136
+ const existed = yield* fs.exists(lockfilePath).pipe(Effect.orElseSucceed(() => true));
137
+ yield* sweepStaleAtomicWriteTemps(fs, lockfilePath);
138
+ const written = yield* writeFileAtomic(fs, {
139
+ targetPath: lockfilePath,
140
+ content: yamlContent,
141
+ skipIfUnchanged: "fail-on-read-error",
142
+ mapError: (failure) => new LockfileWriteError({
143
+ path: failure.step === "write-temp" ? failure.tempPath : lockfilePath,
144
+ step: failure.step,
145
+ cause: failure.cause,
146
+ }),
147
+ });
148
+ if (written === "written") {
149
+ yield* recordFootprint({ path: lockfilePath, change: existed ? "modified" : "created" });
150
+ }
151
+ });
152
+ // -----------------------------------------------------------------------------
153
+ // Public Functions
154
+ // -----------------------------------------------------------------------------
155
+ /**
156
+ * Writes the lockfile to the selected scope's `axm-lock.yaml` in YAML format.
157
+ *
158
+ * Creates the containing directory if it does not exist. Writes are serialized by
159
+ * an in-process keyed semaphore plus a best-effort local advisory lock file.
160
+ * Temporary files are removed by scoped finalizer on interruption, and stale
161
+ * temp files from older crashed writers are swept before each write. When the
162
+ * encoded bytes already match, the existing lockfile is left untouched.
163
+ *
164
+ * `writeLockfile` remains a full replacement operation. Call
165
+ * `commitLockfileUpdates` when applying deltas that must reread the latest
166
+ * lockfile state under the advisory lock.
167
+ *
168
+ * @param axmDir - Directory containing the selected scope's lockfile
169
+ * @param lockfile - The lockfile object to write
170
+ * @returns Effect yielding void on success
171
+ *
172
+ * @experimental This API is unstable and may change without notice.
173
+ */
174
+ export const writeLockfileAtPath = (lockfilePath, lockfile) => Effect.gen(function* () {
175
+ yield* ensureLockfileParent(lockfilePath);
176
+ yield* withLockfileLock(lockfilePath, Effect.gen(function* () {
177
+ yield* writeLockfileUnlocked(lockfilePath, lockfile);
178
+ }));
179
+ });
180
+ export const writeLockfile = (axmDir, lockfile) => Effect.gen(function* () {
181
+ const path = yield* Path.Path;
182
+ yield* writeLockfileAtPath(lockfilePathFor(path, axmDir), lockfile);
183
+ });
184
+ /**
185
+ * Applies lockfile updates in order without writing to disk.
186
+ *
187
+ * @experimental This API is unstable and may change without notice.
188
+ */
189
+ export const applyLockfileUpdates = (lockfile, updates) => updates.reduce((current, update) => update(current), lockfile);
190
+ /**
191
+ * Applies a batch of lockfile updates and writes the result once.
192
+ *
193
+ * This is intended for sync flows that discover multiple render-hash changes
194
+ * while reconciling managed package targets.
195
+ *
196
+ * @experimental This API is unstable and may change without notice.
197
+ */
198
+ export const commitLockfileUpdates = (axmDir, lockfile, updates) => Effect.gen(function* () {
199
+ const path = yield* Path.Path;
200
+ const lockfilePath = lockfilePathFor(path, axmDir);
201
+ yield* ensureLockfileParent(lockfilePath);
202
+ const updated = yield* withLockfileLock(lockfilePath, Effect.gen(function* () {
203
+ const current = yield* readLockfileIfPresent(lockfilePath);
204
+ const updated = applyLockfileUpdates(current ?? lockfile, updates);
205
+ yield* writeLockfileUnlocked(lockfilePath, updated);
206
+ return updated;
207
+ }));
208
+ return updated;
209
+ });
210
+ /**
211
+ * Commits a caller-computed lockfile snapshot as an entry-level patch.
212
+ *
213
+ * The caller supplies the base snapshot it read and the next snapshot it
214
+ * computed. The helper rereads the current on-disk lockfile under the advisory
215
+ * lock, applies only the base→next entry changes, then writes once. This keeps
216
+ * independent concurrent updates from dropping each other while preserving
217
+ * explicit entry deletions.
218
+ *
219
+ * @experimental This API is unstable and may change without notice.
220
+ */
221
+ export const commitLockfileSnapshotUpdateAtPath = (lockfilePath, base, next) => Effect.gen(function* () {
222
+ yield* ensureLockfileParent(lockfilePath);
223
+ const updated = yield* withLockfileLock(lockfilePath, Effect.gen(function* () {
224
+ const current = yield* readLockfileIfPresent(lockfilePath);
225
+ const updated = applyLockfileSnapshotPatch(current ?? base, base, next);
226
+ yield* writeLockfileUnlocked(lockfilePath, updated);
227
+ return updated;
228
+ }));
229
+ return updated;
230
+ });
231
+ export const commitLockfileSnapshotUpdate = (axmDir, base, next) => Effect.gen(function* () {
232
+ const path = yield* Path.Path;
233
+ return yield* commitLockfileSnapshotUpdateAtPath(lockfilePathFor(path, axmDir), base, next);
234
+ });
235
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1,4 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { LockfileResolvedVersionInvalid } from "./errors.js";
3
+ export declare const validateExactResolvedVersion: (field: string, value: string) => Effect.Effect<void, LockfileResolvedVersionInvalid, never>;
4
+ //# sourceMappingURL=resolved-version.d.ts.map
@@ -0,0 +1,7 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Schema from "effect/Schema";
3
+ import { VersionSchema } from "@agentxm/extension-model/unstable/version-constraints";
4
+ import { LockfileResolvedVersionInvalid } from "./errors.js";
5
+ const decodeVersion = Schema.decodeUnknownEffect(VersionSchema);
6
+ export const validateExactResolvedVersion = (field, value) => decodeVersion(value).pipe(Effect.asVoid, Effect.mapError((cause) => new LockfileResolvedVersionInvalid({ field, value, cause })));
7
+ //# sourceMappingURL=resolved-version.js.map