Skip to content

Work Tracking

ContributorsMyles Henaghan

When to use: Plans live in git; the team also needs a board for priorities, phase rollups, and discussion. Use this skill to apply conventions to new work, retrofit an existing repo, or sync progress on items already under tracking. Formerly apply-work-tracking.

Instructions

Goal

Layer Role
Git (source of truth) Plans, ADRs, *.effort.json, optional hoen.yaml
External tracker (visibility) Shared fields only — see shared-fields.md

The board is never authoritative for effort math or decision text. Numbers come from plan-effort-estimate + format-sync.mjs; prose stays in the plan/ADR.

Pair with plan-effort-estimate when a tracked item has *.effort.json.

Modes

Mode When
apply New plan/ADR — add Tracking, link or create board item, optional hoen.yaml
retrofit Existing repo — conventions + backfill Tracking on active plans
sync Already tracked — refresh transferred fields after plan/effort/ADR change

Tracker backends

Backend Status Adapter
Notion Active adapters/notion.md
GitHub Projects Active adapters/github-projects.md
Jira Planned Same shared fields; adapter TBD

Pick one primary backend in hoen.yamlwork_tracking.backend. Adapters differ only in auth and how fields are written.


Shared contract (all backends)

  1. Transferred fieldsshared-fields.md
  2. Plan section — one slim ## Tracking table (not backend-named sections)
  3. hoen.yaml — repo ↔ board linkage (+ optional field IDs). Ask before creating or committing it. If declined, Plan ID + Board item in ## Tracking is enough to sync that item.
  4. Field bootstrap — on first link, create missing board fields when permitted; otherwise stamp values and retry later; store field IDs in hoen.yaml when obtained.
## Tracking

| Field | Value |
|-------|-------|
| **Plan ID** | `my-plan-slug` |
| **Work type** | Epic |
| **Board item** | [#123](https://github.com/org/repo/issues/123) |

Board item is the Notion page URL, GitHub tracking issue, or Jira issue key/URL. Do not paste backend field IDs or CLI recipes into the plan.


Mode: retrofit (repo once)

  1. Choose Component type (one per git repo) and primary backend.
  2. Ask to add root hoen.yaml from assets/hoen.example.yaml (GitHub: assets/hoen.example.github.yaml). If the user declines, continue with per-plan Tracking only.
  3. Validate when present:
    node library/skills/work-tracking/scripts/validate-hoen-yaml.mjs
    
  4. Add AGENTS.md / README / CONVENTIONS pointers from repo-conventions-template.md.
  5. Add ## Tracking to each actively tracked plan/ADR (or note “no card yet”).
  6. Bootstrap board fields when possible (shared-fields.md).

Exit criteria: valid hoen.yaml or explicit skip; AGENTS section; Tracking on active plans; effort-backed plans validate via validate-effort.mjs --scan.


Mode: apply (new work)

  1. Ensure retrofit conventions exist (or run retrofit lightly).
  2. Create plan / ADR + optional *.effort.json in git.
  3. Create or find the board item; write ## Tracking with Plan ID + Board item.
  4. Sync shared fields once (Mode: sync).
  5. If hoen.yaml is missing, ask again whether to add and commit it.

Mode: sync (operate)

After plan progress, ADR status, or effort JSON changes:

Preflight

Backend Check
Notion Tools present this session? Else payload + mcp-preflight.md
GitHub hoen.yaml + gh project scope (or ask before PAT/API path). Prefer interactive terminal if agent DNS to api.github.com fails

When to sync

Repo change Update board?
*.effort.json status Yes — shared fields
ADR decision status Yes — Status + progress headline
Plan promoted / renamed Yes — Plan doc URL, Plan ID
New board item linked Yes — update ## Tracking
Typo in prose only Usually no

Resolve the item

  1. Read Plan ID / Board item from ## Tracking (or filename slug).
  2. Else search board by Plan ID + Component type from hoen.yaml.
  3. If missing and work is Epic/Story/ADR-worthy, create item; update Tracking.

Refresh fields

# Shared payload (all backends)
node library/skills/work-tracking/scripts/format-sync.mjs \
  --input path/to/plan.effort.json --pretty

# Notion property names for MCP / UI paste
node library/skills/work-tracking/scripts/format-sync.mjs \
  --input path/to/plan.effort.json --map notion --pretty

GitHub — prefer one orchestrator (issue body + board fields):

node library/skills/work-tracking/scripts/sync-from-hoen.mjs \
  --input path/to/plan.effort.json --issue N --dry-run
# drop --dry-run to write

Notion — apply format-sync.mjs --map notion via MCP or UI (orchestrator TBD).

Same-session rule: git update, Tracking section, and every board surface (e.g. GitHub issue body and project fields) in one session when possible.

When board / entity update fails

If MCP, gh, permissions, or network prevent writing the external item:

  1. Finish git-side work (plan, effort, ## Tracking).
  2. Tell the user the board could not be updated automatically.
  3. Emit a paste-ready markdown block and ask them to copy it into the ticket/card description (or Progress section) themselves:
node library/skills/work-tracking/scripts/format-sync.mjs \
  --input path/to/plan.effort.json \
  --paste-md \
  --plan-doc path/to/plan.md

The block includes the 👀 rollup, status/phase, numeric summary, and a Detailed plan link to the plan on the remote host — inferred from git remote get-url origin (GitHub, Azure DevOps, or Bitbucket). Never link a local filesystem path (file:// or /home/…). Overrides: --origin, --branch.

  1. Retry automated field sync next session when auth/transport allows.

Work types and hygiene

Work type Typical use
Epic Multi-phase migration or programme
Story Deliverable slice inside an epic
Task / Bug Often stay in the issue tracker; board optional
ADR Decision record — effort JSON optional

Keep titles short (≤ ~70 chars). Put 👀 numbers in progress_headline, not the title. Card views: Work type → progress headline → last sync (see adapters).


References

Use cases:

Scripts:

Script Purpose
scripts/format-sync.mjs Shared payload (+ --map, --paste-md)
scripts/remote-plan-url.mjs Origin → browseable plan URL (GH / ADO / BB)
scripts/paste-block.mjs Manual ticket paste markdown
scripts/sync-payload.mjs Field derivation library (unit-tested)
scripts/sync-from-hoen.mjs GitHub orchestrator: issue body + board fields
scripts/sync-issue-progress.mjs GitHub issue ## Progress section
scripts/format-github-sync.mjs GitHub Projects field writes (transport)
scripts/validate-hoen-yaml.mjs Validate hoen.yaml
scripts/self-test.mjs Operator/agent dry-run smoke checks
scripts/*.test.mjs Unit tests (node --test)

format-notion-sync.mjs remains a thin --map notion wrapper for old call sites.


Troubleshooting

Symptom Likely cause Fix
Board shows wrong effort totals Hand-calculated or stale JSON validate-effort.mjs then format-sync.mjs
Cannot find card Plan ID mismatch / missing Tracking Align ## Tracking; filter by Component type
Teammate cannot sync Notion No Notion MCP mcp-preflight.md; --paste-md
Board / entity update fails Auth, MCP, DNS, permissions Encourage --paste-md into the ticket; remote plan link from origin
Plan doc link broken Wrong host/branch / local path buildPlanDocUrl from git remote get-url origin — never a local path
ADR missing effort fields No sidecar Work type ADR; headline from Status table
validate-hoen-yaml.mjs fails Invalid / missing dotfile Fix per hoen-config + manifest, or skip if user declined
Non-Fibonacci effort values Invalid sidecar Fix JSON — see plan-effort-estimate