memory-tasks — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited memory-tasks (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Manage work-in-progress using Basic Memory's schema system. Tasks are just notes with type: Task — they live in the knowledge graph, validate against a schema, and survive context compaction.
Tasks use the BM schema system. The schema note lives at schema/Task.md:
---
title: Task
type: schema
entity: Task
version: 1
schema:
description: string, what needs to be done
status?(enum, current state): [active, blocked, done, abandoned]
assigned_to?: string, who is working on this
steps?(array): string, ordered steps to complete
current_step?: integer, which step number we're on (1-indexed)
context?: string, key context needed to resume after memory loss
started?: string, when work began
completed?: string, when work finished
blockers?(array): string, what's preventing progress
parent_task?: Task, parent task if this is a subtask
settings:
validation: warn
---When work qualifies, create a task note. Use bm_write with note_type="Task" and put queryable fields in metadata:
bm_write(
title="Descriptive task name",
directory="tasks",
note_type="Task",
metadata={
"status": "active",
"priority": "high",
"assigned_to": "claude",
"current_step": 1,
"steps": ["First step", "Second step", "Third step"]
},
tags=["task"],
content="""# Descriptive task name
## Observations
- [description] What needs to be done, concisely
- [status] active
- [assigned_to] claude
- [current_step] 1
## Steps
1. [ ] First concrete step
2. [ ] Second concrete step
3. [ ] Third concrete step
## Context
What future-you needs to pick up this work. Include:
- Key file paths and repos involved
- Decisions already made and why
- What was tried and what worked/didn't
- Where to look for related context"""
)Why both frontmatter and observations? Fields in metadata (stored as frontmatter) power bm_search with filters. Fields as observations (- [status] active) power bm_schema(command="validate"). Include queryable fields in both places for full coverage.
parent_task [[Other Task]], related_to [[Some Note]]bm_write(note_type="Task") stores type: task, and note_types=["Task"] or note_types=["task"] both match it.On session start or after compaction:
bm_search(note_types=["task"], filters={"status": "active"})context fieldcurrent_step, update context, check off stepsAs work progresses, update the task note:
## Steps
1. [x] First step — done, resulted in X
2. [x] Second step — done, changed approach because Y
3. [ ] Third step — next up
## Context
Updated context reflecting current state...Read the task as JSON first and pass its checksum as expected_checksum on each edit. Two sessions often update the same task, for example in a pre-compaction flush; a revision conflict means the other one wrote first, so re-read before writing.
Update frontmatter too, with command="set_metadata" and the metadata parameter (the body stays unchanged):
task = bm_read(identifier="tasks/descriptive-task-name", output_format="json")
bm_edit(
identifier="tasks/descriptive-task-name",
command="set_metadata",
metadata={"current_step": 3},
expected_checksum=task["checksum"]
)When done:
status: done
completed: YYYY-MM-DDAdd a brief summary of what was accomplished and any follow-up needed.
When a compaction event is imminent:
bm_search(note_types=["task"], filters={"status": "active"})current_step to reflect actual progresscontext with everything needed to resumeWith BM's schema system, tasks are fully queryable:
| Query | What it finds |
|---|---|
bm_search(note_types=["task"]) | All tasks |
bm_search(note_types=["task"], filters={"status": "active"}) | Active tasks |
bm_search(note_types=["task"], filters={"status": "blocked"}) | Blocked tasks |
bm_search(note_types=["task"], filters={"assigned_to": "claude"}) | My tasks |
bm_search("blockers", note_types=["task"]) | Tasks with blockers |
bm_search(note_types=["task"], time_kind="due", valid_overlaps="[2026-10-14,2026-10-21)") | Tasks with a step due this week |
bm_schema(command="validate", note_type="Task") | Validate all tasks against schema |
bm_schema(command="diff", note_type="Task") | Detect drift between schema and actual task notes |
Give a step or the task a due date with a qualifier (see memory-notes), so "what's due" is one search:
- [deadline] @due:2026-10-20 Draft ready for reviewA day-precision due date counts from that day onward, so a due-this-week search also returns overdue items.
activeparent_task [[X]] or relations to connect related workbm_schema(command="validate", note_type="Task") periodically to catch incomplete tasks~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.