whodecided 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/checks/gate.d.ts +10 -0
- package/dist/checks/gate.js +19 -0
- package/dist/checks/gate.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +79 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/apply.d.ts +1 -0
- package/dist/commands/apply.js +68 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/board.d.ts +6 -0
- package/dist/commands/board.js +57 -0
- package/dist/commands/board.js.map +1 -0
- package/dist/commands/distill.d.ts +18 -0
- package/dist/commands/distill.js +116 -0
- package/dist/commands/distill.js.map +1 -0
- package/dist/commands/gate.d.ts +2 -0
- package/dist/commands/gate.js +27 -0
- package/dist/commands/gate.js.map +1 -0
- package/dist/commands/hook.d.ts +1 -0
- package/dist/commands/hook.js +189 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/recall.d.ts +19 -0
- package/dist/commands/recall.js +58 -0
- package/dist/commands/recall.js.map +1 -0
- package/dist/commands/report.d.ts +1 -0
- package/dist/commands/report.js +18 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/review.d.ts +1 -0
- package/dist/commands/review.js +211 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/scope.d.ts +17 -0
- package/dist/commands/scope.js +51 -0
- package/dist/commands/scope.js.map +1 -0
- package/dist/commands/share.d.ts +6 -0
- package/dist/commands/share.js +73 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/sync.d.ts +23 -0
- package/dist/commands/sync.js +214 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +80 -0
- package/dist/config.js.map +1 -0
- package/dist/distill/distiller.d.ts +15 -0
- package/dist/distill/distiller.js +92 -0
- package/dist/distill/distiller.js.map +1 -0
- package/dist/distill/prompt.d.ts +18 -0
- package/dist/distill/prompt.js +53 -0
- package/dist/distill/prompt.js.map +1 -0
- package/dist/distill/watermark.d.ts +5 -0
- package/dist/distill/watermark.js +22 -0
- package/dist/distill/watermark.js.map +1 -0
- package/dist/extract/candidates.d.ts +25 -0
- package/dist/extract/candidates.js +136 -0
- package/dist/extract/candidates.js.map +1 -0
- package/dist/git.d.ts +22 -0
- package/dist/git.js +78 -0
- package/dist/git.js.map +1 -0
- package/dist/jsonl.d.ts +14 -0
- package/dist/jsonl.js +30 -0
- package/dist/jsonl.js.map +1 -0
- package/dist/ledger/io.d.ts +30 -0
- package/dist/ledger/io.js +85 -0
- package/dist/ledger/io.js.map +1 -0
- package/dist/ledger/schema.d.ts +31 -0
- package/dist/ledger/schema.js +57 -0
- package/dist/ledger/schema.js.map +1 -0
- package/dist/patch/apply.d.ts +15 -0
- package/dist/patch/apply.js +63 -0
- package/dist/patch/apply.js.map +1 -0
- package/dist/patch/schema.d.ts +11 -0
- package/dist/patch/schema.js +21 -0
- package/dist/patch/schema.js.map +1 -0
- package/dist/render/html.d.ts +33 -0
- package/dist/render/html.js +593 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/md.d.ts +3 -0
- package/dist/render/md.js +39 -0
- package/dist/render/md.js.map +1 -0
- package/dist/render/term.d.ts +2 -0
- package/dist/render/term.js +40 -0
- package/dist/render/term.js.map +1 -0
- package/dist/trace/schema.d.ts +14 -0
- package/dist/trace/schema.js +25 -0
- package/dist/trace/schema.js.map +1 -0
- package/dist/transcript/locate.d.ts +10 -0
- package/dist/transcript/locate.js +30 -0
- package/dist/transcript/locate.js.map +1 -0
- package/dist/transcript/parser.d.ts +18 -0
- package/dist/transcript/parser.js +130 -0
- package/dist/transcript/parser.js.map +1 -0
- package/dist/validate.d.ts +4 -0
- package/dist/validate.js +13 -0
- package/dist/validate.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const PER_COLUMN = 5;
|
|
2
|
+
export function renderDocket(entries, header) {
|
|
3
|
+
const silent = entries.filter((e) => e.by === "agent" && !e.aware);
|
|
4
|
+
const reflexive = entries.filter((e) => e.by === "user" && !e.aware);
|
|
5
|
+
const deliberate = entries.filter((e) => e.aware);
|
|
6
|
+
const lines = [header, ""];
|
|
7
|
+
column(lines, `⚠ AI decided, never asked (${silent.length})`, silent);
|
|
8
|
+
column(lines, `⚠ you didn't read (${reflexive.length})`, reflexive);
|
|
9
|
+
column(lines, `✓ you decided (${deliberate.length})`, deliberate);
|
|
10
|
+
return lines.join("\n");
|
|
11
|
+
}
|
|
12
|
+
function column(lines, title, entries) {
|
|
13
|
+
if (entries.length === 0)
|
|
14
|
+
return;
|
|
15
|
+
lines.push(title);
|
|
16
|
+
const sorted = [...entries].sort(byUrgency);
|
|
17
|
+
for (const e of sorted.slice(0, PER_COLUMN)) {
|
|
18
|
+
lines.push(` ${e.id.padEnd(4)}${e.what}${annotate(e)}`);
|
|
19
|
+
}
|
|
20
|
+
if (sorted.length > PER_COLUMN)
|
|
21
|
+
lines.push(` (+${sorted.length - PER_COLUMN} more)`);
|
|
22
|
+
lines.push("");
|
|
23
|
+
}
|
|
24
|
+
function byUrgency(a, b) {
|
|
25
|
+
const rank = (e) => (e.precedent ? 10 : 0) + ({ low: 0, medium: 1, high: 2 }[e.reversibility ?? "high"] ?? 2);
|
|
26
|
+
return rank(a) - rank(b);
|
|
27
|
+
}
|
|
28
|
+
function annotate(e) {
|
|
29
|
+
const notes = [];
|
|
30
|
+
if (e.reversibility === "low")
|
|
31
|
+
notes.push("hard to reverse");
|
|
32
|
+
if (e.alternatives?.length)
|
|
33
|
+
notes.push(`vs ${e.alternatives[0]}`);
|
|
34
|
+
if (e.precedent)
|
|
35
|
+
notes.push(`precedent ${e.precedent}, deprioritized`);
|
|
36
|
+
if (e.why)
|
|
37
|
+
notes.push(e.why);
|
|
38
|
+
return notes.length > 0 ? ` ${notes.join(" · ")}` : "";
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=term.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"term.js","sourceRoot":"","sources":["../../src/render/term.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type JsonlResult } from "../jsonl.js";
|
|
2
|
+
export interface TestRunEvent {
|
|
3
|
+
t: string;
|
|
4
|
+
type: "test_run";
|
|
5
|
+
kind: string;
|
|
6
|
+
cmd: string;
|
|
7
|
+
exit: number;
|
|
8
|
+
pass?: number;
|
|
9
|
+
fail?: number;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}
|
|
12
|
+
export type TraceEvent = TestRunEvent;
|
|
13
|
+
export declare function parseTraceEvent(value: unknown): TraceEvent | string;
|
|
14
|
+
export declare function parseTrace(text: string): JsonlResult<TraceEvent>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { parseJsonl } from "../jsonl.js";
|
|
2
|
+
import { isIsoTimestamp, isNonEmptyString, isRecord } from "../validate.js";
|
|
3
|
+
export function parseTraceEvent(value) {
|
|
4
|
+
if (!isRecord(value))
|
|
5
|
+
return "not an object";
|
|
6
|
+
if (value.type !== "test_run")
|
|
7
|
+
return `unknown event type: ${String(value.type)}`;
|
|
8
|
+
if (!isIsoTimestamp(value.t))
|
|
9
|
+
return "t: ISO timestamp required";
|
|
10
|
+
if (!isNonEmptyString(value.kind))
|
|
11
|
+
return "kind: non-empty string required";
|
|
12
|
+
if (!isNonEmptyString(value.cmd))
|
|
13
|
+
return "cmd: non-empty string required";
|
|
14
|
+
if (typeof value.exit !== "number")
|
|
15
|
+
return "exit: number required";
|
|
16
|
+
for (const key of ["pass", "fail"]) {
|
|
17
|
+
if (value[key] !== undefined && typeof value[key] !== "number")
|
|
18
|
+
return `${key}: number expected`;
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
export function parseTrace(text) {
|
|
23
|
+
return parseJsonl(text, parseTraceEvent);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/trace/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAe5E,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IAC7C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,uBAAuB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAClF,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,2BAA2B,CAAC;IACjE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,iCAAiC,CAAC;IAC5E,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,gCAAgC,CAAC;IAC1E,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,uBAAuB,CAAC;IACnE,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,OAAO,GAAG,GAAG,mBAAmB,CAAC;IACnG,CAAC;IACD,OAAO,KAAgC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface LocateOptions {
|
|
2
|
+
cwd: string;
|
|
3
|
+
days: number;
|
|
4
|
+
sessions: number;
|
|
5
|
+
projectsDir?: string;
|
|
6
|
+
}
|
|
7
|
+
/** CC stores transcripts under a directory named after the slugified cwd. */
|
|
8
|
+
export declare function projectSlug(cwd: string): string;
|
|
9
|
+
/** Session files for this project, newest first, bounded by age and count. */
|
|
10
|
+
export declare function locateSessions(opts: LocateOptions): string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/** CC stores transcripts under a directory named after the slugified cwd. */
|
|
5
|
+
export function projectSlug(cwd) {
|
|
6
|
+
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
7
|
+
}
|
|
8
|
+
/** Session files for this project, newest first, bounded by age and count. */
|
|
9
|
+
export function locateSessions(opts) {
|
|
10
|
+
const dir = join(opts.projectsDir ?? join(homedir(), ".claude", "projects"), projectSlug(opts.cwd));
|
|
11
|
+
let names;
|
|
12
|
+
try {
|
|
13
|
+
names = readdirSync(dir);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
const cutoff = Date.now() - opts.days * 24 * 60 * 60 * 1000;
|
|
19
|
+
return names
|
|
20
|
+
.filter((n) => n.endsWith(".jsonl"))
|
|
21
|
+
.map((n) => {
|
|
22
|
+
const path = join(dir, n);
|
|
23
|
+
return { path, mtime: statSync(path).mtimeMs };
|
|
24
|
+
})
|
|
25
|
+
.filter((f) => f.mtime >= cutoff)
|
|
26
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
27
|
+
.slice(0, opts.sessions)
|
|
28
|
+
.map((f) => f.path);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=locate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/transcript/locate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpG,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5D,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IACjD,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACjC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type EventKind = "user_text" | "assistant_text" | "tool_use" | "tool_result" | "question_response" | "plan_approval" | "mode_change" | "unknown";
|
|
2
|
+
export interface SessionEvent {
|
|
3
|
+
session: string;
|
|
4
|
+
line: number;
|
|
5
|
+
t?: string;
|
|
6
|
+
kind: EventKind;
|
|
7
|
+
text?: string;
|
|
8
|
+
toolName?: string;
|
|
9
|
+
toolUseId?: string;
|
|
10
|
+
rejected?: boolean;
|
|
11
|
+
latencyMs?: number;
|
|
12
|
+
branch?: string;
|
|
13
|
+
cwd?: string;
|
|
14
|
+
mode?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Parse one CC transcript (jsonl text) into a flat event stream. */
|
|
18
|
+
export declare function parseTranscript(session: string, text: string): SessionEvent[];
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { isRecord } from "../validate.js";
|
|
2
|
+
const REJECTION_MARKER = "doesn't want to proceed";
|
|
3
|
+
/** Parse one CC transcript (jsonl text) into a flat event stream. */
|
|
4
|
+
export function parseTranscript(session, text) {
|
|
5
|
+
const events = [];
|
|
6
|
+
text.split("\n").forEach((raw, index) => {
|
|
7
|
+
if (raw.trim() === "")
|
|
8
|
+
return;
|
|
9
|
+
let json;
|
|
10
|
+
try {
|
|
11
|
+
json = JSON.parse(raw);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!isRecord(json) || json.isSidechain === true)
|
|
17
|
+
return;
|
|
18
|
+
events.push(...parseLine(session, index + 1, json));
|
|
19
|
+
});
|
|
20
|
+
linkEvents(events);
|
|
21
|
+
return events;
|
|
22
|
+
}
|
|
23
|
+
function parseLine(session, line, v) {
|
|
24
|
+
const base = {
|
|
25
|
+
session,
|
|
26
|
+
line,
|
|
27
|
+
t: typeof v.timestamp === "string" ? v.timestamp : undefined,
|
|
28
|
+
branch: typeof v.gitBranch === "string" ? v.gitBranch : undefined,
|
|
29
|
+
cwd: typeof v.cwd === "string" ? v.cwd : undefined,
|
|
30
|
+
};
|
|
31
|
+
if (v.type === "permission-mode" && typeof v.permissionMode === "string") {
|
|
32
|
+
return [{ ...base, kind: "mode_change", mode: v.permissionMode }];
|
|
33
|
+
}
|
|
34
|
+
if (v.type !== "user" && v.type !== "assistant") {
|
|
35
|
+
return [{ ...base, kind: "unknown" }];
|
|
36
|
+
}
|
|
37
|
+
const message = isRecord(v.message) ? v.message : {};
|
|
38
|
+
// The model that produced this assistant turn; "<synthetic>" is CC's internal
|
|
39
|
+
// filler, not a real decider, so drop it.
|
|
40
|
+
const model = v.type === "assistant" && typeof message.model === "string" && message.model !== "<synthetic>"
|
|
41
|
+
? message.model
|
|
42
|
+
: undefined;
|
|
43
|
+
if (model)
|
|
44
|
+
base.model = model;
|
|
45
|
+
const content = message.content;
|
|
46
|
+
if (v.type === "user" && typeof content === "string") {
|
|
47
|
+
return [{ ...base, kind: "user_text", text: content }];
|
|
48
|
+
}
|
|
49
|
+
if (!Array.isArray(content))
|
|
50
|
+
return [{ ...base, kind: "unknown" }];
|
|
51
|
+
const events = [];
|
|
52
|
+
for (const item of content) {
|
|
53
|
+
if (!isRecord(item))
|
|
54
|
+
continue;
|
|
55
|
+
if (item.type === "text" && typeof item.text === "string") {
|
|
56
|
+
events.push({ ...base, kind: v.type === "user" ? "user_text" : "assistant_text", text: item.text });
|
|
57
|
+
}
|
|
58
|
+
else if (item.type === "tool_use" && typeof item.name === "string") {
|
|
59
|
+
events.push({
|
|
60
|
+
...base,
|
|
61
|
+
kind: "tool_use",
|
|
62
|
+
toolName: item.name,
|
|
63
|
+
toolUseId: typeof item.id === "string" ? item.id : undefined,
|
|
64
|
+
text: summarizeInput(item.input),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else if (item.type === "tool_result") {
|
|
68
|
+
const resultText = flattenResult(item.content);
|
|
69
|
+
events.push({
|
|
70
|
+
...base,
|
|
71
|
+
kind: "tool_result",
|
|
72
|
+
toolUseId: typeof item.tool_use_id === "string" ? item.tool_use_id : undefined,
|
|
73
|
+
rejected: item.is_error === true && resultText.includes(REJECTION_MARKER),
|
|
74
|
+
text: resultText,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return events.length > 0 ? events : [{ ...base, kind: "unknown" }];
|
|
79
|
+
}
|
|
80
|
+
function summarizeInput(input) {
|
|
81
|
+
if (!isRecord(input))
|
|
82
|
+
return "";
|
|
83
|
+
for (const key of ["file_path", "command", "pattern", "url", "prompt"]) {
|
|
84
|
+
if (typeof input[key] === "string")
|
|
85
|
+
return input[key].slice(0, 200);
|
|
86
|
+
}
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
function flattenResult(content) {
|
|
90
|
+
if (typeof content === "string")
|
|
91
|
+
return content;
|
|
92
|
+
if (!Array.isArray(content))
|
|
93
|
+
return "";
|
|
94
|
+
return content
|
|
95
|
+
.map((c) => (isRecord(c) && typeof c.text === "string" ? c.text : ""))
|
|
96
|
+
.join("\n");
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Second pass: re-kind human-gated tool results (AskUserQuestion, ExitPlanMode)
|
|
100
|
+
* and compute response latencies. Those two tools block on the human, so their
|
|
101
|
+
* result latency is a clean think-time signal; ordinary tool results mix
|
|
102
|
+
* approval and execution time and get no latency.
|
|
103
|
+
*/
|
|
104
|
+
function linkEvents(events) {
|
|
105
|
+
const useById = new Map();
|
|
106
|
+
for (const e of events) {
|
|
107
|
+
if (e.kind === "tool_use" && e.toolUseId)
|
|
108
|
+
useById.set(e.toolUseId, e);
|
|
109
|
+
}
|
|
110
|
+
let lastAssistantT;
|
|
111
|
+
for (const e of events) {
|
|
112
|
+
if (e.kind === "assistant_text" || e.kind === "tool_use")
|
|
113
|
+
lastAssistantT = e.t;
|
|
114
|
+
if (e.kind === "user_text" && e.t && lastAssistantT) {
|
|
115
|
+
e.latencyMs = Date.parse(e.t) - Date.parse(lastAssistantT);
|
|
116
|
+
}
|
|
117
|
+
if (e.kind !== "tool_result" || !e.toolUseId)
|
|
118
|
+
continue;
|
|
119
|
+
const use = useById.get(e.toolUseId);
|
|
120
|
+
if (!use)
|
|
121
|
+
continue;
|
|
122
|
+
e.toolName = use.toolName;
|
|
123
|
+
if (use.toolName === "AskUserQuestion" || use.toolName === "ExitPlanMode") {
|
|
124
|
+
e.kind = use.toolName === "AskUserQuestion" ? "question_response" : "plan_approval";
|
|
125
|
+
if (e.t && use.t)
|
|
126
|
+
e.latencyMs = Date.parse(e.t) - Date.parse(use.t);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/transcript/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA4B1C,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEnD,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,IAAY;IAC3D,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACtC,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO;QAC9B,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;YAAE,OAAO;QACzD,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,OAAe,EAAE,IAAY,EAAE,CAA0B;IAC1E,MAAM,IAAI,GAAG;QACX,OAAO;QACP,IAAI;QACJ,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC5D,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACjE,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;KACnD,CAAC;IACF,IAAI,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QACzE,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChD,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,8EAA8E;IAC9E,0CAA0C;IAC1C,MAAM,KAAK,GACT,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,aAAa;QAC5F,CAAC,CAAC,OAAO,CAAC,KAAK;QACf,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,KAAK;QAAG,IAA2B,CAAC,KAAK,GAAG,KAAK,CAAC;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrD,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtG,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrE,MAAM,CAAC,IAAI,CAAC;gBACV,GAAG,IAAI;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,SAAS,EAAE,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;gBAC5D,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC;gBACV,GAAG,IAAI;gBACP,IAAI,EAAE,aAAa;gBACnB,SAAS,EAAE,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;gBAC9E,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBACzE,IAAI,EAAE,UAAU;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QACvE,IAAI,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,OAAQ,KAAK,CAAC,GAAG,CAAY,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACrE,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,MAAsB;IACxC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,cAAkC,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;YAAE,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,IAAI,cAAc,EAAE,CAAC;YACpD,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC,SAAS;YAAE,SAAS;QACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC1B,IAAI,GAAG,CAAC,QAAQ,KAAK,iBAAiB,IAAI,GAAG,CAAC,QAAQ,KAAK,cAAc,EAAE,CAAC;YAC1E,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,eAAe,CAAC;YACpF,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;gBAAE,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
2
|
+
export declare function isNonEmptyString(value: unknown): value is string;
|
|
3
|
+
export declare function isOptionalString(value: unknown): value is string | undefined;
|
|
4
|
+
export declare function isIsoTimestamp(value: unknown): value is string;
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
export function isNonEmptyString(value) {
|
|
5
|
+
return typeof value === "string" && value.length > 0;
|
|
6
|
+
}
|
|
7
|
+
export function isOptionalString(value) {
|
|
8
|
+
return value === undefined || typeof value === "string";
|
|
9
|
+
}
|
|
10
|
+
export function isIsoTimestamp(value) {
|
|
11
|
+
return isNonEmptyString(value) && !Number.isNaN(Date.parse(value));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACrE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "whodecided",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Common law for agentic coding: distill the decisions your AI agent silently made into a one-screen docket; every ruling becomes precedent",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Kai Zhu",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"claude-code",
|
|
10
|
+
"ai-coding",
|
|
11
|
+
"agent",
|
|
12
|
+
"audit",
|
|
13
|
+
"code-review",
|
|
14
|
+
"decision-log",
|
|
15
|
+
"cli"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/zhu-kai/whodecided#readme",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/zhu-kai/whodecided.git"
|
|
21
|
+
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/zhu-kai/whodecided/issues"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"whodecided": "dist/cli.js",
|
|
27
|
+
"wdd": "dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"prepublishOnly": "tsc"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"yaml": "^2.8.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^24.0.0",
|
|
45
|
+
"typescript": "^5.8.0",
|
|
46
|
+
"vitest": "^3.2.0"
|
|
47
|
+
}
|
|
48
|
+
}
|