@pleri/olam-cli 0.1.170 → 0.1.173

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.
@@ -27600,10 +27600,111 @@ var init_exports = {};
27600
27600
  __export(init_exports, {
27601
27601
  register: () => register
27602
27602
  });
27603
- init_v3();
27604
27603
  import * as fs from "node:fs";
27605
27604
  import * as path from "node:path";
27606
27605
  import { execSync } from "node:child_process";
27606
+
27607
+ // ../skill-runtime/dist/skills/init.js
27608
+ init_v3();
27609
+
27610
+ // ../skill-runtime/dist/define-skill.js
27611
+ init_v3();
27612
+ var KEBAB_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
27613
+ function defineSkill(spec) {
27614
+ if (!KEBAB_RE.test(spec.name)) {
27615
+ throw new Error(`defineSkill: name "${spec.name}" must be kebab-case (lowercase letters, digits, and hyphens only; no leading/trailing/double hyphens).`);
27616
+ }
27617
+ if (!(spec.inputSchema instanceof external_exports.ZodObject)) {
27618
+ throw new Error(`defineSkill: inputSchema for skill "${spec.name}" must be a ZodObject (z.object({...})). Non-object schemas (z.string(), z.array(), etc.) are not supported because McpServer.tool() requires a ZodRawShape (the .shape of a ZodObject).`);
27619
+ }
27620
+ return {
27621
+ asMcpTool() {
27622
+ return {
27623
+ name: spec.name,
27624
+ description: spec.description,
27625
+ inputSchema: spec.inputSchema.shape,
27626
+ async handler(params) {
27627
+ try {
27628
+ const parsed = spec.inputSchema.safeParse(params);
27629
+ if (!parsed.success) {
27630
+ return {
27631
+ content: [
27632
+ {
27633
+ type: "text",
27634
+ text: `Invalid input: ${parsed.error.message}`
27635
+ }
27636
+ ],
27637
+ isError: true
27638
+ };
27639
+ }
27640
+ const output = await spec.handler(parsed.data);
27641
+ return {
27642
+ content: [
27643
+ {
27644
+ type: "text",
27645
+ text: typeof output === "string" ? output : JSON.stringify(output)
27646
+ }
27647
+ ]
27648
+ };
27649
+ } catch (err) {
27650
+ const message = err instanceof Error ? err.message : String(err);
27651
+ return {
27652
+ content: [{ type: "text", text: `Error: ${message}` }],
27653
+ isError: true
27654
+ };
27655
+ }
27656
+ }
27657
+ };
27658
+ },
27659
+ asHttpHandler() {
27660
+ return async (req, res) => {
27661
+ const parsed = spec.inputSchema.safeParse(req.body);
27662
+ if (!parsed.success) {
27663
+ res.status(400).json({
27664
+ error: "Invalid input",
27665
+ issues: parsed.error.issues
27666
+ });
27667
+ return;
27668
+ }
27669
+ try {
27670
+ const output = await spec.handler(parsed.data);
27671
+ res.status(200).json({ result: output });
27672
+ } catch (err) {
27673
+ const message = err instanceof Error ? err.message : String(err);
27674
+ res.status(500).json({ error: message });
27675
+ }
27676
+ };
27677
+ },
27678
+ toJsonSchema() {
27679
+ return zodToJsonSchema(spec.inputSchema, { target: "openApi3" });
27680
+ }
27681
+ };
27682
+ }
27683
+
27684
+ // ../skill-runtime/dist/skills/init.js
27685
+ var initInputSchema = external_exports.object({
27686
+ projectPath: external_exports.string().optional().describe("Path to the project root. Defaults to cwd."),
27687
+ pleriBaseUrl: external_exports.string().optional().describe("Pleri API base URL"),
27688
+ pleriPlaneId: external_exports.string().optional().describe("Pleri plane ID"),
27689
+ pleriApiKey: external_exports.string().optional().describe("Pleri API key from device code flow"),
27690
+ skipPleri: external_exports.boolean().optional().default(false).describe("Skip Pleri setup for now")
27691
+ });
27692
+ var initSkill = defineSkill({
27693
+ name: "init",
27694
+ description: "Initialize Olam in the current project. Creates .olam/ directory with configuration.",
27695
+ inputSchema: initInputSchema,
27696
+ handler: (input) => {
27697
+ const root = input.projectPath ?? process.cwd();
27698
+ const pleriStatus = input.skipPleri ? "skipped" : input.pleriApiKey ? "configured" : "pending";
27699
+ return [
27700
+ `Would initialize Olam at ${root}/.olam/`,
27701
+ ` pleri: ${pleriStatus}`,
27702
+ "Use the MCP tool for actual file system execution."
27703
+ ].join("\n");
27704
+ }
27705
+ });
27706
+
27707
+ // ../mcp-server/src/tools/init.ts
27607
27708
  function detectProjectType(projectRoot) {
27608
27709
  if (fs.existsSync(path.join(projectRoot, "Gemfile")) || fs.existsSync(path.join(projectRoot, "config", "routes.rb"))) {
27609
27710
  return "rails";
@@ -27663,16 +27764,11 @@ function updateGitignore(projectRoot, entries) {
27663
27764
  }
27664
27765
  }
27665
27766
  function register(server, _ctx, _initError) {
27767
+ const { description, inputSchema } = initSkill.asMcpTool();
27666
27768
  server.tool(
27667
27769
  "olam_init",
27668
- "Initialize Olam in the current project. Creates .olam/ directory with configuration.",
27669
- {
27670
- projectPath: external_exports.string().optional().describe("Path to the project root. Defaults to cwd."),
27671
- pleriBaseUrl: external_exports.string().optional().describe("Pleri API base URL"),
27672
- pleriPlaneId: external_exports.string().optional().describe("Pleri plane ID"),
27673
- pleriApiKey: external_exports.string().optional().describe("Pleri API key from device code flow"),
27674
- skipPleri: external_exports.boolean().optional().default(false).describe("Skip Pleri setup for now")
27675
- },
27770
+ description,
27771
+ inputSchema,
27676
27772
  async (params) => {
27677
27773
  try {
27678
27774
  const startDir = params.projectPath ?? process.cwd();
@@ -27799,7 +27895,6 @@ __export(auth_exports, {
27799
27895
  formatAccountFlag: () => formatAccountFlag,
27800
27896
  register: () => register2
27801
27897
  });
27802
- init_v3();
27803
27898
 
27804
27899
  // ../core/dist/auth/secret.js
27805
27900
  import * as crypto from "node:crypto";
@@ -28202,6 +28297,52 @@ function describe2(err) {
28202
28297
  return err instanceof Error ? err.message : "unknown error";
28203
28298
  }
28204
28299
 
28300
+ // ../skill-runtime/dist/skills/auth-status.js
28301
+ init_v3();
28302
+ var authStatusInputSchema = external_exports.object({});
28303
+ var authStatusSkill = defineSkill({
28304
+ name: "auth-status",
28305
+ description: "Show the local auth container state and stored Claude accounts. The container runs the OAuth PKCE dance once and persists tokens across world creations.",
28306
+ inputSchema: authStatusInputSchema,
28307
+ handler: (_input) => "Auth status requires an active AuthClient. Use the MCP tool surface or HTTP endpoint with a configured host."
28308
+ });
28309
+
28310
+ // ../skill-runtime/dist/skills/auth-up.js
28311
+ init_v3();
28312
+ var authUpInputSchema = external_exports.object({});
28313
+ var authUpSkill = defineSkill({
28314
+ name: "auth-up",
28315
+ description: "Start the local auth container (idempotent). Builds the image on first run. After this, run olam_auth_login to store a Claude account.",
28316
+ inputSchema: authUpInputSchema,
28317
+ handler: (_input) => "Auth container control requires an active AuthContainerController. Use the MCP tool surface or HTTP endpoint with a configured host."
28318
+ });
28319
+
28320
+ // ../skill-runtime/dist/skills/auth-login.js
28321
+ init_v3();
28322
+ var authLoginInputSchema = external_exports.object({
28323
+ label: external_exports.string().default("primary").describe("Account label shown in olam_auth_status (e.g. personal, team)."),
28324
+ provider: external_exports.enum(["claude", "codex"]).default("claude")
28325
+ });
28326
+ var authLoginSkill = defineSkill({
28327
+ name: "auth-login",
28328
+ description: "Begin the OAuth PKCE flow. Returns a login URL to open in a browser and a state token. After approving, call olam_auth_complete with the returned authorization code.",
28329
+ inputSchema: authLoginInputSchema,
28330
+ handler: (input) => `OAuth PKCE login requires an active AuthClient. Would initiate login for account "${input.label}" (${input.provider}). Use the MCP tool surface or HTTP endpoint with a configured host.`
28331
+ });
28332
+
28333
+ // ../skill-runtime/dist/skills/auth-complete.js
28334
+ init_v3();
28335
+ var authCompleteInputSchema = external_exports.object({
28336
+ state: external_exports.string().describe("State token returned by olam_auth_login."),
28337
+ code: external_exports.string().describe("Authorization code copied from the Claude redirect page.")
28338
+ });
28339
+ var authCompleteSkill = defineSkill({
28340
+ name: "auth-complete",
28341
+ description: "Complete a PKCE login flow by exchanging the authorization code for tokens. Uses the state returned by olam_auth_login.",
28342
+ inputSchema: authCompleteInputSchema,
28343
+ handler: (input) => `Token exchange requires an active AuthClient. Would complete PKCE flow for state "${input.state}". Use the MCP tool surface or HTTP endpoint with a configured host.`
28344
+ });
28345
+
28205
28346
  // ../mcp-server/src/tools/auth.ts
28206
28347
  function formatAccountFlag(a, now = Date.now()) {
28207
28348
  if (a.state === "disabled") return "disabled";
@@ -28219,10 +28360,11 @@ function formatAccountFlag(a, now = Date.now()) {
28219
28360
  return "valid";
28220
28361
  }
28221
28362
  function register2(server, _ctx, _initError) {
28363
+ const authStatus = authStatusSkill.asMcpTool();
28222
28364
  server.tool(
28223
28365
  "olam_auth_status",
28224
- "Show the local auth container state and stored Claude accounts. The container runs the OAuth PKCE dance once and persists tokens across world creations.",
28225
- {},
28366
+ authStatus.description,
28367
+ authStatus.inputSchema,
28226
28368
  async () => {
28227
28369
  const controller = new AuthContainerController();
28228
28370
  const state = controller.status();
@@ -28247,10 +28389,11 @@ function register2(server, _ctx, _initError) {
28247
28389
  return { content: [{ type: "text", text: lines.join("\n") }] };
28248
28390
  }
28249
28391
  );
28392
+ const authUp = authUpSkill.asMcpTool();
28250
28393
  server.tool(
28251
28394
  "olam_auth_up",
28252
- "Start the local auth container (idempotent). Builds the image on first run. After this, run olam_auth_login to store a Claude account.",
28253
- {},
28395
+ authUp.description,
28396
+ authUp.inputSchema,
28254
28397
  async () => {
28255
28398
  const controller = new AuthContainerController();
28256
28399
  const initial = controller.status();
@@ -28277,13 +28420,11 @@ function register2(server, _ctx, _initError) {
28277
28420
  };
28278
28421
  }
28279
28422
  );
28423
+ const authLogin = authLoginSkill.asMcpTool();
28280
28424
  server.tool(
28281
28425
  "olam_auth_login",
28282
- "Begin the OAuth PKCE flow. Returns a login URL to open in a browser and a state token. After approving, call olam_auth_complete with the returned authorization code.",
28283
- {
28284
- label: external_exports.string().default("primary").describe("Account label shown in olam_auth_status (e.g. personal, team)."),
28285
- provider: external_exports.enum(["claude", "codex"]).default("claude")
28286
- },
28426
+ authLogin.description,
28427
+ authLogin.inputSchema,
28287
28428
  async ({ label, provider }) => {
28288
28429
  const client = new AuthClient();
28289
28430
  const controller = new AuthContainerController();
@@ -28318,13 +28459,11 @@ function register2(server, _ctx, _initError) {
28318
28459
  }
28319
28460
  }
28320
28461
  );
28462
+ const authComplete = authCompleteSkill.asMcpTool();
28321
28463
  server.tool(
28322
28464
  "olam_auth_complete",
28323
- "Complete a PKCE login flow by exchanging the authorization code for tokens. Uses the state returned by olam_auth_login.",
28324
- {
28325
- state: external_exports.string().describe("State token returned by olam_auth_login."),
28326
- code: external_exports.string().describe("Authorization code copied from the Claude redirect page.")
28327
- },
28465
+ authComplete.description,
28466
+ authComplete.inputSchema,
28328
28467
  async ({ state, code }) => {
28329
28468
  const client = new AuthClient();
28330
28469
  try {
@@ -28350,7 +28489,6 @@ var pr_exports = {};
28350
28489
  __export(pr_exports, {
28351
28490
  register: () => register3
28352
28491
  });
28353
- init_v3();
28354
28492
 
28355
28493
  // ../core/dist/world/registry.js
28356
28494
  import { createRequire } from "node:module";
@@ -28685,6 +28823,81 @@ async function decideGate(portOffset, id, payload) {
28685
28823
  return await res.json();
28686
28824
  }
28687
28825
 
28826
+ // ../skill-runtime/dist/skills/pr-list.js
28827
+ init_v3();
28828
+ var prListInputSchema = external_exports.object({});
28829
+ var prListSkill = defineSkill({
28830
+ name: "pr-list",
28831
+ description: "List every PR-gate request across every running world. A gate is opened by the in-world PreToolUse hook whenever Claude is about to run `gh pr create`.",
28832
+ inputSchema: prListInputSchema,
28833
+ handler: (_input) => "PR gate listing requires an active WorldRegistry. Use the MCP tool surface."
28834
+ });
28835
+
28836
+ // ../skill-runtime/dist/skills/pr-show.js
28837
+ init_v3();
28838
+ var prShowInputSchema = external_exports.object({
28839
+ id: external_exports.string().describe("Gate id (full UUID).")
28840
+ });
28841
+ var prShowSkill = defineSkill({
28842
+ name: "pr-show",
28843
+ description: "Show full detail for a gate: diff, commit log, branch, base, and any prior decision.",
28844
+ inputSchema: prShowInputSchema,
28845
+ handler: (input) => `PR gate detail for "${input.id}" requires an active WorldRegistry. Use the MCP tool surface.`
28846
+ });
28847
+
28848
+ // ../skill-runtime/dist/skills/pr-approve.js
28849
+ init_v3();
28850
+ var prApproveInputSchema = external_exports.object({
28851
+ id: external_exports.string().describe("Gate id (full UUID)."),
28852
+ reason: external_exports.string().optional().describe("Short free-text reason surfaced back to Claude on block."),
28853
+ by: external_exports.string().optional().describe('Deciding identity (defaults to "mcp").')
28854
+ });
28855
+ var prApproveSkill = defineSkill({
28856
+ name: "pr-approve",
28857
+ description: "Approve a pending PR-gate so the in-world `gh pr create` proceeds.",
28858
+ inputSchema: prApproveInputSchema,
28859
+ handler: (input) => `Approve gate "${input.id}" by "${input.by ?? "mcp"}" requires an active WorldRegistry. Use the MCP tool surface.`
28860
+ });
28861
+
28862
+ // ../skill-runtime/dist/skills/pr-reject.js
28863
+ init_v3();
28864
+ var prRejectInputSchema = external_exports.object({
28865
+ id: external_exports.string().describe("Gate id (full UUID)."),
28866
+ reason: external_exports.string().optional().describe("Short free-text reason surfaced back to Claude on block."),
28867
+ by: external_exports.string().optional().describe('Deciding identity (defaults to "mcp").')
28868
+ });
28869
+ var prRejectSkill = defineSkill({
28870
+ name: "pr-reject",
28871
+ description: "Block a pending PR-gate. The in-world hook exits non-zero so Claude sees a tool error and can address or retry.",
28872
+ inputSchema: prRejectInputSchema,
28873
+ handler: (input) => `Block gate "${input.id}" by "${input.by ?? "mcp"}" requires an active WorldRegistry. Use the MCP tool surface.`
28874
+ });
28875
+
28876
+ // ../skill-runtime/dist/skills/pr-track.js
28877
+ init_v3();
28878
+ var prTrackInputSchema = external_exports.object({
28879
+ worldId: external_exports.string().describe("World ID"),
28880
+ prUrl: external_exports.string().url().describe("Full GitHub PR URL (e.g. https://github.com/org/repo/pull/123)"),
28881
+ prNumber: external_exports.number().int().positive().optional().describe("PR number"),
28882
+ prRepo: external_exports.string().optional().describe("Repo slug (owner/repo)")
28883
+ });
28884
+ var prTrackSkill = defineSkill({
28885
+ name: "pr-track",
28886
+ description: "Record a PR association for a world after gh pr create succeeds. Call this after the PR is created to enable auto-destroy when the PR merges.",
28887
+ inputSchema: prTrackInputSchema,
28888
+ handler: (input) => {
28889
+ const urlMatch = input.prUrl.match(/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)/);
28890
+ const resolvedRepo = input.prRepo ?? (urlMatch ? urlMatch[1] : void 0);
28891
+ const resolvedNumber = input.prNumber ?? (urlMatch ? parseInt(urlMatch[2], 10) : void 0);
28892
+ return [
28893
+ `PR tracked for world ${input.worldId}: ${input.prUrl}`,
28894
+ resolvedRepo ? ` repo: ${resolvedRepo}` : "",
28895
+ resolvedNumber ? ` number: ${resolvedNumber}` : "",
28896
+ "Auto-destroy will fire when PR merges (after grace period)."
28897
+ ].filter(Boolean).join("\n");
28898
+ }
28899
+ });
28900
+
28688
28901
  // ../mcp-server/src/tools/pr.ts
28689
28902
  function runningWorlds() {
28690
28903
  const registry2 = new WorldRegistry();
@@ -28709,10 +28922,11 @@ function asMessage2(err) {
28709
28922
  return err instanceof Error ? err.message : String(err);
28710
28923
  }
28711
28924
  function register3(server, _ctx, _initError) {
28925
+ const prListTool = prListSkill.asMcpTool();
28712
28926
  server.tool(
28713
28927
  "olam_pr_list",
28714
- "List every PR-gate request across every running world. A gate is opened by the in-world PreToolUse hook whenever Claude is about to run `gh pr create`.",
28715
- {},
28928
+ prListTool.description,
28929
+ prListTool.inputSchema,
28716
28930
  async () => {
28717
28931
  const worlds = runningWorlds();
28718
28932
  const rows = [];
@@ -28739,10 +28953,11 @@ function register3(server, _ctx, _initError) {
28739
28953
  return { content: [{ type: "text", text: lines.join("\n") }] };
28740
28954
  }
28741
28955
  );
28956
+ const prShowTool = prShowSkill.asMcpTool();
28742
28957
  server.tool(
28743
28958
  "olam_pr_show",
28744
- "Show full detail for a gate: diff, commit log, branch, base, and any prior decision.",
28745
- { id: external_exports.string().describe("Gate id (full UUID).") },
28959
+ prShowTool.description,
28960
+ prShowTool.inputSchema,
28746
28961
  async ({ id }) => {
28747
28962
  const found = await findGate(id);
28748
28963
  if (!found) {
@@ -28771,14 +28986,11 @@ function register3(server, _ctx, _initError) {
28771
28986
  }
28772
28987
  );
28773
28988
  const decideTool = (name, decision) => {
28989
+ const skillTool = decision === "approve" ? prApproveSkill.asMcpTool() : prRejectSkill.asMcpTool();
28774
28990
  server.tool(
28775
28991
  name,
28776
- decision === "approve" ? "Approve a pending PR-gate so the in-world `gh pr create` proceeds." : "Block a pending PR-gate. The in-world hook exits non-zero so Claude sees a tool error and can address or retry.",
28777
- {
28778
- id: external_exports.string().describe("Gate id (full UUID)."),
28779
- reason: external_exports.string().optional().describe("Short free-text reason surfaced back to Claude on block."),
28780
- by: external_exports.string().optional().describe('Deciding identity (defaults to "mcp").')
28781
- },
28992
+ skillTool.description,
28993
+ skillTool.inputSchema,
28782
28994
  async ({ id, reason, by }) => {
28783
28995
  const found = await findGate(id);
28784
28996
  if (!found) {
@@ -28807,15 +29019,11 @@ function register3(server, _ctx, _initError) {
28807
29019
  };
28808
29020
  decideTool("olam_pr_approve", "approve");
28809
29021
  decideTool("olam_pr_reject", "block");
29022
+ const prTrackTool = prTrackSkill.asMcpTool();
28810
29023
  server.tool(
28811
29024
  "olam_pr_track",
28812
- "Record a PR association for a world after gh pr create succeeds. Call this after the PR is created to enable auto-destroy when the PR merges.",
28813
- {
28814
- worldId: external_exports.string().describe("World ID"),
28815
- prUrl: external_exports.string().url().describe("Full GitHub PR URL (e.g. https://github.com/org/repo/pull/123)"),
28816
- prNumber: external_exports.number().int().positive().optional().describe("PR number"),
28817
- prRepo: external_exports.string().optional().describe("Repo slug (owner/repo)")
28818
- },
29025
+ prTrackTool.description,
29026
+ prTrackTool.inputSchema,
28819
29027
  async ({ worldId, prUrl, prNumber, prRepo }) => {
28820
29028
  const urlMatch = prUrl.match(/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)/);
28821
29029
  const resolvedRepo = prRepo ?? (urlMatch ? urlMatch[1] : void 0);
@@ -28874,7 +29082,6 @@ var workspace_exports = {};
28874
29082
  __export(workspace_exports, {
28875
29083
  register: () => register4
28876
29084
  });
28877
- init_v3();
28878
29085
  import { stringify as stringifyYaml2 } from "yaml";
28879
29086
 
28880
29087
  // ../core/dist/workspace/index.js
@@ -29007,7 +29214,30 @@ function logRuntimeReconciliation(repoName, runtime) {
29007
29214
  console.warn(`[manifest] repo "${repoName}" supersedes central stack: ${validated.join(", ")}`);
29008
29215
  }
29009
29216
 
29010
- // ../mcp-server/src/tools/workspace.ts
29217
+ // ../skill-runtime/dist/skills/workspace-list.js
29218
+ init_v3();
29219
+ var workspaceListInputSchema = external_exports.object({});
29220
+ var workspaceListSkill = defineSkill({
29221
+ name: "workspace-list",
29222
+ description: "List every workspace in the local catalog. A workspace is a named bundle of repos that worlds instantiate from. Returns CF-compatible summaries: { name, repoCount, updatedAt }.",
29223
+ inputSchema: workspaceListInputSchema,
29224
+ handler: (_input) => JSON.stringify({ note: "workspace listing requires local catalog access; use MCP surface" }, null, 2)
29225
+ });
29226
+
29227
+ // ../skill-runtime/dist/skills/workspace-show.js
29228
+ init_v3();
29229
+ var workspaceShowInputSchema = external_exports.object({
29230
+ name: external_exports.string().describe("Workspace name.")
29231
+ });
29232
+ var workspaceShowSkill = defineSkill({
29233
+ name: "workspace-show",
29234
+ description: "Return the full workspace definition as YAML (name, repos, defaults, updatedAt).",
29235
+ inputSchema: workspaceShowInputSchema,
29236
+ handler: ({ name }) => JSON.stringify({ name, note: "workspace lookup requires local catalog access; use MCP surface" }, null, 2)
29237
+ });
29238
+
29239
+ // ../skill-runtime/dist/skills/workspace-add.js
29240
+ init_v3();
29011
29241
  var repoInputSchema = external_exports.object({
29012
29242
  name: external_exports.string().min(1).optional().describe("Repo name; defaults to last URL segment."),
29013
29243
  url: external_exports.string().min(1),
@@ -29015,6 +29245,32 @@ var repoInputSchema = external_exports.object({
29015
29245
  submodules: external_exports.boolean().optional(),
29016
29246
  setupCmd: external_exports.string().optional()
29017
29247
  });
29248
+ var workspaceAddInputSchema = external_exports.object({
29249
+ name: external_exports.string().describe("Workspace name (lowercase alphanumerics + dashes, 1\u201364 chars)."),
29250
+ repos: external_exports.array(repoInputSchema).min(1),
29251
+ defaultBranch: external_exports.string().optional().describe("Fallback branch for repos without an explicit branch."),
29252
+ force: external_exports.boolean().optional().describe("Overwrite if a workspace with this name already exists.")
29253
+ });
29254
+ var workspaceAddSkill = defineSkill({
29255
+ name: "workspace-add",
29256
+ description: "Create a new workspace. Pass an array of repos (each with url + optional branch, submodules, setupCmd). Rejects duplicate names unless force:true.",
29257
+ inputSchema: workspaceAddInputSchema,
29258
+ handler: ({ name, repos }) => JSON.stringify({ name, repoCount: repos.length, note: "workspace creation requires local catalog access; use MCP surface" }, null, 2)
29259
+ });
29260
+
29261
+ // ../skill-runtime/dist/skills/workspace-remove.js
29262
+ init_v3();
29263
+ var workspaceRemoveInputSchema = external_exports.object({
29264
+ name: external_exports.string().describe("Workspace name.")
29265
+ });
29266
+ var workspaceRemoveSkill = defineSkill({
29267
+ name: "workspace-remove",
29268
+ description: "Delete a workspace. Does not affect already-created worlds that referenced it.",
29269
+ inputSchema: workspaceRemoveInputSchema,
29270
+ handler: ({ name }) => JSON.stringify({ name, note: "workspace removal requires local catalog access; use MCP surface" }, null, 2)
29271
+ });
29272
+
29273
+ // ../mcp-server/src/tools/workspace.ts
29018
29274
  function deriveRepoName(url2) {
29019
29275
  return url2.replace(/\.git$/, "").split(/[\/:]/).filter(Boolean).at(-1) ?? "repo";
29020
29276
  }
@@ -29022,10 +29278,11 @@ function asMessage3(err) {
29022
29278
  return err instanceof Error ? err.message : String(err);
29023
29279
  }
29024
29280
  function register4(server, _ctx, _initError) {
29281
+ const listTool = workspaceListSkill.asMcpTool();
29025
29282
  server.tool(
29026
29283
  "olam_workspace_list",
29027
- "List every workspace in the local catalog. A workspace is a named bundle of repos that worlds instantiate from. Returns CF-compatible summaries: { name, repoCount, updatedAt }.",
29028
- {},
29284
+ listTool.description,
29285
+ listTool.inputSchema,
29029
29286
  async () => {
29030
29287
  const all = listWorkspaces();
29031
29288
  if (all.length === 0) {
@@ -29039,10 +29296,11 @@ function register4(server, _ctx, _initError) {
29039
29296
  return { content: [{ type: "text", text: lines.join("\n") }] };
29040
29297
  }
29041
29298
  );
29299
+ const showTool = workspaceShowSkill.asMcpTool();
29042
29300
  server.tool(
29043
29301
  "olam_workspace_show",
29044
- "Return the full workspace definition as YAML (name, repos, defaults, updatedAt).",
29045
- { name: external_exports.string().describe("Workspace name.") },
29302
+ showTool.description,
29303
+ showTool.inputSchema,
29046
29304
  async ({ name }) => {
29047
29305
  try {
29048
29306
  const ws = readWorkspace(name);
@@ -29058,15 +29316,11 @@ function register4(server, _ctx, _initError) {
29058
29316
  }
29059
29317
  }
29060
29318
  );
29319
+ const addTool = workspaceAddSkill.asMcpTool();
29061
29320
  server.tool(
29062
29321
  "olam_workspace_add",
29063
- "Create a new workspace. Pass an array of repos (each with url + optional branch, submodules, setupCmd). Rejects duplicate names unless force:true.",
29064
- {
29065
- name: external_exports.string().describe("Workspace name (lowercase alphanumerics + dashes, 1\u201364 chars)."),
29066
- repos: external_exports.array(repoInputSchema).min(1),
29067
- defaultBranch: external_exports.string().optional().describe("Fallback branch for repos without an explicit branch."),
29068
- force: external_exports.boolean().optional().describe("Overwrite if a workspace with this name already exists.")
29069
- },
29322
+ addTool.description,
29323
+ addTool.inputSchema,
29070
29324
  async ({ name, repos, defaultBranch, force }) => {
29071
29325
  try {
29072
29326
  const filled = repos.map((r) => ({
@@ -29097,10 +29351,11 @@ function register4(server, _ctx, _initError) {
29097
29351
  }
29098
29352
  }
29099
29353
  );
29354
+ const removeTool = workspaceRemoveSkill.asMcpTool();
29100
29355
  server.tool(
29101
29356
  "olam_workspace_remove",
29102
- "Delete a workspace. Does not affect already-created worlds that referenced it.",
29103
- { name: external_exports.string().describe("Workspace name.") },
29357
+ removeTool.description,
29358
+ removeTool.inputSchema,
29104
29359
  async ({ name }) => {
29105
29360
  try {
29106
29361
  const removed = removeWorkspace(name);
@@ -29124,10 +29379,35 @@ __export(role_exports, {
29124
29379
  register: () => register5
29125
29380
  });
29126
29381
  init_v3();
29382
+
29383
+ // ../skill-runtime/dist/skills/role-assign.js
29384
+ init_v3();
29385
+ var ROLE_ARCHETYPES = [
29386
+ "user",
29387
+ "workspace-curator",
29388
+ "policy-admin",
29389
+ "bootstrapper",
29390
+ "admin",
29391
+ "dev"
29392
+ ];
29393
+ var roleAssignInputSchema = external_exports.object({
29394
+ email: external_exports.string().email().describe("Target user email."),
29395
+ archetype: external_exports.enum(ROLE_ARCHETYPES).describe("Named archetype preset."),
29396
+ capabilities: external_exports.array(external_exports.string()).optional().describe("Optional additive capabilities on top of the archetype.")
29397
+ });
29127
29398
  var ROLE_DEPRECATED_MESSAGE = "olam_role_* tools were deprecated in PR #31 \u2014 role management now lives in Pylon. Use `pylon role grant --app=olam --email=<email> --archetype=<name>`, `pylon role list --app=olam`, or `pylon role revoke --email-hash=<sha256>` directly. Install via `npm install -g @pleri/pylon-cli`.";
29399
+ var roleAssignSkill = defineSkill({
29400
+ name: "role-assign",
29401
+ description: "DEPRECATED \u2014 use `pylon role grant --app=olam --email=<email> --archetype=<name>` instead. Role management moved to Pylon in PR #31.",
29402
+ inputSchema: roleAssignInputSchema,
29403
+ handler: (_input) => ROLE_DEPRECATED_MESSAGE
29404
+ });
29405
+
29406
+ // ../mcp-server/src/tools/role.ts
29407
+ var ROLE_DEPRECATED_MESSAGE2 = "olam_role_* tools were deprecated in PR #31 \u2014 role management now lives in Pylon. Use `pylon role grant --app=olam --email=<email> --archetype=<name>`, `pylon role list --app=olam`, or `pylon role revoke --email-hash=<sha256>` directly. Install via `npm install -g @pleri/pylon-cli`.";
29128
29408
  function deprecatedResult() {
29129
29409
  return {
29130
- content: [{ type: "text", text: ROLE_DEPRECATED_MESSAGE }],
29410
+ content: [{ type: "text", text: ROLE_DEPRECATED_MESSAGE2 }],
29131
29411
  isError: true
29132
29412
  };
29133
29413
  }
@@ -29138,15 +29418,14 @@ function register5(server, _ctx, _initError) {
29138
29418
  {},
29139
29419
  async () => deprecatedResult()
29140
29420
  );
29421
+ const roleAssignTool = roleAssignSkill.asMcpTool();
29141
29422
  server.tool(
29142
29423
  "olam_role_assign",
29143
- "DEPRECATED \u2014 use `pylon role grant --app=olam --email=<email> --archetype=<name>` instead. Role management moved to Pylon in PR #31.",
29144
- {
29145
- email: external_exports.string().email().describe("Target user email."),
29146
- archetype: external_exports.enum(["user", "workspace-curator", "policy-admin", "bootstrapper", "admin", "dev"]).describe("Named archetype preset."),
29147
- capabilities: external_exports.array(external_exports.string()).optional().describe("Optional additive capabilities on top of the archetype.")
29148
- },
29149
- async () => deprecatedResult()
29424
+ roleAssignTool.description,
29425
+ roleAssignTool.inputSchema,
29426
+ async (params) => roleAssignTool.handler(
29427
+ params
29428
+ )
29150
29429
  );
29151
29430
  server.tool(
29152
29431
  "olam_role_revoke",
@@ -29163,7 +29442,6 @@ var world_create_exports = {};
29163
29442
  __export(world_create_exports, {
29164
29443
  register: () => register6
29165
29444
  });
29166
- init_v3();
29167
29445
 
29168
29446
  // ../mcp-server/src/utils/logger.ts
29169
29447
  var LEVEL_ORDER = {
@@ -31126,7 +31404,8 @@ function createSshProvider(config2) {
31126
31404
  return new SSHProvider(hosts);
31127
31405
  }
31128
31406
 
31129
- // ../mcp-server/src/tools/world-create.ts
31407
+ // ../skill-runtime/dist/skills/world-create.js
31408
+ init_v3();
31130
31409
  var taskContextSchema = external_exports.object({
31131
31410
  source: external_exports.enum(["linear", "github", "manual"]),
31132
31411
  ticketId: external_exports.string().optional(),
@@ -31138,27 +31417,49 @@ var taskContextSchema = external_exports.object({
31138
31417
  githubRepo: external_exports.string().optional(),
31139
31418
  githubBranch: external_exports.string().optional()
31140
31419
  }).optional();
31420
+ var worldCreateInputSchema = external_exports.object({
31421
+ name: external_exports.string(),
31422
+ repos: external_exports.array(external_exports.string()).optional(),
31423
+ workspace: external_exports.string().optional().describe("Named workspace from the host catalog (~/.olam/workspaces/<name>.yaml). Inline `repos` wins over this."),
31424
+ task: external_exports.string().optional(),
31425
+ linearTicketId: external_exports.string().optional(),
31426
+ branchName: external_exports.string().optional().describe("Override the default branch name (e.g., feat/ATL-1234-payment-webhook)"),
31427
+ planFile: external_exports.string().optional().describe("Path to a plan file on the host to inject into the world"),
31428
+ taskContext: taskContextSchema.describe("Structured task context from Linear, GitHub, or manual entry"),
31429
+ carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false"),
31430
+ runbookName: external_exports.string().optional().describe("Named runbook profile from ~/.olam/config.json \u2014 seeds ports, env overrides, and fixture-copy steps")
31431
+ });
31432
+ var worldCreateSkill = defineSkill({
31433
+ name: "world-create",
31434
+ description: "Provision a new isolated development world with optional repository cloning, initial task, and Linear/GitHub task context.",
31435
+ inputSchema: worldCreateInputSchema,
31436
+ handler: (input) => {
31437
+ const hasTask = Boolean(input.task?.trim() || input.linearTicketId?.trim() || input.taskContext?.ticketId?.trim());
31438
+ if (!hasTask) {
31439
+ return "olam_create requires one of: `task`, `linearTicketId`, or `taskContext.ticketId`. Worlds are only created with an actionable input.";
31440
+ }
31441
+ return JSON.stringify({
31442
+ name: input.name,
31443
+ repos: input.repos ?? [],
31444
+ workspace: input.workspace,
31445
+ task: input.task,
31446
+ linearTicketId: input.linearTicketId,
31447
+ branchName: input.branchName,
31448
+ planFile: input.planFile,
31449
+ taskContext: input.taskContext,
31450
+ carryUncommitted: input.carryUncommitted ?? false,
31451
+ runbookName: input.runbookName
31452
+ }, null, 2);
31453
+ }
31454
+ });
31455
+
31456
+ // ../mcp-server/src/tools/world-create.ts
31141
31457
  function register6(server, ctx, initError) {
31458
+ const { description, inputSchema } = worldCreateSkill.asMcpTool();
31142
31459
  server.tool(
31143
31460
  "olam_create",
31144
- "Provision a new isolated development world with optional repository cloning, initial task, and Linear/GitHub task context.",
31145
- {
31146
- name: external_exports.string(),
31147
- repos: external_exports.array(external_exports.string()).optional(),
31148
- workspace: external_exports.string().optional().describe("Named workspace from the host catalog (~/.olam/workspaces/<name>.yaml). Inline `repos` wins over this."),
31149
- task: external_exports.string().optional(),
31150
- linearTicketId: external_exports.string().optional(),
31151
- branchName: external_exports.string().optional().describe("Override the default branch name (e.g., feat/ATL-1234-payment-webhook)"),
31152
- planFile: external_exports.string().optional().describe("Path to a plan file on the host to inject into the world"),
31153
- taskContext: taskContextSchema.describe("Structured task context from Linear, GitHub, or manual entry"),
31154
- // Phase B B3 (olam-session-stability): mirror of CLI's
31155
- // --carry-uncommitted flag. Default OFF (clean tree). Skips B1's
31156
- // strip step so any operator-side uncommitted edits survive into
31157
- // the world's worktree. The baseline-diff snapshot still runs
31158
- // unconditionally (Phase C reaper still needs it).
31159
- carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false"),
31160
- runbookName: external_exports.string().optional().describe("Named runbook profile from ~/.olam/config.json \u2014 seeds ports, env overrides, and fixture-copy steps")
31161
- },
31461
+ description,
31462
+ inputSchema,
31162
31463
  async (params) => {
31163
31464
  if (!ctx) {
31164
31465
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -31314,14 +31615,26 @@ var world_destroy_exports = {};
31314
31615
  __export(world_destroy_exports, {
31315
31616
  register: () => register7
31316
31617
  });
31618
+
31619
+ // ../skill-runtime/dist/skills/world-destroy.js
31317
31620
  init_v3();
31621
+ var worldDestroyInputSchema = external_exports.object({
31622
+ worldId: external_exports.string()
31623
+ });
31624
+ var worldDestroySkill = defineSkill({
31625
+ name: "world-destroy",
31626
+ description: "Destroy an existing world and clean up all associated resources.",
31627
+ inputSchema: worldDestroyInputSchema,
31628
+ handler: ({ worldId }) => `Destroy requested for world: ${worldId}`
31629
+ });
31630
+
31631
+ // ../mcp-server/src/tools/world-destroy.ts
31318
31632
  function register7(server, ctx, initError) {
31633
+ const { description, inputSchema } = worldDestroySkill.asMcpTool();
31319
31634
  server.tool(
31320
31635
  "olam_destroy",
31321
- "Destroy an existing world and clean up all associated resources.",
31322
- {
31323
- worldId: external_exports.string()
31324
- },
31636
+ description,
31637
+ inputSchema,
31325
31638
  async (params) => {
31326
31639
  if (!ctx) {
31327
31640
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -31355,11 +31668,24 @@ var world_list_exports = {};
31355
31668
  __export(world_list_exports, {
31356
31669
  register: () => register8
31357
31670
  });
31671
+
31672
+ // ../skill-runtime/dist/skills/world-list.js
31673
+ init_v3();
31674
+ var worldListInputSchema = external_exports.object({});
31675
+ var worldListSkill = defineSkill({
31676
+ name: "world-list",
31677
+ description: "List all active development worlds and their current status.",
31678
+ inputSchema: worldListInputSchema,
31679
+ handler: (_input) => "World listing requires an active OlamContext. Use the MCP tool surface or HTTP endpoint with a configured host."
31680
+ });
31681
+
31682
+ // ../mcp-server/src/tools/world-list.ts
31358
31683
  function register8(server, ctx, initError) {
31684
+ const { description, inputSchema } = worldListSkill.asMcpTool();
31359
31685
  server.tool(
31360
31686
  "olam_list",
31361
- "List all active development worlds and their current status.",
31362
- {},
31687
+ description,
31688
+ inputSchema,
31363
31689
  async () => {
31364
31690
  if (!ctx) {
31365
31691
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -31415,7 +31741,6 @@ __export(world_dispatch_exports, {
31415
31741
  dispatchInputSchema: () => dispatchInputSchema,
31416
31742
  register: () => register9
31417
31743
  });
31418
- init_v3();
31419
31744
  import "node:path";
31420
31745
 
31421
31746
  // ../core/dist/world-paths.js
@@ -31881,7 +32206,8 @@ var MCP_SERVER_ALLOWLIST = /* @__PURE__ */ new Set([
31881
32206
  "command",
31882
32207
  "args",
31883
32208
  "type",
31884
- "url"
32209
+ "url",
32210
+ "alwaysLoad"
31885
32211
  ]);
31886
32212
  function stripMcpServers(mcpServers) {
31887
32213
  const out = {};
@@ -31902,6 +32228,8 @@ function stripMcpServers(mcpServers) {
31902
32228
  stripped.type = value;
31903
32229
  } else if (key === "url" && typeof value === "string") {
31904
32230
  stripped.url = value;
32231
+ } else if (key === "alwaysLoad" && typeof value === "boolean") {
32232
+ stripped.alwaysLoad = value;
31905
32233
  }
31906
32234
  }
31907
32235
  out[svc] = stripped;
@@ -32518,28 +32846,59 @@ async function verifyCommentPosted(spec, worldId, execGh) {
32518
32846
  };
32519
32847
  }
32520
32848
 
32521
- // ../mcp-server/src/tools/world-dispatch.ts
32522
- var dispatchInputSchema = {
32849
+ // ../skill-runtime/dist/skills/world-dispatch.js
32850
+ init_v3();
32851
+ var goalSpecSchema = external_exports.object({
32852
+ type: external_exports.enum([
32853
+ "pr-merged",
32854
+ "pr-green",
32855
+ "file-exists",
32856
+ "test-passes",
32857
+ "comment-posted"
32858
+ ]),
32859
+ spec: external_exports.string().min(1).describe("Type-specific spec: PR number, file path, test name, or comment marker"),
32860
+ timeoutMinutes: external_exports.number().int().min(1).max(720).default(90)
32861
+ }).describe("Optional structured completion condition; when set, the world loops between turns checking this until met or timeout");
32862
+ var worldDispatchInputSchema = external_exports.object({
32523
32863
  worldId: external_exports.string(),
32524
32864
  prompt: external_exports.string(),
32525
32865
  maxTurns: external_exports.number().optional(),
32526
- mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe(
32527
- "Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"
32528
- ),
32529
- goal: GoalSpecSchema.optional().describe(
32530
- "Optional structured completion condition. When set, the world's dispatch loop checks this condition after each turn until met or the timeout window closes. v1 ships a single post-dispatch check; v2 will close the loop. /goal-mode parity with Claude Code 2.1.139."
32531
- ),
32532
- escalationTiers: external_exports.array(external_exports.enum(["haiku", "sonnet", "opus"])).optional().default(["sonnet"]).describe(
32533
- "Ordered model-tier escalation chain for dispatch retries. On each retry, host-cp advances to the next tier instead of repeating the failed model. Default ['sonnet'] = no escalation (current behaviour, no cost surprise). Operators opt in via e.g. ['sonnet','opus'] or ['haiku','sonnet','opus']."
32534
- )
32535
- };
32536
- var dispatchInputObject = external_exports.object(dispatchInputSchema);
32866
+ mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe("Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"),
32867
+ goal: goalSpecSchema.optional().describe("Optional structured completion condition. When set, the world's dispatch loop checks this condition after each turn until met or the timeout window closes. v1 ships a single post-dispatch check; v2 will close the loop. /goal-mode parity with Claude Code 2.1.139."),
32868
+ escalationTiers: external_exports.array(external_exports.enum(["haiku", "sonnet", "opus"])).optional().default(["sonnet"]).describe("Ordered model-tier escalation chain for dispatch retries. On each retry, host-cp advances to the next tier instead of repeating the failed model. Default ['sonnet'] = no escalation (current behaviour, no cost surprise). Operators opt in via e.g. ['sonnet','opus'] or ['haiku','sonnet','opus'].")
32869
+ });
32870
+ var worldDispatchSkill = defineSkill({
32871
+ name: "world-dispatch",
32872
+ description: "Send a task prompt to a world for autonomous execution.",
32873
+ inputSchema: worldDispatchInputSchema,
32874
+ handler: (input) => {
32875
+ const lines = [
32876
+ `Dispatch queued.`,
32877
+ ``,
32878
+ ` worldId: ${input.worldId}`,
32879
+ ` mode: ${input.mode ?? "auto"}`,
32880
+ ` prompt: ${input.prompt.slice(0, 120)}${input.prompt.length > 120 ? "\u2026" : ""}`
32881
+ ];
32882
+ if (input.goal) {
32883
+ lines.push(` goal: ${input.goal.type} (${input.goal.spec})`);
32884
+ }
32885
+ if (input.escalationTiers && input.escalationTiers.length > 0) {
32886
+ lines.push(` tiers: ${input.escalationTiers.join(", ")}`);
32887
+ }
32888
+ return lines.join("\n");
32889
+ }
32890
+ });
32891
+
32892
+ // ../mcp-server/src/tools/world-dispatch.ts
32893
+ var dispatchInputObject = worldDispatchInputSchema;
32894
+ var dispatchInputSchema = worldDispatchSkill.asMcpTool().inputSchema;
32537
32895
  function register9(server, ctx, initError, deps) {
32538
32896
  const verify = deps?.verifyGoal ?? verifyGoal;
32897
+ const { description, inputSchema } = worldDispatchSkill.asMcpTool();
32539
32898
  server.tool(
32540
32899
  "olam_dispatch",
32541
- "Send a task prompt to a world for autonomous execution.",
32542
- dispatchInputSchema,
32900
+ description,
32901
+ inputSchema,
32543
32902
  async (params) => {
32544
32903
  if (!ctx) {
32545
32904
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -32682,14 +33041,26 @@ var world_observe_exports = {};
32682
33041
  __export(world_observe_exports, {
32683
33042
  register: () => register10
32684
33043
  });
33044
+
33045
+ // ../skill-runtime/dist/skills/world-observe.js
32685
33046
  init_v3();
33047
+ var worldObserveInputSchema = external_exports.object({
33048
+ worldId: external_exports.string()
33049
+ });
33050
+ var worldObserveSkill = defineSkill({
33051
+ name: "world-observe",
33052
+ description: "Watch a world's reasoning process and retrieve its current thought stream.",
33053
+ inputSchema: worldObserveInputSchema,
33054
+ handler: (_input) => "Observation is coming in a future release. This feature will stream a world's reasoning in real-time."
33055
+ });
33056
+
33057
+ // ../mcp-server/src/tools/world-observe.ts
32686
33058
  function register10(server, ctx, initError) {
33059
+ const { description, inputSchema } = worldObserveSkill.asMcpTool();
32687
33060
  server.tool(
32688
33061
  "olam_observe",
32689
- "Watch a world's reasoning process and retrieve its current thought stream.",
32690
- {
32691
- worldId: external_exports.string()
32692
- },
33062
+ description,
33063
+ inputSchema,
32693
33064
  async (_params) => {
32694
33065
  if (!ctx) {
32695
33066
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -32711,7 +33082,6 @@ var world_enter_exports = {};
32711
33082
  __export(world_enter_exports, {
32712
33083
  register: () => register11
32713
33084
  });
32714
- init_v3();
32715
33085
 
32716
33086
  // ../core/dist/orchestrator/enter.js
32717
33087
  function getEnterCommand(worldId, containerId, provider, sshHost) {
@@ -32747,14 +33117,25 @@ function getEnterCommand(worldId, containerId, provider, sshHost) {
32747
33117
  };
32748
33118
  }
32749
33119
 
33120
+ // ../skill-runtime/dist/skills/world-enter.js
33121
+ init_v3();
33122
+ var worldEnterInputSchema = external_exports.object({
33123
+ worldId: external_exports.string()
33124
+ });
33125
+ var worldEnterSkill = defineSkill({
33126
+ name: "world-enter",
33127
+ description: "Enter a world for interactive collaboration within its isolated environment.",
33128
+ inputSchema: worldEnterInputSchema,
33129
+ handler: ({ worldId }) => `Enter requested for world: ${worldId}`
33130
+ });
33131
+
32750
33132
  // ../mcp-server/src/tools/world-enter.ts
32751
33133
  function register11(server, ctx, initError) {
33134
+ const { description, inputSchema } = worldEnterSkill.asMcpTool();
32752
33135
  server.tool(
32753
33136
  "olam_enter",
32754
- "Enter a world for interactive collaboration within its isolated environment.",
32755
- {
32756
- worldId: external_exports.string()
32757
- },
33137
+ description,
33138
+ inputSchema,
32758
33139
  async ({ worldId }) => {
32759
33140
  if (!ctx) {
32760
33141
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -32805,7 +33186,6 @@ var world_crystallize_exports = {};
32805
33186
  __export(world_crystallize_exports, {
32806
33187
  register: () => register12
32807
33188
  });
32808
- init_v3();
32809
33189
  import "node:path";
32810
33190
  import * as fs10 from "node:fs";
32811
33191
 
@@ -32818,14 +33198,25 @@ function computeGraphChecksum(nodes, edges) {
32818
33198
  return createHash2("sha256").update(payload).digest("hex");
32819
33199
  }
32820
33200
 
33201
+ // ../skill-runtime/dist/skills/world-crystallize.js
33202
+ init_v3();
33203
+ var worldCrystallizeInputSchema = external_exports.object({
33204
+ worldId: external_exports.string()
33205
+ });
33206
+ var worldCrystallizeSkill = defineSkill({
33207
+ name: "world-crystallize",
33208
+ description: "Save a world's current thoughts and reasoning into a persistent thought graph via Pleri Plane.",
33209
+ inputSchema: worldCrystallizeInputSchema,
33210
+ handler: (_input) => "Crystallization requires an active OlamContext with a configured Pleri connection. Use the MCP tool surface or HTTP endpoint with a configured host."
33211
+ });
33212
+
32821
33213
  // ../mcp-server/src/tools/world-crystallize.ts
32822
33214
  function register12(server, ctx, initError) {
33215
+ const { description, inputSchema } = worldCrystallizeSkill.asMcpTool();
32823
33216
  server.tool(
32824
33217
  "olam_crystallize",
32825
- "Save a world's current thoughts and reasoning into a persistent thought graph via Pleri Plane.",
32826
- {
32827
- worldId: external_exports.string()
32828
- },
33218
+ description,
33219
+ inputSchema,
32829
33220
  async (params) => {
32830
33221
  if (!ctx) {
32831
33222
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -32953,78 +33344,6 @@ init_v3();
32953
33344
 
32954
33345
  // ../skill-runtime/dist/skills/olam-status.js
32955
33346
  init_v3();
32956
-
32957
- // ../skill-runtime/dist/define-skill.js
32958
- var KEBAB_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
32959
- function defineSkill(spec) {
32960
- if (!KEBAB_RE.test(spec.name)) {
32961
- throw new Error(`defineSkill: name "${spec.name}" must be kebab-case (lowercase letters, digits, and hyphens only; no leading/trailing/double hyphens).`);
32962
- }
32963
- return {
32964
- asMcpTool() {
32965
- return {
32966
- name: spec.name,
32967
- description: spec.description,
32968
- inputSchema: spec.inputSchema,
32969
- async handler(params) {
32970
- try {
32971
- const parsed = spec.inputSchema.safeParse(params);
32972
- if (!parsed.success) {
32973
- return {
32974
- content: [
32975
- {
32976
- type: "text",
32977
- text: `Invalid input: ${parsed.error.message}`
32978
- }
32979
- ],
32980
- isError: true
32981
- };
32982
- }
32983
- const output = await spec.handler(parsed.data);
32984
- return {
32985
- content: [
32986
- {
32987
- type: "text",
32988
- text: typeof output === "string" ? output : JSON.stringify(output)
32989
- }
32990
- ]
32991
- };
32992
- } catch (err) {
32993
- const message = err instanceof Error ? err.message : String(err);
32994
- return {
32995
- content: [{ type: "text", text: `Error: ${message}` }],
32996
- isError: true
32997
- };
32998
- }
32999
- }
33000
- };
33001
- },
33002
- asHttpHandler() {
33003
- return async (req, res) => {
33004
- const parsed = spec.inputSchema.safeParse(req.body);
33005
- if (!parsed.success) {
33006
- res.status(400).json({
33007
- error: "Invalid input",
33008
- issues: parsed.error.issues
33009
- });
33010
- return;
33011
- }
33012
- try {
33013
- const output = await spec.handler(parsed.data);
33014
- res.status(200).json({ result: output });
33015
- } catch (err) {
33016
- const message = err instanceof Error ? err.message : String(err);
33017
- res.status(500).json({ error: message });
33018
- }
33019
- };
33020
- },
33021
- toJsonSchema() {
33022
- return zodToJsonSchema(spec.inputSchema, { target: "openApi3" });
33023
- }
33024
- };
33025
- }
33026
-
33027
- // ../skill-runtime/dist/skills/olam-status.js
33028
33347
  var olamStatusInputSchema = external_exports.object({
33029
33348
  world: external_exports.object({
33030
33349
  id: external_exports.string(),
@@ -33135,11 +33454,24 @@ var control_plane_exports = {};
33135
33454
  __export(control_plane_exports, {
33136
33455
  register: () => register14
33137
33456
  });
33457
+
33458
+ // ../skill-runtime/dist/skills/control-plane.js
33459
+ init_v3();
33460
+ var controlPlaneInputSchema = external_exports.object({});
33461
+ var controlPlaneSkill = defineSkill({
33462
+ name: "control-plane",
33463
+ description: "Access the Olam control plane dashboard URL and status.",
33464
+ inputSchema: controlPlaneInputSchema,
33465
+ handler: (_input) => "Control plane access requires an active OlamContext. Use the MCP tool surface or HTTP endpoint with a configured host."
33466
+ });
33467
+
33468
+ // ../mcp-server/src/tools/control-plane.ts
33138
33469
  function register14(server, ctx, initError) {
33470
+ const { description, inputSchema } = controlPlaneSkill.asMcpTool();
33139
33471
  server.tool(
33140
33472
  "olam_control_plane",
33141
- "Access the Olam control plane dashboard URL and status.",
33142
- {},
33473
+ description,
33474
+ inputSchema,
33143
33475
  async () => {
33144
33476
  if (!ctx) {
33145
33477
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -33170,18 +33502,36 @@ var lane_create_exports = {};
33170
33502
  __export(lane_create_exports, {
33171
33503
  register: () => register15
33172
33504
  });
33505
+
33506
+ // ../skill-runtime/dist/skills/lane-create.js
33173
33507
  init_v3();
33508
+ var laneCreateInputSchema = external_exports.object({
33509
+ worldId: external_exports.string(),
33510
+ name: external_exports.string().describe("Kebab-case lane name (e.g., auth-fix, add-tests)"),
33511
+ task: external_exports.string().describe("Task description for the lane agent"),
33512
+ scope: external_exports.array(external_exports.string()).describe("File globs this lane is allowed to modify"),
33513
+ avoids: external_exports.array(external_exports.string()).optional().describe("File globs this lane must not touch")
33514
+ });
33515
+ var laneCreateSkill = defineSkill({
33516
+ name: "lane-create",
33517
+ description: "Create a new parallel lane within a world for isolated task execution with file-level locking.",
33518
+ inputSchema: laneCreateInputSchema,
33519
+ handler: (input) => JSON.stringify({
33520
+ worldId: input.worldId,
33521
+ name: input.name,
33522
+ task: input.task,
33523
+ scope: input.scope,
33524
+ avoids: input.avoids ?? []
33525
+ }, null, 2)
33526
+ });
33527
+
33528
+ // ../mcp-server/src/tools/lane-create.ts
33174
33529
  function register15(server, ctx, initError) {
33530
+ const { description, inputSchema } = laneCreateSkill.asMcpTool();
33175
33531
  server.tool(
33176
33532
  "olam_create_lane",
33177
- "Create a new parallel lane within a world for isolated task execution with file-level locking.",
33178
- {
33179
- worldId: external_exports.string(),
33180
- name: external_exports.string().describe("Kebab-case lane name (e.g., auth-fix, add-tests)"),
33181
- task: external_exports.string().describe("Task description for the lane agent"),
33182
- scope: external_exports.array(external_exports.string()).describe("File globs this lane is allowed to modify"),
33183
- avoids: external_exports.array(external_exports.string()).optional().describe("File globs this lane must not touch")
33184
- },
33533
+ description,
33534
+ inputSchema,
33185
33535
  async (params) => {
33186
33536
  if (!ctx) {
33187
33537
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -33253,14 +33603,26 @@ var lane_list_exports = {};
33253
33603
  __export(lane_list_exports, {
33254
33604
  register: () => register16
33255
33605
  });
33606
+
33607
+ // ../skill-runtime/dist/skills/lane-list.js
33256
33608
  init_v3();
33609
+ var laneListInputSchema = external_exports.object({
33610
+ worldId: external_exports.string()
33611
+ });
33612
+ var laneListSkill = defineSkill({
33613
+ name: "lane-list",
33614
+ description: "List all lanes in a world and their current status.",
33615
+ inputSchema: laneListInputSchema,
33616
+ handler: (_input) => "Lane listing requires an active OlamContext. Use the MCP tool surface or HTTP endpoint with a configured host."
33617
+ });
33618
+
33619
+ // ../mcp-server/src/tools/lane-list.ts
33257
33620
  function register16(server, ctx, initError) {
33621
+ const { description, inputSchema } = laneListSkill.asMcpTool();
33258
33622
  server.tool(
33259
33623
  "olam_list_lanes",
33260
- "List all lanes in a world and their current status.",
33261
- {
33262
- worldId: external_exports.string()
33263
- },
33624
+ description,
33625
+ inputSchema,
33264
33626
  async (params) => {
33265
33627
  if (!ctx) {
33266
33628
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -33324,16 +33686,37 @@ var lane_dispatch_exports = {};
33324
33686
  __export(lane_dispatch_exports, {
33325
33687
  register: () => register17
33326
33688
  });
33689
+
33690
+ // ../skill-runtime/dist/skills/lane-dispatch.js
33327
33691
  init_v3();
33692
+ var laneDispatchInputSchema = external_exports.object({
33693
+ worldId: external_exports.string(),
33694
+ laneName: external_exports.string(),
33695
+ prompt: external_exports.string()
33696
+ });
33697
+ var laneDispatchSkill = defineSkill({
33698
+ name: "lane-dispatch",
33699
+ description: "Send a task prompt to a specific lane within a world.",
33700
+ inputSchema: laneDispatchInputSchema,
33701
+ handler: (input) => {
33702
+ const lines = [
33703
+ `Dispatch queued for lane.`,
33704
+ ``,
33705
+ ` worldId: ${input.worldId}`,
33706
+ ` lane: ${input.laneName}`,
33707
+ ` prompt: ${input.prompt.slice(0, 100)}${input.prompt.length > 100 ? "..." : ""}`
33708
+ ];
33709
+ return lines.join("\n");
33710
+ }
33711
+ });
33712
+
33713
+ // ../mcp-server/src/tools/lane-dispatch.ts
33328
33714
  function register17(server, ctx, initError) {
33715
+ const { description, inputSchema } = laneDispatchSkill.asMcpTool();
33329
33716
  server.tool(
33330
33717
  "olam_dispatch_lane",
33331
- "Send a task prompt to a specific lane within a world.",
33332
- {
33333
- worldId: external_exports.string(),
33334
- laneName: external_exports.string(),
33335
- prompt: external_exports.string()
33336
- },
33718
+ description,
33719
+ inputSchema,
33337
33720
  async (params) => {
33338
33721
  if (!ctx) {
33339
33722
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -33399,15 +33782,27 @@ var lane_destroy_exports = {};
33399
33782
  __export(lane_destroy_exports, {
33400
33783
  register: () => register18
33401
33784
  });
33785
+
33786
+ // ../skill-runtime/dist/skills/lane-destroy.js
33402
33787
  init_v3();
33788
+ var laneDestroyInputSchema = external_exports.object({
33789
+ worldId: external_exports.string(),
33790
+ laneName: external_exports.string()
33791
+ });
33792
+ var laneDestroySkill = defineSkill({
33793
+ name: "lane-destroy",
33794
+ description: "Destroy a lane within a world and release its file locks.",
33795
+ inputSchema: laneDestroyInputSchema,
33796
+ handler: (input) => `Lane destruction requires an active OlamContext. Target: world="${input.worldId}", lane="${input.laneName}".`
33797
+ });
33798
+
33799
+ // ../mcp-server/src/tools/lane-destroy.ts
33403
33800
  function register18(server, ctx, initError) {
33801
+ const { description, inputSchema } = laneDestroySkill.asMcpTool();
33404
33802
  server.tool(
33405
33803
  "olam_destroy_lane",
33406
- "Destroy a lane within a world and release its file locks.",
33407
- {
33408
- worldId: external_exports.string(),
33409
- laneName: external_exports.string()
33410
- },
33804
+ description,
33805
+ inputSchema,
33411
33806
  async (params) => {
33412
33807
  if (!ctx) {
33413
33808
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -33459,15 +33854,32 @@ var lane_merge_exports = {};
33459
33854
  __export(lane_merge_exports, {
33460
33855
  register: () => register19
33461
33856
  });
33857
+
33858
+ // ../skill-runtime/dist/skills/lane-merge.js
33462
33859
  init_v3();
33860
+ var laneMergeInputSchema = external_exports.object({
33861
+ worldId: external_exports.string(),
33862
+ laneName: external_exports.string()
33863
+ });
33864
+ var laneMergeSkill = defineSkill({
33865
+ name: "lane-merge",
33866
+ description: "Merge a lane's changes back into the world's main branch.",
33867
+ inputSchema: laneMergeInputSchema,
33868
+ handler: (input) => {
33869
+ return `Lane merge queued.
33870
+
33871
+ worldId: ${input.worldId}
33872
+ lane: ${input.laneName}`;
33873
+ }
33874
+ });
33875
+
33876
+ // ../mcp-server/src/tools/lane-merge.ts
33463
33877
  function register19(server, ctx, initError) {
33878
+ const { description, inputSchema } = laneMergeSkill.asMcpTool();
33464
33879
  server.tool(
33465
33880
  "olam_merge_lane",
33466
- "Merge a lane's changes back into the world's main branch.",
33467
- {
33468
- worldId: external_exports.string(),
33469
- laneName: external_exports.string()
33470
- },
33881
+ description,
33882
+ inputSchema,
33471
33883
  async (params) => {
33472
33884
  if (!ctx) {
33473
33885
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -34282,6 +34694,67 @@ function checkLiteral(host, allowLoopback) {
34282
34694
  return null;
34283
34695
  }
34284
34696
 
34697
+ // ../skill-runtime/dist/skills/capture-view.js
34698
+ init_v3();
34699
+ var SHOT_NAME_RE = /^[A-Za-z0-9._-]+$/;
34700
+ var shotSpec = external_exports.object({
34701
+ name: external_exports.string().min(1).max(64).regex(SHOT_NAME_RE, "name must match /^[A-Za-z0-9._-]+$/ \u2014 no slashes, spaces, or path separators").describe("Shot identifier; written as `<name>.png` in `outDir`. Must be unique within a `capture_view` call."),
34702
+ url: external_exports.string().describe("Page URL. May be absolute (`https://\u2026`) or world-relative (`world://<world_id>/<path>`). Rejects `file://`, `chrome-extension://`, `about:`, `javascript:`, `data:`, RFC1918, link-local, cloud-metadata."),
34703
+ viewport: external_exports.object({
34704
+ width: external_exports.number().int().min(320).max(3840),
34705
+ height: external_exports.number().int().min(240).max(2160)
34706
+ }).optional().describe("Browser viewport in CSS pixels. Default `{1280,800}`."),
34707
+ deviceScaleFactor: external_exports.number().int().min(1).max(2).optional().describe("Default 1; cap 2 to keep mobile GPUs sane."),
34708
+ media: external_exports.object({
34709
+ reducedMotion: external_exports.enum(["no-preference", "reduce"]).optional(),
34710
+ colorScheme: external_exports.enum(["light", "dark"]).optional()
34711
+ }).optional().describe("CSS media-feature emulation. Use to capture reduced-motion fallbacks, dark-mode renders, etc."),
34712
+ waitForSelector: external_exports.string().optional().describe("CSS selector to wait for before screenshot."),
34713
+ waitForNetworkIdle: external_exports.boolean().optional().describe("Wait for `networkidle` event before screenshot. Default true."),
34714
+ afterLoadMs: external_exports.number().int().min(0).max(1e4).optional().describe("Sleep N ms after load before screenshot. Use to let WebGL/canvas animations reach a non-zero frame."),
34715
+ fill: external_exports.record(external_exports.string(), external_exports.string()).optional().describe("Selector \u2192 value map. Filled before `submit` (if any). Keys are CSS selectors, values are literal strings."),
34716
+ submit: external_exports.string().optional().describe("Form selector to `requestSubmit()` after `fill`."),
34717
+ afterSubmitMs: external_exports.number().int().min(0).max(1e4).optional().describe("Sleep N ms after submit before screenshot. Use to let success-card render."),
34718
+ mockFetch: external_exports.array(external_exports.object({
34719
+ pattern: external_exports.string().min(1).describe("URL match pattern. Forms: `/regex/` treats inner as RegExp source; otherwise matched as a literal substring."),
34720
+ method: external_exports.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method filter. When set, only requests with this method are intercepted."),
34721
+ status: external_exports.number().int().default(200),
34722
+ bodyJson: external_exports.unknown().optional(),
34723
+ bodyText: external_exports.string().optional()
34724
+ })).max(64).optional().describe("Intercept fetch/XHR matching the pattern; return the canned response. Max 64 entries per shot."),
34725
+ setStorage: external_exports.record(external_exports.enum(["local", "session"]), external_exports.record(external_exports.string().min(1).max(128), external_exports.string().max(64 * 1024))).refine((s) => {
34726
+ let total = 0;
34727
+ if (s.local)
34728
+ total += Object.keys(s.local).length;
34729
+ if (s.session)
34730
+ total += Object.keys(s.session).length;
34731
+ return total <= 50;
34732
+ }, { message: "setStorage entries (local + session combined) must not exceed 50 keys" }).optional().describe("Pre-load LocalStorage / SessionStorage entries before navigation. Per scope: keys \u2264 128 chars, values \u2264 64 KB. Combined (local + session) total \u2264 50 entries."),
34733
+ eval: external_exports.string().optional().describe("Raw page-script run after navigation, before screenshot. Gated behind `--allow-eval` on the calling skill.")
34734
+ });
34735
+ var captureViewInputSchema = external_exports.object({
34736
+ shots: external_exports.array(shotSpec).min(1).max(50).refine((shots) => new Set(shots.map((s) => s.name)).size === shots.length, { message: "shot.name must be unique within a single capture_view call" }).describe("Shots to capture. One Chromium boot per call; reused across shots. Names must be unique within the call."),
34737
+ outDir: external_exports.string().describe("Host-side directory to write artifacts. Created if missing. Files are `<name>.png` plus `manifest.json`."),
34738
+ format: external_exports.enum(["png", "jpeg"]).default("png").describe("Output format. Default `png`."),
34739
+ jpegQuality: external_exports.number().int().min(50).max(100).default(85).describe("JPEG quality if `format='jpeg'`."),
34740
+ ttlSeconds: external_exports.number().int().min(30).max(600).default(120).describe("Capability token TTL. Capped at 60 when called from inside a world."),
34741
+ allowEval: external_exports.boolean().default(false).describe("Permit `eval` page-scripts in shots. Default false.")
34742
+ });
34743
+ var captureViewSkill = defineSkill({
34744
+ name: "capture-view",
34745
+ description: "Brokered screenshot primitive: take spec-driven screenshots of a web app via the supervisor's Chromium. Used by the olam:ui-shoot skill (host) and by autonomous in-world agents (which cannot run Playwright themselves). Worlds never get raw browser access; they request artifacts here, the supervisor renders.",
34746
+ inputSchema: captureViewInputSchema,
34747
+ handler: (input) => {
34748
+ const shotNames = input.shots.map((s) => s.name).join(", ");
34749
+ return [
34750
+ `Would capture ${input.shots.length} shot(s) to ${input.outDir}`,
34751
+ ` shots: ${shotNames}`,
34752
+ ` format: ${input.format}`,
34753
+ "Use the MCP tool for actual Chromium execution (requires OlamContext + Playwright)."
34754
+ ].join("\n");
34755
+ }
34756
+ });
34757
+
34285
34758
  // ../mcp-server/src/tools/capture-view.ts
34286
34759
  var CHROMIUM_CONCURRENCY_CAP = Math.max(
34287
34760
  1,
@@ -34400,9 +34873,9 @@ async function rewriteShotUrl(ctx, shotUrl, cache2) {
34400
34873
  url: `http://${endpoint.host}:${endpoint.port}${parsed.pathname}${parsed.search}`
34401
34874
  };
34402
34875
  }
34403
- var SHOT_NAME_RE = /^[A-Za-z0-9._-]+$/;
34404
- var shotSpec = external_exports.object({
34405
- name: external_exports.string().min(1).max(64).regex(SHOT_NAME_RE, "name must match /^[A-Za-z0-9._-]+$/ \u2014 no slashes, spaces, or path separators").describe(
34876
+ var SHOT_NAME_RE2 = /^[A-Za-z0-9._-]+$/;
34877
+ var shotSpec2 = external_exports.object({
34878
+ name: external_exports.string().min(1).max(64).regex(SHOT_NAME_RE2, "name must match /^[A-Za-z0-9._-]+$/ \u2014 no slashes, spaces, or path separators").describe(
34406
34879
  "Shot identifier; written as `<name>.png` in `outDir`. Must be unique within a `capture_view` call. Letters/digits/dots/dashes/underscores only \u2014 schema-level guard against path traversal via filename."
34407
34880
  ),
34408
34881
  url: external_exports.string().describe(
@@ -34472,7 +34945,7 @@ var shotSpec = external_exports.object({
34472
34945
  )
34473
34946
  });
34474
34947
  var captureViewInput = {
34475
- shots: external_exports.array(shotSpec).min(1).max(50).refine(
34948
+ shots: external_exports.array(shotSpec2).min(1).max(50).refine(
34476
34949
  (shots) => new Set(shots.map((s) => s.name)).size === shots.length,
34477
34950
  // Without this refine, two shots with the same name would silently
34478
34951
  // overwrite each other on disk while the success envelope reports
@@ -34623,10 +35096,11 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
34623
35096
  }
34624
35097
  }
34625
35098
  function register20(server, ctx, initError) {
35099
+ const { description, inputSchema } = captureViewSkill.asMcpTool();
34626
35100
  server.tool(
34627
35101
  "olam_capture_view",
34628
- "Brokered screenshot primitive: take spec-driven screenshots of a web app via the supervisor's Chromium. Used by the olam:ui-shoot skill (host) and by autonomous in-world agents (which cannot run Playwright themselves). Worlds never get raw browser access; they request artifacts here, the supervisor renders.",
34629
- captureViewInput,
35102
+ description,
35103
+ inputSchema,
34630
35104
  async (params) => {
34631
35105
  if (!ctx) {
34632
35106
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -34889,7 +35363,47 @@ var create_from_prompt_exports = {};
34889
35363
  __export(create_from_prompt_exports, {
34890
35364
  register: () => register21
34891
35365
  });
35366
+
35367
+ // ../skill-runtime/dist/skills/create-from-prompt.js
34892
35368
  init_v3();
35369
+ var createFromPromptInputSchema = external_exports.object({
35370
+ prompt: external_exports.string().min(1).describe("Natural-language task. Repo names extracted via heuristic; falls back to picker on ambiguity."),
35371
+ repos: external_exports.array(external_exports.string()).optional().describe("Explicit repos. Bypasses NL inference."),
35372
+ workspace: external_exports.string().optional().describe("Named workspace. Bypasses inference + match."),
35373
+ name: external_exports.string().optional().describe("World name. Defaults to slugified prompt."),
35374
+ autoCodexReview: external_exports.boolean().optional().describe("Spawn parallel codex-review sub-lane (Phase C9)."),
35375
+ noOpen: external_exports.boolean().optional().describe("Suppress browser auto-open after world is up."),
35376
+ carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false")
35377
+ });
35378
+ var createFromPromptSkill = defineSkill({
35379
+ name: "create-from-prompt",
35380
+ description: "Phase D one-shot world creator: NL prompt \u2192 workspace match \u2192 world create + auto-dispatch + browser open. Returns picker payload on inference ambiguity.",
35381
+ inputSchema: createFromPromptInputSchema,
35382
+ handler: (input) => {
35383
+ const parts = [
35384
+ `Create-from-prompt requires an active OlamContext with WorldManager.`,
35385
+ ``,
35386
+ ` prompt: ${input.prompt.slice(0, 80)}${input.prompt.length > 80 ? "\u2026" : ""}`
35387
+ ];
35388
+ if (input.repos && input.repos.length > 0) {
35389
+ parts.push(` repos: ${input.repos.join(", ")}`);
35390
+ }
35391
+ if (input.workspace) {
35392
+ parts.push(` workspace: ${input.workspace}`);
35393
+ }
35394
+ if (input.name) {
35395
+ parts.push(` name: ${input.name}`);
35396
+ }
35397
+ if (input.autoCodexReview) {
35398
+ parts.push(` autoCodexReview: true`);
35399
+ }
35400
+ if (input.carryUncommitted) {
35401
+ parts.push(` carryUncommitted: true`);
35402
+ }
35403
+ parts.push(``, `Use the MCP tool surface or HTTP endpoint with a configured host.`);
35404
+ return parts.join("\n");
35405
+ }
35406
+ });
34893
35407
 
34894
35408
  // ../core/dist/world/infer-repos.js
34895
35409
  var PICKER_CONFIDENCE_THRESHOLD = 0.7;
@@ -35106,20 +35620,11 @@ function defaultNameFromPrompt(prompt) {
35106
35620
  return slug || "unnamed";
35107
35621
  }
35108
35622
  function register21(server, ctx, initError) {
35623
+ const { description, inputSchema } = createFromPromptSkill.asMcpTool();
35109
35624
  server.tool(
35110
35625
  "olam_create_from_prompt",
35111
- "Phase D one-shot world creator: NL prompt \u2192 workspace match \u2192 world create + auto-dispatch + browser open. Returns picker payload on inference ambiguity.",
35112
- {
35113
- prompt: external_exports.string().min(1).describe("Natural-language task. Repo names extracted via heuristic; falls back to picker on ambiguity."),
35114
- repos: external_exports.array(external_exports.string()).optional().describe("Explicit repos. Bypasses NL inference."),
35115
- workspace: external_exports.string().optional().describe("Named workspace. Bypasses inference + match."),
35116
- name: external_exports.string().optional().describe("World name. Defaults to slugified prompt."),
35117
- autoCodexReview: external_exports.boolean().optional().describe("Spawn parallel codex-review sub-lane (Phase C9)."),
35118
- noOpen: external_exports.boolean().optional().describe("Suppress browser auto-open after world is up."),
35119
- // Phase B B3 (olam-session-stability): mirror of CLI's
35120
- // --carry-uncommitted flag. Default OFF.
35121
- carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false")
35122
- },
35626
+ description,
35627
+ inputSchema,
35123
35628
  async (params) => {
35124
35629
  if (!ctx) {
35125
35630
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -35297,16 +35802,80 @@ var repo_exports = {};
35297
35802
  __export(repo_exports, {
35298
35803
  register: () => register22
35299
35804
  });
35300
- init_v3();
35301
35805
  init_global_config();
35806
+
35807
+ // ../skill-runtime/dist/skills/repo-list.js
35808
+ init_v3();
35809
+ var repoListInputSchema = external_exports.object({});
35810
+ var repoListSkill = defineSkill({
35811
+ name: "repo-list",
35812
+ description: "List every repo registered in ~/.olam/config.json. Returns { repos: RepoEntry[] }.",
35813
+ inputSchema: repoListInputSchema,
35814
+ handler: (_input) => "Repo listing requires access to ~/.olam/config.json. Use the MCP tool surface."
35815
+ });
35816
+
35817
+ // ../skill-runtime/dist/skills/repo-add.js
35818
+ init_v3();
35819
+ var repoAddInputSchema = external_exports.object({
35820
+ name: external_exports.string().min(1).describe("Repo name (lowercase, digits, dash; 1\u201364 chars)."),
35821
+ path: external_exports.string().min(1).describe("Absolute or ~/... path to the local repo directory."),
35822
+ description: external_exports.string().optional().describe("Optional human-readable description."),
35823
+ defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
35824
+ });
35825
+ var repoAddSkill = defineSkill({
35826
+ name: "repo-add",
35827
+ description: "Register a local repo path in the global registry. The path must exist on disk. Rejects duplicate names.",
35828
+ inputSchema: repoAddInputSchema,
35829
+ handler: (input) => `Would register repo "${input.name}" at ${input.path}. Use the MCP tool for actual file system execution.`
35830
+ });
35831
+
35832
+ // ../skill-runtime/dist/skills/repo-remove.js
35833
+ init_v3();
35834
+ var repoRemoveInputSchema = external_exports.object({
35835
+ name: external_exports.string().min(1).describe("Repo name to remove.")
35836
+ });
35837
+ var repoRemoveSkill = defineSkill({
35838
+ name: "repo-remove",
35839
+ description: "Remove a repo from the global registry. Does not delete any files on disk.",
35840
+ inputSchema: repoRemoveInputSchema,
35841
+ handler: (input) => `Would remove repo "${input.name}" from the global registry. Use the MCP tool for actual execution.`
35842
+ });
35843
+
35844
+ // ../skill-runtime/dist/skills/repo-update.js
35845
+ init_v3();
35846
+ var repoUpdateInputSchema = external_exports.object({
35847
+ name: external_exports.string().min(1).describe("Repo name to update."),
35848
+ path: external_exports.string().optional().describe("New local path."),
35849
+ description: external_exports.string().optional().describe("New description."),
35850
+ defaultBranch: external_exports.string().optional().describe("New default branch.")
35851
+ });
35852
+ var repoUpdateSkill = defineSkill({
35853
+ name: "repo-update",
35854
+ description: "Update a registered repo's path, description, or default branch.",
35855
+ inputSchema: repoUpdateInputSchema,
35856
+ handler: (input) => {
35857
+ const fields = [];
35858
+ if (input.path)
35859
+ fields.push(`path: ${input.path}`);
35860
+ if (input.description)
35861
+ fields.push(`description: "${input.description}"`);
35862
+ if (input.defaultBranch)
35863
+ fields.push(`defaultBranch: ${input.defaultBranch}`);
35864
+ const changes = fields.length > 0 ? fields.join(", ") : "(no changes specified)";
35865
+ return `Would update repo "${input.name}": ${changes}. Use the MCP tool for actual execution.`;
35866
+ }
35867
+ });
35868
+
35869
+ // ../mcp-server/src/tools/repo.ts
35302
35870
  function asMessage4(err) {
35303
35871
  return err instanceof Error ? err.message : String(err);
35304
35872
  }
35305
35873
  function register22(server, _ctx, _initError) {
35874
+ const repoListTool = repoListSkill.asMcpTool();
35306
35875
  server.tool(
35307
35876
  "olam_repo_list",
35308
- "List every repo registered in ~/.olam/config.json. Returns { repos: RepoEntry[] }.",
35309
- {},
35877
+ repoListTool.description,
35878
+ repoListTool.inputSchema,
35310
35879
  async () => {
35311
35880
  const repos = listRepos();
35312
35881
  return {
@@ -35317,15 +35886,11 @@ function register22(server, _ctx, _initError) {
35317
35886
  };
35318
35887
  }
35319
35888
  );
35889
+ const repoAddTool = repoAddSkill.asMcpTool();
35320
35890
  server.tool(
35321
35891
  "olam_repo_add",
35322
- "Register a local repo path in the global registry. The path must exist on disk. Rejects duplicate names.",
35323
- {
35324
- name: external_exports.string().min(1).describe("Repo name (lowercase, digits, dash; 1\u201364 chars)."),
35325
- path: external_exports.string().min(1).describe("Absolute or ~/... path to the local repo directory."),
35326
- description: external_exports.string().optional().describe("Optional human-readable description."),
35327
- defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
35328
- },
35892
+ repoAddTool.description,
35893
+ repoAddTool.inputSchema,
35329
35894
  async ({ name, path: path53, description, defaultBranch }) => {
35330
35895
  try {
35331
35896
  const entry = addRepo({ name, path: path53, description, defaultBranch });
@@ -35340,12 +35905,11 @@ function register22(server, _ctx, _initError) {
35340
35905
  }
35341
35906
  }
35342
35907
  );
35908
+ const repoRemoveTool = repoRemoveSkill.asMcpTool();
35343
35909
  server.tool(
35344
35910
  "olam_repo_remove",
35345
- "Remove a repo from the global registry. Does not delete any files on disk.",
35346
- {
35347
- name: external_exports.string().min(1).describe("Repo name to remove.")
35348
- },
35911
+ repoRemoveTool.description,
35912
+ repoRemoveTool.inputSchema,
35349
35913
  async ({ name }) => {
35350
35914
  try {
35351
35915
  removeRepo(name);
@@ -35360,15 +35924,11 @@ function register22(server, _ctx, _initError) {
35360
35924
  }
35361
35925
  }
35362
35926
  );
35927
+ const repoUpdateTool = repoUpdateSkill.asMcpTool();
35363
35928
  server.tool(
35364
35929
  "olam_repo_update",
35365
- "Update a registered repo's path, description, or default branch.",
35366
- {
35367
- name: external_exports.string().min(1).describe("Repo name to update."),
35368
- path: external_exports.string().optional().describe("New local path."),
35369
- description: external_exports.string().optional().describe("New description."),
35370
- defaultBranch: external_exports.string().optional().describe("New default branch.")
35371
- },
35930
+ repoUpdateTool.description,
35931
+ repoUpdateTool.inputSchema,
35372
35932
  async ({ name, path: path53, description, defaultBranch }) => {
35373
35933
  try {
35374
35934
  const entry = updateRepo(name, { path: path53, description, defaultBranch });
@@ -35391,10 +35951,49 @@ __export(process_port_exports, {
35391
35951
  register: () => register23,
35392
35952
  resolveHostCpToken: () => resolveHostCpToken
35393
35953
  });
35394
- init_v3();
35395
35954
  import fs35 from "node:fs";
35396
35955
  import os20 from "node:os";
35397
35956
  import path34 from "node:path";
35957
+
35958
+ // ../skill-runtime/dist/skills/process-list.js
35959
+ init_v3();
35960
+ var processListInputSchema = external_exports.object({
35961
+ world_id: external_exports.string().describe("World ID.")
35962
+ });
35963
+ var processListSkill = defineSkill({
35964
+ name: "process-list",
35965
+ description: "List running processes inside a world container. Returns a process table snapshot via host-cp. Fields per process: pid, user, cpu, mem, started, state, command.",
35966
+ inputSchema: processListInputSchema,
35967
+ handler: (input) => `Process listing requires a host-cp connection. Would fetch processes for world "${input.world_id}". Use the MCP tool surface or HTTP endpoint with a configured host.`
35968
+ });
35969
+
35970
+ // ../skill-runtime/dist/skills/port-expose.js
35971
+ init_v3();
35972
+ var portExposeInputSchema = external_exports.object({
35973
+ world_id: external_exports.string().describe("World ID."),
35974
+ port: external_exports.number().int().min(1).max(65535).describe("Container port to expose on the host.")
35975
+ });
35976
+ var portExposeSkill = defineSkill({
35977
+ name: "port-expose",
35978
+ description: "Expose a port inside a world container to the host by creating a socat bridge. Returns the host-side URL and bridge metadata. The bridge persists until removed with olam_port_unexpose.",
35979
+ inputSchema: portExposeInputSchema,
35980
+ handler: (input) => `Port expose requires a host-cp connection. Would create socat bridge for world "${input.world_id}" port ${input.port}. Use the MCP tool surface or HTTP endpoint with a configured host.`
35981
+ });
35982
+
35983
+ // ../skill-runtime/dist/skills/port-unexpose.js
35984
+ init_v3();
35985
+ var portUnexposeInputSchema = external_exports.object({
35986
+ world_id: external_exports.string().describe("World ID."),
35987
+ port: external_exports.number().int().min(1).max(65535).describe("Container port whose bridge should be removed.")
35988
+ });
35989
+ var portUnexposeSkill = defineSkill({
35990
+ name: "port-unexpose",
35991
+ description: "Tear down a port bridge for a world container. Removes the socat sidecar and frees the host port.",
35992
+ inputSchema: portUnexposeInputSchema,
35993
+ handler: (input) => `Port unexpose requires a host-cp connection. Would remove socat bridge for world "${input.world_id}" port ${input.port}. Use the MCP tool surface or HTTP endpoint with a configured host.`
35994
+ });
35995
+
35996
+ // ../mcp-server/src/tools/process-port.ts
35398
35997
  var HOST_CP_BASE = "http://127.0.0.1:19000";
35399
35998
  function resolveHostCpToken() {
35400
35999
  const envToken = process.env["OLAM_HOST_CP_TOKEN"];
@@ -35416,12 +36015,11 @@ function asMessage5(err) {
35416
36015
  return err instanceof Error ? err.message : String(err);
35417
36016
  }
35418
36017
  function register23(server, _ctx, _initError) {
36018
+ const processList = processListSkill.asMcpTool();
35419
36019
  server.tool(
35420
36020
  "olam_process_list",
35421
- "List running processes inside a world container. Returns a process table snapshot via host-cp. Fields per process: pid, user, cpu, mem, started, state, command.",
35422
- {
35423
- world_id: external_exports.string().describe("World ID.")
35424
- },
36021
+ processList.description,
36022
+ processList.inputSchema,
35425
36023
  async ({ world_id }) => {
35426
36024
  const token = resolveHostCpToken();
35427
36025
  if (!token) return tokenMissingError();
@@ -35446,13 +36044,11 @@ function register23(server, _ctx, _initError) {
35446
36044
  }
35447
36045
  }
35448
36046
  );
36047
+ const portExpose = portExposeSkill.asMcpTool();
35449
36048
  server.tool(
35450
36049
  "olam_port_expose",
35451
- "Expose a port inside a world container to the host by creating a socat bridge. Returns the host-side URL and bridge metadata. The bridge persists until removed with olam_port_unexpose.",
35452
- {
35453
- world_id: external_exports.string().describe("World ID."),
35454
- port: external_exports.number().int().min(1).max(65535).describe("Container port to expose on the host.")
35455
- },
36050
+ portExpose.description,
36051
+ portExpose.inputSchema,
35456
36052
  async ({ world_id, port: port2 }) => {
35457
36053
  const token = resolveHostCpToken();
35458
36054
  if (!token) return tokenMissingError();
@@ -35491,13 +36087,11 @@ function register23(server, _ctx, _initError) {
35491
36087
  }
35492
36088
  }
35493
36089
  );
36090
+ const portUnexpose = portUnexposeSkill.asMcpTool();
35494
36091
  server.tool(
35495
36092
  "olam_port_unexpose",
35496
- "Tear down a port bridge for a world container. Removes the socat sidecar and frees the host port.",
35497
- {
35498
- world_id: external_exports.string().describe("World ID."),
35499
- port: external_exports.number().int().min(1).max(65535).describe("Container port whose bridge should be removed.")
35500
- },
36093
+ portUnexpose.description,
36094
+ portUnexpose.inputSchema,
35501
36095
  async ({ world_id, port: port2 }) => {
35502
36096
  const token = resolveHostCpToken();
35503
36097
  if (!token) return tokenMissingError();
@@ -35527,8 +36121,90 @@ var runbook_exports = {};
35527
36121
  __export(runbook_exports, {
35528
36122
  register: () => register24
35529
36123
  });
35530
- init_v3();
35531
36124
  init_global_config();
36125
+
36126
+ // ../skill-runtime/dist/skills/runbook-list.js
36127
+ init_v3();
36128
+ var runbookListInputSchema = external_exports.object({});
36129
+ var runbookListSkill = defineSkill({
36130
+ name: "runbook-list",
36131
+ description: "List all runbooks in ~/.olam/config.json. Returns { runbooks: Runbook[] }.",
36132
+ inputSchema: runbookListInputSchema,
36133
+ handler: (_input) => JSON.stringify({ note: "runbook listing requires global config access; use MCP surface" }, null, 2)
36134
+ });
36135
+
36136
+ // ../skill-runtime/dist/skills/runbook-show.js
36137
+ init_v3();
36138
+ var runbookShowInputSchema = external_exports.object({
36139
+ name: external_exports.string().min(1).describe("Runbook name.")
36140
+ });
36141
+ var runbookShowSkill = defineSkill({
36142
+ name: "runbook-show",
36143
+ description: "Show a single runbook by name. Returns { runbook: Runbook }.",
36144
+ inputSchema: runbookShowInputSchema,
36145
+ handler: ({ name }) => JSON.stringify({ name, note: "runbook lookup requires global config access; use MCP surface" }, null, 2)
36146
+ });
36147
+
36148
+ // ../skill-runtime/dist/skills/runbook-add.js
36149
+ init_v3();
36150
+ var seedSchema = external_exports.union([
36151
+ external_exports.object({
36152
+ type: external_exports.literal("sql-file"),
36153
+ repo: external_exports.string(),
36154
+ service: external_exports.string(),
36155
+ path: external_exports.string()
36156
+ }),
36157
+ external_exports.object({ type: external_exports.literal("command"), repo: external_exports.string(), run: external_exports.string() }),
36158
+ external_exports.object({
36159
+ type: external_exports.literal("fixture-copy"),
36160
+ repo: external_exports.string(),
36161
+ src: external_exports.string(),
36162
+ dest: external_exports.string()
36163
+ })
36164
+ ]);
36165
+ var runbookAddInputSchema = external_exports.object({
36166
+ name: external_exports.string().min(1).describe("Runbook name (lowercase, digits, dash; 1\u201364 chars)."),
36167
+ repos: external_exports.array(external_exports.string().min(1)).min(1).describe("Repo names (must exist in registry)."),
36168
+ description: external_exports.string().optional().describe("Optional human-readable description."),
36169
+ portMap: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.number().int())).optional().describe("Port mappings: { repoName: { serviceName: hostPort } }."),
36170
+ seeds: external_exports.array(seedSchema).optional().describe("Optional seed operations to run when applying the runbook."),
36171
+ env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional().describe("Per-repo environment variable overrides.")
36172
+ });
36173
+ var runbookAddSkill = defineSkill({
36174
+ name: "runbook-add",
36175
+ description: "Create a new runbook. Validates that all referenced repos exist in the global registry and that portMap has no duplicates.",
36176
+ inputSchema: runbookAddInputSchema,
36177
+ handler: ({ name, repos }) => JSON.stringify({ name, repos, note: "runbook creation requires config store + registry access; use MCP surface" }, null, 2)
36178
+ });
36179
+
36180
+ // ../skill-runtime/dist/skills/runbook-remove.js
36181
+ init_v3();
36182
+ var runbookRemoveInputSchema = external_exports.object({
36183
+ name: external_exports.string().min(1).describe("Runbook name to remove.")
36184
+ });
36185
+ var runbookRemoveSkill = defineSkill({
36186
+ name: "runbook-remove",
36187
+ description: "Remove a runbook from the global config. Does not affect any running worlds.",
36188
+ inputSchema: runbookRemoveInputSchema,
36189
+ handler: ({ name }) => JSON.stringify({ name, note: "runbook removal requires config store access; use MCP surface" }, null, 2)
36190
+ });
36191
+
36192
+ // ../skill-runtime/dist/skills/runbook-apply.js
36193
+ init_v3();
36194
+ var runbookApplyInputSchema = external_exports.object({
36195
+ name: external_exports.string().min(1).describe("Runbook name."),
36196
+ worldName: external_exports.string().optional().describe("Override the world name."),
36197
+ task: external_exports.string().optional().describe("Initial task to dispatch into the world."),
36198
+ branchName: external_exports.string().optional().describe("Override the default branch name.")
36199
+ });
36200
+ var runbookApplySkill = defineSkill({
36201
+ name: "runbook-apply",
36202
+ description: "Validate ports then create a world from a runbook. Errors (isError: true) on port conflicts. Returns world metadata on success.",
36203
+ inputSchema: runbookApplyInputSchema,
36204
+ handler: ({ name, worldName, task }) => JSON.stringify({ name, worldName: worldName ?? name, task: task ?? `Apply runbook "${name}"`, note: "apply requires OlamContext + port validation; use MCP surface" }, null, 2)
36205
+ });
36206
+
36207
+ // ../mcp-server/src/tools/runbook.ts
35532
36208
  function asMessage6(err) {
35533
36209
  return err instanceof Error ? err.message : String(err);
35534
36210
  }
@@ -35540,10 +36216,11 @@ function formatConflicts(conflicts) {
35540
36216
  return lines.join("\n");
35541
36217
  }
35542
36218
  function register24(server, ctx, _initError) {
36219
+ const listTool = runbookListSkill.asMcpTool();
35543
36220
  server.tool(
35544
36221
  "olam_runbook_list",
35545
- "List all runbooks in ~/.olam/config.json. Returns { runbooks: Runbook[] }.",
35546
- {},
36222
+ listTool.description,
36223
+ listTool.inputSchema,
35547
36224
  async () => {
35548
36225
  const runbooks = listRunbooks();
35549
36226
  return {
@@ -35551,12 +36228,11 @@ function register24(server, ctx, _initError) {
35551
36228
  };
35552
36229
  }
35553
36230
  );
36231
+ const showTool = runbookShowSkill.asMcpTool();
35554
36232
  server.tool(
35555
36233
  "olam_runbook_show",
35556
- "Show a single runbook by name. Returns { runbook: Runbook }.",
35557
- {
35558
- name: external_exports.string().min(1).describe("Runbook name.")
35559
- },
36234
+ showTool.description,
36235
+ showTool.inputSchema,
35560
36236
  async ({ name }) => {
35561
36237
  try {
35562
36238
  const runbook = getRunbook(name);
@@ -35568,23 +36244,11 @@ function register24(server, ctx, _initError) {
35568
36244
  }
35569
36245
  }
35570
36246
  );
36247
+ const addTool = runbookAddSkill.asMcpTool();
35571
36248
  server.tool(
35572
36249
  "olam_runbook_add",
35573
- "Create a new runbook. Validates that all referenced repos exist in the global registry and that portMap has no duplicates.",
35574
- {
35575
- name: external_exports.string().min(1).describe("Runbook name (lowercase, digits, dash; 1\u201364 chars)."),
35576
- repos: external_exports.array(external_exports.string().min(1)).min(1).describe("Repo names (must exist in registry)."),
35577
- description: external_exports.string().optional().describe("Optional human-readable description."),
35578
- portMap: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.number().int())).optional().describe("Port mappings: { repoName: { serviceName: hostPort } }."),
35579
- seeds: external_exports.array(
35580
- external_exports.union([
35581
- external_exports.object({ type: external_exports.literal("sql-file"), repo: external_exports.string(), service: external_exports.string(), path: external_exports.string() }),
35582
- external_exports.object({ type: external_exports.literal("command"), repo: external_exports.string(), run: external_exports.string() }),
35583
- external_exports.object({ type: external_exports.literal("fixture-copy"), repo: external_exports.string(), src: external_exports.string(), dest: external_exports.string() })
35584
- ])
35585
- ).optional().describe("Optional seed operations to run when applying the runbook."),
35586
- env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional().describe("Per-repo environment variable overrides.")
35587
- },
36250
+ addTool.description,
36251
+ addTool.inputSchema,
35588
36252
  async ({ name, repos, description, portMap, seeds, env }) => {
35589
36253
  try {
35590
36254
  const runbook = addRunbook({ name, repos, description, portMap, seeds, env });
@@ -35599,12 +36263,11 @@ function register24(server, ctx, _initError) {
35599
36263
  }
35600
36264
  }
35601
36265
  );
36266
+ const removeTool = runbookRemoveSkill.asMcpTool();
35602
36267
  server.tool(
35603
36268
  "olam_runbook_remove",
35604
- "Remove a runbook from the global config. Does not affect any running worlds.",
35605
- {
35606
- name: external_exports.string().min(1).describe("Runbook name to remove.")
35607
- },
36269
+ removeTool.description,
36270
+ removeTool.inputSchema,
35608
36271
  async ({ name }) => {
35609
36272
  try {
35610
36273
  removeRunbook(name);
@@ -35619,15 +36282,11 @@ function register24(server, ctx, _initError) {
35619
36282
  }
35620
36283
  }
35621
36284
  );
36285
+ const applyTool = runbookApplySkill.asMcpTool();
35622
36286
  server.tool(
35623
36287
  "olam_runbook_apply",
35624
- "Validate ports then create a world from a runbook. Errors (isError: true) on port conflicts. Returns world metadata on success.",
35625
- {
35626
- name: external_exports.string().min(1).describe("Runbook name."),
35627
- worldName: external_exports.string().optional().describe("Override the world name."),
35628
- task: external_exports.string().optional().describe("Initial task to dispatch into the world."),
35629
- branchName: external_exports.string().optional().describe("Override the default branch name.")
35630
- },
36288
+ applyTool.description,
36289
+ applyTool.inputSchema,
35631
36290
  async ({ name, worldName, task, branchName }) => {
35632
36291
  if (!ctx) {
35633
36292
  return {
@@ -35686,8 +36345,70 @@ var skill_source_exports = {};
35686
36345
  __export(skill_source_exports, {
35687
36346
  register: () => register25
35688
36347
  });
35689
- init_v3();
35690
36348
  init_skill_sources();
36349
+
36350
+ // ../skill-runtime/dist/skills/skills-source-list.js
36351
+ init_v3();
36352
+ var skillsSourceListInputSchema = external_exports.object({});
36353
+ var skillsSourceListSkill = defineSkill({
36354
+ name: "skills-source-list",
36355
+ description: "List every registered skill source. Returns { skillSources: SkillSource[] }.",
36356
+ inputSchema: skillsSourceListInputSchema,
36357
+ handler: (_input) => JSON.stringify({ note: "skillSource listing requires global config access; use MCP surface" }, null, 2)
36358
+ });
36359
+
36360
+ // ../skill-runtime/dist/skills/skills-source-add.js
36361
+ init_v3();
36362
+ var skillsSourceAddInputSchema = external_exports.object({
36363
+ name: external_exports.string().min(1).describe("Display name (lowercase, digits, dash; 1\u201364 chars)."),
36364
+ gitUrl: external_exports.string().min(1).describe("Git URL (https://, git@, ssh://, file://, or absolute path)."),
36365
+ branch: external_exports.string().min(1).optional().describe('Branch to track. Defaults to "main".'),
36366
+ trust: external_exports.boolean().optional().describe("Explicit trust (T6 capability-class). MCP context is non-interactive \u2014 must be true to register; otherwise the call is refused with an audit-log entry.")
36367
+ });
36368
+ var skillsSourceAddSkill = defineSkill({
36369
+ name: "skills-source-add",
36370
+ description: "Register and clone a skill source. Clones to ~/.olam/state/skill-sources/<id>/. Atomic: rolls back the state-store entry if the clone fails.",
36371
+ inputSchema: skillsSourceAddInputSchema,
36372
+ handler: ({ name, gitUrl, branch, trust }) => JSON.stringify({ name, gitUrl, branch: branch ?? "main", trust: trust ?? false, note: "add/clone requires fs + config store; use MCP surface" }, null, 2)
36373
+ });
36374
+
36375
+ // ../skill-runtime/dist/skills/skills-source-remove.js
36376
+ init_v3();
36377
+ var skillsSourceRemoveInputSchema = external_exports.object({
36378
+ id: external_exports.string().length(12).describe("Skill source id (from olam_skills_source_list).")
36379
+ });
36380
+ var skillsSourceRemoveSkill = defineSkill({
36381
+ name: "skills-source-remove",
36382
+ description: "Remove a registered skill source. Deletes the clone directory and the state entry.",
36383
+ inputSchema: skillsSourceRemoveInputSchema,
36384
+ handler: ({ id }) => JSON.stringify({ id, note: "remove requires config store + fs access; use MCP surface" }, null, 2)
36385
+ });
36386
+
36387
+ // ../skill-runtime/dist/skills/skills-source-pull.js
36388
+ init_v3();
36389
+ var skillsSourcePullInputSchema = external_exports.object({
36390
+ id: external_exports.string().length(12).describe("Skill source id.")
36391
+ });
36392
+ var skillsSourcePullSkill = defineSkill({
36393
+ name: "skills-source-pull",
36394
+ description: "Fetch + reset the clone to upstream HEAD. Updates lastPulledSha.",
36395
+ inputSchema: skillsSourcePullInputSchema,
36396
+ handler: ({ id }) => JSON.stringify({ id, note: "pull requires git + config store access; use MCP surface" }, null, 2)
36397
+ });
36398
+
36399
+ // ../skill-runtime/dist/skills/skills-source-show.js
36400
+ init_v3();
36401
+ var skillsSourceShowInputSchema = external_exports.object({
36402
+ id: external_exports.string().length(12).describe("Skill source id.")
36403
+ });
36404
+ var skillsSourceShowSkill = defineSkill({
36405
+ name: "skills-source-show",
36406
+ description: "Show details for a single skill source (state-store entry + resolved clone path).",
36407
+ inputSchema: skillsSourceShowInputSchema,
36408
+ handler: ({ id }) => JSON.stringify({ id, note: "show requires config store access; use MCP surface" }, null, 2)
36409
+ });
36410
+
36411
+ // ../mcp-server/src/tools/skill-source.ts
35691
36412
  function asMessage7(err) {
35692
36413
  return err instanceof Error ? err.message : String(err);
35693
36414
  }
@@ -35703,23 +36424,20 @@ function fail(err) {
35703
36424
  };
35704
36425
  }
35705
36426
  function register25(server, _ctx, _initError) {
36427
+ const listTool = skillsSourceListSkill.asMcpTool();
35706
36428
  server.tool(
35707
36429
  "olam_skills_source_list",
35708
- "List every registered skill source. Returns { skillSources: SkillSource[] }.",
35709
- {},
36430
+ listTool.description,
36431
+ listTool.inputSchema,
35710
36432
  async () => {
35711
36433
  return ok({ skillSources: listSkillSources() });
35712
36434
  }
35713
36435
  );
36436
+ const addTool = skillsSourceAddSkill.asMcpTool();
35714
36437
  server.tool(
35715
36438
  "olam_skills_source_add",
35716
- "Register and clone a skill source. Clones to ~/.olam/state/skill-sources/<id>/. Atomic: rolls back the state-store entry if the clone fails.",
35717
- {
35718
- name: external_exports.string().min(1).describe("Display name (lowercase, digits, dash; 1\u201364 chars)."),
35719
- gitUrl: external_exports.string().min(1).describe("Git URL (https://, git@, ssh://, file://, or absolute path)."),
35720
- branch: external_exports.string().min(1).optional().describe('Branch to track. Defaults to "main".'),
35721
- trust: external_exports.boolean().optional().describe("Explicit trust (T6 capability-class). MCP context is non-interactive \u2014 must be true to register; otherwise the call is refused with an audit-log entry.")
35722
- },
36439
+ addTool.description,
36440
+ addTool.inputSchema,
35723
36441
  async ({ name, gitUrl, branch, trust }) => {
35724
36442
  if (trust !== true) {
35725
36443
  try {
@@ -35763,12 +36481,11 @@ function register25(server, _ctx, _initError) {
35763
36481
  }
35764
36482
  }
35765
36483
  );
36484
+ const removeTool = skillsSourceRemoveSkill.asMcpTool();
35766
36485
  server.tool(
35767
36486
  "olam_skills_source_remove",
35768
- "Remove a registered skill source. Deletes the clone directory and the state entry.",
35769
- {
35770
- id: external_exports.string().length(12).describe("Skill source id (from olam_skills_source_list).")
35771
- },
36487
+ removeTool.description,
36488
+ removeTool.inputSchema,
35772
36489
  async ({ id }) => {
35773
36490
  try {
35774
36491
  removeSkillSourceClone(id);
@@ -35779,12 +36496,11 @@ function register25(server, _ctx, _initError) {
35779
36496
  }
35780
36497
  }
35781
36498
  );
36499
+ const pullTool = skillsSourcePullSkill.asMcpTool();
35782
36500
  server.tool(
35783
36501
  "olam_skills_source_pull",
35784
- "Fetch + reset the clone to upstream HEAD. Updates lastPulledSha.",
35785
- {
35786
- id: external_exports.string().length(12).describe("Skill source id.")
35787
- },
36502
+ pullTool.description,
36503
+ pullTool.inputSchema,
35788
36504
  async ({ id }) => {
35789
36505
  const entry = getSkillSource(id);
35790
36506
  if (!entry) {
@@ -35806,12 +36522,11 @@ function register25(server, _ctx, _initError) {
35806
36522
  }
35807
36523
  }
35808
36524
  );
36525
+ const showTool = skillsSourceShowSkill.asMcpTool();
35809
36526
  server.tool(
35810
36527
  "olam_skills_source_show",
35811
- "Show details for a single skill source (state-store entry + resolved clone path).",
35812
- {
35813
- id: external_exports.string().length(12).describe("Skill source id.")
35814
- },
36528
+ showTool.description,
36529
+ showTool.inputSchema,
35815
36530
  async ({ id }) => {
35816
36531
  const entry = getSkillSource(id);
35817
36532
  if (!entry) {
@@ -35830,10 +36545,65 @@ var skills_exports = {};
35830
36545
  __export(skills_exports, {
35831
36546
  register: () => register26
35832
36547
  });
35833
- init_v3();
35834
36548
  init_skill_sources();
35835
36549
  import * as fs36 from "node:fs";
35836
36550
  import * as path35 from "node:path";
36551
+
36552
+ // ../skill-runtime/dist/skills/skills-sync.js
36553
+ init_v3();
36554
+ var skillsSyncInputSchema = external_exports.object({
36555
+ dryRun: external_exports.boolean().optional().describe("Resolve artifacts but do not deploy or merge. Returns the summary that sync would produce."),
36556
+ atlasUser: external_exports.string().optional().describe("Override atlas-user identifier (defaults to ~/.claude/.atlas-user).")
36557
+ });
36558
+ var skillsSyncSkill = defineSkill({
36559
+ name: "skills-sync",
36560
+ description: "Sync all registered skill sources to ~/.claude/. Returns SyncSummary with per-source artifact breakdown, deploy result, and merge result.",
36561
+ inputSchema: skillsSyncInputSchema,
36562
+ handler: (input) => {
36563
+ const mode = input.dryRun ? "dry-run" : "live";
36564
+ const userNote = input.atlasUser ? ` (atlas-user: ${input.atlasUser})` : "";
36565
+ return `Skills sync (${mode}${userNote}) requires the skill-sources engine. Use the MCP tool surface or HTTP endpoint with a configured host.`;
36566
+ }
36567
+ });
36568
+
36569
+ // ../skill-runtime/dist/skills/skills-diff.js
36570
+ init_v3();
36571
+ var skillsDiffInputSchema = external_exports.object({
36572
+ atlasUser: external_exports.string().optional().describe("Override atlas-user identifier.")
36573
+ });
36574
+ var skillsDiffSkill = defineSkill({
36575
+ name: "skills-diff",
36576
+ description: "Show what `olam skills sync` would deploy without making on-disk changes. Equivalent to sync with dryRun=true.",
36577
+ inputSchema: skillsDiffInputSchema,
36578
+ handler: (input) => {
36579
+ const userNote = input.atlasUser ? ` (atlas-user: ${input.atlasUser})` : "";
36580
+ return `Skills diff${userNote} requires the skill-sources engine. Use the MCP tool surface or HTTP endpoint with a configured host.`;
36581
+ }
36582
+ });
36583
+
36584
+ // ../skill-runtime/dist/skills/skills-list.js
36585
+ init_v3();
36586
+ var skillsListInputSchema = external_exports.object({});
36587
+ var skillsListSkill = defineSkill({
36588
+ name: "skills-list",
36589
+ description: "List artifacts currently deployed under ~/.claude/{skills,agents,scripts,rules,commands}/ along with their source-id (if from a registered olam source).",
36590
+ inputSchema: skillsListInputSchema,
36591
+ handler: (_input) => "Skills listing requires filesystem access to ~/.claude/. Use the MCP tool surface or HTTP endpoint with a configured host."
36592
+ });
36593
+
36594
+ // ../skill-runtime/dist/skills/skills-show.js
36595
+ init_v3();
36596
+ var skillsShowInputSchema = external_exports.object({
36597
+ name: external_exports.string().min(1).describe("Artifact name (basename under any of the managed buckets).")
36598
+ });
36599
+ var skillsShowSkill = defineSkill({
36600
+ name: "skills-show",
36601
+ description: 'Show details for a deployed artifact by name (e.g. "plan-hard" or "codex-second-opinion.md"). Returns one or more matches across buckets.',
36602
+ inputSchema: skillsShowInputSchema,
36603
+ handler: (input) => `Skills show for "${input.name}" requires filesystem access to ~/.claude/. Use the MCP tool surface or HTTP endpoint with a configured host.`
36604
+ });
36605
+
36606
+ // ../mcp-server/src/tools/skills.ts
35837
36607
  function asMessage8(err) {
35838
36608
  return err instanceof Error ? err.message : String(err);
35839
36609
  }
@@ -35879,13 +36649,11 @@ function listDeployed() {
35879
36649
  return entries;
35880
36650
  }
35881
36651
  function register26(server, _ctx, _initError) {
36652
+ const skillsSync = skillsSyncSkill.asMcpTool();
35882
36653
  server.tool(
35883
36654
  "olam_skills_sync",
35884
- "Sync all registered skill sources to ~/.claude/. Returns SyncSummary with per-source artifact breakdown, deploy result, and merge result.",
35885
- {
35886
- dryRun: external_exports.boolean().optional().describe("Resolve artifacts but do not deploy or merge. Returns the summary that sync would produce."),
35887
- atlasUser: external_exports.string().optional().describe("Override atlas-user identifier (defaults to ~/.claude/.atlas-user).")
35888
- },
36655
+ skillsSync.description,
36656
+ skillsSync.inputSchema,
35889
36657
  async ({ dryRun, atlasUser }) => {
35890
36658
  try {
35891
36659
  const summary = await syncSkills({ dryRun, atlasUser });
@@ -35895,12 +36663,11 @@ function register26(server, _ctx, _initError) {
35895
36663
  }
35896
36664
  }
35897
36665
  );
36666
+ const skillsDiff = skillsDiffSkill.asMcpTool();
35898
36667
  server.tool(
35899
36668
  "olam_skills_diff",
35900
- "Show what `olam skills sync` would deploy without making on-disk changes. Equivalent to sync with dryRun=true.",
35901
- {
35902
- atlasUser: external_exports.string().optional().describe("Override atlas-user identifier.")
35903
- },
36669
+ skillsDiff.description,
36670
+ skillsDiff.inputSchema,
35904
36671
  async ({ atlasUser }) => {
35905
36672
  try {
35906
36673
  const summary = await syncSkills({ dryRun: true, atlasUser });
@@ -35910,10 +36677,11 @@ function register26(server, _ctx, _initError) {
35910
36677
  }
35911
36678
  }
35912
36679
  );
36680
+ const skillsList = skillsListSkill.asMcpTool();
35913
36681
  server.tool(
35914
36682
  "olam_skills_list",
35915
- "List artifacts currently deployed under ~/.claude/{skills,agents,scripts,rules,commands}/ along with their source-id (if from a registered olam source).",
35916
- {},
36683
+ skillsList.description,
36684
+ skillsList.inputSchema,
35917
36685
  async () => {
35918
36686
  try {
35919
36687
  const entries = listDeployed();
@@ -35923,12 +36691,11 @@ function register26(server, _ctx, _initError) {
35923
36691
  }
35924
36692
  }
35925
36693
  );
36694
+ const skillsShow = skillsShowSkill.asMcpTool();
35926
36695
  server.tool(
35927
36696
  "olam_skills_show",
35928
- 'Show details for a deployed artifact by name (e.g. "plan-hard" or "codex-second-opinion.md"). Returns one or more matches across buckets.',
35929
- {
35930
- name: external_exports.string().min(1).describe("Artifact name (basename under any of the managed buckets).")
35931
- },
36697
+ skillsShow.description,
36698
+ skillsShow.inputSchema,
35932
36699
  async ({ name }) => {
35933
36700
  try {
35934
36701
  const entries = listDeployed().filter((e) => e.name === name);
@@ -35948,7 +36715,6 @@ var skills_search_exports = {};
35948
36715
  __export(skills_search_exports, {
35949
36716
  register: () => register27
35950
36717
  });
35951
- init_v3();
35952
36718
  import * as path37 from "node:path";
35953
36719
  import * as os22 from "node:os";
35954
36720
 
@@ -36090,6 +36856,19 @@ function searchIndex(dbPath, query, k = 5) {
36090
36856
  var DEFAULT_DB_PATH = path36.join(os21.homedir(), ".olam", "skills.vec.db");
36091
36857
  var DEFAULT_SOURCE_DIR = path36.join(os21.homedir(), ".claude", "skills");
36092
36858
 
36859
+ // ../skill-runtime/dist/skills/skills-search.js
36860
+ init_v3();
36861
+ var skillsSearchInputSchema = external_exports.object({
36862
+ query: external_exports.string().min(1).describe('Natural-language description of the kind of skill you want (e.g. "stage and commit my changes" or "roll out a new release").'),
36863
+ k: external_exports.number().int().min(1).max(50).optional().describe("Number of hits to return (default 5, max 50).")
36864
+ });
36865
+ var skillsSearchSkill = defineSkill({
36866
+ name: "skills-search",
36867
+ description: "Semantic search over the local Claude skills index. Returns top-k skills ranked by cosine similarity against a deterministic bag-of-words embedding. Requires `scripts/skills-index-build.mjs` to have been run; set `SKILLS_INDEX_PATH` to override the index location (defaults to ~/.olam/skills.vec.db).",
36868
+ inputSchema: skillsSearchInputSchema,
36869
+ handler: ({ query, k }) => JSON.stringify({ query, k: k ?? 5, note: "searchIndex call requires on-disk DB; use MCP surface" }, null, 2)
36870
+ });
36871
+
36093
36872
  // ../mcp-server/src/tools/skills-search.ts
36094
36873
  function defaultDbPath() {
36095
36874
  const override = process.env["SKILLS_INDEX_PATH"];
@@ -36111,13 +36890,11 @@ function fail3(err) {
36111
36890
  };
36112
36891
  }
36113
36892
  function register27(server, _ctx, _initError) {
36893
+ const tool = skillsSearchSkill.asMcpTool();
36114
36894
  server.tool(
36115
36895
  "olam_skills_search",
36116
- "Semantic search over the local Claude skills index. Returns top-k skills ranked by cosine similarity against a deterministic bag-of-words embedding. Requires `scripts/skills-index-build.mjs` to have been run; set `SKILLS_INDEX_PATH` to override the index location (defaults to ~/.olam/skills.vec.db).",
36117
- {
36118
- query: external_exports.string().min(1).describe('Natural-language description of the kind of skill you want (e.g. "stage and commit my changes" or "roll out a new release").'),
36119
- k: external_exports.number().int().min(1).max(50).optional().describe("Number of hits to return (default 5, max 50).")
36120
- },
36896
+ tool.description,
36897
+ tool.inputSchema,
36121
36898
  async ({ query, k }) => {
36122
36899
  try {
36123
36900
  const hits = searchIndex(defaultDbPath(), query, k ?? 5);
@@ -36134,7 +36911,6 @@ var kg_classify_exports = {};
36134
36911
  __export(kg_classify_exports, {
36135
36912
  register: () => register28
36136
36913
  });
36137
- init_v3();
36138
36914
 
36139
36915
  // ../core/dist/kg/kg-service-client.js
36140
36916
  var KG_SERVICE_PORT_DEFAULT = 9997;
@@ -36206,15 +36982,34 @@ async function status(opts = {}) {
36206
36982
  return getJson(kgServiceStatusUrl(), opts.timeoutMs);
36207
36983
  }
36208
36984
 
36985
+ // ../skill-runtime/dist/skills/kg-classify.js
36986
+ init_v3();
36987
+ var kgClassifyInputSchema = external_exports.object({
36988
+ question: external_exports.string().describe("The natural-language question to route"),
36989
+ workspace: external_exports.string().optional().describe("Optional workspace name to scope the L2 probe gate (defaults to no probe)")
36990
+ });
36991
+ var kgClassifySkill = defineSkill({
36992
+ name: "kg-classify",
36993
+ description: "Route a question to kg | grep | both via the 4-layer classifier (kg-service container). Returns route + layer + reason + matched exemplar. Requires olam-kg-service running (see `olam services up`).",
36994
+ inputSchema: kgClassifyInputSchema,
36995
+ handler: (input) => {
36996
+ return JSON.stringify({
36997
+ route: "grep",
36998
+ layer: 0,
36999
+ reason: "skill-runtime stub \u2014 kg-service not available outside MCP context",
37000
+ question: input.question,
37001
+ workspace: input.workspace ?? null
37002
+ }, null, 2);
37003
+ }
37004
+ });
37005
+
36209
37006
  // ../mcp-server/src/tools/kg-classify.ts
36210
37007
  function register28(server, _ctx, _initError) {
37008
+ const { description, inputSchema } = kgClassifySkill.asMcpTool();
36211
37009
  server.tool(
36212
37010
  "olam_kg_classify",
36213
- "Route a question to kg | grep | both via the 4-layer classifier (kg-service container). Returns route + layer + reason + matched exemplar. Requires olam-kg-service running (see `olam services up`).",
36214
- {
36215
- question: external_exports.string().describe("The natural-language question to route"),
36216
- workspace: external_exports.string().optional().describe("Optional workspace name to scope the L2 probe gate (defaults to no probe)")
36217
- },
37011
+ description,
37012
+ inputSchema,
36218
37013
  async (params) => {
36219
37014
  try {
36220
37015
  const result = await classify({ q: params.question, workspace: params.workspace });
@@ -36257,6 +37052,29 @@ var kg_doctor_exports = {};
36257
37052
  __export(kg_doctor_exports, {
36258
37053
  register: () => register29
36259
37054
  });
37055
+
37056
+ // ../skill-runtime/dist/skills/kg-doctor.js
37057
+ init_v3();
37058
+ var kgDoctorInputSchema = external_exports.object({});
37059
+ var kgDoctorSkill = defineSkill({
37060
+ name: "kg-doctor",
37061
+ description: "Diagnostic report for olam-kg-service over HTTP: /health readiness, workspace inventory, and /classify round-trip. Returns a JSON `probes` array. If the container isn't running, all probes fail with a hint to run `olam services up`.",
37062
+ inputSchema: kgDoctorInputSchema,
37063
+ handler: (_input) => {
37064
+ return JSON.stringify({
37065
+ probes: [
37066
+ {
37067
+ name: "health",
37068
+ status: "fail",
37069
+ detail: "skill-runtime stub \u2014 kg-service not available outside MCP context",
37070
+ remedy: "`olam services up`"
37071
+ }
37072
+ ]
37073
+ }, null, 2);
37074
+ }
37075
+ });
37076
+
37077
+ // ../mcp-server/src/tools/kg-doctor.ts
36260
37078
  async function runProbes() {
36261
37079
  const results = [];
36262
37080
  try {
@@ -36306,10 +37124,11 @@ async function runProbes() {
36306
37124
  return results;
36307
37125
  }
36308
37126
  function register29(server, _ctx, _initError) {
37127
+ const { description, inputSchema } = kgDoctorSkill.asMcpTool();
36309
37128
  server.tool(
36310
37129
  "olam_kg_doctor",
36311
- "Diagnostic report for olam-kg-service over HTTP: /health readiness, workspace inventory, and /classify round-trip. Returns a JSON `probes` array. If the container isn't running, all probes fail with a hint to run `olam services up`.",
36312
- {},
37130
+ description,
37131
+ inputSchema,
36313
37132
  async () => {
36314
37133
  try {
36315
37134
  const probes = await runProbes();
@@ -36343,7 +37162,6 @@ var kg_install_hook_exports = {};
36343
37162
  __export(kg_install_hook_exports, {
36344
37163
  register: () => register30
36345
37164
  });
36346
- init_v3();
36347
37165
  init_merge_settings();
36348
37166
  import * as fs38 from "node:fs";
36349
37167
  import * as path38 from "node:path";
@@ -36394,6 +37212,29 @@ function buildHookMatcherEntry(opts) {
36394
37212
  };
36395
37213
  }
36396
37214
 
37215
+ // ../skill-runtime/dist/skills/kg-install-hook.js
37216
+ init_v3();
37217
+ var kgInstallHookInputSchema = external_exports.object({
37218
+ scope: external_exports.enum(["project", "user"]).optional().describe("project (default) or user"),
37219
+ projectPath: external_exports.string().optional().describe("Override the project root. Defaults to cwd. Ignored when scope=user.")
37220
+ });
37221
+ var kgInstallHookSkill = defineSkill({
37222
+ name: "kg-install-hook",
37223
+ description: "Install the kg-service PreToolUse hook into .claude/settings.json. Idempotent (sentinel-detected). Default scope=project (writes <cwd>/.claude/settings.json); scope=user writes ~/.claude/settings.json.",
37224
+ inputSchema: kgInstallHookInputSchema,
37225
+ handler: (input) => {
37226
+ const scope = input.scope === "user" ? "user" : "project";
37227
+ return JSON.stringify({
37228
+ ok: false,
37229
+ status: "skill-runtime-stub",
37230
+ scope,
37231
+ filePath: null,
37232
+ backup: null,
37233
+ message: "skill-runtime stub \u2014 filesystem access not available outside MCP context"
37234
+ }, null, 2);
37235
+ }
37236
+ });
37237
+
36397
37238
  // ../mcp-server/src/tools/kg-install-hook.ts
36398
37239
  function settingsPathFor2(scope, projectPath) {
36399
37240
  if (scope === "user") {
@@ -36403,13 +37244,11 @@ function settingsPathFor2(scope, projectPath) {
36403
37244
  return path38.join(root, ".claude", "settings.json");
36404
37245
  }
36405
37246
  function register30(server, _ctx, _initError) {
37247
+ const { description, inputSchema } = kgInstallHookSkill.asMcpTool();
36406
37248
  server.tool(
36407
37249
  "olam_kg_install_hook",
36408
- "Install the kg-service PreToolUse hook into .claude/settings.json. Idempotent (sentinel-detected). Default scope=project (writes <cwd>/.claude/settings.json); scope=user writes ~/.claude/settings.json.",
36409
- {
36410
- scope: external_exports.enum(["project", "user"]).optional().describe("project (default) or user"),
36411
- projectPath: external_exports.string().optional().describe("Override the project root. Defaults to cwd. Ignored when scope=user.")
36412
- },
37250
+ description,
37251
+ inputSchema,
36413
37252
  async (params) => {
36414
37253
  const scope = params.scope === "user" ? "user" : "project";
36415
37254
  const filePath = settingsPathFor2(scope, params.projectPath);
@@ -36473,10 +37312,28 @@ var kg_uninstall_hook_exports = {};
36473
37312
  __export(kg_uninstall_hook_exports, {
36474
37313
  register: () => register31
36475
37314
  });
36476
- init_v3();
36477
37315
  import * as fs39 from "node:fs";
36478
37316
  import * as path39 from "node:path";
36479
37317
  import * as os24 from "node:os";
37318
+
37319
+ // ../skill-runtime/dist/skills/kg-uninstall-hook.js
37320
+ init_v3();
37321
+ var kgUninstallHookInputSchema = external_exports.object({
37322
+ scope: external_exports.enum(["project", "user"]).optional().describe("project (default) or user"),
37323
+ projectPath: external_exports.string().optional().describe("Override the project root. Defaults to cwd.")
37324
+ });
37325
+ var kgUninstallHookSkill = defineSkill({
37326
+ name: "kg-uninstall-hook",
37327
+ description: "Remove the kg-service PreToolUse hook from .claude/settings.json. Sentinel-matched: only the olam entry is removed; other PreToolUse hooks are preserved.",
37328
+ inputSchema: kgUninstallHookInputSchema,
37329
+ handler: (input) => {
37330
+ const scope = input.scope ?? "project";
37331
+ const where = input.projectPath ? ` at ${input.projectPath}` : "";
37332
+ return `Would remove kg-service hook from ${scope} settings.json${where}. Use the MCP tool for actual execution.`;
37333
+ }
37334
+ });
37335
+
37336
+ // ../mcp-server/src/tools/kg-uninstall-hook.ts
36480
37337
  function settingsPathFor3(scope, projectPath) {
36481
37338
  if (scope === "user") {
36482
37339
  return path39.join(os24.homedir(), ".claude", "settings.json");
@@ -36505,13 +37362,11 @@ function dropSentinel(matchers) {
36505
37362
  return { matchers: out, changed };
36506
37363
  }
36507
37364
  function register31(server, _ctx, _initError) {
37365
+ const { description, inputSchema } = kgUninstallHookSkill.asMcpTool();
36508
37366
  server.tool(
36509
37367
  "olam_kg_uninstall_hook",
36510
- "Remove the kg-service PreToolUse hook from .claude/settings.json. Sentinel-matched: only the olam entry is removed; other PreToolUse hooks are preserved.",
36511
- {
36512
- scope: external_exports.enum(["project", "user"]).optional().describe("project (default) or user"),
36513
- projectPath: external_exports.string().optional().describe("Override the project root. Defaults to cwd.")
36514
- },
37368
+ description,
37369
+ inputSchema,
36515
37370
  async (params) => {
36516
37371
  const scope = params.scope === "user" ? "user" : "project";
36517
37372
  const filePath = settingsPathFor3(scope, params.projectPath);