zam-core 0.3.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/.claude/skills/zam/SKILL.md +331 -0
- package/.gemini/skills/zam/SKILL.md +335 -0
- package/LICENSE +199 -0
- package/README.de.md +86 -0
- package/README.md +86 -0
- package/dist/cli/index.js +3661 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +998 -0
- package/dist/index.js +1920 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
import { Database } from 'libsql';
|
|
2
|
+
|
|
3
|
+
interface ConnectionOptions {
|
|
4
|
+
/** Path to the SQLite database file. Defaults to ~/.zam/zam.db */
|
|
5
|
+
dbPath?: string;
|
|
6
|
+
/** If true, create the directory and run schema migrations on open */
|
|
7
|
+
initialize?: boolean;
|
|
8
|
+
/** Turso sync URL for cloud replication (e.g. libsql://db-name.turso.io) */
|
|
9
|
+
syncUrl?: string;
|
|
10
|
+
/** Turso auth token for cloud replication */
|
|
11
|
+
authToken?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Open (or create) the ZAM database.
|
|
15
|
+
* Uses WAL mode for concurrent access from AI CLI and user CLI.
|
|
16
|
+
* When syncUrl is provided, enables embedded replica sync with Turso.
|
|
17
|
+
*/
|
|
18
|
+
declare function openDatabase(options?: ConnectionOptions): Database;
|
|
19
|
+
/**
|
|
20
|
+
* Open the database with Turso cloud sync auto-detected from stored settings.
|
|
21
|
+
* Reads turso.url and turso.token from user_config. If present, reopens
|
|
22
|
+
* the database with embedded replica sync enabled.
|
|
23
|
+
*/
|
|
24
|
+
declare function openDatabaseWithSync(options?: Omit<ConnectionOptions, "syncUrl" | "authToken">): Database;
|
|
25
|
+
/** Get the default database path */
|
|
26
|
+
declare function getDefaultDbPath(): string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Token repository — typed wrappers around the tokens table.
|
|
30
|
+
*
|
|
31
|
+
* Tokens are atomic knowledge concepts with Bloom taxonomy levels
|
|
32
|
+
* and optional symbiosis modes (shadowing / copilot / autonomy).
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
type BloomLevel$1 = 1 | 2 | 3 | 4 | 5;
|
|
36
|
+
type SymbiosisMode = "shadowing" | "copilot" | "autonomy";
|
|
37
|
+
interface Token {
|
|
38
|
+
id: string;
|
|
39
|
+
slug: string;
|
|
40
|
+
concept: string;
|
|
41
|
+
domain: string;
|
|
42
|
+
bloom_level: BloomLevel$1;
|
|
43
|
+
context: string;
|
|
44
|
+
symbiosis_mode: SymbiosisMode | null;
|
|
45
|
+
created_at: string;
|
|
46
|
+
updated_at: string;
|
|
47
|
+
deprecated_at: string | null;
|
|
48
|
+
}
|
|
49
|
+
interface CreateTokenInput {
|
|
50
|
+
slug: string;
|
|
51
|
+
concept: string;
|
|
52
|
+
domain?: string;
|
|
53
|
+
bloom_level?: BloomLevel$1;
|
|
54
|
+
context?: string;
|
|
55
|
+
symbiosis_mode?: SymbiosisMode | null;
|
|
56
|
+
}
|
|
57
|
+
interface ListTokensOptions {
|
|
58
|
+
domain?: string;
|
|
59
|
+
}
|
|
60
|
+
interface ScoredToken extends Token {
|
|
61
|
+
score: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a new knowledge token.
|
|
65
|
+
* Throws if a token with the same slug already exists.
|
|
66
|
+
*/
|
|
67
|
+
declare function createToken(db: Database, input: CreateTokenInput): Token;
|
|
68
|
+
/**
|
|
69
|
+
* Look up a token by its unique slug.
|
|
70
|
+
* Returns undefined if not found.
|
|
71
|
+
*/
|
|
72
|
+
declare function getTokenBySlug(db: Database, slug: string): Token | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Look up a token by its ULID.
|
|
75
|
+
* Returns undefined if not found.
|
|
76
|
+
*/
|
|
77
|
+
declare function getTokenById(db: Database, id: string): Token | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Mark a token as deprecated. Deprecated tokens are excluded from review queues
|
|
80
|
+
* and search results but are not deleted — they can still be consulted.
|
|
81
|
+
*
|
|
82
|
+
* Throws if the token does not exist or is already deprecated.
|
|
83
|
+
*/
|
|
84
|
+
declare function deprecateToken(db: Database, slug: string): Token;
|
|
85
|
+
/**
|
|
86
|
+
* Fuzzy search for tokens by keyword query.
|
|
87
|
+
*
|
|
88
|
+
* Ported from the PoC's find-token command: splits the query into word
|
|
89
|
+
* tokens, scores each database token by word overlap plus a substring
|
|
90
|
+
* bonus on the concept field, and returns all matches sorted by score
|
|
91
|
+
* descending.
|
|
92
|
+
*/
|
|
93
|
+
declare function findTokens(db: Database, query: string): ScoredToken[];
|
|
94
|
+
/**
|
|
95
|
+
* List all tokens, optionally filtered by domain.
|
|
96
|
+
* Results are ordered by bloom_level then slug.
|
|
97
|
+
*/
|
|
98
|
+
declare function listTokens(db: Database, options?: ListTokensOptions): Token[];
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Prerequisite repository — typed wrappers around the prerequisites table.
|
|
102
|
+
*
|
|
103
|
+
* Models the dependency graph: "to learn token A, first know token B."
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
interface Prerequisite {
|
|
107
|
+
token_id: string;
|
|
108
|
+
requires_id: string;
|
|
109
|
+
}
|
|
110
|
+
/** A prerequisite row joined with the token it points to. */
|
|
111
|
+
interface PrerequisiteWithToken extends Prerequisite {
|
|
112
|
+
slug: string;
|
|
113
|
+
concept: string;
|
|
114
|
+
domain: string;
|
|
115
|
+
bloom_level: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Add a prerequisite edge: tokenId requires requiresId.
|
|
119
|
+
*
|
|
120
|
+
* Idempotent — silently ignores duplicate edges.
|
|
121
|
+
* Throws if either token ID does not exist (FK constraint).
|
|
122
|
+
* Throws if a token is declared as its own prerequisite.
|
|
123
|
+
*/
|
|
124
|
+
declare function addPrerequisite(db: Database, tokenId: string, requiresId: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Get the direct prerequisites of a token — "what does token X require?"
|
|
127
|
+
*
|
|
128
|
+
* Returns prerequisite rows joined with the required token's details.
|
|
129
|
+
*/
|
|
130
|
+
declare function getPrerequisites(db: Database, tokenId: string): PrerequisiteWithToken[];
|
|
131
|
+
/**
|
|
132
|
+
* Get the direct dependents of a token — "what depends on token X?"
|
|
133
|
+
*
|
|
134
|
+
* Returns prerequisite rows joined with the dependent token's details.
|
|
135
|
+
*/
|
|
136
|
+
declare function getDependents(db: Database, tokenId: string): PrerequisiteWithToken[];
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Card repository — typed wrappers around the cards table.
|
|
140
|
+
*
|
|
141
|
+
* Each card tracks one user's scheduling state for one token,
|
|
142
|
+
* using FSRS fields (stability, difficulty, elapsed_days, etc.).
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
type CardState$1 = "new" | "learning" | "review" | "relearning";
|
|
146
|
+
interface Card {
|
|
147
|
+
id: string;
|
|
148
|
+
token_id: string;
|
|
149
|
+
user_id: string;
|
|
150
|
+
stability: number;
|
|
151
|
+
difficulty: number;
|
|
152
|
+
elapsed_days: number;
|
|
153
|
+
scheduled_days: number;
|
|
154
|
+
reps: number;
|
|
155
|
+
lapses: number;
|
|
156
|
+
state: CardState$1;
|
|
157
|
+
due_at: string;
|
|
158
|
+
last_review_at: string | null;
|
|
159
|
+
blocked: number;
|
|
160
|
+
}
|
|
161
|
+
interface UpdateCardInput {
|
|
162
|
+
stability?: number;
|
|
163
|
+
difficulty?: number;
|
|
164
|
+
elapsed_days?: number;
|
|
165
|
+
scheduled_days?: number;
|
|
166
|
+
reps?: number;
|
|
167
|
+
lapses?: number;
|
|
168
|
+
state?: CardState$1;
|
|
169
|
+
due_at?: string;
|
|
170
|
+
last_review_at?: string | null;
|
|
171
|
+
blocked?: number;
|
|
172
|
+
}
|
|
173
|
+
/** A due card joined with its token details. */
|
|
174
|
+
interface DueCard extends Card {
|
|
175
|
+
slug: string;
|
|
176
|
+
concept: string;
|
|
177
|
+
domain: string;
|
|
178
|
+
bloom_level: number;
|
|
179
|
+
}
|
|
180
|
+
/** A blocked card joined with its token details. */
|
|
181
|
+
interface BlockedCard extends Card {
|
|
182
|
+
slug: string;
|
|
183
|
+
concept: string;
|
|
184
|
+
domain: string;
|
|
185
|
+
bloom_level: number;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Ensure a card exists for the given token+user pair.
|
|
189
|
+
*
|
|
190
|
+
* If one already exists, return it. Otherwise create a new card with
|
|
191
|
+
* default FSRS values (due immediately) and return it.
|
|
192
|
+
*
|
|
193
|
+
* Ported from the PoC's ensureCard helper.
|
|
194
|
+
*/
|
|
195
|
+
declare function ensureCard(db: Database, tokenId: string, userId: string): Card;
|
|
196
|
+
/**
|
|
197
|
+
* Get a card by token+user. Returns undefined if no card exists.
|
|
198
|
+
*/
|
|
199
|
+
declare function getCard(db: Database, tokenId: string, userId: string): Card | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* Update a card's scheduling fields.
|
|
202
|
+
*
|
|
203
|
+
* Only the fields present in `updates` are changed. Throws if the card
|
|
204
|
+
* does not exist.
|
|
205
|
+
*/
|
|
206
|
+
declare function updateCard(db: Database, cardId: string, updates: UpdateCardInput): Card;
|
|
207
|
+
/**
|
|
208
|
+
* Get all cards that are due for review.
|
|
209
|
+
*
|
|
210
|
+
* A card is due when it is not blocked and due_at <= now.
|
|
211
|
+
* Results are ordered by bloom_level ascending (fundamentals first),
|
|
212
|
+
* then by due_at ascending (oldest first).
|
|
213
|
+
*
|
|
214
|
+
* Ported from the PoC's due-tokens command.
|
|
215
|
+
*/
|
|
216
|
+
declare function getDueCards(db: Database, userId: string, now?: string): DueCard[];
|
|
217
|
+
/**
|
|
218
|
+
* Get all blocked cards for a user.
|
|
219
|
+
*
|
|
220
|
+
* Returns cards joined with their token details so the caller can
|
|
221
|
+
* see what is waiting and why.
|
|
222
|
+
*/
|
|
223
|
+
declare function getBlockedCards(db: Database, userId: string): BlockedCard[];
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Review log repository — typed wrappers around the review_logs table.
|
|
227
|
+
*
|
|
228
|
+
* The review log is immutable: every rating event is appended, never
|
|
229
|
+
* updated or deleted. This provides a complete audit trail of a user's
|
|
230
|
+
* learning history.
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
interface ReviewLog {
|
|
234
|
+
id: string;
|
|
235
|
+
card_id: string;
|
|
236
|
+
token_id: string;
|
|
237
|
+
user_id: string;
|
|
238
|
+
rating: number;
|
|
239
|
+
response_time_ms: number | null;
|
|
240
|
+
reviewed_at: string;
|
|
241
|
+
scheduled_at: string;
|
|
242
|
+
session_id: string | null;
|
|
243
|
+
}
|
|
244
|
+
interface CreateReviewInput {
|
|
245
|
+
card_id: string;
|
|
246
|
+
token_id: string;
|
|
247
|
+
user_id: string;
|
|
248
|
+
rating: number;
|
|
249
|
+
scheduled_at: string;
|
|
250
|
+
response_time_ms?: number | null;
|
|
251
|
+
session_id?: string | null;
|
|
252
|
+
}
|
|
253
|
+
interface ListReviewsOptions {
|
|
254
|
+
/** Maximum number of reviews to return. */
|
|
255
|
+
limit?: number;
|
|
256
|
+
/** Return reviews after this ISO timestamp. */
|
|
257
|
+
after?: string;
|
|
258
|
+
/** Return reviews before this ISO timestamp. */
|
|
259
|
+
before?: string;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Log an immutable review event.
|
|
263
|
+
*
|
|
264
|
+
* Validates that the rating is between 1 and 4 (matching the schema CHECK).
|
|
265
|
+
* Returns the created review log entry.
|
|
266
|
+
*/
|
|
267
|
+
declare function logReview(db: Database, input: CreateReviewInput): ReviewLog;
|
|
268
|
+
/**
|
|
269
|
+
* Get all reviews for a specific card, ordered by reviewed_at ascending.
|
|
270
|
+
*/
|
|
271
|
+
declare function getReviewsForCard(db: Database, cardId: string): ReviewLog[];
|
|
272
|
+
/**
|
|
273
|
+
* Get reviews for a user, with optional filtering.
|
|
274
|
+
*
|
|
275
|
+
* Results are ordered by reviewed_at descending (most recent first).
|
|
276
|
+
*/
|
|
277
|
+
declare function getReviewsForUser(db: Database, userId: string, options?: ListReviewsOptions): ReviewLog[];
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Session repository — typed wrappers around sessions and session_steps.
|
|
281
|
+
*
|
|
282
|
+
* A session represents a work+learning episode. Steps within a session
|
|
283
|
+
* record which tokens were touched and by whom (user or agent).
|
|
284
|
+
*/
|
|
285
|
+
|
|
286
|
+
type ExecutionContext = "shell" | "ui" | "reallife";
|
|
287
|
+
interface Session {
|
|
288
|
+
id: string;
|
|
289
|
+
user_id: string;
|
|
290
|
+
task: string;
|
|
291
|
+
execution_context: ExecutionContext;
|
|
292
|
+
started_at: string;
|
|
293
|
+
completed_at: string | null;
|
|
294
|
+
}
|
|
295
|
+
interface SessionStep {
|
|
296
|
+
id: string;
|
|
297
|
+
session_id: string;
|
|
298
|
+
token_id: string;
|
|
299
|
+
done_by: "user" | "agent";
|
|
300
|
+
rating: number | null;
|
|
301
|
+
notes: string | null;
|
|
302
|
+
created_at: string;
|
|
303
|
+
}
|
|
304
|
+
interface CreateSessionInput {
|
|
305
|
+
user_id: string;
|
|
306
|
+
task: string;
|
|
307
|
+
execution_context?: ExecutionContext;
|
|
308
|
+
}
|
|
309
|
+
interface LogStepInput {
|
|
310
|
+
session_id: string;
|
|
311
|
+
token_id: string;
|
|
312
|
+
done_by: "user" | "agent";
|
|
313
|
+
rating?: number | null;
|
|
314
|
+
notes?: string | null;
|
|
315
|
+
}
|
|
316
|
+
/** A step joined with its token details, returned by getSessionSummary. */
|
|
317
|
+
interface StepWithToken extends SessionStep {
|
|
318
|
+
slug: string;
|
|
319
|
+
concept: string;
|
|
320
|
+
domain: string;
|
|
321
|
+
bloom_level: number;
|
|
322
|
+
}
|
|
323
|
+
interface SessionSummary {
|
|
324
|
+
session: Session;
|
|
325
|
+
steps: StepWithToken[];
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Start a new session. Returns the created session.
|
|
329
|
+
*
|
|
330
|
+
* Ported from the PoC's start-session command.
|
|
331
|
+
*/
|
|
332
|
+
declare function startSession(db: Database, input: CreateSessionInput): Session;
|
|
333
|
+
/**
|
|
334
|
+
* End a session by setting its completed_at timestamp.
|
|
335
|
+
*
|
|
336
|
+
* Throws if the session does not exist or is already completed.
|
|
337
|
+
*
|
|
338
|
+
* Ported from the PoC's end-session command.
|
|
339
|
+
*/
|
|
340
|
+
declare function endSession(db: Database, sessionId: string): Session;
|
|
341
|
+
/**
|
|
342
|
+
* Log a step within a session.
|
|
343
|
+
*
|
|
344
|
+
* Validates that done_by is 'user' or 'agent' and that the rating
|
|
345
|
+
* (if provided) is between 1 and 4.
|
|
346
|
+
*
|
|
347
|
+
* Ported from the PoC's log-step command.
|
|
348
|
+
*/
|
|
349
|
+
declare function logStep(db: Database, input: LogStepInput): SessionStep;
|
|
350
|
+
/**
|
|
351
|
+
* Get a full session summary: the session record plus all steps
|
|
352
|
+
* joined with their token details.
|
|
353
|
+
*
|
|
354
|
+
* Ported from the PoC's session-summary command.
|
|
355
|
+
* Throws if the session does not exist.
|
|
356
|
+
*/
|
|
357
|
+
declare function getSessionSummary(db: Database, sessionId: string): SessionSummary;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Agent skills: task recipes the agent learns from user guidance.
|
|
361
|
+
*
|
|
362
|
+
* When the agent cannot execute a step, it admits it, asks for guidance,
|
|
363
|
+
* and saves the successful approach here. Skills are linked to tokens so
|
|
364
|
+
* FSRS decay naturally resurfaces them for review — automation ≠ retention.
|
|
365
|
+
*/
|
|
366
|
+
|
|
367
|
+
type SkillSource = "learned" | "builtin";
|
|
368
|
+
interface AgentSkill {
|
|
369
|
+
id: string;
|
|
370
|
+
slug: string;
|
|
371
|
+
description: string;
|
|
372
|
+
steps: string[];
|
|
373
|
+
token_slugs: string[];
|
|
374
|
+
source: SkillSource;
|
|
375
|
+
created_at: string;
|
|
376
|
+
updated_at: string;
|
|
377
|
+
}
|
|
378
|
+
interface CreateAgentSkillInput {
|
|
379
|
+
slug: string;
|
|
380
|
+
description: string;
|
|
381
|
+
steps: string[];
|
|
382
|
+
token_slugs?: string[];
|
|
383
|
+
source?: SkillSource;
|
|
384
|
+
}
|
|
385
|
+
declare function createAgentSkill(db: Database, input: CreateAgentSkillInput): AgentSkill;
|
|
386
|
+
declare function getAgentSkill(db: Database, slug: string): AgentSkill | undefined;
|
|
387
|
+
declare function listAgentSkills(db: Database): AgentSkill[];
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* User settings — key/value store backed by the user_config table.
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
interface UserSetting {
|
|
394
|
+
key: string;
|
|
395
|
+
value: string;
|
|
396
|
+
updated_at: string;
|
|
397
|
+
}
|
|
398
|
+
/** Get a single setting by key. Returns undefined if not set. */
|
|
399
|
+
declare function getSetting(db: Database, key: string): string | undefined;
|
|
400
|
+
/** Get all settings as a key-value map. */
|
|
401
|
+
declare function getAllSettings(db: Database): Record<string, string>;
|
|
402
|
+
/** Get all settings with metadata. */
|
|
403
|
+
declare function getAllSettingsDetailed(db: Database): UserSetting[];
|
|
404
|
+
/** Set a setting (insert or update). */
|
|
405
|
+
declare function setSetting(db: Database, key: string, value: string): void;
|
|
406
|
+
/** Delete a setting. Returns true if it existed. */
|
|
407
|
+
declare function deleteSetting(db: Database, key: string): boolean;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* FSRS-5 — Free Spaced Repetition Scheduler (v5)
|
|
411
|
+
*
|
|
412
|
+
* Pure-function implementation of the FSRS algorithm that replaces
|
|
413
|
+
* the PoC's SM-2 scheduler. This is the mathematical heart of ZAM's
|
|
414
|
+
* spaced-repetition engine.
|
|
415
|
+
*
|
|
416
|
+
* Reference: https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Algorithm
|
|
417
|
+
*/
|
|
418
|
+
/** 1 = Again (forgot), 2 = Hard, 3 = Good, 4 = Easy */
|
|
419
|
+
type Rating = 1 | 2 | 3 | 4;
|
|
420
|
+
type CardState = "new" | "learning" | "review" | "relearning";
|
|
421
|
+
interface SchedulingCard {
|
|
422
|
+
/** Memory stability in days — expected half-life of recall probability. */
|
|
423
|
+
stability: number;
|
|
424
|
+
/** Intrinsic difficulty on a 1–10 scale. */
|
|
425
|
+
difficulty: number;
|
|
426
|
+
/** Days elapsed since the last review. */
|
|
427
|
+
elapsedDays: number;
|
|
428
|
+
/** Currently scheduled interval in days. */
|
|
429
|
+
scheduledDays: number;
|
|
430
|
+
/** Count of successful consecutive reviews. */
|
|
431
|
+
reps: number;
|
|
432
|
+
/** Times the card was forgotten (rated Again). */
|
|
433
|
+
lapses: number;
|
|
434
|
+
/** Current learning state. */
|
|
435
|
+
state: CardState;
|
|
436
|
+
/** When the card is next due. */
|
|
437
|
+
dueAt: Date;
|
|
438
|
+
/** When the card was last reviewed (null for new cards). */
|
|
439
|
+
lastReviewAt: Date | null;
|
|
440
|
+
}
|
|
441
|
+
interface FSRSParameters {
|
|
442
|
+
/** 19 optimised weight parameters (w0 – w18). */
|
|
443
|
+
w: number[];
|
|
444
|
+
/** Target retention rate, e.g. 0.9 means we aim for 90% recall. */
|
|
445
|
+
requestRetention: number;
|
|
446
|
+
}
|
|
447
|
+
interface FSRS {
|
|
448
|
+
/** Return a fully updated card after applying a rating. Pure function. */
|
|
449
|
+
schedule(card: SchedulingCard, rating: Rating, now?: Date): SchedulingCard;
|
|
450
|
+
/** The parameters baked into this instance. */
|
|
451
|
+
readonly params: Readonly<FSRSParameters>;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Create an FSRS scheduler instance.
|
|
455
|
+
*
|
|
456
|
+
* All scheduling is done through pure functions — no side effects,
|
|
457
|
+
* no database access, no mutation of the input card.
|
|
458
|
+
*/
|
|
459
|
+
declare function createFSRS(params?: Partial<FSRSParameters>): FSRS;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Cascade Block & Unblock — prerequisite-aware blocking logic.
|
|
463
|
+
*
|
|
464
|
+
* Ported from the PoC's cascade-block and unblock-ready commands.
|
|
465
|
+
*
|
|
466
|
+
* When a user rates a token as "forgot" (rating 1) and that token has
|
|
467
|
+
* prerequisites, we block the token and surface its prerequisites into
|
|
468
|
+
* the active deck. When all prerequisites are met, we unblock.
|
|
469
|
+
*/
|
|
470
|
+
|
|
471
|
+
interface CascadeBlockResult {
|
|
472
|
+
blockedSlug: string;
|
|
473
|
+
prerequisites: Array<{
|
|
474
|
+
slug: string;
|
|
475
|
+
concept: string;
|
|
476
|
+
bloomLevel: number;
|
|
477
|
+
}>;
|
|
478
|
+
}
|
|
479
|
+
interface UnblockResult {
|
|
480
|
+
unblocked: Array<{
|
|
481
|
+
slug: string;
|
|
482
|
+
concept: string;
|
|
483
|
+
}>;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Block a token and surface its prerequisites.
|
|
487
|
+
*
|
|
488
|
+
* Called when a user rates a token as "forgot" (rating 1). The token is
|
|
489
|
+
* marked as blocked so it won't appear in review queues. All direct
|
|
490
|
+
* prerequisites are ensured to have cards (unblocked, due now) so they
|
|
491
|
+
* appear in the user's next review session.
|
|
492
|
+
*
|
|
493
|
+
* @param db - Database connection
|
|
494
|
+
* @param userId - The user whose card to block
|
|
495
|
+
* @param tokenSlug - Slug of the token the user forgot
|
|
496
|
+
* @returns Info about what was blocked and which prerequisites were surfaced
|
|
497
|
+
*/
|
|
498
|
+
declare function cascadeBlock(db: Database, userId: string, tokenSlug: string): CascadeBlockResult;
|
|
499
|
+
/**
|
|
500
|
+
* Scan all blocked cards for a user and unblock any whose prerequisites are met.
|
|
501
|
+
*
|
|
502
|
+
* A blocked card is ready to unblock when ALL of its direct prerequisites have:
|
|
503
|
+
* - reps >= 1 (the user has successfully recalled it at least once)
|
|
504
|
+
* - blocked = 0 (the prerequisite itself is not blocked)
|
|
505
|
+
*
|
|
506
|
+
* If a blocked card has no prerequisites at all, it is unblocked immediately
|
|
507
|
+
* (it was likely blocked in error or its prerequisites were removed).
|
|
508
|
+
*
|
|
509
|
+
* @param db - Database connection
|
|
510
|
+
* @param userId - The user whose blocked cards to check
|
|
511
|
+
* @returns List of cards that were unblocked
|
|
512
|
+
*/
|
|
513
|
+
declare function unblockReady(db: Database, userId: string): UnblockResult;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Reorder items so no domain appears more than `maxConsecutive` times in a row.
|
|
517
|
+
*
|
|
518
|
+
* Algorithm: group items by domain, then round-robin across domain groups.
|
|
519
|
+
* Each round picks one item from each non-exhausted domain. Within a domain,
|
|
520
|
+
* the original order is preserved (so urgency sorting survives).
|
|
521
|
+
*
|
|
522
|
+
* If a domain has more items than others, its extras will appear after all
|
|
523
|
+
* other domains are exhausted — but the `maxConsecutive` cap is still
|
|
524
|
+
* respected by inserting items from the largest remaining domains first.
|
|
525
|
+
*
|
|
526
|
+
* @param items - Array of items to interleave. Not mutated.
|
|
527
|
+
* @param maxConsecutive - Max consecutive items from the same domain. Defaults to 2.
|
|
528
|
+
* @returns A new array with the same items in interleaved order.
|
|
529
|
+
*/
|
|
530
|
+
declare function interleave<T extends {
|
|
531
|
+
domain: string;
|
|
532
|
+
}>(items: T[], maxConsecutive?: number): T[];
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Review Queue Builder — assembles a session's review queue.
|
|
536
|
+
*
|
|
537
|
+
* Combines due-card fetching, new-card selection, urgency sorting,
|
|
538
|
+
* and cross-domain interleaving into a single ready-to-review queue.
|
|
539
|
+
*/
|
|
540
|
+
|
|
541
|
+
interface ReviewQueueOptions {
|
|
542
|
+
userId: string;
|
|
543
|
+
maxNew?: number;
|
|
544
|
+
maxReviews?: number;
|
|
545
|
+
now?: Date;
|
|
546
|
+
}
|
|
547
|
+
interface ReviewQueueItem {
|
|
548
|
+
cardId: string;
|
|
549
|
+
tokenId: string;
|
|
550
|
+
slug: string;
|
|
551
|
+
concept: string;
|
|
552
|
+
domain: string;
|
|
553
|
+
bloomLevel: number;
|
|
554
|
+
state: string;
|
|
555
|
+
dueAt: string;
|
|
556
|
+
}
|
|
557
|
+
interface ReviewQueue {
|
|
558
|
+
items: ReviewQueueItem[];
|
|
559
|
+
newCount: number;
|
|
560
|
+
reviewCount: number;
|
|
561
|
+
relearnCount: number;
|
|
562
|
+
totalDomains: string[];
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Build a review queue for a user's study session.
|
|
566
|
+
*
|
|
567
|
+
* The queue is assembled in stages:
|
|
568
|
+
* 1. Fetch all due cards (not blocked, due_at <= now, state in review/relearning/learning)
|
|
569
|
+
* 2. Fetch new cards (state = 'new', not blocked) up to maxNew
|
|
570
|
+
* 3. Sort overdue cards by urgency — most overdue first
|
|
571
|
+
* 4. Apply cross-domain interleaving to prevent same-domain streaks
|
|
572
|
+
* 5. Intersperse new cards at regular intervals (every 5th position)
|
|
573
|
+
* 6. Cap total at maxReviews
|
|
574
|
+
*
|
|
575
|
+
* @param db - Database connection
|
|
576
|
+
* @param options - Queue building options
|
|
577
|
+
* @returns The assembled review queue with metadata
|
|
578
|
+
*/
|
|
579
|
+
declare function buildReviewQueue(db: Database, options: ReviewQueueOptions): ReviewQueue;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Active Recall Prompt Generation
|
|
583
|
+
*
|
|
584
|
+
* Generates review prompts from tokens, adapting the question style
|
|
585
|
+
* to the token's Bloom taxonomy level. This is NOT an LLM call —
|
|
586
|
+
* it's template-based prompt assembly for the CLI and bridge.
|
|
587
|
+
*/
|
|
588
|
+
type BloomLevel = 1 | 2 | 3 | 4 | 5;
|
|
589
|
+
interface RecallPrompt {
|
|
590
|
+
cardId: string;
|
|
591
|
+
tokenId: string;
|
|
592
|
+
slug: string;
|
|
593
|
+
question: string;
|
|
594
|
+
concept: string;
|
|
595
|
+
domain: string;
|
|
596
|
+
bloomLevel: BloomLevel;
|
|
597
|
+
bloomVerb: string;
|
|
598
|
+
hints: string[];
|
|
599
|
+
}
|
|
600
|
+
interface PromptInput {
|
|
601
|
+
cardId: string;
|
|
602
|
+
tokenId: string;
|
|
603
|
+
slug: string;
|
|
604
|
+
concept: string;
|
|
605
|
+
domain: string;
|
|
606
|
+
bloomLevel: BloomLevel;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Generate a recall prompt for a token at its Bloom level.
|
|
610
|
+
* When called from the CLI, the prompt is rendered in the terminal.
|
|
611
|
+
* When called from the AI bridge, the JSON is returned for the AI to present conversationally.
|
|
612
|
+
*/
|
|
613
|
+
declare function generatePrompt(input: PromptInput): RecallPrompt;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Rating Evaluator
|
|
617
|
+
*
|
|
618
|
+
* Processes a user's self-assessment rating after a recall attempt.
|
|
619
|
+
* Coordinates between FSRS scheduling, review logging, and blocking.
|
|
620
|
+
*/
|
|
621
|
+
|
|
622
|
+
interface EvaluateInput {
|
|
623
|
+
cardId: string;
|
|
624
|
+
tokenId: string;
|
|
625
|
+
userId: string;
|
|
626
|
+
rating: Rating;
|
|
627
|
+
sessionId?: string;
|
|
628
|
+
responseTimeMs?: number;
|
|
629
|
+
}
|
|
630
|
+
interface EvaluateResult {
|
|
631
|
+
nextDueAt: string;
|
|
632
|
+
stability: number;
|
|
633
|
+
difficulty: number;
|
|
634
|
+
state: string;
|
|
635
|
+
scheduledDays: number;
|
|
636
|
+
reps: number;
|
|
637
|
+
lapses: number;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Process a rating: update the card via FSRS, log the review.
|
|
641
|
+
* Returns the updated scheduling state.
|
|
642
|
+
*
|
|
643
|
+
* Note: blocking logic (cascade-block) is handled separately by the caller
|
|
644
|
+
* when rating === 1 and the token has prerequisites.
|
|
645
|
+
*/
|
|
646
|
+
declare function evaluateRating(db: Database, input: EvaluateInput): EvaluateResult;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Learning Analytics
|
|
650
|
+
*
|
|
651
|
+
* Progress statistics, competence tracking, and session summaries.
|
|
652
|
+
* Ported from PoC's `stats` command with additions for FSRS and symbiosis modes.
|
|
653
|
+
*/
|
|
654
|
+
|
|
655
|
+
interface UserStats {
|
|
656
|
+
userId: string;
|
|
657
|
+
totalTokens: number;
|
|
658
|
+
cardsInDeck: number;
|
|
659
|
+
dueToday: number;
|
|
660
|
+
blocked: number;
|
|
661
|
+
mature: number;
|
|
662
|
+
avgStability: number | null;
|
|
663
|
+
totalSessions: number;
|
|
664
|
+
lastSession: string | null;
|
|
665
|
+
}
|
|
666
|
+
interface DomainCompetence {
|
|
667
|
+
domain: string;
|
|
668
|
+
totalCards: number;
|
|
669
|
+
matureCards: number;
|
|
670
|
+
avgStability: number;
|
|
671
|
+
retentionRate: number;
|
|
672
|
+
suggestedMode: "shadowing" | "copilot" | "autonomy";
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Get overall learning stats for a user (ported from PoC's `stats` command).
|
|
676
|
+
*/
|
|
677
|
+
declare function getUserStats(db: Database, userId: string): UserStats;
|
|
678
|
+
/**
|
|
679
|
+
* Get competence per domain for a user.
|
|
680
|
+
* Used to suggest symbiosis mode transitions.
|
|
681
|
+
*/
|
|
682
|
+
declare function getDomainCompetence(db: Database, userId: string): DomainCompetence[];
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Monitor log analyzer — maps observed shell commands to token ratings.
|
|
686
|
+
*
|
|
687
|
+
* Pure functions, no DB or filesystem access. Takes parsed command records
|
|
688
|
+
* and a token-to-pattern mapping, returns ratings with evidence.
|
|
689
|
+
*/
|
|
690
|
+
interface MonitorEvent {
|
|
691
|
+
type: "command_start" | "command_end" | "monitor_meta";
|
|
692
|
+
ts: string;
|
|
693
|
+
seq?: number;
|
|
694
|
+
pid?: number;
|
|
695
|
+
command?: string;
|
|
696
|
+
cwd?: string;
|
|
697
|
+
exit_code?: number;
|
|
698
|
+
event?: "start" | "stop";
|
|
699
|
+
session_id?: string;
|
|
700
|
+
shell?: string;
|
|
701
|
+
}
|
|
702
|
+
interface CommandRecord {
|
|
703
|
+
seq: number;
|
|
704
|
+
pid: number;
|
|
705
|
+
command: string;
|
|
706
|
+
cwd: string;
|
|
707
|
+
startedAt: string;
|
|
708
|
+
endedAt: string | null;
|
|
709
|
+
durationMs: number | null;
|
|
710
|
+
exitCode: number | null;
|
|
711
|
+
}
|
|
712
|
+
interface TokenPattern {
|
|
713
|
+
slug: string;
|
|
714
|
+
patterns: string[];
|
|
715
|
+
}
|
|
716
|
+
interface ObservationRating {
|
|
717
|
+
tokenSlug: string;
|
|
718
|
+
rating: 1 | 2 | 3 | 4 | null;
|
|
719
|
+
confidence: "high" | "medium" | "low";
|
|
720
|
+
evidence: {
|
|
721
|
+
matchedCommands: number;
|
|
722
|
+
helpSeeking: boolean;
|
|
723
|
+
errorCount: number;
|
|
724
|
+
selfCorrections: number;
|
|
725
|
+
medianGapMs: number | null;
|
|
726
|
+
thinkingGapMs: number | null;
|
|
727
|
+
};
|
|
728
|
+
matchedCommandTexts: string[];
|
|
729
|
+
}
|
|
730
|
+
interface AnalysisResult {
|
|
731
|
+
ratings: ObservationRating[];
|
|
732
|
+
unmatchedCommands: string[];
|
|
733
|
+
timeSpan: {
|
|
734
|
+
start: string;
|
|
735
|
+
end: string;
|
|
736
|
+
durationMs: number;
|
|
737
|
+
} | null;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Parse a JSONL string into MonitorEvent objects.
|
|
741
|
+
* Skips malformed lines silently.
|
|
742
|
+
*/
|
|
743
|
+
declare function parseMonitorLog(jsonl: string): MonitorEvent[];
|
|
744
|
+
/**
|
|
745
|
+
* Pair command_start and command_end events by (pid, seq) into CommandRecords.
|
|
746
|
+
*/
|
|
747
|
+
declare function pairCommands(events: MonitorEvent[]): CommandRecord[];
|
|
748
|
+
/**
|
|
749
|
+
* Analyze observed commands against token patterns and produce ratings.
|
|
750
|
+
*/
|
|
751
|
+
declare function analyzeObservation(commands: CommandRecord[], tokenPatterns: TokenPattern[]): AnalysisResult;
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Monitor I/O — read/write JSONL files for shell observation.
|
|
755
|
+
*
|
|
756
|
+
* Monitor logs live at ~/.zam/monitor/<session-id>.jsonl.
|
|
757
|
+
* Separated from analyzer.ts so the analyzer remains pure-function testable.
|
|
758
|
+
*/
|
|
759
|
+
|
|
760
|
+
/** Get the monitor directory path. */
|
|
761
|
+
declare function getMonitorDir(): string;
|
|
762
|
+
/** Get the JSONL file path for a session. */
|
|
763
|
+
declare function getMonitorPath(sessionId: string): string;
|
|
764
|
+
/** Ensure the monitor directory exists (mode 0700 for privacy). */
|
|
765
|
+
declare function ensureMonitorDir(): void;
|
|
766
|
+
/** Append a single event to the session's JSONL file. */
|
|
767
|
+
declare function writeMonitorEvent(sessionId: string, event: MonitorEvent): void;
|
|
768
|
+
/** Read and parse all events from a session's monitor log. */
|
|
769
|
+
declare function readMonitorLog(sessionId: string): MonitorEvent[];
|
|
770
|
+
/** Check if a monitor log exists for a session. */
|
|
771
|
+
declare function monitorLogExists(sessionId: string): boolean;
|
|
772
|
+
/** Get basic stats about a monitor log without full parsing. */
|
|
773
|
+
declare function getMonitorLogStats(sessionId: string): {
|
|
774
|
+
exists: boolean;
|
|
775
|
+
sizeBytes: number;
|
|
776
|
+
lineCount: number;
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Shell hook code generation for zsh and bash.
|
|
781
|
+
*
|
|
782
|
+
* Pure functions that return shell code strings. The CLI command
|
|
783
|
+
* `zam monitor start/stop` calls these and prints to stdout.
|
|
784
|
+
* The user wraps with `eval "$(zam monitor start ...)"`.
|
|
785
|
+
*/
|
|
786
|
+
/**
|
|
787
|
+
* Generate zsh hooks that capture commands to a JSONL file.
|
|
788
|
+
* Uses $EPOCHREALTIME for sub-second timestamp precision.
|
|
789
|
+
*/
|
|
790
|
+
declare function generateZshHooks(monitorFile: string, sessionId: string): string;
|
|
791
|
+
/**
|
|
792
|
+
* Generate bash hooks that capture commands to a JSONL file.
|
|
793
|
+
* Uses DEBUG trap for preexec, PROMPT_COMMAND for precmd.
|
|
794
|
+
*/
|
|
795
|
+
declare function generateBashHooks(monitorFile: string, sessionId: string): string;
|
|
796
|
+
/** Generate zsh code to remove monitor hooks. */
|
|
797
|
+
declare function generateZshUnhooks(): string;
|
|
798
|
+
/** Generate bash code to remove monitor hooks. */
|
|
799
|
+
declare function generateBashUnhooks(): string;
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Skill Discovery — identifies recurring non-standard command patterns
|
|
803
|
+
* across multiple sessions and proposes them as minimal reusable skills.
|
|
804
|
+
*
|
|
805
|
+
* The key insight from Increment 2: "The human's demonstrated competence
|
|
806
|
+
* is the gate for automation — not the other way around." A pattern must
|
|
807
|
+
* appear consistently across sessions before being proposed as a skill.
|
|
808
|
+
*
|
|
809
|
+
* Pure functions — no DB access. Callers provide command records and
|
|
810
|
+
* existing skills; this module returns proposed skills.
|
|
811
|
+
*/
|
|
812
|
+
|
|
813
|
+
interface CommandSequence {
|
|
814
|
+
/** The ordered command prefixes forming the pattern (e.g., ["git checkout", "npm install", "npm run build"]) */
|
|
815
|
+
steps: string[];
|
|
816
|
+
/** How many sessions contained this sequence */
|
|
817
|
+
sessionCount: number;
|
|
818
|
+
/** Total occurrences across all sessions */
|
|
819
|
+
totalOccurrences: number;
|
|
820
|
+
/** Example full commands from the most recent occurrence */
|
|
821
|
+
examples: string[];
|
|
822
|
+
}
|
|
823
|
+
interface SkillProposal {
|
|
824
|
+
/** Suggested slug for the skill */
|
|
825
|
+
slug: string;
|
|
826
|
+
/** Human-readable description of what the pattern does */
|
|
827
|
+
description: string;
|
|
828
|
+
/** The command steps forming the skill */
|
|
829
|
+
steps: string[];
|
|
830
|
+
/** How many sessions demonstrated this pattern */
|
|
831
|
+
sessionCount: number;
|
|
832
|
+
/** Confidence that this is a real, repeatable skill */
|
|
833
|
+
confidence: "high" | "medium" | "low";
|
|
834
|
+
/** Example commands from actual usage */
|
|
835
|
+
examples: string[];
|
|
836
|
+
}
|
|
837
|
+
interface DiscoveryOptions {
|
|
838
|
+
/** Minimum number of sessions a pattern must appear in (default: 2) */
|
|
839
|
+
minSessions?: number;
|
|
840
|
+
/** Minimum sequence length to consider (default: 2) */
|
|
841
|
+
minSequenceLength?: number;
|
|
842
|
+
/** Maximum sequence length to consider (default: 5) */
|
|
843
|
+
maxSequenceLength?: number;
|
|
844
|
+
/** Existing skill slugs to exclude from proposals */
|
|
845
|
+
existingSkillSlugs?: string[];
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Discover recurring command patterns across multiple sessions.
|
|
849
|
+
*
|
|
850
|
+
* Takes a map of session ID → command records, finds command sequences
|
|
851
|
+
* that appear in multiple sessions, and proposes them as skills.
|
|
852
|
+
*
|
|
853
|
+
* @param sessionCommands - Map of session ID to that session's commands
|
|
854
|
+
* @param options - Discovery configuration
|
|
855
|
+
* @returns Array of skill proposals, sorted by confidence then session count
|
|
856
|
+
*/
|
|
857
|
+
declare function discoverSkills(sessionCommands: Map<string, CommandRecord[]>, options?: DiscoveryOptions): SkillProposal[];
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Goal file parser — reads markdown files with YAML-style frontmatter.
|
|
861
|
+
*
|
|
862
|
+
* Goals are persisted as markdown files in the personal repo.
|
|
863
|
+
* Each file has simple key: value frontmatter (no nested structures)
|
|
864
|
+
* and a markdown body with description, tasks, and token references.
|
|
865
|
+
*/
|
|
866
|
+
type GoalStatus = "active" | "completed" | "paused" | "abandoned";
|
|
867
|
+
interface Goal {
|
|
868
|
+
slug: string;
|
|
869
|
+
title: string;
|
|
870
|
+
status: GoalStatus;
|
|
871
|
+
parent: string | null;
|
|
872
|
+
created: string;
|
|
873
|
+
updated: string;
|
|
874
|
+
body: string;
|
|
875
|
+
filePath: string;
|
|
876
|
+
}
|
|
877
|
+
interface GoalFrontmatter {
|
|
878
|
+
title?: string;
|
|
879
|
+
status?: string;
|
|
880
|
+
parent?: string;
|
|
881
|
+
created?: string;
|
|
882
|
+
updated?: string;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Parse a goal markdown file into a Goal object.
|
|
886
|
+
*
|
|
887
|
+
* Expected format:
|
|
888
|
+
* ```
|
|
889
|
+
* ---
|
|
890
|
+
* title: Learn Rust fundamentals
|
|
891
|
+
* status: active
|
|
892
|
+
* parent: become-systems-programmer
|
|
893
|
+
* created: 2026-03-28
|
|
894
|
+
* updated: 2026-03-28
|
|
895
|
+
* ---
|
|
896
|
+
*
|
|
897
|
+
* ## Description
|
|
898
|
+
* ...
|
|
899
|
+
* ```
|
|
900
|
+
*
|
|
901
|
+
* @param content - Raw file content
|
|
902
|
+
* @param slug - Goal slug (derived from filename by caller)
|
|
903
|
+
* @param filePath - Absolute path to the file
|
|
904
|
+
*/
|
|
905
|
+
declare function parseGoalFile(content: string, slug: string, filePath: string): Goal;
|
|
906
|
+
/**
|
|
907
|
+
* Serialize a Goal back to markdown with frontmatter.
|
|
908
|
+
*/
|
|
909
|
+
declare function serializeGoal(goal: Goal): string;
|
|
910
|
+
/**
|
|
911
|
+
* Extract tasks (checklist items) from goal body.
|
|
912
|
+
* Returns items like { text: "Complete Rustlings", done: false }.
|
|
913
|
+
*/
|
|
914
|
+
declare function extractTasks(body: string): Array<{
|
|
915
|
+
text: string;
|
|
916
|
+
done: boolean;
|
|
917
|
+
}>;
|
|
918
|
+
/**
|
|
919
|
+
* Extract token references from goal body.
|
|
920
|
+
* Looks for lines like `- token/slug` under a "## Tokens" section.
|
|
921
|
+
*/
|
|
922
|
+
declare function extractTokenRefs(body: string): string[];
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Goal Engine — manages goal lifecycle via markdown files.
|
|
926
|
+
*
|
|
927
|
+
* Goals live as markdown files in a directory (typically the personal repo's
|
|
928
|
+
* goals/ folder). The engine reads, creates, and updates these files.
|
|
929
|
+
* It does not depend on the database — goals are git-tracked, not DB-tracked.
|
|
930
|
+
*/
|
|
931
|
+
|
|
932
|
+
interface GoalSummary {
|
|
933
|
+
slug: string;
|
|
934
|
+
title: string;
|
|
935
|
+
status: GoalStatus;
|
|
936
|
+
parent: string | null;
|
|
937
|
+
taskCount: number;
|
|
938
|
+
tasksDone: number;
|
|
939
|
+
tokenCount: number;
|
|
940
|
+
}
|
|
941
|
+
interface CreateGoalInput {
|
|
942
|
+
slug: string;
|
|
943
|
+
title: string;
|
|
944
|
+
status?: GoalStatus;
|
|
945
|
+
parent?: string;
|
|
946
|
+
description?: string;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* List all goals in the goals directory.
|
|
950
|
+
* Returns summaries sorted by status (active first) then title.
|
|
951
|
+
*/
|
|
952
|
+
declare function listGoals(goalsDir: string): GoalSummary[];
|
|
953
|
+
/**
|
|
954
|
+
* Get a single goal by slug (filename without .md).
|
|
955
|
+
* Returns undefined if the file doesn't exist.
|
|
956
|
+
*/
|
|
957
|
+
declare function getGoal(goalsDir: string, slug: string): Goal | undefined;
|
|
958
|
+
/**
|
|
959
|
+
* Create a new goal file. Throws if a goal with this slug already exists.
|
|
960
|
+
*/
|
|
961
|
+
declare function createGoal(goalsDir: string, input: CreateGoalInput): Goal;
|
|
962
|
+
/**
|
|
963
|
+
* Update a goal's status. Writes the updated file back to disk.
|
|
964
|
+
*/
|
|
965
|
+
declare function updateGoalStatus(goalsDir: string, slug: string, status: GoalStatus): Goal;
|
|
966
|
+
/**
|
|
967
|
+
* Get the goal tree — goals organized by parent relationships.
|
|
968
|
+
* Returns root goals (no parent) with nested children.
|
|
969
|
+
*/
|
|
970
|
+
declare function getGoalTree(goalsDir: string): Array<GoalSummary & {
|
|
971
|
+
children: GoalSummary[];
|
|
972
|
+
}>;
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* Azure DevOps connector — fetches work items from ADO boards.
|
|
976
|
+
*/
|
|
977
|
+
|
|
978
|
+
interface ADOConfig {
|
|
979
|
+
orgUrl: string;
|
|
980
|
+
project: string;
|
|
981
|
+
pat: string;
|
|
982
|
+
}
|
|
983
|
+
interface WorkItem {
|
|
984
|
+
id: number;
|
|
985
|
+
title: string;
|
|
986
|
+
state: string;
|
|
987
|
+
type: string;
|
|
988
|
+
assignedTo: string;
|
|
989
|
+
}
|
|
990
|
+
/** Load ADO config from user settings. Returns null if not configured. */
|
|
991
|
+
declare function loadADOConfig(db: Database): ADOConfig | null;
|
|
992
|
+
/**
|
|
993
|
+
* Fetch active work items assigned to the current user.
|
|
994
|
+
* Uses WIQL to query, then batch-fetches work item details.
|
|
995
|
+
*/
|
|
996
|
+
declare function fetchActiveWorkItems(config: ADOConfig): Promise<WorkItem[]>;
|
|
997
|
+
|
|
998
|
+
export { type ADOConfig, type AgentSkill, type AnalysisResult, type BloomLevel$1 as BloomLevel, type Card, type CardState$1 as CardState, type CascadeBlockResult, type CommandRecord, type CommandSequence, type CreateAgentSkillInput, type CreateGoalInput, type CreateReviewInput, type CreateSessionInput, type CreateTokenInput, type DiscoveryOptions, type DomainCompetence, type EvaluateInput, type EvaluateResult, type ExecutionContext, type FSRSParameters, type Goal, type GoalFrontmatter, type GoalStatus, type GoalSummary, type LogStepInput, type MonitorEvent, type ObservationRating, type Prerequisite, type PrerequisiteWithToken, type PromptInput, type Rating, type RecallPrompt, type ReviewLog, type ReviewQueue, type ReviewQueueItem, type ReviewQueueOptions, type SchedulingCard, type Session, type SessionStep, type SessionSummary, type SkillProposal, type SkillSource, type SymbiosisMode, type Token, type TokenPattern, type UnblockResult, type UpdateCardInput, type UserSetting, type UserStats, type WorkItem, addPrerequisite, analyzeObservation, buildReviewQueue, cascadeBlock, createAgentSkill, createFSRS, createGoal, createToken, deleteSetting, deprecateToken, discoverSkills, endSession, ensureCard, ensureMonitorDir, evaluateRating, extractTasks, extractTokenRefs, fetchActiveWorkItems, findTokens, generateBashHooks, generateBashUnhooks, generatePrompt, generateZshHooks, generateZshUnhooks, getAgentSkill, getAllSettings, getAllSettingsDetailed, getBlockedCards, getCard, getDefaultDbPath, getDependents, getDomainCompetence, getDueCards, getGoal, getGoalTree, getMonitorDir, getMonitorLogStats, getMonitorPath, getPrerequisites, getReviewsForCard, getReviewsForUser, getSessionSummary, getSetting, getTokenById, getTokenBySlug, getUserStats, interleave, listAgentSkills, listGoals, listTokens, loadADOConfig, logReview, logStep, monitorLogExists, openDatabase, openDatabaseWithSync, pairCommands, parseGoalFile, parseMonitorLog, readMonitorLog, serializeGoal, setSetting, startSession, unblockReady, updateCard, updateGoalStatus, writeMonitorEvent };
|