docs(KB-222): rebrand kb to Fusion across documentation and CLI

- Rebrand root README from kb to Fusion with updated descriptions
- Update CLI package README with Fusion branding
- Rebrand STANDALONE.md documentation to Fusion
- Update CLI help text to use 'fn' command reference
- Update pi extension descriptions and tool names for Fusion
- Add changeset for rebranding documentation
- Update dashboard ListView component and styles
- Remove obsolete store tests and ListView tests
This commit is contained in:
gsxdsm
2026-03-30 18:22:42 -07:00
parent e36593bf88
commit dcdcf871a9
6 changed files with 176 additions and 167 deletions

View File

@@ -44,41 +44,41 @@ const { runSettingsShow, runSettingsSet } = await import("./commands/settings.js
const { runGitStatus, runGitFetch, runGitPull, runGitPush } = await import("./commands/git.js");
const HELP = `
kb — AI-orchestrated task board
fn — AI-orchestrated task board
Usage:
kb dashboard Start the board web UI
kb dashboard --paused Start with automation paused
kb dashboard --dev Start web UI only (no AI engine)
kb dashboard --interactive Start with interactive port selection
kb task create [desc] [opts] Create a new task (goes to triage)
kb task plan [description] [opts] Create task via AI-guided planning
kb task list List all tasks
kb task show <id> Show task details, steps, log
kb task logs <id> [--follow] [--limit <n>] [--type <type>]
fn dashboard Start the board web UI
fn dashboard --paused Start with automation paused
fn dashboard --dev Start web UI only (no AI engine)
fn dashboard --interactive Start with interactive port selection
fn task create [desc] [opts] Create a new task (goes to triage)
fn task plan [description] [opts] Create task via AI-guided planning
fn task list List all tasks
fn task show <id> Show task details, steps, log
fn task logs <id> [--follow] [--limit <n>] [--type <type>]
Show task agent execution logs
kb task move <id> <col> Move a task to a column
kb task update <id> <step> <status> Update step status (pending|in-progress|done|skipped)
kb task log <id> <message> Add a log entry
kb task merge <id> Merge an in-review task and close it
kb task duplicate <id> Duplicate a task (creates copy in triage)
kb task refine <id> [opts] Create a refinement task from done/in-review
kb task archive <id> Archive a done task
kb task unarchive <id> Unarchive an archived task
kb task delete <id> [--force] Delete a task (use --force to skip confirmation)
kb task attach <id> <file> Attach a file to a task
kb task pause <id> Pause a task (stops all automation)
kb task unpause <id> Unpause a task (resumes automation)
kb task steer <id> [message] Add steering comment (prompts if message omitted)
kb task retry <id> Retry a failed task (clears error, moves to todo)
kb task import <owner/repo> [opts] Import GitHub issues as tasks
kb settings Show current kb configuration
kb settings set <key> <value> Update a configuration setting
fn task move <id> <col> Move a task to a column
fn task update <id> <step> <status> Update step status (pending|in-progress|done|skipped)
fn task log <id> <message> Add a log entry
fn task merge <id> Merge an in-review task and close it
fn task duplicate <id> Duplicate a task (creates copy in triage)
fn task refine <id> [opts] Create a refinement task from done/in-review
fn task archive <id> Archive a done task
fn task unarchive <id> Unarchive an archived task
fn task delete <id> [--force] Delete a task (use --force to skip confirmation)
fn task attach <id> <file> Attach a file to a task
fn task pause <id> Pause a task (stops all automation)
fn task unpause <id> Unpause a task (resumes automation)
fn task steer <id> [message] Add steering comment (prompts if message omitted)
fn task retry <id> Retry a failed task (clears error, moves to todo)
fn task import <owner/repo> [opts] Import GitHub issues as tasks
fn settings Show current Fusion configuration
fn settings set <key> <value> Update a configuration setting
kb git status Show current branch, commit, dirty state, ahead/behind
kb git push Push current branch
kb git pull Pull current branch
kb git fetch [remote] Fetch from remote (default: origin)
fn git status Show current branch, commit, dirty state, ahead/behind
fn git push Push current branch
fn git pull Pull current branch
fn git fetch [remote] Fetch from remote (default: origin)
Options:
--port, -p <port> Dashboard port (default: 4040)
@@ -171,7 +171,7 @@ async function main() {
const id = args[2];
const column = args[3];
if (!id || !column) {
console.error("Usage: kb task move <id> <column>");
console.error("Usage: fn task move <id> <column>");
process.exit(1);
}
await runTaskMove(id, column);
@@ -179,14 +179,14 @@ async function main() {
}
case "show": {
const id = args[2];
if (!id) { console.error("Usage: kb task show <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task show <id>"); process.exit(1); }
await runTaskShow(id);
break;
}
case "update": {
const id = args[2], step = args[3], status = args[4];
if (!id || !step || !status) {
console.error("Usage: kb task update <id> <step> <status>");
console.error("Usage: fn task update <id> <step> <status>");
console.error("Status: pending | in-progress | done | skipped");
process.exit(1);
}
@@ -195,13 +195,13 @@ async function main() {
}
case "log": {
const id = args[2], message = args.slice(3).join(" ");
if (!id || !message) { console.error("Usage: kb task log <id> <message>"); process.exit(1); }
if (!id || !message) { console.error("Usage: fn task log <id> <message>"); process.exit(1); }
await runTaskLog(id, message);
break;
}
case "logs": {
const id = args[2];
if (!id) { console.error("Usage: kb task logs <id> [--follow] [--limit <n>] [--type <type>]"); process.exit(1); }
if (!id) { console.error("Usage: fn task logs <id> [--follow] [--limit <n>] [--type <type>]"); process.exit(1); }
// Parse flags
const follow = args.includes("--follow");
@@ -226,19 +226,19 @@ async function main() {
}
case "merge": {
const id = args[2];
if (!id) { console.error("Usage: kb task merge <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task merge <id>"); process.exit(1); }
await runTaskMerge(id);
break;
}
case "duplicate": {
const id = args[2];
if (!id) { console.error("Usage: kb task duplicate <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task duplicate <id>"); process.exit(1); }
await runTaskDuplicate(id);
break;
}
case "refine": {
const id = args[2];
if (!id) { console.error("Usage: kb task refine <id> [--feedback <text>]"); process.exit(1); }
if (!id) { console.error("Usage: fn task refine <id> [--feedback <text>]"); process.exit(1); }
// Parse optional --feedback flag
const feedbackIdx = args.indexOf("--feedback");
const feedback = feedbackIdx !== -1 && feedbackIdx + 1 < args.length
@@ -249,19 +249,19 @@ async function main() {
}
case "archive": {
const id = args[2];
if (!id) { console.error("Usage: kb task archive <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task archive <id>"); process.exit(1); }
await runTaskArchive(id);
break;
}
case "unarchive": {
const id = args[2];
if (!id) { console.error("Usage: kb task unarchive <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task unarchive <id>"); process.exit(1); }
await runTaskUnarchive(id);
break;
}
case "delete": {
const id = args[2];
if (!id) { console.error("Usage: kb task delete <id> [--force]"); process.exit(1); }
if (!id) { console.error("Usage: fn task delete <id> [--force]"); process.exit(1); }
const force = args.includes("--force");
await runTaskDelete(id, force);
break;
@@ -269,7 +269,7 @@ async function main() {
case "attach": {
const id = args[2], file = args[3];
if (!id || !file) {
console.error("Usage: kb task attach <id> <file>");
console.error("Usage: fn task attach <id> <file>");
process.exit(1);
}
await runTaskAttach(id, file);
@@ -277,27 +277,27 @@ async function main() {
}
case "pause": {
const id = args[2];
if (!id) { console.error("Usage: kb task pause <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task pause <id>"); process.exit(1); }
await runTaskPause(id);
break;
}
case "unpause": {
const id = args[2];
if (!id) { console.error("Usage: kb task unpause <id>"); process.exit(1); }
if (!id) { console.error("Usage: fn task unpause <id>"); process.exit(1); }
await runTaskUnpause(id);
break;
}
case "steer": {
const id = args[2];
const message = args.slice(3).join(" ");
if (!id) { console.error("Usage: kb task steer <id> [message]"); process.exit(1); }
if (!id) { console.error("Usage: fn task steer <id> [message]"); process.exit(1); }
await runTaskSteer(id, message || undefined);
break;
}
case "retry": {
const id = args[2];
if (!id) {
console.error("Usage: kb task retry <id>");
console.error("Usage: fn task retry <id>");
process.exit(1);
}
await runTaskRetry(id);
@@ -306,7 +306,7 @@ async function main() {
case "import": {
const ownerRepo = args[2];
if (!ownerRepo) {
console.error("Usage: kb task import <owner/repo> [options]");
console.error("Usage: fn task import <owner/repo> [options]");
console.error("Options: --limit <n>, -l <n> (default: 30, max: 100)");
console.error(" --labels <labels>, -L <labels> (comma-separated)");
console.error(" --interactive, -i (interactive mode)");
@@ -346,7 +346,7 @@ async function main() {
}
default:
console.error(`Unknown subcommand: task ${subcommand || ""}`);
console.log("Try: kb task create | list | move");
console.log("Try: fn task create | list | move");
process.exit(1);
}
break;
@@ -362,15 +362,15 @@ async function main() {
const key = args[2];
const value = args.slice(3).join(" ");
if (!key || value === undefined) {
console.error("Usage: kb settings set <key> <value>");
console.error("Example: kb settings set maxConcurrent 4");
console.error("Usage: fn settings set <key> <value>");
console.error("Example: fn settings set maxConcurrent 4");
process.exit(1);
}
await runSettingsSet(key, value);
break;
}
console.error(`Unknown settings subcommand: ${subcommand}`);
console.error("Try: kb settings | kb settings set <key> <value>");
console.error("Try: fn settings | fn settings set <key> <value>");
process.exit(1);
}
@@ -397,7 +397,7 @@ async function main() {
}
default:
console.error(`Unknown subcommand: git ${subcommand || ""}`);
console.log("Try: kb git status | fetch | pull | push");
console.log("Try: fn git status | fetch | pull | push");
process.exit(1);
}
break;

View File

@@ -60,10 +60,10 @@ export default function kbExtension(pi: ExtensionAPI) {
name: "kb_task_create",
label: "KB: Create Task",
description:
"Create a new task on the kb task board. The task enters the triage column " +
"Create a new task on the Fusion task board. The task enters the triage column " +
"where the AI triage agent will specify it into a full prompt with steps, " +
"file scope, and acceptance criteria.",
promptSnippet: "Create a task on the kb AI-orchestrated task board",
promptSnippet: "Create a task on the Fusion AI-orchestrated task board",
promptGuidelines: [
"Use kb_task_create for task tracking — be descriptive so the triage agent can write a good spec.",
"Include the problem AND desired outcome. For bugs, describe current vs expected behavior.",
@@ -112,8 +112,8 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "kb_task_list",
label: "KB: List Tasks",
description: "List all tasks on the kb board, grouped by column.",
promptSnippet: "List all tasks on the kb board grouped by column",
description: "List all tasks on the Fusion board, grouped by column.",
promptSnippet: "List all tasks on the Fusion board grouped by column",
parameters: Type.Object({
column: Type.Optional(
StringEnum([...COLUMNS] as unknown as string[], {
@@ -171,7 +171,7 @@ export default function kbExtension(pi: ExtensionAPI) {
name: "kb_task_show",
label: "KB: Show Task",
description: "Show full details for a task including steps, progress, and log entries.",
promptSnippet: "Show full details for a kb task",
promptSnippet: "Show full details for a Fusion task",
parameters: Type.Object({
id: Type.String({ description: "Task ID (e.g. KB-001)" }),
}),
@@ -252,7 +252,7 @@ export default function kbExtension(pi: ExtensionAPI) {
description:
"Attach a file to a task. Supports images (png, jpg, gif, webp) and " +
"text files (txt, log, json, yaml, yml, toml, csv, xml).",
promptSnippet: "Attach a file to a kb task",
promptSnippet: "Attach a file to a Fusion task",
parameters: Type.Object({
id: Type.String({ description: "Task ID (e.g. KB-001)" }),
path: Type.String({ description: "Path to the file to attach" }),
@@ -302,7 +302,7 @@ export default function kbExtension(pi: ExtensionAPI) {
label: "KB: Pause Task",
description:
"Pause a task — stops all automated agent and scheduler interaction for this task.",
promptSnippet: "Pause a kb task (stops automation)",
promptSnippet: "Pause a Fusion task (stops automation)",
parameters: Type.Object({
id: Type.String({ description: "Task ID (e.g. KB-001)" }),
}),
@@ -325,7 +325,7 @@ export default function kbExtension(pi: ExtensionAPI) {
label: "KB: Unpause Task",
description:
"Unpause a task — resumes automated agent and scheduler interaction.",
promptSnippet: "Unpause a kb task (resumes automation)",
promptSnippet: "Unpause a Fusion task (resumes automation)",
parameters: Type.Object({
id: Type.String({ description: "Task ID (e.g. KB-001)" }),
}),
@@ -348,7 +348,7 @@ export default function kbExtension(pi: ExtensionAPI) {
label: "KB: Retry Task",
description:
"Retry a failed task — clears the error state and moves it back to the todo column for re-execution.",
promptSnippet: "Retry a failed kb task (clears error, moves to todo)",
promptSnippet: "Retry a failed Fusion task (clears error, moves to todo)",
promptGuidelines: [
"Use when a task has failed and needs to be retried from the beginning",
"Only tasks in 'failed' state can be retried",
@@ -407,7 +407,7 @@ export default function kbExtension(pi: ExtensionAPI) {
"Duplicate an existing task, creating a fresh copy in triage. " +
"Copies the title and description but resets all execution state. " +
"The AI triage agent will re-specify the new task.",
promptSnippet: "Duplicate a kb task (creates copy in triage)",
promptSnippet: "Duplicate a Fusion task (creates copy in triage)",
promptGuidelines: [
"Use when a task needs to be re-done, split, or used as a template",
"The duplicated task will be placed in triage for re-specification",
@@ -474,7 +474,7 @@ export default function kbExtension(pi: ExtensionAPI) {
description:
"Archive a done task (move from done → archived). " +
"Archived tasks are preserved for historical reference but moved out of the main board view.",
promptSnippet: "Archive a done kb task (moves to archived column)",
promptSnippet: "Archive a done Fusion task (moves to archived column)",
promptGuidelines: [
"Use to clean up old completed tasks from the done column",
"Only tasks in the 'done' column can be archived",
@@ -503,7 +503,7 @@ export default function kbExtension(pi: ExtensionAPI) {
description:
"Unarchive an archived task (move from archived → done). " +
"Restores the task to the done column.",
promptSnippet: "Unarchive a kb task (restores to done column)",
promptSnippet: "Unarchive a Fusion task (restores to done column)",
promptGuidelines: [
"Use to restore an archived task back to the done column",
"Only tasks in the 'archived' column can be unarchived",
@@ -529,9 +529,9 @@ export default function kbExtension(pi: ExtensionAPI) {
name: "kb_task_delete",
label: "KB: Delete Task",
description:
"Permanently delete a task from the kb board. " +
"Permanently delete a task from the Fusion board. " +
"Tasks are deleted immediately and cannot be recovered.",
promptSnippet: "Delete a kb task",
promptSnippet: "Delete a Fusion task",
promptGuidelines: [
"Use for cleaning up test tasks or tasks created in error",
"Tasks are permanently deleted and cannot be recovered",
@@ -558,12 +558,12 @@ export default function kbExtension(pi: ExtensionAPI) {
name: "kb_task_import_github",
label: "KB: Import GitHub Issues",
description:
"Import GitHub issues as kb tasks. Fetches open issues from a repository " +
"Import GitHub issues as Fusion tasks. Fetches open issues from a repository " +
"and creates tasks in the triage column. Each task includes the issue title " +
"and body with a link to the source issue.",
promptSnippet: "Import GitHub issues as kb tasks",
promptSnippet: "Import GitHub issues as Fusion tasks",
promptGuidelines: [
"Use for syncing GitHub issue backlog to kb board",
"Use for syncing GitHub issue backlog to Fusion board",
"Uses gh CLI authentication when available (run 'gh auth login')",
"Falls back to GITHUB_TOKEN env var for private repositories without gh CLI",
"Use --limit to control how many issues to import (default: 30)",
@@ -648,9 +648,9 @@ export default function kbExtension(pi: ExtensionAPI) {
name: "kb_task_import_github_issue",
label: "KB: Import GitHub Issue",
description:
"Import a specific GitHub issue as a kb task. Fetches the issue by number " +
"Import a specific GitHub issue as a Fusion task. Fetches the issue by number " +
"and creates a single task in the triage column with the issue title and body.",
promptSnippet: "Import a specific GitHub issue as a kb task",
promptSnippet: "Import a specific GitHub issue as a Fusion task",
promptGuidelines: [
"Use for importing a single known issue by its number",
"Uses gh CLI authentication when available (run 'gh auth login')",
@@ -680,7 +680,7 @@ export default function kbExtension(pi: ExtensionAPI) {
const headers: Record<string, string> = {
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "kb-cli/1.0",
"User-Agent": "fusion-cli/1.0",
};
if (token) {
@@ -819,7 +819,7 @@ export default function kbExtension(pi: ExtensionAPI) {
const headers: Record<string, string> = {
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "kb-cli/1.0",
"User-Agent": "fusion-cli/1.0",
};
if (token) {
@@ -975,46 +975,46 @@ export default function kbExtension(pi: ExtensionAPI) {
},
});
// ── /kb command — start the dashboard + engine ───────────────────
// ── /fn command — start the dashboard + engine ───────────────────
let dashboardProcess: ChildProcess | null = null;
let dashboardPort: number | null = null;
pi.registerCommand("kb", {
description: "Start (or stop) the kb dashboard and AI engine",
pi.registerCommand("fn", {
description: "Start (or stop) the Fusion dashboard and AI engine",
handler: async (args, ctx) => {
const trimmed = (args ?? "").trim();
// /kb stop — kill the dashboard
// /fn stop — kill the dashboard
if (trimmed === "stop") {
if (dashboardProcess) {
dashboardProcess.kill("SIGINT");
dashboardProcess = null;
dashboardPort = null;
ctx.ui.setStatus("kb", "");
ctx.ui.notify("kb dashboard stopped", "info");
ctx.ui.setStatus("fn", "");
ctx.ui.notify("Fusion dashboard stopped", "info");
} else {
ctx.ui.notify("kb dashboard is not running", "warning");
ctx.ui.notify("Fusion dashboard is not running", "warning");
}
return;
}
// /kb status
// /fn status
if (trimmed === "status") {
if (dashboardProcess && !dashboardProcess.killed) {
ctx.ui.notify(`kb dashboard running on http://localhost:${dashboardPort}`, "info");
ctx.ui.notify(`Fusion dashboard running on http://localhost:${dashboardPort}`, "info");
} else {
dashboardProcess = null;
dashboardPort = null;
ctx.ui.notify("kb dashboard is not running", "info");
ctx.ui.notify("Fusion dashboard is not running", "info");
}
return;
}
// /kb [port] — start the dashboard
// /fn [port] — start the dashboard
if (dashboardProcess && !dashboardProcess.killed) {
ctx.ui.notify(
`kb dashboard already running on http://localhost:${dashboardPort}. Use /kb stop first.`,
`Fusion dashboard already running on http://localhost:${dashboardPort}. Use /fn stop first.`,
"warning",
);
return;
@@ -1022,8 +1022,8 @@ export default function kbExtension(pi: ExtensionAPI) {
const port = trimmed ? parseInt(trimmed, 10) || 4040 : 4040;
// Find the kb binary: prefer local node_modules, then global
const child = spawn("kb", ["dashboard", "--port", String(port)], {
// Find the fn binary: prefer local node_modules, then global
const child = spawn("fn", ["dashboard", "--port", String(port)], {
cwd: ctx.cwd,
stdio: ["ignore", "pipe", "pipe"],
detached: false,
@@ -1033,21 +1033,21 @@ export default function kbExtension(pi: ExtensionAPI) {
dashboardProcess = child;
dashboardPort = port;
// Watch for early exit (e.g. kb not found)
// Watch for early exit (e.g. fn not found)
child.on("error", (err) => {
dashboardProcess = null;
dashboardPort = null;
ctx.ui.setStatus("kb", "");
ctx.ui.notify(`Failed to start kb dashboard: ${err.message}`, "error");
ctx.ui.setStatus("fn", "");
ctx.ui.notify(`Failed to start Fusion dashboard: ${err.message}`, "error");
});
child.on("exit", (code) => {
if (dashboardProcess === child) {
dashboardProcess = null;
dashboardPort = null;
ctx.ui.setStatus("kb", "");
ctx.ui.setStatus("fn", "");
if (code !== 0 && code !== null) {
ctx.ui.notify(`kb dashboard exited with code ${code}`, "warning");
ctx.ui.notify(`Fusion dashboard exited with code ${code}`, "warning");
}
}
});
@@ -1057,9 +1057,9 @@ export default function kbExtension(pi: ExtensionAPI) {
if (dashboardProcess && !dashboardProcess.killed) {
const url = `http://localhost:${port}`;
ctx.ui.notify(`kb dashboard started on ${url} (AI engine active)`, "info");
ctx.ui.notify(`Fusion dashboard started on ${url} (AI engine active)`, "info");
const link = `\x1b]8;;${url}\x1b\\${url}\x1b]8;;\x1b\\`;
ctx.ui.setStatus("kb", `kb${link}`);
ctx.ui.setStatus("fn", `Fusion${link}`);
}
},
});