friction-log 0.6.0 → 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.
- package/CHANGELOG.md +10 -0
- package/dist/cli.js +10 -501
- package/dist/cli.js.map +1 -1
- package/dist/main.d.ts +1 -0
- package/dist/main.js +503 -0
- package/dist/main.js.map +1 -0
- package/dist/node-guard.d.ts +14 -0
- package/dist/node-guard.js +36 -0
- package/dist/node-guard.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.1] - 2026-10-10
|
|
11
|
+
|
|
12
|
+
First release cut for the tag-driven `publish-npm.yml` workflow (npm Trusted Publishing), which publishes with `--provenance`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- The CLI now refuses to start on a Node version below the `engines.node` range (currently `>=22`), exiting 1 with a stderr message that names the required and the running version. Previously npm only warned, and the first database command crashed with a SIGSEGV. The check runs in a small entry module (`dist/cli.js`) before the real CLI, and thus `better-sqlite3`, is loaded; `--help` and `--version` are refused as well. (11dc376f)
|
|
17
|
+
|
|
10
18
|
## [0.6.0] - 2026-10-10
|
|
11
19
|
|
|
12
20
|
First release published to npm (`npm i -g friction-log`). Earlier versions ran from a local build of this repository. The entries below cover everything since the 0.5.0 milestone tag.
|
|
13
21
|
|
|
22
|
+
0.6.0 was published by hand from a build of commit `48926fca`, because npm accepts a Trusted Publisher entry only for a package that already exists; it therefore has no provenance attestation. There is deliberately no `friction-log/v0.6.0` git tag: pushing it would trigger `publish-npm.yml`, which refuses a registry version without an attestation and would fail red.
|
|
23
|
+
|
|
14
24
|
### Added
|
|
15
25
|
|
|
16
26
|
- Opt-in `sync_export` config block and a `sync-export` command: a deterministic, atomic, no-op-skipping export of the local database, written through after each of the six mutating commands (`log`, `update`, `rm`, `file`, `import`, `scan`). Without the config block everything is an exact no-op. See [sync export](docs/sync-export.md).
|
package/dist/cli.js
CHANGED
|
@@ -1,504 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { runImport } from "./commands/import.js";
|
|
11
|
-
import { runInit } from "./commands/init.js";
|
|
12
|
-
import { formatTable, runList } from "./commands/list.js";
|
|
13
|
-
import { runLog } from "./commands/log.js";
|
|
14
|
-
import { runRm } from "./commands/rm.js";
|
|
15
|
-
import { payloadToScanInput, runScan, summarize, } from "./commands/scan.js";
|
|
16
|
-
import { runSearch } from "./commands/search.js";
|
|
17
|
-
import { runSyncExport } from "./commands/sync-export.js";
|
|
18
|
-
import { runUpdate } from "./commands/update.js";
|
|
19
|
-
import { parseSinkOpts } from "./config.js";
|
|
20
|
-
import { availableSinks } from "./sinks/index.js";
|
|
21
|
-
function readPackageVersion() {
|
|
22
|
-
try {
|
|
23
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
24
|
-
const pkgPath = join(here, "..", "package.json");
|
|
25
|
-
const raw = readFileSync(pkgPath, "utf8");
|
|
26
|
-
const parsed = JSON.parse(raw);
|
|
27
|
-
return typeof parsed.version === "string" ? parsed.version : "0.0.0";
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return "0.0.0";
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const SEVERITY_CHOICES = ["low", "medium", "high", "critical"];
|
|
34
|
-
const STATUS_CHOICES = ["open", "filed", "resolved", "wontfix"];
|
|
35
|
-
const SOURCE_CHOICES = ["scan", "manual", "import"];
|
|
36
|
-
const SCANNER_CHOICES = ["claude-code"];
|
|
37
|
-
const DIGEST_GROUP_CHOICES = [
|
|
38
|
-
"tool",
|
|
39
|
-
"category",
|
|
40
|
-
"severity",
|
|
41
|
-
"source",
|
|
42
|
-
];
|
|
43
|
-
const EXPORT_FORMAT_CHOICES = ["json", "csv", "md"];
|
|
44
|
-
const IMPORT_FORMAT_CHOICES = ["markdown-frontmatter"];
|
|
45
|
-
const program = new Command();
|
|
46
|
-
program
|
|
47
|
-
.name("friction-log")
|
|
48
|
-
.description("Capture, query, and infer agent-workflow frictions.")
|
|
49
|
-
.version(readPackageVersion());
|
|
50
|
-
program
|
|
51
|
-
.command("log")
|
|
52
|
-
.description("Manually record a friction.")
|
|
53
|
-
.requiredOption("--title <title>", "Short title describing the friction")
|
|
54
|
-
.option("--description <text>", "Longer description / reproduction notes")
|
|
55
|
-
.option("--tool <surface>", "Tool surface that caused the friction (e.g. mcp:agent-tasks/tasks_list)")
|
|
56
|
-
.option("--category <name>", "Category (e.g. output-overflow, tool-error)")
|
|
57
|
-
.addOption(new Option("--severity <level>", "Severity level").choices([
|
|
58
|
-
...SEVERITY_CHOICES,
|
|
59
|
-
]))
|
|
60
|
-
.option("--session <id>", "Session id to associate with this friction")
|
|
61
|
-
.option("--recurrence-of <id>", "Mark this friction as a recurrence of an existing one", (v) => Number(v))
|
|
62
|
-
.option("--db <path>", "Override database path (default: XDG)")
|
|
63
|
-
.action((opts) => {
|
|
64
|
-
const recurrenceOfRaw = opts.recurrenceOf;
|
|
65
|
-
let recurrenceOfId;
|
|
66
|
-
if (recurrenceOfRaw !== undefined) {
|
|
67
|
-
if (typeof recurrenceOfRaw !== "number" ||
|
|
68
|
-
!Number.isInteger(recurrenceOfRaw) ||
|
|
69
|
-
recurrenceOfRaw <= 0) {
|
|
70
|
-
process.stderr.write(`friction-log: --recurrence-of must be a positive integer, got "${String(recurrenceOfRaw)}"\n`);
|
|
71
|
-
process.exit(2);
|
|
72
|
-
}
|
|
73
|
-
recurrenceOfId = recurrenceOfRaw;
|
|
74
|
-
}
|
|
75
|
-
const out = runLog({
|
|
76
|
-
title: opts.title,
|
|
77
|
-
description: opts.description,
|
|
78
|
-
tool: opts.tool,
|
|
79
|
-
category: opts.category,
|
|
80
|
-
severity: opts.severity,
|
|
81
|
-
sessionId: opts.session,
|
|
82
|
-
recurrenceOfId,
|
|
83
|
-
dbPath: opts.db,
|
|
84
|
-
});
|
|
85
|
-
const recurrenceTag = out.recurrenceOfId != null ? ` recurrence_of=${out.recurrenceOfId}` : "";
|
|
86
|
-
process.stdout.write(`friction id=${out.id} captured_at=${out.capturedAt}${recurrenceTag}\n`);
|
|
87
|
-
});
|
|
88
|
-
program
|
|
89
|
-
.command("list")
|
|
90
|
-
.description("List frictions with optional filters.")
|
|
91
|
-
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
92
|
-
...STATUS_CHOICES,
|
|
93
|
-
]))
|
|
94
|
-
.option("--tool <surface>", "Filter by tool surface")
|
|
95
|
-
.option("--category <name>", "Filter by category")
|
|
96
|
-
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
97
|
-
...SOURCE_CHOICES,
|
|
98
|
-
]))
|
|
99
|
-
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
100
|
-
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
101
|
-
.option("--json", "Emit JSON instead of a table")
|
|
102
|
-
.option("--db <path>", "Override database path")
|
|
103
|
-
.action((opts) => {
|
|
104
|
-
const out = runList({
|
|
105
|
-
status: opts.status,
|
|
106
|
-
tool: opts.tool,
|
|
107
|
-
category: opts.category,
|
|
108
|
-
source: opts.source,
|
|
109
|
-
age: opts.age,
|
|
110
|
-
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
111
|
-
dbPath: opts.db,
|
|
112
|
-
});
|
|
113
|
-
if (opts.json) {
|
|
114
|
-
process.stdout.write(JSON.stringify(out.frictions, null, 2) + "\n");
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
process.stdout.write(formatTable(out.frictions) + "\n");
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
program
|
|
121
|
-
.command("file <frictionId>")
|
|
122
|
-
.description("Push a friction to a configured sink. Default sink: markdown-file.")
|
|
123
|
-
.addOption(new Option("--sink <name>", "Sink to use")
|
|
124
|
-
.choices([...availableSinks])
|
|
125
|
-
.default("markdown-file"))
|
|
126
|
-
.option("--template <name>", "Template override (defaults to friction.category match)")
|
|
127
|
-
.option("--sink-target <value>", "Sink-specific target (markdown-file: directory path)")
|
|
128
|
-
.option("--sink-opt <key=value>", "Per-sink option override, repeatable (e.g. --sink-opt repo=owner/name)", (value, previous = []) => [...previous, value], [])
|
|
129
|
-
.option("--config <path>", "Override config file path (default: $XDG_CONFIG_HOME/friction-log/config.yml)")
|
|
130
|
-
.option("--db <path>", "Override database path")
|
|
131
|
-
.action(async (frictionId, opts) => {
|
|
132
|
-
const id = Number(frictionId);
|
|
133
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
134
|
-
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
135
|
-
process.exit(2);
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
const sinkOptPairs = Array.isArray(opts.sinkOpt)
|
|
139
|
-
? opts.sinkOpt
|
|
140
|
-
: [];
|
|
141
|
-
const sinkOpts = sinkOptPairs.length
|
|
142
|
-
? parseSinkOpts(sinkOptPairs)
|
|
143
|
-
: undefined;
|
|
144
|
-
const out = await runFile({
|
|
145
|
-
frictionId: id,
|
|
146
|
-
sink: opts.sink,
|
|
147
|
-
template: opts.template,
|
|
148
|
-
sinkTarget: opts.sinkTarget,
|
|
149
|
-
sinkOpts,
|
|
150
|
-
configPath: opts.config,
|
|
151
|
-
dbPath: opts.db,
|
|
152
|
-
});
|
|
153
|
-
process.stdout.write(`filed friction id=${id} via sink=${out.sinkName} target=${out.sinkTarget}\n${out.message}\n`);
|
|
154
|
-
}
|
|
155
|
-
catch (err) {
|
|
156
|
-
process.stderr.write(`${err.message}\n`);
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
program
|
|
161
|
-
.command("scan")
|
|
162
|
-
.description("Scan a transcript for candidate frictions and store them.")
|
|
163
|
-
.option("--session <id>", "Session id (defaults to derivation from --transcript filename)")
|
|
164
|
-
.option("--transcript <path>", "Path to the transcript file (e.g. ~/.claude/projects/.../<id>.jsonl)")
|
|
165
|
-
.addOption(new Option("--adapter <name>", "Scanner adapter").choices([
|
|
166
|
-
...SCANNER_CHOICES,
|
|
167
|
-
]))
|
|
168
|
-
.option("--silent", "Never throw, exit 0 always (Stop-hook mode)")
|
|
169
|
-
.option("--stdin-payload", "Read a JSON Stop-hook payload from stdin to derive session+transcript")
|
|
170
|
-
.option("--db <path>", "Override database path")
|
|
171
|
-
.action(async (opts) => {
|
|
172
|
-
try {
|
|
173
|
-
let baseInput = {
|
|
174
|
-
sessionId: opts.session,
|
|
175
|
-
transcriptPath: opts.transcript,
|
|
176
|
-
adapter: opts.adapter,
|
|
177
|
-
dbPath: opts.db,
|
|
178
|
-
};
|
|
179
|
-
if (opts.stdinPayload) {
|
|
180
|
-
const payload = await readStdinPayload();
|
|
181
|
-
const derived = payloadToScanInput(payload, baseInput.adapter);
|
|
182
|
-
baseInput = {
|
|
183
|
-
sessionId: derived.sessionId ?? baseInput.sessionId,
|
|
184
|
-
transcriptPath: derived.transcriptPath ?? baseInput.transcriptPath,
|
|
185
|
-
adapter: derived.adapter ?? baseInput.adapter,
|
|
186
|
-
dbPath: baseInput.dbPath,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
const out = await runScan(baseInput);
|
|
190
|
-
if (!opts.silent) {
|
|
191
|
-
process.stdout.write(summarize(out, out.sessionId) + "\n");
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
catch (err) {
|
|
195
|
-
if (opts.silent) {
|
|
196
|
-
process.stderr.write(`friction-log scan (silent): ${err.message}\n`);
|
|
197
|
-
process.exit(0);
|
|
198
|
-
}
|
|
199
|
-
process.stderr.write(`${err.message}\n`);
|
|
200
|
-
process.exit(1);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
program
|
|
204
|
-
.command("bilanz")
|
|
205
|
-
.description("Format a session-boundary bilanz: tools, frictions, tasks.")
|
|
206
|
-
.option("--session <id>", "Session id (defaults to most-recent in db)")
|
|
207
|
-
.option("--db <path>", "Override database path")
|
|
208
|
-
.action(async (opts) => {
|
|
209
|
-
try {
|
|
210
|
-
const out = await runBilanz({ sessionId: opts.session, dbPath: opts.db });
|
|
211
|
-
process.stdout.write(out.formatted);
|
|
212
|
-
}
|
|
213
|
-
catch (err) {
|
|
214
|
-
process.stderr.write(`${err.message}\n`);
|
|
215
|
-
process.exit(1);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
program
|
|
219
|
-
.command("rm <frictionId>")
|
|
220
|
-
.description("Delete a friction (and any task rows pointing at it) from the local store.")
|
|
221
|
-
.option("--db <path>", "Override database path")
|
|
222
|
-
.action((frictionId, opts) => {
|
|
223
|
-
const id = Number(frictionId);
|
|
224
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
225
|
-
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
226
|
-
process.exit(2);
|
|
227
|
-
}
|
|
228
|
-
try {
|
|
229
|
-
const out = runRm({ frictionId: id, dbPath: opts.db });
|
|
230
|
-
process.stdout.write(`removed friction id=${id} (${out.removed ? "ok" : "no-op"})\n`);
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
process.stderr.write(`${err.message}\n`);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
program
|
|
238
|
-
.command("update <frictionId>")
|
|
239
|
-
.description("Update a friction (status only in M2; more fields in later milestones).")
|
|
240
|
-
.addOption(new Option("--status <status>", "New status")
|
|
241
|
-
.choices([...STATUS_CHOICES])
|
|
242
|
-
.makeOptionMandatory(true))
|
|
243
|
-
.option("--db <path>", "Override database path")
|
|
244
|
-
.action((frictionId, opts) => {
|
|
245
|
-
const id = Number(frictionId);
|
|
246
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
247
|
-
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
248
|
-
process.exit(2);
|
|
249
|
-
}
|
|
250
|
-
try {
|
|
251
|
-
const out = runUpdate({
|
|
252
|
-
frictionId: id,
|
|
253
|
-
status: opts.status,
|
|
254
|
-
dbPath: opts.db,
|
|
255
|
-
});
|
|
256
|
-
process.stdout.write(`updated friction id=${out.id} status=${out.status}\n`);
|
|
257
|
-
}
|
|
258
|
-
catch (err) {
|
|
259
|
-
process.stderr.write(`${err.message}\n`);
|
|
260
|
-
process.exit(1);
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
program
|
|
264
|
-
.command("search <query>")
|
|
265
|
-
.description("Full-text search over title + description (FTS5).")
|
|
266
|
-
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
267
|
-
...STATUS_CHOICES,
|
|
268
|
-
]))
|
|
269
|
-
.option("--tool <surface>", "Filter by tool surface")
|
|
270
|
-
.option("--category <name>", "Filter by category")
|
|
271
|
-
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
272
|
-
...SOURCE_CHOICES,
|
|
273
|
-
]))
|
|
274
|
-
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
275
|
-
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
276
|
-
.option("--json", "Emit JSON instead of a table")
|
|
277
|
-
.option("--db <path>", "Override database path")
|
|
278
|
-
.action((query, opts) => {
|
|
279
|
-
try {
|
|
280
|
-
const out = runSearch({
|
|
281
|
-
query,
|
|
282
|
-
status: opts.status,
|
|
283
|
-
tool: opts.tool,
|
|
284
|
-
category: opts.category,
|
|
285
|
-
source: opts.source,
|
|
286
|
-
age: opts.age,
|
|
287
|
-
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
288
|
-
dbPath: opts.db,
|
|
289
|
-
});
|
|
290
|
-
if (opts.json) {
|
|
291
|
-
process.stdout.write(JSON.stringify(out.frictions, null, 2) + "\n");
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
process.stdout.write(formatTable(out.frictions) + "\n");
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (err) {
|
|
298
|
-
process.stderr.write(`${err.message}\n`);
|
|
299
|
-
process.exit(1);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
program
|
|
303
|
-
.command("digest")
|
|
304
|
-
.description("Aggregations over frictions: counts, open-vs-filed, recurrences, avg hours to triage.")
|
|
305
|
-
.addOption(new Option("--group-by <field>", "Group by field")
|
|
306
|
-
.choices([...DIGEST_GROUP_CHOICES])
|
|
307
|
-
.makeOptionMandatory(true))
|
|
308
|
-
.option("--last <span>", "Restrict to frictions newer than e.g. 30d, 4w, 12h")
|
|
309
|
-
.option("--include-peers", "Also render read-only digest sections for each configured sync_export.peer_paths file")
|
|
310
|
-
.option("--json", "Emit JSON instead of a table")
|
|
311
|
-
.option("--config <path>", "Override config file path (only used by --include-peers)")
|
|
312
|
-
.option("--db <path>", "Override database path")
|
|
313
|
-
.action((opts) => {
|
|
314
|
-
try {
|
|
315
|
-
const out = runDigest({
|
|
316
|
-
groupBy: opts.groupBy,
|
|
317
|
-
last: opts.last,
|
|
318
|
-
dbPath: opts.db,
|
|
319
|
-
configPath: opts.config,
|
|
320
|
-
includePeers: Boolean(opts.includePeers),
|
|
321
|
-
});
|
|
322
|
-
if (opts.json) {
|
|
323
|
-
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
process.stdout.write(formatDigest(out) + "\n");
|
|
327
|
-
}
|
|
328
|
-
if (out.peers) {
|
|
329
|
-
for (const peer of out.peers) {
|
|
330
|
-
if (peer.error) {
|
|
331
|
-
process.stderr.write(`friction-log: warning: peer digest source ${peer.sourcePath} (origin=${peer.origin}) skipped: ${peer.error}\n`);
|
|
332
|
-
}
|
|
333
|
-
else if (peer.skipped > 0) {
|
|
334
|
-
process.stderr.write(`friction-log: warning: peer digest source ${peer.sourcePath} (origin=${peer.origin}) skipped ${peer.skipped} malformed record(s)\n`);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
catch (err) {
|
|
340
|
-
process.stderr.write(`${err.message}\n`);
|
|
341
|
-
process.exit(1);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
program
|
|
345
|
-
.command("export")
|
|
346
|
-
.description("Export frictions as JSON, CSV, or Markdown.")
|
|
347
|
-
.addOption(new Option("--format <fmt>", "Output format")
|
|
348
|
-
.choices([...EXPORT_FORMAT_CHOICES])
|
|
349
|
-
.default("json"))
|
|
350
|
-
.option("--out <path>", "Write to a file instead of stdout")
|
|
351
|
-
.option("--query <text>", "Only export frictions matching an FTS5 query")
|
|
352
|
-
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
353
|
-
...STATUS_CHOICES,
|
|
354
|
-
]))
|
|
355
|
-
.option("--tool <surface>", "Filter by tool surface")
|
|
356
|
-
.option("--category <name>", "Filter by category")
|
|
357
|
-
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
358
|
-
...SOURCE_CHOICES,
|
|
359
|
-
]))
|
|
360
|
-
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
361
|
-
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
362
|
-
.option("--db <path>", "Override database path")
|
|
363
|
-
.action((opts) => {
|
|
364
|
-
try {
|
|
365
|
-
const out = runExport({
|
|
366
|
-
format: opts.format,
|
|
367
|
-
out: opts.out,
|
|
368
|
-
query: opts.query,
|
|
369
|
-
status: opts.status,
|
|
370
|
-
tool: opts.tool,
|
|
371
|
-
category: opts.category,
|
|
372
|
-
source: opts.source,
|
|
373
|
-
age: opts.age,
|
|
374
|
-
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
375
|
-
dbPath: opts.db,
|
|
376
|
-
});
|
|
377
|
-
if (out.out) {
|
|
378
|
-
process.stderr.write(`exported ${out.count} records (${out.format}) to ${out.out}\n`);
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
process.stdout.write(out.rendered);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
catch (err) {
|
|
385
|
-
process.stderr.write(`${err.message}\n`);
|
|
386
|
-
process.exit(1);
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
program
|
|
390
|
-
.command("sync-export")
|
|
391
|
-
.description("Write every friction as deterministic, origin-tagged JSON to the configured sync_export.path. " +
|
|
392
|
-
'No-op error unless "sync_export" (path + origin) is set in config.yml or via FRICTION_LOG_SYNC_EXPORT_PATH/_ORIGIN.')
|
|
393
|
-
.option("--config <path>", "Override config file path")
|
|
394
|
-
.option("--db <path>", "Override database path")
|
|
395
|
-
.action((opts) => {
|
|
396
|
-
try {
|
|
397
|
-
const out = runSyncExport({
|
|
398
|
-
configPath: opts.config,
|
|
399
|
-
dbPath: opts.db,
|
|
400
|
-
});
|
|
401
|
-
process.stderr.write(`sync-export: wrote ${out.count} frictions (origin=${out.origin}) to ${out.path}\n`);
|
|
402
|
-
}
|
|
403
|
-
catch (err) {
|
|
404
|
-
process.stderr.write(`${err.message}\n`);
|
|
405
|
-
process.exit(1);
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
program
|
|
409
|
-
.command("init")
|
|
410
|
-
.description("Interactive setup: write config.yml, optionally install Stop-hook.")
|
|
411
|
-
.addOption(new Option("--sink <name>", "Default sink (skips the interactive prompt)").choices([...availableSinks]))
|
|
412
|
-
.option("-y, --yes", "Non-interactive; use --sink (or markdown-file fallback) and skip Stop-hook offer")
|
|
413
|
-
.option("--install-stop-hook", "Force-install the Claude Code Stop-hook (skip the interactive y/N)")
|
|
414
|
-
.option("--config <path>", "Override config file path")
|
|
415
|
-
.option("--sync-export-path <path>", "Opt in to sync-export: write this config's sync_export.path")
|
|
416
|
-
.option("--sync-export-origin <name>", "Opt in to sync-export: this machine's sync_export.origin label")
|
|
417
|
-
.option("--sync-export-peer <path>", "Peer sync-export file to read for `digest --include-peers`, repeatable", (value, previous = []) => [...previous, value], [])
|
|
418
|
-
.action(async (opts) => {
|
|
419
|
-
try {
|
|
420
|
-
const syncExportPath = opts.syncExportPath;
|
|
421
|
-
const syncExportOrigin = opts.syncExportOrigin;
|
|
422
|
-
if (Boolean(syncExportPath) !== Boolean(syncExportOrigin)) {
|
|
423
|
-
process.stderr.write("friction-log: --sync-export-path and --sync-export-origin must be given together\n");
|
|
424
|
-
process.exit(2);
|
|
425
|
-
}
|
|
426
|
-
const syncExportPeers = Array.isArray(opts.syncExportPeer)
|
|
427
|
-
? opts.syncExportPeer
|
|
428
|
-
: [];
|
|
429
|
-
const out = await runInit({
|
|
430
|
-
configPath: opts.config,
|
|
431
|
-
sink: opts.sink,
|
|
432
|
-
yes: Boolean(opts.yes),
|
|
433
|
-
installStopHook: opts.installStopHook === true ? true : undefined,
|
|
434
|
-
syncExport: syncExportPath && syncExportOrigin
|
|
435
|
-
? {
|
|
436
|
-
path: syncExportPath,
|
|
437
|
-
origin: syncExportOrigin,
|
|
438
|
-
peerPaths: syncExportPeers,
|
|
439
|
-
}
|
|
440
|
-
: undefined,
|
|
441
|
-
});
|
|
442
|
-
process.stdout.write(`init: ${out.configWritten ? "wrote" : "no change to"} ${out.configPath}\n` +
|
|
443
|
-
(out.stopHookWrittenTo
|
|
444
|
-
? `init: Stop-hook installed at ${out.stopHookWrittenTo}\n`
|
|
445
|
-
: "") +
|
|
446
|
-
"\nNext steps:\n" +
|
|
447
|
-
out.nextSteps.map((s) => ` ${s}`).join("\n") +
|
|
448
|
-
"\n");
|
|
449
|
-
}
|
|
450
|
-
catch (err) {
|
|
451
|
-
process.stderr.write(`${err.message}\n`);
|
|
452
|
-
process.exit(1);
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
program
|
|
456
|
-
.command("import <path>")
|
|
457
|
-
.description("Bulk-ingest frictions from a directory of markdown files.")
|
|
458
|
-
.addOption(new Option("--format <fmt>", "Source format")
|
|
459
|
-
.choices([...IMPORT_FORMAT_CHOICES])
|
|
460
|
-
.default("markdown-frontmatter"))
|
|
461
|
-
.option("--db <path>", "Override database path")
|
|
462
|
-
.action((path, opts) => {
|
|
463
|
-
try {
|
|
464
|
-
const out = runImport({
|
|
465
|
-
format: opts.format,
|
|
466
|
-
path,
|
|
467
|
-
dbPath: opts.db,
|
|
468
|
-
});
|
|
469
|
-
process.stdout.write(`import: scanned=${out.scanned} imported=${out.imported} skipped=${out.skipped}\n`);
|
|
470
|
-
if (out.errors.length) {
|
|
471
|
-
process.stderr.write(`import: ${out.errors.length} errors:\n`);
|
|
472
|
-
for (const e of out.errors.slice(0, 10)) {
|
|
473
|
-
process.stderr.write(` ${e.file}: ${e.reason}\n`);
|
|
474
|
-
}
|
|
475
|
-
if (out.errors.length > 10) {
|
|
476
|
-
process.stderr.write(` ... and ${out.errors.length - 10} more\n`);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
catch (err) {
|
|
481
|
-
process.stderr.write(`${err.message}\n`);
|
|
482
|
-
process.exit(1);
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
async function readStdinPayload() {
|
|
486
|
-
const chunks = [];
|
|
487
|
-
for await (const chunk of process.stdin) {
|
|
488
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
489
|
-
}
|
|
490
|
-
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
491
|
-
if (!text)
|
|
492
|
-
return {};
|
|
493
|
-
try {
|
|
494
|
-
return JSON.parse(text);
|
|
495
|
-
}
|
|
496
|
-
catch {
|
|
497
|
-
return {};
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
program.parseAsync(process.argv).catch((err) => {
|
|
501
|
-
process.stderr.write(`friction-log: ${err.message}\n`);
|
|
2
|
+
// Entry point. Static imports are evaluated before any code in the importing
|
|
3
|
+
// module, and the real CLI reaches better-sqlite3 through them. So this file
|
|
4
|
+
// imports only the dependency-free guard and loads the CLI dynamically after
|
|
5
|
+
// the Node version check has passed.
|
|
6
|
+
import { nodeGuardMessage, readEnginesNode } from "./node-guard.js";
|
|
7
|
+
const message = nodeGuardMessage(process.versions.node, readEnginesNode());
|
|
8
|
+
if (message) {
|
|
9
|
+
process.stderr.write(`${message}\n`);
|
|
502
10
|
process.exit(1);
|
|
503
|
-
}
|
|
11
|
+
}
|
|
12
|
+
await import("./main.js");
|
|
504
13
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,SAAS,GAEV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,OAAO,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AACxE,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AACzE,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAC7D,MAAM,eAAe,GAAG,CAAC,aAAa,CAAU,CAAC;AACjD,MAAM,oBAAoB,GAAG;IAC3B,MAAM;IACN,UAAU;IACV,UAAU;IACV,QAAQ;CACA,CAAC;AACX,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAU,CAAC;AAC7D,MAAM,qBAAqB,GAAG,CAAC,sBAAsB,CAAU,CAAC;AAEhE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,cAAc,CAAC;KACpB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEjC,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,6BAA6B,CAAC;KAC1C,cAAc,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;KACxE,MAAM,CAAC,sBAAsB,EAAE,yCAAyC,CAAC;KACzE,MAAM,CACL,kBAAkB,EAClB,yEAAyE,CAC1E;KACA,MAAM,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;KAC1E,SAAS,CACR,IAAI,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,OAAO,CAAC;IACzD,GAAG,gBAAgB;CACpB,CAAC,CACH;KACA,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;KACtE,MAAM,CACL,sBAAsB,EACtB,uDAAuD,EACvD,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CACjB;KACA,MAAM,CAAC,aAAa,EAAE,uCAAuC,CAAC;KAC9D,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;IACxC,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC;IAC1C,IAAI,cAAkC,CAAC;IACvC,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,IACE,OAAO,eAAe,KAAK,QAAQ;YACnC,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC;YAClC,eAAe,IAAI,CAAC,EACpB,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kEAAkE,MAAM,CAAC,eAAe,CAAC,KAAK,CAC/F,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,cAAc,GAAG,eAAe,CAAC;IACnC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,KAAK,EAAE,IAAI,CAAC,KAAe;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAiC;QACnD,IAAI,EAAE,IAAI,CAAC,IAA0B;QACrC,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,QAAQ,EAAE,IAAI,CAAC,QAAgC;QAC/C,SAAS,EAAE,IAAI,CAAC,OAA6B;QAC7C,cAAc;QACd,MAAM,EAAE,IAAI,CAAC,EAAwB;KACtC,CAAC,CAAC;IACH,MAAM,aAAa,GACjB,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,kBAAkB,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,GAAG,CAAC,EAAE,gBAAgB,GAAG,CAAC,UAAU,GAAG,aAAa,IAAI,CACxE,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;KACjD,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,cAAc,EAAE,6CAA6C,CAAC;KACrE,MAAM,CAAC,aAAa,EAAE,wBAAwB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KACjE,MAAM,CAAC,QAAQ,EAAE,8BAA8B,CAAC;KAChD,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC;QAClB,MAAM,EAAE,IAAI,CAAC,MAAoC;QACjD,IAAI,EAAE,IAAI,CAAC,IAA0B;QACrC,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,MAAM,EAAE,IAAI,CAAC,MAAoC;QACjD,GAAG,EAAE,IAAI,CAAC,GAAyB;QACnC,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QAC9D,MAAM,EAAE,IAAI,CAAC,EAAwB;KACtC,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACtE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CACV,oEAAoE,CACrE;KACA,SAAS,CACR,IAAI,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;KACvC,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;KAC5B,OAAO,CAAC,eAAe,CAAC,CAC5B;KACA,MAAM,CACL,mBAAmB,EACnB,yDAAyD,CAC1D;KACA,MAAM,CACL,uBAAuB,EACvB,sDAAsD,CACvD;KACA,MAAM,CACL,wBAAwB,EACxB,wEAAwE,EACxE,CAAC,KAAa,EAAE,WAAqB,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,EAChE,EAAc,CACf;KACA,MAAM,CACL,iBAAiB,EACjB,+EAA+E,CAChF;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,IAA6B,EAAE,EAAE;IAClE,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+DAA+D,UAAU,KAAK,CAC/E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAC9C,CAAC,CAAE,IAAI,CAAC,OAAoB;YAC5B,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM;YAClC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC;YAC7B,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;YACxB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,IAAI,CAAC,IAAc;YACzB,QAAQ,EAAE,IAAI,CAAC,QAA8B;YAC7C,UAAU,EAAE,IAAI,CAAC,UAAgC;YACjD,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,MAA4B;YAC7C,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qBAAqB,EAAE,aAAa,GAAG,CAAC,QAAQ,WAAW,GAAG,CAAC,UAAU,KAAK,GAAG,CAAC,OAAO,IAAI,CAC9F,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2DAA2D,CAAC;KACxE,MAAM,CACL,gBAAgB,EAChB,gEAAgE,CACjE;KACA,MAAM,CACL,qBAAqB,EACrB,sEAAsE,CACvE;KACA,SAAS,CACR,IAAI,MAAM,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC,OAAO,CAAC;IACxD,GAAG,eAAe;CACnB,CAAC,CACH;KACA,MAAM,CAAC,UAAU,EAAE,6CAA6C,CAAC;KACjE,MAAM,CACL,iBAAiB,EACjB,uEAAuE,CACxE;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,IAA6B,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,IAAI,SAAS,GAAG;YACd,SAAS,EAAE,IAAI,CAAC,OAA6B;YAC7C,cAAc,EAAE,IAAI,CAAC,UAAgC;YACrD,OAAO,EAAE,IAAI,CAAC,OAA6B;YAC3C,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC;QACF,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;YAC/D,SAAS,GAAG;gBACV,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS;gBACnD,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,SAAS,CAAC,cAAc;gBAClE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO;gBAC7C,MAAM,EAAE,SAAS,CAAC,MAAM;aACzB,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+BAAgC,GAAa,CAAC,OAAO,IAAI,CAC1D,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;KACtE,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,IAA4B,EAAE,EAAE;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CACV,4EAA4E,CAC7E;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,UAAkB,EAAE,IAA4B,EAAE,EAAE;IAC3D,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+DAA+D,UAAU,KAAK,CAC/E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,EAAE,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,CAChE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CACV,yEAAyE,CAC1E;KACA,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC;KAC1C,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;KAC5B,mBAAmB,CAAC,IAAI,CAAC,CAC7B;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,UAAkB,EAAE,IAA4B,EAAE,EAAE;IAC3D,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+DAA+D,UAAU,KAAK,CAC/E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC;YACpB,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,IAAI,CAAC,MAAwB;YACrC,MAAM,EAAE,IAAI,CAAC,EAAE;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,IAAI,CACvD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,mDAAmD,CAAC;KAChE,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;KACjD,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,cAAc,EAAE,6CAA6C,CAAC;KACrE,MAAM,CAAC,aAAa,EAAE,wBAAwB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KACjE,MAAM,CAAC,QAAQ,EAAE,8BAA8B,CAAC;KAChD,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,KAAa,EAAE,IAA6B,EAAE,EAAE;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC;YACpB,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,MAAoC;YACjD,IAAI,EAAE,IAAI,CAAC,IAA0B;YACrC,QAAQ,EAAE,IAAI,CAAC,QAA8B;YAC7C,MAAM,EAAE,IAAI,CAAC,MAAoC;YACjD,GAAG,EAAE,IAAI,CAAC,GAAyB;YACnC,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;YAC9D,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CACV,uFAAuF,CACxF;KACA,SAAS,CACR,IAAI,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CAAC;KAC/C,OAAO,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC;KAClC,mBAAmB,CAAC,IAAI,CAAC,CAC7B;KACA,MAAM,CAAC,eAAe,EAAE,oDAAoD,CAAC;KAC7E,MAAM,CACL,iBAAiB,EACjB,uFAAuF,CACxF;KACA,MAAM,CAAC,QAAQ,EAAE,8BAA8B,CAAC;KAChD,MAAM,CACL,iBAAiB,EACjB,0DAA0D,CAC3D;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC;YACpB,OAAO,EAAE,IAAI,CAAC,OAAwB;YACtC,IAAI,EAAE,IAAI,CAAC,IAA0B;YACrC,MAAM,EAAE,IAAI,CAAC,EAAwB;YACrC,UAAU,EAAE,IAAI,CAAC,MAA4B;YAC7C,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;SACzC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC7B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6CAA6C,IAAI,CAAC,UAAU,YAAY,IAAI,CAAC,MAAM,cAAc,IAAI,CAAC,KAAK,IAAI,CAChH,CAAC;gBACJ,CAAC;qBAAM,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6CAA6C,IAAI,CAAC,UAAU,YAAY,IAAI,CAAC,MAAM,aAAa,IAAI,CAAC,OAAO,wBAAwB,CACrI,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,SAAS,CACR,IAAI,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC;KAC1C,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC;KACnC,OAAO,CAAC,MAAM,CAAC,CACnB;KACA,MAAM,CAAC,cAAc,EAAE,mCAAmC,CAAC;KAC3D,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;KACxE,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;KACjD,SAAS,CACR,IAAI,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC;IAC1D,GAAG,cAAc;CAClB,CAAC,CACH;KACA,MAAM,CAAC,cAAc,EAAE,6CAA6C,CAAC;KACrE,MAAM,CAAC,aAAa,EAAE,wBAAwB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KACjE,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC;YACpB,MAAM,EAAE,IAAI,CAAC,MAAsB;YACnC,GAAG,EAAE,IAAI,CAAC,GAAyB;YACnC,KAAK,EAAE,IAAI,CAAC,KAA2B;YACvC,MAAM,EAAE,IAAI,CAAC,MAAoC;YACjD,IAAI,EAAE,IAAI,CAAC,IAA0B;YACrC,QAAQ,EAAE,IAAI,CAAC,QAA8B;YAC7C,MAAM,EAAE,IAAI,CAAC,MAAoC;YACjD,GAAG,EAAE,IAAI,CAAC,GAAyB;YACnC,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;YAC9D,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,GAAG,CAAC,KAAK,aAAa,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAChE,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CACV,gGAAgG;IAC9F,qHAAqH,CACxH;KACA,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,IAA6B,EAAE,EAAE;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC;YACxB,UAAU,EAAE,IAAI,CAAC,MAA4B;YAC7C,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sBAAsB,GAAG,CAAC,KAAK,sBAAsB,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,IAAI,CACpF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CACV,oEAAoE,CACrE;KACA,SAAS,CACR,IAAI,MAAM,CACR,eAAe,EACf,6CAA6C,CAC9C,CAAC,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAC/B;KACA,MAAM,CACL,WAAW,EACX,kFAAkF,CACnF;KACA,MAAM,CACL,qBAAqB,EACrB,oEAAoE,CACrE;KACA,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CACL,2BAA2B,EAC3B,6DAA6D,CAC9D;KACA,MAAM,CACL,6BAA6B,EAC7B,gEAAgE,CACjE;KACA,MAAM,CACL,2BAA2B,EAC3B,wEAAwE,EACxE,CAAC,KAAa,EAAE,WAAqB,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,EAChE,EAAc,CACf;KACA,MAAM,CAAC,KAAK,EAAE,IAA6B,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,CAAC,cAAoC,CAAC;QACjE,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAsC,CAAC;QACrE,IAAI,OAAO,CAAC,cAAc,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oFAAoF,CACrF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC;YACxD,CAAC,CAAE,IAAI,CAAC,cAA2B;YACnC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;YACxB,UAAU,EAAE,IAAI,CAAC,MAA4B;YAC7C,IAAI,EAAE,IAAI,CAAC,IAA0D;YACrE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YACtB,eAAe,EAAE,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACjE,UAAU,EACR,cAAc,IAAI,gBAAgB;gBAChC,CAAC,CAAC;oBACE,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,gBAAgB;oBACxB,SAAS,EAAE,eAAe;iBAC3B;gBACH,CAAC,CAAC,SAAS;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,SAAS,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,IAAI;YACzE,CAAC,GAAG,CAAC,iBAAiB;gBACpB,CAAC,CAAC,gCAAgC,GAAG,CAAC,iBAAiB,IAAI;gBAC3D,CAAC,CAAC,EAAE,CAAC;YACP,iBAAiB;YACjB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7C,IAAI,CACP,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,2DAA2D,CAAC;KACxE,SAAS,CACR,IAAI,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC;KAC1C,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC;KACnC,OAAO,CAAC,sBAAsB,CAAC,CACnC;KACA,MAAM,CAAC,aAAa,EAAE,wBAAwB,CAAC;KAC/C,MAAM,CAAC,CAAC,IAAY,EAAE,IAA6B,EAAE,EAAE;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC;YACpB,MAAM,EAAE,IAAI,CAAC,MAAsB;YACnC,IAAI;YACJ,MAAM,EAAE,IAAI,CAAC,EAAwB;SACtC,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mBAAmB,GAAG,CAAC,OAAO,aAAa,GAAG,CAAC,QAAQ,YAAY,GAAG,CAAC,OAAO,IAAI,CACnF,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,MAAM,CAAC,MAAM,YAAY,CAAC,CAAC;YAC/D,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;YACrD,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,SAAS,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,KAAK,UAAU,gBAAgB;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AACrC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAC3E,IAAI,OAAO,EAAE,CAAC;IACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { runBilanz } from "./commands/bilanz.js";
|
|
6
|
+
import { formatDigest, runDigest } from "./commands/digest.js";
|
|
7
|
+
import { runExport } from "./commands/export.js";
|
|
8
|
+
import { runFile } from "./commands/file.js";
|
|
9
|
+
import { runImport } from "./commands/import.js";
|
|
10
|
+
import { runInit } from "./commands/init.js";
|
|
11
|
+
import { formatTable, runList } from "./commands/list.js";
|
|
12
|
+
import { runLog } from "./commands/log.js";
|
|
13
|
+
import { runRm } from "./commands/rm.js";
|
|
14
|
+
import { payloadToScanInput, runScan, summarize, } from "./commands/scan.js";
|
|
15
|
+
import { runSearch } from "./commands/search.js";
|
|
16
|
+
import { runSyncExport } from "./commands/sync-export.js";
|
|
17
|
+
import { runUpdate } from "./commands/update.js";
|
|
18
|
+
import { parseSinkOpts } from "./config.js";
|
|
19
|
+
import { availableSinks } from "./sinks/index.js";
|
|
20
|
+
function readPackageVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const pkgPath = join(here, "..", "package.json");
|
|
24
|
+
const raw = readFileSync(pkgPath, "utf8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return typeof parsed.version === "string" ? parsed.version : "0.0.0";
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return "0.0.0";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const SEVERITY_CHOICES = ["low", "medium", "high", "critical"];
|
|
33
|
+
const STATUS_CHOICES = ["open", "filed", "resolved", "wontfix"];
|
|
34
|
+
const SOURCE_CHOICES = ["scan", "manual", "import"];
|
|
35
|
+
const SCANNER_CHOICES = ["claude-code"];
|
|
36
|
+
const DIGEST_GROUP_CHOICES = [
|
|
37
|
+
"tool",
|
|
38
|
+
"category",
|
|
39
|
+
"severity",
|
|
40
|
+
"source",
|
|
41
|
+
];
|
|
42
|
+
const EXPORT_FORMAT_CHOICES = ["json", "csv", "md"];
|
|
43
|
+
const IMPORT_FORMAT_CHOICES = ["markdown-frontmatter"];
|
|
44
|
+
const program = new Command();
|
|
45
|
+
program
|
|
46
|
+
.name("friction-log")
|
|
47
|
+
.description("Capture, query, and infer agent-workflow frictions.")
|
|
48
|
+
.version(readPackageVersion());
|
|
49
|
+
program
|
|
50
|
+
.command("log")
|
|
51
|
+
.description("Manually record a friction.")
|
|
52
|
+
.requiredOption("--title <title>", "Short title describing the friction")
|
|
53
|
+
.option("--description <text>", "Longer description / reproduction notes")
|
|
54
|
+
.option("--tool <surface>", "Tool surface that caused the friction (e.g. mcp:agent-tasks/tasks_list)")
|
|
55
|
+
.option("--category <name>", "Category (e.g. output-overflow, tool-error)")
|
|
56
|
+
.addOption(new Option("--severity <level>", "Severity level").choices([
|
|
57
|
+
...SEVERITY_CHOICES,
|
|
58
|
+
]))
|
|
59
|
+
.option("--session <id>", "Session id to associate with this friction")
|
|
60
|
+
.option("--recurrence-of <id>", "Mark this friction as a recurrence of an existing one", (v) => Number(v))
|
|
61
|
+
.option("--db <path>", "Override database path (default: XDG)")
|
|
62
|
+
.action((opts) => {
|
|
63
|
+
const recurrenceOfRaw = opts.recurrenceOf;
|
|
64
|
+
let recurrenceOfId;
|
|
65
|
+
if (recurrenceOfRaw !== undefined) {
|
|
66
|
+
if (typeof recurrenceOfRaw !== "number" ||
|
|
67
|
+
!Number.isInteger(recurrenceOfRaw) ||
|
|
68
|
+
recurrenceOfRaw <= 0) {
|
|
69
|
+
process.stderr.write(`friction-log: --recurrence-of must be a positive integer, got "${String(recurrenceOfRaw)}"\n`);
|
|
70
|
+
process.exit(2);
|
|
71
|
+
}
|
|
72
|
+
recurrenceOfId = recurrenceOfRaw;
|
|
73
|
+
}
|
|
74
|
+
const out = runLog({
|
|
75
|
+
title: opts.title,
|
|
76
|
+
description: opts.description,
|
|
77
|
+
tool: opts.tool,
|
|
78
|
+
category: opts.category,
|
|
79
|
+
severity: opts.severity,
|
|
80
|
+
sessionId: opts.session,
|
|
81
|
+
recurrenceOfId,
|
|
82
|
+
dbPath: opts.db,
|
|
83
|
+
});
|
|
84
|
+
const recurrenceTag = out.recurrenceOfId != null ? ` recurrence_of=${out.recurrenceOfId}` : "";
|
|
85
|
+
process.stdout.write(`friction id=${out.id} captured_at=${out.capturedAt}${recurrenceTag}\n`);
|
|
86
|
+
});
|
|
87
|
+
program
|
|
88
|
+
.command("list")
|
|
89
|
+
.description("List frictions with optional filters.")
|
|
90
|
+
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
91
|
+
...STATUS_CHOICES,
|
|
92
|
+
]))
|
|
93
|
+
.option("--tool <surface>", "Filter by tool surface")
|
|
94
|
+
.option("--category <name>", "Filter by category")
|
|
95
|
+
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
96
|
+
...SOURCE_CHOICES,
|
|
97
|
+
]))
|
|
98
|
+
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
99
|
+
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
100
|
+
.option("--json", "Emit JSON instead of a table")
|
|
101
|
+
.option("--db <path>", "Override database path")
|
|
102
|
+
.action((opts) => {
|
|
103
|
+
const out = runList({
|
|
104
|
+
status: opts.status,
|
|
105
|
+
tool: opts.tool,
|
|
106
|
+
category: opts.category,
|
|
107
|
+
source: opts.source,
|
|
108
|
+
age: opts.age,
|
|
109
|
+
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
110
|
+
dbPath: opts.db,
|
|
111
|
+
});
|
|
112
|
+
if (opts.json) {
|
|
113
|
+
process.stdout.write(JSON.stringify(out.frictions, null, 2) + "\n");
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
process.stdout.write(formatTable(out.frictions) + "\n");
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
program
|
|
120
|
+
.command("file <frictionId>")
|
|
121
|
+
.description("Push a friction to a configured sink. Default sink: markdown-file.")
|
|
122
|
+
.addOption(new Option("--sink <name>", "Sink to use")
|
|
123
|
+
.choices([...availableSinks])
|
|
124
|
+
.default("markdown-file"))
|
|
125
|
+
.option("--template <name>", "Template override (defaults to friction.category match)")
|
|
126
|
+
.option("--sink-target <value>", "Sink-specific target (markdown-file: directory path)")
|
|
127
|
+
.option("--sink-opt <key=value>", "Per-sink option override, repeatable (e.g. --sink-opt repo=owner/name)", (value, previous = []) => [...previous, value], [])
|
|
128
|
+
.option("--config <path>", "Override config file path (default: $XDG_CONFIG_HOME/friction-log/config.yml)")
|
|
129
|
+
.option("--db <path>", "Override database path")
|
|
130
|
+
.action(async (frictionId, opts) => {
|
|
131
|
+
const id = Number(frictionId);
|
|
132
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
133
|
+
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
134
|
+
process.exit(2);
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const sinkOptPairs = Array.isArray(opts.sinkOpt)
|
|
138
|
+
? opts.sinkOpt
|
|
139
|
+
: [];
|
|
140
|
+
const sinkOpts = sinkOptPairs.length
|
|
141
|
+
? parseSinkOpts(sinkOptPairs)
|
|
142
|
+
: undefined;
|
|
143
|
+
const out = await runFile({
|
|
144
|
+
frictionId: id,
|
|
145
|
+
sink: opts.sink,
|
|
146
|
+
template: opts.template,
|
|
147
|
+
sinkTarget: opts.sinkTarget,
|
|
148
|
+
sinkOpts,
|
|
149
|
+
configPath: opts.config,
|
|
150
|
+
dbPath: opts.db,
|
|
151
|
+
});
|
|
152
|
+
process.stdout.write(`filed friction id=${id} via sink=${out.sinkName} target=${out.sinkTarget}\n${out.message}\n`);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
process.stderr.write(`${err.message}\n`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
program
|
|
160
|
+
.command("scan")
|
|
161
|
+
.description("Scan a transcript for candidate frictions and store them.")
|
|
162
|
+
.option("--session <id>", "Session id (defaults to derivation from --transcript filename)")
|
|
163
|
+
.option("--transcript <path>", "Path to the transcript file (e.g. ~/.claude/projects/.../<id>.jsonl)")
|
|
164
|
+
.addOption(new Option("--adapter <name>", "Scanner adapter").choices([
|
|
165
|
+
...SCANNER_CHOICES,
|
|
166
|
+
]))
|
|
167
|
+
.option("--silent", "Never throw, exit 0 always (Stop-hook mode)")
|
|
168
|
+
.option("--stdin-payload", "Read a JSON Stop-hook payload from stdin to derive session+transcript")
|
|
169
|
+
.option("--db <path>", "Override database path")
|
|
170
|
+
.action(async (opts) => {
|
|
171
|
+
try {
|
|
172
|
+
let baseInput = {
|
|
173
|
+
sessionId: opts.session,
|
|
174
|
+
transcriptPath: opts.transcript,
|
|
175
|
+
adapter: opts.adapter,
|
|
176
|
+
dbPath: opts.db,
|
|
177
|
+
};
|
|
178
|
+
if (opts.stdinPayload) {
|
|
179
|
+
const payload = await readStdinPayload();
|
|
180
|
+
const derived = payloadToScanInput(payload, baseInput.adapter);
|
|
181
|
+
baseInput = {
|
|
182
|
+
sessionId: derived.sessionId ?? baseInput.sessionId,
|
|
183
|
+
transcriptPath: derived.transcriptPath ?? baseInput.transcriptPath,
|
|
184
|
+
adapter: derived.adapter ?? baseInput.adapter,
|
|
185
|
+
dbPath: baseInput.dbPath,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const out = await runScan(baseInput);
|
|
189
|
+
if (!opts.silent) {
|
|
190
|
+
process.stdout.write(summarize(out, out.sessionId) + "\n");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
if (opts.silent) {
|
|
195
|
+
process.stderr.write(`friction-log scan (silent): ${err.message}\n`);
|
|
196
|
+
process.exit(0);
|
|
197
|
+
}
|
|
198
|
+
process.stderr.write(`${err.message}\n`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
program
|
|
203
|
+
.command("bilanz")
|
|
204
|
+
.description("Format a session-boundary bilanz: tools, frictions, tasks.")
|
|
205
|
+
.option("--session <id>", "Session id (defaults to most-recent in db)")
|
|
206
|
+
.option("--db <path>", "Override database path")
|
|
207
|
+
.action(async (opts) => {
|
|
208
|
+
try {
|
|
209
|
+
const out = await runBilanz({ sessionId: opts.session, dbPath: opts.db });
|
|
210
|
+
process.stdout.write(out.formatted);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
process.stderr.write(`${err.message}\n`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
program
|
|
218
|
+
.command("rm <frictionId>")
|
|
219
|
+
.description("Delete a friction (and any task rows pointing at it) from the local store.")
|
|
220
|
+
.option("--db <path>", "Override database path")
|
|
221
|
+
.action((frictionId, opts) => {
|
|
222
|
+
const id = Number(frictionId);
|
|
223
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
224
|
+
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
225
|
+
process.exit(2);
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
const out = runRm({ frictionId: id, dbPath: opts.db });
|
|
229
|
+
process.stdout.write(`removed friction id=${id} (${out.removed ? "ok" : "no-op"})\n`);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
process.stderr.write(`${err.message}\n`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
program
|
|
237
|
+
.command("update <frictionId>")
|
|
238
|
+
.description("Update a friction (status only in M2; more fields in later milestones).")
|
|
239
|
+
.addOption(new Option("--status <status>", "New status")
|
|
240
|
+
.choices([...STATUS_CHOICES])
|
|
241
|
+
.makeOptionMandatory(true))
|
|
242
|
+
.option("--db <path>", "Override database path")
|
|
243
|
+
.action((frictionId, opts) => {
|
|
244
|
+
const id = Number(frictionId);
|
|
245
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
246
|
+
process.stderr.write(`friction-log: <frictionId> must be a positive integer, got "${frictionId}"\n`);
|
|
247
|
+
process.exit(2);
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const out = runUpdate({
|
|
251
|
+
frictionId: id,
|
|
252
|
+
status: opts.status,
|
|
253
|
+
dbPath: opts.db,
|
|
254
|
+
});
|
|
255
|
+
process.stdout.write(`updated friction id=${out.id} status=${out.status}\n`);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
process.stderr.write(`${err.message}\n`);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
program
|
|
263
|
+
.command("search <query>")
|
|
264
|
+
.description("Full-text search over title + description (FTS5).")
|
|
265
|
+
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
266
|
+
...STATUS_CHOICES,
|
|
267
|
+
]))
|
|
268
|
+
.option("--tool <surface>", "Filter by tool surface")
|
|
269
|
+
.option("--category <name>", "Filter by category")
|
|
270
|
+
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
271
|
+
...SOURCE_CHOICES,
|
|
272
|
+
]))
|
|
273
|
+
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
274
|
+
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
275
|
+
.option("--json", "Emit JSON instead of a table")
|
|
276
|
+
.option("--db <path>", "Override database path")
|
|
277
|
+
.action((query, opts) => {
|
|
278
|
+
try {
|
|
279
|
+
const out = runSearch({
|
|
280
|
+
query,
|
|
281
|
+
status: opts.status,
|
|
282
|
+
tool: opts.tool,
|
|
283
|
+
category: opts.category,
|
|
284
|
+
source: opts.source,
|
|
285
|
+
age: opts.age,
|
|
286
|
+
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
287
|
+
dbPath: opts.db,
|
|
288
|
+
});
|
|
289
|
+
if (opts.json) {
|
|
290
|
+
process.stdout.write(JSON.stringify(out.frictions, null, 2) + "\n");
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
process.stdout.write(formatTable(out.frictions) + "\n");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
process.stderr.write(`${err.message}\n`);
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
program
|
|
302
|
+
.command("digest")
|
|
303
|
+
.description("Aggregations over frictions: counts, open-vs-filed, recurrences, avg hours to triage.")
|
|
304
|
+
.addOption(new Option("--group-by <field>", "Group by field")
|
|
305
|
+
.choices([...DIGEST_GROUP_CHOICES])
|
|
306
|
+
.makeOptionMandatory(true))
|
|
307
|
+
.option("--last <span>", "Restrict to frictions newer than e.g. 30d, 4w, 12h")
|
|
308
|
+
.option("--include-peers", "Also render read-only digest sections for each configured sync_export.peer_paths file")
|
|
309
|
+
.option("--json", "Emit JSON instead of a table")
|
|
310
|
+
.option("--config <path>", "Override config file path (only used by --include-peers)")
|
|
311
|
+
.option("--db <path>", "Override database path")
|
|
312
|
+
.action((opts) => {
|
|
313
|
+
try {
|
|
314
|
+
const out = runDigest({
|
|
315
|
+
groupBy: opts.groupBy,
|
|
316
|
+
last: opts.last,
|
|
317
|
+
dbPath: opts.db,
|
|
318
|
+
configPath: opts.config,
|
|
319
|
+
includePeers: Boolean(opts.includePeers),
|
|
320
|
+
});
|
|
321
|
+
if (opts.json) {
|
|
322
|
+
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
process.stdout.write(formatDigest(out) + "\n");
|
|
326
|
+
}
|
|
327
|
+
if (out.peers) {
|
|
328
|
+
for (const peer of out.peers) {
|
|
329
|
+
if (peer.error) {
|
|
330
|
+
process.stderr.write(`friction-log: warning: peer digest source ${peer.sourcePath} (origin=${peer.origin}) skipped: ${peer.error}\n`);
|
|
331
|
+
}
|
|
332
|
+
else if (peer.skipped > 0) {
|
|
333
|
+
process.stderr.write(`friction-log: warning: peer digest source ${peer.sourcePath} (origin=${peer.origin}) skipped ${peer.skipped} malformed record(s)\n`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
process.stderr.write(`${err.message}\n`);
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
program
|
|
344
|
+
.command("export")
|
|
345
|
+
.description("Export frictions as JSON, CSV, or Markdown.")
|
|
346
|
+
.addOption(new Option("--format <fmt>", "Output format")
|
|
347
|
+
.choices([...EXPORT_FORMAT_CHOICES])
|
|
348
|
+
.default("json"))
|
|
349
|
+
.option("--out <path>", "Write to a file instead of stdout")
|
|
350
|
+
.option("--query <text>", "Only export frictions matching an FTS5 query")
|
|
351
|
+
.addOption(new Option("--status <status>", "Filter by status").choices([
|
|
352
|
+
...STATUS_CHOICES,
|
|
353
|
+
]))
|
|
354
|
+
.option("--tool <surface>", "Filter by tool surface")
|
|
355
|
+
.option("--category <name>", "Filter by category")
|
|
356
|
+
.addOption(new Option("--source <source>", "Filter by source").choices([
|
|
357
|
+
...SOURCE_CHOICES,
|
|
358
|
+
]))
|
|
359
|
+
.option("--age <span>", "Only frictions newer than e.g. 14d, 4w, 12h")
|
|
360
|
+
.option("--limit <n>", "Max rows (default 100)", (v) => Number(v))
|
|
361
|
+
.option("--db <path>", "Override database path")
|
|
362
|
+
.action((opts) => {
|
|
363
|
+
try {
|
|
364
|
+
const out = runExport({
|
|
365
|
+
format: opts.format,
|
|
366
|
+
out: opts.out,
|
|
367
|
+
query: opts.query,
|
|
368
|
+
status: opts.status,
|
|
369
|
+
tool: opts.tool,
|
|
370
|
+
category: opts.category,
|
|
371
|
+
source: opts.source,
|
|
372
|
+
age: opts.age,
|
|
373
|
+
limit: typeof opts.limit === "number" ? opts.limit : undefined,
|
|
374
|
+
dbPath: opts.db,
|
|
375
|
+
});
|
|
376
|
+
if (out.out) {
|
|
377
|
+
process.stderr.write(`exported ${out.count} records (${out.format}) to ${out.out}\n`);
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
process.stdout.write(out.rendered);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
catch (err) {
|
|
384
|
+
process.stderr.write(`${err.message}\n`);
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
program
|
|
389
|
+
.command("sync-export")
|
|
390
|
+
.description("Write every friction as deterministic, origin-tagged JSON to the configured sync_export.path. " +
|
|
391
|
+
'No-op error unless "sync_export" (path + origin) is set in config.yml or via FRICTION_LOG_SYNC_EXPORT_PATH/_ORIGIN.')
|
|
392
|
+
.option("--config <path>", "Override config file path")
|
|
393
|
+
.option("--db <path>", "Override database path")
|
|
394
|
+
.action((opts) => {
|
|
395
|
+
try {
|
|
396
|
+
const out = runSyncExport({
|
|
397
|
+
configPath: opts.config,
|
|
398
|
+
dbPath: opts.db,
|
|
399
|
+
});
|
|
400
|
+
process.stderr.write(`sync-export: wrote ${out.count} frictions (origin=${out.origin}) to ${out.path}\n`);
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
process.stderr.write(`${err.message}\n`);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
program
|
|
408
|
+
.command("init")
|
|
409
|
+
.description("Interactive setup: write config.yml, optionally install Stop-hook.")
|
|
410
|
+
.addOption(new Option("--sink <name>", "Default sink (skips the interactive prompt)").choices([...availableSinks]))
|
|
411
|
+
.option("-y, --yes", "Non-interactive; use --sink (or markdown-file fallback) and skip Stop-hook offer")
|
|
412
|
+
.option("--install-stop-hook", "Force-install the Claude Code Stop-hook (skip the interactive y/N)")
|
|
413
|
+
.option("--config <path>", "Override config file path")
|
|
414
|
+
.option("--sync-export-path <path>", "Opt in to sync-export: write this config's sync_export.path")
|
|
415
|
+
.option("--sync-export-origin <name>", "Opt in to sync-export: this machine's sync_export.origin label")
|
|
416
|
+
.option("--sync-export-peer <path>", "Peer sync-export file to read for `digest --include-peers`, repeatable", (value, previous = []) => [...previous, value], [])
|
|
417
|
+
.action(async (opts) => {
|
|
418
|
+
try {
|
|
419
|
+
const syncExportPath = opts.syncExportPath;
|
|
420
|
+
const syncExportOrigin = opts.syncExportOrigin;
|
|
421
|
+
if (Boolean(syncExportPath) !== Boolean(syncExportOrigin)) {
|
|
422
|
+
process.stderr.write("friction-log: --sync-export-path and --sync-export-origin must be given together\n");
|
|
423
|
+
process.exit(2);
|
|
424
|
+
}
|
|
425
|
+
const syncExportPeers = Array.isArray(opts.syncExportPeer)
|
|
426
|
+
? opts.syncExportPeer
|
|
427
|
+
: [];
|
|
428
|
+
const out = await runInit({
|
|
429
|
+
configPath: opts.config,
|
|
430
|
+
sink: opts.sink,
|
|
431
|
+
yes: Boolean(opts.yes),
|
|
432
|
+
installStopHook: opts.installStopHook === true ? true : undefined,
|
|
433
|
+
syncExport: syncExportPath && syncExportOrigin
|
|
434
|
+
? {
|
|
435
|
+
path: syncExportPath,
|
|
436
|
+
origin: syncExportOrigin,
|
|
437
|
+
peerPaths: syncExportPeers,
|
|
438
|
+
}
|
|
439
|
+
: undefined,
|
|
440
|
+
});
|
|
441
|
+
process.stdout.write(`init: ${out.configWritten ? "wrote" : "no change to"} ${out.configPath}\n` +
|
|
442
|
+
(out.stopHookWrittenTo
|
|
443
|
+
? `init: Stop-hook installed at ${out.stopHookWrittenTo}\n`
|
|
444
|
+
: "") +
|
|
445
|
+
"\nNext steps:\n" +
|
|
446
|
+
out.nextSteps.map((s) => ` ${s}`).join("\n") +
|
|
447
|
+
"\n");
|
|
448
|
+
}
|
|
449
|
+
catch (err) {
|
|
450
|
+
process.stderr.write(`${err.message}\n`);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
program
|
|
455
|
+
.command("import <path>")
|
|
456
|
+
.description("Bulk-ingest frictions from a directory of markdown files.")
|
|
457
|
+
.addOption(new Option("--format <fmt>", "Source format")
|
|
458
|
+
.choices([...IMPORT_FORMAT_CHOICES])
|
|
459
|
+
.default("markdown-frontmatter"))
|
|
460
|
+
.option("--db <path>", "Override database path")
|
|
461
|
+
.action((path, opts) => {
|
|
462
|
+
try {
|
|
463
|
+
const out = runImport({
|
|
464
|
+
format: opts.format,
|
|
465
|
+
path,
|
|
466
|
+
dbPath: opts.db,
|
|
467
|
+
});
|
|
468
|
+
process.stdout.write(`import: scanned=${out.scanned} imported=${out.imported} skipped=${out.skipped}\n`);
|
|
469
|
+
if (out.errors.length) {
|
|
470
|
+
process.stderr.write(`import: ${out.errors.length} errors:\n`);
|
|
471
|
+
for (const e of out.errors.slice(0, 10)) {
|
|
472
|
+
process.stderr.write(` ${e.file}: ${e.reason}\n`);
|
|
473
|
+
}
|
|
474
|
+
if (out.errors.length > 10) {
|
|
475
|
+
process.stderr.write(` ... and ${out.errors.length - 10} more\n`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch (err) {
|
|
480
|
+
process.stderr.write(`${err.message}\n`);
|
|
481
|
+
process.exit(1);
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
async function readStdinPayload() {
|
|
485
|
+
const chunks = [];
|
|
486
|
+
for await (const chunk of process.stdin) {
|
|
487
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
488
|
+
}
|
|
489
|
+
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
490
|
+
if (!text)
|
|
491
|
+
return {};
|
|
492
|
+
try {
|
|
493
|
+
return JSON.parse(text);
|
|
494
|
+
}
|
|
495
|
+
catch {
|
|
496
|
+
return {};
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
500
|
+
process.stderr.write(`friction-log: ${err.message}\n`);
|
|
501
|
+
process.exit(1);
|
|
502
|
+
});
|
|
503
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract the minimum major version from an engines range such as ">=22".
|
|
3
|
+
* Returns null when the range is not of the simple ">=N[.x.y]" form.
|
|
4
|
+
*/
|
|
5
|
+
export declare function parseMinMajor(range: string): number | null;
|
|
6
|
+
/** True when the running Node version satisfies the minimum major. */
|
|
7
|
+
export declare function isSupportedNode(running: string, minMajor: number): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Returns an error message when `running` is below the major required by
|
|
10
|
+
* `enginesRange`, or null when it is supported (or the range is not parseable).
|
|
11
|
+
*/
|
|
12
|
+
export declare function nodeGuardMessage(running: string, enginesRange: string): string | null;
|
|
13
|
+
/** Reads the `engines.node` range from the package's own package.json. */
|
|
14
|
+
export declare function readEnginesNode(): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
/**
|
|
5
|
+
* Extract the minimum major version from an engines range such as ">=22".
|
|
6
|
+
* Returns null when the range is not of the simple ">=N[.x.y]" form.
|
|
7
|
+
*/
|
|
8
|
+
export function parseMinMajor(range) {
|
|
9
|
+
const m = /^\s*>=\s*v?(\d+)(?:\.\d+){0,2}\s*$/.exec(range);
|
|
10
|
+
return m ? Number(m[1]) : null;
|
|
11
|
+
}
|
|
12
|
+
/** True when the running Node version satisfies the minimum major. */
|
|
13
|
+
export function isSupportedNode(running, minMajor) {
|
|
14
|
+
const major = Number(running.replace(/^v/, "").split(".")[0]);
|
|
15
|
+
return Number.isInteger(major) && major >= minMajor;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns an error message when `running` is below the major required by
|
|
19
|
+
* `enginesRange`, or null when it is supported (or the range is not parseable).
|
|
20
|
+
*/
|
|
21
|
+
export function nodeGuardMessage(running, enginesRange) {
|
|
22
|
+
const minMajor = parseMinMajor(enginesRange);
|
|
23
|
+
if (minMajor === null || isSupportedNode(running, minMajor))
|
|
24
|
+
return null;
|
|
25
|
+
return (`friction-log requires Node ${enginesRange} but is running on Node ${running}. ` +
|
|
26
|
+
`Its SQLite binding does not work on this version; upgrade Node and retry.`);
|
|
27
|
+
}
|
|
28
|
+
/** Reads the `engines.node` range from the package's own package.json. */
|
|
29
|
+
export function readEnginesNode() {
|
|
30
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
const raw = readFileSync(join(here, "..", "package.json"), "utf8");
|
|
32
|
+
const parsed = JSON.parse(raw);
|
|
33
|
+
const node = parsed.engines?.node;
|
|
34
|
+
return typeof node === "string" ? node : "";
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=node-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-guard.js","sourceRoot":"","sources":["../src/node-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,QAAgB;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,YAAoB;IAEpB,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,IAAI,IAAI,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,OAAO,CACL,8BAA8B,YAAY,2BAA2B,OAAO,IAAI;QAChF,2EAA2E,CAC5E,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqC,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;IAClC,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC"}
|
package/package.json
CHANGED