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,77 @@
1
+ /**
2
+ * What the other sessions on this checkout are doing right now.
3
+ *
4
+ * Two KONECK sessions in the same repository cannot see each other's work. One edits a file the
5
+ * other has just rewritten and the second write silently wins; both run the same test suite, which
6
+ * on a four-core machine is a hundred and seventy seconds each; one restarts a dev server the other
7
+ * is using. That is not hypothetical — a dev server on port 3000 was killed here by exactly this
8
+ * blindness, while another session depended on it.
9
+ *
10
+ * The registry in `session-bus` already knows which sessions are alive, with their pids and repos.
11
+ * What it does not know is what each of them is *touching*. So this is a claim: a session says
12
+ * "I am writing this file" or "I am running this command" before it does, and any other session
13
+ * asking about the same target is told who else is on it and how long ago.
14
+ *
15
+ * Three decisions worth stating, because each could sensibly have gone the other way:
16
+ *
17
+ * It reports rather than blocks. A lock between two agents that each wait for the other is a
18
+ * deadlock with no user present to break it, and a lock held by a session that dies mid-turn is
19
+ * worse than no lock. Telling the model "another session wrote this forty seconds ago" lets it
20
+ * decide — re-read first, work elsewhere, or say so and stop — which is what a person in the same
21
+ * position would do.
22
+ *
23
+ * A claim is evidence, not permission. It carries a pid, so a claim from a session that no longer
24
+ * exists is discarded on sight rather than trusted because it was recent.
25
+ *
26
+ * It is keyed by repository, not by directory. Two sessions in different subdirectories of one
27
+ * checkout are working on the same code and must see each other; two sessions in unrelated repos
28
+ * that happen to share a filename must not.
29
+ */
30
+ /** What a session can be in the middle of. */
31
+ export type ClaimKind = 'file' | 'command';
32
+ export interface Claim {
33
+ kind: ClaimKind;
34
+ /** A repo-relative path, or the command line. */
35
+ target: string;
36
+ session: string;
37
+ /** A name a person would recognise, when the surface has one. Falls back to a short id. */
38
+ label?: string;
39
+ pid: number;
40
+ /** ISO. Age is the whole point: a claim from an hour ago says something different from one now. */
41
+ at: string;
42
+ /** Set when the work finished, so "is editing" and "edited" are not the same report. */
43
+ done?: string;
44
+ }
45
+ /**
46
+ * How long a finished claim is still worth mentioning.
47
+ *
48
+ * A file another session wrote a minute ago is a reason to re-read before editing. The same file an
49
+ * hour ago is just history, and reporting it would train the reader to ignore these.
50
+ */
51
+ export declare const CLAIM_INTEREST_MS: number;
52
+ /** One file per repository, so unrelated checkouts never see each other's claims. */
53
+ export declare function claimsPath(repo: string, home?: string): string;
54
+ /** Records that this session is starting on something. Returns what else is already on it. */
55
+ export declare function claim(repo: string, kind: ClaimKind, target: string, session: string, home?: string, now?: Date, label?: string): Claim[];
56
+ /** Marks this session's claim finished, so it becomes "edited" rather than "is editing". */
57
+ export declare function release(repo: string, kind: ClaimKind, target: string, session: string, home?: string, now?: Date): void;
58
+ /** Everything this session had open, finished at once. For the end of a session. */
59
+ export declare function releaseAll(repo: string, session: string, home?: string, now?: Date): void;
60
+ /** Who else is on a target, newest first, without claiming it. */
61
+ export declare function whoElse(repo: string, kind: ClaimKind, target: string, session: string, home?: string, now?: Date): Claim[];
62
+ /** Everything live across the repo, for a status view. */
63
+ export declare function allClaims(repo: string, home?: string, now?: Date): Claim[];
64
+ /**
65
+ * What to tell the model, or nothing when there is nothing worth saying.
66
+ *
67
+ * Written as an observation rather than an instruction. The reader is better placed to decide what
68
+ * to do about it than this function is: re-read before editing, work elsewhere, or wait for a build
69
+ * that is already running. Being told what to do on evidence this thin is how a warning gets
70
+ * ignored.
71
+ */
72
+ export declare function describeClaims(claims: readonly Claim[], now?: number): string | null;
73
+ /** Clears a repository's claims entirely. For tests, and for a user who wants a clean slate. */
74
+ export declare function forgetClaims(repo: string, home?: string): void;
75
+ /** The directory claims live in, so it can be reported. */
76
+ export declare function claimsRoot(): string;
77
+ //# sourceMappingURL=claims.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAMH,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3C,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,mGAAmG;IACnG,EAAE,EAAE,MAAM,CAAC;IACX,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAe,GAAG,MAAM,CAGpE;AA0CD,8FAA8F;AAC9F,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAC9D,IAAI,SAAe,EAAE,GAAG,OAAa,EAAE,KAAK,CAAC,EAAE,MAAM,GACpD,KAAK,EAAE,CAUT;AAED,4FAA4F;AAC5F,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAC9D,IAAI,SAAe,EAAE,GAAG,OAAa,GACpC,IAAI,CAON;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,SAAe,EAAE,GAAG,OAAa,GACnE,IAAI,CAKN;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAC9D,IAAI,SAAe,EAAE,GAAG,OAAa,GACpC,KAAK,EAAE,CAIT;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAe,EAAE,GAAG,OAAa,GAAG,KAAK,EAAE,CAGtF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,IAAI,CAexF;AAuBD,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAe,GAAG,IAAI,CAEpE;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,IAAI,MAAM,CAAiB"}
package/dist/claims.js ADDED
@@ -0,0 +1,186 @@
1
+ /**
2
+ * What the other sessions on this checkout are doing right now.
3
+ *
4
+ * Two KONECK sessions in the same repository cannot see each other's work. One edits a file the
5
+ * other has just rewritten and the second write silently wins; both run the same test suite, which
6
+ * on a four-core machine is a hundred and seventy seconds each; one restarts a dev server the other
7
+ * is using. That is not hypothetical — a dev server on port 3000 was killed here by exactly this
8
+ * blindness, while another session depended on it.
9
+ *
10
+ * The registry in `session-bus` already knows which sessions are alive, with their pids and repos.
11
+ * What it does not know is what each of them is *touching*. So this is a claim: a session says
12
+ * "I am writing this file" or "I am running this command" before it does, and any other session
13
+ * asking about the same target is told who else is on it and how long ago.
14
+ *
15
+ * Three decisions worth stating, because each could sensibly have gone the other way:
16
+ *
17
+ * It reports rather than blocks. A lock between two agents that each wait for the other is a
18
+ * deadlock with no user present to break it, and a lock held by a session that dies mid-turn is
19
+ * worse than no lock. Telling the model "another session wrote this forty seconds ago" lets it
20
+ * decide — re-read first, work elsewhere, or say so and stop — which is what a person in the same
21
+ * position would do.
22
+ *
23
+ * A claim is evidence, not permission. It carries a pid, so a claim from a session that no longer
24
+ * exists is discarded on sight rather than trusted because it was recent.
25
+ *
26
+ * It is keyed by repository, not by directory. Two sessions in different subdirectories of one
27
+ * checkout are working on the same code and must see each other; two sessions in unrelated repos
28
+ * that happen to share a filename must not.
29
+ */
30
+ import fs from 'fs';
31
+ import os from 'os';
32
+ import path from 'path';
33
+ const ROOT = path.join(os.homedir(), '.koneck', 'claims');
34
+ /**
35
+ * How long a finished claim is still worth mentioning.
36
+ *
37
+ * A file another session wrote a minute ago is a reason to re-read before editing. The same file an
38
+ * hour ago is just history, and reporting it would train the reader to ignore these.
39
+ */
40
+ export const CLAIM_INTEREST_MS = 10 * 60 * 1000;
41
+ /** One file per repository, so unrelated checkouts never see each other's claims. */
42
+ export function claimsPath(repo, home = os.homedir()) {
43
+ const safe = repo.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'workspace';
44
+ return path.join(home, '.koneck', 'claims', `${safe}.json`);
45
+ }
46
+ function read(file) {
47
+ try {
48
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
49
+ return Array.isArray(parsed) ? parsed : [];
50
+ }
51
+ catch {
52
+ // Absent or damaged: a session must start whatever the state of this file.
53
+ return [];
54
+ }
55
+ }
56
+ function write(file, claims) {
57
+ try {
58
+ fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
59
+ const tmp = `${file}.${process.pid}.tmp`;
60
+ fs.writeFileSync(tmp, JSON.stringify(claims, null, 2) + '\n', { mode: 0o600 });
61
+ fs.renameSync(tmp, file);
62
+ }
63
+ catch { /* a claim that cannot be written must not fail the work it describes */ }
64
+ }
65
+ /** Whether the session that made a claim is still running. */
66
+ function claimantAlive(claim) {
67
+ if (claim.pid === process.pid)
68
+ return true;
69
+ try {
70
+ process.kill(claim.pid, 0);
71
+ return true;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
77
+ /**
78
+ * Which claims are still worth reporting.
79
+ *
80
+ * Dropped: anything from a session that no longer exists, and anything finished long enough ago to
81
+ * be history rather than news. An unfinished claim from a live session is kept however old — a
82
+ * session that has been building for five minutes is exactly what another session needs to know.
83
+ */
84
+ function current(claims, now = Date.now()) {
85
+ return claims.filter(claim => {
86
+ if (!claimantAlive(claim))
87
+ return false;
88
+ if (!claim.done)
89
+ return true;
90
+ return now - Date.parse(claim.done) < CLAIM_INTEREST_MS;
91
+ });
92
+ }
93
+ /** Records that this session is starting on something. Returns what else is already on it. */
94
+ export function claim(repo, kind, target, session, home = os.homedir(), now = new Date(), label) {
95
+ const file = claimsPath(repo, home);
96
+ const kept = current(read(file), now.getTime())
97
+ // This session's own earlier claim on the same target is replaced, not stacked.
98
+ .filter(c => !(c.session === session && c.kind === kind && c.target === target));
99
+ const others = kept.filter(c => c.session !== session && c.kind === kind && c.target === target);
100
+ kept.push({ kind, target, session, pid: process.pid, at: now.toISOString(),
101
+ ...(label ? { label } : {}) });
102
+ write(file, kept);
103
+ return others;
104
+ }
105
+ /** Marks this session's claim finished, so it becomes "edited" rather than "is editing". */
106
+ export function release(repo, kind, target, session, home = os.homedir(), now = new Date()) {
107
+ const file = claimsPath(repo, home);
108
+ const claims = current(read(file), now.getTime()).map(c => c.session === session && c.kind === kind && c.target === target && !c.done
109
+ ? { ...c, done: now.toISOString() }
110
+ : c);
111
+ write(file, claims);
112
+ }
113
+ /** Everything this session had open, finished at once. For the end of a session. */
114
+ export function releaseAll(repo, session, home = os.homedir(), now = new Date()) {
115
+ const file = claimsPath(repo, home);
116
+ const claims = current(read(file), now.getTime()).map(c => c.session === session && !c.done ? { ...c, done: now.toISOString() } : c);
117
+ write(file, claims);
118
+ }
119
+ /** Who else is on a target, newest first, without claiming it. */
120
+ export function whoElse(repo, kind, target, session, home = os.homedir(), now = new Date()) {
121
+ return current(read(claimsPath(repo, home)), now.getTime())
122
+ .filter(c => c.session !== session && c.kind === kind && c.target === target)
123
+ .sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
124
+ }
125
+ /** Everything live across the repo, for a status view. */
126
+ export function allClaims(repo, home = os.homedir(), now = new Date()) {
127
+ return current(read(claimsPath(repo, home)), now.getTime())
128
+ .sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
129
+ }
130
+ /**
131
+ * What to tell the model, or nothing when there is nothing worth saying.
132
+ *
133
+ * Written as an observation rather than an instruction. The reader is better placed to decide what
134
+ * to do about it than this function is: re-read before editing, work elsewhere, or wait for a build
135
+ * that is already running. Being told what to do on evidence this thin is how a warning gets
136
+ * ignored.
137
+ */
138
+ export function describeClaims(claims, now = Date.now()) {
139
+ if (claims.length === 0)
140
+ return null;
141
+ const lines = claims.slice(0, 4).map(c => {
142
+ const since = ago(now - Date.parse(c.done ?? c.at));
143
+ const who = nameOf(c);
144
+ return c.done
145
+ ? ` ${who} finished with it ${since} ago`
146
+ : ` ${who} has been on it for ${since}`;
147
+ });
148
+ const what = claims[0].kind === 'file' ? 'file' : 'command';
149
+ return `Another KONECK session is working on this ${what} in this repository:\n`
150
+ + lines.join('\n')
151
+ + (claims[0].kind === 'file'
152
+ ? '\nRead it again before writing, or its changes will be lost.'
153
+ : '\nIts result will be available; running the same thing twice costs the same time twice.');
154
+ }
155
+ /*
156
+ * Who, in a form a reader can scan.
157
+ *
158
+ * A session id here is a timestamp — 20260826-114437-0d770000 — and three of those in a list is a
159
+ * wall of digits nobody reads. The name is used when a surface has one; otherwise the tail of the
160
+ * id, which is short enough to compare at a glance and still distinguishes one session from
161
+ * another.
162
+ */
163
+ function nameOf(claim) {
164
+ if (claim.label)
165
+ return claim.label;
166
+ return `session ${claim.session.slice(-8)}`;
167
+ }
168
+ function ago(ms) {
169
+ const seconds = Math.max(1, Math.round(ms / 1000));
170
+ if (seconds < 90)
171
+ return `${seconds}s`;
172
+ const minutes = Math.round(seconds / 60);
173
+ if (minutes < 90)
174
+ return `${minutes}m`;
175
+ return `${Math.round(minutes / 60)}h`;
176
+ }
177
+ /** Clears a repository's claims entirely. For tests, and for a user who wants a clean slate. */
178
+ export function forgetClaims(repo, home = os.homedir()) {
179
+ try {
180
+ fs.rmSync(claimsPath(repo, home), { force: true });
181
+ }
182
+ catch { /* nothing to clear */ }
183
+ }
184
+ /** The directory claims live in, so it can be reported. */
185
+ export function claimsRoot() { return ROOT; }
186
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAc5B,OAAO,EAA0C,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAY9E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWtC,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAWlB,OAAO,EAAE,kBAAkB,EAAuD,MAAM,iBAAiB,CAAC;AAI1G,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EAEX,UAAU,EAKX,MAAM,YAAY,CAAC;AAIpB;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;AAC7C;;;;GAIG;AACH,KAAK,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,MAAM,CAmFR;AAED,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAEpF;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACxG,IAAI,CAQN;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAyC9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAc,GAAG,MAAM,CAuBxF;AAED;;;;;;;GAOG;AACH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG/D;AAqCD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkB7D;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAG,OAAO,CAExF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAcvD;AAID,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAQvD;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAOrE;AAiDD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAG/D;AAED,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAEtC,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,MAAM,CAStF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAmB,GAAG,MAAM,CAK/E;AAyID;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,GAAG,EAAE,OAAO,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,gBAAgB,GAC1B,MAAM,EAAE,CAMV;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE7E;AA+DD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG7E;AAQD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EACrC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACzC,OAAO,CAAC,CAAC,EAAE,CAAC,CAad;AAkJD;;;;;GAKG;AACH;;;;;;;GAOG;AACH,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAM1E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAGlE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAevD;AAGD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASpE;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,OAAO,EACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAiDR;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,cAAc,EAAE,EAC5B,OAAO,EAAE,WAAW,EAAE,EAEtB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAC7C,UAAU,SAAI,EACd,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,kBAAkB;AAC/B;;;;;;GAMG;AACH,OAAO,GAAE;IAAE,OAAO,EAAE,IAAI,CAAA;CAA4B;AACpD,2FAA2F;AAC3F,UAAU,CAAC,EAAE,UAAU;AACvB,4FAA4F;AAC5F,eAAe,GAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAmB,GACpD,OAAO,CAAC,OAAO,CAAC,CAo1ClB;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,8FAA8F;IAC9F,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,CAAC;IAC3G,6FAA6F;IAC7F,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/F;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CAC3B;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAarE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE;AAC3B;;;;;;;GAOG;AACH,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;AAClC,iGAAiG;AACjG,WAAW,CAAC,EAAE,IAAI,GACjB,OAAO,CAAC,YAAY,CAAC,CA0PvB;AAwBD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,EAC3B,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,YAAY,CAAC,CAwKvB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -10,6 +10,9 @@ import { hasWorkspaceOwnedGitRepo, gitScope, createWorktree, mergeWorktree, pres
10
10
  import { resolveProvider, getApiKey, keyProvenance, servesLocally, servesOwnWeights, isPrivateHost } from './providers.js';
11
11
  import { wireEffort, looksLikeEffortUnsupported } from './pace.js';
12
12
  import { triggerFor, pickNext, describeSwitch, askSwitch, keyOf as failoverKey } from './failover.js';
13
+ import { claim, release, describeClaims } from './claims.js';
14
+ import { readAll as readLedger, relevant as relevantFindings, withStaleness, describeFindings, deriveFindings, record as recordFindings, changedSince, currentSha } from './ledger.js';
15
+ import { repoNameFor } from './session-bus.js';
13
16
  import { compressIfNeeded } from './compressor.js';
14
17
  import { contextLimitFor, looksLikeContextOverflow, parseContextLimit, fetchModelContextLimit, ollamaServingLimit, fixedRequestTokens, overheadIsCrowded, crowdedWindowAdvice, probeOllamaContext, detectWindowPlateau, truncationNotice, } from './context-limit.js';
15
18
  import { generateSessionId, saveSession } from './session.js';
@@ -299,6 +302,15 @@ const MAX_DUPLICATE_CALLS = 6;
299
302
  const STATE_CHANGING_TOOLS = new Set([
300
303
  'write_file', 'search_replace', 'apply_diff', 'delete_file', 'move_file', 'execute_command',
301
304
  ]);
305
+ /**
306
+ * Commands long enough that running one twice in a repository is worth avoiding.
307
+ *
308
+ * Not every command: claiming `ls` would fill the record with noise and make the cases that matter
309
+ * harder to see. These are the ones measured in tens of seconds — a test suite here takes between
310
+ * 95 and 170 seconds on four cores, so two sessions each running it is minutes of duplicated wait,
311
+ * and a build or an install competing with itself is worse than slow.
312
+ */
313
+ const SHARED_WORK = /\b(npm|yarn|pnpm|bun)\s+(run\s+\S+|test|install|ci|build|start|add|update|upgrade)\b|\bnpx\s+(vitest|jest|tsc|playwright)\b|\b(vitest|jest|pytest|cargo|gradle|mvn|make|tsc|docker)\b|\bgo\s+(test|build)\b|\bpip3?\s+install\b/;
302
314
  /**
303
315
  * Text in which the model states outright that it did not finish — "I stopped there", "I have
304
316
  * not yet read the controller", "I only ran initial searches". These are unambiguous: a model
@@ -1014,6 +1026,58 @@ detectedContext = { current: 0 }) {
1014
1026
  const switchedTo = [failoverKey({ provider: config.provider, model: config.model })];
1015
1027
  let switches = 0;
1016
1028
  let discovered = null;
1029
+ /*
1030
+ * Which claim a call is about, or none.
1031
+ *
1032
+ * Only writes and commands: a read cannot lose anybody's work, and claiming every read would
1033
+ * fill the record with noise that makes the two cases worth reporting harder to see.
1034
+ */
1035
+ /*
1036
+ * The ledger, read once per turn rather than once per tool call.
1037
+ *
1038
+ * A turn makes a dozen calls and the file does not change under it, so re-reading would be a
1039
+ * dozen reads for one answer. Null until something asks, so a turn that touches nothing shared
1040
+ * never opens it at all.
1041
+ */
1042
+ let ledgerCache = null;
1043
+ async function recallFor(claimed) {
1044
+ try {
1045
+ if (ledgerCache === null)
1046
+ ledgerCache = await readLedger(effectiveCwd);
1047
+ if (ledgerCache.length === 0)
1048
+ return null;
1049
+ const hits = relevantFindings(ledgerCache, claimed.kind === 'file'
1050
+ ? { paths: [claimed.target] }
1051
+ : { commands: [claimed.target] });
1052
+ if (hits.length === 0)
1053
+ return null;
1054
+ // Judged against git, so a finding about code that has since changed is marked rather than
1055
+ // presented as current fact.
1056
+ const checked = await withStaleness(hits, sha => changedSince(effectiveCwd, sha));
1057
+ return describeFindings(checked);
1058
+ }
1059
+ catch {
1060
+ return null;
1061
+ }
1062
+ }
1063
+ const claimRepo = repoNameFor(effectiveCwd);
1064
+ const claimSessionId = config.auditSessionId ?? `pid-${process.pid}`;
1065
+ function claimFor(name, args) {
1066
+ if (name === 'execute_command') {
1067
+ try {
1068
+ const command = String(JSON.parse(args).command ?? '').trim();
1069
+ // Only the ones long enough to be worth not doing twice. Claiming `ls` is noise.
1070
+ return command && SHARED_WORK.test(command) ? { kind: 'command', target: command } : null;
1071
+ }
1072
+ catch {
1073
+ return null;
1074
+ }
1075
+ }
1076
+ if (!STATE_CHANGING_TOOLS.has(name))
1077
+ return null;
1078
+ const file = filePathFrom(args);
1079
+ return file ? { kind: 'file', target: file } : null;
1080
+ }
1017
1081
  async function tryFailover(err) {
1018
1082
  if (!failoverPolicy?.enabled)
1019
1083
  return false;
@@ -2071,6 +2135,29 @@ detectedContext = { current: 0 }) {
2071
2135
  tui.printToolCall(tc.name, tc.arguments);
2072
2136
  const toolSpinner = silent ? null : tui.startSpinner(tc.name + '…');
2073
2137
  const toolStart = Date.now();
2138
+ /*
2139
+ * What another session on this checkout is already doing to the same thing.
2140
+ *
2141
+ * Claimed before the work, released after, and reported to the model as an observation rather
2142
+ * than a rule. Two sessions in one repository could not see each other at all: one wrote over
2143
+ * a file the other had just rewritten, both ran the same three-minute suite, and a dev server
2144
+ * one of them depended on was restarted by the other. Reporting rather than locking is
2145
+ * deliberate — a lock between two agents each waiting for the other is a deadlock with nobody
2146
+ * present to break it.
2147
+ */
2148
+ const claimed = claimFor(effectiveName, tc.arguments);
2149
+ let othersOnIt = null;
2150
+ if (claimed) {
2151
+ othersOnIt = describeClaims(claim(claimRepo, claimed.kind, claimed.target, claimSessionId, undefined, undefined, config.sessionLabel));
2152
+ }
2153
+ /*
2154
+ * What earlier sessions in this project found out the hard way about this exact thing.
2155
+ *
2156
+ * Keyed, not dumped: only the findings filed against this path or this command prefix, at the
2157
+ * moment they are useful. The whole point of the ledger is that it can grow without costing
2158
+ * context, which it cannot do if it is loaded into every prompt.
2159
+ */
2160
+ const alreadyKnown = claimed ? await recallFor(claimed) : null;
2074
2161
  let result;
2075
2162
  const policyDecision = evaluatePolicy(policy, effectiveName, tc.arguments, effectiveCwd);
2076
2163
  // Asked of the interface, which knows the mode and what the user has already agreed to.
@@ -2222,6 +2309,20 @@ detectedContext = { current: 0 }) {
2222
2309
  }
2223
2310
  const toolElapsed = Date.now() - toolStart;
2224
2311
  const toolFailed = isToolFailure(result);
2312
+ // Finished with it, so another session sees "edited" rather than "is editing".
2313
+ if (claimed)
2314
+ release(claimRepo, claimed.kind, claimed.target, claimSessionId);
2315
+ /*
2316
+ * What another session was doing, said alongside the result rather than instead of it.
2317
+ *
2318
+ * The work is not prevented — the model is better placed to decide whether to re-read, work
2319
+ * elsewhere, or say so and stop. Appended after the result so it reads as context, not as the
2320
+ * outcome of the call.
2321
+ */
2322
+ if (othersOnIt)
2323
+ result = `${result}\n\n${othersOnIt}`;
2324
+ if (alreadyKnown)
2325
+ result = `${result}\n\n${alreadyKnown}`;
2225
2326
  // The reason travels with the result. Without it a failed step showed as "x read_files ·
2226
2327
  // 0ms" and nothing else, so the model knew why and the person watching did not.
2227
2328
  config.onToolResult?.(tc.name, !toolFailed, toolElapsed, toolFailed ? failureReason(result) : undefined);
@@ -2552,6 +2653,25 @@ initialPlan) {
2552
2653
  // Commit even when the turn threw or was interrupted — a partial edit is exactly
2553
2654
  // the case where being able to undo matters most.
2554
2655
  await checkpoint.commit().catch(() => null);
2656
+ /*
2657
+ * What this turn learned, written down for the next session.
2658
+ *
2659
+ * Derived from the trajectory rather than asked of the model: the trajectory is written
2660
+ * whether or not anybody is being reflective, so this happens every turn instead of the rare
2661
+ * one where the model thinks to leave a note. In the finally block because a turn that failed
2662
+ * is often the one that learned the most — the command that did not work is exactly the thing
2663
+ * the next session should not repeat.
2664
+ */
2665
+ try {
2666
+ const sha = await currentSha(config.cwd);
2667
+ const learned = deriveFindings(trajectory?.all() ?? [], {
2668
+ ...(sha ? { sha } : {}),
2669
+ ...(config.sessionLabel ? { session: config.sessionLabel } : {}),
2670
+ });
2671
+ if (learned.length > 0)
2672
+ await recordFindings(config.cwd, learned);
2673
+ }
2674
+ catch { /* a ledger that cannot be written must never fail the work it describes */ }
2555
2675
  }
2556
2676
  return _completed;
2557
2677
  }