feat(FN-1216): rename extension tools to fn_* across CLI and docs
- Rename all pi extension tool registrations from kb_* to fn_* across task, mission, and agent tool families - Update extension and skill-sync tests plus Fusion skill docs/workflows to assert and document the new fn_* tool names - Align product-identity strings across core, dashboard, and CLI references, including GitHub import examples, User-Agent headers, and terminal TERM_PROGRAM - Add a @gsxdsm/fusion minor changeset describing the extension tool-prefix rename
This commit is contained in:
@@ -19,13 +19,13 @@ Fusion (kb) is an AI-orchestrated task board. You throw in rough ideas; AI speci
|
||||
**Missions** provide hierarchical planning above tasks:
|
||||
Mission → Milestone → Slice → Feature → Task
|
||||
|
||||
**Available tools:** Fusion registers tools via the pi extension (prefixed `kb_*`). No CLI commands or Bash needed — use the registered tools directly.
|
||||
**Available tools:** Fusion registers tools via the pi extension (prefixed `fn_*`). No CLI commands or Bash needed — use the registered tools directly.
|
||||
|
||||
**Tool categories:**
|
||||
- **Task tools** — `kb_task_create`, `kb_task_update`, `kb_task_list`, `kb_task_show`, `kb_task_attach`, `kb_task_pause`, `kb_task_unpause`, `kb_task_retry`, `kb_task_duplicate`, `kb_task_refine`, `kb_task_archive`, `kb_task_unarchive`, `kb_task_delete`, `kb_task_plan`
|
||||
- **GitHub tools** — `kb_task_import_github`, `kb_task_import_github_issue`, `kb_task_browse_github_issues`
|
||||
- **Mission tools** — `kb_mission_create`, `kb_mission_list`, `kb_mission_show`, `kb_mission_delete`, `kb_milestone_add`, `kb_slice_add`, `kb_feature_add`, `kb_slice_activate`, `kb_feature_link_task`
|
||||
- **Agent tools** — `kb_agent_stop`, `kb_agent_start`
|
||||
- **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`
|
||||
- **Dashboard** — Use `/fn` command to start/stop the dashboard
|
||||
|
||||
</essential_principles>
|
||||
@@ -45,32 +45,32 @@ Based on the user's request, route to the appropriate workflow:
|
||||
**Dashboard and CLI:**
|
||||
- Start dashboard, use CLI commands, settings → workflows/dashboard-cli.md
|
||||
|
||||
**If the intent is simple and clear** (e.g., "create a task to fix the login bug"), execute directly using the appropriate `kb_*` tool without loading a workflow file. Only load workflows for guidance on complex operations or when the user needs help understanding Fusion concepts.
|
||||
**If the intent is simple and clear** (e.g., "create a task to fix the login bug"), execute directly using the appropriate `fn_*` tool without loading a workflow file. Only load workflows for guidance on complex operations or when the user needs help understanding Fusion concepts.
|
||||
|
||||
</routing>
|
||||
|
||||
<quick_reference>
|
||||
|
||||
**Create a task:**
|
||||
Use `kb_task_create` with a descriptive message. Include the problem AND desired outcome.
|
||||
Use `fn_task_create` with a descriptive message. Include the problem AND desired outcome.
|
||||
|
||||
**List tasks:**
|
||||
Use `kb_task_list` to see all tasks grouped by column. Use `column` param to filter.
|
||||
Use `fn_task_list` to see all tasks grouped by column. Use `column` param to filter.
|
||||
|
||||
**Show task details:**
|
||||
Use `kb_task_show` with the task ID (e.g., KB-001) to see steps, progress, and log.
|
||||
Use `fn_task_show` with the task ID (e.g., KB-001) to see steps, progress, and log.
|
||||
|
||||
**Plan complex work:**
|
||||
Use `kb_task_plan` for AI-guided planning that interviews you before creating the task.
|
||||
Use `fn_task_plan` for AI-guided planning that interviews you before creating the task.
|
||||
|
||||
**Import GitHub issues:**
|
||||
Use `kb_task_browse_github_issues` to preview, then `kb_task_import_github_issue` for specific issues.
|
||||
Use `fn_task_browse_github_issues` to preview, then `fn_task_import_github_issue` for specific issues.
|
||||
|
||||
**Start dashboard:**
|
||||
Use `/fn` command. `/fn stop` to stop. `/fn status` to check.
|
||||
|
||||
**Mission planning:**
|
||||
Use `kb_mission_create` for high-level objectives, then add milestones, slices, and features.
|
||||
Use `fn_mission_create` for high-level objectives, then add milestones, slices, and features.
|
||||
|
||||
</quick_reference>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
- Write one-liner descriptions like "fix the bug"
|
||||
- Include implementation details the AI should figure out
|
||||
- Create tasks that are too large (break into smaller tasks or use missions)
|
||||
- Duplicate existing tasks — check `kb_task_list` first
|
||||
- Duplicate existing tasks — check `fn_task_list` first
|
||||
|
||||
## Task Size Guidelines
|
||||
|
||||
@@ -29,14 +29,14 @@ For work larger than L, use missions to break it into phases.
|
||||
|
||||
| Scenario | Tool |
|
||||
|----------|------|
|
||||
| Quick task with clear scope | `kb_task_create` |
|
||||
| Vague idea needing refinement | `kb_task_plan` |
|
||||
| Large project with phases | `kb_mission_create` + hierarchy |
|
||||
| Task failed, needs retry | `kb_task_retry` |
|
||||
| Task needs manual intervention | `kb_task_pause` |
|
||||
| Completed task needs follow-up | `kb_task_refine` |
|
||||
| Clean up done tasks | `kb_task_archive` |
|
||||
| Import external work | `kb_task_import_github*` |
|
||||
| Quick task with clear scope | `fn_task_create` |
|
||||
| Vague idea needing refinement | `fn_task_plan` |
|
||||
| Large project with phases | `fn_mission_create` + hierarchy |
|
||||
| Task failed, needs retry | `fn_task_retry` |
|
||||
| Task needs manual intervention | `fn_task_pause` |
|
||||
| Completed task needs follow-up | `fn_task_refine` |
|
||||
| Clean up done tasks | `fn_task_archive` |
|
||||
| Import external work | `fn_task_import_github*` |
|
||||
|
||||
## Dependency Management
|
||||
|
||||
@@ -49,10 +49,10 @@ For work larger than L, use missions to break it into phases.
|
||||
## Working with the AI Engine
|
||||
|
||||
- **Don't fight the automation** — let triage, scheduler, and executor do their jobs
|
||||
- **Pause if needed** — use `kb_task_pause` when you want manual control
|
||||
- **Pause if needed** — use `fn_task_pause` when you want manual control
|
||||
- **Steer don't micromanage** — use steering comments (via CLI `fn task steer`) to guide the AI without rewriting the spec
|
||||
- **Check progress** — use `kb_task_show` to monitor step completion
|
||||
- **Let it fail and retry** — if a task fails, check the log, then `kb_task_retry`
|
||||
- **Check progress** — use `fn_task_show` to monitor step completion
|
||||
- **Let it fail and retry** — if a task fails, check the log, then `fn_task_retry`
|
||||
|
||||
## Mission Planning Tips
|
||||
|
||||
@@ -66,18 +66,18 @@ For work larger than L, use missions to break it into phases.
|
||||
## Common Patterns
|
||||
|
||||
**Bug fix flow:**
|
||||
1. `kb_task_create` with bug description (current vs expected behavior)
|
||||
1. `fn_task_create` with bug description (current vs expected behavior)
|
||||
2. Wait for triage to generate specification
|
||||
3. Monitor with `kb_task_show` until done
|
||||
3. Monitor with `fn_task_show` until done
|
||||
|
||||
**Feature development flow:**
|
||||
1. `kb_task_plan` to refine requirements
|
||||
1. `fn_task_plan` to refine requirements
|
||||
2. Check the task in triage → todo → in-progress
|
||||
3. Review in `kb_task_show` when in-review
|
||||
3. Review in `fn_task_show` when in-review
|
||||
4. Task auto-merges to main
|
||||
|
||||
**Large project flow:**
|
||||
1. `kb_mission_create` with project overview
|
||||
1. `fn_mission_create` with project overview
|
||||
2. Add milestones for each phase
|
||||
3. Add slices and features for the first milestone
|
||||
4. Activate first slice, create and link tasks
|
||||
@@ -85,7 +85,7 @@ For work larger than L, use missions to break it into phases.
|
||||
6. Activate next slice (or use auto-advance)
|
||||
|
||||
**GitHub issue triage flow:**
|
||||
1. `kb_task_browse_github_issues` to see what's open
|
||||
2. `kb_task_import_github_issue` for high-priority issues
|
||||
1. `fn_task_browse_github_issues` to see what's open
|
||||
2. `fn_task_import_github_issue` for high-priority issues
|
||||
3. Tasks enter triage and get AI-specified
|
||||
4. Monitor board as AI works through them
|
||||
|
||||
@@ -4,7 +4,7 @@ All tools are registered via the pi extension. They are available in any pi agen
|
||||
|
||||
## Task Tools
|
||||
|
||||
### kb_task_create
|
||||
### fn_task_create
|
||||
|
||||
Create a new task on the Fusion board. Enters triage for AI specification.
|
||||
|
||||
@@ -15,7 +15,7 @@ Create a new task on the Fusion board. Enters triage for AI specification.
|
||||
|
||||
Returns: task ID, column, dependencies, path
|
||||
|
||||
### kb_task_update
|
||||
### fn_task_update
|
||||
|
||||
Update fields on an existing task (title, description, dependencies).
|
||||
|
||||
@@ -28,7 +28,7 @@ Update fields on an existing task (title, description, dependencies).
|
||||
|
||||
Returns: task ID, list of updated fields
|
||||
|
||||
### kb_task_list
|
||||
### fn_task_list
|
||||
|
||||
List all tasks grouped by column.
|
||||
|
||||
@@ -39,7 +39,7 @@ List all tasks grouped by column.
|
||||
|
||||
Returns: formatted task list grouped by column
|
||||
|
||||
### kb_task_show
|
||||
### fn_task_show
|
||||
|
||||
Show full task details including steps, progress, prompt preview, and log.
|
||||
|
||||
@@ -49,7 +49,7 @@ Show full task details including steps, progress, prompt preview, and log.
|
||||
|
||||
Returns: task details with steps, prompt preview (500 chars), last 5 log entries
|
||||
|
||||
### kb_task_attach
|
||||
### fn_task_attach
|
||||
|
||||
Attach a file to a task. Copies file to task's attachments directory.
|
||||
|
||||
@@ -60,7 +60,7 @@ Attach a file to a task. Copies file to task's attachments directory.
|
||||
|
||||
Supported formats: png, jpg, jpeg, gif, webp, txt, log, json, yaml, yml, toml, csv, xml
|
||||
|
||||
### kb_task_pause
|
||||
### fn_task_pause
|
||||
|
||||
Pause automation for a task. Scheduler and executor will skip this task.
|
||||
|
||||
@@ -68,7 +68,7 @@ Pause automation for a task. Scheduler and executor will skip this task.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID |
|
||||
|
||||
### kb_task_unpause
|
||||
### fn_task_unpause
|
||||
|
||||
Resume automation for a paused task.
|
||||
|
||||
@@ -76,7 +76,7 @@ Resume automation for a paused task.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID |
|
||||
|
||||
### kb_task_retry
|
||||
### fn_task_retry
|
||||
|
||||
Retry a failed task. Clears error state, moves to todo for re-execution.
|
||||
|
||||
@@ -84,7 +84,7 @@ Retry a failed task. Clears error state, moves to todo for re-execution.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID (must be in failed state) |
|
||||
|
||||
### kb_task_duplicate
|
||||
### fn_task_duplicate
|
||||
|
||||
Duplicate a task. Creates a fresh copy in triage with same title and description.
|
||||
|
||||
@@ -92,7 +92,7 @@ Duplicate a task. Creates a fresh copy in triage with same title and description
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Source task ID to duplicate |
|
||||
|
||||
### kb_task_refine
|
||||
### fn_task_refine
|
||||
|
||||
Create a follow-up task for a completed task. New task depends on the original.
|
||||
|
||||
@@ -101,7 +101,7 @@ Create a follow-up task for a completed task. New task depends on the original.
|
||||
| `id` | string | ✓ | Task ID (must be done or in-review) |
|
||||
| `feedback` | string | ✓ | What needs to be refined (1-2000 chars) |
|
||||
|
||||
### kb_task_archive
|
||||
### fn_task_archive
|
||||
|
||||
Archive a done task. Moves from done → archived.
|
||||
|
||||
@@ -109,7 +109,7 @@ Archive a done task. Moves from done → archived.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID (must be in done column) |
|
||||
|
||||
### kb_task_unarchive
|
||||
### fn_task_unarchive
|
||||
|
||||
Restore an archived task. Moves from archived → done.
|
||||
|
||||
@@ -117,7 +117,7 @@ Restore an archived task. Moves from archived → done.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID (must be in archived column) |
|
||||
|
||||
### kb_task_delete
|
||||
### fn_task_delete
|
||||
|
||||
Permanently delete a task. Cannot be undone.
|
||||
|
||||
@@ -125,7 +125,7 @@ Permanently delete a task. Cannot be undone.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Task ID |
|
||||
|
||||
### kb_task_plan
|
||||
### fn_task_plan
|
||||
|
||||
Create a task via AI-guided planning mode. Non-interactive when called from extension.
|
||||
|
||||
@@ -135,7 +135,7 @@ Create a task via AI-guided planning mode. Non-interactive when called from exte
|
||||
|
||||
## GitHub Tools
|
||||
|
||||
### kb_task_import_github
|
||||
### fn_task_import_github
|
||||
|
||||
Batch import GitHub issues as Fusion tasks.
|
||||
|
||||
@@ -145,7 +145,7 @@ Batch import GitHub issues as Fusion tasks.
|
||||
| `limit` | number | — | Max issues (default: 30, max: 100) |
|
||||
| `labels` | string[] | — | Label names to filter by |
|
||||
|
||||
### kb_task_import_github_issue
|
||||
### fn_task_import_github_issue
|
||||
|
||||
Import a single GitHub issue by number.
|
||||
|
||||
@@ -155,7 +155,7 @@ Import a single GitHub issue by number.
|
||||
| `repo` | string | ✓ | Repository name |
|
||||
| `issueNumber` | number | ✓ | GitHub issue number |
|
||||
|
||||
### kb_task_browse_github_issues
|
||||
### fn_task_browse_github_issues
|
||||
|
||||
Browse open issues from a repository before importing.
|
||||
|
||||
@@ -168,7 +168,7 @@ Browse open issues from a repository before importing.
|
||||
|
||||
## Mission Tools
|
||||
|
||||
### kb_mission_create
|
||||
### fn_mission_create
|
||||
|
||||
Create a new mission — a high-level objective spanning multiple milestones.
|
||||
|
||||
@@ -178,11 +178,11 @@ Create a new mission — a high-level objective spanning multiple milestones.
|
||||
| `description` | string | — | Detailed objectives and context |
|
||||
| `autoAdvance` | boolean | — | Auto-activate next slice on completion |
|
||||
|
||||
### kb_mission_list
|
||||
### fn_mission_list
|
||||
|
||||
List all missions with current status. No parameters.
|
||||
|
||||
### kb_mission_show
|
||||
### fn_mission_show
|
||||
|
||||
Show mission details with full hierarchy.
|
||||
|
||||
@@ -190,7 +190,7 @@ Show mission details with full hierarchy.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Mission ID (e.g., M-001) |
|
||||
|
||||
### kb_mission_delete
|
||||
### fn_mission_delete
|
||||
|
||||
Delete a mission and all children. Tasks are NOT deleted.
|
||||
|
||||
@@ -198,7 +198,7 @@ Delete a mission and all children. Tasks are NOT deleted.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Mission ID |
|
||||
|
||||
### kb_milestone_add
|
||||
### fn_milestone_add
|
||||
|
||||
Add a milestone to a mission.
|
||||
|
||||
@@ -208,7 +208,7 @@ Add a milestone to a mission.
|
||||
| `title` | string | ✓ | Milestone title |
|
||||
| `description` | string | — | Milestone description |
|
||||
|
||||
### kb_slice_add
|
||||
### fn_slice_add
|
||||
|
||||
Add a slice to a milestone.
|
||||
|
||||
@@ -218,7 +218,7 @@ Add a slice to a milestone.
|
||||
| `title` | string | ✓ | Slice title |
|
||||
| `description` | string | — | Slice description |
|
||||
|
||||
### kb_feature_add
|
||||
### fn_feature_add
|
||||
|
||||
Add a feature to a slice.
|
||||
|
||||
@@ -229,7 +229,7 @@ Add a feature to a slice.
|
||||
| `description` | string | — | Feature description |
|
||||
| `acceptanceCriteria` | string | — | Acceptance criteria |
|
||||
|
||||
### kb_slice_activate
|
||||
### fn_slice_activate
|
||||
|
||||
Activate a pending slice for implementation.
|
||||
|
||||
@@ -237,7 +237,7 @@ Activate a pending slice for implementation.
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Slice ID (must be pending) |
|
||||
|
||||
### kb_feature_link_task
|
||||
### fn_feature_link_task
|
||||
|
||||
Link a feature to a kb task. Updates feature status to triaged.
|
||||
|
||||
@@ -246,7 +246,7 @@ Link a feature to a kb task. Updates feature status to triaged.
|
||||
| `featureId` | string | ✓ | Feature ID (e.g., F-001) |
|
||||
| `taskId` | string | ✓ | Task ID (e.g., KB-001) |
|
||||
|
||||
### kb_agent_stop
|
||||
### fn_agent_stop
|
||||
|
||||
Stop (pause) a running agent. Transitions the agent from running/active to paused state.
|
||||
|
||||
@@ -254,7 +254,7 @@ Stop (pause) a running agent. Transitions the agent from running/active to pause
|
||||
|-----------|------|----------|-------------|
|
||||
| `id` | string | ✓ | Agent ID to stop (e.g., agent-abc123) |
|
||||
|
||||
### kb_agent_start
|
||||
### fn_agent_start
|
||||
|
||||
Start (resume) a stopped agent. Transitions the agent from paused to active state.
|
||||
|
||||
|
||||
@@ -9,34 +9,34 @@ Triage → Todo → In Progress → In Review → Done → Archived
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `kb_task_create` | Create a new task in triage |
|
||||
| `kb_task_update` | Update task title, description, or dependencies |
|
||||
| `kb_task_list` | List all tasks grouped by column |
|
||||
| `kb_task_show` | Show full task details, steps, log |
|
||||
| `kb_task_attach` | Attach a file to a task |
|
||||
| `kb_task_pause` | Pause automation for a task |
|
||||
| `kb_task_unpause` | Resume automation for a task |
|
||||
| `kb_task_retry` | Retry a failed task (clears error, moves to todo) |
|
||||
| `kb_task_duplicate` | Duplicate a task (copy to triage) |
|
||||
| `kb_task_refine` | Create refinement task for follow-up work |
|
||||
| `kb_task_archive` | Archive a done task |
|
||||
| `kb_task_unarchive` | Restore an archived task |
|
||||
| `kb_task_delete` | Permanently delete a task |
|
||||
| `kb_task_import_github` | Batch import GitHub issues as tasks |
|
||||
| `kb_task_import_github_issue` | Import a single GitHub issue |
|
||||
| `kb_task_browse_github_issues` | Browse GitHub issues before importing |
|
||||
| `kb_task_plan` | Create task via AI-guided planning mode |
|
||||
| `kb_mission_create` | Create a new mission |
|
||||
| `kb_mission_list` | List all missions |
|
||||
| `kb_mission_show` | Show mission hierarchy |
|
||||
| `kb_mission_delete` | Delete a mission |
|
||||
| `kb_milestone_add` | Add a milestone to a mission |
|
||||
| `kb_slice_add` | Add a slice to a milestone |
|
||||
| `kb_feature_add` | Add a feature to a slice |
|
||||
| `kb_slice_activate` | Activate a pending slice |
|
||||
| `kb_feature_link_task` | Link a feature to a task |
|
||||
| `kb_agent_stop` | Stop (pause) a running agent |
|
||||
| `kb_agent_start` | Start (resume) a stopped agent |
|
||||
| `fn_task_create` | Create a new task in triage |
|
||||
| `fn_task_update` | Update task title, description, or dependencies |
|
||||
| `fn_task_list` | List all tasks grouped by column |
|
||||
| `fn_task_show` | Show full task details, steps, log |
|
||||
| `fn_task_attach` | Attach a file to a task |
|
||||
| `fn_task_pause` | Pause automation for a task |
|
||||
| `fn_task_unpause` | Resume automation for a task |
|
||||
| `fn_task_retry` | Retry a failed task (clears error, moves to todo) |
|
||||
| `fn_task_duplicate` | Duplicate a task (copy to triage) |
|
||||
| `fn_task_refine` | Create refinement task for follow-up work |
|
||||
| `fn_task_archive` | Archive a done task |
|
||||
| `fn_task_unarchive` | Restore an archived task |
|
||||
| `fn_task_delete` | Permanently delete a task |
|
||||
| `fn_task_import_github` | Batch import GitHub issues as tasks |
|
||||
| `fn_task_import_github_issue` | Import a single GitHub issue |
|
||||
| `fn_task_browse_github_issues` | Browse GitHub issues before importing |
|
||||
| `fn_task_plan` | Create task via AI-guided planning mode |
|
||||
| `fn_mission_create` | Create a new mission |
|
||||
| `fn_mission_list` | List all missions |
|
||||
| `fn_mission_show` | Show mission hierarchy |
|
||||
| `fn_mission_delete` | Delete a mission |
|
||||
| `fn_milestone_add` | Add a milestone to a mission |
|
||||
| `fn_slice_add` | Add a slice to a milestone |
|
||||
| `fn_feature_add` | Add a feature to a slice |
|
||||
| `fn_slice_activate` | Activate a pending slice |
|
||||
| `fn_feature_link_task` | Link a feature to a task |
|
||||
| `fn_agent_stop` | Stop (pause) a running agent |
|
||||
| `fn_agent_start` | Start (resume) a stopped agent |
|
||||
|
||||
## CLI Commands (fn)
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ The executor agent follows this specification step by step.
|
||||
|
||||
**Using AI-guided planning:**
|
||||
|
||||
For complex or vague ideas, use `kb_task_plan`:
|
||||
For complex or vague ideas, use `fn_task_plan`:
|
||||
```
|
||||
kb_task_plan({ description: "Build a notification system for the app" })
|
||||
fn_task_plan({ description: "Build a notification system for the app" })
|
||||
```
|
||||
|
||||
The planning mode will:
|
||||
@@ -65,38 +65,38 @@ For large-scale projects spanning multiple tasks, use the mission hierarchy:
|
||||
|
||||
1. **Create a mission** — The high-level objective
|
||||
```
|
||||
kb_mission_create({ title: "Build Authentication System", description: "Complete auth with login, signup, password reset, and OAuth" })
|
||||
fn_mission_create({ title: "Build Authentication System", description: "Complete auth with login, signup, password reset, and OAuth" })
|
||||
```
|
||||
|
||||
2. **Add milestones** — Major phases
|
||||
```
|
||||
kb_milestone_add({ missionId: "M-001", title: "Database Schema" })
|
||||
kb_milestone_add({ missionId: "M-001", title: "API Endpoints" })
|
||||
kb_milestone_add({ missionId: "M-001", title: "UI Integration" })
|
||||
fn_milestone_add({ missionId: "M-001", title: "Database Schema" })
|
||||
fn_milestone_add({ missionId: "M-001", title: "API Endpoints" })
|
||||
fn_milestone_add({ missionId: "M-001", title: "UI Integration" })
|
||||
```
|
||||
|
||||
3. **Add slices** — Parallel work units within milestones
|
||||
```
|
||||
kb_slice_add({ milestoneId: "MS-001", title: "User Tables" })
|
||||
kb_slice_add({ milestoneId: "MS-001", title: "Token Storage" })
|
||||
fn_slice_add({ milestoneId: "MS-001", title: "User Tables" })
|
||||
fn_slice_add({ milestoneId: "MS-001", title: "Token Storage" })
|
||||
```
|
||||
|
||||
4. **Add features** — Individual deliverables
|
||||
```
|
||||
kb_feature_add({ sliceId: "SL-001", title: "User model", description: "Create user table with email, password hash, timestamps" })
|
||||
kb_feature_add({ sliceId: "SL-001", title: "Session table", description: "Create session table with token, expiry, user FK" })
|
||||
fn_feature_add({ sliceId: "SL-001", title: "User model", description: "Create user table with email, password hash, timestamps" })
|
||||
fn_feature_add({ sliceId: "SL-001", title: "Session table", description: "Create session table with token, expiry, user FK" })
|
||||
```
|
||||
|
||||
5. **Activate a slice** — Enable it for implementation
|
||||
```
|
||||
kb_slice_activate({ id: "SL-001" })
|
||||
fn_slice_activate({ id: "SL-001" })
|
||||
```
|
||||
|
||||
6. **Link features to tasks** — Connect features to kb tasks
|
||||
```
|
||||
kb_task_create({ description: "Create user model with email, password hash, and timestamps" })
|
||||
fn_task_create({ description: "Create user model with email, password hash, and timestamps" })
|
||||
# → Created KB-101
|
||||
kb_feature_link_task({ featureId: "F-001", taskId: "KB-101" })
|
||||
fn_feature_link_task({ featureId: "F-001", taskId: "KB-101" })
|
||||
```
|
||||
|
||||
**Mission status flows automatically:**
|
||||
@@ -109,7 +109,7 @@ For large-scale projects spanning multiple tasks, use the mission hierarchy:
|
||||
|
||||
**Viewing mission progress:**
|
||||
```
|
||||
kb_mission_show({ id: "M-001" })
|
||||
fn_mission_show({ id: "M-001" })
|
||||
```
|
||||
Shows the full hierarchy with status icons:
|
||||
- `●` active, `○` pending, `✓` complete, `⚠` blocked
|
||||
|
||||
@@ -17,7 +17,7 @@ Triage → Todo → In Progress → In Review → Done → Archived
|
||||
Each column transition is driven by the AI engine or user action:
|
||||
|
||||
**Triage (specification)**
|
||||
- Task enters triage when created via `kb_task_create`
|
||||
- Task enters triage when created via `fn_task_create`
|
||||
- The **TriageProcessor** reads the project context and writes a full PROMPT.md specification
|
||||
- Specification includes: steps, file scope, acceptance criteria, review level, size estimate
|
||||
- If `requirePlanApproval` is enabled, task stays in triage as "awaiting-approval" until manually approved
|
||||
@@ -49,12 +49,12 @@ Each column transition is driven by the AI engine or user action:
|
||||
|
||||
**Done**
|
||||
- Work is merged to main branch
|
||||
- Task is available for archival via `kb_task_archive`
|
||||
- Can be refined with `kb_task_refine` to create follow-up work
|
||||
- Task is available for archival via `fn_task_archive`
|
||||
- Can be refined with `fn_task_refine` to create follow-up work
|
||||
|
||||
**Archived**
|
||||
- Removed from active board view
|
||||
- Can be restored with `kb_task_unarchive`
|
||||
- Can be restored with `fn_task_unarchive`
|
||||
- Can be cleaned up to free disk space (removes task directory, keeps metadata)
|
||||
|
||||
**Task statuses (within any column):**
|
||||
@@ -63,7 +63,7 @@ Each column transition is driven by the AI engine or user action:
|
||||
|--------|---------|
|
||||
| (none) | Normal state |
|
||||
| `paused` | Automation suspended — scheduler/executor skip this task |
|
||||
| `failed` | Execution error — use `kb_task_retry` to reset |
|
||||
| `failed` | Execution error — use `fn_task_retry` to reset |
|
||||
| `awaiting-approval` | Spec complete, waiting for manual approval (triage only) |
|
||||
|
||||
**Review levels:**
|
||||
@@ -82,9 +82,9 @@ The AI triage agent sets the review level based on task complexity and risk asse
|
||||
- Tasks can depend on other tasks (by task ID)
|
||||
- Dependent tasks wait in todo until all dependencies are in **done** or **archived**
|
||||
- Circular dependencies are prevented
|
||||
- Use `depends` parameter on `kb_task_create` to declare dependencies
|
||||
- Use `depends` parameter on `fn_task_create` to declare dependencies
|
||||
|
||||
**Interpreting `kb_task_show` output:**
|
||||
**Interpreting `fn_task_show` output:**
|
||||
|
||||
```
|
||||
KB-042: Fix login validation
|
||||
|
||||
@@ -11,7 +11,7 @@ Guide the agent through creating, viewing, and managing tasks on the Fusion boar
|
||||
|
||||
**Creating a task:**
|
||||
|
||||
1. Use `kb_task_create` with a clear, descriptive message
|
||||
1. Use `fn_task_create` with a clear, descriptive message
|
||||
- Include the problem AND the desired outcome
|
||||
- Be specific — the AI triage agent uses your description to write the specification
|
||||
- Optionally add dependencies with the `depends` parameter
|
||||
@@ -25,7 +25,7 @@ Guide the agent through creating, viewing, and managing tasks on the Fusion boar
|
||||
|
||||
Example:
|
||||
```
|
||||
kb_task_create({
|
||||
fn_task_create({
|
||||
description: "The login form doesn't validate email format before submission. Add client-side email validation that shows an inline error message when the email is invalid. Use the existing form validation pattern from the signup form.",
|
||||
depends: ["KB-042"]
|
||||
})
|
||||
@@ -33,21 +33,21 @@ kb_task_create({
|
||||
|
||||
**AI-guided planning for complex tasks:**
|
||||
|
||||
Use `kb_task_plan` when the idea is vague or complex. The AI will:
|
||||
Use `fn_task_plan` when the idea is vague or complex. The AI will:
|
||||
1. Ask clarifying questions about scope, constraints, and approach
|
||||
2. Help break down the work into actionable pieces
|
||||
3. Create the task with a refined description
|
||||
|
||||
**Listing tasks:**
|
||||
|
||||
Use `kb_task_list` to see the board:
|
||||
Use `fn_task_list` to see the board:
|
||||
- No params → all tasks grouped by column
|
||||
- `column: "in-progress"` → filter to specific column
|
||||
- `limit: 5` → limit tasks shown per column
|
||||
|
||||
**Viewing task details:**
|
||||
|
||||
Use `kb_task_show` with the task ID:
|
||||
Use `fn_task_show` with the task ID:
|
||||
- Shows steps with progress indicators (✓ done, ▸ in-progress, – skipped)
|
||||
- Shows prompt preview (truncated to 500 chars)
|
||||
- Shows recent log entries (last 5)
|
||||
@@ -56,29 +56,29 @@ Use `kb_task_show` with the task ID:
|
||||
|
||||
| Action | Tool | Notes |
|
||||
|--------|------|-------|
|
||||
| Pause automation | `kb_task_pause` | Stops scheduler and executor from touching the task |
|
||||
| Resume automation | `kb_task_unpause` | Re-enables automated processing |
|
||||
| Retry failed task | `kb_task_retry` | Clears error, moves back to todo |
|
||||
| Duplicate task | `kb_task_duplicate` | Creates fresh copy in triage |
|
||||
| Refine completed task | `kb_task_refine` | Creates follow-up task with dependency on original |
|
||||
| Archive done task | `kb_task_archive` | Moves from done → archived |
|
||||
| Restore archived task | `kb_task_unarchive` | Moves from archived → done |
|
||||
| Delete task | `kb_task_delete` | Permanent — cannot be undone |
|
||||
| Pause automation | `fn_task_pause` | Stops scheduler and executor from touching the task |
|
||||
| Resume automation | `fn_task_unpause` | Re-enables automated processing |
|
||||
| Retry failed task | `fn_task_retry` | Clears error, moves back to todo |
|
||||
| Duplicate task | `fn_task_duplicate` | Creates fresh copy in triage |
|
||||
| Refine completed task | `fn_task_refine` | Creates follow-up task with dependency on original |
|
||||
| Archive done task | `fn_task_archive` | Moves from done → archived |
|
||||
| Restore archived task | `fn_task_unarchive` | Moves from archived → done |
|
||||
| Delete task | `fn_task_delete` | Permanent — cannot be undone |
|
||||
|
||||
**Attaching files:**
|
||||
|
||||
Use `kb_task_attach` with the task ID and file path:
|
||||
Use `fn_task_attach` with the task ID and file path:
|
||||
- Supports images: png, jpg, gif, webp
|
||||
- Supports text: txt, log, json, yaml, csv, xml
|
||||
- Files are copied to `.fusion/tasks/{ID}/attachments/`
|
||||
|
||||
**Importing from GitHub:**
|
||||
|
||||
1. Browse issues first: `kb_task_browse_github_issues({ owner: "org", repo: "repo" })`
|
||||
1. Browse issues first: `fn_task_browse_github_issues({ owner: "org", repo: "repo" })`
|
||||
- Shows issue numbers, titles, labels
|
||||
- Marks already-imported issues with ✓
|
||||
2. Import specific issue: `kb_task_import_github_issue({ owner: "org", repo: "repo", issueNumber: 42 })`
|
||||
3. Bulk import: `kb_task_import_github({ ownerRepo: "org/repo", limit: 20 })`
|
||||
2. Import specific issue: `fn_task_import_github_issue({ owner: "org", repo: "repo", issueNumber: 42 })`
|
||||
3. Bulk import: `fn_task_import_github({ ownerRepo: "org/repo", limit: 20 })`
|
||||
|
||||
</process>
|
||||
|
||||
|
||||
@@ -74,36 +74,36 @@ describe("fn pi extension", () => {
|
||||
describe("registration", () => {
|
||||
it("registers all expected tools", () => {
|
||||
const expected = [
|
||||
"kb_task_create",
|
||||
"kb_task_update",
|
||||
"kb_task_list",
|
||||
"kb_task_show",
|
||||
"kb_task_attach",
|
||||
"kb_task_pause",
|
||||
"kb_task_unpause",
|
||||
"kb_task_retry",
|
||||
"kb_task_duplicate",
|
||||
"kb_task_refine",
|
||||
"kb_task_import_github",
|
||||
"kb_task_import_github_issue",
|
||||
"kb_task_browse_github_issues",
|
||||
"kb_task_archive",
|
||||
"kb_task_unarchive",
|
||||
"kb_task_delete",
|
||||
"kb_task_plan",
|
||||
"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_import_github",
|
||||
"fn_task_import_github_issue",
|
||||
"fn_task_browse_github_issues",
|
||||
"fn_task_archive",
|
||||
"fn_task_unarchive",
|
||||
"fn_task_delete",
|
||||
"fn_task_plan",
|
||||
// Mission tools
|
||||
"kb_mission_create",
|
||||
"kb_mission_list",
|
||||
"kb_mission_show",
|
||||
"kb_mission_delete",
|
||||
"kb_milestone_add",
|
||||
"kb_slice_add",
|
||||
"kb_feature_add",
|
||||
"kb_slice_activate",
|
||||
"kb_feature_link_task",
|
||||
"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
|
||||
"kb_agent_stop",
|
||||
"kb_agent_start",
|
||||
"fn_agent_stop",
|
||||
"fn_agent_start",
|
||||
];
|
||||
|
||||
for (const name of expected) {
|
||||
@@ -113,10 +113,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("does not register engine-internal tools", () => {
|
||||
expect(api.tools.has("kb_task_move")).toBe(false);
|
||||
expect(api.tools.has("kb_task_update_step")).toBe(false);
|
||||
expect(api.tools.has("kb_task_log")).toBe(false);
|
||||
expect(api.tools.has("kb_task_merge")).toBe(false);
|
||||
expect(api.tools.has("fn_task_move")).toBe(false);
|
||||
expect(api.tools.has("fn_task_update_step")).toBe(false);
|
||||
expect(api.tools.has("fn_task_log")).toBe(false);
|
||||
expect(api.tools.has("fn_task_merge")).toBe(false);
|
||||
});
|
||||
|
||||
it("registers the /fn command", () => {
|
||||
@@ -129,9 +129,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_create", () => {
|
||||
describe("fn_task_create", () => {
|
||||
it("creates a task and returns its ID", async () => {
|
||||
const tool = api.tools.get("kb_task_create")!;
|
||||
const tool = api.tools.get("fn_task_create")!;
|
||||
const result = await tool.execute(
|
||||
"call-1",
|
||||
{ description: "Fix the login button" },
|
||||
@@ -148,7 +148,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("creates a task with dependencies", async () => {
|
||||
const tool = api.tools.get("kb_task_create")!;
|
||||
const tool = api.tools.get("fn_task_create")!;
|
||||
await tool.execute(
|
||||
"call-1",
|
||||
{ description: "First task" },
|
||||
@@ -171,7 +171,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("creates a task with assigned agent ID", async () => {
|
||||
const tool = api.tools.get("kb_task_create")!;
|
||||
const tool = api.tools.get("fn_task_create")!;
|
||||
const result = await tool.execute(
|
||||
"call-1",
|
||||
{ description: "Task with assignee", agentId: "agent-abc123" },
|
||||
@@ -185,13 +185,13 @@ describe("fn pi extension", () => {
|
||||
expect(result.content[0].text).toContain("Assigned to: agent-abc123");
|
||||
|
||||
// Verify persistence via show
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const show = await showTool.execute("s1", { id: "FN-001" }, undefined, undefined, makeCtx(tmpDir));
|
||||
expect(show.details.task.assignedAgentId).toBe("agent-abc123");
|
||||
});
|
||||
|
||||
it("creates a task without assigned agent ID by default", async () => {
|
||||
const tool = api.tools.get("kb_task_create")!;
|
||||
const tool = api.tools.get("fn_task_create")!;
|
||||
const result = await tool.execute(
|
||||
"call-1",
|
||||
{ description: "Task without assignee" },
|
||||
@@ -206,12 +206,12 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_update", () => {
|
||||
describe("fn_task_update", () => {
|
||||
it("updates task title", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute("c1", { description: "Original" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-001", title: "New Title" },
|
||||
@@ -225,16 +225,16 @@ describe("fn pi extension", () => {
|
||||
expect(result.details.updatedFields).toEqual(["title"]);
|
||||
|
||||
// Verify via show
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const show = await showTool.execute("s1", { id: "FN-001" }, undefined, undefined, makeCtx(tmpDir));
|
||||
expect(show.content[0].text).toContain("New Title");
|
||||
});
|
||||
|
||||
it("updates task description", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute("c1", { description: "Original desc" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-001", description: "Updated description" },
|
||||
@@ -248,11 +248,11 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("updates task dependencies", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute("c1", { description: "First" }, undefined, undefined, makeCtx(tmpDir));
|
||||
await createTool.execute("c2", { description: "Second" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-002", depends: ["FN-001"] },
|
||||
@@ -266,10 +266,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("updates multiple fields at once", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute("c1", { description: "Original" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-001", title: "New Title", description: "New desc", depends: [] },
|
||||
@@ -282,10 +282,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("updates task assigned agent ID", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute("c1", { description: "Original" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-001", agentId: "agent-abc123" },
|
||||
@@ -298,13 +298,13 @@ describe("fn pi extension", () => {
|
||||
expect(result.content[0].text).toContain("agentId");
|
||||
expect(result.details.updatedFields).toEqual(["agentId"]);
|
||||
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const show = await showTool.execute("s1", { id: "FN-001" }, undefined, undefined, makeCtx(tmpDir));
|
||||
expect(show.details.task.assignedAgentId).toBe("agent-abc123");
|
||||
});
|
||||
|
||||
it("clears task assigned agent ID with null", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "Original", agentId: "agent-abc123" },
|
||||
@@ -313,7 +313,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-001", agentId: null },
|
||||
@@ -326,13 +326,13 @@ describe("fn pi extension", () => {
|
||||
expect(result.content[0].text).toContain("agentId");
|
||||
expect(result.details.updatedFields).toEqual(["agentId"]);
|
||||
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const show = await showTool.execute("s1", { id: "FN-001" }, undefined, undefined, makeCtx(tmpDir));
|
||||
expect(show.details.task.assignedAgentId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns error when task not found", async () => {
|
||||
const updateTool = api.tools.get("kb_task_update")!;
|
||||
const updateTool = api.tools.get("fn_task_update")!;
|
||||
const result = await updateTool.execute(
|
||||
"u1",
|
||||
{ id: "FN-999", title: "Nope" },
|
||||
@@ -346,9 +346,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_list", () => {
|
||||
describe("fn_task_list", () => {
|
||||
it("returns empty message when no tasks", async () => {
|
||||
const tool = api.tools.get("kb_task_list")!;
|
||||
const tool = api.tools.get("fn_task_list")!;
|
||||
const result = await tool.execute(
|
||||
"call-1",
|
||||
{},
|
||||
@@ -362,7 +362,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("lists tasks grouped by column", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "Task A" },
|
||||
@@ -378,7 +378,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const listTool = api.tools.get("kb_task_list")!;
|
||||
const listTool = api.tools.get("fn_task_list")!;
|
||||
const result = await listTool.execute(
|
||||
"call-1",
|
||||
{},
|
||||
@@ -394,7 +394,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("filters by column", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "Task A" },
|
||||
@@ -403,7 +403,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const listTool = api.tools.get("kb_task_list")!;
|
||||
const listTool = api.tools.get("fn_task_list")!;
|
||||
const triageResult = await listTool.execute(
|
||||
"call-1",
|
||||
{ column: "triage" },
|
||||
@@ -425,7 +425,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("respects per-column limit", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await createTool.execute(
|
||||
`c${i}`,
|
||||
@@ -436,7 +436,7 @@ describe("fn pi extension", () => {
|
||||
);
|
||||
}
|
||||
|
||||
const listTool = api.tools.get("kb_task_list")!;
|
||||
const listTool = api.tools.get("fn_task_list")!;
|
||||
const result = await listTool.execute(
|
||||
"call-1",
|
||||
{ limit: 2 },
|
||||
@@ -453,9 +453,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_show", () => {
|
||||
describe("fn_task_show", () => {
|
||||
it("shows task details", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "Implement caching layer" },
|
||||
@@ -464,7 +464,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const result = await showTool.execute(
|
||||
"call-1",
|
||||
{ id: "FN-001" },
|
||||
@@ -481,9 +481,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_attach", () => {
|
||||
describe("fn_task_attach", () => {
|
||||
it("attaches a file to a task", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "A task" },
|
||||
@@ -495,7 +495,7 @@ describe("fn pi extension", () => {
|
||||
const testFile = join(tmpDir, "test.txt");
|
||||
await writeFile(testFile, "hello world");
|
||||
|
||||
const attachTool = api.tools.get("kb_task_attach")!;
|
||||
const attachTool = api.tools.get("fn_task_attach")!;
|
||||
const result = await attachTool.execute(
|
||||
"call-1",
|
||||
{ id: "FN-001", path: "test.txt" },
|
||||
@@ -511,7 +511,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("rejects unsupported file types", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "A task" },
|
||||
@@ -523,7 +523,7 @@ describe("fn pi extension", () => {
|
||||
const testFile = join(tmpDir, "file.exe");
|
||||
await writeFile(testFile, "binary");
|
||||
|
||||
const attachTool = api.tools.get("kb_task_attach")!;
|
||||
const attachTool = api.tools.get("fn_task_attach")!;
|
||||
await expect(
|
||||
attachTool.execute(
|
||||
"call-1",
|
||||
@@ -536,9 +536,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_task_pause / unpause", () => {
|
||||
describe("fn_task_pause / unpause", () => {
|
||||
it("pauses and unpauses a task", async () => {
|
||||
const createTool = api.tools.get("kb_task_create")!;
|
||||
const createTool = api.tools.get("fn_task_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ description: "A task" },
|
||||
@@ -547,7 +547,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const pauseTool = api.tools.get("kb_task_pause")!;
|
||||
const pauseTool = api.tools.get("fn_task_pause")!;
|
||||
const pauseResult = await pauseTool.execute(
|
||||
"call-1",
|
||||
{ id: "FN-001" },
|
||||
@@ -558,7 +558,7 @@ describe("fn pi extension", () => {
|
||||
expect(pauseResult.content[0].text).toContain("Paused FN-001");
|
||||
|
||||
// Verify it's paused
|
||||
const showTool = api.tools.get("kb_task_show")!;
|
||||
const showTool = api.tools.get("fn_task_show")!;
|
||||
const show = await showTool.execute(
|
||||
"call-2",
|
||||
{ id: "FN-001" },
|
||||
@@ -569,7 +569,7 @@ describe("fn pi extension", () => {
|
||||
expect(show.content[0].text).toContain("PAUSED");
|
||||
|
||||
// Unpause
|
||||
const unpauseTool = api.tools.get("kb_task_unpause")!;
|
||||
const unpauseTool = api.tools.get("fn_task_unpause")!;
|
||||
const unpauseResult = await unpauseTool.execute(
|
||||
"call-3",
|
||||
{ id: "FN-001" },
|
||||
@@ -581,9 +581,9 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_mission_create", () => {
|
||||
describe("fn_mission_create", () => {
|
||||
it("creates mission and returns mission data", async () => {
|
||||
const tool = api.tools.get("kb_mission_create")!;
|
||||
const tool = api.tools.get("fn_mission_create")!;
|
||||
const result = await tool.execute(
|
||||
"call-1",
|
||||
{ title: "Test Mission", description: "Test description", autoAdvance: true },
|
||||
@@ -601,10 +601,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_mission_list", () => {
|
||||
describe("fn_mission_list", () => {
|
||||
it("returns formatted list of missions", async () => {
|
||||
// First create a mission
|
||||
const createTool = api.tools.get("kb_mission_create")!;
|
||||
const createTool = api.tools.get("fn_mission_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
{ title: "Mission A" },
|
||||
@@ -613,7 +613,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const listTool = api.tools.get("kb_mission_list")!;
|
||||
const listTool = api.tools.get("fn_mission_list")!;
|
||||
const result = await listTool.execute(
|
||||
"call-1",
|
||||
{},
|
||||
@@ -628,10 +628,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_mission_show", () => {
|
||||
describe("fn_mission_show", () => {
|
||||
it("returns mission with hierarchy", async () => {
|
||||
// Create mission
|
||||
const createTool = api.tools.get("kb_mission_create")!;
|
||||
const createTool = api.tools.get("fn_mission_create")!;
|
||||
const created = await createTool.execute(
|
||||
"c1",
|
||||
{ title: "Test Mission" },
|
||||
@@ -640,7 +640,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const showTool = api.tools.get("kb_mission_show")!;
|
||||
const showTool = api.tools.get("fn_mission_show")!;
|
||||
const result = await showTool.execute(
|
||||
"call-1",
|
||||
{ id: created.details.missionId },
|
||||
@@ -654,7 +654,7 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("returns error when mission not found", async () => {
|
||||
const showTool = api.tools.get("kb_mission_show")!;
|
||||
const showTool = api.tools.get("fn_mission_show")!;
|
||||
const result = await showTool.execute(
|
||||
"call-1",
|
||||
{ id: "M-999" },
|
||||
@@ -668,10 +668,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_mission_delete", () => {
|
||||
describe("fn_mission_delete", () => {
|
||||
it("deletes mission and confirms", async () => {
|
||||
// Create mission
|
||||
const createTool = api.tools.get("kb_mission_create")!;
|
||||
const createTool = api.tools.get("fn_mission_create")!;
|
||||
const created = await createTool.execute(
|
||||
"c1",
|
||||
{ title: "Mission to Delete" },
|
||||
@@ -680,7 +680,7 @@ describe("fn pi extension", () => {
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
|
||||
const deleteTool = api.tools.get("kb_mission_delete")!;
|
||||
const deleteTool = api.tools.get("fn_mission_delete")!;
|
||||
const result = await deleteTool.execute(
|
||||
"call-1",
|
||||
{ id: created.details.missionId },
|
||||
@@ -694,10 +694,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_milestone_add", () => {
|
||||
describe("fn_milestone_add", () => {
|
||||
it("creates a milestone in the mission store", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
const result = await milestoneTool.execute(
|
||||
@@ -718,11 +718,11 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_slice_add", () => {
|
||||
describe("fn_slice_add", () => {
|
||||
it("creates a slice in the mission store", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
"ms1",
|
||||
@@ -750,12 +750,12 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_feature_add", () => {
|
||||
describe("fn_feature_add", () => {
|
||||
it("creates a feature in the mission store", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const featureTool = api.tools.get("kb_feature_add")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const featureTool = api.tools.get("fn_feature_add")!;
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
"ms1",
|
||||
@@ -790,12 +790,12 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_slice_activate", () => {
|
||||
describe("fn_slice_activate", () => {
|
||||
it("returns error when slice is already active", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const activateTool = api.tools.get("kb_slice_activate")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const activateTool = api.tools.get("fn_slice_activate")!;
|
||||
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
@@ -821,10 +821,10 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("activates slice and updates status", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const activateTool = api.tools.get("kb_slice_activate")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const activateTool = api.tools.get("fn_slice_activate")!;
|
||||
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
@@ -860,13 +860,13 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("kb_feature_link_task", () => {
|
||||
describe("fn_feature_link_task", () => {
|
||||
it("returns error when task is missing", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const featureTool = api.tools.get("kb_feature_add")!;
|
||||
const linkTool = api.tools.get("kb_feature_link_task")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const featureTool = api.tools.get("fn_feature_add")!;
|
||||
const linkTool = api.tools.get("fn_feature_link_task")!;
|
||||
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
@@ -904,12 +904,12 @@ describe("fn pi extension", () => {
|
||||
});
|
||||
|
||||
it("links feature to task", async () => {
|
||||
const missionTool = api.tools.get("kb_mission_create")!;
|
||||
const milestoneTool = api.tools.get("kb_milestone_add")!;
|
||||
const sliceTool = api.tools.get("kb_slice_add")!;
|
||||
const featureTool = api.tools.get("kb_feature_add")!;
|
||||
const createTaskTool = api.tools.get("kb_task_create")!;
|
||||
const linkTool = api.tools.get("kb_feature_link_task")!;
|
||||
const missionTool = api.tools.get("fn_mission_create")!;
|
||||
const milestoneTool = api.tools.get("fn_milestone_add")!;
|
||||
const sliceTool = api.tools.get("fn_slice_add")!;
|
||||
const featureTool = api.tools.get("fn_feature_add")!;
|
||||
const createTaskTool = api.tools.get("fn_task_create")!;
|
||||
const linkTool = api.tools.get("fn_feature_link_task")!;
|
||||
|
||||
const mission = await missionTool.execute("m1", { title: "Mission" }, undefined, undefined, makeCtx(tmpDir));
|
||||
const milestone = await milestoneTool.execute(
|
||||
|
||||
@@ -14,19 +14,19 @@ const extensionPath = resolve(cliRoot, "src/extension.ts");
|
||||
*/
|
||||
function getExtensionToolNames(): string[] {
|
||||
const src = readFileSync(extensionPath, "utf-8");
|
||||
const matches = [...src.matchAll(/name:\s*"(kb_[a-z_]+)"/g)];
|
||||
const matches = [...src.matchAll(/name:\s*"(fn_[a-z_]+)"/g)];
|
||||
return matches.map((m) => m[1]).sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract tool names documented in extension-tools.md (### kb_* headings).
|
||||
* Extract tool names documented in extension-tools.md (### fn_* headings).
|
||||
*/
|
||||
function getDocumentedToolNames(): string[] {
|
||||
const doc = readFileSync(
|
||||
resolve(skillDir, "references/extension-tools.md"),
|
||||
"utf-8",
|
||||
);
|
||||
const matches = [...doc.matchAll(/^### (kb_[a-z_]+)/gm)];
|
||||
const matches = [...doc.matchAll(/^### (fn_[a-z_]+)/gm)];
|
||||
return matches.map((m) => m[1]).sort();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ function getDocumentedToolNames(): string[] {
|
||||
*/
|
||||
function getSkillMdToolNames(): string[] {
|
||||
const doc = readFileSync(resolve(skillDir, "SKILL.md"), "utf-8");
|
||||
const matches = [...doc.matchAll(/`(kb_[a-z_]+)`/g)];
|
||||
const matches = [...doc.matchAll(/`(fn_[a-z_]+)`/g)];
|
||||
// Deduplicate
|
||||
return [...new Set(matches.map((m) => m[1]))].sort();
|
||||
}
|
||||
@@ -48,7 +48,7 @@ function getCapabilitiesToolNames(): string[] {
|
||||
resolve(skillDir, "references/fusion-capabilities.md"),
|
||||
"utf-8",
|
||||
);
|
||||
const matches = [...doc.matchAll(/\| `(kb_[a-z_]+)` \|/g)];
|
||||
const matches = [...doc.matchAll(/\| `(fn_[a-z_]+)` \|/g)];
|
||||
return matches.map((m) => m[1]).sort();
|
||||
}
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@ export async function runTaskImportGitHubInteractive(
|
||||
const match = ownerRepo.match(/^([^/]+)\/([^/]+)$/);
|
||||
if (!match) {
|
||||
console.error(`Invalid owner/repo format: ${ownerRepo}`);
|
||||
console.error(`Expected format: owner/repo (e.g., dustinbyrne/kb)`);
|
||||
console.error(`Expected format: owner/repo (e.g., dustinbyrne/fusion)`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ export async function fetchGitHubIssues(
|
||||
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": "fn/1.0",
|
||||
};
|
||||
|
||||
if (token) {
|
||||
@@ -913,7 +913,7 @@ export async function runTaskImportFromGitHub(
|
||||
const match = ownerRepo.match(/^([^/]+)\/([^/]+)$/);
|
||||
if (!match) {
|
||||
console.error(`Invalid owner/repo format: ${ownerRepo}`);
|
||||
console.error(`Expected format: owner/repo (e.g., dustinbyrne/kb)`);
|
||||
console.error(`Expected format: owner/repo (e.g., dustinbyrne/fusion)`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,10 @@ function formatTaskLine(t: Task): string {
|
||||
// ── Extension entry point ──────────────────────────────────────────
|
||||
|
||||
export default function kbExtension(pi: ExtensionAPI) {
|
||||
// ── kb_task_create ───────────────────────────────────────────────
|
||||
// ── fn_task_create ───────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_create",
|
||||
name: "fn_task_create",
|
||||
label: "KB: Create Task",
|
||||
description:
|
||||
"Create a new task on the Fusion task board. The task enters the triage column " +
|
||||
@@ -65,7 +65,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
"file scope, and acceptance criteria.",
|
||||
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.",
|
||||
"Use fn_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.",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
@@ -121,17 +121,17 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_update ────────────────────────────────────────────────
|
||||
// ── fn_task_update ────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_update",
|
||||
name: "fn_task_update",
|
||||
label: "KB: Update Task",
|
||||
description:
|
||||
"Update fields on an existing task. Supports modifying the title, " +
|
||||
"description, dependencies, and assigned agent after task creation.",
|
||||
promptSnippet: "Update fields on an existing Fusion task",
|
||||
promptGuidelines: [
|
||||
"Use kb_task_update to modify task title, description, dependencies, or assigned agent after creation.",
|
||||
"Use fn_task_update to modify task title, description, dependencies, or assigned agent after creation.",
|
||||
"At least one field must be provided to update.",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
@@ -211,10 +211,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_list ─────────────────────────────────────────────────
|
||||
// ── fn_task_list ─────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_list",
|
||||
name: "fn_task_list",
|
||||
label: "KB: List Tasks",
|
||||
description: "List all tasks on the Fusion board, grouped by column.",
|
||||
promptSnippet: "List all tasks on the Fusion board grouped by column",
|
||||
@@ -269,10 +269,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_show ─────────────────────────────────────────────────
|
||||
// ── fn_task_show ─────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_show",
|
||||
name: "fn_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 Fusion task",
|
||||
@@ -348,10 +348,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_attach ───────────────────────────────────────────────
|
||||
// ── fn_task_attach ───────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_attach",
|
||||
name: "fn_task_attach",
|
||||
label: "KB: Attach File",
|
||||
description:
|
||||
"Attach a file to a task. Supports images (png, jpg, gif, webp) and " +
|
||||
@@ -399,10 +399,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_pause ────────────────────────────────────────────────
|
||||
// ── fn_task_pause ────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_pause",
|
||||
name: "fn_task_pause",
|
||||
label: "KB: Pause Task",
|
||||
description:
|
||||
"Pause a task — stops all automated agent and scheduler interaction for this task.",
|
||||
@@ -422,10 +422,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_unpause ──────────────────────────────────────────────
|
||||
// ── fn_task_unpause ──────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_unpause",
|
||||
name: "fn_task_unpause",
|
||||
label: "KB: Unpause Task",
|
||||
description:
|
||||
"Unpause a task — resumes automated agent and scheduler interaction.",
|
||||
@@ -445,10 +445,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_retry ────────────────────────────────────────────────
|
||||
// ── fn_task_retry ────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_retry",
|
||||
name: "fn_task_retry",
|
||||
label: "KB: Retry Task",
|
||||
description:
|
||||
"Retry a failed task — clears the error state and moves it back to the todo column for re-execution.",
|
||||
@@ -502,10 +502,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_duplicate ─────────────────────────────────────────────
|
||||
// ── fn_task_duplicate ─────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_duplicate",
|
||||
name: "fn_task_duplicate",
|
||||
label: "KB: Duplicate Task",
|
||||
description:
|
||||
"Duplicate an existing task, creating a fresh copy in triage. " +
|
||||
@@ -532,10 +532,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_refine ──────────────────────────────────────────────
|
||||
// ── fn_task_refine ──────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_refine",
|
||||
name: "fn_task_refine",
|
||||
label: "KB: Refine Task",
|
||||
description:
|
||||
"Request a refinement of a completed or in-review task. " +
|
||||
@@ -570,10 +570,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_archive ───────────────────────────────────────────────
|
||||
// ── fn_task_archive ───────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_archive",
|
||||
name: "fn_task_archive",
|
||||
label: "KB: Archive Task",
|
||||
description:
|
||||
"Archive a done task (move from done → archived). " +
|
||||
@@ -599,10 +599,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_unarchive ─────────────────────────────────────────────
|
||||
// ── fn_task_unarchive ─────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_unarchive",
|
||||
name: "fn_task_unarchive",
|
||||
label: "KB: Unarchive Task",
|
||||
description:
|
||||
"Unarchive an archived task (move from archived → done). " +
|
||||
@@ -627,10 +627,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_delete ─────────────────────────────────────────────────
|
||||
// ── fn_task_delete ─────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_delete",
|
||||
name: "fn_task_delete",
|
||||
label: "KB: Delete Task",
|
||||
description:
|
||||
"Permanently delete a task from the Fusion board. " +
|
||||
@@ -656,10 +656,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_import_github ─────────────────────────────────────────
|
||||
// ── fn_task_import_github ─────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_import_github",
|
||||
name: "fn_task_import_github",
|
||||
label: "KB: Import GitHub Issues",
|
||||
description:
|
||||
"Import GitHub issues as Fusion tasks. Fetches open issues from a repository " +
|
||||
@@ -675,7 +675,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
],
|
||||
parameters: Type.Object({
|
||||
ownerRepo: Type.String({
|
||||
description: "Repository in owner/repo format (e.g., 'dustinbyrne/kb')",
|
||||
description: "Repository in owner/repo format (e.g., 'dustinbyrne/fusion')",
|
||||
pattern: "^[^/]+/[^/]+$",
|
||||
}),
|
||||
limit: Type.Optional(
|
||||
@@ -745,11 +745,11 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_import_github_issue ───────────────────────────────────
|
||||
// ── fn_task_import_github_issue ───────────────────────────────────
|
||||
// Import a single GitHub issue by its issue number
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_import_github_issue",
|
||||
name: "fn_task_import_github_issue",
|
||||
label: "KB: Import GitHub Issue",
|
||||
description:
|
||||
"Import a specific GitHub issue as a Fusion task. Fetches the issue by number " +
|
||||
@@ -766,7 +766,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
description: "Repository owner (e.g., 'dustinbyrne')",
|
||||
}),
|
||||
repo: Type.String({
|
||||
description: "Repository name (e.g., 'kb')",
|
||||
description: "Repository name (e.g., 'fusion')",
|
||||
}),
|
||||
issueNumber: Type.Number({
|
||||
description: "GitHub issue number to import",
|
||||
@@ -867,15 +867,15 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_browse_github_issues ──────────────────────────────────
|
||||
// ── fn_task_browse_github_issues ──────────────────────────────────
|
||||
// Browse available GitHub issues before importing
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_browse_github_issues",
|
||||
name: "fn_task_browse_github_issues",
|
||||
label: "KB: Browse GitHub Issues",
|
||||
description:
|
||||
"List open GitHub issues from a repository to browse before importing. " +
|
||||
"Returns issue numbers, titles, and URLs for selection. Use with kb_task_import_github_issue " +
|
||||
"Returns issue numbers, titles, and URLs for selection. Use with fn_task_import_github_issue " +
|
||||
"to import specific issues by number.",
|
||||
promptSnippet: "Browse open GitHub issues in a repository",
|
||||
promptGuidelines: [
|
||||
@@ -890,7 +890,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
description: "Repository owner (e.g., 'dustinbyrne')",
|
||||
}),
|
||||
repo: Type.String({
|
||||
description: "Repository name (e.g., 'kb')",
|
||||
description: "Repository name (e.g., 'fusion')",
|
||||
}),
|
||||
limit: Type.Optional(
|
||||
Type.Number({
|
||||
@@ -990,7 +990,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
lines.push(` ${issue.html_url}`);
|
||||
}
|
||||
|
||||
lines.push("\nUse kb_task_import_github_issue to import a specific issue by number.");
|
||||
lines.push("\nUse fn_task_import_github_issue to import a specific issue by number.");
|
||||
|
||||
return {
|
||||
content: [{ type: "text", text: lines.join("\n") }],
|
||||
@@ -1008,11 +1008,11 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_task_plan ────────────────────────────────────────────────
|
||||
// ── fn_task_plan ────────────────────────────────────────────────
|
||||
// Create a task via AI-guided planning mode
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_task_plan",
|
||||
name: "fn_task_plan",
|
||||
label: "KB: Plan Task",
|
||||
description:
|
||||
"Create a task via AI-guided planning mode — interactive conversation to refine your idea into a well-specified task.",
|
||||
@@ -1082,10 +1082,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
// ── Mission Tools ───────────────────────────────────────────────
|
||||
// Mission hierarchy management for multi-phase project planning
|
||||
|
||||
// ── kb_mission_create ───────────────────────────────────────────
|
||||
// ── fn_mission_create ───────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_mission_create",
|
||||
name: "fn_mission_create",
|
||||
label: "KB: Create Mission",
|
||||
description:
|
||||
"Create a new mission — a high-level objective that can span multiple milestones. " +
|
||||
@@ -1138,17 +1138,17 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_mission_list ──────────────────────────────────────────────
|
||||
// ── fn_mission_list ──────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_mission_list",
|
||||
name: "fn_mission_list",
|
||||
label: "KB: List Missions",
|
||||
description: "List all missions with their current status.",
|
||||
promptSnippet: "List all missions",
|
||||
promptGuidelines: [
|
||||
"Use to see all missions and their current status",
|
||||
"Missions are grouped by status (active, planning, complete, etc.)",
|
||||
"Use before kb_mission_show to find a specific mission ID",
|
||||
"Use before fn_mission_show to find a specific mission ID",
|
||||
],
|
||||
parameters: Type.Object({}),
|
||||
|
||||
@@ -1192,10 +1192,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_mission_show ──────────────────────────────────────────────
|
||||
// ── fn_mission_show ──────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_mission_show",
|
||||
name: "fn_mission_show",
|
||||
label: "KB: Show Mission",
|
||||
description: "Show mission details with full hierarchy: milestones → slices → features.",
|
||||
promptSnippet: "Show mission details with hierarchy",
|
||||
@@ -1257,10 +1257,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_mission_delete ───────────────────────────────────────────
|
||||
// ── fn_mission_delete ───────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_mission_delete",
|
||||
name: "fn_mission_delete",
|
||||
label: "KB: Delete Mission",
|
||||
description: "Delete a mission and all its milestones, slices, and features. Cannot be undone.",
|
||||
promptSnippet: "Delete a mission and all its contents",
|
||||
@@ -1295,10 +1295,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_milestone_add ────────────────────────────────────────────
|
||||
// ── fn_milestone_add ────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_milestone_add",
|
||||
name: "fn_milestone_add",
|
||||
label: "KB: Add Milestone",
|
||||
description: "Add a milestone to a mission. Milestones represent phases of work.",
|
||||
promptSnippet: "Add a milestone to a mission",
|
||||
@@ -1339,10 +1339,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_slice_add ─────────────────────────────────────────────────
|
||||
// ── fn_slice_add ─────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_slice_add",
|
||||
name: "fn_slice_add",
|
||||
label: "KB: Add Slice",
|
||||
description: "Add a slice to a milestone. Slices are work units that can be activated for implementation.",
|
||||
promptSnippet: "Add a work slice to a milestone",
|
||||
@@ -1384,17 +1384,17 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_feature_add ────────────────────────────────────────────────
|
||||
// ── fn_feature_add ────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_feature_add",
|
||||
name: "fn_feature_add",
|
||||
label: "KB: Add Feature",
|
||||
description: "Add a feature to a slice. Features are deliverables that can be linked to tasks.",
|
||||
promptSnippet: "Add a feature to a slice",
|
||||
promptGuidelines: [
|
||||
"Features represent deliverables within a slice",
|
||||
"Features start as 'defined' and progress through 'triaged' → 'in-progress' → 'done'",
|
||||
"Link features to tasks using kb_feature_link_task",
|
||||
"Link features to tasks using fn_feature_link_task",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
sliceId: Type.String({ description: "Parent slice ID (e.g., SL-001)" }),
|
||||
@@ -1433,10 +1433,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_slice_activate ────────────────────────────────────────────
|
||||
// ── fn_slice_activate ────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_slice_activate",
|
||||
name: "fn_slice_activate",
|
||||
label: "KB: Activate Slice",
|
||||
description:
|
||||
"Activate a pending slice for implementation. " +
|
||||
@@ -1486,10 +1486,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_feature_link_task ──────────────────────────────────────────
|
||||
// ── fn_feature_link_task ──────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_feature_link_task",
|
||||
name: "fn_feature_link_task",
|
||||
label: "KB: Link Feature to Task",
|
||||
description:
|
||||
"Link a feature to a fn task for implementation. " +
|
||||
@@ -1545,10 +1545,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_agent_stop ─────────────────────────────────────────────────
|
||||
// ── fn_agent_stop ─────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_agent_stop",
|
||||
name: "fn_agent_stop",
|
||||
label: "KB: Stop Agent",
|
||||
description:
|
||||
"Stop a running agent — pauses its execution. " +
|
||||
@@ -1556,7 +1556,7 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
promptSnippet: "Stop (pause) a running Fusion agent",
|
||||
promptGuidelines: [
|
||||
"Use to pause an agent that is currently running or active",
|
||||
"Stopped agents can be resumed with kb_agent_start",
|
||||
"Stopped agents can be resumed with fn_agent_start",
|
||||
"Agents in 'idle', 'error', or 'terminated' state cannot be stopped",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
@@ -1608,10 +1608,10 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
// ── kb_agent_start ────────────────────────────────────────────────
|
||||
// ── fn_agent_start ────────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
name: "kb_agent_start",
|
||||
name: "fn_agent_start",
|
||||
label: "KB: Start Agent",
|
||||
description:
|
||||
"Start a stopped agent — resumes its execution. " +
|
||||
|
||||
Reference in New Issue
Block a user