svamp-cli 0.2.255 → 0.2.257

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/bin/skills/artifact/SKILL.md +1 -1
  2. package/dist/{agentCommands-Bd7sTL72.mjs → agentCommands-fCsOp7ko.mjs} +5 -5
  3. package/dist/{auth-K6RHd3Se.mjs → auth-BH6Awl3O.mjs} +1 -1
  4. package/dist/cli.mjs +61 -61
  5. package/dist/{commands-B1rI6nQ_.mjs → commands-B5veY89L.mjs} +1 -1
  6. package/dist/{commands-yoeiGRYI.mjs → commands-B6BkPRui.mjs} +84 -19
  7. package/dist/{commands-BjhpfRPs.mjs → commands-BCmpKBjg.mjs} +1 -1
  8. package/dist/{commands-zkbQRqlq.mjs → commands-BpNDUqvv.mjs} +6 -6
  9. package/dist/{commands-DwXWC_ka.mjs → commands-BzF6GzdR.mjs} +1 -1
  10. package/dist/{commands-E4FV1Mrf.mjs → commands-CE1PdEJJ.mjs} +1 -1
  11. package/dist/{commands-DSFK1j6n.mjs → commands-DNIxtTXe.mjs} +2 -2
  12. package/dist/{fleet-B_38I5pd.mjs → fleet-XYsLuf-3.mjs} +1 -1
  13. package/dist/{frpc-C6yDezIg.mjs → frpc-QESvQN-s.mjs} +1 -1
  14. package/dist/{headlessCli-0He_Dybz.mjs → headlessCli-DuCmcrAL.mjs} +2 -2
  15. package/dist/index.mjs +1 -1
  16. package/dist/{package-Dm1gKqm5.mjs → package-BA3c2JLu.mjs} +1 -1
  17. package/dist/{rpc-D_d_zq8R.mjs → rpc-Bscxex4z.mjs} +1 -1
  18. package/dist/{rpc-BAhRday-.mjs → rpc-DCeDG4c7.mjs} +1 -1
  19. package/dist/{run-ClMTHM__.mjs → run-BmOCcZRG.mjs} +1 -1
  20. package/dist/{run-DsAMQZUu.mjs → run-BtGnnEMI.mjs} +138 -85
  21. package/dist/{scheduler-BwZS9UWD.mjs → scheduler-Dbqmnd_o.mjs} +20 -2
  22. package/dist/{serveCommands-sEZ7mQc4.mjs → serveCommands-DueTsJSe.mjs} +5 -5
  23. package/dist/{serveManager-C1-FPoEa.mjs → serveManager-BclzoPIb.mjs} +2 -2
  24. package/dist/{sideband-CQJ-0LbS.mjs → sideband-C_ifGgde.mjs} +1 -1
  25. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
- import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-E4FV1Mrf.mjs';
3
+ import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-CE1PdEJJ.mjs';
4
4
  import { execSync } from 'node:child_process';
5
- import { u as updateIssue, t as addComment, v as addIssue, k as shortId } from './run-DsAMQZUu.mjs';
5
+ import { u as updateIssue, t as addComment, v as addIssue, k as shortId } from './run-BtGnnEMI.mjs';
6
6
  import 'node:os';
7
7
  import 'os';
8
8
  import 'fs/promises';
@@ -106,7 +106,7 @@ ${childStatus}`
106
106
  return { ok: false, stage: "merge", rework: true, detail: `merge conflict \u2014 aborted:
107
107
  ${detail.trim()}` };
108
108
  }
109
- try {
109
+ if (!isMainWorkingTree(projectRoot, worktreePath)) try {
110
110
  git(projectRoot, `worktree remove --force ${worktreePath}`);
111
111
  } catch (e) {
112
112
  try {
@@ -123,7 +123,7 @@ ${detail.trim()}` };
123
123
  return { ok: false, stage: "remove-worktree", detail: `merged OK but worktree removal failed: ${detail.trim()}` };
124
124
  }
125
125
  }
126
- if (input.deleteBranch !== false) {
126
+ if (input.deleteBranch !== false && branch !== baseBranch) {
127
127
  try {
128
128
  git(projectRoot, `branch -d ${branch}`);
129
129
  } catch {
@@ -131,12 +131,47 @@ ${detail.trim()}` };
131
131
  }
132
132
  return { ok: true, stage: "done", detail: `merged ${branch} into ${baseBranch}` };
133
133
  }
134
+ function isMainWorkingTree(projectRoot, worktreePath) {
135
+ if (resolve(worktreePath) === resolve(projectRoot)) return true;
136
+ try {
137
+ const first = git(projectRoot, "worktree list --porcelain").split("\n").find((l) => l.startsWith("worktree "));
138
+ if (first) return resolve(first.slice("worktree ".length).trim()) === resolve(worktreePath);
139
+ } catch {
140
+ }
141
+ return false;
142
+ }
134
143
  function projectRootFromWorktree(worktreePath) {
135
144
  const marker = "/.dev/worktree/";
136
145
  const idx = worktreePath.indexOf(marker);
137
146
  if (idx === -1) return null;
138
147
  return worktreePath.slice(0, idx);
139
148
  }
149
+ function removeWorktree(worktreePath) {
150
+ const projectRoot = projectRootFromWorktree(worktreePath);
151
+ if (!projectRoot) return;
152
+ let branch = null;
153
+ try {
154
+ branch = currentBranch(worktreePath);
155
+ } catch {
156
+ }
157
+ try {
158
+ git(projectRoot, `worktree remove --force ${worktreePath}`);
159
+ } catch {
160
+ }
161
+ try {
162
+ git(projectRoot, "worktree prune");
163
+ } catch {
164
+ }
165
+ if (branch) {
166
+ try {
167
+ git(projectRoot, `branch -D ${branch}`);
168
+ } catch {
169
+ }
170
+ }
171
+ }
172
+ function resolveNotifyLead(leadId, childParentSessionId, childId) {
173
+ return leadId || childParentSessionId || childId;
174
+ }
140
175
 
141
176
  function isStandaloneChild(crew) {
142
177
  return !!crew && crew.standalone === true;
@@ -204,13 +239,13 @@ async function featureStart(brief, opts = {}) {
204
239
  }
205
240
  const leadId = requireLead(opts.leadId);
206
241
  const { server, machine } = await connectAndGetMachine(opts.machineId);
242
+ let wt = null;
207
243
  try {
208
244
  const sessions = await machine.listSessions();
209
245
  const lead = resolveSessionId(sessions, leadId);
210
246
  const standalone = !!opts.noWorktree;
211
247
  let childDir;
212
248
  let base = "";
213
- let wt = null;
214
249
  if (standalone) {
215
250
  const dir = opts.directory;
216
251
  if (!dir) {
@@ -248,6 +283,13 @@ async function featureStart(brief, opts = {}) {
248
283
  ...opts.model ? { model: opts.model } : {}
249
284
  });
250
285
  if (result.type !== "success" || !result.sessionId) {
286
+ if (wt) {
287
+ try {
288
+ removeWorktree(wt.path);
289
+ console.error(`Cleaned up worktree ${wt.branch}.`);
290
+ } catch {
291
+ }
292
+ }
251
293
  console.error(`Failed to spawn feature child: ${result.errorMessage || result.type}`);
252
294
  process.exit(1);
253
295
  }
@@ -329,6 +371,15 @@ async function featureStart(brief, opts = {}) {
329
371
  console.log(` branch: ${wt.branch} (merges back to ${base})`);
330
372
  }
331
373
  console.log(judges.length ? ` gate: ${judges.map((j) => j.type).join(" \u2192 ")} (oracle auto-approves \u2192 lead ${standalone ? "closes" : "merges"})` : ` gate: none \u2014 child runs \`feature done\` when complete; lead ${standalone ? "detaches & closes" : "reviews & merges"}`);
374
+ } catch (e) {
375
+ if (wt) {
376
+ try {
377
+ removeWorktree(wt.path);
378
+ console.error(`Cleaned up worktree ${wt.branch} after error.`);
379
+ } catch {
380
+ }
381
+ }
382
+ throw e;
332
383
  } finally {
333
384
  await server.disconnect();
334
385
  }
@@ -506,25 +557,24 @@ async function featureMerge(childPartial, opts = {}) {
506
557
  console.error("Could not determine the lead project root (base worktree).");
507
558
  process.exit(1);
508
559
  }
509
- if (leadId) {
510
- try {
511
- await inbox(
512
- machine,
513
- leadId,
514
- childId,
515
- `<crew-freeze>Your lead is merging branch ${branch} into ${base}. Stop editing files now; do not commit until told.</crew-freeze>`,
516
- "crew: freeze for merge"
517
- );
518
- } catch {
519
- }
560
+ const notifyLead = resolveNotifyLead(leadId, meta?.parentSessionId, childId);
561
+ try {
562
+ await inbox(
563
+ machine,
564
+ notifyLead,
565
+ childId,
566
+ `<crew-freeze>Your lead is merging branch ${branch} into ${base}. Stop editing files now; do not commit until told.</crew-freeze>`,
567
+ "crew: freeze for merge"
568
+ );
569
+ } catch {
520
570
  }
521
571
  const r = mergeBack({ projectRoot, branch, worktreePath, baseBranch: base, deleteBranch: opts.deleteBranch });
522
572
  if (!r.ok) {
523
- if (r.rework && leadId) {
573
+ if (r.rework) {
524
574
  try {
525
575
  await inbox(
526
576
  machine,
527
- leadId,
577
+ notifyLead,
528
578
  childId,
529
579
  `<crew-rework branch="${branch}">
530
580
  Merge was not applied: ${r.detail}
@@ -537,7 +587,21 @@ Resolve and run \`svamp feature done\` again.
537
587
  console.error(`Merge deferred (rework) at ${r.stage}: ${r.detail}`);
538
588
  console.error(`Child ${childId.slice(0, 8)} re-woken with guidance; left running.`);
539
589
  } else {
590
+ try {
591
+ await inbox(
592
+ machine,
593
+ notifyLead,
594
+ childId,
595
+ `<crew-blocked branch="${branch}">
596
+ Merge could not be applied (${r.stage}): ${r.detail}
597
+ Stop editing and hold \u2014 do not keep working. Once the blocker is resolved, the lead can retry \`svamp feature merge\`.
598
+ </crew-blocked>`,
599
+ "crew: merge blocked"
600
+ );
601
+ } catch {
602
+ }
540
603
  console.error(`Merge failed at ${r.stage}: ${r.detail}`);
604
+ console.error(`Child ${childId.slice(0, 8)} notified + left running (un-merged work preserved). Resolve the blocker, then retry \`svamp feature merge ${childId.slice(0, 8)}\`.`);
541
605
  }
542
606
  process.exit(1);
543
607
  }
@@ -548,7 +612,8 @@ Resolve and run \`svamp feature done\` again.
548
612
  console.warn(`Merged, but could not archive child: ${e.message}`);
549
613
  }
550
614
  }
551
- console.log(`\u2705 Merged ${branch} \u2192 ${base}; worktree removed; child ${childId.slice(0, 8)} ${opts.keepChild ? "kept" : "archived"}.`);
615
+ const cleanup = isMainWorkingTree(projectRoot, worktreePath) ? "ran in the lead tree (no worktree to remove)" : "worktree removed";
616
+ console.log(`\u2705 Merged ${branch} \u2192 ${base}; ${cleanup}; child ${childId.slice(0, 8)} ${opts.keepChild ? "kept" : "archived"}.`);
552
617
  } finally {
553
618
  await server.disconnect();
554
619
  }
@@ -1,7 +1,7 @@
1
1
  import os from 'os';
2
2
  import fs__default from 'fs';
3
3
  import { resolve, join, relative } from 'path';
4
- import { T as parseFrontmatter, U as getSkillsServer, V as getSkillsWorkspaceName, W as getSkillsCollectionName, X as fetchWithTimeout, Y as searchSkills, Z as SKILLS_DIR, _ as getSkillInfo, $ as downloadSkillFile, a0 as listSkillFiles } from './run-DsAMQZUu.mjs';
4
+ import { T as parseFrontmatter, U as getSkillsServer, V as getSkillsWorkspaceName, W as getSkillsCollectionName, X as fetchWithTimeout, Y as searchSkills, Z as SKILLS_DIR, _ as getSkillInfo, $ as downloadSkillFile, a0 as listSkillFiles } from './run-BtGnnEMI.mjs';
5
5
  import 'fs/promises';
6
6
  import 'url';
7
7
  import 'child_process';
@@ -58,7 +58,7 @@ async function serviceExpose(args) {
58
58
  process.exit(1);
59
59
  }
60
60
  if (foreground) {
61
- const { runFrpcTunnel } = await import('./frpc-C6yDezIg.mjs');
61
+ const { runFrpcTunnel } = await import('./frpc-QESvQN-s.mjs');
62
62
  await runFrpcTunnel(name, ports, void 0, {
63
63
  group,
64
64
  groupKey,
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
68
68
  });
69
69
  return;
70
70
  }
71
- const { connectAndGetMachine } = await import('./commands-E4FV1Mrf.mjs');
71
+ const { connectAndGetMachine } = await import('./commands-CE1PdEJJ.mjs');
72
72
  const { server, machine } = await connectAndGetMachine();
73
73
  try {
74
74
  const status = await machine.tunnelStart({
@@ -90,7 +90,7 @@ async function serviceExpose(args) {
90
90
  console.log(` port ${port}: ${url}`);
91
91
  }
92
92
  if (process.env.SVAMP_SESSION_ID) {
93
- const { autoAddSessionLink } = await import('./agentCommands-Bd7sTL72.mjs');
93
+ const { autoAddSessionLink } = await import('./agentCommands-fCsOp7ko.mjs');
94
94
  let added = 0;
95
95
  for (const [port, url] of urlEntries) {
96
96
  const label = urlEntries.length > 1 ? `${name}:${port}` : name;
@@ -136,7 +136,7 @@ async function serviceServe(args) {
136
136
  };
137
137
  process.on("SIGINT", cleanup);
138
138
  process.on("SIGTERM", cleanup);
139
- const { runFrpcTunnel } = await import('./frpc-C6yDezIg.mjs');
139
+ const { runFrpcTunnel } = await import('./frpc-QESvQN-s.mjs');
140
140
  await runFrpcTunnel(name, [caddyPort]);
141
141
  } catch (err) {
142
142
  console.error(`Error serving directory: ${err.message}`);
@@ -145,7 +145,7 @@ async function serviceServe(args) {
145
145
  }
146
146
  async function serviceList(_args) {
147
147
  try {
148
- const { connectAndGetMachine } = await import('./commands-E4FV1Mrf.mjs');
148
+ const { connectAndGetMachine } = await import('./commands-CE1PdEJJ.mjs');
149
149
  const { server, machine } = await connectAndGetMachine();
150
150
  try {
151
151
  const tunnels = await machine.tunnelList({});
@@ -185,7 +185,7 @@ async function serviceDelete(args) {
185
185
  process.exit(1);
186
186
  }
187
187
  try {
188
- const { connectAndGetMachine } = await import('./commands-E4FV1Mrf.mjs');
188
+ const { connectAndGetMachine } = await import('./commands-CE1PdEJJ.mjs');
189
189
  const { server, machine } = await connectAndGetMachine();
190
190
  try {
191
191
  await machine.tunnelStop({ name });
@@ -1,7 +1,7 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
- import { n as resolveProjectRoot, x as searchIssues, w as listIssues, p as resumeIssue, q as pauseIssue, t as addComment, u as updateIssue, o as getIssue, y as isVisibleTo, L as summarize, v as addIssue } from './run-DsAMQZUu.mjs';
4
+ import { n as resolveProjectRoot, x as searchIssues, w as listIssues, p as resumeIssue, q as pauseIssue, t as addComment, u as updateIssue, o as getIssue, y as isVisibleTo, L as summarize, v as addIssue } from './run-BtGnnEMI.mjs';
5
5
  import 'os';
6
6
  import 'fs/promises';
7
7
  import 'fs';
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { basename, resolve, join, isAbsolute } from 'node:path';
4
4
  import os from 'node:os';
5
- import { a2 as formatHandle, a3 as normalizeAllowedUser, a4 as loadSecurityContextConfig, a5 as resolveSecurityContext, a6 as buildSecurityContextFromFlags, a7 as mergeSecurityContexts, c as connectToHypha, a8 as buildSessionShareUrl, a9 as computeOutboundHop, k as shortId, aa as registerAwaitingReply, ab as buildMachineShareUrl, ac as parseHandle, ad as handleMatchesMetadata } from './run-DsAMQZUu.mjs';
5
+ import { a2 as formatHandle, a3 as normalizeAllowedUser, a4 as loadSecurityContextConfig, a5 as resolveSecurityContext, a6 as buildSecurityContextFromFlags, a7 as mergeSecurityContexts, c as connectToHypha, a8 as buildSessionShareUrl, a9 as computeOutboundHop, k as shortId, aa as registerAwaitingReply, ab as buildMachineShareUrl, ac as parseHandle, ad as handleMatchesMetadata } from './run-BtGnnEMI.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-E4FV1Mrf.mjs';
3
+ import { connectAndGetMachine } from './commands-CE1PdEJJ.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:child_process';
6
6
  import 'node:path';
7
7
  import 'node:os';
8
- import './run-DsAMQZUu.mjs';
8
+ import './run-BtGnnEMI.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import os from 'node:os';
4
- import { c as connectToHypha } from './run-DsAMQZUu.mjs';
4
+ import { c as connectToHypha } from './run-BtGnnEMI.mjs';
5
5
  import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-DuLXaoGP.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
@@ -4,7 +4,7 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
4
4
  import { join } from 'path';
5
5
  import { homedir, platform, arch } from 'os';
6
6
  import { randomUUID, createHash } from 'crypto';
7
- import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-DsAMQZUu.mjs';
7
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-BtGnnEMI.mjs';
8
8
  import 'fs/promises';
9
9
  import 'url';
10
10
  import 'node:crypto';
@@ -1,5 +1,5 @@
1
- import { a1 as resolveModel, ae as describeMisconfiguration, af as buildMachineDeps } from './run-DsAMQZUu.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CQJ-0LbS.mjs';
1
+ import { a1 as resolveModel, ae as describeMisconfiguration, af as buildMachineDeps } from './run-BtGnnEMI.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-C_ifGgde.mjs';
3
3
  import { WebSocket } from 'ws';
4
4
  import { execSync, spawn } from 'child_process';
5
5
  import 'os';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-DsAMQZUu.mjs';
1
+ export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-BtGnnEMI.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,5 +1,5 @@
1
1
  var name = "svamp-cli";
2
- var version = "0.2.255";
2
+ var version = "0.2.257";
3
3
  var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
4
  var author = "Amun AI AB";
5
5
  var license = "SEE LICENSE IN LICENSE";
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, u as updateIssue, o as getIssue, p as resumeIssue, q as pauseIssue, t as addComment, v as addIssue, w as listIssues, x as searchIssues, y as isVisibleTo } from './run-DsAMQZUu.mjs';
1
+ import { n as resolveProjectRoot, u as updateIssue, o as getIssue, p as resumeIssue, q as pauseIssue, t as addComment, v as addIssue, w as listIssues, x as searchIssues, y as isVisibleTo } from './run-BtGnnEMI.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, z as getRun, A as listRuns, B as getWorkflow, C as runWorkflow, D as setWorkflowEnabled, E as removeWorkflow, F as saveWorkflow, G as rawWorkflow, H as listWorkflows } from './run-DsAMQZUu.mjs';
1
+ import { n as resolveProjectRoot, z as getRun, A as listRuns, B as getWorkflow, C as runWorkflow, D as setWorkflowEnabled, E as removeWorkflow, F as saveWorkflow, G as rawWorkflow, H as listWorkflows } from './run-BtGnnEMI.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ag as applyClaudeProxyEnv, ah as composeSessionId, ai as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, aj as generateHookSettings } from './run-DsAMQZUu.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ag as applyClaudeProxyEnv, ah as composeSessionId, ai as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, aj as generateHookSettings } from './run-BtGnnEMI.mjs';
2
2
  import os from 'node:os';
3
3
  import { resolve, join } from 'node:path';
4
4
  import { existsSync, readFileSync, watch } from 'node:fs';