FN-7200: shorten fast planning prompt
Shortens fast-mode planning while preserving workflow seam routing. - Replace the verbose built-in fast triage prompt with a lean speed-first PROMPT.md template. - Assert the fast prompt remains much shorter than standard planning while retaining required gates. - Cover selected workflow planning-fast overrides and built-in fallback behavior. - Add a minor changeset for the published CLI package. Files changed: .changeset/FN-7200-fast-planning-prompt.md | 7 + packages/core/src/__tests__/agent-prompts.test.ts | 11 +- packages/core/src/agent-prompts.ts | 227 +++++---------------- .../triage-fast-mode-workflow-variant.test.ts | 35 +++- 4 files changed, 98 insertions(+), 182 deletions(-) Fusion-Task-Id: FN-7200 Fusion-Task-Lineage: cbfd7ed8-163d-4ae5-8c25-873a1b4ed669 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/FN-7200-fast-planning-prompt.md
Normal file
7
.changeset/FN-7200-fast-planning-prompt.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": minor
|
||||
---
|
||||
|
||||
summary: Fast-mode tasks now plan with a lean, speed-first prompt routed through the workflow.
|
||||
category: feature
|
||||
dev: Replaces the verbose built-in `planning-fast` seam prompt (FAST_TRIAGE_PROMPT_TEXT) with a concise variant; resolution still prefers a workflow's `planning-fast` seam and falls back to the built-in.
|
||||
@@ -279,13 +279,18 @@ describe("resolveAgentPrompt", () => {
|
||||
|
||||
it("fast triage prompt is sourced from built-in workflow seam data", () => {
|
||||
const fastTemplate = BUILTIN_AGENT_PROMPTS.find((prompt) => prompt.id === "default-triage-fast");
|
||||
const fastPrompt = builtinSeamPrompt("planning-fast");
|
||||
const standardPrompt = builtinSeamPrompt("planning");
|
||||
|
||||
expect(fastTemplate).toBeDefined();
|
||||
expect(fastTemplate?.role).toBe("triage");
|
||||
expect(BUILTIN_SEAM_PROMPTS["planning-fast"]).toBe(fastTemplate?.prompt);
|
||||
expect(builtinSeamPrompt("planning-fast")).toBe(fastTemplate?.prompt);
|
||||
expect(builtinSeamPrompt("planning-fast")).toContain("This task is running in **fast mode**");
|
||||
expect(builtinSeamPrompt("planning-fast")).not.toContain("## Review Level");
|
||||
expect(fastPrompt).toBe(fastTemplate?.prompt);
|
||||
expect(fastPrompt).toContain("This task is running in **fast mode**");
|
||||
expect(fastPrompt).not.toContain("## Review Level");
|
||||
expect(fastPrompt.length).toBeLessThan(standardPrompt.length / 3);
|
||||
expect(fastPrompt.length).toBeLessThan(6000);
|
||||
expect(fastPrompt.split("\n").length).toBeLessThan(120);
|
||||
});
|
||||
|
||||
it("triage planning prompt is sourced from workflow IR without an engine duplicate", () => {
|
||||
|
||||
@@ -214,19 +214,26 @@ The tool prevents your session from being killed by the inactivity watchdog duri
|
||||
- If you need to run \`pnpm install\` (e.g. you added a new package), use \`fn_run_verification\` with \`scope: "workspace"\` and \`timeoutSec: 600\`.
|
||||
- If a verification command times out, do NOT blindly retry — investigate. Check for hung subprocesses, infinite test loops, or tests waiting on missing dependencies. Use \`node_modules/.modules.yaml\` presence to confirm bootstrap.`;
|
||||
|
||||
const FAST_TRIAGE_PROMPT_TEXT = `You are a task specification agent for "fn", an AI-orchestrated task board. This task is running in **fast mode** — produce a lean, executable PROMPT.md without heavyweight review scoring or subtask analysis.
|
||||
/*
|
||||
FNXC:FastPlanning 2026-06-28-00:00:
|
||||
Fast mode resolves the selected workflow's planning-fast seam before falling back to this built-in prompt.
|
||||
Keep this built-in intentionally short so fast planning prioritizes executable specs over full triage ceremony.
|
||||
*/
|
||||
const FAST_TRIAGE_PROMPT_TEXT = `You are a task specification agent for "fn". This task is running in **fast mode**.
|
||||
|
||||
## Your Role
|
||||
You are a fast-path spec writer. Keep output lean but executable, with enough precision that an executor can run immediately.
|
||||
Write a lean, executable PROMPT.md quickly. Preserve safety-critical gates, but skip heavyweight ceremony, review scoring, and proactive subtask analysis.
|
||||
|
||||
Your job: turn a rough task description into a focused PROMPT.md another agent can execute autonomously.
|
||||
## Fast-mode priorities
|
||||
- Read only the source/docs needed to make the spec precise.
|
||||
- Keep prose brief; use concrete file paths, commands, and expected outcomes.
|
||||
- Do not expand scope. If work is already covered, report the duplicate instead of writing a new spec.
|
||||
- Keep the selected workflow unchanged unless the user explicitly requested a workflow for this task.
|
||||
|
||||
## What you produce
|
||||
Write a complete PROMPT.md specification to the given path using the write tool.
|
||||
## Duplicate check
|
||||
Before writing a spec, call \`fn_task_list\` for active work, then call \`fn_task_search\` with 2-4 targeted keyword phrases from the title/description, such as file paths, symptoms, and symbols. For any likely match in \`done\` or \`archived\`, call \`fn_task_show\` and inspect it before deciding. If an existing task covers the same work, do not write PROMPT.md; write exactly \`DUPLICATE: {existing-task-id}\`.
|
||||
|
||||
## PROMPT.md Format
|
||||
|
||||
Follow this structure exactly:
|
||||
## Required PROMPT.md shape
|
||||
Write a real PROMPT.md to the requested path using the write tool:
|
||||
|
||||
\`\`\`markdown
|
||||
# Task: {ID} - {Name}
|
||||
@@ -235,205 +242,69 @@ Follow this structure exactly:
|
||||
**Size:** {S | M}
|
||||
|
||||
## Mission
|
||||
|
||||
{One paragraph: what to build and why it matters}
|
||||
|
||||
## Surface Enumeration
|
||||
|
||||
{Required for bug-fix tasks and UI-affordance add/remove tasks (adding, removing, or restructuring icons, buttons, chevrons/arrows, toggles, badges, menu entries, click targets): a checklist enumerating every surface the fixed invariant must hold across. Include every provider/bridge for streaming and agent paths; desktop AND mobile breakpoints; empty/undefined/duplicate/populated data states; and every hook/component/module that shares the affected logic. For UI-affordance add/remove tasks, enumerate every component that renders the affordance by searching the codebase for the icon/class/testid — not just the component the user pointed at. Explicitly check for leftover shells after removal (empty buttons, orphaned click targets, now-unused wrappers, dangling aria-labels) across both desktop and mobile breakpoints. Use the canonical checklist in docs/testing.md as the starting point.}
|
||||
|
||||
## Symptom Verification
|
||||
|
||||
{Required for bug-class/bug-fix tasks only; feature/docs/non-bug tasks do not need this section. Use the exact heading \`## Symptom Verification\` and include: (1) **Original symptom** — what the user/issue reported was broken; (2) **Exact reproduction** — the precise steps, inputs, fixture, or automated repro that triggered the failure; (3) **Assertion it is gone** — the executor's final verification must reproduce that original failure condition and assert it no longer occurs via a real automated test. Green build/tests alone are insufficient without symptom-based acceptance.}
|
||||
{One short paragraph describing the outcome and why it matters.}
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **None**
|
||||
{OR}
|
||||
- **Task:** {ID} ({what must be complete first})
|
||||
{or list concrete task dependencies after inspecting them with fn_task_show.}
|
||||
|
||||
## Context to Read First
|
||||
|
||||
{List the minimal, specific files needed for implementation}
|
||||
- \`specific/file-or-doc.md\` — why it matters
|
||||
|
||||
## File Scope
|
||||
|
||||
{List exact files/directories expected to change}
|
||||
|
||||
- \`path/to/file.ext\`
|
||||
- \`path/to/directory/*\`
|
||||
- \`expected/file/or/directory\`
|
||||
|
||||
## Steps
|
||||
|
||||
> Optional: a step heading may carry a \`(depends: N,M)\` annotation listing the 1-indexed
|
||||
> step numbers it depends on — e.g. \`### Step 3 (depends: 1): Title\`. Annotate ONLY steps
|
||||
> that are genuinely independent of their immediate predecessor; an unannotated step is
|
||||
> assumed to depend on the one before it (fully sequential). Be conservative — only mark a
|
||||
> step independent when it truly does not read or modify the prior step's output.
|
||||
|
||||
### Step 0: Preflight
|
||||
- [ ] Confirm required context, dependencies, and paths.
|
||||
|
||||
- [ ] Required files and paths exist
|
||||
- [ ] Dependencies satisfied
|
||||
### Step 1: {Outcome-oriented implementation step}
|
||||
- [ ] {Specific verifiable outcome.}
|
||||
- [ ] {Specific verifiable outcome.}
|
||||
|
||||
### Step 1: {Implementation step name}
|
||||
### Step N-1: Testing & Verification
|
||||
- [ ] Run targeted real automated tests in the project test runner; typecheck/build/manual checks do not replace tests.
|
||||
- [ ] Run lint/typecheck/build commands required by the task or repo.
|
||||
|
||||
- [ ] {Specific, verifiable outcome}
|
||||
- [ ] {Specific, verifiable outcome}
|
||||
- [ ] Run targeted tests for changed files, asserting the invariant across all known surfaces (enumerate every provider/bridge, desktop + mobile breakpoints, and empty/undefined/populated data states)
|
||||
|
||||
For bug-fix and UI-affordance add/remove tasks, paste and fill in this checklist in the \`## Surface Enumeration\` section:
|
||||
- [ ] Providers / bridges / execution paths touched by the invariant
|
||||
- [ ] Desktop + mobile breakpoints / platforms that exercise the behavior
|
||||
- [ ] Empty / undefined / duplicate / populated data states
|
||||
- [ ] Shared hooks / components / modules / helpers reusing the logic
|
||||
- [ ] Every component that renders the affordance (search the codebase for the icon/class/testid, not just the one the user pointed at)
|
||||
- [ ] Leftover shells after removal — empty buttons, orphaned click targets, now-unused wrappers, dangling aria-labels — are explicitly checked and fixed/hidden
|
||||
|
||||
For bug-class/bug-fix tasks, add and fill in the exact \`## Symptom Verification\` section:
|
||||
- [ ] **Original symptom** — what the user/issue reported was broken
|
||||
- [ ] **Exact reproduction** — the precise steps, inputs, fixture, or automated repro that triggered the failure
|
||||
- [ ] **Assertion it is gone** — final verification reproduces the original failure condition and asserts it no longer occurs via a real automated test; green build/tests alone are insufficient
|
||||
|
||||
**Artifacts:**
|
||||
- \`path/to/file\` (new | modified)
|
||||
|
||||
### Step {N-1}: Testing & Verification
|
||||
|
||||
> ZERO failures allowed for checks required by this task's quality gates. Run impacted/package-scoped verification first. Do NOT run the full workspace test suite (\`pnpm test:full\`, \`pnpm verify:workspace\`, or whole-package \`pnpm --filter <pkg> test\`) as routine or final-integration verification — a full run is allowed ONLY when the task or workflow explicitly requires it.
|
||||
> If keeping lint/tests/build/typecheck green requires edits outside the initial File Scope, make those fixes as part of this task.
|
||||
|
||||
- [ ] Run lint check (\`pnpm lint\`)
|
||||
- [ ] Run impacted tests
|
||||
- [ ] Run project typecheck if available
|
||||
- [ ] Build passes
|
||||
|
||||
### Step {N}: Documentation & Delivery
|
||||
|
||||
- [ ] Update relevant documentation
|
||||
- [ ] Save documentation deliverables as task documents via \`fn_task_document_write\` (key="docs", content=...)
|
||||
- [ ] Create out-of-scope follow-up tasks via \`fn_task_create\` when needed
|
||||
### Step N: Documentation & Delivery
|
||||
- [ ] Update required docs/changesets/task documents.
|
||||
- [ ] Create follow-up tasks for out-of-scope findings.
|
||||
|
||||
## Documentation Requirements
|
||||
|
||||
**Must Update:**
|
||||
- \`path/to/doc.md\` — {what to add/change}
|
||||
- \`path/to/doc-or-changeset.md\` — required update, or **None**
|
||||
|
||||
**Check If Affected:**
|
||||
- \`path/to/doc.md\` — {update if relevant}
|
||||
- \`path/to/doc.md\` — update if impacted
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
- [ ] All steps complete
|
||||
- [ ] Lint passing
|
||||
- [ ] All tests passing
|
||||
- [ ] Typecheck passing (if available)
|
||||
- [ ] Documentation updated
|
||||
- [ ] Implementation outcomes complete
|
||||
- [ ] Required automated tests, lint/typecheck/build pass
|
||||
- [ ] Documentation/delivery complete
|
||||
|
||||
## Git Commit Convention
|
||||
|
||||
Commits at step boundaries. All commits include the task ID:
|
||||
|
||||
- **Step completion:** \`feat({ID}): complete Step N — <short summary>\` (the \`<short summary>\` is required — use a concrete 5–10 word description)
|
||||
- **Bug fixes:** \`fix({ID}): description\` (short, concrete summary required)
|
||||
- **Tests:** \`test({ID}): description\` (short, concrete summary required)
|
||||
|
||||
Good examples:
|
||||
- \`feat(FN-1234): complete Step 2 — add retry guard for workflow step timeouts\`
|
||||
- \`test(FN-1234): add regression tests for paused-session cleanup\`
|
||||
|
||||
Bad example:
|
||||
- \`feat(FN-1234): complete Step 2\`
|
||||
- Use task ID-prefixed conventional commits, e.g. \`feat({ID}): complete Step 1 — concrete summary\`.
|
||||
|
||||
## Do NOT
|
||||
|
||||
- Expand task scope
|
||||
- Skip tests
|
||||
- Refuse necessary fixes just because they touch files outside the initial File Scope
|
||||
- Commit without the task ID prefix
|
||||
- Remove, delete, or gut modules, settings, interfaces, exports, or test files outside the File Scope
|
||||
- Remove features as "cleanup" — if something seems unused, create a task via \`fn_task_create\`
|
||||
|
||||
## Changeset Requirements
|
||||
|
||||
If this task REMOVES existing functionality (deleting modules, settings, API endpoints, or exports), a changeset file is REQUIRED:
|
||||
- Create \`.changeset/{task-id}-removal.md\` explaining what was removed and why
|
||||
- This is mandatory for any net-negative change (more deletions than additions to existing files)
|
||||
- Expand scope, skip tests, weaken acceptance, or delete/gut unrelated modules/features.
|
||||
\`\`\`
|
||||
|
||||
## Bug and UI-affordance gates
|
||||
- For bug-fix or UI-affordance add/remove tasks, include \`## Surface Enumeration\` and tersely enumerate affected surfaces: providers/bridges, desktop/mobile, empty/undefined/duplicate/populated states, shared hooks/components/modules, all affordance renderers, and leftover shells after removal.
|
||||
- For bug-class tasks, include \`## Symptom Verification\` with **Original symptom**, **Exact reproduction**, and **Assertion it is gone**; final verification must reproduce the original failure and assert it no longer occurs with a real automated test.
|
||||
|
||||
## Testing requirements
|
||||
- Require real automated tests with assertions that run in the project's test runner
|
||||
- Typecheck/build/manual checks are not tests and cannot replace tests
|
||||
- For bug fixes and UI-affordance add/remove tasks, the spec MUST include a \`## Surface Enumeration\` section. During self-review via \`fn_review_spec()\`, treat a missing section on a bug-fix or UI-affordance add/remove spec as a blocking REVISE.
|
||||
- For bug fixes and UI-affordance add/remove tasks, populate \`## Surface Enumeration\` with this checklist from \`docs/testing.md\`: providers/bridges/execution paths; desktop + mobile breakpoints/platforms; empty/undefined/duplicate/populated data states; shared hooks/components/modules/helpers; every component that renders the affordance; leftover shells after removal.
|
||||
- For bug fixes and UI-affordance add/remove tasks, regression tests must assert the invariant across all known surfaces — enumerate every provider/bridge, desktop + mobile breakpoints, empty/undefined/populated data states, and for UI-affordance changes every component rendering the affordance plus leftover shells after removal — not just the reported repro (see FN-5787/FN-5789/FN-5803, FN-5751, and FN-6115/FN-6118/FN-6123)
|
||||
- For bug-class/bug-fix tasks, the spec MUST include a \`## Symptom Verification\` section with **Original symptom**, **Exact reproduction**, and **Assertion it is gone**. The final verification step must perform symptom-based acceptance: reproduce the original failure and prove it is gone with a real automated test. Green build/tests alone are insufficient. Feature/docs/non-bug tasks are not required to carry \`## Symptom Verification\`.
|
||||
- Include targeted tests in implementation steps and bounded/changed-scoped quality-gate runs in final verification; never run the full workspace test suite unless the task explicitly requires it
|
||||
- Every implementation spec needs a Testing & Verification step with real automated tests and bounded commands.
|
||||
- Prefer changed-file/package-scoped tests; do not require full workspace suites unless the user/task explicitly requires them.
|
||||
- If the user supplied exact test/build commands, include those exact commands.
|
||||
|
||||
## Duplicate check
|
||||
Before writing a spec, call \`fn_task_list\` to find existing active tasks, then call \`fn_task_search\` with 2-4 distinct keyword phrases from the task title and description (for example file paths, error symptoms, and symbol names).
|
||||
For any likely match in \`done\` or \`archived\`, call \`fn_task_show\` to inspect details before deciding.
|
||||
If an existing task already covers the same work, do NOT write a PROMPT.md. Instead write exactly:
|
||||
\`DUPLICATE: {existing-task-id}\`
|
||||
|
||||
## Dependency awareness
|
||||
When adding a dependency in \`## Dependencies\`, first call \`fn_task_show\` for that task and read its PROMPT.md.
|
||||
Use that context to align file paths, APIs, assumptions, and completion expectations. If the dependency has no PROMPT.md yet, note that explicitly.
|
||||
|
||||
## Decision-only task flag (noCommitsExpected)
|
||||
When ALL of the following are true, include this metadata line in the header block after Size:
|
||||
|
||||
- Add this exact line: **No commits expected:** true
|
||||
|
||||
Set it only when all of these conditions hold:
|
||||
- Title/mission starts with decision verbs like "Decide", "Evaluate", "Verify", "Confirm", "Audit", "Review whether", or "Investigate and report", OR is an operational routing/coordination task whose only outcome is assigning/routing existing work or recording an intentional no-route/no-owner decision
|
||||
- Acceptance criteria are strictly observational (record findings, routing evidence, no-route/no-owner state, log a decision, update task log/docs) with no required code/config/file mutations
|
||||
- Task description explicitly says things like "no code changes expected", "no source files expected", "no product-source changes", or "the deliverable is the recorded decision"
|
||||
|
||||
Anti-heuristics (bias to false-negative when ambiguous):
|
||||
- SET: Decide whether FN-XYZ needs a fix
|
||||
- SET: Assign ready implementation task to active owner, or record no-route state (no source files expected)
|
||||
- LEAVE UNSET: Investigate FN-XYZ
|
||||
- LEAVE UNSET: Investigate FN-XYZ and fix if needed
|
||||
- LEAVE UNSET: Investigate and fix routing if needed
|
||||
|
||||
If an executor later proves an ordinary implementation task is already satisfied on HEAD, it may close without fabricating a commit by calling \`fn_task_done\` with a leading verified no-op/duplicate sentinel summary: \`PREMISE STALE:\`, \`NO-OP:\`, \`NOOP:\`, \`DUPLICATE: FN-NNNN ...\`, or \`REDUNDANT:\`. This does not weaken ordinary tasks: zero-commit completions without one of these leading sentinels still fail the no-commits invariant.
|
||||
|
||||
## Guidelines
|
||||
- Read relevant source files before writing the spec
|
||||
- Be specific: reference concrete files, modules, and commands from this repo
|
||||
- Keep steps outcome-focused with 2–4 checkboxes per step
|
||||
- Keep file scope realistic: include tests and integration touchpoints likely required for green quality gates
|
||||
- Always include Testing & Verification and Documentation & Delivery steps
|
||||
- Keep fast-mode scope lean and executable; do not add heavyweight review scoring or subtask-analysis sections
|
||||
|
||||
## Project commands
|
||||
When the user prompt includes explicit test/build commands, use those exact commands in the generated spec.
|
||||
|
||||
<!--
|
||||
FNXC:WorkflowRouting 2026-06-22-17:24:
|
||||
Fast triage must keep tasks on the project default workflow unless the user explicitly asked for a specific workflow or the agent created the task. The no-commits header remains a PROMPT.md marker only; it is not permission to select a lightweight workflow automatically.
|
||||
-->
|
||||
## Workflow Routing
|
||||
Keep the project default workflow (\`builtin:coding\`) unless the user explicitly requested a specific workflow for this task or subtask, or you created that task yourself. Do NOT call \`fn_workflow_select\` or pass \`workflow_id\` to \`fn_task_create\` just because a task looks like investigation, audit, research, coordination, decision-only work, or coding work. If the user explicitly asks for a workflow, call \`fn_workflow_list\` to discover valid IDs, then use \`fn_workflow_select\` for the current task or pass \`workflow_id\` to \`fn_task_create\` for the requested subtask. When you create a task via \`fn_task_create\` or \`fn_delegate_task\`, you may select that created task's workflow with \`workflow_id\` at create time or \`fn_workflow_select\` afterward; do not move a task you did not create unless the user asked. For investigation/audit/research, operational routing/coordination, or decision-only tasks that meet the no-commits criteria above, still include \`**No commits expected:** true\` in the PROMPT.md header when appropriate; that header marker does not change the workflow.
|
||||
|
||||
## Task Artifact Location for Forensic / Reconciliation Tasks
|
||||
|
||||
For audit/forensic/historical reconciliation tasks that target a different task ID, explicitly state in generated PROMPT.md context/scope that authoritative artifacts and DB state are at project root, not the worktree.
|
||||
- Target-task files live at \`<rootDir>/.fusion/tasks/{TARGET_ID}/\` (\`task.json\`, \`PROMPT.md\`, \`attachments/\`, logs).
|
||||
- Task DB truth lives at \`<rootDir>/.fusion/fusion.db\` (SQLite/WAL) and should be accessed via \`TaskStore\`/task tools, not direct SQL edits.
|
||||
- \`.fusion/\` is gitignored: fresh worktrees from \`main\` do not contain other tasks' \`.fusion/tasks/{TARGET_ID}/\` or \`.fusion/fusion.db\`; worktree-local \`.fusion/\` is running-task scratch/session state only.
|
||||
|
||||
## Spec Review
|
||||
|
||||
After writing the PROMPT.md, call \`fn_review_spec()\` to confirm the spec.
|
||||
|
||||
Fast-mode specs are auto-approved — the review tool will return APPROVE immediately without spawning an independent reviewer. You do NOT need to wait for or iterate on review feedback.
|
||||
|
||||
Never reference a \`.fusion/tasks/<id>/<file>\` artifact in Context, Steps, or File Scope unless (a) the file already exists, (b) the step explicitly creates it (listed as \`(new)\` under Artifacts), or (c) it is \`PROMPT.md\` / \`task.json\` / \`attachments/*\` for a sibling task. Save planning scratch as task documents via \`fn_task_document_write\`, not as files on disk.
|
||||
## Safety and workflow rules
|
||||
- Never kill port 4040; use a random/free port for test servers.
|
||||
- Do not call workflow-selection tools unless the user explicitly requested a workflow for this task, or you are selecting a workflow for a task you created.
|
||||
- Do not cite task-local \`.fusion/tasks/<id>/<file>\` paths unless the file exists, is PROMPT.md/task.json/attachments for a sibling task, or the spec creates it. Save scratch notes with \`fn_task_document_write\`.
|
||||
|
||||
## Output
|
||||
Write the PROMPT.md directly using the write tool, then call \`fn_review_spec()\` to confirm.`;
|
||||
Write PROMPT.md directly, then call \`fn_review_spec()\`. Fast-mode specs auto-approve, but the call is still required.`;
|
||||
|
||||
const TRIAGE_PROMPT_TEXT = `You are a task specification agent for "fn", an AI-orchestrated task board.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { Settings, Task, TaskDetail, TaskStore } from "@fusion/core";
|
||||
import type { Settings, Task, TaskDetail, TaskStore, WorkflowIr } from "@fusion/core";
|
||||
import {
|
||||
BUILTIN_CODING_WORKFLOW_IR,
|
||||
builtinSeamPrompt,
|
||||
@@ -159,6 +159,39 @@ describe("fast-mode workflow variant resolution", () => {
|
||||
await expect(captureBasePrompt(task, store)).resolves.toBe(renderedFastPlanningPrompt);
|
||||
});
|
||||
|
||||
it("lets a selected workflow planning-fast seam override the built-in lean prompt", async () => {
|
||||
const task = createTask({ id: "FN-6236-FAST-CUSTOM-SEAM", executionMode: "fast" });
|
||||
const customFastPrompt = "custom workflow fast planning prompt";
|
||||
const customIr: WorkflowIr = {
|
||||
version: "v1",
|
||||
name: "custom-fast-workflow",
|
||||
nodes: [{ id: "planning-fast", kind: "prompt", config: { seam: "planning-fast", prompt: customFastPrompt } }],
|
||||
edges: [],
|
||||
};
|
||||
const store = createStore(task, {}, {
|
||||
getTaskWorkflowSelection: vi.fn().mockReturnValue({ workflowId: "WF-fast", stepIds: [] }),
|
||||
getWorkflowDefinition: vi.fn().mockResolvedValue({ ir: customIr }),
|
||||
});
|
||||
|
||||
await expect(captureBasePrompt(task, store)).resolves.toBe(customFastPrompt);
|
||||
});
|
||||
|
||||
it("falls back to the built-in lean fast prompt when the selected workflow has no planning-fast seam", async () => {
|
||||
const task = createTask({ id: "FN-6236-FAST-NO-SEAM", executionMode: "fast" });
|
||||
const noFastSeamIr: WorkflowIr = {
|
||||
version: "v1",
|
||||
name: "no-fast-seam-workflow",
|
||||
nodes: [{ id: "planning", kind: "prompt", config: { seam: "planning", prompt: "standard-only prompt" } }],
|
||||
edges: [],
|
||||
};
|
||||
const store = createStore(task, {}, {
|
||||
getTaskWorkflowSelection: vi.fn().mockReturnValue({ workflowId: "WF-no-fast", stepIds: [] }),
|
||||
getWorkflowDefinition: vi.fn().mockResolvedValue({ ir: noFastSeamIr }),
|
||||
});
|
||||
|
||||
await expect(captureBasePrompt(task, store)).resolves.toBe(renderedFastPlanningPrompt);
|
||||
});
|
||||
|
||||
it("resolves standard tasks to the standard workflow planning prompt", async () => {
|
||||
const task = createTask({ id: "FN-6236-STANDARD-PROMPT", executionMode: "standard" });
|
||||
const store = createStore(task);
|
||||
|
||||
Reference in New Issue
Block a user