AGENT SKILL

tracker

Work the issue tracker – `publish` projects a PRD and its plan into a parent issue and one child issue per story, `triage` labels and routes incoming items toward implementation or a human decision, and `setup` writes the Issue Tracker document. Trigger on 'publish this plan to the tracker', 'triage the backlog', 'set up the issue tracker'.

适用职业产品经理
License 许可
MIT
所属仓库
IT-HUSET/andthen
最近更新
2026-11-11
Stars
★ 4
Forks
2

01 前言 Front Matter

description
Work the issue tracker – `publish` projects a PRD and its plan into a parent issue and one child issue per story, `triage` labels and routes incoming items toward implementation or a human decision, and `setup` writes the Issue Tracker document. Trigger on 'publish this plan to the tracker', 'triage the backlog', 'set up the issue tracker'.
argument-hint
[--auto] (publish <plan.json | prd.md> [--dry-run] | triage [issue number(s) or tracker query] | setup)

02 资源文件 3

03 SKILL.md 正文

Tracker

Work the project's issue tracker through its Issue Tracker document, one verb per run.

Input

$ARGUMENTS opens with the verb, and ARGUMENTS is the rest minus flags. With no verb there, take the one the request's words name.

Verb ARGUMENTS Read
publish a plan.json, or a prd.md alone § 2a below
triage issue number(s) or a tracker query; empty triages the untriaged backlog triage.md, agent-brief.md
setup none § 2c below

Rules

  • Print each recommended skill invocation as a complete, paste-ready line in the host's syntax, including its target path or request and required arguments.

  • Executable config. The Issue Tracker document is security-critical, because its table values run as commands. Each value is a single direct command invocation (an executable, fixed arguments, <placeholders>) with no pipes, shell operators, command substitution, or piping to an interpreter. Review changes to it as code.

  • Complete mapping first. Before a verb's first tracker call, reads included, stop on any operation it needs that the Operation Table leaves unmapped, so a multi-issue write never strands partial state.

  • Durability rule. What you write into a tracker body or comment outlives the branch that prompted it. Name interfaces (types, signatures, commands) and behavior, never file paths, line numbers, commits, or code snippets. A snippet that itself encodes a settled decision (schema, state machine, type) may be inlined, trimmed to the decision-carrying part.

  • Argv-safe. Every title, body, and issue number is data: pass the title, the body file, and the issue number as distinct argv elements (or structured MCP fields), never as interpolated shell source. On GitHub, fetch issue maps the issue number to gh issue view <N> --json title,body,labels,state,comments, create issue maps them to gh issue create --title and --body-file, edit body maps the issue number and the body file to gh issue edit --body-file, and comment maps them to gh issue comment <N> --body-file. An operation-table backend keeps the same argument boundary, and a mapping that only offers a shell template is unresolved executable config: stop before the first external call.

Workflow

1. Tracker resolution

Before publish or triage runs any tracker operation, resolve the Issue Tracker document (Project Document Index; default docs/ISSUE-TRACKER.md) by its Backend: line:

  • GitHub takes the built-in gh flows.
  • none declares no tracker: end on one line saying so, naming the Backend: line.
  • Another backend substitutes every operation from its Operation Table. A value naming an MCP tool is invoked the same way.
  • An unparseable Backend: line takes setup.
  • An absent document takes the gh default where the repository has a GitHub remote, and setup where it has none, since there is nothing to read.

Taking setup means offering it, and an unattended run stops as step 2c says. On acceptance, run it, then resolve against the document it wrote.

Gate: the backend is known and every operation the verb needs is mapped.

2a. Publish

The bundle is agent truth, and the tracker is its human projection. publish never writes plan.json, and sync is one way: a PM reprioritizing in the tracker is a re-plan.

Operations used: fetch issue, list issues, create issue, edit body.

The issues

Each body you write is projected from one hidden line down. On the parent the line is <!-- andthen-projection <source> -->, where <source> is the repo path of the PRD, else of the plan.json, kept as identity only. On a child it is <!-- andthen-projection <id> <source> -->, led by its story's id so the parent's line never matches it. Keep the text above the line, such as a source issue's original request, and put the line below the text of an issue that has none.

  • The parent is titled by the PRD's heading, else Plan: <plan directory name>. Below the line goes the PRD, each file path it cites replaced by what the file is, then a ## Stories checklist with one - [ ] <id> <ref> – <name> per story, <ref> the child's #<number>, or its key (ENG-123) on a tracker whose issue ids are keys, checked once the story is done or skipped. A plan without a PRD writes only the checklist. A prd.md alone writes only the PRD and keeps the checklist already there.
  • A child per story is titled <plan directory name> <id> - <name>, because story ids restart in every plan. Below the line go the story's scope, then its FIS's Intent, Expected Outcomes, and Acceptance Scenarios without their Proof lines, then Blocked by: its dependencies' issues, and once the story is done Verified: with its verified.summary.
  • A closed issue is the shipped record, so never edit one. A found issue keeps its title, because publish has no retitle operation.
  • The checklist never loses a finished story or a link. A story it checks stays checked, because another branch's copy of plan.json finished it; while this copy has not, leave that story's child as it is. An entry for a story the plan no longer has stays too, and the preview and Output name its open child to close. A re-plan numbers new stories after the highest old ID, so an old entry never names a new story.

Find them

The parent is the first open issue among the issue the PRD's header names, a tracker item the plan's sourceRefs cite, and the issue list issues finds with the line as the body-search phrase. With none open, create the parent, and when a candidate was closed, link it in the text above the line. A child is the issue the parent's checklist links for its story, else the open issue list issues finds with its line, because a run that stopped before the checklist write left it unlinked. Two open candidates at one step, for the parent or a child, stop the run, naming both.

On GitHub, list issues for a line is gh issue list --state all --json number,state,body --search with one argument, "<line text>" in:body: the text inside the comment markers, quoted as one phrase, because unquoted its words match unrelated issues. Only a hit whose body holds the exact line counts.

Preview and send

Compare each composed body with the issue's text below its line. Show each issue to create and what each update changes, and ask once before the first write, because an update replaces an edit made in the tracker since the last publish. An edit worth keeping goes into its source first: prd.md through the andthen:clarify skill, or the story's FIS. When the skill that invoked this run already showed this preview and got a yes, as the andthen:ship skill does, that answer is the ask.

--dry-run prints the preview and stops before any write. An unattended run skips the ask.

Write each body as a UTF-8 file under .agent_temp/tracker-bodies/ and send it as the body file. Create the missing issues, parent first and stories in plan order, and add each child to the parent's checklist as soon as it exists. Then edit each body still missing an issue reference it names, and send the other updates.

Gate: every issue created, updated, or found unchanged, or the user's no; under --dry-run, the preview printed.

2b. Triage

Follow triage.md.

2c. Setup

Ask which backend the tracker uses, for any backend but GitHub the command each operation maps to, and whether a feature's requirements record lives in the repo or the tracker. An unattended run writes nothing and stops on BLOCKED: naming setup and the Backend: line to set.

  • An existing document is edited in place, with no template loaded: set its Backend: and Record: lines and the operations the answer maps.
  • A new document is seeded by a subagent – the installed worker role agent when available, else a generic inherited one – that invokes the andthen:init skill with seed Issue Tracker, the chosen backend, and the record's home, which keeps the templates out of this run's context.

Gate: the document carries a parseable Backend: line and every operation the chosen backend needs.

Output

publish reports each issue it created, updated, found unchanged, or left closed, by number or key, naming the open child of a dropped story for the user to close, and in an unattended run what each update replaced.