sqlew
Version:
MCP server for efficient context sharing between Claude Code sub-agents (60-70% token reduction), Kanban Task Watcher, Decision or Constraint Context, and streamlined documentation
1,315 lines (1,071 loc) • 33.4 kB
Markdown
# Task System - Kanban Task Watcher
**Version:** 3.0.0
**Last Updated:** 2025-10-17
## Table of Contents
1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Quick Start](#quick-start)
4. [Task Lifecycle](#task-lifecycle)
5. [Tool Reference](#tool-reference)
6. [Auto-Stale Detection](#auto-stale-detection)
7. [Linking System](#linking-system)
8. [Token Efficiency](#token-efficiency)
9. [Best Practices](#best-practices)
10. [Migration Guide](#migration-guide)
11. [Troubleshooting](#troubleshooting)
## Overview
The Kanban Task Watcher is an AI-optimized task management system designed to solve token waste from misuse of the `decision` tool for task/todo tracking.
### Problem Statement
Real-world usage analysis revealed:
- **204 task-like decisions** in 3-day production usage
- **~825 tokens** to query 10 task-like decisions (332 bytes/decision average)
- **No lifecycle management:** Tasks stuck in "in_progress" after interrupts or usage limits
- **Inefficient queries:** Full text content loaded even for simple list operations
### Solution
Dedicated Kanban task system with:
- **70% token reduction** via metadata-only list queries
- **Auto-stale detection** to handle interrupted sessions
- **Status validation** with enforced state machine transitions
- **Linking system** to connect tasks with decisions, constraints, files
- **Flat hierarchy** for AI simplicity (no subtasks)
## Architecture
### Database Schema
#### Master Tables
**`m_task_statuses`** - Task status definitions
```sql
CREATE TABLE m_task_statuses (
status_id INTEGER PRIMARY KEY,
status_name TEXT NOT NULL UNIQUE
);
-- 6 Statuses:
-- 1: todo
-- 2: in_progress
-- 3: waiting_review
-- 4: blocked
-- 5: done
-- 6: archived
```
#### Transaction Tables
**`t_tasks`** - Core task data
```sql
CREATE TABLE t_tasks (
task_id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
status_id INTEGER NOT NULL DEFAULT 1,
priority_id INTEGER,
assignee TEXT,
layer_id INTEGER,
created_ts INTEGER NOT NULL DEFAULT (unixepoch()),
updated_ts INTEGER NOT NULL DEFAULT (unixepoch()),
FOREIGN KEY (status_id) REFERENCES m_task_statuses(status_id),
FOREIGN KEY (priority_id) REFERENCES m_priorities(priority_id),
FOREIGN KEY (layer_id) REFERENCES m_layers(layer_id)
);
```
**`t_task_details`** - Task descriptions (separated for token efficiency)
```sql
CREATE TABLE t_task_details (
task_id INTEGER PRIMARY KEY,
description TEXT,
FOREIGN KEY (task_id) REFERENCES t_tasks(task_id) ON DELETE CASCADE
);
```
**`t_task_tags`** - Many-to-many task tags
```sql
CREATE TABLE t_task_tags (
task_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
PRIMARY KEY (task_id, tag_id),
FOREIGN KEY (task_id) REFERENCES t_tasks(task_id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES m_tags(tag_id) ON DELETE CASCADE
);
```
**`t_task_decision_links`** - Link tasks to decisions
```sql
CREATE TABLE t_task_decision_links (
task_id INTEGER NOT NULL,
decision_key_id INTEGER NOT NULL,
PRIMARY KEY (task_id, decision_key_id),
FOREIGN KEY (task_id) REFERENCES t_tasks(task_id) ON DELETE CASCADE,
FOREIGN KEY (decision_key_id) REFERENCES m_context_keys(key_id) ON DELETE CASCADE
);
```
**`t_task_constraint_links`** - Link tasks to constraints
```sql
CREATE TABLE t_task_constraint_links (
task_id INTEGER NOT NULL,
constraint_id INTEGER NOT NULL,
PRIMARY KEY (task_id, constraint_id),
FOREIGN KEY (task_id) REFERENCES t_tasks(task_id) ON DELETE CASCADE,
FOREIGN KEY (constraint_id) REFERENCES t_constraints(constraint_id) ON DELETE CASCADE
);
```
**`t_task_file_links`** - Link tasks to file changes
```sql
CREATE TABLE t_task_file_links (
task_id INTEGER NOT NULL,
file_id INTEGER NOT NULL,
PRIMARY KEY (task_id, file_id),
FOREIGN KEY (task_id) REFERENCES t_tasks(task_id) ON DELETE CASCADE,
FOREIGN KEY (file_id) REFERENCES m_files(file_id) ON DELETE CASCADE
);
```
#### Views
**`v_task_board`** - Token-efficient task queries (metadata only, no descriptions)
```sql
CREATE VIEW v_task_board AS
SELECT
t.task_id,
t.title,
s.status_name,
p.priority_name,
t.assignee,
l.layer_name,
GROUP_CONCAT(tag.tag_name, ',') AS tags,
t.created_ts,
t.updated_ts
FROM t_tasks t
LEFT JOIN m_task_statuses s ON t.status_id = s.status_id
LEFT JOIN m_priorities p ON t.priority_id = p.priority_id
LEFT JOIN m_layers l ON t.layer_id = l.layer_id
LEFT JOIN t_task_tags tt ON t.task_id = tt.task_id
LEFT JOIN m_tags tag ON tt.tag_id = tag.tag_id
GROUP BY t.task_id;
```
**Token efficiency:** ~100 bytes/task (vs ~332 bytes for full task with description)
#### Triggers
**`trg_log_task_create`** - Automatic activity logging on task creation
```sql
CREATE TRIGGER trg_log_task_create AFTER INSERT ON t_tasks
BEGIN
INSERT INTO t_activity_log (agent_id, entity_type, entity_id, action_type, details, ts)
VALUES (
(SELECT agent_id FROM m_agents WHERE agent_name = NEW.assignee),
'task',
NEW.task_id,
'create',
json_object('title', NEW.title, 'status_id', NEW.status_id),
NEW.created_ts
);
END;
```
**`trg_log_task_status_change`** - Log status transitions
```sql
CREATE TRIGGER trg_log_task_status_change AFTER UPDATE OF status_id ON t_tasks
WHEN OLD.status_id != NEW.status_id
BEGIN
INSERT INTO t_activity_log (agent_id, entity_type, entity_id, action_type, details, ts)
VALUES (
(SELECT agent_id FROM m_agents WHERE agent_name = NEW.assignee),
'task',
NEW.task_id,
'status_change',
json_object('old_status', OLD.status_id, 'new_status', NEW.status_id),
unixepoch()
);
END;
```
**`trg_update_task_timestamp`** - Auto-update task timestamp
```sql
CREATE TRIGGER trg_update_task_timestamp AFTER UPDATE ON t_tasks
BEGIN
UPDATE t_tasks SET updated_ts = unixepoch() WHERE task_id = NEW.task_id;
END;
```
### Configuration
Auto-stale detection config keys in `m_config` table:
- `task_auto_stale_enabled` ('1'): Enable/disable (0=false, 1=true)
- `task_stale_hours_in_progress` ('2'): Hours before in_progress → waiting_review
- `task_stale_hours_waiting_review` ('24'): Hours before waiting_review → todo
> See [Auto-Stale Detection](#auto-stale-detection) section for configuration details.
## Quick Start
### Creating Your First Task
```javascript
// Minimal task creation
{
action: "create",
title: "Implement JWT authentication"
}
// Returns: { task_id: 1, status: "todo" }
// Complete task creation with metadata
{
action: "create",
title: "Implement JWT authentication",
description: "Add JWT-based authentication to API endpoints with refresh token support",
status: "todo",
priority: "high",
assignee: "auth-agent",
tags: ["security", "authentication", "api"],
layer: "business"
}
```
### Listing Tasks
```javascript
// List all tasks (metadata only - token efficient)
{
action: "list"
}
// List filtered tasks
{
action: "list",
status: "in_progress",
assignee: "auth-agent",
tags: ["security"]
}
// Response includes stale_tasks_transitioned count
{
tasks: [
{
task_id: 1,
title: "Implement JWT authentication",
status_name: "in_progress",
priority_name: "high",
assignee: "auth-agent",
layer_name: "business",
tags: "security,authentication,api",
created_ts: 1697545200,
updated_ts: 1697545800
}
],
count: 1,
stale_tasks_transitioned: 0
}
```
### Getting Task Details
```javascript
// Get full task with description
{
action: "get",
task_id: 1
}
// Response includes description and links
{
task_id: 1,
title: "Implement JWT authentication",
description: "Add JWT-based authentication to API endpoints with refresh token support",
status: "in_progress",
priority: "high",
assignee: "auth-agent",
layer: "business",
tags: ["security", "authentication", "api"],
created_ts: 1697545200,
updated_ts: 1697545800,
decision_links: ["auth_method", "jwt_secret"],
constraint_links: [5],
file_links: ["/src/auth/jwt.ts", "/src/auth/middleware.ts"]
}
```
### Moving Tasks
```javascript
// Move task to next status (validated)
{
action: "move",
task_id: 1,
new_status: "waiting_review"
}
// Error if invalid transition
{
action: "move",
task_id: 1,
new_status: "archived" // Invalid: can't go from in_progress to archived
}
// Returns: Error: Invalid status transition from in_progress to archived
```
### Linking Tasks
```javascript
// Link to decision
{
action: "link",
task_id: 1,
link_type: "decision",
link_key: "auth_method"
}
// Link to constraint
{
action: "link",
task_id: 1,
link_type: "constraint",
link_id: 5
}
// Link to file
{
action: "link",
task_id: 1,
link_type: "file",
link_path: "/src/auth/jwt.ts"
}
```
## Task Lifecycle
### Status Definitions
| Status | ID | Description | Use Case |
|--------|----|-----------|----|
| `todo` | 1 | Not yet started | Backlog, planned work |
| `in_progress` | 2 | Actively being worked on | Current focus |
| `waiting_review` | 3 | Awaiting feedback or approval | Code review, design review |
| `blocked` | 4 | Cannot proceed due to blocker | Dependency, question, issue |
| `done` | 5 | Completed | Finished work |
| `archived` | 6 | Completed and archived | Historical reference |
### State Machine Transitions
```
todo → in_progress → waiting_review → done → archived
↓ ↓
blocked ────────┘
```
**Valid Transitions:**
| From Status | To Status(es) |
|-------------|--------------|
| `todo` | `in_progress`, `blocked` |
| `in_progress` | `waiting_review`, `blocked`, `done` |
| `waiting_review` | `in_progress`, `todo`, `done` |
| `blocked` | `todo`, `in_progress` |
| `done` | `archived` |
| `archived` | *(terminal state)* |
**Validation:**
- Enforced by `moveTask()` function
- Invalid transitions return error
- Use `update` action to bypass validation (use with caution)
### Auto-Stale Transitions
Tasks automatically transition when idle:
1. **`in_progress` → `waiting_review`** (>2 hours idle)
- Rationale: Likely waiting for review or hit usage limit
2. **`waiting_review` → `todo`** (>24 hours idle)
- Rationale: Review not happening, reset to backlog
**When It Runs:** Automatically before `list` and `move` actions
> **Configuration:** See [Auto-Stale Detection](#auto-stale-detection) section for detailed configuration options.
## Tool Reference
### Action: `create`
Create a new task.
**Required Parameters:**
- `action`: "create"
- `title`: Task title (string)
**Optional Parameters:**
- `description`: Full task description (string)
- `status`: Initial status (string: "todo", "in_progress", "waiting_review", "blocked", "done", "archived") - default: "todo"
- `priority`: Priority level (string: "low", "medium", "high", "critical")
- `assignee`: Agent or user assigned (string)
- `tags`: Array of tags (string[])
- `layer`: Architecture layer (string) - See [AI Agent Guide](AI_AGENT_GUIDE.md#6-always-specify-layer-for-decisions) for layer definitions
**Example:**
```javascript
{
action: "create",
title: "Implement JWT authentication",
description: "Add JWT-based authentication with refresh tokens",
status: "todo",
priority: "high",
assignee: "auth-agent",
tags: ["security", "authentication"],
layer: "business"
}
```
**Response:**
```javascript
{
task_id: 1,
message: "Task created successfully"
}
```
### Action: `update`
Update existing task fields.
**Required Parameters:**
- `action`: "update"
- `task_id`: Task ID (number)
**Optional Parameters (at least one required):**
- `status`: New status (string)
- `description`: New description (string)
- `priority`: New priority (string)
- `assignee`: New assignee (string)
- `tags`: New tags array (string[]) - replaces existing tags
- `layer`: New layer (string)
**Note:** Use `move` action for status transitions with validation.
**Example:**
```javascript
{
action: "update",
task_id: 1,
description: "Updated requirements: Add OAuth2 support",
priority: "critical"
}
```
**Response:**
```javascript
{
success: true,
message: "Task updated successfully"
}
```
### Action: `get`
Get single task with full details.
**Required Parameters:**
- `action`: "get"
- `task_id`: Task ID (number)
**Example:**
```javascript
{
action: "get",
task_id: 1
}
```
**Response:**
```javascript
{
task_id: 1,
title: "Implement JWT authentication",
description: "Add JWT-based authentication with refresh tokens",
status: "in_progress",
priority: "high",
assignee: "auth-agent",
layer: "business",
tags: ["security", "authentication"],
created_ts: 1697545200,
updated_ts: 1697545800,
decision_links: ["auth_method"],
constraint_links: [5],
file_links: ["/src/auth/jwt.ts"]
}
```
### Action: `list`
List tasks with filtering (metadata only, no descriptions).
**Required Parameters:**
- `action`: "list"
**Optional Parameters:**
- `status`: Filter by status (string)
- `priority`: Filter by priority (string)
- `assignee`: Filter by assignee (string)
- `tags`: Filter by tags (string[])
- `layer`: Filter by layer (string)
- `limit`: Maximum results (number) - default: 100
**Example:**
```javascript
{
action: "list",
status: "in_progress",
assignee: "auth-agent",
tags: ["security"]
}
```
**Response:**
```javascript
{
tasks: [
{
task_id: 1,
title: "Implement JWT authentication",
status_name: "in_progress",
priority_name: "high",
assignee: "auth-agent",
layer_name: "business",
tags: "security,authentication",
created_ts: 1697545200,
updated_ts: 1697545800
}
],
count: 1,
stale_tasks_transitioned: 0
}
```
**Token Efficiency:**
- ~100 bytes/task (no descriptions)
- Use `get` for full details when needed
### Action: `move`
Move task to new status with validation.
**Required Parameters:**
- `action`: "move"
- `task_id`: Task ID (number)
- `new_status`: Target status (string)
**Example:**
```javascript
{
action: "move",
task_id: 1,
new_status: "waiting_review"
}
```
**Response (success):**
```javascript
{
success: true,
message: "Task moved from in_progress to waiting_review"
}
```
**Response (invalid transition):**
```javascript
{
error: "Invalid status transition from in_progress to archived. Valid transitions: waiting_review, blocked, done"
}
```
**Auto-Stale Detection:**
- Runs before move operation
- Returns `stale_tasks_transitioned` count
### Action: `link`
Link task to decision, constraint, or file.
**Required Parameters:**
- `action`: "link"
- `task_id`: Task ID (number)
- `link_type`: Link type (string: "decision", "constraint", "file")
**Type-Specific Required Parameters:**
- `link_type="decision"`: `link_key` (string) - Decision key
- `link_type="constraint"`: `link_id` (number) - Constraint ID
- `link_type="file"`: `link_path` (string) - File path
**Examples:**
```javascript
// Link to decision
{
action: "link",
task_id: 1,
link_type: "decision",
link_key: "auth_method"
}
// Link to constraint
{
action: "link",
task_id: 1,
link_type: "constraint",
link_id: 5
}
// Link to file
{
action: "link",
task_id: 1,
link_type: "file",
link_path: "/src/auth/jwt.ts"
}
```
**Response:**
```javascript
{
success: true,
message: "Task linked to decision 'auth_method'"
}
```
### Action: `archive`
Archive completed task (soft delete).
**Required Parameters:**
- `action`: "archive"
- `task_id`: Task ID (number)
**Example:**
```javascript
{
action: "archive",
task_id: 1
}
```
**Response:**
```javascript
{
success: true,
message: "Task archived successfully"
}
```
**Note:** Only tasks with `status="done"` can be archived.
### Action: `batch_create`
Create multiple tasks atomically or best-effort.
**Required Parameters:**
- `action`: "batch_create"
- `tasks`: Array of task objects (max 50)
**Optional Parameters:**
- `atomic`: Boolean (default: true) - All-or-nothing vs best-effort mode
**Example:**
```javascript
{
action: "batch_create",
tasks: [
{
title: "Setup database schema",
status: "todo",
priority: "high",
assignee: "db-agent"
},
{
title: "Implement API endpoints",
status: "todo",
priority: "medium",
assignee: "api-agent"
}
],
atomic: false // Recommended for AI agents - allows partial success
}
```
**Response (atomic=true, success):**
```javascript
{
success: true,
created_count: 2,
task_ids: [1, 2]
}
```
**Response (atomic=false, partial success):**
```javascript
{
success: true,
created_count: 1,
failed_count: 1,
task_ids: [1],
errors: ["Task 2: Invalid priority 'ultra-high'"]
}
```
> **Note on Atomic Mode:** For AI agents, `atomic: false` is recommended to avoid transaction failures. See [AI Agent Guide - Batch Operations](AI_AGENT_GUIDE.md#batch-operations-guide) for details.
### Action: `help`
Get comprehensive on-demand documentation.
**Required Parameters:**
- `action`: "help"
**Example:**
```javascript
{
action: "help"
}
```
**Response:**
- Complete tool documentation
- Parameter matrices
- Examples
- Status transition rules
- Token efficiency tips
## Auto-Stale Detection
### Overview
Auto-stale detection automatically transitions idle tasks to prevent them from getting stuck.
**Why It's Needed:**
- AI agents hit usage limits mid-task
- Sessions get interrupted (network, timeout)
- Code generation takes longer than expected
- Reviews don't happen promptly
### Detection Logic
**Implementation:** `src/utils/task-stale-detection.ts`
The logic:
1. Check if enabled via `task_auto_stale_enabled` config
2. Get threshold hours/days from config
3. Run SQL UPDATE to transition stale tasks based on `updated_ts`
4. Return count of transitioned tasks
**Transition Rules:**
1. **`in_progress` → `waiting_review`** (>2 hours idle)
2. **`waiting_review` → `todo`** (>24 hours idle)
3. **`done` → `archived`** (>48 hours idle, weekend-aware) - **Auto-Archive**
SQL Pattern:
```sql
UPDATE t_tasks
SET status_id = ?, updated_ts = unixepoch()
WHERE status_id = ? AND updated_ts < unixepoch() - ?
```
### When It Runs
1. **Before `list` action**
- Ensures stale tasks show correct status
- Returns `stale_tasks_transitioned` count
- Returns `archived_tasks` count
2. **Before `move` action**
- Prevents moving already-stale tasks
- Ensures status consistency
3. **On database startup**
- Maintenance on initialization
- Cleans up stale/old tasks
### Configuration
**Via MCP Tool (config):**
```javascript
// Update auto-archive threshold
{
action: "update",
auto_archive_done_days: "3" // Archive after 3 days instead of 2
}
// Enable weekend-aware mode (affects auto-archive, messages, files)
{
action: "update",
autodelete_ignore_weekend: "1"
}
```
**Via .sqlew/config.toml:**
```toml
[tasks]
auto_archive_done_days = 3 # Archive after 3 days
stale_hours_in_progress = 4 # in_progress → waiting_review after 4 hours
stale_hours_waiting_review = 48 # waiting_review → todo after 48 hours
auto_stale_enabled = true
[autodelete]
ignore_weekend = true # Weekend-aware mode (shared setting)
```
**Via SQL (Advanced):**
```sql
-- Enable/Disable
UPDATE m_config SET value = '1' WHERE key = 'task_auto_stale_enabled'; -- Enable
UPDATE m_config SET value = '0' WHERE key = 'task_auto_stale_enabled'; -- Disable
-- Adjust auto-archive threshold
UPDATE m_config SET value = '3' WHERE key = 'auto_archive_done_days'; -- 3 days
-- Adjust stale detection thresholds
UPDATE m_config SET value = '4' WHERE key = 'task_stale_hours_in_progress';
UPDATE m_config SET value = '48' WHERE key = 'task_stale_hours_waiting_review';
-- Check current config
SELECT key, value FROM m_config WHERE key LIKE 'task_%' OR key LIKE 'auto_%';
```
### Monitoring
Track transitions via `t_activity_log` table:
```sql
-- Recent transitions (including auto-archive)
SELECT * FROM t_activity_log
WHERE entity_type = 'task' AND action_type = 'status_change'
ORDER BY ts DESC LIMIT 20;
-- Frequently stale tasks (>2 auto-transitions)
SELECT task_id, COUNT(*) as stale_count FROM t_activity_log
WHERE entity_type = 'task' AND json_extract(details, '$.new_status') = 3
GROUP BY task_id HAVING stale_count > 2;
-- Recently auto-archived tasks
SELECT * FROM t_activity_log
WHERE entity_type = 'task'
AND action_type = 'status_change'
AND json_extract(details, '$.new_status') = 6 -- ARCHIVED status
ORDER BY ts DESC LIMIT 20;
-- Count of archived tasks per day
SELECT date(ts, 'unixepoch') as day, COUNT(*) as archived_count
FROM t_activity_log
WHERE entity_type = 'task'
AND action_type = 'status_change'
AND json_extract(details, '$.new_status') = 6
GROUP BY day
ORDER BY day DESC;
```
### Weekend-Aware Behavior
When `autodelete_ignore_weekend` is enabled (via config.toml or MCP tool):
**Example 1 - Task Completed on Friday:**
- Task marked `done`: Friday 5:00 PM
- Default 48 hours: Would archive Sunday 5:00 PM
- **Weekend-aware**: Archives Tuesday 5:00 PM (skips Sat/Sun)
**Example 2 - Task Completed on Wednesday:**
- Task marked `done`: Wednesday 2:00 PM
- Default 48 hours: Would archive Friday 2:00 PM
- **Weekend-aware**: Archives Friday 2:00 PM (no weekend in between)
**Why Weekend-Aware Mode?**
- Teams/AI agents may not work on weekends
- Prevents premature archiving during weekend breaks
- Consistent with message/file retention behavior
- Configurable: Disable if you work 7 days/week
## Linking System
### Overview
Tasks can be linked to:
- **Decisions:** Track which architectural decisions relate to this task
- **Constraints:** Associate performance/security/architecture constraints
- **Files:** Connect to modified files for context
### Use Cases
**Decision Links:**
```javascript
// Task: "Implement JWT authentication"
// Link to decision: "auth_method"
{
action: "link",
task_id: 1,
link_type: "decision",
link_key: "auth_method"
}
// Benefit: When viewing task, see related auth decision
```
**Constraint Links:**
```javascript
// Task: "Optimize API response time"
// Link to constraint: "API response <100ms"
{
action: "link",
task_id: 2,
link_type: "constraint",
link_id: 5
}
// Benefit: Track which constraint this task addresses
```
**File Links:**
```javascript
// Task: "Refactor auth module"
// Link to files being modified
{
action: "link",
task_id: 3,
link_type: "file",
link_path: "/src/auth/jwt.ts"
}
// Benefit: See which files are affected by this task
```
### Querying Links
**Get Task with Links:**
```javascript
{
action: "get",
task_id: 1
}
// Response includes all links
{
task_id: 1,
title: "Implement JWT authentication",
decision_links: ["auth_method", "jwt_secret"],
constraint_links: [5, 8],
file_links: ["/src/auth/jwt.ts", "/src/auth/middleware.ts"]
}
```
**Find Tasks by Link:**
```sql
-- Tasks linked to specific decision
SELECT t.* FROM t_tasks t
JOIN t_task_decision_links tdl ON t.task_id = tdl.task_id
JOIN m_context_keys ck ON tdl.decision_key_id = ck.key_id
WHERE ck.key_name = 'auth_method';
-- Tasks linked to specific constraint
SELECT t.* FROM t_tasks t
JOIN t_task_constraint_links tcl ON t.task_id = tcl.task_id
WHERE tcl.constraint_id = 5;
-- Tasks linked to specific file
SELECT t.* FROM t_tasks t
JOIN t_task_file_links tfl ON t.task_id = tfl.task_id
JOIN m_files f ON tfl.file_id = f.file_id
WHERE f.file_path = '/src/auth/jwt.ts';
```
## Token Efficiency
### Metadata-Only Queries
**Problem:** Full task content loads descriptions (~232 bytes extra per task)
**Solution:** `v_task_board` view provides metadata only
**Comparison:**
| Query Type | Bytes/Task | 10 Tasks | Use Case |
|------------|-----------|----------|----------|
| `list` (metadata only) | ~100 | ~1,000 | Browse, filter, status check |
| `get` (full details) | ~332 | ~3,320 | Read description, view links |
| Old `decision` method | ~332 | ~3,320 | What AIs were doing before v3.0 |
**Token Savings:**
- `list` vs `decision`: 70% reduction
- 10 tasks: 3,320 → 1,000 bytes (2,320 bytes saved)
### Best Practices
1. **Use `list` for browsing**
```javascript
// Get all in_progress tasks (metadata only)
{ action: "list", status: "in_progress" }
```
2. **Use `get` only when needed**
```javascript
// User wants to read task description
{ action: "get", task_id: 5 }
```
3. **Filter aggressively**
```javascript
// Narrow results with filters
{
action: "list",
status: "in_progress",
assignee: "auth-agent",
tags: ["security"]
}
```
4. **Batch create instead of sequential**
```javascript
// Create 5 tasks in one call
{
action: "batch_create",
tasks: [...]
}
```
### Monitoring Token Usage
**Estimate bytes returned:**
```sql
-- Estimate list query size
SELECT COUNT(*) * 100 as estimated_bytes
FROM v_task_board
WHERE status_name = 'in_progress';
-- Estimate get query size
SELECT
LENGTH(title) + LENGTH(COALESCE(description, '')) + 232 as estimated_bytes
FROM t_tasks t
LEFT JOIN t_task_details td ON t.task_id = td.task_id
WHERE t.task_id = 1;
```
## Best Practices
### For AI Agents
1. **Always use `action` parameter**
```javascript
// ❌ WRONG
{ task_id: 1 }
// ✅ CORRECT
{ action: "get", task_id: 1 }
```
2. **Use `move` for status changes (not `update`)**
```javascript
// ❌ WRONG (bypasses validation)
{ action: "update", task_id: 1, status: "archived" }
// ✅ CORRECT (validates transition)
{ action: "move", task_id: 1, new_status: "waiting_review" }
```
3. **Use `list` before `get`**
```javascript
// ❌ WRONG (loads all descriptions)
tasks.forEach(t => get({ action: "get", task_id: t.id }))
// ✅ CORRECT (metadata first, details on demand)
const tasks = list({ action: "list", status: "in_progress" });
const details = get({ action: "get", task_id: tasks[0].task_id });
```
4. **Prefer batch operations for efficiency**
```javascript
// Create multiple tasks in one call
{
action: "batch_create",
tasks: [...]
}
```
5. **Link tasks to relevant context**
```javascript
// Create task
const task = create({ action: "create", title: "Implement auth" });
// Link to decision
link({
action: "link",
task_id: task.task_id,
link_type: "decision",
link_key: "auth_method"
});
```
### For Multi-Agent Workflows
1. **Use assignee for coordination**
```javascript
// Agent A creates task for Agent B
{
action: "create",
title: "Implement auth middleware",
assignee: "auth-agent",
tags: ["handoff"]
}
// Agent B lists assigned tasks
{
action: "list",
assignee: "auth-agent",
status: "todo"
}
```
2. **Use priority for orchestration**
```javascript
// Critical blocker
{ action: "create", title: "Fix DB connection", priority: "critical" }
// High priority
{ action: "create", title: "Implement API", priority: "high" }
// Background work
{ action: "create", title: "Update docs", priority: "low" }
```
3. **Track dependencies with links**
```javascript
// Task depends on constraint being met
{
action: "link",
task_id: 5,
link_type: "constraint",
link_id: 3 // "DB schema must be finalized"
}
```
## Migration Guide
### From Decision-Based Task Tracking
**Before (v2.x):**
```javascript
// Using decision tool for tasks
{
action: "set",
key: "task_implement_auth",
value: "in_progress: Implementing JWT authentication with refresh tokens",
layer: "infrastructure",
tags: ["task", "security", "in_progress"]
}
```
**After (v3.0):**
```javascript
// Using task tool
{
action: "create",
title: "Implement JWT authentication",
description: "Implementing JWT authentication with refresh tokens",
status: "in_progress",
priority: "high",
assignee: "auth-agent",
tags: ["security", "authentication"],
layer: "business"
}
```
### Migration Strategy
1. **Find task-like decisions:** `search_tags` with `tags: ["task"]`
2. **Parse format:** Extract status and description from decision value
3. **Create tasks:** Use `task` tool's `create` action
4. **Link context:** Use `link` action to connect task to original decision
5. **Deprecate old:** Update decision `status: "deprecated"`
> **Tip:** See docs/DECISION_TO_TASK_MIGRATION_GUIDE.md for complete migration script.
## Troubleshooting
### Common Errors
> **For general MCP tool errors** (missing action parameter, invalid layer, atomic mode), see [AI Agent Guide](AI_AGENT_GUIDE.md#common-errors--solutions)
**Error: "Invalid status transition"**
```javascript
// Problem: Trying to move from in_progress to archived
{ action: "move", task_id: 1, new_status: "archived" }
// Solution: Move to done first
{ action: "move", task_id: 1, new_status: "done" }
{ action: "archive", task_id: 1 }
```
**Error: "Task not found"**
```javascript
// Problem: Invalid task_id
{ action: "get", task_id: 9999 }
// Solution: List tasks first to get valid IDs
{ action: "list" }
```
**Error: "Invalid link type"**
```javascript
// Problem: Typo in link_type
{ action: "link", task_id: 1, link_type: "decisions" }
// Solution: Use exact link_type
{ action: "link", task_id: 1, link_type: "decision", link_key: "..." }
```
**Error: "Cannot archive task not in done status"**
```javascript
// Problem: Trying to archive incomplete task
{ action: "archive", task_id: 1 } // Task is in_progress
// Solution: Complete task first
{ action: "move", task_id: 1, new_status: "done" }
{ action: "archive", task_id: 1 }
```
### Debugging
```sql
-- Check task exists
SELECT * FROM t_tasks WHERE task_id = 1;
-- Check status
SELECT t.task_id, s.status_name FROM t_tasks t
JOIN m_task_statuses s ON t.status_id = s.status_id WHERE t.task_id = 1;
-- Check links
SELECT * FROM t_task_decision_links WHERE task_id = 1;
SELECT * FROM t_task_constraint_links WHERE task_id = 1;
SELECT * FROM t_task_file_links WHERE task_id = 1;
-- Check config & activity
SELECT * FROM m_config WHERE key LIKE 'task_%';
SELECT * FROM t_activity_log WHERE entity_type = 'task' AND entity_id = 1 ORDER BY ts DESC;
```
### Performance Issues
- **Slow queries:** Check index usage with `EXPLAIN QUERY PLAN`
- **Large results:** Use `limit` parameter (default: 100, reduce to 20)
## Appendix
### Complete Status Reference
| Status ID | Status Name | Description |
|-----------|------------|-------------|
| 1 | todo | Not yet started |
| 2 | in_progress | Actively being worked on |
| 3 | waiting_review | Awaiting feedback/approval |
| 4 | blocked | Cannot proceed (dependency/issue) |
| 5 | done | Completed |
| 6 | archived | Completed and archived |
### Complete Transition Matrix
| From ↓ / To → | todo | in_progress | waiting_review | blocked | done | archived |
|---------------|------|-------------|----------------|---------|------|----------|
| **todo** | - | ✅ | ❌ | ✅ | ❌ | ❌ |
| **in_progress** | ❌ | - | ✅ | ✅ | ✅ | ❌ |
| **waiting_review** | ✅ | ✅ | - | ❌ | ✅ | ❌ |
| **blocked** | ✅ | ✅ | ❌ | - | ❌ | ❌ |
| **done** | ❌ | ❌ | ❌ | ❌ | - | ✅ |
| **archived** | ❌ | ❌ | ❌ | ❌ | ❌ | - |
✅ = Valid transition
❌ = Invalid transition
\- = Same status (no transition)
### Related Documentation
- **README.md:** Quick start and overview
- **CHANGELOG.md:** Version history and release notes
- **CLAUDE.md:** Developer instructions and architecture
- **ARCHITECTURE.md:** Technical architecture details
- **AI_AGENT_GUIDE.md:** Comprehensive AI agent guide
### Future Enhancements
Potential v3.1.0 features: task dependencies, subtasks, time tracking, task templates, configurable auto-stale via tool, recurring tasks, export/import
### Support
- **Issues:** [GitHub Issues](https://github.com/sin5ddd/mcp-sqlew/issues)
- **Discussions:** [GitHub Discussions](https://github.com/sin5ddd/mcp-sqlew/discussions)
---
**Version:** 3.0.0
**Last Updated:** 2025-10-17
**Author:** sin5ddd