Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 14 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# taskflow

Home of **`tskflwctl`** — a local-first planning CLI over markdown+frontmatter
task/epic/audit files. It's the Go port of the Python `pm` prototype (now
retired — see below), and it dogfoods on its own planning under
task/epic/audit files. It dogfoods on its own planning under
[`planning/`](./planning/).

## Demos
Expand All @@ -19,6 +18,7 @@ status-grouped **finding tree**:
| :-- | :-- |
| `tskflwctl status` — counts, in-progress, epic bars, open audits | ![status](./assets/status.gif) |
| `tskflwctl audit show <id>` — segmented finding bar + finding tree | ![audit show](./assets/audit-show.gif) |
| `tskflwctl task new` with no `--epic` — on a TTY it prompts: an epic picker, then tags | ![epic picker](./assets/picker.gif) |

▸ **[All demos, how they're recorded, and the demo fixture →
`assets/README.md`](./assets/README.md)** — rendered with
Expand Down Expand Up @@ -75,11 +75,11 @@ tskflwctl init # scaffold a planning tree here
tskflwctl status # at-a-glance board: counts, in-progress, epic progress

# create
tskflwctl task new "Add retry backoff" --epic 17-pm-go-cli --tags net
tskflwctl task new "Triage flake" --epic 17-pm-go-cli --tags ci --description "is CI red?" --start # straight to in-progress (--next/--start need --description)
echo "$BODY" | tskflwctl task new "Long writeup" --epic 17-pm-go-cli --tags x --body-file - # body from stdin/file
tskflwctl task new "Add retry backoff" --epic <epic-id> --tags net
tskflwctl task new "Triage flake" --epic <epic-id> --tags ci --description "is CI red?" --start # straight to in-progress (--next/--start need --description)
echo "$BODY" | tskflwctl task new "Long writeup" --epic <epic-id> --tags x --body-file - # body from stdin/file
tskflwctl epic new "Billing overhaul" --description "Replace legacy pipeline"
tskflwctl audit new dispatcher # → audits/open/YYYY-MM-DD-dispatcher.md (--date to override)
tskflwctl audit new dispatcher # → audits/<id>-YYYY-MM-DD-dispatcher.md (--date to override)
tskflwctl audit new auth --template security # pick a body scaffold (default|security); --template is shell-completable

# read
Expand Down Expand Up @@ -114,15 +114,15 @@ tskflwctl audit close|reopen|defer <slug>...

# hygiene
tskflwctl lint # validate active task frontmatter
tskflwctl lint --fix # auto-repair (normalize, relocate misfiled, backfill ids)
tskflwctl lint --fix # auto-repair frontmatter (quote ':' values, normalize lists, backfill ids)
```

A task's `status:` is authoritative in frontmatter; `tasks/<status>/` is a
lock-step mirror of it. Lifecycle verbs change the status and relocate the file,
stamping dates atomically (`lint --fix` re-syncs a hand-edited drift). Errors
carry semantic exit codes — `10`
not-found, `11` validation, `13` ambiguous, `14`
conflict (e.g. a name already taken).
Tasks and audits are stored flat and id-led (`tasks/<id>-<slug>.md`,
`audits/<id>-<slug>.md`); `status:` / `bucket:` is authoritative in frontmatter,
with no mirror directory. Lifecycle verbs edit that field in place and stamp the
dates atomically — no file moves (`lint --fix` re-normalizes a hand-edited
drift). Errors carry semantic exit codes — `10` not-found, `11` validation, `13`
ambiguous, `14` conflict (e.g. a name already taken).

**Body templates.** Each kind ships named body scaffolds; `task/epic/audit new
--template <name>` picks one (omit it for `default`). Names are shell-completable
Expand Down Expand Up @@ -196,13 +196,6 @@ output stays byte-identical. Program precedence: `TSKFLW_PAGER` → `[pager].com
(in `.tskflwctl.toml`) → `$PAGER` → `less -FRX`. On/off: `--no-pager` → `--paginate`
→ `[pager].enabled` → default on.

### `pm` is retired

The Python prototype (`bin/pm`) this tool was ported from is **gone** —
`tskflwctl` covers the full create → update → move → lint loop, and the Go
test suite is the executable spec now. The prototype and its tests live only
in git history (last at commit `39f1b83`) if archaeology is ever needed.

## Shell completion

`tskflwctl` ships cobra-generated completion for bash/zsh/fish. For zsh:
Expand Down Expand Up @@ -236,8 +229,7 @@ a file's frontmatter is malformed).
- `just fmt` — gofmt + lint formatting
- `just tidy` — `go mod tidy`

Design rationale lives in [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) and
[`planning/epics/17-pm-go-cli.md`](./planning/epics/17-pm-go-cli.md).
Design rationale lives in [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md).

### Interactive TUI (`tskflwctl ui`)

Expand Down
10 changes: 10 additions & 0 deletions assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ open) above the status-grouped **finding tree**.

![tskflwctl audit show](./audit-show.gif)

## Interactive pickers (`task new` with no `--epic`)

On a TTY, a missing required input **prompts** instead of erroring: `task new`
without `--epic` opens a type-to-filter epic picker, then a free-text tags
prompt. Off a TTY (a pipe, `--json`, `--no-input`) the same command fails with
the flag to pass — so nothing interactive can block a script. Prompts render to
stderr, so stdout stays a clean data stream.

![task new epic picker](./picker.gif)

---

## How they're made
Expand Down
Binary file modified assets/audit-show.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 8 additions & 6 deletions assets/demo-planning/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Demo planning fixture

A small, **curated** planning tree the demo GIFs ([`../`](../)) record against —
authored to show `tskflwctl`'s symbology off in one screen, rather than recording
this repo's own [`planning/`](../../planning/) (whose audits are all closed, so the
open-audit section and the segmented bar wouldn't appear).
a **bike-workshop** project board (touring repairs, gravel upgrades, a BMX neon
paint job, a fixed-gear build) authored to show `tskflwctl`'s symbology off in
one screen, rather than recording this repo's own [`planning/`](../../planning/)
(whose audits are all closed, so the open-audit section and the segmented bar
wouldn't appear).

It's a self-contained planning root (`taskflow_root = "."` in
[`.tskflwctl.toml`](./.tskflwctl.toml)); the tapes `cd` into it.
Expand All @@ -12,9 +14,9 @@ It's a self-contained planning root (`taskflow_root = "."` in

| | Contents | Shows off |
| :-- | :-- | :-- |
| **Epics** | `01-api-gateway` (50%), `02-observability` (33%), `03-data-pipeline` (100%) | the rollup bars at a spread of completion |
| **Tasks** | 8 across every active + archived status (in-progress, next-up, ready, completed, deferred) | the status glyphs and the dashboard's count line |
| **Audits** | one **open** (`2026-06-20-api-gateway`) + one **closed** (`2026-06-10-data-pipeline`) | the bucket glyphs and the Open-audits dashboard section |
| **Epics** | `01-touring-bike-repairs` (75%), `02-gravel-bike-upgrades` (50%), `03-bmx-neon-paint-job` (25%), `04-fixed-gear-build` (0%) | the rollup bars at a spread of completion |
| **Tasks** | 14 across every active + archived status (in-progress, next-up, ready, completed, deferred), each with a fleshed-out objective + acceptance criteria | the status glyphs, the dashboard's count line, and the `task ac` tally |
| **Audits** | one **open** (`2026-06-20-pre-tour-inspection`, 8 findings) + one **closed** (`2026-06-10-wheel-build-qc`) | the bucket glyphs and the Open-audits dashboard section |

The open audit's eight findings deliberately span **fixed · landed ·
in-progress · open · deferred · wontfix**, so the **segmented finding bar** shows
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
schema: 1
id: 6fq9h1erg8ed
bucket: open
area: pre-tour-inspection
date: "2026-06-20"
---
# Audit: pre-tour-inspection — 2026-06-20

> Pre-departure safety sweep of the touring bike. Edit findings in place and flip
> each `**Status:**` as you work it.

## Findings

#### H1. Rear brake pads worn past the wear line · **Status:** fixed (2026-06-20)

**Component:** brakes
**Effort:** S · **Urgency:** acute

Both rear pads are down to the metal backing, glazed, and biting late — on a
loaded bike descending a pass that's a stopping-distance problem, not a comfort
one.

**Recommendation:** fit fresh cartridge pads, bed them in, and re-check toe-in.

#### H2. Chain stretched beyond 0.75% · **Status:** fixed (2026-06-20)

**Component:** drivetrain
**Effort:** S · **Urgency:** soon

The wear gauge drops fully in at 0.75%. Left on, it will start skating over the
cassette under climbing load and chew the chainrings.

**Recommendation:** replace the chain; re-measure the cassette for hooking.

#### H3. Headset has a notchy index at center · **Status:** landed (2026-06-19)

**Component:** headset
**Effort:** M · **Urgency:** soon

Bars settle to dead-center on their own — the bearing races are brinelled from
years of braking loads, so the steering catches straight ahead.

**Recommendation:** replace both cartridge bearings; grease and re-preload.

#### H4. Rear derailleur hanger is slightly bent inboard · **Status:** in-progress

**Component:** drivetrain
**Effort:** S · **Urgency:** soon

Indexing won't hold across the two largest cogs; a hanger-alignment gauge shows
~4mm of inboard lean at the rim.

**Recommendation:** cold-set the hanger true with the gauge, then re-index.

#### H5. Front tire sidewall is cracking · **Status:** open

**Component:** tires
**Effort:** S · **Urgency:** soon

Fine crazing runs the length of both sidewalls where the casing flexes. It holds
air today, but not a 60-mile day in the heat with a load.

**Recommendation:** replace with a touring-rated tire; keep the old one as a boot.

#### H6. Bottom bracket creaks under climbing load · **Status:** open

**Component:** bottom-bracket
**Effort:** M · **Urgency:** soon

A sharp creak tracks pedal pressure, loudest out of the saddle. Could be the BB
cups, the crank interface, or the pedals — needs isolating.

**Recommendation:** pull the crank, degrease and re-torque the interfaces, then
retest before condemning the BB.

#### H7. Bar tape is frayed at the hoods · **Status:** wontfix

**Component:** cockpit
**Effort:** XS · **Urgency:** eventually

Cosmetic wear where the hands rest. The rider likes the broken-in grip and wants
it left alone until after the trip.

**Recommendation:** none for now; re-wrap post-tour.

#### H8. Front fender rattles on washboard · **Status:** deferred

**Component:** fenders
**Effort:** XS · **Urgency:** eventually

The fender stay buzzes on rough gravel. Annoying, not a safety issue; deferred
behind the drivetrain and brake work.

**Recommendation:** add a rubber grommet at the stay mount.

## Candidate tasks

- ✅ `tskflwctl task new "Replace chain and cassette" --epic 01-touring-bike-repairs --tags drivetrain` — chain past 0.75%
- ⏳ `tskflwctl task new "Overhaul bottom bracket" --epic 01-touring-bike-repairs --tags bearings` — isolate the climbing creak
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
schema: 1
id: 6fq9h1et173b
bucket: closed
area: wheel-build-qc
date: "2026-06-10"
---
# Audit: wheel-build-qc — 2026-06-10

> Quality check on the freshly built touring rear wheel before it goes on the
> bike. Edit findings in place and flip each `**Status:**` as you work it.

## Findings

#### H1. Drive-side spoke tension uneven · **Status:** fixed (2026-06-11)

**Component:** wheels
**Effort:** M · **Urgency:** soon

The tension meter shows a 25% spread across the drive side — a few loose spokes
that will detension and go pingy under a loaded rack.

**Recommendation:** even the tension to within 10%, stress-relieve, re-check.

#### H2. Rim not dished to center · **Status:** fixed (2026-06-11)

**Component:** wheels
**Effort:** S · **Urgency:** soon

The rim sits ~2mm to the non-drive side in the dishing gauge, so the wheel won't
center in the frame.

**Recommendation:** add drive-side tension to pull the rim to true center.

#### H3. Nipples creak under first load · **Status:** landed (2026-06-10)

**Component:** wheels
**Effort:** XS · **Urgency:** eventually

New nipples creak against the rim eyelets on the first hard pedal — dry seats,
not a build fault.

**Recommendation:** a drop of oil at each nipple/rim interface; re-stress.

#### H4. Slight radial hop at the valve hole · **Status:** wontfix

**Component:** wheels
**Effort:** S · **Urgency:** eventually

~0.3mm of radial runout at the seam. It's within touring tolerance and chasing it
would unbalance the lateral true.

**Recommendation:** none; within spec.

## Candidate tasks

- ✅ `tskflwctl task new "True both wheels" --epic 01-touring-bike-repairs --tags wheels` — even tension + dish
12 changes: 0 additions & 12 deletions assets/demo-planning/audits/closed/2026-06-10-data-pipeline.md

This file was deleted.

32 changes: 0 additions & 32 deletions assets/demo-planning/audits/open/2026-06-20-api-gateway.md

This file was deleted.

20 changes: 0 additions & 20 deletions assets/demo-planning/epics/01-api-gateway.md

This file was deleted.

23 changes: 23 additions & 0 deletions assets/demo-planning/epics/01-touring-bike-repairs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
schema: 1
status: active
description: Overhaul a steel touring bike end-to-end for a cross-country trip.
priority: high
tags: [touring, repair]
created: "2026-07-18"
---
# Touring bike repairs

## Goal

Overhaul a steel touring bike end-to-end for a self-supported cross-country trip
— bearings, drivetrain, and wheels all trip-ready with margin to spare.

## Why this is its own epic

The tour has a hard departure date, so each subsystem gets its own tracked fix
instead of a vague "give it a once-over."

## Out of scope

- Frame respray — the paint is sound; this epic is mechanical.
23 changes: 23 additions & 0 deletions assets/demo-planning/epics/02-gravel-bike-upgrades.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
schema: 1
status: active
description: Upgrade a gravel bike for multi-day bikepacking races.
priority: medium
tags: [gravel, upgrade]
created: "2026-07-18"
---
# Gravel bike upgrades

## Goal

Upgrade a gravel bike for multi-day bikepacking races: tubeless traction, a
simpler 1x drivetrain, and enough mounts to carry three days of kit.

## Why this is its own epic

These are discretionary upgrades on a working bike, sequenced so the race-day
setup can be tested on training rides before it counts.

## Out of scope

- A new frameset — this is about getting more out of the current one.
Loading
Loading