@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,977 @@
1
+ /**
2
+ * Schema definitions for AXM settings configuration.
3
+ *
4
+ * Settings define workspace configuration including sources, agents, and extensions.
5
+ *
6
+ * @experimental This API is unstable and may change without notice.
7
+ */
8
+ import * as Schema from "effect/Schema";
9
+ import * as SchemaTransformation from "effect/SchemaTransformation";
10
+ import { ConfigurableAgentIdSchema, ExtensionVisibilitySchema, EXTENSION_NAME_PATTERN, } from "@agentxm/extension-model/unstable/extensions/common";
11
+ import { ReleaseAgeExcludePatternSchema } from "@agentxm/extension-model/unstable/extensions/fqn-pattern";
12
+ import { HandleSchema } from "@agentxm/extension-model/unstable/extensions/handle";
13
+ import { LintConfigSchema } from "@agentxm/registry-protocol/unstable/lint/config";
14
+ import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
15
+ // -----------------------------------------------------------------------------
16
+ // Source Host Config (array-based, discriminated on `type` field)
17
+ // -----------------------------------------------------------------------------
18
+ /**
19
+ * Pattern for source names: lowercase alphanumeric, hyphens, and dots.
20
+ * Must start with a letter or digit.
21
+ *
22
+ * @experimental This API is unstable and may change without notice.
23
+ */
24
+ const SOURCE_NAME_PATTERN = /^(?!(?:git|local|workspace)$)[a-z0-9][a-z0-9.-]*$/;
25
+ const SourceNameSchema = Schema.String.check(Schema.isPattern(SOURCE_NAME_PATTERN, {
26
+ message: 'source name must start with a letter or digit, contain only lowercase alphanumeric characters, hyphens, and dots, and must not be a reserved name: "git", "local", or "workspace"',
27
+ })).annotate({
28
+ identifier: "SourceName",
29
+ title: "Source Name",
30
+ description: 'A source host alias: lowercase letters, numbers, hyphens, and dots. The names "git", "local", and "workspace" are reserved.',
31
+ examples: ["github", "my-registry.dev"],
32
+ });
33
+ const sourceNameFieldSchema = SourceNameSchema.pipe(Schema.annotateKey({ messageMissingKey: "source name is required" }), Schema.annotate({
34
+ description: "Alias used in entry source strings for this source host.",
35
+ }));
36
+ const sourceUrlFieldSchema = Schema.URLFromString.pipe(Schema.annotateKey({ messageMissingKey: "source url is required" }), Schema.annotate({
37
+ description: "Base URL for this source host endpoint.",
38
+ }));
39
+ /**
40
+ * GitHub source host configuration.
41
+ *
42
+ * @experimental This API is unstable and may change without notice.
43
+ */
44
+ const GitHubSourceHostConfigSchema = Schema.Struct({
45
+ name: sourceNameFieldSchema,
46
+ type: Schema.Literal("github"),
47
+ url: sourceUrlFieldSchema,
48
+ }).annotate({
49
+ identifier: "GitHubSourceHostConfig",
50
+ title: "GitHub Source Host",
51
+ description: "A GitHub source host.",
52
+ });
53
+ /**
54
+ * GitLab source host configuration.
55
+ *
56
+ * @experimental This API is unstable and may change without notice.
57
+ */
58
+ const GitLabSourceHostConfigSchema = Schema.Struct({
59
+ name: sourceNameFieldSchema,
60
+ type: Schema.Literal("gitlab"),
61
+ url: sourceUrlFieldSchema,
62
+ }).annotate({
63
+ identifier: "GitLabSourceHostConfig",
64
+ title: "GitLab Source Host",
65
+ description: "A GitLab source host.",
66
+ });
67
+ /**
68
+ * Bitbucket source host configuration.
69
+ *
70
+ * @experimental This API is unstable and may change without notice.
71
+ */
72
+ const BitbucketSourceHostConfigSchema = Schema.Struct({
73
+ name: sourceNameFieldSchema,
74
+ type: Schema.Literal("bitbucket"),
75
+ url: sourceUrlFieldSchema,
76
+ }).annotate({
77
+ identifier: "BitbucketSourceHostConfig",
78
+ title: "Bitbucket Source Host",
79
+ description: "A Bitbucket source host.",
80
+ });
81
+ /**
82
+ * Azure Repos source host configuration.
83
+ *
84
+ * @experimental This API is unstable and may change without notice.
85
+ */
86
+ const AzureReposSourceHostConfigSchema = Schema.Struct({
87
+ name: sourceNameFieldSchema,
88
+ type: Schema.Literal("azurerepos"),
89
+ url: sourceUrlFieldSchema,
90
+ }).annotate({
91
+ identifier: "AzureReposSourceHostConfig",
92
+ title: "Azure Repos Source Host",
93
+ description: "An Azure Repos source host.",
94
+ });
95
+ /**
96
+ * Registry source host configuration.
97
+ *
98
+ * @experimental This API is unstable and may change without notice.
99
+ */
100
+ const RegistrySourceHostConfigSchema = Schema.Struct({
101
+ name: sourceNameFieldSchema,
102
+ type: Schema.Literal("registry"),
103
+ location: Schema.URLFromString.pipe(Schema.annotateKey({ messageMissingKey: "source location is required" }), Schema.annotate({
104
+ description: "Registry endpoint for this source; accepts http(s)://, file://, or local paths.",
105
+ })),
106
+ }).annotate({
107
+ identifier: "RegistrySourceHostConfig",
108
+ title: "Registry Source Host",
109
+ description: "A package registry source host.",
110
+ });
111
+ /**
112
+ * Discriminated union of source host configurations on the `type` field.
113
+ *
114
+ * Variants: github, gitlab, bitbucket, azurerepos, registry.
115
+ *
116
+ * @experimental This API is unstable and may change without notice.
117
+ */
118
+ export const SourceHostConfigSchema = Schema.Union([
119
+ GitHubSourceHostConfigSchema,
120
+ GitLabSourceHostConfigSchema,
121
+ BitbucketSourceHostConfigSchema,
122
+ AzureReposSourceHostConfigSchema,
123
+ RegistrySourceHostConfigSchema,
124
+ ]).annotate({
125
+ identifier: "SourceHostConfig",
126
+ title: "Source Host Config",
127
+ description: "A source host configuration: GitHub, GitLab, Bitbucket, Azure Repos, or a package registry.",
128
+ });
129
+ const ExtensionMapKeySchema = Schema.String.check(Schema.isPattern(EXTENSION_NAME_PATTERN, {
130
+ message: "Names must be max 64 chars, lowercase letters/numbers/hyphens, not starting or ending with hyphen.",
131
+ }));
132
+ const enabledFieldSchema = Schema.optionalKey(Schema.Boolean.annotate({
133
+ description: "Set to false to disable this entry. Omit otherwise — true is the default and should not be written explicitly.",
134
+ default: true,
135
+ }));
136
+ const entrySourceFieldSchema = (label, fqnType) => Schema.NonEmptyString.pipe(Schema.annotateKey({ messageMissingKey: `${label} source is required` }), Schema.annotate({
137
+ description: "FQN with optional version constraint, source-scheme ref like github:owner/repo, or local path.",
138
+ examples: [
139
+ `@acme/${fqnType}/code-review@^1.0.0`,
140
+ "github:acme/agent-extensions",
141
+ "./extensions/code-review",
142
+ ],
143
+ }));
144
+ const workspaceEntriesMatch = (pluralType) => Schema.makeFilter((entries) => {
145
+ for (const [entryName, entry] of Object.entries(entries)) {
146
+ if (entry.source.startsWith("workspace:") || entry.source === "authored") {
147
+ return `Workspace package "${entryName}" must use the compact source "workspace" in ${pluralType}`;
148
+ }
149
+ if (!isWorkspaceSourceLocator(entry.source))
150
+ continue;
151
+ }
152
+ return undefined;
153
+ });
154
+ const mcpWorkspaceEntriesMatch = Schema.makeFilter((entries) => {
155
+ for (const [entryName, entry] of Object.entries(entries)) {
156
+ if (entry.kind !== "sourced")
157
+ continue;
158
+ if (entry.source.startsWith("workspace:") || entry.source === "authored") {
159
+ return `Workspace package "${entryName}" must use the compact source "workspace" in mcps`;
160
+ }
161
+ }
162
+ return undefined;
163
+ });
164
+ const McpServerEnvSchema = Schema.Union([
165
+ Schema.Record(Schema.String, Schema.String),
166
+ Schema.Array(Schema.String),
167
+ ]).annotate({
168
+ identifier: "McpServerEnv",
169
+ title: "MCP Server Env",
170
+ description: "MCP environment values as a map or pass-through variable names. Array entries decode to ${VAR} references.",
171
+ });
172
+ const McpServerAgentsSchema = Schema.Array(ConfigurableAgentIdSchema)
173
+ .annotate({
174
+ description: "Coding agents this MCP server applies to. Omit to target every configured agent.",
175
+ examples: [["claude-code", "codex"]],
176
+ })
177
+ .check(Schema.isMinLength(1), Schema.isUnique());
178
+ const decodeMcpEnv = (env) => {
179
+ if (env === undefined)
180
+ return {};
181
+ if (Array.isArray(env)) {
182
+ return Object.fromEntries(env.map((name) => [name, `\${${name}}`]));
183
+ }
184
+ return Object.fromEntries(Object.entries(env));
185
+ };
186
+ const hasOwnKey = (entry, key) => Object.hasOwn(entry, key) && entry[key] !== undefined;
187
+ const validateMcpTransportExclusivity = (entry) => {
188
+ const transports = ["source", "command", "url"].filter((key) => hasOwnKey(entry, key));
189
+ if (transports.length !== 1) {
190
+ return "MCP server entry must include exactly one of source, command, or url";
191
+ }
192
+ if (hasOwnKey(entry, "source") && (hasOwnKey(entry, "args") || hasOwnKey(entry, "headers"))) {
193
+ return "MCP server source entries cannot include args or headers";
194
+ }
195
+ if (hasOwnKey(entry, "command") && hasOwnKey(entry, "headers")) {
196
+ return "MCP server command entries cannot include headers";
197
+ }
198
+ if (hasOwnKey(entry, "url") && hasOwnKey(entry, "args")) {
199
+ return "MCP server URL entries cannot include args";
200
+ }
201
+ return undefined;
202
+ };
203
+ export const MinimumReleaseAgeSchema = Schema.String.check(Schema.isPattern(/^\d+(ms|s|m|h|d)$/, {
204
+ message: "minimumReleaseAge must be a duration such as 24h, 1440m, or 0s",
205
+ })).annotate({
206
+ identifier: "MinimumReleaseAge",
207
+ title: "Minimum Release Age",
208
+ description: "Minimum age for registry versions during unattended resolution. Use 0s to disable the holdback.",
209
+ default: "24h",
210
+ examples: ["24h", "1440m", "0s"],
211
+ });
212
+ const compactOrVerboseEntry = (objectSchema, canonicalSchema, transformation, annotations) => Schema.Union([Schema.String, objectSchema])
213
+ .annotate(annotations)
214
+ .pipe(Schema.decodeTo(canonicalSchema, SchemaTransformation.transform(transformation)));
215
+ const EnabledEntryCanonicalSchema = Schema.Struct({
216
+ source: Schema.String,
217
+ enabled: Schema.Boolean,
218
+ });
219
+ const decodeEnabledEntry = (entry) => typeof entry === "string"
220
+ ? { source: entry, enabled: true }
221
+ : {
222
+ source: entry.source,
223
+ enabled: entry.enabled ?? true,
224
+ };
225
+ const encodeEnabledEntry = (entry) => {
226
+ if (entry.enabled)
227
+ return entry.source;
228
+ const obj = {
229
+ source: entry.source,
230
+ };
231
+ if (!entry.enabled)
232
+ obj.enabled = false;
233
+ return obj;
234
+ };
235
+ const enabledEntryTransformation = {
236
+ decode: decodeEnabledEntry,
237
+ encode: encodeEnabledEntry,
238
+ };
239
+ const compactEnabledEntry = (objectSchema, annotations) => compactOrVerboseEntry(objectSchema, EnabledEntryCanonicalSchema, enabledEntryTransformation, annotations);
240
+ /**
241
+ * Managed skill with source and optional config flags.
242
+ *
243
+ * @experimental This API is unstable and may change without notice.
244
+ */
245
+ export const SkillEntryObjectSchema = Schema.Struct({
246
+ source: entrySourceFieldSchema("skill", "skills"),
247
+ enabled: enabledFieldSchema,
248
+ origin: Schema.optionalKey(Schema.Literal("bundled").annotate({
249
+ description: "Marks the official AXM skill as materialized from the running CLI's embedded bundle.",
250
+ })),
251
+ }).annotate({
252
+ title: "Skill Entry Object",
253
+ description: "A skill entry with source, optional enabled state, and bundled origin marker.",
254
+ });
255
+ const SkillEntryCanonicalSchema = Schema.Struct({
256
+ source: Schema.String,
257
+ enabled: Schema.Boolean,
258
+ origin: Schema.optionalKey(Schema.Literal("bundled")),
259
+ });
260
+ const decodeSkillEntry = (entry) => typeof entry === "string"
261
+ ? { source: entry, enabled: true }
262
+ : {
263
+ source: entry.source,
264
+ enabled: entry.enabled ?? true,
265
+ ...(entry.origin === undefined ? {} : { origin: entry.origin }),
266
+ };
267
+ const encodeSkillEntry = (entry) => {
268
+ if (entry.enabled && entry.origin === undefined)
269
+ return entry.source;
270
+ return {
271
+ source: entry.source,
272
+ ...(!entry.enabled ? { enabled: false } : {}),
273
+ ...(entry.origin === undefined ? {} : { origin: entry.origin }),
274
+ };
275
+ };
276
+ /**
277
+ * Union of skill entry forms: plain source string or object with source + enabled.
278
+ *
279
+ * Decodes to canonical `{ source, enabled }` form; encodes back to the most
280
+ * compact JSON representation.
281
+ *
282
+ * @experimental This API is unstable and may change without notice.
283
+ */
284
+ export const SkillEntrySchema = Schema.Union([Schema.String, SkillEntryObjectSchema])
285
+ .annotate({
286
+ identifier: "SkillEntry",
287
+ title: "Skill Entry",
288
+ description: "A skill entry: a source string, or an object with source plus optional flags and bundled origin.",
289
+ examples: [
290
+ "@acme/skills/code-review@^1.0.0",
291
+ { source: "github:acme/agent-extensions", enabled: false },
292
+ ],
293
+ })
294
+ .pipe(Schema.decodeTo(SkillEntryCanonicalSchema, SchemaTransformation.transform({
295
+ decode: decodeSkillEntry,
296
+ encode: encodeSkillEntry,
297
+ })));
298
+ /**
299
+ * Skills map - maps skill names to skill entries.
300
+ *
301
+ * Keys must be valid skill names per agentskills.io specification:
302
+ * - Max 64 characters
303
+ * - Lowercase letters, numbers, and hyphens only
304
+ * - Must not start or end with a hyphen
305
+ *
306
+ * Values are skill entries: plain source strings or objects with source + enabled.
307
+ *
308
+ * @experimental This API is unstable and may change without notice.
309
+ */
310
+ export const SkillsMapSchema = Schema.Record(Schema.String, SkillEntrySchema)
311
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
312
+ .check(workspaceEntriesMatch("skills"))
313
+ .annotate({
314
+ identifier: "SkillsMap",
315
+ title: "Skills Map",
316
+ description: "A map of skill names to skill entries.",
317
+ });
318
+ // -----------------------------------------------------------------------------
319
+ // Rule Entry Schemas
320
+ // -----------------------------------------------------------------------------
321
+ /**
322
+ * Managed rule with source and optional config flags.
323
+ *
324
+ * @experimental This API is unstable and may change without notice.
325
+ */
326
+ export const RuleEntryObjectSchema = Schema.Struct({
327
+ source: entrySourceFieldSchema("rule", "rules"),
328
+ enabled: enabledFieldSchema,
329
+ }).annotate({
330
+ title: "Rule Entry Object",
331
+ description: "A rule entry with source and an optional enabled flag.",
332
+ });
333
+ /**
334
+ * Union of rule entry forms: plain source string or object with source + enabled.
335
+ *
336
+ * @experimental This API is unstable and may change without notice.
337
+ */
338
+ export const RuleEntrySchema = compactEnabledEntry(RuleEntryObjectSchema, {
339
+ identifier: "RuleEntry",
340
+ title: "Rule Entry",
341
+ description: "A rule entry: a source string, or an object with source plus optional flags.",
342
+ examples: [
343
+ "@acme/rules/api-conventions@^1.0.0",
344
+ { source: "@acme/rules/api-conventions@^1.0.0", enabled: false },
345
+ ],
346
+ });
347
+ /**
348
+ * Rules map - maps rule names to rule entries.
349
+ *
350
+ * @experimental This API is unstable and may change without notice.
351
+ */
352
+ export const RulesMapSchema = Schema.Record(Schema.String, RuleEntrySchema)
353
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
354
+ .check(workspaceEntriesMatch("rules"))
355
+ .annotate({
356
+ identifier: "RulesMap",
357
+ title: "Rules Map",
358
+ description: "A map of rule names to rule entries.",
359
+ });
360
+ // -----------------------------------------------------------------------------
361
+ // Hook Entry Schemas
362
+ // -----------------------------------------------------------------------------
363
+ /**
364
+ * Managed hook with source and optional config flags.
365
+ *
366
+ * @experimental This API is unstable and may change without notice.
367
+ */
368
+ export const HookEntryObjectSchema = Schema.Struct({
369
+ source: entrySourceFieldSchema("hook", "hooks"),
370
+ enabled: enabledFieldSchema,
371
+ }).annotate({
372
+ title: "Hook Entry Object",
373
+ description: "A hook entry with source and an optional enabled flag.",
374
+ });
375
+ /**
376
+ * Union of hook entry forms: plain source string or object with source + enabled.
377
+ *
378
+ * @experimental This API is unstable and may change without notice.
379
+ */
380
+ export const HookEntrySchema = compactEnabledEntry(HookEntryObjectSchema, {
381
+ identifier: "HookEntry",
382
+ title: "Hook Entry",
383
+ description: "A hook entry: a source string, or an object with source plus optional flags.",
384
+ examples: [
385
+ "@acme/hooks/block-secrets@^1.0.0",
386
+ { source: "@acme/hooks/block-secrets@^1.0.0", enabled: false },
387
+ ],
388
+ });
389
+ /**
390
+ * Hooks map - maps hook names to hook entries.
391
+ *
392
+ * @experimental This API is unstable and may change without notice.
393
+ */
394
+ export const HooksMapSchema = Schema.Record(Schema.String, HookEntrySchema)
395
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
396
+ .check(workspaceEntriesMatch("hooks"))
397
+ .annotate({
398
+ identifier: "HooksMap",
399
+ title: "Hooks Map",
400
+ description: "A map of hook names to hook entries.",
401
+ });
402
+ // -----------------------------------------------------------------------------
403
+ // Knowledge Entry Schemas
404
+ // -----------------------------------------------------------------------------
405
+ export const KnowledgeEntryObjectSchema = Schema.Struct({
406
+ source: entrySourceFieldSchema("knowledge bundle", "knowledge"),
407
+ enabled: enabledFieldSchema,
408
+ instructionEntry: Schema.optionalKey(Schema.Boolean.annotate({
409
+ description: "Include this bundle in the managed Knowledge Bundles instruction table. Omit to inherit the manifest default.",
410
+ })),
411
+ }).annotate({
412
+ title: "Knowledge Entry Object",
413
+ description: "A knowledge bundle entry with source, optional enabled state, and an optional instruction-entry override.",
414
+ });
415
+ const KnowledgeEntryCanonicalSchema = Schema.Struct({
416
+ source: Schema.String,
417
+ enabled: Schema.Boolean,
418
+ instructionEntry: Schema.optionalKey(Schema.Boolean),
419
+ });
420
+ const decodeKnowledgeEntry = (entry) => typeof entry === "string"
421
+ ? { source: entry, enabled: true }
422
+ : {
423
+ source: entry.source,
424
+ enabled: entry.enabled ?? true,
425
+ ...(entry.instructionEntry === undefined
426
+ ? {}
427
+ : { instructionEntry: entry.instructionEntry }),
428
+ };
429
+ const encodeKnowledgeEntry = (entry) => {
430
+ if (entry.enabled && entry.instructionEntry === undefined)
431
+ return entry.source;
432
+ return {
433
+ source: entry.source,
434
+ ...(!entry.enabled ? { enabled: false } : {}),
435
+ ...(entry.instructionEntry === undefined ? {} : { instructionEntry: entry.instructionEntry }),
436
+ };
437
+ };
438
+ export const KnowledgeEntrySchema = compactOrVerboseEntry(KnowledgeEntryObjectSchema, KnowledgeEntryCanonicalSchema, { decode: decodeKnowledgeEntry, encode: encodeKnowledgeEntry }, {
439
+ identifier: "KnowledgeEntry",
440
+ title: "Knowledge Entry",
441
+ description: "A knowledge bundle source string, or an object with optional lifecycle and instruction-entry settings.",
442
+ examples: [
443
+ "@acme/knowledge/payments@^1.0.0",
444
+ { source: "@acme/knowledge/payments@^1.0.0", enabled: false },
445
+ { source: "@acme/knowledge/payments@^1.0.0", instructionEntry: false },
446
+ ],
447
+ });
448
+ export const KnowledgeMapSchema = Schema.Record(Schema.String, KnowledgeEntrySchema)
449
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
450
+ .check(workspaceEntriesMatch("knowledge"))
451
+ .annotate({
452
+ identifier: "KnowledgeMap",
453
+ title: "Knowledge Map",
454
+ description: "A map of isolated Open Knowledge Format bundles.",
455
+ });
456
+ // -----------------------------------------------------------------------------
457
+ // MCP Server Entry Schemas
458
+ // -----------------------------------------------------------------------------
459
+ /**
460
+ * MCP server entry object with source.
461
+ *
462
+ * @experimental This API is unstable and may change without notice.
463
+ */
464
+ export const McpServerEntryObjectSchema = Schema.Struct({
465
+ source: entrySourceFieldSchema("MCP server", "mcps"),
466
+ enabled: enabledFieldSchema,
467
+ env: Schema.optionalKey(McpServerEnvSchema),
468
+ agents: Schema.optionalKey(McpServerAgentsSchema),
469
+ }).annotate({
470
+ title: "MCP Server Entry Object",
471
+ description: "An MCP server entry with source and optional enabled/env fields.",
472
+ });
473
+ const McpServerVerboseEntryObjectSchema = Schema.Struct({
474
+ source: Schema.optionalKey(entrySourceFieldSchema("MCP server", "mcps")),
475
+ command: Schema.optionalKey(Schema.NonEmptyString.pipe(Schema.annotate({
476
+ description: "Executable command for an inline stdio MCP server.",
477
+ examples: ["npx"],
478
+ }))),
479
+ args: Schema.optionalKey(Schema.Array(Schema.String).annotate({
480
+ description: "Arguments passed to the inline stdio MCP server command.",
481
+ examples: [["-y", "linear-mcp-server"]],
482
+ })),
483
+ url: Schema.optionalKey(Schema.NonEmptyString.pipe(Schema.annotate({
484
+ description: "Remote MCP server URL.",
485
+ examples: ["https://mcp.sentry.dev/sse"],
486
+ }))),
487
+ headers: Schema.optionalKey(Schema.Record(Schema.String, Schema.String).annotate({
488
+ description: "HTTP headers for a remote MCP server. Prefer ${VAR} references for secrets.",
489
+ })),
490
+ enabled: enabledFieldSchema,
491
+ env: Schema.optionalKey(McpServerEnvSchema),
492
+ agents: Schema.optionalKey(McpServerAgentsSchema),
493
+ }).pipe(Schema.check(Schema.makeFilter((entry) => validateMcpTransportExclusivity(entry))));
494
+ /**
495
+ * Union of MCP server entry forms: plain source string or object with source + enabled + env.
496
+ *
497
+ * Decodes to canonical `{ source, enabled, env }` form; encodes back to the most
498
+ * compact JSON representation.
499
+ *
500
+ * @experimental This API is unstable and may change without notice.
501
+ */
502
+ export const McpServerEntrySchema = compactOrVerboseEntry(McpServerVerboseEntryObjectSchema, Schema.Union([
503
+ Schema.Struct({
504
+ kind: Schema.optional(Schema.Literal("sourced")),
505
+ source: Schema.String,
506
+ command: Schema.optional(Schema.String),
507
+ args: Schema.optional(Schema.Array(Schema.String)),
508
+ url: Schema.optional(Schema.String),
509
+ headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),
510
+ enabled: Schema.Boolean,
511
+ env: Schema.Record(Schema.String, Schema.String),
512
+ agents: Schema.optional(Schema.Array(ConfigurableAgentIdSchema)),
513
+ }),
514
+ Schema.Struct({
515
+ kind: Schema.Literal("inline"),
516
+ source: Schema.optional(Schema.Never),
517
+ command: Schema.optional(Schema.String),
518
+ args: Schema.optional(Schema.Array(Schema.String)),
519
+ url: Schema.optional(Schema.String),
520
+ headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),
521
+ enabled: Schema.Boolean,
522
+ env: Schema.Record(Schema.String, Schema.String),
523
+ agents: Schema.optional(Schema.Array(ConfigurableAgentIdSchema)),
524
+ }),
525
+ ]), {
526
+ decode: (entry) => typeof entry === "string"
527
+ ? { kind: "sourced", source: entry, enabled: true, env: {} }
528
+ : entry.source !== undefined
529
+ ? {
530
+ kind: "sourced",
531
+ source: entry.source,
532
+ enabled: entry.enabled ?? true,
533
+ env: decodeMcpEnv(entry.env),
534
+ ...(entry.agents === undefined ? {} : { agents: entry.agents }),
535
+ }
536
+ : {
537
+ kind: "inline",
538
+ ...(entry.command === undefined ? {} : { command: entry.command }),
539
+ ...(entry.args === undefined ? {} : { args: entry.args }),
540
+ ...(entry.url === undefined ? {} : { url: entry.url }),
541
+ ...(entry.headers === undefined ? {} : { headers: entry.headers }),
542
+ enabled: entry.enabled ?? true,
543
+ env: decodeMcpEnv(entry.env),
544
+ ...(entry.agents === undefined ? {} : { agents: entry.agents }),
545
+ },
546
+ encode: (entry) => {
547
+ if (entry.kind !== "inline" &&
548
+ entry.enabled &&
549
+ Object.keys(entry.env).length === 0 &&
550
+ entry.agents === undefined) {
551
+ return entry.source;
552
+ }
553
+ const obj = {};
554
+ if (entry.kind !== "inline")
555
+ obj.source = entry.source;
556
+ if (entry.kind === "inline" && entry.command !== undefined)
557
+ obj.command = entry.command;
558
+ if (entry.kind === "inline" && entry.args !== undefined && entry.args.length > 0)
559
+ obj.args = entry.args;
560
+ if (entry.kind === "inline" && entry.url !== undefined)
561
+ obj.url = entry.url;
562
+ if (entry.kind === "inline" &&
563
+ entry.headers !== undefined &&
564
+ Object.keys(entry.headers).length > 0) {
565
+ obj.headers = entry.headers;
566
+ }
567
+ if (!entry.enabled)
568
+ obj.enabled = false;
569
+ if (Object.keys(entry.env).length > 0)
570
+ obj.env = entry.env;
571
+ if (entry.agents !== undefined)
572
+ obj.agents = entry.agents;
573
+ if (entry.kind !== "inline") {
574
+ return {
575
+ source: entry.source,
576
+ ...(obj.enabled === undefined ? {} : { enabled: obj.enabled }),
577
+ ...(obj.env === undefined ? {} : { env: obj.env }),
578
+ ...(obj.agents === undefined ? {} : { agents: obj.agents }),
579
+ };
580
+ }
581
+ if (entry.command !== undefined) {
582
+ return {
583
+ command: entry.command,
584
+ ...(obj.args === undefined ? {} : { args: obj.args }),
585
+ ...(obj.enabled === undefined ? {} : { enabled: obj.enabled }),
586
+ ...(obj.env === undefined ? {} : { env: obj.env }),
587
+ ...(obj.agents === undefined ? {} : { agents: obj.agents }),
588
+ };
589
+ }
590
+ return {
591
+ url: entry.url ?? "",
592
+ ...(obj.headers === undefined ? {} : { headers: obj.headers }),
593
+ ...(obj.enabled === undefined ? {} : { enabled: obj.enabled }),
594
+ ...(obj.env === undefined ? {} : { env: obj.env }),
595
+ ...(obj.agents === undefined ? {} : { agents: obj.agents }),
596
+ };
597
+ },
598
+ }, {
599
+ identifier: "McpServerEntry",
600
+ title: "MCP Server Entry",
601
+ description: "An MCP server entry: a source string, sourced object, inline command object, or inline URL object.",
602
+ examples: [
603
+ "@acme/mcps/context@^1.0.0",
604
+ { source: "github:acme/agent-extensions", enabled: false },
605
+ {
606
+ command: "npx",
607
+ args: ["-y", "linear-mcp-server"],
608
+ env: ["LINEAR_API_KEY"],
609
+ agents: ["claude-code"],
610
+ },
611
+ { url: "https://mcp.sentry.dev/sse", headers: { Authorization: "Bearer ${SENTRY_TOKEN}" } },
612
+ ],
613
+ });
614
+ export const isSourcedMcpServerEntry = (entry) => entry.kind !== "inline";
615
+ export const isInlineMcpServerEntry = (entry) => entry.kind === "inline";
616
+ /**
617
+ * MCP servers map - maps MCP server names to MCP server entries.
618
+ *
619
+ * Keys use the canonical MCP server name schema from the shared kernel.
620
+ *
621
+ * @experimental This API is unstable and may change without notice.
622
+ */
623
+ export const McpServersMapSchema = Schema.Record(Schema.String, McpServerEntrySchema)
624
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
625
+ .check(mcpWorkspaceEntriesMatch)
626
+ .annotate({
627
+ identifier: "McpServersMap",
628
+ title: "MCP Servers Map",
629
+ description: "A map of MCP server names to MCP server entries.",
630
+ });
631
+ // -----------------------------------------------------------------------------
632
+ // Subagent Entry Schemas
633
+ // -----------------------------------------------------------------------------
634
+ /**
635
+ * Managed subagent with source and optional config flags.
636
+ *
637
+ * @experimental This API is unstable and may change without notice.
638
+ */
639
+ export const SubagentEntryObjectSchema = Schema.Struct({
640
+ source: entrySourceFieldSchema("subagent", "subagents"),
641
+ enabled: enabledFieldSchema,
642
+ }).annotate({
643
+ title: "Subagent Entry Object",
644
+ description: "A subagent entry with source and an optional enabled flag.",
645
+ });
646
+ /**
647
+ * Union of subagent entry forms: plain source string or object with source + enabled.
648
+ *
649
+ * Decodes to canonical `{ source, enabled }` form; encodes back to the most
650
+ * compact JSON representation.
651
+ *
652
+ * @experimental This API is unstable and may change without notice.
653
+ */
654
+ export const SubagentEntrySchema = compactEnabledEntry(SubagentEntryObjectSchema, {
655
+ identifier: "SubagentEntry",
656
+ title: "Subagent Entry",
657
+ description: "A subagent entry: a source string, or an object with source plus optional flags.",
658
+ examples: [
659
+ "@acme/subagents/reviewer@^1.0.0",
660
+ { source: "github:acme/agent-extensions", enabled: false },
661
+ ],
662
+ });
663
+ /**
664
+ * Subagents map - maps subagent names to subagent entries.
665
+ *
666
+ * Keys must be valid extension names per agentskills.io specification:
667
+ * - Max 64 characters
668
+ * - Lowercase letters, numbers, and hyphens only
669
+ * - Must not start or end with a hyphen
670
+ *
671
+ * Values are subagent entries: plain source strings or objects with source + enabled.
672
+ *
673
+ * @experimental This API is unstable and may change without notice.
674
+ */
675
+ export const SubagentsMapSchema = Schema.Record(Schema.String, SubagentEntrySchema)
676
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
677
+ .check(workspaceEntriesMatch("subagents"))
678
+ .annotate({
679
+ identifier: "SubagentsMap",
680
+ title: "Subagents Map",
681
+ description: "A map of subagent names to subagent entries.",
682
+ });
683
+ // -----------------------------------------------------------------------------
684
+ // Pack Entry Schemas
685
+ // -----------------------------------------------------------------------------
686
+ /**
687
+ * Pack entry object with source.
688
+ *
689
+ * @experimental This API is unstable and may change without notice.
690
+ */
691
+ export const PackEntryObjectSchema = Schema.Struct({
692
+ source: entrySourceFieldSchema("pack", "packs"),
693
+ enabled: enabledFieldSchema,
694
+ }).annotate({
695
+ title: "Pack Entry Object",
696
+ description: "A pack entry with a source and an optional enabled flag.",
697
+ });
698
+ /**
699
+ * Union of pack entry forms: plain source string or object with source.
700
+ *
701
+ * Decodes to canonical `{ source }` form and encodes back to a source string.
702
+ *
703
+ * @experimental This API is unstable and may change without notice.
704
+ */
705
+ export const PackEntrySchema = compactEnabledEntry(PackEntryObjectSchema, {
706
+ identifier: "PackEntry",
707
+ title: "Pack Entry",
708
+ description: "A pack entry: a source string, or an object with source plus optional flags.",
709
+ examples: [
710
+ "@acme/packs/typescript@^1.0.0",
711
+ { source: "@acme/packs/typescript@^1.0.0", enabled: false },
712
+ ],
713
+ });
714
+ /**
715
+ * Packs map - maps pack names to pack entries.
716
+ *
717
+ * Keys must be valid extension names per agentskills.io specification:
718
+ * - Max 64 characters
719
+ * - Lowercase letters, numbers, and hyphens only
720
+ * - Must not start or end with a hyphen
721
+ *
722
+ * Values are pack entries: plain source strings or objects with source + enabled.
723
+ *
724
+ * @experimental This API is unstable and may change without notice.
725
+ */
726
+ export const PacksMapSchema = Schema.Record(Schema.String, PackEntrySchema)
727
+ .check(Schema.isPropertyNames(ExtensionMapKeySchema))
728
+ .check(workspaceEntriesMatch("packs"))
729
+ .annotate({
730
+ identifier: "PacksMap",
731
+ title: "Packs Map",
732
+ description: "A map of pack names to pack entries.",
733
+ });
734
+ // -----------------------------------------------------------------------------
735
+ // Feature Config Schemas
736
+ // -----------------------------------------------------------------------------
737
+ /**
738
+ * Workspace instruction-file propagation settings.
739
+ *
740
+ * @experimental This API is unstable and may change without notice.
741
+ */
742
+ export const InstructionsConfigSchema = Schema.Struct({
743
+ fileName: Schema.optionalKey(Schema.String.annotate({
744
+ description: "Source-of-truth instruction file name.",
745
+ default: "AGENTS.md",
746
+ examples: ["AGENTS.md"],
747
+ })),
748
+ gitignoreAliases: Schema.optionalKey(Schema.Boolean.annotate({
749
+ description: "Whether AXM adds each exact propagated alias target (e.g. /CLAUDE.md or /docs/CLAUDE.md) to a managed .gitignore region. The source-of-truth file (fileName) is never ignored.",
750
+ default: true,
751
+ examples: [true, false],
752
+ })),
753
+ }).annotate({
754
+ identifier: "InstructionsConfig",
755
+ title: "Instructions Config",
756
+ description: "Instruction-file management settings for configured agents.",
757
+ });
758
+ const authoredDirectoryFieldSchema = Schema.optionalKey(Schema.NonEmptyString.annotate({
759
+ description: "Workspace-relative authored package directory for this extension type. Omit to use the conventional root directory.",
760
+ examples: ["extensions/skills"],
761
+ }));
762
+ const authoredDirectoryConfigSchema = (identifier, title) => Schema.Struct({ dir: authoredDirectoryFieldSchema }).annotate({
763
+ identifier,
764
+ title,
765
+ description: "Authored package directory configuration. AXM reads this manual override but never rewrites it.",
766
+ });
767
+ export const SkillsConfigSchema = authoredDirectoryConfigSchema("SkillsConfig", "Skills Config");
768
+ export const RulesConfigSchema = authoredDirectoryConfigSchema("RulesConfig", "Rules Config");
769
+ export const HooksConfigSchema = authoredDirectoryConfigSchema("HooksConfig", "Hooks Config");
770
+ export const SubagentsConfigSchema = authoredDirectoryConfigSchema("SubagentsConfig", "Subagents Config");
771
+ export const McpServersConfigSchema = authoredDirectoryConfigSchema("McpServersConfig", "MCP Servers Config");
772
+ export const PacksConfigSchema = authoredDirectoryConfigSchema("PacksConfig", "Packs Config");
773
+ export const KnowledgeConfigSchema = Schema.Struct({
774
+ dir: authoredDirectoryFieldSchema,
775
+ instructions: Schema.optionalKey(Schema.Boolean.annotate({
776
+ description: "Whether active Knowledge is synchronized into the canonical instruction source. Omit true; persist only false.",
777
+ default: true,
778
+ examples: [false],
779
+ })),
780
+ }).annotate({
781
+ identifier: "KnowledgeConfig",
782
+ title: "Knowledge Config",
783
+ description: "Knowledge discovery settings. Omit the config to synchronize active bundles into instructions; set instructions to false to disable that table.",
784
+ });
785
+ /** Workspace-level publication defaults. */
786
+ export const WorkspacePublishOptionsSchema = Schema.Struct({
787
+ defaultVisibility: Schema.optional(ExtensionVisibilitySchema.annotate({
788
+ description: "Fallback whole-Extension Registry visibility when an extension manifest does not declare publish.visibility.",
789
+ })),
790
+ }).annotate({
791
+ identifier: "WorkspacePublishOptions",
792
+ title: "Workspace Publish Options",
793
+ description: "Workspace defaults used when extension publication policy is unconfigured.",
794
+ });
795
+ /**
796
+ * Each catalog extension type's feature-level config schema, or `null` where
797
+ * none exists yet.
798
+ *
799
+ * Total by construction: a new extension type fails compile here until its
800
+ * settings coverage is decided. The parity conformance suite reads this map,
801
+ * and every `null` must be matched by a ledger row.
802
+ *
803
+ * @experimental This API is unstable and may change without notice.
804
+ */
805
+ export const SETTINGS_CONFIG_SCHEMA_BY_TYPE = {
806
+ skill: SkillsConfigSchema,
807
+ "mcp-server": McpServersConfigSchema,
808
+ subagent: SubagentsConfigSchema,
809
+ rule: RulesConfigSchema,
810
+ hook: HooksConfigSchema,
811
+ knowledge: KnowledgeConfigSchema,
812
+ };
813
+ /**
814
+ * Canonical key order for settings properties.
815
+ *
816
+ * Used by `writeSettingsAtPath` for new files and to place new top-level keys in
817
+ * existing files whose recognized keys already follow this order.
818
+ *
819
+ * @experimental This API is unstable and may change without notice.
820
+ */
821
+ export const SETTINGS_KEY_ORDER = [
822
+ "$schema",
823
+ "owner",
824
+ "publish",
825
+ "minimumReleaseAge",
826
+ "minimumReleaseAgeExclude",
827
+ "sources",
828
+ "agents",
829
+ "instructionFiles",
830
+ "skills",
831
+ "skillsConfig",
832
+ "rules",
833
+ "rulesConfig",
834
+ "hooks",
835
+ "hooksConfig",
836
+ "knowledge",
837
+ "knowledgeConfig",
838
+ "subagents",
839
+ "subagentsConfig",
840
+ "packs",
841
+ "packsConfig",
842
+ "mcpServers",
843
+ "mcpServersConfig",
844
+ "lint",
845
+ ];
846
+ /**
847
+ * AXM settings configuration schema.
848
+ *
849
+ * Settings define workspace configuration for AXM including:
850
+ * - owner: Workspace owner handle used for new/scaffold and reconciliation of non-registry sources
851
+ * - minimumReleaseAge: Minimum published age for registry versions during unattended resolution
852
+ * - minimumReleaseAgeExclude: Registry extension identities exempt from minimum release age
853
+ * - sources: Source provider configurations
854
+ * - agents: List of agent IDs to sync extensions to
855
+ * - instructionFiles: Workspace instruction-file propagation settings
856
+ * - skills: Desired skills by name to source string
857
+ * - rules: Desired rules by name to source string
858
+ * - hooks: Desired hooks by name to source string
859
+ * - knowledge: Desired Open Knowledge Format bundles by name to source string
860
+ * - knowledgeConfig: Knowledge discovery-table options
861
+ * - subagents: Desired subagents by name to version specifier
862
+ * - packs: Desired packs by name to version specifier
863
+ * - mcpServers: Desired MCP servers by name to version specifier
864
+ *
865
+ * @experimental This API is unstable and may change without notice.
866
+ */
867
+ const SettingsBaseSchema = Schema.Struct({
868
+ $schema: Schema.optionalKey(Schema.String.annotate({
869
+ description: "URL to the AXM settings JSON Schema. Editors use this to provide autocomplete and validation.",
870
+ examples: ["https://axm.sh/schemas/settings.schema.json"],
871
+ })),
872
+ owner: Schema.optionalKey(Schema.Union([HandleSchema]).annotate({
873
+ description: "Default owner handle used when AXM scaffolds or resolves workspace extensions.",
874
+ })),
875
+ publish: Schema.optionalKey(Schema.Union([WorkspacePublishOptionsSchema]).annotate({
876
+ description: "Workspace-level publication defaults.",
877
+ })),
878
+ minimumReleaseAge: Schema.optionalKey(Schema.Union([MinimumReleaseAgeSchema]).annotate({
879
+ description: "Minimum published age for registry versions during unattended sync/update resolution. Defaults to 24h; use 0s to disable.",
880
+ })),
881
+ minimumReleaseAgeExclude: Schema.optionalKey(Schema.Array(ReleaseAgeExcludePatternSchema)
882
+ .annotate({
883
+ description: "Registry extension identities exempt from minimumReleaseAge, as exact FQNs, owner/type patterns, or owner patterns.",
884
+ })
885
+ .pipe(Schema.annotateEncoded({
886
+ examples: [["@acme/skills/code-review", "@acme/rules/*", "@acme/*"]],
887
+ }))
888
+ .check(Schema.isUnique())),
889
+ agents: Schema.optionalKey(Schema.Array(ConfigurableAgentIdSchema)
890
+ .annotate({
891
+ description: "Coding agents AXM should sync managed extensions into.",
892
+ examples: [["claude-code", "codex"]],
893
+ })
894
+ .check(Schema.isUnique())),
895
+ instructionFiles: Schema.optionalKey(Schema.Union([Schema.Literal(false), InstructionsConfigSchema]).annotate({
896
+ description: "Instruction-file management: false for manual management, an object for enabled propagation, or absent when unset.",
897
+ examples: [false, { fileName: "AGENTS.md", gitignoreAliases: true }],
898
+ })),
899
+ sources: Schema.optionalKey(Schema.Array(SourceHostConfigSchema).annotate({
900
+ description: "Named source hosts used to resolve source-scheme entry references.",
901
+ })),
902
+ skills: Schema.optionalKey(Schema.Union([SkillsMapSchema]).annotate({
903
+ description: "Desired skills, keyed by workspace skill name. Prefer plain source strings; use the object form only to set `enabled: false`.",
904
+ })),
905
+ skillsConfig: Schema.optionalKey(SkillsConfigSchema),
906
+ rules: Schema.optionalKey(Schema.Union([RulesMapSchema]).annotate({
907
+ description: "Desired rules, keyed by workspace rule name. Prefer plain source strings; use the object form only to set `enabled: false`.",
908
+ })),
909
+ rulesConfig: Schema.optionalKey(RulesConfigSchema),
910
+ hooks: Schema.optionalKey(Schema.Union([HooksMapSchema]).annotate({
911
+ description: "Desired hooks, keyed by workspace hook name. Prefer plain source strings; use the object form only to set `enabled: false`.",
912
+ })),
913
+ hooksConfig: Schema.optionalKey(HooksConfigSchema),
914
+ knowledge: Schema.optionalKey(Schema.Union([KnowledgeMapSchema]).annotate({
915
+ description: "Desired Open Knowledge Format bundles discovered from agent instruction files.",
916
+ })),
917
+ knowledgeConfig: Schema.optionalKey(Schema.Union([KnowledgeConfigSchema]).annotate({
918
+ description: "Feature-level instruction discovery options for knowledge bundle management.",
919
+ })),
920
+ subagents: Schema.optionalKey(Schema.Union([SubagentsMapSchema]).annotate({
921
+ description: "Desired subagents, keyed by workspace subagent name. Prefer plain source strings; use the object form only to set `enabled: false`.",
922
+ })),
923
+ subagentsConfig: Schema.optionalKey(SubagentsConfigSchema),
924
+ packs: Schema.optionalKey(Schema.Union([PacksMapSchema]).annotate({
925
+ description: "Desired packs, keyed by workspace pack name. Pack entries do not support `enabled`.",
926
+ })),
927
+ packsConfig: Schema.optionalKey(PacksConfigSchema),
928
+ mcpServers: Schema.optionalKey(Schema.Union([McpServersMapSchema]).annotate({
929
+ description: "Desired MCP servers, keyed by workspace MCP server name. Prefer plain source strings; use the object form to set enabled state, persisted env values, or an agent target subset.",
930
+ })),
931
+ mcpServersConfig: Schema.optionalKey(McpServersConfigSchema),
932
+ lint: Schema.optionalKey(Schema.Union([LintConfigSchema]).annotate({
933
+ description: "Lint configuration for `axm lint` in this workspace.",
934
+ })),
935
+ });
936
+ // Unknown top-level keys are carried by the rest record so a settings file
937
+ // written by a newer AXM survives a read-modify-write cycle instead of being
938
+ // silently rewritten without them. Nested strictness is unchanged: unknown
939
+ // keys inside entry objects still fail decode. The
940
+ // `workspace/settings-keys-recognized` lint rule reports unknown top-level keys
941
+ // at error severity.
942
+ export const SettingsSchema = Schema.StructWithRest(SettingsBaseSchema, [
943
+ Schema.Record(Schema.String, Schema.Unknown),
944
+ ]).annotate({
945
+ identifier: "AxmSettings",
946
+ title: "AXM Settings",
947
+ description: "Your workspace configuration — owner, sources, installed extensions, feature config, and lint config.",
948
+ // Examples are emitted verbatim into the generated JSON Schema. We declare
949
+ // them in the encoded (compact) form so agents see the preferred shape:
950
+ // plain source strings, with the object form reserved for non-default flags.
951
+ // Assertion needed: `.annotate()` types examples against the decoded
952
+ // canonical shape (where `enabled` is a required boolean), but
953
+ // emitting that shape would teach agents to write the very defaults we want
954
+ // them to omit.
955
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
956
+ examples: [
957
+ {
958
+ agents: ["claude-code", "codex"],
959
+ skills: {
960
+ "code-review": "@acme/skills/code-review@^1.0.0",
961
+ "disabled-review": { source: "@acme/skills/disabled-review@^1.0.0", enabled: false },
962
+ },
963
+ lint: {
964
+ rules: {
965
+ "workspace/settings-schema-valid": "error",
966
+ },
967
+ },
968
+ },
969
+ ],
970
+ });
971
+ /**
972
+ * The recognized top-level settings keys, derived from the schema.
973
+ *
974
+ * @experimental This API is unstable and may change without notice.
975
+ */
976
+ export const SETTINGS_KNOWN_KEYS = new Set(Object.keys(SettingsBaseSchema.fields));
977
+ //# sourceMappingURL=schema.js.map