@dungle-scrubs/tallow 0.8.26 → 0.8.28
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/README.md +42 -1
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/interactive-mode-patch.d.ts +1 -0
- package/dist/interactive-mode-patch.d.ts.map +1 -1
- package/dist/interactive-mode-patch.js +40 -1
- package/dist/interactive-mode-patch.js.map +1 -1
- package/dist/model-metadata-overrides.d.ts +2 -5
- package/dist/model-metadata-overrides.d.ts.map +1 -1
- package/dist/model-metadata-overrides.js +23 -12
- package/dist/model-metadata-overrides.js.map +1 -1
- package/dist/pid-manager.d.ts +2 -9
- package/dist/pid-manager.d.ts.map +1 -1
- package/dist/pid-manager.js +1 -58
- package/dist/pid-manager.js.map +1 -1
- package/dist/pid-schema.d.ts +51 -0
- package/dist/pid-schema.d.ts.map +1 -0
- package/dist/pid-schema.js +70 -0
- package/dist/pid-schema.js.map +1 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +24 -17
- package/dist/sdk.js.map +1 -1
- package/dist/workspace-transition-interactive.d.ts.map +1 -1
- package/dist/workspace-transition-interactive.js +53 -3
- package/dist/workspace-transition-interactive.js.map +1 -1
- package/dist/workspace-transition.d.ts +2 -1
- package/dist/workspace-transition.d.ts.map +1 -1
- package/dist/workspace-transition.js +16 -4
- package/dist/workspace-transition.js.map +1 -1
- package/extensions/__integration__/audit-findings.test.ts +309 -0
- package/extensions/__integration__/cd-tool-guidelines.test.ts +46 -0
- package/extensions/__integration__/tasks-runtime.test.ts +63 -12
- package/extensions/__integration__/welcome-screen.test.ts +240 -0
- package/extensions/_shared/lazy-init.ts +88 -3
- package/extensions/_shared/pid-registry.ts +8 -82
- package/extensions/background-task-tool/index.ts +1 -1
- package/extensions/cd-tool/index.ts +4 -1
- package/extensions/cheatsheet/__tests__/cheatsheet.test.ts +47 -0
- package/extensions/clear/__tests__/clear.test.ts +38 -0
- package/extensions/edit-tool-enhanced/index.ts +3 -1
- package/extensions/git-status/__tests__/git-status.test.ts +32 -0
- package/extensions/health/__tests__/diagnostics.test.ts +25 -0
- package/extensions/health/index.ts +61 -0
- package/extensions/loop/__tests__/loop.test.ts +365 -1
- package/extensions/loop/index.ts +213 -3
- package/extensions/mcp-adapter-tool/index.ts +1 -1
- package/extensions/minimal-skill-display/__tests__/minimal-skill-display.test.ts +20 -0
- package/extensions/permissions/__tests__/permissions.test.ts +213 -0
- package/extensions/progress-indicator/__tests__/progress-indicator.test.ts +104 -0
- package/extensions/prompt-suggestions/__tests__/autocomplete.test.ts +111 -3
- package/extensions/prompt-suggestions/autocomplete.ts +23 -5
- package/extensions/prompt-suggestions/index.ts +62 -3
- package/extensions/random-spinner/__tests__/random-spinner.test.ts +35 -0
- package/extensions/read-tool-enhanced/index.ts +5 -1
- package/extensions/session-memory/index.ts +1 -1
- package/extensions/session-namer/index.ts +1 -1
- package/extensions/show-system-prompt/__tests__/show-system-prompt.test.ts +51 -0
- package/extensions/subagent-tool/__tests__/presentation-rendering.test.ts +9 -8
- package/extensions/subagent-tool/__tests__/process-liveness.test.ts +51 -0
- package/extensions/subagent-tool/__tests__/subprocess-args.test.ts +120 -0
- package/extensions/subagent-tool/formatting.ts +2 -0
- package/extensions/subagent-tool/index.ts +160 -97
- package/extensions/subagent-tool/process.ts +152 -40
- package/extensions/tasks/commands/register-tasks-extension.ts +64 -20
- package/extensions/tasks/extension.json +1 -0
- package/extensions/tasks/index.ts +2 -12
- package/extensions/tasks/state/index.ts +26 -0
- package/extensions/teams-tool/dashboard.ts +13 -1
- package/extensions/teams-tool/sessions/spawn.ts +2 -2
- package/extensions/teams-tool/tools/register-extension.ts +10 -2
- package/extensions/upstream-check/__tests__/upstream-check.test.ts +49 -0
- package/extensions/welcome-screen/__tests__/welcome-screen.test.ts +35 -0
- package/extensions/welcome-screen/extension.json +20 -0
- package/extensions/welcome-screen/index.ts +189 -0
- package/extensions/wezterm-notify/__tests__/index.test.ts +49 -11
- package/extensions/wezterm-notify/index.ts +5 -3
- package/extensions/write-tool-enhanced/__tests__/write-tool-enhanced.test.ts +296 -0
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts +2 -2
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/index.js +2 -2
- package/node_modules/@mariozechner/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts +309 -25
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js +392 -72
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts +30 -0
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.js +50 -6
- package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts +27 -0
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js +59 -4
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts +9 -0
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.js +50 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/package.json +1 -1
- package/node_modules/@mariozechner/pi-tui/src/__tests__/mouse-events.test.ts +134 -0
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tmux-compat.test.ts +204 -0
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-diff-regression.test.ts +49 -0
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-render-scheduling.test.ts +2 -0
- package/node_modules/@mariozechner/pi-tui/src/index.ts +11 -0
- package/node_modules/@mariozechner/pi-tui/src/keybindings.ts +478 -140
- package/node_modules/@mariozechner/pi-tui/src/keys.ts +84 -6
- package/node_modules/@mariozechner/pi-tui/src/terminal.ts +69 -4
- package/node_modules/@mariozechner/pi-tui/src/tui.ts +64 -1
- package/package.json +11 -10
- package/runtime/config.ts +7 -0
- package/runtime/model-metadata-overrides.ts +7 -0
- package/runtime/pid-schema.ts +13 -0
- package/skills/tallow-expert/SKILL.md +7 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-transition-interactive.js","sourceRoot":"","sources":["../src/workspace-transition-interactive.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"workspace-transition-interactive.js","sourceRoot":"","sources":["../src/workspace-transition-interactive.ts"],"names":[],"mappings":"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"}
|
|
@@ -96,7 +96,8 @@ export declare function getWorkspaceTransitionHost(): WorkspaceTransitionHost |
|
|
|
96
96
|
* @param targetCwd - Workspace after the move
|
|
97
97
|
* @param initiator - Transition source kind
|
|
98
98
|
* @param trustedOnEntry - Whether repo-controlled surfaces are enabled in the target workspace
|
|
99
|
+
* @param taskContext - Optional task context carried forward from the previous session
|
|
99
100
|
* @returns Synthetic transition summary for the restarted turn
|
|
100
101
|
*/
|
|
101
|
-
export declare function buildWorkspaceTransitionSummary(sourceCwd: string, targetCwd: string, initiator: WorkspaceTransitionInitiator, trustedOnEntry: boolean): string;
|
|
102
|
+
export declare function buildWorkspaceTransitionSummary(sourceCwd: string, targetCwd: string, initiator: WorkspaceTransitionInitiator, trustedOnEntry: boolean, taskContext?: string): string;
|
|
102
103
|
//# sourceMappingURL=workspace-transition.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-transition.d.ts","sourceRoot":"","sources":["../src/workspace-transition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,2DAA2D;AAC3D,MAAM,MAAM,4BAA4B,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtE;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,IAAI,CAAC;IACnE;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,+DAA+D;AAC/D,MAAM,WAAW,0BAA0B;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;IACjD,kDAAkD;IAClD,QAAQ,CAAC,EAAE,EAAE,qBAAqB,CAAC;CACnC;AAED,qCAAqC;AACrC,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC;AAED,oCAAoC;AACpC,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC7B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oCAAoC;IACpD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,wCAAwC;AACxC,MAAM,MAAM,yBAAyB,GAClC,kCAAkC,GAClC,kCAAkC,GAClC,oCAAoC,CAAC;AAExC,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;CAC3F;AAED;;;;;GAKG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAID;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,uBAAuB,GAAG,IAAI,CAE3E;AAED
|
|
1
|
+
{"version":3,"file":"workspace-transition.d.ts","sourceRoot":"","sources":["../src/workspace-transition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,2DAA2D;AAC3D,MAAM,MAAM,4BAA4B,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtE;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,IAAI,CAAC;IACnE;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,+DAA+D;AAC/D,MAAM,WAAW,0BAA0B;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;IACjD,kDAAkD;IAClD,QAAQ,CAAC,EAAE,EAAE,qBAAqB,CAAC;CACnC;AAED,qCAAqC;AACrC,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC;AAED,oCAAoC;AACpC,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC7B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oCAAoC;IACpD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,wCAAwC;AACxC,MAAM,MAAM,yBAAyB,GAClC,kCAAkC,GAClC,kCAAkC,GAClC,oCAAoC,CAAC;AAExC,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;CAC3F;AAED;;;;;GAKG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,oBAAoB,CAAC;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAID;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,uBAAuB,GAAG,IAAI,CAE3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC9C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,4BAA4B,EACvC,cAAc,EAAE,OAAO,EACvB,WAAW,CAAC,EAAE,MAAM,GAClB,MAAM,CAuBR"}
|
|
@@ -23,17 +23,29 @@ export function getWorkspaceTransitionHost() {
|
|
|
23
23
|
* @param targetCwd - Workspace after the move
|
|
24
24
|
* @param initiator - Transition source kind
|
|
25
25
|
* @param trustedOnEntry - Whether repo-controlled surfaces are enabled in the target workspace
|
|
26
|
+
* @param taskContext - Optional task context carried forward from the previous session
|
|
26
27
|
* @returns Synthetic transition summary for the restarted turn
|
|
27
28
|
*/
|
|
28
|
-
export function buildWorkspaceTransitionSummary(sourceCwd, targetCwd, initiator, trustedOnEntry) {
|
|
29
|
+
export function buildWorkspaceTransitionSummary(sourceCwd, targetCwd, initiator, trustedOnEntry, taskContext) {
|
|
29
30
|
const initiatorLabel = initiator === "tool" ? "tool request" : "user command";
|
|
30
31
|
const trustLabel = trustedOnEntry
|
|
31
32
|
? "repo-controlled project surfaces are enabled in the target workspace"
|
|
32
33
|
: "repo-controlled project surfaces remain blocked because the target workspace is untrusted";
|
|
33
|
-
|
|
34
|
+
let summary = `Workspace transition complete (${initiatorLabel}).\n` +
|
|
34
35
|
`Previous workspace: ${sourceCwd}\n` +
|
|
35
36
|
`Current workspace: ${targetCwd}\n` +
|
|
36
|
-
`${trustLabel}.\n
|
|
37
|
-
|
|
37
|
+
`${trustLabel}.\n`;
|
|
38
|
+
if (taskContext) {
|
|
39
|
+
summary +=
|
|
40
|
+
"\n--- Task context carried forward from previous workspace ---\n" +
|
|
41
|
+
`${taskContext}\n` +
|
|
42
|
+
"--- End task context ---\n\n" +
|
|
43
|
+
"Continue working on the task above in the new workspace.";
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
summary +=
|
|
47
|
+
"Treat the interrupted turn as ended. Re-evaluate the new workspace before continuing.";
|
|
48
|
+
}
|
|
49
|
+
return summary;
|
|
38
50
|
}
|
|
39
51
|
//# sourceMappingURL=workspace-transition.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-transition.js","sourceRoot":"","sources":["../src/workspace-transition.ts"],"names":[],"mappings":"AA2FA,IAAI,UAAU,GAAmC,IAAI,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAAC,IAAoC;IACnF,UAAU,GAAG,IAAI,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B;IACzC,OAAO,UAAU,CAAC;AACnB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"workspace-transition.js","sourceRoot":"","sources":["../src/workspace-transition.ts"],"names":[],"mappings":"AA2FA,IAAI,UAAU,GAAmC,IAAI,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAAC,IAAoC;IACnF,UAAU,GAAG,IAAI,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B;IACzC,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,+BAA+B,CAC9C,SAAiB,EACjB,SAAiB,EACjB,SAAuC,EACvC,cAAuB,EACvB,WAAoB;IAEpB,MAAM,cAAc,GAAG,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC;IAC9E,MAAM,UAAU,GAAG,cAAc;QAChC,CAAC,CAAC,sEAAsE;QACxE,CAAC,CAAC,2FAA2F,CAAC;IAC/F,IAAI,OAAO,GACV,kCAAkC,cAAc,MAAM;QACtD,uBAAuB,SAAS,IAAI;QACpC,sBAAsB,SAAS,IAAI;QACnC,GAAG,UAAU,KAAK,CAAC;IAEpB,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO;YACN,kEAAkE;gBAClE,GAAG,WAAW,IAAI;gBAClB,8BAA8B;gBAC9B,0DAA0D,CAAC;IAC7D,CAAC;SAAM,CAAC;QACP,OAAO;YACN,uFAAuF,CAAC;IAC1F,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for issues identified in the repository audit.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - Dead cwd_changed listener removal
|
|
6
|
+
* - session_shutdown type safety (no 'as never' casts)
|
|
7
|
+
* - Tool restriction enforcement
|
|
8
|
+
* - Extension startup policy filtering
|
|
9
|
+
* - session_shutdown handlers fire during cleanup
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
13
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
14
|
+
import { join, resolve } from "node:path";
|
|
15
|
+
import type { ExtensionAPI, ExtensionFactory } from "@mariozechner/pi-coding-agent";
|
|
16
|
+
import { ExtensionHarness } from "../../test-utils/extension-harness.js";
|
|
17
|
+
import { createScriptedStreamFn } from "../../test-utils/mock-model.js";
|
|
18
|
+
import { createSessionRunner, type SessionRunner } from "../../test-utils/session-runner.js";
|
|
19
|
+
|
|
20
|
+
let runner: SessionRunner | undefined;
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
runner?.dispose();
|
|
24
|
+
runner = undefined;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// ════════════════════════════════════════════════════════════════
|
|
28
|
+
// Audit Finding 1.1: Dead cwd_changed listener removed
|
|
29
|
+
// ════════════════════════════════════════════════════════════════
|
|
30
|
+
|
|
31
|
+
describe("cwd_changed event listener removal", () => {
|
|
32
|
+
it("sdk.ts does not contain tallow:cwd_changed event listener", () => {
|
|
33
|
+
const sdkPath = resolve(__dirname, "../../src/sdk.ts");
|
|
34
|
+
const sdkSource = readFileSync(sdkPath, "utf-8");
|
|
35
|
+
// The dead listener was removed — verify it stays gone
|
|
36
|
+
expect(sdkSource).not.toContain('events.on("tallow:cwd_changed"');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("sdk.ts contains the explanatory comment about why cwd_changed is unnecessary", () => {
|
|
40
|
+
const sdkPath = resolve(__dirname, "../../src/sdk.ts");
|
|
41
|
+
const sdkSource = readFileSync(sdkPath, "utf-8");
|
|
42
|
+
expect(sdkSource).toContain("Trust context does not need a cwd_changed event listener");
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// ════════════════════════════════════════════════════════════════
|
|
47
|
+
// Audit Finding 1.4: session_shutdown type safety
|
|
48
|
+
// ════════════════════════════════════════════════════════════════
|
|
49
|
+
|
|
50
|
+
describe("session_shutdown type safety", () => {
|
|
51
|
+
const extensionsDir = resolve(__dirname, "..");
|
|
52
|
+
|
|
53
|
+
it("no extension uses 'as never' cast for session_shutdown", () => {
|
|
54
|
+
const violations: string[] = [];
|
|
55
|
+
const dirs = readdirSync(extensionsDir, { withFileTypes: true })
|
|
56
|
+
.filter((d) => d.isDirectory() && !d.name.startsWith("_"))
|
|
57
|
+
.map((d) => join(extensionsDir, d.name));
|
|
58
|
+
|
|
59
|
+
for (const dir of dirs) {
|
|
60
|
+
const indexPath = join(dir, "index.ts");
|
|
61
|
+
if (!existsSync(indexPath)) continue;
|
|
62
|
+
const source = readFileSync(indexPath, "utf-8");
|
|
63
|
+
if (source.includes('session_shutdown" as never')) {
|
|
64
|
+
violations.push(dir.split("/").pop()!);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Also check nested files (e.g. teams-tool/tools/register-extension.ts)
|
|
69
|
+
for (const dir of dirs) {
|
|
70
|
+
try {
|
|
71
|
+
const subDirs = readdirSync(dir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
72
|
+
for (const sub of subDirs) {
|
|
73
|
+
if (sub.name === "__tests__" || sub.name === "node_modules") continue;
|
|
74
|
+
const subPath = join(dir, sub.name);
|
|
75
|
+
const files = readdirSync(subPath).filter((f) => f.endsWith(".ts"));
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
const source = readFileSync(join(subPath, file), "utf-8");
|
|
78
|
+
if (source.includes('session_shutdown" as never')) {
|
|
79
|
+
violations.push(`${dir.split("/").pop()}/${sub.name}/${file}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
// not a directory with subdirs
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
expect(violations).toEqual([]);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// ════════════════════════════════════════════════════════════════
|
|
93
|
+
// Audit Finding 1.5: subagent-tool has session_shutdown
|
|
94
|
+
// ════════════════════════════════════════════════════════════════
|
|
95
|
+
|
|
96
|
+
describe("subagent-tool session_shutdown", () => {
|
|
97
|
+
it("subagent-tool/index.ts contains session_shutdown handler", () => {
|
|
98
|
+
const source = readFileSync(resolve(__dirname, "../subagent-tool/index.ts"), "utf-8");
|
|
99
|
+
expect(source).toContain('on("session_shutdown"');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// ════════════════════════════════════════════════════════════════
|
|
104
|
+
// Tool Restriction Enforcement (--tools flag)
|
|
105
|
+
// ════════════════════════════════════════════════════════════════
|
|
106
|
+
|
|
107
|
+
describe("Explicit tool restriction", () => {
|
|
108
|
+
it("tool_call handler blocks tools not in the allowlist", async () => {
|
|
109
|
+
const blocked: string[] = [];
|
|
110
|
+
const extensionFactory: ExtensionFactory = (pi: ExtensionAPI) => {
|
|
111
|
+
const allowed = new Set(["read"]);
|
|
112
|
+
pi.on("tool_call", async (event) => {
|
|
113
|
+
if (!allowed.has(event.toolName)) {
|
|
114
|
+
blocked.push(event.toolName);
|
|
115
|
+
return { block: true, reason: "Not allowed" };
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const harness = ExtensionHarness.create();
|
|
121
|
+
await harness.loadExtension(extensionFactory);
|
|
122
|
+
const results = await harness.fireEvent("tool_call", {
|
|
123
|
+
type: "tool_call",
|
|
124
|
+
toolName: "bash",
|
|
125
|
+
toolCallId: "test-1",
|
|
126
|
+
input: { command: "ls" },
|
|
127
|
+
});
|
|
128
|
+
const blockResult = results.find(
|
|
129
|
+
(r) => r && typeof r === "object" && (r as { block?: boolean }).block
|
|
130
|
+
);
|
|
131
|
+
expect(blockResult).toBeDefined();
|
|
132
|
+
expect(blocked).toContain("bash");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("tool_call handler allows tools in the allowlist", async () => {
|
|
136
|
+
const extensionFactory: ExtensionFactory = (pi: ExtensionAPI) => {
|
|
137
|
+
const allowed = new Set(["read", "bash"]);
|
|
138
|
+
pi.on("tool_call", async (event) => {
|
|
139
|
+
if (!allowed.has(event.toolName)) {
|
|
140
|
+
return { block: true, reason: "Not allowed" };
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const harness = ExtensionHarness.create();
|
|
146
|
+
await harness.loadExtension(extensionFactory);
|
|
147
|
+
const results = await harness.fireEvent("tool_call", {
|
|
148
|
+
type: "tool_call",
|
|
149
|
+
toolName: "read",
|
|
150
|
+
toolCallId: "test-2",
|
|
151
|
+
input: { path: "test.txt" },
|
|
152
|
+
});
|
|
153
|
+
const blockResult = results.find(
|
|
154
|
+
(r) => r && typeof r === "object" && (r as { block?: boolean }).block
|
|
155
|
+
);
|
|
156
|
+
expect(blockResult).toBeUndefined();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// ════════════════════════════════════════════════════════════════
|
|
161
|
+
// session_shutdown handler fires during lifecycle
|
|
162
|
+
// ════════════════════════════════════════════════════════════════
|
|
163
|
+
|
|
164
|
+
describe("session_shutdown lifecycle", () => {
|
|
165
|
+
it("session_shutdown handler fires when simulated", async () => {
|
|
166
|
+
let shutdownFired = false;
|
|
167
|
+
const extensionFactory: ExtensionFactory = (pi: ExtensionAPI) => {
|
|
168
|
+
pi.on("session_shutdown", async () => {
|
|
169
|
+
shutdownFired = true;
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const harness = ExtensionHarness.create();
|
|
174
|
+
await harness.loadExtension(extensionFactory);
|
|
175
|
+
await harness.fireEvent("session_shutdown", { type: "session_shutdown" });
|
|
176
|
+
expect(shutdownFired).toBe(true);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("multiple session_shutdown handlers all fire", async () => {
|
|
180
|
+
const fired: string[] = [];
|
|
181
|
+
const ext1: ExtensionFactory = (pi: ExtensionAPI) => {
|
|
182
|
+
pi.on("session_shutdown", async () => {
|
|
183
|
+
fired.push("ext1");
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
const ext2: ExtensionFactory = (pi: ExtensionAPI) => {
|
|
187
|
+
pi.on("session_shutdown", async () => {
|
|
188
|
+
fired.push("ext2");
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const harness = ExtensionHarness.create();
|
|
193
|
+
await harness.loadExtension(ext1);
|
|
194
|
+
await harness.loadExtension(ext2);
|
|
195
|
+
await harness.fireEvent("session_shutdown", { type: "session_shutdown" });
|
|
196
|
+
expect(fired).toContain("ext1");
|
|
197
|
+
expect(fired).toContain("ext2");
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// ════════════════════════════════════════════════════════════════
|
|
202
|
+
// Lazy-init circuit breaker
|
|
203
|
+
// ════════════════════════════════════════════════════════════════
|
|
204
|
+
|
|
205
|
+
describe("lazy-init circuit breaker", () => {
|
|
206
|
+
it("createLazyInitializer exposes isPermanentlyFailed()", async () => {
|
|
207
|
+
const { createLazyInitializer } = await import("../../extensions/_shared/lazy-init.js");
|
|
208
|
+
const init = createLazyInitializer({
|
|
209
|
+
name: "test",
|
|
210
|
+
maxRetries: 1,
|
|
211
|
+
initialize: async () => {
|
|
212
|
+
throw new Error("always fails");
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(init.isPermanentlyFailed()).toBe(false);
|
|
217
|
+
|
|
218
|
+
// First call fails
|
|
219
|
+
try {
|
|
220
|
+
await init.ensureInitialized({ trigger: "test", context: {} });
|
|
221
|
+
} catch {
|
|
222
|
+
// expected
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// After maxRetries, permanently failed
|
|
226
|
+
expect(init.isPermanentlyFailed()).toBe(true);
|
|
227
|
+
|
|
228
|
+
// Next call rejects immediately
|
|
229
|
+
try {
|
|
230
|
+
await init.ensureInitialized({ trigger: "test", context: {} });
|
|
231
|
+
expect(true).toBe(false); // should not reach
|
|
232
|
+
} catch (e) {
|
|
233
|
+
expect((e as Error).message).toContain("always fails");
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("reset() clears permanent failure state", async () => {
|
|
238
|
+
const { createLazyInitializer } = await import("../../extensions/_shared/lazy-init.js");
|
|
239
|
+
let callCount = 0;
|
|
240
|
+
const init = createLazyInitializer({
|
|
241
|
+
name: "test-reset",
|
|
242
|
+
maxRetries: 1,
|
|
243
|
+
initialize: async () => {
|
|
244
|
+
callCount++;
|
|
245
|
+
if (callCount <= 1) throw new Error("fail first");
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
await init.ensureInitialized({ trigger: "test", context: {} });
|
|
251
|
+
} catch {
|
|
252
|
+
// expected
|
|
253
|
+
}
|
|
254
|
+
expect(init.isPermanentlyFailed()).toBe(true);
|
|
255
|
+
|
|
256
|
+
init.reset();
|
|
257
|
+
expect(init.isPermanentlyFailed()).toBe(false);
|
|
258
|
+
|
|
259
|
+
// Should succeed after reset
|
|
260
|
+
await init.ensureInitialized({ trigger: "test", context: {} });
|
|
261
|
+
expect(init.isInitialized()).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// ════════════════════════════════════════════════════════════════
|
|
266
|
+
// AGENTS.md accuracy
|
|
267
|
+
// ════════════════════════════════════════════════════════════════
|
|
268
|
+
|
|
269
|
+
describe("AGENTS.md accuracy", () => {
|
|
270
|
+
it("config.ts description does not mention cache", () => {
|
|
271
|
+
const agentsMd = readFileSync(resolve(__dirname, "../../AGENTS.md"), "utf-8");
|
|
272
|
+
// The cache myth was removed
|
|
273
|
+
expect(agentsMd).not.toContain(".env.cache");
|
|
274
|
+
expect(agentsMd).not.toContain("1h TTL");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("TUI conflict surface lists more than 3 files", () => {
|
|
278
|
+
const agentsMd = readFileSync(resolve(__dirname, "../../AGENTS.md"), "utf-8");
|
|
279
|
+
// The old claim was only 3 files; now it should list many more
|
|
280
|
+
expect(agentsMd).toContain("editor-component.ts");
|
|
281
|
+
expect(agentsMd).toContain("terminal-image.ts");
|
|
282
|
+
expect(agentsMd).toContain("components/editor.ts");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("sdk.ts description acknowledges ~2900 lines and inline factory extensions", () => {
|
|
286
|
+
const agentsMd = readFileSync(resolve(__dirname, "../../AGENTS.md"), "utf-8");
|
|
287
|
+
expect(agentsMd).toContain("~2900 lines");
|
|
288
|
+
expect(agentsMd).toContain("inline factory extensions");
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ════════════════════════════════════════════════════════════════
|
|
293
|
+
// Every extension has tests
|
|
294
|
+
// ════════════════════════════════════════════════════════════════
|
|
295
|
+
|
|
296
|
+
describe("Extension test coverage completeness", () => {
|
|
297
|
+
it("all non-utility extension directories have __tests__/", () => {
|
|
298
|
+
const skip = new Set(["__integration__", "_shared", "_icons"]);
|
|
299
|
+
const dirs = readdirSync(resolve(__dirname, ".."), { withFileTypes: true })
|
|
300
|
+
.filter((d) => d.isDirectory() && !skip.has(d.name))
|
|
301
|
+
.map((d) => d.name);
|
|
302
|
+
|
|
303
|
+
const untested = dirs.filter(
|
|
304
|
+
(name) => !existsSync(join(resolve(__dirname, ".."), name, "__tests__"))
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
expect(untested).toEqual([]);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test: cd tool prompt guidelines.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the cd tool's promptGuidelines are injected into the
|
|
5
|
+
* system prompt, preventing the model from combining cd with other tools.
|
|
6
|
+
*/
|
|
7
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
8
|
+
import { createScriptedStreamFn } from "../../test-utils/mock-model.js";
|
|
9
|
+
import { createSessionRunner, type SessionRunner } from "../../test-utils/session-runner.js";
|
|
10
|
+
import cdToolExtension from "../cd-tool/index.js";
|
|
11
|
+
|
|
12
|
+
let runner: SessionRunner | undefined;
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
runner?.dispose();
|
|
16
|
+
runner = undefined;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("cd tool prompt guidelines", () => {
|
|
20
|
+
it("injects exclusive-call guideline into the system prompt", async () => {
|
|
21
|
+
runner = await createSessionRunner({
|
|
22
|
+
streamFn: createScriptedStreamFn([{ text: "ok" }]),
|
|
23
|
+
extensionFactories: [cdToolExtension],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Run a prompt so the system prompt is built (includes tool guidelines)
|
|
27
|
+
await runner.run("hello");
|
|
28
|
+
|
|
29
|
+
const systemPrompt = runner.session.systemPrompt;
|
|
30
|
+
expect(systemPrompt).toContain("cd tool triggers an interactive workspace transition");
|
|
31
|
+
expect(systemPrompt).toContain("SOLE tool call");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("includes the cd tool in the available tools", async () => {
|
|
35
|
+
runner = await createSessionRunner({
|
|
36
|
+
streamFn: createScriptedStreamFn([{ text: "ok" }]),
|
|
37
|
+
extensionFactories: [cdToolExtension],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await runner.run("hello");
|
|
41
|
+
|
|
42
|
+
const systemPrompt = runner.session.systemPrompt;
|
|
43
|
+
// The tool description should appear (either in the tools section or as a snippet)
|
|
44
|
+
expect(systemPrompt).toContain("cd");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
2
4
|
import type { ExtensionContext, ToolDefinition } from "@mariozechner/pi-coding-agent";
|
|
3
5
|
import { ExtensionHarness } from "../../test-utils/extension-harness.js";
|
|
4
6
|
import { registerTasksExtension } from "../tasks/commands/register-tasks-extension.js";
|
|
5
|
-
import { TaskListStore } from "../tasks/state/index.js";
|
|
7
|
+
import { buildSessionTaskGroupName, TASK_GROUPS_DIR, TaskListStore } from "../tasks/state/index.js";
|
|
6
8
|
|
|
7
9
|
const ORIGINAL_PI_IS_SUBAGENT = process.env.PI_IS_SUBAGENT;
|
|
8
10
|
const ORIGINAL_PI_TEAM_NAME = process.env.PI_TEAM_NAME;
|
|
11
|
+
const TEST_TASK_GROUPS = new Set<string>();
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Build a minimal extension context for direct tool execution in tests.
|
|
12
15
|
*
|
|
16
|
+
* @param options - Optional session/cwd overrides
|
|
13
17
|
* @returns Stub extension context
|
|
14
18
|
*/
|
|
15
|
-
function createContext(
|
|
19
|
+
function createContext(options?: {
|
|
20
|
+
cwd?: string;
|
|
21
|
+
entries?: Array<{ type: string; customType?: string; data?: unknown }>;
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
}): ExtensionContext {
|
|
16
24
|
return {
|
|
17
25
|
ui: {
|
|
18
26
|
async select() {
|
|
@@ -61,10 +69,11 @@ function createContext(): ExtensionContext {
|
|
|
61
69
|
setToolsExpanded() {},
|
|
62
70
|
} as ExtensionContext["ui"],
|
|
63
71
|
hasUI: false,
|
|
64
|
-
cwd: process.cwd(),
|
|
72
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
65
73
|
sessionManager: {
|
|
66
|
-
getEntries: () => [],
|
|
74
|
+
getEntries: () => options?.entries ?? [],
|
|
67
75
|
appendEntry: () => {},
|
|
76
|
+
getSessionId: () => options?.sessionId ?? "test-session",
|
|
68
77
|
} as never,
|
|
69
78
|
modelRegistry: {
|
|
70
79
|
getApiKeyForProvider: async () => undefined,
|
|
@@ -110,19 +119,18 @@ function getTool(harness: ExtensionHarness, name: string): ToolDefinition {
|
|
|
110
119
|
*
|
|
111
120
|
* @param tool - Registered manage_tasks tool
|
|
112
121
|
* @param params - Tool parameters
|
|
122
|
+
* @param ctx - Optional extension context override
|
|
113
123
|
* @returns Tool execution result
|
|
114
124
|
*/
|
|
115
125
|
async function execManage(
|
|
116
126
|
tool: ToolDefinition,
|
|
117
|
-
params: Record<string, unknown
|
|
127
|
+
params: Record<string, unknown>,
|
|
128
|
+
ctx = createContext()
|
|
118
129
|
): Promise<{ content: Array<{ type: string; text?: string }>; details: unknown }> {
|
|
119
|
-
return (await tool.execute(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
undefined,
|
|
124
|
-
createContext()
|
|
125
|
-
)) as { content: Array<{ type: string; text?: string }>; details: unknown };
|
|
130
|
+
return (await tool.execute("test-tool-call", params as never, undefined, undefined, ctx)) as {
|
|
131
|
+
content: Array<{ type: string; text?: string }>;
|
|
132
|
+
details: unknown;
|
|
133
|
+
};
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
beforeEach(() => {
|
|
@@ -131,6 +139,10 @@ beforeEach(() => {
|
|
|
131
139
|
});
|
|
132
140
|
|
|
133
141
|
afterEach(() => {
|
|
142
|
+
for (const groupName of TEST_TASK_GROUPS) {
|
|
143
|
+
rmSync(join(TASK_GROUPS_DIR, groupName), { force: true, recursive: true });
|
|
144
|
+
}
|
|
145
|
+
TEST_TASK_GROUPS.clear();
|
|
134
146
|
if (ORIGINAL_PI_IS_SUBAGENT === undefined) delete process.env.PI_IS_SUBAGENT;
|
|
135
147
|
else process.env.PI_IS_SUBAGENT = ORIGINAL_PI_IS_SUBAGENT;
|
|
136
148
|
if (ORIGINAL_PI_TEAM_NAME === undefined) delete process.env.PI_TEAM_NAME;
|
|
@@ -205,6 +217,45 @@ describe("Tasks runtime wiring", () => {
|
|
|
205
217
|
expect(listText).toContain("2. [in_progress] Deploy fix");
|
|
206
218
|
});
|
|
207
219
|
|
|
220
|
+
it("isolates file-backed task groups per session and reloads them on session_switch", async () => {
|
|
221
|
+
process.env.PI_IS_SUBAGENT = "0";
|
|
222
|
+
process.env.PI_TEAM_NAME = "foreign-shared-group";
|
|
223
|
+
const harness = ExtensionHarness.create();
|
|
224
|
+
registerTasksExtension(harness.api, new TaskListStore(null), null);
|
|
225
|
+
const manage = getTool(harness, "manage_tasks");
|
|
226
|
+
const ctxA = createContext({
|
|
227
|
+
cwd: "/tmp/workspace-a",
|
|
228
|
+
sessionId: "session-a",
|
|
229
|
+
});
|
|
230
|
+
const ctxB = createContext({
|
|
231
|
+
cwd: "/tmp/workspace-b",
|
|
232
|
+
sessionId: "session-b",
|
|
233
|
+
});
|
|
234
|
+
const groupA = buildSessionTaskGroupName("session-a", "/tmp/workspace-a");
|
|
235
|
+
const groupB = buildSessionTaskGroupName("session-b", "/tmp/workspace-b");
|
|
236
|
+
TEST_TASK_GROUPS.add(groupA);
|
|
237
|
+
TEST_TASK_GROUPS.add(groupB);
|
|
238
|
+
|
|
239
|
+
await harness.fireEvent("session_start", {}, ctxA);
|
|
240
|
+
expect(process.env.PI_TEAM_NAME).toBe(groupA);
|
|
241
|
+
await execManage(manage, { action: "add", task: "Task from session A" }, ctxA);
|
|
242
|
+
await execManage(manage, { action: "update", index: 1, status: "pending" }, ctxA);
|
|
243
|
+
expect(firstText(await execManage(manage, { action: "list" }, ctxA))).toContain(
|
|
244
|
+
"Task from session A"
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
await harness.fireEvent("session_switch", {}, ctxB);
|
|
248
|
+
expect(process.env.PI_TEAM_NAME).toBe(groupB);
|
|
249
|
+
expect(firstText(await execManage(manage, { action: "list" }, ctxB))).toBe("No tasks.");
|
|
250
|
+
await execManage(manage, { action: "add", task: "Task from session B" }, ctxB);
|
|
251
|
+
await execManage(manage, { action: "update", index: 1, status: "pending" }, ctxB);
|
|
252
|
+
|
|
253
|
+
await harness.fireEvent("session_switch", {}, ctxA);
|
|
254
|
+
const listA = firstText(await execManage(manage, { action: "list" }, ctxA));
|
|
255
|
+
expect(listA).toContain("Task from session A");
|
|
256
|
+
expect(listA).not.toContain("Task from session B");
|
|
257
|
+
});
|
|
258
|
+
|
|
208
259
|
it("injects active-task context before agent start and clears orphaned in-progress tasks on agent_end", async () => {
|
|
209
260
|
const harness = ExtensionHarness.create();
|
|
210
261
|
registerTasksExtension(harness.api, new TaskListStore(null), null);
|