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.yaml → work_tracking.backend. Adapters
differ only in auth and how fields are written.
Shared contract (all backends)¶
- Transferred fields — shared-fields.md
- Plan section — one slim
## Trackingtable (not backend-named sections) hoen.yaml— repo ↔ board linkage (+ optional field IDs). Ask before creating or committing it. If declined, Plan ID + Board item in## Trackingis enough to sync that item.- Field bootstrap — on first link, create missing board fields when permitted;
otherwise stamp values and retry later; store field IDs in
hoen.yamlwhen 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)¶
- Choose Component type (one per git repo) and primary backend.
- Ask to add root
hoen.yamlfrom assets/hoen.example.yaml (GitHub: assets/hoen.example.github.yaml). If the user declines, continue with per-plan Tracking only. - Validate when present:
- Add AGENTS.md / README / CONVENTIONS pointers from repo-conventions-template.md.
- Add
## Trackingto each actively tracked plan/ADR (or note “no card yet”). - 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)¶
- Ensure retrofit conventions exist (or run retrofit lightly).
- Create plan / ADR + optional
*.effort.jsonin git. - Create or find the board item; write
## Trackingwith Plan ID + Board item. - Sync shared fields once (Mode: sync).
- If
hoen.yamlis 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¶
- Read Plan ID / Board item from
## Tracking(or filename slug). - Else search board by Plan ID + Component type from
hoen.yaml. - 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:
- Finish git-side work (plan, effort,
## Tracking). - Tell the user the board could not be updated automatically.
- 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.
- 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¶
- Shared fields — transferable contract
hoen.yamlconfigwork_trackingschema- Notion adapter
- GitHub Projects adapter
- Notion MCP preflight
- Repo conventions template
- plan-effort-estimate
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 |