@pellux/goodvibes-agent 0.1.112 → 0.1.114

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.
@@ -816523,7 +816523,7 @@ var createStyledCell = (char, overrides = {}) => ({
816523
816523
  // src/version.ts
816524
816524
  import { readFileSync } from "fs";
816525
816525
  import { join } from "path";
816526
- var _version = "0.1.112";
816526
+ var _version = "0.1.114";
816527
816527
  var _sdkVersion = "0.33.35";
816528
816528
  try {
816529
816529
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
@@ -816960,7 +816960,7 @@ class UIFactory {
816960
816960
  const CYAN = "#00ffff";
816961
816961
  const GREY = "244";
816962
816962
  const TITLE_COLOR = "250";
816963
- const brand = ` GoodVibes `;
816963
+ const brand = ` GoodVibes Agent `;
816964
816964
  const ver = `v${VERSION} `;
816965
816965
  const stats = ` ${model} `;
816966
816966
  const prov = `(${provider}) `;
@@ -841974,7 +841974,7 @@ async function initializeBootstrapCore(stdout, options, getControlPlaneRecentEve
841974
841974
  }
841975
841975
 
841976
841976
  // src/runtime/bootstrap-shell.ts
841977
- import { join as join89 } from "path";
841977
+ import { join as join91 } from "path";
841978
841978
 
841979
841979
  // src/input/command-registry.ts
841980
841980
  class CommandRegistry {
@@ -852664,6 +852664,100 @@ function registerDelegationRuntimeCommands(registry5) {
852664
852664
  });
852665
852665
  }
852666
852666
 
852667
+ // src/agent/persona-discovery.ts
852668
+ import { promises as fsPromises5 } from "fs";
852669
+ import { join as join87 } from "path";
852670
+ var DIRECTORY_MARKERS = ["PERSONA.md", "persona.md", "AGENT.md", "agent.md"];
852671
+ function parseFrontmatter2(content) {
852672
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
852673
+ if (!match)
852674
+ return {};
852675
+ const result2 = {};
852676
+ for (const line of match[1].split(`
852677
+ `)) {
852678
+ const [key, ...rest] = line.split(":");
852679
+ if (key && rest.length > 0) {
852680
+ result2[key.trim()] = rest.join(":").trim();
852681
+ }
852682
+ }
852683
+ return result2;
852684
+ }
852685
+ function getPersonaDirectories(cwd, homeDir) {
852686
+ return [
852687
+ { root: join87(cwd, ".goodvibes", "personas"), origin: "project-local" },
852688
+ { root: join87(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "project-local" },
852689
+ { root: join87(cwd, ".goodvibes", "agents"), origin: "project-local" },
852690
+ { root: join87(homeDir, ".goodvibes", "personas"), origin: "global" },
852691
+ { root: join87(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "global" },
852692
+ { root: join87(homeDir, ".goodvibes", "agents"), origin: "global" }
852693
+ ];
852694
+ }
852695
+ async function readPersonaFile(path7, origin) {
852696
+ let content = "";
852697
+ try {
852698
+ content = await fsPromises5.readFile(path7, "utf-8");
852699
+ } catch {
852700
+ return null;
852701
+ }
852702
+ const frontmatter = parseFrontmatter2(content);
852703
+ const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
852704
+ const body2 = (frontmatter.system_prompt ?? markdownBody).trim();
852705
+ if (!body2)
852706
+ return null;
852707
+ const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "persona";
852708
+ const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
852709
+ return {
852710
+ name: name51,
852711
+ description,
852712
+ path: path7,
852713
+ origin,
852714
+ body: body2,
852715
+ frontmatter
852716
+ };
852717
+ }
852718
+ async function scanPersonaDirectory(root, origin) {
852719
+ let entries = [];
852720
+ try {
852721
+ entries = await fsPromises5.readdir(root);
852722
+ } catch {
852723
+ return [];
852724
+ }
852725
+ const records = [];
852726
+ for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
852727
+ if (entry.endsWith(".md")) {
852728
+ const record2 = await readPersonaFile(join87(root, entry), origin);
852729
+ if (record2)
852730
+ records.push(record2);
852731
+ continue;
852732
+ }
852733
+ for (const marker of DIRECTORY_MARKERS) {
852734
+ const record2 = await readPersonaFile(join87(root, entry, marker), origin);
852735
+ if (record2) {
852736
+ records.push(record2);
852737
+ break;
852738
+ }
852739
+ }
852740
+ }
852741
+ return records;
852742
+ }
852743
+ async function discoverPersonas(shellPaths) {
852744
+ const seen = new Set;
852745
+ const records = [];
852746
+ for (const { root, origin } of getPersonaDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
852747
+ for (const record2 of await scanPersonaDirectory(root, origin)) {
852748
+ const key = record2.name.toLowerCase();
852749
+ if (seen.has(key))
852750
+ continue;
852751
+ seen.add(key);
852752
+ records.push(record2);
852753
+ }
852754
+ }
852755
+ return records.sort((a4, b3) => {
852756
+ const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
852757
+ return originRank || a4.name.localeCompare(b3.name);
852758
+ });
852759
+ }
852760
+
852667
852761
  // src/input/commands/personas-runtime.ts
852668
852762
  function parsePersonaArgs(args2) {
852669
852763
  const flags2 = new Map;
@@ -852737,6 +852831,84 @@ function renderPersona(persona, activePersonaId) {
852737
852831
  ].filter(Boolean).join(`
852738
852832
  `);
852739
852833
  }
852834
+ function summarizeDiscoveredPersona(persona) {
852835
+ const description = persona.description ? ` - ${persona.description}` : "";
852836
+ return ` ${persona.name} ${persona.origin}${description}
852837
+ path: ${persona.path}`;
852838
+ }
852839
+ function renderDiscoveredPersonas(personas) {
852840
+ if (personas.length === 0) {
852841
+ return [
852842
+ "Discovered Agent persona files",
852843
+ " No persona markdown files found in project/global Agent persona folders.",
852844
+ " Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
852845
+ ].join(`
852846
+ `);
852847
+ }
852848
+ return [
852849
+ `Discovered Agent persona files (${personas.length})`,
852850
+ ...personas.map(summarizeDiscoveredPersona),
852851
+ "",
852852
+ "Import one with: /personas import-discovered <name> --yes"
852853
+ ].join(`
852854
+ `);
852855
+ }
852856
+ function discoveredPersonaLookupValues(persona) {
852857
+ const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
852858
+ const basename5 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
852859
+ return [persona.name, slug, persona.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
852860
+ }
852861
+ function findDiscoveredPersona(personas, idOrName) {
852862
+ const lookup = idOrName.trim().toLowerCase();
852863
+ if (!lookup)
852864
+ return null;
852865
+ return personas.find((persona) => discoveredPersonaLookupValues(persona).includes(lookup)) ?? null;
852866
+ }
852867
+ function frontmatterList(persona, key) {
852868
+ const value = persona.frontmatter[key];
852869
+ if (!value)
852870
+ return [];
852871
+ return splitList(value);
852872
+ }
852873
+ async function importDiscoveredPersona(args2, ctx, personaRegistry) {
852874
+ const parsed = parsePersonaArgs(args2);
852875
+ const name51 = parsed.rest.join(" ").trim();
852876
+ if (!name51) {
852877
+ ctx.print("Usage: /personas import-discovered <name> [--use] --yes");
852878
+ return;
852879
+ }
852880
+ const discovered = findDiscoveredPersona(await discoverPersonas(requireShellPaths(ctx)), name51);
852881
+ if (!discovered) {
852882
+ ctx.print(`Unknown discovered Agent persona: ${name51}
852883
+ Run /personas discover to inspect available persona files.`);
852884
+ return;
852885
+ }
852886
+ if (!parsed.yes) {
852887
+ ctx.print([
852888
+ "Agent persona import preview",
852889
+ ` name: ${discovered.name}`,
852890
+ ` origin: ${discovered.origin}`,
852891
+ ` path: ${discovered.path}`,
852892
+ ` description: ${discovered.description || "(none)"}`,
852893
+ ` body characters: ${discovered.body.length}`,
852894
+ " next: rerun with --yes to import into the Agent-local persona registry"
852895
+ ].join(`
852896
+ `));
852897
+ return;
852898
+ }
852899
+ const persona = personaRegistry.create({
852900
+ name: discovered.name,
852901
+ description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
852902
+ body: discovered.body,
852903
+ tags: frontmatterList(discovered, "tags"),
852904
+ triggers: frontmatterList(discovered, "triggers"),
852905
+ source: "imported",
852906
+ provenance: `discovered:${discovered.origin}:${discovered.path}`
852907
+ });
852908
+ if (parsed.flags.get("use") === "true")
852909
+ personaRegistry.setActive(persona.id);
852910
+ ctx.print(`Imported Agent persona ${persona.id}: ${persona.name}${parsed.flags.get("use") === "true" ? " (active)" : ""}`);
852911
+ }
852740
852912
  function requiredFlag(flags2, key) {
852741
852913
  const value = flags2.get(key)?.trim();
852742
852914
  if (!value)
@@ -852751,7 +852923,7 @@ function registerPersonasRuntimeCommands(registry5) {
852751
852923
  name: "personas",
852752
852924
  aliases: ["persona"],
852753
852925
  description: "Manage local GoodVibes Agent personas",
852754
- usage: "[list|search <query>|show <id>|create --name <name> --description <summary> --body <instructions>|update <id> [--name ...] [--description ...] [--body ...]|use <id>|active|clear|review <id>|stale <id> <reason...>|delete <id> --yes]",
852926
+ usage: "[list|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --body <instructions>|update <id> [--name ...] [--description ...] [--body ...]|use <id>|active|clear|review <id>|stale <id> <reason...>|delete <id> --yes]",
852755
852927
  async handler(args2, ctx) {
852756
852928
  const sub = (args2[0] ?? "list").toLowerCase();
852757
852929
  const registryStore = registryFromContext(ctx);
@@ -852760,6 +852932,14 @@ function registerPersonasRuntimeCommands(registry5) {
852760
852932
  ctx.print(renderList("Agent Personas", registryStore, registryStore.list()));
852761
852933
  return;
852762
852934
  }
852935
+ if (sub === "discover" || sub === "discovered") {
852936
+ ctx.print(renderDiscoveredPersonas(await discoverPersonas(requireShellPaths(ctx))));
852937
+ return;
852938
+ }
852939
+ if (sub === "import-discovered" || sub === "import-persona") {
852940
+ await importDiscoveredPersona(args2.slice(1), ctx, registryStore);
852941
+ return;
852942
+ }
852763
852943
  if (sub === "search") {
852764
852944
  const query2 = args2.slice(1).join(" ").trim();
852765
852945
  ctx.print(renderList(query2 ? `Agent Personas matching "${query2}"` : "Agent Personas", registryStore, registryStore.search(query2)));
@@ -852864,7 +853044,7 @@ function registerPersonasRuntimeCommands(registry5) {
852864
853044
  ctx.print(`Deleted Agent persona ${removed.id}: ${removed.name}`);
852865
853045
  return;
852866
853046
  }
852867
- ctx.print("Usage: /personas [list|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
853047
+ ctx.print("Usage: /personas [list|discover|import-discovered|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
852868
853048
  } catch (error51) {
852869
853049
  printError2(ctx, error51);
852870
853050
  }
@@ -852975,7 +853155,7 @@ function findDiscoveredSkill(skills, idOrName) {
852975
853155
  return null;
852976
853156
  return skills.find((skill) => discoveredSkillLookupValues(skill).includes(lookup)) ?? null;
852977
853157
  }
852978
- function frontmatterList(skill, key) {
853158
+ function frontmatterList2(skill, key) {
852979
853159
  const value = skill.frontmatter[key];
852980
853160
  if (!value)
852981
853161
  return [];
@@ -853011,8 +853191,8 @@ Run /agent-skills discover to inspect available skill files.`);
853011
853191
  name: discovered.name,
853012
853192
  description: discovered.description || `Imported skill from ${discovered.origin} skill file.`,
853013
853193
  procedure: discovered.body,
853014
- triggers: frontmatterList(discovered, "triggers"),
853015
- tags: frontmatterList(discovered, "tags"),
853194
+ triggers: frontmatterList2(discovered, "triggers"),
853195
+ tags: frontmatterList2(discovered, "tags"),
853016
853196
  enabled: parsed.flags.get("enabled") === "true",
853017
853197
  source: "imported",
853018
853198
  provenance: `discovered:${discovered.origin}:${discovered.path}`
@@ -853317,6 +853497,98 @@ function registerAgentSkillsRuntimeCommands(registry5) {
853317
853497
  });
853318
853498
  }
853319
853499
 
853500
+ // src/agent/routine-discovery.ts
853501
+ import { promises as fsPromises6 } from "fs";
853502
+ import { join as join88 } from "path";
853503
+ var DIRECTORY_MARKERS2 = ["ROUTINE.md", "routine.md"];
853504
+ function parseFrontmatter3(content) {
853505
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
853506
+ if (!match)
853507
+ return {};
853508
+ const result2 = {};
853509
+ for (const line of match[1].split(`
853510
+ `)) {
853511
+ const [key, ...rest] = line.split(":");
853512
+ if (key && rest.length > 0) {
853513
+ result2[key.trim()] = rest.join(":").trim();
853514
+ }
853515
+ }
853516
+ return result2;
853517
+ }
853518
+ function getRoutineDirectories(cwd, homeDir) {
853519
+ return [
853520
+ { root: join88(cwd, ".goodvibes", "routines"), origin: "project-local" },
853521
+ { root: join88(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "project-local" },
853522
+ { root: join88(homeDir, ".goodvibes", "routines"), origin: "global" },
853523
+ { root: join88(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "global" }
853524
+ ];
853525
+ }
853526
+ async function readRoutineFile(path7, origin) {
853527
+ let content = "";
853528
+ try {
853529
+ content = await fsPromises6.readFile(path7, "utf-8");
853530
+ } catch {
853531
+ return null;
853532
+ }
853533
+ const frontmatter = parseFrontmatter3(content);
853534
+ const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
853535
+ const steps = (frontmatter.steps ?? markdownBody).trim();
853536
+ if (!steps)
853537
+ return null;
853538
+ const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "routine";
853539
+ const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
853540
+ return {
853541
+ name: name51,
853542
+ description,
853543
+ path: path7,
853544
+ origin,
853545
+ steps,
853546
+ frontmatter
853547
+ };
853548
+ }
853549
+ async function scanRoutineDirectory(root, origin) {
853550
+ let entries = [];
853551
+ try {
853552
+ entries = await fsPromises6.readdir(root);
853553
+ } catch {
853554
+ return [];
853555
+ }
853556
+ const records = [];
853557
+ for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
853558
+ if (entry.endsWith(".md")) {
853559
+ const record2 = await readRoutineFile(join88(root, entry), origin);
853560
+ if (record2)
853561
+ records.push(record2);
853562
+ continue;
853563
+ }
853564
+ for (const marker of DIRECTORY_MARKERS2) {
853565
+ const record2 = await readRoutineFile(join88(root, entry, marker), origin);
853566
+ if (record2) {
853567
+ records.push(record2);
853568
+ break;
853569
+ }
853570
+ }
853571
+ }
853572
+ return records;
853573
+ }
853574
+ async function discoverRoutines(shellPaths) {
853575
+ const seen = new Set;
853576
+ const records = [];
853577
+ for (const { root, origin } of getRoutineDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
853578
+ for (const record2 of await scanRoutineDirectory(root, origin)) {
853579
+ const key = record2.name.toLowerCase();
853580
+ if (seen.has(key))
853581
+ continue;
853582
+ seen.add(key);
853583
+ records.push(record2);
853584
+ }
853585
+ }
853586
+ return records.sort((a4, b3) => {
853587
+ const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
853588
+ return originRank || a4.name.localeCompare(b3.name);
853589
+ });
853590
+ }
853591
+
853320
853592
  // src/input/commands/routines-runtime.ts
853321
853593
  function parseRoutineArgs(args2) {
853322
853594
  const flags2 = new Map;
@@ -853400,9 +853672,86 @@ function renderRoutine(routine) {
853400
853672
  ].filter(Boolean).join(`
853401
853673
  `);
853402
853674
  }
853675
+ function summarizeDiscoveredRoutine(routine) {
853676
+ const description = routine.description ? ` - ${routine.description}` : "";
853677
+ return ` ${routine.name} ${routine.origin}${description}
853678
+ path: ${routine.path}`;
853679
+ }
853680
+ function renderDiscoveredRoutines(routines) {
853681
+ if (routines.length === 0) {
853682
+ return [
853683
+ "Discovered Agent routine files",
853684
+ " No routine markdown files found in project/global Agent routine folders.",
853685
+ " Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
853686
+ ].join(`
853687
+ `);
853688
+ }
853689
+ return [
853690
+ `Discovered Agent routine files (${routines.length})`,
853691
+ ...routines.map(summarizeDiscoveredRoutine),
853692
+ "",
853693
+ "Import one with: /routines import-discovered <name> --yes"
853694
+ ].join(`
853695
+ `);
853696
+ }
853697
+ function discoveredRoutineLookupValues(routine) {
853698
+ const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
853699
+ const basename5 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
853700
+ return [routine.name, slug, routine.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
853701
+ }
853702
+ function findDiscoveredRoutine(routines, idOrName) {
853703
+ const lookup = idOrName.trim().toLowerCase();
853704
+ if (!lookup)
853705
+ return null;
853706
+ return routines.find((routine) => discoveredRoutineLookupValues(routine).includes(lookup)) ?? null;
853707
+ }
853708
+ function frontmatterList3(routine, key) {
853709
+ const value = routine.frontmatter[key];
853710
+ if (!value)
853711
+ return [];
853712
+ return splitList3(value);
853713
+ }
853403
853714
  function printError4(ctx, error51) {
853404
853715
  ctx.print(`Error: ${error51 instanceof Error ? error51.message : String(error51)}`);
853405
853716
  }
853717
+ async function importDiscoveredRoutine(args2, ctx, routineRegistry) {
853718
+ const parsed = parseRoutineArgs(args2);
853719
+ const name51 = parsed.rest.join(" ").trim();
853720
+ if (!name51) {
853721
+ ctx.print("Usage: /routines import-discovered <name> [--enabled] --yes");
853722
+ return;
853723
+ }
853724
+ const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name51);
853725
+ if (!discovered) {
853726
+ ctx.print(`Unknown discovered Agent routine: ${name51}
853727
+ Run /routines discover to inspect available routine files.`);
853728
+ return;
853729
+ }
853730
+ if (!parsed.yes) {
853731
+ ctx.print([
853732
+ "Agent routine import preview",
853733
+ ` name: ${discovered.name}`,
853734
+ ` origin: ${discovered.origin}`,
853735
+ ` path: ${discovered.path}`,
853736
+ ` description: ${discovered.description || "(none)"}`,
853737
+ ` steps characters: ${discovered.steps.length}`,
853738
+ " next: rerun with --yes to import into the Agent-local routine registry"
853739
+ ].join(`
853740
+ `));
853741
+ return;
853742
+ }
853743
+ const routine = routineRegistry.create({
853744
+ name: discovered.name,
853745
+ description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
853746
+ steps: discovered.steps,
853747
+ tags: frontmatterList3(discovered, "tags"),
853748
+ triggers: frontmatterList3(discovered, "triggers"),
853749
+ enabled: parsed.flags.get("enabled") === "true",
853750
+ source: "imported",
853751
+ provenance: `discovered:${discovered.origin}:${discovered.path}`
853752
+ });
853753
+ ctx.print(`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`);
853754
+ }
853406
853755
  async function promoteRoutine(args2, routineRegistry, ctx) {
853407
853756
  const parsed = parseRoutineSchedulePromotionArgs(args2);
853408
853757
  if (parsed.errors.length > 0) {
@@ -853444,6 +853793,14 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
853444
853793
  ctx.print(renderList3("Enabled Agent Routines", routineRegistry, snapshot.enabledRoutines));
853445
853794
  return;
853446
853795
  }
853796
+ if (sub === "discover" || sub === "discovered") {
853797
+ ctx.print(renderDiscoveredRoutines(await discoverRoutines(requireShellPaths(ctx))));
853798
+ return;
853799
+ }
853800
+ if (sub === "import-discovered" || sub === "import-routine") {
853801
+ await importDiscoveredRoutine(args2.slice(1), ctx, routineRegistry);
853802
+ return;
853803
+ }
853447
853804
  if (sub === "search") {
853448
853805
  const query2 = args2.slice(1).join(" ").trim();
853449
853806
  ctx.print(renderList3(query2 ? `Agent Routines matching "${query2}"` : "Agent Routines", routineRegistry, routineRegistry.search(query2)));
@@ -853579,7 +853936,7 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
853579
853936
  ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
853580
853937
  return;
853581
853938
  }
853582
- ctx.print("Usage: /routines [list|enabled|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
853939
+ ctx.print("Usage: /routines [list|enabled|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
853583
853940
  } catch (error51) {
853584
853941
  printError4(ctx, error51);
853585
853942
  }
@@ -853589,14 +853946,14 @@ function registerRoutinesRuntimeCommands(registry5) {
853589
853946
  name: "routines",
853590
853947
  aliases: ["routine"],
853591
853948
  description: "Manage local GoodVibes Agent routines",
853592
- usage: "[list|enabled|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps>|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]",
853949
+ usage: "[list|enabled|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps>|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]",
853593
853950
  handler: runRoutinesRuntimeCommand
853594
853951
  });
853595
853952
  }
853596
853953
 
853597
853954
  // src/input/commands/channels-runtime.ts
853598
853955
  import { existsSync as existsSync72, readFileSync as readFileSync79 } from "fs";
853599
- import { join as join87 } from "path";
853956
+ import { join as join89 } from "path";
853600
853957
 
853601
853958
  // src/input/agent-workspace-channels.ts
853602
853959
  var AGENT_WORKSPACE_CHANNEL_SPECS = [
@@ -853807,7 +854164,7 @@ function resolveChannelDaemonConnection(context) {
853807
854164
  const host = typeof hostValue === "string" && hostValue.trim().length > 0 ? hostValue.trim() : "127.0.0.1";
853808
854165
  const port = typeof portValue === "number" && Number.isFinite(portValue) ? portValue : 3421;
853809
854166
  const homeDirectory = context.workspace?.shellPaths?.homeDirectory ?? process.env.HOME ?? "";
853810
- const tokenPath = join87(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
854167
+ const tokenPath = join89(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
853811
854168
  if (!existsSync72(tokenPath))
853812
854169
  return { baseUrl: `http://${host}:${port}`, token: null, tokenPath };
853813
854170
  try {
@@ -854903,7 +855260,7 @@ function registerBuiltinCommands(registry5) {
854903
855260
 
854904
855261
  // src/input/input-history.ts
854905
855262
  import { existsSync as existsSync73, mkdirSync as mkdirSync61, readFileSync as readFileSync80, writeFileSync as writeFileSync52 } from "fs";
854906
- import { dirname as dirname59, join as join88 } from "path";
855263
+ import { dirname as dirname59, join as join90 } from "path";
854907
855264
  class HistorySearch {
854908
855265
  getEntries;
854909
855266
  active = false;
@@ -854982,7 +855339,7 @@ function resolveHistoryPath2(options) {
854982
855339
  if (!userRoot) {
854983
855340
  throw new Error("InputHistory requires historyPath or an explicit userRoot/homeDirectory.");
854984
855341
  }
854985
- return join88(userRoot, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "input-history.json");
855342
+ return join90(userRoot, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "input-history.json");
854986
855343
  }
854987
855344
 
854988
855345
  class InputHistory {
@@ -863784,7 +864141,7 @@ function createBootstrapShell(options) {
863784
864141
  hookActivityTracker: services.hookActivityTracker,
863785
864142
  hookWorkbench: services.hookWorkbench,
863786
864143
  mcpRegistry: services.mcpRegistry,
863787
- daemonHomeDir: join89(services.homeDirectory, ".goodvibes", "daemon")
864144
+ daemonHomeDir: join91(services.homeDirectory, ".goodvibes", "daemon")
863788
864145
  });
863789
864146
  services.panelManager.prewarmRegistered();
863790
864147
  const systemMessageRouter = createSystemMessageRouter(conversation, systemMessagesPanel, (kind2) => {
@@ -866199,7 +866556,7 @@ import { dirname as dirname61 } from "path";
866199
866556
  // src/runtime/onboarding/verify.ts
866200
866557
  init_config8();
866201
866558
  import { existsSync as existsSync75 } from "fs";
866202
- import { join as join90 } from "path";
866559
+ import { join as join92 } from "path";
866203
866560
  function getNow(deps) {
866204
866561
  return deps.clock?.() ?? Date.now();
866205
866562
  }
@@ -866280,7 +866637,7 @@ function verifyAuthOperation(_deps, operation) {
866280
866637
  }
866281
866638
  function verifyCreateAgentProfileOperation(deps, operation) {
866282
866639
  const resolution2 = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name);
866283
- const ok3 = existsSync75(join90(resolution2.homeDirectory, "profile.json"));
866640
+ const ok3 = existsSync75(join92(resolution2.homeDirectory, "profile.json"));
866284
866641
  return {
866285
866642
  id: `agent-profile:${resolution2.id}`,
866286
866643
  status: ok3 ? "pass" : "fail",
@@ -868337,7 +868694,7 @@ class AutocompleteEngine {
868337
868694
 
868338
868695
  // src/input/file-picker.ts
868339
868696
  import { readdir as readdir6 } from "fs/promises";
868340
- import { join as join91, relative as relative15 } from "path";
868697
+ import { join as join93, relative as relative15 } from "path";
868341
868698
 
868342
868699
  class FilePickerModal {
868343
868700
  shellPaths;
@@ -868470,7 +868827,7 @@ class FilePickerModal {
868470
868827
  continue;
868471
868828
  if (entry.name === "node_modules" || entry.name === "dist")
868472
868829
  continue;
868473
- const fullPath = join91(dir, entry.name);
868830
+ const fullPath = join93(dir, entry.name);
868474
868831
  const relPath = relative15(this.shellPaths.workingDirectory, fullPath);
868475
868832
  if (entry.isDirectory()) {
868476
868833
  files.push(relPath + "/");
@@ -871900,7 +872257,7 @@ function splitCommaList(value) {
871900
872257
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
871901
872258
  }
871902
872259
  function isAgentWorkspaceBasicCommandEditorKind(kind2) {
871903
- return kind2 === "knowledge-bookmarks" || kind2 === "knowledge-file" || kind2 === "knowledge-browser-history" || kind2 === "knowledge-connector-ingest" || kind2 === "tts-prompt" || kind2 === "image-input" || kind2 === "skill-bundle" || kind2 === "skill-discovery-import" || kind2 === "profile-template-export" || kind2 === "profile-template-import" || kind2 === "mcp-server" || kind2 === "notify-webhook" || kind2 === "notify-webhook-remove" || kind2 === "notify-webhook-test";
872260
+ return kind2 === "knowledge-bookmarks" || kind2 === "knowledge-file" || kind2 === "knowledge-browser-history" || kind2 === "knowledge-connector-ingest" || kind2 === "tts-prompt" || kind2 === "image-input" || kind2 === "skill-bundle" || kind2 === "persona-discovery-import" || kind2 === "routine-discovery-import" || kind2 === "skill-discovery-import" || kind2 === "profile-template-export" || kind2 === "profile-template-import" || kind2 === "mcp-server" || kind2 === "notify-webhook" || kind2 === "notify-webhook-remove" || kind2 === "notify-webhook-test";
871904
872261
  }
871905
872262
  function createAgentWorkspaceBasicCommandEditor(kind2) {
871906
872263
  if (kind2 === "knowledge-bookmarks") {
@@ -872090,6 +872447,34 @@ function createAgentWorkspaceBasicCommandEditor(kind2) {
872090
872447
  ]
872091
872448
  };
872092
872449
  }
872450
+ if (kind2 === "persona-discovery-import") {
872451
+ return {
872452
+ kind: kind2,
872453
+ mode: "create",
872454
+ title: "Import Discovered Persona",
872455
+ selectedFieldIndex: 0,
872456
+ message: "Import one discovered persona markdown file into the Agent-local persona registry. Type yes on the final field to confirm.",
872457
+ fields: [
872458
+ { id: "name", label: "Discovered persona", value: "", required: true, multiline: false, hint: "Name shown by /personas discover." },
872459
+ { id: "use", label: "Use now", value: "yes", required: false, multiline: false, hint: "yes/no." },
872460
+ { id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /personas import-discovered with --yes." }
872461
+ ]
872462
+ };
872463
+ }
872464
+ if (kind2 === "routine-discovery-import") {
872465
+ return {
872466
+ kind: kind2,
872467
+ mode: "create",
872468
+ title: "Import Discovered Routine",
872469
+ selectedFieldIndex: 0,
872470
+ message: "Import one discovered routine markdown file into the Agent-local routine registry. Type yes on the final field to confirm.",
872471
+ fields: [
872472
+ { id: "name", label: "Discovered routine", value: "", required: true, multiline: false, hint: "Name shown by /routines discover." },
872473
+ { id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." },
872474
+ { id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /routines import-discovered with --yes." }
872475
+ ]
872476
+ };
872477
+ }
872093
872478
  return {
872094
872479
  kind: kind2,
872095
872480
  mode: "create",
@@ -872460,6 +872845,66 @@ function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, comm
872460
872845
  }
872461
872846
  };
872462
872847
  }
872848
+ if (editor.kind === "persona-discovery-import") {
872849
+ if (!isAffirmative2(readField("confirm"))) {
872850
+ return {
872851
+ kind: "editor",
872852
+ editor: { ...editor, message: "Discovered persona import not confirmed. Type yes, then press Enter." },
872853
+ status: "Agent persona import not confirmed."
872854
+ };
872855
+ }
872856
+ const parts2 = [
872857
+ "/personas",
872858
+ "import-discovered",
872859
+ quoteSlashCommandArg(readField("name"))
872860
+ ];
872861
+ if (isAffirmative2(readField("use")))
872862
+ parts2.push("--use");
872863
+ parts2.push("--yes");
872864
+ const command9 = parts2.join(" ");
872865
+ return {
872866
+ kind: "dispatch",
872867
+ command: command9,
872868
+ status: "Opening discovered persona import.",
872869
+ actionResult: {
872870
+ kind: "dispatched",
872871
+ title: "Opening discovered persona import",
872872
+ detail: "The workspace handed a confirmed local persona import command to the shell-owned command router.",
872873
+ command: command9,
872874
+ safety: "safe"
872875
+ }
872876
+ };
872877
+ }
872878
+ if (editor.kind === "routine-discovery-import") {
872879
+ if (!isAffirmative2(readField("confirm"))) {
872880
+ return {
872881
+ kind: "editor",
872882
+ editor: { ...editor, message: "Discovered routine import not confirmed. Type yes, then press Enter." },
872883
+ status: "Agent routine import not confirmed."
872884
+ };
872885
+ }
872886
+ const parts2 = [
872887
+ "/routines",
872888
+ "import-discovered",
872889
+ quoteSlashCommandArg(readField("name"))
872890
+ ];
872891
+ if (isAffirmative2(readField("enabled")))
872892
+ parts2.push("--enabled");
872893
+ parts2.push("--yes");
872894
+ const command9 = parts2.join(" ");
872895
+ return {
872896
+ kind: "dispatch",
872897
+ command: command9,
872898
+ status: "Opening discovered routine import.",
872899
+ actionResult: {
872900
+ kind: "dispatched",
872901
+ title: "Opening discovered routine import",
872902
+ detail: "The workspace handed a confirmed local routine import command to the shell-owned command router.",
872903
+ command: command9,
872904
+ safety: "safe"
872905
+ }
872906
+ };
872907
+ }
872463
872908
  const commandParts = [
872464
872909
  "/agent-skills bundle create",
872465
872910
  "--name",
@@ -873034,6 +873479,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
873034
873479
  actions: [
873035
873480
  { id: "personas-list", label: "List personas", detail: "Print the full local persona library.", command: "/personas list", kind: "command", safety: "read-only" },
873036
873481
  { id: "personas-active", label: "Show active persona", detail: "Inspect the active local persona applied to new turns.", command: "/personas active", kind: "command", safety: "read-only" },
873482
+ { id: "personas-discover", label: "Discover persona files", detail: "Scan project and global Agent persona folders for persona markdown without importing it.", command: "/personas discover", kind: "command", safety: "read-only" },
873483
+ { id: "personas-import-discovered", label: "Import discovered persona", detail: "Open an in-workspace form that imports one reviewed persona markdown file into the Agent-local persona registry after typed confirmation.", editorKind: "persona-discovery-import", kind: "editor", safety: "safe" },
873037
873484
  { id: "personas-prev", label: "Previous persona", detail: "Move the local persona selection up without changing active state.", localKind: "persona", selectionDelta: -1, kind: "local-selection", safety: "safe" },
873038
873485
  { id: "personas-next", label: "Next persona", detail: "Move the local persona selection down without changing active state.", localKind: "persona", selectionDelta: 1, kind: "local-selection", safety: "safe" },
873039
873486
  { id: "personas-create", label: "Create persona", detail: "Open an in-workspace form for a local persona that writes Agent-local state only.", editorKind: "persona", kind: "editor", safety: "safe" },
@@ -873076,6 +873523,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
873076
873523
  actions: [
873077
873524
  { id: "routines-list", label: "List routines", detail: "Print the full local Agent routine library.", command: "/routines list", kind: "command", safety: "read-only" },
873078
873525
  { id: "routines-enabled", label: "Enabled routines", detail: "Show routines available for direct use.", command: "/routines enabled", kind: "command", safety: "read-only" },
873526
+ { id: "routines-discover", label: "Discover routine files", detail: "Scan project and global Agent routine folders for routine markdown without importing it.", command: "/routines discover", kind: "command", safety: "read-only" },
873527
+ { id: "routines-import-discovered", label: "Import discovered routine", detail: "Open an in-workspace form that imports one reviewed routine markdown file into the Agent-local routine registry after typed confirmation.", editorKind: "routine-discovery-import", kind: "editor", safety: "safe" },
873079
873528
  { id: "routines-prev", label: "Previous routine", detail: "Move the local routine selection up without changing enabled state.", localKind: "routine", selectionDelta: -1, kind: "local-selection", safety: "safe" },
873080
873529
  { id: "routines-next", label: "Next routine", detail: "Move the local routine selection down without changing enabled state.", localKind: "routine", selectionDelta: 1, kind: "local-selection", safety: "safe" },
873081
873530
  { id: "routines-create", label: "Create routine", detail: "Open an in-workspace form for a repeatable local workflow that writes Agent-local state only.", editorKind: "routine", kind: "editor", safety: "safe" },
@@ -883063,7 +883512,7 @@ function wireShellUiOpeners(options) {
883063
883512
 
883064
883513
  // src/cli/entrypoint.ts
883065
883514
  import { existsSync as existsSync85 } from "fs";
883066
- import { join as join99 } from "path";
883515
+ import { join as join101 } from "path";
883067
883516
  // src/cli/parser.ts
883068
883517
  var COMMAND_ALIASES = {
883069
883518
  run: "run",
@@ -883428,7 +883877,7 @@ function parseGoodVibesCli(argv, binary2 = "goodvibes-agent") {
883428
883877
  }
883429
883878
  // src/cli/help.ts
883430
883879
  import { existsSync as existsSync79, readFileSync as readFileSync87 } from "fs";
883431
- import { dirname as dirname63, join as join92 } from "path";
883880
+ import { dirname as dirname63, join as join94 } from "path";
883432
883881
  import { fileURLToPath as fileURLToPath4 } from "url";
883433
883882
  function readJsonVersion(path7) {
883434
883883
  try {
@@ -883442,7 +883891,7 @@ function readJsonVersion(path7) {
883442
883891
  }
883443
883892
  function getPackageVersion() {
883444
883893
  const here = dirname63(fileURLToPath4(import.meta.url));
883445
- return readJsonVersion(join92(here, "..", "..", "package.json")) ?? VERSION;
883894
+ return readJsonVersion(join94(here, "..", "..", "package.json")) ?? VERSION;
883446
883895
  }
883447
883896
  function renderGoodVibesVersion(binary2 = "goodvibes-agent") {
883448
883897
  return `${binary2} ${getPackageVersion()}`;
@@ -883582,6 +884031,8 @@ var COMMAND_HELP = {
883582
884031
  usage: [
883583
884032
  "personas list",
883584
884033
  "personas active",
884034
+ "personas discover",
884035
+ "personas import-discovered <name> [--use] --yes",
883585
884036
  "personas search <query>",
883586
884037
  "personas show <id>",
883587
884038
  "personas create --name <name> --description <summary> --body <instructions> [--tags a,b] [--triggers a,b] [--use]",
@@ -883595,6 +884046,8 @@ var COMMAND_HELP = {
883595
884046
  summary: "Manage Agent-local personas for the serial main conversation. Personas do not spawn worker agents.",
883596
884047
  examples: [
883597
884048
  "personas list",
884049
+ "personas discover",
884050
+ 'personas import-discovered "Travel Planner" --use --yes',
883598
884051
  'personas create --name "Travel Planner" --description "Plan trips" --body "Compare options before booking" --use',
883599
884052
  "personas review travel-planner",
883600
884053
  "personas delete travel-planner --yes"
@@ -883605,6 +884058,8 @@ var COMMAND_HELP = {
883605
884058
  "skills list",
883606
884059
  "skills enabled",
883607
884060
  "skills active",
884061
+ "skills discover",
884062
+ "skills import-discovered <name> [--enabled] --yes",
883608
884063
  "skills search <query>",
883609
884064
  "skills show <id>",
883610
884065
  "skills create --name <name> --description <summary> --procedure <steps> [--tags a,b] [--triggers a,b] [--enabled]",
@@ -883619,6 +884074,8 @@ var COMMAND_HELP = {
883619
884074
  summary: "Manage reusable Agent-local procedures and skill bundles for the main conversation.",
883620
884075
  examples: [
883621
884076
  "skills list",
884077
+ "skills discover",
884078
+ 'skills import-discovered "Daily Brief" --enabled --yes',
883622
884079
  'skills create --name "Daily Brief" --description "Summarize operator state" --procedure "Review Agent Knowledge, work plans, approvals, and routines" --enabled',
883623
884080
  'skills bundle create --name "Ops Pack" --description "Daily operations bundle" --skills daily-brief --enabled',
883624
884081
  "skills delete daily-brief --yes"
@@ -883656,15 +884113,19 @@ var COMMAND_HELP = {
883656
884113
  usage: [
883657
884114
  "routines list",
883658
884115
  "routines enabled",
884116
+ "routines discover",
884117
+ "routines import-discovered <name> [--enabled] --yes",
883659
884118
  "routines show <id>",
883660
884119
  "routines receipts",
883661
884120
  "routines reconcile",
883662
884121
  "routines receipt <receipt-id>",
883663
884122
  "routines promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--timezone <tz>] [--name <schedule-name>] [--provider <id>] [--model <model>] [--delivery-channel <channel[:route[:label]]>|--delivery-route <route[:label]>|--delivery-webhook <url>|--delivery-link <url>] [--disabled] --yes"
883664
884123
  ],
883665
- summary: "Inspect Agent-local routines, review local promotion receipts, reconcile receipts against live connected schedules, and explicitly promote a reviewed routine into a GoodVibes schedule. Without --yes, promote only prints the schedules.create preview.",
884124
+ summary: "Inspect and import Agent-local routines, review local promotion receipts, reconcile receipts against live connected schedules, and explicitly promote a reviewed routine into a GoodVibes schedule. Without --yes, promote only prints the schedules.create preview.",
883666
884125
  examples: [
883667
884126
  "routines list",
884127
+ "routines discover",
884128
+ 'routines import-discovered "Daily Brief" --enabled --yes',
883668
884129
  "routines show daily-operations-sweep",
883669
884130
  "routines receipts",
883670
884131
  "routines reconcile",
@@ -883882,8 +884343,6 @@ function bindLine(label, enabled, binding) {
883882
884343
  function buildCliDoctorFindings(options) {
883883
884344
  const config6 = options.configManager;
883884
884345
  const serviceEnabled = config6.get("service.enabled") === true;
883885
- const serviceAutostart = config6.get("service.autostart") === true;
883886
- const restartOnFailure = config6.get("service.restartOnFailure") === true;
883887
884346
  const daemonEnabled = config6.get("danger.daemon") === true;
883888
884347
  const listenerEnabled = config6.get("danger.httpListener") === true;
883889
884348
  const webEnabled = config6.get("web.enabled") === true;
@@ -883957,28 +884416,6 @@ function buildCliDoctorFindings(options) {
883957
884416
  action: "Manage connected-service availability from GoodVibes TUI or the owning host, then use Agent for read-only diagnostics."
883958
884417
  });
883959
884418
  }
883960
- if (serviceEnabled && !serviceAutostart) {
883961
- findings.push({
883962
- id: "runtime-autostart-disabled",
883963
- area: "runtime",
883964
- severity: "warning",
883965
- summary: "Connected-service autostart is off.",
883966
- cause: "service.enabled is true and service.autostart is false.",
883967
- impact: "Connected GoodVibes services may not be available after login or reboot even though host-managed startup is selected.",
883968
- action: "Configure autostart from GoodVibes TUI or the owning host; Agent will not mutate this setting."
883969
- });
883970
- }
883971
- if (serviceEnabled && !restartOnFailure) {
883972
- findings.push({
883973
- id: "runtime-restart-disabled",
883974
- area: "runtime",
883975
- severity: "warning",
883976
- summary: "Connected-service restart-on-failure is off.",
883977
- cause: "service.enabled is true and service.restartOnFailure is false.",
883978
- impact: "A crashed connected service or listener may stay down until manually restarted.",
883979
- action: "Configure restart-on-failure from GoodVibes TUI or the owning host; Agent will not mutate this setting."
883980
- });
883981
- }
883982
884419
  if (options.service) {
883983
884420
  for (const issue2 of options.service.issues) {
883984
884421
  if (findings.some((finding) => finding.summary === issue2))
@@ -884109,8 +884546,6 @@ function renderCliStatus(options) {
884109
884546
  const config6 = options.configManager;
884110
884547
  const snapshot2 = buildCliStatusSnapshot(options);
884111
884548
  const serviceEnabled = snapshot2.runtimeConnection.enabled;
884112
- const serviceAutostart = snapshot2.runtimeConnection.autostart;
884113
- const restartOnFailure = snapshot2.runtimeConnection.restartOnFailure;
884114
884549
  const controlPlaneEnabled = snapshot2.runtimeEndpoints.controlPlane.enabled;
884115
884550
  const listenerEnabled = snapshot2.runtimeEndpoints.httpListener.enabled;
884116
884551
  const webEnabled = snapshot2.runtimeEndpoints.web.enabled;
@@ -884169,7 +884604,7 @@ function renderCliStatus(options) {
884169
884604
  ` updatedAt: ${marker?.payload ? new Date(marker.payload.updatedAt).toISOString() : "n/a"}`
884170
884605
  ];
884171
884606
  if (options.doctor) {
884172
- lines.push("", "Connected-Service Config Signals:", ` host config present: ${yesNo(serviceEnabled)}`, ` host autostart: ${yesNo(serviceAutostart)}`, ` host restart policy: ${yesNo(restartOnFailure)}`, "", "Endpoint Diagnostics:", bindLine("runtimeApi", controlPlaneEnabled, controlPlaneBinding), bindLine("incomingWebhook", listenerEnabled, httpListenerBinding), bindLine("browserCompanion", webEnabled, webBinding));
884607
+ lines.push("", "Connected-Service Config Signals:", ` host config present: ${yesNo(serviceEnabled)}`, " lifecycle config: external to Agent", "", "Endpoint Diagnostics:", bindLine("runtimeApi", controlPlaneEnabled, controlPlaneBinding), bindLine("incomingWebhook", listenerEnabled, httpListenerBinding), bindLine("browserCompanion", webEnabled, webBinding));
884173
884608
  lines.push("", "Warnings:");
884174
884609
  if (findings.length === 0) {
884175
884610
  lines.push(" none");
@@ -884197,7 +884632,7 @@ function renderOnboardingCliStatus(options) {
884197
884632
  }
884198
884633
  // src/cli/external-runtime.ts
884199
884634
  import { existsSync as existsSync80, readFileSync as readFileSync88 } from "fs";
884200
- import { join as join93 } from "path";
884635
+ import { join as join95 } from "path";
884201
884636
  function isRecord29(value) {
884202
884637
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
884203
884638
  }
@@ -884211,7 +884646,7 @@ function resolveBaseUrl2(configManager) {
884211
884646
  return `http://${host}:${Number.isFinite(port) ? port : 3421}`;
884212
884647
  }
884213
884648
  function readOperatorToken(homeDirectory) {
884214
- const path7 = join93(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
884649
+ const path7 = join95(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
884215
884650
  if (!existsSync80(path7))
884216
884651
  return { token: null, path: path7 };
884217
884652
  try {
@@ -884589,7 +885024,7 @@ function applyRuntimeCommandEndpointFlagOverrides(configManager, command8, flags
884589
885024
  }
884590
885025
  // src/cli/bundle-command.ts
884591
885026
  import { existsSync as existsSync82, mkdirSync as mkdirSync65, readFileSync as readFileSync89, writeFileSync as writeFileSync56 } from "fs";
884592
- import { dirname as dirname64, join as join95 } from "path";
885027
+ import { dirname as dirname64, join as join97 } from "path";
884593
885028
 
884594
885029
  // src/cli/provider-classification.ts
884595
885030
  var SUBSCRIPTION_PROVIDERS = new Set([
@@ -884680,7 +885115,7 @@ function classifyProviderSetup(input) {
884680
885115
  // src/cli/service-posture.ts
884681
885116
  import { closeSync as closeSync4, existsSync as existsSync81, openSync as openSync4, readSync as readSync2, statSync as statSync21 } from "fs";
884682
885117
  import net3 from "net";
884683
- import { isAbsolute as isAbsolute13, join as join94 } from "path";
885118
+ import { isAbsolute as isAbsolute13, join as join96 } from "path";
884684
885119
 
884685
885120
  // src/cli/redaction.ts
884686
885121
  var REDACTED_VALUE = "<redacted>";
@@ -884850,7 +885285,7 @@ function resolveConfiguredLogPath(runtime3) {
884850
885285
  const trimmed2 = value.trim();
884851
885286
  if (!trimmed2)
884852
885287
  return;
884853
- return isAbsolute13(trimmed2) ? trimmed2 : join94(runtime3.homeDirectory, trimmed2);
885288
+ return isAbsolute13(trimmed2) ? trimmed2 : join96(runtime3.homeDirectory, trimmed2);
884854
885289
  }
884855
885290
  function createExternalDaemonLifecycle(logPath) {
884856
885291
  return {
@@ -884892,12 +885327,6 @@ async function buildCliServicePosture(runtime3, options = {}) {
884892
885327
  if (serverBackedEnabled && !config6.enabled) {
884893
885328
  issues.push("Connected-service settings are present, but Agent service ownership is disabled by design.");
884894
885329
  }
884895
- if (config6.enabled && !config6.autostart) {
884896
- issues.push("Connected-service autostart is off.");
884897
- }
884898
- if (config6.enabled && !config6.restartOnFailure) {
884899
- issues.push("Connected-service restart-on-failure is off.");
884900
- }
884901
885330
  for (const endpoint5 of endpoints5) {
884902
885331
  if (endpoint5.enabled && options.probe && endpoint5.reachable === false) {
884903
885332
  issues.push(`${endpoint5.label} is enabled but not reachable on ${endpoint5.binding.host}:${endpoint5.binding.port}.`);
@@ -884965,7 +885394,7 @@ function readAuthPosture(runtime3) {
884965
885394
  });
884966
885395
  const userStorePath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
884967
885396
  const bootstrapCredentialPath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
884968
- const operatorTokenPath = join95(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
885397
+ const operatorTokenPath = join97(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
884969
885398
  return {
884970
885399
  userStorePath,
884971
885400
  userStorePresent: existsSync82(userStorePath),
@@ -885125,7 +885554,7 @@ async function handleBundleCommand(runtime3) {
885125
885554
  }
885126
885555
  // src/cli/management.ts
885127
885556
  import { existsSync as existsSync84 } from "fs";
885128
- import { join as join98 } from "path";
885557
+ import { join as join100 } from "path";
885129
885558
  import { spawn as spawn5 } from "child_process";
885130
885559
  import { networkInterfaces as networkInterfaces4 } from "os";
885131
885560
 
@@ -885152,7 +885581,7 @@ function formatProviderAuthRoute(route) {
885152
885581
 
885153
885582
  // src/cli/management-commands.ts
885154
885583
  import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync57 } from "fs";
885155
- import { dirname as dirname65, join as join96 } from "path";
885584
+ import { dirname as dirname65, join as join98 } from "path";
885156
885585
  init_config8();
885157
885586
  init_config8();
885158
885587
  init_config8();
@@ -885469,7 +885898,7 @@ async function handleTasks(runtime3) {
885469
885898
  });
885470
885899
  }
885471
885900
  async function renderPairing(runtime3) {
885472
- const daemonHomeDir = join96(runtime3.homeDirectory, ".goodvibes", "daemon");
885901
+ const daemonHomeDir = join98(runtime3.homeDirectory, ".goodvibes", "daemon");
885473
885902
  const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
885474
885903
  const binding = resolveRuntimeEndpointBinding(runtime3.configManager, "controlPlane");
885475
885904
  const daemonUrl = `http://${urlHostForBindHost2(binding.host)}:${binding.port}`;
@@ -886008,7 +886437,7 @@ var DELEGATION_METHOD = {
886008
886437
 
886009
886438
  // src/cli/agent-knowledge-runtime.ts
886010
886439
  import { existsSync as existsSync83, readFileSync as readFileSync90 } from "fs";
886011
- import { join as join97 } from "path";
886440
+ import { join as join99 } from "path";
886012
886441
 
886013
886442
  // node_modules/@pellux/goodvibes-sdk/dist/browser-scoped.js
886014
886443
  init_dist();
@@ -886374,7 +886803,7 @@ function resolveDaemonConnection(runtime3) {
886374
886803
  const host = String(runtime3.configManager.get("controlPlane.host") ?? "127.0.0.1");
886375
886804
  const port = Number(runtime3.configManager.get("controlPlane.port") ?? 3421);
886376
886805
  const baseUrl = `http://${host}:${Number.isFinite(port) ? port : 3421}`;
886377
- const tokenPath = join97(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
886806
+ const tokenPath = join99(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
886378
886807
  if (!existsSync83(tokenPath))
886379
886808
  return { baseUrl, token: null, tokenPath };
886380
886809
  try {
@@ -887113,6 +887542,12 @@ function skillRegistry(runtime3) {
887113
887542
  homeDirectory: runtime3.homeDirectory
887114
887543
  }));
887115
887544
  }
887545
+ function shellPaths(runtime3) {
887546
+ return createShellPathService2({
887547
+ workingDirectory: runtime3.workingDirectory,
887548
+ homeDirectory: runtime3.homeDirectory
887549
+ });
887550
+ }
887116
887551
  function summarizePersona2(persona, activePersonaId) {
887117
887552
  const active = persona.id === activePersonaId ? "active" : "available";
887118
887553
  const tags = persona.tags.length > 0 ? ` tags=${persona.tags.join(",")}` : "";
@@ -887154,6 +887589,48 @@ function renderPersona2(persona, activePersonaId) {
887154
887589
  ].filter((line2) => Boolean(line2)).join(`
887155
887590
  `);
887156
887591
  }
887592
+ function summarizeDiscoveredPersona2(persona) {
887593
+ const description = persona.description ? ` - ${persona.description}` : "";
887594
+ return [
887595
+ ` ${persona.name} ${persona.origin}${description}`,
887596
+ ` path: ${persona.path}`
887597
+ ].join(`
887598
+ `);
887599
+ }
887600
+ function renderDiscoveredPersonaList(personas) {
887601
+ if (personas.length === 0) {
887602
+ return [
887603
+ "Discovered Agent persona files",
887604
+ " No persona markdown files found in Agent persona folders.",
887605
+ " Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
887606
+ ].join(`
887607
+ `);
887608
+ }
887609
+ return [
887610
+ `Discovered Agent persona files (${personas.length})`,
887611
+ ...personas.map(summarizeDiscoveredPersona2),
887612
+ "",
887613
+ "Import one with: goodvibes-agent personas import-discovered <name> --yes"
887614
+ ].join(`
887615
+ `);
887616
+ }
887617
+ function discoveredPersonaLookupValues2(persona) {
887618
+ const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
887619
+ const basename6 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
887620
+ return [persona.name, slug, persona.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
887621
+ }
887622
+ function findDiscoveredPersona2(personas, idOrName) {
887623
+ const lookup = idOrName.trim().toLowerCase();
887624
+ if (!lookup)
887625
+ return null;
887626
+ return personas.find((persona) => discoveredPersonaLookupValues2(persona).includes(lookup)) ?? null;
887627
+ }
887628
+ function discoveredPersonaFrontmatterList(persona, key) {
887629
+ const value = persona.frontmatter[key];
887630
+ if (!value)
887631
+ return [];
887632
+ return value.split(",").map((entry) => entry.trim()).filter(Boolean);
887633
+ }
887157
887634
  function summarizeSkill2(skill) {
887158
887635
  const enabled = skill.enabled ? "enabled" : "disabled";
887159
887636
  const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(",")}` : "";
@@ -887179,6 +887656,50 @@ function renderSkillList(title, path7, skills) {
887179
887656
  ].join(`
887180
887657
  `);
887181
887658
  }
887659
+ function summarizeDiscoveredSkill2(skill) {
887660
+ const description = skill.description ? ` - ${skill.description}` : "";
887661
+ const dependencies = skill.dependencies.length > 0 ? ` deps=${skill.dependencies.join(",")}` : "";
887662
+ const includes = skill.includes.length > 0 ? ` includes=${skill.includes.join(",")}` : "";
887663
+ return [
887664
+ ` ${skill.name} ${skill.origin}${description}${dependencies}${includes}`,
887665
+ ` path: ${skill.path}`
887666
+ ].join(`
887667
+ `);
887668
+ }
887669
+ function renderDiscoveredSkillList(skills) {
887670
+ if (skills.length === 0) {
887671
+ return [
887672
+ "Discovered Agent skill files",
887673
+ " No SKILL.md or .md skill files found in Agent skill folders.",
887674
+ " Search roots: .goodvibes/skills, .goodvibes/agent/skills, ~/.goodvibes/skills, ~/.goodvibes/agent/skills"
887675
+ ].join(`
887676
+ `);
887677
+ }
887678
+ return [
887679
+ `Discovered Agent skill files (${skills.length})`,
887680
+ ...skills.map(summarizeDiscoveredSkill2),
887681
+ "",
887682
+ "Import one with: goodvibes-agent skills import-discovered <name> --yes"
887683
+ ].join(`
887684
+ `);
887685
+ }
887686
+ function discoveredSkillLookupValues2(skill) {
887687
+ const slug = skill.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
887688
+ const basename6 = skill.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
887689
+ return [skill.name, slug, skill.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
887690
+ }
887691
+ function findDiscoveredSkill2(skills, idOrName) {
887692
+ const lookup = idOrName.trim().toLowerCase();
887693
+ if (!lookup)
887694
+ return null;
887695
+ return skills.find((skill) => discoveredSkillLookupValues2(skill).includes(lookup)) ?? null;
887696
+ }
887697
+ function discoveredFrontmatterList(skill, key) {
887698
+ const value = skill.frontmatter[key];
887699
+ if (!value)
887700
+ return [];
887701
+ return value.split(",").map((entry) => entry.trim()).filter(Boolean);
887702
+ }
887182
887703
  function renderBundleList2(title, path7, bundles) {
887183
887704
  if (bundles.length === 0) {
887184
887705
  return [
@@ -887233,10 +887754,10 @@ function renderBundle2(bundle) {
887233
887754
  `);
887234
887755
  }
887235
887756
  function usagePersonas() {
887236
- return "Usage: goodvibes-agent personas [list|active|search <query>|show <id>|create|update <id>|use <id>|clear|review <id>|stale <id> <reason>|delete <id> --yes]";
887757
+ return "Usage: goodvibes-agent personas [list|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|use <id>|clear|review <id>|stale <id> <reason>|delete <id> --yes]";
887237
887758
  }
887238
887759
  function usageSkills() {
887239
- return "Usage: goodvibes-agent skills [list|enabled|active|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]";
887760
+ return "Usage: goodvibes-agent skills [list|enabled|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]";
887240
887761
  }
887241
887762
  function usageBundles() {
887242
887763
  return "Usage: goodvibes-agent skills bundle [list|enabled|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes]";
@@ -887262,6 +887783,45 @@ async function handlePersonasCommand(runtime3) {
887262
887783
  return failure(runtime3, "agent.personas.active_missing", "No active Agent persona.", 1);
887263
887784
  return success3(runtime3, "agent.personas.active", active, renderPersona2(active, active.id));
887264
887785
  }
887786
+ if (normalized === "discover") {
887787
+ const discovered = await discoverPersonas(shellPaths(runtime3));
887788
+ return success3(runtime3, "agent.personas.discover", { personas: discovered }, renderDiscoveredPersonaList(discovered));
887789
+ }
887790
+ if (normalized === "import-discovered" || normalized === "import-persona") {
887791
+ const options = parseOptions(rest);
887792
+ const name51 = options.positionals.join(" ").trim();
887793
+ if (!name51)
887794
+ return failure(runtime3, "invalid_persona_command", "Usage: goodvibes-agent personas import-discovered <name> [--use] --yes", 2);
887795
+ const discovered = findDiscoveredPersona2(await discoverPersonas(shellPaths(runtime3)), name51);
887796
+ if (!discovered) {
887797
+ return failure(runtime3, "persona_discovery_not_found", `Unknown discovered Agent persona: ${name51}
887798
+ Run goodvibes-agent personas discover to inspect available persona files.`, 1);
887799
+ }
887800
+ if (!hasFlag3(options, "yes")) {
887801
+ return success3(runtime3, "agent.personas.import_discovered.preview", { persona: discovered }, [
887802
+ "Agent persona import preview",
887803
+ ` name: ${discovered.name}`,
887804
+ ` origin: ${discovered.origin}`,
887805
+ ` path: ${discovered.path}`,
887806
+ ` description: ${discovered.description || "(none)"}`,
887807
+ ` body characters: ${discovered.body.length}`,
887808
+ " next: rerun with --yes to import into the Agent-local persona registry"
887809
+ ].join(`
887810
+ `));
887811
+ }
887812
+ const persona = registry5.create({
887813
+ name: discovered.name,
887814
+ description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
887815
+ body: discovered.body,
887816
+ tags: discoveredPersonaFrontmatterList(discovered, "tags"),
887817
+ triggers: discoveredPersonaFrontmatterList(discovered, "triggers"),
887818
+ source: "imported",
887819
+ provenance: `discovered:${discovered.origin}:${discovered.path}`
887820
+ });
887821
+ if (hasFlag3(options, "use"))
887822
+ registry5.setActive(persona.id);
887823
+ return success3(runtime3, "agent.personas.import_discovered", persona, `Imported Agent persona ${persona.id}: ${persona.name}${hasFlag3(options, "use") ? " (active)" : ""}`);
887824
+ }
887265
887825
  if (normalized === "search" || normalized === "find") {
887266
887826
  const query2 = rest.join(" ").trim();
887267
887827
  const results = registry5.search(query2);
@@ -887466,6 +888026,44 @@ async function handleSkillsCommand(runtime3) {
887466
888026
 
887467
888027
  `));
887468
888028
  }
888029
+ if (normalized === "discover") {
888030
+ const discovered = await discoverSkills(shellPaths(runtime3));
888031
+ return success3(runtime3, "agent.skills.discover", { skills: discovered }, renderDiscoveredSkillList(discovered));
888032
+ }
888033
+ if (normalized === "import-discovered" || normalized === "import-skill") {
888034
+ const options = parseOptions(rest);
888035
+ const name51 = options.positionals.join(" ").trim();
888036
+ if (!name51)
888037
+ return failure(runtime3, "invalid_skill_command", "Usage: goodvibes-agent skills import-discovered <name> [--enabled] --yes", 2);
888038
+ const discovered = findDiscoveredSkill2(await discoverSkills(shellPaths(runtime3)), name51);
888039
+ if (!discovered) {
888040
+ return failure(runtime3, "skill_discovery_not_found", `Unknown discovered Agent skill: ${name51}
888041
+ Run goodvibes-agent skills discover to inspect available skill files.`, 1);
888042
+ }
888043
+ if (!hasFlag3(options, "yes")) {
888044
+ return success3(runtime3, "agent.skills.import_discovered.preview", { skill: discovered }, [
888045
+ "Agent skill import preview",
888046
+ ` name: ${discovered.name}`,
888047
+ ` origin: ${discovered.origin}`,
888048
+ ` path: ${discovered.path}`,
888049
+ ` description: ${discovered.description || "(none)"}`,
888050
+ ` procedure characters: ${discovered.body.length}`,
888051
+ " next: rerun with --yes to import into the Agent-local skill registry"
888052
+ ].join(`
888053
+ `));
888054
+ }
888055
+ const skill = registry5.create({
888056
+ name: discovered.name,
888057
+ description: discovered.description || `Imported skill from ${discovered.origin} skill file.`,
888058
+ procedure: discovered.body,
888059
+ tags: discoveredFrontmatterList(discovered, "tags"),
888060
+ triggers: discoveredFrontmatterList(discovered, "triggers"),
888061
+ enabled: hasFlag3(options, "enabled"),
888062
+ source: "imported",
888063
+ provenance: `discovered:${discovered.origin}:${discovered.path}`
888064
+ });
888065
+ return success3(runtime3, "agent.skills.import_discovered", skill, `Imported Agent skill ${skill.id}: ${skill.name}${skill.enabled ? " (enabled)" : ""}`);
888066
+ }
887469
888067
  if (normalized === "search" || normalized === "find") {
887470
888068
  const query2 = rest.join(" ").trim();
887471
888069
  const results = registry5.search(query2);
@@ -888451,17 +889049,87 @@ function routineRegistry(runtime3) {
888451
889049
  homeDirectory: runtime3.homeDirectory
888452
889050
  }));
888453
889051
  }
889052
+ function shellPaths2(runtime3) {
889053
+ return createShellPathService2({
889054
+ workingDirectory: runtime3.workingDirectory,
889055
+ homeDirectory: runtime3.homeDirectory
889056
+ });
889057
+ }
888454
889058
  function routineReceiptStore(runtime3) {
888455
889059
  return RoutineScheduleReceiptStore.fromShellPaths(createShellPathService2({
888456
889060
  workingDirectory: runtime3.workingDirectory,
888457
889061
  homeDirectory: runtime3.homeDirectory
888458
889062
  }));
888459
889063
  }
889064
+ function splitList6(value) {
889065
+ if (!value)
889066
+ return [];
889067
+ return value.split(",").map((entry) => entry.trim()).filter(Boolean);
889068
+ }
889069
+ function parseImportFlags(args2) {
889070
+ const positionals = [];
889071
+ let enabled = false;
889072
+ let yes = false;
889073
+ for (const arg of args2) {
889074
+ if (arg === "--enabled") {
889075
+ enabled = true;
889076
+ continue;
889077
+ }
889078
+ if (arg === "--yes") {
889079
+ yes = true;
889080
+ continue;
889081
+ }
889082
+ positionals.push(arg);
889083
+ }
889084
+ return { name: positionals.join(" ").trim(), enabled, yes };
889085
+ }
888460
889086
  function summarizeRoutine2(routine) {
888461
889087
  const enabled = routine.enabled ? "enabled" : "disabled";
888462
889088
  const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(",")}` : "";
888463
889089
  return ` ${routine.id} ${enabled} ${routine.reviewState} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
888464
889090
  }
889091
+ function summarizeDiscoveredRoutine2(routine) {
889092
+ const description = routine.description ? ` - ${routine.description}` : "";
889093
+ return [
889094
+ ` ${routine.name} ${routine.origin}${description}`,
889095
+ ` path: ${routine.path}`
889096
+ ].join(`
889097
+ `);
889098
+ }
889099
+ function renderDiscoveredRoutineList(routines) {
889100
+ if (routines.length === 0) {
889101
+ return [
889102
+ "Discovered Agent routine files",
889103
+ " No routine markdown files found in Agent routine folders.",
889104
+ " Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
889105
+ ].join(`
889106
+ `);
889107
+ }
889108
+ return [
889109
+ `Discovered Agent routine files (${routines.length})`,
889110
+ ...routines.map(summarizeDiscoveredRoutine2),
889111
+ "",
889112
+ "Import one with: goodvibes-agent routines import-discovered <name> --yes"
889113
+ ].join(`
889114
+ `);
889115
+ }
889116
+ function discoveredRoutineLookupValues2(routine) {
889117
+ const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
889118
+ const basename6 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
889119
+ return [routine.name, slug, routine.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
889120
+ }
889121
+ function findDiscoveredRoutine2(routines, idOrName) {
889122
+ const lookup = idOrName.trim().toLowerCase();
889123
+ if (!lookup)
889124
+ return null;
889125
+ return routines.find((routine) => discoveredRoutineLookupValues2(routine).includes(lookup)) ?? null;
889126
+ }
889127
+ function discoveredRoutineFrontmatterList(routine, key) {
889128
+ const value = routine.frontmatter[key];
889129
+ if (!value)
889130
+ return [];
889131
+ return splitList6(value);
889132
+ }
888465
889133
  function renderRoutineList(title, path7, routines) {
888466
889134
  if (routines.length === 0) {
888467
889135
  return [
@@ -888580,6 +889248,84 @@ async function handleRoutinesCommand(runtime3) {
888580
889248
  exitCode: 0
888581
889249
  };
888582
889250
  }
889251
+ if (normalized === "discover") {
889252
+ const discovered = await discoverRoutines(shellPaths2(runtime3));
889253
+ const value = {
889254
+ ok: true,
889255
+ kind: "agent.routines.discover",
889256
+ data: { routines: discovered }
889257
+ };
889258
+ return {
889259
+ output: jsonOrText3(runtime3, value, renderDiscoveredRoutineList(discovered)),
889260
+ exitCode: 0
889261
+ };
889262
+ }
889263
+ if (normalized === "import-discovered" || normalized === "import-routine") {
889264
+ const parsed = parseImportFlags(rest);
889265
+ if (!parsed.name) {
889266
+ const failure3 = {
889267
+ ok: false,
889268
+ kind: "invalid_routine_command",
889269
+ error: "Usage: goodvibes-agent routines import-discovered <name> [--enabled] --yes"
889270
+ };
889271
+ return {
889272
+ output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
889273
+ exitCode: 2
889274
+ };
889275
+ }
889276
+ const discovered = findDiscoveredRoutine2(await discoverRoutines(shellPaths2(runtime3)), parsed.name);
889277
+ if (!discovered) {
889278
+ const failure3 = {
889279
+ ok: false,
889280
+ kind: "routine_discovery_not_found",
889281
+ error: `Unknown discovered Agent routine: ${parsed.name}
889282
+ Run goodvibes-agent routines discover to inspect available routine files.`
889283
+ };
889284
+ return {
889285
+ output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
889286
+ exitCode: 1
889287
+ };
889288
+ }
889289
+ if (!parsed.yes) {
889290
+ const value2 = {
889291
+ ok: true,
889292
+ kind: "agent.routines.import_discovered.preview",
889293
+ data: { routine: discovered }
889294
+ };
889295
+ return {
889296
+ output: jsonOrText3(runtime3, value2, [
889297
+ "Agent routine import preview",
889298
+ ` name: ${discovered.name}`,
889299
+ ` origin: ${discovered.origin}`,
889300
+ ` path: ${discovered.path}`,
889301
+ ` description: ${discovered.description || "(none)"}`,
889302
+ ` steps characters: ${discovered.steps.length}`,
889303
+ " next: rerun with --yes to import into the Agent-local routine registry"
889304
+ ].join(`
889305
+ `)),
889306
+ exitCode: 0
889307
+ };
889308
+ }
889309
+ const routine = registry5.create({
889310
+ name: discovered.name,
889311
+ description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
889312
+ steps: discovered.steps,
889313
+ tags: discoveredRoutineFrontmatterList(discovered, "tags"),
889314
+ triggers: discoveredRoutineFrontmatterList(discovered, "triggers"),
889315
+ enabled: parsed.enabled,
889316
+ source: "imported",
889317
+ provenance: `discovered:${discovered.origin}:${discovered.path}`
889318
+ });
889319
+ const value = {
889320
+ ok: true,
889321
+ kind: "agent.routines.import_discovered",
889322
+ data: routine
889323
+ };
889324
+ return {
889325
+ output: jsonOrText3(runtime3, value, `Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`),
889326
+ exitCode: 0
889327
+ };
889328
+ }
888583
889329
  if (normalized === "show") {
888584
889330
  const id = rest[0];
888585
889331
  if (!id)
@@ -888644,7 +889390,7 @@ async function handleRoutinesCommand(runtime3) {
888644
889390
  return handleRoutinePromotion(runtime3, rest);
888645
889391
  }
888646
889392
  return {
888647
- output: "Usage: goodvibes-agent routines [list|enabled|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]",
889393
+ output: "Usage: goodvibes-agent routines [list|enabled|discover|import-discovered <name> --yes|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]",
888648
889394
  exitCode: 2
888649
889395
  };
888650
889396
  }
@@ -888746,13 +889492,13 @@ async function withRuntimeServices(runtime3, fn) {
888746
889492
  }
888747
889493
  }
888748
889494
  function readAuthPaths(runtime3) {
888749
- const shellPaths = createShellPathService2({
889495
+ const shellPaths3 = createShellPathService2({
888750
889496
  workingDirectory: runtime3.workingDirectory,
888751
889497
  homeDirectory: runtime3.homeDirectory
888752
889498
  });
888753
- const userStorePath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
888754
- const bootstrapCredentialPath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
888755
- const operatorTokenPath = join98(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
889499
+ const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
889500
+ const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
889501
+ const operatorTokenPath = join100(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
888756
889502
  return {
888757
889503
  userStorePath,
888758
889504
  userStorePresent: existsSync84(userStorePath),
@@ -889267,7 +890013,7 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
889267
890013
  workingDirectory: bootstrapWorkingDir,
889268
890014
  homeDirectory: bootstrapHomeDirectory
889269
890015
  } = ownership;
889270
- configureActivityLogger(join99(bootstrapWorkingDir, ".goodvibes", "logs"));
890016
+ configureActivityLogger(join101(bootstrapWorkingDir, ".goodvibes", "logs"));
889271
890017
  const configManager = new ConfigManager({
889272
890018
  workingDir: bootstrapWorkingDir,
889273
890019
  homeDir: bootstrapHomeDirectory,
@@ -889312,14 +890058,14 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
889312
890058
  process.exit(2);
889313
890059
  }
889314
890060
  if (cli.command === "status" || cli.command === "doctor" || cli.command === "onboarding" && cli.commandArgs[0] === "status") {
889315
- const shellPaths = createShellPathService2({
890061
+ const shellPaths3 = createShellPathService2({
889316
890062
  workingDirectory: bootstrapWorkingDir,
889317
890063
  homeDirectory: bootstrapHomeDirectory
889318
890064
  });
889319
- const userStorePath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
889320
- const bootstrapCredentialPath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
889321
- const operatorTokenPath = join99(bootstrapHomeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
889322
- const onboardingMarkers = readOnboardingCheckMarkers(shellPaths);
890065
+ const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
890066
+ const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
890067
+ const operatorTokenPath = join101(bootstrapHomeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
890068
+ const onboardingMarkers = readOnboardingCheckMarkers(shellPaths3);
889323
890069
  const service = await buildCliServicePosture({
889324
890070
  configManager,
889325
890071
  workingDirectory: bootstrapWorkingDir,
@@ -889433,8 +890179,8 @@ function getInteractiveTerminalLaunchError(input) {
889433
890179
  `);
889434
890180
  }
889435
890181
  function applyInitialTuiCliState(options) {
889436
- const { cli, input, commandRegistry, commandContext, shellPaths, render } = options;
889437
- const globalOnboardingMarker = readOnboardingCheckMarker(shellPaths, "user");
890182
+ const { cli, input, commandRegistry, commandContext, shellPaths: shellPaths3, render } = options;
890183
+ const globalOnboardingMarker = readOnboardingCheckMarker(shellPaths3, "user");
889438
890184
  const seededPrompt = cli.flags.prompt ?? (cli.rawCommand === undefined && cli.positionals.length > 0 ? cli.positionals.join(" ") : undefined);
889439
890185
  if (cli.command === "onboarding") {
889440
890186
  input.openOnboardingWizard({ mode: "edit", reset: true });
@@ -889456,7 +890202,7 @@ function applyInitialTuiCliState(options) {
889456
890202
 
889457
890203
  // src/audio/player.ts
889458
890204
  import { accessSync, constants as constants4 } from "fs";
889459
- import { delimiter, join as join100 } from "path";
890205
+ import { delimiter, join as join102 } from "path";
889460
890206
  import { spawn as spawn6 } from "child_process";
889461
890207
 
889462
890208
  class LocalStreamingAudioPlayer {
@@ -889553,7 +890299,7 @@ function findExecutable(name51, env2) {
889553
890299
  if (!dir)
889554
890300
  continue;
889555
890301
  for (const ext of extensions14) {
889556
- const candidate = join100(dir, `${name51}${ext}`);
890302
+ const candidate = join102(dir, `${name51}${ext}`);
889557
890303
  try {
889558
890304
  accessSync(candidate, constants4.X_OK);
889559
890305
  return candidate;