Files
vitya 13abe176fd feat(using-tasks): session lock guard v1.4.0
Adds `.tasks/.lock` awareness to the `using-tasks` skill:

- Session start new step 1: read `.tasks/.lock`; if type:"agent" with
  heartbeat ≤10 min → hard warning + require user confirmation; stale
  lock (TTL expired) → silently overwrite; absent/cleared → write
  type:"interactive" lock (120-min TTL).
- Session end new step 1: delete `.tasks/.lock` when type:"interactive".
- Structure section: `.lock` entry with gitignored callout.
- Rules bullet: "Honour `.tasks/.lock`".
- `.gitignore`: adds `.tasks/.lock` (ephemeral runtime state).
- dist/using-tasks.skill rebuilt.

Closes [using-tasks-session-lock].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 12:57:48 +03:00

15 KiB
Raw Permalink Blame History

name, version, description
name version description
using-tasks 1.4.0 Policy skill for working with an existing `.tasks/` board (per-task files + STATUS.md). Use whenever the user is switching between tasks, resuming a paused task, starting a new task, asking "where were we", says "use task management system", "pause", "switch to X", "what's the status", "update status", or wants to track progress across parallel workstreams. Trigger on any context-switching or multi-task coordination question in a code project. If `.tasks/` is missing or non-canonical (no per-task `<task-slug>.md` files, no emoji status legend in STATUS.md), delegate to `setup-tasks` first — it has its own confirmation gate. Renamed from `task-status-wiki` at v1.0.0.

using-tasks

Policy for maintaining compressed working context across parallel tasks in a monorepo. The agent reads and updates .tasks/ so every session starts oriented and every switch costs seconds, not minutes. This skill governs usage of an existing .tasks/ — initial creation and migration to canon are owned by setup-tasks.

Prerequisites

This skill assumes the project has a canonical .tasks/ layout:

  • .tasks/STATUS.md — the board, with per-task blocks using emoji status (🔴 active / 🟡 paused / ready / 🟢 done / 🔵 blocked).
  • .tasks/<task-slug>.md — one deep-context file per active or paused task.

If .tasks/ is missing, or STATUS.md exists but is non-canonical (e.g. flat sections like "## Done" / "## In Progress" without the emoji + per-task block format, or no per-task files exist alongside STATUS.md) — invoke setup-tasks first. It detects greenfield vs migrate, has its own confirmation gate, and creates / migrates the structure. Only after setup-tasks finishes should this skill operate on .tasks/.

Structure

<monorepo-root>/
  .tasks/
    STATUS.md          ← active board: 🔴 / 🟡 / ⚪ / 🔵 blocks, sorted by priority
    <task-slug>.md     ← deep context per task, one file each
    .lock              ← runtime session lock; **gitignored** (never committed)
    archive/
      YYYY-MM.md       ← 🟢 done blocks moved off the board, one file per month

Commit .tasks/ to git. Decision history is valuable; diffs show how thinking evolved.

STATUS.md is the active board — it must stay lean so orientation reads stay cheap. Closed 🟢 tasks are archived to archive/YYYY-MM.md once they pile up; see "### Archiving done tasks".

.tasks/.lock must be listed in .gitignore (add .tasks/.lock to your project's .gitignore). The lock file is ephemeral runtime state, not project history — it must never be committed.


STATUS.md format

# Task Board
_Updated: YYYY-MM-DD_

## 🔴 [task-slug] — short description
**Status:** active | paused | blocked | done
**Where I stopped:** one sentence — the exact thought or action interrupted
**Next action:** one concrete step to resume immediately
**Blocker:** (only if blocked) what is preventing progress
**Session break:** (optional) `true` — or a hint string for the next track. Marks this task as a session boundary.
**Branch:** git branch name

---

Emoji convention:

  • 🔴 Active — currently worked on (only one at a time)
  • 🟡 Paused — in progress, resumable
  • Ready — not started, fully defined
  • 🟢 Done — completed; kept on the board until merged, then archived (see "### Archiving done tasks")
  • 🔵 Blocked — waiting on external input

session_break marker

A task may carry a session_break marker — set by whoever defines the task (e.g. the delegating workshop) when its completion is a natural place to stop and start a fresh session. It signals an autonomous agent: finish this task, then pause instead of immediately claiming the next one.

  • Type: boolean or string.
    • session_break: true — pause after close; the next track is "see STATUS.md".
    • session_break: "<hint>" — pause after close; <hint> names the recommended next track.
  • Where it lives: in the task's frontmatter when delivered via the task system (session_break: true / session_break: "<hint>"); mirrored on the local board as the optional **Session break:** field in the task's STATUS.md block.
  • Absent → behaviour is unchanged: close the task and continue as usual.

The check is enforced in the Task completion flow below (after close, before claiming the next task).


Per-task file format (<task-slug>.md)

# <task-slug>

## Goal
One paragraph. What this achieves and why it matters in the monorepo.

## Key files
- `path/to/file.ts` — role in this task
- `path/to/other.ts:42` — specific line if relevant

## Decisions log
Reverse-chronological. Append only — never rewrite past entries.
- YYYY-MM-DD: Why X was chosen over Y
- YYYY-MM-DD: Constraint Z discovered, approach adjusted

## Open questions
- [ ] unresolved design or dependency questions

## Completed steps
- [x] steps finished this or previous sessions

## Notes
Temporary hypotheses, links, names of people to consult.

Agent operations

Session start

  1. Session lock guard. If .tasks/ exists, read .tasks/.lock.
    • Active agent locktype:"agent" with heartbeat ≤ 10 minutes old: print the hard warning below and require explicit user confirmation before proceeding. Do not touch the board until the user confirms.
      ⚠️ поллер ведёт <slug> — нельзя работать параллельно
      
      (Substitute the slug field from the lock file if present, otherwise omit it.)
    • Stale lock — any type whose TTL has expired (type:"agent" with heartbeat > 10 min ago; type:"interactive" with started_at > 2 h ago): silently overwrite.
    • Absent or stale lock (including after user confirmation): write .tasks/.lock:
      {"type":"interactive","started_at":"<ISO8601>","ttl_minutes":120}
      
  2. Check if .tasks/STATUS.md exists. If not → invoke setup-tasks and stop here until it returns.
  3. Read STATUS.md — this is the orientation read (see note below on why it's a local read, not an MCP call).
  4. If user names a task, read its <task-slug>.md.
  5. Confirm in one sentence: "We're in the middle of X, next step is Y."
  6. Ask if the plan is still correct before doing anything.
  7. If STATUS.md _Updated date is >3 days ago, flag it and ask user to confirm current state.
  8. If STATUS.md holds ≥ 10 🟢 done blocks, archive them first (see "### Archiving done tasks") so the board you orient on is lean.

Orient by reading the local STATUS.md, not an MCP call. It is the live board and — kept lean by archival — cheap to read. Do not reach for projects-meta tools to enumerate the current project's board:

  • tasks_aggregate is cache-based, cross-project, and does not index ready/done — its own docs say to read .tasks/STATUS.md directly for the current project.
  • tasks_get_status(target_project, slug) returns a single task's live status ({status, found}) by a slug you already know — it cannot list the board. Use it only to check one known task (e.g. confirm a delegated task's board state, or detect async-human parking), never for orientation.

Session end / pause / switch

  1. Release session lock. If .tasks/.lock exists and contains "type":"interactive": delete .tasks/.lock. (Stale interactive locks are cleaned up here too; silently delete any interactive lock regardless of TTL.)
  2. Update STATUS.md: set current task to 🟡, update "Where I stopped" and "Next action".
  3. Append to <task-slug>.md Decisions log any non-obvious choices made this session.
  4. Move finished items to "Completed steps".
  5. Commit: git add .tasks/ && git commit -m "chore: update task status [<task-slug>]"

Task switch

  1. Perform session-end operations for the current task.
  2. Read the target <task-slug>.md.
  3. Set it to 🔴 in STATUS.md (demote previous active to 🟡).
  4. Confirm orientation before starting work.

New task creation

  1. Ask: task name (slug), goal, known key files, branch name.
  2. Create <task-slug>.md with Goal and Key files populated.
  3. Add block to STATUS.md.
  4. Create and checkout branch if it doesn't exist.

Task completion

  1. Pre-close coverage check. Before setting 🟢:
    • List acceptance criteria from the per-task <slug>.md (or the STATUS block if no per-task file).
    • For each criterion, locate evidence: a test name in the diff, a smoke-test artefact, a manual-checklist tick in the per-task file, or a design-doc reference.
    • Missing evidence on any criterion → flag to user and ask "закрывать или подождать coverage'а?". Never silently close.
    • If acceptance criteria are policy / docs-only and have no testable shape, an explicit user "ok, closed by inspection" is required (record this in the close-note).
  2. Resolve or drop all open questions.
  3. Set status to 🟢 in STATUS.md.
  4. Append final summary line to Decisions log.
  5. Remind user to delete the branch after merge.
  6. Session-break check (after close, before claiming the next task). Once the task is 🟢 and committed — and before any tasks_claim_next or starting the next task — read the closed task's session_break marker (its frontmatter session_break, or the **Session break:** field in its STATUS.md block). If present:
    • Print this line verbatim, substituting the closed task's slug for [slug] and the marker's string value for [value | "см. STATUS.md"] (use the literal см. STATUS.md when the marker is just true):

      🔚 SESSION BOUNDARY — [slug] закрыта. Рекомендую завершить текущую сессию. Следующий трек: [value | "см. STATUS.md"]

    • Stop. Do not claim or start the next task.

    • If the marker is absent → behaviour is unchanged: proceed to claim / start the next task as usual.

  7. Archival check. After the close is committed, if STATUS.md now holds ≥ 10 🟢 done blocks, archive them (see "### Archiving done tasks"). This keeps the board lean for the next orientation read.

Archiving done tasks

🟢 done blocks accumulate in STATUS.md and bloat it — and since orientation reads the whole board, a bloated file burns context on every session start (the recurring "huge STATUS.md" complaint). Keep the board lean: done blocks stay only until merged, then move to a monthly archive.

Threshold. When STATUS.md holds ≥ 10 🟢 done blocks, archive them. Check at two moments: (a) right after closing a task (Task completion step 7), and (b) at session start, before orienting (Session start step 7). The threshold is a ceiling, not a target — archive in batches; don't churn one block at a time.

Where. Append the archived blocks to .tasks/archive/YYYY-MM.md — one file per calendar month, keyed by the date of archival. Create .tasks/archive/ and the month file if absent. If the month file already exists, append; never overwrite.

Archive file format (header written once, on file creation):

# Archived done tasks — YYYY-MM

Moved out of `.tasks/STATUS.md` to keep the active board lean.
Full source is git history; this file is for grep-able historical context.

---

…followed by each 🟢 block verbatim (including its trailing --- separator and any <!-- closed-by … --> comments).

After archiving, STATUS.md keeps only 🔴 / 🟡 / / 🔵 blocks. Commit the move on its own:

git add .tasks/ && git commit -m "meta(tasks): archive done batch → .tasks/archive/YYYY-MM.md"

Leave a just-closed 🟢 block on the board only while it's still useful at a glance (pending merge, fresh reference). Everything older goes to the archive.

Post-commit task closure prompt

After any implementation commit (feat: / fix: / similar), prompt the user once:

Эта работа закрывает таску <slug>?

Slug candidates, in priority: (a) commit message scope, (b) current branch name, (c) the most recent Where I stopped field that mentions a now-shipped artefact. If user says yes → run the pre-close coverage check from "### Task completion". If no → silent.

Skip on chore: / meta: / docs: / style: commits — they rarely close work.

This exists because shipped code can sit while the task block stays ready (e.g. extend-project-discipline-brainstorm-workspaces lived as for a day after 215afdd shipped Rule 5). The prompt forces a one-line decision while the work is fresh.

Recommendations / "what's next" trigger

When the user asks «что дальше», «срочные», «куда копаем», «status», «what next», or session-start lands on a project — recommend in this order:

  1. Local cwd-project board ranked 🔴🟡. Group by status, summarize one line each. Cite slugs.
  2. One footnote line if cross-project state is relevant: Cross-project: N 🔴 active in other repos (см. mcp__projects-meta__tasks_aggregate). Only when N>0 and there is no active 🔴 in the current cwd. Never bury local recommendations under it.

Cross-project urgents are information, not the driver of "what to do here". The user chose this cwd; that's the implicit scope.

If the user explicitly asks "across all projects" / "по всем проектам" / "cross-project status" — flip the order: cross-project first, local as footnote.

Pair: using-projects-meta declares local-first for reads; this rule extends local-first to the recommendation phase.


Rules

  • Honour .tasks/.lock — read the lock at session start before touching the board; write it after clearing the guard; delete it at session end/pause. Never skip the lock check when .tasks/ exists. The lock file must be gitignored.
  • Never lose "Where I stopped" — most critical field. If unclear, ask before ending session.
  • One sentence per STATUS.md field — compress, don't write prose.
  • Key files must be specific — not "auth module" but packages/auth/src/useAuth.ts:87.
  • Decisions log is append-only — past entries are immutable.
  • Commit after every session end — git log is the history of thinking.
  • Always confirm orientation at session start — state understanding before acting.
  • One active task at a time — only one 🔴 in STATUS.md.
  • Keep the board lean — orientation reads the local STATUS.md whole, so archive 🟢 done blocks to .tasks/archive/YYYY-MM.md once ≥10 pile up. Never enumerate the current project's board via tasks_aggregate (cross-project cache) or tasks_get_status (single-task, by slug). See "### Archiving done tasks".
  • Never close a task without a coverage check — see "### Task completion" step 1. Acceptance criteria with no evidence → ask, don't auto-close.
  • Honour session_break — a closed task carrying a session_break marker means stop after close; never chain into tasks_claim_next. See "### Task completion" step 6.
  • Local-first recommendations — cwd-project board comes first; cross-project urgents are at most one footnote line.