opencode-swarm 7.62.1 → 7.63.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/dist/agents/explorer.d.ts +1 -1
- package/dist/agents/reviewer-directive-compliance.d.ts +43 -0
- package/dist/cli/index.js +3246 -1024
- package/dist/config/schema.d.ts +16 -0
- package/dist/hooks/delegate-ack-collector.d.ts +51 -0
- package/dist/hooks/delegate-directive-injection.d.ts +33 -0
- package/dist/hooks/knowledge-application.d.ts +4 -3
- package/dist/hooks/knowledge-curator.d.ts +73 -1
- package/dist/hooks/knowledge-escalator.d.ts +50 -0
- package/dist/hooks/knowledge-events.d.ts +63 -3
- package/dist/hooks/knowledge-injector.d.ts +69 -1
- package/dist/hooks/knowledge-types.d.ts +41 -1
- package/dist/hooks/knowledge-validator.d.ts +38 -0
- package/dist/hooks/micro-reflector.d.ts +91 -0
- package/dist/hooks/phase-complete-directive-gate.d.ts +44 -0
- package/dist/hooks/phase-directives.d.ts +29 -0
- package/dist/hooks/reviewer-verdict-parser.d.ts +64 -0
- package/dist/hooks/search-knowledge.d.ts +33 -0
- package/dist/index.js +6480 -3661
- package/dist/services/directive-predicate-runner.d.ts +72 -0
- package/dist/services/knowledge-diagnostics.d.ts +19 -0
- package/dist/services/skill-improver.d.ts +11 -0
- package/dist/services/status-service.d.ts +3 -0
- package/dist/services/synonym-map.d.ts +136 -0
- package/dist/services/trajectory-cluster.d.ts +49 -0
- package/dist/services/unactionable-hardening.d.ts +47 -0
- package/dist/tools/phase-complete.d.ts +10 -0
- package/package.json +1 -1
package/dist/config/schema.d.ts
CHANGED
|
@@ -497,6 +497,7 @@ export declare const KnowledgeConfigSchema: z.ZodObject<{
|
|
|
497
497
|
hive_max_entries: z.ZodDefault<z.ZodNumber>;
|
|
498
498
|
auto_promote_days: z.ZodDefault<z.ZodNumber>;
|
|
499
499
|
max_inject_count: z.ZodDefault<z.ZodNumber>;
|
|
500
|
+
delegate_max_inject_count: z.ZodDefault<z.ZodNumber>;
|
|
500
501
|
inject_char_budget: z.ZodDefault<z.ZodNumber>;
|
|
501
502
|
context_budget_threshold: z.ZodOptional<z.ZodNumber>;
|
|
502
503
|
max_lesson_display_chars: z.ZodDefault<z.ZodNumber>;
|
|
@@ -520,6 +521,13 @@ export declare const KnowledgeConfigSchema: z.ZodObject<{
|
|
|
520
521
|
default_max_phases: z.ZodDefault<z.ZodNumber>;
|
|
521
522
|
todo_max_phases: z.ZodDefault<z.ZodNumber>;
|
|
522
523
|
sweep_enabled: z.ZodDefault<z.ZodBoolean>;
|
|
524
|
+
retrieval: z.ZodOptional<z.ZodObject<{
|
|
525
|
+
mmr_lambda: z.ZodDefault<z.ZodNumber>;
|
|
526
|
+
cold_start_bonus: z.ZodDefault<z.ZodNumber>;
|
|
527
|
+
cold_start_max_age_phases: z.ZodDefault<z.ZodNumber>;
|
|
528
|
+
synonym_min_cooccurrence: z.ZodDefault<z.ZodNumber>;
|
|
529
|
+
synonym_map_max_pairs: z.ZodDefault<z.ZodNumber>;
|
|
530
|
+
}, z.core.$strip>>;
|
|
523
531
|
}, z.core.$strip>;
|
|
524
532
|
export type KnowledgeConfig = z.infer<typeof KnowledgeConfigSchema>;
|
|
525
533
|
export declare const MemoryConfigSchema: z.ZodObject<{
|
|
@@ -1264,6 +1272,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1264
1272
|
hive_max_entries: z.ZodDefault<z.ZodNumber>;
|
|
1265
1273
|
auto_promote_days: z.ZodDefault<z.ZodNumber>;
|
|
1266
1274
|
max_inject_count: z.ZodDefault<z.ZodNumber>;
|
|
1275
|
+
delegate_max_inject_count: z.ZodDefault<z.ZodNumber>;
|
|
1267
1276
|
inject_char_budget: z.ZodDefault<z.ZodNumber>;
|
|
1268
1277
|
context_budget_threshold: z.ZodOptional<z.ZodNumber>;
|
|
1269
1278
|
max_lesson_display_chars: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1287,6 +1296,13 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1287
1296
|
default_max_phases: z.ZodDefault<z.ZodNumber>;
|
|
1288
1297
|
todo_max_phases: z.ZodDefault<z.ZodNumber>;
|
|
1289
1298
|
sweep_enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1299
|
+
retrieval: z.ZodOptional<z.ZodObject<{
|
|
1300
|
+
mmr_lambda: z.ZodDefault<z.ZodNumber>;
|
|
1301
|
+
cold_start_bonus: z.ZodDefault<z.ZodNumber>;
|
|
1302
|
+
cold_start_max_age_phases: z.ZodDefault<z.ZodNumber>;
|
|
1303
|
+
synonym_min_cooccurrence: z.ZodDefault<z.ZodNumber>;
|
|
1304
|
+
synonym_map_max_pairs: z.ZodDefault<z.ZodNumber>;
|
|
1305
|
+
}, z.core.$strip>>;
|
|
1290
1306
|
}, z.core.$strip>>;
|
|
1291
1307
|
memory: z.ZodOptional<z.ZodObject<{
|
|
1292
1308
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegate ack collection (Swarm Learning System, Change 1 / Task 1.5).
|
|
3
|
+
*
|
|
4
|
+
* A `tool.execute.after` hook on the `Task` tool. After a delegated subagent
|
|
5
|
+
* returns, this reconciles the directives that were shown to it (recovered by
|
|
6
|
+
* parsing the `<delegate_knowledge_directives>` block out of the delegation
|
|
7
|
+
* prompt) against the ack markers in the subagent's transcript:
|
|
8
|
+
*
|
|
9
|
+
* - For every ack whose ID was actually shown, emit a receipt event of the
|
|
10
|
+
* matching type (applied / ignored / violated / n_a). Acks for IDs that were
|
|
11
|
+
* never shown are DROPPED (anti-spoofing).
|
|
12
|
+
* - For every CRITICAL directive that was shown but never acknowledged, emit a
|
|
13
|
+
* `violated` event with reason `unacknowledged` and append an audit line to
|
|
14
|
+
* `.swarm/unacknowledged-criticals.jsonl`.
|
|
15
|
+
*
|
|
16
|
+
* Stateless by design: it re-parses the prompt rather than relying on
|
|
17
|
+
* cross-hook mutable state, so it is safe under parallel delegations. Fail-open:
|
|
18
|
+
* never throws, never blocks.
|
|
19
|
+
*/
|
|
20
|
+
export interface DelegateAckInput {
|
|
21
|
+
tool: unknown;
|
|
22
|
+
agent?: unknown;
|
|
23
|
+
sessionID?: unknown;
|
|
24
|
+
args?: unknown;
|
|
25
|
+
}
|
|
26
|
+
export interface DelegateAckOutput {
|
|
27
|
+
output?: unknown;
|
|
28
|
+
}
|
|
29
|
+
export interface CollectDelegateAcksResult {
|
|
30
|
+
emitted: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
type: string;
|
|
33
|
+
}>;
|
|
34
|
+
unacknowledgedCriticals: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Core reconciliation used by both the runtime hook and tests. Returns a summary
|
|
38
|
+
* of what was emitted. Never throws.
|
|
39
|
+
*/
|
|
40
|
+
export declare function collectDelegateAcks(params: {
|
|
41
|
+
directory: string;
|
|
42
|
+
prompt: string;
|
|
43
|
+
transcript: string;
|
|
44
|
+
agent: string;
|
|
45
|
+
sessionId?: string;
|
|
46
|
+
taskId?: string;
|
|
47
|
+
}): Promise<CollectDelegateAcksResult>;
|
|
48
|
+
/**
|
|
49
|
+
* `tool.execute.after` adapter. Reconciles delegate acks for a completed Task.
|
|
50
|
+
*/
|
|
51
|
+
export declare function collectDelegateAcksAfter(directory: string, input: DelegateAckInput, output: DelegateAckOutput): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architect-side delegate directive injection (Swarm Learning System, Change 1 /
|
|
3
|
+
* Task 1.4).
|
|
4
|
+
*
|
|
5
|
+
* When the architect delegates via the `Task` tool, this `tool.execute.before`
|
|
6
|
+
* hook prepends the role-scoped `<delegate_knowledge_directives>` block to the
|
|
7
|
+
* subagent's prompt so the delegate sees the directives (and the ack contract)
|
|
8
|
+
* from its very first message. It mirrors the existing skill-injection pattern
|
|
9
|
+
* in src/index.ts, which already mutates `input.args.prompt`.
|
|
10
|
+
*
|
|
11
|
+
* This is ADVISORY (prompt enrichment): it must never throw or block a
|
|
12
|
+
* delegation. A retrieval failure simply leaves the prompt unchanged.
|
|
13
|
+
*
|
|
14
|
+
* NOTE on plan deviation: the implementation plan listed `src/agents/architect.ts`
|
|
15
|
+
* as the "delegation prompt builder". The architect is prompt-driven — real
|
|
16
|
+
* delegations are constructed by the model at runtime via the Task tool, so the
|
|
17
|
+
* code-accurate interception point is this hook, not the architect prompt
|
|
18
|
+
* template. The architect's own `<swarm_knowledge_directives>` injection is
|
|
19
|
+
* untouched.
|
|
20
|
+
*/
|
|
21
|
+
import type { KnowledgeConfig } from './knowledge-types.js';
|
|
22
|
+
export interface DelegateInjectionInput {
|
|
23
|
+
tool: unknown;
|
|
24
|
+
agent?: unknown;
|
|
25
|
+
sessionID?: unknown;
|
|
26
|
+
args?: unknown;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Prepend the per-delegate directive block to a Task delegation's prompt.
|
|
30
|
+
* Returns the number of directives injected (0 when nothing was injected),
|
|
31
|
+
* primarily for test assertions. Never throws.
|
|
32
|
+
*/
|
|
33
|
+
export declare function injectDelegateDirectivesBefore(directory: string, input: DelegateInjectionInput, config: KnowledgeConfig): Promise<number>;
|
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
import type { KnowledgeApplicationResult } from './knowledge-types.js';
|
|
9
9
|
export declare function resolveApplicationLogPath(directory: string): string;
|
|
10
10
|
/**
|
|
11
|
-
* Parse explicit knowledge-acknowledgment markers from architect text.
|
|
11
|
+
* Parse explicit knowledge-acknowledgment markers from architect/delegate text.
|
|
12
12
|
* Recognised forms (case-insensitive, line-anchored or inline):
|
|
13
13
|
* KNOWLEDGE_APPLIED: <id>
|
|
14
14
|
* KNOWLEDGE_IGNORED: <id> reason=<reason>
|
|
15
15
|
* KNOWLEDGE_VIOLATED: <id> reason=<reason>
|
|
16
|
+
* KNOWLEDGE_N_A: <id> reason=<reason> (delegate contract, Change 1)
|
|
16
17
|
*/
|
|
17
18
|
export interface ParsedAcknowledgment {
|
|
18
19
|
id: string;
|
|
19
|
-
result: 'applied' | 'ignored' | 'violated';
|
|
20
|
+
result: 'applied' | 'ignored' | 'violated' | 'n_a';
|
|
20
21
|
reason?: string;
|
|
21
22
|
}
|
|
22
23
|
export declare function parseAcknowledgments(text: string): ParsedAcknowledgment[];
|
|
@@ -38,7 +39,7 @@ export declare function recordKnowledgeShown(directory: string, ids: string[], c
|
|
|
38
39
|
export declare function recordAcknowledgment(directory: string, ack: ParsedAcknowledgment, ctx: RecordContext): Promise<void>;
|
|
39
40
|
/** Build the dedup key. Exported so test code and the runtime integration
|
|
40
41
|
* share the exact format. */
|
|
41
|
-
export declare function buildAckDedupKey(sessionId: string, id: string, result: KnowledgeApplicationResult, now?: Date): string;
|
|
42
|
+
export declare function buildAckDedupKey(sessionId: string, id: string, result: KnowledgeApplicationResult | 'n_a', now?: Date): string;
|
|
42
43
|
/** Acknowledgment recording with dedup. Returns whether a record was actually
|
|
43
44
|
* written (false on dedup hit). dedupSet should be swarmState.knowledgeAckDedup
|
|
44
45
|
* in production; tests can pass a fresh Set. */
|
|
@@ -1,10 +1,68 @@
|
|
|
1
1
|
/** Knowledge curator hook for opencode-swarm v6.17 two-tier knowledge system. */
|
|
2
|
-
import type {
|
|
2
|
+
import type { CuratorLLMDelegate } from './curator.js';
|
|
3
|
+
import type { ActionableDirectiveFields, KnowledgeConfig, SwarmKnowledgeEntry } from './knowledge-types.js';
|
|
4
|
+
import { type InsightCandidate } from './micro-reflector.js';
|
|
5
|
+
declare const seenRetroSections: Map<string, {
|
|
6
|
+
value: string;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Bound seenRetroSections to MAX_TRACKED_RETRO_SECTIONS entries, evicting the
|
|
11
|
+
* oldest-timestamp entries first. Called after every insert so the map can never
|
|
12
|
+
* exceed the cap regardless of how many distinct sessions appear within the
|
|
13
|
+
* 24-hour prune window.
|
|
14
|
+
*/
|
|
15
|
+
declare function capSeenRetroSections(): void;
|
|
16
|
+
/** Record a seen-section hash and enforce the size cap in one step. */
|
|
17
|
+
declare function recordSeenRetroSection(key: string, value: string, timestamp: number): void;
|
|
3
18
|
/**
|
|
4
19
|
* Check if the input is a write operation targeting an evidence file.
|
|
5
20
|
* Exported for testing purposes only.
|
|
6
21
|
*/
|
|
7
22
|
export declare function isWriteToEvidenceFile(input: unknown): boolean;
|
|
23
|
+
/** Build the v3-schema enrichment prompt for a single prose lesson. */
|
|
24
|
+
export declare function buildV3EnrichmentPrompt(lesson: string, category: string, tags: string[]): string;
|
|
25
|
+
/**
|
|
26
|
+
* Parse + validate an enrichment response. Returns the sanitized fields when
|
|
27
|
+
* the output is shape-valid AND actionable, otherwise the list of missing
|
|
28
|
+
* requirements (for the RETRY follow-up). Untrusted-input hardened: only
|
|
29
|
+
* allowlisted fields are copied, then shape-validated by
|
|
30
|
+
* validateActionableFields (length caps, name patterns, injection checks).
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseV3EnrichmentResponse(text: string): {
|
|
33
|
+
fields: ActionableDirectiveFields;
|
|
34
|
+
} | {
|
|
35
|
+
missing: string[];
|
|
36
|
+
};
|
|
37
|
+
export interface EnrichmentQuotaOptions {
|
|
38
|
+
maxCalls: number;
|
|
39
|
+
window: 'utc' | 'local';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Enrich one prose lesson with v3 actionability fields via the curator LLM.
|
|
43
|
+
* One retry on schema failure (with a RETRY message naming the missing
|
|
44
|
+
* fields). Quota-gated per call via skill-improver-quota. Returns null when
|
|
45
|
+
* enrichment is unavailable (quota exhausted) or fails twice — the caller
|
|
46
|
+
* quarantines the entry. Never throws.
|
|
47
|
+
*/
|
|
48
|
+
export declare function enrichLessonToV3(params: {
|
|
49
|
+
directory: string;
|
|
50
|
+
llmDelegate: CuratorLLMDelegate;
|
|
51
|
+
lesson: string;
|
|
52
|
+
category: string;
|
|
53
|
+
tags: string[];
|
|
54
|
+
quota?: EnrichmentQuotaOptions;
|
|
55
|
+
}): Promise<ActionableDirectiveFields | null>;
|
|
56
|
+
/** Max insight candidates folded into the store per phase boundary. */
|
|
57
|
+
export declare const MESO_INSIGHT_BATCH_LIMIT = 20;
|
|
58
|
+
/**
|
|
59
|
+
* Atomically consume up to `batchLimit` insight candidates from
|
|
60
|
+
* `.swarm/insight-candidates.jsonl`, writing back the unconsumed tail under the
|
|
61
|
+
* same lock so concurrent micro-reflection appends are never lost. Fail-open.
|
|
62
|
+
*/
|
|
63
|
+
export declare function consumeInsightCandidates(directory: string, batchLimit?: number): Promise<InsightCandidate[]>;
|
|
64
|
+
/** Build a SwarmKnowledgeEntry from an already-v3-actionable insight candidate. */
|
|
65
|
+
export declare function insightCandidateToEntry(cand: InsightCandidate, projectName: string, phaseNumber: number, config: KnowledgeConfig): SwarmKnowledgeEntry;
|
|
8
66
|
/**
|
|
9
67
|
* Curate and store swarm knowledge entries from lessons.
|
|
10
68
|
* @returns Promise resolving to an object with counts of stored, skipped, and rejected lessons.
|
|
@@ -13,10 +71,19 @@ export declare function curateAndStoreSwarm(lessons: string[], projectName: stri
|
|
|
13
71
|
phase_number: number;
|
|
14
72
|
}, directory: string, config: KnowledgeConfig, options?: {
|
|
15
73
|
skipAutoPromotion?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Change 4 (Task 4.2): LLM delegate used to enrich plain-prose lessons
|
|
76
|
+
* with v3 actionability fields before the Layer-5 gate. When absent,
|
|
77
|
+
* non-actionable lessons go straight to the unactionable queue.
|
|
78
|
+
*/
|
|
79
|
+
llmDelegate?: CuratorLLMDelegate;
|
|
80
|
+
/** Quota knobs for enrichment calls (defaults: 10/day, utc window). */
|
|
81
|
+
enrichmentQuota?: EnrichmentQuotaOptions;
|
|
16
82
|
}): Promise<{
|
|
17
83
|
stored: number;
|
|
18
84
|
skipped: number;
|
|
19
85
|
rejected: number;
|
|
86
|
+
quarantined: number;
|
|
20
87
|
}>;
|
|
21
88
|
/**
|
|
22
89
|
* Auto-promote swarm entries based on phase confirmations and age.
|
|
@@ -32,4 +99,9 @@ export declare const _internals: {
|
|
|
32
99
|
curateAndStoreSwarm: typeof curateAndStoreSwarm;
|
|
33
100
|
runAutoPromotion: typeof runAutoPromotion;
|
|
34
101
|
createKnowledgeCuratorHook: typeof createKnowledgeCuratorHook;
|
|
102
|
+
seenRetroSections: typeof seenRetroSections;
|
|
103
|
+
recordSeenRetroSection: typeof recordSeenRetroSection;
|
|
104
|
+
capSeenRetroSections: typeof capSeenRetroSections;
|
|
105
|
+
MAX_TRACKED_RETRO_SECTIONS: number;
|
|
35
106
|
};
|
|
107
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repeat-mistake escalator (Swarm Learning System, Change 3 / Task 3.2).
|
|
3
|
+
*
|
|
4
|
+
* When the same directive is violated >= {@link ESCALATION_THRESHOLD} times
|
|
5
|
+
* within {@link ESCALATION_WINDOW_DAYS} days (across sessions), it is
|
|
6
|
+
* auto-promoted to `directive_priority:'critical'` + `enforcement_mode:'enforce'`,
|
|
7
|
+
* its `escalation_history` gets a `repeat_violation` record, and an `escalation`
|
|
8
|
+
* event is emitted. Idempotent: an entry already at critical/enforce is never
|
|
9
|
+
* re-escalated, even on subsequent violations.
|
|
10
|
+
*
|
|
11
|
+
* Persistence goes through `rewriteKnowledge` (never a raw JSONL write). Fail-open:
|
|
12
|
+
* any error leaves the entry untouched and returns `escalated:false`.
|
|
13
|
+
*/
|
|
14
|
+
import type { DirectivePriority } from './knowledge-types.js';
|
|
15
|
+
export declare const ESCALATION_WINDOW_DAYS = 30;
|
|
16
|
+
export declare const ESCALATION_THRESHOLD = 2;
|
|
17
|
+
export interface EscalationResult {
|
|
18
|
+
escalated: boolean;
|
|
19
|
+
entryId: string;
|
|
20
|
+
from?: DirectivePriority;
|
|
21
|
+
to?: DirectivePriority;
|
|
22
|
+
violationsInWindow?: number;
|
|
23
|
+
/** True when the entry was already critical/enforce (no-op, idempotent). */
|
|
24
|
+
alreadyEscalated?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Evaluate and (if warranted) apply a repeat-violation escalation to a single
|
|
28
|
+
* entry. Call AFTER the triggering `violated` event has been persisted.
|
|
29
|
+
*/
|
|
30
|
+
export declare function maybeEscalateOnViolation(directory: string, entryId: string, now?: Date): Promise<EscalationResult>;
|
|
31
|
+
export interface RecentEscalation {
|
|
32
|
+
entry_id: string;
|
|
33
|
+
from: string;
|
|
34
|
+
to: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
at: string;
|
|
37
|
+
}
|
|
38
|
+
export declare const ESCALATION_DISPLAY_WINDOW_DAYS = 7;
|
|
39
|
+
/**
|
|
40
|
+
* Read escalation events from the last `windowDays` days, newest first. Used by
|
|
41
|
+
* the architect briefing and `/swarm status`. Fail-open: returns [] on error.
|
|
42
|
+
*/
|
|
43
|
+
export declare function readRecentEscalations(directory: string, windowDays?: number, now?: Date): Promise<RecentEscalation[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Render the architect-briefing "Recently Escalated" subsection. Returns null
|
|
46
|
+
* when there is nothing to show (no empty header).
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildEscalationBriefing(escalations: RecentEscalation[], windowDays?: number): string | null;
|
|
49
|
+
/** Run the escalator for several entry IDs (deduped). Never throws. */
|
|
50
|
+
export declare function escalateViolatedEntries(directory: string, entryIds: string[], now?: Date): Promise<EscalationResult[]>;
|
|
@@ -29,7 +29,11 @@ export declare const KNOWLEDGE_EVENT_SCHEMA_VERSION = 1;
|
|
|
29
29
|
*/
|
|
30
30
|
export declare const MAX_EVENT_LOG_ENTRIES = 5000;
|
|
31
31
|
/** Retrieval modes that surface knowledge to an agent. */
|
|
32
|
-
export type RetrievalEventMode = 'manual' | 'auto_injection' | 'coder_context' | 'review_context' | 'curator'
|
|
32
|
+
export type RetrievalEventMode = 'manual' | 'auto_injection' | 'coder_context' | 'review_context' | 'curator'
|
|
33
|
+
/** Per-delegate directive injection (Change 1): a delegated subagent
|
|
34
|
+
* (coder/reviewer/test_engineer/sme/docs/designer/critic/curator) was shown
|
|
35
|
+
* the subset of directives scoped to its role + expected tools. */
|
|
36
|
+
| 'delegate_inject';
|
|
33
37
|
/** A retrieval: a query returned a ranked set of knowledge entries. */
|
|
34
38
|
export interface RetrievedEvent {
|
|
35
39
|
type: 'retrieved';
|
|
@@ -52,7 +56,13 @@ export interface RetrievedEvent {
|
|
|
52
56
|
}
|
|
53
57
|
/** A receipt: an agent explicitly considered a specific knowledge entry. */
|
|
54
58
|
export interface ReceiptEvent {
|
|
55
|
-
type: 'acknowledged' | 'applied' | 'ignored' | 'contradicted' | 'violated'
|
|
59
|
+
type: 'acknowledged' | 'applied' | 'ignored' | 'contradicted' | 'violated'
|
|
60
|
+
/** Delegate decided a shown directive did not apply to its task (Change 1).
|
|
61
|
+
* Recorded for auditability; never penalizes the entry's outcome signal. */
|
|
62
|
+
| 'n_a'
|
|
63
|
+
/** Architect explicitly accepted an unresolved critical violation at
|
|
64
|
+
* phase_complete (Change 2, Task 2.4). Audit-only; never affects rollups. */
|
|
65
|
+
| 'override';
|
|
56
66
|
schema_version?: number;
|
|
57
67
|
event_id: string;
|
|
58
68
|
trace_id: string;
|
|
@@ -63,6 +73,19 @@ export interface ReceiptEvent {
|
|
|
63
73
|
task_id?: string;
|
|
64
74
|
agent: string;
|
|
65
75
|
reason?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Origin discriminator (Change 2). Distinguishes reviewer-issued verdicts
|
|
78
|
+
* (`'reviewer'`) from delegate self-acks (`'delegate'`) without changing the
|
|
79
|
+
* `type`, so existing counter rollups (which switch on `type`) stay intact.
|
|
80
|
+
* A reviewer VERIFIED maps to type:'applied' with source:'reviewer'.
|
|
81
|
+
*/
|
|
82
|
+
source?: 'delegate' | 'reviewer' | string;
|
|
83
|
+
/** Result of executing a directive's verification_predicate (Change 2). */
|
|
84
|
+
predicate_check?: {
|
|
85
|
+
predicate: string;
|
|
86
|
+
result: 'pass' | 'fail' | 'error';
|
|
87
|
+
detail: string;
|
|
88
|
+
};
|
|
66
89
|
evidence?: {
|
|
67
90
|
files?: string[];
|
|
68
91
|
commands?: string[];
|
|
@@ -96,7 +119,19 @@ export interface ArchivedEvent {
|
|
|
96
119
|
evidence?: string;
|
|
97
120
|
previous_status?: string;
|
|
98
121
|
}
|
|
99
|
-
|
|
122
|
+
/** An escalation: a directive was auto-promoted by the repeat-mistake escalator. */
|
|
123
|
+
export interface EscalationEvent {
|
|
124
|
+
type: 'escalation';
|
|
125
|
+
schema_version?: number;
|
|
126
|
+
event_id: string;
|
|
127
|
+
timestamp: string;
|
|
128
|
+
entry_id: string;
|
|
129
|
+
from: string;
|
|
130
|
+
to: string;
|
|
131
|
+
reason: string;
|
|
132
|
+
enforcement_mode?: string;
|
|
133
|
+
}
|
|
134
|
+
export type KnowledgeEvent = RetrievedEvent | ReceiptEvent | OutcomeEvent | ArchivedEvent | EscalationEvent;
|
|
100
135
|
export type KnowledgeEventType = KnowledgeEvent['type'];
|
|
101
136
|
/**
|
|
102
137
|
* Event shape accepted by {@link appendKnowledgeEvent} / {@link recordKnowledgeEvent}.
|
|
@@ -154,6 +189,9 @@ export interface CounterRollup {
|
|
|
154
189
|
ignored_count: number;
|
|
155
190
|
violated_count: number;
|
|
156
191
|
contradicted_count: number;
|
|
192
|
+
/** Count of explicit not-applicable decisions (Change 1). Auditable, neutral:
|
|
193
|
+
* never contributes to the outcome ranking signal. */
|
|
194
|
+
n_a_count: number;
|
|
157
195
|
succeeded_after_shown_count: number;
|
|
158
196
|
failed_after_shown_count: number;
|
|
159
197
|
/**
|
|
@@ -164,7 +202,15 @@ export interface CounterRollup {
|
|
|
164
202
|
partial_after_shown_count: number;
|
|
165
203
|
last_applied_at?: string;
|
|
166
204
|
last_acknowledged_at?: string;
|
|
205
|
+
/**
|
|
206
|
+
* The most recent violation timestamps for this entry (ISO 8601, newest
|
|
207
|
+
* first, capped at the last {@link MAX_VIOLATION_TIMESTAMPS}). Feeds the
|
|
208
|
+
* repeat-mistake escalator (Change 3).
|
|
209
|
+
*/
|
|
210
|
+
violation_timestamps: string[];
|
|
167
211
|
}
|
|
212
|
+
/** Cap on retained per-entry violation timestamps. */
|
|
213
|
+
export declare const MAX_VIOLATION_TIMESTAMPS = 10;
|
|
168
214
|
/**
|
|
169
215
|
* Recompute per-entry counters deterministically from the immutable event log,
|
|
170
216
|
* optionally folding in legacy `knowledge-application.jsonl` records.
|
|
@@ -189,6 +235,20 @@ export interface CounterRollup {
|
|
|
189
235
|
* @param legacyRecords Optional legacy application records (any order).
|
|
190
236
|
*/
|
|
191
237
|
export declare function recomputeCounters(events: KnowledgeEvent[], legacyRecords?: KnowledgeApplicationRecord[]): Map<string, CounterRollup>;
|
|
238
|
+
/**
|
|
239
|
+
* Count how many of the given violation timestamps fall within `windowDays` of
|
|
240
|
+
* `now` (inclusive). Pure helper — deterministic given its inputs. Malformed
|
|
241
|
+
* timestamps are ignored.
|
|
242
|
+
*/
|
|
243
|
+
export declare function countViolationsInWindow(timestamps: string[], windowDays: number, now?: Date): number;
|
|
244
|
+
/**
|
|
245
|
+
* Async convenience: count an entry's violations within a day-window. Counts
|
|
246
|
+
* directly from the event log + legacy application records so the result is
|
|
247
|
+
* INDEPENDENT of the {@link MAX_VIOLATION_TIMESTAMPS} display cap (the rollup's
|
|
248
|
+
* `violation_timestamps` keeps only the newest 10 and would undercount an entry
|
|
249
|
+
* with more in-window violations). Fail-open: returns 0 on error.
|
|
250
|
+
*/
|
|
251
|
+
export declare function countEntryViolationsInWindow(directory: string, entryId: string, windowDays: number, now?: Date): Promise<number>;
|
|
192
252
|
/**
|
|
193
253
|
* Fail-open rollup reader for hot paths. Search and promotion use this instead
|
|
194
254
|
* of stale persisted counters so `knowledge_receipt` feedback affects ranking
|
|
@@ -7,8 +7,76 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { recordKnowledgeShown } from './knowledge-application.js';
|
|
9
9
|
import { recordKnowledgeEvent } from './knowledge-events.js';
|
|
10
|
-
import type {
|
|
10
|
+
import type { RankedEntry } from './knowledge-reader.js';
|
|
11
|
+
import type { DirectivePriority, KnowledgeConfig, MessageWithParts } from './knowledge-types.js';
|
|
11
12
|
import { searchKnowledge } from './search-knowledge.js';
|
|
13
|
+
/** Marker that uniquely identifies the delegate directive block in a transcript. */
|
|
14
|
+
export declare const DELEGATE_DIRECTIVE_BLOCK_TAG = "<delegate_knowledge_directives>";
|
|
15
|
+
/**
|
|
16
|
+
* Render a sanitized, deterministic `<delegate_knowledge_directives>` block for
|
|
17
|
+
* a delegated subagent (Change 1, Task 1.3). Entries are sorted by priority
|
|
18
|
+
* (critical first) then ID so the block is stable across runs and prompt caches
|
|
19
|
+
* remain warm. Returns null when there are no entries (no empty wrapper).
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildDelegateDirectiveBlock(entries: RankedEntry[], cfg: KnowledgeConfig): string | null;
|
|
22
|
+
/** A directive that was rendered into a delegate block, recovered by parsing. */
|
|
23
|
+
export interface ShownDelegateDirective {
|
|
24
|
+
id: string;
|
|
25
|
+
priority: DirectivePriority;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Recover the directive IDs (and priorities) that were rendered into a
|
|
29
|
+
* `<delegate_knowledge_directives>` block. Used by the ack-collector
|
|
30
|
+
* (Task 1.5) to reconcile a delegate's ack markers against what was actually
|
|
31
|
+
* shown — only IDs present here are honored, so a delegate cannot fabricate an
|
|
32
|
+
* ack for a directive it never received. Returns [] when no block is present.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseDelegateDirectiveBlock(text: string): ShownDelegateDirective[];
|
|
35
|
+
export interface InjectForDelegateParams {
|
|
36
|
+
directory: string;
|
|
37
|
+
agent: string;
|
|
38
|
+
expectedTools?: string[];
|
|
39
|
+
taskTitle?: string;
|
|
40
|
+
sessionId?: string;
|
|
41
|
+
config: KnowledgeConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Phase label recorded on the emitted `delegate_inject` event. Threading the
|
|
44
|
+
* real plan phase (rather than the task title) lets the reviewer verdict loop
|
|
45
|
+
* and the phase-complete gate window directives by phase (Change 2).
|
|
46
|
+
*/
|
|
47
|
+
phase?: string;
|
|
48
|
+
/** Test seam: override the search function. Defaults to the live one. */
|
|
49
|
+
searchFn?: typeof searchKnowledge;
|
|
50
|
+
}
|
|
51
|
+
export interface InjectForDelegateResult {
|
|
52
|
+
entries: RankedEntry[];
|
|
53
|
+
trace_id: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Retrieve the subset of active knowledge directives scoped to a delegated
|
|
57
|
+
* subagent's role + expected tools (Change 1, Task 1.2). Emits a single
|
|
58
|
+
* `retrieved` event tagged `mode:'delegate_inject'` with the capped, in-scope
|
|
59
|
+
* entry IDs. Fail-open: any error yields an empty result.
|
|
60
|
+
*/
|
|
61
|
+
export declare function injectForDelegate(params: InjectForDelegateParams): Promise<InjectForDelegateResult>;
|
|
62
|
+
/** Returns true if this agent is the architect (the sole intended recipient of orchestrator-tier knowledge injection). */
|
|
63
|
+
export declare function isOrchestratorAgent(agentName: string): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Returns true if this agent is a delegated subagent that should receive the
|
|
66
|
+
* per-agent directive block. Swarm prefixes (e.g. `mega_coder`) are stripped so
|
|
67
|
+
* prefixed agent names still match their canonical role.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isDelegatedAgent(agentName: string): boolean;
|
|
70
|
+
/** Returns the default expected-tools list for a delegated agent role. */
|
|
71
|
+
export declare function defaultExpectedToolsForAgent(agentName: string): string[];
|
|
72
|
+
/**
|
|
73
|
+
* Per-delegate scope match implementing the Change-1 OR semantics: an entry is
|
|
74
|
+
* in scope for a delegate when it is untargeted (no agent and no tool scope),
|
|
75
|
+
* OR its `applies_to_agents` includes the delegate's role, OR its
|
|
76
|
+
* `applies_to_tools` intersects the delegate's expected tools. Swarm prefixes
|
|
77
|
+
* are stripped on both sides so `mega_coder` matches a bare `coder`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function matchesDelegateScope(entry: Pick<RankedEntry, 'applies_to_agents' | 'applies_to_tools'>, role: string, expectedTools: readonly string[]): boolean;
|
|
12
80
|
/**
|
|
13
81
|
* Creates a knowledge injection hook that injects relevant knowledge into the
|
|
14
82
|
* architect's message context at phase start. Supports caching for re-injection
|
|
@@ -43,9 +43,19 @@ export interface RetrievalOutcome {
|
|
|
43
43
|
succeeded_after_shown_count?: number;
|
|
44
44
|
/** v2: phase-failure count after a "shown" (replaces failed_after_count). */
|
|
45
45
|
failed_after_shown_count?: number;
|
|
46
|
+
/** v3: recent violation timestamps (newest-first, capped) folded from the
|
|
47
|
+
* event-derived rollup. Surfaced for the repeat-mistake escalator. */
|
|
48
|
+
violation_timestamps?: string[];
|
|
46
49
|
}
|
|
47
50
|
/** v2: priority used by retrieval ranking and enforcement. */
|
|
48
51
|
export type DirectivePriority = 'low' | 'medium' | 'high' | 'critical';
|
|
52
|
+
/** One automatic escalation applied to a directive (Change 3). */
|
|
53
|
+
export interface DirectiveEscalationRecord {
|
|
54
|
+
from: DirectivePriority;
|
|
55
|
+
to: DirectivePriority;
|
|
56
|
+
reason: 'repeat_violation' | string;
|
|
57
|
+
at: string;
|
|
58
|
+
}
|
|
49
59
|
/** v2: optional actionable-directive metadata attached to a knowledge entry. */
|
|
50
60
|
export interface ActionableDirectiveFields {
|
|
51
61
|
/** Trigger phrases that surface this entry (e.g. "coder delegation modifying source"). */
|
|
@@ -60,6 +70,15 @@ export interface ActionableDirectiveFields {
|
|
|
60
70
|
applies_to_tools?: string[];
|
|
61
71
|
/** Reviewer/test-engineer/runtime checks the directive expects. */
|
|
62
72
|
verification_checks?: string[];
|
|
73
|
+
/**
|
|
74
|
+
* A single machine-checkable verification predicate (Change 2). DSL:
|
|
75
|
+
* grep:<regex>:<path-glob> pass when ripgrep finds zero matches
|
|
76
|
+
* tool:<argv> pass when the (allowlisted, shell-free) command exits 0
|
|
77
|
+
* file_not_modified:<path> pass when the path is unchanged in the working tree
|
|
78
|
+
* file_modified:<path> pass when the path is changed in the working tree
|
|
79
|
+
* Runs fail-closed (parse error → error) with a hard 15s timeout, no shell.
|
|
80
|
+
*/
|
|
81
|
+
verification_predicate?: string;
|
|
63
82
|
/** Source pointers (file:line, plan section, etc.). Sanitized. */
|
|
64
83
|
source_refs?: string[];
|
|
65
84
|
/** UUIDs of source knowledge entries (for derived/clustered entries). */
|
|
@@ -70,6 +89,14 @@ export interface ActionableDirectiveFields {
|
|
|
70
89
|
generated_skill_path?: string;
|
|
71
90
|
/** Directive priority for ranking/enforcement. */
|
|
72
91
|
directive_priority?: DirectivePriority;
|
|
92
|
+
/**
|
|
93
|
+
* Enforcement posture (Change 3). `'enforce'` makes the directive block at the
|
|
94
|
+
* point of violation; `'warn'` only records. Auto-set to `'enforce'` by the
|
|
95
|
+
* repeat-mistake escalator.
|
|
96
|
+
*/
|
|
97
|
+
enforcement_mode?: 'warn' | 'enforce';
|
|
98
|
+
/** Audit trail of automatic escalations applied to this directive (Change 3). */
|
|
99
|
+
escalation_history?: DirectiveEscalationRecord[];
|
|
73
100
|
/** ISO 8601 timestamp of last explicit application. */
|
|
74
101
|
last_applied_at?: string;
|
|
75
102
|
/** ISO 8601 timestamp of last explicit acknowledgment. */
|
|
@@ -83,7 +110,10 @@ export interface KnowledgeEntryBase extends ActionableDirectiveFields {
|
|
|
83
110
|
tags: string[];
|
|
84
111
|
scope: string;
|
|
85
112
|
confidence: number;
|
|
86
|
-
status: 'candidate' | 'established' | 'promoted' | 'archived' | 'quarantined'
|
|
113
|
+
status: 'candidate' | 'established' | 'promoted' | 'archived' | 'quarantined'
|
|
114
|
+
/** Change 4: failed the actionability layer (no predicate or no scope tag).
|
|
115
|
+
* Held out of the active store pending hardening by the skill-improver. */
|
|
116
|
+
| 'quarantined_unactionable';
|
|
87
117
|
confirmed_by: PhaseConfirmationRecord[] | ProjectConfirmationRecord[];
|
|
88
118
|
retrieval_outcomes: RetrievalOutcome;
|
|
89
119
|
schema_version: number;
|
|
@@ -128,6 +158,8 @@ export interface KnowledgeConfig {
|
|
|
128
158
|
auto_promote_days: number;
|
|
129
159
|
/** Maximum knowledge entries to inject per architect message. Default: 5 */
|
|
130
160
|
max_inject_count: number;
|
|
161
|
+
/** Maximum knowledge directives injected into a delegated subagent's prompt. Default: 8 */
|
|
162
|
+
delegate_max_inject_count?: number;
|
|
131
163
|
/** Maximum total chars for the entire injection block. Default: 2000 */
|
|
132
164
|
inject_char_budget?: number;
|
|
133
165
|
/** Minimum headroom chars required before knowledge injection activates. Default: 300 */
|
|
@@ -172,6 +204,14 @@ export interface KnowledgeConfig {
|
|
|
172
204
|
todo_max_phases: number;
|
|
173
205
|
/** Enable age-based sweep of knowledge entries. Default: true */
|
|
174
206
|
sweep_enabled: boolean;
|
|
207
|
+
/** Change 5: retrieval-upgrade tuning (MMR / cold-start / synonyms). */
|
|
208
|
+
retrieval?: {
|
|
209
|
+
mmr_lambda?: number;
|
|
210
|
+
cold_start_bonus?: number;
|
|
211
|
+
cold_start_max_age_phases?: number;
|
|
212
|
+
synonym_min_cooccurrence?: number;
|
|
213
|
+
synonym_map_max_pairs?: number;
|
|
214
|
+
};
|
|
175
215
|
}
|
|
176
216
|
export interface MessageInfo {
|
|
177
217
|
role: string;
|
|
@@ -30,6 +30,44 @@ export declare function validateSkillPath(p: unknown): boolean;
|
|
|
30
30
|
/** Validate the optional ActionableDirectiveFields block on a knowledge entry. */
|
|
31
31
|
export declare function validateActionableFields(fields: ActionableDirectiveFields | undefined): ActionableValidationResult;
|
|
32
32
|
export type { ActionableDirectiveFields, DirectivePriority };
|
|
33
|
+
export interface ActionabilityResult {
|
|
34
|
+
actionable: boolean;
|
|
35
|
+
/** Present only when not actionable. */
|
|
36
|
+
reason?: 'missing_predicate' | 'missing_scope' | 'missing_predicate_and_scope';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Layer 5: an entry is actionable only when it carries at least one
|
|
40
|
+
* machine-checkable predicate AND at least one scope tag.
|
|
41
|
+
*
|
|
42
|
+
* predicate := forbidden_actions | required_actions | verification_checks
|
|
43
|
+
* | verification_predicate
|
|
44
|
+
* scope := applies_to_tools | applies_to_agents
|
|
45
|
+
*
|
|
46
|
+
* Plain-prose lessons (no predicate, no scope) are NOT actionable and must be
|
|
47
|
+
* quarantined rather than activated.
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateActionability(entry: Pick<KnowledgeEntryBase, 'forbidden_actions' | 'required_actions' | 'verification_checks' | 'verification_predicate' | 'applies_to_tools' | 'applies_to_agents'>): ActionabilityResult;
|
|
50
|
+
/** Returns `.swarm/knowledge-unactionable.jsonl` for the given directory. */
|
|
51
|
+
export declare function resolveUnactionablePath(directory: string): string;
|
|
52
|
+
/** One quarantined-unactionable record. */
|
|
53
|
+
export interface UnactionableRecord extends KnowledgeEntryBase {
|
|
54
|
+
status: 'quarantined_unactionable';
|
|
55
|
+
unactionable_reason: string;
|
|
56
|
+
quarantined_at: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Persist an entry that failed the actionability layer to the unactionable
|
|
60
|
+
* queue (held out of the active store, pending hardening by the skill-improver).
|
|
61
|
+
* FIFO-capped at 200. Best-effort: throws only on lock failure for tests.
|
|
62
|
+
*
|
|
63
|
+
* Flooding tradeoff (Phase 4 review): duplicate prose lessons are NOT deduped
|
|
64
|
+
* at queue time, so a looping producer can fill the queue with duplicates and
|
|
65
|
+
* FIFO-evict older legitimate records. Accepted because (a) the cap bounds the
|
|
66
|
+
* damage at 200 records of plain text, (b) the hardening loop's promotion path
|
|
67
|
+
* dedups at commit time against the active store, and (c) queue producers are
|
|
68
|
+
* themselves quota- or phase-bounded. Revisit if telemetry shows real evictions.
|
|
69
|
+
*/
|
|
70
|
+
export declare function appendUnactionable(directory: string, entry: KnowledgeEntryBase, reason: string): Promise<void>;
|
|
33
71
|
export interface QuarantinedEntry extends KnowledgeEntryBase {
|
|
34
72
|
original_status: string;
|
|
35
73
|
quarantine_reason: string;
|