14 · v0.4.2 — Task Status Model

Series: Building synlynk — a single-file Python CLI that turns any AI CLI into a context-aware multi-agent workgroup harness.


Where we were

v0.4.1 (PR #45) shipped Instruction Reach — synlynk now writes its context-injection protocol into 7 IDE and CLI instruction targets (CLAUDE.md, GEMINI.md, AGENTS.md, Cursor MDC, Copilot instructions, Windsurf rules, AI_INSTRUCTIONS.md) with SHA-based drift detection. Every agent in the workgroup receives identical constraints from a single source of truth.

The broader goal at the end of v0.4.1: move synlynk toward a model where it can operate itself — dispatching Claude, AGY, and Codex on real tasks, with the capability ledger accumulating enough signal to route intelligently. That requires the project state layer (todo.md, roadmap.md, memory.md) to be expressive enough to represent not just what's open and what's done, but the full lifecycle of a task.


The shift this PR makes

v0.4.2 is a focused quality-of-life upgrade: the binary checkbox model ([ ]/[x]) is insufficient for real multi-agent workflows. When an agent supersedes an approach or scope is absorbed into another task, [x] is technically wrong (the work wasn't completed, it was resolved differently). And deferred tasks disappear from context even though they represent active intent.

The fix: replace two states with five.


What shipped

Five-State Task Status Model

TASK_STATUSES constant

A module-level dict that makes the 5-state vocabulary explicit and testable:

TASK_STATUSES = {
    "[ ]": "active",
    "[x]": "done",
    "[-]": "deferred",
    "[~]": "superseded",
    "[>]": "absorbed",
}

generate_context() — deferred tasks in context

Previously: only [ ] lines were surfaced in the context snapshot agents receive.

Now: [ ] tasks appear under ## Active Tasks; [-] deferred tasks appear under ### Deferred. Superseded [~] and absorbed [>] are intentionally excluded — they are resolved states that don't require agent attention.

active, deferred = [], []
for line in f:
    if "- [ ]" in line:   active.append(line)
    elif "- [-]" in line: deferred.append(line)
if active or deferred:
    out.write("## Active Tasks\n")
    out.writelines(active)
    if deferred:
        out.write("\n### Deferred\n")
        out.writelines(deferred)

checkpoint() — archives all resolved states

Previously: only [x] (done) lines were archived and removed from todo.md.

Now: [x], [~], and [>] are all archived as "Resolved". Deferred [-] lines are kept. The devlog section heading changed from "Completed" to "Resolved" to reflect the broader semantics.

Regex: r'\s*-\s*\[(x|~|>)\]'

Agent instruction templates

All three instruction builders (_build_templates, the GEMINI.md/AGENTS.md variant, and _build_windsurf_rules) now include the 5-state legend instead of "Mark tasks [x]":

Update task status in project-docs/todo.md — do not delete tasks:
`[ ]` active · `[x]` done · `[-]` deferred · `[~]` superseded · `[>]` absorbed

init() todo template

New init todo.md includes a one-line HTML comment legend so the format is self-documenting:

<!-- Status: [ ] active  [x] done  [-] deferred  [~] superseded  [>] absorbed -->

Tests

7 new tests, 251 total passing:

  • test_task_statuses_constant_defined — validates all 5 states in the dict
  • test_generate_context_includes_deferred_tasks[-] in context, [x] not
  • test_generate_context_excludes_superseded_tasks[~] excluded
  • test_generate_context_excludes_absorbed_tasks[>] excluded
  • test_checkpoint_archives_superseded_tasks[~] removed from todo after checkpoint
  • test_checkpoint_archives_absorbed_tasks[>] removed from todo after checkpoint
  • test_checkpoint_keeps_deferred_tasks[-] survives checkpoint

Progress on the long arc

The 5-state model removes a subtle but important ambiguity that would have corrupted the capability ledger. If an agent marks a task [x] because the approach was superseded (not because the work was done), the telemetry records a false success. With [~] and [>] as distinct resolved states, checkpoint can archive them separately — and future scoring logic can treat them differently from genuine completions.

The three remaining brainstorm initiatives from this session are:

  • v0.5.1 Static Scan Qualitygenerate_context() reads source code architecture beyond README + git log
  • v0.6.1 Capability Dogfood — use synlynk to build synlynk, accumulate real routing signal
  • v0.7.0 Async Pipeline + Daemon — HTTP context server, background dispatch, TUI

New goalpost

v0.4.2 is the last patch on the 0.4.x line. The project-docs/ state layer is now expressive enough to support the capability ledger without ambiguity.

Next: v0.5.1 Static Scan Qualitygenerate_context() currently misses the most valuable signal available without AI calls: the repo's source code architecture. Surfacing key function signatures, module structure, and cross-file dependency patterns in context will narrow the semantic gap between what agents read and what the codebase actually contains.