@impetik/xeer-mcp 0.2.19 → 0.2.20

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/README.md CHANGED
@@ -63,11 +63,11 @@ The generated registry is the complete MCP tool and exclusion surface:
63
63
  | `xeer_check` | `check` | `author` / `operator` | Validate a project and report structured diagnostics. | `directory?`: `string` | `read-source`<br>`write-generated` | writes; idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | none |
64
64
  | `xeer_build` | `build` | `author` / `operator` | Build and verify a content-addressed application artifact. | `directory?`: `string` | `read-source`<br>`write-generated`<br>`run-local` | writes; idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | none |
65
65
  | `xeer_test` | `test` | `author` / `operator` | Run application tests against fresh isolated local state. | `directory?`: `string`<br>`timeoutMilliseconds?`: `integer` [1000..1800000] | `read-source`<br>`write-generated`<br>`run-local`<br>`write-state` | writes; idempotent; reversible; non-destructive | `project-relative` | `xeer.dev.v0` | none |
66
- | `xeer_new` | `new` | `author` / `operator` | Create a new project from a supported scaffold. | `directory`: `string`<br>`template?`: `notes` / `todo` / `blog` / `personal-site` | `write-source` | writes; non-idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | none |
66
+ | `xeer_new` | `new` | `author` / `operator` | Create a new project from a supported scaffold. | `directory`: `string`<br>`template?`: `notes` / `todo` / `blog` / `personal-site`<br>`ui?`: `preact` / `react` | `write-source` | writes; non-idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | none |
67
67
  | `xeer_agent_context` | `agent.context` | `author` / `operator` | Read normalized project facts, operations, diagnostics, tests, and safe next actions. | `directory?`: `string` | `read-source` | read-only; idempotent; reversible; non-destructive | `project-relative` | `xeer.agent-context.v0` | none |
68
68
  | `xeer_docs_search` | `docs.search` | `author` / `operator` | Search the installed-version Xeer documentation index. | `query`: `string`<br>`limit?`: `integer` [1..20]; default `5` | none | read-only; idempotent; reversible; non-destructive | `none` | `xeer.docs-search.v0` | none |
69
69
  | `xeer_doctor` | `doctor` | `author` / `operator` | Diagnose the toolchain and generated project state. | `directory?`: `string` | `read-source`<br>`write-generated` | writes; idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | none |
70
- | `xeer_deploy_preview` | `deploy.preview` | `author` / `operator` | Build and deploy an artifact to preview only. | `directory?`: `string`<br>`controlUrl?`: `string` | `read-source`<br>`write-generated`<br>`run-local`<br>`network-read`<br>`network-write` | writes; non-idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | A human must establish the builder credential with xeer auth login. |
70
+ | `xeer_deploy_preview` | `deploy.preview` | `author` / `operator` | Build and deploy an artifact to preview only. | `directory?`: `string`<br>`controlUrl?`: `string` | `read-source`<br>`write-generated`<br>`run-local`<br>`network-read`<br>`network-write` | writes; non-idempotent; reversible; non-destructive | `project-relative` | `xeer.command.v0` | A human must establish the builder credential with xeer auth login, or issue the service token supplied in XEER_SERVICE_TOKEN. |
71
71
  | `xeer_promote` | `promote.operator` | `operator` | Promote an exact review receipt in operator mode. | `directory?`: `string`<br>`receiptId`: `string`<br>`controlUrl?`: `string` | `network-read`<br>`network-write`<br>`production-change` | writes; non-idempotent; reversible; non-destructive | `project-or-url` | `xeer.command.v0` | A human must review the exact artifact and start xeer-mcp with XEER_MCP_PROFILE=operator. |
72
72
  | `xeer_auth_status` | `auth.status` | `author` / `operator` | Report builder credential metadata. | `controlUrl?`: `string` | `network-read`<br>`secret-metadata` | read-only; idempotent; reversible; non-destructive | `none` | `xeer.command.v0` | none |
73
73
  | `xeer_inspect` | `inspect` | `author` / `operator` | Read a running application manifest. | `previewUrl`: `string`<br>`view?`: `manifest` / `state` / `logs` / `export`; default `manifest`<br>`after?`: `string` | `network-read`<br>`read-state` | read-only; idempotent; reversible; non-destructive | `app-or-url` | `xeer.command.v0` | none |
package/dist/server.js CHANGED
@@ -369,7 +369,10 @@ export function createXeerMcpServer(options = {}) {
369
369
  server.registerTool('xeer_new', {
370
370
  ...toolPolicy('new'),
371
371
  outputSchema: commandOutput,
372
- }, async ({ directory, template }) => withDirectory(directory, 'new', (resolved) => commandTool('new', ['new', resolved, ...(template === undefined ? [] : ['--template', template])], projectRoot())));
372
+ }, async ({ directory, template, ui }) => withDirectory(directory, 'new', (resolved) => commandTool('new', ['new', resolved,
373
+ ...(template === undefined ? [] : ['--template', template]),
374
+ ...(ui === undefined ? [] : ['--ui', ui]),
375
+ ], projectRoot())));
373
376
  server.registerTool('xeer_doctor', {
374
377
  ...toolPolicy('doctor'),
375
378
  outputSchema: commandOutput,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impetik/xeer-mcp",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "type": "module",
5
5
  "description": "Model Context Protocol server for Xeer: the scaffold, check, dev, build, and deploy loop as agent tools.",
6
6
  "license": "MIT",
@@ -47,7 +47,7 @@
47
47
  "dependencies": {
48
48
  "@modelcontextprotocol/sdk": "^1.29.0",
49
49
  "zod": "^4.0.10",
50
- "@impetik/xeer": "0.2.19"
50
+ "@impetik/xeer": "0.2.20"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^24.1.0"
@@ -194,7 +194,7 @@ declare const actions: readonly [{
194
194
  readonly command: readonly ["new"];
195
195
  readonly summary: "Create a new project from a supported scaffold.";
196
196
  readonly description: string;
197
- readonly usage: readonly ["new <directory> [--template {{templates}}] [--json]"];
197
+ readonly usage: readonly ["new <directory> [--template {{templates}}] [--ui preact|react] [--json]"];
198
198
  readonly helpOrder: 30;
199
199
  readonly outputProtocol: "xeer.command.v0";
200
200
  readonly effects: readonly ["write-source"];
@@ -216,6 +216,11 @@ declare const actions: readonly [{
216
216
  readonly type: "string";
217
217
  readonly enum: readonly ["notes", "todo", "blog", "personal-site"];
218
218
  };
219
+ readonly ui: {
220
+ readonly description: string;
221
+ readonly type: "string";
222
+ readonly enum: readonly ["preact", "react"];
223
+ };
219
224
  };
220
225
  readonly required: readonly ["directory"];
221
226
  };
@@ -351,7 +356,7 @@ declare const actions: readonly [{
351
356
  readonly idempotent: false;
352
357
  readonly reversible: true;
353
358
  readonly destructive: false;
354
- readonly humanPrerequisites: readonly ["A human must establish the builder credential with xeer auth login."];
359
+ readonly humanPrerequisites: readonly [string];
355
360
  readonly pathPolicy: "project-relative";
356
361
  readonly surfaces: {
357
362
  readonly cli: true;
@@ -385,7 +390,7 @@ declare const actions: readonly [{
385
390
  readonly idempotent: false;
386
391
  readonly reversible: true;
387
392
  readonly destructive: false;
388
- readonly humanPrerequisites: readonly ["A human must establish the builder credential with xeer auth login."];
393
+ readonly humanPrerequisites: readonly [string];
389
394
  readonly pathPolicy: "project-relative";
390
395
  readonly surfaces: {
391
396
  readonly mcpInputSchema: {
@@ -576,7 +581,7 @@ declare const actions: readonly [{
576
581
  readonly idempotent: false;
577
582
  readonly reversible: true;
578
583
  readonly destructive: false;
579
- readonly humanPrerequisites: readonly ["A human must sign in and deliberately keep the public tunnel process running."];
584
+ readonly humanPrerequisites: readonly [string, "A human must deliberately keep the public tunnel process running."];
580
585
  readonly pathPolicy: "none";
581
586
  readonly surfaces: {
582
587
  readonly cli: true;
@@ -723,7 +728,7 @@ declare const actions: readonly [{
723
728
  readonly idempotent: true;
724
729
  readonly reversible: true;
725
730
  readonly destructive: false;
726
- readonly humanPrerequisites: readonly ["A human must establish the builder credential with xeer auth login."];
731
+ readonly humanPrerequisites: readonly [string];
727
732
  readonly pathPolicy: "project-or-url";
728
733
  readonly surfaces: {
729
734
  readonly cli: true;
@@ -25,6 +25,11 @@ const SERVICE_CREDENTIALS = 'Service credential issuance and revocation are inte
25
25
  const DESTRUCTIVE_STATE = 'Destructive state replacement requires an explicit CLI invocation.';
26
26
  const PREVIEW_ONLY = 'MCP exposes a separate preview-only deploy action; direct production deploy stays CLI-only.';
27
27
  const OPERATOR_ONLY = 'MCP promotion is a separate action available only when the server starts in operator profile.';
28
+ // Both ways an invocation comes to hold a builder credential, written once because it is one rule:
29
+ // either a person signed in here, or a person issued the service token this environment presents.
30
+ // Neither branch produces a credential no human authorized, which is what the prerequisite is for.
31
+ const BUILDER_CREDENTIAL = 'A human must establish the builder credential with xeer auth login, '
32
+ + 'or issue the service token supplied in XEER_SERVICE_TOKEN.';
28
33
  const PROJECT_DIRECTORY_INPUT = {
29
34
  description: 'Project directory. Relative paths resolve against the server root; defaults to it.',
30
35
  type: 'string',
@@ -86,8 +91,10 @@ const MCP_PRESENTATION = {
86
91
  + 'Every template checks, tests, and builds clean, so use one as the starting point rather '
87
92
  + 'than writing a manifest by hand. "notes" (the default) and "todo" are per-user apps, "blog" '
88
93
  + 'is public to read and private to write, and "personal-site" has no database at all. None of '
89
- + 'them scaffolds sign-in UI. result is { directory, name, template, files }; an unknown '
90
- + 'template is XE3002 and writes nothing.',
94
+ + 'them scaffolds sign-in UI. "ui" selects the UI provider independently of the template — '
95
+ + '"preact" (the default) or "react" — and changes the manifest rather than any source file. '
96
+ + 'result is { directory, name, template, ui, files }; an unknown template is XE3002, an '
97
+ + 'unknown ui is XE3003, and either writes nothing.',
91
98
  },
92
99
  doctor: {
93
100
  mcpTitle: 'Diagnose the Xeer toolchain',
@@ -197,8 +204,11 @@ const actions = [
197
204
  id: 'new', command: ['new'], summary: 'Create a new project from a supported scaffold.',
198
205
  description: 'Creates a complete project that checks, tests, and builds clean. Templates do not '
199
206
  + 'scaffold sign-in UI: every visitor already has a verified identity, and the generated README '
200
- + 'explains how to opt in to a persistent account.',
201
- usage: ['new <directory> [--template {{templates}}] [--json]'], helpOrder: 30,
207
+ + 'explains how to opt in to a persistent account. `--template` and `--ui` are orthogonal: the '
208
+ + 'template decides what the app does, the UI provider decides which renderer the identical '
209
+ + 'client sources compile against. `result.template` and `result.ui` report both, so neither '
210
+ + 'has to be inferred from the written files.',
211
+ usage: ['new <directory> [--template {{templates}}] [--ui preact|react] [--json]'], helpOrder: 30,
202
212
  outputProtocol: 'xeer.command.v0', effects: ['write-source'], idempotent: false,
203
213
  reversible: true, destructive: false, humanPrerequisites: [], pathPolicy: 'project-relative',
204
214
  surfaces: {
@@ -214,6 +224,11 @@ const actions = [
214
224
  description: 'Which scaffold to write. Defaults to notes.', type: 'string',
215
225
  enum: ['notes', 'todo', 'blog', 'personal-site'],
216
226
  },
227
+ ui: {
228
+ description: 'Which UI provider the written manifest selects. Defaults to preact, and '
229
+ + 'omitting it writes no client block at all. Orthogonal to template.',
230
+ type: 'string', enum: ['preact', 'react'],
231
+ },
217
232
  },
218
233
  required: ['directory'],
219
234
  },
@@ -275,7 +290,7 @@ const actions = [
275
290
  outputProtocol: 'xeer.command.v0',
276
291
  effects: ['read-source', 'write-generated', 'run-local', 'network-read', 'network-write', 'production-change'],
277
292
  idempotent: false, reversible: true, destructive: false,
278
- humanPrerequisites: ['A human must establish the builder credential with xeer auth login.'],
293
+ humanPrerequisites: [BUILDER_CREDENTIAL],
279
294
  pathPolicy: 'project-relative', surfaces: { cli: true, mcpExclusion: PREVIEW_ONLY },
280
295
  },
281
296
  {
@@ -295,7 +310,7 @@ const actions = [
295
310
  usage: [], outputProtocol: 'xeer.command.v0',
296
311
  effects: ['read-source', 'write-generated', 'run-local', 'network-read', 'network-write'],
297
312
  idempotent: false, reversible: true, destructive: false,
298
- humanPrerequisites: ['A human must establish the builder credential with xeer auth login.'],
313
+ humanPrerequisites: [BUILDER_CREDENTIAL],
299
314
  pathPolicy: 'project-relative', surfaces: {
300
315
  cli: false, mcpTool: 'xeer_deploy_preview', mcpProfiles: ['author', 'operator'],
301
316
  ...MCP_PRESENTATION.deploy,
@@ -391,7 +406,7 @@ const actions = [
391
406
  helpOrder: 225, outputProtocol: 'xeer.tunnel.cli.v0',
392
407
  effects: ['run-local', 'network-read', 'network-write'], idempotent: false,
393
408
  reversible: true, destructive: false,
394
- humanPrerequisites: ['A human must sign in and deliberately keep the public tunnel process running.'],
409
+ humanPrerequisites: [BUILDER_CREDENTIAL, 'A human must deliberately keep the public tunnel process running.'],
395
410
  pathPolicy: 'none', surfaces: { cli: true, mcpExclusion: NOT_EXPOSED_V0 },
396
411
  },
397
412
  {
@@ -456,7 +471,7 @@ const actions = [
456
471
  usage: ['deployments [app|directory] [--limit <n>] [--control-url <url>] [--json]'], helpOrder: 70,
457
472
  outputProtocol: 'xeer.command.v0', effects: ['network-read', 'read-state', 'secret-metadata'],
458
473
  idempotent: true, reversible: true, destructive: false,
459
- humanPrerequisites: ['A human must establish the builder credential with xeer auth login.'],
474
+ humanPrerequisites: [BUILDER_CREDENTIAL],
460
475
  pathPolicy: 'project-or-url', surfaces: { cli: true, mcpExclusion: NOT_EXPOSED_V0 },
461
476
  },
462
477
  {
@@ -12,7 +12,45 @@
12
12
  * catalogue disagree in either direction, so a new code cannot ship
13
13
  * undocumented and a retired code cannot linger here.
14
14
  */
15
- import { CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES, CLIENT_BUNDLE_ERROR_BUDGET_BYTES, CLIENT_IMPORT_POLICY, SERVER_IMPORT_POLICY, } from './import-policy.js';
15
+ import { CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES, CLIENT_BUNDLE_ERROR_BUDGET_BYTES, CLIENT_IMPORT_POLICY, CLIENT_RUNTIME_PROVIDERS, SERVER_IMPORT_POLICY, clientImportPolicy, } from './import-policy.js';
16
+ /**
17
+ * The client zone's managed renderer surface, stated for every provider, derived from the policies
18
+ * rather than written out.
19
+ *
20
+ * A catalogue entry is static text answering a question that arrives with no project attached:
21
+ * `xeer diagnostics XE1202` is handed a code and nothing else, and the agent reference is rendered
22
+ * offline by `pnpm generate:agent-reference`. Neither can know which provider an application
23
+ * selected, so an entry that describes one of them describes the wrong one half the time — and the
24
+ * sentence this replaced named Preact alone, which under the React provider is an accurate account
25
+ * of the policy the application is *not* under.
26
+ *
27
+ * The diagnostic a compile actually emits does better and should: `zoneRejectionHint` and
28
+ * `foreignFamilyHint` build its `hint` from `clientImportPolicy(provider)` at the point of refusal,
29
+ * so an agent reading the refusal itself already gets the selected provider's rule. This is the
30
+ * fallback surface an agent reaches when it asks about the code alone.
31
+ */
32
+ const MANAGED_RENDERER_SURFACE = CLIENT_RUNTIME_PROVIDERS.map((provider) => {
33
+ const policy = clientImportPolicy(provider);
34
+ const anchors = policy.managedFamilies.flatMap((family) => [...family.anchorPackages]);
35
+ const aliases = policy.managedFamilies.flatMap((family) => [...family.compatAliases.values()]);
36
+ // One alias target names the whole compatibility surface: every React-ecosystem specifier under
37
+ // Preact lands on a subpath of it, and restating each mapping here would restate the alias table.
38
+ const compat = aliases.length === 0 ? ''
39
+ : `, with the React-ecosystem specifiers aliased onto ${aliases[0].split('/').slice(0, 2).join('/')}`;
40
+ const foreign = policy.foreignFamilies.flatMap((family) => [...family.anchorPackages]);
41
+ const refused = foreign.length === 0 ? ''
42
+ : `, and ${prose(foreign)} refused as the unselected renderer`;
43
+ const surface = anchors.length === 1
44
+ ? `${anchors[0]} with its supported entrypoints`
45
+ : `${prose(anchors)} with their supported entrypoints`;
46
+ return `under ${provider}, ${surface}${compat}${refused}`;
47
+ }).join('; ');
48
+ /** A list as a sentence reads it: "a", "a and b", "a, b and c". */
49
+ function prose(items) {
50
+ if (items.length < 2)
51
+ return items.join('');
52
+ return `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`;
53
+ }
16
54
  export const DIAGNOSTIC_FAMILIES = [
17
55
  {
18
56
  prefix: 'XE00',
@@ -156,8 +194,8 @@ export const DIAGNOSTIC_DEFINITIONS = [
156
194
  + 'source, or a package family the other zone owns — the renderer (preact, react, react-dom, '
157
195
  + 'scheduler) in the server zone. It is not reported for an ordinary npm package in either zone: '
158
196
  + 'both admit any declared and installed dependency.', `The client zone admits ${CLIENT_IMPORT_POLICY.platformModules.join(', ')} and the `
159
- + 'platform-managed renderer surface (preact and its supported entrypoints, plus '
160
- + 'React-ecosystem imports aliased onto preact/compat); the server zone admits '
197
+ + `platform-managed renderer surface, which is whichever provider client.runtime.provider `
198
+ + `selects — ${MANAGED_RENDERER_SURFACE}; the server zone admits `
161
199
  + `${SERVER_IMPORT_POLICY.platformModules.join(', ')}. Both zones additionally admit any npm `
162
200
  + 'package declared in package.json dependencies and installed. Node builtins and native addons '
163
201
  + 'are never importable anywhere: the client runs in a browser and the server runs in workerd, '
@@ -187,6 +225,36 @@ export const DIAGNOSTIC_DEFINITIONS = [
187
225
  + 'type-checks in every zone, but only the client bundler has a loader that turns one into a URL.', 'Import images, fonts, and wasm only from client modules; the server bundle has no asset stage. '
188
226
  + 'A server handler that needs the bytes should read them from public/ or receive the URL from '
189
227
  + 'the client.', CHECKED_BY_EVERY_COMPILE),
228
+ define('XE1210', 'package.json declares a package the platform provides — the renderer selected by '
229
+ + '`client.runtime.provider`, or one of the React-family names that resolve to it. The '
230
+ + 'declaration has no effect on what the application bundles: every one of those specifiers is '
231
+ + 'pinned to the platform\'s copy, for application code and for dependencies alike. A warning '
232
+ + 'rather than an error, so an application that already carries the declaration keeps building.', 'Remove the package from "dependencies". A library that peer-depends on the renderer is already '
233
+ + 'satisfied by the platform copy, so the declaration buys nothing — and it gives the package '
234
+ + 'manager a second copy to reconcile, which is how an unrelated later install starts failing.', CHECKED_BY_EVERY_COMPILE),
235
+ define('XE1211', 'The renderer a package manager resolves for this project is a different version '
236
+ + 'from the one the platform bundles. The message names both versions and which of them ships. '
237
+ + 'A second copy usually arrives when a package manager hoists an older peer of some dependency '
238
+ + 'to the project root; nothing in the application selected it, and nothing in the application '
239
+ + 'is served by it.', 'Nothing is required — the artifact contains the platform copy either way. To make the tree '
240
+ + 'agree with the artifact, remove any renderer package from "dependencies" and reinstall.', CHECKED_BY_EVERY_COMPILE),
241
+ define('XE1212', 'xeer.app.json acknowledges a dependency as untyped that package.json does not '
242
+ + 'declare in dependencies. The acknowledgment describes the type declarations of a package this '
243
+ + 'application never said it uses, so either the declaration is missing or the acknowledgment '
244
+ + 'outlived the dependency it was written for.', 'Declare the package in package.json "dependencies" if the application imports it, or remove it '
245
+ + 'from "untypedDependencies" in xeer.app.json if it does not.', CHECKED_BY_EVERY_COMPILE),
246
+ define('XE1213', 'xeer.app.json acknowledges a dependency as untyped, but it already resolves to '
247
+ + 'TypeScript declarations — its own, or a separately installed @types companion. The '
248
+ + 'acknowledgment is ignored rather than applied, because generating an ambient declaration for '
249
+ + 'it would not be redundant: an ambient declaration overrides module resolution, so it would '
250
+ + 'replace real declarations with `any` and a call with the wrong argument types would compile '
251
+ + 'clean. The real declarations still apply.', 'Remove the package from "untypedDependencies" in xeer.app.json. Its own declarations are what '
252
+ + 'the application is being checked against either way.', CHECKED_BY_EVERY_COMPILE),
253
+ define('XE1214', 'xeer.app.json acknowledges a dependency as shipping no TypeScript declarations, '
254
+ + 'so it and every subpath under it are typed as `any`. Informational, and emitted on every '
255
+ + 'check for as long as the acknowledgment stands: the acknowledgment is a deliberate hole in '
256
+ + 'type safety, and one that is never reported is one nobody removes.', 'Nothing is required. If declarations are published — conventionally at @types/<name>, with a '
257
+ + 'scope flattened as @types/scope__name — install them and remove the acknowledgment.', CHECKED_BY_EVERY_COMPILE),
190
258
  define('XE1300', 'The default server export is not a statically inspectable defineServer({...}) call, '
191
259
  + 'or an operation group is not a literal object.', 'Export `default defineServer({ queries: {...}, mutations: {...}, endpoints: {...} })` with literal '
192
260
  + 'object members: no spreads, shorthand, computed keys, or wrappers.', CHECKED_BY_EVERY_COMPILE),
@@ -210,9 +278,11 @@ export const DIAGNOSTIC_DEFINITIONS = [
210
278
  + '`budgets.clientBundleBytes` when declared. The message attributes bytes to the packages that '
211
279
  + 'contributed them.', 'Read the attribution in the message and remove or replace the heaviest dependency, or raise '
212
280
  + '`budgets.clientBundleBytes` (bounded by the 10 MiB module ceiling) if the size is intended.', BUILT_BY_EVERY_BUILD),
213
- define('XE1406', 'The minified client JavaScript bundle exceeds the fixed '
214
- + `${Math.round(CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES / 1024)} KiB advisory tier. The build still `
215
- + 'succeeds; this is a warning with per-package byte attribution.', 'Nothing is required. If the growth is unintended, the attribution in the message names the '
281
+ define('XE1406', 'The application\'s own share of the minified client JavaScript bundle exceeds '
282
+ + `the fixed ${Math.round(CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES / 1024)} KiB advisory tier — the `
283
+ + 'bundle minus the platform-selected renderer, which an application neither declares nor can '
284
+ + 'remove. The build still succeeds; this is a warning with per-package byte attribution. The '
285
+ + 'error tier (XE1405) is measured over the whole bundle instead.', 'Nothing is required. If the growth is unintended, the attribution in the message names the '
216
286
  + 'packages to reconsider before the error tier is reached.', BUILT_BY_EVERY_BUILD),
217
287
  define('XE1501', 'Bundling failed after the module graph and types were accepted.', 'Read the bundler message in `message`. It usually names a syntax construct the target does not '
218
288
  + 'support, rather than a Xeer rule.', BUILT_BY_EVERY_BUILD),
@@ -224,11 +294,15 @@ export const DIAGNOSTIC_DEFINITIONS = [
224
294
  + 'Neither zone has Node builtins to offer, so the platform refuses the bundle rather than '
225
295
  + 'shipping one that throws at load time. This is a property of the dependency chain and so is '
226
296
  + 'found at build, not at check.', BUILT_BY_EVERY_BUILD),
227
- define('XE1503', 'The client bundle would contain a second physical copy of the managed renderer. '
228
- + 'Bare renderer imports are pinned to the platform anchor, so a second copy means a path-based '
229
- + 'escape: a relative or absolute import reaching into some node_modules copy of the renderer.', 'Import the renderer by its bare specifier (preact, preact/hooks, react, …) so the platform pins '
230
- + 'it to one instance. Two renderer copies means two options singletons — hooks and components '
231
- + 'silently stop sharing state.',
297
+ define('XE1503', 'The client bundle would contain a renderer it must not: a second physical copy '
298
+ + 'of the one the application selected, or the one it did not. Bare renderer imports are pinned '
299
+ + 'to the platform anchor, so a second copy means a path-based escape — a relative or absolute '
300
+ + 'import reaching into some node_modules copy of the renderer. The unselected renderer is '
301
+ + 'installed by the platform whichever provider an application chooses, so only this rule keeps '
302
+ + 'it out of the bundle.', 'Import the renderer by its bare specifier (preact, preact/hooks, react, …) so the platform pins '
303
+ + 'it to one instance, and import only the renderer client.runtime.provider selects. Two copies '
304
+ + 'of one renderer means two options singletons — hooks and components silently stop sharing '
305
+ + 'state; two different renderers means two reconcilers rendering into one tree.',
232
306
  // The analyzer admits path imports against the managed-renderer roots, so the escape is reported
233
307
  // at the user's own import during `check`; the build's metafile verification reports the same
234
308
  // code for the same defect one stage later, when it survives as a second bundled copy.
@@ -240,6 +314,10 @@ export const DIAGNOSTIC_DEFINITIONS = [
240
314
  define('XE1604', 'The manifest could not be watched for changes, so edits to it will not rebuild the '
241
315
  + 'preview. Everything already serving keeps serving.', 'On Linux this is normally an exhausted inotify allowance: raise `fs.inotify.max_user_watches` and '
242
316
  + '`fs.inotify.max_user_instances`. Restart `xeer dev` afterwards.', ['dev']),
317
+ define('XE1605', 'A rebuild changed `client.runtime` — the UI provider — under a running dev server. '
318
+ + 'The preview keeps serving the renderer it started with rather than serving the new manifest '
319
+ + 'through the old one.', 'Stop and restart `xeer dev`. The dev server resolves its JSX runtime, its renderer aliases, and '
320
+ + 'its Fast Refresh transform once, at startup; `xeer build` and `xeer preview` need no restart.', ['dev']),
243
321
  // `xeer build` runs the same verification `preview`, `test` and `deploy` gate on, against the
244
322
  // artifact it has just written, so these four codes are build surfaces too: a build that cannot
245
323
  // be previewed is reported as a failed build rather than a success (issue #56).
@@ -322,6 +400,9 @@ export const DIAGNOSTIC_DEFINITIONS = [
322
400
  define('XE3002', '`--template` named a scaffold that does not exist. Refused before the target '
323
401
  + 'directory is read, so nothing was written.', 'Use one of the names the message lists, or omit --template for the default. `xeer --help` '
324
402
  + 'describes each template.', ['new']),
403
+ define('XE3003', '`--ui` named a UI provider that does not exist. Refused before the target '
404
+ + 'directory is read, so nothing was written.', 'Use preact or react, or omit --ui for the default (preact). The choice is orthogonal to '
405
+ + '--template: every template scaffolds on either provider from the same client sources.', ['new']),
325
406
  define('XE3101', 'Agent setup check found one or more generated files missing or stale. No files were written.', 'Run `xeer agent setup`, then repeat `xeer agent setup --check --json`.', ['agent']),
326
407
  define('XE3102', 'Agent setup found a path owned by the user or another tool. The entire write was refused.', 'Move, rename, or deliberately remove the conflicting path; setup never overwrites an unowned file.', ['agent']),
327
408
  define('XE3103', '`--target` named an agent adapter that Xeer does not support.', 'Use auto, agents, claude, codex, cursor, vscode, or mcp.', ['agent']),
@@ -330,6 +411,9 @@ export const DIAGNOSTIC_DEFINITIONS = [
330
411
  define('XE5000', 'An auth subcommand was invoked with wrong arguments.', 'Use `xeer auth <login|status|logout|as|clear>`; `auth as` takes alice or bob.', ['auth']),
331
412
  define('XE5001', 'The --control-url value is not an exact HTTP(S) origin, or is plain HTTP off localhost.', 'Pass an origin such as https://control.example.com with no path.', ['auth', 'deploy']),
332
413
  define('XE5002', 'No valid builder credential is stored.', 'A human must run `xeer auth login` and approve the shown code. An agent cannot complete sign-in.', ['auth', 'deploy']),
414
+ define('XE5003', 'XEER_SERVICE_TOKEN is set to something that is not a service token, so no command '
415
+ + 'that authenticates can present a credential. The value is never echoed; it is a live secret.', 'Set it to `xst_` followed by 43 characters — `xeer token create --name <label>` issues one — or '
416
+ + 'unset it to fall back to the credential `xeer auth login` stored on this machine.', ['auth', 'deploy']),
333
417
  define('XE5004', 'The control plane returned a response the CLI will not trust.', 'Retry; if it persists the control plane is misconfigured or unreachable. Not a project defect.', ['auth']),
334
418
  define('XE5005', 'The device authorization expired before sign-in completed.', 'Run `xeer auth login` again and approve promptly.', ['auth']),
335
419
  define('XE5008', 'The stored CLI credential file is unreadable or invalid.', 'Run `xeer auth logout` and sign in again.', ['auth', 'deploy']),
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The editor settings a scaffolded application carries.
3
+ *
4
+ * Separate from the type-check profile beside it, and the split is about what each answers. That
5
+ * module states the compiler *options* both tools enforce; this one states which tsserver binary the
6
+ * editor runs them with. `tsconfig.json` already makes the editor and `xeer check` apply the same
7
+ * rules — this is what makes them apply those rules with the same compiler, which matters because
8
+ * TypeScript changes inference, narrowing, and its check set in every minor.
9
+ *
10
+ * The settings file is only half of that. An editor can only offer a workspace TypeScript that
11
+ * exists, and under pnpm's isolated layout `node_modules/typescript` exists *only* because the
12
+ * application declares `typescript` as a direct devDependency. Without that declaration the path
13
+ * below names nothing.
14
+ *
15
+ * Both spellings of both settings, because the names moved. VS Code renamed `typescript.tsdk` and
16
+ * `typescript.enablePromptUseWorkspaceTsdk` to `js/ts.tsdk.path` and
17
+ * `js/ts.tsdk.promptToUseWorkspaceVersion`, keeping a deprecation alias — so the pairs cannot
18
+ * disagree — while the forks lag the rename. Writing one pair alone either leaves a deprecation
19
+ * squiggle in current VS Code or leaves the setting inert in a fork.
20
+ *
21
+ * Serialized here rather than returned as an object, for the same reason `applicationTsconfigDocument`
22
+ * is: what has to match is the file, and two callers stringifying one object with different options
23
+ * produce two different files.
24
+ */
25
+ export declare const APPLICATION_TSDK_PATH: "node_modules/typescript/lib";
26
+ export declare function vscodeSettingsDocument(): string;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The editor settings a scaffolded application carries.
3
+ *
4
+ * Separate from the type-check profile beside it, and the split is about what each answers. That
5
+ * module states the compiler *options* both tools enforce; this one states which tsserver binary the
6
+ * editor runs them with. `tsconfig.json` already makes the editor and `xeer check` apply the same
7
+ * rules — this is what makes them apply those rules with the same compiler, which matters because
8
+ * TypeScript changes inference, narrowing, and its check set in every minor.
9
+ *
10
+ * The settings file is only half of that. An editor can only offer a workspace TypeScript that
11
+ * exists, and under pnpm's isolated layout `node_modules/typescript` exists *only* because the
12
+ * application declares `typescript` as a direct devDependency. Without that declaration the path
13
+ * below names nothing.
14
+ *
15
+ * Both spellings of both settings, because the names moved. VS Code renamed `typescript.tsdk` and
16
+ * `typescript.enablePromptUseWorkspaceTsdk` to `js/ts.tsdk.path` and
17
+ * `js/ts.tsdk.promptToUseWorkspaceVersion`, keeping a deprecation alias — so the pairs cannot
18
+ * disagree — while the forks lag the rename. Writing one pair alone either leaves a deprecation
19
+ * squiggle in current VS Code or leaves the setting inert in a fork.
20
+ *
21
+ * Serialized here rather than returned as an object, for the same reason `applicationTsconfigDocument`
22
+ * is: what has to match is the file, and two callers stringifying one object with different options
23
+ * produce two different files.
24
+ */
25
+ export const APPLICATION_TSDK_PATH = 'node_modules/typescript/lib';
26
+ export function vscodeSettingsDocument() {
27
+ return `${JSON.stringify({
28
+ 'js/ts.tsdk.path': APPLICATION_TSDK_PATH,
29
+ 'js/ts.tsdk.promptToUseWorkspaceVersion': true,
30
+ 'typescript.tsdk': APPLICATION_TSDK_PATH,
31
+ 'typescript.enablePromptUseWorkspaceTsdk': true,
32
+ }, null, 2)}\n`;
33
+ }