diff --git a/packages/cli/skill/fusion/references/engine-tools.md b/packages/cli/skill/fusion/references/engine-tools.md index 9f809f68fe..1b89a91c97 100644 --- a/packages/cli/skill/fusion/references/engine-tools.md +++ b/packages/cli/skill/fusion/references/engine-tools.md @@ -30,6 +30,8 @@ These tools are **not** part of the user-invokable extension surface. They are i | `fn_workflow_create` | executor, chat, planning | Create a custom workflow definition from a graph IR (validated server-side). v2 IR supports step-inversion constructs: `parse-steps`, `foreach` (mode/isolation/concurrency/maxReworkCycles), `step-execute`, `step-review`, `code` nodes, `rework` edges, plus `artifacts` and custom `fields` declarations | `name` (string), `description?` (string), `ir` (object), `layout?` (object) | | `fn_workflow_update` | executor, chat, planning | Update a custom workflow definition's name/description/ir/layout (built-ins cannot be edited; same step-inversion IR constructs as create; editing `fields` orphans rather than destroys existing task values) | `workflow_id` (string), `name?` (string), `description?` (string), `ir?` (object), `layout?` (object), `rehome_to?` (string) | | `fn_workflow_delete` | executor, chat, planning | Delete a custom workflow definition (built-ins cannot be deleted); selecting tasks are re-homed to the default workflow's entry column | `workflow_id` (string) | + +| `fn_ask_question` | chat | Ask the user a structured question that renders as an interactive chat card; after calling it, end the turn and wait for the user's next message | `questions` (array of objects with `question`, optional `header`, optional `description`, optional `type`, optional `options`, optional `multiSelect`) | | `fn_task_promote` | executor | Promote a held task out of a manual-release hold column (defaults to the current task) | `task_id?` (string) | | `fn_trait_list` | executor, chat, planning | List the registered column trait catalog (built-in and plugin traits) | none | | `fn_memory_search` | triage, executor, heartbeat | Search project memory plus per-agent layered memory snippets | `query` (string), `limit?` (number) | diff --git a/packages/cli/src/__tests__/skill-sync.test.ts b/packages/cli/src/__tests__/skill-sync.test.ts index 1655025f56..fec82aa2b5 100644 --- a/packages/cli/src/__tests__/skill-sync.test.ts +++ b/packages/cli/src/__tests__/skill-sync.test.ts @@ -410,7 +410,11 @@ describe("Skill-Extension Sync", () => { const engineTools = getEngineSessionToolNames(); const documented = getDocumentedEngineToolNames(); const missing = engineTools.filter((name) => !documented.includes(name)); - expect(missing).toEqual([]); + // FNXC:SkillSync 2026-06-17-23:06: This test enforces the invariant that every engine session-scoped `fn_*` registration across the engine source set must be mirrored in `engine-tools.md`, so failures must print the exact undocumented names instead of hiding drift behind a generic deep-equality diff. + expect( + missing, + `undocumented engine tools in engine-tools.md: ${missing.join(", ") || "none"}`, + ).toEqual([]); }); it("covers the full Fusion skill markdown surface", () => {