@garygentry/system1-core 0.3.2 → 0.4.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/dist/egress/scrub.d.ts.map +1 -1
- package/dist/egress/scrub.js +16 -0
- package/dist/egress/scrub.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/model/schema.d.ts +22 -0
- package/dist/model/schema.d.ts.map +1 -0
- package/dist/model/schema.js +26 -0
- package/dist/model/schema.js.map +1 -0
- package/dist/opportunities/backlog.d.ts +280 -0
- package/dist/opportunities/backlog.d.ts.map +1 -0
- package/dist/opportunities/backlog.js +393 -0
- package/dist/opportunities/backlog.js.map +1 -0
- package/dist/prepare.d.ts +8 -0
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +42 -6
- package/dist/prepare.js.map +1 -1
- package/dist/project/project.d.ts +36 -0
- package/dist/project/project.d.ts.map +1 -1
- package/dist/project/project.js +64 -18
- package/dist/project/project.js.map +1 -1
- package/dist/sources/filter.d.ts +19 -0
- package/dist/sources/filter.d.ts.map +1 -0
- package/dist/sources/filter.js +30 -0
- package/dist/sources/filter.js.map +1 -0
- package/dist/sources/read.d.ts +10 -0
- package/dist/sources/read.d.ts.map +1 -1
- package/dist/sources/read.js +7 -2
- package/dist/sources/read.js.map +1 -1
- package/dist/sources/types.d.ts +2 -2
- package/dist/sources/types.d.ts.map +1 -1
- package/dist/spec/lint.d.ts +35 -0
- package/dist/spec/lint.d.ts.map +1 -0
- package/dist/spec/lint.js +175 -0
- package/dist/spec/lint.js.map +1 -0
- package/dist/spec/spec.d.ts +2 -0
- package/dist/spec/spec.d.ts.map +1 -1
- package/dist/spec/spec.js +3 -1
- package/dist/spec/spec.js.map +1 -1
- package/dist/tools/ask.d.ts.map +1 -1
- package/dist/tools/ask.js +10 -13
- package/dist/tools/ask.js.map +1 -1
- package/dist/tools/context.d.ts +5 -0
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +24 -0
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/doctor.d.ts +1 -1
- package/dist/tools/doctor.d.ts.map +1 -1
- package/dist/tools/doctor.js +33 -1
- package/dist/tools/doctor.js.map +1 -1
- package/dist/tools/many.d.ts.map +1 -1
- package/dist/tools/many.js +3 -0
- package/dist/tools/many.js.map +1 -1
- package/dist/tools/opportunities.d.ts +33 -0
- package/dist/tools/opportunities.d.ts.map +1 -0
- package/dist/tools/opportunities.js +74 -0
- package/dist/tools/opportunities.js.map +1 -0
- package/dist/tools/schemas.d.ts +155 -12
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +32 -25
- package/dist/tools/schemas.js.map +1 -1
- package/dist/tools/spec-check.d.ts +6 -0
- package/dist/tools/spec-check.d.ts.map +1 -1
- package/dist/tools/spec-check.js +3 -0
- package/dist/tools/spec-check.js.map +1 -1
- package/dist/tools/spec-lint.d.ts +31 -0
- package/dist/tools/spec-lint.d.ts.map +1 -0
- package/dist/tools/spec-lint.js +53 -0
- package/dist/tools/spec-lint.js.map +1 -0
- package/dist/transport/openrouter.d.ts +4 -1
- package/dist/transport/openrouter.d.ts.map +1 -1
- package/dist/transport/openrouter.js +5 -2
- package/dist/transport/openrouter.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { Type } from "typebox";
|
|
5
|
+
import { Value } from "typebox/value";
|
|
6
|
+
import { stateDir } from "../config/load.js";
|
|
7
|
+
import { DecisionsError } from "../errors.js";
|
|
8
|
+
import { QuestionSchema } from "../model/schema.js";
|
|
9
|
+
import { assertQuestionSet } from "../model/validate.js";
|
|
10
|
+
import { tokenizeFilter, tokenizeSort } from "../project/project.js";
|
|
11
|
+
/**
|
|
12
|
+
* The scout backlog: places where an LLM call, a hand-written heuristic or an
|
|
13
|
+
* agent fan-out is doing a decision model's job. The `scout` skill decides what
|
|
14
|
+
* counts; this module validates and persists it, so the backlog is a typed
|
|
15
|
+
* artifact rather than prose in a transcript. Every saving in it is projected
|
|
16
|
+
* (arithmetic over the inputs shown beside it), never measured.
|
|
17
|
+
*/
|
|
18
|
+
export const BACKLOG_FORMAT = 1;
|
|
19
|
+
const CLOSED = { additionalProperties: false };
|
|
20
|
+
const Text = Type.String({ minLength: 1 });
|
|
21
|
+
/** Bounded so the computed saving is always a finite number that survives JSON. */
|
|
22
|
+
const Usd = Type.Number({ minimum: 0, maximum: 1e6 });
|
|
23
|
+
const Status = Type.Union([
|
|
24
|
+
Type.Literal("new"),
|
|
25
|
+
Type.Literal("stale"),
|
|
26
|
+
Type.Literal("adopted"),
|
|
27
|
+
Type.Literal("rejected"),
|
|
28
|
+
]);
|
|
29
|
+
const candidateFields = {
|
|
30
|
+
/** `code`: a codebase (Mode A). `agents`: skills, hooks, agent configuration (Mode B). */
|
|
31
|
+
mode: Type.Union([Type.Literal("code"), Type.Literal("agents")]),
|
|
32
|
+
location: Type.Object({
|
|
33
|
+
path: Text,
|
|
34
|
+
lines: Type.Optional(Type.Object({ start: Type.Integer({ minimum: 1 }), end: Type.Integer({ minimum: 1 }) }, CLOSED)),
|
|
35
|
+
}, CLOSED),
|
|
36
|
+
/** What does the job today, e.g. "gpt-4o call parsed to an enum". */
|
|
37
|
+
mechanism: Text,
|
|
38
|
+
shape: Type.Union([
|
|
39
|
+
Type.Literal("single"),
|
|
40
|
+
Type.Literal("fanout"),
|
|
41
|
+
Type.Literal("cascade"),
|
|
42
|
+
Type.Literal("pairwise"),
|
|
43
|
+
]),
|
|
44
|
+
/**
|
|
45
|
+
* The text that triggered it, taken verbatim from the screened item. The id is
|
|
46
|
+
* derived from it, so it must be copied, not paraphrased.
|
|
47
|
+
*/
|
|
48
|
+
evidence: Type.String({ pattern: "\\S" }),
|
|
49
|
+
/** A draft question set that would replace the mechanism. */
|
|
50
|
+
questions: Type.Record(Type.String(), QuestionSchema, { minProperties: 1 }),
|
|
51
|
+
/**
|
|
52
|
+
* What replacing the mechanism would mainly buy. `cost`: cheaper calls.
|
|
53
|
+
* `quality`: better or more consistent verdicts (a regex or heuristic that
|
|
54
|
+
* costs nothing today, so its `savingUsd` can be negative). `latency`:
|
|
55
|
+
* faster answers. Rank within a benefit, not across them.
|
|
56
|
+
*/
|
|
57
|
+
benefit: Type.Union([Type.Literal("cost"), Type.Literal("quality"), Type.Literal("latency")]),
|
|
58
|
+
/** The inputs of the projected saving. The saving itself is computed here. */
|
|
59
|
+
projected: Type.Object({
|
|
60
|
+
volume: Type.Number({ minimum: 0, maximum: 1e12 }),
|
|
61
|
+
/** What `volume` counts per, e.g. "day", "PR", "run". */
|
|
62
|
+
per: Text,
|
|
63
|
+
currentCostPerItemUsd: Usd,
|
|
64
|
+
decisionCostPerItemUsd: Usd,
|
|
65
|
+
/** Where the figures came from. */
|
|
66
|
+
note: Type.Optional(Type.String()),
|
|
67
|
+
}, CLOSED),
|
|
68
|
+
risk: Type.Object({
|
|
69
|
+
level: Type.Union([Type.Literal("low"), Type.Literal("medium"), Type.Literal("high")]),
|
|
70
|
+
/** What would go wrong if the replacement erred. */
|
|
71
|
+
note: Text,
|
|
72
|
+
}, CLOSED),
|
|
73
|
+
/** The next step, e.g. "save the spec with design, then adopt". */
|
|
74
|
+
next: Text,
|
|
75
|
+
/** Defaults to `new`. `rejected` needs a `statusReason`. */
|
|
76
|
+
status: Type.Optional(Status),
|
|
77
|
+
statusReason: Type.Optional(Text),
|
|
78
|
+
/** Which sweep produced it, and whether its screening answers were live or replayed. */
|
|
79
|
+
source: Type.Object({
|
|
80
|
+
sweep: Text,
|
|
81
|
+
answers: Type.Union([Type.Literal("live"), Type.Literal("replay")]),
|
|
82
|
+
}, CLOSED),
|
|
83
|
+
};
|
|
84
|
+
export const CandidateSchema = Type.Object(candidateFields, CLOSED);
|
|
85
|
+
export const OpportunitySchema = Type.Object({
|
|
86
|
+
id: Type.String({ pattern: "^op-[0-9a-f]{12}$" }),
|
|
87
|
+
...candidateFields,
|
|
88
|
+
status: Status,
|
|
89
|
+
projected: Type.Object({
|
|
90
|
+
...candidateFields.projected.properties,
|
|
91
|
+
basis: Type.Literal("projected"),
|
|
92
|
+
/** volume × (current − decision), per `per`. Negative means it would cost more. */
|
|
93
|
+
savingUsd: Type.Number(),
|
|
94
|
+
}, CLOSED),
|
|
95
|
+
firstSeenAt: Type.String(),
|
|
96
|
+
seenAt: Type.String(),
|
|
97
|
+
}, CLOSED);
|
|
98
|
+
export const BacklogSchema = Type.Object({
|
|
99
|
+
version: Type.Literal(BACKLOG_FORMAT),
|
|
100
|
+
opportunities: Type.Array(OpportunitySchema),
|
|
101
|
+
}, CLOSED);
|
|
102
|
+
export function backlogPath(repoRoot) {
|
|
103
|
+
return join(stateDir(repoRoot), "opportunities.json");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stable across re-runs and file moves: the mode and the evidence, with
|
|
107
|
+
* whitespace collapsed. Not the path (a moved file keeps its id) and nothing
|
|
108
|
+
* the agent paraphrases.
|
|
109
|
+
*/
|
|
110
|
+
export function opportunityId(mode, evidence) {
|
|
111
|
+
const normal = evidence.replace(/\s+/g, " ").trim();
|
|
112
|
+
return `op-${createHash("sha256").update(`${mode}\n${normal}`).digest("hex").slice(0, 12)}`;
|
|
113
|
+
}
|
|
114
|
+
export function projectedSaving(p) {
|
|
115
|
+
return round(p.volume * (p.currentCostPerItemUsd - p.decisionCostPerItemUsd));
|
|
116
|
+
}
|
|
117
|
+
/** Every problem with a backlog value, as `path message` lines. Empty when valid. */
|
|
118
|
+
export function backlogProblems(value) {
|
|
119
|
+
const problems = [...Value.Errors(BacklogSchema, value)].map((e) => `${e.instancePath || "/"} ${e.message}`);
|
|
120
|
+
if (problems.length)
|
|
121
|
+
return problems;
|
|
122
|
+
const backlog = value;
|
|
123
|
+
const seen = new Set();
|
|
124
|
+
backlog.opportunities.forEach((o, i) => {
|
|
125
|
+
if (seen.has(o.id))
|
|
126
|
+
problems.push(`/opportunities/${i}/id ${o.id} appears twice`);
|
|
127
|
+
seen.add(o.id);
|
|
128
|
+
if (o.id !== opportunityId(o.mode, o.evidence)) {
|
|
129
|
+
problems.push(`/opportunities/${i}/id does not match its mode and evidence`);
|
|
130
|
+
}
|
|
131
|
+
if (o.projected.savingUsd !== projectedSaving(o.projected)) {
|
|
132
|
+
problems.push(`/opportunities/${i}/projected/savingUsd does not match its inputs`);
|
|
133
|
+
}
|
|
134
|
+
problems.push(...candidateProblems(o, `/opportunities/${i}`));
|
|
135
|
+
});
|
|
136
|
+
return problems;
|
|
137
|
+
}
|
|
138
|
+
/** The checks a schema can't express. */
|
|
139
|
+
function candidateProblems(c, at) {
|
|
140
|
+
const problems = [];
|
|
141
|
+
if (c.status === "rejected" && !c.statusReason) {
|
|
142
|
+
problems.push(`${at}/statusReason is required when status is rejected`);
|
|
143
|
+
}
|
|
144
|
+
if (!Number.isFinite(projectedSaving(c.projected))) {
|
|
145
|
+
problems.push(`${at}/projected gives a saving that isn't a finite number`);
|
|
146
|
+
}
|
|
147
|
+
if (c.location.lines && c.location.lines.end < c.location.lines.start) {
|
|
148
|
+
problems.push(`${at}/location/lines end is before start`);
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
assertQuestionSet(c.questions);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
problems.push(`${at}/questions ${error.message}`);
|
|
155
|
+
}
|
|
156
|
+
return problems;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Read the backlog. A missing file is an empty backlog; a malformed one is an
|
|
160
|
+
* error, and is never repaired or overwritten.
|
|
161
|
+
*/
|
|
162
|
+
export function readBacklog(file) {
|
|
163
|
+
if (!existsSync(file))
|
|
164
|
+
return { version: BACKLOG_FORMAT, opportunities: [] };
|
|
165
|
+
let text;
|
|
166
|
+
try {
|
|
167
|
+
text = readFileSync(file, "utf8");
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
throw malformed(file, [`cannot read it: ${error.message}`]);
|
|
171
|
+
}
|
|
172
|
+
let value;
|
|
173
|
+
try {
|
|
174
|
+
value = JSON.parse(text);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw malformed(file, [`not JSON: ${error.message}`]);
|
|
178
|
+
}
|
|
179
|
+
const problems = backlogProblems(value);
|
|
180
|
+
if (problems.length)
|
|
181
|
+
throw malformed(file, problems);
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
function malformed(file, problems) {
|
|
185
|
+
return new DecisionsError("invalid-request", `${file} is not a valid backlog (it was left as it is):\n ${problems.join("\n ")}`, { file, problems });
|
|
186
|
+
}
|
|
187
|
+
const LOCK_WAIT_MS = 5_000;
|
|
188
|
+
const LOCK_STALE_MS = 30_000;
|
|
189
|
+
/**
|
|
190
|
+
* Run `body` holding the backlog's lock, so concurrent `add`s (two sweeps, or
|
|
191
|
+
* a sweep run in parallel) serialise instead of losing each other's entries.
|
|
192
|
+
* A lock older than 30 s is from a crashed run and is taken over.
|
|
193
|
+
*/
|
|
194
|
+
export function withBacklogLock(file, body) {
|
|
195
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
196
|
+
const lock = `${file}.lock`;
|
|
197
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
198
|
+
for (;;) {
|
|
199
|
+
try {
|
|
200
|
+
closeSync(openSync(lock, "wx"));
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
if (error.code !== "EEXIST")
|
|
205
|
+
throw error;
|
|
206
|
+
try {
|
|
207
|
+
if (Date.now() - statSync(lock).mtimeMs > LOCK_STALE_MS)
|
|
208
|
+
rmSync(lock, { force: true });
|
|
209
|
+
}
|
|
210
|
+
catch { }
|
|
211
|
+
if (Date.now() > deadline) {
|
|
212
|
+
throw new DecisionsError("invalid-request", `${file} is locked by another \`decide opportunities add\` (${lock}). Retry, or delete the lock file if no add is running.`, { file, lock });
|
|
213
|
+
}
|
|
214
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
return body();
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
rmSync(lock, { force: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/** Written whole, through a temp file, so a crash never leaves half a backlog. */
|
|
225
|
+
export function writeBacklog(file, backlog) {
|
|
226
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
227
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
228
|
+
writeFileSync(tmp, `${JSON.stringify(backlog, null, 2)}\n`);
|
|
229
|
+
renameSync(tmp, file);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Merge candidates into a backlog.
|
|
233
|
+
*
|
|
234
|
+
* - A candidate whose id exists updates that entry (location, draft, figures,
|
|
235
|
+
* `seenAt`), keeping `firstSeenAt`. Its status changes only when the
|
|
236
|
+
* candidate gives one, so a rejection survives a re-sweep.
|
|
237
|
+
* - A new id is added with status `new` unless the candidate says otherwise.
|
|
238
|
+
* - A `new` entry that this add's sweep produced before, at a path the add
|
|
239
|
+
* covers, in the same mode, and that the add didn't see again is marked
|
|
240
|
+
* `stale`: its evidence changed. It is never deleted. A stale entry seen again
|
|
241
|
+
* is `new` again.
|
|
242
|
+
*/
|
|
243
|
+
export function mergeCandidates(backlog, candidates, now) {
|
|
244
|
+
const problems = candidates.flatMap((c, i) => candidateProblems(c, `/candidates/${i}`));
|
|
245
|
+
if (problems.length) {
|
|
246
|
+
throw new DecisionsError("invalid-request", `Invalid candidates:\n ${problems.join("\n ")}`, {
|
|
247
|
+
problems,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const byId = new Map(backlog.opportunities.map((o) => [o.id, o]));
|
|
251
|
+
const existed = new Set(byId.keys());
|
|
252
|
+
const seen = new Set();
|
|
253
|
+
for (const { statusReason: reason, ...c } of candidates) {
|
|
254
|
+
const id = opportunityId(c.mode, c.evidence);
|
|
255
|
+
seen.add(id);
|
|
256
|
+
const before = byId.get(id);
|
|
257
|
+
// A new status replaces the old reason; no status keeps both.
|
|
258
|
+
const statusReason = reason ?? (c.status ? undefined : before?.statusReason);
|
|
259
|
+
byId.set(id, {
|
|
260
|
+
id,
|
|
261
|
+
...c,
|
|
262
|
+
// Seeing the evidence again disproves "stale"; any other status stands.
|
|
263
|
+
status: c.status ?? (before?.status === "stale" ? "new" : before?.status) ?? "new",
|
|
264
|
+
...(statusReason ? { statusReason } : {}),
|
|
265
|
+
projected: { ...c.projected, basis: "projected", savingUsd: projectedSaving(c.projected) },
|
|
266
|
+
firstSeenAt: before?.firstSeenAt ?? now,
|
|
267
|
+
seenAt: now,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const added = [...seen].filter((id) => !existed.has(id));
|
|
271
|
+
const updated = [...seen].filter((id) => existed.has(id));
|
|
272
|
+
// Coverage is per sweep: another sweep's entries at the same path (different
|
|
273
|
+
// questions, or an incremental add) are not disproved by this one.
|
|
274
|
+
const key = (o) => `${o.mode}\n${o.location.path}\n${o.source.sweep}`;
|
|
275
|
+
const covered = new Set(candidates.map(key));
|
|
276
|
+
const staled = [];
|
|
277
|
+
for (const o of byId.values()) {
|
|
278
|
+
if (o.status === "new" && !seen.has(o.id) && covered.has(key(o))) {
|
|
279
|
+
byId.set(o.id, { ...o, status: "stale" });
|
|
280
|
+
staled.push(o.id);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
backlog: { version: BACKLOG_FORMAT, opportunities: [...byId.values()] },
|
|
285
|
+
added,
|
|
286
|
+
updated,
|
|
287
|
+
staled,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Fields a record filter or sort may name: the sub-fields each object field
|
|
292
|
+
* has, and the one a bare name means. Checked statically, so a typo is an
|
|
293
|
+
* error even on an empty backlog.
|
|
294
|
+
*/
|
|
295
|
+
const FIELDS = {
|
|
296
|
+
id: {},
|
|
297
|
+
mode: {},
|
|
298
|
+
benefit: {},
|
|
299
|
+
status: {},
|
|
300
|
+
statusReason: {},
|
|
301
|
+
shape: {},
|
|
302
|
+
mechanism: {},
|
|
303
|
+
evidence: {},
|
|
304
|
+
next: {},
|
|
305
|
+
firstSeenAt: {},
|
|
306
|
+
seenAt: {},
|
|
307
|
+
risk: { default: "level", subs: ["level", "note"] },
|
|
308
|
+
projected: {
|
|
309
|
+
default: "savingUsd",
|
|
310
|
+
subs: [
|
|
311
|
+
"savingUsd",
|
|
312
|
+
"volume",
|
|
313
|
+
"per",
|
|
314
|
+
"currentCostPerItemUsd",
|
|
315
|
+
"decisionCostPerItemUsd",
|
|
316
|
+
"basis",
|
|
317
|
+
"note",
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
location: { default: "path", subs: ["path", "lines.start", "lines.end"] },
|
|
321
|
+
source: { default: "sweep", subs: ["sweep", "answers"] },
|
|
322
|
+
};
|
|
323
|
+
/** Top-level fields of an entry, for `--fields`. */
|
|
324
|
+
export const ENTRY_FIELDS = [...Object.keys(OpportunitySchema.properties)];
|
|
325
|
+
/** `status=new`, `risk in medium,high`, `projected>=0.5`, `location.path=src/a.ts`. */
|
|
326
|
+
export function parseRecordFilter(text) {
|
|
327
|
+
const t = tokenizeFilter(text);
|
|
328
|
+
if (!t) {
|
|
329
|
+
throw new DecisionsError("invalid-request", `Cannot parse --keep "${text}". Use <field>[.<sub>]<op><value>, e.g. status=new or projected>=0.01`);
|
|
330
|
+
}
|
|
331
|
+
const field = recordField(t.name, t.path, text);
|
|
332
|
+
if ((t.op === ">" || t.op === ">=" || t.op === "<" || t.op === "<=") &&
|
|
333
|
+
typeof t.value !== "number") {
|
|
334
|
+
throw new DecisionsError("invalid-request", `--keep "${text}": ${t.op} needs a number`);
|
|
335
|
+
}
|
|
336
|
+
return { field, op: t.op, value: t.value, source: text };
|
|
337
|
+
}
|
|
338
|
+
export function parseRecordSort(text) {
|
|
339
|
+
const t = tokenizeSort(text);
|
|
340
|
+
if (!t) {
|
|
341
|
+
throw new DecisionsError("invalid-request", `Cannot parse --sort "${text}". Use <field>[.<sub>][:asc|desc]`);
|
|
342
|
+
}
|
|
343
|
+
return { field: recordField(t.name, t.path, text), direction: t.direction };
|
|
344
|
+
}
|
|
345
|
+
function recordField(name, path, text) {
|
|
346
|
+
const spec = Object.hasOwn(FIELDS, name) ? FIELDS[name] : undefined;
|
|
347
|
+
if (!spec) {
|
|
348
|
+
throw new DecisionsError("invalid-request", `"${text}": no field "${name}". Fields: ${Object.keys(FIELDS).join(", ")}`);
|
|
349
|
+
}
|
|
350
|
+
if (path && !spec.subs?.includes(path)) {
|
|
351
|
+
throw new DecisionsError("invalid-request", spec.subs
|
|
352
|
+
? `"${text}": ${name} has no "${path}". Use one of: ${spec.subs.join(", ")}`
|
|
353
|
+
: `"${text}": ${name} has no sub-fields`);
|
|
354
|
+
}
|
|
355
|
+
const sub = path || spec.default;
|
|
356
|
+
return sub ? `${name}.${sub}` : name;
|
|
357
|
+
}
|
|
358
|
+
export function readField(o, field) {
|
|
359
|
+
let value = o;
|
|
360
|
+
for (const key of field.split(".")) {
|
|
361
|
+
if (value === null || typeof value !== "object")
|
|
362
|
+
return undefined;
|
|
363
|
+
value = value[key];
|
|
364
|
+
}
|
|
365
|
+
return value;
|
|
366
|
+
}
|
|
367
|
+
export function recordMatches(o, f) {
|
|
368
|
+
const actual = readField(o, f.field);
|
|
369
|
+
switch (f.op) {
|
|
370
|
+
case "in":
|
|
371
|
+
return f.value.includes(String(actual));
|
|
372
|
+
case "=":
|
|
373
|
+
return String(actual) === String(f.value);
|
|
374
|
+
case "!=":
|
|
375
|
+
return String(actual) !== String(f.value);
|
|
376
|
+
default: {
|
|
377
|
+
if (typeof actual !== "number")
|
|
378
|
+
return false;
|
|
379
|
+
const v = f.value;
|
|
380
|
+
return f.op === ">="
|
|
381
|
+
? actual >= v
|
|
382
|
+
: f.op === ">"
|
|
383
|
+
? actual > v
|
|
384
|
+
: f.op === "<="
|
|
385
|
+
? actual <= v
|
|
386
|
+
: actual < v;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function round(n) {
|
|
391
|
+
return Math.round(n * 1e9) / 1e9;
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=backlog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backlog.js","sourceRoot":"","sources":["../../src/opportunities/backlog.ts"],"names":[],"mappings":"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"}
|
package/dist/prepare.d.ts
CHANGED
|
@@ -12,9 +12,17 @@ export interface PrepareInput {
|
|
|
12
12
|
cwd: string;
|
|
13
13
|
/** Extra exclude patterns from config. */
|
|
14
14
|
exclude?: readonly string[];
|
|
15
|
+
/** Paths the caller asked to leave out (`--exclude`), reported as `filtered`. */
|
|
16
|
+
filter?: readonly string[];
|
|
15
17
|
maxFileBytes?: number;
|
|
16
18
|
/** Allow content from outside the repo (off by default). */
|
|
17
19
|
allowOutside?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* `skip`: an item over the model's size limit is reported in `skipped` as
|
|
22
|
+
* `too-large`, with the fix in `detail`, and the rest go ahead. A fan-out
|
|
23
|
+
* wants this; `ask`, which has one item, keeps the error (`throw`, the default).
|
|
24
|
+
*/
|
|
25
|
+
oversize?: "throw" | "skip";
|
|
18
26
|
}
|
|
19
27
|
export interface Prepared {
|
|
20
28
|
/** Ready to send: excluded, scrubbed and size-checked. */
|
package/dist/prepare.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,mBAAmB,CAAA;AAG3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,kBAAkB,CAAA;AAE1D,OAAO,EAAE,KAAK,UAAU,EAAW,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,mBAAmB,CAAA;AAG3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,kBAAkB,CAAA;AAE1D,OAAO,EAAE,KAAK,UAAU,EAAW,MAAM,iBAAiB,CAAA;AAG1D,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,EAAa,KAAK,SAAS,EAAS,MAAM,kBAAkB,CAAA;AAEnE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IAC9B,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,WAAW,CAAA;IACtB,OAAO,EAAE,YAAY,CAAA;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,iFAAiF;IACjF,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,0DAA0D;IAC1D,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,2EAA2E;IAC3E,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,uEAAuE;IACvE,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACjE,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkFpE"}
|
package/dist/prepare.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { applyExcludes } from "./egress/exclude.js";
|
|
2
2
|
import { scrubState, scrubText } from "./egress/scrub.js";
|
|
3
3
|
import { assertStateFits } from "./egress/size.js";
|
|
4
|
-
import { DecisionsError } from "./errors.js";
|
|
4
|
+
import { DecisionsError, isDecisionsError } from "./errors.js";
|
|
5
5
|
import { assertQuestionSet } from "./model/validate.js";
|
|
6
6
|
import { project } from "./run/budget.js";
|
|
7
|
+
import { applyFilter } from "./sources/filter.js";
|
|
7
8
|
import { readSources } from "./sources/read.js";
|
|
8
9
|
import { joinItems, split } from "./split/split.js";
|
|
9
10
|
/**
|
|
@@ -19,6 +20,7 @@ export async function prepare(input) {
|
|
|
19
20
|
cwd: input.cwd,
|
|
20
21
|
...(input.maxFileBytes ? { maxFileBytes: input.maxFileBytes } : {}),
|
|
21
22
|
...(input.allowOutside ? { allowOutside: true } : {}),
|
|
23
|
+
...(input.filter?.length ? { filter: input.filter, withhold: input.exclude ?? [] } : {}),
|
|
22
24
|
});
|
|
23
25
|
const byKind = {};
|
|
24
26
|
/** How many documents or items had at least one redaction. */
|
|
@@ -32,9 +34,12 @@ export async function prepare(input) {
|
|
|
32
34
|
// Excluded files are dropped before anything else touches them, so a
|
|
33
35
|
// withheld file is never reported as scrubbed.
|
|
34
36
|
const allowed = applyExcludes(read.documents, input.exclude);
|
|
37
|
+
// Then what the caller left out. Globs were filtered before reading; this
|
|
38
|
+
// catches files, diffs and rows. After egress, so a secret is never `filtered`.
|
|
39
|
+
const chosen = applyFilter(allowed.items, input.filter);
|
|
35
40
|
// Then scrub whole documents: a private key cut across two line windows
|
|
36
41
|
// would otherwise lose the markers that identify it.
|
|
37
|
-
const documents =
|
|
42
|
+
const documents = chosen.items.map((doc) => {
|
|
38
43
|
const counts = {};
|
|
39
44
|
const scrubbed = {
|
|
40
45
|
...doc,
|
|
@@ -51,17 +56,37 @@ export async function prepare(input) {
|
|
|
51
56
|
// Then each item again, so anything the split produced (a join, a row read
|
|
52
57
|
// as a value) is covered too.
|
|
53
58
|
const tokens = [];
|
|
54
|
-
const
|
|
59
|
+
const oversize = [];
|
|
60
|
+
const items = kept.flatMap((item) => {
|
|
55
61
|
const counts = {};
|
|
56
62
|
const state = scrubState(item.state, counts);
|
|
57
63
|
if (count(counts) > 0)
|
|
58
64
|
redactedSources += 1;
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
try {
|
|
66
|
+
tokens.push(assertStateFits(item.id, state, input.questions, input.profile));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (input.oversize !== "skip" || !isDecisionsError(error))
|
|
70
|
+
throw error;
|
|
71
|
+
const estimated = error.details.estimatedTokens;
|
|
72
|
+
oversize.push({
|
|
73
|
+
path: item.path ?? item.id,
|
|
74
|
+
reason: "too-large",
|
|
75
|
+
detail: `about ${estimated} tokens with its questions (limit ${input.profile.maxStateTokens}); re-run it with --split lines:400/40`,
|
|
76
|
+
});
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
return [{ ...item, state }];
|
|
61
80
|
});
|
|
62
81
|
return {
|
|
63
82
|
items,
|
|
64
|
-
skipped: [
|
|
83
|
+
skipped: unique([
|
|
84
|
+
...read.skipped,
|
|
85
|
+
...allowed.excluded,
|
|
86
|
+
...chosen.filtered,
|
|
87
|
+
...filtered.excluded,
|
|
88
|
+
...oversize,
|
|
89
|
+
]),
|
|
65
90
|
redactions: {
|
|
66
91
|
total: Object.values(byKind).reduce((a, b) => a + b, 0),
|
|
67
92
|
byKind,
|
|
@@ -81,4 +106,15 @@ function assertChoicesFit(questions, profile) {
|
|
|
81
106
|
}
|
|
82
107
|
}
|
|
83
108
|
}
|
|
109
|
+
/** One entry per path and reason: a glob and a `--file` can name the same path. */
|
|
110
|
+
function unique(skipped) {
|
|
111
|
+
const seen = new Set();
|
|
112
|
+
return skipped.filter((s) => {
|
|
113
|
+
const key = `${s.path}\0${s.reason}`;
|
|
114
|
+
if (seen.has(key))
|
|
115
|
+
return false;
|
|
116
|
+
seen.add(key);
|
|
117
|
+
return true;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
84
120
|
//# sourceMappingURL=prepare.js.map
|
package/dist/prepare.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAoB,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,24 @@ export interface SortKey {
|
|
|
19
19
|
field: string;
|
|
20
20
|
direction: "asc" | "desc";
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* The `--keep` grammar, shared by answer filters and record filters
|
|
24
|
+
* (`decide opportunities list`): `<name>[.<path>]<op><value>`.
|
|
25
|
+
*/
|
|
26
|
+
export interface FilterTokens {
|
|
27
|
+
name: string;
|
|
28
|
+
/** The dotted path after the name, without the leading dot; "" when absent. */
|
|
29
|
+
path: string;
|
|
30
|
+
op: Op;
|
|
31
|
+
value: number | string | string[];
|
|
32
|
+
}
|
|
33
|
+
export declare function tokenizeFilter(text: string): FilterTokens | undefined;
|
|
34
|
+
/** The `--sort` grammar: `<name>[.<path>][:asc|desc]`. */
|
|
35
|
+
export declare function tokenizeSort(text: string): {
|
|
36
|
+
name: string;
|
|
37
|
+
path: string;
|
|
38
|
+
direction: "asc" | "desc";
|
|
39
|
+
} | undefined;
|
|
22
40
|
/** Parse `relevant>=0.7`, `kind=fix`, `kind in fix,feature`, `kind.probabilities.fix>=0.5`. */
|
|
23
41
|
export declare function parseFilter(text: string, questions?: QuestionSet): Filter;
|
|
24
42
|
/** Parse `relevant`, `relevant.noul:asc`, `risk.score:desc`. Defaults to descending. */
|
|
@@ -29,6 +47,8 @@ export interface ProjectInput<T extends {
|
|
|
29
47
|
}> {
|
|
30
48
|
rows: readonly T[];
|
|
31
49
|
keep?: readonly Filter[];
|
|
50
|
+
/** Kept when any of these matches (and every `keep` does). */
|
|
51
|
+
keepAny?: readonly Filter[];
|
|
32
52
|
sort?: SortKey;
|
|
33
53
|
limit?: number;
|
|
34
54
|
fields?: readonly string[];
|
|
@@ -46,6 +66,22 @@ export interface Projected<T> {
|
|
|
46
66
|
}>;
|
|
47
67
|
dropped: number;
|
|
48
68
|
}
|
|
69
|
+
export interface Verdict {
|
|
70
|
+
verdict: "kept" | "dropped" | "undecided";
|
|
71
|
+
/** For `undecided`: the questions whose flat answers could change the outcome. */
|
|
72
|
+
questions: string[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* One row's verdict under `keep` (all must match) and `keepAny` (at least one
|
|
76
|
+
* must match).
|
|
77
|
+
*
|
|
78
|
+
* A flat answer on a `keep` or `sort` question makes the row undecided, as
|
|
79
|
+
* before. A flat `keepAny` answer only does when it could change the outcome:
|
|
80
|
+
* if a decided `keepAny` filter already matches, the row is kept; if none
|
|
81
|
+
* matches and none is flat, it is dropped. With no filters and no sort, every
|
|
82
|
+
* question counts.
|
|
83
|
+
*/
|
|
84
|
+
export declare function verdictOf(answers: Answers, flat: readonly string[], keep: readonly Filter[], keepAny?: readonly Filter[], sortQuestion?: string): Verdict;
|
|
49
85
|
/**
|
|
50
86
|
* Split rows into kept / undecided / dropped.
|
|
51
87
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/project/project.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAU,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAErE;;;;GAIG;AAEH,MAAM,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAE5D,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAA;IACb,EAAE,EAAE,EAAE,CAAA;IACN,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B;AAID,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,WAAW,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/project/project.ts"],"names":[],"mappings":"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"}
|