codekin 0.4.1 → 0.5.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 (81) hide show
  1. package/README.md +12 -15
  2. package/bin/codekin.mjs +52 -32
  3. package/dist/assets/index-BwKZeT4V.css +1 -0
  4. package/dist/assets/index-CfBnNU24.js +186 -0
  5. package/dist/index.html +2 -2
  6. package/package.json +2 -7
  7. package/server/dist/approval-manager.d.ts +7 -2
  8. package/server/dist/approval-manager.js +44 -78
  9. package/server/dist/approval-manager.js.map +1 -1
  10. package/server/dist/claude-process.d.ts +23 -3
  11. package/server/dist/claude-process.js +120 -27
  12. package/server/dist/claude-process.js.map +1 -1
  13. package/server/dist/commit-event-handler.js.map +1 -1
  14. package/server/dist/config.d.ts +4 -0
  15. package/server/dist/config.js +17 -0
  16. package/server/dist/config.js.map +1 -1
  17. package/server/dist/diff-manager.d.ts +41 -0
  18. package/server/dist/diff-manager.js +303 -0
  19. package/server/dist/diff-manager.js.map +1 -0
  20. package/server/dist/error-page.d.ts +5 -0
  21. package/server/dist/error-page.js +144 -0
  22. package/server/dist/error-page.js.map +1 -0
  23. package/server/dist/native-permissions.d.ts +44 -0
  24. package/server/dist/native-permissions.js +163 -0
  25. package/server/dist/native-permissions.js.map +1 -0
  26. package/server/dist/orchestrator-children.d.ts +74 -0
  27. package/server/dist/orchestrator-children.js +281 -0
  28. package/server/dist/orchestrator-children.js.map +1 -0
  29. package/server/dist/orchestrator-learning.d.ts +134 -0
  30. package/server/dist/orchestrator-learning.js +567 -0
  31. package/server/dist/orchestrator-learning.js.map +1 -0
  32. package/server/dist/orchestrator-manager.d.ts +25 -0
  33. package/server/dist/orchestrator-manager.js +353 -0
  34. package/server/dist/orchestrator-manager.js.map +1 -0
  35. package/server/dist/orchestrator-memory.d.ts +77 -0
  36. package/server/dist/orchestrator-memory.js +288 -0
  37. package/server/dist/orchestrator-memory.js.map +1 -0
  38. package/server/dist/orchestrator-monitor.d.ts +59 -0
  39. package/server/dist/orchestrator-monitor.js +238 -0
  40. package/server/dist/orchestrator-monitor.js.map +1 -0
  41. package/server/dist/orchestrator-reports.d.ts +45 -0
  42. package/server/dist/orchestrator-reports.js +124 -0
  43. package/server/dist/orchestrator-reports.js.map +1 -0
  44. package/server/dist/orchestrator-routes.d.ts +17 -0
  45. package/server/dist/orchestrator-routes.js +526 -0
  46. package/server/dist/orchestrator-routes.js.map +1 -0
  47. package/server/dist/session-archive.js +9 -2
  48. package/server/dist/session-archive.js.map +1 -1
  49. package/server/dist/session-manager.d.ts +99 -39
  50. package/server/dist/session-manager.js +565 -394
  51. package/server/dist/session-manager.js.map +1 -1
  52. package/server/dist/session-naming.d.ts +6 -10
  53. package/server/dist/session-naming.js +60 -62
  54. package/server/dist/session-naming.js.map +1 -1
  55. package/server/dist/session-persistence.d.ts +6 -1
  56. package/server/dist/session-persistence.js +6 -0
  57. package/server/dist/session-persistence.js.map +1 -1
  58. package/server/dist/session-restart-scheduler.d.ts +30 -0
  59. package/server/dist/session-restart-scheduler.js +41 -0
  60. package/server/dist/session-restart-scheduler.js.map +1 -0
  61. package/server/dist/session-routes.js +122 -61
  62. package/server/dist/session-routes.js.map +1 -1
  63. package/server/dist/stepflow-types.d.ts +1 -1
  64. package/server/dist/tsconfig.tsbuildinfo +1 -1
  65. package/server/dist/types.d.ts +34 -2
  66. package/server/dist/types.js +8 -1
  67. package/server/dist/types.js.map +1 -1
  68. package/server/dist/upload-routes.js +7 -1
  69. package/server/dist/upload-routes.js.map +1 -1
  70. package/server/dist/version-check.d.ts +17 -0
  71. package/server/dist/version-check.js +89 -0
  72. package/server/dist/version-check.js.map +1 -0
  73. package/server/dist/workflow-engine.d.ts +74 -1
  74. package/server/dist/workflow-engine.js +20 -1
  75. package/server/dist/workflow-engine.js.map +1 -1
  76. package/server/dist/ws-message-handler.js +115 -9
  77. package/server/dist/ws-message-handler.js.map +1 -1
  78. package/server/dist/ws-server.js +90 -15
  79. package/server/dist/ws-server.js.map +1 -1
  80. package/dist/assets/index-BAdQqYEY.js +0 -182
  81. package/dist/assets/index-CeZYNLWt.css +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-permissions.js","sourceRoot":"","sources":["../native-permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Orchestrator child session manager — spawns, monitors, and reports on
3
+ * implementation sessions created by the orchestrator.
4
+ *
5
+ * Follows the same patterns as workflow-loader.ts for session creation
6
+ * and result polling.
7
+ */
8
+ import type { SessionManager } from './session-manager.js';
9
+ export interface ChildSessionRequest {
10
+ /** Target repository path. */
11
+ repo: string;
12
+ /** Human-readable task description. */
13
+ task: string;
14
+ /** Branch name for the fix. */
15
+ branchName: string;
16
+ /** How changes should land. */
17
+ completionPolicy: 'pr' | 'merge' | 'commit-only';
18
+ /** Whether to deploy after merge. */
19
+ deployAfter: boolean;
20
+ /** Use a git worktree for isolation. */
21
+ useWorktree: boolean;
22
+ /** Timeout in ms (default 10 minutes). */
23
+ timeoutMs?: number;
24
+ /** Optional model override. */
25
+ model?: string;
26
+ }
27
+ export type ChildStatus = 'starting' | 'running' | 'completed' | 'failed' | 'timed_out';
28
+ export interface ChildSession {
29
+ id: string;
30
+ request: ChildSessionRequest;
31
+ status: ChildStatus;
32
+ startedAt: string;
33
+ completedAt: string | null;
34
+ result: string | null;
35
+ error: string | null;
36
+ }
37
+ export declare class OrchestratorChildManager {
38
+ private children;
39
+ private sessions;
40
+ constructor(sessions: SessionManager);
41
+ /** Get all active/recent child sessions. */
42
+ list(): ChildSession[];
43
+ /** Get a child session by ID. */
44
+ get(id: string): ChildSession | null;
45
+ /** Purge completed/failed children older than the retention period. */
46
+ private purgeStaleChildren;
47
+ /** Count currently active (non-terminal) child sessions. */
48
+ activeCount(): number;
49
+ /**
50
+ * Spawn a child session to implement a task in a target repo.
51
+ * Returns the child session info or throws if at capacity.
52
+ */
53
+ spawn(request: ChildSessionRequest): Promise<ChildSession>;
54
+ /**
55
+ * Build a focused task prompt for a child session.
56
+ */
57
+ private buildPrompt;
58
+ /**
59
+ * Monitor a child session until completion or timeout using event hooks.
60
+ * Replaces the old polling loop with SessionManager's onSessionResult and
61
+ * onSessionExit hooks for lower latency and no wasted CPU.
62
+ */
63
+ private monitorChild;
64
+ /**
65
+ * Check whether the session completed the expected final step (PR, push, deploy).
66
+ * If not, send a follow-up instruction and return true so monitoring continues.
67
+ * Only nudges once per child to avoid infinite loops.
68
+ */
69
+ private ensureFinalStep;
70
+ /**
71
+ * Extract assistant text from session output history.
72
+ */
73
+ private extractText;
74
+ }
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Orchestrator child session manager — spawns, monitors, and reports on
3
+ * implementation sessions created by the orchestrator.
4
+ *
5
+ * Follows the same patterns as workflow-loader.ts for session creation
6
+ * and result polling.
7
+ */
8
+ import { randomUUID } from 'crypto';
9
+ import { getAgentDisplayName } from './config.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Constants
12
+ // ---------------------------------------------------------------------------
13
+ const MAX_CONCURRENT = 5;
14
+ const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes
15
+ const CHILD_RETENTION_MS = 3_600_000; // keep completed/failed children for 1 hour
16
+ const MAX_RETAINED_CHILDREN = 100; // hard cap on total entries
17
+ // ---------------------------------------------------------------------------
18
+ // Manager
19
+ // ---------------------------------------------------------------------------
20
+ export class OrchestratorChildManager {
21
+ children = new Map();
22
+ sessions;
23
+ constructor(sessions) {
24
+ this.sessions = sessions;
25
+ }
26
+ /** Get all active/recent child sessions. */
27
+ list() {
28
+ this.purgeStaleChildren();
29
+ return Array.from(this.children.values())
30
+ .sort((a, b) => b.startedAt.localeCompare(a.startedAt));
31
+ }
32
+ /** Get a child session by ID. */
33
+ get(id) {
34
+ return this.children.get(id) ?? null;
35
+ }
36
+ /** Purge completed/failed children older than the retention period. */
37
+ purgeStaleChildren() {
38
+ const now = Date.now();
39
+ for (const [id, child] of this.children) {
40
+ if (child.status === 'starting' || child.status === 'running')
41
+ continue;
42
+ if (child.completedAt && now - new Date(child.completedAt).getTime() > CHILD_RETENTION_MS) {
43
+ this.children.delete(id);
44
+ }
45
+ }
46
+ // Hard cap: if still over limit, remove oldest completed entries
47
+ if (this.children.size > MAX_RETAINED_CHILDREN) {
48
+ const completed = Array.from(this.children.entries())
49
+ .filter(([, c]) => c.status !== 'starting' && c.status !== 'running')
50
+ .sort((a, b) => (a[1].completedAt ?? '').localeCompare(b[1].completedAt ?? ''));
51
+ while (this.children.size > MAX_RETAINED_CHILDREN && completed.length > 0) {
52
+ const [id] = completed.shift();
53
+ this.children.delete(id);
54
+ }
55
+ }
56
+ }
57
+ /** Count currently active (non-terminal) child sessions. */
58
+ activeCount() {
59
+ return Array.from(this.children.values())
60
+ .filter(c => c.status === 'starting' || c.status === 'running')
61
+ .length;
62
+ }
63
+ /**
64
+ * Spawn a child session to implement a task in a target repo.
65
+ * Returns the child session info or throws if at capacity.
66
+ */
67
+ async spawn(request) {
68
+ this.purgeStaleChildren();
69
+ if (this.activeCount() >= MAX_CONCURRENT) {
70
+ throw new Error(`Cannot spawn child session: ${MAX_CONCURRENT} concurrent sessions already running`);
71
+ }
72
+ const sessionId = randomUUID();
73
+ const sessionName = `${getAgentDisplayName().toLowerCase()}:${request.branchName}`;
74
+ const now = new Date().toISOString();
75
+ const child = {
76
+ id: sessionId,
77
+ request,
78
+ status: 'starting',
79
+ startedAt: now,
80
+ completedAt: null,
81
+ result: null,
82
+ error: null,
83
+ };
84
+ this.children.set(sessionId, child);
85
+ try {
86
+ // Create the session
87
+ this.sessions.create(sessionName, request.repo, {
88
+ source: 'agent',
89
+ id: sessionId,
90
+ groupDir: request.repo,
91
+ model: request.model,
92
+ permissionMode: 'acceptEdits',
93
+ allowedTools: ['Bash(curl:*)'],
94
+ });
95
+ // Create a git worktree for isolation if requested (default for Joe children).
96
+ // This must happen BEFORE startClaude so Claude runs in the worktree directory.
97
+ if (request.useWorktree) {
98
+ const wtPath = await this.sessions.createWorktree(sessionId, request.repo);
99
+ if (!wtPath) {
100
+ console.warn(`[orchestrator-child] Failed to create worktree for ${sessionId}, falling back to main directory`);
101
+ }
102
+ }
103
+ // Start Claude
104
+ this.sessions.startClaude(sessionId);
105
+ child.status = 'running';
106
+ // Build and send the task prompt
107
+ const prompt = this.buildPrompt(request);
108
+ this.sessions.sendInput(sessionId, prompt);
109
+ // Monitor completion asynchronously
110
+ void this.monitorChild(child);
111
+ return child;
112
+ }
113
+ catch (err) {
114
+ child.status = 'failed';
115
+ child.error = err instanceof Error ? err.message : String(err);
116
+ child.completedAt = new Date().toISOString();
117
+ return child;
118
+ }
119
+ }
120
+ /**
121
+ * Build a focused task prompt for a child session.
122
+ */
123
+ buildPrompt(request) {
124
+ const lines = [
125
+ `# Task: ${request.task}`,
126
+ '',
127
+ '## Instructions',
128
+ '',
129
+ `You have been spawned by Agent ${getAgentDisplayName()} (the Codekin orchestrator) to implement a specific task in this repository.`,
130
+ '',
131
+ `**Task**: ${request.task}`,
132
+ `**Branch**: Create your changes on branch \`${request.branchName}\``,
133
+ '',
134
+ ];
135
+ if (request.completionPolicy === 'pr') {
136
+ lines.push('## Completion', '', '1. Create a new branch with the name specified above', '2. Make the necessary changes', '3. Commit your changes with a clear commit message', '4. Push the branch and create a Pull Request', '5. Include a clear PR description explaining what was changed and why', '');
137
+ }
138
+ else if (request.completionPolicy === 'merge') {
139
+ lines.push('## Completion', '', '1. Make the necessary changes on the current branch', '2. Commit your changes with a clear commit message', '3. Push directly to the current branch', '');
140
+ }
141
+ else {
142
+ lines.push('## Completion', '', '1. Make the necessary changes', '2. Commit your changes with a clear commit message', '3. Do NOT push — just commit locally', '');
143
+ }
144
+ lines.push('## Guidelines', '', '- Keep changes minimal and focused on the task', '- Do not refactor unrelated code', '- If you encounter issues that block the task, explain what went wrong', '- When done, provide a brief summary of what you changed');
145
+ return lines.join('\n');
146
+ }
147
+ /**
148
+ * Monitor a child session until completion or timeout using event hooks.
149
+ * Replaces the old polling loop with SessionManager's onSessionResult and
150
+ * onSessionExit hooks for lower latency and no wasted CPU.
151
+ */
152
+ async monitorChild(child) {
153
+ const timeoutMs = child.request.timeoutMs ?? DEFAULT_TIMEOUT_MS;
154
+ try {
155
+ await new Promise((resolve) => {
156
+ let settled = false;
157
+ const settle = () => { if (!settled) {
158
+ settled = true;
159
+ resolve();
160
+ } };
161
+ // Timeout handler
162
+ const timer = setTimeout(() => {
163
+ if (settled)
164
+ return;
165
+ child.status = 'timed_out';
166
+ child.error = `Timed out after ${timeoutMs}ms`;
167
+ child.completedAt = new Date().toISOString();
168
+ const session = this.sessions.get(child.id);
169
+ if (session?.claudeProcess?.isAlive()) {
170
+ session.claudeProcess.stop();
171
+ }
172
+ settle();
173
+ }, timeoutMs);
174
+ // Result hook: Claude completed a turn
175
+ const onResult = (sessionId, isError) => {
176
+ if (sessionId !== child.id || settled)
177
+ return;
178
+ const session = this.sessions.get(child.id);
179
+ if (!session) {
180
+ child.status = 'failed';
181
+ child.error = 'Session was deleted';
182
+ child.completedAt = new Date().toISOString();
183
+ clearTimeout(timer);
184
+ settle();
185
+ return;
186
+ }
187
+ const text = this.extractText(session.outputHistory);
188
+ // Check if the final step was done; if not, nudge (keep listening)
189
+ if (this.ensureFinalStep(child, session, text))
190
+ return;
191
+ // Don't mark as completed while the session still has pending
192
+ // tool approvals or control requests — the Claude process may
193
+ // still be alive and blocked on an approval (e.g. git push).
194
+ // Keep monitoring; the next result/exit event will re-evaluate.
195
+ if (session.pendingToolApprovals.size > 0 || session.pendingControlRequests.size > 0)
196
+ return;
197
+ child.status = isError ? 'failed' : 'completed';
198
+ child.result = text || null;
199
+ child.error = isError ? 'Claude returned an error' : null;
200
+ child.completedAt = new Date().toISOString();
201
+ clearTimeout(timer);
202
+ settle();
203
+ };
204
+ // Exit hook: Claude process exited
205
+ const onExit = (sessionId, _code, _signal, willRestart) => {
206
+ if (sessionId !== child.id || settled)
207
+ return;
208
+ if (willRestart)
209
+ return; // Will auto-restart, keep monitoring
210
+ const session = this.sessions.get(child.id);
211
+ const text = session ? this.extractText(session.outputHistory) : '';
212
+ child.status = text.length > 100 ? 'completed' : 'failed';
213
+ child.result = text || null;
214
+ child.error = text.length <= 100 ? 'Claude exited without sufficient output' : null;
215
+ child.completedAt = new Date().toISOString();
216
+ clearTimeout(timer);
217
+ settle();
218
+ };
219
+ this.sessions.onSessionResult(onResult);
220
+ this.sessions.onSessionExit(onExit);
221
+ });
222
+ }
223
+ finally {
224
+ // Safety net: ensure isProcessing is cleared when monitoring ends.
225
+ // handleClaudeResult should have already done this, but edge cases
226
+ // (nudge race, missed result event) can leave the flag stuck.
227
+ this.sessions.clearProcessingFlag(child.id);
228
+ }
229
+ }
230
+ /**
231
+ * Check whether the session completed the expected final step (PR, push, deploy).
232
+ * If not, send a follow-up instruction and return true so monitoring continues.
233
+ * Only nudges once per child to avoid infinite loops.
234
+ */
235
+ ensureFinalStep(child, session, text) {
236
+ // Only nudge once
237
+ if (child._nudged)
238
+ return false;
239
+ const policy = child.request.completionPolicy;
240
+ const lowerText = text.toLowerCase();
241
+ let missing = false;
242
+ let instruction = '';
243
+ if (policy === 'pr') {
244
+ // Check if a PR was created
245
+ const prCreated = lowerText.includes('pull request') || lowerText.includes('created a pr') || lowerText.includes('gh pr create');
246
+ if (!prCreated) {
247
+ missing = true;
248
+ instruction = 'You completed the code changes but did not create a Pull Request. Please push your branch and create a PR now with a clear description of what was changed and why.';
249
+ }
250
+ }
251
+ else if (policy === 'merge') {
252
+ // Check if changes were pushed
253
+ const pushed = lowerText.includes('git push') || lowerText.includes('pushed');
254
+ if (!pushed) {
255
+ missing = true;
256
+ instruction = 'You completed the code changes but did not push them. Please push your changes to the remote now.';
257
+ }
258
+ }
259
+ if (missing && instruction && session.claudeProcess?.isAlive()) {
260
+ child._nudged = true;
261
+ // Mark the result message as superseded so monitoring can ignore it
262
+ // without mutating the outputHistory array (which would break replay)
263
+ const resultMsg = session.outputHistory.find(m => m.type === 'result');
264
+ if (resultMsg)
265
+ resultMsg._superseded = true;
266
+ this.sessions.sendInput(child.id, instruction);
267
+ return true;
268
+ }
269
+ return false;
270
+ }
271
+ /**
272
+ * Extract assistant text from session output history.
273
+ */
274
+ extractText(history) {
275
+ return history
276
+ .filter((m) => m.type === 'output')
277
+ .map(m => m.data)
278
+ .join('');
279
+ }
280
+ }
281
+ //# sourceMappingURL=orchestrator-children.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-children.js","sourceRoot":"","sources":["../orchestrator-children.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Orchestrator self-improving memory — extraction, deduplication, aging,
3
+ * pattern learning, and user skill modeling.
4
+ *
5
+ * This module adds the intelligence layer on top of OrchestratorMemory:
6
+ * - Extracts memory candidates from session interactions
7
+ * - Deduplicates against existing memories using FTS similarity
8
+ * - Ages and decays stale items on a schedule
9
+ * - Tracks finding outcomes to improve future triage
10
+ * - Maintains a user skill model that adapts guidance
11
+ * - Records decisions with outcome tracking
12
+ */
13
+ import { OrchestratorMemory, type MemoryType, type MemoryItem } from './orchestrator-memory.js';
14
+ /** A candidate extracted from a session interaction. */
15
+ export interface MemoryCandidate {
16
+ memoryType: MemoryType;
17
+ title: string;
18
+ content: string;
19
+ scope: string | null;
20
+ tags: string[];
21
+ confidence: number;
22
+ }
23
+ /** Finding outcome — tracks what happened when a finding was acted on or skipped. */
24
+ export interface FindingOutcome {
25
+ findingId: string;
26
+ repo: string;
27
+ category: string;
28
+ severity: string;
29
+ action: 'implemented' | 'skipped' | 'deferred';
30
+ reason: string;
31
+ sessionId: string | null;
32
+ outcome: 'success' | 'failure' | 'pending' | null;
33
+ timestamp: string;
34
+ }
35
+ /** User skill assessment per domain. */
36
+ export interface SkillLevel {
37
+ domain: string;
38
+ level: 'beginner' | 'intermediate' | 'advanced' | 'expert';
39
+ confidence: number;
40
+ signals: string[];
41
+ lastUpdated: string;
42
+ }
43
+ /** A decision record with outcome tracking. */
44
+ export interface DecisionRecord {
45
+ id: string;
46
+ decision: string;
47
+ rationale: string;
48
+ repo: string | null;
49
+ relatedFinding: string | null;
50
+ expectedOutcome: string;
51
+ actualOutcome: string | null;
52
+ outcomeAssessedAt: string | null;
53
+ timestamp: string;
54
+ }
55
+ /**
56
+ * Extract memory candidates from an interaction transcript.
57
+ *
58
+ * This is a rule-based extractor that looks for patterns indicating
59
+ * durable information worth remembering. In future, this could be
60
+ * enhanced with an LLM call for richer extraction.
61
+ */
62
+ export declare function extractMemoryCandidates(userMessage: string, assistantResponse: string, currentRepo: string | null): MemoryCandidate[];
63
+ /**
64
+ * Check if a candidate is a duplicate of an existing memory item.
65
+ * Uses FTS search to find similar items, then compares content overlap.
66
+ */
67
+ export declare function findDuplicate(memory: OrchestratorMemory, candidate: MemoryCandidate, threshold?: number): MemoryItem | null;
68
+ /**
69
+ * Smart upsert: insert candidate if no duplicate exists, update if similar.
70
+ * Returns the memory item ID and whether it was new or updated.
71
+ */
72
+ export declare function smartUpsert(memory: OrchestratorMemory, candidate: MemoryCandidate, sourceRef?: string | null): {
73
+ id: string;
74
+ action: 'inserted' | 'updated' | 'skipped';
75
+ };
76
+ /**
77
+ * Run the aging/decay cycle:
78
+ * 1. Expire items past their TTL
79
+ * 2. Compact old journal entries into monthly summaries
80
+ * 3. Decay confidence of items that haven't been accessed recently
81
+ */
82
+ export declare function runAgingCycle(memory: OrchestratorMemory): {
83
+ expired: number;
84
+ compacted: number;
85
+ decayed: number;
86
+ };
87
+ /**
88
+ * Record the outcome of a finding triage decision.
89
+ */
90
+ export declare function recordFindingOutcome(memory: OrchestratorMemory, outcome: FindingOutcome): string;
91
+ /**
92
+ * Analyze past finding outcomes to compute a triage recommendation.
93
+ * Returns the likely action and confidence based on historical patterns.
94
+ */
95
+ export declare function getTriageRecommendation(memory: OrchestratorMemory, category: string, severity: string, repo: string | null): {
96
+ action: 'implement' | 'skip' | 'defer' | 'unknown';
97
+ confidence: number;
98
+ reason: string;
99
+ };
100
+ /** Load the user's skill profile from disk. */
101
+ export declare function loadSkillProfile(): SkillLevel[];
102
+ /** Save the skill profile to disk. */
103
+ export declare function saveSkillProfile(profile: SkillLevel[]): void;
104
+ /**
105
+ * Update the user's skill level for a domain based on observed signals.
106
+ * Signals are things like: "used advanced git rebase", "asked basic TypeScript question",
107
+ * "configured CI pipeline without help".
108
+ */
109
+ export declare function updateSkillLevel(domain: string, signal: string, indicatedLevel: 'beginner' | 'intermediate' | 'advanced' | 'expert'): SkillLevel;
110
+ /**
111
+ * Get the user's assessed skill level for a domain.
112
+ * Returns null if we have no data for this domain.
113
+ */
114
+ export declare function getSkillLevel(domain: string): SkillLevel | null;
115
+ /**
116
+ * Get a guidance style recommendation based on the user's overall skill profile.
117
+ */
118
+ export declare function getGuidanceStyle(): {
119
+ tone: 'tutorial' | 'collaborative' | 'concise';
120
+ explainLevel: 'detailed' | 'moderate' | 'minimal';
121
+ domains: Record<string, SkillLevel['level']>;
122
+ };
123
+ /**
124
+ * Record a decision with expected outcome.
125
+ */
126
+ export declare function recordDecision(memory: OrchestratorMemory, decision: Omit<DecisionRecord, 'id' | 'timestamp' | 'actualOutcome' | 'outcomeAssessedAt'>): string;
127
+ /**
128
+ * Update a decision's actual outcome.
129
+ */
130
+ export declare function assessDecisionOutcome(memory: OrchestratorMemory, decisionId: string, actualOutcome: string): boolean;
131
+ /**
132
+ * Get decisions that need outcome assessment (older than 7 days, no outcome yet).
133
+ */
134
+ export declare function getPendingOutcomeAssessments(memory: OrchestratorMemory): DecisionRecord[];