opencode-swarm 7.79.7 → 7.81.0
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/.opencode/skills/brainstorm/SKILL.md +2 -2
- package/.opencode/skills/codebase-review-swarm/SKILL.md +6 -0
- package/.opencode/skills/codebase-review-swarm/references/review-protocol-v8.2.md +5 -5
- package/.opencode/skills/council/SKILL.md +10 -3
- package/.opencode/skills/deep-dive/SKILL.md +4 -2
- package/.opencode/skills/deep-research/SKILL.md +13 -5
- package/.opencode/skills/plan/SKILL.md +1 -1
- package/.opencode/skills/specify/SKILL.md +1 -1
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +35 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +102 -62
- package/dist/background/completion-observer.d.ts +5 -5
- package/dist/background/pending-delegations.d.ts +58 -17
- package/dist/background/task-envelope.d.ts +5 -0
- package/dist/cli/index.js +183 -16
- package/dist/commands/pr-feedback.d.ts +8 -6
- package/dist/config/schema.d.ts +2 -0
- package/dist/hooks/knowledge-curator.d.ts +2 -0
- package/dist/hooks/knowledge-types.d.ts +1 -0
- package/dist/index.js +884 -66
- package/dist/memory/schema.d.ts +4 -4
- package/dist/tools/dispatch-lanes.d.ts +118 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/manifest.d.ts +2 -0
- package/dist/tools/tool-metadata.d.ts +8 -0
- package/package.json +1 -1
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Append-only JSONL event log under project-root `.swarm/background-delegations.jsonl`.
|
|
5
5
|
* Each line is a full record snapshot; readers fold to the latest snapshot per
|
|
6
|
-
* `correlationId`. This tracks background
|
|
7
|
-
* trusted
|
|
8
|
-
* number of permanently-running
|
|
9
|
-
* the folded in-memory view stays bounded by distinct correlationIds.
|
|
10
|
-
* log itself is append-only and is NOT compacted
|
|
11
|
-
* fixed number of lines
|
|
6
|
+
* `correlationId`. This tracks native background `Task` dispatches and deterministic
|
|
7
|
+
* async advisory lanes so trusted completions can be correlated to a real dispatch.
|
|
8
|
+
* The stale sweep bounds the number of permanently-running entries by transitioning
|
|
9
|
+
* them to `stale`, so the folded in-memory view stays bounded by distinct correlationIds.
|
|
10
|
+
* The on-disk log itself is append-only and is NOT compacted; each dispatch leaves a
|
|
11
|
+
* small, fixed number of lines.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* Scope: dispatch records `pending`/`running` snapshots, collection or trusted synthetic
|
|
14
|
+
* completions record terminal snapshots, and the stale sweep records `stale` snapshots.
|
|
15
|
+
* This store still has NO gate advancement and NO gate evidence side effect; it is an
|
|
16
|
+
* advisory result ledger only.
|
|
17
17
|
*
|
|
18
18
|
* Concurrency: all writes (append, sweep) run under a single project-scoped lock via
|
|
19
19
|
* `withEvidenceLock`, so concurrent dispatches/sweeps cannot interleave appends. Reads are
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
* `.swarm/` (Invariant 4).
|
|
24
24
|
*/
|
|
25
25
|
export declare const BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
|
|
26
|
-
export type BackgroundDelegationStatus = 'pending' | 'completed' | 'error' | 'stale';
|
|
26
|
+
export type BackgroundDelegationStatus = 'pending' | 'running' | 'completed' | 'error' | 'cancelled' | 'stale' | 'consumed';
|
|
27
27
|
export interface BackgroundDelegationRecord {
|
|
28
|
-
schemaVersion: 1;
|
|
28
|
+
schemaVersion: 1 | 2;
|
|
29
29
|
/** Subagent session id from the dispatch envelope — the correlation key. */
|
|
30
30
|
correlationId: string;
|
|
31
31
|
/** Structured jobId from dispatch metadata when available, else null. */
|
|
@@ -46,6 +46,33 @@ export interface BackgroundDelegationRecord {
|
|
|
46
46
|
status: BackgroundDelegationStatus;
|
|
47
47
|
createdAt: number;
|
|
48
48
|
updatedAt: number;
|
|
49
|
+
/** Async advisory lane batch id. Present for dispatch_lanes_async records. */
|
|
50
|
+
batchId?: string;
|
|
51
|
+
/** Stable lane id within batchId. */
|
|
52
|
+
laneId?: string;
|
|
53
|
+
/** Advisory workflow/mode that launched the lane. */
|
|
54
|
+
mode?: string;
|
|
55
|
+
/** Canonical hash of prompt/provenance inputs captured at dispatch time. */
|
|
56
|
+
promptHash?: string;
|
|
57
|
+
/** Project/root provenance captured at dispatch time. */
|
|
58
|
+
workspace?: BackgroundWorkspaceSnapshot;
|
|
59
|
+
generation?: number;
|
|
60
|
+
result?: BackgroundDelegationResult;
|
|
61
|
+
completedAt?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface BackgroundWorkspaceSnapshot {
|
|
64
|
+
directory: string;
|
|
65
|
+
gitHead: string | null;
|
|
66
|
+
dirtyHash: string | null;
|
|
67
|
+
prHeadSha: string | null;
|
|
68
|
+
scope: string | null;
|
|
69
|
+
}
|
|
70
|
+
export interface BackgroundDelegationResult {
|
|
71
|
+
text?: string;
|
|
72
|
+
error?: string;
|
|
73
|
+
chars: number;
|
|
74
|
+
truncated: boolean;
|
|
75
|
+
digest: string;
|
|
49
76
|
}
|
|
50
77
|
/**
|
|
51
78
|
* Read and fold the store to the latest snapshot per correlationId. Lock-free and
|
|
@@ -53,10 +80,8 @@ export interface BackgroundDelegationRecord {
|
|
|
53
80
|
* (never throws). Records are returned in first-seen correlationId order.
|
|
54
81
|
*
|
|
55
82
|
* Cost: O(lines on disk) per call — a full read + parse + fold with no in-memory cache.
|
|
56
|
-
* This is intentionally simple and acceptable at
|
|
57
|
-
* background delegations, and the on-disk log is small).
|
|
58
|
-
* background load ever makes this hot, a future stage should add a stat-invalidated in-memory
|
|
59
|
-
* cache and/or JSONL compaction (the same future-compaction work noted in the module header).
|
|
83
|
+
* This is intentionally simple and acceptable at advisory-lane volumes (a swarm has few
|
|
84
|
+
* concurrent background delegations, and the on-disk log is small).
|
|
60
85
|
*/
|
|
61
86
|
export declare function readDelegations(directory: string): BackgroundDelegationRecord[];
|
|
62
87
|
/** Returns the folded record for a correlationId, or null. Lock-free read. */
|
|
@@ -71,16 +96,32 @@ export interface RecordPendingInput {
|
|
|
71
96
|
swarmPrefixedAgent: string;
|
|
72
97
|
planTaskId: string | null;
|
|
73
98
|
evidenceTaskId: string | null;
|
|
99
|
+
batchId?: string;
|
|
100
|
+
laneId?: string;
|
|
101
|
+
mode?: string;
|
|
102
|
+
promptHash?: string;
|
|
103
|
+
workspace?: BackgroundWorkspaceSnapshot;
|
|
104
|
+
generation?: number;
|
|
74
105
|
}
|
|
75
106
|
/**
|
|
76
107
|
* Record a `pending` background delegation. Runs the stale sweep first (lazy maintenance,
|
|
77
108
|
* no plugin-init cost), then appends the pending snapshot — all under one lock acquisition
|
|
78
109
|
* so concurrent dispatches cannot interleave. Best-effort: returns null on lock timeout or
|
|
79
|
-
* write failure
|
|
110
|
+
* write failure. Async advisory launchers must treat null as a launch failure so they do
|
|
111
|
+
* not create untracked background work.
|
|
80
112
|
*/
|
|
81
113
|
export declare function recordPendingDelegation(directory: string, input: RecordPendingInput, options?: {
|
|
82
114
|
staleTimeoutMs?: number;
|
|
83
115
|
}): Promise<BackgroundDelegationRecord | null>;
|
|
116
|
+
export declare function appendDelegationTransition(directory: string, correlationId: string, transition: {
|
|
117
|
+
status: BackgroundDelegationStatus;
|
|
118
|
+
result?: BackgroundDelegationResult;
|
|
119
|
+
completedAt?: number;
|
|
120
|
+
}): Promise<BackgroundDelegationRecord | null>;
|
|
121
|
+
export declare function findByBatchId(directory: string, batchId: string, opts?: {
|
|
122
|
+
parentSessionId?: string;
|
|
123
|
+
}): BackgroundDelegationRecord[];
|
|
124
|
+
export declare function findOpenAsyncLaneBatches(directory: string): BackgroundDelegationRecord[];
|
|
84
125
|
/**
|
|
85
126
|
* Public stale sweep: acquires the store lock and marks overdue pendings as `stale`.
|
|
86
127
|
* Best-effort; returns the number swept (0 on lock timeout / error).
|
|
@@ -21,6 +21,11 @@ export interface TaskEnvelope {
|
|
|
21
21
|
/** The subagent session id from `<task id="...">` — the cross-event correlation key. */
|
|
22
22
|
sessionId: string;
|
|
23
23
|
state: TaskEnvelopeState;
|
|
24
|
+
summary?: string;
|
|
25
|
+
resultText?: string;
|
|
26
|
+
errorText?: string;
|
|
27
|
+
resultChars?: number;
|
|
28
|
+
resultTruncated?: boolean;
|
|
24
29
|
}
|
|
25
30
|
/**
|
|
26
31
|
* Parse a task envelope from arbitrary text. Returns null when the text does not contain
|
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.
|
|
55
|
+
version: "7.81.0",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -17760,6 +17760,14 @@ var init_tool_metadata = __esm(() => {
|
|
|
17760
17760
|
description: "dispatch multiple read-only exploration/review lanes concurrently and return a structured join result",
|
|
17761
17761
|
agents: ["architect"]
|
|
17762
17762
|
},
|
|
17763
|
+
dispatch_lanes_async: {
|
|
17764
|
+
description: "launch multiple read-only advisory lanes asynchronously and return a batch id for later collection",
|
|
17765
|
+
agents: ["architect"]
|
|
17766
|
+
},
|
|
17767
|
+
collect_lane_results: {
|
|
17768
|
+
description: "collect or poll results for a dispatch_lanes_async advisory batch without advancing workflow gates",
|
|
17769
|
+
agents: ["architect"]
|
|
17770
|
+
},
|
|
17763
17771
|
summarize_work: {
|
|
17764
17772
|
description: "emit a short structured summary of completed work (key decisions, assumptions, risks, constraints) at task completion; rolls up per phase for architecture-supervisor review. Advisory, never blocks.",
|
|
17765
17773
|
agents: [
|
|
@@ -18787,7 +18795,8 @@ var init_schema = __esm(() => {
|
|
|
18787
18795
|
}).optional(),
|
|
18788
18796
|
enrichment: exports_external.object({
|
|
18789
18797
|
max_calls_per_day: exports_external.number().int().min(0).max(1000).default(30),
|
|
18790
|
-
quota_window: exports_external.enum(["utc", "local"]).default("utc")
|
|
18798
|
+
quota_window: exports_external.enum(["utc", "local"]).default("utc"),
|
|
18799
|
+
batch_size: exports_external.number().int().min(1).max(100).optional()
|
|
18791
18800
|
}).default({ max_calls_per_day: 30, quota_window: "utc" })
|
|
18792
18801
|
});
|
|
18793
18802
|
MemoryConfigSchema = exports_external.object({
|
|
@@ -43829,6 +43838,35 @@ function buildV3EnrichmentPrompt(lesson, category, tags) {
|
|
|
43829
43838
|
].join(`
|
|
43830
43839
|
`);
|
|
43831
43840
|
}
|
|
43841
|
+
function buildV3BatchEnrichmentPrompt(lessons) {
|
|
43842
|
+
const lessonLines = lessons.map((item, idx) => `${idx + 1}. LESSON: ${item.lesson}
|
|
43843
|
+
CATEGORY: ${item.category}
|
|
43844
|
+
TAGS: ${item.tags.join(", ")}`).join(`
|
|
43845
|
+
`);
|
|
43846
|
+
return [
|
|
43847
|
+
"Convert each prose lesson below into an actionable knowledge directive.",
|
|
43848
|
+
"Output ONLY a JSON array (no code fences, no commentary).",
|
|
43849
|
+
`The array length MUST be exactly ${lessons.length}.`,
|
|
43850
|
+
"Each array element at position i maps to lesson i (1-indexed above).",
|
|
43851
|
+
"",
|
|
43852
|
+
"For EACH element, mandatory requirements:",
|
|
43853
|
+
"- At least ONE scope field non-empty:",
|
|
43854
|
+
' "applies_to_agents": string[] \u2014 roles from: architect, coder, reviewer, test_engineer, sme, docs, designer, critic, curator',
|
|
43855
|
+
' "applies_to_tools": string[] \u2014 tool names from: edit, write, patch, bash, read, grep, glob',
|
|
43856
|
+
"- At least ONE predicate field non-empty:",
|
|
43857
|
+
' "forbidden_actions": string[] | "required_actions": string[] | "verification_checks": string[]',
|
|
43858
|
+
"",
|
|
43859
|
+
"Optional per element:",
|
|
43860
|
+
'"triggers": string[], "directive_priority": "low" | "medium" | "high" | "critical"',
|
|
43861
|
+
"",
|
|
43862
|
+
"Example array:",
|
|
43863
|
+
'[{"applies_to_agents":["coder"],"required_actions":["run focused tests before commit"],"directive_priority":"high"}]',
|
|
43864
|
+
"",
|
|
43865
|
+
"LESSONS:",
|
|
43866
|
+
lessonLines
|
|
43867
|
+
].join(`
|
|
43868
|
+
`);
|
|
43869
|
+
}
|
|
43832
43870
|
function parseV3EnrichmentResponse(text) {
|
|
43833
43871
|
if (!text || typeof text !== "string") {
|
|
43834
43872
|
return { missing: ["valid JSON object"] };
|
|
@@ -43869,6 +43907,109 @@ function parseV3EnrichmentResponse(text) {
|
|
|
43869
43907
|
}
|
|
43870
43908
|
return { fields };
|
|
43871
43909
|
}
|
|
43910
|
+
function parseV3BatchEnrichmentResponse(text, expectedLength) {
|
|
43911
|
+
const empty = Array.from({ length: expectedLength }, () => null);
|
|
43912
|
+
if (!text || typeof text !== "string") {
|
|
43913
|
+
return { fields: empty, missing: ["valid JSON array"] };
|
|
43914
|
+
}
|
|
43915
|
+
const start = text.indexOf("[");
|
|
43916
|
+
const end = text.lastIndexOf("]");
|
|
43917
|
+
if (start < 0 || end <= start) {
|
|
43918
|
+
return { fields: empty, missing: ["valid JSON array"] };
|
|
43919
|
+
}
|
|
43920
|
+
let parsed;
|
|
43921
|
+
try {
|
|
43922
|
+
parsed = JSON.parse(text.slice(start, end + 1));
|
|
43923
|
+
} catch {
|
|
43924
|
+
return { fields: empty, missing: ["valid JSON array"] };
|
|
43925
|
+
}
|
|
43926
|
+
if (!Array.isArray(parsed)) {
|
|
43927
|
+
return { fields: empty, missing: ["valid JSON array"] };
|
|
43928
|
+
}
|
|
43929
|
+
const fields = Array.from({ length: expectedLength }, () => null);
|
|
43930
|
+
const missing = [];
|
|
43931
|
+
for (let i = 0;i < expectedLength; i++) {
|
|
43932
|
+
const item = parsed[i];
|
|
43933
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
43934
|
+
missing.push(`item ${i + 1}: valid JSON object`);
|
|
43935
|
+
continue;
|
|
43936
|
+
}
|
|
43937
|
+
const raw = item;
|
|
43938
|
+
const candidate = {};
|
|
43939
|
+
for (const key of ENRICHMENT_ALLOWED_FIELDS) {
|
|
43940
|
+
if (raw[key] !== undefined) {
|
|
43941
|
+
candidate[key] = raw[key];
|
|
43942
|
+
}
|
|
43943
|
+
}
|
|
43944
|
+
const shape = validateActionableFields(candidate);
|
|
43945
|
+
if (!shape.valid) {
|
|
43946
|
+
missing.push(`item ${i + 1}: ${shape.errors.join("; ")}`);
|
|
43947
|
+
continue;
|
|
43948
|
+
}
|
|
43949
|
+
const actionability = validateActionability(candidate);
|
|
43950
|
+
if (!actionability.actionable) {
|
|
43951
|
+
const expected = [];
|
|
43952
|
+
if (actionability.reason === "missing_predicate" || actionability.reason === "missing_predicate_and_scope") {
|
|
43953
|
+
expected.push("a non-empty predicate field (forbidden_actions, required_actions, or verification_checks)");
|
|
43954
|
+
}
|
|
43955
|
+
if (actionability.reason === "missing_scope" || actionability.reason === "missing_predicate_and_scope") {
|
|
43956
|
+
expected.push("a non-empty scope field (applies_to_agents or applies_to_tools)");
|
|
43957
|
+
}
|
|
43958
|
+
missing.push(`item ${i + 1}: ${expected.join("; ")}`);
|
|
43959
|
+
continue;
|
|
43960
|
+
}
|
|
43961
|
+
fields[i] = candidate;
|
|
43962
|
+
}
|
|
43963
|
+
if (parsed.length < expectedLength) {
|
|
43964
|
+
missing.push(`expected ${expectedLength} items but got ${parsed.length}`);
|
|
43965
|
+
} else if (parsed.length > expectedLength) {
|
|
43966
|
+
warn(`[knowledge-curator] parseV3BatchEnrichmentResponse received ${parsed.length} items but expected ${expectedLength}; extras will be discarded`);
|
|
43967
|
+
missing.push(`got ${parsed.length} items but only first ${expectedLength} will be used; extras discarded`);
|
|
43968
|
+
}
|
|
43969
|
+
return { fields, missing };
|
|
43970
|
+
}
|
|
43971
|
+
async function enrichLessonsToV3Batched(params) {
|
|
43972
|
+
const quota = params.quota ?? { maxCalls: 10, window: "utc" };
|
|
43973
|
+
const out = Array.from({ length: params.lessons.length }, () => null);
|
|
43974
|
+
const batchSize = params.batchSize ?? ENRICHMENT_BATCH_SIZE;
|
|
43975
|
+
for (let start = 0;start < params.lessons.length; start += batchSize) {
|
|
43976
|
+
const batch = params.lessons.slice(start, start + batchSize);
|
|
43977
|
+
const prompt = buildV3BatchEnrichmentPrompt(batch);
|
|
43978
|
+
let userInput = prompt;
|
|
43979
|
+
let best = Array.from({ length: batch.length }, () => null);
|
|
43980
|
+
let retryHint = "";
|
|
43981
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
43982
|
+
try {
|
|
43983
|
+
const reservation = await reserveQuota(params.directory, {
|
|
43984
|
+
nCalls: 1,
|
|
43985
|
+
maxCalls: quota.maxCalls,
|
|
43986
|
+
window: quota.window,
|
|
43987
|
+
scope: "knowledge-enrichment"
|
|
43988
|
+
});
|
|
43989
|
+
if (!reservation.allowed)
|
|
43990
|
+
break;
|
|
43991
|
+
const response = await params.llmDelegate("", userInput, AbortSignal.timeout(ENRICHMENT_LLM_TIMEOUT_MS));
|
|
43992
|
+
const parsed = parseV3BatchEnrichmentResponse(response, batch.length);
|
|
43993
|
+
best = best.map((current, idx) => current ?? parsed.fields[idx]);
|
|
43994
|
+
const unresolved = best.map((fields, idx) => ({ fields, idx })).filter((item) => item.fields === null).map((item) => item.idx + 1);
|
|
43995
|
+
if (unresolved.length === 0)
|
|
43996
|
+
break;
|
|
43997
|
+
retryHint = parsed.missing.join("; ");
|
|
43998
|
+
const resolvedList = best.map((fields, idx) => ({ fields, idx })).filter((item) => item.fields !== null).map((item) => item.idx + 1);
|
|
43999
|
+
const preserveClause = resolvedList.length > 0 ? `Preserve the already-valid entries for items ${resolvedList.join(", ")} exactly as you returned them previously. ` : "";
|
|
44000
|
+
userInput = `${prompt}
|
|
44001
|
+
|
|
44002
|
+
RETRY: your last output still missed valid directives for items ${unresolved.join(", ")}. ${retryHint} ${preserveClause}Return a full JSON array with valid entries for every item.`;
|
|
44003
|
+
} catch (err) {
|
|
44004
|
+
warn(`[knowledge-curator] v3 batch enrichment attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
44005
|
+
}
|
|
44006
|
+
}
|
|
44007
|
+
for (let i = 0;i < best.length; i++) {
|
|
44008
|
+
out[start + i] = best[i];
|
|
44009
|
+
}
|
|
44010
|
+
}
|
|
44011
|
+
return out;
|
|
44012
|
+
}
|
|
43872
44013
|
async function enrichLessonToV3(params) {
|
|
43873
44014
|
const quota = params.quota ?? { maxCalls: 10, window: "utc" };
|
|
43874
44015
|
const prompt = buildV3EnrichmentPrompt(params.lesson, params.category, params.tags);
|
|
@@ -44006,6 +44147,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
44006
44147
|
const snapshotPlusNew = [...snapshot];
|
|
44007
44148
|
const toAdd = [];
|
|
44008
44149
|
const pendingReinforcementIds = new Set;
|
|
44150
|
+
const pendingBatchEnrichment = [];
|
|
44009
44151
|
for (const lesson of lessons) {
|
|
44010
44152
|
const tags = inferTags(lesson);
|
|
44011
44153
|
let category = "process";
|
|
@@ -44068,20 +44210,10 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
44068
44210
|
project_name: projectName,
|
|
44069
44211
|
auto_generated: true
|
|
44070
44212
|
};
|
|
44071
|
-
|
|
44213
|
+
const actionability = validateActionability(entry);
|
|
44072
44214
|
if (!actionability.actionable && options?.llmDelegate) {
|
|
44073
|
-
|
|
44074
|
-
|
|
44075
|
-
llmDelegate: options.llmDelegate,
|
|
44076
|
-
lesson,
|
|
44077
|
-
category,
|
|
44078
|
-
tags,
|
|
44079
|
-
quota: options.enrichmentQuota
|
|
44080
|
-
});
|
|
44081
|
-
if (enriched) {
|
|
44082
|
-
Object.assign(entry, enriched);
|
|
44083
|
-
actionability = validateActionability(entry);
|
|
44084
|
-
}
|
|
44215
|
+
pendingBatchEnrichment.push({ entry, lesson, category, tags });
|
|
44216
|
+
continue;
|
|
44085
44217
|
}
|
|
44086
44218
|
if (!actionability.actionable) {
|
|
44087
44219
|
quarantined++;
|
|
@@ -44098,6 +44230,41 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
44098
44230
|
toAdd.push(entry);
|
|
44099
44231
|
snapshotPlusNew.push(entry);
|
|
44100
44232
|
}
|
|
44233
|
+
if (pendingBatchEnrichment.length > 0 && options?.llmDelegate) {
|
|
44234
|
+
const enrichedBatch = await enrichLessonsToV3Batched({
|
|
44235
|
+
directory,
|
|
44236
|
+
llmDelegate: options.llmDelegate,
|
|
44237
|
+
lessons: pendingBatchEnrichment.map((item) => ({
|
|
44238
|
+
lesson: item.lesson,
|
|
44239
|
+
category: item.category,
|
|
44240
|
+
tags: item.tags
|
|
44241
|
+
})),
|
|
44242
|
+
quota: options.enrichmentQuota,
|
|
44243
|
+
batchSize: config3.enrichment?.batch_size
|
|
44244
|
+
});
|
|
44245
|
+
for (let i = 0;i < pendingBatchEnrichment.length; i++) {
|
|
44246
|
+
const pending = pendingBatchEnrichment[i];
|
|
44247
|
+
const enriched = enrichedBatch[i];
|
|
44248
|
+
if (enriched) {
|
|
44249
|
+
Object.assign(pending.entry, enriched);
|
|
44250
|
+
}
|
|
44251
|
+
const actionability = validateActionability(pending.entry);
|
|
44252
|
+
if (!actionability.actionable) {
|
|
44253
|
+
quarantined++;
|
|
44254
|
+
try {
|
|
44255
|
+
await appendUnactionable(directory, pending.entry, actionability.reason ?? "unactionable");
|
|
44256
|
+
} catch {}
|
|
44257
|
+
await appendCuratorSkippedEvent(directory, {
|
|
44258
|
+
entry_id: pending.entry.id,
|
|
44259
|
+
lesson: pending.lesson,
|
|
44260
|
+
reason: actionability.reason ?? "unactionable"
|
|
44261
|
+
});
|
|
44262
|
+
continue;
|
|
44263
|
+
}
|
|
44264
|
+
toAdd.push(pending.entry);
|
|
44265
|
+
snapshotPlusNew.push(pending.entry);
|
|
44266
|
+
}
|
|
44267
|
+
}
|
|
44101
44268
|
try {
|
|
44102
44269
|
const insights = await consumeInsightCandidates(directory);
|
|
44103
44270
|
for (const cand of insights) {
|
|
@@ -44301,7 +44468,7 @@ function createKnowledgeCuratorHook(directory, config3, options = {}) {
|
|
|
44301
44468
|
};
|
|
44302
44469
|
return safeHook(handler);
|
|
44303
44470
|
}
|
|
44304
|
-
var seenRetroSections, MAX_TRACKED_RETRO_SECTIONS = 500, ENRICHMENT_ALLOWED_FIELDS, ENRICHMENT_LLM_TIMEOUT_MS = 60000, MESO_INSIGHT_BATCH_LIMIT = 20, KNOWLEDGE_CATEGORIES, OUTCOME_PROMOTION_BLOCK = -0.3, _internals20;
|
|
44471
|
+
var seenRetroSections, MAX_TRACKED_RETRO_SECTIONS = 500, ENRICHMENT_ALLOWED_FIELDS, ENRICHMENT_LLM_TIMEOUT_MS = 60000, ENRICHMENT_BATCH_SIZE = 6, MESO_INSIGHT_BATCH_LIMIT = 20, KNOWLEDGE_CATEGORIES, OUTCOME_PROMOTION_BLOCK = -0.3, _internals20;
|
|
44305
44472
|
var init_knowledge_curator = __esm(() => {
|
|
44306
44473
|
init_skill_improver_quota();
|
|
44307
44474
|
init_synonym_map();
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Handle /swarm pr-feedback command.
|
|
3
3
|
*
|
|
4
|
-
* Triggers the architect to enter MODE: PR_FEEDBACK
|
|
4
|
+
* Triggers the architect to enter MODE: PR_FEEDBACK — the swarm workflow for
|
|
5
5
|
* ingesting and closing KNOWN pull-request feedback (review comments, requested
|
|
6
6
|
* changes, CI failures, merge conflicts, stale branches, pasted notes). This is
|
|
7
7
|
* distinct from /swarm pr-review, which discovers NEW findings.
|
|
8
8
|
*
|
|
9
9
|
* Input contract (PR reference is optional):
|
|
10
|
-
* /swarm pr-feedback 155
|
|
11
|
-
* /swarm pr-feedback 155 also fix the lint errors
|
|
12
|
-
* /swarm pr-feedback
|
|
10
|
+
* /swarm pr-feedback 155 → feedback pass on PR 155
|
|
11
|
+
* /swarm pr-feedback 155 also fix the lint errors → PR 155 + extra instructions
|
|
12
|
+
* /swarm pr-feedback 155 continue from .swarm/pr-review/<run_id>/feedback-handoff.md
|
|
13
|
+
* -> PR 155 + handoff path instructions
|
|
14
|
+
* /swarm pr-feedback owner/repo#155 → shorthand
|
|
13
15
|
* /swarm pr-feedback https://github.com/.../pull/155
|
|
14
|
-
* /swarm pr-feedback
|
|
16
|
+
* /swarm pr-feedback → bare signal; architect builds
|
|
15
17
|
* the ledger from current PR/branch
|
|
16
18
|
* /swarm pr-feedback address the review notes about error handling
|
|
17
|
-
*
|
|
19
|
+
* → no parseable PR ref ⇒ the whole
|
|
18
20
|
* input is forwarded as instructions
|
|
19
21
|
*
|
|
20
22
|
* PR-reference parsing and injection-hardening are shared with /swarm pr-review
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -592,6 +592,7 @@ export declare const KnowledgeConfigSchema: z.ZodObject<{
|
|
|
592
592
|
utc: "utc";
|
|
593
593
|
local: "local";
|
|
594
594
|
}>>;
|
|
595
|
+
batch_size: z.ZodOptional<z.ZodNumber>;
|
|
595
596
|
}, z.core.$strip>>;
|
|
596
597
|
}, z.core.$strip>;
|
|
597
598
|
export type KnowledgeConfig = z.infer<typeof KnowledgeConfigSchema>;
|
|
@@ -1597,6 +1598,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1597
1598
|
utc: "utc";
|
|
1598
1599
|
local: "local";
|
|
1599
1600
|
}>>;
|
|
1601
|
+
batch_size: z.ZodOptional<z.ZodNumber>;
|
|
1600
1602
|
}, z.core.$strip>>;
|
|
1601
1603
|
}, z.core.$strip>>;
|
|
1602
1604
|
memory: z.ZodOptional<z.ZodObject<{
|
|
@@ -35,6 +35,8 @@ export declare function parseV3EnrichmentResponse(text: string): {
|
|
|
35
35
|
} | {
|
|
36
36
|
missing: string[];
|
|
37
37
|
};
|
|
38
|
+
/** Max lessons enriched per LLM call (batch mode). */
|
|
39
|
+
export declare const ENRICHMENT_BATCH_SIZE = 6;
|
|
38
40
|
export interface EnrichmentQuotaOptions {
|
|
39
41
|
maxCalls: number;
|
|
40
42
|
window: 'utc' | 'local';
|