@wrongstack/core 0.302.0 → 0.303.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.
Files changed (74) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-status-tracker.d.ts +6 -2
  3. package/dist/chronicle/index.js +1949 -1671
  4. package/dist/chronicle/metrics-store.d.ts +14 -0
  5. package/dist/chronicle/project-server-protocol.d.ts +13 -0
  6. package/dist/chronicle/project-server.js +1756 -1573
  7. package/dist/chronicle/rollup-adapter.d.ts +2 -0
  8. package/dist/chronicle/sqlite-journal.d.ts +59 -0
  9. package/dist/coordination/agents/index.js +4313 -3516
  10. package/dist/coordination/agents/project-agent-auto-optimize.d.ts +116 -0
  11. package/dist/coordination/agents/project-agent-capture-window.d.ts +29 -0
  12. package/dist/coordination/agents/project-agent-config-io.d.ts +11 -0
  13. package/dist/coordination/agents/project-agent-consolidation.d.ts +29 -2
  14. package/dist/coordination/agents/project-agent-files.d.ts +12 -3
  15. package/dist/coordination/agents/project-agent-identity-types.d.ts +4 -0
  16. package/dist/coordination/agents/project-agent-identity.d.ts +22 -9
  17. package/dist/coordination/agents/project-agent-learning-entries.d.ts +8 -2
  18. package/dist/coordination/agents/project-agent-learning-structured.d.ts +27 -1
  19. package/dist/coordination/agents/project-agent-optimizer.d.ts +49 -0
  20. package/dist/coordination/agents/project-agent-skill-layer.d.ts +101 -0
  21. package/dist/coordination/agents/role-skills.d.ts +11 -1
  22. package/dist/coordination/index.d.ts +1 -1
  23. package/dist/coordination/index.js +4927 -3589
  24. package/dist/coordination/mail-tools.d.ts +3 -3
  25. package/dist/core/context.d.ts +4 -0
  26. package/dist/core/continue-intent.d.ts +2 -0
  27. package/dist/core/conversation-state.d.ts +5 -0
  28. package/dist/core/index.js +129 -19
  29. package/dist/defaults/index.js +1620 -768
  30. package/dist/execution/index.js +2941 -2630
  31. package/dist/goal/index.js +7 -0
  32. package/dist/index.d.ts +3 -1
  33. package/dist/index.js +12269 -9212
  34. package/dist/infrastructure/index.js +722 -672
  35. package/dist/kernel/events/agent-events.d.ts +28 -0
  36. package/dist/kernel/events/memory-events.d.ts +62 -0
  37. package/dist/plugin/index.js +2167 -1986
  38. package/dist/security/index.js +69 -3
  39. package/dist/security/kanban-boundary.d.ts +5 -1
  40. package/dist/session-catalog/client.d.ts +62 -0
  41. package/dist/session-catalog/endpoint.d.ts +6 -0
  42. package/dist/session-catalog/index.d.ts +6 -0
  43. package/dist/session-catalog/index.js +2000 -0
  44. package/dist/session-catalog/project-server.d.ts +3 -0
  45. package/dist/session-catalog/project-server.js +1861 -0
  46. package/dist/session-catalog/protocol.d.ts +284 -0
  47. package/dist/session-catalog/registry.d.ts +59 -0
  48. package/dist/session-catalog/store.d.ts +71 -0
  49. package/dist/storage/index.d.ts +42 -38
  50. package/dist/storage/index.js +13896 -12931
  51. package/dist/storage/plan-store.d.ts +1 -1
  52. package/dist/storage/session-event-bridge.d.ts +2 -2
  53. package/dist/storage/session-store.d.ts +6 -0
  54. package/dist/tasking/index.js +5 -0
  55. package/dist/tools/index.js +2832 -2606
  56. package/dist/types/config/root.d.ts +11 -1
  57. package/dist/types/config/skills-fleet-brain.d.ts +34 -0
  58. package/dist/types/config/ui.d.ts +14 -0
  59. package/dist/types/config.d.ts +1 -0
  60. package/dist/types/context-evidence.d.ts +2 -0
  61. package/dist/types/index.d.ts +2 -2
  62. package/dist/types/index.js +20 -0
  63. package/dist/types/messages.d.ts +8 -0
  64. package/dist/types/multi-agent.d.ts +7 -0
  65. package/dist/types/session.d.ts +19 -0
  66. package/dist/types/task-graph.d.ts +2 -0
  67. package/dist/types/tool-executor.d.ts +2 -0
  68. package/dist/utils/context-evidence.d.ts +13 -1
  69. package/dist/utils/index.js +29 -2
  70. package/instructions/system-lite.md +23 -8
  71. package/instructions/system-pro.md +29 -9
  72. package/instructions/system.md +29 -9
  73. package/package.json +7 -3
  74. package/skills/wrongstack-kanban/SKILL.md +39 -8
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Automatic learning optimization.
3
+ *
4
+ * Capture is automatic, but distillation used to be a button someone had to
5
+ * press — so a role kept accumulating raw directives and its skills never grew
6
+ * unless a human remembered to run `/agent-improve <role> optimize`. This
7
+ * scheduler closes that gap: it watches captures, decides when a role has
8
+ * earned a pass, and runs `optimizeProjectAgentLearning` in the background.
9
+ *
10
+ * Design constraints, in priority order:
11
+ *
12
+ * 1. **Never block user-facing work.** Every pass is detached and debounced;
13
+ * a capture returns immediately.
14
+ * 2. **Never stampede.** One pass at a time process-wide, one pending pass per
15
+ * role, and a per-role cooldown so a chatty fleet cannot spend the budget
16
+ * on back-to-back optimizations of the same buffer.
17
+ * 3. **Never crash the host.** Failures are swallowed into an exponential
18
+ * backoff; a dead provider degrades to "no optimization" and not to a hot
19
+ * retry loop or a rejected promise nobody awaits.
20
+ * 4. **Do something useful without a model.** With no LLM available the pass
21
+ * still writes the deterministic per-skill addenda, so tagged learning
22
+ * reaches the skill layer on a headless box.
23
+ */
24
+ import { type LearningOptimizerLlm, type OptimizeLearningResult } from './project-agent-optimizer.js';
25
+ export interface AutoOptimizePolicy {
26
+ /** Master switch. Default true. */
27
+ enabled: boolean;
28
+ /** Raw buffer size that makes a role eligible. Default = the soft limit. */
29
+ thresholdBytes: number;
30
+ /** Never optimize a nearly-empty buffer, whatever its byte size. */
31
+ minEntries: number;
32
+ /**
33
+ * Directives already routed to a skill that has no addendum yet. Reaching
34
+ * this count makes a role eligible even below `thresholdBytes` — getting
35
+ * learning into the skill layer promptly is the point of the loop, and
36
+ * waiting for the buffer to fatten delays it for no reason.
37
+ */
38
+ minPendingSkillDirectives: number;
39
+ /** Minimum gap between two automatic passes for one role. */
40
+ minIntervalMs: number;
41
+ /** Quiet period after the last capture before a pass may start. */
42
+ debounceMs: number;
43
+ }
44
+ export declare const DEFAULT_AUTO_OPTIMIZE_POLICY: AutoOptimizePolicy;
45
+ /** Shape accepted from config, where every field is independently optional. */
46
+ export type AutoOptimizePolicyOverrides = {
47
+ [K in keyof AutoOptimizePolicy]?: AutoOptimizePolicy[K] | undefined;
48
+ } & {
49
+ sweepOnStart?: boolean | undefined;
50
+ };
51
+ export declare function resolveAutoOptimizePolicy(overrides?: AutoOptimizePolicyOverrides | undefined): AutoOptimizePolicy;
52
+ export type AutoOptimizeSkipReason = 'disabled' | 'learning-paused' | 'too-few-entries' | 'below-threshold' | 'cooling-down';
53
+ export type AutoOptimizeDecision = {
54
+ eligible: true;
55
+ reason: 'size' | 'pending-skills';
56
+ } | {
57
+ eligible: false;
58
+ reason: AutoOptimizeSkipReason;
59
+ };
60
+ /**
61
+ * Pure eligibility check — no timers, no I/O beyond reading the role's files.
62
+ * Exported so the decision can be tested and surfaced in a status view
63
+ * without running a pass.
64
+ */
65
+ export declare function evaluateAutoOptimize(role: string, projectRoot: string | undefined, policy: AutoOptimizePolicy, now?: number): AutoOptimizeDecision;
66
+ export interface AutoOptimizeEvent {
67
+ role: string;
68
+ trigger: 'size' | 'pending-skills' | 'manual-sweep';
69
+ result?: OptimizeLearningResult | undefined;
70
+ error?: string | undefined;
71
+ }
72
+ export interface LearningOptimizationSchedulerOptions {
73
+ projectRoot: string;
74
+ getPolicy: () => AutoOptimizePolicy;
75
+ /** Resolved lazily so a pass never holds a provider open between runs. */
76
+ getLlm: () => Promise<LearningOptimizerLlm | undefined> | LearningOptimizerLlm | undefined;
77
+ onEvent?: ((event: AutoOptimizeEvent) => void) | undefined;
78
+ /** Injectable clock/timer for deterministic tests. */
79
+ now?: (() => number) | undefined;
80
+ scheduleTimer?: ((fn: () => void, ms: number) => NodeJS.Timeout) | undefined;
81
+ cancelTimer?: ((handle: NodeJS.Timeout) => void) | undefined;
82
+ }
83
+ export declare class LearningOptimizationScheduler {
84
+ private readonly opts;
85
+ private readonly pending;
86
+ private readonly failures;
87
+ private running;
88
+ private inFlight;
89
+ private disposed;
90
+ constructor(opts: LearningOptimizationSchedulerOptions);
91
+ private get now();
92
+ private schedule;
93
+ /**
94
+ * Called after a capture persisted new directives. Debounced per role: a
95
+ * burst of captures collapses into one pass.
96
+ */
97
+ notifyCaptured(role: string): void;
98
+ /**
99
+ * Evaluate every role that has learning data and queue the eligible ones.
100
+ * Run once at host start so roles that crossed the threshold before the
101
+ * scheduler existed are not stuck waiting for their next capture.
102
+ */
103
+ sweep(roles: readonly string[]): void;
104
+ private runIfEligible;
105
+ /** Serialize passes: one optimization at a time, process-wide. */
106
+ private enqueue;
107
+ private execute;
108
+ private recordFailure;
109
+ /** Role currently being optimized, for status surfaces. */
110
+ activeRole(): string | null;
111
+ /** Cancel pending debounces. Safe to call more than once. */
112
+ dispose(): void;
113
+ /** Await the queue — tests only; production never blocks on a pass. */
114
+ idle(): Promise<void>;
115
+ }
116
+ //# sourceMappingURL=project-agent-auto-optimize.d.ts.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Capture rate-limiting window.
3
+ *
4
+ * The frequency cap is documented as "per session", but the counters used to
5
+ * live in module-level Maps that were never reset. In a long-lived project
6
+ * daemon that made the cap "3 captures per role per *process lifetime*" — the
7
+ * observable symptom being roles that silently stopped learning days ago.
8
+ *
9
+ * The window is now time-boxed: counters roll over after
10
+ * `CAPTURE_SESSION_WINDOW_MS`, and a host can reset them explicitly when a real
11
+ * session boundary occurs (`/clear`, resume, new REPL turn batch).
12
+ */
13
+ /** Minimum spacing between two automatic captures for one role. */
14
+ export declare const CAPTURE_COOLDOWN_MS = 120000;
15
+ /** Automatic captures allowed per role within one window. */
16
+ export declare const CAPTURE_MAX_PER_SESSION = 3;
17
+ /** How long a counting window lasts before it rolls over. */
18
+ export declare const CAPTURE_SESSION_WINDOW_MS: number;
19
+ export declare function captureWindowState(key: string, now?: number): {
20
+ count: number;
21
+ lastCaptureAt: number | undefined;
22
+ remaining: number;
23
+ };
24
+ export declare function recordCaptureAttempt(key: string, now?: number): void;
25
+ /** Drop every counter. Called on an explicit session boundary and by tests. */
26
+ export declare function resetCaptureWindows(): void;
27
+ /** Drop the counters for one role/project key. */
28
+ export declare function resetCaptureWindow(key: string): void;
29
+ //# sourceMappingURL=project-agent-capture-window.d.ts.map
@@ -0,0 +1,11 @@
1
+ import type { ProjectAgentConfig } from './project-agent-identity-types.js';
2
+ /**
3
+ * Load the project-level agent config for a given role.
4
+ * Returns `undefined` when no project override exists.
5
+ *
6
+ * Lives in its own module (rather than in `project-agent-identity.ts`) so the
7
+ * skill layer can read the role's `skillNames` override without importing the
8
+ * identity module, which imports the skill layer.
9
+ */
10
+ export declare function loadProjectAgentConfig(role: string, projectRoot?: string): ProjectAgentConfig | undefined;
11
+ //# sourceMappingURL=project-agent-config-io.d.ts.map
@@ -1,7 +1,15 @@
1
+ import { type StructuredLearnedEntry } from './project-agent-learning-structured.js';
1
2
  export interface ConsolidationMetadata {
2
3
  /** ISO timestamp of the last consolidation. */
3
4
  consolidatedAt: string;
4
- /** Number of raw learned.md entries that were synthesized. */
5
+ /**
6
+ * Number of raw `learned.md` **directives** that were synthesized.
7
+ *
8
+ * Counted with the structured parser. It used to be counted with
9
+ * `splitLearnedEntries`, which returns 2 for any structured buffer, so the
10
+ * freshness comparison in `buildProjectContextualizedPrompt` compared 2
11
+ * against 2 forever and the delta-injection branch was unreachable.
12
+ */
5
13
  sourceEntryCount: number;
6
14
  /** Byte size of the raw learned.md at consolidation time. */
7
15
  sourceBytes: number;
@@ -11,11 +19,30 @@ export interface ConsolidationMetadata {
11
19
  trigger: 'manual' | 'automatic';
12
20
  /** Optional model that produced the consolidation. */
13
21
  model?: string | undefined;
22
+ /** Whether the raw buffer was archived and reset after synthesis. */
23
+ pruned?: boolean | undefined;
24
+ /** Archive file holding the pre-prune raw buffer, when pruned. */
25
+ archivePath?: string | undefined;
26
+ /** Skill addenda refreshed by this pass. */
27
+ skills?: string[] | undefined;
14
28
  }
29
+ /** Structured directives in the raw buffer, with legacy-format fallback. */
30
+ export declare function readRawLearnedEntries(role: string, projectRoot?: string): StructuredLearnedEntry[];
15
31
  export declare function loadProjectAgentConsolidated(role: string, projectRoot?: string): string;
16
32
  export declare function loadConsolidationMetadata(role: string, projectRoot?: string): ConsolidationMetadata | undefined;
17
33
  export declare function isConsolidated(role: string, projectRoot?: string): boolean;
18
- export declare function saveProjectAgentConsolidated(role: string, content: string, projectRoot?: string, metadata?: Partial<ConsolidationMetadata>): string;
34
+ export interface SaveConsolidationOptions extends Partial<ConsolidationMetadata> {
35
+ /**
36
+ * Archive the raw buffer and reset it to an empty structured document.
37
+ *
38
+ * Consolidation used to leave `learned.md` untouched, so a role whose buffer
39
+ * had crossed the soft limit stayed over it forever and never captured
40
+ * again. Pruning is what actually closes the optimize→learn loop; the
41
+ * pre-prune buffer is kept under `archive/` for audit.
42
+ */
43
+ prune?: boolean | undefined;
44
+ }
45
+ export declare function saveProjectAgentConsolidated(role: string, content: string, projectRoot?: string, options?: SaveConsolidationOptions): string;
19
46
  export declare function clearProjectAgentConsolidated(role: string, projectRoot?: string): void;
20
47
  export declare function buildConsolidationInstruction(role: string, projectRoot?: string): {
21
48
  instruction: string;
@@ -1,8 +1,17 @@
1
1
  import type { ProjectAgentConfig, RoleKnowledgeManifest } from './project-agent-identity-types.js';
2
2
  /**
3
- * Write or update the learned wisdom file for a given role.
4
- * Appends to existing content when `mode` is 'append'; replaces when
5
- * it is 'replace'. Returns the full path written so callers can log it.
3
+ * Write or update the learned instruction buffer for a given role.
4
+ *
5
+ * `append` (the "teach this agent" flow) merges the text into the **structured**
6
+ * entry list rather than concatenating it after the rendered document. Raw
7
+ * concatenation used to be silently destructive: the structured parser only
8
+ * falls back to the legacy chunk path when it finds no stamped entries, so a
9
+ * taught paragraph appended to a stamped buffer was invisible to the parser and
10
+ * the next capture — which re-renders the whole file from parsed entries —
11
+ * deleted it without a trace.
12
+ *
13
+ * `replace` writes the content verbatim (the review/edit surfaces own the
14
+ * document at that point).
6
15
  */
7
16
  export declare function updateProjectAgentLearned(role: string, content: string, projectRoot?: string, mode?: 'append' | 'replace'): string;
8
17
  /**
@@ -70,6 +70,10 @@ export interface LearnedCaptureResult {
70
70
  skipped: number;
71
71
  status: 'captured' | 'disabled' | 'empty_output' | 'no_blocks' | 'guarded' | 'quality_rejected';
72
72
  reason?: string | undefined;
73
+ /** Skills the captured directives were routed to, if any. */
74
+ skills?: string[] | undefined;
75
+ /** Older directives evicted to keep the buffer inside its budget. */
76
+ evicted?: number | undefined;
73
77
  }
74
78
  /**
75
79
  * Current-knowledge manifest for a role: what live facts the agent should
@@ -19,17 +19,27 @@
19
19
  */
20
20
  import { existsSync } from 'node:fs';
21
21
  import type { SubagentConfig } from '../../types/multi-agent.js';
22
+ import { CAPTURE_COOLDOWN_MS, CAPTURE_MAX_PER_SESSION } from './project-agent-capture-window.js';
22
23
  import { type ConsolidationMetadata } from './project-agent-consolidation.js';
23
24
  import type { LearnedCaptureResult, ProjectAgentConfig, RoleKnowledgeManifest } from './project-agent-identity-types.js';
24
25
  import { type ProjectAgentLearningPolicy } from './project-agent-learning-policy.js';
25
26
  import { type StructuredLearnedEntry } from './project-agent-learning-structured.js';
26
27
  export { validateProjectAgentConfig } from './project-agent-config-validation.js';
28
+ export { loadProjectAgentConfig } from './project-agent-config-io.js';
29
+ export { CAPTURE_SESSION_WINDOW_MS, resetCaptureWindow, resetCaptureWindows, } from './project-agent-capture-window.js';
30
+ export { CAPTURE_COOLDOWN_MS, CAPTURE_MAX_PER_SESSION };
31
+ export { buildSkillDistillInstruction, clearProjectSkillAugmentation, DEFAULT_EAGER_SKILL_LIMIT, listProjectSkillAugmentations, loadProjectSkillAugmentation, loadSkillAffinity, rankRoleSkills, recordSkillLoad, recordSkillOutcome, renderSkillAugmentation, resolveRoleSkillCandidates, routeDirectiveToSkill, saveProjectSkillAugmentation, setSkillPinned, SKILL_AUGMENTATION_MAX_BYTES, type SkillAffinity, type SkillAffinityEntry, } from './project-agent-skill-layer.js';
32
+ export { readRawLearnedEntries, type SaveConsolidationOptions } from './project-agent-consolidation.js';
33
+ export { type AutoOptimizeDecision, type AutoOptimizeEvent, type AutoOptimizePolicy, type AutoOptimizePolicyOverrides, DEFAULT_AUTO_OPTIMIZE_POLICY, evaluateAutoOptimize, LearningOptimizationScheduler, type LearningOptimizationSchedulerOptions, resolveAutoOptimizePolicy, } from './project-agent-auto-optimize.js';
34
+ export { type LearningOptimizerLlm, type OptimizeLearningOptions, type OptimizeLearningResult, optimizeProjectAgentLearning, unwrapWholeDocumentFence, } from './project-agent-optimizer.js';
27
35
  export { buildConsolidationInstruction, type ConsolidationMetadata, clearProjectAgentConsolidated, isConsolidated, loadConsolidationMetadata, loadProjectAgentConsolidated, saveProjectAgentConsolidated, } from './project-agent-consolidation.js';
28
36
  export type { CreateProjectAgentInput, LearnedCaptureResult, ProjectAgentConfig, ProjectAgentProfile, RoleKnowledgeManifest, } from './project-agent-identity-types.js';
29
37
  export { classifyLearnedEntry, LEARNED_ENTRY_MAX_CHARS, LEARNED_HARD_LIMIT, LEARNED_SOFT_LIMIT, type LearnedEntryCategory, normalizeLearnedEntry, } from './project-agent-learning-normalize.js';
30
38
  export { loadProjectAgentLearningPolicy, type ProjectAgentLearningPolicy, updateProjectAgentLearningPolicy, } from './project-agent-learning-policy.js';
31
- export { decomposeLearnedEntry, mergeStructuredEntries, parseLearnedEntryStamp, renderLearnedInstructions, type StructuredLearnedEntry, } from './project-agent-learning-structured.js';
39
+ export { decomposeLearnedEntry, enforceLearnedBudget, mergeStructuredEntries, parseLearnedEntryStamp, renderLearnedInstructions, type StructuredLearnedEntry, } from './project-agent-learning-structured.js';
32
40
  export { assertProjectAgentRole } from './project-agent-paths.js';
41
+ export { splitLearnedEntries, tokenOverlap } from './project-agent-learning-entries.js';
42
+ export { parseStructuredLearnedEntriesFromContent } from './project-agent-learning-structured.js';
33
43
  export { listProjectAgentRoles, refreshProjectAgentIdentity, resetProjectAgentIdentity, updateProjectAgentConfig, updateProjectAgentIdentity, updateProjectAgentKnowledge, updateProjectAgentLearned, } from './project-agent-files.js';
34
44
  export { createProjectAgent, loadProjectAgentProfile, slugifyProjectAgentRole, } from './project-agent-profile.js';
35
45
  /**
@@ -39,11 +49,6 @@ export { createProjectAgent, loadProjectAgentProfile, slugifyProjectAgentRole, }
39
49
  * roles may opt into a deliberately narrow runtime.
40
50
  */
41
51
  export declare function createProjectAgentRoster(baseRoster: Record<string, SubagentConfig>, projectRoot?: string): Record<string, SubagentConfig>;
42
- /**
43
- * Load the project-level agent config for a given role.
44
- * Returns `undefined` when no project override exists.
45
- */
46
- export declare function loadProjectAgentConfig(role: string, projectRoot?: string): ProjectAgentConfig | undefined;
47
52
  /**
48
53
  * Load the project-level identity appendix for a given role.
49
54
  * Appended to the subagent prompt after the base role prompt and policy.
@@ -84,13 +89,17 @@ export declare function applyProjectAgentConfig(base: SubagentConfig, projectCon
84
89
  export declare function buildProjectContextualizedPrompt(basePrompt: string, role: string, projectRoot?: string, options?: {
85
90
  identityOverride?: string | undefined;
86
91
  }): string;
87
- export declare const CAPTURE_COOLDOWN_MS = 120000;
88
- export declare const CAPTURE_MAX_PER_SESSION = 3;
89
92
  /**
90
93
  * Check whether a new capture is allowed for this role. Returns a rejection
91
94
  * reason string when blocked, or undefined when capture may proceed.
95
+ *
96
+ * `existingSize` is accepted for call-site compatibility but no longer gates
97
+ * anything: an over-budget buffer is now trimmed at write time
98
+ * (`enforceLearnedBudget`) instead of blocking every future capture. The old
99
+ * size gate had no self-clearing path, so the roles with the most learning
100
+ * were the ones that had silently stopped learning.
92
101
  */
93
- export declare function canCaptureNewLearned(role: string, existingSize: number, isManual: boolean, projectRoot?: string): string | undefined;
102
+ export declare function canCaptureNewLearned(role: string, _existingSize: number, isManual: boolean, projectRoot?: string): string | undefined;
94
103
  /**
95
104
  * Per-role learning stats for monitoring UIs.
96
105
  */
@@ -116,6 +125,10 @@ export interface ProjectAgentLearnStats {
116
125
  isConsolidated: boolean;
117
126
  /** Consolidation metadata, if a consolidation has been performed. */
118
127
  consolidation?: ConsolidationMetadata | undefined;
128
+ /** Skills this project has developed a dedicated addendum for. */
129
+ skills: string[];
130
+ /** Directives already routed to a skill and awaiting distillation. */
131
+ skilledEntryCount: number;
119
132
  }
120
133
  export declare function getProjectAgentLearnStats(role: string, projectRoot?: string): ProjectAgentLearnStats;
121
134
  /**
@@ -3,8 +3,14 @@
3
3
  */
4
4
  export declare function tokenOverlap(a: string, b: string): number;
5
5
  /**
6
- * Split an existing learned.md body into individual entries.
7
- * Entries are delimited by `---\n\n` sequences.
6
+ * Split a **legacy** learned.md body into individual entries.
7
+ *
8
+ * Entries are delimited by `---` runs, which is only meaningful for the old
9
+ * append-only journal format. The structured document uses `---` exactly once
10
+ * (before its footer), so this function returns 2 chunks for any structured
11
+ * buffer regardless of how many directives it holds. Callers that need a real
12
+ * entry count must use `parseStructuredLearnedEntries` — this one exists only
13
+ * to migrate pre-structured files.
8
14
  */
9
15
  export declare function splitLearnedEntries(body: string): string[];
10
16
  //# sourceMappingURL=project-agent-learning-entries.d.ts.map
@@ -12,10 +12,21 @@ export interface StructuredLearnedEntry {
12
12
  what: string;
13
13
  /** Why this directive exists — derived from category and directive signals. */
14
14
  why: string;
15
- /** Concrete, runnable anchor — commands, file paths, package names. */
15
+ /**
16
+ * Concrete, runnable anchors — commands, file paths, package names.
17
+ * One anchor per line, WITHOUT any list marker: the renderer owns the
18
+ * markup. Storing markup here is what produced the `- *How:* - *How:*`
19
+ * nesting that compounded on every capture.
20
+ */
16
21
  how: string;
17
22
  /** ISO timestamp of when this entry was originally captured. */
18
23
  capturedAt: string;
24
+ /**
25
+ * Skill this directive develops, when capture could route it. Entries with a
26
+ * skill are distilled into `.wrongstack/agents/<role>/skills/<skill>.md` by
27
+ * the optimization pass; unrouted entries stay role-level.
28
+ */
29
+ skill?: string | undefined;
19
30
  }
20
31
  export declare function parseLearnedEntryStamp(entry: string): {
21
32
  capturedAt: string;
@@ -31,6 +42,21 @@ export declare function mergeStructuredEntries(existing: StructuredLearnedEntry[
31
42
  text: string;
32
43
  category: LearnedEntryCategory;
33
44
  capturedAt: string;
45
+ skill?: string | undefined;
34
46
  }): StructuredLearnedEntry[];
35
47
  export declare function renderLearnedInstructions(role: string, entries: StructuredLearnedEntry[], capturedAt: string): string;
48
+ /**
49
+ * Keep the rendered buffer within `maxBytes` by evicting the least valuable
50
+ * entries — oldest first, plain facts before hard-won warnings.
51
+ *
52
+ * This replaces the old "block every automatic capture once the file passes
53
+ * 8 KB" gate. That gate had no way to ever clear itself (consolidation wrote a
54
+ * separate file and never touched the raw buffer), so the roles that had
55
+ * learned the most were exactly the roles that had permanently stopped
56
+ * learning. Bounding the buffer is the same protection without the deadlock.
57
+ */
58
+ export declare function enforceLearnedBudget(entries: readonly StructuredLearnedEntry[], capturedAt: string, maxBytes: number, role?: string): {
59
+ kept: StructuredLearnedEntry[];
60
+ dropped: StructuredLearnedEntry[];
61
+ };
36
62
  //# sourceMappingURL=project-agent-learning-structured.d.ts.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Learning optimization pass: raw captures → consolidated role document +
3
+ * per-skill project addenda → pruned capture buffer.
4
+ *
5
+ * One implementation, shared by every surface. The CLI used to build the
6
+ * instruction and hand it to the chat loop with nothing on the other end to
7
+ * persist the result, so `/agent-improve <role> consolidate` produced a wall of
8
+ * markdown and no state change; the WebUI had the only working pipeline.
9
+ */
10
+ import type { Provider } from '../../types/index.js';
11
+ /** Resolved model handle used for headless synthesis. */
12
+ export interface LearningOptimizerLlm {
13
+ provider: Provider;
14
+ model: string;
15
+ }
16
+ export interface OptimizeLearningOptions {
17
+ llm?: LearningOptimizerLlm | undefined;
18
+ trigger?: 'manual' | 'automatic' | undefined;
19
+ /** Archive + reset the raw buffer after a successful pass. Default true. */
20
+ prune?: boolean | undefined;
21
+ maxTokens?: number | undefined;
22
+ timeoutMs?: number | undefined;
23
+ signal?: AbortSignal | undefined;
24
+ }
25
+ export interface OptimizeLearningResult {
26
+ role: string;
27
+ status: 'optimized' | 'no-entries' | 'no-llm' | 'empty-synthesis' | 'failed';
28
+ rawEntryCount: number;
29
+ /** Skills whose project addendum was refreshed by this pass. */
30
+ skills: string[];
31
+ content?: string | undefined;
32
+ model?: string | undefined;
33
+ pruned?: boolean | undefined;
34
+ /** Present on `no-llm`: the caller may drive the pass through a chat agent. */
35
+ instruction?: string | undefined;
36
+ error?: string | undefined;
37
+ }
38
+ /** Strip a whole-document code fence a model sometimes wraps output in. */
39
+ export declare function unwrapWholeDocumentFence(text: string): string;
40
+ /**
41
+ * Run the full optimization pass for one role.
42
+ *
43
+ * Without an LLM the pass degrades rather than failing: the role-level
44
+ * instruction is returned for a caller-driven consolidation, and each skill
45
+ * still gets a deterministically rendered addendum from its routed directives,
46
+ * so tagged learning reaches the skill layer even on a headless box.
47
+ */
48
+ export declare function optimizeProjectAgentLearning(role: string, projectRoot?: string, options?: OptimizeLearningOptions): Promise<OptimizeLearningResult>;
49
+ //# sourceMappingURL=project-agent-optimizer.d.ts.map
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Project-specific **skill development** layer for roster agents.
3
+ *
4
+ * This is deliberately not a memory store. A roster agent's skills are what it
5
+ * knows how to *do*; this layer lets a project grow those skills in place — the
6
+ * bundled `testing` skill body, plus everything this project has taught the
7
+ * `verifier` agent about testing *here*. The addendum is injected directly
8
+ * beneath the bundled skill body at spawn time, so the agent reads one coherent
9
+ * skill rather than a skill plus a pile of recalled facts.
10
+ *
11
+ * Files under `.wrongstack/agents/<role>/skills/`:
12
+ * `<skill>.md` — project addendum for that skill (distilled, bounded)
13
+ * `affinity.json` — per-skill load/outcome/learning counters that drive which
14
+ * skills are eagerly loaded for this role in this project
15
+ *
16
+ * Ownership: capture routes each learned directive to a skill
17
+ * (`project-agent-identity.ts`); the optimization pass distills the routed
18
+ * directives into `<skill>.md`; the spawn path reads both
19
+ * (`packages/cli/src/fleet/host-context.ts`).
20
+ */
21
+ /** Hard cap on a single skill addendum. Keeps the spawn budget predictable. */
22
+ export declare const SKILL_AUGMENTATION_MAX_BYTES = 6144;
23
+ /** Default number of skills eagerly loaded into a spawn. */
24
+ export declare const DEFAULT_EAGER_SKILL_LIMIT = 3;
25
+ export declare function isProjectSkillName(name: string): boolean;
26
+ export declare function assertProjectSkillName(name: string): string;
27
+ export declare function projectSkillsDir(role: string, projectRoot?: string): string;
28
+ export declare function projectSkillAugmentationPath(role: string, skill: string, projectRoot?: string): string;
29
+ export declare function projectSkillAffinityPath(role: string, projectRoot?: string): string;
30
+ export declare function loadProjectSkillAugmentation(role: string, skill: string, projectRoot?: string): string;
31
+ export declare function saveProjectSkillAugmentation(role: string, skill: string, content: string, projectRoot?: string): string;
32
+ export declare function clearProjectSkillAugmentation(role: string, skill?: string, projectRoot?: string): void;
33
+ /** Skill names that have a project addendum for this role. */
34
+ export declare function listProjectSkillAugmentations(role: string, projectRoot?: string): string[];
35
+ /**
36
+ * Render a distilled skill addendum. Used as the deterministic fallback when
37
+ * no LLM is available — the directives are already instructive, so emitting
38
+ * them verbatim under a stable header is strictly better than no addendum.
39
+ */
40
+ export declare function renderSkillAugmentation(role: string, skill: string, directives: readonly string[], updatedAt: string): string;
41
+ /**
42
+ * Instruction for the optimization pass: turn the directives that capture
43
+ * routed to one skill into that skill's project addendum.
44
+ */
45
+ export declare function buildSkillDistillInstruction(role: string, skill: string, directives: readonly string[], existing?: string): string;
46
+ export interface SkillAffinityEntry {
47
+ /** Times this skill was eagerly loaded into a spawn of this role. */
48
+ loaded: number;
49
+ /** Task outcomes observed while this skill was loaded. */
50
+ succeeded: number;
51
+ failed: number;
52
+ /** Learned directives routed to this skill. */
53
+ learned: number;
54
+ lastUsedAt?: string | undefined;
55
+ /** Operator pin — always selected, never rotated out. */
56
+ pinned?: boolean | undefined;
57
+ }
58
+ export interface SkillAffinity {
59
+ role: string;
60
+ entries: Record<string, SkillAffinityEntry>;
61
+ updatedAt: string;
62
+ }
63
+ export declare function loadSkillAffinity(role: string, projectRoot?: string): SkillAffinity;
64
+ /** Record that these skills were loaded into a spawn of `role`. */
65
+ export declare function recordSkillLoad(role: string, skills: readonly string[], projectRoot?: string): void;
66
+ /** Record the outcome of a task that ran with these skills loaded. */
67
+ export declare function recordSkillOutcome(role: string, skills: readonly string[], ok: boolean, projectRoot?: string): void;
68
+ /** Record that a learned directive was routed to this skill. */
69
+ export declare function recordSkillLearned(role: string, skill: string, projectRoot?: string): void;
70
+ export declare function setSkillPinned(role: string, skill: string, pinned: boolean, projectRoot?: string): SkillAffinity;
71
+ /**
72
+ * Score a skill for this role. Higher wins. Deterministic and monotone:
73
+ * with no recorded history every candidate scores the same, so ranking falls
74
+ * back to the curated order and behaviour matches a fresh project exactly.
75
+ */
76
+ export declare function scoreSkillAffinity(entry: SkillAffinityEntry | undefined): number;
77
+ /**
78
+ * Rank the candidate skills for a role by project affinity, keeping the
79
+ * curated order as a stable tie-break, and return at most `limit` names.
80
+ *
81
+ * A skill that has accumulated project-specific learning outranks one that has
82
+ * not: the whole point of the layer is that a skill the project actually
83
+ * developed is more valuable here than a generic sibling.
84
+ */
85
+ export declare function rankRoleSkills(role: string, candidates: readonly string[], projectRoot?: string, limit?: number): string[];
86
+ /**
87
+ * Every skill this role could legitimately develop in this project:
88
+ * the project override when present, otherwise the curated catalog set (or the
89
+ * base role's set for a project-created role), always unioned with any skill
90
+ * that already carries a project addendum.
91
+ */
92
+ export declare function resolveRoleSkillCandidates(role: string, projectRoot?: string): string[];
93
+ /** Explicit tag form the agent can use: `## LEARNED [skill: testing]`. */
94
+ export declare const LEARNED_SKILL_TAG: RegExp;
95
+ /**
96
+ * Route a captured directive to one of the role's candidate skills.
97
+ * Returns `undefined` when nothing matches well enough — an unrouted directive
98
+ * stays role-level rather than being forced into the wrong skill.
99
+ */
100
+ export declare function routeDirectiveToSkill(text: string, candidates: readonly string[]): string | undefined;
101
+ //# sourceMappingURL=project-agent-skill-layer.d.ts.map
@@ -97,6 +97,16 @@ export declare const ROLE_SKILL_SETS: {
97
97
  export type CatalogRoleWithSkills = keyof typeof ROLE_SKILL_SETS;
98
98
  /** Standalone operational role that lives outside the phase catalog. */
99
99
  export declare const SHADOW_AGENT_SKILLS: ("api-design" | "audit-log" | "bug-hunter" | "chimera" | "data-governance" | "docker-deploy" | "git-flow" | "mnemosyne" | "multi-agent" | "node-modern" | "observability" | "output-standards" | "plugin-author" | "prompt-engineering" | "react-modern" | "refactor-planner" | "research-web" | "sdd" | "security-scanner" | "skill-creator" | "tech-stack" | "testing" | "typescript-strict" | "wrongstack-mailbox")[];
100
- /** Attach a bounded, fresh skill-name array so catalog templates remain mutation-safe. */
100
+ export declare const MAX_EAGER_ROSTER_SKILLS = 3;
101
+ /**
102
+ * Attach a bounded, fresh skill-name array so catalog templates remain
103
+ * mutation-safe.
104
+ *
105
+ * `skillNames` stays capped at `MAX_EAGER_ROSTER_SKILLS` — it is the default
106
+ * eager set for a project with no learning history. The full curated set is
107
+ * also carried as `skillPool` so the spawn path can rank *all* candidates by
108
+ * project affinity instead of being permanently limited to whichever three
109
+ * happened to be written first in this file.
110
+ */
101
111
  export declare function assignSkillsToAgents(definitions: readonly AgentDefinition[]): AgentDefinition[];
102
112
  //# sourceMappingURL=role-skills.d.ts.map
@@ -1,6 +1,6 @@
1
1
  export { createMessage, InMemoryAgentBridge, InMemoryBridgeTransport, } from './agent-bridge.js';
2
2
  export { type AgentFactory, type AgentFactoryResult, type AgentRunnerOptions, makeAgentSubagentRunner, withDisabledToolFiltering, } from './agent-subagent-runner.js';
3
- export { AGENT_CATALOG, AGENTS_BY_PHASE, type AgentBudgetTier, type AgentCapability, type AgentDefinition, type AgentPhase, ALL_AGENT_DEFINITIONS, applyProjectAgentConfig, assertProjectAgentRole, BUILD_AGENTS, buildConsolidationInstruction, buildProjectContextualizedPrompt, CAPTURE_COOLDOWN_MS, CAPTURE_MAX_PER_SESSION, type ConsolidationMetadata, type CreateProjectAgentInput, canCaptureNewLearned, captureLearnedFromAgentOutput, captureLearnedFromAgentOutputDetailed, clearProjectAgentConsolidated, createProjectAgent, createProjectAgentRoster, DELIVERY_AGENTS, DISCOVERY_AGENTS, DOMAIN_AGENTS, detectLearnedConflicts, getAgentDefinition, getProjectAgentLearnStats, HEAVY_BUDGET, hintLearnedNeedsSummarization, isConsolidated, KNOWLEDGE_AGENTS, LEARNED_HARD_LIMIT, LEARNED_SOFT_LIMIT, type LearnedCaptureResult, LIGHT_BUDGET, listProjectAgentLearnedEntries, listProjectAgentRoles, loadConsolidationMetadata, loadProjectAgentConfig, loadProjectAgentConsolidated, loadProjectAgentIdentity, loadProjectAgentLearned, loadProjectAgentLearningPolicy, loadProjectAgentProfile, loadRoleKnowledgeManifest, MEDIUM_BUDGET, META_AGENTS, PLANNING_AGENTS, type ProjectAgentConfig, type ProjectAgentLearningPolicy, type ProjectAgentProfile, REVIEW_AGENTS, type RoleKnowledgeManifest, refreshProjectAgentIdentity, resetProjectAgentIdentity, saveProjectAgentConsolidated, slugifyProjectAgentRole, updateProjectAgentConfig, updateProjectAgentIdentity, updateProjectAgentKnowledge, updateProjectAgentLearned, updateProjectAgentLearningPolicy, VERIFY_AGENTS, validateProjectAgentConfig, } from './agents/index.js';
3
+ export { AGENT_CATALOG, AGENTS_BY_PHASE, type AgentBudgetTier, type AgentCapability, type AgentDefinition, type AgentPhase, ALL_AGENT_DEFINITIONS, applyProjectAgentConfig, assertProjectAgentRole, BUILD_AGENTS, buildConsolidationInstruction, buildProjectContextualizedPrompt, buildSkillDistillInstruction, CAPTURE_COOLDOWN_MS, CAPTURE_MAX_PER_SESSION, CAPTURE_SESSION_WINDOW_MS, type ConsolidationMetadata, type CreateProjectAgentInput, canCaptureNewLearned, captureLearnedFromAgentOutput, captureLearnedFromAgentOutputDetailed, clearProjectAgentConsolidated, clearProjectSkillAugmentation, createProjectAgent, createProjectAgentRoster, DEFAULT_EAGER_SKILL_LIMIT, DELIVERY_AGENTS, DISCOVERY_AGENTS, DOMAIN_AGENTS, detectLearnedConflicts, getAgentDefinition, getProjectAgentLearnStats, HEAVY_BUDGET, hintLearnedNeedsSummarization, isConsolidated, KNOWLEDGE_AGENTS, LEARNED_HARD_LIMIT, LEARNED_SOFT_LIMIT, type LearnedCaptureResult, type AutoOptimizeDecision, type AutoOptimizeEvent, type AutoOptimizePolicy, type AutoOptimizePolicyOverrides, DEFAULT_AUTO_OPTIMIZE_POLICY, evaluateAutoOptimize, LearningOptimizationScheduler, type LearningOptimizationSchedulerOptions, resolveAutoOptimizePolicy, type LearningOptimizerLlm, LIGHT_BUDGET, type OptimizeLearningOptions, type OptimizeLearningResult, optimizeProjectAgentLearning, unwrapWholeDocumentFence, listProjectAgentLearnedEntries, listProjectAgentRoles, listProjectSkillAugmentations, loadConsolidationMetadata, loadProjectAgentConfig, loadProjectAgentConsolidated, loadProjectAgentIdentity, loadProjectAgentLearned, loadProjectAgentLearningPolicy, loadProjectAgentProfile, loadProjectSkillAugmentation, loadRoleKnowledgeManifest, loadSkillAffinity, MEDIUM_BUDGET, META_AGENTS, PLANNING_AGENTS, type ProjectAgentConfig, type ProjectAgentLearningPolicy, type ProjectAgentProfile, REVIEW_AGENTS, type RoleKnowledgeManifest, rankRoleSkills, readRawLearnedEntries, recordSkillLoad, recordSkillOutcome, refreshProjectAgentIdentity, renderSkillAugmentation, resetCaptureWindow, resetCaptureWindows, resetProjectAgentIdentity, resolveRoleSkillCandidates, routeDirectiveToSkill, SKILL_AUGMENTATION_MAX_BYTES, type SaveConsolidationOptions, type SkillAffinity, type SkillAffinityEntry, saveProjectAgentConsolidated, saveProjectSkillAugmentation, setSkillPinned, slugifyProjectAgentRole, updateProjectAgentConfig, updateProjectAgentIdentity, updateProjectAgentKnowledge, updateProjectAgentLearned, updateProjectAgentLearningPolicy, VERIFY_AGENTS, validateProjectAgentConfig, } from './agents/index.js';
4
4
  export { type AutoExtendCeiling, type AutoExtendPolicy, attachAutoExtend, } from './auto-extend.js';
5
5
  export { type BrainArbiter, type BrainDecision, type BrainDecisionOption, BrainDecisionQueue, type BrainDecisionRequest, type BrainDecisionSource, type BrainEscalationMode, type BrainFallback, type BrainRisk, DefaultBrainArbiter, type DefaultBrainArbiterOptions, EscalationRoutingBrainArbiter, formatHumanPrompt, HumanEscalatingBrainArbiter, ObservableBrainArbiter, terminalPolicyDecision, } from './brain.js';
6
6
  export { BrainDecisionLedger, type BrainDecisionLedgerOptions, type BrainLedgerEntry, brainDecisionKey, createLedgerGuardBrainArbiter, type LedgerGuardBrainArbiterOptions, } from './brain-ledger.js';