@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.
- package/LICENSE +110 -0
- package/README.md +11 -0
- package/dist/src/index.d.ts +72 -0
- package/dist/src/index.js +88 -0
- package/dist/src/knowledge/discovery-config.d.ts +12 -0
- package/dist/src/knowledge/discovery-config.js +9 -0
- package/dist/src/lockfile/accepted-registry-version.d.ts +12 -0
- package/dist/src/lockfile/accepted-registry-version.js +13 -0
- package/dist/src/lockfile/entry-fields.d.ts +189 -0
- package/dist/src/lockfile/entry-fields.js +89 -0
- package/dist/src/lockfile/errors.d.ts +48 -0
- package/dist/src/lockfile/errors.js +27 -0
- package/dist/src/lockfile/index.d.ts +18 -0
- package/dist/src/lockfile/index.js +16 -0
- package/dist/src/lockfile/lockfile.d.ts +2255 -0
- package/dist/src/lockfile/lockfile.js +235 -0
- package/dist/src/lockfile/resolved-version.d.ts +4 -0
- package/dist/src/lockfile/resolved-version.js +7 -0
- package/dist/src/lockfile/schema.d.ts +3062 -0
- package/dist/src/lockfile/schema.js +406 -0
- package/dist/src/schema/index.d.ts +3 -0
- package/dist/src/schema/index.js +2 -0
- package/dist/src/schema/read-and-validate-json-file.d.ts +20 -0
- package/dist/src/schema/read-and-validate-json-file.js +85 -0
- package/dist/src/schema/types.d.ts +26 -0
- package/dist/src/schema/types.js +2 -0
- package/dist/src/settings/errors.d.ts +22 -0
- package/dist/src/settings/errors.js +15 -0
- package/dist/src/settings/format-preserving-json.d.ts +40 -0
- package/dist/src/settings/format-preserving-json.js +80 -0
- package/dist/src/settings/index.d.ts +15 -0
- package/dist/src/settings/index.js +14 -0
- package/dist/src/settings/schema.d.ts +687 -0
- package/dist/src/settings/schema.js +977 -0
- package/dist/src/settings/settings.d.ts +38 -0
- package/dist/src/settings/settings.js +213 -0
- package/dist/src/testing.d.ts +17 -0
- package/dist/src/testing.js +17 -0
- package/dist/src/utils/atomic-write.d.ts +67 -0
- package/dist/src/utils/atomic-write.js +71 -0
- package/dist/src/utils/environment.d.ts +16 -0
- package/dist/src/utils/environment.js +19 -0
- package/dist/src/utils/path-safety.d.ts +25 -0
- package/dist/src/utils/path-safety.js +34 -0
- package/dist/src/utils/resolve-parent-symlinks.d.ts +16 -0
- package/dist/src/utils/resolve-parent-symlinks.js +36 -0
- package/dist/src/workspace/accepted-canonical-ref.d.ts +58 -0
- package/dist/src/workspace/accepted-canonical-ref.js +229 -0
- package/dist/src/workspace/artifact-change.d.ts +14 -0
- package/dist/src/workspace/artifact-change.js +18 -0
- package/dist/src/workspace/canonical-observation.d.ts +39 -0
- package/dist/src/workspace/canonical-observation.js +307 -0
- package/dist/src/workspace/configured-agent-outcome.d.ts +22 -0
- package/dist/src/workspace/configured-agent-outcome.js +33 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.d.ts +50 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.js +26 -0
- package/dist/src/workspace/configured-agent-outcomes.d.ts +48 -0
- package/dist/src/workspace/configured-agent-outcomes.js +113 -0
- package/dist/src/workspace/configured-entry-resolution/types.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/types.js +2 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.js +176 -0
- package/dist/src/workspace/constants.d.ts +6 -0
- package/dist/src/workspace/constants.js +6 -0
- package/dist/src/workspace/create-symlink.d.ts +26 -0
- package/dist/src/workspace/create-symlink.js +87 -0
- package/dist/src/workspace/desired-pack-lock.d.ts +18 -0
- package/dist/src/workspace/desired-pack-lock.js +132 -0
- package/dist/src/workspace/desired-state-enabled.d.ts +18 -0
- package/dist/src/workspace/desired-state-enabled.js +16 -0
- package/dist/src/workspace/desired-state-graph.d.ts +114 -0
- package/dist/src/workspace/desired-state-graph.js +384 -0
- package/dist/src/workspace/desired-state-problem-text.d.ts +6 -0
- package/dist/src/workspace/desired-state-problem-text.js +27 -0
- package/dist/src/workspace/errors.d.ts +184 -0
- package/dist/src/workspace/errors.js +79 -0
- package/dist/src/workspace/extension-name.d.ts +28 -0
- package/dist/src/workspace/extension-name.js +66 -0
- package/dist/src/workspace/extension-paths.d.ts +82 -0
- package/dist/src/workspace/extension-paths.js +172 -0
- package/dist/src/workspace/footprint-recorder.d.ts +30 -0
- package/dist/src/workspace/footprint-recorder.js +32 -0
- package/dist/src/workspace/layout.d.ts +43 -0
- package/dist/src/workspace/layout.js +164 -0
- package/dist/src/workspace/lock-entry-to-ref.d.ts +40 -0
- package/dist/src/workspace/lock-entry-to-ref.js +433 -0
- package/dist/src/workspace/lock-entry-to-source-params.d.ts +26 -0
- package/dist/src/workspace/lock-entry-to-source-params.js +81 -0
- package/dist/src/workspace/locked-entries.d.ts +30 -0
- package/dist/src/workspace/locked-entries.js +34 -0
- package/dist/src/workspace/materialized-file-target.d.ts +14 -0
- package/dist/src/workspace/materialized-file-target.js +14 -0
- package/dist/src/workspace/materialized-tree.d.ts +23 -0
- package/dist/src/workspace/materialized-tree.js +90 -0
- package/dist/src/workspace/mcp-entry-semantics.d.ts +31 -0
- package/dist/src/workspace/mcp-entry-semantics.js +60 -0
- package/dist/src/workspace/observed-installed.d.ts +9 -0
- package/dist/src/workspace/observed-installed.js +9 -0
- package/dist/src/workspace/pack-manifest-content-identity.d.ts +12 -0
- package/dist/src/workspace/pack-manifest-content-identity.js +20 -0
- package/dist/src/workspace/pack-paths.d.ts +24 -0
- package/dist/src/workspace/pack-paths.js +16 -0
- package/dist/src/workspace/package-hash.d.ts +25 -0
- package/dist/src/workspace/package-hash.js +45 -0
- package/dist/src/workspace/paths.d.ts +24 -0
- package/dist/src/workspace/paths.js +52 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.d.ts +199 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.js +588 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.d.ts +15 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.js +15 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.d.ts +72 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.js +134 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.d.ts +99 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.js +142 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.d.ts +60 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.js +57 -0
- package/dist/src/workspace/read-model/agent-presence.d.ts +32 -0
- package/dist/src/workspace/read-model/agent-presence.js +21 -0
- package/dist/src/workspace/read-model/agent-root-resolver.d.ts +38 -0
- package/dist/src/workspace/read-model/agent-root-resolver.js +35 -0
- package/dist/src/workspace/read-model/agents/index.d.ts +38 -0
- package/dist/src/workspace/read-model/agents/index.js +45 -0
- package/dist/src/workspace/read-model/agents/shared.d.ts +27 -0
- package/dist/src/workspace/read-model/agents/shared.js +63 -0
- package/dist/src/workspace/read-model/agents/types.d.ts +133 -0
- package/dist/src/workspace/read-model/agents/types.js +51 -0
- package/dist/src/workspace/read-model/diagnostics.d.ts +18 -0
- package/dist/src/workspace/read-model/diagnostics.js +14 -0
- package/dist/src/workspace/read-model/discovery/index.d.ts +5 -0
- package/dist/src/workspace/read-model/discovery/index.js +5 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.d.ts +16 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.js +168 -0
- package/dist/src/workspace/read-model/discovery/skills.d.ts +58 -0
- package/dist/src/workspace/read-model/discovery/skills.js +263 -0
- package/dist/src/workspace/read-model/discovery/subagents.d.ts +37 -0
- package/dist/src/workspace/read-model/discovery/subagents.js +48 -0
- package/dist/src/workspace/read-model/errors.d.ts +93 -0
- package/dist/src/workspace/read-model/errors.js +30 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.d.ts +4 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.js +4 -0
- package/dist/src/workspace/read-model/extensions/hook.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/hook.js +119 -0
- package/dist/src/workspace/read-model/extensions/index.d.ts +19 -0
- package/dist/src/workspace/read-model/extensions/index.js +43 -0
- package/dist/src/workspace/read-model/extensions/indexByName.d.ts +31 -0
- package/dist/src/workspace/read-model/extensions/indexByName.js +30 -0
- package/dist/src/workspace/read-model/extensions/inventory.d.ts +99 -0
- package/dist/src/workspace/read-model/extensions/inventory.js +111 -0
- package/dist/src/workspace/read-model/extensions/knowledge.d.ts +101 -0
- package/dist/src/workspace/read-model/extensions/knowledge.js +121 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.d.ts +106 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.js +122 -0
- package/dist/src/workspace/read-model/extensions/pack.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/pack.js +123 -0
- package/dist/src/workspace/read-model/extensions/package-root.d.ts +39 -0
- package/dist/src/workspace/read-model/extensions/package-root.js +48 -0
- package/dist/src/workspace/read-model/extensions/projection.d.ts +137 -0
- package/dist/src/workspace/read-model/extensions/projection.js +180 -0
- package/dist/src/workspace/read-model/extensions/rule.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/rule.js +113 -0
- package/dist/src/workspace/read-model/extensions/skill.d.ts +170 -0
- package/dist/src/workspace/read-model/extensions/skill.js +148 -0
- package/dist/src/workspace/read-model/extensions/subagent.d.ts +97 -0
- package/dist/src/workspace/read-model/extensions/subagent.js +120 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.d.ts +49 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.js +180 -0
- package/dist/src/workspace/read-model/scanners/agent-root.d.ts +73 -0
- package/dist/src/workspace/read-model/scanners/agent-root.js +148 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.d.ts +43 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.js +54 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.d.ts +48 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.js +237 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.d.ts +63 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.js +106 -0
- package/dist/src/workspace/read-model/scanners/index.d.ts +15 -0
- package/dist/src/workspace/read-model/scanners/index.js +34 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.d.ts +47 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.js +212 -0
- package/dist/src/workspace/read-model/scanners/types.d.ts +170 -0
- package/dist/src/workspace/read-model/scanners/types.js +86 -0
- package/dist/src/workspace/read-model/service.d.ts +103 -0
- package/dist/src/workspace/read-model/service.js +391 -0
- package/dist/src/workspace/read-model/state.d.ts +35 -0
- package/dist/src/workspace/read-model/state.js +97 -0
- package/dist/src/workspace/read-model/types.d.ts +75 -0
- package/dist/src/workspace/read-model/types.js +26 -0
- package/dist/src/workspace/read-model-record-readers.d.ts +34 -0
- package/dist/src/workspace/read-model-record-readers.js +467 -0
- package/dist/src/workspace/read-model-record-rows.d.ts +45 -0
- package/dist/src/workspace/read-model-record-rows.js +33 -0
- package/dist/src/workspace/read-model-record-types.d.ts +45 -0
- package/dist/src/workspace/read-model-record-types.js +13 -0
- package/dist/src/workspace/remove-if-exists.d.ts +13 -0
- package/dist/src/workspace/remove-if-exists.js +26 -0
- package/dist/src/workspace/rendered-files.d.ts +53 -0
- package/dist/src/workspace/rendered-files.js +50 -0
- package/dist/src/workspace/scope-refusal.d.ts +26 -0
- package/dist/src/workspace/scope-refusal.js +29 -0
- package/dist/src/workspace/service-interface.d.ts +479 -0
- package/dist/src/workspace/service-interface.js +27 -0
- package/dist/src/workspace/service.d.ts +1665 -0
- package/dist/src/workspace/service.js +1263 -0
- package/dist/src/workspace/setup-scope-support.d.ts +27 -0
- package/dist/src/workspace/setup-scope-support.js +299 -0
- package/dist/src/workspace/skill-paths.d.ts +33 -0
- package/dist/src/workspace/skill-paths.js +14 -0
- package/dist/src/workspace/source-metadata.d.ts +7 -0
- package/dist/src/workspace/source-metadata.js +10 -0
- package/dist/src/workspace/source-to-lock-entry.d.ts +32 -0
- package/dist/src/workspace/source-to-lock-entry.js +68 -0
- package/dist/src/workspace/test-stubs.d.ts +144 -0
- package/dist/src/workspace/test-stubs.js +412 -0
- package/dist/src/workspace/transaction.d.ts +218 -0
- package/dist/src/workspace/transaction.js +177 -0
- package/package.json +57 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as FileSystem from "effect/FileSystem";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
6
|
+
import * as Path from "effect/Path";
|
|
7
|
+
import * as Schema from "effect/Schema";
|
|
8
|
+
const TREE_INTEGRITY_PREFIX = "sha256-tree-v1:";
|
|
9
|
+
export const TreeIntegritySchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => /^sha256-tree-v1:[0-9a-f]{64}$/u.test(value)
|
|
10
|
+
? undefined
|
|
11
|
+
: "Expected a sha256-tree-v1 materialized-tree digest")), Schema.brand("TreeIntegrity")).annotate({
|
|
12
|
+
identifier: "TreeIntegrity",
|
|
13
|
+
description: "Strict SHA-256 integrity of regular-file paths and bytes using AXM materialized-tree framing v1.",
|
|
14
|
+
});
|
|
15
|
+
const decodeTreeIntegrity = Schema.decodeUnknownSync(TreeIntegritySchema);
|
|
16
|
+
/**
|
|
17
|
+
* A materialized package tree failed strict integrity walking: unreadable,
|
|
18
|
+
* unsafe, colliding, or unsupported entries. `reason` carries the walk's fact
|
|
19
|
+
* sentence.
|
|
20
|
+
*/
|
|
21
|
+
export class MaterializedTreeInvalid extends Data.TaggedError("MaterializedTreeInvalid") {
|
|
22
|
+
}
|
|
23
|
+
const treeError = (root, reason, cause) => new MaterializedTreeInvalid({ root, reason, ...(cause === undefined ? {} : { cause }) });
|
|
24
|
+
const frame = (hash, bytes) => {
|
|
25
|
+
const length = Buffer.alloc(8);
|
|
26
|
+
length.writeBigUInt64BE(BigInt(bytes.byteLength));
|
|
27
|
+
hash.update(length);
|
|
28
|
+
hash.update(bytes);
|
|
29
|
+
};
|
|
30
|
+
export const computeMaterializedTreeIntegrity = (root) => Effect.gen(function* () {
|
|
31
|
+
const fs = yield* FileSystem.FileSystem;
|
|
32
|
+
const path = yield* Path.Path;
|
|
33
|
+
const files = [];
|
|
34
|
+
const caseFoldedPaths = new Map();
|
|
35
|
+
const walk = (directory, relativeDirectory) => Effect.gen(function* () {
|
|
36
|
+
const entries = yield* fs
|
|
37
|
+
.readDirectory(directory)
|
|
38
|
+
.pipe(Effect.mapError((cause) => treeError(root, `cannot read ${relativeDirectory || "."}`, cause)));
|
|
39
|
+
const ordered = [...entries].sort((left, right) => left.localeCompare(right, "en"));
|
|
40
|
+
for (const entry of ordered) {
|
|
41
|
+
if (entry.length === 0 ||
|
|
42
|
+
entry === "." ||
|
|
43
|
+
entry === ".." ||
|
|
44
|
+
entry.includes("/") ||
|
|
45
|
+
entry.includes("\\")) {
|
|
46
|
+
return yield* treeError(root, `unsafe path segment ${JSON.stringify(entry)}`);
|
|
47
|
+
}
|
|
48
|
+
const relativePath = relativeDirectory.length === 0 ? entry : `${relativeDirectory}/${entry}`;
|
|
49
|
+
if (relativePath.startsWith("/") || relativePath.split("/").includes("..")) {
|
|
50
|
+
return yield* treeError(root, `unsafe relative path ${JSON.stringify(relativePath)}`);
|
|
51
|
+
}
|
|
52
|
+
const folded = relativePath.normalize("NFC").toLocaleLowerCase("en-US");
|
|
53
|
+
const colliding = caseFoldedPaths.get(folded);
|
|
54
|
+
if (colliding !== undefined && colliding !== relativePath) {
|
|
55
|
+
return yield* treeError(root, `case-fold collision between ${JSON.stringify(colliding)} and ${JSON.stringify(relativePath)}`);
|
|
56
|
+
}
|
|
57
|
+
caseFoldedPaths.set(folded, relativePath);
|
|
58
|
+
const absolutePath = path.join(directory, entry);
|
|
59
|
+
const link = yield* fs.readLink(absolutePath).pipe(Effect.option);
|
|
60
|
+
if (Option.isSome(link)) {
|
|
61
|
+
return yield* treeError(root, `symlink is not allowed: ${relativePath}`);
|
|
62
|
+
}
|
|
63
|
+
const info = yield* fs
|
|
64
|
+
.stat(absolutePath)
|
|
65
|
+
.pipe(Effect.mapError((cause) => treeError(root, `cannot inspect ${relativePath}`, cause)));
|
|
66
|
+
if (info.type === "Directory") {
|
|
67
|
+
yield* walk(absolutePath, relativePath);
|
|
68
|
+
}
|
|
69
|
+
else if (info.type === "File") {
|
|
70
|
+
files.push({ relativePath, absolutePath });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return yield* treeError(root, `unsupported filesystem entry: ${relativePath}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
yield* walk(root, "");
|
|
78
|
+
files.sort((left, right) => left.relativePath.localeCompare(right.relativePath, "en"));
|
|
79
|
+
const hash = crypto.createHash("sha256");
|
|
80
|
+
frame(hash, Buffer.from("agentxm-materialized-tree"));
|
|
81
|
+
frame(hash, Buffer.from("1"));
|
|
82
|
+
for (const file of files) {
|
|
83
|
+
frame(hash, Buffer.from(file.relativePath, "utf8"));
|
|
84
|
+
frame(hash, yield* fs
|
|
85
|
+
.readFile(file.absolutePath)
|
|
86
|
+
.pipe(Effect.mapError((cause) => treeError(root, `cannot read ${file.relativePath}`, cause))));
|
|
87
|
+
}
|
|
88
|
+
return decodeTreeIntegrity(`${TREE_INTEGRITY_PREFIX}${hash.digest("hex")}`);
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=materialized-tree.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings-semantics predicates for MCP server entries.
|
|
3
|
+
*
|
|
4
|
+
* Pure derivations over workspace-owned MCP entry shapes: per-agent targeting
|
|
5
|
+
* of a configured settings entry, and AXM ownership/provenance metadata
|
|
6
|
+
* embedded in agent-native MCP config entries.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Schema from "effect/Schema";
|
|
13
|
+
import type { McpServerEntry } from "../settings/schema.js";
|
|
14
|
+
export declare const isMcpServerApplicableToAgent: (entry: McpServerEntry, agentId: string) => boolean;
|
|
15
|
+
export declare const AXM_MCP_METADATA_KEY = "x-axm";
|
|
16
|
+
export declare const AxmMcpMetadataSchema: Schema.Union<readonly [Schema.Struct<{
|
|
17
|
+
readonly v: Schema.Literal<1>;
|
|
18
|
+
readonly managed: Schema.Literal<true>;
|
|
19
|
+
readonly ext: Schema.NonEmptyString;
|
|
20
|
+
readonly source: Schema.Literal<"inline">;
|
|
21
|
+
}>, Schema.Struct<{
|
|
22
|
+
readonly v: Schema.Literal<1>;
|
|
23
|
+
readonly managed: Schema.Literal<true>;
|
|
24
|
+
readonly ext: Schema.NonEmptyString;
|
|
25
|
+
readonly source: Schema.Literals<readonly ["github", "gitlab", "bitbucket", "azurerepos", "git", "registry", "local", "workspace"]>;
|
|
26
|
+
readonly ref: Schema.NonEmptyString;
|
|
27
|
+
}>]>;
|
|
28
|
+
export type AxmMcpMetadata = typeof AxmMcpMetadataSchema.Type;
|
|
29
|
+
export declare const readAxmMcpMetadata: (entry: Readonly<Record<string, unknown>>) => Option.Option<AxmMcpMetadata>;
|
|
30
|
+
export declare const isAxmManagedMcpEntry: (entry: Readonly<Record<string, unknown>>) => boolean;
|
|
31
|
+
//# sourceMappingURL=mcp-entry-semantics.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings-semantics predicates for MCP server entries.
|
|
3
|
+
*
|
|
4
|
+
* Pure derivations over workspace-owned MCP entry shapes: per-agent targeting
|
|
5
|
+
* of a configured settings entry, and AXM ownership/provenance metadata
|
|
6
|
+
* embedded in agent-native MCP config entries.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Schema from "effect/Schema";
|
|
13
|
+
export const isMcpServerApplicableToAgent = (entry, agentId) => entry.agents === undefined || entry.agents.some((candidate) => candidate === agentId);
|
|
14
|
+
export const AXM_MCP_METADATA_KEY = "x-axm";
|
|
15
|
+
const ResolvableSourceTypeSchema = Schema.Literals([
|
|
16
|
+
"github",
|
|
17
|
+
"gitlab",
|
|
18
|
+
"bitbucket",
|
|
19
|
+
"azurerepos",
|
|
20
|
+
"git",
|
|
21
|
+
"registry",
|
|
22
|
+
"local",
|
|
23
|
+
"workspace",
|
|
24
|
+
]);
|
|
25
|
+
export const AxmMcpMetadataSchema = Schema.Union([
|
|
26
|
+
Schema.Struct({
|
|
27
|
+
v: Schema.Literal(1),
|
|
28
|
+
managed: Schema.Literal(true),
|
|
29
|
+
ext: Schema.NonEmptyString,
|
|
30
|
+
source: Schema.Literal("inline"),
|
|
31
|
+
}),
|
|
32
|
+
Schema.Struct({
|
|
33
|
+
v: Schema.Literal(1),
|
|
34
|
+
managed: Schema.Literal(true),
|
|
35
|
+
ext: Schema.NonEmptyString,
|
|
36
|
+
source: ResolvableSourceTypeSchema,
|
|
37
|
+
ref: Schema.NonEmptyString,
|
|
38
|
+
}),
|
|
39
|
+
]).annotate({
|
|
40
|
+
identifier: "AxmMcpMetadata",
|
|
41
|
+
title: "AXM MCP Metadata",
|
|
42
|
+
description: "AXM ownership and provenance metadata for an agent MCP config entry.",
|
|
43
|
+
});
|
|
44
|
+
const decodeMetadataOption = Schema.decodeUnknownOption(AxmMcpMetadataSchema);
|
|
45
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
|
+
const hasValidRefShape = (metadata) => {
|
|
47
|
+
const source = metadata["source"];
|
|
48
|
+
const ref = metadata["ref"];
|
|
49
|
+
if (source === "inline")
|
|
50
|
+
return ref === undefined;
|
|
51
|
+
return typeof ref === "string" && ref.length > 0;
|
|
52
|
+
};
|
|
53
|
+
export const readAxmMcpMetadata = (entry) => {
|
|
54
|
+
const metadata = entry[AXM_MCP_METADATA_KEY];
|
|
55
|
+
if (!isRecord(metadata) || !hasValidRefShape(metadata))
|
|
56
|
+
return Option.none();
|
|
57
|
+
return decodeMetadataOption(metadata);
|
|
58
|
+
};
|
|
59
|
+
export const isAxmManagedMcpEntry = (entry) => Option.isSome(readAxmMcpMetadata(entry));
|
|
60
|
+
//# sourceMappingURL=mcp-entry-semantics.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import type { InstallableExtensionType } from "@agentxm/extension-model/unstable/extensions/installable-types";
|
|
3
|
+
import type { WorkspaceMutationsService, WorkspaceStateReadFailure } from "./service-interface.js";
|
|
4
|
+
/**
|
|
5
|
+
* Determine installation from the observable workspace inventory. Lock
|
|
6
|
+
* presence is intentionally irrelevant.
|
|
7
|
+
*/
|
|
8
|
+
export declare const isObservedInstalled: (workspace: WorkspaceMutationsService, type: InstallableExtensionType, name: string) => Effect.Effect<boolean, WorkspaceStateReadFailure>;
|
|
9
|
+
//# sourceMappingURL=observed-installed.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
/**
|
|
3
|
+
* Determine installation from the observable workspace inventory. Lock
|
|
4
|
+
* presence is intentionally irrelevant.
|
|
5
|
+
*/
|
|
6
|
+
export const isObservedInstalled = (workspace, type, name) => workspace.records
|
|
7
|
+
.getExtensionInventory(type, {})
|
|
8
|
+
.pipe(Effect.map((inventory) => inventory.items.some((item) => item.name === name && item.installed)));
|
|
9
|
+
//# sourceMappingURL=observed-installed.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type SourceHash } from "@agentxm/extension-model/unstable/sources/source-hash";
|
|
2
|
+
interface PackManifestIdentityInput {
|
|
3
|
+
readonly owner: string;
|
|
4
|
+
readonly type: "pack";
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly version: string;
|
|
7
|
+
readonly dependencies: Readonly<Record<string, string>>;
|
|
8
|
+
}
|
|
9
|
+
/** Identity of the decoded Pack manifest semantics used to authorize reachability. */
|
|
10
|
+
export declare const computePackManifestContentIdentity: (manifest: PackManifestIdentityInput) => SourceHash;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=pack-manifest-content-identity.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { computeSourceHash } from "./rendered-files.js";
|
|
2
|
+
import {} from "@agentxm/extension-model/unstable/sources/source-hash";
|
|
3
|
+
const normalize = (value) => {
|
|
4
|
+
if (Array.isArray(value))
|
|
5
|
+
return value.map(normalize);
|
|
6
|
+
if (typeof value !== "object" || value === null)
|
|
7
|
+
return value;
|
|
8
|
+
return Object.fromEntries(Object.entries(value)
|
|
9
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
10
|
+
.map(([key, entry]) => [key, normalize(entry)]));
|
|
11
|
+
};
|
|
12
|
+
/** Identity of the decoded Pack manifest semantics used to authorize reachability. */
|
|
13
|
+
export const computePackManifestContentIdentity = (manifest) => computeSourceHash(JSON.stringify(normalize({
|
|
14
|
+
owner: manifest.owner,
|
|
15
|
+
type: manifest.type,
|
|
16
|
+
name: manifest.name,
|
|
17
|
+
version: manifest.version,
|
|
18
|
+
dependencies: manifest.dependencies,
|
|
19
|
+
})));
|
|
20
|
+
//# sourceMappingURL=pack-manifest-content-identity.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized pack path computation.
|
|
3
|
+
*
|
|
4
|
+
* Provides types and a pure function for computing pack directory paths.
|
|
5
|
+
* Packs are either workspace-authored or Registry-sourced. Acquired packs
|
|
6
|
+
* retain the exact Registry source name in their canonical path.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
import type { Handle } from "@agentxm/extension-model/unstable/extensions/handle";
|
|
11
|
+
import { type AbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
12
|
+
import type { WorkspaceLayout } from "./layout.js";
|
|
13
|
+
/**
|
|
14
|
+
* Computed path for an installed pack directory.
|
|
15
|
+
*
|
|
16
|
+
* `canonicalPath` = `<base>/agent_extensions/<source-name>/<owner>/packs/<name>/`
|
|
17
|
+
*
|
|
18
|
+
* No `src/` subdirectory for packs.
|
|
19
|
+
*/
|
|
20
|
+
export interface PackDirPath {
|
|
21
|
+
readonly canonicalPath: AbsolutePath;
|
|
22
|
+
}
|
|
23
|
+
export declare const computePackPathsForLayout: (join: (...paths: string[]) => string, layout: WorkspaceLayout, sourceName: "workspace" | string, owner: Handle, name: string) => PackDirPath;
|
|
24
|
+
//# sourceMappingURL=pack-paths.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized pack path computation.
|
|
3
|
+
*
|
|
4
|
+
* Provides types and a pure function for computing pack directory paths.
|
|
5
|
+
* Packs are either workspace-authored or Registry-sourced. Acquired packs
|
|
6
|
+
* retain the exact Registry source name in their canonical path.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
import { decodeAbsolutePathSync, } from "@agentxm/extension-model/unstable/path-types";
|
|
11
|
+
export const computePackPathsForLayout = (join, layout, sourceName, owner, name) => ({
|
|
12
|
+
canonicalPath: layout.scope === "project" && sourceName === "workspace"
|
|
13
|
+
? decodeAbsolutePathSync(join(layout.authoredRoot("pack"), name))
|
|
14
|
+
: decodeAbsolutePathSync(join(layout.acquiredRoot, sourceName, owner, "packs", name)),
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=pack-paths.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content hashing for installed extension packages.
|
|
3
|
+
*
|
|
4
|
+
* @experimental This API is unstable and may change without notice.
|
|
5
|
+
*/
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as FileSystem from "effect/FileSystem";
|
|
8
|
+
import * as Path from "effect/Path";
|
|
9
|
+
import { PackageContentHashFailed } from "./errors.js";
|
|
10
|
+
import type { SourceHash } from "@agentxm/extension-model/unstable/sources/source-hash";
|
|
11
|
+
/**
|
|
12
|
+
* Compute an advisory SHA-256 change marker over package content recursively.
|
|
13
|
+
*
|
|
14
|
+
* File order is normalized by sorting on relative path, and each entry
|
|
15
|
+
* contributes its path and bytes separated by NUL so that a rename cannot
|
|
16
|
+
* collide with a content change.
|
|
17
|
+
*
|
|
18
|
+
* The result is a change-detection marker for created/updated/unchanged
|
|
19
|
+
* reporting, never a tamper seal — installed content is workspace-owned and
|
|
20
|
+
* may be rewritten by content-preserving tools after install.
|
|
21
|
+
*
|
|
22
|
+
* @experimental This API is unstable and may change without notice.
|
|
23
|
+
*/
|
|
24
|
+
export declare const computePackageContentHash: (packageDir: string) => Effect.Effect<SourceHash, PackageContentHashFailed, FileSystem.FileSystem | Path.Path>;
|
|
25
|
+
//# sourceMappingURL=package-hash.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content hashing for installed extension packages.
|
|
3
|
+
*
|
|
4
|
+
* @experimental This API is unstable and may change without notice.
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from "node:crypto";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as FileSystem from "effect/FileSystem";
|
|
9
|
+
import * as Path from "effect/Path";
|
|
10
|
+
import { PackageContentHashFailed } from "./errors.js";
|
|
11
|
+
import { computeSourceHash } from "./rendered-files.js";
|
|
12
|
+
/**
|
|
13
|
+
* Compute an advisory SHA-256 change marker over package content recursively.
|
|
14
|
+
*
|
|
15
|
+
* File order is normalized by sorting on relative path, and each entry
|
|
16
|
+
* contributes its path and bytes separated by NUL so that a rename cannot
|
|
17
|
+
* collide with a content change.
|
|
18
|
+
*
|
|
19
|
+
* The result is a change-detection marker for created/updated/unchanged
|
|
20
|
+
* reporting, never a tamper seal — installed content is workspace-owned and
|
|
21
|
+
* may be rewritten by content-preserving tools after install.
|
|
22
|
+
*
|
|
23
|
+
* @experimental This API is unstable and may change without notice.
|
|
24
|
+
*/
|
|
25
|
+
export const computePackageContentHash = (packageDir) => Effect.gen(function* () {
|
|
26
|
+
const fs = yield* FileSystem.FileSystem;
|
|
27
|
+
const path = yield* Path.Path;
|
|
28
|
+
const rawEntries = yield* fs.readDirectory(packageDir, { recursive: true });
|
|
29
|
+
const candidates = yield* Effect.forEach(rawEntries, (relativePath) => Effect.gen(function* () {
|
|
30
|
+
const absolutePath = path.join(packageDir, relativePath);
|
|
31
|
+
const info = yield* fs.stat(absolutePath);
|
|
32
|
+
return { relativePath, absolutePath, isFile: info.type === "File" };
|
|
33
|
+
}), { concurrency: 16 });
|
|
34
|
+
const files = candidates.filter((candidate) => candidate.isFile);
|
|
35
|
+
files.sort((left, right) => left.relativePath < right.relativePath ? -1 : left.relativePath > right.relativePath ? 1 : 0);
|
|
36
|
+
const hash = crypto.createHash("sha256");
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
hash.update(file.relativePath);
|
|
39
|
+
hash.update("\0");
|
|
40
|
+
hash.update(yield* fs.readFile(file.absolutePath));
|
|
41
|
+
hash.update("\0");
|
|
42
|
+
}
|
|
43
|
+
return computeSourceHash(hash.digest("hex"));
|
|
44
|
+
}).pipe(Effect.mapError((cause) => new PackageContentHashFailed({ packageDir, cause })));
|
|
45
|
+
//# sourceMappingURL=package-hash.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** AXM application-home and workspace path resolution. */
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Path from "effect/Path";
|
|
4
|
+
import { type AbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
5
|
+
import type { WorkspaceScope } from "@agentxm/extension-model/unstable/workspace-scope";
|
|
6
|
+
export { AXM_DIR_NAME, USER_WORKSPACE_DIRECTORY } from "./constants.js";
|
|
7
|
+
export interface WorkspaceLocation {
|
|
8
|
+
readonly scope: WorkspaceScope;
|
|
9
|
+
readonly path: AbsolutePath;
|
|
10
|
+
readonly baseDir: AbsolutePath;
|
|
11
|
+
readonly workspaceRoot: AbsolutePath;
|
|
12
|
+
readonly settingsPath: AbsolutePath;
|
|
13
|
+
readonly lockPath: AbsolutePath;
|
|
14
|
+
readonly acquiredRoot: AbsolutePath;
|
|
15
|
+
}
|
|
16
|
+
export declare const resolveUserHomePure: (configuredHome: string | undefined) => string;
|
|
17
|
+
export declare const resolveUserAxmHomePure: (pathJoin: (...segments: ReadonlyArray<string>) => string, homeDir: string) => string;
|
|
18
|
+
export declare const resolveUserWorkspaceRootPure: (pathJoin: (...segments: ReadonlyArray<string>) => string, homeDir: string) => string;
|
|
19
|
+
export declare const resolveUserHome: () => Effect.Effect<AbsolutePath, never, Path.Path>;
|
|
20
|
+
export declare const resolveUserAxmHome: () => Effect.Effect<AbsolutePath, never, Path.Path>;
|
|
21
|
+
export declare const resolveUserWorkspaceRoot: () => Effect.Effect<AbsolutePath, never, Path.Path>;
|
|
22
|
+
export declare const getProjectRuntimeDir: (projectRoot: AbsolutePath) => Effect.Effect<AbsolutePath, never, Path.Path>;
|
|
23
|
+
export declare const locateWorkspace: (scope: WorkspaceScope, projectRoot: AbsolutePath) => Effect.Effect<WorkspaceLocation, never, Path.Path>;
|
|
24
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** AXM application-home and workspace path resolution. */
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as Config from "effect/Config";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
6
|
+
import * as Path from "effect/Path";
|
|
7
|
+
import { ACQUIRED_EXTENSIONS_DIR, AXM_DIR_NAME, LOCK_FILENAME, USER_WORKSPACE_DIRECTORY, } from "./constants.js";
|
|
8
|
+
import { makeAbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
9
|
+
import { SETTINGS_FILENAME } from "@agentxm/extension-model/unstable/workspace-files";
|
|
10
|
+
export { AXM_DIR_NAME, USER_WORKSPACE_DIRECTORY } from "./constants.js";
|
|
11
|
+
const axmUserHomeConfig = Config.option(Config.string("AXM_USER_HOME"));
|
|
12
|
+
export const resolveUserHomePure = (configuredHome) => configuredHome ?? os.homedir();
|
|
13
|
+
export const resolveUserAxmHomePure = (pathJoin, homeDir) => pathJoin(homeDir, AXM_DIR_NAME);
|
|
14
|
+
export const resolveUserWorkspaceRootPure = (pathJoin, homeDir) => pathJoin(resolveUserAxmHomePure(pathJoin, homeDir), USER_WORKSPACE_DIRECTORY);
|
|
15
|
+
export const resolveUserHome = () => Effect.gen(function* () {
|
|
16
|
+
const path = yield* Path.Path;
|
|
17
|
+
// eslint-disable-next-line no-restricted-syntax -- Optional string decoding is total, so failure means the Config provider violated its contract.
|
|
18
|
+
const configuredHome = yield* Effect.orDie(axmUserHomeConfig);
|
|
19
|
+
return makeAbsolutePath(path, resolveUserHomePure(Option.getOrUndefined(configuredHome)));
|
|
20
|
+
});
|
|
21
|
+
export const resolveUserAxmHome = () => Effect.gen(function* () {
|
|
22
|
+
const path = yield* Path.Path;
|
|
23
|
+
const home = yield* resolveUserHome();
|
|
24
|
+
return makeAbsolutePath(path, resolveUserAxmHomePure(path.join, home));
|
|
25
|
+
});
|
|
26
|
+
export const resolveUserWorkspaceRoot = () => Effect.gen(function* () {
|
|
27
|
+
const path = yield* Path.Path;
|
|
28
|
+
const home = yield* resolveUserHome();
|
|
29
|
+
return makeAbsolutePath(path, resolveUserWorkspaceRootPure(path.join, home));
|
|
30
|
+
});
|
|
31
|
+
export const getProjectRuntimeDir = (projectRoot) => Effect.gen(function* () {
|
|
32
|
+
const path = yield* Path.Path;
|
|
33
|
+
return makeAbsolutePath(path, path.join(projectRoot, AXM_DIR_NAME));
|
|
34
|
+
});
|
|
35
|
+
export const locateWorkspace = (scope, projectRoot) => Effect.gen(function* () {
|
|
36
|
+
const path = yield* Path.Path;
|
|
37
|
+
const baseDir = scope === "user" ? yield* resolveUserHome() : projectRoot;
|
|
38
|
+
const workspaceRoot = scope === "user"
|
|
39
|
+
? makeAbsolutePath(path, resolveUserWorkspaceRootPure(path.join, baseDir))
|
|
40
|
+
: projectRoot;
|
|
41
|
+
const runtimeDir = makeAbsolutePath(path, path.join(workspaceRoot, AXM_DIR_NAME));
|
|
42
|
+
return {
|
|
43
|
+
scope,
|
|
44
|
+
path: runtimeDir,
|
|
45
|
+
baseDir,
|
|
46
|
+
workspaceRoot,
|
|
47
|
+
settingsPath: makeAbsolutePath(path, path.join(workspaceRoot, SETTINGS_FILENAME)),
|
|
48
|
+
lockPath: makeAbsolutePath(path, path.join(workspaceRoot, LOCK_FILENAME)),
|
|
49
|
+
acquiredRoot: makeAbsolutePath(path, path.join(workspaceRoot, ACQUIRED_EXTENSIONS_DIR)),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixture builder: synthesizes minimal workspace trees from declarative specs
|
|
3
|
+
* against an in-memory `FileSystem` for tests.
|
|
4
|
+
*
|
|
5
|
+
* Phase 5 of the workspace read-model change. Downstream phases (scanners,
|
|
6
|
+
* per-extension subject modules, the live `WorkspaceReadModel` service, and
|
|
7
|
+
* golden-fixture scenario tests) call `buildFixture(spec)` to materialize a
|
|
8
|
+
* minimal directory tree; named scenario constructors below provide the
|
|
9
|
+
* canonical specs for the spec scenarios listed in `proposal.md`.
|
|
10
|
+
*
|
|
11
|
+
* Key design choices:
|
|
12
|
+
*
|
|
13
|
+
* - The builder operates on a self-contained in-memory `Map<string, string>`
|
|
14
|
+
* filesystem, exposed through `FileSystem.makeNoop`. No `node:fs` is used.
|
|
15
|
+
* Tests get deterministic, ordered file sets without touching disk.
|
|
16
|
+
* - Path-escape attempts (entries containing `..` segments or absolute paths)
|
|
17
|
+
* fail the builder with `PathEscapeError`. This makes the upcoming
|
|
18
|
+
* Phase 9 `WorkspaceRootEscape` test a separate, deliberate scenario and
|
|
19
|
+
* eliminates the chance of a leaky test fixture corrupting the host fs.
|
|
20
|
+
* - Settings and lockfile files are serialized through `JSON.stringify` and
|
|
21
|
+
* `YAML.stringify` respectively when their `_tag === "valid"`. For
|
|
22
|
+
* `byteCorrupt`, the literal bytes are written verbatim. For
|
|
23
|
+
* `schemaInvalid`, the JSON/YAML serialization of the spec object is
|
|
24
|
+
* written so the parser accepts it but the schema decoder rejects it.
|
|
25
|
+
* - The builder NEVER constructs the live `WorkspaceReadModel` itself. The
|
|
26
|
+
* sibling `test-layer.ts` exposes a `WorkspaceReadModelTest` layer that
|
|
27
|
+
* composes the builder output with the real (Phase 9) Live layer; in
|
|
28
|
+
* Phase 5 it falls back to a `Layer.fail` placeholder.
|
|
29
|
+
*/
|
|
30
|
+
import * as Effect from "effect/Effect";
|
|
31
|
+
import * as FileSystem from "effect/FileSystem";
|
|
32
|
+
import * as Path from "effect/Path";
|
|
33
|
+
import type { Settings } from "../../../settings/schema.js";
|
|
34
|
+
/**
|
|
35
|
+
* A file-spec describes one workspace file. The four tags express the four
|
|
36
|
+
* source-cell states that WorkspaceReadModel source loaders distinguish:
|
|
37
|
+
* absent, valid (parses + decodes), byte-corrupt (parser rejects), and
|
|
38
|
+
* schema-invalid (parser accepts but decoder rejects).
|
|
39
|
+
*/
|
|
40
|
+
export type FileSpec = {
|
|
41
|
+
readonly _tag: "absent";
|
|
42
|
+
} | {
|
|
43
|
+
readonly _tag: "valid";
|
|
44
|
+
/**
|
|
45
|
+
* Object content for files with a known structure (axm.json,
|
|
46
|
+
* lockfile, .mcp.json). The builder serializes through `JSON.stringify`
|
|
47
|
+
* for JSON files and `YAML.stringify` for YAML files. Pass a string
|
|
48
|
+
* literal to bypass serialization.
|
|
49
|
+
*/
|
|
50
|
+
readonly contents: object | string;
|
|
51
|
+
} | {
|
|
52
|
+
readonly _tag: "byteCorrupt";
|
|
53
|
+
readonly bytes: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly _tag: "schemaInvalid";
|
|
56
|
+
/**
|
|
57
|
+
* Object content that serializes cleanly as JSON/YAML but fails the
|
|
58
|
+
* relevant Schema decoder. The builder writes the serialized form so
|
|
59
|
+
* `JSON.parse` / `YAML.parse` succeed.
|
|
60
|
+
*/
|
|
61
|
+
readonly contents: object;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* A tree of files. Keys are workspace-relative paths (no leading slash, no
|
|
65
|
+
* `..` segments). Values are either the file's contents as a string (for
|
|
66
|
+
* inline content) or a `FileSpec` discriminator (for absent/byte-corrupt/
|
|
67
|
+
* schema-invalid).
|
|
68
|
+
*/
|
|
69
|
+
export type TreeFiles = Readonly<Record<string, string | FileSpec>>;
|
|
70
|
+
/**
|
|
71
|
+
* Per-scope file specs. `settings` and `lockfile` are scoped settings/lockfile
|
|
72
|
+
* files. `axmExtensions` synthesizes contents under the scope's
|
|
73
|
+
* `agent_extensions/` directory.
|
|
74
|
+
* `agentDirs` synthesizes per-agent rendered directories. `mcpJson` writes
|
|
75
|
+
* `.mcp.json` at the workspace/user root. `agentSettings` writes per-agent
|
|
76
|
+
* native settings files (e.g. `.claude/settings.json`).
|
|
77
|
+
*/
|
|
78
|
+
export interface ScopeFiles {
|
|
79
|
+
readonly settings?: FileSpec;
|
|
80
|
+
readonly lockfile?: FileSpec;
|
|
81
|
+
readonly axmExtensions?: TreeFiles;
|
|
82
|
+
readonly agentDirs?: Readonly<Record<string, TreeFiles>>;
|
|
83
|
+
readonly mcpJson?: FileSpec;
|
|
84
|
+
readonly agentSettings?: Readonly<Record<string, FileSpec>>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Top-level fixture spec. `workspaceRoot` is the project root; `userHome` is
|
|
88
|
+
* the user-scope home directory (workspace state lives at
|
|
89
|
+
* `${userHome}/.axm/workspace/`).
|
|
90
|
+
*/
|
|
91
|
+
export interface FixtureSpec {
|
|
92
|
+
readonly workspaceRoot: string;
|
|
93
|
+
readonly userHome: string;
|
|
94
|
+
readonly project?: ScopeFiles;
|
|
95
|
+
readonly user?: ScopeFiles;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Test deps returned from `buildFixture(spec)`. Downstream layers consume
|
|
99
|
+
* `fs` and `path` to satisfy the `FileSystem` and `Path` services. `files`
|
|
100
|
+
* exposes the raw map for diagnostic snapshots (test-only).
|
|
101
|
+
*/
|
|
102
|
+
export interface FixtureTestDeps {
|
|
103
|
+
readonly fs: FileSystem.FileSystem;
|
|
104
|
+
readonly path: Path.Path;
|
|
105
|
+
readonly files: ReadonlyMap<string, string>;
|
|
106
|
+
readonly workspaceRoot: string;
|
|
107
|
+
readonly userHome: string;
|
|
108
|
+
}
|
|
109
|
+
export declare const resolveFixtureProjectLayout: (deps: FixtureTestDeps, settings?: Settings) => Effect.Effect<import("../../layout.js").ProjectWorkspaceLayout, import("../../errors.ts").WorkspaceLayoutError, never>;
|
|
110
|
+
export declare const resolveFixtureUserLayout: (deps: FixtureTestDeps, settings?: Settings) => Effect.Effect<import("../../layout.js").UserWorkspaceLayout, never, never>;
|
|
111
|
+
declare const PathEscapeError_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 & {
|
|
112
|
+
readonly _tag: "PathEscapeError";
|
|
113
|
+
} & Readonly<A>;
|
|
114
|
+
/**
|
|
115
|
+
* Builder rejected an entry because the spec asked to write outside the
|
|
116
|
+
* workspace/user-home root. Phase 9's `WorkspaceRootEscape` is a different
|
|
117
|
+
* (Layer-level) error; this one is purely a fixture sanity check so tests
|
|
118
|
+
* cannot accidentally clobber files outside the intended tree.
|
|
119
|
+
*/
|
|
120
|
+
export declare class PathEscapeError extends PathEscapeError_base<{
|
|
121
|
+
readonly path: string;
|
|
122
|
+
readonly reason: string;
|
|
123
|
+
}> {
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build a fixture against an in-memory FileSystem.
|
|
127
|
+
*
|
|
128
|
+
* The returned `FixtureTestDeps` value is a stable, dependency-closed value:
|
|
129
|
+
* it carries the synthesized `FileSystem`, a `Path.Path` value, and the
|
|
130
|
+
* raw file map. Downstream test layers compose these with the real Live
|
|
131
|
+
* implementations.
|
|
132
|
+
*
|
|
133
|
+
* Failures: the builder fails with `PathEscapeError` when any tree entry
|
|
134
|
+
* contains a `..` segment or an absolute path. Phase 9's
|
|
135
|
+
* `WorkspaceRootEscape` is a different (Layer-construction) failure.
|
|
136
|
+
*/
|
|
137
|
+
export declare const buildFixture: (spec: FixtureSpec) => Effect.Effect<FixtureTestDeps, PathEscapeError>;
|
|
138
|
+
/**
|
|
139
|
+
* No source files materialize. Both scopes return absent for every cell.
|
|
140
|
+
*/
|
|
141
|
+
export declare const absentAll: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
142
|
+
/**
|
|
143
|
+
* Both project sources present and decodable; user scope settings present.
|
|
144
|
+
*/
|
|
145
|
+
export declare const validAll: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
146
|
+
/**
|
|
147
|
+
* Settings is valid; the lockfile is byte-corrupt.
|
|
148
|
+
*/
|
|
149
|
+
export declare const lockfileInvalidOnly: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
150
|
+
/**
|
|
151
|
+
* Lockfile is valid; settings is byte-corrupt.
|
|
152
|
+
*/
|
|
153
|
+
export declare const settingsInvalidOnly: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
154
|
+
/**
|
|
155
|
+
* Both project sources are byte-corrupt.
|
|
156
|
+
*/
|
|
157
|
+
export declare const bothInvalid: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
158
|
+
/**
|
|
159
|
+
* Project state present; user scope absent.
|
|
160
|
+
*/
|
|
161
|
+
export declare const projectOnly: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
162
|
+
/**
|
|
163
|
+
* User scope settings present; project state absent.
|
|
164
|
+
*/
|
|
165
|
+
export declare const userOnly: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
166
|
+
/**
|
|
167
|
+
* Both scopes declare a source-host with the same name. Phase 9 verifies that
|
|
168
|
+
* the WorkspaceReadModel exposes both scope reads independently and does not
|
|
169
|
+
* implicitly merge them.
|
|
170
|
+
*/
|
|
171
|
+
export declare const projectUserShadowing: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
172
|
+
/**
|
|
173
|
+
* Agent dir exists on disk but settings does not declare the agent. Phase 9
|
|
174
|
+
* verifies the `agents.detected` projection surfaces a mismatch.
|
|
175
|
+
*/
|
|
176
|
+
export declare const agentPresentNoDeclaration: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
177
|
+
/**
|
|
178
|
+
* Settings declares an agent whose directory does not exist.
|
|
179
|
+
*/
|
|
180
|
+
export declare const agentDeclaredNotInstalled: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
181
|
+
/**
|
|
182
|
+
* Settings disagrees with `.mcp.json`: the keys differ between the two
|
|
183
|
+
* surfaces. Phase 9 verifies the MCP-server projection exposes both views
|
|
184
|
+
* without silently reconciling them.
|
|
185
|
+
*/
|
|
186
|
+
export declare const mcpConfigDrift: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
187
|
+
/**
|
|
188
|
+
* Same skill name across agent skill dirs (`.claude/skills/`, `.agents/skills/`)
|
|
189
|
+
* and canonical AXM storage.
|
|
190
|
+
*/
|
|
191
|
+
export declare const sameNameAcrossOrigins: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
192
|
+
/**
|
|
193
|
+
* Spec containing a `..` segment so callers can verify the builder rejects it.
|
|
194
|
+
* The fixture intentionally returns an unbuildable spec; consumers invoke
|
|
195
|
+
* `buildFixture` to assert the rejection path.
|
|
196
|
+
*/
|
|
197
|
+
export declare const pathEscapeAttempt: (workspaceRoot: string, userHome: string) => FixtureSpec;
|
|
198
|
+
export {};
|
|
199
|
+
//# sourceMappingURL=builder.d.ts.map
|