svamp-cli 0.2.342 → 0.2.356
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/skills/artifact/SKILL.md +19 -5
- package/bin/skills/crew/SKILL.md +62 -13
- package/dist/DefaultTransport-vfp78fug.mjs +47 -0
- package/dist/GeminiTransport-3OkhtFRO.mjs +130 -0
- package/dist/KimiTransport-D8n009Tr.mjs +141 -0
- package/dist/acpAgentConfig-CObOPlA8.mjs +48 -0
- package/dist/acpBackend-UaBD4zL3.mjs +925 -0
- package/dist/{adminCommands-CRTBDZan.mjs → adminCommands-BvsYnRDA.mjs} +2 -18
- package/dist/{agentCommands-BuO988tJ.mjs → agentCommands-D91RcjqQ.mjs} +6 -23
- package/dist/api-BHjyC0Ph.mjs +157 -0
- package/dist/{auth--WS0wezs.mjs → auth-CRz8TsEl.mjs} +1 -22
- package/dist/bootStatus-DqtNgJch.mjs +143 -0
- package/dist/claudeAuth-C0wc1GTM.mjs +291 -0
- package/dist/cli.mjs +2948 -5
- package/dist/codexAppServerBackend-VGsYtbqg.mjs +786 -0
- package/dist/codexProvider-BtxYc5Rj.mjs +68 -0
- package/dist/{commands-DDuGBSsz.mjs → commands-B-yczgz_.mjs} +115 -49
- package/dist/{commands-DU4B-4Gh.mjs → commands-BMeDrpSv.mjs} +55 -25
- package/dist/{commands-DXLOKJOj.mjs → commands-BbmypSgx.mjs} +62 -27
- package/dist/{commands-C0HQiu-S.mjs → commands-BkdbelFo.mjs} +78 -38
- package/dist/{commands-DXM17M6n.mjs → commands-C13-yE2R.mjs} +42 -19
- package/dist/{commands-BKb1g8Gq.mjs → commands-CoOc4qiw.mjs} +20 -30
- package/dist/{commands-BsKgZ5sQ.mjs → commands-DW5RnHZw.mjs} +2 -19
- package/dist/{commands-Cwxy-C5N.mjs → commands-sPvRcG3J.mjs} +10 -32
- package/dist/cron-hHGdb5kU.mjs +132 -0
- package/dist/detectIsolation-CrV8IFDv.mjs +339 -0
- package/dist/envFlag-COOuJ3AH.mjs +11 -0
- package/dist/fileLock-BMPwCrB6.mjs +80 -0
- package/dist/{fleet-BHzlAvnu.mjs → fleet-Ca-UjJNL.mjs} +122 -36
- package/dist/flushExit-C-i6SGjj.mjs +37 -0
- package/dist/friendlyName-1UZcyDhu.mjs +586 -0
- package/dist/{headlessCli-C2gvOpOt.mjs → headlessCli-C8HzQvis.mjs} +3 -21
- package/dist/hookSettings-FFc1pi8j.mjs +10546 -0
- package/dist/{httpServer-Be1Hcddr.mjs → httpServer-BzEDbOGn.mjs} +14 -5
- package/dist/hyphaClient-ybivOjZo.mjs +49 -0
- package/dist/index.mjs +40 -8
- package/dist/instance-CeHz5C8v.mjs +203 -0
- package/dist/kimiProvider-DbxODebR.mjs +69 -0
- package/dist/kimiSetup-NGsoYB5h.mjs +48 -0
- package/dist/loopVerify-DALtTk2V.mjs +444 -0
- package/dist/machineTools-DygM1jXW.mjs +580 -0
- package/dist/model-CUHojegn.mjs +66 -0
- package/dist/{notifyCommands-0aZUwKQK.mjs → notifyCommands-CCUE18Q-.mjs} +3 -18
- package/dist/package-BrsiNutS.mjs +64 -0
- package/dist/pinnedCodex-XW4qvOAe.mjs +11 -0
- package/dist/pinnedNono-5ZHb6328.mjs +15 -0
- package/dist/{rpc-rAQQ1q8t.mjs → rpc-CBkSkzsI.mjs} +38 -6
- package/dist/{rpc-B2Lc2BAB.mjs → rpc-ccY7xvlo.mjs} +33 -22
- package/dist/{run-C7QVfyw4.mjs → run-DCq3aEiF.mjs} +17 -9
- package/dist/run-DDmeV9K3.mjs +9826 -0
- package/dist/sandboxDetect-Cdzsj5TC.mjs +19 -0
- package/dist/{scheduler-CzF4lOe_.mjs → scheduler-BkVJ27Ki.mjs} +38 -6
- package/dist/securityContext-Cm5UTCuD.mjs +218 -0
- package/dist/serveAuth-4M0vwMyj.mjs +460 -0
- package/dist/{serveCommands-EIEqdaVu.mjs → serveCommands-CLhkccJM.mjs} +13 -34
- package/dist/sharingNotificationSync-qGIQ-3yf.mjs +359 -0
- package/dist/{sideband-BoutiRJi.mjs → sideband-68HhGT0i.mjs} +1 -21
- package/dist/store-B4E6NzG6.mjs +356 -0
- package/dist/store-fi0f-ff1.mjs +184 -0
- package/dist/types-57J3Re0n.mjs +17 -0
- package/dist/wantsHelp-6bMOeNUz.mjs +5 -0
- package/dist/wrapCommand-CdNawSaa.mjs +117 -0
- package/package.json +3 -3
- package/dist/cli-B24CmIli.mjs +0 -2780
- package/dist/package-CTbGYaJG.mjs +0 -64
- package/dist/run-CF4kAVPW.mjs +0 -26508
- package/dist/sandboxDetect-DNTcbgWD.mjs +0 -12
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import './serviceManager-hlOVxkhW.mjs';
|
|
6
|
-
import 'os';
|
|
7
|
-
import 'fs/promises';
|
|
8
|
-
import 'fs';
|
|
9
|
-
import 'path';
|
|
10
|
-
import 'url';
|
|
11
|
-
import 'child_process';
|
|
12
|
-
import 'crypto';
|
|
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';
|
|
13
5
|
import 'node:crypto';
|
|
14
6
|
import 'node:child_process';
|
|
15
|
-
import '
|
|
16
|
-
import 'http';
|
|
17
|
-
import 'net';
|
|
18
|
-
import 'node:os';
|
|
19
|
-
import 'node:events';
|
|
20
|
-
import '@agentclientprotocol/sdk';
|
|
21
|
-
import 'node:util';
|
|
22
|
-
import 'node:readline';
|
|
23
|
-
import 'node:fs/promises';
|
|
24
|
-
import 'yaml';
|
|
7
|
+
import './fileLock-BMPwCrB6.mjs';
|
|
25
8
|
|
|
26
9
|
const STATUS_GLYPH = {
|
|
27
10
|
ready: "\u25C9",
|
|
@@ -64,12 +47,27 @@ function loopActiveForCwd(cwd = process.cwd(), sid = process.env.SVAMP_SESSION_I
|
|
|
64
47
|
}
|
|
65
48
|
return false;
|
|
66
49
|
}
|
|
50
|
+
const VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
51
|
+
"--answer",
|
|
52
|
+
"--blocked",
|
|
53
|
+
"--body",
|
|
54
|
+
"--branch",
|
|
55
|
+
"--label",
|
|
56
|
+
"--option",
|
|
57
|
+
"--question",
|
|
58
|
+
"--scope",
|
|
59
|
+
"--session",
|
|
60
|
+
"--status",
|
|
61
|
+
"--title",
|
|
62
|
+
"--verify",
|
|
63
|
+
"--verify-cmd"
|
|
64
|
+
]);
|
|
67
65
|
function positional(args) {
|
|
68
66
|
const out = [];
|
|
69
67
|
for (let i = 0; i < args.length; i++) {
|
|
70
68
|
const a = args[i];
|
|
71
69
|
if (a.startsWith("--")) {
|
|
72
|
-
if (a
|
|
70
|
+
if (!a.includes("=") && VALUE_FLAGS.has(a)) i++;
|
|
73
71
|
continue;
|
|
74
72
|
}
|
|
75
73
|
out.push(a);
|
|
@@ -272,11 +270,44 @@ ${res.output || ""}
|
|
|
272
270
|
if (labels.length) patch.labels = labels;
|
|
273
271
|
const v = buildVerify(rest);
|
|
274
272
|
if (v || has(rest, "--no-verify")) patch.verify = has(rest, "--no-verify") ? null : v;
|
|
275
|
-
if (flag(rest, "--scope"))
|
|
273
|
+
if (flag(rest, "--scope")) {
|
|
274
|
+
const nextScope = parseScopeArg(flag(rest, "--scope"));
|
|
275
|
+
if (!nextScope) {
|
|
276
|
+
console.error(`Invalid --scope "${flag(rest, "--scope")}". Must be one of: ${ISSUE_SCOPES.join(", ")}.`);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
patch.scope = nextScope;
|
|
280
|
+
}
|
|
276
281
|
if (has(rest, "--unclaim")) patch.session = null;
|
|
277
282
|
else if (flag(rest, "--session")) patch.session = flag(rest, "--session");
|
|
278
283
|
if (flag(rest, "--body")) patch.body = flag(rest, "--body");
|
|
279
|
-
if (flag(rest, "--status"))
|
|
284
|
+
if (flag(rest, "--status")) {
|
|
285
|
+
const nextStatus = parseStatusArg(flag(rest, "--status"));
|
|
286
|
+
if (!nextStatus) {
|
|
287
|
+
console.error(`Invalid --status "${flag(rest, "--status")}". Must be one of: ${ISSUE_STATUSES.join(", ")}.`);
|
|
288
|
+
console.error(`(To close an issue, use \`svamp issue close ${id}\` \u2014 it runs the verify-cmd.)`);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
if (nextStatus === "archived") {
|
|
292
|
+
const current = getIssue(root, id);
|
|
293
|
+
const vc = current?.verify?.type === "command" ? current.verify.text?.trim() : "";
|
|
294
|
+
if (vc && current?.status !== "archived") {
|
|
295
|
+
if (has(rest, "--force")) {
|
|
296
|
+
console.error(`\u26A0 #${id}: archiving WITHOUT running verify-cmd (--force): \`${vc}\``);
|
|
297
|
+
} else {
|
|
298
|
+
const res = checkVerifyCommand(root, current);
|
|
299
|
+
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.)`);
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
patch.status = nextStatus;
|
|
310
|
+
}
|
|
280
311
|
if (has(rest, "--crew")) patch.disposition = "crew";
|
|
281
312
|
else if (has(rest, "--inline")) patch.disposition = "inline";
|
|
282
313
|
if (has(rest, "--triaged")) patch.triaged = true;
|
|
@@ -291,7 +322,7 @@ ${res.output || ""}
|
|
|
291
322
|
case "triage": {
|
|
292
323
|
const id = positional(rest)[0];
|
|
293
324
|
if (!id) {
|
|
294
|
-
console.error('usage: svamp issue triage <id> [--title "\u2026"] [--label x \u2026] [--crew|--inline] [--verify-cmd "cmd" | --verify "criterion" | --manual] [--body "rewritten"]
|
|
325
|
+
console.error('usage: svamp issue triage <id> [--title "\u2026"] [--label x \u2026] [--crew|--inline] [--verify-cmd "cmd" | --verify "criterion" | --manual] [--body "rewritten"]');
|
|
295
326
|
process.exit(1);
|
|
296
327
|
}
|
|
297
328
|
const patch = { triaged: true };
|
|
@@ -303,7 +334,10 @@ ${res.output || ""}
|
|
|
303
334
|
const tv = buildVerify(rest);
|
|
304
335
|
if (tv) patch.verify = tv;
|
|
305
336
|
if (flag(rest, "--body")) patch.body = flag(rest, "--body");
|
|
306
|
-
patch
|
|
337
|
+
applyTriageStatus(root, id, patch, (m) => {
|
|
338
|
+
console.error(m);
|
|
339
|
+
process.exit(1);
|
|
340
|
+
});
|
|
307
341
|
const updated = updateIssue(root, id, patch);
|
|
308
342
|
if (!updated) {
|
|
309
343
|
console.error(`Issue not found: ${id}`);
|
|
@@ -497,7 +531,8 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
|
|
|
497
531
|
" # A paused issue drops out of `pending`, so a loop converges cleanly instead",
|
|
498
532
|
' # of spinning on it. NOT for "please check my work" \u2014 close finished work.',
|
|
499
533
|
' resume <id> [--answer "\u2026"] # un-pause (the user answering a --question resumes it automatically)',
|
|
500
|
-
" pending [--session <id>] [--mine] # exit 0
|
|
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.",
|
|
501
536
|
' search "<query>" [--json]',
|
|
502
537
|
" guide <triage|work> # the triage / work-loop procedure (so triggers can stay short)"
|
|
503
538
|
].join("\n"));
|
|
@@ -508,4 +543,4 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
|
|
|
508
543
|
}
|
|
509
544
|
}
|
|
510
545
|
|
|
511
|
-
export { issueCommand, loopActiveForCwd };
|
|
546
|
+
export { VALUE_FLAGS, issueCommand, loopActiveForCwd, positional };
|
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
|
-
import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-
|
|
3
|
+
import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-B-yczgz_.mjs';
|
|
4
4
|
import { execFileSync } from 'node:child_process';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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';
|
|
8
|
+
import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
|
|
7
9
|
import 'node:os';
|
|
8
|
-
import '
|
|
9
|
-
import '
|
|
10
|
+
import './hyphaClient-ybivOjZo.mjs';
|
|
11
|
+
import './types-57J3Re0n.mjs';
|
|
12
|
+
import './securityContext-Cm5UTCuD.mjs';
|
|
13
|
+
import './loopVerify-DALtTk2V.mjs';
|
|
14
|
+
import './instance-CeHz5C8v.mjs';
|
|
10
15
|
import 'fs';
|
|
11
16
|
import 'path';
|
|
12
|
-
import '
|
|
13
|
-
import '
|
|
14
|
-
import 'crypto';
|
|
17
|
+
import 'os';
|
|
18
|
+
import './flushExit-C-i6SGjj.mjs';
|
|
15
19
|
import 'node:crypto';
|
|
16
|
-
import 'util';
|
|
17
|
-
import 'http';
|
|
18
|
-
import 'net';
|
|
19
|
-
import 'node:events';
|
|
20
|
-
import '@agentclientprotocol/sdk';
|
|
21
|
-
import 'node:util';
|
|
22
|
-
import 'node:readline';
|
|
23
|
-
import 'node:fs/promises';
|
|
24
|
-
import 'yaml';
|
|
25
|
-
import './serviceManager-hlOVxkhW.mjs';
|
|
26
20
|
|
|
27
21
|
function git(cwd, args) {
|
|
28
22
|
return execFileSync("git", args, { cwd, stdio: "pipe", encoding: "utf-8" }).toString();
|
|
@@ -187,6 +181,9 @@ function projectRootFromWorktree(worktreePath) {
|
|
|
187
181
|
if (idx === -1) return null;
|
|
188
182
|
return worktreePath.slice(0, idx);
|
|
189
183
|
}
|
|
184
|
+
function canonicalProjectRoot(anyPathInProject) {
|
|
185
|
+
return projectRootFromWorktree(anyPathInProject) ?? anyPathInProject;
|
|
186
|
+
}
|
|
190
187
|
function removeWorktree(worktreePath) {
|
|
191
188
|
const projectRoot = projectRootFromWorktree(worktreePath);
|
|
192
189
|
if (!projectRoot) return;
|
|
@@ -214,14 +211,17 @@ function resolveNotifyLead(leadId, childParentSessionId, childId) {
|
|
|
214
211
|
return leadId || childParentSessionId || childId;
|
|
215
212
|
}
|
|
216
213
|
|
|
214
|
+
function crewReportUrgency(crew) {
|
|
215
|
+
return crew?.action === "block" ? "urgent" : "normal";
|
|
216
|
+
}
|
|
217
217
|
function isStandaloneChild(crew) {
|
|
218
218
|
return !!crew && crew.standalone === true;
|
|
219
219
|
}
|
|
220
|
-
function worktreeCrewMeta(feature, branch, worktreePath, baseBranch) {
|
|
221
|
-
return { role: "feature", feature, branch, worktreePath, baseBranch };
|
|
220
|
+
function worktreeCrewMeta(feature, branch, worktreePath, baseBranch, action) {
|
|
221
|
+
return { role: "feature", feature, branch, worktreePath, baseBranch, ...action ? { action } : {} };
|
|
222
222
|
}
|
|
223
|
-
function standaloneCrewMeta(feature, directory) {
|
|
224
|
-
return { role: "feature", feature, standalone: true, directory };
|
|
223
|
+
function standaloneCrewMeta(feature, directory, action) {
|
|
224
|
+
return { role: "feature", feature, standalone: true, directory, ...action ? { action } : {} };
|
|
225
225
|
}
|
|
226
226
|
function childDirectory(crew, sessionDir) {
|
|
227
227
|
return crew?.worktreePath || crew?.directory || sessionDir || "";
|
|
@@ -277,7 +277,7 @@ async function waitForChildIdle(machine, childId, timeoutMs = 2e4) {
|
|
|
277
277
|
}
|
|
278
278
|
return false;
|
|
279
279
|
}
|
|
280
|
-
async function inbox(machine, fromId, toId, body, subject) {
|
|
280
|
+
async function inbox(machine, fromId, toId, body, subject, urgency = "normal") {
|
|
281
281
|
await rpc(machine, toId, "sendInboxMessage", {
|
|
282
282
|
message: {
|
|
283
283
|
messageId: shortId(),
|
|
@@ -288,7 +288,7 @@ async function inbox(machine, fromId, toId, body, subject) {
|
|
|
288
288
|
fromSession: fromId,
|
|
289
289
|
to: toId,
|
|
290
290
|
subject,
|
|
291
|
-
urgency
|
|
291
|
+
urgency
|
|
292
292
|
}
|
|
293
293
|
});
|
|
294
294
|
}
|
|
@@ -306,6 +306,7 @@ async function featureStart(brief, opts = {}) {
|
|
|
306
306
|
const standalone = !!opts.noWorktree;
|
|
307
307
|
let childDir;
|
|
308
308
|
let base = "";
|
|
309
|
+
const leadDir = opts.directory || lead.directory;
|
|
309
310
|
if (standalone) {
|
|
310
311
|
const dir = opts.directory;
|
|
311
312
|
if (!dir) {
|
|
@@ -319,14 +320,14 @@ async function featureStart(brief, opts = {}) {
|
|
|
319
320
|
}
|
|
320
321
|
console.log(`Standalone child folder: ${childDir} (no worktree)`);
|
|
321
322
|
} else {
|
|
322
|
-
|
|
323
|
-
if (!projectRoot2) {
|
|
323
|
+
if (!leadDir) {
|
|
324
324
|
console.error("Could not determine the lead project directory.");
|
|
325
325
|
process.exit(1);
|
|
326
326
|
}
|
|
327
|
-
|
|
327
|
+
const worktreeRoot = canonicalProjectRoot(leadDir);
|
|
328
|
+
base = opts.baseBranch || currentBranch(worktreeRoot) || "main";
|
|
328
329
|
try {
|
|
329
|
-
wt = createWorktree(
|
|
330
|
+
wt = createWorktree(worktreeRoot);
|
|
330
331
|
} catch (e) {
|
|
331
332
|
console.error(`Failed to create worktree: ${e.message}`);
|
|
332
333
|
process.exit(1);
|
|
@@ -334,7 +335,7 @@ async function featureStart(brief, opts = {}) {
|
|
|
334
335
|
childDir = wt.path;
|
|
335
336
|
console.log(`Worktree: ${wt.branch} \u2192 ${wt.path}`);
|
|
336
337
|
}
|
|
337
|
-
const projectRoot =
|
|
338
|
+
const projectRoot = canonicalProjectRoot(leadDir || childDir);
|
|
338
339
|
const result = await machine.spawnSession({
|
|
339
340
|
directory: childDir,
|
|
340
341
|
agent: "claude",
|
|
@@ -395,8 +396,9 @@ async function featureStart(brief, opts = {}) {
|
|
|
395
396
|
}
|
|
396
397
|
const oracle = opts.oracle?.trim();
|
|
397
398
|
const patch = {
|
|
398
|
-
crew: standalone ? standaloneCrewMeta(brief.trim(), childDir) : worktreeCrewMeta(brief.trim(), wt.branch, wt.path, base)
|
|
399
|
+
crew: standalone ? standaloneCrewMeta(brief.trim(), childDir, opts.action) : worktreeCrewMeta(brief.trim(), wt.branch, wt.path, base, opts.action)
|
|
399
400
|
};
|
|
401
|
+
const childMaxIterations = opts.maxRounds ?? 20;
|
|
400
402
|
let judges = [];
|
|
401
403
|
if (oracle) {
|
|
402
404
|
judges = [{ type: "oracle", cmd: oracle, on_fail: "escalate" }, { type: "parent", parent: lead.sessionId }];
|
|
@@ -404,8 +406,10 @@ async function featureStart(brief, opts = {}) {
|
|
|
404
406
|
until: brief.trim(),
|
|
405
407
|
oracle,
|
|
406
408
|
parent: lead.sessionId,
|
|
407
|
-
max_iterations:
|
|
409
|
+
max_iterations: childMaxIterations
|
|
408
410
|
};
|
|
411
|
+
} else if (opts.maxRounds != null) {
|
|
412
|
+
patch.loop = { max_iterations: childMaxIterations };
|
|
409
413
|
}
|
|
410
414
|
try {
|
|
411
415
|
await rpc(machine, childId, "updateConfig", { patch });
|
|
@@ -527,9 +531,10 @@ async function featureReport(text, opts = {}) {
|
|
|
527
531
|
process.exit(1);
|
|
528
532
|
}
|
|
529
533
|
const kind = opts.blocker ? "blocker" : "progress";
|
|
534
|
+
const urgency = opts.blocker ? "urgent" : crewReportUrgency(meta?.crew);
|
|
530
535
|
await inbox(machine, selfId, parent, `<feature-${kind} from="${selfId}">
|
|
531
536
|
${text.trim()}
|
|
532
|
-
</feature-${kind}>`, `feature ${kind}
|
|
537
|
+
</feature-${kind}>`, `feature ${kind}`, urgency);
|
|
533
538
|
console.log(`Reported ${kind} to lead ${parent.slice(0, 8)}.`);
|
|
534
539
|
} finally {
|
|
535
540
|
await server.disconnect();
|
|
@@ -555,7 +560,7 @@ async function featureDone(opts = {}) {
|
|
|
555
560
|
`No branch to merge (standalone folder). Detach & close with: svamp feature merge ${selfId.slice(0, 8)}`,
|
|
556
561
|
`</done-request>`
|
|
557
562
|
].filter(Boolean).join("\n");
|
|
558
|
-
await inbox(machine, selfId, parent, body2, `done-request (standalone)
|
|
563
|
+
await inbox(machine, selfId, parent, body2, `done-request (standalone)`, crewReportUrgency(crew));
|
|
559
564
|
console.log(`Sent done-request to lead ${parent.slice(0, 8)} (standalone folder ${dir2 || "?"}; no branch to merge).`);
|
|
560
565
|
return;
|
|
561
566
|
}
|
|
@@ -576,7 +581,7 @@ async function featureDone(opts = {}) {
|
|
|
576
581
|
`Review & merge with: svamp feature merge ${selfId.slice(0, 8)}`,
|
|
577
582
|
`</merge-request>`
|
|
578
583
|
].filter(Boolean).join("\n");
|
|
579
|
-
await inbox(machine, selfId, parent, body, `merge-request (${branch || "feature"})
|
|
584
|
+
await inbox(machine, selfId, parent, body, `merge-request (${branch || "feature"})`, crewReportUrgency(crew));
|
|
580
585
|
console.log(`Sent merge-request to lead ${parent.slice(0, 8)} (branch ${branch || "?"}, +${ab.ahead} commits).`);
|
|
581
586
|
if (dirty) console.log(" \u26A0 Worktree is dirty \u2014 commit your work or the merge will be rejected.");
|
|
582
587
|
} finally {
|
|
@@ -624,7 +629,14 @@ async function featureMerge(childPartial, opts = {}) {
|
|
|
624
629
|
notifyLead,
|
|
625
630
|
childId,
|
|
626
631
|
`<crew-freeze>Your lead is merging branch ${branch} into ${base}. Stop editing files now; do not commit until told.</crew-freeze>`,
|
|
627
|
-
"crew: freeze for merge"
|
|
632
|
+
"crew: freeze for merge",
|
|
633
|
+
// #1619: URGENT. This is a pre-emption notice, and the state it must interrupt —
|
|
634
|
+
// a child mid-work — is by definition NOT idle, so at 'normal' urgency
|
|
635
|
+
// classifyInbound QUEUES it until the child stops on its own. waitForChildIdle
|
|
636
|
+
// below is supposed to observe the child halting BECAUSE of this message; a queued
|
|
637
|
+
// message causes no halt, so the wait could only ever time out, and mergeBack can
|
|
638
|
+
// then reach `git worktree remove --force` on a tree the child is still writing.
|
|
639
|
+
"urgent"
|
|
628
640
|
);
|
|
629
641
|
} catch {
|
|
630
642
|
}
|
|
@@ -644,7 +656,10 @@ async function featureMerge(childPartial, opts = {}) {
|
|
|
644
656
|
Merge was not applied: ${r.detail}
|
|
645
657
|
Resolve and run \`svamp feature done\` again.
|
|
646
658
|
</crew-rework>`,
|
|
647
|
-
"crew: rework needed"
|
|
659
|
+
"crew: rework needed",
|
|
660
|
+
// #1619: URGENT — the comment above says 're-wake the child', which at
|
|
661
|
+
// 'normal' urgency is exactly what did not happen.
|
|
662
|
+
"urgent"
|
|
648
663
|
);
|
|
649
664
|
} catch {
|
|
650
665
|
}
|
|
@@ -660,7 +675,12 @@ Resolve and run \`svamp feature done\` again.
|
|
|
660
675
|
Merge could not be applied (${r.stage}): ${r.detail}
|
|
661
676
|
Stop editing and hold \u2014 do not keep working. Once the blocker is resolved, the lead can retry \`svamp feature merge\`.
|
|
662
677
|
</crew-blocked>`,
|
|
663
|
-
"crew: merge blocked"
|
|
678
|
+
"crew: merge blocked",
|
|
679
|
+
// #1619: URGENT. #0353's whole point is to STOP a child that is 'silently
|
|
680
|
+
// LOOPING against an un-merged branch, burning tokens toward the cost
|
|
681
|
+
// ceiling'. A looping child is never idle, so a queued STOP notice arrived
|
|
682
|
+
// only once it was no longer needed.
|
|
683
|
+
"urgent"
|
|
664
684
|
);
|
|
665
685
|
} catch {
|
|
666
686
|
}
|
|
@@ -676,6 +696,12 @@ Stop editing and hold \u2014 do not keep working. Once the blocker is resolved,
|
|
|
676
696
|
console.warn(`Merged, but could not archive child: ${e.message}`);
|
|
677
697
|
}
|
|
678
698
|
}
|
|
699
|
+
try {
|
|
700
|
+
const resolved = resolveCrewIssueOnMerge(projectRoot, childId, { branch, base });
|
|
701
|
+
if (resolved) console.log(` issue: #${resolved.id} closed (merged).`);
|
|
702
|
+
} catch (e) {
|
|
703
|
+
console.warn(`Merged, but could not close the crew tracking issue: ${e.message}`);
|
|
704
|
+
}
|
|
679
705
|
const cleanup = r.cleanupWarning ? "worktree NOT removed (see warning)" : isMainWorkingTree(projectRoot, worktreePath) ? "ran in the lead tree (no worktree to remove)" : "worktree removed";
|
|
680
706
|
if (r.cleanupWarning) console.warn(`\u26A0\uFE0F ${r.cleanupWarning}`);
|
|
681
707
|
console.log(`\u2705 Merged ${branch} \u2192 ${base}; ${cleanup}; child ${childId.slice(0, 8)} ${opts.keepChild ? "kept" : "archived"}.`);
|
|
@@ -711,6 +737,10 @@ const FEATURE_HELP = `Usage: svamp feature <command>
|
|
|
711
737
|
[--max N] [--dir <path>] [--no-worktree] [--model <id>] [--lead <id>] [-m <machine>]
|
|
712
738
|
Spawn a managed child of the lead + attach a loop gate (oracle\u2192parent).
|
|
713
739
|
--model sets the child's model (e.g. claude-fable-5, claude-opus-4-8).
|
|
740
|
+
--action nudge|block controls how the lead is notified when the child reports or
|
|
741
|
+
finishes: 'nudge' (default) sends at normal urgency, which the lead picks up on its
|
|
742
|
+
next idle turn; 'block' sends urgent, which WAKES the lead. An explicit
|
|
743
|
+
'crew report --blocker' is always urgent regardless.
|
|
714
744
|
--issue <id> links the child to an existing backlog issue: the child's verdict
|
|
715
745
|
routes ONTO that issue \u2014 the seam that joins crew to the backlog that
|
|
716
746
|
'svamp issue pending' (the loop oracle) reads.
|
|
@@ -737,6 +767,16 @@ async function crewCommand(args) {
|
|
|
737
767
|
const valueFlags = ["--oracle", "--base", "--action", "--max", "--dir", "-d", "--lead", "-m", "--machine", "--issue", "--model"];
|
|
738
768
|
const brief = positionals(rest, valueFlags).join(" ");
|
|
739
769
|
const maxStr = flag(rest, "--max");
|
|
770
|
+
let maxRounds;
|
|
771
|
+
if (maxStr !== void 0) {
|
|
772
|
+
const n = Number(maxStr);
|
|
773
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
774
|
+
console.error(`Error: --max must be a positive integer (got "${maxStr}").`);
|
|
775
|
+
console.error(" Omit it to use the default round cap; it is a HARD stop for the child.");
|
|
776
|
+
process.exit(1);
|
|
777
|
+
}
|
|
778
|
+
maxRounds = n;
|
|
779
|
+
}
|
|
740
780
|
const action = flag(rest, "--action");
|
|
741
781
|
await featureStart(brief, {
|
|
742
782
|
leadId: lead,
|
|
@@ -748,7 +788,7 @@ async function crewCommand(args) {
|
|
|
748
788
|
issueId: flag(rest, "--issue"),
|
|
749
789
|
model: flag(rest, "--model"),
|
|
750
790
|
action: action === "block" ? "block" : action === "nudge" ? "nudge" : void 0,
|
|
751
|
-
maxRounds
|
|
791
|
+
maxRounds
|
|
752
792
|
});
|
|
753
793
|
} else if (sub === "list" || sub === "ls") {
|
|
754
794
|
await featureList({ leadId: lead, machineId, json: has(rest, "--json") });
|
|
@@ -1,28 +1,22 @@
|
|
|
1
|
-
import { connectAndResolveSession } from './commands-
|
|
2
|
-
import { w as wantsHelp } from './
|
|
1
|
+
import { connectAndResolveSession } from './commands-B-yczgz_.mjs';
|
|
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
|
-
import './
|
|
8
|
-
import '
|
|
9
|
-
import '
|
|
7
|
+
import './hyphaClient-ybivOjZo.mjs';
|
|
8
|
+
import './friendlyName-1UZcyDhu.mjs';
|
|
9
|
+
import 'node:crypto';
|
|
10
|
+
import './types-57J3Re0n.mjs';
|
|
11
|
+
import './securityContext-Cm5UTCuD.mjs';
|
|
12
|
+
import './loopVerify-DALtTk2V.mjs';
|
|
13
|
+
import './instance-CeHz5C8v.mjs';
|
|
10
14
|
import 'fs';
|
|
11
15
|
import 'path';
|
|
12
|
-
import '
|
|
13
|
-
import '
|
|
14
|
-
import '
|
|
15
|
-
import '
|
|
16
|
-
import 'util';
|
|
17
|
-
import 'http';
|
|
18
|
-
import 'net';
|
|
19
|
-
import 'node:events';
|
|
20
|
-
import '@agentclientprotocol/sdk';
|
|
21
|
-
import 'node:util';
|
|
22
|
-
import 'node:readline';
|
|
23
|
-
import 'node:fs/promises';
|
|
24
|
-
import 'yaml';
|
|
25
|
-
import './serviceManager-hlOVxkhW.mjs';
|
|
16
|
+
import 'os';
|
|
17
|
+
import './store-B4E6NzG6.mjs';
|
|
18
|
+
import './fileLock-BMPwCrB6.mjs';
|
|
19
|
+
import './flushExit-C-i6SGjj.mjs';
|
|
26
20
|
|
|
27
21
|
function argVal(args, name) {
|
|
28
22
|
const i = args.indexOf(name);
|
|
@@ -117,6 +111,27 @@ async function outpostInstall(args) {
|
|
|
117
111
|
if (info.downloadBase) console.log("Direct download: " + info.downloadBase);
|
|
118
112
|
}
|
|
119
113
|
}
|
|
114
|
+
async function outpostRotate(args) {
|
|
115
|
+
const dl = argVal(args, "--download-base");
|
|
116
|
+
if (!args.includes("--yes") && !args.includes("-y")) {
|
|
117
|
+
console.log("This REVOKES this session's outpost token and mints a new one.");
|
|
118
|
+
console.log("Every currently-connected outpost will stop working until it re-runs the new");
|
|
119
|
+
console.log("install command. Re-run with --yes to proceed.");
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
const info = await withSession((m, id) => m.sessionRPC(id, "outpostRotateToken", dl ? { params: { downloadBase: dl } } : {}));
|
|
123
|
+
if (!info || info.error) {
|
|
124
|
+
console.error(`Could not rotate the outpost token: ${info?.error || "unknown error"}`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
console.log("\u2713 outpost token rotated \u2014 the previous token no longer works.\n");
|
|
128
|
+
console.log("Any machine that was connected must re-run the install command below:\n");
|
|
129
|
+
const gen = info.install || {};
|
|
130
|
+
if (gen.unix) console.log(" macOS / Linux:\n " + gen.unix + "\n");
|
|
131
|
+
if (gen.windows) console.log(" Windows (PowerShell):\n " + gen.windows + "\n");
|
|
132
|
+
if (info.pairingCode) console.log(` \u2026or the short pairing code: ${info.pairingCode}
|
|
133
|
+
`);
|
|
134
|
+
}
|
|
120
135
|
function usage() {
|
|
121
136
|
console.log(`svamp outpost \u2014 drive a connected remote machine (FDE outpost)
|
|
122
137
|
|
|
@@ -127,6 +142,10 @@ function usage() {
|
|
|
127
142
|
stdout/stderr/exit code synchronously (like a local command).
|
|
128
143
|
With one outpost connected, --machine is optional.
|
|
129
144
|
svamp outpost install [--os <os>] Reprint the install one-liner(s) for this session's outpost
|
|
145
|
+
svamp outpost rotate [--yes] REVOKE this session's outpost token and mint a new one.
|
|
146
|
+
Use after the install one-liner has been shared somewhere it
|
|
147
|
+
should not have been. Every currently-connected outpost stops
|
|
148
|
+
working and must re-run the new install command.
|
|
130
149
|
|
|
131
150
|
With several machines connected, target each by id, e.g.:
|
|
132
151
|
svamp outpost exec --machine build-mac "uname -a"
|
|
@@ -155,6 +174,10 @@ async function outpostCommand(args) {
|
|
|
155
174
|
await outpostInstall(args.slice(1));
|
|
156
175
|
return;
|
|
157
176
|
}
|
|
177
|
+
if (sub === "rotate" || sub === "revoke") {
|
|
178
|
+
await outpostRotate(args.slice(1));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
158
181
|
console.error(`unknown outpost command: ${sub}`);
|
|
159
182
|
usage();
|
|
160
183
|
process.exit(1);
|
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import '
|
|
5
|
-
import 'fs/promises';
|
|
6
|
-
import 'fs';
|
|
7
|
-
import 'path';
|
|
8
|
-
import 'url';
|
|
9
|
-
import 'child_process';
|
|
10
|
-
import 'crypto';
|
|
1
|
+
import { r as resolveProjectRoot } from './store-B4E6NzG6.mjs';
|
|
2
|
+
import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
|
|
3
|
+
import { s as setWorkflowEnabled, i as isWorkflowEnabled, r as removeWorkflow, g as getWorkflow, l as listWorkflows, c as workflowSteps, a as saveWorkflow, b as rawWorkflow } from './store-fi0f-ff1.mjs';
|
|
4
|
+
import { v as validateCronExpr, d as describeNextFire } from './cron-hHGdb5kU.mjs';
|
|
11
5
|
import 'node:fs';
|
|
12
6
|
import 'node:path';
|
|
13
7
|
import 'node:crypto';
|
|
14
|
-
import '
|
|
15
|
-
import '
|
|
16
|
-
import 'net';
|
|
17
|
-
import 'node:os';
|
|
18
|
-
import 'node:events';
|
|
19
|
-
import '@agentclientprotocol/sdk';
|
|
20
|
-
import 'node:util';
|
|
21
|
-
import 'node:readline';
|
|
22
|
-
import 'node:fs/promises';
|
|
8
|
+
import 'node:child_process';
|
|
9
|
+
import './fileLock-BMPwCrB6.mjs';
|
|
23
10
|
import 'yaml';
|
|
24
|
-
import './serviceManager-hlOVxkhW.mjs';
|
|
25
11
|
|
|
26
12
|
function flag(args, name) {
|
|
27
13
|
const i = args.indexOf(name);
|
|
@@ -161,16 +147,20 @@ async function workflowCommand(args) {
|
|
|
161
147
|
console.error(`Workflow not found: ${name}`);
|
|
162
148
|
process.exit(1);
|
|
163
149
|
}
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
console.log(` [${
|
|
169
|
-
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
150
|
+
const { runWorkflow } = await import('./run-DDmeV9K3.mjs').then(function (n) { return n.e; });
|
|
151
|
+
const run = await runWorkflow(root, wf, { trigger: "manual", actor: process.env.SVAMP_SESSION_ID || null });
|
|
152
|
+
console.log(`\u25B6 ran workflow "${wf.name}" (${run.steps.length} step${run.steps.length === 1 ? "" : "s"}) \u2192 ${run.status}`);
|
|
153
|
+
for (const st of run.steps) {
|
|
154
|
+
console.log(` [${st.index + 1}] $ ${st.cmd}`);
|
|
155
|
+
if (st.stdout) console.log(st.stdout.trimEnd());
|
|
156
|
+
if (st.stderr) console.error(st.stderr.trimEnd());
|
|
157
|
+
if (st.timedOut) console.error(` \u2717 step ${st.index + 1} timed out.`);
|
|
158
|
+
else if (st.exitCode !== 0) console.error(` \u2717 step ${st.index + 1} failed (exit ${st.exitCode ?? "signal"}).`);
|
|
159
|
+
}
|
|
160
|
+
if (run.escalatedIssue) console.log(` \u21B3 escalated to issue #${run.escalatedIssue} (agent will correct the workflow).`);
|
|
161
|
+
if (run.status !== "success") {
|
|
162
|
+
console.error(`\u2717 workflow "${wf.name}" failed.`);
|
|
163
|
+
process.exit(1);
|
|
174
164
|
}
|
|
175
165
|
console.log(`\u2713 workflow "${wf.name}" completed.`);
|
|
176
166
|
break;
|
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
2
|
import fs__default from 'fs';
|
|
3
3
|
import { resolve, join, relative } from 'path';
|
|
4
|
-
import {
|
|
5
|
-
import '
|
|
6
|
-
import 'url';
|
|
7
|
-
import 'child_process';
|
|
8
|
-
import 'crypto';
|
|
9
|
-
import 'node:fs';
|
|
10
|
-
import 'node:path';
|
|
11
|
-
import 'node:crypto';
|
|
12
|
-
import 'node:child_process';
|
|
13
|
-
import 'util';
|
|
14
|
-
import 'http';
|
|
15
|
-
import 'net';
|
|
16
|
-
import 'node:os';
|
|
17
|
-
import 'node:events';
|
|
18
|
-
import '@agentclientprotocol/sdk';
|
|
19
|
-
import 'node:util';
|
|
20
|
-
import 'node:readline';
|
|
21
|
-
import 'node:fs/promises';
|
|
22
|
-
import 'yaml';
|
|
4
|
+
import { parseFrontmatter, getSkillsServer, getSkillsWorkspaceName, getSkillsCollectionName, fetchWithTimeout, searchSkills, SKILLS_DIR, getSkillInfo, downloadSkillFile, listSkillFiles } from './api-BHjyC0Ph.mjs';
|
|
5
|
+
import './instance-CeHz5C8v.mjs';
|
|
23
6
|
|
|
24
7
|
const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
|
|
25
8
|
const ENV_FILE = join(SVAMP_HOME, ".env");
|