@gobing-ai/spur 0.3.84 → 0.3.85
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/.claude-plugin/marketplace.json +1 -1
- package/config/config.global.yaml +11 -6
- package/config/workflows/idea-pipeline.yaml +1 -1
- package/config/workflows/wrapup-pipeline.yaml +1 -1
- package/package.json +1 -1
- package/plugins/sp/agents/super-planner.md +2 -1
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/surface-drift-inventory.ts +1 -1
- package/spur.js +244 -18
- package/web/_astro/BoardApp.CHenHFia.js +1 -0
- package/web/_astro/{BoardApp.D4mBUGLT.js → BoardApp.yW425dRZ.js} +60 -60
- package/web/_astro/{TaskDetail.DhCWaOPR.js → TaskDetail.CGwJAinW.js} +1 -1
- package/web/_astro/{arc.D3X0nfq-.js → arc.B-qNXzSO.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.BQDoiGme.js → architectureDiagram-3BPJPVTR.Bdg-xiji.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.BjHekBbM.js → blockDiagram-GPEHLZMM.DFArg3Kp.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.BvHt171l.js → c4Diagram-AAUBKEIU.BkOLcjyx.js} +1 -1
- package/web/_astro/channel.CbDHK5UQ.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.CwxGXlDR.js → chunk-2J33WTMH.DN3c20V4.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.Dia1YtwU.js → chunk-4BX2VUAB.B64K0Ttd.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.Oz9epCXa.js → chunk-55IACEB6.C-AJvNwa.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.DKFYJjYJ.js → chunk-727SXJPM.DMkr46uS.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.AD7w5oVz.js → chunk-AQP2D5EJ.4_WGbI64.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.D0OqTj52.js → chunk-FMBD7UC4.cbFW_lVE.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.CU5ppR7j.js → chunk-ND2GUHAM.CDW_-2O1.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.Bu1rFztw.js → chunk-QZHKN3VN.BoYOt_yg.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.C0Pgm5yE.js → classDiagram-4FO5ZUOK.BNT6XpHQ.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.C0Pgm5yE.js → classDiagram-v2-Q7XG4LA2.BNT6XpHQ.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.C0ecLb1e.js → cose-bilkent-S5V4N54A.CI1DQxR3.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.CpStVmhO.js → cynefin-OW5HDTMX.A8ARH61p.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BPWN3W9f.js → dagre-BM42HDAG.u28ZmqwR.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.DnXbEot4.js → diagram-2AECGRRQ.Dx8JcrGc.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.BYJsgUiI.js → diagram-5GNKFQAL.BXJUG9GY.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CU4Bqprx.js → diagram-KO2AKTUF.BtlMuWqW.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BQLOANIu.js → diagram-LMA3HP47.C4T7qaAy.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Cn1UVhqj.js → diagram-OG6HWLK6.D5HECE10.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.C8FdZyvA.js → erDiagram-TEJ5UH35.B_hMR3yw.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.QSZCR8Uo.js → flowDiagram-I6XJVG4X.BAmpcYl3.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.O1Py31MY.js → ganttDiagram-6RSMTGT7.DV1bSWK-.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.DoeJRBfY.js → gitGraphDiagram-PVQCEYII.DxYKkKrJ.js} +1 -1
- package/web/_astro/{index.TPF1FerP.css → index.CcU5weKX.css} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.9npLJecW.js → infoDiagram-5YYISTIA.BAWY2xMb.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.DXanvOr3.js → ishikawaDiagram-YF4QCWOH.CZssRn6V.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.DxbVjxAv.js → journeyDiagram-JHISSGLW.C--muARd.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.BDk6_iq0.js → kanban-definition-UN3LZRKU.D_QCK4et.js} +1 -1
- package/web/_astro/{linear.C9cCDjT3.js → linear.DzrmTtZ0.js} +1 -1
- package/web/_astro/{mermaid.core.CpHRe5nH.js → mermaid.core.Da03W3iu.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.D-6C85bn.js → mindmap-definition-RKZ34NQL.6cy-8hR_.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.B3Oxodty.js → pieDiagram-4H26LBE5.C5rS1pdU.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.QZ_9Hshu.js → quadrantDiagram-W4KKPZXB.w56GZZ6Q.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.BimvuK53.js → requirementDiagram-4Y6WPE33.CipX3Pwu.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.D5Kkpx2C.js → sankeyDiagram-5OEKKPKP.C0VVzgJm.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.B4YR6fAE.js → sequenceDiagram-3UESZ5HK.BX2dUUbF.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.Bt2wkZok.js → stateDiagram-AJRCARHV.ypCdgODQ.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.YZ4X7dfQ.js → stateDiagram-v2-BHNVJYJU.In0baEtg.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.DmiTBL8w.js → timeline-definition-PNZ67QCA.CJN4Vkvl.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.KNJV40mf.js → vennDiagram-CIIHVFJN.Cf8KkIPY.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BVAaKgWH.js → wardleyDiagram-YWT4CUSO.DCZBo9xw.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.D5Jx7zB2.js → xychartDiagram-2RQKCTM6.Cm4v_MiJ.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.DFPYpI5O.js +0 -1
- package/web/_astro/channel.BlQwxyoI.js +0 -1
|
@@ -95,7 +95,7 @@ agent:
|
|
|
95
95
|
# claude-*-5 via claude, grok-4.6 via grok, gemini-3.x via agy) —
|
|
96
96
|
# consistently outperforms the same model routed through a third-party CLI,
|
|
97
97
|
# and belongs at the capable rungs. `portable` models (glm-5.x,
|
|
98
|
-
# deepseek-v4-*, …) are provider-agnostic and best carried by
|
|
98
|
+
# deepseek-v4-*, …) are provider-agnostic and best carried by pi at
|
|
99
99
|
# the cheap/standard rungs. The ladder below mixes both classes on purpose;
|
|
100
100
|
# measure pairings with the history plane before promoting a portable model
|
|
101
101
|
# into a capable rung. Live tiers: cheap | standard | capable-1 | capable-2
|
|
@@ -106,19 +106,24 @@ agent:
|
|
|
106
106
|
# capable-1.
|
|
107
107
|
#
|
|
108
108
|
# Because this is the global layer, a project that wants one different model
|
|
109
|
-
# writes only `- name:
|
|
110
|
-
# here.
|
|
109
|
+
# writes only `- name: pi-dsv4-flash` + `model: …` — the agent and tier come
|
|
110
|
+
# from here.
|
|
111
111
|
executors:
|
|
112
112
|
# cheap rung is optional: with none declared, scribe-role work starts
|
|
113
113
|
# one rung up at the cheapest standard executor. Add one when
|
|
114
114
|
# transcript-heavy mechanical commands (changelog/gitmsg/handover) get
|
|
115
115
|
# noisy on cost.
|
|
116
116
|
# - name: minimax
|
|
117
|
-
# agent:
|
|
117
|
+
# agent: pi
|
|
118
118
|
# model: minimax/MiniMax-M3
|
|
119
119
|
# tier: cheap
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
# Standard rung. An `agent:` here is a live DISPATCH target, not a label:
|
|
121
|
+
# role routing (`agent.default: coder`, `--agent auto`, every workflow step
|
|
122
|
+
# declaring `agent: auto`) lands on the cheapest eligible standard executor,
|
|
123
|
+
# so listing an agent makes Spur delegate work to it. Keep this rung on an
|
|
124
|
+
# agent the supported install targets actually carry.
|
|
125
|
+
- name: pi-dsv4-flash
|
|
126
|
+
agent: pi
|
|
122
127
|
model: opencode/deepseek-v4-flash
|
|
123
128
|
tier: standard
|
|
124
129
|
- name: pi
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
# lets profile=auto route around the idea-eval taste gate (default "false")
|
|
34
34
|
# CLI --approve-taste sets both design_approved and idea_approved to true.
|
|
35
35
|
# spurBin — PATH-independent spur invocation (overridden by CLI at run start)
|
|
36
|
-
# agent — agent for agent.run steps (default:
|
|
36
|
+
# agent — agent for agent.run steps (default: auto → `agent.default` in config)
|
|
37
37
|
#
|
|
38
38
|
# Reliability (aligned with task-pipeline / ADR-043):
|
|
39
39
|
# - Soft agent doctor at start → failed via transitions (not raw lifecycle abort)
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
# merge — set --vars '{"merge":"true"}' to run branch cleanup (irreversible
|
|
32
32
|
# HITL)
|
|
33
33
|
# spurBin — PATH-independent spur invocation (overridden by CLI at run start)
|
|
34
|
-
# agent — agent for agent.run steps (default:
|
|
34
|
+
# agent — agent for agent.run steps (default: auto → `agent.default` in config)
|
|
35
35
|
#
|
|
36
36
|
# Reliability (aligned with task-pipeline / ADR-043):
|
|
37
37
|
# - Prefer pure slash commands when a command exists; free-form inputs remain
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.85",
|
|
4
4
|
"description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"spur",
|
|
@@ -97,7 +97,8 @@ You own the spaces **between** task runs:
|
|
|
97
97
|
You explicitly do **NOT** own step-level execution:
|
|
98
98
|
|
|
99
99
|
- How an `agent.run` step (implement/test/review/verify) runs is `vars.agent`'s concern - default
|
|
100
|
-
`
|
|
100
|
+
`auto` (`agent.default` in config resolves the executor), pinned in `task-pipeline.yaml`.
|
|
101
|
+
`--agent <value>` from the command flows into each
|
|
101
102
|
per-task `vars.agent`; you forward it, you do not interpret it.
|
|
102
103
|
- You never edit the pipeline YAML, never reach into a step, and never decide how a single
|
|
103
104
|
`agent.run` stage executes. The per-task pipeline is invoked **verbatim**.
|
package/plugins/sp/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.85",
|
|
4
4
|
"description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
|
|
5
5
|
"extensions": {
|
|
6
6
|
"pi": ["./hooks/pi/guard-extension.ts"]
|
|
@@ -636,7 +636,7 @@ const JSON_PROBES: string[][] = [
|
|
|
636
636
|
['feature', 'show', 'I3', '--json'],
|
|
637
637
|
['rule', 'list', '--json'],
|
|
638
638
|
['agent', 'list', '--json'],
|
|
639
|
-
['agent', 'doctor', '
|
|
639
|
+
['agent', 'doctor', 'pi', '--json'],
|
|
640
640
|
['workflow', 'list', '--json'],
|
|
641
641
|
['workflow', 'validate', 'basic.yaml', '--json'],
|
|
642
642
|
['status', '--json'],
|
package/spur.js
CHANGED
|
@@ -39521,6 +39521,7 @@ var init_slash_commands = __esm(() => {
|
|
|
39521
39521
|
description: exports_external.string().min(1),
|
|
39522
39522
|
category: slashCommandCategorySchema.default("dev"),
|
|
39523
39523
|
argumentHint: exports_external.string().optional(),
|
|
39524
|
+
tags: exports_external.array(exports_external.string()).default([]),
|
|
39524
39525
|
role: exports_external.string().optional(),
|
|
39525
39526
|
source: exports_external.string().optional()
|
|
39526
39527
|
});
|
|
@@ -86449,8 +86450,13 @@ function schedulerJobTimeoutEnvName(name) {
|
|
|
86449
86450
|
const snake = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([^A-Za-z0-9]+)/g, "_").toUpperCase().replace(/^_+|_+$/g, "");
|
|
86450
86451
|
return `SPUR_SCHEDULER_TIMEOUT_${snake}_MS`;
|
|
86451
86452
|
}
|
|
86452
|
-
function resolveSchedulerJobTimeoutMs(name, env, fallbackMs) {
|
|
86453
|
-
|
|
86453
|
+
function resolveSchedulerJobTimeoutMs(name, env, fallbackMs, declaredMs) {
|
|
86454
|
+
const override = env[schedulerJobTimeoutEnvName(name)];
|
|
86455
|
+
if (override !== undefined)
|
|
86456
|
+
return normalizeLegacyTimeoutMs(override, fallbackMs);
|
|
86457
|
+
if (declaredMs !== undefined)
|
|
86458
|
+
return declaredMs;
|
|
86459
|
+
return fallbackMs;
|
|
86454
86460
|
}
|
|
86455
86461
|
function outputTail(text4) {
|
|
86456
86462
|
const trimmed = text4.trim();
|
|
@@ -86506,6 +86512,10 @@ async function handleSchedulerCustomJob(deps, job) {
|
|
|
86506
86512
|
throw new Error(describeBoundedFailure({ subject: `scheduler job "${payload.name}"`, outcome, outputTail: detail }));
|
|
86507
86513
|
}
|
|
86508
86514
|
if (result.exitCode === null) {
|
|
86515
|
+
if (deps.isShuttingDown?.() === true) {
|
|
86516
|
+
deps.onShutdownAbandon?.(payload.name);
|
|
86517
|
+
return;
|
|
86518
|
+
}
|
|
86509
86519
|
const signalDetail = result.signal === undefined ? "" : ` (${result.signal})`;
|
|
86510
86520
|
throw new Error(`scheduler job "${payload.name}" terminated before a normal exit${signalDetail} ` + `after ${Math.round(outcome.elapsedMs)}ms${detail && `: ${detail}`}`);
|
|
86511
86521
|
}
|
|
@@ -88375,7 +88385,7 @@ class AgentRunActionRunner {
|
|
|
88375
88385
|
const priority = asOptionalString(options.priority);
|
|
88376
88386
|
const compareExecutorWith = asOptionalString(options.compareExecutorWith) ?? "implement";
|
|
88377
88387
|
const agentLabel = dispatchAgent ?? "<default>";
|
|
88378
|
-
const targetAgentDir = dispatchAgent ?? this.agentConfig.default ?? "
|
|
88388
|
+
const targetAgentDir = dispatchAgent ?? this.agentConfig.default ?? "default";
|
|
88379
88389
|
const prevAgent = freshSession ? undefined : asOptionalString(context4.vars.__agentSessionAgent);
|
|
88380
88390
|
let sessionDir = freshSession ? undefined : asOptionalString(context4.vars.__agentSessionDir);
|
|
88381
88391
|
if (affinityOn) {
|
|
@@ -94264,7 +94274,7 @@ function scanMarkdownCommands(dirPath, options = {}) {
|
|
|
94264
94274
|
if (!existsSync8(dirPath)) {
|
|
94265
94275
|
return [];
|
|
94266
94276
|
}
|
|
94267
|
-
const { prefix = "/", source = "plugin:sp", defaultCategory } = options;
|
|
94277
|
+
const { prefix = "/", source = "plugin:sp", defaultCategory, pluginId } = options;
|
|
94268
94278
|
const items = [];
|
|
94269
94279
|
try {
|
|
94270
94280
|
const entries = readdirSync7(dirPath, { withFileTypes: true });
|
|
@@ -94301,15 +94311,56 @@ function scanMarkdownCommands(dirPath, options = {}) {
|
|
|
94301
94311
|
} else {
|
|
94302
94312
|
category = defaultCategory ?? deduceCommandCategory(stem);
|
|
94303
94313
|
}
|
|
94304
|
-
const hintRaw = frontmatter["argument-hint"] ?? frontmatter.argumentHint;
|
|
94314
|
+
const hintRaw = frontmatter["argument-hint"] ?? frontmatter.argumentHint ?? frontmatter.arguments ?? frontmatter.args;
|
|
94305
94315
|
const argumentHint = typeof hintRaw === "string" && hintRaw.trim().length > 0 ? hintRaw.trim() : undefined;
|
|
94306
94316
|
const roleRaw = frontmatter.role;
|
|
94307
94317
|
const role = typeof roleRaw === "string" && roleRaw.trim().length > 0 ? roleRaw.trim() : undefined;
|
|
94318
|
+
const rawTags = frontmatter.tags ?? frontmatter.tag;
|
|
94319
|
+
const tagSet = new Set;
|
|
94320
|
+
if (Array.isArray(rawTags)) {
|
|
94321
|
+
for (const t of rawTags) {
|
|
94322
|
+
if (typeof t === "string" && t.trim().length > 0) {
|
|
94323
|
+
tagSet.add(t.trim().toLowerCase());
|
|
94324
|
+
}
|
|
94325
|
+
}
|
|
94326
|
+
} else if (typeof rawTags === "string" && rawTags.trim().length > 0) {
|
|
94327
|
+
for (const t of rawTags.split(",")) {
|
|
94328
|
+
if (t.trim().length > 0) {
|
|
94329
|
+
tagSet.add(t.trim().toLowerCase());
|
|
94330
|
+
}
|
|
94331
|
+
}
|
|
94332
|
+
}
|
|
94333
|
+
if (Array.isArray(options.tags)) {
|
|
94334
|
+
for (const t of options.tags) {
|
|
94335
|
+
if (t.trim().length > 0) {
|
|
94336
|
+
tagSet.add(t.trim().toLowerCase());
|
|
94337
|
+
}
|
|
94338
|
+
}
|
|
94339
|
+
}
|
|
94340
|
+
if (category) {
|
|
94341
|
+
tagSet.add(category);
|
|
94342
|
+
}
|
|
94343
|
+
if (pluginId) {
|
|
94344
|
+
tagSet.add(pluginId.toLowerCase());
|
|
94345
|
+
} else if (prefix && prefix !== "/") {
|
|
94346
|
+
const clean = prefix.replace(/^[/:]+|[/:]+$/g, "").toLowerCase();
|
|
94347
|
+
if (clean.length > 0) {
|
|
94348
|
+
tagSet.add(clean);
|
|
94349
|
+
}
|
|
94350
|
+
}
|
|
94351
|
+
for (const part of stem.split(/[-_]/)) {
|
|
94352
|
+
const p = part.trim().toLowerCase();
|
|
94353
|
+
if (p.length > 1 && !tagSet.has(p)) {
|
|
94354
|
+
tagSet.add(p);
|
|
94355
|
+
}
|
|
94356
|
+
}
|
|
94357
|
+
const tags = Array.from(tagSet);
|
|
94308
94358
|
items.push({
|
|
94309
94359
|
name,
|
|
94310
94360
|
description,
|
|
94311
94361
|
category,
|
|
94312
94362
|
argumentHint,
|
|
94363
|
+
tags,
|
|
94313
94364
|
role,
|
|
94314
94365
|
source
|
|
94315
94366
|
});
|
|
@@ -94317,14 +94368,133 @@ function scanMarkdownCommands(dirPath, options = {}) {
|
|
|
94317
94368
|
} catch {}
|
|
94318
94369
|
return items;
|
|
94319
94370
|
}
|
|
94371
|
+
function discoverEnabledClaudePlugins(options = {}) {
|
|
94372
|
+
const { projectRoot = process.cwd(), claudeDir = join30(homedir9(), ".claude") } = options;
|
|
94373
|
+
const userSettingsPath = join30(claudeDir, "settings.json");
|
|
94374
|
+
const projectSettingsPath = join30(projectRoot, ".claude", "settings.json");
|
|
94375
|
+
const installedPath = join30(claudeDir, "plugins", "installed_plugins.json");
|
|
94376
|
+
let userSettings = {};
|
|
94377
|
+
if (existsSync8(userSettingsPath)) {
|
|
94378
|
+
try {
|
|
94379
|
+
userSettings = JSON.parse(readFileSync10(userSettingsPath, "utf-8"));
|
|
94380
|
+
} catch {}
|
|
94381
|
+
}
|
|
94382
|
+
let projectSettings = {};
|
|
94383
|
+
if (existsSync8(projectSettingsPath)) {
|
|
94384
|
+
try {
|
|
94385
|
+
projectSettings = JSON.parse(readFileSync10(projectSettingsPath, "utf-8"));
|
|
94386
|
+
} catch {}
|
|
94387
|
+
}
|
|
94388
|
+
const enabledPlugins = {
|
|
94389
|
+
...userSettings.enabledPlugins ?? {},
|
|
94390
|
+
...projectSettings.enabledPlugins ?? {}
|
|
94391
|
+
};
|
|
94392
|
+
const extraKnownMarketplaces = {
|
|
94393
|
+
...userSettings.extraKnownMarketplaces ?? {},
|
|
94394
|
+
...projectSettings.extraKnownMarketplaces ?? {}
|
|
94395
|
+
};
|
|
94396
|
+
let installedManifest = { plugins: {} };
|
|
94397
|
+
if (existsSync8(installedPath)) {
|
|
94398
|
+
try {
|
|
94399
|
+
installedManifest = JSON.parse(readFileSync10(installedPath, "utf-8"));
|
|
94400
|
+
} catch {}
|
|
94401
|
+
}
|
|
94402
|
+
const installedPlugins = installedManifest.plugins ?? {};
|
|
94403
|
+
const candidateKeys = new Set;
|
|
94404
|
+
for (const [key2, isEnabled] of Object.entries(enabledPlugins)) {
|
|
94405
|
+
if (isEnabled) {
|
|
94406
|
+
candidateKeys.add(key2);
|
|
94407
|
+
}
|
|
94408
|
+
}
|
|
94409
|
+
if (candidateKeys.size === 0) {
|
|
94410
|
+
for (const key2 of Object.keys(installedPlugins)) {
|
|
94411
|
+
if (enabledPlugins[key2] !== false) {
|
|
94412
|
+
candidateKeys.add(key2);
|
|
94413
|
+
}
|
|
94414
|
+
}
|
|
94415
|
+
}
|
|
94416
|
+
const results = [];
|
|
94417
|
+
for (const pluginKey of candidateKeys) {
|
|
94418
|
+
if (enabledPlugins[pluginKey] === false) {
|
|
94419
|
+
continue;
|
|
94420
|
+
}
|
|
94421
|
+
const atIndex = pluginKey.indexOf("@");
|
|
94422
|
+
const pluginName = atIndex !== -1 ? pluginKey.slice(0, atIndex) : pluginKey;
|
|
94423
|
+
const marketplaceName = atIndex !== -1 ? pluginKey.slice(atIndex + 1) : undefined;
|
|
94424
|
+
let resolvedDir = null;
|
|
94425
|
+
const installs = installedPlugins[pluginKey];
|
|
94426
|
+
if (Array.isArray(installs)) {
|
|
94427
|
+
for (const inst of installs) {
|
|
94428
|
+
if (typeof inst.installPath === "string" && existsSync8(inst.installPath)) {
|
|
94429
|
+
resolvedDir = inst.installPath;
|
|
94430
|
+
break;
|
|
94431
|
+
}
|
|
94432
|
+
}
|
|
94433
|
+
}
|
|
94434
|
+
if (!resolvedDir && marketplaceName && extraKnownMarketplaces[marketplaceName]) {
|
|
94435
|
+
const mSrc = extraKnownMarketplaces[marketplaceName]?.source;
|
|
94436
|
+
if (mSrc?.source === "directory" && typeof mSrc.path === "string") {
|
|
94437
|
+
const cand1 = join30(mSrc.path, "plugins", pluginName);
|
|
94438
|
+
const cand2 = join30(mSrc.path, pluginName);
|
|
94439
|
+
if (existsSync8(cand1)) {
|
|
94440
|
+
resolvedDir = cand1;
|
|
94441
|
+
} else if (existsSync8(cand2)) {
|
|
94442
|
+
resolvedDir = cand2;
|
|
94443
|
+
}
|
|
94444
|
+
}
|
|
94445
|
+
}
|
|
94446
|
+
if (!resolvedDir && marketplaceName) {
|
|
94447
|
+
const cacheDir = join30(claudeDir, "plugins", "cache", marketplaceName, pluginName);
|
|
94448
|
+
if (existsSync8(cacheDir)) {
|
|
94449
|
+
try {
|
|
94450
|
+
const entries = readdirSync7(cacheDir, { withFileTypes: true });
|
|
94451
|
+
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
94452
|
+
const lastDir = dirs[dirs.length - 1];
|
|
94453
|
+
if (lastDir) {
|
|
94454
|
+
resolvedDir = join30(cacheDir, lastDir);
|
|
94455
|
+
}
|
|
94456
|
+
} catch {}
|
|
94457
|
+
}
|
|
94458
|
+
}
|
|
94459
|
+
if (!resolvedDir && marketplaceName) {
|
|
94460
|
+
const mpDir = join30(claudeDir, "plugins", "marketplaces", marketplaceName, "plugins", pluginName);
|
|
94461
|
+
if (existsSync8(mpDir)) {
|
|
94462
|
+
resolvedDir = mpDir;
|
|
94463
|
+
}
|
|
94464
|
+
}
|
|
94465
|
+
if (!resolvedDir) {
|
|
94466
|
+
const localPlugin = resolve16(projectRoot, "plugins", pluginName);
|
|
94467
|
+
if (existsSync8(localPlugin)) {
|
|
94468
|
+
resolvedDir = localPlugin;
|
|
94469
|
+
}
|
|
94470
|
+
}
|
|
94471
|
+
let commandsDir;
|
|
94472
|
+
if (resolvedDir) {
|
|
94473
|
+
const candidateCommands = join30(resolvedDir, "commands");
|
|
94474
|
+
if (existsSync8(candidateCommands)) {
|
|
94475
|
+
commandsDir = candidateCommands;
|
|
94476
|
+
}
|
|
94477
|
+
}
|
|
94478
|
+
results.push({
|
|
94479
|
+
id: pluginKey,
|
|
94480
|
+
name: pluginName,
|
|
94481
|
+
marketplace: marketplaceName,
|
|
94482
|
+
installPath: resolvedDir ?? undefined,
|
|
94483
|
+
commandsDir
|
|
94484
|
+
});
|
|
94485
|
+
}
|
|
94486
|
+
return results;
|
|
94487
|
+
}
|
|
94320
94488
|
function generateSlashCommands(options = {}) {
|
|
94321
94489
|
const {
|
|
94322
94490
|
projectRoot = process.cwd(),
|
|
94323
94491
|
includeBuiltin = true,
|
|
94324
94492
|
includePluginSp = true,
|
|
94493
|
+
includeAllPlugins = true,
|
|
94325
94494
|
includeProjectClaude = true,
|
|
94326
94495
|
includeUserClaude = true,
|
|
94327
|
-
includeUserSpur = true
|
|
94496
|
+
includeUserSpur = true,
|
|
94497
|
+
claudeDir
|
|
94328
94498
|
} = options;
|
|
94329
94499
|
const commandMap = new Map;
|
|
94330
94500
|
if (includeBuiltin) {
|
|
@@ -94332,15 +94502,34 @@ function generateSlashCommands(options = {}) {
|
|
|
94332
94502
|
commandMap.set(cmd.name, cmd);
|
|
94333
94503
|
}
|
|
94334
94504
|
}
|
|
94505
|
+
if (includeAllPlugins) {
|
|
94506
|
+
const plugins = discoverEnabledClaudePlugins({ projectRoot, claudeDir });
|
|
94507
|
+
for (const plugin of plugins) {
|
|
94508
|
+
if (plugin.commandsDir) {
|
|
94509
|
+
const pluginCommands = scanMarkdownCommands(plugin.commandsDir, {
|
|
94510
|
+
prefix: `/${plugin.name}:`,
|
|
94511
|
+
source: `plugin:${plugin.name}`,
|
|
94512
|
+
pluginId: plugin.name,
|
|
94513
|
+
defaultCategory: deduceCommandCategory(plugin.name)
|
|
94514
|
+
});
|
|
94515
|
+
for (const cmd of pluginCommands) {
|
|
94516
|
+
commandMap.set(cmd.name, cmd);
|
|
94517
|
+
}
|
|
94518
|
+
}
|
|
94519
|
+
}
|
|
94520
|
+
}
|
|
94335
94521
|
if (includePluginSp) {
|
|
94336
94522
|
const spCommandsDir = findPluginsSpCommandsDir(projectRoot) ?? resolve16(projectRoot, "plugins", "sp", "commands");
|
|
94337
|
-
|
|
94338
|
-
|
|
94339
|
-
|
|
94340
|
-
|
|
94341
|
-
|
|
94342
|
-
|
|
94343
|
-
|
|
94523
|
+
if (existsSync8(spCommandsDir)) {
|
|
94524
|
+
const spCommands = scanMarkdownCommands(spCommandsDir, {
|
|
94525
|
+
prefix: "/sp:",
|
|
94526
|
+
source: "plugin:sp",
|
|
94527
|
+
pluginId: "sp",
|
|
94528
|
+
defaultCategory: "harness"
|
|
94529
|
+
});
|
|
94530
|
+
for (const cmd of spCommands) {
|
|
94531
|
+
commandMap.set(cmd.name, cmd);
|
|
94532
|
+
}
|
|
94344
94533
|
}
|
|
94345
94534
|
}
|
|
94346
94535
|
if (includeProjectClaude) {
|
|
@@ -94368,6 +94557,7 @@ function generateSlashCommands(options = {}) {
|
|
|
94368
94557
|
const userSpurCommands = scanMarkdownCommands(userSpurDir, {
|
|
94369
94558
|
prefix: "/sp:",
|
|
94370
94559
|
source: "spur:user",
|
|
94560
|
+
pluginId: "sp",
|
|
94371
94561
|
defaultCategory: "harness"
|
|
94372
94562
|
});
|
|
94373
94563
|
for (const cmd of userSpurCommands) {
|
|
@@ -94456,90 +94646,114 @@ var init_slash_commands_service = __esm(() => {
|
|
|
94456
94646
|
name: "/help",
|
|
94457
94647
|
description: "View available commands, tools, and usage hints",
|
|
94458
94648
|
category: "sys",
|
|
94649
|
+
argumentHint: "[command]",
|
|
94650
|
+
tags: ["builtin", "sys", "help"],
|
|
94459
94651
|
source: "builtin"
|
|
94460
94652
|
},
|
|
94461
94653
|
{
|
|
94462
94654
|
name: "/clear",
|
|
94463
94655
|
description: "Clear conversation history and reset context window",
|
|
94464
94656
|
category: "sys",
|
|
94657
|
+
tags: ["builtin", "sys", "clear"],
|
|
94465
94658
|
source: "builtin"
|
|
94466
94659
|
},
|
|
94467
94660
|
{
|
|
94468
94661
|
name: "/compact",
|
|
94469
94662
|
description: "Purge execution trace and condense context window",
|
|
94470
94663
|
category: "sys",
|
|
94664
|
+
argumentHint: "[focus]",
|
|
94665
|
+
tags: ["builtin", "sys", "compact", "context"],
|
|
94471
94666
|
source: "builtin"
|
|
94472
94667
|
},
|
|
94473
94668
|
{
|
|
94474
94669
|
name: "/cost",
|
|
94475
94670
|
description: "Inspect token breakdown and USD expenditure",
|
|
94476
94671
|
category: "sys",
|
|
94672
|
+
tags: ["builtin", "sys", "cost", "tokens"],
|
|
94477
94673
|
source: "builtin"
|
|
94478
94674
|
},
|
|
94479
94675
|
{
|
|
94480
94676
|
name: "/doctor",
|
|
94481
94677
|
description: "Run diagnostic health checks on environment and tools",
|
|
94482
94678
|
category: "sys",
|
|
94679
|
+
tags: ["builtin", "sys", "doctor", "health"],
|
|
94483
94680
|
source: "builtin"
|
|
94484
94681
|
},
|
|
94485
94682
|
{
|
|
94486
94683
|
name: "/init",
|
|
94487
94684
|
description: "Initialize project instructions, settings and guidelines",
|
|
94488
94685
|
category: "harness",
|
|
94686
|
+
tags: ["builtin", "harness", "init"],
|
|
94489
94687
|
source: "builtin"
|
|
94490
94688
|
},
|
|
94491
94689
|
{
|
|
94492
94690
|
name: "/review",
|
|
94493
94691
|
description: "Inspect staged git diff, verify test coverage & lint",
|
|
94494
94692
|
category: "git",
|
|
94693
|
+
argumentHint: "[target] [--cached]",
|
|
94694
|
+
tags: ["builtin", "git", "review"],
|
|
94495
94695
|
source: "builtin"
|
|
94496
94696
|
},
|
|
94497
94697
|
{
|
|
94498
94698
|
name: "/commit",
|
|
94499
94699
|
description: "Draft conventional commit message from staged hunks",
|
|
94500
94700
|
category: "git",
|
|
94701
|
+
argumentHint: "[--all] [-m <message>]",
|
|
94702
|
+
tags: ["builtin", "git", "commit"],
|
|
94501
94703
|
source: "builtin"
|
|
94502
94704
|
},
|
|
94503
94705
|
{
|
|
94504
94706
|
name: "/terminal",
|
|
94505
94707
|
description: "Run isolated bash execution in sandbox mirror",
|
|
94506
94708
|
category: "sys",
|
|
94709
|
+
argumentHint: "[command]",
|
|
94710
|
+
tags: ["builtin", "sys", "terminal", "bash"],
|
|
94507
94711
|
source: "builtin"
|
|
94508
94712
|
},
|
|
94509
94713
|
{
|
|
94510
94714
|
name: "/revert",
|
|
94511
94715
|
description: "Undo last agent file changes or restore git stash",
|
|
94512
94716
|
category: "git",
|
|
94717
|
+
argumentHint: "[stash-id | file]",
|
|
94718
|
+
tags: ["builtin", "git", "revert"],
|
|
94513
94719
|
source: "builtin"
|
|
94514
94720
|
},
|
|
94515
94721
|
{
|
|
94516
94722
|
name: "/resume",
|
|
94517
94723
|
description: "Resume paused background agent run",
|
|
94518
94724
|
category: "dev",
|
|
94725
|
+
argumentHint: "[run-id]",
|
|
94726
|
+
tags: ["builtin", "dev", "resume"],
|
|
94519
94727
|
source: "builtin"
|
|
94520
94728
|
},
|
|
94521
94729
|
{
|
|
94522
94730
|
name: "/bug",
|
|
94523
94731
|
description: "Report a bug or issue with diagnostic transcript",
|
|
94524
94732
|
category: "sys",
|
|
94733
|
+
argumentHint: "[description]",
|
|
94734
|
+
tags: ["builtin", "sys", "bug"],
|
|
94525
94735
|
source: "builtin"
|
|
94526
94736
|
},
|
|
94527
94737
|
{
|
|
94528
94738
|
name: "/config",
|
|
94529
94739
|
description: "View or update local/global configuration settings",
|
|
94530
94740
|
category: "sys",
|
|
94741
|
+
argumentHint: "[key] [value]",
|
|
94742
|
+
tags: ["builtin", "sys", "config"],
|
|
94531
94743
|
source: "builtin"
|
|
94532
94744
|
},
|
|
94533
94745
|
{
|
|
94534
94746
|
name: "/login",
|
|
94535
94747
|
description: "Authenticate account and refresh API credentials",
|
|
94536
94748
|
category: "sys",
|
|
94749
|
+
tags: ["builtin", "sys", "login", "auth"],
|
|
94537
94750
|
source: "builtin"
|
|
94538
94751
|
},
|
|
94539
94752
|
{
|
|
94540
94753
|
name: "/logout",
|
|
94541
94754
|
description: "Sign out of current account and remove stored session",
|
|
94542
94755
|
category: "sys",
|
|
94756
|
+
tags: ["builtin", "sys", "logout", "auth"],
|
|
94543
94757
|
source: "builtin"
|
|
94544
94758
|
}
|
|
94545
94759
|
];
|
|
@@ -98424,6 +98638,7 @@ __export(exports_src2, {
|
|
|
98424
98638
|
enqueueHistoryRefresh: () => enqueueHistoryRefresh,
|
|
98425
98639
|
encodeRunListCursor: () => encodeRunListCursor,
|
|
98426
98640
|
drainPendingAgentQuotaUpdates: () => drainPendingAgentQuotaUpdates,
|
|
98641
|
+
discoverEnabledClaudePlugins: () => discoverEnabledClaudePlugins,
|
|
98427
98642
|
deriveVerdict: () => deriveVerdict,
|
|
98428
98643
|
deduceCommandCategory: () => deduceCommandCategory,
|
|
98429
98644
|
decorateWorkflowEvent: () => decorateWorkflowEvent,
|
|
@@ -110305,7 +110520,7 @@ import { createRequire } from "module";
|
|
|
110305
110520
|
var CLI_CONFIG = {
|
|
110306
110521
|
binaryName: "spur",
|
|
110307
110522
|
binaryLabel: "spur",
|
|
110308
|
-
binaryVersion: "0.3.
|
|
110523
|
+
binaryVersion: "0.3.85",
|
|
110309
110524
|
configDir: ".spur",
|
|
110310
110525
|
configFile: ".spur/config.yaml",
|
|
110311
110526
|
databaseFile: ".spur/spur.db"
|
|
@@ -122335,7 +122550,7 @@ function registerSchedulerEntries(scheduler3, ctx, jobs = [], options = {}) {
|
|
|
122335
122550
|
});
|
|
122336
122551
|
for (const job of jobs) {
|
|
122337
122552
|
const schedule = job.cron ?? String(job.intervalMinutes * 60000);
|
|
122338
|
-
const jobPolicy = resolveSchedulerJobTimeoutMs(job.name, env, timeoutMs);
|
|
122553
|
+
const jobPolicy = resolveSchedulerJobTimeoutMs(job.name, env, timeoutMs, job.timeoutMs);
|
|
122339
122554
|
const sweepThresholdMs = jobPolicy === null ? null : jobPolicy + resolveKillGraceMs3(env);
|
|
122340
122555
|
register(schedule, `${SCHEDULER_CUSTOM_JOB}:${job.name}`, async () => {
|
|
122341
122556
|
const queue = await ctx.jobQueue();
|
|
@@ -122666,10 +122881,11 @@ async function startServer(options, deps = defaultDeps) {
|
|
|
122666
122881
|
});
|
|
122667
122882
|
registry3.register(SCHEDULER_CUSTOM_JOB, async (job) => {
|
|
122668
122883
|
await emitQueueJobStarted(ctx, job);
|
|
122884
|
+
const declaredTimeouts = new Map(appRt.config.scheduler.jobs.map((entry) => [entry.name, entry.timeoutMs]));
|
|
122669
122885
|
return handleSchedulerCustomJob({
|
|
122670
122886
|
cwd: ctx.cwd,
|
|
122671
122887
|
executor: childExecutor,
|
|
122672
|
-
resolveTimeoutMs: (name) => resolveSchedulerJobTimeoutMs(name, env, schedulerCustomTimeoutMs),
|
|
122888
|
+
resolveTimeoutMs: (name) => resolveSchedulerJobTimeoutMs(name, env, schedulerCustomTimeoutMs, declaredTimeouts.get(name)),
|
|
122673
122889
|
onDuplicate: (name) => {
|
|
122674
122890
|
ctx.eventBus().emit("scheduler.job.executed", {
|
|
122675
122891
|
name: `${SCHEDULER_CUSTOM_JOB}:${name}`,
|
|
@@ -122678,10 +122894,20 @@ async function startServer(options, deps = defaultDeps) {
|
|
|
122678
122894
|
skipped: true,
|
|
122679
122895
|
reason: `duplicate execution suppressed; ${name} is already running in this process`
|
|
122680
122896
|
});
|
|
122681
|
-
}
|
|
122897
|
+
},
|
|
122898
|
+
onShutdownAbandon: (name) => {
|
|
122899
|
+
ctx.eventBus().emit("scheduler.job.executed", {
|
|
122900
|
+
name: `${SCHEDULER_CUSTOM_JOB}:${name}`,
|
|
122901
|
+
durationMs: 0,
|
|
122902
|
+
severity: "info",
|
|
122903
|
+
skipped: true,
|
|
122904
|
+
reason: `abandoned by server shutdown; the next tick resumes ${name}`
|
|
122905
|
+
});
|
|
122906
|
+
},
|
|
122907
|
+
isShuttingDown: () => shuttingDown
|
|
122682
122908
|
}, job);
|
|
122683
122909
|
});
|
|
122684
|
-
const unlimitedJobNames = appRt.config.scheduler.jobs.filter((job) => resolveSchedulerJobTimeoutMs(job.name, env, schedulerCustomTimeoutMs) === null).map((job) => job.name);
|
|
122910
|
+
const unlimitedJobNames = appRt.config.scheduler.jobs.filter((job) => resolveSchedulerJobTimeoutMs(job.name, env, schedulerCustomTimeoutMs, job.timeoutMs) === null).map((job) => job.name);
|
|
122685
122911
|
const orphanCount = await failOrphanedProcessingJobs(await ctx.getDb(), Date.now(), unlimitedJobNames);
|
|
122686
122912
|
if (orphanCount > 0) {
|
|
122687
122913
|
appRt.logger.warn("Swept orphaned processing jobs at startup", {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as a}from"./BoardApp.yW425dRZ.js";import"./index.De90oHcH.js";export{a as default};
|