From taskmanager
Manage project memories - constraints, decisions, conventions with conflict detection and resolution
How this skill is triggered — by the user, by Claude, or both
Slash command
/taskmanager:taskmanager-memoryThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You manage the **project-wide memory** for this repository using SQLite.
You manage the project-wide memory for this repository using SQLite.
Your goal is to:
memories table in .taskmanager/taskmanager.db valid and consistent.Always work relative to the project root.
.taskmanager/taskmanager.dbmemoriesmemories_fts (FTS5 virtual table)state.task_memory (JSON column in state table)Use sqlite3 via the Bash tool for all database operations.
The memories table has these columns:
| Column | Type | Description |
|---|---|---|
id | TEXT PRIMARY KEY | Stable ID, e.g. "M-0001" |
title | TEXT NOT NULL | Short summary (<= 140 chars) |
kind | TEXT NOT NULL | One of: constraint, decision, bugfix, workaround, convention, architecture, process, integration, anti-pattern, other |
why_important | TEXT NOT NULL | Concise explanation of why this memory matters |
body | TEXT NOT NULL | Detailed description / rationale / examples |
source_type | TEXT NOT NULL | One of: user, agent, command, hook, other |
source_name | TEXT | Human/agent/command identifier |
source_via | TEXT | Free-text, e.g. "cli", "tests/run-test-suite" |
auto_updatable | INTEGER | 0 for user-created (never auto-update), 1 for system-created |
importance | INTEGER | 1-5 (how critical), default 3 |
confidence | REAL | 0-1 (how sure we are), default 0.8 |
status | TEXT | One of: active, deprecated, superseded, draft |
superseded_by | TEXT | ID of newer memory (if superseded) |
scope | TEXT (JSON) | Object with: project, files, tasks, commands, agents, domains. The tasks field links memories to specific task IDs for auto-loading during execution. |
tags | TEXT (JSON) | Array of free-form tags, e.g. ["testing", "laravel"] |
links | TEXT (JSON) | Array of links to docs/PRs/etc |
use_count | INTEGER | Usage counter, default 0 |
last_used_at | TEXT | ISO timestamp of last use |
last_conflict_at | TEXT | ISO timestamp of last detected conflict |
conflict_resolutions | TEXT (JSON) | Array of conflict resolution history entries |
created_at | TEXT | ISO timestamp |
updated_at | TEXT | ISO timestamp |
Deferrals (tracked in the deferrals table) are separate from memories. Deferrals track work deferred from one task to another with source-target linkage and lifecycle management. They are managed by the run and update commands, not by this memory skill. Do not create memories to track deferred work; use the deferrals system instead.
When you start working:
.taskmanager/taskmanager.db exists.memories table exists:
SELECT name FROM sqlite_master WHERE type='table' AND name='memories';
Given a natural-language description of the current work (files, task IDs, domains):
Parse the description into:
domains (e.g. testing, performance, security, architecture).files / directories.Use SQL to find matching memories:
Full-text search (for keyword matching):
SELECT m.id, m.title, m.kind, m.why_important, m.importance, m.use_count
FROM memories m
JOIN memories_fts fts ON m.rowid = fts.rowid
WHERE m.status = 'active'
AND memories_fts MATCH '<search_terms>'
ORDER BY rank, m.importance DESC, m.use_count DESC
LIMIT 10;
Scope-based search (for file matching):
SELECT id, title, kind, why_important, importance, use_count
FROM memories
WHERE status = 'active'
AND (
scope = '{}'
OR json_extract(scope, '$.files') IS NULL
OR EXISTS (
SELECT 1 FROM json_each(json_extract(scope, '$.files')) f
WHERE '<current_file>' LIKE f.value
)
)
ORDER BY importance DESC, use_count DESC
LIMIT 10;
Domain-based search:
SELECT id, title, kind, why_important, importance, use_count
FROM memories
WHERE status = 'active'
AND EXISTS (
SELECT 1 FROM json_each(json_extract(scope, '$.domains')) d
WHERE d.value IN ('<domain1>', '<domain2>')
)
ORDER BY importance DESC, use_count DESC;
Task-based search:
SELECT id, title, kind, why_important, importance, use_count
FROM memories
WHERE status = 'active'
AND EXISTS (
SELECT 1 FROM json_each(json_extract(scope, '$.tasks')) t
WHERE t.value = '<task_id>'
)
ORDER BY importance DESC;
Prefer:
importance.use_count.last_used_at.Return a compact summary (bullet list) with:
id, title, kind, why_important.You should never dump all memories into context unless explicitly asked; always select the smallest relevant subset.
When a user or another skill makes a decision that should persist for future work:
Check whether a similar memory already exists:
SELECT id, title, kind FROM memories
WHERE status = 'active'
AND kind = '<kind>'
AND (
title LIKE '%<keyword>%'
OR EXISTS (
SELECT 1 FROM json_each(tags) t WHERE t.value = '<tag>'
)
);
If it is truly new, generate the next ID:
SELECT 'M-' || printf('%04d', COALESCE(MAX(CAST(SUBSTR(id, 3) AS INTEGER)), 0) + 1)
FROM memories;
Insert the new memory:
INSERT INTO memories (
id, title, kind, why_important, body,
source_type, source_name, source_via, auto_updatable,
importance, confidence, status,
scope, tags, links,
use_count, created_at, updated_at
) VALUES (
'<id>', '<title>', '<kind>', '<why_important>', '<body>',
'<source_type>', '<source_name>', '<source_via>', <0_or_1>,
<importance>, <confidence>, 'active',
'<scope_json>', '<tags_json>', '<links_json>',
0, datetime('now'), datetime('now')
);
When in doubt whether something deserves a memory, ask: "Will this decision/convention matter for future tasks?" If yes, create a memory.
When the plan command's macro architectural questions (Phase 3) capture a user decision:
INSERT INTO memories (
id, title, kind, why_important, body,
source_type, source_name, source_via, auto_updatable,
importance, confidence, status,
scope, tags
) VALUES (
'M-0012',
'Use Redis for queue driver',
'architecture',
'Affects all background job processing',
'User chose Redis as the queue driver during macro analysis. Rationale: existing Redis infrastructure, supports priorities and delayed jobs.',
'user', 'developer', 'taskmanager:plan:macro-questions', 0,
4, 1.0, 'active',
'{"domains": ["infrastructure", "queues"], "tasks": ["1.3", "2.1"]}',
'["redis", "queue", "architecture"]'
);
Note the scope.tasks field linking this memory to relevant task IDs. During task execution, the run command auto-loads memories where the current task ID appears in scope.tasks.
When an existing memory is refined or corrected:
If it's a small correction:
UPDATE memories SET
body = '<new_body>',
tags = '<new_tags_json>',
scope = '<new_scope_json>',
updated_at = datetime('now')
WHERE id = '<memory_id>';
If it's a substantial change or reversal:
UPDATE memories SET
status = 'superseded',
superseded_by = '<new_id>',
updated_at = datetime('now')
WHERE id = '<old_id>';
Never silently rewrite history in a way that hides past decisions.
Whenever a memory directly influences planning or execution:
UPDATE memories SET
use_count = use_count + 1,
last_used_at = datetime('now'),
updated_at = datetime('now')
WHERE id = '<memory_id>';
This allows future tools to treat highly-used, high-importance memories as more trustworthy.
When planning or executing non-trivial work (new features, refactors, risky changes):
This way, the memories table becomes the single, durable "project brain" that all agents/commands/skills can rely on.
Task-scoped memories are temporary memories that live only for the duration of a single task. They are stored in the state table under the task_memory JSON column.
When a user provides --task-memory "description" or -tm "description" to a command:
UPDATE state SET
task_memory = json_insert(
task_memory,
'$[#]',
json_object(
'content', '<the description>',
'addedAt', datetime('now'),
'taskId', '<current task ID>',
'source', 'user'
)
)
WHERE id = 1;
System-generated task memories use 'source', 'system'.
Before executing a task:
SELECT value FROM state, json_each(state.task_memory)
WHERE state.id = 1
AND (
json_extract(value, '$.taskId') = '<current_task_id>'
OR json_extract(value, '$.taskId') = '*'
);
Include these memories alongside global memories when applying constraints.
At task completion (before marking "done"):
Check if any task memories exist for this task.
If task memories exist, use AskUserQuestion to ask:
"The following task memories were used during this task. Should any be promoted to global (persistent) memory?"
Options for each memory:
For promoted memories:
memories table.source_type = 'user' if originally from user, or 'agent' if from system.Clear the task memories for this task:
UPDATE state SET
task_memory = (
SELECT json_group_array(value)
FROM json_each(task_memory)
WHERE json_extract(value, '$.taskId') != '<task_id>'
)
WHERE id = 1;
Conflict detection is available via taskmanager:memory conflicts. It is NOT run automatically during task execution.
When invoked, it checks active memories for:
scope.files that no longer existuse_count = 0 and created_at older than 30 daysFor each conflict found, offer resolution options via AskUserQuestion:
Record all resolutions in the conflict_resolutions JSON column:
UPDATE memories SET
conflict_resolutions = json_insert(
conflict_resolutions,
'$[#]',
json_object(
'timestamp', datetime('now'),
'resolution', '<kept|modified|deprecated>',
'reason', '<brief explanation>',
'taskId', '<task ID>'
)
),
last_conflict_at = datetime('now'),
updated_at = datetime('now')
WHERE id = '<memory_id>';
When resolving conflicts (whether via opt-in detection or during manual review):
source_type = 'user')NEVER auto-update. ALWAYS ask the user via AskUserQuestion.
source_type != 'user')auto_updatableWhen creating a memory, set auto_updatable based on source_type:
auto_updatable = (source_type != 'user') ? 1 : 0
source_type = 'user' -> auto_updatable = 0source_type = 'agent' | 'command' | 'hook' | 'other' -> auto_updatable = 1| Source Type | Small Update | Substantial Change |
|---|---|---|
user | Ask user | Ask user |
agent | Auto-update | Ask user |
command | Auto-update | Ask user |
hook | Auto-update | Ask user |
other | Auto-update | Ask user |
Memories are never deleted. They are either:
activedeprecated (no longer relevant)superseded with a pointer to the new memoryThis preserves decision history and audit trail.
All logging goes to a single file: .taskmanager/logs/activity.log.
<timestamp> [<level>] [memory] <message>
Levels: ERROR, DECISION. Logs are append-only.
Log these events:
Examples:
2025-12-11T10:00:00Z [DECISION] [memory] Created memory M-0005: "Always validate API inputs"
2025-12-11T10:00:01Z [DECISION] [memory] Applied memories to task 1.2: M-0001, M-0003, M-0005
2025-12-11T10:00:02Z [ERROR] [memory] Conflict: M-0001 references deleted file app/OldAuth.php
2025-12-11T10:05:00Z [DECISION] [memory] Deprecated M-0002: "No longer using old auth pattern"
Get all active memories:
SELECT * FROM memories WHERE status = 'active' ORDER BY importance DESC, use_count DESC;
Full-text search:
SELECT m.* FROM memories m
JOIN memories_fts fts ON m.rowid = fts.rowid
WHERE memories_fts MATCH '<search_term>'
AND m.status = 'active'
ORDER BY rank, m.importance DESC;
Get memories for a specific file:
SELECT * FROM memories
WHERE status = 'active'
AND (
scope = '{}'
OR json_extract(scope, '$.files') IS NULL
OR EXISTS (
SELECT 1 FROM json_each(json_extract(scope, '$.files')) f
WHERE '<current_file>' LIKE f.value
)
)
ORDER BY importance DESC;
Record memory usage:
UPDATE memories
SET use_count = use_count + 1,
last_used_at = datetime('now'),
updated_at = datetime('now')
WHERE id = '<memory_id>';
Record conflict resolution:
UPDATE memories SET
conflict_resolutions = json_insert(
conflict_resolutions,
'$[#]',
json_object(
'timestamp', datetime('now'),
'resolution', '<resolution>',
'reason', '<reason>',
'taskId', '<taskId>'
)
),
last_conflict_at = datetime('now'),
updated_at = datetime('now')
WHERE id = '<memory_id>';
Get next memory ID:
SELECT 'M-' || printf('%04d', COALESCE(MAX(CAST(SUBSTR(id, 3) AS INTEGER)), 0) + 1)
FROM memories;
Deprecate a memory:
UPDATE memories SET
status = 'deprecated',
updated_at = datetime('now')
WHERE id = '<memory_id>';
Supersede a memory:
UPDATE memories SET
status = 'superseded',
superseded_by = '<new_memory_id>',
updated_at = datetime('now')
WHERE id = '<old_memory_id>';
npx claudepluginhub mwguerra/plugins --plugin taskmanagerCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.