wicked-crew 0.16.4 → 0.16.6
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/dist/api/ask-paths.d.ts +5 -2
- package/dist/api/ask-paths.d.ts.map +1 -1
- package/dist/api/ask-paths.js +6 -3
- package/dist/api/ask-paths.js.map +1 -1
- package/dist/api/chat-scope.d.ts +8 -3
- package/dist/api/chat-scope.d.ts.map +1 -1
- package/dist/api/chat-scope.js +17 -5
- package/dist/api/chat-scope.js.map +1 -1
- package/dist/api/chat-workflow.d.ts +60 -0
- package/dist/api/chat-workflow.d.ts.map +1 -0
- package/dist/api/chat-workflow.js +80 -0
- package/dist/api/chat-workflow.js.map +1 -0
- package/dist/api/endpoint-manifest-live.d.ts.map +1 -1
- package/dist/api/endpoint-manifest-live.js +2 -0
- package/dist/api/endpoint-manifest-live.js.map +1 -1
- package/dist/api/needs.d.ts +116 -0
- package/dist/api/needs.d.ts.map +1 -0
- package/dist/api/needs.js +618 -0
- package/dist/api/needs.js.map +1 -0
- package/dist/api/routes.d.ts +23 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +297 -25
- package/dist/api/routes.js.map +1 -1
- package/dist/api/run-liveness.d.ts +8 -0
- package/dist/api/run-liveness.d.ts.map +1 -1
- package/dist/api/run-liveness.js +39 -7
- package/dist/api/run-liveness.js.map +1 -1
- package/dist/api/run-timing-index.d.ts +6 -0
- package/dist/api/run-timing-index.d.ts.map +1 -1
- package/dist/api/run-timing-index.js +18 -0
- package/dist/api/run-timing-index.js.map +1 -1
- package/dist/api/server.d.ts +8 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +149 -3
- package/dist/api/server.js.map +1 -1
- package/dist/api/system-snapshot.d.ts +7 -15
- package/dist/api/system-snapshot.d.ts.map +1 -1
- package/dist/api/system-snapshot.js +7 -115
- package/dist/api/system-snapshot.js.map +1 -1
- package/dist/core/run-identity.d.ts.map +1 -1
- package/dist/core/run-identity.js +3 -0
- package/dist/core/run-identity.js.map +1 -1
- package/dist/evals/capture.d.ts +93 -0
- package/dist/evals/capture.d.ts.map +1 -0
- package/dist/evals/capture.js +419 -0
- package/dist/evals/capture.js.map +1 -0
- package/dist/evals/replay.d.ts +33 -0
- package/dist/evals/replay.d.ts.map +1 -0
- package/dist/evals/replay.js +87 -0
- package/dist/evals/replay.js.map +1 -0
- package/dist/evals/routes.d.ts +48 -0
- package/dist/evals/routes.d.ts.map +1 -0
- package/dist/evals/routes.js +121 -0
- package/dist/evals/routes.js.map +1 -0
- package/dist/evals/run-cli.d.ts +31 -0
- package/dist/evals/run-cli.d.ts.map +1 -0
- package/dist/evals/run-cli.js +128 -0
- package/dist/evals/run-cli.js.map +1 -0
- package/dist/evals/runner.d.ts +34 -0
- package/dist/evals/runner.d.ts.map +1 -0
- package/dist/evals/runner.js +181 -0
- package/dist/evals/runner.js.map +1 -0
- package/dist/evals/score.d.ts +31 -0
- package/dist/evals/score.d.ts.map +1 -0
- package/dist/evals/score.js +191 -0
- package/dist/evals/score.js.map +1 -0
- package/dist/evals/seed-needs-you.d.ts +17 -0
- package/dist/evals/seed-needs-you.d.ts.map +1 -0
- package/dist/evals/seed-needs-you.js +57 -0
- package/dist/evals/seed-needs-you.js.map +1 -0
- package/dist/evals/seed-rig.d.ts +9 -0
- package/dist/evals/seed-rig.d.ts.map +1 -0
- package/dist/evals/seed-rig.js +156 -0
- package/dist/evals/seed-rig.js.map +1 -0
- package/dist/evals/stats.d.ts +31 -0
- package/dist/evals/stats.d.ts.map +1 -0
- package/dist/evals/stats.js +59 -0
- package/dist/evals/stats.js.map +1 -0
- package/dist/evals/steering.d.ts +9 -0
- package/dist/evals/steering.d.ts.map +1 -0
- package/dist/evals/steering.js +25 -0
- package/dist/evals/steering.js.map +1 -0
- package/dist/evals/store.d.ts +26 -0
- package/dist/evals/store.d.ts.map +1 -0
- package/dist/evals/store.js +96 -0
- package/dist/evals/store.js.map +1 -0
- package/dist/evals/synthetic.d.ts +17 -0
- package/dist/evals/synthetic.d.ts.map +1 -0
- package/dist/evals/synthetic.js +71 -0
- package/dist/evals/synthetic.js.map +1 -0
- package/dist/evals/types.d.ts +29 -0
- package/dist/evals/types.d.ts.map +1 -0
- package/dist/evals/types.js +25 -0
- package/dist/evals/types.js.map +1 -0
- package/dist/evals/workflow.d.ts +33 -0
- package/dist/evals/workflow.d.ts.map +1 -0
- package/dist/evals/workflow.js +66 -0
- package/dist/evals/workflow.js.map +1 -0
- package/dist/insights/analyze-cli.d.ts +18 -0
- package/dist/insights/analyze-cli.d.ts.map +1 -0
- package/dist/insights/analyze-cli.js +71 -0
- package/dist/insights/analyze-cli.js.map +1 -0
- package/dist/insights/analyze.d.ts +136 -0
- package/dist/insights/analyze.d.ts.map +1 -0
- package/dist/insights/analyze.js +358 -0
- package/dist/insights/analyze.js.map +1 -0
- package/dist/insights/review-service.d.ts +127 -0
- package/dist/insights/review-service.d.ts.map +1 -0
- package/dist/insights/review-service.js +392 -0
- package/dist/insights/review-service.js.map +1 -0
- package/dist/insights/routes.d.ts +15 -0
- package/dist/insights/routes.d.ts.map +1 -0
- package/dist/insights/routes.js +66 -0
- package/dist/insights/routes.js.map +1 -0
- package/dist/insights/run-facts.d.ts +64 -0
- package/dist/insights/run-facts.d.ts.map +1 -0
- package/dist/insights/run-facts.js +152 -0
- package/dist/insights/run-facts.js.map +1 -0
- package/dist/insights/stats.d.ts +38 -0
- package/dist/insights/stats.d.ts.map +1 -0
- package/dist/insights/stats.js +102 -0
- package/dist/insights/stats.js.map +1 -0
- package/dist/insights/store.d.ts +89 -0
- package/dist/insights/store.d.ts.map +1 -0
- package/dist/insights/store.js +87 -0
- package/dist/insights/store.js.map +1 -0
- package/dist/insights/workflow.d.ts +22 -0
- package/dist/insights/workflow.d.ts.map +1 -0
- package/dist/insights/workflow.js +39 -0
- package/dist/insights/workflow.js.map +1 -0
- package/dist/qe/ledger.d.ts +15 -0
- package/dist/qe/ledger.d.ts.map +1 -1
- package/dist/qe/ledger.js +24 -0
- package/dist/qe/ledger.js.map +1 -1
- package/dist/schedules/routes.d.ts +48 -0
- package/dist/schedules/routes.d.ts.map +1 -0
- package/dist/schedules/routes.js +72 -0
- package/dist/schedules/routes.js.map +1 -0
- package/dist/schedules/scheduler.d.ts +58 -0
- package/dist/schedules/scheduler.d.ts.map +1 -0
- package/dist/schedules/scheduler.js +194 -0
- package/dist/schedules/scheduler.js.map +1 -0
- package/dist/schedules/store.d.ts +67 -0
- package/dist/schedules/store.d.ts.map +1 -0
- package/dist/schedules/store.js +148 -0
- package/dist/schedules/store.js.map +1 -0
- package/dist/skills/runtime.d.ts +12 -2
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +27 -1
- package/dist/skills/runtime.js.map +1 -1
- package/dist/team/routes.d.ts +10 -0
- package/dist/team/routes.d.ts.map +1 -1
- package/dist/team/routes.js +3 -0
- package/dist/team/routes.js.map +1 -1
- package/endpoint-manifest.json +132 -1
- package/package.json +4 -3
- package/workflows/review-recent-work.json +54 -0
- package/workflows/run-evals.json +29 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/insights/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One run, folded into the facts the review counts (DES-RUNS-REVIEW-001 §4). Pure: a `SessionView` and its recorded
|
|
3
|
+
* events in, a {@link RunFact} out. Nothing here is estimated; a value the events do not carry is `null` or 0 and
|
|
4
|
+
* says so (`spendReported`).
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionView } from 'wicked-crew-api-types';
|
|
7
|
+
/** A recorded event as `runEvents` returns it: the frame plus `ts` (epoch ms). Read loosely, field by field. */
|
|
8
|
+
export type LooseEvent = {
|
|
9
|
+
type: string;
|
|
10
|
+
ts?: number;
|
|
11
|
+
ord?: number;
|
|
12
|
+
} & Record<string, unknown>;
|
|
13
|
+
export type RunOutcome = 'passed' | 'failed' | 'cancelled' | 'open';
|
|
14
|
+
export interface RunOverride {
|
|
15
|
+
ord: number;
|
|
16
|
+
/** The escalation's condition (`floor_failed`, `judge_unavailable`, …), else `unknown`. */
|
|
17
|
+
condition: string;
|
|
18
|
+
/** What denied it (`repo_checks`, `substance`, …), when the engine said. */
|
|
19
|
+
source: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface RunFact {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
workflow: string;
|
|
25
|
+
repo: string | null;
|
|
26
|
+
projectId: string | null;
|
|
27
|
+
/** Every CLI that was assigned a unit. */
|
|
28
|
+
agents: string[];
|
|
29
|
+
createdAtMs: number;
|
|
30
|
+
endedAtMs: number | null;
|
|
31
|
+
status: string;
|
|
32
|
+
outcome: RunOutcome;
|
|
33
|
+
deliverRequested: boolean;
|
|
34
|
+
delivered: boolean;
|
|
35
|
+
archived: boolean;
|
|
36
|
+
/** Launch → the end of a delivered run, ms. `null` when nothing was delivered. */
|
|
37
|
+
timeToPrMs: number | null;
|
|
38
|
+
/** Σ repo-check durations, ms (0 when no floor ran). */
|
|
39
|
+
floorMs: number;
|
|
40
|
+
/** Σ time parked on a person, ms (a gate or an escalation, until it was decided). */
|
|
41
|
+
waitHumanMs: number;
|
|
42
|
+
overrides: RunOverride[];
|
|
43
|
+
spendUsd: number;
|
|
44
|
+
/** Whether any `cliUsage` frame carried a cost (an unreported CLI reads 0, which is not "free"). */
|
|
45
|
+
spendReported: boolean;
|
|
46
|
+
tokens: number;
|
|
47
|
+
/** Reassignments plus failed steps. */
|
|
48
|
+
retries: number;
|
|
49
|
+
stalls: number;
|
|
50
|
+
benched: {
|
|
51
|
+
cli: string;
|
|
52
|
+
reason: string;
|
|
53
|
+
}[];
|
|
54
|
+
/** For a failed run: what stopped it, as one comparable line. */
|
|
55
|
+
failureSignature: string | null;
|
|
56
|
+
/** A failure nobody archived, or a run open for over a day. */
|
|
57
|
+
unresolved: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** A run open longer than this is unresolved (it is waiting on someone, or stuck). */
|
|
60
|
+
export declare const STALE_OPEN_MS: number;
|
|
61
|
+
/** `created_at` is epoch seconds on the wire; a value already in ms is kept. */
|
|
62
|
+
export declare function epochMs(v: unknown): number;
|
|
63
|
+
export declare function runFactOf(view: SessionView, events: readonly LooseEvent[], nowMs: number): RunFact;
|
|
64
|
+
//# sourceMappingURL=run-facts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-facts.d.ts","sourceRoot":"","sources":["../../src/insights/run-facts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,gHAAgH;AAChH,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/F,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,2FAA2F;IAC3F,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,oGAAoG;IACpG,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,iEAAiE;IACjE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,sFAAsF;AACtF,eAAO,MAAM,aAAa,QAAiB,CAAC;AAO5C,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAG1C;AAaD,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CA8GlG"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One run, folded into the facts the review counts (DES-RUNS-REVIEW-001 §4). Pure: a `SessionView` and its recorded
|
|
3
|
+
* events in, a {@link RunFact} out. Nothing here is estimated; a value the events do not carry is `null` or 0 and
|
|
4
|
+
* says so (`spendReported`).
|
|
5
|
+
*/
|
|
6
|
+
/** A run open longer than this is unresolved (it is waiting on someone, or stuck). */
|
|
7
|
+
export const STALE_OPEN_MS = 24 * 3_600_000;
|
|
8
|
+
/** One wait longer than this is clipped (a gate left over a weekend should not swamp a median). */
|
|
9
|
+
const MAX_WAIT_MS = 7 * 24 * 3_600_000;
|
|
10
|
+
const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
|
|
11
|
+
const str = (v) => (typeof v === 'string' && v.trim() !== '' ? v : null);
|
|
12
|
+
/** `created_at` is epoch seconds on the wire; a value already in ms is kept. */
|
|
13
|
+
export function epochMs(v) {
|
|
14
|
+
const n = num(v);
|
|
15
|
+
return n > 0 && n < 1e12 ? n * 1000 : n;
|
|
16
|
+
}
|
|
17
|
+
function outcomeOf(status, deliverRequested, delivered) {
|
|
18
|
+
if (status === 'completed')
|
|
19
|
+
return deliverRequested && !delivered ? 'failed' : 'passed';
|
|
20
|
+
if (status === 'failed')
|
|
21
|
+
return 'failed';
|
|
22
|
+
if (status === 'cancelled')
|
|
23
|
+
return 'cancelled';
|
|
24
|
+
return 'open';
|
|
25
|
+
}
|
|
26
|
+
const TERMINAL_EVENTS = new Set(['sessionCompleted', 'sessionFailed', 'sessionCancelled']);
|
|
27
|
+
const PARK_EVENTS = new Set(['awaitingHuman', 'gateEscalated']);
|
|
28
|
+
const UNPARK_EVENTS = new Set(['gateDecided', 'resumed']);
|
|
29
|
+
export function runFactOf(view, events, nowMs) {
|
|
30
|
+
const s = view.session;
|
|
31
|
+
const status = String(s['status'] ?? 'unknown');
|
|
32
|
+
const deliverRequested = s['deliver_requested'] === true;
|
|
33
|
+
const delivered = s['delivery'] === 'delivered';
|
|
34
|
+
const createdAtMs = epochMs(s['created_at']) || num(events[0]?.ts);
|
|
35
|
+
const ordered = [...events].sort((a, b) => num(a.ts) - num(b.ts));
|
|
36
|
+
let endedAtMs = null;
|
|
37
|
+
let floorMs = 0;
|
|
38
|
+
let waitHumanMs = 0;
|
|
39
|
+
let spendUsd = 0;
|
|
40
|
+
let spendReported = false;
|
|
41
|
+
let tokens = 0;
|
|
42
|
+
let retries = 0;
|
|
43
|
+
let stalls = 0;
|
|
44
|
+
const overrides = [];
|
|
45
|
+
const benched = new Map();
|
|
46
|
+
// A unit parked on a person: when it parked, and the escalation (if any) a later allow overrides.
|
|
47
|
+
const parked = new Map();
|
|
48
|
+
const escalated = new Map();
|
|
49
|
+
let lastEscalation = null;
|
|
50
|
+
let lastStepFailure = null;
|
|
51
|
+
for (const e of ordered) {
|
|
52
|
+
const ts = num(e.ts);
|
|
53
|
+
const ord = num(e.ord);
|
|
54
|
+
if (TERMINAL_EVENTS.has(e.type))
|
|
55
|
+
endedAtMs = ts;
|
|
56
|
+
if (e.type === 'repoChecksEvaluated' && Array.isArray(e['checks'])) {
|
|
57
|
+
for (const c of e['checks'])
|
|
58
|
+
floorMs += num(c?.['durationMs']);
|
|
59
|
+
}
|
|
60
|
+
if (PARK_EVENTS.has(e.type) && !parked.has(ord))
|
|
61
|
+
parked.set(ord, ts);
|
|
62
|
+
if (e.type === 'gateEscalated') {
|
|
63
|
+
const condition = str(e['condition']) ?? 'unknown';
|
|
64
|
+
const source = str(e['denialSource']);
|
|
65
|
+
escalated.set(ord, { condition, source });
|
|
66
|
+
lastEscalation = source !== null ? `${condition} (${source})` : condition;
|
|
67
|
+
}
|
|
68
|
+
if (UNPARK_EVENTS.has(e.type) && parked.has(ord)) {
|
|
69
|
+
waitHumanMs += Math.min(MAX_WAIT_MS, Math.max(0, ts - parked.get(ord)));
|
|
70
|
+
parked.delete(ord);
|
|
71
|
+
}
|
|
72
|
+
if (e.type === 'gateDecided' && e['allow'] === true && escalated.has(ord)) {
|
|
73
|
+
const esc = escalated.get(ord);
|
|
74
|
+
overrides.push({ ord, condition: esc.condition, source: esc.source });
|
|
75
|
+
escalated.delete(ord);
|
|
76
|
+
}
|
|
77
|
+
if (e.type === 'cliUsage') {
|
|
78
|
+
if (typeof e['costUsd'] === 'number') {
|
|
79
|
+
spendUsd += num(e['costUsd']);
|
|
80
|
+
spendReported = true;
|
|
81
|
+
}
|
|
82
|
+
tokens += num(e['inputTokens']) + num(e['outputTokens']);
|
|
83
|
+
}
|
|
84
|
+
if (e.type === 'unitReassigned')
|
|
85
|
+
retries += 1;
|
|
86
|
+
if (e.type === 'stepFailed') {
|
|
87
|
+
retries += 1;
|
|
88
|
+
lastStepFailure = str(e['failureKind']);
|
|
89
|
+
}
|
|
90
|
+
if (e.type === 'workerStalled')
|
|
91
|
+
stalls += 1;
|
|
92
|
+
if (e.type === 'seatBenched') {
|
|
93
|
+
const cli = str(e['cli']);
|
|
94
|
+
if (cli !== null)
|
|
95
|
+
benched.set(cli, { cli, reason: str(e['reason']) ?? 'unknown' });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const lastTs = ordered.length > 0 ? num(ordered[ordered.length - 1]?.ts) : null;
|
|
99
|
+
const terminal = status === 'completed' || status === 'failed' || status === 'cancelled';
|
|
100
|
+
if (terminal && endedAtMs === null)
|
|
101
|
+
endedAtMs = lastTs;
|
|
102
|
+
// A gate still open on a live run counts its wait so far.
|
|
103
|
+
if (!terminal)
|
|
104
|
+
for (const since of parked.values())
|
|
105
|
+
waitHumanMs += Math.min(MAX_WAIT_MS, Math.max(0, nowMs - since));
|
|
106
|
+
const outcome = outcomeOf(status, deliverRequested, delivered);
|
|
107
|
+
const archived = s['archived_at'] !== null && s['archived_at'] !== undefined;
|
|
108
|
+
// Agents are the seats that did work: a Tool unit (`routing.method: "tool"`, run by `bash` or `wicked-estate`) is not one.
|
|
109
|
+
const agents = [...new Set(view.units.flatMap((u) => {
|
|
110
|
+
const unit = u;
|
|
111
|
+
if (unit['routing']?.method === 'tool')
|
|
112
|
+
return [];
|
|
113
|
+
const cli = str(unit['assigned_cli']);
|
|
114
|
+
return cli === null ? [] : [cli];
|
|
115
|
+
}))].sort();
|
|
116
|
+
let failureSignature = null;
|
|
117
|
+
if (outcome === 'failed') {
|
|
118
|
+
if (status === 'completed')
|
|
119
|
+
failureSignature = 'deliver did not land';
|
|
120
|
+
else
|
|
121
|
+
failureSignature = lastEscalation ?? lastStepFailure ?? 'unknown';
|
|
122
|
+
}
|
|
123
|
+
const unresolved = (outcome === 'failed' && !archived) || (outcome === 'open' && !archived && nowMs - createdAtMs > STALE_OPEN_MS);
|
|
124
|
+
return {
|
|
125
|
+
id: String(s['id']),
|
|
126
|
+
title: (str(s['title']) ?? str(s['problem']) ?? String(s['id'])).split('\n')[0]?.slice(0, 120) ?? String(s['id']),
|
|
127
|
+
workflow: str(s['workflow_id']) ?? 'free-text',
|
|
128
|
+
repo: str(s['repo_ref']),
|
|
129
|
+
projectId: str(s['project_id']),
|
|
130
|
+
agents,
|
|
131
|
+
createdAtMs,
|
|
132
|
+
endedAtMs,
|
|
133
|
+
status,
|
|
134
|
+
outcome,
|
|
135
|
+
deliverRequested,
|
|
136
|
+
delivered,
|
|
137
|
+
archived,
|
|
138
|
+
timeToPrMs: delivered && endedAtMs !== null ? Math.max(0, endedAtMs - createdAtMs) : null,
|
|
139
|
+
floorMs,
|
|
140
|
+
waitHumanMs,
|
|
141
|
+
overrides,
|
|
142
|
+
spendUsd,
|
|
143
|
+
spendReported,
|
|
144
|
+
tokens,
|
|
145
|
+
retries,
|
|
146
|
+
stalls,
|
|
147
|
+
benched: [...benched.values()],
|
|
148
|
+
failureSignature,
|
|
149
|
+
unresolved,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=run-facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-facts.js","sourceRoot":"","sources":["../../src/insights/run-facts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The statistics the run review stands on (DES-RUNS-REVIEW-001 §4). Pure and deterministic: the same inputs give
|
|
3
|
+
* the same numbers, byte for byte, so a review can be re-derived.
|
|
4
|
+
*
|
|
5
|
+
* - Rates: Wilson score interval (95 %), which stays inside [0, 1] and is honest at small n.
|
|
6
|
+
* - Long-tailed data (durations, spend, retries): the median and percentiles, never the mean. The interval is a
|
|
7
|
+
* bootstrap 95 % CI of the median: 1,000 resamples from a SEEDED generator (mulberry32), so it is reproducible.
|
|
8
|
+
* - Below {@link MIN_SAMPLE} no trend is called: the comparison says "too few runs to tell".
|
|
9
|
+
*/
|
|
10
|
+
/** The smallest sample a trend may be called on, in the window and in the baseline. */
|
|
11
|
+
export declare const MIN_SAMPLE = 5;
|
|
12
|
+
export declare const BOOTSTRAP_RESAMPLES = 1000;
|
|
13
|
+
export interface Interval {
|
|
14
|
+
lo: number;
|
|
15
|
+
hi: number;
|
|
16
|
+
}
|
|
17
|
+
/** Wilson score interval for `successes` of `n` (95 %). `null` when n is 0. */
|
|
18
|
+
export declare function wilson(successes: number, n: number, z?: number): Interval | null;
|
|
19
|
+
/** Linear-interpolated percentile (q in [0, 1]) of an ALREADY SORTED array. `null` when empty. */
|
|
20
|
+
export declare function percentileSorted(sorted: readonly number[], q: number): number | null;
|
|
21
|
+
export declare function sortedCopy(values: readonly number[]): number[];
|
|
22
|
+
export declare function median(values: readonly number[]): number | null;
|
|
23
|
+
/** mulberry32: a small, well-mixed 32-bit PRNG. Seeded, so every bootstrap is reproducible. */
|
|
24
|
+
export declare function mulberry32(seed: number): () => number;
|
|
25
|
+
/** A stable 32-bit seed from a label (FNV-1a), so each metric's bootstrap has its own reproducible stream. */
|
|
26
|
+
export declare function seedOf(label: string): number;
|
|
27
|
+
/** Bootstrap 95 % percentile CI of the median. `null` when empty. */
|
|
28
|
+
export declare function bootstrapMedianCI(values: readonly number[], seed: number, resamples?: number): Interval | null;
|
|
29
|
+
/** What a comparison against the baseline concluded. */
|
|
30
|
+
export type Verdict = 'too-few' | 'no-change' | 'improved' | 'regressed';
|
|
31
|
+
/**
|
|
32
|
+
* Compare a window value (with its interval) against a baseline point value. Notable only when BOTH samples reach
|
|
33
|
+
* {@link MIN_SAMPLE} and the window's interval EXCLUDES the baseline value. `higherIsBetter` gives the direction.
|
|
34
|
+
*/
|
|
35
|
+
export declare function compare(windowN: number, windowInterval: Interval | null, baselineN: number, baselineValue: number | null, higherIsBetter: boolean): Verdict;
|
|
36
|
+
/** Round for display and storage (a review is read by people; 4 significant decimals are plenty). */
|
|
37
|
+
export declare function round(v: number | null, places?: number): number | null;
|
|
38
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/insights/stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uFAAuF;AACvF,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,SAAM,GAAG,QAAQ,GAAG,IAAI,CAS7E;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQpF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE9D;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAE/D;AAED,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,MAAM,CASrD;AAED,8GAA8G;AAC9G,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO5C;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,SAAsB,GAAG,QAAQ,GAAG,IAAI,CAc3H;AAED,wDAAwD;AACxD,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,QAAQ,GAAG,IAAI,EAC/B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,OAAO,GACtB,OAAO,CAKT;AAED,qGAAqG;AACrG,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,SAAI,GAAG,MAAM,GAAG,IAAI,CAIjE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The statistics the run review stands on (DES-RUNS-REVIEW-001 §4). Pure and deterministic: the same inputs give
|
|
3
|
+
* the same numbers, byte for byte, so a review can be re-derived.
|
|
4
|
+
*
|
|
5
|
+
* - Rates: Wilson score interval (95 %), which stays inside [0, 1] and is honest at small n.
|
|
6
|
+
* - Long-tailed data (durations, spend, retries): the median and percentiles, never the mean. The interval is a
|
|
7
|
+
* bootstrap 95 % CI of the median: 1,000 resamples from a SEEDED generator (mulberry32), so it is reproducible.
|
|
8
|
+
* - Below {@link MIN_SAMPLE} no trend is called: the comparison says "too few runs to tell".
|
|
9
|
+
*/
|
|
10
|
+
/** The smallest sample a trend may be called on, in the window and in the baseline. */
|
|
11
|
+
export const MIN_SAMPLE = 5;
|
|
12
|
+
const Z95 = 1.959963984540054;
|
|
13
|
+
export const BOOTSTRAP_RESAMPLES = 1000;
|
|
14
|
+
/** Wilson score interval for `successes` of `n` (95 %). `null` when n is 0. */
|
|
15
|
+
export function wilson(successes, n, z = Z95) {
|
|
16
|
+
if (n <= 0)
|
|
17
|
+
return null;
|
|
18
|
+
const p = successes / n;
|
|
19
|
+
const z2 = z * z;
|
|
20
|
+
const denom = 1 + z2 / n;
|
|
21
|
+
const centre = (p + z2 / (2 * n)) / denom;
|
|
22
|
+
const half = (z * Math.sqrt((p * (1 - p)) / n + z2 / (4 * n * n))) / denom;
|
|
23
|
+
// Exact at the edges (no float dust): 0 successes has lower bound 0, n successes upper bound 1.
|
|
24
|
+
return { lo: successes === 0 ? 0 : Math.max(0, centre - half), hi: successes === n ? 1 : Math.min(1, centre + half) };
|
|
25
|
+
}
|
|
26
|
+
/** Linear-interpolated percentile (q in [0, 1]) of an ALREADY SORTED array. `null` when empty. */
|
|
27
|
+
export function percentileSorted(sorted, q) {
|
|
28
|
+
if (sorted.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
const pos = (sorted.length - 1) * Math.min(1, Math.max(0, q));
|
|
31
|
+
const lo = Math.floor(pos);
|
|
32
|
+
const hi = Math.ceil(pos);
|
|
33
|
+
const a = sorted[lo];
|
|
34
|
+
const b = sorted[hi];
|
|
35
|
+
return a + (b - a) * (pos - lo);
|
|
36
|
+
}
|
|
37
|
+
export function sortedCopy(values) {
|
|
38
|
+
return [...values].sort((a, b) => a - b);
|
|
39
|
+
}
|
|
40
|
+
export function median(values) {
|
|
41
|
+
return percentileSorted(sortedCopy(values), 0.5);
|
|
42
|
+
}
|
|
43
|
+
/** mulberry32: a small, well-mixed 32-bit PRNG. Seeded, so every bootstrap is reproducible. */
|
|
44
|
+
export function mulberry32(seed) {
|
|
45
|
+
let a = seed >>> 0;
|
|
46
|
+
return () => {
|
|
47
|
+
a = (a + 0x6d2b79f5) >>> 0;
|
|
48
|
+
let t = a;
|
|
49
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
50
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
51
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** A stable 32-bit seed from a label (FNV-1a), so each metric's bootstrap has its own reproducible stream. */
|
|
55
|
+
export function seedOf(label) {
|
|
56
|
+
let h = 0x811c9dc5;
|
|
57
|
+
for (let i = 0; i < label.length; i += 1) {
|
|
58
|
+
h ^= label.charCodeAt(i);
|
|
59
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
60
|
+
}
|
|
61
|
+
return h >>> 0;
|
|
62
|
+
}
|
|
63
|
+
/** Bootstrap 95 % percentile CI of the median. `null` when empty. */
|
|
64
|
+
export function bootstrapMedianCI(values, seed, resamples = BOOTSTRAP_RESAMPLES) {
|
|
65
|
+
const n = values.length;
|
|
66
|
+
if (n === 0)
|
|
67
|
+
return null;
|
|
68
|
+
if (n === 1)
|
|
69
|
+
return { lo: values[0], hi: values[0] };
|
|
70
|
+
const rand = mulberry32(seed);
|
|
71
|
+
const medians = new Array(resamples);
|
|
72
|
+
const sample = new Array(n);
|
|
73
|
+
for (let r = 0; r < resamples; r += 1) {
|
|
74
|
+
for (let i = 0; i < n; i += 1)
|
|
75
|
+
sample[i] = values[Math.floor(rand() * n)];
|
|
76
|
+
sample.sort((a, b) => a - b);
|
|
77
|
+
medians[r] = percentileSorted(sample, 0.5);
|
|
78
|
+
}
|
|
79
|
+
medians.sort((a, b) => a - b);
|
|
80
|
+
return { lo: percentileSorted(medians, 0.025), hi: percentileSorted(medians, 0.975) };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Compare a window value (with its interval) against a baseline point value. Notable only when BOTH samples reach
|
|
84
|
+
* {@link MIN_SAMPLE} and the window's interval EXCLUDES the baseline value. `higherIsBetter` gives the direction.
|
|
85
|
+
*/
|
|
86
|
+
export function compare(windowN, windowInterval, baselineN, baselineValue, higherIsBetter) {
|
|
87
|
+
if (windowN < MIN_SAMPLE || baselineN < MIN_SAMPLE || windowInterval === null || baselineValue === null)
|
|
88
|
+
return 'too-few';
|
|
89
|
+
if (windowInterval.lo > baselineValue)
|
|
90
|
+
return higherIsBetter ? 'improved' : 'regressed';
|
|
91
|
+
if (windowInterval.hi < baselineValue)
|
|
92
|
+
return higherIsBetter ? 'regressed' : 'improved';
|
|
93
|
+
return 'no-change';
|
|
94
|
+
}
|
|
95
|
+
/** Round for display and storage (a review is read by people; 4 significant decimals are plenty). */
|
|
96
|
+
export function round(v, places = 4) {
|
|
97
|
+
if (v === null || !Number.isFinite(v))
|
|
98
|
+
return null;
|
|
99
|
+
const f = 10 ** places;
|
|
100
|
+
return Math.round(v * f) / f;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/insights/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The review history (DES-RUNS-REVIEW-001 §6): every review, its numbers, its recommendations and what happened
|
|
3
|
+
* to each. One JSON file in the state home, `daemon-insights.json` (the `daemon-` prefix the state-home fence
|
|
4
|
+
* already classifies), written atomically. A malformed file starts empty and never fails the boot.
|
|
5
|
+
*/
|
|
6
|
+
import type { Candidate, Confidence, Finding, MetricId, RecommendationKind, SampleStat, Window } from './analyze.js';
|
|
7
|
+
import type { Verdict } from './stats.js';
|
|
8
|
+
export declare const INSIGHTS_FILENAME = "daemon-insights.json";
|
|
9
|
+
/** Reviews kept (about four months at the default cadence). */
|
|
10
|
+
export declare const MAX_REVIEWS = 60;
|
|
11
|
+
export type ReviewStatus = 'running' | 'completed' | 'failed' | 'cancelled';
|
|
12
|
+
export type RecommendationState = 'new' | 'accepted' | 'dismissed';
|
|
13
|
+
export interface Recommendation {
|
|
14
|
+
/** `<review run id>:<candidate id>`: unique across the history. */
|
|
15
|
+
id: string;
|
|
16
|
+
candidate: string;
|
|
17
|
+
kind: RecommendationKind;
|
|
18
|
+
title: string;
|
|
19
|
+
evidence: Candidate['evidence'];
|
|
20
|
+
expectedEffect: string;
|
|
21
|
+
confidence: Confidence;
|
|
22
|
+
changeMind: string;
|
|
23
|
+
impact: number;
|
|
24
|
+
basis: Candidate['basis'];
|
|
25
|
+
action: Candidate['action'];
|
|
26
|
+
state: RecommendationState;
|
|
27
|
+
reason: string | null;
|
|
28
|
+
decidedAt: string | null;
|
|
29
|
+
/** The approve-queue proposal filed for a steering-rule or memory recommendation. */
|
|
30
|
+
proposalId: string | null;
|
|
31
|
+
proposalError: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface SeriesPoint {
|
|
34
|
+
metric: MetricId;
|
|
35
|
+
window: SampleStat;
|
|
36
|
+
baseline: SampleStat;
|
|
37
|
+
verdict: Verdict;
|
|
38
|
+
}
|
|
39
|
+
export interface Review {
|
|
40
|
+
runId: string;
|
|
41
|
+
trigger: 'schedule' | 'manual';
|
|
42
|
+
scheduleId: string | null;
|
|
43
|
+
launchedAt: string;
|
|
44
|
+
endedAt: string | null;
|
|
45
|
+
status: ReviewStatus;
|
|
46
|
+
window: Window;
|
|
47
|
+
baselineWindows: Window[];
|
|
48
|
+
projectIds: string[];
|
|
49
|
+
/** The seat's plain-language summary; `null` when the run wrote no usable report. */
|
|
50
|
+
summary: string | null;
|
|
51
|
+
/** Whether the seat's report was read (false = crew's own wording is shown, labelled "not interpreted"). */
|
|
52
|
+
interpreted: boolean;
|
|
53
|
+
totals: Record<string, number> | null;
|
|
54
|
+
/** The `all` segment's metrics: the trend lines. */
|
|
55
|
+
series: SeriesPoint[];
|
|
56
|
+
improvements: Pick<Finding, 'metric' | 'segment' | 'line'>[];
|
|
57
|
+
regressions: Pick<Finding, 'metric' | 'segment' | 'line'>[];
|
|
58
|
+
recommendations: Recommendation[];
|
|
59
|
+
watching: {
|
|
60
|
+
id: string;
|
|
61
|
+
title: string;
|
|
62
|
+
line: string;
|
|
63
|
+
}[];
|
|
64
|
+
error: string | null;
|
|
65
|
+
}
|
|
66
|
+
export declare function defaultInsightsPath(env?: NodeJS.ProcessEnv): string;
|
|
67
|
+
export declare class InsightsStore {
|
|
68
|
+
private readonly path;
|
|
69
|
+
private reviews;
|
|
70
|
+
constructor(path?: string);
|
|
71
|
+
/** Newest first. */
|
|
72
|
+
list(): Review[];
|
|
73
|
+
get(runId: string): Review | undefined;
|
|
74
|
+
/** The latest review that finished with numbers, of one scope (its sorted project ids joined; `''` = all runs):
|
|
75
|
+
* that scope's next window starts where this one's ended. No scope given = any review. */
|
|
76
|
+
lastCompleted(scope?: string): Review | undefined;
|
|
77
|
+
running(): Review[];
|
|
78
|
+
add(review: Review): void;
|
|
79
|
+
update(runId: string, patch: Partial<Omit<Review, 'runId'>>): Review | undefined;
|
|
80
|
+
findRecommendation(id: string): {
|
|
81
|
+
review: Review;
|
|
82
|
+
rec: Recommendation;
|
|
83
|
+
} | undefined;
|
|
84
|
+
updateRecommendation(id: string, patch: Partial<Omit<Recommendation, 'id'>>): Recommendation | undefined;
|
|
85
|
+
/** Recommendations nobody has decided yet, across the history. */
|
|
86
|
+
newCount(): number;
|
|
87
|
+
private persist;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/insights/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The review history (DES-RUNS-REVIEW-001 §6): every review, its numbers, its recommendations and what happened
|
|
3
|
+
* to each. One JSON file in the state home, `daemon-insights.json` (the `daemon-` prefix the state-home fence
|
|
4
|
+
* already classifies), written atomically. A malformed file starts empty and never fails the boot.
|
|
5
|
+
*/
|
|
6
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import { crewStateHome } from '../projects/state-home.js';
|
|
9
|
+
export const INSIGHTS_FILENAME = 'daemon-insights.json';
|
|
10
|
+
/** Reviews kept (about four months at the default cadence). */
|
|
11
|
+
export const MAX_REVIEWS = 60;
|
|
12
|
+
export function defaultInsightsPath(env = process.env) {
|
|
13
|
+
return env['WICKED_CREW_INSIGHTS'] ?? join(crewStateHome(), INSIGHTS_FILENAME);
|
|
14
|
+
}
|
|
15
|
+
export class InsightsStore {
|
|
16
|
+
path;
|
|
17
|
+
reviews = [];
|
|
18
|
+
constructor(path) {
|
|
19
|
+
this.path = path ?? defaultInsightsPath();
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(readFileSync(this.path, 'utf8'));
|
|
22
|
+
if (Array.isArray(parsed?.reviews)) {
|
|
23
|
+
this.reviews = parsed.reviews.filter((r) => typeof r === 'object' && r !== null && typeof r.runId === 'string' && Array.isArray(r.recommendations));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Missing or malformed: no history yet.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Newest first. */
|
|
31
|
+
list() {
|
|
32
|
+
return [...this.reviews].sort((a, b) => b.launchedAt.localeCompare(a.launchedAt));
|
|
33
|
+
}
|
|
34
|
+
get(runId) {
|
|
35
|
+
return this.reviews.find((r) => r.runId === runId);
|
|
36
|
+
}
|
|
37
|
+
/** The latest review that finished with numbers, of one scope (its sorted project ids joined; `''` = all runs):
|
|
38
|
+
* that scope's next window starts where this one's ended. No scope given = any review. */
|
|
39
|
+
lastCompleted(scope) {
|
|
40
|
+
return this.list().find((r) => r.status === 'completed' && (scope === undefined || [...r.projectIds].sort().join(',') === scope));
|
|
41
|
+
}
|
|
42
|
+
running() {
|
|
43
|
+
return this.reviews.filter((r) => r.status === 'running');
|
|
44
|
+
}
|
|
45
|
+
add(review) {
|
|
46
|
+
this.reviews = [review, ...this.reviews.filter((r) => r.runId !== review.runId)];
|
|
47
|
+
this.reviews = this.list().slice(0, MAX_REVIEWS);
|
|
48
|
+
this.persist();
|
|
49
|
+
}
|
|
50
|
+
update(runId, patch) {
|
|
51
|
+
const i = this.reviews.findIndex((r) => r.runId === runId);
|
|
52
|
+
if (i < 0)
|
|
53
|
+
return undefined;
|
|
54
|
+
const next = { ...this.reviews[i], ...patch };
|
|
55
|
+
this.reviews[i] = next;
|
|
56
|
+
this.persist();
|
|
57
|
+
return next;
|
|
58
|
+
}
|
|
59
|
+
findRecommendation(id) {
|
|
60
|
+
for (const review of this.reviews) {
|
|
61
|
+
const rec = review.recommendations.find((r) => r.id === id);
|
|
62
|
+
if (rec !== undefined)
|
|
63
|
+
return { review, rec };
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
updateRecommendation(id, patch) {
|
|
68
|
+
const found = this.findRecommendation(id);
|
|
69
|
+
if (found === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
const next = { ...found.rec, ...patch };
|
|
72
|
+
found.review.recommendations = found.review.recommendations.map((r) => (r.id === id ? next : r));
|
|
73
|
+
this.persist();
|
|
74
|
+
return next;
|
|
75
|
+
}
|
|
76
|
+
/** Recommendations nobody has decided yet, across the history. */
|
|
77
|
+
newCount() {
|
|
78
|
+
return this.reviews.reduce((a, r) => a + r.recommendations.filter((x) => x.state === 'new').length, 0);
|
|
79
|
+
}
|
|
80
|
+
persist() {
|
|
81
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
82
|
+
const tmp = `${this.path}.tmp-${process.pid}`;
|
|
83
|
+
writeFileSync(tmp, JSON.stringify({ version: 1, reviews: this.reviews }, null, 2), 'utf8');
|
|
84
|
+
renameSync(tmp, this.path);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/insights/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `review-recent-work` workflow (DES-RUNS-REVIEW-001 §3) is DATA: `packages/crew/workflows/review-recent-work.json`.
|
|
3
|
+
* This module only reads it, fills the three host tokens (`{node}`, `{analyze_cli}`, `{reviews_dir}`) and hands it to
|
|
4
|
+
* the engine, which validates it (`adapter.registerWorkflow`) like the interactive seams' runtime defs.
|
|
5
|
+
*/
|
|
6
|
+
import type { WorkflowDef } from '../core/types.js';
|
|
7
|
+
export declare const REVIEW_WORKFLOW = "review-recent-work";
|
|
8
|
+
/** The packaged def (`packages/crew/workflows/`), from `src/insights/` and from `dist/insights/` alike. */
|
|
9
|
+
export declare const REVIEW_WORKFLOW_FILE: string;
|
|
10
|
+
/** The analyze script beside this module (`.js` in dist; under vitest the `.ts` source sits here instead). */
|
|
11
|
+
export declare const ANALYZE_CLI: string;
|
|
12
|
+
/** Where each review's run directory lives: outside the daemon state home (the worker fence), like walkthroughs. */
|
|
13
|
+
export declare function defaultReviewsDir(env?: NodeJS.ProcessEnv): string;
|
|
14
|
+
export interface ReviewWorkflowTokens {
|
|
15
|
+
node: string;
|
|
16
|
+
analyzeCli: string;
|
|
17
|
+
reviewsDir: string;
|
|
18
|
+
}
|
|
19
|
+
/** Fill the def's tokens. Only the Tool `cmd` carries them; anything else unfilled is a packaging error. */
|
|
20
|
+
export declare function fillReviewWorkflow(raw: unknown, tokens: ReviewWorkflowTokens): WorkflowDef;
|
|
21
|
+
export declare function loadReviewWorkflow(tokens: ReviewWorkflowTokens, file?: string): WorkflowDef;
|
|
22
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/insights/workflow.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,eAAO,MAAM,eAAe,uBAAuB,CAAC;AAEpD,2GAA2G;AAC3G,eAAO,MAAM,oBAAoB,QAAqF,CAAC;AACvH,8GAA8G;AAC9G,eAAO,MAAM,WAAW,QAA8D,CAAC;AAEvF,oHAAoH;AACpH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE9E;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4GAA4G;AAC5G,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,GAAG,WAAW,CAc1F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,EAAE,IAAI,SAAuB,GAAG,WAAW,CAEzG"}
|