diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-24 07:09:21 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-24 07:09:21 -0400 |
| commit | 9709638f1d50193bd4636205a142a2277f92e4f4 (patch) | |
| tree | 8b9adc4fee6a853c4f629dd85210de91807db157 /.ai | |
| parent | 06b6cbcf086729414ff9a533b1f031fb41c4088b (diff) | |
| download | rulesets-9709638f1d50193bd4636205a142a2277f92e4f4.tar.gz rulesets-9709638f1d50193bd4636205a142a2277f92e4f4.zip | |
refactor(tasks): use a :blocker: tag, not a :BLOCKS: property
:BLOCKS: rulesets: was a malformed org tag, and the property form (:BLOCKED_BY: / :BLOCKS: carrying <project>: <what>) was more structure than the dependency needs. The blocking side now carries a plain :blocker: tag, mirroring :blocked: on the waiting side, with the which-project detail in the task body rather than a property. open-tasks.org reads the body for the blocking/requesting project; the scheme, the todo-format convention, and the inbox blocking-dependency handoff all move to the two-tag form. No property anywhere.
Diffstat (limited to '.ai')
| -rw-r--r-- | .ai/workflows/inbox.org | 2 | ||||
| -rw-r--r-- | .ai/workflows/open-tasks.org | 16 |
2 files changed, 9 insertions, 9 deletions
diff --git a/.ai/workflows/inbox.org b/.ai/workflows/inbox.org index f3d400a..5fc855f 100644 --- a/.ai/workflows/inbox.org +++ b/.ai/workflows/inbox.org @@ -114,7 +114,7 @@ The item extends a task already filed. Update the parent TODO's body with a date ** File as TODO Substantive but waits, or needs design/triage before implementation. Add the TODO under =* <Project> Open Work= with priority + tags per the priority-scheme check (core §6). Body summarizes the proposal and links the inbox content if it's been moved to =docs/design/=. Delete the inbox file (or move it to =docs/design/= first if the content survives). -*Blocking-dependency handoff.* A special shape: another project sends a note that *this* project's work is blocking one of theirs ("your task X is blocked on us — we need Y"). File or link the owning task and add a =:BLOCKS: <their-project>: <what>= property to it (see the cross-project dependency convention in =todo-format.md=). The =:BLOCKS:= marker makes =open-tasks.org= surface that task *first*, since clearing it unblocks the other project. Dedup against an existing task rather than filing a duplicate. When the work later lands, drop =:BLOCKS:= and notify the waiting project (=inbox-send <their-project> --text "Delivered: <what> — you're unblocked."=) so it can lift its own =:blocked:=. +*Blocking-dependency handoff.* A special shape: another project sends a note that *this* project's work is blocking one of theirs ("your task X is blocked on us — we need Y"). File or link the owning task, tag it =:blocker:=, and name the requesting project in the body (see the cross-project dependency convention in =todo-format.md=). The =:blocker:= tag makes =open-tasks.org= surface that task *first*, since clearing it unblocks the other project. Dedup against an existing task rather than filing a duplicate. When the work later lands, drop =:blocker:= and notify the waiting project (=inbox-send <their-project> --text "Delivered: <what> — you're unblocked."=) so it can lift its own =:blocked:=. ** Defer Rename in place to =inbox/PROCESSED-<original-filename>= and add a brief comment line at the top: =# Deferred YYYY-MM-DD: <condition>=. Don't accumulate deferred items indefinitely — sweep them on a future process pass when the condition is met or the deferral has aged out. diff --git a/.ai/workflows/open-tasks.org b/.ai/workflows/open-tasks.org index 873fc0e..4ba29dd 100644 --- a/.ai/workflows/open-tasks.org +++ b/.ai/workflows/open-tasks.org @@ -176,9 +176,9 @@ Next Mode answers two questions in one output: "what matters most right now?" (t Apply the prioritization cascade in order. Stop at the first matching step. This is the importance/urgency answer. -*Exclude blocked tasks.* A task tagged =:blocked:= has an unmet cross-project dependency (its =:BLOCKED_BY:= property names the project and the work owed, per =todo-format.md=). It can't be worked until that other project delivers, so it is *never* the cascade recommendation — skip it at every cascade step below. Blocked tasks are surfaced on their own in Step 3 so the stalled dependency stays visible instead of silently dropping out of view. +*Exclude blocked tasks.* A task tagged =:blocked:= has an unmet cross-project dependency (its body names the project and the work owed, per =todo-format.md=). It can't be worked until that other project delivers, so it is *never* the cascade recommendation — skip it at every cascade step below. Blocked tasks are surfaced on their own in Step 3 so the stalled dependency stays visible instead of silently dropping out of view. -*Surface blocking tasks first.* The mirror of the above: a task carrying a =:BLOCKS:= property is holding up work in *another* project (the property names which project and what's owed, per =todo-format.md=). Clearing it unblocks that project, so it carries borrowed urgency — surface it at the *top* of the cascade recommendation regardless of its own priority cookie, ahead of the normal In-Progress / deadline / priority order. When several =:BLOCKS:= tasks exist, lead with the one blocking the most, or the longest. This is the "do the thing that unblocks someone else first" rule; a =:BLOCKS:= task left at its own low priority is exactly how a cross-project dependency stalls. +*Surface blocking tasks first.* The mirror of the above: a task tagged =:blocker:= is holding up work in *another* project (its body names which project and what's owed, per =todo-format.md=). Clearing it unblocks that project, so it carries borrowed urgency — surface it at the *top* of the cascade recommendation regardless of its own priority cookie, ahead of the normal In-Progress / deadline / priority order. When several =:blocker:= tasks exist, lead with the one blocking the most, or the longest. This is the "do the thing that unblocks someone else first" rule; a =:blocker:= task left at its own low priority is exactly how a cross-project dependency stalls. **** 1. In-Progress Tasks - Look for tasks marked =DOING= or partially complete. @@ -236,7 +236,7 @@ The friction filter is the override path. When the cascade winner is partially b Independently of the cascade and the friction filter, collect every open task tagged =:blocked:=. These are tasks this project can't advance until another project delivers; surfacing them keeps a cross-project dependency from rotting at low priority on the other side — the exact failure the tag exists to prevent (a blocked task whose blocker is a =[#D]= in another project sits forever otherwise). -For each blocked task, read its =:BLOCKED_BY:= property (=<project>: <what>=) and present one line: the task, the blocking project, and what that project owes. Then offer — per blocked task — to nudge the blocker: an =inbox-send <project> --text= note naming what's needed and why it's blocking, so the dependency gets attention in the project that owns it. Don't send without the user's go. +For each blocked task, read its body for the blocking project and what's owed, and present one line: the task, the blocking project, and what that project owes. Then offer — per blocked task — to nudge the blocker: an =inbox-send <project> --text= note naming what's needed and why it's blocking, so the dependency gets attention in the project that owns it. Don't send without the user's go. If no =:blocked:= tasks exist, omit this surface entirely (the common case). @@ -246,7 +246,7 @@ Pair the cascade recommendation with the friction block beneath it, and the bloc #+begin_example Unblocks other projects (do these first): -- ai-term wrap-teardown companion — :BLOCKS: rulesets (the three ai-term functions) +- ai-term wrap-teardown companion — :blocker:, unblocks rulesets (the three ai-term functions) Cascade recommendation (importance/urgency): - Fix org-noter reliability — [#A], Method 1, 8/18 complete, blocks daily reading/annotation @@ -260,20 +260,20 @@ Blocked on other projects (can't advance until the blocker delivers): - Wrap-teardown feature — blocked by emacsd: ai-term companion functions — nudge? #+end_example -The =:BLOCKS:= surface sits at the very top — clearing one of those is the highest-leverage thing on the list, since it frees work in another project. Omit it when no =:BLOCKS:= task exists (the common case). +The =:blocker:= surface sits at the very top — clearing one of those is the highest-leverage thing on the list, since it frees work in another project. Omit it when no =:blocker:= task exists (the common case). Include for each row: - Task name / description. - Priority + tag cluster. - One-line reasoning. For the cascade row, name which cascade step matched. For friction rows, an effort hint when one is obvious. - Progress indicator (for V2MOM-structured todos) on the cascade row only. -- For a =:BLOCKS:= row: the project it unblocks and what's owed (from the =:BLOCKS:= property). -- For a blocked row: the blocking project and what it owes (from =:BLOCKED_BY:=), plus the nudge offer. +- For a =:blocker:= row: the project it unblocks and what's owed (from the task body). +- For a blocked row: the blocking project and what it owes (from the task body), plus the nudge offer. **** Edge cases - *Empty friction block.* If no =:quick:= or =:solo:= tagged tasks exist in the open set, omit the friction block entirely. Present only the cascade recommendation. -- *No =:BLOCKS:= tasks.* Omit the "Unblocks other projects" surface entirely (the common case) — show it only when a task carries a =:BLOCKS:= property. +- *No =:blocker:= tasks.* Omit the "Unblocks other projects" surface entirely (the common case) — show it only when a task carries the =:blocker:= tag. - *Dedupe.* If the cascade recommendation IS the same task as one of the friction rows (e.g. it's =:quick:solo:= and also won the cascade), show it once at the top with both labels. Don't list it twice. - *Decline behavior.* If the user declines the cascade recommendation, drop straight to the friction block as the natural next prompt. Do not fall through to lower-cascade-tier tasks; the friction filter IS the override. |
