@proagentstore/cli 0.4.49 → 0.4.50
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.
|
@@ -290,7 +290,16 @@ export function repoTree(workDir, relPath = ".", maxDepth = 3, maxEntries = 500)
|
|
|
290
290
|
try {
|
|
291
291
|
size = statSync(abs).size;
|
|
292
292
|
}
|
|
293
|
-
catch {
|
|
293
|
+
catch {
|
|
294
|
+
// Benign, and traced rather than assumed (#291). `size` stays `undefined`, which JSON
|
|
295
|
+
// drops, so the entry reaches the model as `{path, type: "file"}` — the same listing a
|
|
296
|
+
// successful stat produces, because `repo-local.ts`'s renderer prints `e.path` and has
|
|
297
|
+
// never shown a size at all. The test is whether the fallback can be mistaken for a
|
|
298
|
+
// real answer: `size: 0` would be a claim about an empty file; an absent field is not
|
|
299
|
+
// a claim. The entry itself is still emitted because `readdir` saw it, and the one
|
|
300
|
+
// case where that is already stale — deleted between the readdir and this stat —
|
|
301
|
+
// degrades into an honest error from `repo_read_file`, not into a wrong listing.
|
|
302
|
+
}
|
|
294
303
|
entries.push({ path: rel, type: "file", size });
|
|
295
304
|
}
|
|
296
305
|
}
|
|
@@ -119,10 +119,18 @@ export function switchRepoBranch(workDir, branch) {
|
|
|
119
119
|
// CONFIRM, do not assume. The exit code says the command ran; only reading HEAD back says where
|
|
120
120
|
// the checkout actually is, and that is the only thing the cloud is allowed to report as done.
|
|
121
121
|
const after = currentBranch(workDir);
|
|
122
|
-
|
|
122
|
+
// And the same rule for the tree: `null` when git would not answer, never `false`. Nothing in
|
|
123
|
+
// the cloud reads this field today — `repo-policy-act.ts` acts on `refused`, `error` and its own
|
|
124
|
+
// independent read — so this is prophylactic rather than a live defect, and it is recorded that
|
|
125
|
+
// way. What makes it worth changing anyway is that the value is a CLAIM and the next reader
|
|
126
|
+
// inherits it: `dirty: false` off a failed `git status` says "clean" in the one field whose
|
|
127
|
+
// whole job is to say whether anything came across. Absent is degraded; manufactured is wrong.
|
|
128
|
+
let dirtyAfter;
|
|
123
129
|
try {
|
|
124
130
|
dirtyAfter = isDirty(workDir);
|
|
125
131
|
}
|
|
126
|
-
catch {
|
|
132
|
+
catch {
|
|
133
|
+
dirtyAfter = null;
|
|
134
|
+
}
|
|
127
135
|
return { ok: after === to, changed: after === to, from, to, branch: after, dirty: dirtyAfter };
|
|
128
136
|
}
|
|
@@ -187,6 +187,17 @@ export class CodingRuntime {
|
|
|
187
187
|
* turn of a session very often runs after the final capture poll, and ending is where that
|
|
188
188
|
* record would otherwise be lost — silently, and only for the turns at the end of every
|
|
189
189
|
* session, which is a bias rather than noise.
|
|
190
|
+
*
|
|
191
|
+
* …and, since #554, WHO PAID for it. The spend was already returned here; the observation that
|
|
192
|
+
* makes it attributable was one field away on the session object in hand, so every closing turn
|
|
193
|
+
* of every session reached the ledger with `payer` NULL even when the credential was known. The
|
|
194
|
+
* bias is the same one the paragraph above describes, which is why the omission mattered: it
|
|
195
|
+
* did not lose a random sample of turns, it lost the last turn of every session.
|
|
196
|
+
*
|
|
197
|
+
* `null` is a REAL answer here, not a default. `end()` tolerates a `sessionId` it has never
|
|
198
|
+
* heard of, and the honest report for a session this runner does not have is that it cannot say
|
|
199
|
+
* what the engine authenticated with — not a guess derived from the preset (see
|
|
200
|
+
* `usage-payer.ts`, and the alternative #554 rejected).
|
|
190
201
|
*/
|
|
191
202
|
end(sessionId) {
|
|
192
203
|
const session = this.sessions.get(sessionId);
|
|
@@ -196,12 +207,16 @@ export class CodingRuntime {
|
|
|
196
207
|
// happens after the final capture poll. Discarding the tail would systematically lose exactly
|
|
197
208
|
// the acts this record exists for.
|
|
198
209
|
const acts = session ? session.takeActs() : [];
|
|
210
|
+
// Read BEFORE `stop()`: `authResolved` is a live getter over the merged spawn env
|
|
211
|
+
// (`headless.ts`), so it must be taken while the session is still the object that spawned
|
|
212
|
+
// the process rather than after it has been torn down and dropped from the map.
|
|
213
|
+
const authResolved = session ? session.authResolved : null;
|
|
199
214
|
if (session) {
|
|
200
215
|
session.stop();
|
|
201
216
|
this.sessions.delete(sessionId);
|
|
202
217
|
}
|
|
203
218
|
this.takeovers.delete(sessionId);
|
|
204
|
-
return { ok: true, usage, acts };
|
|
219
|
+
return { ok: true, usage, acts, authResolved };
|
|
205
220
|
}
|
|
206
221
|
list() {
|
|
207
222
|
return [...this.sessions.entries()].map(([sessionId, s]) => ({
|