@agentxm/workspace-projection 0.28.14-preview.1789139351.5cd4595aa

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 (75) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +17 -0
  3. package/dist/src/agent-output-observation.d.ts +59 -0
  4. package/dist/src/agent-output-observation.js +226 -0
  5. package/dist/src/agents/coding-agent-repository.d.ts +33 -0
  6. package/dist/src/agents/coding-agent-repository.js +19 -0
  7. package/dist/src/agents/repository.d.ts +14 -0
  8. package/dist/src/agents/repository.js +25 -0
  9. package/dist/src/agents/selection.d.ts +27 -0
  10. package/dist/src/agents/selection.js +33 -0
  11. package/dist/src/constraint-invariant-fact.d.ts +68 -0
  12. package/dist/src/constraint-invariant-fact.js +156 -0
  13. package/dist/src/contributors.d.ts +78 -0
  14. package/dist/src/contributors.js +82 -0
  15. package/dist/src/errors.d.ts +119 -0
  16. package/dist/src/errors.js +57 -0
  17. package/dist/src/exclusions.d.ts +39 -0
  18. package/dist/src/exclusions.js +34 -0
  19. package/dist/src/expected-names.d.ts +25 -0
  20. package/dist/src/expected-names.js +29 -0
  21. package/dist/src/generation.d.ts +6 -0
  22. package/dist/src/generation.js +7 -0
  23. package/dist/src/hooks/outcomes.d.ts +14 -0
  24. package/dist/src/hooks/outcomes.js +53 -0
  25. package/dist/src/index.d.ts +50 -0
  26. package/dist/src/index.js +61 -0
  27. package/dist/src/instructions/errors.d.ts +30 -0
  28. package/dist/src/instructions/errors.js +25 -0
  29. package/dist/src/instructions/instructions.d.ts +236 -0
  30. package/dist/src/instructions/instructions.js +1042 -0
  31. package/dist/src/instructions/reconciliation.d.ts +83 -0
  32. package/dist/src/instructions/reconciliation.js +113 -0
  33. package/dist/src/invariant-facts.d.ts +95 -0
  34. package/dist/src/invariant-facts.js +239 -0
  35. package/dist/src/knowledge/discovery.d.ts +40 -0
  36. package/dist/src/knowledge/discovery.js +112 -0
  37. package/dist/src/knowledge/installed-bundles.d.ts +42 -0
  38. package/dist/src/knowledge/installed-bundles.js +70 -0
  39. package/dist/src/knowledge/instruction-entry.d.ts +18 -0
  40. package/dist/src/knowledge/instruction-entry.js +23 -0
  41. package/dist/src/live.d.ts +11 -0
  42. package/dist/src/live.js +11 -0
  43. package/dist/src/managed-file-banner.d.ts +44 -0
  44. package/dist/src/managed-file-banner.js +121 -0
  45. package/dist/src/managed-file-discovery.d.ts +27 -0
  46. package/dist/src/managed-file-discovery.js +43 -0
  47. package/dist/src/managed-region-adapter.d.ts +34 -0
  48. package/dist/src/managed-region-adapter.js +85 -0
  49. package/dist/src/materialization-currency.d.ts +39 -0
  50. package/dist/src/materialization-currency.js +86 -0
  51. package/dist/src/mcps/drift.d.ts +19 -0
  52. package/dist/src/mcps/drift.js +43 -0
  53. package/dist/src/mcps/errors.d.ts +14 -0
  54. package/dist/src/mcps/errors.js +12 -0
  55. package/dist/src/mcps/inspection.d.ts +52 -0
  56. package/dist/src/mcps/inspection.js +349 -0
  57. package/dist/src/native-write-authority-live.d.ts +13 -0
  58. package/dist/src/native-write-authority-live.js +18 -0
  59. package/dist/src/packs/dependency-reachability.d.ts +37 -0
  60. package/dist/src/packs/dependency-reachability.js +53 -0
  61. package/dist/src/participants.d.ts +86 -0
  62. package/dist/src/participants.js +49 -0
  63. package/dist/src/planning.d.ts +103 -0
  64. package/dist/src/planning.js +98 -0
  65. package/dist/src/subagents/managed-file.d.ts +5 -0
  66. package/dist/src/subagents/managed-file.js +9 -0
  67. package/dist/src/subagents/managed-render.d.ts +24 -0
  68. package/dist/src/subagents/managed-render.js +38 -0
  69. package/dist/src/testing.d.ts +38 -0
  70. package/dist/src/testing.js +45 -0
  71. package/dist/src/units.d.ts +97 -0
  72. package/dist/src/units.js +67 -0
  73. package/dist/src/workspace-catalog-live.d.ts +24 -0
  74. package/dist/src/workspace-catalog-live.js +115 -0
  75. package/package.json +67 -0
package/LICENSE ADDED
@@ -0,0 +1,110 @@
1
+ # Functional Source License, Version 1.1, MIT Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-MIT
6
+
7
+ ## Notice
8
+
9
+ Copyright 2025-2026 AgentXM, Inc.
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the MIT license that is effective on the second anniversary of the date we make
91
+ the Software available. On or after that date, you may use the Software under
92
+ the MIT license, in which case the following will apply:
93
+
94
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
95
+ this software and associated documentation files (the "Software"), to deal in
96
+ the Software without restriction, including without limitation the rights to
97
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
98
+ of the Software, and to permit persons to whom the Software is furnished to do
99
+ so, subject to the following conditions:
100
+
101
+ The above copyright notice and this permission notice shall be included in all
102
+ copies or substantial portions of the Software.
103
+
104
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
105
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
106
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
107
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
108
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
109
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
110
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @agentxm/workspace-projection
2
+
3
+ The AXM workspace projection capability: the ownership-unit registry, projection
4
+ planning and its participant registry, managed-file ownership grammar and
5
+ provenance banners, managed-region reconciliation, instruction targets, workspace
6
+ invariant facts, and the read-side reconciliation facts (MCP drift, hook agent
7
+ outcomes, Knowledge discovery and instruction entries, agent-output observation)
8
+ that lint, sync, and inspection consume without re-deriving them.
9
+
10
+ The package root is the public API; the coding-agent repository layer, the
11
+ participant-free invariant-facts layer, and the native-write authority that lets
12
+ `@agentxm/agent-integration` write under the enclosing workspace transaction live
13
+ behind `./live`. Deterministic ports for feature tests live behind `./testing`.
14
+ The surface is unsupported and may change in any release. Ordinary users should
15
+ use the [`axm` CLI](https://axm.sh) instead.
16
+
17
+ Part of the [AgentXM](https://agentxm.ai) toolchain.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Read-only inventory of agent-native outputs and their ownership proofs.
3
+ *
4
+ * Output containers may be shared by several coding agents. An output is
5
+ * desired when at least one claimant for its resolved container is desired and
6
+ * its managed unit name is expected for that extension type.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import * as Effect from "effect/Effect";
11
+ import * as FileSystem from "effect/FileSystem";
12
+ import * as Path from "effect/Path";
13
+ import type { PerAgentType } from "@agentxm/extension-model/unstable/extensions/common";
14
+ import type { WorkspaceScope } from "@agentxm/extension-model/unstable/workspace-scope";
15
+ import { CodingAgentRepository } from "./agents/coding-agent-repository.js";
16
+ import { type WorkspaceOwnershipIssue } from "./managed-file-discovery.js";
17
+ export type AgentOutputOwnershipProof = "storage-root-symlink" | "managed-banner" | "managed-mcp-entry" | "managed-hook-group";
18
+ export interface AgentOutputObservation {
19
+ readonly extensionType: PerAgentType;
20
+ readonly containerPath: string;
21
+ readonly path: string;
22
+ readonly entryName: string;
23
+ readonly claimantAgentIds: ReadonlyArray<string>;
24
+ readonly ownership: "owned" | "unowned";
25
+ readonly proof?: AgentOutputOwnershipProof;
26
+ readonly desired: boolean;
27
+ }
28
+ export interface AgentOutputInventory {
29
+ readonly outputs: ReadonlyArray<AgentOutputObservation>;
30
+ readonly ownedResidue: ReadonlyArray<AgentOutputObservation>;
31
+ readonly unownedFootprints: ReadonlyArray<AgentOutputObservation>;
32
+ }
33
+ export interface ObserveAgentOutputsArgs {
34
+ readonly workspaceRoot: string;
35
+ readonly scope: WorkspaceScope;
36
+ readonly desiredAgentIds: ReadonlySet<string>;
37
+ readonly expectedNames: Readonly<Record<PerAgentType, ReadonlySet<string>>>;
38
+ readonly skillOwnershipRoots: ReadonlyArray<string>;
39
+ }
40
+ /** Observe every known agent output without writing to the workspace. */
41
+ export declare const observeAgentOutputs: (args: ObserveAgentOutputsArgs) => Effect.Effect<AgentOutputInventory, never, CodingAgentRepository | FileSystem.FileSystem | Path.Path>;
42
+ /**
43
+ * The ownership problems a workspace's agent-native outputs present, with no
44
+ * expectation of what should be there.
45
+ *
46
+ * Reporting ownership is a different question from reconciling it: the
47
+ * reporter must not need a desired graph, because the workspaces most in need
48
+ * of the answer are the ones whose desired state cannot be resolved. Every
49
+ * expected-name set is therefore empty, and the answer is only about proof —
50
+ * a file that sits where AXM writes but carries no ownership marker, and a
51
+ * hook command pointed at an AXM canonical path without one.
52
+ */
53
+ export declare const observeWorkspaceOwnershipIssues: (args: {
54
+ readonly workspaceRoot: string;
55
+ readonly scope: WorkspaceScope;
56
+ readonly configuredAgentIds: ReadonlySet<string>;
57
+ readonly skillOwnershipRoots: ReadonlyArray<string>;
58
+ }) => Effect.Effect<ReadonlyArray<WorkspaceOwnershipIssue>, never, CodingAgentRepository | FileSystem.FileSystem | Path.Path>;
59
+ //# sourceMappingURL=agent-output-observation.d.ts.map
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Read-only inventory of agent-native outputs and their ownership proofs.
3
+ *
4
+ * Output containers may be shared by several coding agents. An output is
5
+ * desired when at least one claimant for its resolved container is desired and
6
+ * its managed unit name is expected for that extension type.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import * as Effect from "effect/Effect";
11
+ import * as FileSystem from "effect/FileSystem";
12
+ import * as Path from "effect/Path";
13
+ import { AGENTS as CAPABILITY_AGENTS } from "@agentxm/extension-model/unstable/agent-capabilities";
14
+ import { CodingAgentRepository } from "./agents/coding-agent-repository.js";
15
+ import { extensionNameFromFilename, hasAxmManagedMarker, safeReadDirectory, safeReadFileString, } from "./managed-file-discovery.js";
16
+ import { collectManagedAgentMcpServers } from "./mcps/inspection.js";
17
+ import { readAmbiguousHookCommands, readManagedHookUnits } from "@agentxm/agent-integration";
18
+ const isWithin = (path, parent, child) => {
19
+ const relative = path.relative(path.resolve(parent), path.resolve(child));
20
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
21
+ };
22
+ const groupContainers = (containers) => {
23
+ const grouped = new Map();
24
+ for (const container of containers) {
25
+ const claimants = grouped.get(container.path) ?? new Set();
26
+ claimants.add(container.agentId);
27
+ grouped.set(container.path, claimants);
28
+ }
29
+ return [...grouped].map(([path, claimants]) => ({
30
+ path,
31
+ claimantAgentIds: [...claimants].sort(),
32
+ }));
33
+ };
34
+ const containerIsDesired = (claimantAgentIds, desiredAgentIds) => claimantAgentIds.some((agentId) => desiredAgentIds.has(agentId));
35
+ /** Observe every known agent output without writing to the workspace. */
36
+ export const observeAgentOutputs = (args) => Effect.gen(function* () {
37
+ const fs = yield* FileSystem.FileSystem;
38
+ const path = yield* Path.Path;
39
+ const agentRepo = yield* CodingAgentRepository;
40
+ const agents = yield* agentRepo.all;
41
+ const outputs = [];
42
+ const ownershipRoots = yield* Effect.forEach(args.skillOwnershipRoots, (root) => fs.realPath(root).pipe(Effect.orElseSucceed(() => path.resolve(root))));
43
+ const skillContainers = yield* Effect.forEach(agents, (agent) => agent.resolveEffectiveSkillsDir({ workspaceRoot: args.workspaceRoot }).pipe(Effect.map((resolved) => resolved._tag === "supported"
44
+ ? [{ path: path.resolve(resolved.dir), agentId: agent.id }]
45
+ : []), Effect.catch(() => Effect.succeed([])))).pipe(Effect.map((containers) => containers.flat()));
46
+ for (const container of groupContainers(skillContainers)) {
47
+ const desiredContainer = containerIsDesired(container.claimantAgentIds, args.desiredAgentIds);
48
+ for (const entry of yield* safeReadDirectory(fs, container.path)) {
49
+ const artifactPath = path.join(container.path, entry);
50
+ const linkTarget = yield* fs.readLink(artifactPath).pipe(Effect.option);
51
+ let proof;
52
+ if (linkTarget._tag === "Some") {
53
+ const resolvedTarget = path.resolve(container.path, linkTarget.value);
54
+ const canonicalTarget = yield* fs
55
+ .realPath(resolvedTarget)
56
+ .pipe(Effect.orElseSucceed(() => resolvedTarget));
57
+ if (ownershipRoots.some((root) => isWithin(path, root, canonicalTarget))) {
58
+ proof = "storage-root-symlink";
59
+ }
60
+ }
61
+ else {
62
+ const stat = yield* fs.stat(artifactPath).pipe(Effect.option);
63
+ if (stat._tag === "Some" && stat.value.type === "Directory") {
64
+ const content = yield* safeReadFileString(fs, path.join(artifactPath, "SKILL.md"));
65
+ if (hasAxmManagedMarker(content))
66
+ proof = "managed-banner";
67
+ }
68
+ }
69
+ outputs.push({
70
+ extensionType: "skill",
71
+ containerPath: container.path,
72
+ path: artifactPath,
73
+ entryName: entry,
74
+ claimantAgentIds: container.claimantAgentIds,
75
+ ownership: proof === undefined ? "unowned" : "owned",
76
+ ...(proof === undefined ? {} : { proof }),
77
+ desired: desiredContainer && args.expectedNames.skill.has(entry),
78
+ });
79
+ }
80
+ }
81
+ const subagentContainers = yield* Effect.forEach(agents, (agent) => agent
82
+ .resolveEffectiveSubagentsDir({ workspaceRoot: args.workspaceRoot, scope: args.scope })
83
+ .pipe(Effect.map((resolved) => resolved._tag === "supported"
84
+ ? [{ path: path.resolve(resolved.dir), agentId: agent.id }]
85
+ : []), Effect.catch(() => Effect.succeed([])))).pipe(Effect.map((containers) => containers.flat()));
86
+ for (const container of groupContainers(subagentContainers)) {
87
+ const desiredContainer = containerIsDesired(container.claimantAgentIds, args.desiredAgentIds);
88
+ for (const entry of yield* safeReadDirectory(fs, container.path)) {
89
+ const artifactPath = path.join(container.path, entry);
90
+ const stat = yield* fs.stat(artifactPath).pipe(Effect.option);
91
+ if (stat._tag === "None" || stat.value.type !== "File")
92
+ continue;
93
+ const content = yield* safeReadFileString(fs, artifactPath);
94
+ const managed = hasAxmManagedMarker(content);
95
+ const entryName = extensionNameFromFilename(entry);
96
+ outputs.push({
97
+ extensionType: "subagent",
98
+ containerPath: container.path,
99
+ path: artifactPath,
100
+ entryName,
101
+ claimantAgentIds: container.claimantAgentIds,
102
+ ownership: managed ? "owned" : "unowned",
103
+ ...(managed ? { proof: "managed-banner" } : {}),
104
+ desired: desiredContainer && args.expectedNames.subagent.has(entryName),
105
+ });
106
+ }
107
+ }
108
+ const capabilityAgentIds = CAPABILITY_AGENTS.map(({ id }) => id);
109
+ const managedMcpServers = yield* collectManagedAgentMcpServers({
110
+ workspaceRoot: args.workspaceRoot,
111
+ scope: args.scope,
112
+ agentIds: capabilityAgentIds,
113
+ }).pipe(Effect.catch(() => Effect.succeed([])));
114
+ const mcpGroups = new Map();
115
+ for (const server of managedMcpServers) {
116
+ const key = `${server.absolutePath}\u0000${server.serverName}`;
117
+ const group = mcpGroups.get(key) ?? {
118
+ path: server.absolutePath,
119
+ name: server.serverName,
120
+ claimants: new Set(),
121
+ };
122
+ group.claimants.add(server.agentId);
123
+ mcpGroups.set(key, group);
124
+ }
125
+ for (const group of mcpGroups.values()) {
126
+ const claimants = [...group.claimants].sort();
127
+ outputs.push({
128
+ extensionType: "mcp-server",
129
+ containerPath: group.path,
130
+ path: `${group.path}#${group.name}`,
131
+ entryName: group.name,
132
+ claimantAgentIds: claimants,
133
+ ownership: "owned",
134
+ proof: "managed-mcp-entry",
135
+ desired: containerIsDesired(claimants, args.desiredAgentIds) &&
136
+ args.expectedNames["mcp-server"].has(group.name),
137
+ });
138
+ }
139
+ const hookContainers = new Map();
140
+ for (const agent of CAPABILITY_AGENTS) {
141
+ const writer = agent.capabilities.hook.axm.writer;
142
+ if (writer === null)
143
+ continue;
144
+ for (const file of writer.configFiles.filter((candidate) => candidate.scope === args.scope && candidate.format === "json")) {
145
+ const configPath = path.resolve(args.workspaceRoot, file.path);
146
+ const key = `${configPath}\u0000${writer.settingsKey}`;
147
+ const group = hookContainers.get(key) ?? {
148
+ path: configPath,
149
+ settingsKey: writer.settingsKey,
150
+ claimants: new Set(),
151
+ };
152
+ group.claimants.add(agent.id);
153
+ hookContainers.set(key, group);
154
+ }
155
+ }
156
+ for (const group of hookContainers.values()) {
157
+ const exists = yield* fs.exists(group.path).pipe(Effect.catch(() => Effect.succeed(false)));
158
+ if (!exists)
159
+ continue;
160
+ const raw = yield* safeReadFileString(fs, group.path);
161
+ const claimants = [...group.claimants].sort();
162
+ const units = yield* readManagedHookUnits(group.path, group.settingsKey, raw).pipe(Effect.catch(() => Effect.succeed([])));
163
+ for (const unit of units) {
164
+ outputs.push({
165
+ extensionType: "hook",
166
+ containerPath: group.path,
167
+ path: `${group.path}#${unit.name}`,
168
+ entryName: unit.name,
169
+ claimantAgentIds: claimants,
170
+ ownership: "owned",
171
+ proof: "managed-hook-group",
172
+ desired: containerIsDesired(claimants, args.desiredAgentIds) &&
173
+ args.expectedNames.hook.has(unit.name),
174
+ });
175
+ }
176
+ const ambiguous = yield* readAmbiguousHookCommands(group.path, group.settingsKey, raw).pipe(Effect.catch(() => Effect.succeed([])));
177
+ for (const command of ambiguous) {
178
+ outputs.push({
179
+ extensionType: "hook",
180
+ containerPath: group.path,
181
+ path: group.path,
182
+ entryName: command,
183
+ claimantAgentIds: claimants,
184
+ ownership: "unowned",
185
+ desired: false,
186
+ });
187
+ }
188
+ }
189
+ return {
190
+ outputs,
191
+ ownedResidue: outputs.filter((output) => output.ownership === "owned" && !output.desired),
192
+ unownedFootprints: outputs.filter((output) => output.ownership === "unowned"),
193
+ };
194
+ });
195
+ /**
196
+ * The ownership problems a workspace's agent-native outputs present, with no
197
+ * expectation of what should be there.
198
+ *
199
+ * Reporting ownership is a different question from reconciling it: the
200
+ * reporter must not need a desired graph, because the workspaces most in need
201
+ * of the answer are the ones whose desired state cannot be resolved. Every
202
+ * expected-name set is therefore empty, and the answer is only about proof —
203
+ * a file that sits where AXM writes but carries no ownership marker, and a
204
+ * hook command pointed at an AXM canonical path without one.
205
+ */
206
+ export const observeWorkspaceOwnershipIssues = (args) => observeAgentOutputs({
207
+ workspaceRoot: args.workspaceRoot,
208
+ scope: args.scope,
209
+ desiredAgentIds: args.configuredAgentIds,
210
+ expectedNames: {
211
+ skill: new Set(),
212
+ subagent: new Set(),
213
+ "mcp-server": new Set(),
214
+ hook: new Set(),
215
+ },
216
+ skillOwnershipRoots: args.skillOwnershipRoots,
217
+ }).pipe(Effect.map((observed) => observed.unownedFootprints.map((output) => ({
218
+ kind: output.extensionType === "hook"
219
+ ? "hook-ownership-ambiguous"
220
+ : "managed-file-unowned",
221
+ path: output.path,
222
+ detail: output.extensionType === "hook"
223
+ ? `Hook command targets an AXM canonical extension path without x-axm ownership metadata: ${output.entryName}`
224
+ : `Agent ${output.extensionType} artifact has no AXM ownership proof.`,
225
+ }))));
226
+ //# sourceMappingURL=agent-output-observation.js.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The coding-agent repository service.
3
+ *
4
+ * The per-agent adapter contract (`CodingAgent`) is native format mechanics
5
+ * and lives in `@agentxm/agent-integration`; deciding which agents a
6
+ * workspace projects onto is a core decision, so the repository that answers
7
+ * it lives here.
8
+ *
9
+ * The settings-derived members keep `WorkspaceMutations` in `R`. The decisions
10
+ * themselves are pure over the configured agent IDs (`selection.ts`), so a
11
+ * caller that already holds those IDs never needs the service at all.
12
+ *
13
+ * @experimental This API is unstable and may change without notice.
14
+ * @packageDocumentation
15
+ */
16
+ import type * as Effect from "effect/Effect";
17
+ import * as ServiceMap from "effect/Context";
18
+ import type { CodingAgent } from "@agentxm/agent-integration";
19
+ import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
20
+ import type { WorkspaceMutations, WorkspaceSettingsReadFailure } from "@agentxm/workspace-state";
21
+ /** Repository for coding-agent implementations. */
22
+ export interface CodingAgentRepositoryService {
23
+ readonly get: (id: AgentId) => Effect.Effect<CodingAgent>;
24
+ readonly all: Effect.Effect<ReadonlyArray<CodingAgent>>;
25
+ readonly getConfiguredAgents: () => Effect.Effect<ReadonlyArray<CodingAgent>, WorkspaceSettingsReadFailure, WorkspaceMutations>;
26
+ readonly getMaterializationAgents: () => Effect.Effect<ReadonlyArray<CodingAgent>, WorkspaceSettingsReadFailure, WorkspaceMutations>;
27
+ readonly getUnknownConfiguredAgentIds: () => Effect.Effect<ReadonlyArray<string>, WorkspaceSettingsReadFailure, WorkspaceMutations>;
28
+ }
29
+ declare const CodingAgentRepository_base: ServiceMap.ServiceClass<CodingAgentRepository, "@agentxm/workspace-projection/agents/CodingAgentRepository", CodingAgentRepositoryService>;
30
+ export declare class CodingAgentRepository extends CodingAgentRepository_base {
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=coding-agent-repository.d.ts.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The coding-agent repository service.
3
+ *
4
+ * The per-agent adapter contract (`CodingAgent`) is native format mechanics
5
+ * and lives in `@agentxm/agent-integration`; deciding which agents a
6
+ * workspace projects onto is a core decision, so the repository that answers
7
+ * it lives here.
8
+ *
9
+ * The settings-derived members keep `WorkspaceMutations` in `R`. The decisions
10
+ * themselves are pure over the configured agent IDs (`selection.ts`), so a
11
+ * caller that already holds those IDs never needs the service at all.
12
+ *
13
+ * @experimental This API is unstable and may change without notice.
14
+ * @packageDocumentation
15
+ */
16
+ import * as ServiceMap from "effect/Context";
17
+ export class CodingAgentRepository extends ServiceMap.Service()("@agentxm/workspace-projection/agents/CodingAgentRepository") {
18
+ }
19
+ //# sourceMappingURL=coding-agent-repository.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Coding-agent repository: which agents this workspace projects onto.
3
+ *
4
+ * Selecting the configured and materialization agents is a workspace
5
+ * decision made from settings; the decision itself is pure (`selection.ts`)
6
+ * and the per-agent adapters come from `@agentxm/agent-integration`.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import * as Layer from "effect/Layer";
11
+ import { CodingAgentRepository, type CodingAgentRepositoryService } from "./coding-agent-repository.js";
12
+ export declare const DefaultCodingAgentRepository: CodingAgentRepositoryService;
13
+ export declare const CodingAgentRepositoryLive: Layer.Layer<CodingAgentRepository, never, never>;
14
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Coding-agent repository: which agents this workspace projects onto.
3
+ *
4
+ * Selecting the configured and materialization agents is a workspace
5
+ * decision made from settings; the decision itself is pure (`selection.ts`)
6
+ * and the per-agent adapters come from `@agentxm/agent-integration`.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import * as Effect from "effect/Effect";
11
+ import * as Layer from "effect/Layer";
12
+ import { codingAgentForId } from "@agentxm/agent-integration";
13
+ import { WorkspaceMutations } from "@agentxm/workspace-state";
14
+ import { CodingAgentRepository, } from "./coding-agent-repository.js";
15
+ import { allCodingAgents, configuredCodingAgents, materializationCodingAgents, unknownConfiguredAgentIds, } from "./selection.js";
16
+ const configuredAgentIds = () => WorkspaceMutations.pipe(Effect.flatMap((ws) => ws.getConfiguredAgents()));
17
+ export const DefaultCodingAgentRepository = {
18
+ get: (id) => Effect.succeed(codingAgentForId(id)),
19
+ all: Effect.sync(allCodingAgents),
20
+ getConfiguredAgents: () => configuredAgentIds().pipe(Effect.map(configuredCodingAgents)),
21
+ getMaterializationAgents: () => configuredAgentIds().pipe(Effect.map(materializationCodingAgents)),
22
+ getUnknownConfiguredAgentIds: () => configuredAgentIds().pipe(Effect.map(unknownConfiguredAgentIds)),
23
+ };
24
+ export const CodingAgentRepositoryLive = Layer.succeed(CodingAgentRepository, DefaultCodingAgentRepository);
25
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Which agents a workspace projects onto, decided from the configured agent
3
+ * IDs alone.
4
+ *
5
+ * Every function here is pure over the IDs settings declares, so planning,
6
+ * facts, and reporting share one decision instead of each re-reading settings.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import { type CodingAgent } from "@agentxm/agent-integration";
11
+ import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
12
+ /** The agent every workspace projects onto, whatever it configures. */
13
+ export declare const UNIVERSAL_AGENT_ID: "universal";
14
+ export declare const isKnownAgentId: (id: string) => id is AgentId;
15
+ /** Every adapter AXM ships, in catalog order. */
16
+ export declare const allCodingAgents: () => ReadonlyArray<CodingAgent>;
17
+ /**
18
+ * The configured agents AXM can project onto: known, configurable, in the
19
+ * order the workspace declared them. Unknown and non-configurable IDs are
20
+ * reported separately rather than silently dropped.
21
+ */
22
+ export declare const configuredCodingAgents: (configuredAgentIds: ReadonlyArray<string>) => ReadonlyArray<CodingAgent>;
23
+ /** The universal agent followed by every configured agent. */
24
+ export declare const materializationCodingAgents: (configuredAgentIds: ReadonlyArray<string>) => ReadonlyArray<CodingAgent>;
25
+ /** Configured IDs this AXM build does not recognise. */
26
+ export declare const unknownConfiguredAgentIds: (configuredAgentIds: ReadonlyArray<string>) => ReadonlyArray<string>;
27
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Which agents a workspace projects onto, decided from the configured agent
3
+ * IDs alone.
4
+ *
5
+ * Every function here is pure over the IDs settings declares, so planning,
6
+ * facts, and reporting share one decision instead of each re-reading settings.
7
+ *
8
+ * @experimental This API is unstable and may change without notice.
9
+ */
10
+ import { codingAgentForId } from "@agentxm/agent-integration";
11
+ import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
12
+ import { AGENT_IDS, isConfigurableAgentId } from "@agentxm/extension-model/unstable/agents/types";
13
+ /** The agent every workspace projects onto, whatever it configures. */
14
+ export const UNIVERSAL_AGENT_ID = "universal";
15
+ export const isKnownAgentId = (id) => Object.hasOwn(AGENTS, id);
16
+ /** Every adapter AXM ships, in catalog order. */
17
+ export const allCodingAgents = () => AGENT_IDS.map((id) => codingAgentForId(id));
18
+ /**
19
+ * The configured agents AXM can project onto: known, configurable, in the
20
+ * order the workspace declared them. Unknown and non-configurable IDs are
21
+ * reported separately rather than silently dropped.
22
+ */
23
+ export const configuredCodingAgents = (configuredAgentIds) => configuredAgentIds
24
+ .filter((id) => isKnownAgentId(id) && isConfigurableAgentId(id))
25
+ .map((id) => codingAgentForId(id));
26
+ /** The universal agent followed by every configured agent. */
27
+ export const materializationCodingAgents = (configuredAgentIds) => [
28
+ codingAgentForId(UNIVERSAL_AGENT_ID),
29
+ ...configuredCodingAgents(configuredAgentIds),
30
+ ];
31
+ /** Configured IDs this AXM build does not recognise. */
32
+ export const unknownConfiguredAgentIds = (configuredAgentIds) => configuredAgentIds.filter((id) => !isKnownAgentId(id));
33
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Shared invariant facts for desired extension version constraints.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ */
6
+ import { type ExtensionType } from "@agentxm/extension-model/unstable/extensions";
7
+ import type { PackDependencyAuthority, PackDependencyReachability } from "./packs/dependency-reachability.js";
8
+ import type { CanonicalConstraintContributor, CanonicalConstraintMismatchObservation } from "@agentxm/workspace-state";
9
+ import type { DesiredExtensionNode } from "@agentxm/workspace-state";
10
+ export declare const EXTENSION_CONSTRAINT_INVARIANT_PREDICATE: "workspace/extension-constraints-satisfied";
11
+ export interface ExtensionConstraintFactContributor extends CanonicalConstraintContributor {
12
+ readonly authority?: PackDependencyAuthority;
13
+ }
14
+ export interface ExtensionConstraintInvariantFact {
15
+ readonly predicate: typeof EXTENSION_CONSTRAINT_INVARIANT_PREDICATE;
16
+ readonly subject: {
17
+ readonly type: ExtensionType;
18
+ readonly name: string;
19
+ readonly identity: string;
20
+ readonly path?: string;
21
+ };
22
+ readonly authority: {
23
+ readonly source: "desired-state-graph" | "prospective-publish-selection";
24
+ readonly locator: string;
25
+ readonly constraints: ReadonlyArray<ExtensionConstraintFactContributor>;
26
+ };
27
+ readonly observation: {
28
+ readonly status: "constraint-mismatch";
29
+ readonly acceptedVersion?: string;
30
+ readonly observedVersion?: string;
31
+ readonly candidateVersion?: string;
32
+ readonly violations?: ReadonlyArray<ExtensionConstraintFactContributor>;
33
+ };
34
+ readonly expectation: {
35
+ readonly status: "satisfied";
36
+ readonly ranges: ReadonlyArray<string>;
37
+ };
38
+ }
39
+ export interface ProspectiveExtensionConstraintCandidate {
40
+ readonly fqn: string;
41
+ readonly type: ExtensionType;
42
+ readonly version: string;
43
+ readonly dependencies?: Readonly<Record<string, string>>;
44
+ }
45
+ /**
46
+ * Evaluate prospective selected versions against the locally represented Pack
47
+ * constraints. Selected Pack manifests replace their current local declaration
48
+ * for this fact evaluation, matching the state that a coordinated publication
49
+ * would establish.
50
+ */
51
+ export declare const makeProspectiveExtensionConstraintFacts: (args: {
52
+ readonly candidates: ReadonlyArray<ProspectiveExtensionConstraintCandidate>;
53
+ readonly reachability: ReadonlyArray<PackDependencyReachability>;
54
+ }) => ReadonlyArray<ExtensionConstraintInvariantFact>;
55
+ export type ExtensionConstraintPlanningDecision = {
56
+ readonly readiness: "ready";
57
+ readonly reason: "satisfying-version-resolved";
58
+ readonly version: string;
59
+ } | {
60
+ readonly readiness: "blocked";
61
+ readonly reason: "no-satisfying-version" | "candidate-violates-constraints";
62
+ readonly candidateVersion?: string;
63
+ };
64
+ export declare const makeExtensionConstraintInvariantFact: (desired: DesiredExtensionNode, observation: CanonicalConstraintMismatchObservation) => ExtensionConstraintInvariantFact;
65
+ export declare const planExtensionConstraintFact: (fact: ExtensionConstraintInvariantFact, candidateVersion: string | undefined) => ExtensionConstraintPlanningDecision;
66
+ /** Stable human and machine-display detail shared by lint and sync. */
67
+ export declare const extensionConstraintFactText: (fact: ExtensionConstraintInvariantFact) => string;
68
+ //# sourceMappingURL=constraint-invariant-fact.d.ts.map