werkmeister 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -44,7 +44,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
44
44
  var define_SANDBOX_BUILD_default;
45
45
  var init_define_SANDBOX_BUILD = __esm({
46
46
  "<define:__SANDBOX_BUILD__>"() {
47
- define_SANDBOX_BUILD_default = { sha: "5503d8809006bd32e3b203187be0e307fe0292ff", dirty: false };
47
+ define_SANDBOX_BUILD_default = { sha: "8bf0338bcc3351a5e1154beba68c1b6f9beea71a", dirty: false };
48
48
  }
49
49
  });
50
50
 
@@ -13276,7 +13276,7 @@ function writeWorkspaceSettings(workspaceRoot) {
13276
13276
  writeWorkspaceModel(workspaceRoot, readModel(workspaceRoot));
13277
13277
  writeAutoStopHook(workspaceRoot, readAutoStop(workspaceRoot));
13278
13278
  }
13279
- var _HOOK_MARKER, _GATE_MARKER, _PR_GUARD_MARKER, _AUTO_STOP_MARKER, _SKILLS_SELF_HEAL, SESSION_START_COMMAND, PRE_TOOL_USE_GATE_COMMAND, PR_GUARD_COMMAND, SESSION_END_COMMAND, _SESSION_END_TIMEOUT_S, READ_ONLY_GIT_RULES, AUTONOMOUS_RULES, AUTONOMOUS_DENY, permissionsRecord, _strings;
13279
+ var _HOOK_MARKER, _GATE_MARKER, _PR_GUARD_MARKER, _AUTO_STOP_MARKER, _SKILLS_SELF_HEAL, SESSION_START_COMMAND, PRE_TOOL_USE_GATE_COMMAND, PR_GUARD_COMMAND, SESSION_END_COMMAND, _SESSION_END_TIMEOUT_S, READ_ONLY_GIT_RULES, PLUGIN_MCP_PREFIXES, pluginTool, AUTONOMOUS_RULES, AUTONOMOUS_DENY, permissionsRecord, _strings;
13280
13280
  var init_hooks_gen = __esm({
13281
13281
  "../../packages/sandbox-core/dist/hooks_gen.js"() {
13282
13282
  "use strict";
@@ -13299,6 +13299,11 @@ var init_hooks_gen = __esm({
13299
13299
  "Bash(git status:*)",
13300
13300
  "Bash(git ls-files:*)"
13301
13301
  ];
13302
+ PLUGIN_MCP_PREFIXES = [
13303
+ "mcp__plugin_werkmeister_workspaces__",
13304
+ "mcp__plugin_sandbox-tools_sandbox-workspace__"
13305
+ ];
13306
+ pluginTool = (tool) => PLUGIN_MCP_PREFIXES.map((prefix) => `${prefix}${tool}`);
13302
13307
  AUTONOMOUS_RULES = [
13303
13308
  "Bash(git:*)",
13304
13309
  // `sandbox pr open` does the push and the PR; gh is read-only here.
@@ -13322,7 +13327,7 @@ var init_hooks_gen = __esm({
13322
13327
  "workspace-prs",
13323
13328
  "kube-context",
13324
13329
  "k8s-forwards-status"
13325
- ].map((tool) => `mcp__plugin_sandbox-tools_sandbox-workspace__${tool}`)
13330
+ ].flatMap(pluginTool)
13326
13331
  ];
13327
13332
  AUTONOMOUS_DENY = [
13328
13333
  ...[
@@ -13365,7 +13370,7 @@ var init_hooks_gen = __esm({
13365
13370
  "claude-send",
13366
13371
  "claude-resume",
13367
13372
  "sandbox-connect"
13368
- ].map((tool) => `mcp__plugin_sandbox-tools_sandbox-workspace__${tool}`)
13373
+ ].flatMap(pluginTool)
13369
13374
  ];
13370
13375
  permissionsRecord = (workspaceRoot) => path7.join(dotDir(workspaceRoot), "claude-permissions.json");
13371
13376
  _strings = (v) => Array.isArray(v) ? v.filter((r) => typeof r === "string") : [];
@@ -32507,7 +32512,7 @@ models:
32507
32512
  claude-sonnet-5: { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 }
32508
32513
  claude-haiku-4-5: { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.10 }
32509
32514
  `;
32510
- SANDBOX_MCP_SERVER = "sandbox";
32515
+ SANDBOX_MCP_SERVER = "werkmeister";
32511
32516
  REGISTRY_DEFAULTS = {
32512
32517
  archetypes: {
32513
32518
  "node-web": {
@@ -54253,7 +54258,7 @@ function cacheSet(key, v) {
54253
54258
  await fs45.writeFile(tmp, JSON.stringify(store), "utf-8");
54254
54259
  await fs45.rename(tmp, file);
54255
54260
  } catch (e) {
54256
- console.error(`[sandbox-workspace] cache write failed for ${key}:`, e.message);
54261
+ console.error(`[werkmeister] cache write failed for ${key}:`, e.message);
54257
54262
  }
54258
54263
  });
54259
54264
  writeChain = run34.catch(() => {
@@ -54266,7 +54271,7 @@ function runBatchOnce(keys, job) {
54266
54271
  return;
54267
54272
  for (const k of fresh)
54268
54273
  inFlight.add(k);
54269
- void Promise.resolve().then(() => job(fresh)).catch((e) => console.error("[sandbox-workspace] background cache refresh failed:", e.message)).finally(() => {
54274
+ void Promise.resolve().then(() => job(fresh)).catch((e) => console.error("[werkmeister] background cache refresh failed:", e.message)).finally(() => {
54270
54275
  for (const k of fresh)
54271
54276
  inFlight.delete(k);
54272
54277
  });
@@ -57378,13 +57383,13 @@ function loadRegistry(claudePluginsDir) {
57378
57383
  const plugins = typeof data === "object" && data !== null && !Array.isArray(data) ? data["plugins"] : void 0;
57379
57384
  return typeof plugins === "object" && plugins !== null && !Array.isArray(plugins) ? plugins : null;
57380
57385
  }
57381
- function installedPlugin(claudePluginsDir) {
57386
+ function installedPlugin(claudePluginsDir, name = PLUGIN_NAME) {
57382
57387
  const plugins = loadRegistry(claudePluginsDir);
57383
57388
  if (plugins === null) {
57384
57389
  return [null, null];
57385
57390
  }
57386
57391
  for (const [key, entries] of Object.entries(plugins)) {
57387
- if (!key.startsWith(`${PLUGIN_NAME}@`) || !Array.isArray(entries)) {
57392
+ if (!key.startsWith(`${name}@`) || !Array.isArray(entries)) {
57388
57393
  continue;
57389
57394
  }
57390
57395
  for (const entry of entries) {
@@ -57466,8 +57471,13 @@ function pluginDriftWarnings(repoPluginDir, claudePluginsDir) {
57466
57471
  }
57467
57472
  const [installedVersion2, installPath] = installedPlugin(claudePluginsDir);
57468
57473
  if (installPath === null) {
57474
+ if (installedPlugin(claudePluginsDir, LEGACY_PLUGIN_NAME)[1] !== null) {
57475
+ return [
57476
+ `the ${LEGACY_PLUGIN_NAME} plugin was renamed ${PLUGIN_NAME}, and only the old one is installed \u2014 its skills are now ${PLUGIN_NAME}:diagnose, ${PLUGIN_NAME}:status, ${PLUGIN_NAME}:workspace, \u2026 Run \`w9r setup\` to switch over.`
57477
+ ];
57478
+ }
57469
57479
  return [
57470
- `${PLUGIN_NAME} plugin is not installed \u2014 the sandbox-* ops skills (sandbox-diagnose, sandbox-status, sandbox-workspace, \u2026) will not surface in Claude Code sessions. Run \`sandbox setup\` to install it (or use /plugin in Claude Code). The sb-* skills are unaffected \u2014 they are projected into each workspace by init-workspace.`
57480
+ `${PLUGIN_NAME} plugin is not installed \u2014 the ops skills (${PLUGIN_NAME}:diagnose, ${PLUGIN_NAME}:status, ${PLUGIN_NAME}:workspace, \u2026) will not surface in Claude Code sessions. Run \`w9r setup\` to install it (or use /plugin in Claude Code). The sb-* skills are unaffected \u2014 they are projected into each workspace by init-workspace.`
57471
57481
  ];
57472
57482
  }
57473
57483
  const drift = skillDrift(path58.join(repoPluginDir, "skills"), path58.join(installPath, "skills"));
@@ -57483,14 +57493,15 @@ function pluginDriftWarnings(repoPluginDir, claudePluginsDir) {
57483
57493
  }
57484
57494
  return [`${lag}: ${drift.join("; ")} \u2014 ${REFRESH_HINT}.`];
57485
57495
  }
57486
- var PLUGIN_NAME, REFRESH_HINT;
57496
+ var PLUGIN_NAME, LEGACY_PLUGIN_NAME, REFRESH_HINT;
57487
57497
  var init_plugin_check = __esm({
57488
57498
  "../../packages/sandbox-core/dist/plugin_check.js"() {
57489
57499
  "use strict";
57490
57500
  init_define_SANDBOX_BUILD();
57491
57501
  init_config();
57492
- PLUGIN_NAME = "sandbox-tools";
57493
- REFRESH_HINT = "run `sandbox setup` to refresh it so sessions pick up the current sandbox-* ops skills";
57502
+ PLUGIN_NAME = "werkmeister";
57503
+ LEGACY_PLUGIN_NAME = "sandbox-tools";
57504
+ REFRESH_HINT = "run `w9r setup` to refresh it so sessions pick up the current werkmeister ops skills";
57494
57505
  }
57495
57506
  });
57496
57507
 
@@ -57629,6 +57640,53 @@ function briefOutput(out, maxLines = 4) {
57629
57640
  return out.trim().slice(0, 200);
57630
57641
  return lines.slice(0, maxLines).join("; ");
57631
57642
  }
57643
+ function retireLegacyPlugin(claudePluginsDir, runner, checkOnly) {
57644
+ const label = `plugin ${LEGACY_PLUGIN.name} (renamed ${PLUGIN_NAME})`;
57645
+ const installed = installedVersion(claudePluginsDir, LEGACY_PLUGIN) !== null;
57646
+ const marketplaceKnown = LEGACY_PLUGIN.marketplace in knownMarketplaces(claudePluginsDir);
57647
+ if (!installed && !marketplaceKnown)
57648
+ return [];
57649
+ if (checkOnly) {
57650
+ return [
57651
+ {
57652
+ label,
57653
+ ok: false,
57654
+ detail: `old name still set up; run \`w9r setup\` to switch to ${PLUGIN_NAME}`
57655
+ }
57656
+ ];
57657
+ }
57658
+ const steps = [];
57659
+ if (installed) {
57660
+ const [rc, out] = runner([
57661
+ "claude",
57662
+ "plugin",
57663
+ "uninstall",
57664
+ `${LEGACY_PLUGIN.name}@${LEGACY_PLUGIN.marketplace}`
57665
+ ]);
57666
+ steps.push({
57667
+ label,
57668
+ ok: rc === 0,
57669
+ detail: rc === 0 ? "uninstalled" : `uninstall failed: ${out}`
57670
+ });
57671
+ if (rc !== 0)
57672
+ return steps;
57673
+ }
57674
+ if (marketplaceKnown) {
57675
+ const [rc, out] = runner([
57676
+ "claude",
57677
+ "plugin",
57678
+ "marketplace",
57679
+ "remove",
57680
+ LEGACY_PLUGIN.marketplace
57681
+ ]);
57682
+ steps.push({
57683
+ label,
57684
+ ok: rc === 0,
57685
+ detail: rc === 0 ? `removed marketplace ${LEGACY_PLUGIN.marketplace}` : `marketplace remove failed: ${out}`
57686
+ });
57687
+ }
57688
+ return steps;
57689
+ }
57632
57690
  function workspaceRepoUrl(slug) {
57633
57691
  return `https://github.com/${slug}.git`;
57634
57692
  }
@@ -58378,7 +58436,7 @@ async function runSetup(options = {}) {
58378
58436
  const checkOnly = options.checkOnly ?? false;
58379
58437
  const reposRoot = options.reposRoot ?? getReposRoot();
58380
58438
  const claudePluginsDir = options.claudePluginsDir ?? path60.join(os18.homedir(), ".claude", "plugins");
58381
- const repoPluginDir = options.repoPluginDir ?? path60.join(sandboxRoot(), "plugins", "sandbox-tools");
58439
+ const repoPluginDir = options.repoPluginDir ?? path60.join(sandboxRoot(), "plugins", PLUGIN_NAME);
58382
58440
  const runner = options.runner ?? defaultRunner;
58383
58441
  const jira2 = options.jira ?? loadJira();
58384
58442
  const steps = [];
@@ -58393,15 +58451,19 @@ async function runSetup(options = {}) {
58393
58451
  steps.push({
58394
58452
  label: "claude CLI",
58395
58453
  ok: false,
58396
- detail: "not found on PATH \u2014 the sandbox-tools and ponytail plugins cannot be installed without it. Install Claude Code from https://claude.com/claude-code (the VS Code extension alone does not put `claude` on PATH), then re-run `sandbox setup`."
58454
+ detail: `not found on PATH \u2014 the ${PLUGIN_NAME} and ponytail plugins cannot be installed without it. Install Claude Code from https://claude.com/claude-code (the VS Code extension alone does not put \`claude\` on PATH), then re-run \`sandbox setup\`.`
58397
58455
  });
58398
58456
  } else {
58399
58457
  for (const spec of REQUIRED_PLUGINS) {
58400
58458
  let driftProbe = null;
58401
- if (spec.name === "sandbox-tools") {
58459
+ if (spec.name === PLUGIN_NAME) {
58402
58460
  driftProbe = () => pluginDriftWarnings(repoPluginDir, claudePluginsDir);
58403
58461
  }
58404
- steps.push(...syncPlugin(spec, claudePluginsDir, runner, checkOnly, driftProbe));
58462
+ const synced = syncPlugin(spec, claudePluginsDir, runner, checkOnly, driftProbe);
58463
+ steps.push(...synced);
58464
+ if (spec.name === PLUGIN_NAME && (checkOnly || synced.every((step) => step.ok))) {
58465
+ steps.push(...retireLegacyPlugin(claudePluginsDir, runner, checkOnly));
58466
+ }
58405
58467
  }
58406
58468
  for (const spec of OPTIONAL_PLUGINS) {
58407
58469
  steps.push(...syncOptionalPlugin(spec, claudePluginsDir, runner, checkOnly, options.installOptionalPlugins ?? false));
@@ -58432,7 +58494,7 @@ async function runSetup(options = {}) {
58432
58494
  steps.push(...syncVscodeExtension(checkOnly, options.installVscodeExtension ?? false, vscodeExtensionState(runner), runner));
58433
58495
  return steps;
58434
58496
  }
58435
- var REQUIRED_PLUGINS, OPTIONAL_PLUGINS, WORKSPACE_ROOT_REPO, isLogin, DEMO_SERVICES_REPO, DEMO_SERVICES_REPO_URL, workspaceRootSpec, DEMO_SERVICES_SPEC, LEGACY_CONFIG_DIR, JIRA_TOKEN_URL, JIRA_REQUIRED_KEYS, JIRA_CONFIG_SNIPPET, EDITOR_SCHEMAS, VSCODE_EXTENSION_ID, BUNDLED_VSIX_REL;
58497
+ var REQUIRED_PLUGINS, LEGACY_PLUGIN, OPTIONAL_PLUGINS, WORKSPACE_ROOT_REPO, isLogin, DEMO_SERVICES_REPO, DEMO_SERVICES_REPO_URL, workspaceRootSpec, DEMO_SERVICES_SPEC, LEGACY_CONFIG_DIR, JIRA_TOKEN_URL, JIRA_REQUIRED_KEYS, JIRA_CONFIG_SNIPPET, EDITOR_SCHEMAS, VSCODE_EXTENSION_ID, BUNDLED_VSIX_REL;
58436
58498
  var init_machine_setup = __esm({
58437
58499
  "../../packages/sandbox-core/dist/machine_setup.js"() {
58438
58500
  "use strict";
@@ -58449,11 +58511,11 @@ var init_machine_setup = __esm({
58449
58511
  init_test_run();
58450
58512
  REQUIRED_PLUGINS = [
58451
58513
  // This repo doubles as the marketplace: `.claude-plugin/marketplace.json` at
58452
- // the root serves `plugins/sandbox-tools`. `marketplace` must match the
58514
+ // the root serves `plugins/werkmeister`. `marketplace` must match the
58453
58515
  // `name` field in that manifest, or install resolves nothing.
58454
58516
  {
58455
- name: "sandbox-tools",
58456
- marketplace: "sandbox",
58517
+ name: "werkmeister",
58518
+ marketplace: "werkmeister",
58457
58519
  source: "jbbz-sandbox/werkmeister@main"
58458
58520
  },
58459
58521
  {
@@ -58462,6 +58524,11 @@ var init_machine_setup = __esm({
58462
58524
  source: "DietrichGebert/ponytail"
58463
58525
  }
58464
58526
  ];
58527
+ LEGACY_PLUGIN = {
58528
+ name: LEGACY_PLUGIN_NAME,
58529
+ marketplace: "sandbox",
58530
+ source: "jbbz-sandbox/werkmeister@main"
58531
+ };
58465
58532
  OPTIONAL_PLUGINS = [
58466
58533
  {
58467
58534
  // Not obra/superpowers directly: that repo's manifest names itself
@@ -58495,7 +58562,7 @@ var init_machine_setup = __esm({
58495
58562
  "services-fragment.schema.json": "**/.sandbox/services.yaml",
58496
58563
  "workspace.schema.json": "**/.sandbox/workspace.yml"
58497
58564
  };
58498
- VSCODE_EXTENSION_ID = "jbbz.vscode-plugin";
58565
+ VSCODE_EXTENSION_ID = "jbbz.werkmeister-vscode";
58499
58566
  BUNDLED_VSIX_REL = path60.join("dist", "sandbox-workspaces.vsix");
58500
58567
  }
58501
58568
  });
@@ -58575,14 +58642,19 @@ function writeWorkspaceMcp(workspaceRoot, serverNames, definitions, vars2 = {})
58575
58642
  delete servers[name];
58576
58643
  }
58577
58644
  }
58645
+ const legacy = servers[LEGACY_SERVER];
58646
+ if (legacy?.headers?.["X-Sandbox-Feature"] !== void 0)
58647
+ delete servers[LEGACY_SERVER];
58578
58648
  Object.assign(servers, wanted);
58579
58649
  fs53.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + "\n");
58580
58650
  return mcpPath;
58581
58651
  }
58652
+ var LEGACY_SERVER;
58582
58653
  var init_mcp_gen = __esm({
58583
58654
  "../../packages/sandbox-core/dist/mcp_gen.js"() {
58584
58655
  "use strict";
58585
58656
  init_define_SANDBOX_BUILD();
58657
+ LEGACY_SERVER = "sandbox";
58586
58658
  }
58587
58659
  });
58588
58660
 
@@ -63631,7 +63703,7 @@ import { execFileSync } from "node:child_process";
63631
63703
  import * as fs21 from "node:fs";
63632
63704
  import * as path22 from "node:path";
63633
63705
  var BUILD_STAMP = typeof define_SANDBOX_BUILD_default === "undefined" ? void 0 : define_SANDBOX_BUILD_default;
63634
- var REBUILD_COMMAND = "npm run build --workspace sandbox-core && npm run build --workspace apps/cli";
63706
+ var REBUILD_COMMAND = "npm run build --workspace werkmeister-core && npm run build --workspace apps/cli";
63635
63707
  function staleBuildWarning(build, repoRoot) {
63636
63708
  if (!build?.sha || !fs21.existsSync(path22.join(repoRoot, ".git"))) return null;
63637
63709
  let head;
@@ -64366,7 +64438,7 @@ ${_RED}Interrupted${_RESET}`));
64366
64438
  for (const [name, description] of [
64367
64439
  [
64368
64440
  "dashboard",
64369
- "Launch the workspace dashboard's MCP server over stdio (Claude Desktop, the sandbox-tools plugin)"
64441
+ "Launch the workspace dashboard's MCP server over stdio (Claude Desktop, the werkmeister plugin)"
64370
64442
  ],
64371
64443
  [
64372
64444
  "mcp",
package/dist/mcp.js CHANGED
@@ -83141,6 +83141,11 @@ var READ_ONLY_GIT_RULES = [
83141
83141
  "Bash(git status:*)",
83142
83142
  "Bash(git ls-files:*)"
83143
83143
  ];
83144
+ var PLUGIN_MCP_PREFIXES = [
83145
+ "mcp__plugin_werkmeister_workspaces__",
83146
+ "mcp__plugin_sandbox-tools_sandbox-workspace__"
83147
+ ];
83148
+ var pluginTool = (tool) => PLUGIN_MCP_PREFIXES.map((prefix) => `${prefix}${tool}`);
83144
83149
  var AUTONOMOUS_RULES = [
83145
83150
  "Bash(git:*)",
83146
83151
  // `sandbox pr open` does the push and the PR; gh is read-only here.
@@ -83164,7 +83169,7 @@ var AUTONOMOUS_RULES = [
83164
83169
  "workspace-prs",
83165
83170
  "kube-context",
83166
83171
  "k8s-forwards-status"
83167
- ].map((tool) => `mcp__plugin_sandbox-tools_sandbox-workspace__${tool}`)
83172
+ ].flatMap(pluginTool)
83168
83173
  ];
83169
83174
  function autonomousRules(feature2, services) {
83170
83175
  if (!feature2)
@@ -83223,7 +83228,7 @@ var AUTONOMOUS_DENY = [
83223
83228
  "claude-send",
83224
83229
  "claude-resume",
83225
83230
  "sandbox-connect"
83226
- ].map((tool) => `mcp__plugin_sandbox-tools_sandbox-workspace__${tool}`)
83231
+ ].flatMap(pluginTool)
83227
83232
  ];
83228
83233
  var permissionsRecord = (workspaceRoot) => path27.join(dotDir(workspaceRoot), "claude-permissions.json");
83229
83234
  function buildAllowRules(feature2, services, servicesConfig, archetypes) {
@@ -85906,8 +85911,9 @@ init_config();
85906
85911
  import * as fs39 from "node:fs";
85907
85912
  import * as os11 from "node:os";
85908
85913
  import * as path36 from "node:path";
85909
- var PLUGIN_NAME = "sandbox-tools";
85910
- var REFRESH_HINT = "run `sandbox setup` to refresh it so sessions pick up the current sandbox-* ops skills";
85914
+ var PLUGIN_NAME = "werkmeister";
85915
+ var LEGACY_PLUGIN_NAME = "sandbox-tools";
85916
+ var REFRESH_HINT = "run `w9r setup` to refresh it so sessions pick up the current werkmeister ops skills";
85911
85917
  function defaultRepoPluginDir() {
85912
85918
  return path36.join(sandboxRoot(), "plugins", PLUGIN_NAME);
85913
85919
  }
@@ -85936,13 +85942,13 @@ function loadRegistry(claudePluginsDir) {
85936
85942
  const plugins = typeof data === "object" && data !== null && !Array.isArray(data) ? data["plugins"] : void 0;
85937
85943
  return typeof plugins === "object" && plugins !== null && !Array.isArray(plugins) ? plugins : null;
85938
85944
  }
85939
- function installedPlugin(claudePluginsDir) {
85945
+ function installedPlugin(claudePluginsDir, name = PLUGIN_NAME) {
85940
85946
  const plugins = loadRegistry(claudePluginsDir);
85941
85947
  if (plugins === null) {
85942
85948
  return [null, null];
85943
85949
  }
85944
85950
  for (const [key, entries] of Object.entries(plugins)) {
85945
- if (!key.startsWith(`${PLUGIN_NAME}@`) || !Array.isArray(entries)) {
85951
+ if (!key.startsWith(`${name}@`) || !Array.isArray(entries)) {
85946
85952
  continue;
85947
85953
  }
85948
85954
  for (const entry of entries) {
@@ -86024,8 +86030,13 @@ function pluginDriftWarnings(repoPluginDir, claudePluginsDir) {
86024
86030
  }
86025
86031
  const [installedVersion, installPath] = installedPlugin(claudePluginsDir);
86026
86032
  if (installPath === null) {
86033
+ if (installedPlugin(claudePluginsDir, LEGACY_PLUGIN_NAME)[1] !== null) {
86034
+ return [
86035
+ `the ${LEGACY_PLUGIN_NAME} plugin was renamed ${PLUGIN_NAME}, and only the old one is installed \u2014 its skills are now ${PLUGIN_NAME}:diagnose, ${PLUGIN_NAME}:status, ${PLUGIN_NAME}:workspace, \u2026 Run \`w9r setup\` to switch over.`
86036
+ ];
86037
+ }
86027
86038
  return [
86028
- `${PLUGIN_NAME} plugin is not installed \u2014 the sandbox-* ops skills (sandbox-diagnose, sandbox-status, sandbox-workspace, \u2026) will not surface in Claude Code sessions. Run \`sandbox setup\` to install it (or use /plugin in Claude Code). The sb-* skills are unaffected \u2014 they are projected into each workspace by init-workspace.`
86039
+ `${PLUGIN_NAME} plugin is not installed \u2014 the ops skills (${PLUGIN_NAME}:diagnose, ${PLUGIN_NAME}:status, ${PLUGIN_NAME}:workspace, \u2026) will not surface in Claude Code sessions. Run \`w9r setup\` to install it (or use /plugin in Claude Code). The sb-* skills are unaffected \u2014 they are projected into each workspace by init-workspace.`
86029
86040
  ];
86030
86041
  }
86031
86042
  const drift = skillDrift(path36.join(repoPluginDir, "skills"), path36.join(installPath, "skills"));
@@ -86054,7 +86065,7 @@ import * as path37 from "node:path";
86054
86065
 
86055
86066
  // ../../packages/sandbox-core/dist/scaffold.js
86056
86067
  init_define_SANDBOX_BUILD();
86057
- var SANDBOX_MCP_SERVER = "sandbox";
86068
+ var SANDBOX_MCP_SERVER = "werkmeister";
86058
86069
  var REGISTRY_DEFAULTS = {
86059
86070
  archetypes: {
86060
86071
  "node-web": {
@@ -86338,6 +86349,7 @@ var BUNDLED_VSIX_REL = path39.join("dist", "sandbox-workspaces.vsix");
86338
86349
  init_define_SANDBOX_BUILD();
86339
86350
  import * as fs42 from "node:fs";
86340
86351
  import * as path40 from "node:path";
86352
+ var LEGACY_SERVER = "sandbox";
86341
86353
  function resolveWorkspaceMcpServers(presentArchetypes2, archetypes) {
86342
86354
  const names = /* @__PURE__ */ new Set();
86343
86355
  for (const archName of Object.keys(presentArchetypes2)) {
@@ -86410,6 +86422,9 @@ function writeWorkspaceMcp(workspaceRoot, serverNames, definitions, vars2 = {})
86410
86422
  delete servers[name];
86411
86423
  }
86412
86424
  }
86425
+ const legacy = servers[LEGACY_SERVER];
86426
+ if (legacy?.headers?.["X-Sandbox-Feature"] !== void 0)
86427
+ delete servers[LEGACY_SERVER];
86413
86428
  Object.assign(servers, wanted);
86414
86429
  fs42.writeFileSync(mcpPath, JSON.stringify(config2, null, 2) + "\n");
86415
86430
  return mcpPath;
@@ -89075,7 +89090,7 @@ function registerTools(server) {
89075
89090
  }
89076
89091
  function registerLifecycleTools(server) {
89077
89092
  server.registerTool(
89078
- "sandbox-up",
89093
+ "up",
89079
89094
  {
89080
89095
  title: "Bring a feature up",
89081
89096
  description: "Allocate the feature's slot, start its containers, and point the reverse proxy at them. Returns the slot, port range, local services and their URLs.",
@@ -89087,10 +89102,10 @@ function registerLifecycleTools(server) {
89087
89102
  })
89088
89103
  );
89089
89104
  server.registerTool(
89090
- "sandbox-down",
89105
+ "down",
89091
89106
  {
89092
89107
  title: "Tear a feature down",
89093
- description: "Leave the feature's k8s intercepts, remove its containers, and release its slot. Does not reload the reverse proxy \u2014 call sandbox-proxy-reload after tearing down.",
89108
+ description: "Leave the feature's k8s intercepts, remove its containers, and release its slot. Does not reload the reverse proxy \u2014 call proxy-reload after tearing down.",
89094
89109
  inputSchema: {
89095
89110
  ...FEATURE_ARG,
89096
89111
  removeVolumes: external_exports.boolean().optional().describe("Also remove the feature's named volumes. Default false.")
@@ -89107,10 +89122,10 @@ function registerLifecycleTools(server) {
89107
89122
  })
89108
89123
  );
89109
89124
  server.registerTool(
89110
- "sandbox-stop",
89125
+ "stop",
89111
89126
  {
89112
89127
  title: "Stop a feature's containers",
89113
- description: "Stop the containers, leaving them and the slot in place so sandbox-restart or sandbox-up can resume the feature.",
89128
+ description: "Stop the containers, leaving them and the slot in place so restart or up can resume the feature.",
89114
89129
  inputSchema: { ...FEATURE_ARG }
89115
89130
  },
89116
89131
  async (args, extra) => adapt(async () => ({
@@ -89118,7 +89133,7 @@ function registerLifecycleTools(server) {
89118
89133
  }))
89119
89134
  );
89120
89135
  server.registerTool(
89121
- "sandbox-restart",
89136
+ "restart",
89122
89137
  {
89123
89138
  title: "Restart a feature's containers",
89124
89139
  description: "Bounce the feature's containers, reusing its slot.",
@@ -89129,7 +89144,7 @@ function registerLifecycleTools(server) {
89129
89144
  }))
89130
89145
  );
89131
89146
  server.registerTool(
89132
- "sandbox-status",
89147
+ "status",
89133
89148
  {
89134
89149
  title: "Sandbox status",
89135
89150
  description: "Everything `sandbox status` knows: infrastructure containers, the host web servers, k8s forwards, every feature's slot and containers, and telepresence intercepts. Host-side, so the k8s forward health reported here is the real one.",
@@ -89141,7 +89156,7 @@ function registerLifecycleTools(server) {
89141
89156
  }))
89142
89157
  );
89143
89158
  server.registerTool(
89144
- "sandbox-detect",
89159
+ "detect",
89145
89160
  {
89146
89161
  title: "Generate a repo's service-registry fragment",
89147
89162
  description: "Scan a repo (package manifests, Dockerfiles, compose, Helm, k8s, kustomize) and propose its .sandbox/services.yaml. Returns the report, the proposed YAML and the questions the scan could not settle. Writes only with write: true. Answer questions by passing `answers` ({ item: <question id>, value, reason, files_read }); answers can only fill those questions.",
@@ -89189,7 +89204,7 @@ function registerLifecycleTools(server) {
89189
89204
  })
89190
89205
  );
89191
89206
  server.registerTool(
89192
- "sandbox-services",
89207
+ "services",
89193
89208
  {
89194
89209
  title: "Where a feature's services answer",
89195
89210
  description: "Every registered service and its endpoint for this feature \u2014 local container, k8s forward, or not configured.",
@@ -89202,7 +89217,7 @@ function registerLifecycleTools(server) {
89202
89217
  }))
89203
89218
  );
89204
89219
  server.registerTool(
89205
- "sandbox-logs",
89220
+ "logs",
89206
89221
  {
89207
89222
  title: "Read a feature's container logs",
89208
89223
  description: "A bounded read of `docker compose logs` for the feature, optionally one service. This is not a subscription: it never follows, and returns the last `tail` lines.",
@@ -89221,7 +89236,7 @@ function registerLifecycleTools(server) {
89221
89236
  })
89222
89237
  );
89223
89238
  server.registerTool(
89224
- "sandbox-remove",
89239
+ "remove",
89225
89240
  {
89226
89241
  title: "Drop a service from a feature",
89227
89242
  description: "Remove one service from the feature's local services so it falls back to k8s: regenerate the workspace files, restart (or stop) the containers, re-point the proxy.",
@@ -89238,7 +89253,7 @@ function registerLifecycleTools(server) {
89238
89253
  }))
89239
89254
  );
89240
89255
  server.registerTool(
89241
- "sandbox-test",
89256
+ "test",
89242
89257
  {
89243
89258
  title: "Run a feature's Playwright suite",
89244
89259
  description: "Run the feature's Playwright tests with SANDBOX_FEATURE set, so the suite carries the X-Feature routing cookie. Runs only when the workspace has a Playwright config; otherwise nothing runs and `message` lists each service's test command and validation guidance. A failing suite is a result (non-zero `status`), not an error.",
@@ -89260,7 +89275,7 @@ function registerLifecycleTools(server) {
89260
89275
  })
89261
89276
  );
89262
89277
  server.registerTool(
89263
- "sandbox-proxy-reload",
89278
+ "proxy-reload",
89264
89279
  {
89265
89280
  title: "Regenerate and reload the reverse proxy",
89266
89281
  description: "Rebuild the Caddyfile from the active features and hand it to Caddy, starting Caddy if it is down. Call this after tearing features down.",
@@ -89283,7 +89298,7 @@ var WORKSPACE_FIELDS = {
89283
89298
  };
89284
89299
  function registerAuthoringTools(server) {
89285
89300
  server.registerTool(
89286
- "sandbox-workspace",
89301
+ "workspace",
89287
89302
  {
89288
89303
  title: "Create a sandbox workspace",
89289
89304
  description: "Create a workspace: git worktrees on a <user>/<workspace> branch under the workspaces root, then init-workspace. Runs `createWorkspace` in this process; with an `issue_id` the issue is fetched and stored in `.sandbox/issue.md` (the create fails if it can't be read). Non-interactive \u2014 every wizard input is an argument here. Never opens VS Code.",
@@ -89302,7 +89317,7 @@ function registerAuthoringTools(server) {
89302
89317
  })
89303
89318
  );
89304
89319
  server.registerTool(
89305
- "sandbox-list-workspaces",
89320
+ "list-workspaces",
89306
89321
  {
89307
89322
  title: "List sandbox workspaces",
89308
89323
  description: "Every workspace directory under the workspaces root, with its path, issue ID, labels and VS Code URI. Not scoped to a feature \u2014 this is the whole root, and it lists workspaces that were never brought up.",
@@ -89318,12 +89333,12 @@ function registerAuthoringTools(server) {
89318
89333
  })
89319
89334
  );
89320
89335
  server.registerTool(
89321
- "sandbox-close-out",
89336
+ "close-out",
89322
89337
  {
89323
89338
  title: "End a workspace",
89324
89339
  description: "The one way to end a workspace. After every PR shipped: close the issue, write closeout.md, commit and push every branch, tear the feature down, delete the workspace directory and the merged code branches. With `abandon` (a reason) when work is unshipped: record the reason, leave the issue, push and keep every branch, then remove. Destructive, and NOT scoped to your feature \u2014 it names a workspace. Nothing is deleted if any branch cannot be pushed.",
89325
89340
  inputSchema: {
89326
- name: external_exports.string().describe("Workspace directory name, as sandbox-list-workspaces reports it."),
89341
+ name: external_exports.string().describe("Workspace directory name, as list-workspaces reports it."),
89327
89342
  abandon: external_exports.string().optional().describe(
89328
89343
  "Close out without shipping: why the work is abandoned. Recorded in closeout.md and the PR files."
89329
89344
  )
@@ -89342,7 +89357,7 @@ function registerAuthoringTools(server) {
89342
89357
  })
89343
89358
  );
89344
89359
  server.registerTool(
89345
- "sandbox-init-workspace",
89360
+ "init-workspace",
89346
89361
  {
89347
89362
  title: "Reconcile a workspace",
89348
89363
  description: `Re-run init-workspace against an existing workspace: reconcile worktrees, regenerate CLAUDE.md, .env, ${COMPOSE_FILE}, skills, agents, hooks and .mcp.json from .sandbox/workspace.yml plus any arguments given here.`,
@@ -89356,7 +89371,7 @@ function registerAuthoringTools(server) {
89356
89371
  })
89357
89372
  );
89358
89373
  server.registerTool(
89359
- "sandbox-skills",
89374
+ "skills",
89360
89375
  {
89361
89376
  title: "Check or sync a workspace's context layer",
89362
89377
  description: "`check` reports drift between the workspace's context layer and a fresh rendering; `sync` rewrites what drifted. The layer is the workspace's `context_strategy` (jit: sb-* skills and gate manifest; icm: standards and stage contracts).",
@@ -89373,7 +89388,7 @@ function registerAuthoringTools(server) {
89373
89388
  })
89374
89389
  );
89375
89390
  server.registerTool(
89376
- "sandbox-standards",
89391
+ "standards",
89377
89392
  {
89378
89393
  title: "Validate the standards tree",
89379
89394
  description: "Run every structural validator over the configured standards tree. Errors come back as data \u2014 an empty `errors` with a non-zero `moduleCount` is a clean tree.",
@@ -89382,7 +89397,7 @@ function registerAuthoringTools(server) {
89382
89397
  async () => adapt(async () => ({ ...checkStandards() }))
89383
89398
  );
89384
89399
  server.registerTool(
89385
- "sandbox-hooks",
89400
+ "hooks",
89386
89401
  {
89387
89402
  title: "Refresh a workspace's context layer",
89388
89403
  description: "Refresh the workspace's context layer the way `sandbox up` does: jit re-merges its SessionStart and PreToolUse hooks into .claude/settings.json; icm removes any sandbox-managed hooks. Never touches hooks it does not own.",
@@ -89397,7 +89412,7 @@ function registerAuthoringTools(server) {
89397
89412
  })
89398
89413
  );
89399
89414
  server.registerTool(
89400
- "sandbox-notes",
89415
+ "notes",
89401
89416
  {
89402
89417
  title: "Read or graduate a workspace's notes",
89403
89418
  description: "`context` renders the session-start standards + notes block. `list` returns the workspace's notes. `graduate` scaffolds a decision note into a standards domain \u2014 domain and kind must be supplied, because the CLI's prompts are not available here.",
@@ -89444,7 +89459,7 @@ function registerAuthoringTools(server) {
89444
89459
  }
89445
89460
  function registerHostTools(server) {
89446
89461
  server.registerTool(
89447
- "sandbox-connect",
89462
+ "connect",
89448
89463
  {
89449
89464
  title: "Start shared infrastructure",
89450
89465
  description: "Bring up the shared infra every feature depends on: generated proxy files, the corporate CA, the compose stack (caddy, k8s forwards, jaeger) and the host web servers. Host-wide, not scoped to your feature.",
@@ -89460,7 +89475,7 @@ function registerHostTools(server) {
89460
89475
  })
89461
89476
  );
89462
89477
  server.registerTool(
89463
- "sandbox-open",
89478
+ "open",
89464
89479
  {
89465
89480
  title: "Open a feature-tagged browser window",
89466
89481
  description: "Launch a browser window on the HOST, pre-configured with the feature's X-Feature routing cookie and tagged so it is unmistakably this feature's window. The window outlives this call; it closes when the user closes it.",
@@ -89500,7 +89515,7 @@ function registerHostTools(server) {
89500
89515
  })
89501
89516
  );
89502
89517
  server.registerTool(
89503
- "sandbox-intercept",
89518
+ "intercept",
89504
89519
  {
89505
89520
  title: "Start or leave a k8s traffic intercept",
89506
89521
  description: "Route the slice of live k8s dev traffic carrying `x-feature: <feature>` to this feature's local container, or stop doing so. Runs host-side, where the telepresence root daemon lives \u2014 with exactly the authority a host terminal has.",
@@ -89540,7 +89555,7 @@ function registerHostTools(server) {
89540
89555
 
89541
89556
  // ../mcp/src/main.ts
89542
89557
  function createServer2() {
89543
- const server = new McpServer({ name: "sandbox", version: "0.1.0" });
89558
+ const server = new McpServer({ name: "werkmeister", version: "0.1.0" });
89544
89559
  registerTools(server);
89545
89560
  return server;
89546
89561
  }
Binary file
@@ -26,7 +26,7 @@
26
26
  "autonomous": {
27
27
  "type": "boolean",
28
28
  "default": false,
29
- "description": "icm: run stage 01 to `sandbox pr open` with self-checks instead of human checks. Every strategy: add the Bash and sandbox-workspace MCP allow rules a headless session needs to .claude/settings.json (recorded in .sandbox/claude-permissions.json, removed when this turns off)."
29
+ "description": "icm: run stage 01 to `sandbox pr open` with self-checks instead of human checks. Every strategy: add the Bash and werkmeister workspaces MCP allow rules a headless session needs to .claude/settings.json (recorded in .sandbox/claude-permissions.json, removed when this turns off)."
30
30
  },
31
31
  "model": {
32
32
  "type": "string",
@@ -20,7 +20,7 @@ description: "Begin the test phase in a sandbox workspace. Use when running or w
20
20
  assertions with suspected causes, and open questions.
21
21
  - **Verifying the running feature.** The tester agents run a proxy smoke check (curl
22
22
  through Caddy with the `X-Feature` cookie) when the containers are up. For a headed
23
- browser session against the feature URL, use the `sandbox-tools:sandbox-feature-test`
23
+ browser session against the feature URL, use the `werkmeister:feature-test`
24
24
  plugin skill; the URL and cookie are in `.sandbox/sandbox-context.md`. That applies to
25
25
  URL-addressed services only; libraries, CLIs and extensions follow the "How to validate"
26
26
  section of the same file.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werkmeister",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Multi-feature concurrent development orchestrator CLI tool",
5
5
  "type": "module",
6
6
  "engines": {
@@ -53,7 +53,7 @@
53
53
  "@types/node": "^22.13.0",
54
54
  "commander": "^13.1.0",
55
55
  "esbuild": "^0.24.0",
56
- "sandbox-core": "^0.14.0",
56
+ "werkmeister-core": "^0.15.0",
57
57
  "tsx": "^4.19.0",
58
58
  "typescript": "^5.7.0",
59
59
  "vitest": "^3.0.0",
package/werkmeister CHANGED
@@ -5,7 +5,7 @@ set -euo pipefail
5
5
 
6
6
  # Load machine-global config exports (generated by `sandbox config` from
7
7
  # ~/.sandbox/config.yaml) so the CLI inherits SANDBOX_* without a per-client env block.
8
- # ~/.werkmeister wins when it exists, else ~/.sandbox (SW-7), same as sandbox-core's dotDir.
8
+ # ~/.werkmeister wins when it exists, else ~/.sandbox (SW-7), same as werkmeister-core's dotDir.
9
9
  for d in .werkmeister .sandbox; do
10
10
  if [ -d "$HOME/$d" ]; then
11
11
  [ -f "$HOME/$d/env.sh" ] && . "$HOME/$d/env.sh"
@@ -74,7 +74,7 @@ fi
74
74
 
75
75
  # `dashboard` and `mcp` are sibling apps, not CLI subcommands: each has its own
76
76
  # dist/main.js. Both are launched here over stdio, which is what an MCP client
77
- # (Claude Desktop, the sandbox-tools plugin) needs -- their HTTP modes are
77
+ # (Claude Desktop, the werkmeister plugin) needs -- their HTTP modes are
78
78
  # started by `sandbox connect` as managed WebApps, which execs those same
79
79
  # entrypoints directly without --stdio. That is why neither verb takes a
80
80
  # transport flag; extra args are still forwarded, so an explicit --stdio from an
@@ -85,7 +85,7 @@ fi
85
85
  # package as dist/mcp.js (esbuild.mjs), so `mcp` always has a target. The
86
86
  # dashboard (Jira, PRs, MCP Apps UI) is checkout-only; where it is missing its
87
87
  # verb falls back to the headless server, which carries the same sandbox-*
88
- # verbs, so the sandbox-tools plugin's `sandbox dashboard` MCP entry keeps
88
+ # verbs, so the werkmeister plugin's `w9r dashboard` MCP entry keeps
89
89
  # working on a package install instead of failing at every session start.
90
90
  case "${1:-}" in
91
91
  dashboard) app_dir="sandbox-dashboard" ;;