pi-cohort 7.4.3 → 7.4.5
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/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/src/extension/index.ts +1 -3
- package/src/shared/utils.ts +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [7.4.5] - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Child personas that allow `subagent` and inherit extensions now start without a duplicate-tool error; the explicit child extension is the only registrant. (#26)
|
|
7
|
+
|
|
8
|
+
## [7.4.4] - 2026-10-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Async run status reads no longer serve a stale `running` state after an atomic `status.json` replacement that lands on the same mtime; the read cache now also compares inode and size.
|
|
12
|
+
- The Tests workflow passes on Windows again: CRLF, POSIX file-mode, ENOTDIR, and SIGUSR2 assumptions in tests are normalized or skipped on win32, and run-dir cleanup retries while detached runners finish writing.
|
|
13
|
+
|
|
3
14
|
## [7.4.3] - 2026-10-20
|
|
4
15
|
|
|
5
16
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cohort",
|
|
3
|
-
"version": "7.4.
|
|
3
|
+
"version": "7.4.5",
|
|
4
4
|
"description": "Delegate Pi work to focused child agents: code review, scouting, implementation, parallel audits, saved chains, and background jobs.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"license": "MIT",
|
package/src/extension/index.ts
CHANGED
|
@@ -34,8 +34,7 @@ import { registerSlashSubagentBridge } from "../slash/slash-bridge.ts";
|
|
|
34
34
|
import { clearSlashSnapshots, getSlashRenderableSnapshot, resolveSlashMessageDetails, restoreSlashFinalSnapshots, type SlashMessageDetails } from "../slash/slash-live-state.ts";
|
|
35
35
|
import { inspectSubagentStatus } from "../runs/background/run-status.ts";
|
|
36
36
|
import registerSubagentNotify, { type SubagentNotifyDetails } from "../runs/background/notify.ts";
|
|
37
|
-
import { SUBAGENT_CHILD_ENV
|
|
38
|
-
import registerFanoutChildSubagentExtension from "./fanout-child.ts";
|
|
37
|
+
import { SUBAGENT_CHILD_ENV } from "../runs/shared/pi-args.ts";
|
|
39
38
|
import { formatDuration, shortenPath } from "../shared/formatters.ts";
|
|
40
39
|
import { loadConfig } from "./config.ts";
|
|
41
40
|
import { deriveForwardedFlags } from "../runs/shared/forward-flags.ts";
|
|
@@ -242,7 +241,6 @@ function formatSubagentRoster(cwd: string): string | undefined {
|
|
|
242
241
|
|
|
243
242
|
export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
244
243
|
if (process.env[SUBAGENT_CHILD_ENV] === "1") {
|
|
245
|
-
if (process.env[SUBAGENT_FANOUT_CHILD_ENV] === "1") registerFanoutChildSubagentExtension(pi);
|
|
246
244
|
return;
|
|
247
245
|
}
|
|
248
246
|
const globalStore = globalThis as Record<string, unknown>;
|
package/src/shared/utils.ts
CHANGED
|
@@ -16,7 +16,9 @@ import type { AgentProgress, AsyncStatus, Details, DisplayItem, ErrorInfo, Singl
|
|
|
16
16
|
|
|
17
17
|
export { getAgentDir } from "./agent-dir.ts";
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// Keyed on inode too: writeAtomicJson renames a fresh file in, and a coarse
|
|
20
|
+
// filesystem clock can give the replacement the same mtime as the original.
|
|
21
|
+
const statusCache = new Map<string, { mtime: number; ino: number; size: number; status: AsyncStatus }>();
|
|
20
22
|
|
|
21
23
|
function getErrorMessage(error: unknown): string {
|
|
22
24
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -35,7 +37,7 @@ function isNotFoundError(error: unknown): boolean {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
|
-
* Read async job status from disk (with
|
|
40
|
+
* Read async job status from disk (with stat-based caching)
|
|
39
41
|
*/
|
|
40
42
|
export function readStatus(asyncDir: string): AsyncStatus | null {
|
|
41
43
|
const statusPath = path.join(asyncDir, "status.json");
|
|
@@ -51,7 +53,7 @@ export function readStatus(asyncDir: string): AsyncStatus | null {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
const cached = statusCache.get(statusPath);
|
|
54
|
-
if (cached && cached.mtime === stat.mtimeMs) {
|
|
56
|
+
if (cached && cached.mtime === stat.mtimeMs && cached.ino === stat.ino && cached.size === stat.size) {
|
|
55
57
|
return cached.status;
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -74,7 +76,7 @@ export function readStatus(asyncDir: string): AsyncStatus | null {
|
|
|
74
76
|
});
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
statusCache.set(statusPath, { mtime: stat.mtimeMs, status });
|
|
79
|
+
statusCache.set(statusPath, { mtime: stat.mtimeMs, ino: stat.ino, size: stat.size, status });
|
|
78
80
|
if (statusCache.size > 50) {
|
|
79
81
|
const firstKey = statusCache.keys().next().value;
|
|
80
82
|
if (firstKey) statusCache.delete(firstKey);
|