agentleFS
AirMileAirMile/claude-config/skills/project-todo/SKILL.md

project-todo

Skill0 starsChanged 4 months agoMITView on GitHub

Use with /project-todo to capture an idea or finding as a backlog item.

The file

Show its rules and text

We split this skill into the rules it gives an agent

22 rules. About 0 are common, 8 are distinctive, and 14 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 14

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    NOT for: concept-level ideation (/project-seed), iterating on existing items (/project-seed brainstorm, /project-seed critique).

    line 35
  2. Very specific:

    Check whether .project/project.json exists.

    line 41
  3. Distinctive:

    No argument → ask the user directly: "What do you want to add to the backlog?" Wait for their answer.

    line 68
  4. Very specific:

    No token, user typed /project-todo themselves → CARD_ORIGIN = "user", CARD_SOURCE = "/project-todo".

    line 75
  5. Very specific:

    No token but a skill invoked this run → CARD_ORIGIN unset (the field is omitted entirely), CARD_SOURCE = "/project-todo".

    line 76
  6. Distinctive:

    Write a minimal data object:

    line 111
  7. Very specific:

    Check the five criteria in references/inference-rules.md § Ambiguity gate.

    line 158
  8. Distinctive:

    If criterion 2 (thin description) fired, fold the answers into the sharpened description — that is the only path that later writes a …

    line 164
  9. Very specific:

    Loop: all steps run per item in the queue.

    line 168
  10. Very specific:

    Read .project/backlog.json → parse JSON

    line 170
  11. Very specific:

    transition rule: only include "transition": "designing" when type === "PAGE" or type === "COMPONENT".

    line 192
  12. Very specific:

    No mutation to project.json for thinking — output goes in separate md files per DASHBOARD.md.

    line 225
  13. Very specific:

    Read .project/project.json (already read in Pre-PHASE 0)

    line 228
  14. Very specific:

    Check duplicate on name — if found and status > TODO: MERGE (update summary, preserve status).

    line 230
  15. Distinctive:

    Always report what was inferred and why, plus the correction line — the gate buys correctness cheaply after the fact instead of expensively …

    line 254
  16. Distinctive:

    Do NOT write implementation code

    line 359
  17. Distinctive:

    Do NOT modify existing items in the backlog (PHASE 4 corrects only the item just added, in the same turn)

    line 360
  18. Very specific:

    Do NOT ask for priority, type, category or dependencies — the inference rules resolve them.

    line 361
  19. Very specific:

    Do NOT raise more than one AskUserQuestion call per run

    line 362
  20. Very specific:

    NEVER use blockquote syntax (>) for displaying content — causes unreadable white background in dark terminals

    line 369
  21. Distinctive:

    NEVER use inline code backticks for emphasis on regular words — use bold or plain text

    line 370
  22. Distinctive:

    Follow the Language Policy in CLAUDE.md.

    line 375

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Todo

Capture new backlog items and add them to the backlog. The bridge between "I have an idea" and a backlog item ready for /dev-ship (define phase) (web) or /game-ship (define phase) (game).

Trigger: /project-todo or /project-todo [description]

Autonomous by default. Priority, type and dependencies are inferred from the description — never asked. The happy path runs with zero modals. Only the ambiguity gate (PHASE 1x) may raise a question, and only for the criteria listed there.

This matters beyond convenience: dev-ship and game-ship route out-of-scope findings here from inside the manual walkthrough and the live playtest. The user is present at those call sites, so the gate may fire normally — but parking three findings used to cost twelve modals. Adding a todo should cost one sentence.

When to Use

  • User has a new feature, change, bug fix, improvement, mechanic, or content idea for an existing project
  • User wants to quickly capture an item without full /project-plan

NOT for: concept-level ideation (/project-seed), iterating on existing items (/project-seed brainstorm, /project-seed critique).

Workflow

Pre-PHASE 0: Project Detection

Check whether .project/project.json exists.

  • Exists → read it, go to Stack Detection.
  • Does not exist → detect the project type from the filesystem, scaffold silently, continue. No modal.

    • project.godot present → GAME
    • otherwise → WEB
    • neither detectable (empty dir) → this is gate criterion 5; fold the question into the PHASE 1x modal.

    Write two files:

    1. .project/project.json — { "name": "{dir name}", "created": "{YYYY-MM-DD}", "stack": {}, "features": [] }, with "stack": { "engine": "godot" } for GAME.
    2. .project/session/setup-pending.json — { "source": "/project-todo", "mode": "greenfield", "createdAt": "{YYYY-MM-DD}" }

    Show: PROJECT.JSON CREATED — run /core-setup later for full setup.

Stack Detection (pre-PHASE 0)

stack.engine === "godot" OR concept.platform === "game" → GAME MODE. Otherwise → WEB MODE.

STACK: web    (→ /dev-ship pipeline)
STACK: game   (→ /game-ship pipeline)

PHASE 0: Input + Backlog Check

  1. Determine description:

    • Argument provided → use as starting description
    • No argument → ask the user directly: "What do you want to add to the backlog?" Wait for their answer.

    Provenance token (strip before anything else): a calling skill passes an explicit origin agent via /{skill} token inside the sentence (shared/BACKLOG.md § Card provenance). Detect it, record CARD_ORIGIN / CARD_SOURCE, and remove the token from the description text so it never lands on the card:

    • Token present → CARD_ORIGIN = "agent", CARD_SOURCE = "/{skill}".
    • No token, user typed /project-todo themselves → CARD_ORIGIN = "user", CARD_SOURCE = "/project-todo".
    • No token but a skill invoked this run → CARD_ORIGIN unset (the field is omitted entirely), CARD_SOURCE = "/project-todo". Never fall back to "user" here: that would relabel an un-migrated caller as human intent, and provenance you cannot trust is worse than provenance you do not have.

    Both values are carried through the whole run and applied identically in PHASE 2 steps 3 and 8. In a multi-item split every child inherits them — the split is a formatting decision, not a change of who asked.

  2. Size advisory (no modal):

    Count indicators of a large feature: multiple components/layers, cross-cutting concern, unbounded scope, multiple phases, keywords "redesign", "overhaul", "full", "entire", "system".

    ≥2 indicators → print one advisory line, then continue normally:

    ⚠ Large feature — consider /project-seed to structure it. Adding as a todo for now.

    Fewer than 2: no output.

  3. Multi-item split (automatic, no modal):

    [GAME MODE]: skip. Multi-item split is a dev/frontend concept and does not apply to MECHANIC/SYSTEM/CONTENT/POLISH/UI.

    [WEB MODE]: detect cross-domain signals — connectors ("including", "with accompanying", "and the page", "plus frontend"), or an explicit description of both backend/logic/API and UI/page/component.

    Detected → split automatically into 2-3 sub-items (max 3), each { name (kebab), type, description }, using the § Type inference tables. Link them: frontend children get dependencies: ["<dev-parent-name>"]. Set the internal queue items = [...] and report the split in PHASE 3 output. No confirmation prompt.

    Not detected → items = [single item].

  4. Backlog check:
    • Read .project/backlog.json
    • Not found → create it (see shared/BACKLOG.md § Writing for the legacy backlog.html migration rule):
      1. mkdir -p .project
      2. Write a minimal data object:
        {
          "schemaVersion": 2,
          "project": "{project directory name}",
          "generated": "{YYYY-MM-DD}",
          "updated": "{YYYY-MM-DD}",
          "source": "/project-todo",
          "overview": "",
          "features": [],
          "notes": ""
        }
    • Found → parse JSON, generate the kebab-case name(s), then check for an existing item that means the same thing. An exact name match is not enough: add-dark-mode does not collide with an existing dark-mode-theme, yet they are the same card. Match on both:

      1. Name equality — data.features.find(f => f.name === kebabName)
      2. Token overlap — tokenize (tokens ≥ 3 chars, the same tokenizer as § Dependencies inference) the new name plus the key nouns of its description, and compare against each existing item's name + description. ≥ 2 shared tokens makes it a candidate; then judge semantically whether it is really the same thing.

      Resolve:

      • No candidate → continue.
      • Evidently the same thing → do not add. Report the existing item and its status, suggest /project-seed brainstorm {name} to deepen it. Stop.
      • Evidently different intent (name collision only) → silently append a suffix (-2, -3).
      • Overlapping but unclear → gate criterion 3; carry into PHASE 1x.
      • Multi-item: also check collisions between queue names. Always resolve silently with a suffix — never gate.

PHASE 1: Inference

Todo: Read '.claude/skills/project-todo/references/inference-rules.md' — type, priority and dependency tables plus the ambiguity gate criteria.

Per queue item, derive:

  • type — § Type inference table for the active mode, first match wins. Row 5 (PAGE-GAP) resolves against the page register: project.json#design.pages[] (already read in Pre-PHASE 0) plus any backlog.json feature with type: "PAGE".
  • phase — § Priority inference table. Uncertain → P2. Never a modal.
  • dependencies — § Dependencies inference against the existing backlog names.
  • description — a self-contained card per shared/BACKLOG.md § Description quality: concrete observable behavior, scope boundary, 1–3 sentences. Never a restatement of the name.

    When CARD_ORIGIN === "agent", apply § Description quality → Lead sentence as well: the incoming sentence is a finding written for whoever held the code, so rewrite it into a plain-language lead (what is wrong + the consequence, no paths/symbols/test names in the first six words) followed by the technical locator. Do not paste the caller's sentence through verbatim — that is exactly what produces board rows nobody can scan. A user-typed description is exempt; keep their wording.

Record, per field, whether the inference was certain or hit a gate criterion. Track why each choice was made — PHASE 3 reports it.

Seed alignment scan (after the field derivation, before the gate):

Todo: run the Reader from shared/SEED.md once (cache SEED_CONTEXT across the queue). If SEED_CONTEXT.present → Read '.claude/skills/project-todo/references/seed-alignment.md' and run its § Alignment scan per queue item; otherwise skip silently.

Verdict per item: aligned, or drift { category, entry, proposedEdit }, or drift { category, entry, record-only }. Quality types (BUG/PERF/A11Y/THEME/POLISH) default to aligned; when unsure → aligned.

PHASE 1x: Ambiguity Gate

Check the five criteria in references/inference-rules.md § Ambiguity gate. None triggered, and no drift verdict carries a proposedEdit → no modal at all, straight to PHASE 2.

One or more triggered → one AskUserQuestion call, at most 4 questions, one per triggered criterion. Never two calls in one run. The first option is always the inference result marked (Recommended), so accepting the default equals full-auto.

If any PHASE 1 verdict carries a proposedEdit and no escape-hatch condition holds (references/seed-alignment.md § Escape hatch), append one extra "Seed update" question to this same single call, per seed-alignment.md § Seed update question — with the literal edit(s) as preview. The 4-question cap still wins: cap full → drop the seed question and downgrade its edits to record-only. This never justifies a second call.

If criterion 2 (thin description) fired, fold the answers into the sharpened description — that is the only path that later writes a thinking doc.

PHASE 2: Write to Backlog + Thinking

Loop: all steps run per item in the queue. For a single item, items = [single item]. For multi-item, steps 1-8 run sequentially per item, where dependencies[] refers to previously processed items in the batch.

  1. Read .project/backlog.json → parse JSON
  2. Generate name: kebab-case from description (e.g. "Dash ability with cooldown" → dash-ability)
  3. Insert into data.features[] — add the new object after the last item with status: "DOING" or status: "TODO", or at the start if there are no active items:

    {
      "name": "{kebab-case-name}",
      "type": "{inferred type}",
      "status": "TODO",
      "transition": "designing",
      "phase": "{inferred priority}",
      "description": "{inferred description}",
      "source": "{CARD_SOURCE}",
      "origin": "{CARD_ORIGIN}",
      "dependencies": []
    }

    description norm: apply shared/BACKLOG.md § Description quality — self-contained, concrete behavior + scope boundary, gate answers (PHASE 1x) folded in, 1–3 sentences, and for an agent-parked card the mandatory lead sentence before the locator. The card text is the only context /dev-ship (define phase) / /game-ship (define phase) gets when it is picked up later; never write a bare restatement of the name.

    transition rule: only include "transition": "designing" when type === "PAGE" or type === "COMPONENT". Omit the field entirely for all other types (FEATURE, API, THEME, PAGE-GAP, etc.).

    source / origin rule: both come from PHASE 0 step 1 (CARD_SOURCE / CARD_ORIGIN), never hardcoded. CARD_ORIGIN unset → omit the origin key entirely; never write null and never default to "user". Any source value keeps the card INDEPENDENT for /project-plan (the rule is !== "/project-plan", not === "/project-todo" — see shared/BACKLOG.md § Source field convention), so a re-stamped "/dev-ship" is still protected from a backlog rebuild.

  4. Update metadata: set data.updated to current date (YYYY-MM-DD)
  5. Seed drift resolution (executes the PHASE 1 verdict + 1x answer — no new modal, no re-scan):
    • Aligned → log Seed: ✓ aligned, done.
    • Approved edit (user picked "Apply edit(s)" in the PHASE 1x call) → apply the previewed Edit(s) literally to .project/project-seed.md, then the co-updates per shared/SEED.md § Write targets (pitch only when the replaced sentence appears in seed.pitch; backlog.json#overview rides the step-6 write pass). Details: references/seed-alignment.md § Write path. Log: Seed: ✓ updated — {n} edit(s) applied.
    • Declined / record-only / escape hatch → prepare the drift entry (real category, verbatim seedSays for contradictions) per shared/SEED.md § Drift entry schema with source: "/project-todo", ref: "feature:{name}", for later /project-seed § Sync pickup. Log: Seed: ⚠ drift recorded — {category}: {name}.
  6. Write back: Edit the JSON in .project/backlog.json. Find a unique anchor in the existing features array and use Edit to insert the new object before it. Prepared drift entries from step 5 are appended to data.seedDrift[] in this same write pass (initialize the array if absent) — no separate write roundtrip.
  7. Write thinking output (only if gate criterion 2 fired):

    Path: .project/thinking/feature-idea-{name}.md — mkdir -p .project/thinking

    # {Item Name}
    
    ## Description
    
    {sharpened description}
    
    ## {Question header 1}
    
    {answer}
    
    ## {Question header 2}
    
    {answer, if asked}

    No mutation to project.json for thinking — output goes in separate md files per DASHBOARD.md.

  8. Sync to project.json.features[] (concept sync):

    • Read .project/project.json (already read in Pre-PHASE 0)
    • Initialize features = [] if missing
    • Check duplicate on name — if found and status > TODO: MERGE (update summary, preserve status). Otherwise push:

      {
        "name": "{kebab-name}",
        "type": "{type}",
        "status": "TODO",
        "phase": "{P1-P4}",
        "summary": "{description, max 200 chars}",
        "dependencies": [],
        "source": "{CARD_SOURCE}",
        "origin": "{CARD_ORIGIN}",
        "created": "{YYYY-MM-DD}"
      }

      Same source/origin rule as step 3 — identical values, and origin omitted entirely when unset. Writing one file with provenance and the other without desyncs the dashboard silently.

    • Write .project/project.json

    seed.content is legacy — never write it. project-seed.md is only ever touched by the approved surgical path in step 5.

PHASE 3: Output

Always report what was inferred and why, plus the correction line — the gate buys correctness cheaply after the fact instead of expensively up front. Always print the Seed: verdict line — its presence is the forcing function that the PHASE 1 alignment scan actually ran.

[MULTI-ITEM — when items queue > 1]:

TODOS ADDED ({n} items — auto-split)

  1. {name-1}    {phase} · {type}
     {description-1}

  2. {name-2}    {phase} · {type}     ← depends on: {name-1}
     {description-2}

  Seed: {✓ aligned | updated — {n} edit(s) applied | ⚠ drift recorded — {category}}  ← always shown, the PHASE 2 step-5 verdict
  ⚠ {N} pending drift item(s) in backlog — run /project-seed → "Sync with project"
                                      ← only if data.seedDrift[].length ≥ 3 after the write
  Backlog: .project/backlog.json
  Adjust? Say "make {name-1} P1" or "{name-2} should be COMPONENT".
  Next steps:
  [Per item, appropriate next step from the WEB/GAME MODE output below]

[WEB MODE — single item]:

TODO ADDED

  {name}                {phase} · {type}
  {description}
  Thinking: .project/thinking/feature-idea-{name}.md    ← only if gate criterion 2 fired
  Seed: {✓ aligned | updated — {n} edit(s) applied | ⚠ drift recorded — {category}}  ← always shown, the PHASE 2 step-5 verdict
  ⚠ {N} pending drift item(s) in backlog — run /project-seed → "Sync with project"
                                                        ← only if data.seedDrift[].length ≥ 3 after the write

  Inferred: {phase} ({reason}) · {type} ({reason})
  Adjust? Say "make it P1" or "type is COMPONENT".

  Backlog: .project/backlog.json
  Next steps:
  - /project-seed brainstorm {name} - Deepen the idea with variations
  - /project-seed critique {name} - Test the idea critically
  [If type is FEATURE, CHANGE, BUG, or API:]
  - /dev-ship {name} - Start with requirements and building
  - /team-outsource {name} - Outsource to a teammate via GitHub/Jira/Linear
  [If type is TWEAK:]
  - /dev-tweak {name} - Pick up the tweak on main (no worktree needed)
  [If type is PAGE or COMPONENT:]
  - /design-convert {name} - Build the page/component
  - /design-convert - Define multiple pages at once
  [If type is THEME:]
  - /design-tokens - Set up design tokens (color, typography, spacing)
  [If type is A11Y:]
  - /design-ship {name} - Ship the page (build + runtime check: a11y/perf/SEO)
  [If type is PERF:]
  - /design-ship {name} - Ship the page; its check phase runs the performance and SEO audit
  [If type is PAGE-GAP:]
  - /dev-ship {name} - Define the missing functionality
  [If type is VERIFY:]
  - /dev-manual {parentFeature} - Re-run the deferred manual test(s) once the blocker ships

[GAME MODE]:

FEATURE ADDED

  {name}                {phase} · {type}
  {description}
  Thinking: .project/thinking/feature-idea-{name}.md    ← only if gate criterion 2 fired
  Seed: {✓ aligned | updated — {n} edit(s) applied | ⚠ drift recorded — {category}}  ← always shown, the PHASE 2 step-5 verdict
  ⚠ {N} pending drift item(s) in backlog — run /project-seed → "Sync with project"
                                                        ← only if data.seedDrift[].length ≥ 3 after the write

  Inferred: {phase} ({reason}) · {type} ({reason})
  Adjust? Say "make it P1" or "type is SYSTEM".
  Consider /game-debug for an existing-behavior bug.    ← only on bug signals

  Backlog: .project/backlog.json
  Next steps:
  - /project-seed brainstorm {name} - Deepen the idea with variations
  - /project-seed critique {name} - Test the idea critically
  - /game-ship {name} - Start with requirements and architecture

PHASE 4: Correction

Fires only when the user adjusts a field in the same turn, in response to the PHASE 3 correction line ("make it P1", "type is COMPONENT", "it depends on auth-api"). This is what makes zero-modal inference safe: a wrong guess costs one sentence to undo.

Correctable fields: phase, type, dependencies. Anything else (rewriting the description, rethinking the idea) → point at /project-seed brainstorm {name} and stop.

  1. Patch both files. The card lives in backlog.json#features[] (PHASE 2 step 3) and project.json#features[] (PHASE 2 step 8). Patching one desyncs the dashboard silently. Use the read-parallel → mutate → write-parallel batch from shared/BACKLOG.md § Parallel sync.
  2. Recompute transition when type changes. This is the trap:
    • to PAGE/COMPONENT → add "transition": "designing", otherwise /design-convert will never pick the card up
    • away from PAGE/COMPONENT → remove the transition field entirely
    • neither side is PAGE/COMPONENT → leave it absent
  3. Recompute phase only if the user did not name one. A type correction does not silently re-derive priority — the user already saw and accepted it.
  4. Idempotent: applying the same correction twice yields the same state.

Log one line per field: Corrected: {field} {old} → {new} (plus transition: added|removed when step 2 fired).

Restrictions

  • Do NOT write implementation code
  • Do NOT modify existing items in the backlog (PHASE 4 corrects only the item just added, in the same turn)
  • Do NOT ask for priority, type, category or dependencies — the inference rules resolve them. Only the five ambiguity-gate criteria may raise a question, in a single bundled AskUserQuestion
  • Do NOT raise more than one AskUserQuestion call per run
  • Max 3 items per batch during auto-split
  • Gate criterion 2: max 2 clarifying questions
  • Seed writes ONLY via the approved surgical path (PHASE 2 step 5, references/seed-alignment.md § Surgical edit contract) — a single targeted Edit or section append, never a rewrite. Everything else in project-seed.md/seed.* is owned by /project-seed; seed.content is legacy and never written

Terminal Formatting

  • NEVER use blockquote syntax (>) for displaying content — causes unreadable white background in dark terminals
  • NEVER use inline code backticks for emphasis on regular words — use bold or plain text
  • Backticks only for actual code, file paths, and command references

Language

Follow the Language Policy in CLAUDE.md.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.