Skip to content

Ship the tally-rewind skill, installable as a plugin or with Composer - #10

Merged
ondrejmirtes merged 3 commits into
1.xfrom
tally-rewind-skill
Nov 14, 2026
Merged

ondrejmirtes merged 3 commits into
1.xfrom
tally-rewind-skill

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Tally now comes with an Agent Skill, tally-rewind, that people can install as a Claude Code or Codex plugin, with npx skills, or with Composer. This PR also has two Tally fixes that came up while trying the skill on 11 PHP projects.

Commits

  1. Report commands use the program the user ran. "Reproduce locally" and "Accept the new numbers" always said vendor/bin/tally, which does not exist when Tally lives in a Composer project of its own, such as tools/tally/. Now bin/tally passes how it was run, and the commands use that.
  2. Only the class named like its file is a benchmark class. Before, Tally checked the constructor of every instantiable class in a *Bench.php file. So a helper next to a benchmark, such as final class Money { __construct(public int $cents) }, failed tally list. Five of the ten trial runs hit this. A benchmark that runs at old commits needs its helpers in the bench file, because the autoloader at those commits doesn't know them. Now StrBench in StrBench.php is the only benchmark class in its file, which matches what BenchmarkUsageProvider already assumed.
  3. The tally-rewind skill and how it is installed. The skill finds a project's past performance fixes, turns each into a Tally benchmark locked at the fix, and replays it on the releases since to find the best numbers that code ever had. Then it makes today's code beat those numbers, keeping only changes that make a real workload faster in wall-clock time. It also adds the benchmarks to the project, with the Tally setup and a CI job. scripts/measure.sh measures bench files at several commits, each in its own worktree, with the Tally version the project has installed.

Installing the skill

claude plugin marketplace add phpstan/tally && claude plugin install tally@phpstan
codex plugin marketplace add phpstan/tally && codex plugin add tally@phpstan
npx skills add phpstan/tally -a claude-code -a codex
composer require --dev llm/skills   # needs a skills.json alias for .claude/skills
  • .claude-plugin/marketplace.json is a marketplace named phpstan with the plugin tally, which is the repository root. Codex reads this file too.
  • extra.skills in composer.json declares the skills for llm/skills, so a project gets the skills of the Tally version it requires.

Testing

  • All four routes were tested from a local clone with Claude Code 2.1.325 and Codex 0.169.0. Each one installs the skill where the agent reads it, and the agent loads it: Claude Code's debug log lists it, and Codex has tally-rewind in its prompt. The GitHub shorthand phpstan/tally works only after this is merged.
  • measure.sh was tested on a small repo with a slow version and its fix, at several commits in one run. Also tested: Tally in tools/.tally, a commit whose dev dependencies don't install, TALLY_REWIND_PREPARE, and the error cases. Shellcheck reports nothing apart from its notes about PHP code in single quotes.
  • make lint, make cs, make phpstan, make tests (1083 tests), and make coverage (100 %) pass. Infection killed all 80 mutants in the changed files.

The report's "Reproduce locally" and "Accept the new numbers" commands
always said vendor/bin/tally, which does not exist in a project that
keeps Tally in a Composer project of its own, such as tools/tally/.
bin/tally now passes how it was run, and the commands use that.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d9be-190b-7065-bc04-21b38804941c
Every instantiable class in a *Bench.php file was a benchmark class,
so a helper next to a benchmark, such as a value object whose
constructor takes data, failed tally list because Tally could not
create it. Helpers belong in the bench file when the benchmark runs at
old commits whose autoloader does not know them, as in tally-rewind.

Now the class named like the file, such as StrBench in StrBench.php,
is the benchmark class, as the dead code detector's usage provider
already assumed. Other classes of the file are not checked.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d9be-190b-7065-bc04-21b38804941c
tally-rewind finds a project's past performance fixes, turns each into
a Tally benchmark locked at the fix, replays it on the releases since
to find the best numbers the code had, and makes today's code beat
them with a wall-clock gain on a real workload. It adds the benchmarks
to the project, with the Tally setup and its CI job.

scripts/measure.sh measures bench files at commits of the history,
each in a worktree, with the Tally version the project has installed,
installed apart from the project so that old commits need not fit it.

The repository is a plugin marketplace that Claude Code and Codex both
read (.claude-plugin/marketplace.json), and composer.json declares the
skills for llm/skills, so a project gets the skills of the Tally
version it requires.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d9be-190b-7065-bc04-21b38804941c
@ondrejmirtes
ondrejmirtes merged commit 15b85ef into 1.x Nov 14, 2026
30 checks passed
@ondrejmirtes
ondrejmirtes deleted the tally-rewind-skill branch November 14, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant