koneck 2.54.1 → 2.55.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.
@@ -0,0 +1,152 @@
1
+ /**
2
+ * What this project has already taught KONECK, and whether it is still true.
3
+ *
4
+ * There is a memory file already — `.koneck/MEMORY.md` — and it has two properties that between
5
+ * them explain why sessions keep relearning the same things. It is written only when the model
6
+ * decides to call the remember tool, which is rarely, because the model is busy doing the task. And
7
+ * it is loaded whole into every prompt, so it cannot grow without eating the context window. Memory
8
+ * that must stay small is memory that must forget.
9
+ *
10
+ * This is the other half. Three differences, and each is the point:
11
+ *
12
+ * **Findings are derived, not volunteered.** The knowledge worth keeping is the knowledge that cost
13
+ * a failure to obtain: the command that failed until it was run a different way, the file that had
14
+ * to be edited four times, the test that went red and then green. Those are already in the
15
+ * trajectory. Reading them out is mechanical, so it happens every time rather than when the model
16
+ * happens to be reflective.
17
+ *
18
+ * **Every finding is anchored to a commit and expires.** A note about code that has since changed is
19
+ * not a memory, it is misinformation with a timestamp. Each entry records the sha it was learned at
20
+ * and the paths it concerns; once those paths have moved on it is reported as stale, or withheld.
21
+ * This is the part that makes the whole idea safe rather than dangerous — a shared store with no
22
+ * expiry is a machine for propagating one session's wrong belief into every session that follows.
23
+ * That is not hypothetical: a test run here once wrote a fiction into the live model-status file and
24
+ * the running install believed it for days.
25
+ *
26
+ * **Retrieval is keyed, not wholesale.** Nothing goes into the prompt by default. When a turn is
27
+ * about to write a particular file or run a particular command, the findings filed against that
28
+ * path or that command prefix are surfaced — two lines, at the moment they are useful. That is what
29
+ * lets the ledger grow to thousands of entries at no cost in context, and why there is no embedding
30
+ * index here: an exact key is cheaper, inspectable, and cannot be confidently wrong.
31
+ */
32
+ /** Where a project's findings live. Beside MEMORY.md, which is the same idea done by hand. */
33
+ export declare const LEDGER_FILE = ".koneck/ledger.jsonl";
34
+ export type FindingKind =
35
+ /** How to run something here: what failed, and what worked instead. */
36
+ 'command'
37
+ /** Something about a particular file that cost effort to discover. */
38
+ | 'file'
39
+ /** How long something takes, so nobody plans around a guess. */
40
+ | 'timing'
41
+ /** A rule this workspace enforces — a hook, a policy, a convention. */
42
+ | 'rule';
43
+ export interface Finding {
44
+ kind: FindingKind;
45
+ /** One sentence, in the words a reader needs. Never a paragraph. */
46
+ text: string;
47
+ /** Paths this concerns. Staleness is judged against these. */
48
+ paths?: readonly string[];
49
+ /** Command prefixes this concerns, for keyed retrieval — "npm test", "npx vitest". */
50
+ commands?: readonly string[];
51
+ /** The commit it was learned at, when the workspace is a repository. */
52
+ sha?: string;
53
+ /** ISO. */
54
+ at: string;
55
+ /** Which session learned it, so a reader can go and look. */
56
+ session?: string;
57
+ }
58
+ /** A finding plus what is now known about whether it still holds. */
59
+ export interface RecalledFinding extends Finding {
60
+ /** True when a path this finding depends on has changed since it was learned. */
61
+ stale: boolean;
62
+ }
63
+ /**
64
+ * Appends findings, skipping anything already recorded in the same words.
65
+ *
66
+ * Duplicates are the failure mode of automatic capture: the same command fails the same way in
67
+ * twenty sessions, and twenty identical lines make the useful ones unreadable. Matched on text
68
+ * rather than on time, so a finding relearned after the code changed still replaces nothing — it
69
+ * arrives with a newer sha, which is what makes it worth having again.
70
+ */
71
+ export declare function record(cwd: string, findings: readonly Finding[]): Promise<number>;
72
+ /** Every finding recorded for this workspace, oldest first. Absent or damaged lines are skipped. */
73
+ export declare function readAll(cwd: string): Promise<Finding[]>;
74
+ /**
75
+ * The findings that bear on what is about to happen.
76
+ *
77
+ * Keyed on the path being touched and the first two words of the command being run — `npm test`
78
+ * matches a finding filed against `npm test`, and `npm` alone does not match everything.
79
+ */
80
+ export declare function relevant(findings: readonly Finding[], about: {
81
+ paths?: readonly string[];
82
+ commands?: readonly string[];
83
+ }): Finding[];
84
+ /**
85
+ * The first two words of a command, which is what identifies it.
86
+ *
87
+ * `npm test` and `npm run build` are different things to know about; `npm test -- --watch` is the
88
+ * same thing as `npm test`. One word would file every npm command together, and the whole line
89
+ * would file every variation separately.
90
+ */
91
+ export declare function commandKey(command: string): string;
92
+ /**
93
+ * Marks each finding stale or not, given which paths have changed since it was learned.
94
+ *
95
+ * `changedSince` is asked once per distinct sha rather than once per finding, because it costs a git
96
+ * process each time. A finding with no sha cannot be checked and is reported as current — it is
97
+ * usually a timing or a rule, which code changes do not invalidate the way they invalidate a claim
98
+ * about a particular file.
99
+ */
100
+ export declare function withStaleness(findings: readonly Finding[], changedSince: (sha: string) => Promise<readonly string[] | null>): Promise<RecalledFinding[]>;
101
+ /**
102
+ * What to put in front of the model, or nothing.
103
+ *
104
+ * Stale findings are included but marked, rather than hidden. Hiding them loses the one thing they
105
+ * still tell you — that this used to be true and the code has moved — which is often exactly what a
106
+ * reader needs in order to not be surprised.
107
+ */
108
+ export declare function describeFindings(findings: readonly RecalledFinding[], limit?: number): string | null;
109
+ /**
110
+ * Findings read out of a session's own record of what it did.
111
+ *
112
+ * This is the part that makes the ledger fill up. Asking the model to notice what it learned works
113
+ * occasionally; deriving it from the trajectory works every time, because the trajectory is written
114
+ * whether anyone is being thoughtful or not.
115
+ *
116
+ * Three patterns, chosen because each is unambiguous and each answers a question the next session
117
+ * would otherwise pay to answer again:
118
+ *
119
+ * - a command that failed and then succeeded in a different form. This is "how you run things
120
+ * here", and it is the single most expensive thing to rediscover: the failure is silent
121
+ * knowledge that lives in one session's scrollback.
122
+ * - how long a slow command actually takes. A session that knows the suite takes ninety-five
123
+ * seconds waits for it; one that does not, kills it at thirty and concludes it hangs.
124
+ * - a file that needed several passes. Not a judgement about the file — just that it did, which
125
+ * is a reason to read it properly before starting rather than editing it four times again.
126
+ *
127
+ * Deliberately not derived: anything requiring an opinion about *why*. A guess about cause, written
128
+ * down as a finding and read by twenty later sessions, is worse than nothing.
129
+ */
130
+ export declare function deriveFindings(events: readonly {
131
+ t: string;
132
+ at: number;
133
+ name?: string;
134
+ ms?: number;
135
+ ok?: boolean;
136
+ detail?: string;
137
+ }[], about?: {
138
+ sha?: string;
139
+ session?: string;
140
+ now?: () => string;
141
+ }): Finding[];
142
+ /**
143
+ * Which paths have changed since a commit, or null when the question cannot be answered.
144
+ *
145
+ * Null rather than an empty list, and the distinction matters: "nothing changed" and "this is not a
146
+ * repository, or that commit is gone" lead to opposite conclusions about whether a finding can be
147
+ * trusted. Conflating them would mark every finding current in a directory with no git at all.
148
+ */
149
+ export declare function changedSince(cwd: string, sha: string): Promise<readonly string[] | null>;
150
+ /** The commit a finding should be anchored to, or undefined outside a repository. */
151
+ export declare function currentSha(cwd: string): Promise<string | undefined>;
152
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,8FAA8F;AAC9F,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAElD,MAAM,MAAM,WAAW;AACrB,uEAAuE;AACrE,SAAS;AACX,sEAAsE;GACpE,MAAM;AACR,gEAAgE;GAC9D,QAAQ;AACV,uEAAuE;GACrE,MAAM,CAAC;AAEX,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW;IACX,EAAE,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qEAAqE;AACrE,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;CAChB;AAMD;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAC1B,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,oGAAoG;AACpG,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAa7D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACjE,OAAO,EAAE,CASX;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC,GAC/D,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB5B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,eAAe,EAAE,EAAE,KAAK,SAAI,GAC9C,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EACvG,KAAK,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GACjE,OAAO,EAAE,CAoEX;AAGD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GACvB,OAAO,CAAC,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC,CAOnC;AAED,qFAAqF;AACrF,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAOzE"}
package/dist/ledger.js ADDED
@@ -0,0 +1,276 @@
1
+ /**
2
+ * What this project has already taught KONECK, and whether it is still true.
3
+ *
4
+ * There is a memory file already — `.koneck/MEMORY.md` — and it has two properties that between
5
+ * them explain why sessions keep relearning the same things. It is written only when the model
6
+ * decides to call the remember tool, which is rarely, because the model is busy doing the task. And
7
+ * it is loaded whole into every prompt, so it cannot grow without eating the context window. Memory
8
+ * that must stay small is memory that must forget.
9
+ *
10
+ * This is the other half. Three differences, and each is the point:
11
+ *
12
+ * **Findings are derived, not volunteered.** The knowledge worth keeping is the knowledge that cost
13
+ * a failure to obtain: the command that failed until it was run a different way, the file that had
14
+ * to be edited four times, the test that went red and then green. Those are already in the
15
+ * trajectory. Reading them out is mechanical, so it happens every time rather than when the model
16
+ * happens to be reflective.
17
+ *
18
+ * **Every finding is anchored to a commit and expires.** A note about code that has since changed is
19
+ * not a memory, it is misinformation with a timestamp. Each entry records the sha it was learned at
20
+ * and the paths it concerns; once those paths have moved on it is reported as stale, or withheld.
21
+ * This is the part that makes the whole idea safe rather than dangerous — a shared store with no
22
+ * expiry is a machine for propagating one session's wrong belief into every session that follows.
23
+ * That is not hypothetical: a test run here once wrote a fiction into the live model-status file and
24
+ * the running install believed it for days.
25
+ *
26
+ * **Retrieval is keyed, not wholesale.** Nothing goes into the prompt by default. When a turn is
27
+ * about to write a particular file or run a particular command, the findings filed against that
28
+ * path or that command prefix are surfaced — two lines, at the moment they are useful. That is what
29
+ * lets the ledger grow to thousands of entries at no cost in context, and why there is no embedding
30
+ * index here: an exact key is cheaper, inspectable, and cannot be confidently wrong.
31
+ */
32
+ import fs from 'fs/promises';
33
+ import path from 'path';
34
+ /** Where a project's findings live. Beside MEMORY.md, which is the same idea done by hand. */
35
+ export const LEDGER_FILE = '.koneck/ledger.jsonl';
36
+ function ledgerPath(cwd) {
37
+ return path.join(cwd, LEDGER_FILE);
38
+ }
39
+ /**
40
+ * Appends findings, skipping anything already recorded in the same words.
41
+ *
42
+ * Duplicates are the failure mode of automatic capture: the same command fails the same way in
43
+ * twenty sessions, and twenty identical lines make the useful ones unreadable. Matched on text
44
+ * rather than on time, so a finding relearned after the code changed still replaces nothing — it
45
+ * arrives with a newer sha, which is what makes it worth having again.
46
+ */
47
+ export async function record(cwd, findings) {
48
+ if (findings.length === 0)
49
+ return 0;
50
+ const existing = await readAll(cwd);
51
+ const seen = new Set(existing.map(f => `${f.text}|${f.sha ?? ''}`));
52
+ const fresh = findings.filter(f => !seen.has(`${f.text}|${f.sha ?? ''}`));
53
+ if (fresh.length === 0)
54
+ return 0;
55
+ const file = ledgerPath(cwd);
56
+ await fs.mkdir(path.dirname(file), { recursive: true });
57
+ await fs.appendFile(file, fresh.map(f => JSON.stringify(f)).join('\n') + '\n', 'utf-8');
58
+ return fresh.length;
59
+ }
60
+ /** Every finding recorded for this workspace, oldest first. Absent or damaged lines are skipped. */
61
+ export async function readAll(cwd) {
62
+ let text;
63
+ try {
64
+ text = await fs.readFile(ledgerPath(cwd), 'utf-8');
65
+ }
66
+ catch {
67
+ return [];
68
+ }
69
+ const out = [];
70
+ for (const line of text.split('\n')) {
71
+ if (line.trim() === '')
72
+ continue;
73
+ try {
74
+ const parsed = JSON.parse(line);
75
+ // A line with no text says nothing and would render as an empty bullet.
76
+ if (parsed && typeof parsed.text === 'string' && parsed.text.trim() !== '')
77
+ out.push(parsed);
78
+ }
79
+ catch { /* one bad line must not lose the rest of the ledger */ }
80
+ }
81
+ return out;
82
+ }
83
+ /**
84
+ * The findings that bear on what is about to happen.
85
+ *
86
+ * Keyed on the path being touched and the first two words of the command being run — `npm test`
87
+ * matches a finding filed against `npm test`, and `npm` alone does not match everything.
88
+ */
89
+ export function relevant(findings, about) {
90
+ const paths = new Set((about.paths ?? []).map(p => p.replace(/^\.\//, '')));
91
+ const prefixes = (about.commands ?? []).map(commandKey);
92
+ if (paths.size === 0 && prefixes.length === 0)
93
+ return [];
94
+ return findings.filter(f => {
95
+ if (f.paths?.some(p => paths.has(p.replace(/^\.\//, ''))))
96
+ return true;
97
+ return f.commands?.some(c => prefixes.includes(commandKey(c))) ?? false;
98
+ });
99
+ }
100
+ /**
101
+ * The first two words of a command, which is what identifies it.
102
+ *
103
+ * `npm test` and `npm run build` are different things to know about; `npm test -- --watch` is the
104
+ * same thing as `npm test`. One word would file every npm command together, and the whole line
105
+ * would file every variation separately.
106
+ */
107
+ export function commandKey(command) {
108
+ return String(command ?? '').trim().split(/\s+/).slice(0, 2).join(' ').toLowerCase();
109
+ }
110
+ /**
111
+ * Marks each finding stale or not, given which paths have changed since it was learned.
112
+ *
113
+ * `changedSince` is asked once per distinct sha rather than once per finding, because it costs a git
114
+ * process each time. A finding with no sha cannot be checked and is reported as current — it is
115
+ * usually a timing or a rule, which code changes do not invalidate the way they invalidate a claim
116
+ * about a particular file.
117
+ */
118
+ export async function withStaleness(findings, changedSince) {
119
+ const changedBySha = new Map();
120
+ const out = [];
121
+ for (const finding of findings) {
122
+ if (!finding.sha || !finding.paths || finding.paths.length === 0) {
123
+ out.push({ ...finding, stale: false });
124
+ continue;
125
+ }
126
+ if (!changedBySha.has(finding.sha)) {
127
+ const changed = await changedSince(finding.sha);
128
+ changedBySha.set(finding.sha, changed ? new Set(changed) : null);
129
+ }
130
+ const changed = changedBySha.get(finding.sha);
131
+ // Nothing knowable: reported as current rather than guessed either way, and the reader has the
132
+ // sha if they want to check.
133
+ if (!changed) {
134
+ out.push({ ...finding, stale: false });
135
+ continue;
136
+ }
137
+ out.push({
138
+ ...finding,
139
+ stale: finding.paths.some(p => changed.has(p.replace(/^\.\//, ''))),
140
+ });
141
+ }
142
+ return out;
143
+ }
144
+ /**
145
+ * What to put in front of the model, or nothing.
146
+ *
147
+ * Stale findings are included but marked, rather than hidden. Hiding them loses the one thing they
148
+ * still tell you — that this used to be true and the code has moved — which is often exactly what a
149
+ * reader needs in order to not be surprised.
150
+ */
151
+ export function describeFindings(findings, limit = 6) {
152
+ if (findings.length === 0)
153
+ return null;
154
+ // Current first, then the most recent of the stale, because a current finding is worth more than
155
+ // a newer stale one.
156
+ const ordered = [...findings].sort((a, b) => (a.stale === b.stale ? Date.parse(b.at) - Date.parse(a.at) : a.stale ? 1 : -1));
157
+ const lines = ordered.slice(0, limit).map(f => ` ${f.text}${f.stale ? ' (learned before the code here changed — check it still holds)' : ''}`);
158
+ return 'What earlier sessions in this project found out the hard way:\n' + lines.join('\n');
159
+ }
160
+ /**
161
+ * Findings read out of a session's own record of what it did.
162
+ *
163
+ * This is the part that makes the ledger fill up. Asking the model to notice what it learned works
164
+ * occasionally; deriving it from the trajectory works every time, because the trajectory is written
165
+ * whether anyone is being thoughtful or not.
166
+ *
167
+ * Three patterns, chosen because each is unambiguous and each answers a question the next session
168
+ * would otherwise pay to answer again:
169
+ *
170
+ * - a command that failed and then succeeded in a different form. This is "how you run things
171
+ * here", and it is the single most expensive thing to rediscover: the failure is silent
172
+ * knowledge that lives in one session's scrollback.
173
+ * - how long a slow command actually takes. A session that knows the suite takes ninety-five
174
+ * seconds waits for it; one that does not, kills it at thirty and concludes it hangs.
175
+ * - a file that needed several passes. Not a judgement about the file — just that it did, which
176
+ * is a reason to read it properly before starting rather than editing it four times again.
177
+ *
178
+ * Deliberately not derived: anything requiring an opinion about *why*. A guess about cause, written
179
+ * down as a finding and read by twenty later sessions, is worse than nothing.
180
+ */
181
+ export function deriveFindings(events, about = {}) {
182
+ const at = (about.now ?? (() => new Date().toISOString()))();
183
+ const base = { at, ...(about.sha ? { sha: about.sha } : {}),
184
+ ...(about.session ? { session: about.session } : {}) };
185
+ const findings = [];
186
+ const commands = events.filter(e => e.t === 'tool' && e.name === 'execute_command' && typeof e.detail === 'string' && e.detail.trim());
187
+ /* A command that failed and then worked in a different form. */
188
+ const failedForms = new Map();
189
+ for (const event of commands) {
190
+ const command = event.detail.trim();
191
+ const key = commandKey(command);
192
+ if (event.ok === false) {
193
+ failedForms.set(key, command);
194
+ continue;
195
+ }
196
+ const failed = failedForms.get(key);
197
+ if (failed && failed !== command) {
198
+ findings.push({
199
+ ...base,
200
+ kind: 'command',
201
+ text: `In this project, "${failed}" fails and "${command}" works.`,
202
+ commands: [key],
203
+ });
204
+ failedForms.delete(key);
205
+ }
206
+ }
207
+ /* How long a slow command really takes. */
208
+ const SLOW_ENOUGH_MS = 20_000;
209
+ const timed = new Map();
210
+ for (const event of commands) {
211
+ if (event.ok === false || typeof event.ms !== 'number' || event.ms < SLOW_ENOUGH_MS)
212
+ continue;
213
+ const key = commandKey(event.detail);
214
+ // The longest observed run, because planning around the fastest is how a timeout gets set too
215
+ // low and a working command is reported as hanging.
216
+ timed.set(key, Math.max(timed.get(key) ?? 0, event.ms));
217
+ }
218
+ for (const [key, ms] of timed) {
219
+ findings.push({
220
+ ...base,
221
+ kind: 'timing',
222
+ text: `"${key}" takes about ${Math.round(ms / 1000)}s here — give it time rather than `
223
+ + `assuming it has hung.`,
224
+ commands: [key],
225
+ });
226
+ }
227
+ /* A file that needed several passes. */
228
+ const WRITES = new Set(['write_file', 'search_replace', 'apply_diff']);
229
+ const passes = new Map();
230
+ for (const event of events) {
231
+ if (event.t !== 'tool' || !event.name || !WRITES.has(event.name))
232
+ continue;
233
+ const file = (event.detail ?? '').trim();
234
+ if (!file || /\s/.test(file))
235
+ continue;
236
+ passes.set(file, (passes.get(file) ?? 0) + 1);
237
+ }
238
+ for (const [file, count] of passes) {
239
+ if (count < 3)
240
+ continue;
241
+ findings.push({
242
+ ...base,
243
+ kind: 'file',
244
+ text: `${file} took ${count} passes to get right in one session — read it in full before `
245
+ + `editing it.`,
246
+ paths: [file],
247
+ });
248
+ }
249
+ return findings;
250
+ }
251
+ /**
252
+ * Which paths have changed since a commit, or null when the question cannot be answered.
253
+ *
254
+ * Null rather than an empty list, and the distinction matters: "nothing changed" and "this is not a
255
+ * repository, or that commit is gone" lead to opposite conclusions about whether a finding can be
256
+ * trusted. Conflating them would mark every finding current in a directory with no git at all.
257
+ */
258
+ export async function changedSince(cwd, sha) {
259
+ if (!/^[0-9a-f]{7,40}$/i.test(sha))
260
+ return null;
261
+ const { execa } = await import('execa');
262
+ const done = await execa('git', ['diff', '--name-only', `${sha}..HEAD`], { cwd, reject: false, timeout: 10_000 });
263
+ if (done.exitCode !== 0)
264
+ return null;
265
+ return done.stdout.split('\n').map(l => l.trim()).filter(Boolean);
266
+ }
267
+ /** The commit a finding should be anchored to, or undefined outside a repository. */
268
+ export async function currentSha(cwd) {
269
+ const { execa } = await import('execa');
270
+ const done = await execa('git', ['rev-parse', 'HEAD'], { cwd, reject: false, timeout: 10_000 });
271
+ if (done.exitCode !== 0)
272
+ return undefined;
273
+ const sha = done.stdout.trim();
274
+ return /^[0-9a-f]{7,40}$/i.test(sha) ? sha : undefined;
275
+ }
276
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA4Y5C,CAAC;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAyClC,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BjF;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,QAAc,CAAC;AAsB1C,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,SAAK,GACX;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAOlC;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAGD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAyB,EACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAWpE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,GAAE,MAAyB,EACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAIR;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACrC,OAAO,GAAE,WAAgD,GACxD,OAAO,CAAC,MAAM,CAAC,CAmGjB;AA+CD,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C7E;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBnF;AAgBD,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4CnF;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB/E;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAcD,wBAAsB,aAAa,CACjC,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAmBD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BlE;AAwCD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpE;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcjE;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa/E;AAKD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBzD,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAG1F;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAoBnF;AA+BD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBxE;AAGD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAwBhF;AAGD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAgBpE;AAGD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAgBrD;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACrC,OAAO,GAAE,WAAgD,GACxD,OAAO,CAAC,MAAM,CAAC,CAoDjB;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiDD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AA0CD,0FAA0F;AAC1F,wBAAgB,cAAc,IAAI,OAAO,cAAc,EAAE,OAAO,GAAG,IAAI,CAEtE;AAED,wFAAwF;AACxF,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAIlD"}
package/dist/tools.js CHANGED
@@ -1293,6 +1293,19 @@ export function writeTargets(tool, parsed) {
1293
1293
  * "that write did not happen" — looked exactly like success.
1294
1294
  */
1295
1295
  export function isToolFailure(result) {
1296
+ /*
1297
+ * A command that exited non-zero is a failed command.
1298
+ *
1299
+ * It was not counted as one, because a non-zero exit is reported as "Exit code 1:" and only the
1300
+ * ERROR/POLICY/DENIED prefixes were recognised. Everything downstream believed it: the trajectory
1301
+ * recorded ok, the trail chip drew a green dot, the timing view counted it as fine, and a run that
1302
+ * had just failed to build looked exactly like one that had succeeded. Caught while building the
1303
+ * project ledger, which could not learn "this command does not work here" because nothing
1304
+ * anywhere admitted that it had not worked.
1305
+ */
1306
+ const exited = /^Exit code (\d+):/.exec(result);
1307
+ if (exited && exited[1] !== '0')
1308
+ return true;
1296
1309
  return result.startsWith('ERROR:')
1297
1310
  || result.startsWith('POLICY BLOCKED:')
1298
1311
  || result.startsWith('DENIED:');