clikit-plugin 0.2.45 → 0.2.47
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/AGENTS.md +69 -3
- package/README.md +128 -92
- package/command/commit.md +1 -1
- package/command/create.md +65 -8
- package/command/debug.md +1 -1
- package/command/design.md +183 -43
- package/command/handoff.md +1 -1
- package/command/import-plan.md +2 -2
- package/command/init.md +1 -1
- package/command/issue.md +3 -4
- package/command/pr.md +1 -1
- package/command/research.md +5 -7
- package/command/resume.md +1 -1
- package/command/ship.md +29 -32
- package/command/start.md +38 -27
- package/command/{status-beads.md → status.md} +2 -3
- package/command/verify.md +132 -48
- package/dist/.tsbuildinfo +1 -1
- package/dist/agents/index.d.ts +0 -0
- package/dist/agents/index.d.ts.map +0 -0
- package/dist/beads-context.test.d.ts +2 -0
- package/dist/beads-context.test.d.ts.map +1 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.d.ts.map +0 -0
- package/dist/cli.js +5 -0
- package/dist/cli.test.d.ts +0 -0
- package/dist/cli.test.d.ts.map +0 -0
- package/dist/clikit.schema.json +32 -11
- package/dist/clilog.test.d.ts +0 -0
- package/dist/clilog.test.d.ts.map +0 -0
- package/dist/commands/index.d.ts +0 -0
- package/dist/commands/index.d.ts.map +0 -0
- package/dist/config.d.ts +15 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.test.d.ts +0 -0
- package/dist/config.test.d.ts.map +0 -0
- package/dist/hooks/beads-context.d.ts +2 -0
- package/dist/hooks/beads-context.d.ts.map +1 -1
- package/dist/hooks/empty-message-sanitizer.d.ts +0 -0
- package/dist/hooks/empty-message-sanitizer.d.ts.map +0 -0
- package/dist/hooks/error-logger.d.ts +0 -0
- package/dist/hooks/error-logger.d.ts.map +0 -0
- package/dist/hooks/git-guard.d.ts +0 -0
- package/dist/hooks/git-guard.d.ts.map +0 -0
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/memory-digest.d.ts +1 -0
- package/dist/hooks/memory-digest.d.ts.map +1 -1
- package/dist/hooks/security-check.d.ts +0 -0
- package/dist/hooks/security-check.d.ts.map +0 -0
- package/dist/hooks/subagent-question-blocker.d.ts +0 -0
- package/dist/hooks/subagent-question-blocker.d.ts.map +0 -0
- package/dist/hooks/todo-beads-sync.d.ts +1 -0
- package/dist/hooks/todo-beads-sync.d.ts.map +1 -1
- package/dist/hooks/todo-enforcer.d.ts +1 -1
- package/dist/hooks/todo-enforcer.d.ts.map +1 -1
- package/dist/hooks/truncator.d.ts +0 -0
- package/dist/hooks/truncator.d.ts.map +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +250 -576
- package/dist/skills/index.d.ts +0 -0
- package/dist/skills/index.d.ts.map +0 -0
- package/dist/tools/cass-memory.d.ts +0 -0
- package/dist/tools/cass-memory.d.ts.map +0 -0
- package/dist/tools/context-summary.d.ts +0 -0
- package/dist/tools/context-summary.d.ts.map +0 -0
- package/dist/tools/index.d.ts +0 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/memory-db.d.ts +0 -0
- package/dist/tools/memory-db.d.ts.map +0 -0
- package/dist/tools/memory.d.ts +0 -0
- package/dist/tools/memory.d.ts.map +0 -0
- package/dist/tools/observation.d.ts +0 -0
- package/dist/tools/observation.d.ts.map +0 -0
- package/dist/types.d.ts +0 -0
- package/dist/types.d.ts.map +0 -0
- package/memory/_digest.md +1 -1
- package/memory/_templates/handoff.md +0 -0
- package/memory/_templates/plan.md +35 -0
- package/memory/_templates/prd.md +0 -0
- package/memory/_templates/research.md +0 -0
- package/memory/_templates/review.md +0 -0
- package/memory/_templates/spec.md +12 -0
- package/memory/beads/.gitkeep +0 -0
- package/memory/handoffs/.gitkeep +0 -0
- package/memory/memory.db +0 -0
- package/memory/plans/.gitkeep +0 -0
- package/memory/prds/.gitkeep +0 -0
- package/memory/research/.gitkeep +0 -0
- package/memory/reviews/.gitkeep +0 -0
- package/memory/specs/.gitkeep +0 -0
- package/package.json +4 -4
- package/skill/beads/SKILL.md +42 -43
- package/skill/beads/mcp.json +26 -0
- package/skill/beads/references/api-reference.md +64 -0
- package/skill/chrome-devtools/SKILL.md +22 -23
- package/skill/chrome-devtools/mcp.json +17 -0
- package/skill/chrome-devtools/references/tool-reference.md +63 -0
- package/skill/condition-based-waiting/SKILL.md +28 -66
- package/skill/deep-research/SKILL.md +34 -103
- package/skill/deep-research/mcp.json +21 -0
- package/skill/deep-research/references/lsp-ops.md +44 -0
- package/skill/defense-in-depth/SKILL.md +29 -69
- package/skill/executing-plans/SKILL.md +25 -34
- package/skill/finishing-a-development-branch/SKILL.md +28 -89
- package/skill/playwright/SKILL.md +27 -22
- package/skill/playwright/mcp.json +20 -0
- package/skill/playwright/references/tool-reference.md +64 -0
- package/skill/receiving-code-review/SKILL.md +16 -27
- package/skill/requesting-code-review/SKILL.md +22 -26
- package/skill/ritual-workflow/SKILL.md +22 -82
- package/skill/root-cause-tracing/SKILL.md +30 -54
- package/skill/session-management/SKILL.md +21 -40
- package/skill/source-code-research/SKILL.md +33 -102
- package/skill/source-code-research/mcp.json +13 -0
- package/skill/source-code-research/references/quick-ref.md +65 -0
- package/skill/systematic-debugging/SKILL.md +28 -41
- package/skill/systematic-debugging/references/patterns.md +71 -0
- package/skill/test-driven-development/SKILL.md +16 -40
- package/skill/testing-anti-patterns/SKILL.md +36 -64
- package/skill/testing-anti-patterns/references/decision-matrix.md +55 -0
- package/skill/using-git-worktrees/SKILL.md +27 -103
- package/skill/vercel-react-best-practices/SKILL.md +50 -139
- package/skill/vercel-react-best-practices/references/patterns.md +70 -0
- package/skill/verification-before-completion/SKILL.md +19 -37
- package/skill/writing-plans/SKILL.md +20 -32
- package/skill/writing-skills/SKILL.md +52 -41
- package/skill/writing-skills/references/skill-anatomy.md +210 -0
- package/src/agents/AGENTS.md +48 -18
- package/src/agents/build.md +342 -93
- package/src/agents/explore.md +77 -60
- package/src/agents/index.ts +0 -0
- package/src/agents/oracle.md +154 -64
- package/src/agents/plan.md +275 -110
- package/src/agents/research.md +72 -54
- package/src/agents/review.md +183 -62
- package/src/agents/vision.md +7 -5
- package/command/plan.md +0 -152
- package/command/review-codebase.md +0 -228
- package/command/review.md +0 -135
- package/command/vision.md +0 -210
- package/dist/hooks/swarm-enforcer.d.ts +0 -31
- package/dist/hooks/swarm-enforcer.d.ts.map +0 -1
- package/dist/tools/beads-memory-sync.d.ts +0 -17
- package/dist/tools/beads-memory-sync.d.ts.map +0 -1
- package/dist/tools/quick-research.d.ts +0 -16
- package/dist/tools/quick-research.d.ts.map +0 -1
- package/dist/tools/swarm.d.ts +0 -57
- package/dist/tools/swarm.d.ts.map +0 -1
- package/skill/accessibility-audit/SKILL.md +0 -115
- package/skill/beads-bridge/SKILL.md +0 -45
- package/skill/brainstorming/SKILL.md +0 -41
- package/skill/cass-village/SKILL.md +0 -217
- package/skill/cloudflare/SKILL.md +0 -96
- package/skill/design-system-audit/SKILL.md +0 -136
- package/skill/development-lifecycle/SKILL.md +0 -58
- package/skill/dispatching-parallel-agents/SKILL.md +0 -94
- package/skill/figma/SKILL.md +0 -34
- package/skill/frontend-aesthetics/SKILL.md +0 -63
- package/skill/gemini-large-context/SKILL.md +0 -80
- package/skill/mockup-to-code/SKILL.md +0 -98
- package/skill/mqdh/SKILL.md +0 -54
- package/skill/notebooklm/SKILL.md +0 -71
- package/skill/playwriter/SKILL.md +0 -56
- package/skill/polar/SKILL.md +0 -39
- package/skill/resend/SKILL.md +0 -85
- package/skill/sharing-skills/SKILL.md +0 -50
- package/skill/subagent-driven-development/SKILL.md +0 -69
- package/skill/supabase/SKILL.md +0 -80
- package/skill/supabase-postgres-best-practices/SKILL.md +0 -168
- package/skill/swarm-coordination/SKILL.md +0 -54
- package/skill/testing-skills-with-subagents/SKILL.md +0 -102
- package/skill/ui-ux-research/SKILL.md +0 -93
- package/skill/v0/SKILL.md +0 -67
- package/skill/v1-run/SKILL.md +0 -85
- package/skill/visual-analysis/SKILL.md +0 -113
package/dist/index.js
CHANGED
|
@@ -16196,12 +16196,21 @@ var DEFAULT_CONFIG = {
|
|
|
16196
16196
|
commands: {},
|
|
16197
16197
|
skills: {},
|
|
16198
16198
|
lsp: {},
|
|
16199
|
+
workflow: {
|
|
16200
|
+
mode: "compressed",
|
|
16201
|
+
active_roles: ["build", "plan", "review", "coordinator"],
|
|
16202
|
+
use_packets: true,
|
|
16203
|
+
embed_verify_in_start: true,
|
|
16204
|
+
verify_is_audit: true,
|
|
16205
|
+
subagent_call_budget: 2
|
|
16206
|
+
},
|
|
16199
16207
|
hooks: {
|
|
16200
16208
|
session_logging: false,
|
|
16201
16209
|
tool_logging: false,
|
|
16202
16210
|
todo_enforcer: {
|
|
16203
16211
|
enabled: true,
|
|
16204
|
-
warn_on_incomplete:
|
|
16212
|
+
warn_on_incomplete: false,
|
|
16213
|
+
beads_authoritative: true
|
|
16205
16214
|
},
|
|
16206
16215
|
empty_message_sanitizer: {
|
|
16207
16216
|
enabled: true,
|
|
@@ -16225,25 +16234,22 @@ var DEFAULT_CONFIG = {
|
|
|
16225
16234
|
max_output_lines: 500,
|
|
16226
16235
|
preserve_head_lines: 50,
|
|
16227
16236
|
preserve_tail_lines: 50,
|
|
16228
|
-
|
|
16229
|
-
},
|
|
16230
|
-
swarm_enforcer: {
|
|
16231
|
-
enabled: true,
|
|
16232
|
-
strict_file_locking: true,
|
|
16233
|
-
block_unreserved_edits: false,
|
|
16237
|
+
packet_friendly: true,
|
|
16234
16238
|
log: false
|
|
16235
16239
|
},
|
|
16236
16240
|
memory_digest: {
|
|
16237
16241
|
enabled: true,
|
|
16238
|
-
max_per_type:
|
|
16242
|
+
max_per_type: 5,
|
|
16239
16243
|
include_types: ["decision", "learning", "blocker", "progress", "handoff"],
|
|
16240
|
-
index_highlights_per_type:
|
|
16244
|
+
index_highlights_per_type: 1,
|
|
16241
16245
|
write_topic_files: true,
|
|
16246
|
+
compact_mode: true,
|
|
16242
16247
|
log: false
|
|
16243
16248
|
},
|
|
16244
16249
|
todo_beads_sync: {
|
|
16245
|
-
enabled:
|
|
16250
|
+
enabled: false,
|
|
16246
16251
|
close_missing: true,
|
|
16252
|
+
mode: "disabled",
|
|
16247
16253
|
log: false
|
|
16248
16254
|
},
|
|
16249
16255
|
cass_memory: {
|
|
@@ -16256,8 +16262,10 @@ var DEFAULT_CONFIG = {
|
|
|
16256
16262
|
},
|
|
16257
16263
|
beads_context: {
|
|
16258
16264
|
enabled: true,
|
|
16259
|
-
max_issues:
|
|
16265
|
+
max_issues: 8,
|
|
16260
16266
|
include_closed: false,
|
|
16267
|
+
active_only: true,
|
|
16268
|
+
ready_limit: 3,
|
|
16261
16269
|
log: false
|
|
16262
16270
|
}
|
|
16263
16271
|
}
|
|
@@ -16550,7 +16558,7 @@ function checkTodoCompletion(todos) {
|
|
|
16550
16558
|
inProgress
|
|
16551
16559
|
};
|
|
16552
16560
|
}
|
|
16553
|
-
function formatIncompleteWarning(result, sessionId) {
|
|
16561
|
+
function formatIncompleteWarning(result, sessionId, beadsAuthoritative) {
|
|
16554
16562
|
const safeResult = normalizeTodoResult(result);
|
|
16555
16563
|
const lines = [];
|
|
16556
16564
|
if (sessionId) {
|
|
@@ -16567,7 +16575,7 @@ function formatIncompleteWarning(result, sessionId) {
|
|
|
16567
16575
|
safeResult.incomplete.forEach((t) => lines.push(` - [${t.id}] ${t.content}`));
|
|
16568
16576
|
}
|
|
16569
16577
|
lines.push("");
|
|
16570
|
-
lines.push(" Complete all todos before finishing.");
|
|
16578
|
+
lines.push(beadsAuthoritative ? " Todos are informational only here \u2014 update/close the active Beads issue instead." : " Complete all todos before finishing.");
|
|
16571
16579
|
return lines.join(`
|
|
16572
16580
|
`);
|
|
16573
16581
|
}
|
|
@@ -16890,90 +16898,9 @@ function formatTruncationLog(result) {
|
|
|
16890
16898
|
const saved = result.originalLength - result.truncatedLength;
|
|
16891
16899
|
return `[CliKit:truncator] Truncated output: ${result.originalLines} \u2192 ${result.truncatedLines} lines, saved ${(saved / 1024).toFixed(1)}KB`;
|
|
16892
16900
|
}
|
|
16893
|
-
// src/hooks/swarm-enforcer.ts
|
|
16894
|
-
import * as path6 from "path";
|
|
16895
|
-
function isFileInScope(filePath, scope) {
|
|
16896
|
-
if (typeof filePath !== "string")
|
|
16897
|
-
return false;
|
|
16898
|
-
const normalizedPath = path6.resolve(filePath);
|
|
16899
|
-
for (const reserved of scope.reservedFiles) {
|
|
16900
|
-
const normalizedReserved = path6.resolve(reserved);
|
|
16901
|
-
if (normalizedPath === normalizedReserved) {
|
|
16902
|
-
return true;
|
|
16903
|
-
}
|
|
16904
|
-
}
|
|
16905
|
-
if (scope.allowedPatterns) {
|
|
16906
|
-
for (const pattern of scope.allowedPatterns) {
|
|
16907
|
-
if (normalizedPath.includes(pattern) || normalizedPath.startsWith(path6.resolve(pattern))) {
|
|
16908
|
-
return true;
|
|
16909
|
-
}
|
|
16910
|
-
}
|
|
16911
|
-
}
|
|
16912
|
-
return false;
|
|
16913
|
-
}
|
|
16914
|
-
function checkEditPermission(filePath, scope, config2) {
|
|
16915
|
-
if (!scope) {
|
|
16916
|
-
return { allowed: true };
|
|
16917
|
-
}
|
|
16918
|
-
if (config2?.strict_file_locking === false) {
|
|
16919
|
-
return { allowed: true };
|
|
16920
|
-
}
|
|
16921
|
-
if (typeof filePath !== "string") {
|
|
16922
|
-
return { allowed: false, reason: "Invalid file path" };
|
|
16923
|
-
}
|
|
16924
|
-
if (isFileInScope(filePath, scope)) {
|
|
16925
|
-
return { allowed: true, file: filePath };
|
|
16926
|
-
}
|
|
16927
|
-
return {
|
|
16928
|
-
allowed: false,
|
|
16929
|
-
file: filePath,
|
|
16930
|
-
reason: `File is not in task scope for task ${scope.taskId}`,
|
|
16931
|
-
suggestion: `Reserve the file first using beads-village reserve, or ask the lead agent to reassign.`
|
|
16932
|
-
};
|
|
16933
|
-
}
|
|
16934
|
-
function extractFileFromToolInput(toolName, input) {
|
|
16935
|
-
if (typeof toolName !== "string")
|
|
16936
|
-
return;
|
|
16937
|
-
switch (toolName.toLowerCase()) {
|
|
16938
|
-
case "edit":
|
|
16939
|
-
case "write":
|
|
16940
|
-
case "read":
|
|
16941
|
-
return input.filePath;
|
|
16942
|
-
case "bash": {
|
|
16943
|
-
const cmd = input.command;
|
|
16944
|
-
if (!cmd)
|
|
16945
|
-
return;
|
|
16946
|
-
const writePatterns = [
|
|
16947
|
-
/>\s*["']?([^\s"'|&;]+)/,
|
|
16948
|
-
/tee\s+["']?([^\s"'|&;]+)/,
|
|
16949
|
-
/mv\s+\S+\s+["']?([^\s"'|&;]+)/,
|
|
16950
|
-
/cp\s+\S+\s+["']?([^\s"'|&;]+)/
|
|
16951
|
-
];
|
|
16952
|
-
for (const pattern of writePatterns) {
|
|
16953
|
-
const match = cmd.match(pattern);
|
|
16954
|
-
if (match)
|
|
16955
|
-
return match[1];
|
|
16956
|
-
}
|
|
16957
|
-
return;
|
|
16958
|
-
}
|
|
16959
|
-
default:
|
|
16960
|
-
return;
|
|
16961
|
-
}
|
|
16962
|
-
}
|
|
16963
|
-
function formatEnforcementWarning(result) {
|
|
16964
|
-
if (result.allowed)
|
|
16965
|
-
return "";
|
|
16966
|
-
const lines = [`[CliKit:swarm-enforcer] BLOCKED edit to ${result.file}`];
|
|
16967
|
-
if (result.reason)
|
|
16968
|
-
lines.push(` Reason: ${result.reason}`);
|
|
16969
|
-
if (result.suggestion)
|
|
16970
|
-
lines.push(` Suggestion: ${result.suggestion}`);
|
|
16971
|
-
return lines.join(`
|
|
16972
|
-
`);
|
|
16973
|
-
}
|
|
16974
16901
|
// src/hooks/memory-digest.ts
|
|
16975
16902
|
import * as fs6 from "fs";
|
|
16976
|
-
import * as
|
|
16903
|
+
import * as path6 from "path";
|
|
16977
16904
|
import { Database } from "bun:sqlite";
|
|
16978
16905
|
function parseJsonArray(value) {
|
|
16979
16906
|
if (typeof value !== "string" || !value.trim())
|
|
@@ -16993,7 +16920,7 @@ function formatDate(iso) {
|
|
|
16993
16920
|
}
|
|
16994
16921
|
}
|
|
16995
16922
|
function writeTopicFile(memoryDir, type, heading, rows) {
|
|
16996
|
-
const topicPath =
|
|
16923
|
+
const topicPath = path6.join(memoryDir, `${type}.md`);
|
|
16997
16924
|
const lines = [];
|
|
16998
16925
|
lines.push(`# ${heading}`);
|
|
16999
16926
|
lines.push("");
|
|
@@ -17041,13 +16968,14 @@ function generateMemoryDigest(projectDir, config2) {
|
|
|
17041
16968
|
const result = { written: false, path: "", counts: {} };
|
|
17042
16969
|
if (typeof projectDir !== "string" || !projectDir)
|
|
17043
16970
|
return result;
|
|
17044
|
-
const memoryDir =
|
|
17045
|
-
const dbPath =
|
|
16971
|
+
const memoryDir = path6.join(projectDir, ".opencode", "memory");
|
|
16972
|
+
const dbPath = path6.join(memoryDir, "memory.db");
|
|
17046
16973
|
if (!fs6.existsSync(dbPath)) {
|
|
17047
16974
|
return result;
|
|
17048
16975
|
}
|
|
17049
|
-
const
|
|
17050
|
-
const
|
|
16976
|
+
const compactMode = config2?.compact_mode !== false;
|
|
16977
|
+
const maxPerType = config2?.max_per_type ?? (compactMode ? 5 : 10);
|
|
16978
|
+
const indexHighlightsPerType = config2?.index_highlights_per_type ?? (compactMode ? 1 : 2);
|
|
17051
16979
|
const writeTopicFiles = config2?.write_topic_files !== false;
|
|
17052
16980
|
const includeTypes = config2?.include_types ?? [
|
|
17053
16981
|
"decision",
|
|
@@ -17091,7 +17019,8 @@ function generateMemoryDigest(projectDir, config2) {
|
|
|
17091
17019
|
const date5 = formatDate(row.created_at);
|
|
17092
17020
|
const headline = row.narrative.split(`
|
|
17093
17021
|
`)[0];
|
|
17094
|
-
|
|
17022
|
+
const beadNote = row.bead_id ? ` [${row.bead_id}]` : "";
|
|
17023
|
+
sections.push(`- ${date5}${beadNote}: ${headline}`);
|
|
17095
17024
|
}
|
|
17096
17025
|
sections.push("");
|
|
17097
17026
|
if (writeTopicFiles) {
|
|
@@ -17106,7 +17035,7 @@ function generateMemoryDigest(projectDir, config2) {
|
|
|
17106
17035
|
sections.push("*No observations found in memory database.*");
|
|
17107
17036
|
sections.push("");
|
|
17108
17037
|
}
|
|
17109
|
-
const digestPath =
|
|
17038
|
+
const digestPath = path6.join(memoryDir, "_digest.md");
|
|
17110
17039
|
const content = sections.join(`
|
|
17111
17040
|
`);
|
|
17112
17041
|
try {
|
|
@@ -17128,7 +17057,7 @@ function formatDigestLog(result) {
|
|
|
17128
17057
|
}
|
|
17129
17058
|
// src/hooks/todo-beads-sync.ts
|
|
17130
17059
|
import * as fs7 from "fs";
|
|
17131
|
-
import * as
|
|
17060
|
+
import * as path7 from "path";
|
|
17132
17061
|
import { Database as Database2 } from "bun:sqlite";
|
|
17133
17062
|
import { execFile } from "child_process";
|
|
17134
17063
|
import { promisify } from "util";
|
|
@@ -17272,7 +17201,18 @@ function syncTodosToBeadsAttempt(beadsDbPath, sessionID, todos, config2) {
|
|
|
17272
17201
|
}
|
|
17273
17202
|
}
|
|
17274
17203
|
function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
|
|
17275
|
-
|
|
17204
|
+
if (config2?.mode === "disabled" || config2?.enabled === false) {
|
|
17205
|
+
return {
|
|
17206
|
+
synced: false,
|
|
17207
|
+
sessionID,
|
|
17208
|
+
totalTodos: todos.length,
|
|
17209
|
+
created: 0,
|
|
17210
|
+
updated: 0,
|
|
17211
|
+
closed: 0,
|
|
17212
|
+
skippedReason: "Todo sync disabled; Beads is authoritative"
|
|
17213
|
+
};
|
|
17214
|
+
}
|
|
17215
|
+
const beadsDbPath = path7.join(projectDirectory, ".beads", "beads.db");
|
|
17276
17216
|
if (!fs7.existsSync(beadsDbPath)) {
|
|
17277
17217
|
return {
|
|
17278
17218
|
synced: false,
|
|
@@ -17303,7 +17243,7 @@ function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
|
|
|
17303
17243
|
throw lastError instanceof Error ? lastError : new Error("Todo-Beads sync failed after retries");
|
|
17304
17244
|
}
|
|
17305
17245
|
function flushBeadsJsonl(projectDirectory, result) {
|
|
17306
|
-
const jsonlPath =
|
|
17246
|
+
const jsonlPath = path7.join(projectDirectory, ".beads", "issues.jsonl");
|
|
17307
17247
|
execFileAsync("bd", ["export", "--force", "-o", jsonlPath], {
|
|
17308
17248
|
cwd: projectDirectory,
|
|
17309
17249
|
timeout: 5000
|
|
@@ -17321,7 +17261,7 @@ function formatTodoBeadsSyncLog(result) {
|
|
|
17321
17261
|
}
|
|
17322
17262
|
// src/hooks/beads-context.ts
|
|
17323
17263
|
import * as fs8 from "fs";
|
|
17324
|
-
import * as
|
|
17264
|
+
import * as path8 from "path";
|
|
17325
17265
|
import { Database as Database3 } from "bun:sqlite";
|
|
17326
17266
|
var BEADS_CONTEXT_BUSY_TIMEOUT_MS = 2000;
|
|
17327
17267
|
var PRIORITY_LABELS = {
|
|
@@ -17337,7 +17277,7 @@ var STATUS_ICONS = {
|
|
|
17337
17277
|
closed: "\u2713"
|
|
17338
17278
|
};
|
|
17339
17279
|
function openBeadsDbReadonly(projectDirectory) {
|
|
17340
|
-
const beadsDbPath =
|
|
17280
|
+
const beadsDbPath = path8.join(projectDirectory, ".beads", "beads.db");
|
|
17341
17281
|
if (!fs8.existsSync(beadsDbPath)) {
|
|
17342
17282
|
return null;
|
|
17343
17283
|
}
|
|
@@ -17349,6 +17289,67 @@ function openBeadsDbReadonly(projectDirectory) {
|
|
|
17349
17289
|
return null;
|
|
17350
17290
|
}
|
|
17351
17291
|
}
|
|
17292
|
+
function formatIssueLine(issue2) {
|
|
17293
|
+
const icon = STATUS_ICONS[issue2.status] ?? "?";
|
|
17294
|
+
const priority = PRIORITY_LABELS[issue2.priority] ?? `p${issue2.priority}`;
|
|
17295
|
+
const assignee = issue2.assignee ? ` @${issue2.assignee}` : "";
|
|
17296
|
+
return `- ${icon} \`${issue2.id}\` **${issue2.title}** (${priority}${assignee})`;
|
|
17297
|
+
}
|
|
17298
|
+
function formatCompressedBeadsSnapshot(issues, config2) {
|
|
17299
|
+
if (issues.length === 0) {
|
|
17300
|
+
return null;
|
|
17301
|
+
}
|
|
17302
|
+
const inProgress = issues.filter((issue2) => issue2.status === "in_progress");
|
|
17303
|
+
const ready = issues.filter((issue2) => issue2.status === "open");
|
|
17304
|
+
const includeClosed = config2?.include_closed === true;
|
|
17305
|
+
const closed = includeClosed ? issues.filter((issue2) => issue2.status === "closed") : [];
|
|
17306
|
+
const readyLimit = config2?.ready_limit ?? 3;
|
|
17307
|
+
const activeOnly = config2?.active_only !== false;
|
|
17308
|
+
const lines = [
|
|
17309
|
+
"## Beads Task State",
|
|
17310
|
+
"",
|
|
17311
|
+
"Beads is the live execution source of truth. Prefer the active issue and its direct dependencies.",
|
|
17312
|
+
""
|
|
17313
|
+
];
|
|
17314
|
+
if (inProgress.length > 0) {
|
|
17315
|
+
lines.push("### Active Issue");
|
|
17316
|
+
lines.push(formatIssueLine(inProgress[0]));
|
|
17317
|
+
if (inProgress.length > 1) {
|
|
17318
|
+
lines.push(`- +${inProgress.length - 1} additional in-progress issue(s)`);
|
|
17319
|
+
}
|
|
17320
|
+
lines.push("");
|
|
17321
|
+
}
|
|
17322
|
+
if (!activeOnly && ready.length > 0) {
|
|
17323
|
+
lines.push("### Ready Queue");
|
|
17324
|
+
for (const issue2 of ready.slice(0, readyLimit)) {
|
|
17325
|
+
lines.push(formatIssueLine(issue2));
|
|
17326
|
+
}
|
|
17327
|
+
if (ready.length > readyLimit) {
|
|
17328
|
+
lines.push(`- +${ready.length - readyLimit} more ready issue(s)`);
|
|
17329
|
+
}
|
|
17330
|
+
lines.push("");
|
|
17331
|
+
} else if (activeOnly && ready.length > 0 && inProgress.length === 0) {
|
|
17332
|
+
lines.push("### Ready Queue (fallback)");
|
|
17333
|
+
for (const issue2 of ready.slice(0, readyLimit)) {
|
|
17334
|
+
lines.push(formatIssueLine(issue2));
|
|
17335
|
+
}
|
|
17336
|
+
if (ready.length > readyLimit) {
|
|
17337
|
+
lines.push(`- +${ready.length - readyLimit} more ready issue(s)`);
|
|
17338
|
+
}
|
|
17339
|
+
lines.push("");
|
|
17340
|
+
} else if (activeOnly && ready.length > 0) {
|
|
17341
|
+
lines.push(`Ready queue hidden (active_only=true, ${ready.length} ready issue(s) available).`);
|
|
17342
|
+
lines.push("");
|
|
17343
|
+
}
|
|
17344
|
+
if (closed.length > 0) {
|
|
17345
|
+
lines.push(`Recently closed available on demand: ${closed.length}`);
|
|
17346
|
+
lines.push("");
|
|
17347
|
+
}
|
|
17348
|
+
lines.push("Use `mcp__beads_village__show({id})` for full details.");
|
|
17349
|
+
lines.push("Use `mcp__beads_village__claim()` only when starting the next packet.");
|
|
17350
|
+
return lines.join(`
|
|
17351
|
+
`);
|
|
17352
|
+
}
|
|
17352
17353
|
function getBeadsSnapshot(projectDirectory, config2) {
|
|
17353
17354
|
const db = openBeadsDbReadonly(projectDirectory);
|
|
17354
17355
|
if (!db) {
|
|
@@ -17371,55 +17372,16 @@ function getBeadsSnapshot(projectDirectory, config2) {
|
|
|
17371
17372
|
if (issues.length === 0) {
|
|
17372
17373
|
return null;
|
|
17373
17374
|
}
|
|
17374
|
-
|
|
17375
|
-
|
|
17376
|
-
|
|
17377
|
-
}
|
|
17378
|
-
const statusSummary = Object.entries(countByStatus).map(([status, count]) => `${status}: ${count}`).join(", ");
|
|
17379
|
-
const lines = [
|
|
17380
|
-
`## Active Beads Issues (${statusSummary})`,
|
|
17381
|
-
""
|
|
17382
|
-
];
|
|
17383
|
-
const inProgress = issues.filter((i) => i.status === "in_progress");
|
|
17384
|
-
const open = issues.filter((i) => i.status === "open");
|
|
17385
|
-
const closed = issues.filter((i) => i.status === "closed");
|
|
17386
|
-
if (inProgress.length > 0) {
|
|
17387
|
-
lines.push("### In Progress");
|
|
17388
|
-
for (const issue2 of inProgress) {
|
|
17389
|
-
lines.push(formatIssueLine(issue2));
|
|
17390
|
-
}
|
|
17391
|
-
lines.push("");
|
|
17392
|
-
}
|
|
17393
|
-
if (open.length > 0) {
|
|
17394
|
-
lines.push("### Ready");
|
|
17395
|
-
for (const issue2 of open) {
|
|
17396
|
-
lines.push(formatIssueLine(issue2));
|
|
17397
|
-
}
|
|
17398
|
-
lines.push("");
|
|
17399
|
-
}
|
|
17400
|
-
if (closed.length > 0 && includeClosed) {
|
|
17401
|
-
lines.push("### Recently Closed");
|
|
17402
|
-
for (const issue2 of closed) {
|
|
17403
|
-
lines.push(formatIssueLine(issue2));
|
|
17404
|
-
}
|
|
17405
|
-
lines.push("");
|
|
17406
|
-
}
|
|
17407
|
-
lines.push("Use `mcp__beads_village__show({id})` to see full issue details.");
|
|
17408
|
-
lines.push("Use `mcp__beads_village__claim()` to pick up the next ready task.");
|
|
17409
|
-
return lines.join(`
|
|
17410
|
-
`);
|
|
17375
|
+
return formatCompressedBeadsSnapshot(issues, {
|
|
17376
|
+
...config2,
|
|
17377
|
+
include_closed: includeClosed
|
|
17378
|
+
});
|
|
17411
17379
|
} catch {
|
|
17412
17380
|
return null;
|
|
17413
17381
|
} finally {
|
|
17414
17382
|
db.close();
|
|
17415
17383
|
}
|
|
17416
17384
|
}
|
|
17417
|
-
function formatIssueLine(issue2) {
|
|
17418
|
-
const icon = STATUS_ICONS[issue2.status] ?? "?";
|
|
17419
|
-
const priority = PRIORITY_LABELS[issue2.priority] ?? `p${issue2.priority}`;
|
|
17420
|
-
const assignee = issue2.assignee ? ` @${issue2.assignee}` : "";
|
|
17421
|
-
return `- ${icon} \`${issue2.id}\` **${issue2.title}** (${priority}${assignee})`;
|
|
17422
|
-
}
|
|
17423
17385
|
function getBeadsCompactionContext(projectDirectory, config2) {
|
|
17424
17386
|
const snapshot = getBeadsSnapshot(projectDirectory, {
|
|
17425
17387
|
...config2,
|
|
@@ -17432,8 +17394,8 @@ function getBeadsCompactionContext(projectDirectory, config2) {
|
|
|
17432
17394
|
return [
|
|
17433
17395
|
"## Beads Task State (Source of Truth)",
|
|
17434
17396
|
"",
|
|
17435
|
-
"
|
|
17436
|
-
"
|
|
17397
|
+
"Preserve active Beads task state across compaction. Prefer the active issue and direct packet scope.",
|
|
17398
|
+
"OpenCode todos are informational only when Beads state is available.",
|
|
17437
17399
|
"",
|
|
17438
17400
|
snapshot
|
|
17439
17401
|
].join(`
|
|
@@ -17445,11 +17407,11 @@ import { promisify as promisify2 } from "util";
|
|
|
17445
17407
|
|
|
17446
17408
|
// src/tools/memory-db.ts
|
|
17447
17409
|
import * as fs9 from "fs";
|
|
17448
|
-
import * as
|
|
17410
|
+
import * as path9 from "path";
|
|
17449
17411
|
import { Database as Database4 } from "bun:sqlite";
|
|
17450
17412
|
function getMemoryPaths(projectDir = process.cwd()) {
|
|
17451
|
-
const memoryDir =
|
|
17452
|
-
const memoryDbPath =
|
|
17413
|
+
const memoryDir = path9.join(projectDir, ".opencode", "memory");
|
|
17414
|
+
const memoryDbPath = path9.join(memoryDir, "memory.db");
|
|
17453
17415
|
return { memoryDir, memoryDbPath };
|
|
17454
17416
|
}
|
|
17455
17417
|
function ensureObservationSchema(db) {
|
|
@@ -17774,185 +17736,6 @@ async function cassMemoryReflect(params = {}) {
|
|
|
17774
17736
|
return embeddedReflect(p);
|
|
17775
17737
|
}
|
|
17776
17738
|
|
|
17777
|
-
// src/tools/swarm.ts
|
|
17778
|
-
var swarmState = {
|
|
17779
|
-
planId: null,
|
|
17780
|
-
tasks: new Map,
|
|
17781
|
-
parallelism: 3
|
|
17782
|
-
};
|
|
17783
|
-
function swarm(params) {
|
|
17784
|
-
if (!params || typeof params !== "object") {
|
|
17785
|
-
return { planId: "none", tasks: [], parallelism: 3, estimatedTime: "0m" };
|
|
17786
|
-
}
|
|
17787
|
-
const p = params;
|
|
17788
|
-
switch (p.operation) {
|
|
17789
|
-
case "plan":
|
|
17790
|
-
return swarmPlan(p);
|
|
17791
|
-
case "monitor":
|
|
17792
|
-
return swarmMonitor(p);
|
|
17793
|
-
case "delegate":
|
|
17794
|
-
return swarmDelegate(p);
|
|
17795
|
-
case "abort":
|
|
17796
|
-
return swarmAbort(p);
|
|
17797
|
-
default:
|
|
17798
|
-
return { planId: "none", tasks: [], parallelism: 3, estimatedTime: "0m" };
|
|
17799
|
-
}
|
|
17800
|
-
}
|
|
17801
|
-
function swarmPlan(params) {
|
|
17802
|
-
const planId = `swarm-${Date.now()}`;
|
|
17803
|
-
swarmState.planId = planId;
|
|
17804
|
-
swarmState.tasks.clear();
|
|
17805
|
-
swarmState.parallelism = params.parallelism || 3;
|
|
17806
|
-
for (const task of params.tasks) {
|
|
17807
|
-
swarmState.tasks.set(task.id, { ...task, status: task.status || "pending" });
|
|
17808
|
-
}
|
|
17809
|
-
const completedDeps = findReadyTasks();
|
|
17810
|
-
for (const taskId of completedDeps) {
|
|
17811
|
-
const task = swarmState.tasks.get(taskId);
|
|
17812
|
-
if (task && task.status === "pending") {
|
|
17813
|
-
task.status = "in_progress";
|
|
17814
|
-
}
|
|
17815
|
-
}
|
|
17816
|
-
return {
|
|
17817
|
-
planId,
|
|
17818
|
-
tasks: Array.from(swarmState.tasks.values()),
|
|
17819
|
-
parallelism: swarmState.parallelism,
|
|
17820
|
-
estimatedTime: estimateTime(params.tasks)
|
|
17821
|
-
};
|
|
17822
|
-
}
|
|
17823
|
-
function swarmMonitor(params) {
|
|
17824
|
-
const tasks = Array.from(swarmState.tasks.values());
|
|
17825
|
-
if (params.taskId) {
|
|
17826
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
17827
|
-
if (!task) {
|
|
17828
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
17829
|
-
}
|
|
17830
|
-
}
|
|
17831
|
-
return {
|
|
17832
|
-
planId: swarmState.planId || "none",
|
|
17833
|
-
totalTasks: tasks.length,
|
|
17834
|
-
completed: tasks.filter((t) => t.status === "completed").length,
|
|
17835
|
-
inProgress: tasks.filter((t) => t.status === "in_progress").length,
|
|
17836
|
-
pending: tasks.filter((t) => t.status === "pending").length,
|
|
17837
|
-
failed: tasks.filter((t) => t.status === "failed").length,
|
|
17838
|
-
tasks
|
|
17839
|
-
};
|
|
17840
|
-
}
|
|
17841
|
-
function swarmDelegate(params) {
|
|
17842
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
17843
|
-
if (!task) {
|
|
17844
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
17845
|
-
}
|
|
17846
|
-
task.agentRole = params.agentRole;
|
|
17847
|
-
task.status = "in_progress";
|
|
17848
|
-
return {
|
|
17849
|
-
taskId: params.taskId,
|
|
17850
|
-
delegatedTo: `@${params.agentRole}`,
|
|
17851
|
-
status: "delegated"
|
|
17852
|
-
};
|
|
17853
|
-
}
|
|
17854
|
-
function swarmAbort(params) {
|
|
17855
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
17856
|
-
if (!task) {
|
|
17857
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
17858
|
-
}
|
|
17859
|
-
task.status = "failed";
|
|
17860
|
-
return {
|
|
17861
|
-
taskId: params.taskId,
|
|
17862
|
-
aborted: true,
|
|
17863
|
-
reason: params.reason
|
|
17864
|
-
};
|
|
17865
|
-
}
|
|
17866
|
-
function findReadyTasks() {
|
|
17867
|
-
const ready = [];
|
|
17868
|
-
for (const [id, task] of swarmState.tasks) {
|
|
17869
|
-
if (task.status !== "pending")
|
|
17870
|
-
continue;
|
|
17871
|
-
const deps = task.dependencies || [];
|
|
17872
|
-
const allDepsComplete = deps.every((depId) => {
|
|
17873
|
-
const dep = swarmState.tasks.get(depId);
|
|
17874
|
-
return dep && dep.status === "completed";
|
|
17875
|
-
});
|
|
17876
|
-
if (allDepsComplete) {
|
|
17877
|
-
ready.push(id);
|
|
17878
|
-
}
|
|
17879
|
-
}
|
|
17880
|
-
return ready;
|
|
17881
|
-
}
|
|
17882
|
-
function estimateTime(tasks) {
|
|
17883
|
-
const totalTasks = tasks.length;
|
|
17884
|
-
const parallelism = swarmState.parallelism;
|
|
17885
|
-
const avgTaskTime = 5;
|
|
17886
|
-
const batches = Math.ceil(totalTasks / parallelism);
|
|
17887
|
-
const totalMinutes = batches * avgTaskTime;
|
|
17888
|
-
if (totalMinutes < 60) {
|
|
17889
|
-
return `${totalMinutes} minutes`;
|
|
17890
|
-
} else {
|
|
17891
|
-
const hours = Math.floor(totalMinutes / 60);
|
|
17892
|
-
const mins = totalMinutes % 60;
|
|
17893
|
-
return `${hours}h ${mins}m`;
|
|
17894
|
-
}
|
|
17895
|
-
}
|
|
17896
|
-
|
|
17897
|
-
// src/tools/quick-research.ts
|
|
17898
|
-
function quickResearch(params) {
|
|
17899
|
-
if (!params || typeof params !== "object") {
|
|
17900
|
-
return {
|
|
17901
|
-
query: "",
|
|
17902
|
-
suggestion: "Invalid params provided"
|
|
17903
|
-
};
|
|
17904
|
-
}
|
|
17905
|
-
const p = params;
|
|
17906
|
-
if (!p.query || typeof p.query !== "string") {
|
|
17907
|
-
return {
|
|
17908
|
-
query: "",
|
|
17909
|
-
suggestion: "Missing query parameter"
|
|
17910
|
-
};
|
|
17911
|
-
}
|
|
17912
|
-
const sources = p.sources || ["memory", "context7", "github"];
|
|
17913
|
-
const limit = p.limit || 5;
|
|
17914
|
-
let memoryResults;
|
|
17915
|
-
let context7Hint;
|
|
17916
|
-
let githubHint;
|
|
17917
|
-
if (sources.includes("memory")) {
|
|
17918
|
-
try {
|
|
17919
|
-
memoryResults = memorySearch({ query: p.query, limit });
|
|
17920
|
-
} catch {}
|
|
17921
|
-
}
|
|
17922
|
-
if (sources.includes("context7")) {
|
|
17923
|
-
context7Hint = `Use context7 MCP tool: context7_resolve-library-id({ libraryName: "${p.query}" }) then context7_query-docs()`;
|
|
17924
|
-
}
|
|
17925
|
-
if (sources.includes("github")) {
|
|
17926
|
-
const langHint = p.language ? ` language:${p.language}` : "";
|
|
17927
|
-
githubHint = `Use gh-grep MCP tool: gh-grep_searchGitHub({ query: "${p.query}${langHint}" })`;
|
|
17928
|
-
}
|
|
17929
|
-
const suggestion = buildSuggestion(p.query, memoryResults, sources);
|
|
17930
|
-
return {
|
|
17931
|
-
query: p.query,
|
|
17932
|
-
memory: memoryResults,
|
|
17933
|
-
context7Hint,
|
|
17934
|
-
githubHint,
|
|
17935
|
-
suggestion
|
|
17936
|
-
};
|
|
17937
|
-
}
|
|
17938
|
-
function buildSuggestion(query, memoryResults, sources) {
|
|
17939
|
-
const parts = [];
|
|
17940
|
-
if (memoryResults && memoryResults.length > 0) {
|
|
17941
|
-
parts.push(`Found ${memoryResults.length} relevant observations in memory.`);
|
|
17942
|
-
parts.push(`Check memory-get({ ids: "${memoryResults.map((r) => r.id).join(",")}" }) for details.`);
|
|
17943
|
-
}
|
|
17944
|
-
if (sources?.includes("context7")) {
|
|
17945
|
-
parts.push(`For library docs, run context7_resolve-library-id \u2192 context7_query-docs.`);
|
|
17946
|
-
}
|
|
17947
|
-
if (sources?.includes("github")) {
|
|
17948
|
-
parts.push(`For code examples, run gh-grep_searchGitHub with your query.`);
|
|
17949
|
-
}
|
|
17950
|
-
if (parts.length === 0) {
|
|
17951
|
-
parts.push(`No results found. Try broadening your query or checking different sources.`);
|
|
17952
|
-
}
|
|
17953
|
-
return parts.join(" ");
|
|
17954
|
-
}
|
|
17955
|
-
|
|
17956
17739
|
// src/tools/context-summary.ts
|
|
17957
17740
|
function parseStringArray(value) {
|
|
17958
17741
|
if (typeof value !== "string" || !value.trim()) {
|
|
@@ -18047,170 +17830,6 @@ function buildSummary(sections, maxTokens) {
|
|
|
18047
17830
|
return summary;
|
|
18048
17831
|
}
|
|
18049
17832
|
|
|
18050
|
-
// src/tools/beads-memory-sync.ts
|
|
18051
|
-
import * as path11 from "path";
|
|
18052
|
-
import * as fs10 from "fs";
|
|
18053
|
-
import { Database as Database5 } from "bun:sqlite";
|
|
18054
|
-
var BEADS_DIR = path11.join(process.cwd(), ".beads");
|
|
18055
|
-
function getMemoryDb2() {
|
|
18056
|
-
return openMemoryDb();
|
|
18057
|
-
}
|
|
18058
|
-
function getBeadsDb() {
|
|
18059
|
-
const beadsDbPath = path11.join(BEADS_DIR, "beads.db");
|
|
18060
|
-
if (!fs10.existsSync(beadsDbPath)) {
|
|
18061
|
-
return null;
|
|
18062
|
-
}
|
|
18063
|
-
return new Database5(beadsDbPath);
|
|
18064
|
-
}
|
|
18065
|
-
function beadsMemorySync(params) {
|
|
18066
|
-
if (!params || typeof params !== "object") {
|
|
18067
|
-
return { success: false, operation: "unknown", details: {} };
|
|
18068
|
-
}
|
|
18069
|
-
const p = params;
|
|
18070
|
-
if (!p.operation) {
|
|
18071
|
-
return { success: false, operation: "unknown", details: {} };
|
|
18072
|
-
}
|
|
18073
|
-
switch (p.operation) {
|
|
18074
|
-
case "sync_to_memory":
|
|
18075
|
-
return syncTasksToMemory();
|
|
18076
|
-
case "sync_from_memory":
|
|
18077
|
-
return syncMemoryToTasks();
|
|
18078
|
-
case "link":
|
|
18079
|
-
if (!p.beadId || !p.observationId) {
|
|
18080
|
-
return { success: false, operation: "link", details: {} };
|
|
18081
|
-
}
|
|
18082
|
-
return linkObservationToTask(p.observationId, p.beadId);
|
|
18083
|
-
case "status":
|
|
18084
|
-
return getSyncStatus();
|
|
18085
|
-
default:
|
|
18086
|
-
return { success: false, operation: p.operation, details: {} };
|
|
18087
|
-
}
|
|
18088
|
-
}
|
|
18089
|
-
function syncTasksToMemory() {
|
|
18090
|
-
const beadsDb = getBeadsDb();
|
|
18091
|
-
if (!beadsDb) {
|
|
18092
|
-
return { success: false, operation: "sync_to_memory", details: { tasksSynced: 0 } };
|
|
18093
|
-
}
|
|
18094
|
-
const memoryDb = getMemoryDb2();
|
|
18095
|
-
try {
|
|
18096
|
-
const tasks = beadsDb.query(`
|
|
18097
|
-
SELECT id, title, description, t, desc
|
|
18098
|
-
FROM issues
|
|
18099
|
-
WHERE status IN ('done', 'closed')
|
|
18100
|
-
`).all();
|
|
18101
|
-
let synced = 0;
|
|
18102
|
-
const existsStmt = memoryDb.prepare(`
|
|
18103
|
-
SELECT id FROM observations WHERE type = 'progress' AND bead_id = ? AND narrative = ? LIMIT 1
|
|
18104
|
-
`);
|
|
18105
|
-
const insertStmt = memoryDb.prepare(`
|
|
18106
|
-
INSERT INTO observations (type, narrative, facts, bead_id)
|
|
18107
|
-
VALUES ('progress', ?, '[]', ?)
|
|
18108
|
-
`);
|
|
18109
|
-
for (const task of tasks) {
|
|
18110
|
-
const narrative = task.title || task.t || task.description || task.desc || task.id;
|
|
18111
|
-
const existing = existsStmt.get(task.id, narrative);
|
|
18112
|
-
if (existing) {
|
|
18113
|
-
continue;
|
|
18114
|
-
}
|
|
18115
|
-
insertStmt.run(narrative, task.id);
|
|
18116
|
-
synced += 1;
|
|
18117
|
-
}
|
|
18118
|
-
return {
|
|
18119
|
-
success: true,
|
|
18120
|
-
operation: "sync_to_memory",
|
|
18121
|
-
details: { tasksSynced: synced }
|
|
18122
|
-
};
|
|
18123
|
-
} finally {
|
|
18124
|
-
memoryDb.close();
|
|
18125
|
-
beadsDb.close();
|
|
18126
|
-
}
|
|
18127
|
-
}
|
|
18128
|
-
function syncMemoryToTasks() {
|
|
18129
|
-
const beadsDb = getBeadsDb();
|
|
18130
|
-
if (!beadsDb) {
|
|
18131
|
-
return { success: false, operation: "sync_from_memory", details: {} };
|
|
18132
|
-
}
|
|
18133
|
-
const memoryDb = getMemoryDb2();
|
|
18134
|
-
try {
|
|
18135
|
-
beadsDb.exec(`
|
|
18136
|
-
CREATE TABLE IF NOT EXISTS issue_observations (
|
|
18137
|
-
issue_id TEXT NOT NULL,
|
|
18138
|
-
observation_id INTEGER NOT NULL,
|
|
18139
|
-
observation_type TEXT NOT NULL,
|
|
18140
|
-
narrative TEXT NOT NULL,
|
|
18141
|
-
synced_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
18142
|
-
PRIMARY KEY (issue_id, observation_id)
|
|
18143
|
-
)
|
|
18144
|
-
`);
|
|
18145
|
-
const observations = memoryDb.query(`
|
|
18146
|
-
SELECT id, type, narrative, bead_id
|
|
18147
|
-
FROM observations
|
|
18148
|
-
WHERE bead_id IS NOT NULL
|
|
18149
|
-
AND type IN ('blocker', 'decision')
|
|
18150
|
-
`).all();
|
|
18151
|
-
let linked = 0;
|
|
18152
|
-
const issueExistsStmt = beadsDb.prepare("SELECT id FROM issues WHERE id = ? LIMIT 1");
|
|
18153
|
-
const linkStmt = beadsDb.prepare(`
|
|
18154
|
-
INSERT OR IGNORE INTO issue_observations (issue_id, observation_id, observation_type, narrative)
|
|
18155
|
-
VALUES (?, ?, ?, ?)
|
|
18156
|
-
`);
|
|
18157
|
-
for (const obs of observations) {
|
|
18158
|
-
const existingIssue = issueExistsStmt.get(obs.bead_id);
|
|
18159
|
-
if (!existingIssue) {
|
|
18160
|
-
continue;
|
|
18161
|
-
}
|
|
18162
|
-
const result = linkStmt.run(obs.bead_id, obs.id, obs.type, obs.narrative);
|
|
18163
|
-
if (result.changes > 0) {
|
|
18164
|
-
linked += 1;
|
|
18165
|
-
}
|
|
18166
|
-
}
|
|
18167
|
-
return {
|
|
18168
|
-
success: true,
|
|
18169
|
-
operation: "sync_from_memory",
|
|
18170
|
-
details: { observationsLinked: linked }
|
|
18171
|
-
};
|
|
18172
|
-
} finally {
|
|
18173
|
-
memoryDb.close();
|
|
18174
|
-
beadsDb.close();
|
|
18175
|
-
}
|
|
18176
|
-
}
|
|
18177
|
-
function linkObservationToTask(observationId, beadId) {
|
|
18178
|
-
const memoryDb = getMemoryDb2();
|
|
18179
|
-
try {
|
|
18180
|
-
memoryDb.run("UPDATE observations SET bead_id = ? WHERE id = ?", [beadId, observationId]);
|
|
18181
|
-
return {
|
|
18182
|
-
success: true,
|
|
18183
|
-
operation: "link",
|
|
18184
|
-
details: { observationsLinked: 1 }
|
|
18185
|
-
};
|
|
18186
|
-
} finally {
|
|
18187
|
-
memoryDb.close();
|
|
18188
|
-
}
|
|
18189
|
-
}
|
|
18190
|
-
function getSyncStatus() {
|
|
18191
|
-
const memoryDb = getMemoryDb2();
|
|
18192
|
-
const beadsDb = getBeadsDb();
|
|
18193
|
-
try {
|
|
18194
|
-
const memoryCount = memoryDb.query("SELECT COUNT(*) as count FROM observations").get();
|
|
18195
|
-
let activeTasks = 0;
|
|
18196
|
-
if (beadsDb) {
|
|
18197
|
-
const taskCount = beadsDb.query("SELECT COUNT(*) as count FROM issues WHERE status != 'closed'").get();
|
|
18198
|
-
activeTasks = taskCount.count;
|
|
18199
|
-
}
|
|
18200
|
-
return {
|
|
18201
|
-
success: true,
|
|
18202
|
-
operation: "status",
|
|
18203
|
-
details: {
|
|
18204
|
-
memoryCount: memoryCount.count,
|
|
18205
|
-
activeTasks
|
|
18206
|
-
}
|
|
18207
|
-
};
|
|
18208
|
-
} finally {
|
|
18209
|
-
memoryDb.close();
|
|
18210
|
-
beadsDb?.close();
|
|
18211
|
-
}
|
|
18212
|
-
}
|
|
18213
|
-
|
|
18214
17833
|
// src/index.ts
|
|
18215
17834
|
var execFileAsync3 = promisify3(execFile3);
|
|
18216
17835
|
var CliKitPlugin = async (ctx) => {
|
|
@@ -18348,6 +17967,127 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18348
17967
|
writeErrorLog(hookName, error45, ctx.directory, context);
|
|
18349
17968
|
await cliLog("error", formatHookErrorLog(hookName, error45, context));
|
|
18350
17969
|
}
|
|
17970
|
+
function getEffectiveWorkflow() {
|
|
17971
|
+
const raw = pluginConfig.workflow ?? {};
|
|
17972
|
+
const classicMode = raw.mode === "classic";
|
|
17973
|
+
return {
|
|
17974
|
+
mode: classicMode ? "classic" : "compressed",
|
|
17975
|
+
activeRoles: raw.active_roles || ["build", "plan", "review", "coordinator"],
|
|
17976
|
+
usePackets: classicMode ? raw.use_packets === true : raw.use_packets !== false,
|
|
17977
|
+
embedVerifyInStart: classicMode ? false : raw.embed_verify_in_start !== false,
|
|
17978
|
+
verifyIsAudit: classicMode ? false : raw.verify_is_audit !== false,
|
|
17979
|
+
subagentCallBudget: raw.subagent_call_budget ?? 2
|
|
17980
|
+
};
|
|
17981
|
+
}
|
|
17982
|
+
function prependBlock(content, block) {
|
|
17983
|
+
return `${block.trim()}
|
|
17984
|
+
|
|
17985
|
+
${(content || "").trim()}`.trim();
|
|
17986
|
+
}
|
|
17987
|
+
function applyWorkflowOverridesToAgents(agents) {
|
|
17988
|
+
const workflow = getEffectiveWorkflow();
|
|
17989
|
+
const result = { ...agents };
|
|
17990
|
+
const runtimeBlock = workflow.mode === "classic" ? [
|
|
17991
|
+
"## Runtime Workflow Override",
|
|
17992
|
+
"- Mode: classic",
|
|
17993
|
+
`- Use packets: ${workflow.usePackets ? "yes" : "no"}`,
|
|
17994
|
+
`- Subagent budget per unit of work: ${workflow.subagentCallBudget}`,
|
|
17995
|
+
"- Do not assume `/start` embeds verification; `/verify` is the pre-ship gate \u2014 required before `/ship`."
|
|
17996
|
+
].join(`
|
|
17997
|
+
`) : [
|
|
17998
|
+
"## Runtime Workflow Override",
|
|
17999
|
+
"- Mode: compressed",
|
|
18000
|
+
`- Use packets: ${workflow.usePackets ? "yes" : "no"}`,
|
|
18001
|
+
`- Subagent budget per packet: ${workflow.subagentCallBudget}`,
|
|
18002
|
+
workflow.embedVerifyInStart ? "- `/start` performs execute + verify loop." : "- `/start` performs execute only.",
|
|
18003
|
+
workflow.verifyIsAudit ? "- `/verify` is optional deep audit." : "- `/verify` is the pre-ship gate \u2014 required before `/ship`."
|
|
18004
|
+
].join(`
|
|
18005
|
+
`);
|
|
18006
|
+
for (const agentName of ["build", "plan", "review"]) {
|
|
18007
|
+
const agent = result[agentName];
|
|
18008
|
+
if (!agent)
|
|
18009
|
+
continue;
|
|
18010
|
+
result[agentName] = {
|
|
18011
|
+
...agent,
|
|
18012
|
+
prompt: prependBlock(typeof agent.prompt === "string" ? agent.prompt : "", runtimeBlock)
|
|
18013
|
+
};
|
|
18014
|
+
}
|
|
18015
|
+
return result;
|
|
18016
|
+
}
|
|
18017
|
+
function applyWorkflowOverridesToCommands(commands) {
|
|
18018
|
+
const workflow = getEffectiveWorkflow();
|
|
18019
|
+
const result = { ...commands };
|
|
18020
|
+
if (workflow.mode === "classic") {
|
|
18021
|
+
if (result.start?.template) {
|
|
18022
|
+
result.start = {
|
|
18023
|
+
...result.start,
|
|
18024
|
+
template: prependBlock(result.start.template, [
|
|
18025
|
+
"## Runtime Workflow Override",
|
|
18026
|
+
"- Classic mode is active.",
|
|
18027
|
+
"- Implement using the approved plan/task boundaries.",
|
|
18028
|
+
"- Verification remains a standalone `/verify` gate before `/ship`."
|
|
18029
|
+
].join(`
|
|
18030
|
+
`))
|
|
18031
|
+
};
|
|
18032
|
+
}
|
|
18033
|
+
if (result.verify?.template) {
|
|
18034
|
+
result.verify = {
|
|
18035
|
+
...result.verify,
|
|
18036
|
+
template: prependBlock(result.verify.template, [
|
|
18037
|
+
"## Runtime Workflow Override",
|
|
18038
|
+
"- Classic mode is active.",
|
|
18039
|
+
"- This verification pass is mandatory before ship."
|
|
18040
|
+
].join(`
|
|
18041
|
+
`))
|
|
18042
|
+
};
|
|
18043
|
+
}
|
|
18044
|
+
if (result.ship?.template) {
|
|
18045
|
+
result.ship = {
|
|
18046
|
+
...result.ship,
|
|
18047
|
+
template: prependBlock(result.ship.template, [
|
|
18048
|
+
"## Runtime Workflow Override",
|
|
18049
|
+
"- Classic mode is active.",
|
|
18050
|
+
"- Require `/verify` PASS before `/ship`."
|
|
18051
|
+
].join(`
|
|
18052
|
+
`))
|
|
18053
|
+
};
|
|
18054
|
+
}
|
|
18055
|
+
}
|
|
18056
|
+
if (!workflow.usePackets) {
|
|
18057
|
+
for (const commandName of ["start"]) {
|
|
18058
|
+
const command = result[commandName];
|
|
18059
|
+
if (!command?.template)
|
|
18060
|
+
continue;
|
|
18061
|
+
result[commandName] = {
|
|
18062
|
+
...command,
|
|
18063
|
+
template: prependBlock(command.template, [
|
|
18064
|
+
"## Runtime Workflow Override",
|
|
18065
|
+
"- Packetized execution is disabled.",
|
|
18066
|
+
"- Fall back to approved task/file-impact boundaries from the plan."
|
|
18067
|
+
].join(`
|
|
18068
|
+
`))
|
|
18069
|
+
};
|
|
18070
|
+
}
|
|
18071
|
+
}
|
|
18072
|
+
return result;
|
|
18073
|
+
}
|
|
18074
|
+
function getWorkflowSystemCapsule() {
|
|
18075
|
+
const workflow = getEffectiveWorkflow();
|
|
18076
|
+
const roles = workflow.activeRoles.join(", ");
|
|
18077
|
+
const budget = workflow.subagentCallBudget;
|
|
18078
|
+
return [
|
|
18079
|
+
"## CliKit Workflow Capsule",
|
|
18080
|
+
"",
|
|
18081
|
+
`Mode: ${workflow.mode}`,
|
|
18082
|
+
`Active roles: ${roles}`,
|
|
18083
|
+
workflow.usePackets ? "Execution unit: Task Packet (1 concern, 1-3 files, one verify bundle)" : "Execution unit: plan tasks with explicit file-impact boundaries",
|
|
18084
|
+
"Source of truth: Beads live task state; OpenCode todos are informational only",
|
|
18085
|
+
workflow.usePackets ? `Subagent budget per packet: ${budget}` : `Subagent budget per unit of work: ${budget}`,
|
|
18086
|
+
workflow.embedVerifyInStart ? "`/start` performs execute + verify loop" : "`/start` performs execute only",
|
|
18087
|
+
workflow.verifyIsAudit ? "`/verify` is an optional deep audit / pre-ship confidence pass" : "`/verify` is the mandatory pre-ship gate \u2014 ship only after SHIP_READY verdict"
|
|
18088
|
+
].join(`
|
|
18089
|
+
`);
|
|
18090
|
+
}
|
|
18351
18091
|
const pluginConfig = loadCliKitConfig(ctx.directory) ?? {};
|
|
18352
18092
|
const debugLogsEnabled = pluginConfig.hooks?.session_logging === true && process.env.CLIKIT_DEBUG === "1";
|
|
18353
18093
|
const toolLogsEnabled = pluginConfig.hooks?.tool_logging === true && process.env.CLIKIT_DEBUG === "1";
|
|
@@ -18359,8 +18099,8 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18359
18099
|
const builtinAgents = getBuiltinAgents();
|
|
18360
18100
|
const builtinCommands = getBuiltinCommands();
|
|
18361
18101
|
const builtinSkills = getBuiltinSkills();
|
|
18362
|
-
const filteredAgents = filterAgents(builtinAgents, pluginConfig);
|
|
18363
|
-
const filteredCommands = filterCommands(builtinCommands, pluginConfig);
|
|
18102
|
+
const filteredAgents = applyWorkflowOverridesToAgents(filterAgents(builtinAgents, pluginConfig));
|
|
18103
|
+
const filteredCommands = applyWorkflowOverridesToCommands(filterCommands(builtinCommands, pluginConfig));
|
|
18364
18104
|
const filteredSkills = filterSkills(builtinSkills, pluginConfig);
|
|
18365
18105
|
if (debugLogsEnabled) {
|
|
18366
18106
|
cliLog("info", "[CliKit] Plugin initializing...");
|
|
@@ -18377,42 +18117,6 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18377
18117
|
}
|
|
18378
18118
|
return {
|
|
18379
18119
|
tool: {
|
|
18380
|
-
swarm: tool({
|
|
18381
|
-
description: "Plan, monitor, delegate, and abort tasks in a multi-agent swarm. Use operation=plan to decompose work into parallel tasks, operation=monitor to check progress, operation=delegate to assign a task to an agent role, operation=abort to cancel a task.",
|
|
18382
|
-
args: {
|
|
18383
|
-
operation: tool.schema.enum(["plan", "monitor", "delegate", "abort"]).describe("The swarm operation to perform"),
|
|
18384
|
-
tasks: tool.schema.array(tool.schema.object({
|
|
18385
|
-
id: tool.schema.string(),
|
|
18386
|
-
title: tool.schema.string(),
|
|
18387
|
-
description: tool.schema.string(),
|
|
18388
|
-
dependencies: tool.schema.array(tool.schema.string()).optional(),
|
|
18389
|
-
agentRole: tool.schema.enum(["fe", "be", "mobile", "devops", "qa"]).optional(),
|
|
18390
|
-
files: tool.schema.array(tool.schema.string()).optional(),
|
|
18391
|
-
status: tool.schema.enum(["pending", "in_progress", "completed", "failed", "blocked"])
|
|
18392
|
-
})).optional().describe("Tasks for operation=plan"),
|
|
18393
|
-
parallelism: tool.schema.number().optional().describe("Max parallel tasks (default 3)"),
|
|
18394
|
-
taskId: tool.schema.string().optional().describe("Task ID for operation=monitor|delegate|abort"),
|
|
18395
|
-
agentRole: tool.schema.enum(["fe", "be", "mobile", "devops", "qa"]).optional().describe("Role to delegate to for operation=delegate"),
|
|
18396
|
-
reason: tool.schema.string().optional().describe("Abort reason for operation=abort")
|
|
18397
|
-
},
|
|
18398
|
-
async execute(args) {
|
|
18399
|
-
const result = swarm(args);
|
|
18400
|
-
return JSON.stringify(result, null, 2);
|
|
18401
|
-
}
|
|
18402
|
-
}),
|
|
18403
|
-
quick_research: tool({
|
|
18404
|
-
description: "Search local memory observations and get hints for context7 and GitHub code search. Use this before starting research to check what's already known.",
|
|
18405
|
-
args: {
|
|
18406
|
-
query: tool.schema.string().describe("Search query"),
|
|
18407
|
-
sources: tool.schema.array(tool.schema.enum(["memory", "context7", "github"])).optional().describe("Sources to search (default: all)"),
|
|
18408
|
-
language: tool.schema.string().optional().describe("Language filter for GitHub search"),
|
|
18409
|
-
limit: tool.schema.number().optional().describe("Max memory results (default 5)")
|
|
18410
|
-
},
|
|
18411
|
-
async execute(args) {
|
|
18412
|
-
const result = quickResearch(args);
|
|
18413
|
-
return JSON.stringify(result, null, 2);
|
|
18414
|
-
}
|
|
18415
|
-
}),
|
|
18416
18120
|
context_summary: tool({
|
|
18417
18121
|
description: "Summarize memory observations (decisions, learnings, blockers, progress) into a structured context digest. Useful for compaction or session handoff.",
|
|
18418
18122
|
args: {
|
|
@@ -18424,18 +18128,6 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18424
18128
|
const result = contextSummary(args);
|
|
18425
18129
|
return JSON.stringify(result, null, 2);
|
|
18426
18130
|
}
|
|
18427
|
-
}),
|
|
18428
|
-
beads_memory_sync: tool({
|
|
18429
|
-
description: "Sync between Beads task database and memory observations. Use sync_to_memory to import completed tasks as progress observations, sync_from_memory to link observations back to tasks, link to associate an observation with a task, or status to check sync state.",
|
|
18430
|
-
args: {
|
|
18431
|
-
operation: tool.schema.enum(["sync_to_memory", "sync_from_memory", "link", "status"]).describe("Sync operation to perform"),
|
|
18432
|
-
beadId: tool.schema.string().optional().describe("Bead/task ID for operation=link"),
|
|
18433
|
-
observationId: tool.schema.number().optional().describe("Observation ID for operation=link")
|
|
18434
|
-
},
|
|
18435
|
-
async execute(args) {
|
|
18436
|
-
const result = beadsMemorySync(args);
|
|
18437
|
-
return JSON.stringify(result, null, 2);
|
|
18438
|
-
}
|
|
18439
18131
|
})
|
|
18440
18132
|
},
|
|
18441
18133
|
config: async (config2) => {
|
|
@@ -18561,7 +18253,7 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18561
18253
|
const todoHash = JSON.stringify([...todos].sort((a, b) => a.id.localeCompare(b.id)).map((t) => `${t.id}:${t.status}`));
|
|
18562
18254
|
if (todoHash !== lastTodoHash) {
|
|
18563
18255
|
lastTodoHash = todoHash;
|
|
18564
|
-
if (pluginConfig.hooks?.todo_beads_sync?.enabled !== false) {
|
|
18256
|
+
if (pluginConfig.hooks?.todo_beads_sync?.enabled !== false && pluginConfig.hooks?.todo_beads_sync?.mode !== "disabled") {
|
|
18565
18257
|
try {
|
|
18566
18258
|
const result = syncTodosToBeads(ctx.directory, sessionID, todos, pluginConfig.hooks?.todo_beads_sync);
|
|
18567
18259
|
if (pluginConfig.hooks?.todo_beads_sync?.log === true) {
|
|
@@ -18589,7 +18281,7 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18589
18281
|
if (effectiveTodos.length > 0) {
|
|
18590
18282
|
const result = checkTodoCompletion(effectiveTodos);
|
|
18591
18283
|
if (!result.complete && todoConfig?.warn_on_incomplete !== false) {
|
|
18592
|
-
await cliLog("warn", formatIncompleteWarning(result, sessionID));
|
|
18284
|
+
await cliLog("warn", formatIncompleteWarning(result, sessionID, todoConfig?.beads_authoritative === true));
|
|
18593
18285
|
}
|
|
18594
18286
|
}
|
|
18595
18287
|
} catch (error45) {
|
|
@@ -18717,32 +18409,6 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18717
18409
|
}
|
|
18718
18410
|
}
|
|
18719
18411
|
}
|
|
18720
|
-
if (pluginConfig.hooks?.swarm_enforcer?.enabled !== false) {
|
|
18721
|
-
const editTools = ["edit", "write", "bash"];
|
|
18722
|
-
if (editTools.some((name) => isToolNamed(toolName, name))) {
|
|
18723
|
-
const targetFile = extractFileFromToolInput(toolName, toolInput);
|
|
18724
|
-
try {
|
|
18725
|
-
if (targetFile) {
|
|
18726
|
-
const taskScope = toolInput.taskScope || input.__taskScope;
|
|
18727
|
-
const enforcement = checkEditPermission(targetFile, taskScope, pluginConfig.hooks?.swarm_enforcer);
|
|
18728
|
-
if (!enforcement.allowed) {
|
|
18729
|
-
await cliLog("warn", formatEnforcementWarning(enforcement));
|
|
18730
|
-
if (pluginConfig.hooks?.swarm_enforcer?.block_unreserved_edits) {
|
|
18731
|
-
await showToast(enforcement.reason || "Edit blocked outside task scope", "warning", "CliKit Swarm");
|
|
18732
|
-
blockToolExecution(enforcement.reason || "Edit outside reserved task scope");
|
|
18733
|
-
}
|
|
18734
|
-
} else if (pluginConfig.hooks?.swarm_enforcer?.log === true) {
|
|
18735
|
-
await cliLog("debug", `[CliKit:swarm-enforcer] Allowed edit: ${targetFile}`);
|
|
18736
|
-
}
|
|
18737
|
-
}
|
|
18738
|
-
} catch (error45) {
|
|
18739
|
-
if (isBlockedToolExecutionError(error45)) {
|
|
18740
|
-
throw error45;
|
|
18741
|
-
}
|
|
18742
|
-
await hookErr("swarm-enforcer", error45, { tool: toolName, targetFile });
|
|
18743
|
-
}
|
|
18744
|
-
}
|
|
18745
|
-
}
|
|
18746
18412
|
if (pluginConfig.hooks?.subagent_question_blocker?.enabled !== false) {
|
|
18747
18413
|
if (isSubagentTool(toolName)) {
|
|
18748
18414
|
const prompt = toolInput.prompt;
|
|
@@ -18805,6 +18471,10 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18805
18471
|
},
|
|
18806
18472
|
"experimental.chat.system.transform": async (_input, output) => {
|
|
18807
18473
|
const beadsConfig = pluginConfig.hooks?.beads_context;
|
|
18474
|
+
const workflowCapsule = getWorkflowSystemCapsule();
|
|
18475
|
+
if (workflowCapsule) {
|
|
18476
|
+
output.system.push(workflowCapsule);
|
|
18477
|
+
}
|
|
18808
18478
|
if (beadsConfig?.enabled === false) {
|
|
18809
18479
|
return;
|
|
18810
18480
|
}
|
|
@@ -18822,6 +18492,10 @@ var CliKitPlugin = async (ctx) => {
|
|
|
18822
18492
|
},
|
|
18823
18493
|
"experimental.session.compacting": async (_input, output) => {
|
|
18824
18494
|
const beadsConfig = pluginConfig.hooks?.beads_context;
|
|
18495
|
+
const workflowCapsule = getWorkflowSystemCapsule();
|
|
18496
|
+
if (workflowCapsule) {
|
|
18497
|
+
output.context.push(workflowCapsule);
|
|
18498
|
+
}
|
|
18825
18499
|
if (beadsConfig?.enabled === false) {
|
|
18826
18500
|
return;
|
|
18827
18501
|
}
|