fix: regenerate pi-claude-cli MCP config per session and auto-sync skill tools

The MCP config was generated lazily once and locked, so engine session-scoped
tools (fn_review_spec, fn_review_step) never reached the Claude CLI subprocess
and triage/executor sessions failed with "unknown tool" errors. Now the config
is hashed per call and rewritten when the tool set changes.

Also adds scripts/sync-fusion-skill-tools.mjs to regenerate the SKILL.md
tool-categories block from extension.ts at build time, with a --check mode
wired into skill-sync tests so drift fails CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-25 14:10:56 -07:00
parent c597dd4055
commit e8aab69c67
8 changed files with 231 additions and 26 deletions

View File

@@ -39,6 +39,7 @@
],
"scripts": {
"dev": "tsx src/bin.ts",
"prebuild": "node ../../scripts/sync-fusion-skill-tools.mjs",
"build": "tsup",
"build:exe": "bun run build.ts",
"build:exe:all": "bun run build.ts --all",

View File

@@ -24,11 +24,13 @@ Mission → Milestone → Slice → Feature → Task
**Naming boundary:** The published skill surface always uses `fn_*` tool names (for example `fn_task_create`, `fn_mission_create`). Internal engine runtime tools like `task_create`, `task_update`, `task_log`, and `task_done` are intentionally unprefixed and not part of this skill.
**Tool categories:**
<!-- BEGIN: tool-categories (auto-generated by scripts/sync-fusion-skill-tools.mjs — do not edit by hand) -->
- **Task tools** — `fn_task_create`, `fn_task_update`, `fn_task_list`, `fn_task_show`, `fn_task_attach`, `fn_task_pause`, `fn_task_unpause`, `fn_task_retry`, `fn_task_duplicate`, `fn_task_refine`, `fn_task_archive`, `fn_task_unarchive`, `fn_task_delete`, `fn_task_plan`
- **GitHub tools** — `fn_task_import_github`, `fn_task_import_github_issue`, `fn_task_browse_github_issues`
- **Mission tools** — `fn_mission_create`, `fn_mission_list`, `fn_mission_show`, `fn_mission_delete`, `fn_milestone_add`, `fn_slice_add`, `fn_feature_add`, `fn_slice_activate`, `fn_feature_link_task`
- **Agent tools** — `fn_agent_stop`, `fn_agent_start`
- **Skills tools** — `fn_skills_search`, `fn_skills_install`
<!-- END: tool-categories -->
- **Dashboard** — Use `/fn` command to start/stop the dashboard
</essential_principles>

View File

@@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest";
import { readFileSync, existsSync, readdirSync } from "node:fs";
import { resolve, dirname, relative, join } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
const __dirname = dirname(fileURLToPath(import.meta.url));
const cliRoot = resolve(__dirname, "../..");
@@ -194,6 +195,19 @@ describe("Skill-Extension Sync", () => {
expect(dashboardCli).toContain("/fn");
});
it("SKILL.md tool-categories block matches the sync script output (no drift)", () => {
const repoRoot = resolve(cliRoot, "../..");
const script = resolve(repoRoot, "scripts/sync-fusion-skill-tools.mjs");
const result = spawnSync("node", [script, "--check"], {
encoding: "utf-8",
});
if (result.status !== 0) {
throw new Error(
`sync-fusion-skill-tools --check failed:\n${result.stderr || result.stdout}`,
);
}
});
it("package.json includes skills in pi config and files array", () => {
const pkg = JSON.parse(
readFileSync(resolve(cliRoot, "package.json"), "utf-8"),