koneck 2.54.1 → 2.56.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":"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"}
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';
@@ -290,6 +293,8 @@ export function looksLikeToolsUnsupported(err) {
290
293
  /** Duplicate identical tool calls tolerated before the run is treated as a genuine loop. */
291
294
  // A repeat now returns the earlier result, so repeating is productive rather than wasted and
292
295
  // halting on the third is too eager. This is only a backstop against a model that will not stop.
296
+ /** How often streaming tool arguments are reported. Paces the repaint, keeps every character. */
297
+ const TOOL_ARGS_REPORT_MS = 120;
293
298
  const MAX_DUPLICATE_CALLS = 6;
294
299
  /**
295
300
  * Tools that change disk or process state. After one succeeds, previously seen read
@@ -299,6 +304,15 @@ const MAX_DUPLICATE_CALLS = 6;
299
304
  const STATE_CHANGING_TOOLS = new Set([
300
305
  'write_file', 'search_replace', 'apply_diff', 'delete_file', 'move_file', 'execute_command',
301
306
  ]);
307
+ /**
308
+ * Commands long enough that running one twice in a repository is worth avoiding.
309
+ *
310
+ * Not every command: claiming `ls` would fill the record with noise and make the cases that matter
311
+ * harder to see. These are the ones measured in tens of seconds — a test suite here takes between
312
+ * 95 and 170 seconds on four cores, so two sessions each running it is minutes of duplicated wait,
313
+ * and a build or an install competing with itself is worse than slow.
314
+ */
315
+ 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
316
  /**
303
317
  * Text in which the model states outright that it did not finish — "I stopped there", "I have
304
318
  * not yet read the controller", "I only ran initial searches". These are unambiguous: a model
@@ -1014,6 +1028,58 @@ detectedContext = { current: 0 }) {
1014
1028
  const switchedTo = [failoverKey({ provider: config.provider, model: config.model })];
1015
1029
  let switches = 0;
1016
1030
  let discovered = null;
1031
+ /*
1032
+ * Which claim a call is about, or none.
1033
+ *
1034
+ * Only writes and commands: a read cannot lose anybody's work, and claiming every read would
1035
+ * fill the record with noise that makes the two cases worth reporting harder to see.
1036
+ */
1037
+ /*
1038
+ * The ledger, read once per turn rather than once per tool call.
1039
+ *
1040
+ * A turn makes a dozen calls and the file does not change under it, so re-reading would be a
1041
+ * dozen reads for one answer. Null until something asks, so a turn that touches nothing shared
1042
+ * never opens it at all.
1043
+ */
1044
+ let ledgerCache = null;
1045
+ async function recallFor(claimed) {
1046
+ try {
1047
+ if (ledgerCache === null)
1048
+ ledgerCache = await readLedger(effectiveCwd);
1049
+ if (ledgerCache.length === 0)
1050
+ return null;
1051
+ const hits = relevantFindings(ledgerCache, claimed.kind === 'file'
1052
+ ? { paths: [claimed.target] }
1053
+ : { commands: [claimed.target] });
1054
+ if (hits.length === 0)
1055
+ return null;
1056
+ // Judged against git, so a finding about code that has since changed is marked rather than
1057
+ // presented as current fact.
1058
+ const checked = await withStaleness(hits, sha => changedSince(effectiveCwd, sha));
1059
+ return describeFindings(checked);
1060
+ }
1061
+ catch {
1062
+ return null;
1063
+ }
1064
+ }
1065
+ const claimRepo = repoNameFor(effectiveCwd);
1066
+ const claimSessionId = config.auditSessionId ?? `pid-${process.pid}`;
1067
+ function claimFor(name, args) {
1068
+ if (name === 'execute_command') {
1069
+ try {
1070
+ const command = String(JSON.parse(args).command ?? '').trim();
1071
+ // Only the ones long enough to be worth not doing twice. Claiming `ls` is noise.
1072
+ return command && SHARED_WORK.test(command) ? { kind: 'command', target: command } : null;
1073
+ }
1074
+ catch {
1075
+ return null;
1076
+ }
1077
+ }
1078
+ if (!STATE_CHANGING_TOOLS.has(name))
1079
+ return null;
1080
+ const file = filePathFrom(args);
1081
+ return file ? { kind: 'file', target: file } : null;
1082
+ }
1017
1083
  async function tryFailover(err) {
1018
1084
  if (!failoverPolicy?.enabled)
1019
1085
  return false;
@@ -1352,6 +1418,9 @@ detectedContext = { current: 0 }) {
1352
1418
  // is independent of the SDK: if no chunk arrives within STREAM_IDLE_MS the turn is failed
1353
1419
  // and the run continues rather than blocking forever.
1354
1420
  const iterator = stream[Symbol.asyncIterator]();
1421
+ // Reset per request: a new call's arguments should report immediately, not wait out the
1422
+ // remainder of the previous one's window.
1423
+ let lastArgsReport = 0;
1355
1424
  let framesBeforeContent = 0;
1356
1425
  let thinkingChars = 0;
1357
1426
  // Time to first token, kept apart from the total because the two have different causes: a
@@ -1518,6 +1587,22 @@ detectedContext = { current: 0 }) {
1518
1587
  if (tc.function?.arguments)
1519
1588
  acc.arguments += tc.function.arguments;
1520
1589
  }
1590
+ /*
1591
+ * The arguments as they arrive, so a write can be watched rather than announced.
1592
+ *
1593
+ * A file is written in one call, and that call's content streams in over several seconds.
1594
+ * Reporting only the finished call meant the panel showed the file after it was written —
1595
+ * the work was over by the time there was anything to look at. Throttled, because this
1596
+ * fires per token and a repaint per token is a repaint budget spent on nothing.
1597
+ */
1598
+ const nowAt = Date.now();
1599
+ if (config.onToolArgs && nowAt - lastArgsReport >= TOOL_ARGS_REPORT_MS) {
1600
+ lastArgsReport = nowAt;
1601
+ for (const acc of toolCallMap.values()) {
1602
+ if (acc.name && acc.arguments)
1603
+ config.onToolArgs(acc.name, acc.arguments);
1604
+ }
1605
+ }
1521
1606
  }
1522
1607
  }
1523
1608
  tui.streamEnd();
@@ -2071,6 +2156,29 @@ detectedContext = { current: 0 }) {
2071
2156
  tui.printToolCall(tc.name, tc.arguments);
2072
2157
  const toolSpinner = silent ? null : tui.startSpinner(tc.name + '…');
2073
2158
  const toolStart = Date.now();
2159
+ /*
2160
+ * What another session on this checkout is already doing to the same thing.
2161
+ *
2162
+ * Claimed before the work, released after, and reported to the model as an observation rather
2163
+ * than a rule. Two sessions in one repository could not see each other at all: one wrote over
2164
+ * a file the other had just rewritten, both ran the same three-minute suite, and a dev server
2165
+ * one of them depended on was restarted by the other. Reporting rather than locking is
2166
+ * deliberate — a lock between two agents each waiting for the other is a deadlock with nobody
2167
+ * present to break it.
2168
+ */
2169
+ const claimed = claimFor(effectiveName, tc.arguments);
2170
+ let othersOnIt = null;
2171
+ if (claimed) {
2172
+ othersOnIt = describeClaims(claim(claimRepo, claimed.kind, claimed.target, claimSessionId, undefined, undefined, config.sessionLabel));
2173
+ }
2174
+ /*
2175
+ * What earlier sessions in this project found out the hard way about this exact thing.
2176
+ *
2177
+ * Keyed, not dumped: only the findings filed against this path or this command prefix, at the
2178
+ * moment they are useful. The whole point of the ledger is that it can grow without costing
2179
+ * context, which it cannot do if it is loaded into every prompt.
2180
+ */
2181
+ const alreadyKnown = claimed ? await recallFor(claimed) : null;
2074
2182
  let result;
2075
2183
  const policyDecision = evaluatePolicy(policy, effectiveName, tc.arguments, effectiveCwd);
2076
2184
  // Asked of the interface, which knows the mode and what the user has already agreed to.
@@ -2222,6 +2330,20 @@ detectedContext = { current: 0 }) {
2222
2330
  }
2223
2331
  const toolElapsed = Date.now() - toolStart;
2224
2332
  const toolFailed = isToolFailure(result);
2333
+ // Finished with it, so another session sees "edited" rather than "is editing".
2334
+ if (claimed)
2335
+ release(claimRepo, claimed.kind, claimed.target, claimSessionId);
2336
+ /*
2337
+ * What another session was doing, said alongside the result rather than instead of it.
2338
+ *
2339
+ * The work is not prevented — the model is better placed to decide whether to re-read, work
2340
+ * elsewhere, or say so and stop. Appended after the result so it reads as context, not as the
2341
+ * outcome of the call.
2342
+ */
2343
+ if (othersOnIt)
2344
+ result = `${result}\n\n${othersOnIt}`;
2345
+ if (alreadyKnown)
2346
+ result = `${result}\n\n${alreadyKnown}`;
2225
2347
  // The reason travels with the result. Without it a failed step showed as "x read_files ·
2226
2348
  // 0ms" and nothing else, so the model knew why and the person watching did not.
2227
2349
  config.onToolResult?.(tc.name, !toolFailed, toolElapsed, toolFailed ? failureReason(result) : undefined);
@@ -2552,6 +2674,25 @@ initialPlan) {
2552
2674
  // Commit even when the turn threw or was interrupted — a partial edit is exactly
2553
2675
  // the case where being able to undo matters most.
2554
2676
  await checkpoint.commit().catch(() => null);
2677
+ /*
2678
+ * What this turn learned, written down for the next session.
2679
+ *
2680
+ * Derived from the trajectory rather than asked of the model: the trajectory is written
2681
+ * whether or not anybody is being reflective, so this happens every turn instead of the rare
2682
+ * one where the model thinks to leave a note. In the finally block because a turn that failed
2683
+ * is often the one that learned the most — the command that did not work is exactly the thing
2684
+ * the next session should not repeat.
2685
+ */
2686
+ try {
2687
+ const sha = await currentSha(config.cwd);
2688
+ const learned = deriveFindings(trajectory?.all() ?? [], {
2689
+ ...(sha ? { sha } : {}),
2690
+ ...(config.sessionLabel ? { session: config.sessionLabel } : {}),
2691
+ });
2692
+ if (learned.length > 0)
2693
+ await recordFindings(config.cwd, learned);
2694
+ }
2695
+ catch { /* a ledger that cannot be written must never fail the work it describes */ }
2555
2696
  }
2556
2697
  return _completed;
2557
2698
  }