@selesai/code 0.8.5 → 0.8.7
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 +28 -0
- package/dist/core/agent-session.js +13 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/provider-composer.js +17 -4
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/system-prompt.js +2 -8
- package/dist/core/system-prompt.test.js +6 -0
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/schema-prune.d.ts +16 -0
- package/dist/core/tools/schema-prune.js +39 -0
- package/dist/core/tools/schema-prune.test.d.ts +1 -0
- package/dist/core/tools/schema-prune.test.js +111 -0
- package/dist/defaults/models.json +5 -0
- package/dist/defaults/settings.json +1 -0
- package/dist/extensions/agent-browser.test.ts +178 -2
- package/dist/extensions/agent-browser.ts +2 -0
- package/dist/extensions/copy-turn.test.ts +229 -0
- package/dist/extensions/copy-turn.ts +11 -0
- package/dist/extensions/grep-app/index.test.ts +356 -1
- package/dist/extensions/grep-app/index.ts +6 -1
- package/dist/extensions/handoff-new.test.ts +351 -161
- package/dist/extensions/handoff-new.ts +3 -0
- package/dist/extensions/inline-skills.test.ts +93 -0
- package/dist/extensions/inline-skills.ts +3 -0
- package/dist/extensions/model-prompt-injector/config.json +10 -0
- package/dist/extensions/model-prompt-injector/index.test.ts +112 -0
- package/dist/extensions/model-prompt-injector/index.ts +151 -0
- package/dist/extensions/package.json +1 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +158 -90
- package/dist/extensions/pi-subagents/UPSTREAM-V0.50-MAPPING.md +172 -0
- package/dist/extensions/pi-subagents/agents/builder.md +5 -2
- package/dist/extensions/pi-subagents/agents/commentator.md +1 -1
- package/dist/extensions/pi-subagents/agents/oracle.md +7 -5
- package/dist/extensions/pi-subagents/agents/reviewer.md +2 -2
- package/dist/extensions/pi-subagents/agents/scout.md +1 -1
- package/dist/extensions/pi-subagents/agents/worker.md +1 -1
- package/dist/extensions/pi-subagents/docs/configuration.md +78 -11
- package/dist/extensions/pi-subagents/docs/extension-api.md +36 -0
- package/dist/extensions/pi-subagents/docs/missions.md +5 -3
- package/dist/extensions/pi-subagents/docs/models.md +1 -1
- package/dist/extensions/pi-subagents/docs/observability.md +42 -2
- package/dist/extensions/pi-subagents/docs/tool-reference.md +20 -3
- package/dist/extensions/pi-subagents/docs/workflows.md +4 -4
- package/dist/extensions/pi-subagents/install.mjs +2 -2
- package/dist/extensions/pi-subagents/package-lock.json +1470 -1472
- package/dist/extensions/pi-subagents/package.json +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +5 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +16 -15
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +5 -5
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +46 -26
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +37 -12
- package/dist/extensions/pi-subagents/src/api/external-runs.ts +174 -84
- package/dist/extensions/pi-subagents/src/api/preflight.ts +13 -7
- package/dist/extensions/pi-subagents/src/extension/config.ts +59 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +146 -23
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +34 -6
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +5 -1
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -30
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +10 -9
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +13 -8
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +16 -3
- package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -6
- package/dist/extensions/pi-subagents/src/inspectors/herdr/shell-command.ts +16 -0
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +5 -4
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +19 -42
- package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +3 -1
- package/dist/extensions/pi-subagents/src/missions/store.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +82 -25
- package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +71 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +73 -43
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +17 -6
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -6
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +277 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +11 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +11 -1
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +21 -6
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +437 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +224 -42
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +27 -7
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +76 -19
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +35 -26
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +108 -9
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +54 -28
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +27 -13
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +298 -33
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/async-dismiss-action.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +219 -15
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -4
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +4 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +368 -50
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +107 -1
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +39 -23
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +16 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +66 -62
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +376 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +15 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +1 -9
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +12 -0
- package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +95 -0
- package/dist/extensions/pi-subagents/src/shared/agent-stream-options.ts +5 -0
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +0 -4
- package/dist/extensions/pi-subagents/src/shared/display-text.ts +50 -0
- package/dist/extensions/pi-subagents/src/shared/node-executable.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +71 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +66 -4
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +34 -25
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +4 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +160 -45
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +1 -48
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +129 -17
- package/dist/extensions/pi-subagents/src/tui/render.ts +122 -44
- package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +2 -1
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +4 -3
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +10 -2
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +272 -76
- package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +28 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +68 -9
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +27 -1
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +49 -0
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +144 -0
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +369 -98
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +111 -78
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +12 -0
- package/dist/extensions/pi-subagents/test/support/node-command.ts +15 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +61 -0
- package/dist/extensions/pi-subagents/test/unit/agent-stream-options.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +76 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +162 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +209 -10
- package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/external-runs.test.ts +135 -42
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +252 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +192 -6
- package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +23 -4
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +56 -1
- package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +67 -3
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +25 -2
- package/dist/extensions/pi-subagents/test/unit/node-executable.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +348 -0
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +5 -2
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +6 -1
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +92 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +127 -17
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +247 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +107 -2
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +5 -8
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +456 -4
- package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +73 -0
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +16 -7
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +15 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +79 -15
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +12 -12
- package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +109 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +45 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +94 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +42 -2
- package/dist/extensions/ponytail/index.js +11 -0
- package/dist/extensions/ponytail/ponytail-config.cjs +2 -0
- package/dist/extensions/ponytail/ponytail-instructions.cjs +6 -0
- package/dist/extensions/ponytail/test/extension.test.js +274 -140
- package/dist/extensions/ponytail/test/helpers.test.js +280 -92
- package/dist/extensions/question/index.ts +33 -0
- package/dist/extensions/question/question-list.ts +28 -0
- package/dist/extensions/question/row-layout.ts +3 -0
- package/dist/extensions/question/tests/batch.test.ts +103 -65
- package/dist/extensions/question/tests/exp.test.ts +70 -0
- package/dist/extensions/question/tests/exp2.test.ts +59 -0
- package/dist/extensions/question/tests/exp3.test.ts +47 -0
- package/dist/extensions/question/tests/helpers.test.ts +75 -35
- package/dist/extensions/question/tests/question-list.test.ts +640 -198
- package/dist/extensions/question/tests/row-layout.test.ts +193 -114
- package/dist/extensions/question/tests/schemas.test.ts +42 -19
- package/dist/extensions/question/tests/selection-mode.test.ts +54 -0
- package/dist/extensions/question/tests/shortcuts.test.ts +106 -84
- package/dist/extensions/question/tests/wizard.test.ts +771 -50
- package/dist/extensions/question/tests/zz-ig3.test.ts +20 -0
- package/dist/extensions/question/tests/zz-probe.test.ts +29 -0
- package/dist/extensions/rtk.test.ts +180 -1
- package/dist/extensions/tokenin-onboarding.ts +3 -0
- package/dist/extensions/undo.test.ts +720 -0
- package/dist/extensions/undo.ts +6 -0
- package/dist/extensions/web-agent-onboarding.test.ts +415 -0
- package/dist/extensions/workflow/extension.ts +3 -3
- package/dist/extensions/workflow/modes.ts +41 -19
- package/dist/skills/pi-subagents/SKILL.md +1 -1
- package/dist/skills/pi-subagents/references/constraints-and-recipes.md +5 -4
- package/dist/skills/pi-subagents/references/execution-controls.md +16 -15
- package/dist/skills/pi-subagents/references/management-authoring-rpc.md +5 -5
- package/dist/skills/pi-subagents/references/prompting-and-roles.md +46 -26
- package/docs/plans/workflow-autoloop-reference.md +1 -2
- package/docs/plans/workflow-handoff-carryover.md +108 -0
- package/docs/settings.md +6 -0
- package/package.json +4 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_MAX_WORKFLOW_AUTO_RELAUNCHES,
|
|
5
|
+
resolveAutoRelaunchDecision,
|
|
6
|
+
resolveMaxWorkflowAutoRelaunches,
|
|
7
|
+
} from "../../src/workflows/workflow-auto-relaunch.ts";
|
|
8
|
+
|
|
9
|
+
describe("workflow auto-relaunch policy", () => {
|
|
10
|
+
it("relaunches on a budget result while under the cap", () => {
|
|
11
|
+
const decision = resolveAutoRelaunchDecision({ result: "budget", rounds: 3 }, 2, 12);
|
|
12
|
+
assert.deepEqual(decision, { relaunch: true, capped: false });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("does not relaunch a clean result", () => {
|
|
16
|
+
const decision = resolveAutoRelaunchDecision({ result: "clean", rounds: 3 }, 0, 12);
|
|
17
|
+
assert.deepEqual(decision, { relaunch: false, capped: false });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("does not relaunch non-workflow values", () => {
|
|
21
|
+
for (const value of [undefined, null, 5, "budget", ["budget"], { result: "failed" }]) {
|
|
22
|
+
const decision = resolveAutoRelaunchDecision(value, 0, 12);
|
|
23
|
+
assert.deepEqual(decision, { relaunch: false, capped: false });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("marks the cap as reached when the relaunch count equals the cap", () => {
|
|
28
|
+
const decision = resolveAutoRelaunchDecision({ result: "budget" }, 12, 12);
|
|
29
|
+
assert.deepEqual(decision, { relaunch: false, capped: true });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("relaunches indefinitely when the cap is unlimited", () => {
|
|
33
|
+
const decision = resolveAutoRelaunchDecision({ result: "budget" }, 50, undefined);
|
|
34
|
+
assert.deepEqual(decision, { relaunch: true, capped: false });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("resolves the configured cap with a safe default and 0 as unlimited", () => {
|
|
38
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches(undefined), DEFAULT_MAX_WORKFLOW_AUTO_RELAUNCHES);
|
|
39
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches(5), 5);
|
|
40
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches(0), undefined);
|
|
41
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches(-3), DEFAULT_MAX_WORKFLOW_AUTO_RELAUNCHES);
|
|
42
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches("12"), DEFAULT_MAX_WORKFLOW_AUTO_RELAUNCHES);
|
|
43
|
+
assert.equal(resolveMaxWorkflowAutoRelaunches(2.5), DEFAULT_MAX_WORKFLOW_AUTO_RELAUNCHES);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -4,7 +4,7 @@ import * as fs from "node:fs";
|
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { describe, it } from "node:test";
|
|
7
|
-
import { isSameGitRepository, resolveWorkflowChatProgress } from "../../src/workflows/chat-progress.ts";
|
|
7
|
+
import { buildWorkflowChatProgressRows, isSameGitRepository, resolveWorkflowChatProgress } from "../../src/workflows/chat-progress.ts";
|
|
8
8
|
import { renderSubagentResult } from "../../src/tui/render.ts";
|
|
9
9
|
import { bindMissionWorkflowChildAsyncLaunch, createSubagentExecutor, foregroundResultIntercomStatus, missionWorkflowChildStatus, runMissionWorkflowChild, shouldSuppressRoutineResultIntercom } from "../../src/runs/foreground/subagent-executor.ts";
|
|
10
10
|
import { readMissionBinding } from "../../src/missions/lifecycle.ts";
|
|
@@ -202,6 +202,38 @@ describe("workflow chat progress rendering", () => {
|
|
|
202
202
|
}
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
+
it("warns once when a workflow child outlives its mission record", async () => {
|
|
206
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-workflow-missing-mission-"));
|
|
207
|
+
const originalWarn = console.warn;
|
|
208
|
+
const warnings: string[] = [];
|
|
209
|
+
try {
|
|
210
|
+
const location = {
|
|
211
|
+
projectRoot: root,
|
|
212
|
+
missionDir: path.join(root, ".pi/subagents", "missions"),
|
|
213
|
+
globalIndexDir: path.join(root, ".pi/subagents", "mission-index"),
|
|
214
|
+
writeGlobalIndex: false,
|
|
215
|
+
};
|
|
216
|
+
const mission = createMission(location, { title: "Workflow", objective: "Track child" });
|
|
217
|
+
fs.rmSync(path.join(location.missionDir, `${mission.id}.json`));
|
|
218
|
+
console.warn = (...args: unknown[]) => warnings.push(args.map(String).join(" "));
|
|
219
|
+
|
|
220
|
+
for (const key of ["first", "second"]) {
|
|
221
|
+
await assert.rejects(
|
|
222
|
+
() => runMissionWorkflowChild({ missionId: mission.id, location, autoCreated: false }, "wf-missing-mission", key, "Prep", async () => {
|
|
223
|
+
throw new Error("child failed");
|
|
224
|
+
}),
|
|
225
|
+
/child failed/,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
assert.equal(warnings.length, 1);
|
|
230
|
+
assert.match(warnings[0] ?? "", new RegExp(`Mission '${mission.id}' is no longer in the mission store`));
|
|
231
|
+
} finally {
|
|
232
|
+
console.warn = originalWarn;
|
|
233
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
205
237
|
it("renders stable rows keyed by workflow trace entries", () => {
|
|
206
238
|
const text = componentText(renderSubagentResult({
|
|
207
239
|
content: [{ type: "text", text: "Workflow running." }],
|
|
@@ -215,6 +247,7 @@ describe("workflow chat progress rendering", () => {
|
|
|
215
247
|
{ operation: "run", key: "scout", state: "completed", runId: "run-scout", phase: "Validation", label: "Found renderer seam", durationMs: 12 },
|
|
216
248
|
{ operation: "run", key: "tests", state: "started", phase: "Validation", label: "focused integration suite" },
|
|
217
249
|
{ operation: "run", key: "review", state: "failed", phase: "Validation", label: "fresh-context UX review", error: "needs fixes" },
|
|
250
|
+
{ operation: "run", key: "stale", state: "stopped", phase: "Validation", label: "superseded exact-head review", error: "Workflow stopped by user." },
|
|
218
251
|
],
|
|
219
252
|
emits: [],
|
|
220
253
|
console: [],
|
|
@@ -228,6 +261,66 @@ describe("workflow chat progress rendering", () => {
|
|
|
228
261
|
assert.match(text, /complete\s+scout Found renderer seam/);
|
|
229
262
|
assert.match(text, /running\s+tests focused integration suite/);
|
|
230
263
|
assert.match(text, /failed\s+review fresh-context UX review .* needs fixes/);
|
|
264
|
+
assert.match(text, /stopped\s+stale superseded exact-head review .* Workflow stopped by user/);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("renders detached workflow trace rows as paused attention", () => {
|
|
268
|
+
const trace: NonNullable<Details["workflow"]>["trace"] = [{
|
|
269
|
+
operation: "run",
|
|
270
|
+
key: "detaches",
|
|
271
|
+
state: "detached",
|
|
272
|
+
phase: "Decision",
|
|
273
|
+
label: "supervisor handoff",
|
|
274
|
+
error: "Detached for intercom coordination. Reply to the supervisor request first.",
|
|
275
|
+
}];
|
|
276
|
+
const rows = buildWorkflowChatProgressRows(trace);
|
|
277
|
+
assert.equal(rows[0]?.state, "detached");
|
|
278
|
+
|
|
279
|
+
const text = componentText(renderSubagentResult({
|
|
280
|
+
content: [{ type: "text", text: "Workflow paused." }],
|
|
281
|
+
details: {
|
|
282
|
+
mode: "workflow",
|
|
283
|
+
runId: "wf_detached",
|
|
284
|
+
results: [],
|
|
285
|
+
chatProgress: { mode: "live-card", repoRelation: "same", repoLabel: "pi-subagents" },
|
|
286
|
+
workflow: { trace, emits: [], console: [] },
|
|
287
|
+
},
|
|
288
|
+
}, { expanded: false }, theme as any));
|
|
289
|
+
|
|
290
|
+
assert.match(text, /workflow wf_detached .* same repo .* paused/);
|
|
291
|
+
assert.match(text, /Phase Decision/);
|
|
292
|
+
assert.match(text, /detached\s+detaches supervisor handoff .* Detached for intercom coordination/);
|
|
293
|
+
assert.doesNotMatch(text, /running\s+detaches/);
|
|
294
|
+
assert.doesNotMatch(text, /failed\s+detaches/);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("applies main-window density settings to collapsed workflow live cards", () => {
|
|
298
|
+
const trace = Array.from({ length: 10 }, (_, index) => ({
|
|
299
|
+
operation: "run" as const,
|
|
300
|
+
key: `step-${index}`,
|
|
301
|
+
state: "started" as const,
|
|
302
|
+
label: `review ${index}`,
|
|
303
|
+
}));
|
|
304
|
+
const result = {
|
|
305
|
+
content: [{ type: "text" as const, text: "Workflow running." }],
|
|
306
|
+
details: {
|
|
307
|
+
mode: "workflow" as const,
|
|
308
|
+
runId: "wf_density",
|
|
309
|
+
results: [],
|
|
310
|
+
chatProgress: { mode: "live-card" as const, repoRelation: "same" as const, repoLabel: "pi-subagents" },
|
|
311
|
+
workflow: { trace, emits: [], console: [] },
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const compact = renderSubagentResult(result, { expanded: false }, theme as any, undefined, { horizontalSpacing: 0, compactResultMaxLines: 3 }).render(120);
|
|
316
|
+
assert.equal(compact.length, 3);
|
|
317
|
+
assert.match(compact[1]!, /^Repo pi-subagents\s*$/);
|
|
318
|
+
assert.match(compact[2]!, /rows hidden/);
|
|
319
|
+
|
|
320
|
+
const expanded = renderSubagentResult(result, { expanded: true }, theme as any, undefined, { horizontalSpacing: 0, compactResultMaxLines: 3 }).render(120);
|
|
321
|
+
assert.ok(expanded.length > 3);
|
|
322
|
+
assert.match(expanded[1]!, /^ Repo pi-subagents\s*$/);
|
|
323
|
+
assert.doesNotMatch(expanded.join("\n"), /rows hidden · .* expands/);
|
|
231
324
|
});
|
|
232
325
|
|
|
233
326
|
it("bounds workflow live-card rows and keeps old failed children visible", () => {
|
|
@@ -39,6 +39,26 @@ describe("workflow launch params", () => {
|
|
|
39
39
|
);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
it("keeps a bridge override scoped to the target workflow child", () => {
|
|
43
|
+
assert.deepEqual(
|
|
44
|
+
prepareWorkflowLaunchParams(
|
|
45
|
+
{},
|
|
46
|
+
{ agent: "worker", task: "Run", intercomBridge: { mode: "off" } },
|
|
47
|
+
"workflow-run",
|
|
48
|
+
"isolated",
|
|
49
|
+
),
|
|
50
|
+
{
|
|
51
|
+
agent: "worker",
|
|
52
|
+
task: "Run",
|
|
53
|
+
intercomBridge: { mode: "off" },
|
|
54
|
+
async: false,
|
|
55
|
+
workflowParentRunId: "workflow-run",
|
|
56
|
+
workflowKey: "isolated",
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
assert.equal(prepareWorkflowLaunchParams({}, { agent: "worker", task: "Run" }, "workflow-run", "sibling").intercomBridge, undefined);
|
|
60
|
+
});
|
|
61
|
+
|
|
42
62
|
it("places workflow child gates inside managed worktree tasks", () => {
|
|
43
63
|
assert.deepEqual(
|
|
44
64
|
prepareWorkflowLaunchParams(
|
|
@@ -61,6 +81,25 @@ describe("workflow launch params", () => {
|
|
|
61
81
|
);
|
|
62
82
|
});
|
|
63
83
|
|
|
84
|
+
it("preserves a bridge override for retained workflow children", () => {
|
|
85
|
+
assert.deepEqual(
|
|
86
|
+
prepareWorkflowLaunchParams(
|
|
87
|
+
{},
|
|
88
|
+
{ resume: "retained-run", task: "Continue", intercomBridge: { mode: "off" } },
|
|
89
|
+
"workflow-run",
|
|
90
|
+
"continue",
|
|
91
|
+
),
|
|
92
|
+
{
|
|
93
|
+
action: "resume",
|
|
94
|
+
id: "retained-run",
|
|
95
|
+
message: "Continue",
|
|
96
|
+
workflowParentRunId: "workflow-run",
|
|
97
|
+
workflowKey: "continue",
|
|
98
|
+
intercomBridge: { mode: "off" },
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
64
103
|
it("rejects gate defaults on retained resume items", () => {
|
|
65
104
|
assert.throws(
|
|
66
105
|
() => prepareWorkflowLaunchParams(
|
|
@@ -82,7 +121,7 @@ describe("workflow launch params", () => {
|
|
|
82
121
|
);
|
|
83
122
|
});
|
|
84
123
|
|
|
85
|
-
it("preserves execution limits when routing retained resume items", () => {
|
|
124
|
+
it("preserves execution limits and fan-out identity when routing retained resume items", () => {
|
|
86
125
|
assert.deepEqual(
|
|
87
126
|
prepareWorkflowLaunchParams(
|
|
88
127
|
{ turnBudget: { maxTurns: 8 }, toolBudget: { hard: 12, block: ["read"] } },
|
|
@@ -95,7 +134,7 @@ describe("workflow launch params", () => {
|
|
|
95
134
|
},
|
|
96
135
|
"workflow-run",
|
|
97
136
|
"continue",
|
|
98
|
-
{ missionDetached: true },
|
|
137
|
+
{ missionDetached: true, runFanoutBudget: { version: 1, rootRunId: "root-run", directory: "/tmp/fanout", limit: 64, parentPath: "parent" } },
|
|
99
138
|
),
|
|
100
139
|
{
|
|
101
140
|
action: "resume",
|
|
@@ -103,6 +142,7 @@ describe("workflow launch params", () => {
|
|
|
103
142
|
message: "Continue carefully",
|
|
104
143
|
workflowParentRunId: "workflow-run",
|
|
105
144
|
workflowKey: "continue",
|
|
145
|
+
runFanoutBudget: { version: 1, rootRunId: "root-run", directory: "/tmp/fanout", limit: 64, parentPath: "parent/workflow[continue]" },
|
|
106
146
|
mission: false,
|
|
107
147
|
timeoutMs: 5_000,
|
|
108
148
|
turnBudget: { maxTurns: 3, graceTurns: 1 },
|
|
@@ -16,6 +16,9 @@ export { filterSkillBodyForMode };
|
|
|
16
16
|
export const readDefaultMode = getDefaultMode;
|
|
17
17
|
|
|
18
18
|
export function resolveSessionMode(entries, fallbackMode = DEFAULT_MODE) {
|
|
19
|
+
// Unreachable: normalizePersistedMode always returns a valid mode or null,
|
|
20
|
+
// and the caller passes a valid default.
|
|
21
|
+
/* v8 ignore next 1 */
|
|
19
22
|
const fallback = normalizePersistedMode(fallbackMode) || DEFAULT_MODE;
|
|
20
23
|
if (!Array.isArray(entries)) return fallback;
|
|
21
24
|
|
|
@@ -59,6 +62,9 @@ export default function ponytailExtension(pi) {
|
|
|
59
62
|
|
|
60
63
|
const setMode = (mode, ctx) => {
|
|
61
64
|
const normalized = normalizePersistedMode(mode);
|
|
65
|
+
// Unreachable: setMode is only called with validated modes from the
|
|
66
|
+
// command handler and the deactivation input handler.
|
|
67
|
+
/* v8 ignore next 1 */
|
|
62
68
|
if (!normalized) return;
|
|
63
69
|
|
|
64
70
|
currentMode = normalized;
|
|
@@ -68,6 +74,8 @@ export default function ponytailExtension(pi) {
|
|
|
68
74
|
|
|
69
75
|
const sendAlias = (skillName, args, ctx) => {
|
|
70
76
|
const normalized = String(args || "").trim();
|
|
77
|
+
// Unreachable: the alias command handlers always pass empty args.
|
|
78
|
+
/* v8 ignore next 1 */
|
|
71
79
|
const message = normalized ? `${skillName} ${normalized}` : skillName;
|
|
72
80
|
|
|
73
81
|
if (ctx?.isIdle?.() === false) {
|
|
@@ -91,6 +99,9 @@ export default function ponytailExtension(pi) {
|
|
|
91
99
|
|
|
92
100
|
if (parsed.type === "set-default") {
|
|
93
101
|
const written = writeDefaultMode(parsed.mode);
|
|
102
|
+
// Unreachable: parsePonytailCommand only returns set-default for
|
|
103
|
+
// valid config modes, so writeDefaultMode always succeeds.
|
|
104
|
+
/* v8 ignore next 1 */
|
|
94
105
|
if (written) {
|
|
95
106
|
configuredDefaultMode = getDefaultMode();
|
|
96
107
|
const message = configuredDefaultMode === written
|
|
@@ -57,6 +57,8 @@ function getConfigDir() {
|
|
|
57
57
|
}
|
|
58
58
|
if (process.platform === 'win32') {
|
|
59
59
|
return path.join(
|
|
60
|
+
// Unreachable: APPDATA is always set on Windows.
|
|
61
|
+
/* v8 ignore next 1 */
|
|
60
62
|
process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'),
|
|
61
63
|
'ponytail'
|
|
62
64
|
);
|
|
@@ -14,6 +14,9 @@ const COMPACT_MODE_RULES = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
function filterSkillBodyForMode(body, mode) {
|
|
17
|
+
// Unreachable: normalizeMode returns a valid mode or null, and the caller
|
|
18
|
+
// passes a valid mode.
|
|
19
|
+
/* v8 ignore next 1 */
|
|
17
20
|
const effectiveMode = normalizeMode(mode) || DEFAULT_MODE;
|
|
18
21
|
const withoutFrontmatter = String(body || '').replace(/^---[\s\S]*?---\s*/, '');
|
|
19
22
|
|
|
@@ -90,6 +93,9 @@ function getPonytailInstructions(mode, options) {
|
|
|
90
93
|
return 'PONYTAIL MODE ACTIVE — level: ' + configuredMode + '. Behavior defined by /ponytail-' + configuredMode + ' skill.';
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
// Unreachable: normalizePersistedMode above already falls back to
|
|
97
|
+
// DEFAULT_MODE, so normalizeMode always returns a valid mode here.
|
|
98
|
+
/* v8 ignore next 1 */
|
|
93
99
|
const effectiveMode = normalizeMode(configuredMode) || DEFAULT_MODE;
|
|
94
100
|
if (options?.compact === true) return getCompactInstructions(effectiveMode);
|
|
95
101
|
|