@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,134 @@
1
+ /**
2
+ * Test fixture builders for scanner occurrences.
3
+ *
4
+ * Per the Wave 1A scanner contract, every `CanonicalExtensionOccurrence` and
5
+ * `AgentDirOccurrence` carries `pathSegments`, `subjectFile`, and
6
+ * `subjectFileExists` in addition to its identifying fields. These factories
7
+ * compute those derived fields from minimal inputs so test sites supply only
8
+ * the discriminators they care about.
9
+ *
10
+ * `McpConfigOccurrence` carries a discriminated physical surface. Shared
11
+ * observations omit agent identity; agent-native observations retain it.
12
+ */
13
+ import * as Option from "effect/Option";
14
+ import * as Schema from "effect/Schema";
15
+ import { decodeExtensionNameSync, } from "@agentxm/extension-model/unstable/extensions/common";
16
+ import { decodeHandleSync } from "@agentxm/extension-model/unstable/extensions/handle";
17
+ import { AbsolutePathSchema, } from "@agentxm/extension-model/unstable/path-types";
18
+ // ---------------------------------------------------------------------------
19
+ // Path helpers (POSIX, since fixtures synthesize POSIX paths)
20
+ // ---------------------------------------------------------------------------
21
+ const POSIX_SEP = "/";
22
+ const splitSegments = (absolute) => absolute.split(POSIX_SEP);
23
+ const join = (parent, child) => parent.endsWith(POSIX_SEP) ? `${parent}${child}` : `${parent}${POSIX_SEP}${child}`;
24
+ const decodeFixtureAbsolutePath = Schema.decodeUnknownSync(AbsolutePathSchema);
25
+ const normalizeFileBackedName = (name) => {
26
+ const normalized = name
27
+ .toLowerCase()
28
+ .replace(/[^a-z0-9]+/g, "-")
29
+ .replace(/^-+|-+$/g, "")
30
+ .slice(0, 64)
31
+ .replace(/-+$/g, "");
32
+ return normalized === "" ? "unnamed" : normalized;
33
+ };
34
+ // ---------------------------------------------------------------------------
35
+ // Subject file mapping (must match scanners/canonical-extensions.ts /
36
+ // scanners/agent-dir.ts)
37
+ // ---------------------------------------------------------------------------
38
+ const subjectFileNameForExtensionType = (type, name) => {
39
+ switch (type) {
40
+ case "skill":
41
+ return "SKILL.md";
42
+ case "subagent":
43
+ return `${name}.md`;
44
+ default:
45
+ return null;
46
+ }
47
+ };
48
+ const subjectFileNameForAgentDir = (type, name) => {
49
+ switch (type) {
50
+ case "skill":
51
+ return "SKILL.md";
52
+ case "subagent":
53
+ return `${name}.md`;
54
+ }
55
+ };
56
+ /**
57
+ * Build a `CanonicalExtensionOccurrence` with the new structural fields
58
+ * populated. `pathSegments` is computed from `contentLocation` (POSIX split).
59
+ * `subjectFile` is `Some(<dir>/<name>.md)` for skill/subagent; `None` for
60
+ * mcp-server/rule/hook/knowledge/pack. `subjectFileExists` defaults to `true` when
61
+ * the subject has a canonical primary file; pass `false` to model absence.
62
+ */
63
+ export const makeCanonicalOccurrence = (input) => {
64
+ const subjectFileName = subjectFileNameForExtensionType(input.type, input.name);
65
+ const contentLocation = decodeFixtureAbsolutePath(input.contentLocation);
66
+ const subjectFile = subjectFileName === null
67
+ ? Option.none()
68
+ : Option.some(decodeFixtureAbsolutePath(join(input.contentLocation, subjectFileName)));
69
+ const subjectFileExists = input.subjectFileExists ?? (subjectFileName === null ? false : true);
70
+ return {
71
+ _tag: "canonical-extension",
72
+ scope: input.scope,
73
+ type: input.type,
74
+ origin: input.origin,
75
+ name: decodeExtensionNameSync(input.name),
76
+ owner: input.owner === null ? null : decodeHandleSync(input.owner),
77
+ contentLocation,
78
+ pathSegments: splitSegments(input.contentLocation),
79
+ subjectFile,
80
+ subjectFileExists,
81
+ };
82
+ };
83
+ /**
84
+ * Build an `AgentDirOccurrence` with the new structural fields populated.
85
+ * `pathSegments` is computed from `contentLocation` (POSIX split).
86
+ * `subjectFile` is `<contentLocation>/<canonical-file>` for directory
87
+ * occurrences and the `contentLocation` itself for single-file subagent
88
+ * surfaces. `subjectFileExists` defaults to `true`.
89
+ */
90
+ export const makeAgentDirOccurrence = (input) => {
91
+ const resolvedName = input.singleFile === true ? normalizeFileBackedName(input.name) : input.name;
92
+ const subjectFileName = subjectFileNameForAgentDir(input.type, resolvedName);
93
+ const contentLocation = decodeFixtureAbsolutePath(input.contentLocation);
94
+ const subjectFile = input.singleFile === true
95
+ ? Option.some(contentLocation)
96
+ : subjectFileName === null
97
+ ? Option.none()
98
+ : Option.some(decodeFixtureAbsolutePath(join(input.contentLocation, subjectFileName)));
99
+ const subjectFileExists = input.subjectFileExists ?? true;
100
+ return {
101
+ _tag: "agent-dir",
102
+ scope: input.scope,
103
+ type: input.type,
104
+ agentId: input.agentId,
105
+ name: resolvedName,
106
+ contentLocation,
107
+ pathSegments: splitSegments(input.contentLocation),
108
+ subjectFile,
109
+ subjectFileExists,
110
+ };
111
+ };
112
+ export const makeWorkspaceMcpConfigOccurrence = (input) => ({
113
+ _tag: "mcp-config",
114
+ scope: input.scope,
115
+ surface: { _tag: "shared" },
116
+ name: decodeExtensionNameSync(input.name),
117
+ contentLocation: decodeFixtureAbsolutePath(input.contentLocation),
118
+ config: input.config ?? {},
119
+ });
120
+ export const makeAgentMcpConfigOccurrence = (input) => ({
121
+ _tag: "mcp-config",
122
+ scope: input.scope,
123
+ surface: { _tag: "agent", agentId: input.agentId },
124
+ name: decodeExtensionNameSync(input.name),
125
+ contentLocation: decodeFixtureAbsolutePath(input.contentLocation),
126
+ config: input.config ?? {},
127
+ });
128
+ export const makeAgentSettingsOccurrence = (input) => ({
129
+ _tag: "agent-settings",
130
+ scope: input.scope,
131
+ agentId: input.agentId,
132
+ contentLocation: decodeFixtureAbsolutePath(input.contentLocation),
133
+ });
134
+ //# sourceMappingURL=occurrences.js.map
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Scenario-test harness for the workspace read-model capability.
3
+ *
4
+ * Each scenario file under `__tests__/scenarios/` consumes this harness:
5
+ *
6
+ * - `runScenario(spec, body)` builds both scopes via
7
+ * {@link makeWorkspaceReadModel} against the in-memory fixture FS, exposes
8
+ * them through a thin `ctx.scope(scope)` selector so scenarios can yield
9
+ * from either scope, and runs `body` with the result.
10
+ * - `expectFirst(arr)` asserts the array is non-empty and returns its first
11
+ * element, replacing the silent `if (entry === undefined) return` pattern.
12
+ * - `expectDiagnostics(ctx, scope, predicate)` reads the scoped diagnostics
13
+ * buffer once and asserts at least one warning matches `predicate`.
14
+ * - `tagsOf(cause)` extracts the tagged-error `_tag` set from an `Effect.Cause`
15
+ * so the ≤3-tag assertion in 10.2 stays compact.
16
+ *
17
+ * The harness is a leading-underscore module so vitest does not pick it up as
18
+ * a test file.
19
+ */
20
+ import * as Cause from "effect/Cause";
21
+ import * as Effect from "effect/Effect";
22
+ import * as Option from "effect/Option";
23
+ import * as Result from "effect/Result";
24
+ import type { WorkspaceReadModelTestOptions } from "./test-layer.js";
25
+ import type { FixtureSpec, PathEscapeError } from "./builder.js";
26
+ import type { Warning } from "../diagnostics.js";
27
+ import type { WorkspaceRootEscape } from "../errors.js";
28
+ import { type WorkspaceReadModel } from "../service.js";
29
+ import type { Scope } from "../types.js";
30
+ /**
31
+ * Scenario-side wrapper exposing both scopes through a `scope(scope)`
32
+ * selector. Both scopes are pre-built via {@link makeWorkspaceReadModel} so
33
+ * scenarios can yield from either scope freely. The selector returns a
34
+ * memoized {@link WorkspaceReadModel} per scope.
35
+ */
36
+ export interface WorkspaceReadModelScenarioCtx {
37
+ readonly scope: (scope: Scope) => WorkspaceReadModel;
38
+ }
39
+ /**
40
+ * Default workspace and user-home roots used by scenario specs. Tests may
41
+ * override per-spec by passing different values when constructing a
42
+ * `FixtureSpec`.
43
+ */
44
+ export declare const SCENARIO_WORKSPACE_ROOT = "/scenario/workspace";
45
+ export declare const SCENARIO_USER_HOME = "/scenario/home";
46
+ /**
47
+ * Build per-scope read models against the supplied fixture spec, provide them
48
+ * to `body`, and run the resulting effect. Both scopes are constructed
49
+ * eagerly so the body can yield from either scope without re-running the
50
+ * factory.
51
+ *
52
+ * The body's `E` channel is preserved through to the harness's return type
53
+ * so scenario tests can `yield*` source-backed cells (which fail with
54
+ * `SettingsReadError` / `LockfileReadError`) directly without wrapping every
55
+ * call site in `Effect.result`.
56
+ */
57
+ export declare const runScenario: <A, E = never>(spec: FixtureSpec, body: (ctx: WorkspaceReadModelScenarioCtx) => Effect.Effect<A, E>, options?: WorkspaceReadModelTestOptions) => Effect.Effect<A, E | WorkspaceRootEscape | PathEscapeError>;
58
+ /**
59
+ * Assert that `arr` is non-empty and return its first element. Replaces the
60
+ * silent `if (entry === undefined) return` pattern that lets a misshapen
61
+ * array silently pass a test.
62
+ */
63
+ export declare const expectFirst: <T>(arr: ReadonlyArray<T>, message?: string) => T;
64
+ /**
65
+ * Assert that `option` is `Option.Some` and return its inner value. Replaces
66
+ * the `expect(Option.isSome(opt)).toBe(true); if (!Option.isSome(opt)) return;`
67
+ * pattern that loses the failure message and lets misshapen values silently
68
+ * pass a test.
69
+ */
70
+ export declare const expectSome: <T>(option: Option.Option<T>, message?: string) => T;
71
+ /**
72
+ * Assert that `result` is a `Result.Success` and return its success value.
73
+ * Replaces `expect(result._tag).toBe("Success"); if (result._tag === ...)`
74
+ * narrowing chains.
75
+ */
76
+ export declare const expectSuccess: <A, E>(result: Result.Result<A, E>, message?: string) => A;
77
+ /**
78
+ * Assert that `result` is a `Result.Failure` and return its failure value.
79
+ * Replaces `expect(result._tag).toBe("Failure"); if (result._tag === ...)`
80
+ * narrowing chains.
81
+ */
82
+ export declare const expectFailure: <A, E>(result: Result.Result<A, E>, message?: string) => E;
83
+ /**
84
+ * Extract the set of tagged-error `_tag` values reachable inside a `Cause`.
85
+ * Used for the ≤3-tag-per-cell quality constraint assertion.
86
+ */
87
+ export declare const tagsOf: <E>(cause: Cause.Cause<E>) => ReadonlySet<string>;
88
+ /**
89
+ * Read the scoped diagnostics buffer once and assert at least one warning
90
+ * matches `predicate`. Returns the matching warnings so callers can chain
91
+ * additional assertions.
92
+ */
93
+ export declare const expectDiagnostics: (ctx: WorkspaceReadModelScenarioCtx, scope: Scope, predicate: (warning: Warning) => boolean) => Effect.Effect<ReadonlyArray<Warning>>;
94
+ /**
95
+ * Snapshot the scoped diagnostics buffer without asserting. Useful when a
96
+ * scenario wants to verify the absence of a warning class.
97
+ */
98
+ export declare const readDiagnostics: (ctx: WorkspaceReadModelScenarioCtx, scope: Scope) => Effect.Effect<ReadonlyArray<Warning>>;
99
+ //# sourceMappingURL=scenario-harness.d.ts.map
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Scenario-test harness for the workspace read-model capability.
3
+ *
4
+ * Each scenario file under `__tests__/scenarios/` consumes this harness:
5
+ *
6
+ * - `runScenario(spec, body)` builds both scopes via
7
+ * {@link makeWorkspaceReadModel} against the in-memory fixture FS, exposes
8
+ * them through a thin `ctx.scope(scope)` selector so scenarios can yield
9
+ * from either scope, and runs `body` with the result.
10
+ * - `expectFirst(arr)` asserts the array is non-empty and returns its first
11
+ * element, replacing the silent `if (entry === undefined) return` pattern.
12
+ * - `expectDiagnostics(ctx, scope, predicate)` reads the scoped diagnostics
13
+ * buffer once and asserts at least one warning matches `predicate`.
14
+ * - `tagsOf(cause)` extracts the tagged-error `_tag` set from an `Effect.Cause`
15
+ * so the ≤3-tag assertion in 10.2 stays compact.
16
+ *
17
+ * The harness is a leading-underscore module so vitest does not pick it up as
18
+ * a test file.
19
+ */
20
+ import * as Cause from "effect/Cause";
21
+ import * as Effect from "effect/Effect";
22
+ import * as Option from "effect/Option";
23
+ import * as Result from "effect/Result";
24
+ import { WorkspaceReadModelTest } from "./test-layer.js";
25
+ import { makeWorkspaceReadModel } from "../service.js";
26
+ /**
27
+ * Default workspace and user-home roots used by scenario specs. Tests may
28
+ * override per-spec by passing different values when constructing a
29
+ * `FixtureSpec`.
30
+ */
31
+ export const SCENARIO_WORKSPACE_ROOT = "/scenario/workspace";
32
+ export const SCENARIO_USER_HOME = "/scenario/home";
33
+ /**
34
+ * Build per-scope read models against the supplied fixture spec, provide them
35
+ * to `body`, and run the resulting effect. Both scopes are constructed
36
+ * eagerly so the body can yield from either scope without re-running the
37
+ * factory.
38
+ *
39
+ * The body's `E` channel is preserved through to the harness's return type
40
+ * so scenario tests can `yield*` source-backed cells (which fail with
41
+ * `SettingsReadError` / `LockfileReadError`) directly without wrapping every
42
+ * call site in `Effect.result`.
43
+ */
44
+ export const runScenario = (spec, body, options) => Effect.gen(function* () {
45
+ const project = yield* makeWorkspaceReadModel("project");
46
+ const user = yield* makeWorkspaceReadModel("user");
47
+ const ctx = {
48
+ scope: (scope) => (scope === "project" ? project : user),
49
+ };
50
+ return yield* body(ctx);
51
+ }).pipe(Effect.provide(WorkspaceReadModelTest(spec, options)));
52
+ /**
53
+ * Assert that `arr` is non-empty and return its first element. Replaces the
54
+ * silent `if (entry === undefined) return` pattern that lets a misshapen
55
+ * array silently pass a test.
56
+ */
57
+ export const expectFirst = (arr, message) => {
58
+ const value = arr[0];
59
+ if (value === undefined) {
60
+ throw new Error(message ?? "expectFirst: array is empty");
61
+ }
62
+ return value;
63
+ };
64
+ /**
65
+ * Assert that `option` is `Option.Some` and return its inner value. Replaces
66
+ * the `expect(Option.isSome(opt)).toBe(true); if (!Option.isSome(opt)) return;`
67
+ * pattern that loses the failure message and lets misshapen values silently
68
+ * pass a test.
69
+ */
70
+ export const expectSome = (option, message) => {
71
+ if (!Option.isSome(option)) {
72
+ throw new Error(message ?? "expectSome: option is None");
73
+ }
74
+ return option.value;
75
+ };
76
+ /**
77
+ * Assert that `result` is a `Result.Success` and return its success value.
78
+ * Replaces `expect(result._tag).toBe("Success"); if (result._tag === ...)`
79
+ * narrowing chains.
80
+ */
81
+ export const expectSuccess = (result, message) => {
82
+ if (!Result.isSuccess(result)) {
83
+ throw new Error(message ?? `expectSuccess: result is Failure`);
84
+ }
85
+ return result.success;
86
+ };
87
+ /**
88
+ * Assert that `result` is a `Result.Failure` and return its failure value.
89
+ * Replaces `expect(result._tag).toBe("Failure"); if (result._tag === ...)`
90
+ * narrowing chains.
91
+ */
92
+ export const expectFailure = (result, message) => {
93
+ if (!Result.isFailure(result)) {
94
+ throw new Error(message ?? `expectFailure: result is Success`);
95
+ }
96
+ return result.failure;
97
+ };
98
+ const hasStringTag = (value) => {
99
+ if (typeof value !== "object" || value === null)
100
+ return false;
101
+ if (!("_tag" in value))
102
+ return false;
103
+ // After the `in` narrowing, `value._tag` exists with type `unknown`.
104
+ // Compare its dynamic type without an assertion.
105
+ const tagValue = value._tag;
106
+ return typeof tagValue === "string";
107
+ };
108
+ /**
109
+ * Extract the set of tagged-error `_tag` values reachable inside a `Cause`.
110
+ * Used for the ≤3-tag-per-cell quality constraint assertion.
111
+ */
112
+ export const tagsOf = (cause) => {
113
+ const tags = new Set();
114
+ for (const reason of cause.reasons) {
115
+ if (!Cause.isFailReason(reason))
116
+ continue;
117
+ const candidate = reason.error;
118
+ if (hasStringTag(candidate)) {
119
+ tags.add(candidate._tag);
120
+ }
121
+ }
122
+ return tags;
123
+ };
124
+ /**
125
+ * Read the scoped diagnostics buffer once and assert at least one warning
126
+ * matches `predicate`. Returns the matching warnings so callers can chain
127
+ * additional assertions.
128
+ */
129
+ export const expectDiagnostics = (ctx, scope, predicate) => Effect.gen(function* () {
130
+ const warnings = yield* ctx.scope(scope).diagnostics;
131
+ const matches = warnings.filter(predicate);
132
+ if (matches.length === 0) {
133
+ throw new Error("expected at least one warning matching predicate");
134
+ }
135
+ return matches;
136
+ });
137
+ /**
138
+ * Snapshot the scoped diagnostics buffer without asserting. Useful when a
139
+ * scenario wants to verify the absence of a warning class.
140
+ */
141
+ export const readDiagnostics = (ctx, scope) => ctx.scope(scope).diagnostics;
142
+ //# sourceMappingURL=scenario-harness.js.map
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Workspace read-model test layer.
3
+ *
4
+ * Provides {@link WorkspaceReadModelConfig}, {@link AgentRootResolver},
5
+ * `FileSystem`, and `Path` against fixture-built deps. Test bodies call
6
+ * {@link makeWorkspaceReadModel} directly to obtain a per-scope read model.
7
+ *
8
+ * The layer accepts an optional `options.allowedRoot`; when omitted, the
9
+ * filesystem root (`/`) is used so any `workspaceRoot` / `userHome` from the
10
+ * spec is allowed. Tests that want to verify root-escape failure pass an
11
+ * `allowedRoot` outside the spec's `workspaceRoot`.
12
+ *
13
+ * Tests that need to inject filesystem-level faults (e.g. simulate read
14
+ * failures) provide `options.wrapFileSystem` to wrap the fixture's
15
+ * `FileSystem` before it is composed into the layer.
16
+ */
17
+ import * as FileSystem from "effect/FileSystem";
18
+ import * as Layer from "effect/Layer";
19
+ import * as Path from "effect/Path";
20
+ import { AgentRootResolver } from "../agent-root-resolver.js";
21
+ import { AgentPresenceProbe, type AgentPresenceProbeService } from "../agent-presence.js";
22
+ import { WorkspaceReadModelConfig } from "../service.js";
23
+ import { type FixtureSpec, type PathEscapeError } from "./builder.js";
24
+ /**
25
+ * Optional layer-construction options for {@link WorkspaceReadModelTest}.
26
+ *
27
+ * - `allowedRoot` — workspace-root containment boundary used by
28
+ * {@link makeWorkspaceReadModel} to validate `projectRoot` and `userHome`.
29
+ * Defaults to the filesystem root so tests opt into root-escape behaviour
30
+ * explicitly.
31
+ * - `wrapFileSystem` — optional adapter applied to the fixture's
32
+ * `FileSystem` before it is provided. Tests that simulate IO faults (e.g.
33
+ * read failures on specific paths) wrap the underlying filesystem here
34
+ * without forking the test layer.
35
+ * - `probe` — optional agent-presence probe factory over the fixture's
36
+ * `FileSystem` and `Path`. Defaults to detecting no agents; hosts with a
37
+ * real detection implementation inject one here.
38
+ */
39
+ export interface WorkspaceReadModelTestOptions {
40
+ readonly allowedRoot?: string;
41
+ readonly wrapFileSystem?: (fs: FileSystem.FileSystem) => FileSystem.FileSystem;
42
+ readonly probe?: (fs: FileSystem.FileSystem, path: Path.Path) => AgentPresenceProbeService;
43
+ }
44
+ /**
45
+ * Test layer for the workspace read model. Composes the fixture-built
46
+ * `FileSystem` / `Path` with {@link WorkspaceReadModelConfig} and
47
+ * {@link AgentRootResolver}, the dependencies callers need to invoke
48
+ * {@link makeWorkspaceReadModel}.
49
+ *
50
+ * The error channel covers:
51
+ *
52
+ * - `PathEscapeError` — fixture builder rejection (escapes the
53
+ * synthesized tree). Tests that need to assert this branch pass a
54
+ * spec with a `..`-laden tree entry.
55
+ *
56
+ * Workspace-root escape (`WorkspaceRootEscape`) surfaces from
57
+ * {@link makeWorkspaceReadModel} itself, not the layer.
58
+ */
59
+ export declare const WorkspaceReadModelTest: (spec: FixtureSpec, options?: WorkspaceReadModelTestOptions) => Layer.Layer<FileSystem.FileSystem | Path.Path | WorkspaceReadModelConfig | AgentRootResolver | AgentPresenceProbe, PathEscapeError>;
60
+ //# sourceMappingURL=test-layer.d.ts.map
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Workspace read-model test layer.
3
+ *
4
+ * Provides {@link WorkspaceReadModelConfig}, {@link AgentRootResolver},
5
+ * `FileSystem`, and `Path` against fixture-built deps. Test bodies call
6
+ * {@link makeWorkspaceReadModel} directly to obtain a per-scope read model.
7
+ *
8
+ * The layer accepts an optional `options.allowedRoot`; when omitted, the
9
+ * filesystem root (`/`) is used so any `workspaceRoot` / `userHome` from the
10
+ * spec is allowed. Tests that want to verify root-escape failure pass an
11
+ * `allowedRoot` outside the spec's `workspaceRoot`.
12
+ *
13
+ * Tests that need to inject filesystem-level faults (e.g. simulate read
14
+ * failures) provide `options.wrapFileSystem` to wrap the fixture's
15
+ * `FileSystem` before it is composed into the layer.
16
+ */
17
+ import * as Effect from "effect/Effect";
18
+ import * as FileSystem from "effect/FileSystem";
19
+ import * as Layer from "effect/Layer";
20
+ import * as Path from "effect/Path";
21
+ import { makeAbsolutePath } from "@agentxm/extension-model/unstable/path-types";
22
+ import { AgentRootResolver, AgentRootResolverLive } from "../agent-root-resolver.js";
23
+ import { AgentPresenceProbe } from "../agent-presence.js";
24
+ import { WorkspaceReadModelConfig } from "../service.js";
25
+ import { buildFixture } from "./builder.js";
26
+ /**
27
+ * Test layer for the workspace read model. Composes the fixture-built
28
+ * `FileSystem` / `Path` with {@link WorkspaceReadModelConfig} and
29
+ * {@link AgentRootResolver}, the dependencies callers need to invoke
30
+ * {@link makeWorkspaceReadModel}.
31
+ *
32
+ * The error channel covers:
33
+ *
34
+ * - `PathEscapeError` — fixture builder rejection (escapes the
35
+ * synthesized tree). Tests that need to assert this branch pass a
36
+ * spec with a `..`-laden tree entry.
37
+ *
38
+ * Workspace-root escape (`WorkspaceRootEscape`) surfaces from
39
+ * {@link makeWorkspaceReadModel} itself, not the layer.
40
+ */
41
+ export const WorkspaceReadModelTest = (spec, options = {}) => Layer.unwrap(Effect.gen(function* () {
42
+ const deps = yield* buildFixture(spec);
43
+ const fs = options.wrapFileSystem === undefined ? deps.fs : options.wrapFileSystem(deps.fs);
44
+ const fsLayer = Layer.succeed(FileSystem.FileSystem, fs);
45
+ const pathLayer = Layer.succeed(Path.Path, deps.path);
46
+ const allowedRoot = options.allowedRoot ?? "/";
47
+ const configLayer = Layer.succeed(WorkspaceReadModelConfig, {
48
+ projectRoot: makeAbsolutePath(deps.path, deps.workspaceRoot),
49
+ userHome: makeAbsolutePath(deps.path, deps.userHome),
50
+ allowedRoot: makeAbsolutePath(deps.path, allowedRoot),
51
+ });
52
+ const probeLayer = Layer.succeed(AgentPresenceProbe, options.probe?.(fs, deps.path) ?? {
53
+ detect: () => Effect.succeed(new Set()),
54
+ });
55
+ return Layer.mergeAll(fsLayer, pathLayer, configLayer, probeLayer, AgentRootResolverLive.pipe(Layer.provide(pathLayer)));
56
+ }));
57
+ //# sourceMappingURL=test-layer.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Agent-presence probe port.
3
+ *
4
+ * The read model records which agents are present on the machine as a
5
+ * scoped fact. Detection itself is agent-surface integration, so the state
6
+ * layer declares only this optional port; the application composes an
7
+ * implementation backed by agent detection. An absent probe degrades to an
8
+ * empty presence set, matching the read model's existing failure
9
+ * degradation.
10
+ *
11
+ * @experimental This API is unstable and may change without notice.
12
+ */
13
+ import * as Effect from "effect/Effect";
14
+ import * as ServiceMap from "effect/Context";
15
+ import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
16
+ import type { WorkspaceScope } from "@agentxm/extension-model/unstable/workspace-scope";
17
+ declare const AgentPresenceUnavailable_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
18
+ readonly _tag: "AgentPresenceUnavailable";
19
+ } & Readonly<A>;
20
+ /** Presence detection failed; the read model degrades to an empty set. */
21
+ export declare class AgentPresenceUnavailable extends AgentPresenceUnavailable_base<{
22
+ readonly message: string;
23
+ }> {
24
+ }
25
+ export interface AgentPresenceProbeService {
26
+ readonly detect: (root: string, scope: WorkspaceScope) => Effect.Effect<ReadonlySet<AgentId>, AgentPresenceUnavailable>;
27
+ }
28
+ declare const AgentPresenceProbe_base: ServiceMap.ServiceClass<AgentPresenceProbe, "@agentxm/workspace-state/workspace/read-model/agent-presence/AgentPresenceProbe", AgentPresenceProbeService>;
29
+ export declare class AgentPresenceProbe extends AgentPresenceProbe_base {
30
+ }
31
+ export {};
32
+ //# sourceMappingURL=agent-presence.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Agent-presence probe port.
3
+ *
4
+ * The read model records which agents are present on the machine as a
5
+ * scoped fact. Detection itself is agent-surface integration, so the state
6
+ * layer declares only this optional port; the application composes an
7
+ * implementation backed by agent detection. An absent probe degrades to an
8
+ * empty presence set, matching the read model's existing failure
9
+ * degradation.
10
+ *
11
+ * @experimental This API is unstable and may change without notice.
12
+ */
13
+ import * as Data from "effect/Data";
14
+ import * as Effect from "effect/Effect";
15
+ import * as ServiceMap from "effect/Context";
16
+ /** Presence detection failed; the read model degrades to an empty set. */
17
+ export class AgentPresenceUnavailable extends Data.TaggedError("AgentPresenceUnavailable") {
18
+ }
19
+ export class AgentPresenceProbe extends ServiceMap.Service()("@agentxm/workspace-state/workspace/read-model/agent-presence/AgentPresenceProbe") {
20
+ }
21
+ //# sourceMappingURL=agent-presence.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Cross-scope agent-root resolver service.
3
+ *
4
+ * Wraps the {@link AgentRootResolverState} and the snapshot of warnings
5
+ * emitted by {@link detectAgentRootCollisions}. Sharing one resolver across
6
+ * the per-scope factory ensures the heuristic-fallback warning fires at most
7
+ * once per agent across both scopes and both `mcp-config` / `agent-settings`
8
+ * scanners. Collision detection runs once at layer construction and exposes
9
+ * its warnings as an eager snapshot the project-scope read model seeds into
10
+ * its diagnostics buffer.
11
+ */
12
+ import * as ServiceMap from "effect/Context";
13
+ import * as Layer from "effect/Layer";
14
+ import * as Path from "effect/Path";
15
+ import { type Warning } from "./diagnostics.js";
16
+ import { type AgentRootResolverState } from "./scanners/agent-root.js";
17
+ /** Public shape of the {@link AgentRootResolver} service. */
18
+ export interface AgentRootResolverShape {
19
+ /** Shared resolver state passed to scanners that resolve agent roots. */
20
+ readonly state: AgentRootResolverState;
21
+ /**
22
+ * Snapshot of `scanner-config` warnings produced by
23
+ * {@link detectAgentRootCollisions} at layer construction. The project
24
+ * scope seeds these into its diagnostics buffer; the user scope does not.
25
+ */
26
+ readonly collisionWarnings: ReadonlyArray<Warning>;
27
+ }
28
+ declare const AgentRootResolver_base: ServiceMap.ServiceClass<AgentRootResolver, "@agentxm/workspace-state/workspace/read-model/agent-root-resolver/AgentRootResolver", AgentRootResolverShape>;
29
+ /** Service tag for the cross-scope agent-root resolver. */
30
+ export declare class AgentRootResolver extends AgentRootResolver_base {
31
+ }
32
+ /**
33
+ * Live layer for {@link AgentRootResolver}. Allocates the shared state and
34
+ * runs collision detection once when the layer is built.
35
+ */
36
+ export declare const AgentRootResolverLive: Layer.Layer<AgentRootResolver, never, Path.Path>;
37
+ export {};
38
+ //# sourceMappingURL=agent-root-resolver.d.ts.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Cross-scope agent-root resolver service.
3
+ *
4
+ * Wraps the {@link AgentRootResolverState} and the snapshot of warnings
5
+ * emitted by {@link detectAgentRootCollisions}. Sharing one resolver across
6
+ * the per-scope factory ensures the heuristic-fallback warning fires at most
7
+ * once per agent across both scopes and both `mcp-config` / `agent-settings`
8
+ * scanners. Collision detection runs once at layer construction and exposes
9
+ * its warnings as an eager snapshot the project-scope read model seeds into
10
+ * its diagnostics buffer.
11
+ */
12
+ import * as ServiceMap from "effect/Context";
13
+ import * as Effect from "effect/Effect";
14
+ import * as Layer from "effect/Layer";
15
+ import * as Path from "effect/Path";
16
+ import * as Ref from "effect/Ref";
17
+ import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
18
+ import { makeDiagnostics } from "./diagnostics.js";
19
+ import { detectAgentRootCollisions, makeAgentRootResolverState, } from "./scanners/agent-root.js";
20
+ /** Service tag for the cross-scope agent-root resolver. */
21
+ export class AgentRootResolver extends ServiceMap.Service()("@agentxm/workspace-state/workspace/read-model/agent-root-resolver/AgentRootResolver") {
22
+ }
23
+ /**
24
+ * Live layer for {@link AgentRootResolver}. Allocates the shared state and
25
+ * runs collision detection once when the layer is built.
26
+ */
27
+ export const AgentRootResolverLive = Layer.effect(AgentRootResolver, Effect.gen(function* () {
28
+ const path = yield* Path.Path;
29
+ const state = makeAgentRootResolverState();
30
+ const ref = yield* Ref.make([]);
31
+ yield* detectAgentRootCollisions(path, Object.values(AGENTS), makeDiagnostics(ref));
32
+ const collisionWarnings = yield* Ref.get(ref);
33
+ return AgentRootResolver.of({ state, collisionWarnings });
34
+ }).pipe(Effect.withSpan("workspace.read-model.agent-root-resolver.build")));
35
+ //# sourceMappingURL=agent-root-resolver.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Catalog-derived agent projections and the scoped agent read-model API.
3
+ *
4
+ * All agents share the same declared, actual, and detected projectors. The
5
+ * canonical capability catalog carries genuine per-agent variance, so adding
6
+ * an agent does not require a placeholder module or registry edit here.
7
+ */
8
+ import * as Effect from "effect/Effect";
9
+ import * as Option from "effect/Option";
10
+ import { type AgentDescriptor, type AgentId, type ConfigurableAgentId } from "@agentxm/extension-model/unstable/agents/types";
11
+ import type { SettingsReadError } from "../errors.js";
12
+ import type { Scope } from "../types.js";
13
+ import { type ActualAgent, type AgentModule, type AgentScannerObservations, type DeclaredAgent, type DeclaredSettingsShape, type DetectedAgent } from "./types.js";
14
+ export type { ActualAgent, AgentModule, AgentScannerObservations, AgentSubjectType, DeclaredAgent, DeclaredSettingsShape, DetectedAgent, DetectionStatus, } from "./types.js";
15
+ export { defineAgentModule } from "./types.js";
16
+ /** Every configurable catalog agent, in canonical order. */
17
+ export declare const registeredAgentModules: ReadonlyArray<AgentModule<ConfigurableAgentId>>;
18
+ /** Build the common projector module for one catalog agent. */
19
+ export declare const getAgentModule: <TId extends ConfigurableAgentId>(id: TId) => AgentModule<TId>;
20
+ /** Public shape of `ctx.scope(scope).agents`. */
21
+ export interface ScopedAgentsApi {
22
+ readonly list: Effect.Effect<ReadonlyArray<AgentId>>;
23
+ readonly known: Effect.Effect<ReadonlyArray<AgentDescriptor>>;
24
+ readonly byId: (id: string) => Option.Option<AgentDescriptor>;
25
+ readonly declared: (id: AgentId) => Effect.Effect<Option.Option<DeclaredAgent>, SettingsReadError>;
26
+ readonly actual: (id: AgentId) => Effect.Effect<Option.Option<ActualAgent>>;
27
+ readonly detected: Effect.Effect<ReadonlyArray<DetectedAgent>>;
28
+ }
29
+ /** Dependency-closed inputs captured by the scoped agent API. */
30
+ export interface ScopedAgentsApiDeps {
31
+ readonly scope: Scope;
32
+ readonly settings: Effect.Effect<Option.Option<DeclaredSettingsShape>, SettingsReadError>;
33
+ readonly presence: Effect.Effect<ReadonlySet<AgentId>>;
34
+ readonly observations: Effect.Effect<AgentScannerObservations>;
35
+ }
36
+ /** Build the agent portion of a scoped workspace read model. */
37
+ export declare const makeScopedAgentsApi: (deps: ScopedAgentsApiDeps) => ScopedAgentsApi;
38
+ //# sourceMappingURL=index.d.ts.map