blob: 7e04d96ea95d086de5938772e72b0fedff01a0bf [file] [view]
<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [github-rollup](#github-rollup)
- [Prerequisites](#prerequisites)
- [Configuration](#configuration)
- [Why](#why)
- [Invocation](#invocation)
- [`append <issue> --action "<label>" ...`](#append-issue---action-label-)
- [`list <issue>`](#list-issue)
- [`latest <issue>`](#latest-issue)
- [Failure modes](#failure-modes)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->
# github-rollup
**Capability:** contract:tracker
**Kind:** implementation
**Vendor:** GitHub
Append to (or create) the status-rollup comment on a GitHub
issue **without bringing the rollup body into agent context**.
## Prerequisites
- **Runtime:** Python 3.11+ run via `uv` (`uv run --directory tools/github-rollup github-rollup …`); stdlib-only, no third-party dependencies.
- **CLIs:** `uv`; `gh` — the script shells out to it for all GitHub access (the default `@user` comes from `gh api user`).
- **Credentials / auth:** an authenticated `gh` session (`gh auth status` must pass) — the comment read / append / PATCH all go through `gh`.
- **Network:** `api.github.com` via `gh`.
## Configuration
This helper has no persistent config file of its own. Callers pass the
target issue from `<project-config>/project.md` → `tracker_repo`; the
status-rollup comment format is the GitHub tracker convention documented
in `tools/github/status-rollup.md` and reused by security lifecycle
skills.
## Why
Every skill that updates a `<tracker>` issue (import receipt,
sync passes, CVE allocation, dedupe, fix-PR announcements) folds
its status update into one rollup comment per tracker. The
existing recipe in
[`tools/github/status-rollup.md`](../github/status-rollup.md)
walks the agent through: fetch the comment, concatenate
`<old body>` + ruler + new entry, PATCH the comment. That loops
the full rollup body — which grows monotonically and is the
single largest comment on a long-running tracker — through agent
context every sync pass.
This tool does the read / append / PATCH in a subprocess. Only a
one-line confirmation lands on the agent's stderr. The body never
crosses the boundary.
## Invocation
```bash
uv run --directory tools/github-rollup github-rollup <subcommand> ...
```
### `append <issue> --action "<label>" ...`
Append a new entry to the rollup comment on `<issue>`. Creates
the rollup if none exists. Required: `--action <label>` (the
right-hand field of the entry's summary line). Body comes from
either `--entry-body "<text>"` or `--entry-body-file <path>`
(`-` reads stdin).
Optional flags:
- `--user @handle` — override the summary's `@user` field
(default: the authenticated `gh` user from `gh api user`).
- `--now <ISO8601>` — override the date used in the summary
(default: real now). Useful for deterministic replay tests.
- `--dry-run` — print the decision (create vs append) without
writing.
### `list <issue>`
Print every entry's summary line in order (or `--json` for a
machine-readable array of `{date, user, action}`). Exit 3 if the
issue has no rollup yet.
### `latest <issue>`
Print just the body of the most recent entry. Useful for
*"what did the last sync do?"* in a follow-up script. Exit 3
if the rollup or entries are missing.
## Failure modes
| Exit | Meaning |
|---|---|
| 0 | Success (or `--dry-run` planned). |
| 2 | CLI argument error (mutually-exclusive flags, missing required). |
| 3 | Issue has no rollup yet, or rollup has no entries (for `latest`). |
| other | `gh` returned non-zero; the underlying stderr is forwarded. |