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.
- package/dist/claims.d.ts +77 -0
- package/dist/claims.d.ts.map +1 -0
- package/dist/claims.js +186 -0
- package/dist/claims.js.map +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +120 -0
- package/dist/engine.js.map +1 -1
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +3 -0
- package/dist/ink-chat.js.map +1 -1
- package/dist/ledger.d.ts +152 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +276 -0
- package/dist/ledger.js.map +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +13 -0
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web/sessions.d.ts.map +1 -1
- package/dist/web/sessions.js +3 -0
- package/dist/web/sessions.js.map +1 -1
- package/package.json +1 -1
package/dist/ledger.d.ts
ADDED
|
@@ -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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"}
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -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":"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"}
|
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:');
|