opencode-swarm 7.17.0 → 7.17.1
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/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.17.
|
|
37
|
+
version: "7.17.1",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -15935,7 +15935,6 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
15935
15935
|
return "Spec staleness file was corrupted. It has been removed.";
|
|
15936
15936
|
}
|
|
15937
15937
|
const { planTitle, phase } = stalenessData;
|
|
15938
|
-
await fsPromises3.unlink(specStalenessPath);
|
|
15939
15938
|
let currentHash = null;
|
|
15940
15939
|
let planUpdateSkipped = false;
|
|
15941
15940
|
try {
|
|
@@ -15949,6 +15948,9 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
15949
15948
|
console.error("[acknowledge-spec-drift] Failed to update plan specHash:", planError instanceof Error ? planError.message : String(planError));
|
|
15950
15949
|
planUpdateSkipped = true;
|
|
15951
15950
|
}
|
|
15951
|
+
if (!planUpdateSkipped) {
|
|
15952
|
+
await fsPromises3.unlink(specStalenessPath);
|
|
15953
|
+
}
|
|
15952
15954
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
15953
15955
|
const acknowledgmentEvent = {
|
|
15954
15956
|
type: "spec_drift_acknowledged",
|
|
@@ -35412,6 +35414,8 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
35412
35414
|
const remaining = entries.filter((e) => e.id !== entryId);
|
|
35413
35415
|
const quarantined = {
|
|
35414
35416
|
...entry,
|
|
35417
|
+
status: "quarantined",
|
|
35418
|
+
original_status: entry.status,
|
|
35415
35419
|
quarantine_reason: sanitizedReason,
|
|
35416
35420
|
quarantined_at: new Date().toISOString(),
|
|
35417
35421
|
reported_by: reportedBy
|
|
@@ -35470,7 +35474,24 @@ async function restoreEntry(directory, entryId) {
|
|
|
35470
35474
|
return;
|
|
35471
35475
|
}
|
|
35472
35476
|
const remaining = quarantinedEntries.filter((e) => e.id !== entryId);
|
|
35473
|
-
const {
|
|
35477
|
+
const {
|
|
35478
|
+
quarantine_reason,
|
|
35479
|
+
quarantined_at,
|
|
35480
|
+
reported_by,
|
|
35481
|
+
original_status,
|
|
35482
|
+
status: _quarantineStatus,
|
|
35483
|
+
...rest
|
|
35484
|
+
} = entryToRestore;
|
|
35485
|
+
const original = { ...rest, status: original_status ?? "candidate" };
|
|
35486
|
+
const validation = validateLesson(original.lesson, [], {
|
|
35487
|
+
category: original.category,
|
|
35488
|
+
scope: original.scope,
|
|
35489
|
+
confidence: original.confidence
|
|
35490
|
+
});
|
|
35491
|
+
if (!validation.valid) {
|
|
35492
|
+
warn(`[knowledge-validator] restoreEntry: entry ${entryId} failed re-validation: ${validation.reason}`);
|
|
35493
|
+
return;
|
|
35494
|
+
}
|
|
35474
35495
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
35475
35496
|
`)}
|
|
35476
35497
|
` : "";
|
|
@@ -46325,7 +46346,7 @@ async function selectEntryPoints2(dir) {
|
|
|
46325
46346
|
`)) {
|
|
46326
46347
|
const m = line.match(/=\s*['"]([^'":]+)/);
|
|
46327
46348
|
if (m) {
|
|
46328
|
-
const modPath = m[1].replace(/\./g, "/")
|
|
46349
|
+
const modPath = `${m[1].replace(/\./g, "/")}.py`;
|
|
46329
46350
|
points.add(modPath);
|
|
46330
46351
|
}
|
|
46331
46352
|
}
|
|
@@ -47508,7 +47529,7 @@ function clearDispatchCache() {
|
|
|
47508
47529
|
manifestRootCache.clear();
|
|
47509
47530
|
insertCounter = 0;
|
|
47510
47531
|
}
|
|
47511
|
-
var _internals22, cache, insertCounter = 0, MANIFEST_FILES,
|
|
47532
|
+
var _internals22, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
|
|
47512
47533
|
var init_dispatch = __esm(() => {
|
|
47513
47534
|
init_backends();
|
|
47514
47535
|
init_detector();
|
|
@@ -47540,7 +47561,7 @@ var init_dispatch = __esm(() => {
|
|
|
47540
47561
|
"Gemfile",
|
|
47541
47562
|
"composer.json"
|
|
47542
47563
|
];
|
|
47543
|
-
|
|
47564
|
+
_MANIFEST_SET = new Set(MANIFEST_FILES);
|
|
47544
47565
|
manifestRootCache = new Map;
|
|
47545
47566
|
});
|
|
47546
47567
|
|
|
@@ -9,7 +9,8 @@ import type { KnowledgeConfig, MessageWithParts } from './knowledge-types.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates a knowledge injection hook that injects relevant knowledge into the
|
|
11
11
|
* architect's message context at phase start. Supports caching for re-injection
|
|
12
|
-
* after compaction.
|
|
12
|
+
* after compaction. Cache is per-instance (bound to the returned hook closure),
|
|
13
|
+
* ensuring no cross-test pollution in Bun's shared test-runner process.
|
|
13
14
|
*
|
|
14
15
|
* @param directory - The project directory containing .swarm/
|
|
15
16
|
* @param config - Knowledge system configuration
|
|
@@ -81,7 +81,7 @@ export interface KnowledgeEntryBase extends ActionableDirectiveFields {
|
|
|
81
81
|
tags: string[];
|
|
82
82
|
scope: string;
|
|
83
83
|
confidence: number;
|
|
84
|
-
status: 'candidate' | 'established' | 'promoted' | 'archived';
|
|
84
|
+
status: 'candidate' | 'established' | 'promoted' | 'archived' | 'quarantined';
|
|
85
85
|
confirmed_by: PhaseConfirmationRecord[] | ProjectConfirmationRecord[];
|
|
86
86
|
retrieval_outcomes: RetrievalOutcome;
|
|
87
87
|
schema_version: number;
|
|
@@ -31,6 +31,7 @@ export declare function validateSkillPath(p: unknown): boolean;
|
|
|
31
31
|
export declare function validateActionableFields(fields: ActionableDirectiveFields | undefined): ActionableValidationResult;
|
|
32
32
|
export type { ActionableDirectiveFields, DirectivePriority };
|
|
33
33
|
export interface QuarantinedEntry extends KnowledgeEntryBase {
|
|
34
|
+
original_status: string;
|
|
34
35
|
quarantine_reason: string;
|
|
35
36
|
quarantined_at: string;
|
|
36
37
|
reported_by: 'architect' | 'user' | 'auto';
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.17.
|
|
36
|
+
version: "7.17.1",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -18445,7 +18445,6 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
18445
18445
|
return "Spec staleness file was corrupted. It has been removed.";
|
|
18446
18446
|
}
|
|
18447
18447
|
const { planTitle, phase } = stalenessData;
|
|
18448
|
-
await fsPromises4.unlink(specStalenessPath);
|
|
18449
18448
|
let currentHash = null;
|
|
18450
18449
|
let planUpdateSkipped = false;
|
|
18451
18450
|
try {
|
|
@@ -18459,6 +18458,9 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
18459
18458
|
console.error("[acknowledge-spec-drift] Failed to update plan specHash:", planError instanceof Error ? planError.message : String(planError));
|
|
18460
18459
|
planUpdateSkipped = true;
|
|
18461
18460
|
}
|
|
18461
|
+
if (!planUpdateSkipped) {
|
|
18462
|
+
await fsPromises4.unlink(specStalenessPath);
|
|
18463
|
+
}
|
|
18462
18464
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
18463
18465
|
const acknowledgmentEvent = {
|
|
18464
18466
|
type: "spec_drift_acknowledged",
|
|
@@ -42470,6 +42472,8 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
42470
42472
|
const remaining = entries.filter((e) => e.id !== entryId);
|
|
42471
42473
|
const quarantined = {
|
|
42472
42474
|
...entry,
|
|
42475
|
+
status: "quarantined",
|
|
42476
|
+
original_status: entry.status,
|
|
42473
42477
|
quarantine_reason: sanitizedReason,
|
|
42474
42478
|
quarantined_at: new Date().toISOString(),
|
|
42475
42479
|
reported_by: reportedBy
|
|
@@ -42528,7 +42532,24 @@ async function restoreEntry(directory, entryId) {
|
|
|
42528
42532
|
return;
|
|
42529
42533
|
}
|
|
42530
42534
|
const remaining = quarantinedEntries.filter((e) => e.id !== entryId);
|
|
42531
|
-
const {
|
|
42535
|
+
const {
|
|
42536
|
+
quarantine_reason,
|
|
42537
|
+
quarantined_at,
|
|
42538
|
+
reported_by,
|
|
42539
|
+
original_status,
|
|
42540
|
+
status: _quarantineStatus,
|
|
42541
|
+
...rest
|
|
42542
|
+
} = entryToRestore;
|
|
42543
|
+
const original = { ...rest, status: original_status ?? "candidate" };
|
|
42544
|
+
const validation = validateLesson(original.lesson, [], {
|
|
42545
|
+
category: original.category,
|
|
42546
|
+
scope: original.scope,
|
|
42547
|
+
confidence: original.confidence
|
|
42548
|
+
});
|
|
42549
|
+
if (!validation.valid) {
|
|
42550
|
+
warn(`[knowledge-validator] restoreEntry: entry ${entryId} failed re-validation: ${validation.reason}`);
|
|
42551
|
+
return;
|
|
42552
|
+
}
|
|
42532
42553
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
42533
42554
|
`)}
|
|
42534
42555
|
` : "";
|
|
@@ -44359,7 +44380,9 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
44359
44380
|
const maxInject = config3.max_inject_count ?? 5;
|
|
44360
44381
|
const topN = ranked.slice(0, maxInject);
|
|
44361
44382
|
if (topN.length > 0 && context?.currentPhase) {
|
|
44362
|
-
recordLessonsShown(directory, topN.map((e) => e.id), context.currentPhase).catch(() => {
|
|
44383
|
+
recordLessonsShown(directory, topN.map((e) => e.id), context.currentPhase).catch((err2) => {
|
|
44384
|
+
warn("[knowledge-reader] recordLessonsShown unexpected rejection:", err2);
|
|
44385
|
+
});
|
|
44363
44386
|
}
|
|
44364
44387
|
return topN;
|
|
44365
44388
|
}
|
|
@@ -54848,7 +54871,7 @@ async function selectEntryPoints2(dir) {
|
|
|
54848
54871
|
`)) {
|
|
54849
54872
|
const m = line.match(/=\s*['"]([^'":]+)/);
|
|
54850
54873
|
if (m) {
|
|
54851
|
-
const modPath = m[1].replace(/\./g, "/")
|
|
54874
|
+
const modPath = `${m[1].replace(/\./g, "/")}.py`;
|
|
54852
54875
|
points.add(modPath);
|
|
54853
54876
|
}
|
|
54854
54877
|
}
|
|
@@ -56031,7 +56054,7 @@ function clearDispatchCache() {
|
|
|
56031
56054
|
manifestRootCache.clear();
|
|
56032
56055
|
insertCounter = 0;
|
|
56033
56056
|
}
|
|
56034
|
-
var _internals28, cache, insertCounter = 0, MANIFEST_FILES,
|
|
56057
|
+
var _internals28, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
|
|
56035
56058
|
var init_dispatch = __esm(() => {
|
|
56036
56059
|
init_backends();
|
|
56037
56060
|
init_detector();
|
|
@@ -56063,7 +56086,7 @@ var init_dispatch = __esm(() => {
|
|
|
56063
56086
|
"Gemfile",
|
|
56064
56087
|
"composer.json"
|
|
56065
56088
|
];
|
|
56066
|
-
|
|
56089
|
+
_MANIFEST_SET = new Set(MANIFEST_FILES);
|
|
56067
56090
|
manifestRootCache = new Map;
|
|
56068
56091
|
});
|
|
56069
56092
|
|
|
@@ -71420,7 +71443,7 @@ function decisionFromVerdict(verdict, escalationNeeded) {
|
|
|
71420
71443
|
if (verdict === "APPROVED" || verdict === "ANSWER")
|
|
71421
71444
|
return "allow";
|
|
71422
71445
|
if (verdict === "BLOCKED")
|
|
71423
|
-
return "
|
|
71446
|
+
return "deny";
|
|
71424
71447
|
if (verdict === "PENDING")
|
|
71425
71448
|
return "pending";
|
|
71426
71449
|
return "deny";
|
|
@@ -80646,7 +80669,7 @@ function createFullAutoPermissionHook(options) {
|
|
|
80646
80669
|
phase: effectivePhase,
|
|
80647
80670
|
taskID: taskId ?? undefined,
|
|
80648
80671
|
planID: runState.planID,
|
|
80649
|
-
architectOutput: undefined,
|
|
80672
|
+
architectOutput: output.args ? JSON.stringify(output.args) : undefined,
|
|
80650
80673
|
actionContext: {
|
|
80651
80674
|
tool: toolName,
|
|
80652
80675
|
...decision.context ?? {}
|
|
@@ -81352,6 +81375,7 @@ init_extractors();
|
|
|
81352
81375
|
init_knowledge_reader();
|
|
81353
81376
|
init_knowledge_store();
|
|
81354
81377
|
init_utils2();
|
|
81378
|
+
var INJECTION_SENTINEL = "[[KNOWLEDGE-INJECTED]]";
|
|
81355
81379
|
function buildKnowledgeBlock(entries, charBudget, cfg, currentProject) {
|
|
81356
81380
|
if (entries.length === 0)
|
|
81357
81381
|
return null;
|
|
@@ -81444,7 +81468,7 @@ function isOrchestratorAgent(agentName) {
|
|
|
81444
81468
|
function injectKnowledgeMessage(output, text) {
|
|
81445
81469
|
if (!output.messages)
|
|
81446
81470
|
return;
|
|
81447
|
-
const alreadyInjected = output.messages.some((m) => m.parts?.some((p) => p.text?.includes(
|
|
81471
|
+
const alreadyInjected = output.messages.some((m) => m.parts?.some((p) => p.text?.includes(INJECTION_SENTINEL)));
|
|
81448
81472
|
if (alreadyInjected)
|
|
81449
81473
|
return;
|
|
81450
81474
|
let insertIdx = output.messages.length - 1;
|
|
@@ -81456,14 +81480,11 @@ function injectKnowledgeMessage(output, text) {
|
|
|
81456
81480
|
}
|
|
81457
81481
|
const knowledgeMessage = {
|
|
81458
81482
|
info: { role: "system" },
|
|
81459
|
-
parts: [{ type: "text", text }]
|
|
81483
|
+
parts: [{ type: "text", text: `${INJECTION_SENTINEL}${text}` }]
|
|
81460
81484
|
};
|
|
81461
81485
|
output.messages.splice(insertIdx, 0, knowledgeMessage);
|
|
81462
81486
|
}
|
|
81463
81487
|
function createKnowledgeInjectorHook(directory, config3) {
|
|
81464
|
-
let lastSeenCacheKey = null;
|
|
81465
|
-
let cachedInjectionText = null;
|
|
81466
|
-
let cachedShownIds = [];
|
|
81467
81488
|
function buildContextCacheKey(phase, ctx) {
|
|
81468
81489
|
const parts2 = [
|
|
81469
81490
|
String(phase),
|
|
@@ -81475,6 +81496,9 @@ function createKnowledgeInjectorHook(directory, config3) {
|
|
|
81475
81496
|
].join("|");
|
|
81476
81497
|
return createHash7("sha1").update(parts2).digest("hex").slice(0, 16);
|
|
81477
81498
|
}
|
|
81499
|
+
let lastSeenCacheKey = null;
|
|
81500
|
+
let cachedInjectionText = null;
|
|
81501
|
+
let cachedShownIds = [];
|
|
81478
81502
|
return safeHook(async (_input, output) => {
|
|
81479
81503
|
if (!output.messages || output.messages.length === 0)
|
|
81480
81504
|
return;
|
|
@@ -87862,7 +87886,9 @@ var imports = createSwarmTool({
|
|
|
87862
87886
|
});
|
|
87863
87887
|
// src/tools/knowledge-ack.ts
|
|
87864
87888
|
init_zod();
|
|
87889
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
87865
87890
|
init_state();
|
|
87891
|
+
init_logger();
|
|
87866
87892
|
init_create_tool();
|
|
87867
87893
|
var knowledge_ack = createSwarmTool({
|
|
87868
87894
|
description: "Record an acknowledgment outcome (applied/ignored/violated) for a previously-injected knowledge directive. Updates retrieval-outcome counters and appends a record to .swarm/knowledge-application.jsonl.",
|
|
@@ -87890,7 +87916,11 @@ var knowledge_ack = createSwarmTool({
|
|
|
87890
87916
|
result: a.result,
|
|
87891
87917
|
reason: a.reason
|
|
87892
87918
|
};
|
|
87893
|
-
|
|
87919
|
+
let sessionId = ctx?.sessionID;
|
|
87920
|
+
if (!sessionId) {
|
|
87921
|
+
warn("[knowledge-ack] No sessionID in tool context — dedup disabled for this acknowledgment");
|
|
87922
|
+
sessionId = randomUUID7();
|
|
87923
|
+
}
|
|
87894
87924
|
const dedupKey = buildAckDedupKey(sessionId, a.id, a.result);
|
|
87895
87925
|
if (swarmState.knowledgeAckDedup.has(dedupKey)) {
|
|
87896
87926
|
return JSON.stringify({
|
|
@@ -87919,7 +87949,7 @@ init_knowledge_store();
|
|
|
87919
87949
|
init_knowledge_validator();
|
|
87920
87950
|
init_manager();
|
|
87921
87951
|
init_create_tool();
|
|
87922
|
-
import { randomUUID as
|
|
87952
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
87923
87953
|
var VALID_CATEGORIES2 = [
|
|
87924
87954
|
"process",
|
|
87925
87955
|
"architecture",
|
|
@@ -87993,7 +88023,7 @@ var knowledge_add = createSwarmTool({
|
|
|
87993
88023
|
project_name = plan?.title ?? "";
|
|
87994
88024
|
} catch {}
|
|
87995
88025
|
const entry = {
|
|
87996
|
-
id:
|
|
88026
|
+
id: randomUUID8(),
|
|
87997
88027
|
tier: "swarm",
|
|
87998
88028
|
lesson,
|
|
87999
88029
|
category,
|
|
@@ -99561,7 +99591,7 @@ ${fileList}
|
|
|
99561
99591
|
async _withStateLock(fn) {
|
|
99562
99592
|
const timeoutMs = 1e4;
|
|
99563
99593
|
let timeoutId;
|
|
99564
|
-
const withTimeout2 = new Promise((
|
|
99594
|
+
const withTimeout2 = new Promise((_resolve, reject) => {
|
|
99565
99595
|
timeoutId = setTimeout(() => {
|
|
99566
99596
|
reject(new Error(`_withStateLock timed out after ${timeoutMs}ms — state update will not block subsequent operations`));
|
|
99567
99597
|
}, timeoutMs);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.17.
|
|
3
|
+
"version": "7.17.1",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|