friction-log 0.0.0-stage → 0.6.1

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 (113) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/LICENSE +21 -0
  3. package/README.md +98 -2
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +13 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/bilanz.d.ts +23 -0
  8. package/dist/commands/bilanz.js +106 -0
  9. package/dist/commands/bilanz.js.map +1 -0
  10. package/dist/commands/digest.d.ts +36 -0
  11. package/dist/commands/digest.js +288 -0
  12. package/dist/commands/digest.js.map +1 -0
  13. package/dist/commands/export.d.ts +36 -0
  14. package/dist/commands/export.js +118 -0
  15. package/dist/commands/export.js.map +1 -0
  16. package/dist/commands/file.d.ts +18 -0
  17. package/dist/commands/file.js +51 -0
  18. package/dist/commands/file.js.map +1 -0
  19. package/dist/commands/import.d.ts +31 -0
  20. package/dist/commands/import.js +283 -0
  21. package/dist/commands/import.js.map +1 -0
  22. package/dist/commands/init.d.ts +44 -0
  23. package/dist/commands/init.js +256 -0
  24. package/dist/commands/init.js.map +1 -0
  25. package/dist/commands/list.d.ts +16 -0
  26. package/dist/commands/list.js +57 -0
  27. package/dist/commands/list.js.map +1 -0
  28. package/dist/commands/log.d.ts +18 -0
  29. package/dist/commands/log.js +52 -0
  30. package/dist/commands/log.js.map +1 -0
  31. package/dist/commands/rm.d.ts +9 -0
  32. package/dist/commands/rm.js +22 -0
  33. package/dist/commands/rm.js.map +1 -0
  34. package/dist/commands/scan.d.ts +25 -0
  35. package/dist/commands/scan.js +73 -0
  36. package/dist/commands/scan.js.map +1 -0
  37. package/dist/commands/search.d.ts +15 -0
  38. package/dist/commands/search.js +37 -0
  39. package/dist/commands/search.js.map +1 -0
  40. package/dist/commands/sync-export.d.ts +46 -0
  41. package/dist/commands/sync-export.js +80 -0
  42. package/dist/commands/sync-export.js.map +1 -0
  43. package/dist/commands/update.d.ts +12 -0
  44. package/dist/commands/update.js +24 -0
  45. package/dist/commands/update.js.map +1 -0
  46. package/dist/config.d.ts +31 -0
  47. package/dist/config.js +145 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/db.d.ts +81 -0
  50. package/dist/db.js +548 -0
  51. package/dist/db.js.map +1 -0
  52. package/dist/index.d.ts +15 -0
  53. package/dist/index.js +16 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/main.d.ts +1 -0
  56. package/dist/main.js +503 -0
  57. package/dist/main.js.map +1 -0
  58. package/dist/node-guard.d.ts +14 -0
  59. package/dist/node-guard.js +36 -0
  60. package/dist/node-guard.js.map +1 -0
  61. package/dist/paths.d.ts +12 -0
  62. package/dist/paths.js +34 -0
  63. package/dist/paths.js.map +1 -0
  64. package/dist/scanners/claude-code.d.ts +6 -0
  65. package/dist/scanners/claude-code.js +202 -0
  66. package/dist/scanners/claude-code.js.map +1 -0
  67. package/dist/scanners/index.d.ts +4 -0
  68. package/dist/scanners/index.js +12 -0
  69. package/dist/scanners/index.js.map +1 -0
  70. package/dist/sinks/agent-tasks.d.ts +36 -0
  71. package/dist/sinks/agent-tasks.js +153 -0
  72. package/dist/sinks/agent-tasks.js.map +1 -0
  73. package/dist/sinks/github-issues.d.ts +20 -0
  74. package/dist/sinks/github-issues.js +98 -0
  75. package/dist/sinks/github-issues.js.map +1 -0
  76. package/dist/sinks/index.d.ts +11 -0
  77. package/dist/sinks/index.js +48 -0
  78. package/dist/sinks/index.js.map +1 -0
  79. package/dist/sinks/linear.d.ts +25 -0
  80. package/dist/sinks/linear.js +157 -0
  81. package/dist/sinks/linear.js.map +1 -0
  82. package/dist/sinks/markdown-file.d.ts +7 -0
  83. package/dist/sinks/markdown-file.js +54 -0
  84. package/dist/sinks/markdown-file.js.map +1 -0
  85. package/dist/sinks/stdout-json.d.ts +15 -0
  86. package/dist/sinks/stdout-json.js +49 -0
  87. package/dist/sinks/stdout-json.js.map +1 -0
  88. package/dist/templates/auth-expiry.yml +30 -0
  89. package/dist/templates/doc-gap.yml +30 -0
  90. package/dist/templates/output-overflow.yml +25 -0
  91. package/dist/templates/schema-drift.yml +26 -0
  92. package/dist/templates/tool-error.yml +34 -0
  93. package/dist/templates/tool-missing-capability.yml +26 -0
  94. package/dist/templates/workflow-friction.yml +26 -0
  95. package/dist/templates.d.ts +5 -0
  96. package/dist/templates.js +88 -0
  97. package/dist/templates.js.map +1 -0
  98. package/dist/types.d.ts +79 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/docs/commands.md +74 -0
  102. package/docs/design.md +25 -0
  103. package/docs/sinks.md +79 -0
  104. package/docs/storage.md +20 -0
  105. package/docs/sync-export.md +23 -0
  106. package/package.json +64 -4
  107. package/templates/auth-expiry.yml +30 -0
  108. package/templates/doc-gap.yml +30 -0
  109. package/templates/output-overflow.yml +25 -0
  110. package/templates/schema-drift.yml +26 -0
  111. package/templates/tool-error.yml +34 -0
  112. package/templates/tool-missing-capability.yml +26 -0
  113. package/templates/workflow-friction.yml +26 -0
package/dist/db.js ADDED
@@ -0,0 +1,548 @@
1
+ import Database from "better-sqlite3";
2
+ import { mkdirSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ const MIGRATIONS = [
5
+ {
6
+ version: 2,
7
+ sql: `
8
+ -- Add a CHECK constraint on severity so the programmatic API matches
9
+ -- the CLI's commander-choices validation. SQLite can't ALTER ADD
10
+ -- CONSTRAINT, so we recreate the table. Pre-migration we normalize any
11
+ -- rogue values to NULL so the copy doesn't fail.
12
+ UPDATE frictions
13
+ SET severity = NULL
14
+ WHERE severity IS NOT NULL
15
+ AND severity NOT IN ('low', 'medium', 'high', 'critical');
16
+
17
+ CREATE TABLE frictions_new (
18
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
19
+ session_id TEXT REFERENCES sessions(id),
20
+ tool_surface TEXT,
21
+ title TEXT NOT NULL,
22
+ description TEXT,
23
+ captured_at TEXT NOT NULL,
24
+ severity TEXT CHECK(severity IS NULL OR severity IN ('low', 'medium', 'high', 'critical')),
25
+ category TEXT,
26
+ status TEXT NOT NULL DEFAULT 'open',
27
+ recurrence_of_id INTEGER REFERENCES frictions(id),
28
+ source TEXT NOT NULL CHECK(source IN ('scan', 'manual', 'import'))
29
+ );
30
+
31
+ INSERT INTO frictions_new
32
+ (id, session_id, tool_surface, title, description, captured_at, severity, category, status, recurrence_of_id, source)
33
+ SELECT id, session_id, tool_surface, title, description, captured_at, severity, category, status, recurrence_of_id, source
34
+ FROM frictions;
35
+
36
+ DROP TABLE frictions;
37
+ ALTER TABLE frictions_new RENAME TO frictions;
38
+
39
+ -- Indexes and FTS triggers were dropped with the old table; recreate them.
40
+ CREATE INDEX idx_frictions_status ON frictions(status);
41
+ CREATE INDEX idx_frictions_tool ON frictions(tool_surface);
42
+ CREATE INDEX idx_frictions_category ON frictions(category);
43
+ CREATE INDEX idx_frictions_captured ON frictions(captured_at);
44
+
45
+ -- Rebuild the FTS5 shadow rows; the virtual table itself survives the
46
+ -- DROP because it lives in a separate sqlite_master row, but its
47
+ -- content reference is now stale, so refresh it.
48
+ INSERT INTO frictions_fts(frictions_fts) VALUES ('rebuild');
49
+
50
+ CREATE TRIGGER frictions_ai AFTER INSERT ON frictions BEGIN
51
+ INSERT INTO frictions_fts(rowid, title, description)
52
+ VALUES (new.id, new.title, coalesce(new.description, ''));
53
+ END;
54
+
55
+ CREATE TRIGGER frictions_ad AFTER DELETE ON frictions BEGIN
56
+ INSERT INTO frictions_fts(frictions_fts, rowid, title, description)
57
+ VALUES ('delete', old.id, old.title, coalesce(old.description, ''));
58
+ END;
59
+
60
+ CREATE TRIGGER frictions_au AFTER UPDATE ON frictions BEGIN
61
+ INSERT INTO frictions_fts(frictions_fts, rowid, title, description)
62
+ VALUES ('delete', old.id, old.title, coalesce(old.description, ''));
63
+ INSERT INTO frictions_fts(rowid, title, description)
64
+ VALUES (new.id, new.title, coalesce(new.description, ''));
65
+ END;
66
+ `,
67
+ },
68
+ {
69
+ version: 1,
70
+ sql: `
71
+ CREATE TABLE schema_version (
72
+ version INTEGER PRIMARY KEY,
73
+ applied_at TEXT NOT NULL
74
+ );
75
+
76
+ CREATE TABLE sessions (
77
+ id TEXT PRIMARY KEY,
78
+ started_at TEXT NOT NULL,
79
+ ended_at TEXT,
80
+ project_paths TEXT,
81
+ transcript_path TEXT,
82
+ adapter TEXT NOT NULL
83
+ );
84
+
85
+ CREATE TABLE frictions (
86
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
87
+ session_id TEXT REFERENCES sessions(id),
88
+ tool_surface TEXT,
89
+ title TEXT NOT NULL,
90
+ description TEXT,
91
+ captured_at TEXT NOT NULL,
92
+ severity TEXT,
93
+ category TEXT,
94
+ status TEXT NOT NULL DEFAULT 'open',
95
+ recurrence_of_id INTEGER REFERENCES frictions(id),
96
+ source TEXT NOT NULL CHECK(source IN ('scan', 'manual', 'import'))
97
+ );
98
+
99
+ CREATE INDEX idx_frictions_status ON frictions(status);
100
+ CREATE INDEX idx_frictions_tool ON frictions(tool_surface);
101
+ CREATE INDEX idx_frictions_category ON frictions(category);
102
+ CREATE INDEX idx_frictions_captured ON frictions(captured_at);
103
+
104
+ CREATE VIRTUAL TABLE frictions_fts USING fts5(
105
+ title,
106
+ description,
107
+ content='frictions',
108
+ content_rowid='id'
109
+ );
110
+
111
+ CREATE TRIGGER frictions_ai AFTER INSERT ON frictions BEGIN
112
+ INSERT INTO frictions_fts(rowid, title, description)
113
+ VALUES (new.id, new.title, coalesce(new.description, ''));
114
+ END;
115
+
116
+ CREATE TRIGGER frictions_ad AFTER DELETE ON frictions BEGIN
117
+ INSERT INTO frictions_fts(frictions_fts, rowid, title, description)
118
+ VALUES ('delete', old.id, old.title, coalesce(old.description, ''));
119
+ END;
120
+
121
+ CREATE TRIGGER frictions_au AFTER UPDATE ON frictions BEGIN
122
+ INSERT INTO frictions_fts(frictions_fts, rowid, title, description)
123
+ VALUES ('delete', old.id, old.title, coalesce(old.description, ''));
124
+ INSERT INTO frictions_fts(rowid, title, description)
125
+ VALUES (new.id, new.title, coalesce(new.description, ''));
126
+ END;
127
+
128
+ CREATE TABLE tasks (
129
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
130
+ friction_id INTEGER NOT NULL REFERENCES frictions(id),
131
+ sink_name TEXT NOT NULL,
132
+ sink_target TEXT,
133
+ external_ref TEXT,
134
+ created_at TEXT NOT NULL,
135
+ pr_url TEXT,
136
+ resolution_status TEXT
137
+ );
138
+
139
+ CREATE INDEX idx_tasks_friction ON tasks(friction_id);
140
+
141
+ CREATE TABLE tags (
142
+ friction_id INTEGER NOT NULL REFERENCES frictions(id),
143
+ tag TEXT NOT NULL,
144
+ PRIMARY KEY(friction_id, tag)
145
+ );
146
+ `,
147
+ },
148
+ ];
149
+ function rowToFriction(r) {
150
+ return {
151
+ id: r.id,
152
+ sessionId: r.session_id,
153
+ toolSurface: r.tool_surface,
154
+ title: r.title,
155
+ description: r.description,
156
+ capturedAt: r.captured_at,
157
+ severity: r.severity ?? null,
158
+ category: r.category,
159
+ status: r.status,
160
+ recurrenceOfId: r.recurrence_of_id,
161
+ source: r.source,
162
+ };
163
+ }
164
+ function rowToTask(r) {
165
+ return {
166
+ id: r.id,
167
+ frictionId: r.friction_id,
168
+ sinkName: r.sink_name,
169
+ sinkTarget: r.sink_target,
170
+ externalRef: r.external_ref,
171
+ createdAt: r.created_at,
172
+ prUrl: r.pr_url,
173
+ resolutionStatus: r.resolution_status,
174
+ };
175
+ }
176
+ function rowToSession(r) {
177
+ return {
178
+ id: r.id,
179
+ startedAt: r.started_at,
180
+ endedAt: r.ended_at,
181
+ projectPaths: r.project_paths
182
+ ? JSON.parse(r.project_paths)
183
+ : null,
184
+ transcriptPath: r.transcript_path,
185
+ adapter: r.adapter,
186
+ };
187
+ }
188
+ export class FrictionDb {
189
+ db;
190
+ constructor(path) {
191
+ if (path !== ":memory:") {
192
+ mkdirSync(dirname(path), { recursive: true });
193
+ }
194
+ this.db = new Database(path);
195
+ this.db.pragma("journal_mode = WAL");
196
+ this.db.pragma("foreign_keys = ON");
197
+ this.migrate();
198
+ }
199
+ migrate() {
200
+ const hasVersionTable = this.db
201
+ .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'`)
202
+ .get();
203
+ const currentVersion = hasVersionTable
204
+ ? (this.db
205
+ .prepare(`SELECT MAX(version) AS v FROM schema_version`)
206
+ .get()?.v ?? 0)
207
+ : 0;
208
+ const ordered = [...MIGRATIONS].sort((a, b) => a.version - b.version);
209
+ for (const m of ordered) {
210
+ if (m.version <= currentVersion)
211
+ continue;
212
+ // foreign_keys can only be toggled outside a transaction. Some
213
+ // migrations (notably v2's DROP+RENAME on `frictions`) trip incoming
214
+ // FKs from `tasks` and `tags`, so we drop enforcement, run the
215
+ // migration, then re-enable and re-check before moving on.
216
+ this.db.pragma("foreign_keys = OFF");
217
+ try {
218
+ this.db.transaction(() => {
219
+ this.db.exec(m.sql);
220
+ this.db
221
+ .prepare(`INSERT INTO schema_version (version, applied_at) VALUES (?, ?)`)
222
+ .run(m.version, new Date().toISOString());
223
+ })();
224
+ const violations = this.db.pragma("foreign_key_check");
225
+ if (violations.length > 0) {
226
+ throw new Error(`friction-log: migration v${m.version} left orphan foreign keys: ${JSON.stringify(violations)}`);
227
+ }
228
+ }
229
+ finally {
230
+ this.db.pragma("foreign_keys = ON");
231
+ }
232
+ }
233
+ }
234
+ schemaVersion() {
235
+ const row = this.db
236
+ .prepare(`SELECT MAX(version) AS v FROM schema_version`)
237
+ .get();
238
+ return row?.v ?? 0;
239
+ }
240
+ upsertSession(s) {
241
+ this.db
242
+ .prepare(`INSERT INTO sessions (id, started_at, ended_at, project_paths, transcript_path, adapter)
243
+ VALUES (@id, @startedAt, @endedAt, @projectPaths, @transcriptPath, @adapter)
244
+ ON CONFLICT(id) DO UPDATE SET
245
+ ended_at = excluded.ended_at,
246
+ project_paths = excluded.project_paths,
247
+ transcript_path = excluded.transcript_path,
248
+ adapter = excluded.adapter`)
249
+ .run({
250
+ id: s.id,
251
+ startedAt: s.startedAt,
252
+ endedAt: s.endedAt,
253
+ projectPaths: s.projectPaths ? JSON.stringify(s.projectPaths) : null,
254
+ transcriptPath: s.transcriptPath,
255
+ adapter: s.adapter,
256
+ });
257
+ }
258
+ /**
259
+ * Create a minimal sessions row for `id` if none exists yet. Used by
260
+ * the `log` command path so `friction-log log --session <fresh-id>`
261
+ * can attribute a friction to a live runtime session without a prior
262
+ * `friction-log import`. Defaults: started_at = now, adapter =
263
+ * 'manual' (mirrors `frictions.source = 'manual'` for log-path rows).
264
+ * Idempotent: a subsequent `upsertSession` from an `import` or `scan`
265
+ * later overwrites the placeholder with full metadata.
266
+ */
267
+ ensureSession(id) {
268
+ this.db
269
+ .prepare(`INSERT OR IGNORE INTO sessions (id, started_at, adapter)
270
+ VALUES (?, ?, ?)`)
271
+ .run(id, new Date().toISOString(), "manual");
272
+ }
273
+ getSession(id) {
274
+ const row = this.db
275
+ .prepare(`SELECT * FROM sessions WHERE id = ?`)
276
+ .get(id);
277
+ return row ? rowToSession(row) : null;
278
+ }
279
+ insertFriction(input) {
280
+ const capturedAt = input.capturedAt ?? new Date().toISOString();
281
+ // recurrence_of_id semantics (M3 cheap rule): explicit value wins, else
282
+ // auto-link to the oldest open root friction with the same tool_surface
283
+ // and title. The chain always points to a root, so callers reading
284
+ // recurrence_of_id see a stable parent.
285
+ const recurrenceOfId = input.recurrenceOfId ??
286
+ this.findRecurrenceRoot(input.toolSurface ?? null, input.title);
287
+ const result = this.db
288
+ .prepare(`INSERT INTO frictions
289
+ (session_id, tool_surface, title, description, captured_at, severity, category, source, recurrence_of_id)
290
+ VALUES (@sessionId, @toolSurface, @title, @description, @capturedAt, @severity, @category, @source, @recurrenceOfId)`)
291
+ .run({
292
+ sessionId: input.sessionId ?? null,
293
+ toolSurface: input.toolSurface ?? null,
294
+ title: input.title,
295
+ description: input.description ?? null,
296
+ capturedAt,
297
+ severity: input.severity ?? null,
298
+ category: input.category ?? null,
299
+ source: input.source,
300
+ recurrenceOfId,
301
+ });
302
+ return this.getFriction(Number(result.lastInsertRowid));
303
+ }
304
+ findRecurrenceRoot(toolSurface, title) {
305
+ if (!title)
306
+ return null;
307
+ const row = this.db
308
+ .prepare(`SELECT id FROM frictions
309
+ WHERE status = 'open'
310
+ AND recurrence_of_id IS NULL
311
+ AND title = @title
312
+ AND coalesce(tool_surface, '') = coalesce(@toolSurface, '')
313
+ ORDER BY captured_at ASC
314
+ LIMIT 1`)
315
+ .get({ title, toolSurface: toolSurface ?? null });
316
+ return row?.id ?? null;
317
+ }
318
+ getFriction(id) {
319
+ const row = this.db
320
+ .prepare(`SELECT * FROM frictions WHERE id = ?`)
321
+ .get(id);
322
+ return row ? rowToFriction(row) : null;
323
+ }
324
+ updateFrictionStatus(id, status) {
325
+ this.db
326
+ .prepare(`UPDATE frictions SET status = ? WHERE id = ?`)
327
+ .run(status, id);
328
+ }
329
+ deleteFriction(id) {
330
+ const tx = this.db.transaction((fid) => {
331
+ this.db.prepare(`DELETE FROM tasks WHERE friction_id = ?`).run(fid);
332
+ this.db.prepare(`DELETE FROM tags WHERE friction_id = ?`).run(fid);
333
+ return (this.db.prepare(`DELETE FROM frictions WHERE id = ?`).run(fid).changes >
334
+ 0);
335
+ });
336
+ return tx(id);
337
+ }
338
+ findFrictionByTriple(sessionId, toolSurface, title) {
339
+ const row = this.db
340
+ .prepare(`SELECT * FROM frictions
341
+ WHERE coalesce(session_id, '') = coalesce(@sessionId, '')
342
+ AND coalesce(tool_surface, '') = coalesce(@toolSurface, '')
343
+ AND title = @title
344
+ LIMIT 1`)
345
+ .get({
346
+ sessionId: sessionId ?? null,
347
+ toolSurface: toolSurface ?? null,
348
+ title,
349
+ });
350
+ return row ? rowToFriction(row) : null;
351
+ }
352
+ listFrictionsForSession(sessionId) {
353
+ const rows = this.db
354
+ .prepare(`SELECT * FROM frictions WHERE session_id = ? ORDER BY captured_at ASC`)
355
+ .all(sessionId);
356
+ return rows.map(rowToFriction);
357
+ }
358
+ getMostRecentSession() {
359
+ const row = this.db
360
+ .prepare(`SELECT * FROM sessions ORDER BY coalesce(ended_at, started_at) DESC LIMIT 1`)
361
+ .get();
362
+ return row ? rowToSession(row) : null;
363
+ }
364
+ listFrictions(filter = {}) {
365
+ const where = [];
366
+ const params = {};
367
+ if (filter.status) {
368
+ where.push(`status = @status`);
369
+ params.status = filter.status;
370
+ }
371
+ if (filter.tool) {
372
+ where.push(`tool_surface = @tool`);
373
+ params.tool = filter.tool;
374
+ }
375
+ if (filter.category) {
376
+ where.push(`category = @category`);
377
+ params.category = filter.category;
378
+ }
379
+ if (filter.source) {
380
+ where.push(`source = @source`);
381
+ params.source = filter.source;
382
+ }
383
+ if (filter.sinceIso) {
384
+ where.push(`captured_at >= @sinceIso`);
385
+ params.sinceIso = filter.sinceIso;
386
+ }
387
+ const whereSql = where.length ? `WHERE ${where.join(" AND ")}` : "";
388
+ const rawLimit = filter.limit ?? 100;
389
+ const limit = Math.max(1, Math.min(10_000, Number.isFinite(rawLimit) ? Math.trunc(rawLimit) : 100));
390
+ params.limit = limit;
391
+ // Tiebreaker on `id` makes ordering deterministic when two frictions
392
+ // share a captured_at timestamp (e.g. a bulk import landing in the same
393
+ // millisecond). Backward-compatible: for the overwhelmingly common case
394
+ // of distinct timestamps this changes nothing, and SQLite gave no
395
+ // ordering guarantee on ties before this either.
396
+ const rows = this.db
397
+ .prepare(`SELECT * FROM frictions ${whereSql} ORDER BY captured_at DESC, id DESC LIMIT @limit`)
398
+ .all(params);
399
+ return rows.map(rowToFriction);
400
+ }
401
+ /**
402
+ * Every friction, no limit, sorted oldest-first with an `id` tiebreaker.
403
+ * Dedicated to sync-export: `listFrictions` caps at 10_000 and sorts
404
+ * newest-first for interactive use, neither of which is right for a full,
405
+ * deterministic machine-readable dump.
406
+ */
407
+ listAllFrictionsForSyncExport() {
408
+ const rows = this.db
409
+ .prepare(`SELECT * FROM frictions ORDER BY captured_at ASC, id ASC`)
410
+ .all();
411
+ return rows.map(rowToFriction);
412
+ }
413
+ insertTask(input) {
414
+ const createdAt = new Date().toISOString();
415
+ const result = this.db
416
+ .prepare(`INSERT INTO tasks (friction_id, sink_name, sink_target, external_ref, pr_url, resolution_status, created_at)
417
+ VALUES (@frictionId, @sinkName, @sinkTarget, @externalRef, @prUrl, @resolutionStatus, @createdAt)`)
418
+ .run({
419
+ frictionId: input.frictionId,
420
+ sinkName: input.sinkName,
421
+ sinkTarget: input.sinkTarget ?? null,
422
+ externalRef: input.externalRef ?? null,
423
+ prUrl: input.prUrl ?? null,
424
+ resolutionStatus: input.resolutionStatus ?? null,
425
+ createdAt,
426
+ });
427
+ return this.getTask(Number(result.lastInsertRowid));
428
+ }
429
+ getTask(id) {
430
+ const row = this.db.prepare(`SELECT * FROM tasks WHERE id = ?`).get(id);
431
+ return row ? rowToTask(row) : null;
432
+ }
433
+ listTasksForFriction(frictionId) {
434
+ const rows = this.db
435
+ .prepare(`SELECT * FROM tasks WHERE friction_id = ? ORDER BY created_at ASC`)
436
+ .all(frictionId);
437
+ return rows.map(rowToTask);
438
+ }
439
+ addTag(frictionId, tag) {
440
+ this.db
441
+ .prepare(`INSERT OR IGNORE INTO tags (friction_id, tag) VALUES (?, ?)`)
442
+ .run(frictionId, tag);
443
+ }
444
+ tagsFor(frictionId) {
445
+ const rows = this.db
446
+ .prepare(`SELECT tag FROM tags WHERE friction_id = ? ORDER BY tag`)
447
+ .all(frictionId);
448
+ return rows.map((r) => r.tag);
449
+ }
450
+ searchFrictions(query, filter = {}) {
451
+ const trimmed = query.trim();
452
+ if (!trimmed)
453
+ return [];
454
+ const where = [`frictions_fts MATCH @query`];
455
+ const params = { query: trimmed };
456
+ if (filter.status) {
457
+ where.push(`f.status = @status`);
458
+ params.status = filter.status;
459
+ }
460
+ if (filter.tool) {
461
+ where.push(`f.tool_surface = @tool`);
462
+ params.tool = filter.tool;
463
+ }
464
+ if (filter.category) {
465
+ where.push(`f.category = @category`);
466
+ params.category = filter.category;
467
+ }
468
+ if (filter.source) {
469
+ where.push(`f.source = @source`);
470
+ params.source = filter.source;
471
+ }
472
+ if (filter.sinceIso) {
473
+ where.push(`f.captured_at >= @sinceIso`);
474
+ params.sinceIso = filter.sinceIso;
475
+ }
476
+ const rawLimit = filter.limit ?? 100;
477
+ const limit = Math.max(1, Math.min(10_000, Number.isFinite(rawLimit) ? Math.trunc(rawLimit) : 100));
478
+ params.limit = limit;
479
+ const sql = `
480
+ SELECT f.* FROM frictions f
481
+ JOIN frictions_fts fts ON fts.rowid = f.id
482
+ WHERE ${where.join(" AND ")}
483
+ ORDER BY rank
484
+ LIMIT @limit
485
+ `;
486
+ const rows = this.db.prepare(sql).all(params);
487
+ return rows.map(rowToFriction);
488
+ }
489
+ digest(groupBy, sinceIso) {
490
+ const columnByGroup = {
491
+ tool: "tool_surface",
492
+ category: "category",
493
+ severity: "severity",
494
+ source: "source",
495
+ };
496
+ const column = columnByGroup[groupBy];
497
+ const where = [];
498
+ const params = {};
499
+ if (sinceIso) {
500
+ where.push(`f.captured_at >= @sinceIso`);
501
+ params.sinceIso = sinceIso;
502
+ }
503
+ const whereSql = where.length ? `WHERE ${where.join(" AND ")}` : "";
504
+ // Subquery picks each friction's earliest task creation, then we compute
505
+ // hours from captured_at to that first sink-file event ("time to triage").
506
+ // Frictions never filed contribute NULL and are excluded from the average.
507
+ const sql = `
508
+ SELECT
509
+ coalesce(f.${column}, '(unset)') AS grp,
510
+ count(*) AS total,
511
+ sum(CASE WHEN f.status = 'open' THEN 1 ELSE 0 END) AS open_count,
512
+ sum(CASE WHEN f.status = 'filed' THEN 1 ELSE 0 END) AS filed_count,
513
+ sum(CASE WHEN f.status = 'resolved' THEN 1 ELSE 0 END) AS resolved_count,
514
+ sum(CASE WHEN f.status = 'wontfix' THEN 1 ELSE 0 END) AS wontfix_count,
515
+ sum(CASE WHEN f.recurrence_of_id IS NOT NULL THEN 1 ELSE 0 END) AS recurrences,
516
+ avg(
517
+ CASE
518
+ WHEN t.first_created IS NOT NULL
519
+ THEN (julianday(t.first_created) - julianday(f.captured_at)) * 24.0
520
+ END
521
+ ) AS avg_hours_to_triage
522
+ FROM frictions f
523
+ LEFT JOIN (
524
+ SELECT friction_id, min(created_at) AS first_created
525
+ FROM tasks
526
+ GROUP BY friction_id
527
+ ) t ON t.friction_id = f.id
528
+ ${whereSql}
529
+ GROUP BY grp
530
+ ORDER BY total DESC, grp ASC
531
+ `;
532
+ const rows = this.db.prepare(sql).all(params);
533
+ return rows.map((r) => ({
534
+ group: r.grp,
535
+ total: r.total,
536
+ open: r.open_count,
537
+ filed: r.filed_count,
538
+ resolved: r.resolved_count,
539
+ wontfix: r.wontfix_count,
540
+ recurrences: r.recurrences,
541
+ avgHoursToTriage: r.avg_hours_to_triage,
542
+ }));
543
+ }
544
+ close() {
545
+ this.db.close();
546
+ }
547
+ }
548
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export * from "./types.js";
2
+ export { FrictionDb } from "./db.js";
3
+ export { defaultDbPath, defaultConfigPath, defaultMarkdownSinkDir, } from "./paths.js";
4
+ export { loadTemplate, listTemplates, pickTemplateForCategory, render, } from "./templates.js";
5
+ export { loadSink, availableSinks } from "./sinks/index.js";
6
+ export { MarkdownFileSink } from "./sinks/markdown-file.js";
7
+ export { loadScanner, availableScanners } from "./scanners/index.js";
8
+ export { ClaudeCodeAdapter } from "./scanners/claude-code.js";
9
+ export { runLog } from "./commands/log.js";
10
+ export { runList, formatTable, parseAge } from "./commands/list.js";
11
+ export { runFile } from "./commands/file.js";
12
+ export { runScan, payloadToScanInput, summarize } from "./commands/scan.js";
13
+ export { runBilanz, formatBilanz } from "./commands/bilanz.js";
14
+ export { runRm } from "./commands/rm.js";
15
+ export { runUpdate } from "./commands/update.js";
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ export * from "./types.js";
2
+ export { FrictionDb } from "./db.js";
3
+ export { defaultDbPath, defaultConfigPath, defaultMarkdownSinkDir, } from "./paths.js";
4
+ export { loadTemplate, listTemplates, pickTemplateForCategory, render, } from "./templates.js";
5
+ export { loadSink, availableSinks } from "./sinks/index.js";
6
+ export { MarkdownFileSink } from "./sinks/markdown-file.js";
7
+ export { loadScanner, availableScanners } from "./scanners/index.js";
8
+ export { ClaudeCodeAdapter } from "./scanners/claude-code.js";
9
+ export { runLog } from "./commands/log.js";
10
+ export { runList, formatTable, parseAge } from "./commands/list.js";
11
+ export { runFile } from "./commands/file.js";
12
+ export { runScan, payloadToScanInput, summarize } from "./commands/scan.js";
13
+ export { runBilanz, formatBilanz } from "./commands/bilanz.js";
14
+ export { runRm } from "./commands/rm.js";
15
+ export { runUpdate } from "./commands/update.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,MAAM,GACP,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};