diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8277c08..0e4619e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "qe", "source": "./qe", - "version": "0.7.0", + "version": "0.8.0", "description": "QuantEcon's shared agent skills under one namespace — working through a PR's review feedback, advising on and scoring lecture acceleration (benchmark), bulk read-only repository audits, turning audit reports into tracked work projects, and creating, reading and carrying work-plan state across agent sessions" } ] diff --git a/AGENTS.md b/AGENTS.md index 9148409..9bcf01f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,8 @@ Before adding a paragraph, check whether it already exists. If it does, link to | Style rule text and schema | `QuantEcon/style-guide` (upstream — never authored in this repo) | | What has shipped, and the principles behind it | [CATALOG.md](CATALOG.md) | | Parked ideas, not committed to | [Low-priority enhancement issues](https://github.com/QuantEcon/skills/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement+label%3Alow-priority) in the tracker, one per idea with its merit assessment | -| Work in flight, per skill family | issues [#3](https://github.com/QuantEcon/skills/issues/3) (style), [#4](https://github.com/QuantEcon/skills/issues/4) (benchmark), [#12](https://github.com/QuantEcon/skills/issues/12) (audit) | +| What a skill actually did when it was run | `reviews/` — one record per validation run, cited from [CATALOG.md](CATALOG.md) and the tutorials | +| Work in flight, per skill family | issues [#3](https://github.com/QuantEcon/skills/issues/3) (style, and the `workplan-*` family), [#4](https://github.com/QuantEcon/skills/issues/4) (benchmark), [#12](https://github.com/QuantEcon/skills/issues/12) (audit) — the families outlived the plugins they were named for | ## Working in this repo diff --git a/CATALOG.md b/CATALOG.md index e98f67c..666c6ff 100644 --- a/CATALOG.md +++ b/CATALOG.md @@ -8,9 +8,9 @@ Everything ships in the single `qe` plugin ([#43](https://github.com/QuantEcon/s | Family | Skills | State | Tracking | |---|---|---|---| -| **Author-facing** — from drafting a lecture to merging its PR | `/qe:copilot-review` | Operational, and validated from an installed plugin on 2026-08-03: plugin-root path resolution, cross-repo mode, and running from outside a working tree. The style skills (`check-style` and six per-category siblings) shipped as scaffolding through 0.5.0 and were removed in 0.6.0; their plan lives in [#3](https://github.com/QuantEcon/skills/issues/3), and they return once the rule snapshot and deterministic preflight land. The `workplan-*` family — `/qe:workplan-project` (0.3.0 as `/qe:workplan`, renamed 0.4.0; report bundle → tracking issue with sub-issues) and `/qe:workplan` (0.5.0, consolidating 0.4.0's `workplan-issue` and `workplan-update` and adding a read verb; the work-plan issue's whole lifecycle — create, read/validate/recommend, resume, update, close-and-succeed) — is merged as complete procedures with no validated runs yet, so it is likewise not listed until it has one. Note the name reuse: `/qe:workplan` meant the report-to-project skill for one morning in 0.3.0; from 0.5.0 it is the lifecycle skill. | [#3](https://github.com/QuantEcon/skills/issues/3) | +| **Author-facing** — from drafting a lecture to merging its PR | `/qe:copilot-review`, `/qe:workplan` | `/qe:copilot-review` is operational, validated from an installed plugin on 2026-08-03: plugin-root path resolution, cross-repo mode, and running from outside a working tree. `/qe:workplan` (0.5.0, consolidating 0.4.0's `workplan-issue` and `workplan-update` and adding a `read` verb — the work-plan issue's whole lifecycle: create, read/validate/recommend, resume, update, close-and-succeed) is operational for the verbs that have run: `update` and `resume` on 2026-08-20 from an installed plugin, and this repo's own work-plan issue [#25](https://github.com/QuantEcon/skills/issues/25) revised again on 2026-08-25 as the consolidated skill's first `update`. `create`, `read` and `close` are merged procedures with no run yet, and its sibling `/qe:workplan-project` (0.3.0 as `/qe:workplan`, renamed 0.4.0; report bundle → tracking issue with sub-issues) has never been run against a real bundle, so neither is listed above. Note the name reuse: `/qe:workplan` meant the report-to-project skill for one morning in 0.3.0; from 0.5.0 it is the lifecycle skill. The style skills (`check-style` and six per-category siblings) shipped as scaffolding through 0.5.0 and were removed in 0.6.0; their plan lives in [#3](https://github.com/QuantEcon/skills/issues/3), and they return once the rule snapshot and deterministic preflight land. | [#3](https://github.com/QuantEcon/skills/issues/3) | | **Benchmark** — evaluating accelerated lecture implementations | `/qe:benchmark` (until qe 0.7.0: `/benchmark:review-acceleration`) | Operational for workspace runs: rubric v2, a deterministic scoring engine, and two complete worked evaluations as regression baselines. | [#4](https://github.com/QuantEcon/skills/issues/4) | -| **Audit** — bulk, read-only repository audits | `/qe:audit-issues` (until qe 0.7.0: `/audit:issues`) | Run once **as a skill** — a 230-item tracker on 2026-07-28, 22 minutes, seven plugin defects found and recorded ([record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md)). Both severity-1 defects are fixed as of audit 0.2.0 ([#34](https://github.com/QuantEcon/skills/pull/34)): a `[verified]` citation must now resolve on the ref the audit named, and phase 2 checkpoints its closed pass as well as its open one. That validates the method as far as one run goes and no further: its central claim, resumability, is still untested, because the run was never interrupted. Further runs: [#16](https://github.com/QuantEcon/skills/issues/16). | [#12](https://github.com/QuantEcon/skills/issues/12), [#16](https://github.com/QuantEcon/skills/issues/16) | +| **Audit** — bulk, read-only repository audits | `/qe:audit-issues` (until qe 0.7.0: `/audit:issues`) | Run twice **as a skill**, against deliberately different repo types. Run 1 — a 230-item tracker on 2026-07-28, 22 minutes, seven plugin defects ([record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md)); both severity-1 defects fixed in audit 0.2.0 ([#34](https://github.com/QuantEcon/skills/pull/34)). Run 2 — `QuantEcon/meta`, 317 items and 138 open, 2026-08-25, ~53 minutes including a deliberate kill ([record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-meta-2026-08-25.md)) — **settled the claim the program exists to check**: the open pass resumed across a lost session at the issue predicted beforehand, appending only, with no re-walk, skip or duplicate; and read-only moved from asserted to measured, a before/after fingerprint of all 317 issues hashing identically. What two runs still do not cover: the closed pass writes once for the whole survey, so an interrupt there loses the phase and the resume rule cannot address grouped entries ([#57](https://github.com/QuantEcon/skills/issues/57)); no run has been killed mid-write, so the truncation guard is unexercised; and the working-directory rule's `.audit/` fallback leaves a public checkout untracked-dirty ([#61](https://github.com/QuantEcon/skills/issues/61)). Further runs and the claims table: [#16](https://github.com/QuantEcon/skills/issues/16). | [#12](https://github.com/QuantEcon/skills/issues/12), [#16](https://github.com/QuantEcon/skills/issues/16) | Installation and setup are in [README.md](README.md); what it is like to run one is in [docs/using-skills.md](docs/using-skills.md). diff --git a/docs/developing-skills.md b/docs/developing-skills.md index a406755..92710e5 100644 --- a/docs/developing-skills.md +++ b/docs/developing-skills.md @@ -8,15 +8,17 @@ For contributors adding or modifying plugins in this repo. (Using them: [using-s .claude-plugin/marketplace.json # the catalogue — every plugin registers here scripts/ # manifest + frontmatter validation, version-bump guard (CI runs these) docs/ # these guides -/ # one directory per plugin +reviews/ # validation-run records — what a skill did when it was actually used +qe/ # the plugin (one directory per plugin; since 0.7.0 there is one) .claude-plugin/plugin.json # name, description, version CHANGELOG.md # required: one entry per released version - README.md # the plugin's user guide skills//SKILL.md # one directory per skill - scripts/ # deterministic scripts the skills drive - references/ # rule/rubric content the skills read + scripts// # deterministic scripts the skills drive + references// # rule/rubric/method content the skills read ``` +Under one plugin, `scripts/` and `references/` are subdivided by skill family (`scripts/benchmark/`, `references/audit/`) rather than sitting flat — the [#43](https://github.com/QuantEcon/skills/issues/43) consolidation's one structural consequence. + **A plugin needs its manifest and its changelog; a skill needs only `SKILL.md`.** A skill that is purely a procedure — nothing deterministic to run, no long reference material to point at — is one file in one directory, and should stay that way. `scripts/` appears when there is something mechanical worth doing in code; `references/` when the skill needs more context than belongs in its body. Adding either before you need it just makes the skill harder to read. The live skill families show some of the range: the standalone procedures (a PR-feedback loop with one script of its own, and a two-skill work-plan family: a lifecycle skill whose five verbs share one statement of the org's plan convention, plus a report-to-project packager), `benchmark` (one skill driving a deterministic engine at `scripts/benchmark/`, with worked examples as its regression baseline), and the `audit-*` family (sibling procedures sharing a method document at `references/audit/`). None of these is the house style — they are what the problems happened to need. @@ -120,7 +122,7 @@ A second job runs `claude plugin validate --strict` against each plugin and the ### Tags -Each release is tagged `{name}--v{version}`, so three independently-versioned plugins share one tag namespace. Tag from a clean checkout of `main` after the release merges: +Each release is tagged `{name}--v{version}`. The scheme was adopted when three plugins were versioned independently and shared one tag namespace; since 0.7.0 only `qe` is live, and the retired `benchmark--v*` and `audit--v*` tags stay as archaeology. Tag from a clean checkout of `main` after the release merges: ```bash claude plugin tag ./ --push -m " %s" @@ -134,4 +136,4 @@ It takes the version from `plugin.json`, refuses unless the marketplace entry ag - Branch, PR, CI must be green. This repo **squash-merges** — stacked branches need `git rebase --onto origin/main ` after the base PR merges (already-upstream commits drop automatically). - External contributions land with the contributor as git author (`--author`, GitHub noreply address unless they prefer otherwise) and integration fixes as separate commits — see PR #5 for the pattern. -- [CATALOG.md](../CATALOG.md) lists what has merged *and* is operational, and nothing else, so a PR that makes a skill operational updates it while a PR that merely plans one does not. Scaffolding does not ship at all (a policy set with `qe` 0.6.0): an unbuilt skill lives only as the plan in its plugin's tracking issue ([#3](https://github.com/QuantEcon/skills/issues/3) `qe`, [#4](https://github.com/QuantEcon/skills/issues/4) `benchmark`, [#12](https://github.com/QuantEcon/skills/issues/12) `audit`), never as a shipped menu entry that reports it does nothing. Ideas nobody has committed to belong in the tracker as [low-priority enhancement issues](https://github.com/QuantEcon/skills/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement+label%3Alow-priority), each carrying its own merit assessment. The style-guide rule content is authored in `QuantEcon/style-guide`, never here — when the style skills land, this repo's `qe` plugin will consume a rendered snapshot ([project-style-guide#6](https://github.com/QuantEcon/project-style-guide/issues/6)). +- [CATALOG.md](../CATALOG.md) lists what has merged *and* is operational, and nothing else, so a PR that makes a skill operational updates it while a PR that merely plans one does not. Scaffolding does not ship at all (a policy set with `qe` 0.6.0): an unbuilt skill lives only as the plan in its **family's** tracking issue ([#3](https://github.com/QuantEcon/skills/issues/3) style and workplan, [#4](https://github.com/QuantEcon/skills/issues/4) benchmark, [#12](https://github.com/QuantEcon/skills/issues/12) audit — the families outlived the plugins they were named for), never as a shipped menu entry that reports it does nothing. Ideas nobody has committed to belong in the tracker as [low-priority enhancement issues](https://github.com/QuantEcon/skills/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement+label%3Alow-priority), each carrying its own merit assessment. The style-guide rule content is authored in `QuantEcon/style-guide`, never here — when the style skills land, this repo's `qe` plugin will consume a rendered snapshot ([project-style-guide#6](https://github.com/QuantEcon/project-style-guide/issues/6)). diff --git a/docs/tutorial-run-an-audit.md b/docs/tutorial-run-an-audit.md index e9e06a7..5ec0311 100644 --- a/docs/tutorial-run-an-audit.md +++ b/docs/tutorial-run-an-audit.md @@ -2,16 +2,18 @@ This walks `/qe:audit-issues` end to end against **[QuantEcon/action-translation](https://github.com/QuantEcon/action-translation)** — 228 items, the repo the runbook was first executed against by hand. -It differs from the [evaluation tutorial](tutorial-run-an-evaluation.md) in one important way. That one reproduces a committed reference, so every number you produce can be checked. Here there is no reference: `/qe:audit-issues` has been run as a skill exactly **once** — run 1, against this same repo on 2026-07-28, which found seven plugin defects and is recorded [here](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md). A method generalised from one execution is still a hypothesis, so your run is the next data point in the validation program ([skills#16](https://github.com/QuantEcon/skills/issues/16)), and the part no automation can supply is your judgement of the output. Step 6 is therefore not optional garnish — it is the result. +It differs from the [evaluation tutorial](tutorial-run-an-evaluation.md) in one important way. That one reproduces a committed reference, so every number you produce can be checked. Here there is no reference. `/qe:audit-issues` has been run as a skill **twice**: run 1 against this same repo on 2026-07-28, which found seven plugin defects ([record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md)), and run 2 against `QuantEcon/meta` on 2026-08-25 — 317 items, 138 open — which was deliberately killed mid-run and **resumed correctly**, settling the claim the program exists to check ([record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-meta-2026-08-25.md)). Two points still make a method a hypothesis, so your run is the next data point in the validation program ([skills#16](https://github.com/QuantEcon/skills/issues/16)), and the part no automation can supply is your judgement of the output. Step 6 is therefore not optional garnish — it is the result. + +**What run 3 should target**, since run 2 closed the obvious gaps: interrupt **mid-write** (run 2's kill left a clean entry, so the truncation guard has never fired) and interrupt **inside the closed pass** (run 2's kill landed in the open pass, and the closed pass turns out not to be incrementally checkpointed at all — [#57](https://github.com/QuantEcon/skills/issues/57)). Canonical references (this tutorial points, never restates): the procedure in [SKILL.md](../qe/skills/audit-issues/SKILL.md), the method in [doctrine.md](../qe/references/audit/doctrine.md), the org conventions in [quantecon-context.md](../qe/references/audit/quantecon-context.md), the output contract in [deliverables.md](../qe/references/audit/deliverables.md). ## What you need -- The `audit` plugin installed (Step 0). It is deliberately not in the lecture-repo auto-install block — it is maintainer tooling. +- The `qe` plugin installed (Step 0). Since the [#43](https://github.com/QuantEcon/skills/issues/43) consolidation in qe 0.7.0 there is no separate `audit` plugin: the plugin is the enable unit, so any repo that opts into `qe` gets this maintainer tooling alongside the author-facing skills. - `gh` authenticated. Preflight refuses to start without it, because the anonymous API returns nothing for the org's private repos and is capped at 60 requests/hour. - A checkout of the audited repo. Phase 2 verifies claims against its default branch, so a tracker-only run cannot do the job. -- **Tens of minutes**, and a session you can afford to interrupt — interrupting it is one of the tests. Run 1 took 22 minutes end to end for 230 items, of which phase 2 was about 9 — roughly 10 seconds for each of its 56 open issues. Budget the total, and scale it by the *open* count rather than the item count. +- **Tens of minutes**, and a session you can afford to interrupt — interrupting it is still one of the tests. Run 1 took 22 minutes end to end for 230 items, of which phase 2 was about 9 — roughly 10 seconds for each of its 56 open issues. Run 2 took ~53 minutes for 317 items and 138 open, including its interruption gap. Both the open count (2.5×) and the elapsed time (~2.4×) scaled together, so **scale your budget by the *open* count rather than the item count** — now on two points rather than one. ## Step 0 — install the plugin @@ -39,6 +41,8 @@ git check-ignore -v .dev/scratch/x # → .gitignore:… .dev/scratch/* `action-translation` has a `.dev/` notes system whose `.dev/scratch/*` is already gitignored, which makes it the first-choice working directory: the run leaves `git status` completely clean, and no `.gitignore` edit is needed — that would itself be a change to a tracked file. Repos without one fall back to an untracked `.audit/` at the root ([SKILL.md § Working directory](../qe/skills/audit-issues/SKILL.md)). +**Check that fallback before you take it.** Run 2 exposed the gap ([#61](https://github.com/QuantEcon/skills/issues/61)): the rule's stated goal is that a run leaves `git status` clean, but an untracked `.audit/` *does* show in `git status` unless the repo ignores that path — and `meta` has no `.gitignore` at all. The consequence there was 2.4 MB of findings, including AWS and access-token material, sitting untracked in a public checkout until moved by hand. Check with `git check-ignore -v .audit/x`, and read the **exit code**, not the output: it prints the matching rule and exits 0 when the path is ignored, and prints nothing and exits 1 when it is not — so silence means *not ignored*, which is the case you are looking for. If it exits 1, put the working directory **outside the checkout** instead — `~/work/quantecon/_audits/---issues/` is the convention run 2 settled on. + ## Step 2 — invoke ``` @@ -70,11 +74,13 @@ Your counts will differ from the ones above — the tracker moves (#11 measured ## Step 4 — phase 2, verify — and interrupt it -The long phase: 116 items checked against the default branch rather than against what their threads claim. Findings are appended to `findings.md` **one entry per item, as each is verified** — both passes, the open issues under `## Open` and the closed ones under `## Closed`. +The long phase: 116 items checked against the default branch rather than against what their threads claim. The guarantee is that findings are appended to `findings.md` **one entry per item, as each is verified** — both passes, the open issues under `## Open` and the closed ones under `## Closed` — so an interrupted run loses one item rather than the phase. Run 2 measured that it holds on the open side and not the closed one; see below. + +**This is still the test, and it now has an expected answer.** Once 20–30 entries exist, interrupt the session — close it, or press Esc twice. Then open a new session in the same directory and re-invoke the same command. What should happen: it partitions `issues.json` by state and, for each side independently, resumes at the lowest number with no entry under the matching heading, re-verifying only the last entry in each (which may have been half-written). What would be a failure: restarting from item 1, skipping the item it died on, duplicating entries, or resuming the open set correctly while re-doing the closed set from scratch. -**This is the test.** Once 20–30 entries exist, interrupt the session — close it, or press Esc twice. Then open a new session in the same directory and re-invoke the same command. What should happen: it partitions `issues.json` by state and, for each side independently, resumes at the lowest number with no entry under the matching heading, re-verifying only the last entry in each (which may have been half-written). What would be a failure: restarting from item 1, skipping the item it died on, duplicating entries, or resuming the open set correctly while re-doing the closed set from scratch. +**Write your prediction down before you resume** — the lowest un-entered number on each side, and the file's byte count. Run 2 did exactly this, predicted `#261`, and got it: the pre-kill bytes were byte-identical afterwards, so the resume was a pure append. A prediction recorded after the fact is not evidence. -**Interrupt during the closed pass too, if you get the chance** — that is the half that was not checkpointed at all before #34, so nothing has ever resumed from it. Resumability is asserted in three separate files and has never been tested. Two fixes have gone in ahead of this run and neither has been exercised: [#17](https://github.com/QuantEcon/skills/pull/17) named the artifacts, since before it phases 2 and 3 named none and a resumed session could only work by inventing the same filename; and [#34](https://github.com/QuantEcon/skills/pull/34) made the checkpoint cover both passes, since run 1 wrote only the open set and sent 62 closed issues straight to the catalog. This run is what checks both. +**Interrupt during the closed pass too, if you get the chance** — that is the half nothing has ever resumed from, and run 2 found out why. It sampled `findings.md` throughout and measured the write pattern: 15+ checkpoint writes across the 138 open items, in batches of 8–9 every 75–120 s, against **exactly one** write for all 179 closed ones — the complete section in a single flush at the end. [#34](https://github.com/QuantEcon/skills/pull/34) fixed the *format* (the `## Closed` heading and the two-partition resume rule) and left the *granularity* untouched, so an interrupt anywhere in the closed survey still loses the phase rather than one item, and the resume rule's address-by-issue-number is not well-defined against `deliverables.md`'s grouped entries anyway. That is [#57](https://github.com/QuantEcon/skills/issues/57), open. Expect the closed pass to restart from scratch until it lands — and if you can, sample `findings.md` while it runs so run 3 measures the pattern rather than inferring it. While it runs, `tail findings.md` occasionally. Every status claim should carry `[verified]`, `[stated]` or `[inferred]`, and a `[verified]` should cite `file:line`, a merged PR, a tag, or a commit — **and whatever it cites must resolve on the ref the audit named**, never a comment. A citation that only resolves in the author's working tree or on an unmerged branch is the defect [doctrine §2](../qe/references/audit/doctrine.md#2-evidence-classes) now rules out; run 1's headline finding had exactly that shape. @@ -82,7 +88,7 @@ While it runs, `tail findings.md` occasionally. Every status claim should carry Phase 3 writes the cross-link graph to `links.md`. Phase 4 tiers into the plan it discovered in Step 2 and writes the bundle. Phase 5 reconciles against `coverage.json` and folds any correction *back into* the documents rather than appending an erratum. -With 55 open issues this run should produce the **full four-document bundle**; a repo under about 30 open issues should instead fold the catalog and links into the report. That threshold is new and untested, so note whether four documents felt right at 55 or merely dutiful. The bundle's destination is `.dev/audits/-issues/` — the audit writes it there, but **committing it is your call, not the run's**. +With 55 open issues this run should produce the **full four-document bundle**; a repo under about 30 open issues should instead fold the catalog and links into the report. That threshold is still untested — run 2's 138 open issues did not bind it either — so note whether four documents felt right at 55 or merely dutiful. The bundle's destination is `.dev/audits/-issues/` where a notes system exists; where one does not, keep it wherever Step 1 put the working directory. Either way **committing it is your call, not the run's** — and read it before you decide: run 2's bundle carried AWS and access-token findings that belonged in a different repo than the one audited. ## Step 6 — review the output @@ -101,16 +107,18 @@ The run cannot check any of this about itself. Ten checks, the last two of which | 9 | **Is the tiering right?** | report tiering section | T0 that isn't this week's work, or a tier list not actually tied to `.dev/PLAN.md`. You are the authority; the run is guessing | | 10 | **Would you act on it?** | the whole bundle | The only check that matters, and the only one no self-audit can make | -Then confirm the boundary held: `git status --short` shows nothing but your ignored working directory, and the tracker is unchanged — no comments, no labels, no closures. +Then confirm the boundary held — and **measure it rather than eyeballing it**. `git status --short` should show nothing but your ignored working directory, and `HEAD` should be unmoved. For the tracker, fingerprint it before and after: number, state, `updated_at`, comment count and labels for every issue, hashed. Any close, label or comment moves `updated_at` on the affected issue, so identical hashes turn the doctrine's read-only promise into a measurement for the cost of two `gh` calls. Run 2 did this first and recommends it become a standard step ([#59](https://github.com/QuantEcon/skills/issues/59)); take the baseline *before* invoking, which is the one thing run 2 got slightly wrong. ## Step 7 — record the run Findings belong in this repo; the bundle does not. Write `reviews/audit-run--.md` — run 1's is [audit-run-action-translation-2026-07-28.md](../reviews/audit-run-action-translation-2026-07-28.md) — following the shape of the [ge_arrow validation run](../reviews/validation-run-ge_arrow-2026-07-22.md): - **Setup** — repo, snapshot timestamp, `fetched_by`, item counts, unaccounted numbers, plugin version. -- **Cost** — wall clock and rough token spend per phase. Run 1's figures are in [its record](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md); a second data point at a different repo type is what turns one measurement into an estimate. +- **Cost** — wall clock and rough token spend per phase, against [run 1](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-action-translation-2026-07-28.md) and [run 2](https://github.com/QuantEcon/skills/blob/main/reviews/audit-run-meta-2026-08-25.md). Two points support the open-count scaling rule but do not establish a rate, and run 2's total includes an interruption, so it bounds rather than measures. - **The ten checks** from Step 6, each held or broken, with the evidence. -- **Interruption log** — where you killed it, what resuming actually did. +- **Interruption log** — where you killed it, the prediction you recorded beforehand, and what resuming actually did. Run 2's is the shape to follow: state at kill captured externally, prediction written down, then a table of expectation against result. +- **The read-only fingerprint** — the before and after hashes, per Step 6. +- **What you discarded** — candidate findings you investigated and could not support. A validation report that lists only confirmed findings hides its own false-positive rate; run 2 records two. - **What the doctrine did and did not transfer** — the payload. A rule that was cited and load-bearing, a rule that never came up, and a rule the run had to work around are three different verdicts, and only the third is a bug. - **Your read of the bundle** — checks 9 and 10 in prose. diff --git a/docs/using-skills.md b/docs/using-skills.md index 52859fc..0650765 100644 --- a/docs/using-skills.md +++ b/docs/using-skills.md @@ -44,9 +44,9 @@ Everything that registers in your slash menu — one plugin, five skills. Since | Skill | What it does | Status | |---|---|---| | `/qe:copilot-review` | Work through GitHub Copilot's review of a PR: a verdict and recommended fix per comment, then a threaded reply to each one so they can be resolved from the GitHub UI | operational, validated from an installed plugin 2026-08-03 — [#26](https://github.com/QuantEcon/skills/pull/26) | -| `/qe:workplan-project`, `/qe:workplan` | The work-plan family: `workplan-project` turns an audit/review report into a tracking issue with linked sub-issues; `workplan` carries the single work-plan issue that holds state between agent sessions through its lifecycle — `create`, `read` (validate against live state and recommend next steps; writes nothing), `resume`, `update`, `close`-and-succeed. All GitHub writes are drafted first and gated on your approval | merged as complete procedures, no validated run yet — [skills#3](https://github.com/QuantEcon/skills/issues/3) | +| `/qe:workplan-project`, `/qe:workplan` | The work-plan family: `workplan-project` turns an audit/review report into a tracking issue with linked sub-issues; `workplan` carries the single work-plan issue that holds state between agent sessions through its lifecycle — `create`, `read` (validate against live state and recommend next steps; writes nothing), `resume`, `update`, `close`-and-succeed. All GitHub writes are drafted first and gated on your approval | `workplan` operational for `update` and `resume` (validated from an installed plugin 2026-08-20, and again 2026-08-25 on this repo's own plan issue); its `create`, `read` and `close` verbs, and `workplan-project`, are merged procedures with no run yet — [skills#3](https://github.com/QuantEcon/skills/issues/3) | | `/qe:benchmark` | Advise whether a lecture is worth converting at all (triage — the front door), or score a submitted NumPy→JAX/Numba conversion against the rubric (review) | operational for workspace runs — [guide](../qe/references/benchmark/README.md), [skills#4](https://github.com/QuantEcon/skills/issues/4) | -| `/qe:audit-issues` | Sweep a whole tracker: verify each issue's status against the code rather than the thread, tier the open set into the repo's plan, deliver a report bundle. Read-only — it recommends, never applies | run once as a skill, method validated only that far — [tutorial](tutorial-run-an-audit.md), [guide](../qe/references/audit/README.md), [skills#16](https://github.com/QuantEcon/skills/issues/16) | +| `/qe:audit-issues` | Sweep a whole tracker: verify each issue's status against the code rather than the thread, tier the open set into the repo's plan, deliver a report bundle. Read-only — it recommends, never applies | run twice as a skill (2026-07-28, 2026-08-25); run 2 validated resume-across-a-lost-session and measured the read-only boundary, and left the closed pass's checkpointing as the open defect — [tutorial](tutorial-run-an-audit.md), [guide](../qe/references/audit/README.md), [skills#16](https://github.com/QuantEcon/skills/issues/16) | ## Updating and troubleshooting diff --git a/qe/.claude-plugin/plugin.json b/qe/.claude-plugin/plugin.json index f7eeb26..d874ffd 100644 --- a/qe/.claude-plugin/plugin.json +++ b/qe/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "qe", "description": "QuantEcon's shared agent skills under one namespace — working through a PR's review feedback, advising on and scoring lecture acceleration (benchmark), bulk read-only repository audits, turning audit reports into tracked work projects, and creating, reading and carrying work-plan state across agent sessions", - "version": "0.7.0", + "version": "0.8.0", "author": { "name": "QuantEcon" } } diff --git a/qe/CHANGELOG.md b/qe/CHANGELOG.md index 72992ea..9246a5c 100644 --- a/qe/CHANGELOG.md +++ b/qe/CHANGELOG.md @@ -6,6 +6,22 @@ Versions are [semver](https://semver.org) as a user of this plugin experiences i Repository: [QuantEcon/skills](https://github.com/QuantEcon/skills) ([every commit that touched this plugin](https://github.com/QuantEcon/skills/commits/main/qe)). How a release is made: [developing-skills § Versioning and releases](https://github.com/QuantEcon/skills/blob/main/docs/developing-skills.md#versioning-and-releases). +## 0.8.0 — 2026-08-26 + +The work-plan skills gain a second reader. Since 2026-08-24 the [projects dashboard](https://quantecon.github.io/status-projects/) parses every registered project tracker nightly and publishes a per-tracker compliance block, so a tracker these skills produce is now read by a machine as well as by the next session. The two ends are pointed at one contract — [`docs/contracts/tracker.md`](https://github.com/QuantEcon/status-projects/blob/main/docs/contracts/tracker.md) (C2), which states the rules once and which the skills link to rather than restate ([#49](https://github.com/QuantEcon/skills/issues/49) item 2). + +**Changed** + +- **The revision stamp is now a heading in a fixed form** — `## Where we stand (verified YYYY-MM-DD)`, optionally with a time and zone. The skills carry the two example forms and the one authoring rule, not the parser grammar: C2 owns that and stays the authority, and `status-projects` being private is why the example is inline rather than a bare pointer. Both skills stamped before this release; they stamped in prose the collector cannot read, so a plan revised faithfully every session still published as unstamped. `create` writes the heading, `resume` and `update` re-date it, `read` reports its age and says when it is absent or malformed, and anchor-and-sweep reads the date from the stamp alone — a `verified` in a table cell or a checklist is not a stamp, and taking one as the anchor mis-scopes the sweep. +- **Long-lived trackers carry the native `Project` issue type**, applied after creation by `workplan`'s `create` and by `workplan-project`'s filing step. This replaces "plan issues stay untyped pending the QEP-2 field report": the field report is [qeps#11](https://github.com/QuantEcon/qeps/issues/11) and its answer turned out not to be a label at all, so QEP-2's set is untouched and `type:Project` filters org-wide. Period plans stay untyped — a session's working document is not a project. +- **`workplan-project` drafts the work as native sub-issues, explicitly.** It already created them; the reason is now stated, because it is load-bearing rather than cosmetic — a tracker whose work lives in body checkboxes publishes its progress as `null`, not as a percentage. + +**Added** + +- **Both skills now say that a conformant tracker is still invisible until it is registered**, and offer to draft its `projects.yml` row — slug, programme, stage, owner, one public sentence, and the tracker in `Owner/repo#N` form. Opening the pull request against `QuantEcon/status-projects` stays the user's move; the skills draft and stop. Automating the registration PR end to end is [#49](https://github.com/QuantEcon/skills/issues/49) item 1 and is not in this release. + +**Known gaps, tracked rather than fixed here**: the `qe:tracker-conform` skill the contract names as the fix half of its compliance block ([#49](https://github.com/QuantEcon/skills/issues/49) item 3), and the `wp{issue#}-stage{n}` milestone convention ([#55](https://github.com/QuantEcon/skills/issues/55)). + ## 0.7.0 — 2026-08-25 One namespace ([#43](https://github.com/QuantEcon/skills/issues/43)): the `benchmark` and `audit` plugins fold into `qe`, so every invocation reads as a QuantEcon skill and the catalog is one flat, small list. Three plugin prefixes encoded an installation distinction users don't care about when typing a command. This release starts strictly above every retiring stream (qe 0.6.0, benchmark 0.4.0, audit 0.2.0), so no version number in this merged changelog ever names two trees; the retired plugins' own entries are preserved below as historical sections. diff --git a/qe/skills/workplan-project/SKILL.md b/qe/skills/workplan-project/SKILL.md index 72b272e..1dd6850 100644 --- a/qe/skills/workplan-project/SKILL.md +++ b/qe/skills/workplan-project/SKILL.md @@ -79,9 +79,10 @@ Drop what no longer holds, and record every drop with its reason in the draft's Write drafts into `/workplan/`: `00-tracking.md`, then `NN-.md` per sub-issue. The shape follows the worked exemplar, [QuantEcon.py#925](https://github.com/QuantEcon/QuantEcon.py/issues/925) with sub-issue [#926](https://github.com/QuantEcon/QuantEcon.py/issues/926): -- **Tracking issue**: Background (why now, with sources) → where we stand → a findings/gaps table with severity → a **work plan table** (`Phase | Issue | Work item`) → a sequencing paragraph (what gates what, what can land immediately) → what does *not* need to change → sources, including the report bundle this package came from and the snapshot SHA. When step 3 left genuine unknowns, phase 0 is the phase that converts them into knowns, and the dependent items say they are gated on it. +- **Tracking issue**: Background (why now, with sources) → **`## Where we stand (verified )`** → a findings/gaps table with severity → a **work plan table** (`Phase | Issue | Work item`) → a sequencing paragraph (what gates what, what can land immediately) → what does *not* need to change → sources, including the report bundle this package came from and the snapshot SHA. That heading is the project tracker contract's status stamp and its form is exact — see **The tracker contract** below. When step 3 left genuine unknowns, phase 0 is the phase that converts them into knowns, and the dependent items say they are gated on it. - **Sub-issues**: open with `Part of # (Phase k).`, then the problem with its evidence as SHA-pinned permalinks, the proposed fix, and an **acceptance criteria** checklist. A finding the report left as a judgement call becomes a *decision* sub-issue — the question, the options, and the report's lean — never a silently chosen fix. - **Labels per [QEP-2](https://github.com/QuantEcon/qeps/blob/main/qeps/qep-0002-standard-github-labels.md)**: exactly one type label per issue (`bug`/`enhancement`/`infrastructure`/`maintenance`/`discuss`…), priority labels only for the genuine outliers — there is deliberately no `medium-priority`, unlabelled *is* the middle. Check the labels exist in the target repo (`gh label list`); if not, flag that the repo hasn't adopted the QEP-2 set and propose only labels it has. +- **The tracker contract**: what this skill produces *is* a project tracker — one issue, its direct sub-issues the work — so it is drafted to conform with [`docs/contracts/tracker.md`](https://github.com/QuantEcon/status-projects/blob/main/docs/contracts/tracker.md) (C2), which states the rules once and is not restated here. Three bear on the draft: the stamp heading above in its exact form; the work in **native sub-issues**, never body checkboxes, since checkbox progress publishes as `null`; and the native `Project` issue type, applied at step 5. - **[QEP-1](https://github.com/QuantEcon/qeps/blob/main/qeps/qep-0001-purpose-and-process.md) check**: if the package crosses repositories or changes how the whole team works, it may warrant a QEP rather than (or before) a pile of issues — say so instead of filing. - Every body will be GitHub-rendered, so the [rules for writing to GitHub](https://github.com/QuantEcon/skills/blob/main/AGENTS.md#writing-to-github) apply: one unbroken line per paragraph, no prose in fenced blocks, and never a closing keyword before an `owner/repo#N` reference. @@ -101,11 +102,12 @@ Creation order resolves the numbering chicken-and-egg: gh api repos///issues//sub_issues -F sub_issue_id="$id" ``` -5. Read the tracking issue back and confirm every sub-issue is listed. +5. Apply the tracker's native type: `gh issue edit --repo / --type Project`. It is org-level and label-free, so QEP-2's set is untouched; if the type is missing the call fails harmlessly — report it and carry on, since an untyped tracker is a finding rather than a failure. +6. Read the tracking issue back and confirm every sub-issue is listed, and that the stamp heading survived the step-3 edit intact. **Re-runs are safe if you look first**: before each create, `gh issue list --repo / --search " in:title"` — file only what is missing, and edit rather than duplicate. -When everything is filed, offer — don't do unasked — to move the bundle into its tree's `_processed/`, which is the local convention for "actioned". +When everything is filed, say plainly that the tracker is **not on the projects dashboard until it is registered**: a row in [`projects.yml`](https://github.com/QuantEcon/status-projects/blob/main/projects.yml) carrying its slug, programme, stage, owner, one public sentence and the tracker in `Owner/repo#N` form, landed as a pull request against `QuantEcon/status-projects` and gated by that repo's validator. Offer to draft the row; leave opening the PR to the user. Then offer — don't do unasked — to move the bundle into its tree's `_processed/`, which is the local convention for "actioned". ## Gotchas diff --git a/qe/skills/workplan/SKILL.md b/qe/skills/workplan/SKILL.md index 7eb0deb..14d6418 100644 --- a/qe/skills/workplan/SKILL.md +++ b/qe/skills/workplan/SKILL.md @@ -11,7 +11,7 @@ One skill for the whole lifecycle of the **work-plan issue**: the single GitHub The `workplan-*` family is two skills: this one carries the plan through `create` → `read` → `resume` → `update` → `close`-and-succeed; [`workplan-project`](https://github.com/QuantEcon/skills/blob/main/qe/skills/workplan-project/SKILL.md) builds a **project** (tracker + sub-issues) from an audit or review report. -> **Status: merged, no validated run yet.** First-run validation is tracked in [#3](https://github.com/QuantEcon/skills/issues/3). +> **Status: `update` and `resume` validated from an installed plugin (2026-08-20, and again 2026-08-25); `create`, `read` and `close` have no run yet.** Tracked in [#3](https://github.com/QuantEcon/skills/issues/3). Requires `gh`, authenticated (`read` uses it for reading only). @@ -19,7 +19,7 @@ Requires `gh`, authenticated (`read` uses it for reading only). Observed practice across the org's work-plan issues (exemplars: the [project-translation#37](https://github.com/QuantEcon/project-translation/issues/37) session chain, the [workspace-lectures#48](https://github.com/QuantEcon/workspace-lectures/issues/48) weekly series, [skills#25](https://github.com/QuantEcon/skills/issues/25)). Formalising it as a QEP is planned; until that lands, this section records the practice — and once it lands, this section becomes a pointer. -- **The body is the single source of truth for current state, revised in place.** It never accumulates narrative, and it stamps its own revision — with time and timezone, not a bare date, when sessions run close together (see the date-rollover gotcha below). +- **The body is the single source of truth for current state, revised in place.** It never accumulates narrative, and it stamps its own revision under a `## Where we stand (verified YYYY-MM-DD)` heading — with time and timezone, not a bare date, when sessions run close together (see the date-rollover gotcha below). The heading text and what may sit inside the parentheses are fixed by the tracker contract, not by taste; see below. - **Comments are revision logs**: what changed and why — especially premises that *inverted* rather than merely aged. - **Claims are verified against live state, never assumed or carried forward.** The artifact's whole value is that a future session can trust it blind; one unverified "fact" poisons that. - **New defects become their own issues, not plan paragraphs.** A problem a session discovers is filed as a linked issue (the exemplars file them same-day) and the plan cites it; prose-only findings are how things get lost. @@ -27,7 +27,25 @@ Observed practice across the org's work-plan issues (exemplars: the [project-tra - **Two genres, one lifecycle each.** A *period plan* (a session's or week's work) closes with a ledger and is succeeded; a *long-lived tracker* (a project-duration state register) is resumed and updated but never session-closed. - **Succession never copies.** The successor is built from the carry-forward register — unfinished and deferred items plus what the closing session surfaced — and opens "continuing from #N". - **One open period plan per repo at a time.** This is what makes "resume the session" — and this skill's issue discovery — unambiguous. -- **Plan issues stay untyped** pending the [QEP-2](https://github.com/QuantEcon/qeps/blob/main/qeps/qep-0002-standard-github-labels.md) field report on labelling plan/tracking issues. +- **Period plans stay untyped; long-lived trackers carry the native `Project` issue type.** Neither takes a type *label* — [QEP-2](https://github.com/QuantEcon/qeps/blob/main/qeps/qep-0002-standard-github-labels.md)'s set has none that fits, which is [qeps#11](https://github.com/QuantEcon/qeps/issues/11)'s field report, and the answer turned out not to be a label at all. `Project` is a native org-level issue type, enabled 2026-08-24, so it filters as `type:Project` org-wide and leaves the label vocabulary untouched. + +## The tracker contract + +A long-lived tracker is not only read by the next session. Since 2026-08-24 it is also read nightly by the [projects dashboard](https://quantecon.github.io/status-projects/), whose collector parses registered trackers and publishes a per-tracker compliance block. The rules it parses by are stated once, upstream, in [`docs/contracts/tracker.md`](https://github.com/QuantEcon/status-projects/blob/main/docs/contracts/tracker.md) (C2 — `status-projects` is private, so that link is members-only; the interface C2 implements is planned as a public QEP that C2 will cite, and this section re-points at that once it lands). Everything below is what the skill needs in order to *write* a conformant tracker without reading C2; C2 owns the parser grammar and stays the authority: + +- **The stamp is a heading**, written in one of these two forms: + + ```markdown + ## Where we stand (verified 2026-08-24) + ## Where we stand (verified 2026-08-24 12:05 AEST) + ``` + + The heading text is exactly `Where we stand`; the date is mandatory and the time and zone optional. A `> **Updated 2026-08-24.**` banner is an accepted fallback. **Free text is never a stamp** — a `verified` date in a sentence, a table cell or a checklist item stamps nothing, and neither does a differently-worded heading however well dated, so context goes in the prose *below* the heading rather than inside it. C2 states the full grammar and is the authority wherever this summary and it disagree. +- **Progress is native sub-issues, never body checkboxes.** A tracker whose work lives in checkboxes publishes as *unmeasured* — `null`, not 0% — because counting checkboxes would make progress mean different things on different trackers. +- **The `Project` type is the tracker signal**, and its absence is a finding rather than a failure: an untyped tracker is still read, and simply reports `untyped`. +- **A tracker is observed only once it is registered** in the dashboard's `projects.yml`. Creating a conformant tracker does not put it on the dashboard; see `create` step 4. + +None of this applies to a *period plan*, which is a session's working document and not a project. It carries the stamp heading — one stamp form across both genres is worth more than a distinction nobody remembers — and nothing else here. ## Invocation @@ -56,14 +74,14 @@ Every body and comment is GitHub-rendered, so the [rules for writing to GitHub]( Shared machinery for `read`, `resume`, `update`, and `create`'s session-bootstrap source: -- **Anchor**: the body's own revision stamp — the convention makes the "since when" explicit. Fall back to the issue's last-edit time if the stamp is missing. +- **Anchor**: the body's own revision stamp — the `## Where we stand (verified …)` heading makes the "since when" explicit. Accept the `> **Updated …**` banner as a fallback, and the issue's last-edit time when neither is present. Read the date from the stamp only: a `verified` in prose, a table cell or a checklist item is not a stamp, and taking one as the anchor silently mis-scopes the sweep. - **Sweep**: everything since the anchor, scoped by the plan's own link graph — plans routinely live in one repo while the work spans several. Commits on default branches, PRs opened/merged/closed, issues filed/edited/closed (`gh search issues/prs --updated ">STAMP"`, `git log` where a clone exists). - **Attribute honestly.** Traces since the anchor include other people's, bots', and parallel sessions' work. An update records what *happened*; it claims as this session's only what this session did. - **The conversation supplies only what traces cannot**: decisions made, dead ends worth not repeating, things learned, and the resume pointer. Every claim that *can* carry a trace citation (a PR, commit, or issue number) must. ## `read` — look, validate, recommend (writes nothing) -**Read** the body and comment thread (`gh issue view <n> --comments`) and report, in this order: the **revision stamp with its age** first ("stamped 2026-08-20 18:04 AEST — 5 days ago"); the front of the plan (what leads and why); the live-state facts *as of the stamp*; blocks and their gates; the latest revision-log comment — the previous session's handover; and "explicitly not doing" when the user's question touches something the plan already deferred. A closed plan is still readable: its ledger and carry-forward register answer "what happened to X?"; for the live thread, follow the "continuing from #N" chain forward. +**Read** the body and comment thread (`gh issue view <n> --comments`) and report, in this order: the **revision stamp with its age** first ("stamped 2026-08-20 18:04 AEST — 5 days ago"), noting it when the stamp is absent or not in the contract's form, since that is what the dashboard reports too; the front of the plan (what leads and why); the live-state facts *as of the stamp*; blocks and their gates; the latest revision-log comment — the previous session's handover; and "explicitly not doing" when the user's question touches something the plan already deferred. A closed plan is still readable: its ledger and carry-forward register answer "what happened to X?"; for the live thread, follow the "continuing from #N" chain forward. **Validate**: the body was true at its stamp; the gap since is unaudited. Sweep it and check the plan's premises — default depth is the front-of-plan items plus anything the sweep contradicts; `--full` checks every claim, worth it after a long gap. Classify each checked claim *holds* (still true), *aged* (true but the numbers moved — give both values), or *inverted* (what the plan believed, what is true, and the trace that shows it). Report body and reality side by side, never blended — a half-verified hybrid presented as "the plan" is worse than either, because nobody stamped it. Validation is not revision: a dead premise goes in the report and the recommendation, and the body changes only through `resume`/`update`, gated — that line is what keeps `read` safe to run casually. @@ -79,21 +97,23 @@ Shared machinery for `read`, `resume`, `update`, and `create`'s session-bootstra - **Title**: match the host repo's existing chain; default `Work plan — <scope>: <what leads>` for a period plan (the QEP will settle one form). - **Opening line**: where the plan came from — "continuing from #N (closed <date> with its ledger)" for succession, or the triage/session that produced it — plus the convention line: *this body is the single source of truth for the session, revised in place against live state before working it.* -- **Live-state table**: the step-2 baseline, every row stamped. +- **`## Where we stand (verified <date>)`**, in the contract's exact form, carrying the live-state table below it: the step-2 baseline, every row stamped. This heading is the plan's own revision stamp and the dashboard's anchor at once, so it is the one piece of the body whose wording is not yours to vary. - **Work blocks, ordered by dependency, not size**, each naming its gate, with the **front of the plan explicit**: what leads next session, and why. - **Explicitly not doing**: what was considered and deferred, with the reason — the section that stops the next session from re-litigating. -- **No type label** (see the convention). +- **No type label** (see the convention). For a long-lived tracker, the work belongs in **native sub-issues** rather than body checkboxes — that is what makes progress measurable rather than `null`. Present the draft and **wait for approval**. **4. File it.** Check the one-open-plan invariant first: an existing open period plan is a finding — the right move is usually `update` of that plan, not a second one; create anyway only if the user says the scopes are genuinely disjoint. Then `gh issue create --repo <o>/<r> --title … --body-file …` (no labels). In succession, creation order belongs to `close`. +**For a long-lived tracker, two steps follow the create.** Apply the native type — `gh issue edit <n> --repo <o>/<r> --type Project` — and then say plainly that the tracker is **not on the dashboard until it is registered**: a row in [`projects.yml`](https://github.com/QuantEcon/status-projects/blob/main/projects.yml) naming its slug, programme, stage, owner, one public sentence, and the tracker in `Owner/repo#N` form. Registration is a pull request against `QuantEcon/status-projects`, gated by that repo's validator; offer to draft the row, and leave opening the PR to the user. Neither step applies to a period plan. + ## `resume` and `update` — the session moments Same mechanics at opposite ends of the session: sweep since the anchor, revise the body in place, post a revision-log comment — each write gated as tabulated above. -- **`resume` (session start)**: the plan was true when its last session ended; the gap since is unaudited. Run `read`'s validation at working depth, then revise the body — facts re-measured with fresh stamps, the front of the plan re-pointed, dead premises corrected. Comment when something material changed; an inverted premise *always* gets a comment recording what the plan believed, what is true, and how the work changes. Then the session works the plan. -- **`update` (session end, plan continues)**: tick what completed, re-measure the facts the session touched, and set the **resume pointer** — what leads next session, and why. The comment records what landed (with trace citations), what was decided, what inverted, what was deferred and why. Before posting, test the pair against the acceptance test: could a fresh context resume from the issue alone? Anything essential still living only in the conversation isn't written down yet. +- **`resume` (session start)**: the plan was true when its last session ended; the gap since is unaudited. Run `read`'s validation at working depth, then revise the body — the `## Where we stand` heading re-dated, facts re-measured with fresh stamps, the front of the plan re-pointed, dead premises corrected. Comment when something material changed; an inverted premise *always* gets a comment recording what the plan believed, what is true, and how the work changes. Then the session works the plan. +- **`update` (session end, plan continues)**: tick what completed, re-measure the facts the session touched, re-date the `## Where we stand` heading, and set the **resume pointer** — what leads next session, and why. Re-dating is not cosmetic on a registered tracker: the dashboard publishes the stamp's *age*, so a body revised without its heading re-dated reports as stale work that is in fact current. The comment records what landed (with trace citations), what was decided, what inverted, what was deferred and why. Before posting, test the pair against the acceptance test: could a fresh context resume from the issue alone? Anything essential still living only in the conversation isn't written down yet. `gh issue edit --body` replaces the whole body: fetch the live body immediately before editing and diff against *that*, not what was fetched at session start — another session or a human may have edited in between.