Track Plan Changes
ASecurityRead the issues of a plan, and make the tracker writes of an /update-plan session the person approved — close (as completed or as not planned), reopen, a new title, a new text, a new type, a new parent, a new issue with its type and parent — one by one through the platform adapter's verbs, recording each write at once, so a run that stops part way is picked up again and never makes an issue twice. It writes nothing unless the approval reads "approved" for the very list the person saw (the lis...
- 3 stars
- 0 votes
- 0 copies
- 0 views
- Added November 7, 2026
Security analysis
100/100Pro scans all 5 files and shows the line behind each finding
npx -y skills add intent-driven-ai/garura --skill track-plan-changes --agent claude-codeAre you the author of Track Plan Changes?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/intent-driven-ai-track-plan-changes)---
name: track-plan-changes
description: Read the issues of a plan, and make the tracker writes of an /update-plan session the person approved — close (as completed or as not planned), reopen, a new title, a new text, a new type, a new parent, a new issue with its type and parent — one by one through the platform adapter's verbs, recording each write at once, so a run that stops part way is picked up again and never makes an issue twice. It writes nothing unless the approval reads "approved" for the very list the person saw (the list's sha256). It is mechanical — what to change was decided in the session; this skill decides nothing. Used through project-orchestrator by /update-plan (#730).
user-invocable: false
model: sonnet
allowed-tools: Read, Bash
---
# track-plan-changes
An `/update-plan` session ends with one list the person approved. This skill makes that list's
tracker writes. It also reads the plan's issues, so the session works from what the tracker holds
now. It has no judgment in it: the session worked out each write, and the person approved them.
## Input
| Field | Required | Meaning |
|-------|----------|---------|
| `mode` | yes | `read` or `apply` |
| `issues` | for `read` | The issue numbers to read, comma separated |
| `ops` | for `apply` | `github-ops.json`, which the play's script wrote from the approved list — see the script's header for each op |
| `changes` | for `apply` | The approved list (`changes.yaml`) |
| `approval` | for `apply` | `answer.json`: `decision` and `list_sha` |
| `read`, `before`, `after` | for `apply` | The plan's issue numbers, and where to write the snapshots read before and after the writes |
| `tracker_file` | no | A JSON file that stands in for the tracker (tests and the test run); without it, the code host |
| `out` | yes | Where to write `snapshot.json` (read) or `github-record.json` (apply) |
## Process
1. **Read.** Run:
```bash
python3 scripts/track_changes.py read --issues <numbers> [--tracker-file <json>] --out <snapshot.json>
```
Each issue's title, type, labels, state and close reason, text, parent and sub-issues. An
issue the tracker does not have is listed under `missing`.
2. **Apply.** Run:
```bash
python3 scripts/track_changes.py apply --ops <github-ops.json> --changes <changes.yaml> \
--approval <approval.json> [--tracker-file <json>] \
--read <the plan's issue numbers> --before <snapshot-before.json> --after <snapshot-after.json> \
--out <github-record.json>
```
With `--read`, it reads those issues just before its first write and again after its last
(with the issues it made), so the play can check that nothing else changed.
Exit 0: every write is made, or was already true. Exit 1: a write failed; the record names
it and keeps every write made before it — run the same command again once the cause is
fixed, and it goes on from there. Exit 2: refused, nothing written (not approved, or the list
changed after the approval).
After a crash in the middle of a create (the record does not show the op), the host's search
may not find an issue made seconds earlier. Before the run again, search the tracker for the
marker line "Made by /update-plan (list <12 hex>, op <id>)" of each create the record does
not show. When an issue holds it, the run again finds it; when the search does not show it
yet, wait a minute and search again, so no issue is made twice.
3. Return the output path and the exit code. Never make a write the ops file does not name, and
never write to the tracker any other way.
## Output
`snapshot.json` — `{"issues": {"<number>": {number, title, type, labels, state, state_reason,
body, parent, sub_issues}}, "missing": [..]}`.
`github-record.json` — `{"ok", "list_sha", "done": {"<op id>": {op, issue, result, how}},
"failed"}`; `result` is the number of an issue the op made; `how` is `done`, `made`, `found` (an
earlier run made it: each new issue carries the line "Made by /update-plan (list <12 hex>, op
<id>).", and a create first looks for it) or `already`. A record from another list is refused.
## Rules
- Only the list the person approved, and only through the platform adapter's verbs.
- Each write is recorded as soon as it is made; a run again never repeats one, and a create
looks for its own marker first, so an issue is never made twice.
- No labels are added, and nothing is deleted.
Files in this skill
- SKILL.md
- scripts/platform_adapter.py
- scripts/test_track_changes.py
- scripts/track_changes.py
- scripts/tracker.py
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.