svamp-cli 0.2.356 → 0.2.358

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 (26) hide show
  1. package/dist/{agentCommands-D91RcjqQ.mjs → agentCommands-C_KvvYFp.mjs} +5 -5
  2. package/dist/{claudeAuth-C0wc1GTM.mjs → claudeAuth-DMDvPNhO.mjs} +11 -6
  3. package/dist/cli.mjs +136 -67
  4. package/dist/{commands-CoOc4qiw.mjs → commands-B19lVZjm.mjs} +10 -3
  5. package/dist/{commands-C13-yE2R.mjs → commands-Bmoy6Rlw.mjs} +5 -4
  6. package/dist/{commands-sPvRcG3J.mjs → commands-CFBKkfX8.mjs} +9 -9
  7. package/dist/{commands-B-yczgz_.mjs → commands-CcdoQIkb.mjs} +114 -17
  8. package/dist/{commands-BMeDrpSv.mjs → commands-DH_YQrAP.mjs} +5 -21
  9. package/dist/{commands-BbmypSgx.mjs → commands-DRxANaS5.mjs} +61 -18
  10. package/dist/{commands-BkdbelFo.mjs → commands-nkvTnUJj.mjs} +6 -5
  11. package/dist/friendlyName-B-OEwt0t.mjs +341 -0
  12. package/dist/{headlessCli-C8HzQvis.mjs → headlessCli-BpTXz6FD.mjs} +24 -16
  13. package/dist/{hookSettings-FFc1pi8j.mjs → hookSettings-CvvUhwCK.mjs} +122 -30
  14. package/dist/{friendlyName-1UZcyDhu.mjs → inboxGuard-CDqmIypF.mjs} +32 -347
  15. package/dist/index.mjs +7 -6
  16. package/dist/{loopVerify-DALtTk2V.mjs → loopVerify-CxAKJB5a.mjs} +1 -1
  17. package/dist/package-DTTWvJbp.mjs +64 -0
  18. package/dist/{rpc-ccY7xvlo.mjs → rpc-CAlAHQAy.mjs} +3 -1
  19. package/dist/{rpc-CBkSkzsI.mjs → rpc-CacreLQ8.mjs} +10 -6
  20. package/dist/{run-DCq3aEiF.mjs → run-Bc81iurl.mjs} +26 -7
  21. package/dist/{run-DDmeV9K3.mjs → run-DKOND4dO.mjs} +48 -30
  22. package/dist/{scheduler-BkVJ27Ki.mjs → scheduler-IyLWBF8T.mjs} +25 -7
  23. package/dist/{serveCommands-CLhkccJM.mjs → serveCommands-B-Ym_QXc.mjs} +8 -8
  24. package/dist/{store-B4E6NzG6.mjs → store-D8dok6_d.mjs} +53 -14
  25. package/package.json +3 -3
  26. package/dist/package-BrsiNutS.mjs +0 -64
@@ -1,21 +1,22 @@
1
- import { connectAndResolveSession } from './commands-B-yczgz_.mjs';
1
+ import { a as connectAndResolveSession } from './commands-CcdoQIkb.mjs';
2
2
  import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:child_process';
5
5
  import 'node:path';
6
6
  import 'node:os';
7
7
  import './hyphaClient-ybivOjZo.mjs';
8
- import './friendlyName-1UZcyDhu.mjs';
8
+ import './friendlyName-B-OEwt0t.mjs';
9
9
  import 'node:crypto';
10
10
  import './types-57J3Re0n.mjs';
11
11
  import './securityContext-Cm5UTCuD.mjs';
12
- import './loopVerify-DALtTk2V.mjs';
12
+ import './loopVerify-CxAKJB5a.mjs';
13
13
  import './instance-CeHz5C8v.mjs';
14
14
  import 'fs';
15
15
  import 'path';
16
16
  import 'os';
17
- import './store-B4E6NzG6.mjs';
17
+ import './store-D8dok6_d.mjs';
18
18
  import './fileLock-BMPwCrB6.mjs';
19
+ import './inboxGuard-CDqmIypF.mjs';
19
20
  import './flushExit-C-i6SGjj.mjs';
20
21
 
21
22
  function argVal(args, name) {
@@ -61,7 +61,7 @@ async function serviceExpose(args) {
61
61
  process.exit(1);
62
62
  }
63
63
  if (foreground) {
64
- const { runFrpcTunnel } = await import('./hookSettings-FFc1pi8j.mjs').then(function (n) { return n.w; });
64
+ const { runFrpcTunnel } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
65
65
  await runFrpcTunnel(name, ports, void 0, {
66
66
  group,
67
67
  groupKey,
@@ -71,7 +71,7 @@ async function serviceExpose(args) {
71
71
  });
72
72
  return;
73
73
  }
74
- const { connectAndGetMachine } = await import('./commands-B-yczgz_.mjs');
74
+ const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
75
75
  const { server, machine } = await connectAndGetMachine();
76
76
  try {
77
77
  const status = await machine.tunnelStart({
@@ -93,7 +93,7 @@ async function serviceExpose(args) {
93
93
  console.log(` port ${port}: ${url}`);
94
94
  }
95
95
  if (process.env.SVAMP_SESSION_ID) {
96
- const { autoAddSessionLink } = await import('./agentCommands-D91RcjqQ.mjs');
96
+ const { autoAddSessionLink } = await import('./agentCommands-C_KvvYFp.mjs');
97
97
  let added = 0;
98
98
  for (const [port, url] of urlEntries) {
99
99
  const label = urlEntries.length > 1 ? `${name}:${port}` : name;
@@ -129,8 +129,8 @@ async function serviceServe(args) {
129
129
  const resolvedDir = path.resolve(directory);
130
130
  console.log(`Serving ${resolvedDir}`);
131
131
  const http = await import('http');
132
- const { serveStaticMount } = await import('./hookSettings-FFc1pi8j.mjs').then(function (n) { return n.x; });
133
- const { getFreePort } = await import('./hookSettings-FFc1pi8j.mjs').then(function (n) { return n.w; });
132
+ const { serveStaticMount } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.x; });
133
+ const { getFreePort } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
134
134
  const server = http.createServer((req, res) => {
135
135
  const u = new URL(req.url || "/", "http://127.0.0.1");
136
136
  let rel = u.pathname;
@@ -153,7 +153,7 @@ async function serviceServe(args) {
153
153
  resolve(18080);
154
154
  });
155
155
  });
156
- const { runFrpcTunnel } = await import('./hookSettings-FFc1pi8j.mjs').then(function (n) { return n.w; });
156
+ const { runFrpcTunnel } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
157
157
  void server;
158
158
  await runFrpcTunnel(name, [servePort]);
159
159
  } catch (err) {
@@ -163,7 +163,7 @@ async function serviceServe(args) {
163
163
  }
164
164
  async function serviceList(_args) {
165
165
  try {
166
- const { connectAndGetMachine } = await import('./commands-B-yczgz_.mjs');
166
+ const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
167
167
  const { server, machine } = await connectAndGetMachine();
168
168
  try {
169
169
  const tunnels = await machine.tunnelList({});
@@ -203,11 +203,11 @@ async function serviceDelete(args) {
203
203
  process.exit(1);
204
204
  }
205
205
  try {
206
- const { connectAndGetMachine } = await import('./commands-B-yczgz_.mjs');
206
+ const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
207
207
  const { server, machine } = await connectAndGetMachine();
208
208
  try {
209
209
  await machine.tunnelStop({ name });
210
- const { removeSessionLinkByService } = await import('./agentCommands-D91RcjqQ.mjs');
210
+ const { removeSessionLinkByService } = await import('./agentCommands-C_KvvYFp.mjs');
211
211
  removeSessionLinkByService("tunnel", name);
212
212
  console.log(`Stopped tunnel '${name}'.`);
213
213
  } catch (err) {
@@ -3,18 +3,12 @@ import { execSync, execFileSync } from 'node:child_process';
3
3
  import { basename, resolve, join, isAbsolute } from 'node:path';
4
4
  import os from 'node:os';
5
5
  import { c as connectToHypha } from './hyphaClient-ybivOjZo.mjs';
6
- import { f as formatHandle, c as computeOutboundHop, s as shortId, r as registerAwaitingReply, p as parseHandle, h as handleMatchesMetadata } from './friendlyName-1UZcyDhu.mjs';
6
+ import { f as formatHandle, s as shortId, p as parseHandle, h as handleMatchesMetadata } from './friendlyName-B-OEwt0t.mjs';
7
7
  import { n as normalizeAllowedUser } from './types-57J3Re0n.mjs';
8
8
  import { loadSecurityContextConfig, resolveSecurityContext, buildSecurityContextFromFlags, mergeSecurityContexts } from './securityContext-Cm5UTCuD.mjs';
9
- import { b as buildSessionShareUrl, U as UNBOUNDED_LOOP_ITERATIONS, a as buildMachineShareUrl } from './loopVerify-DALtTk2V.mjs';
9
+ import { b as buildSessionShareUrl, U as UNBOUNDED_LOOP_ITERATIONS, a as buildMachineShareUrl } from './loopVerify-CxAKJB5a.mjs';
10
+ import { computeOutboundHop, resolveOutboundUrgency, registerAwaitingReply } from './inboxGuard-CDqmIypF.mjs';
10
11
  import { f as flushStdout } from './flushExit-C-i6SGjj.mjs';
11
- import 'node:crypto';
12
- import './instance-CeHz5C8v.mjs';
13
- import 'fs';
14
- import 'path';
15
- import 'os';
16
- import './store-B4E6NzG6.mjs';
17
- import './fileLock-BMPwCrB6.mjs';
18
12
 
19
13
  function formatTime(ts) {
20
14
  if (!ts) return "-";
@@ -83,6 +77,23 @@ function formatJson(data) {
83
77
  return JSON.stringify(data, null, 2);
84
78
  }
85
79
 
80
+ function positionalArgs(args, valueFlags) {
81
+ const out = [];
82
+ for (let i = 0; i < args.length; i++) {
83
+ const a = args[i];
84
+ if (a === "--") break;
85
+ if (a.startsWith("-") && a !== "-") {
86
+ if (!a.includes("=") && valueFlags.has(a)) i++;
87
+ continue;
88
+ }
89
+ out.push(a);
90
+ }
91
+ return out;
92
+ }
93
+ function firstPositional(args, valueFlags) {
94
+ return positionalArgs(args, valueFlags)[0];
95
+ }
96
+
86
97
  function machineLabelOf(machine, index) {
87
98
  return String(
88
99
  machine?.metadata?.displayName || machine?.metadata?.host || machine?.machineId || machine?.id || `machine #${index}`
@@ -1885,8 +1896,14 @@ async function sendCore(machine, fullId, message, opts) {
1885
1896
  const preSeq = wantResponse ? await snapshotLatestSeq(machine, fullId) : 0;
1886
1897
  const callerSessionId = process.env.SVAMP_SESSION_ID;
1887
1898
  const hop = computeOutboundHop(callerSessionId);
1888
- let urgency = opts?.urgency ? opts.urgency : opts?.whenIdle ? "normal" : "urgent";
1889
- if (hop.fromInboxTurn) urgency = "normal";
1899
+ const { urgency, downgraded } = resolveOutboundUrgency({
1900
+ explicit: opts?.urgency,
1901
+ whenIdle: opts?.whenIdle,
1902
+ fromInboxTurn: hop.fromInboxTurn
1903
+ });
1904
+ if (downgraded) {
1905
+ console.error("note: sent non-urgent \u2014 this turn was inbox-triggered (anti-cascade safeguard C). Pass --urgency urgent to override.");
1906
+ }
1890
1907
  const inboxMessage = {
1891
1908
  messageId: shortId(),
1892
1909
  body: message,
@@ -2713,8 +2730,14 @@ async function sessionInboxSend(sessionIdPartial, body, machineId, opts) {
2713
2730
  try {
2714
2731
  const callerSessionId = process.env.SVAMP_SESSION_ID;
2715
2732
  const hop = computeOutboundHop(callerSessionId);
2716
- let urgency = opts?.urgency ? opts.urgency : opts?.whenIdle ? "normal" : "urgent";
2717
- if (hop.fromInboxTurn) urgency = "normal";
2733
+ const { urgency, downgraded } = resolveOutboundUrgency({
2734
+ explicit: opts?.urgency,
2735
+ whenIdle: opts?.whenIdle,
2736
+ fromInboxTurn: hop.fromInboxTurn
2737
+ });
2738
+ if (downgraded) {
2739
+ console.error("note: sent non-urgent \u2014 this turn was inbox-triggered (anti-cascade safeguard C). Pass --urgency urgent to override.");
2740
+ }
2718
2741
  const message = {
2719
2742
  messageId: shortId(),
2720
2743
  body,
@@ -2801,7 +2824,21 @@ ${msg.body}`);
2801
2824
  await server.disconnect();
2802
2825
  }
2803
2826
  }
2804
- async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
2827
+ const REPLY_VALUE_FLAGS = /* @__PURE__ */ new Set(["--urgency", "--subject"]);
2828
+ function replyPositionals(args) {
2829
+ return positionalArgs(args, REPLY_VALUE_FLAGS);
2830
+ }
2831
+ const SEND_VALUE_FLAGS = /* @__PURE__ */ new Set([
2832
+ "--timeout",
2833
+ "--subject",
2834
+ "--urgency",
2835
+ "--model",
2836
+ "--issue-title"
2837
+ ]);
2838
+ function sendPositionals(args) {
2839
+ return positionalArgs(args, SEND_VALUE_FLAGS);
2840
+ }
2841
+ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId, opts) {
2805
2842
  const { server, machine, fullId } = await connectAndResolveSession(sessionIdPartial, machineId);
2806
2843
  try {
2807
2844
  const result = await machine.sessionRPC(fullId, "getInbox", {});
@@ -2835,10 +2872,12 @@ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
2835
2872
  fromSession: fullId,
2836
2873
  to: original.fromSession,
2837
2874
  subject: original.subject ? `Re: ${original.subject}` : void 0,
2838
- // A reply wakes the party who is WAITING for it — deliver urgent by default
2875
+ // A reply wakes the party who is WAITING for it — deliver urgent by DEFAULT
2839
2876
  // (owner directive: replies default urgent). The hop cap + circuit breaker still
2840
2877
  // bound any runaway A→B→A cascade; hopCount below carries the depth for that cap.
2841
- urgency: "urgent",
2878
+ // The default is deliberate and safeguard C does NOT apply here (#0290); an
2879
+ // explicit --urgency / --when-idle is honoured so a caller can opt out by hand.
2880
+ urgency: opts?.urgency ?? (opts?.whenIdle ? "normal" : "urgent"),
2842
2881
  hopCount: hop.hopCount,
2843
2882
  replyTo: original.messageId,
2844
2883
  threadId: original.threadId || original.messageId
@@ -2872,4 +2911,62 @@ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
2872
2911
  }
2873
2912
  }
2874
2913
 
2875
- export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, isSelfBtw, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionEditMessage, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionLoopCancel, sessionLoopExtend, sessionLoopStart, sessionLoopStatus, sessionMachines, sessionMessages, sessionQuery, sessionRefineLastReply, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionUndoEdit, sessionWait, sessionWhoami, snapshotLatestSeq, validateSendOptions, wiseAnnounceCli, wiseAskCli, wiseJoinMeetingCli, wiseLeaveMeetingCli, wiseMeetingsCli };
2914
+ var commands = /*#__PURE__*/Object.freeze({
2915
+ __proto__: null,
2916
+ REPLY_VALUE_FLAGS: REPLY_VALUE_FLAGS,
2917
+ SEND_VALUE_FLAGS: SEND_VALUE_FLAGS,
2918
+ collectAssistantResponse: collectAssistantResponse,
2919
+ connectAndGetMachine: connectAndGetMachine,
2920
+ connectAndResolveSession: connectAndResolveSession,
2921
+ createWorktree: createWorktree,
2922
+ generateWorktreeName: generateWorktreeName,
2923
+ isSelfBtw: isSelfBtw,
2924
+ machineExec: machineExec,
2925
+ machineInfo: machineInfo,
2926
+ machineLs: machineLs,
2927
+ machineShare: machineShare,
2928
+ parseShareArg: parseShareArg,
2929
+ queryCore: queryCore,
2930
+ renderMessage: renderMessage,
2931
+ replyPositionals: replyPositionals,
2932
+ resolveSessionId: resolveSessionId,
2933
+ sendCore: sendCore,
2934
+ sendPositionals: sendPositionals,
2935
+ sessionApprove: sessionApprove,
2936
+ sessionArchive: sessionArchive,
2937
+ sessionAttach: sessionAttach,
2938
+ sessionDelete: sessionDelete,
2939
+ sessionDeny: sessionDeny,
2940
+ sessionEditMessage: sessionEditMessage,
2941
+ sessionInboxClear: sessionInboxClear,
2942
+ sessionInboxList: sessionInboxList,
2943
+ sessionInboxRead: sessionInboxRead,
2944
+ sessionInboxReply: sessionInboxReply,
2945
+ sessionInboxSend: sessionInboxSend,
2946
+ sessionInfo: sessionInfo,
2947
+ sessionList: sessionList,
2948
+ sessionLoopCancel: sessionLoopCancel,
2949
+ sessionLoopExtend: sessionLoopExtend,
2950
+ sessionLoopStart: sessionLoopStart,
2951
+ sessionLoopStatus: sessionLoopStatus,
2952
+ sessionMachines: sessionMachines,
2953
+ sessionMessages: sessionMessages,
2954
+ sessionQuery: sessionQuery,
2955
+ sessionRefineLastReply: sessionRefineLastReply,
2956
+ sessionResume: sessionResume,
2957
+ sessionSend: sessionSend,
2958
+ sessionShare: sessionShare,
2959
+ sessionSpawn: sessionSpawn,
2960
+ sessionUndoEdit: sessionUndoEdit,
2961
+ sessionWait: sessionWait,
2962
+ sessionWhoami: sessionWhoami,
2963
+ snapshotLatestSeq: snapshotLatestSeq,
2964
+ validateSendOptions: validateSendOptions,
2965
+ wiseAnnounceCli: wiseAnnounceCli,
2966
+ wiseAskCli: wiseAskCli,
2967
+ wiseJoinMeetingCli: wiseJoinMeetingCli,
2968
+ wiseLeaveMeetingCli: wiseLeaveMeetingCli,
2969
+ wiseMeetingsCli: wiseMeetingsCli
2970
+ });
2971
+
2972
+ export { connectAndResolveSession as a, createWorktree as b, connectAndGetMachine as c, commands as d, firstPositional as f, resolveSessionId as r };
@@ -1,40 +1,24 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-B-yczgz_.mjs';
3
+ import { f as firstPositional, c as connectAndGetMachine } from './commands-CcdoQIkb.mjs';
4
4
  import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:child_process';
7
7
  import 'node:path';
8
8
  import 'node:os';
9
9
  import './hyphaClient-ybivOjZo.mjs';
10
- import './friendlyName-1UZcyDhu.mjs';
10
+ import './friendlyName-B-OEwt0t.mjs';
11
11
  import 'node:crypto';
12
12
  import './types-57J3Re0n.mjs';
13
13
  import './securityContext-Cm5UTCuD.mjs';
14
- import './loopVerify-DALtTk2V.mjs';
14
+ import './loopVerify-CxAKJB5a.mjs';
15
15
  import './instance-CeHz5C8v.mjs';
16
16
  import 'os';
17
- import './store-B4E6NzG6.mjs';
17
+ import './store-D8dok6_d.mjs';
18
18
  import './fileLock-BMPwCrB6.mjs';
19
+ import './inboxGuard-CDqmIypF.mjs';
19
20
  import './flushExit-C-i6SGjj.mjs';
20
21
 
21
- function positionalArgs(args, valueFlags) {
22
- const out = [];
23
- for (let i = 0; i < args.length; i++) {
24
- const a = args[i];
25
- if (a === "--") break;
26
- if (a.startsWith("-") && a !== "-") {
27
- if (!a.includes("=") && valueFlags.has(a)) i++;
28
- continue;
29
- }
30
- out.push(a);
31
- }
32
- return out;
33
- }
34
- function firstPositional(args, valueFlags) {
35
- return positionalArgs(args, valueFlags)[0];
36
- }
37
-
38
22
  const PROCESS_VALUE_FLAGS = /* @__PURE__ */ new Set([
39
23
  "-o",
40
24
  "--output",
@@ -1,11 +1,18 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
2
+ import { join, delimiter } from 'node:path';
3
3
  import { a as flushAndExit } from './flushExit-C-i6SGjj.mjs';
4
- import { r as resolveProjectRoot, s as searchIssues, l as listIssues, j as isPendingIssue, e as resumeIssue, f as pauseIssue, h as addComment, a as applyTriageStatus, u as updateIssue, p as parseScopeArg, I as ISSUE_SCOPES, b as parseStatusArg, d as ISSUE_STATUSES, g as getIssue, m as checkVerifyCommand, k as isVisibleTo, n as summarize, i as addIssue } from './store-B4E6NzG6.mjs';
4
+ import { r as resolveProjectRoot, s as searchIssues, l as listIssues, j as isPendingIssue, f as resumeIssue, h as pauseIssue, b as addComment, a as applyTriageStatus, u as updateIssue, p as parseScopeArg, I as ISSUE_SCOPES, d as parseStatusArg, e as ISSUE_STATUSES, g as getIssue, m as checkVerifyCommand, v as verifyGatePass, k as isVisibleTo, n as summarize, i as addIssue } from './store-D8dok6_d.mjs';
5
5
  import 'node:crypto';
6
6
  import 'node:child_process';
7
7
  import './fileLock-BMPwCrB6.mjs';
8
8
 
9
+ function commandExistsOnPath(name) {
10
+ if (name === "true" || name === "false") return true;
11
+ for (const dir of (process.env.PATH || "").split(delimiter)) {
12
+ if (dir && existsSync(join(dir, name))) return true;
13
+ }
14
+ return false;
15
+ }
9
16
  const STATUS_GLYPH = {
10
17
  ready: "\u25C9",
11
18
  in_progress: "\u25D0",
@@ -55,6 +62,7 @@ const VALUE_FLAGS = /* @__PURE__ */ new Set([
55
62
  "--label",
56
63
  "--option",
57
64
  "--question",
65
+ "--root",
58
66
  "--scope",
59
67
  "--session",
60
68
  "--status",
@@ -81,17 +89,42 @@ function shortSess(s) {
81
89
  }
82
90
  function fmtIssue(i) {
83
91
  const tri = i.triaged === false ? " \u25B3triage" : "";
84
- const owner = i.status === "in_progress" && i.session ? shortSess(i.session) : "";
85
- const disp = i.disposition === "crew" ? owner ? ` {crew:${owner}}` : " {crew}" : owner ? ` {session:${owner}}` : "";
92
+ const holder = shortSess(i.session);
93
+ const disp = i.disposition === "crew" ? holder ? ` {crew:${holder}}` : " {crew}" : holder ? ` {session:${holder}}` : "";
86
94
  const label = i.labels.length ? ` [${i.labels.join(", ")}]` : "";
87
95
  const v = i.verify ? ` (verify:${i.verify.type})` : "";
88
96
  const br = i.branch ? ` {branch:${i.branch}}` : "";
89
97
  const ans = i.answer ? " \u21A9answered" : "";
90
98
  return `#${i.id} ${STATUS_GLYPH[i.status]} ${i.title}${tri}${disp}${label}${v}${br}${ans}`;
91
99
  }
100
+ function verifyGateRefusal(verb, id, res) {
101
+ const via = verb === "archive" ? " via edit" : "";
102
+ const escape = verb === "archive" ? "Use `svamp issue archive` for an obsolete/duplicate item, or pass --force to override." : "Fix the issue, or pass --force to override.";
103
+ if (res.notRunnable) {
104
+ return `Refusing to ${verb} #${id}${via}: its verify-cmd could not be RUN (command not found) \u2014 the ORACLE is mis-specified, not the fix.
105
+ $ ${res.cmd}
106
+ ${res.output || ""}
107
+ Repair it, then ${verb} again:
108
+ svamp issue edit ${id} --verify-cmd "<a command that fails while the bug stands>"
109
+ svamp issue edit ${id} --verify "<a criterion>" # when no shell command can express it
110
+ (${escape})`;
111
+ }
112
+ return `Refusing to ${verb} #${id}${via}: its verify-cmd failed \u2014 the fix is not verified.
113
+ $ ${res.cmd}
114
+ ${res.output || ""}
115
+ (${escape})`;
116
+ }
92
117
  function buildVerify(args) {
93
118
  const cmd = flag(args, "--verify-cmd");
94
- if (cmd) return { type: "command", text: cmd };
119
+ if (cmd) {
120
+ const bare = cmd.trim();
121
+ if (/^[A-Za-z_][A-Za-z0-9_-]*$/.test(bare) && !commandExistsOnPath(bare)) {
122
+ console.error(`Refusing to set --verify-cmd "${bare}": that is a single word and it is not an executable on PATH, so the gate could never pass and the issue could never be closed.`);
123
+ console.error(`Did you mean --verify "${bare}" (an evaluator criterion), or a real command?`);
124
+ process.exit(1);
125
+ }
126
+ return { type: "command", text: cmd };
127
+ }
95
128
  const agent = flag(args, "--verify");
96
129
  if (agent) return { type: "agent", text: agent };
97
130
  if (has(args, "--manual")) return { type: "manual" };
@@ -100,7 +133,12 @@ function buildVerify(args) {
100
133
  async function issueCommand(args) {
101
134
  const sub = args.some((a) => a === "--help" || a === "-h") ? "help" : args[0];
102
135
  const rest = args.slice(1);
103
- const root = resolveProjectRoot();
136
+ const rootFlag = flag(rest, "--root");
137
+ if (rootFlag !== void 0 && !existsSync(join(rootFlag, ".svamp", "issues"))) {
138
+ console.error(`svamp issue: no tracker at ${rootFlag} \u2014 expected ${join(rootFlag, ".svamp", "issues")}`);
139
+ process.exit(1);
140
+ }
141
+ const root = rootFlag ?? resolveProjectRoot();
104
142
  const json = has(args, "--json");
105
143
  const sessionId = process.env.SVAMP_SESSION_ID || null;
106
144
  const out = (text) => console.log(text);
@@ -126,7 +164,12 @@ async function issueCommand(args) {
126
164
  }
127
165
  const labels = rest.filter((a, idx) => rest[idx - 1] === "--label");
128
166
  const owner = flag(rest, "--session") || sessionId;
129
- const scope = flag(rest, "--scope") || (owner ? "session" : "project");
167
+ const rawScope = flag(rest, "--scope");
168
+ const scope = rawScope == null ? owner ? "session" : "project" : parseScopeArg(rawScope);
169
+ if (!scope) {
170
+ console.error(`Invalid --scope "${rawScope}". Must be one of: ${ISSUE_SCOPES.join(", ")}.`);
171
+ process.exit(1);
172
+ }
130
173
  const issue = addIssue(root, {
131
174
  title,
132
175
  // New issues are actionable immediately (#0049) — there is no backlog to promote from.
@@ -241,12 +284,10 @@ ${issue.body}`);
241
284
  } else {
242
285
  const res = checkVerifyCommand(root, current);
243
286
  if (!res.ok) {
244
- console.error(`Refusing to close #${id}: its verify-cmd failed \u2014 the fix is not verified.
245
- $ ${res.cmd}
246
- ${res.output || ""}
247
- (Fix the issue, or pass --force to override.)`);
287
+ console.error(verifyGateRefusal("close", id, res));
248
288
  process.exit(1);
249
289
  }
290
+ console.error(verifyGatePass(res));
250
291
  }
251
292
  }
252
293
  }
@@ -297,12 +338,10 @@ ${res.output || ""}
297
338
  } else {
298
339
  const res = checkVerifyCommand(root, current);
299
340
  if (!res.ok) {
300
- console.error(`Refusing to archive #${id} via edit: its verify-cmd failed \u2014 the fix is not verified.
301
- $ ${res.cmd}
302
- ${res.output || ""}
303
- (Use \`svamp issue archive\` for an obsolete/duplicate item, or pass --force to override.)`);
341
+ console.error(verifyGateRefusal("archive", id, res));
304
342
  process.exit(1);
305
343
  }
344
+ console.error(verifyGatePass(res));
306
345
  }
307
346
  }
308
347
  }
@@ -410,6 +449,7 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
410
449
  const pending = listIssues(root).filter(inScope).filter(isPendingIssue);
411
450
  if (json) console.log(JSON.stringify(pending));
412
451
  else out(pending.length ? `${pending.length} pending: ${pending.map((i) => "#" + i.id).join(" ")}` : "No pending issues.");
452
+ console.error(`tracker: ${join(root, ".svamp", "issues")}${mine ? ` scope: session ${mine}` : " scope: all"}`);
413
453
  await flushAndExit(pending.length ? 1 : 0);
414
454
  break;
415
455
  }
@@ -531,8 +571,11 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
531
571
  " # A paused issue drops out of `pending`, so a loop converges cleanly instead",
532
572
  ' # of spinning on it. NOT for "please check my work" \u2014 close finished work.',
533
573
  ' resume <id> [--answer "\u2026"] # un-pause (the user answering a --question resumes it automatically)',
534
- " pending [--session <id>] [--mine] # exit 0 when NO issue is open \u2014 i.e. every issue is",
535
- " # archived or paused. Counted by EXCLUSION, not an allow-list (#107). The loop oracle.",
574
+ " pending [--session <id>] [--mine] [--root <path>] # exit 0 when NO issue is open \u2014 i.e. every",
575
+ " # issue is archived or paused. Counted by EXCLUSION, not an allow-list (#107). The loop oracle.",
576
+ " # It names the tracker it read on stderr. Pass --root to PIN that tracker instead of",
577
+ " # walking up from the cwd: from the wrong directory the verdict is a clean exit 0 about",
578
+ " # somebody else's backlog, and it reads identically to your own being done (#0315).",
536
579
  ' search "<query>" [--json]',
537
580
  " guide <triage|work> # the triage / work-loop procedure (so triggers can stay short)"
538
581
  ].join("\n"));
@@ -543,4 +586,4 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
543
586
  }
544
587
  }
545
588
 
546
- export { VALUE_FLAGS, issueCommand, loopActiveForCwd, positional };
589
+ export { VALUE_FLAGS, fmtIssue, issueCommand, loopActiveForCwd, positional };
@@ -1,22 +1,23 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { join, resolve } from 'node:path';
3
- import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-B-yczgz_.mjs';
3
+ import { c as connectAndGetMachine, r as resolveSessionId, b as createWorktree, a as connectAndResolveSession } from './commands-CcdoQIkb.mjs';
4
4
  import { execFileSync } from 'node:child_process';
5
5
  import { w as withFileLock } from './fileLock-BMPwCrB6.mjs';
6
- import { u as updateIssue, h as addComment, i as addIssue, o as resolveCrewIssueOnMerge } from './store-B4E6NzG6.mjs';
7
- import { s as shortId } from './friendlyName-1UZcyDhu.mjs';
6
+ import { u as updateIssue, b as addComment, i as addIssue, o as resolveCrewIssueOnMerge } from './store-D8dok6_d.mjs';
7
+ import { s as shortId } from './friendlyName-B-OEwt0t.mjs';
8
8
  import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
9
9
  import 'node:os';
10
10
  import './hyphaClient-ybivOjZo.mjs';
11
11
  import './types-57J3Re0n.mjs';
12
12
  import './securityContext-Cm5UTCuD.mjs';
13
- import './loopVerify-DALtTk2V.mjs';
13
+ import './loopVerify-CxAKJB5a.mjs';
14
14
  import './instance-CeHz5C8v.mjs';
15
15
  import 'fs';
16
16
  import 'path';
17
17
  import 'os';
18
- import './flushExit-C-i6SGjj.mjs';
18
+ import './inboxGuard-CDqmIypF.mjs';
19
19
  import 'node:crypto';
20
+ import './flushExit-C-i6SGjj.mjs';
20
21
 
21
22
  function git(cwd, args) {
22
23
  return execFileSync("git", args, { cwd, stdio: "pipe", encoding: "utf-8" }).toString();