Frame a piece of work using the 4-component convention (Problem / Context / Guiding policy / Master plan) and add it to the project's TODO.md through the framing validator. Use when a user wants to create a [Thought]-tagged TODO item or any item that must pass the framing gate.
Resources
1Install
npx skillscat add dmitrydf/q/work-frame-and-create-todo Install via the SkillsCat registry.
/work-frame-and-create-todo
Conversationally elicit the four framing components, then add the framed item to the project's TODO.md through the code-side framing validator. Thin AI elicitation surface around ${KIT_HOOKS_DIR}/todo.py add --validate-framing; the cap on how many times we retry on validation failure lives in run.py (code), not in this file.
Trigger
Explicit invocation only:
/work-frame-and-create-todo- "frame this and add it to TODO"
- "create a [Thought] TODO for …"
Not auto-triggered. v1 is callable-only — the user (or another skill) invokes it explicitly.
What this skill does
- Elicit the four framing components from the user (and a bucket):
**Title**— the bold-wrapped item titleProblem:— what's broken or unresolvedContext:— relevant background, prior decisions, constraintsGuiding policy:— the overall approach (no implementation detail)Master plan:— either a wikilink to the plan/thought file or the literalMaster plan:label followed by the plan reference
- Ask for the bucket —
NOW/NEXT/NEARBY/NASCENT/SCHEDULED(per 5N just-in-time learning). - Compose a single-line TODO item that matches the convention:
**Title** — Problem: …. Context: …. Guiding policy: …. Master plan: [[…]]. - Call
run.py(the orchestrator) with a JSON payload on stdin. - Branch on
run.py's structured JSON result:status: PASS→ tell the user it landed, show the resolved TODO.md path, stop.status: RETRY→ re-elicit ONLY the components listed inmissing_components; recompose; callrun.pyagain.status: EXHAUSTED→ surfacestderr_verbatimand stop. Do not loop further. The 3-retry cap is code-enforced —run.pywill refuse to retry on the next call regardless of what this skill does.
Calling the orchestrator
Run run.py from this skill folder via Bash. Pass the JSON on stdin via a heredoc-safe pattern (use Write to a temp file then pipe, or pass a single-line JSON):
echo '<json>' | python3 ~/.claude/skills/work-frame-and-create-todo/run.pyInput JSON contract (keys):
| Key | Required | Description |
|---|---|---|
item_text |
yes | The composed single-line TODO item (4 components + bold title + em-dash). |
bucket |
yes | One of NOW, NEXT, NEARBY, NASCENT, SCHEDULED. |
cwd |
no | Working directory to resolve the target TODO.md from. Defaults to the orchestrator's os.getcwd(). |
session_id |
no | Stable identifier so consecutive calls share the retry counter. Defaults to $CLAUDE_SESSION_ID or "default". Pass the current session id when available. |
Output JSON contract (keys): status (PASS / RETRY / EXHAUSTED / ERROR), attempt, max_retries, missing_components, stderr_verbatim, session_id. Exit codes: 0=PASS, 1=RETRY, 2=EXHAUSTED, 3=usage/input error.
Elicitation flow
Step 1 — Title + bucket. Ask the user for a short, action-oriented title and a bucket. Use AskUserQuestion for the bucket so the user can pick from a single-select list.
Step 2 — Four components. Ask for Problem:, Context:, Guiding policy:, Master plan: — one at a time or in a single prompt depending on what the user prefers. Be explicit that:
Problem:should name the critical challenge, not just describe symptoms (Rumelt diagnosis style).Guiding policy:should describe the approach, not the specific actions.Master plan:should be either a wikilink ([[plan-slug]]) to the planning artifact OR the literalMaster plan:label followed by a description; the validator accepts either form.
Step 3 — Compose. Build the item text in this exact shape (the validator regexes match against these labels):
**<Title>** — Problem: <…>. Context: <…>. Guiding policy: <…>. Master plan: [[<plan-slug>]].Master plan: takes either form. Both of these are accepted:
… Master plan: [[omtm-dashboard-plan]].
… Master plan: none yet — this TODO owns the work directly.Show the second form when there is no planning artifact. Only ever showing the
wikilink is what made the other form look unsupported.
Evidence. This skill files through --require-evidence, so an item must
point at somewhere to look — a path:line, a backticked file, a [[wikilink]],
or a URL. An item that points at nothing is refused with a reason, and nothing
is written.
For build-new work there is often nothing to point at yet. Record that
deliberately with the literal token [build-new] in the item text:
**Create a strategy-creation skill** — Problem: no reusable tool helps author a
strategy from a diagnosis. Context: the kernel is documented but nothing
operationalises it. Guiding policy: compose existing sub-skills rather than
adding a new framework. Master plan: none yet. [build-new]The token stays on the list on purpose — an escape hatch that vanishes after the
call cannot be audited, and its overuse should be visible. A citation that does
not resolve produces a warning, never a refusal: most correct citations in
this corpus name a file in another repo or by an ambiguous basename.
Step 4 — Call run.py. Use Bash to invoke the orchestrator. Pass session_id when available so consecutive failed attempts share the retry counter.
Step 5 — Branch on result.
- PASS → "Item added to . Bucket: ." Stop.
- RETRY → look at
missing_components. Re-elicit ONLY those components from the user. Recompose. Callrun.pyagain. - EXHAUSTED → "Framing validation failed after 3 attempts. The validator reports:
<stderr_verbatim>. Re-engage when you have the four components ready, or compose the item directly." Stop. Do not loop further.
Concerns (0–3) convention
When you report PASS / RETRY / EXHAUSTED back to the user, follow the project's Concerns convention: include 0–3 specific concerns about your own elicitation (gaps, assumptions, missing data). One sentence each. No abstract scores.
Constraints
- No re-validation in this skill. The validator (
todo.py add --validate-framing) is the single source of truth for framing correctness. This skill does not parse the user's input against the four components on its own. - Retry cap is code-enforced.
run.pyowns the per-session counter and the 3-retry cap via a state file at~/.claude/state/work-frame-and-create-todo/<session_id>.json. Even if this SKILL.md tells the AI to "keep trying," the orchestrator will returnEXHAUSTEDon the 4th call. Trust Hierarchy: Code > Rules > Skill text. - Producer-never-verifies. AI elicits; code validates. (
~/.claude/rules/code_first_architecture.md:112.) - Thin shim.
run.pycontains NO framing logic — it only orchestrates the loop aroundtodo.py add --validate-framing. cwdresolution.run.pywalks up fromcwdto find the nearestTODO.md. If none is found up to filesystem root, it returns anERRORpayload and exits with code 3.
Edge Cases
| # | Case | Detection | Behavior |
|---|---|---|---|
| E1 | cwd inside a subdir | Working dir is several levels below the project root | run.py walks up looking for TODO.md; uses --project <root> once found. |
| E2 | Partial framing | Validator emits ✗ <err> lines via stderr |
run.py returns status: RETRY with missing_components: [...]; SKILL re-elicits ONLY those fields. |
| E3 | No TODO.md anywhere |
Walk-up from cwd reaches filesystem root with nothing |
run.py returns ERROR exit 3. Tell the user: "No TODO.md found at or any parent. Create one with touch TODO.md, then retry." Stop. |
| E4 | Cap reached | run.py exit code 2, status: EXHAUSTED |
Surface stderr_verbatim. Do not loop. Stop. |
| E5 | Bucket not in enum | User picks something else than NOW/NEXT/NEARBY/NASCENT/SCHEDULED | run.py returns ERROR exit 3. Re-ask the user for a valid bucket. |
| E6 | Empty stdin / bad JSON | Orchestrator can't parse input | run.py returns ERROR exit 3. Skill recomposes and retries. |
| E7 | User abandons elicitation | No reply within one prompt cycle | Skill exits silently. No blocking state; cap state file is per-session and cleaned up on next PASS / EXHAUSTED. |
Examples
Example 1 — Happy path
User: /work-frame-and-create-todo
Skill asks for the title, the bucket, and the four components. User answers each. Skill composes:
**Wire up the OMTM dashboard** — Problem: we can't see week-over-week OMTM movement. Context: dashboard wiring exists but the OMTM query was never plumbed. Guiding policy: reuse the existing dashboard scaffolding; do not introduce a new visualization. Master plan: [[omtm-dashboard-plan]].Skill calls run.py with bucket: NEXT. Validator passes. Skill reports:
Item added to
Personal/foo-Initiative/TODO.mdunder NEXT. Concerns: [].
Example 2 — Retry path
User provides three of four components on the first pass. Skill composes, calls run.py. Validator fails on Master plan:. run.py returns:
{"status": "RETRY", "attempt": 1, "max_retries": 3,
"missing_components": ["Missing 'Master plan:' label or [[wikilink]]"],
"stderr_verbatim": " ✗ Missing 'Master plan:' label or [[wikilink]]\nFraming validation failed. Fix the item text and retry.\n",
"session_id": "abc123"}Skill re-elicits ONLY the Master plan field, recomposes, calls run.py again. Validator passes; item added; state file cleared.
Example 3 — Cap reached
User gives malformed framing four times in a row. Calls 1–3 return RETRY; call 4 returns EXHAUSTED (exit code 2). Skill surfaces the validator's verbatim stderr and stops. The state file at ~/.claude/state/work-frame-and-create-todo/<session_id>.json is deleted by run.py on the EXHAUSTED return, so the next fresh invocation starts a new attempt counter.
Sibling Skills
/clarification(~/.claude/skills/clarification/SKILL.md) — full Clarification phase that creates a_THOUGHT.mdand a framed TODO line in one motion. Use/clarificationwhen the work needs a spine — it is large enough to carry its own Discovery, solution design and plan. Use this skill when you only want the framed TODO.A pre-existing plan or thought file is NOT a precondition for this skill. A framed TODO may own a plan directly, with no
_THOUGHT.mdin between — that is a sanctioned entry point (bookkeeping-model.md§6, "TODO-owned"), not a workaround. Earlier wording here said to use this skill when "the framing artifact (plan / thought file) already exists", which read as a requirement and steered people into/clarificationfor work that never needed a spine. Nothing in the validator asks for one: theMaster plan:field accepts a plain reference as readily as a wikilink (see:73and the second example below)./work-start(~/.claude/skills/work-start/SKILL.md) — moves an already-framed TODO into in-progress.
Created: 2026-05-24 — v1. Code-enforced retry cap via run.py orchestrator (per-session state file). SKILL.md owns elicitation only.