Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ A new library is a target once it has the topic `python` and both of the hub's G

## What a sync would do

[expected.md](expected.md) says, per library and file, what `touchmark plan` should report today: after the rollout, nothing changes anywhere. Every library's `.agents/project.md` is its own (`local`), and mattermind and pg-partsmith keep one file each through `ignore` in their `.engineering-assets.yml`.
[expected.md](expected.md) says, per library and file, what `touchmark plan` should report today: after the starter packs went deeper on 2026-10-11, every library gets one sync pull request with nine updated files and one new one. Every library's `.agents/project.md` is its own (`local`), and mattermind and pg-partsmith keep one file each through `ignore` in their `.engineering-assets.yml`.

Check it in one command, with a read-only GitHub token (a fine-grained token with the default *Public repositories* access is enough, since every target is public):

Expand Down
77 changes: 40 additions & 37 deletions expected.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@ touchmark's check against a real fleet: `touchmark plan --assume-opt-in --all` o

## Where it stands

The rollout finished on 2026-10-07 (README, "Rollout"). Every library has the hub's files, so a plan changes nothing anywhere. What differs, differs on purpose:
The rollout finished on 2026-10-07 (README, "Rollout"), and every library had the hub's files. On 2026-10-11 the starter packs went deeper: the review prompt reviews a large change in slices and asks every addition for its reason, a new prompt `.agents/prompts/pure-refactor.md` checks that a change keeps behaviour, `AGENTS.md` gained working principles, and the `python-library` guidelines gained concrete rules. So every library gets one sync pull request: nine files updated and one created. What differs otherwise, differs on purpose:

- every library filled in `.agents/project.md`, which is therefore its own (`local`);
- mattermind keeps its own `.github/workflows/docs.yml`, since its docs dependencies are an extra, and pg-partsmith its own `.github/dependabot.yml`, which adds the `docker` ecosystem. Their `.engineering-assets.yml` lists those files under `ignore`.

Once those pull requests are merged, a plan changes nothing anywhere again: write the expectation again then.

The expectation holds while:

- only mattermind and pg-partsmith have an `.engineering-assets.yml`, and it only ignores those files. `targets.yml` subscribes every target (`defaults.opt_in: assumed`), so `--assume-opt-in` changes nothing;
- the organisation's repositories with the topic `python`, minus the `exclude` patterns of `targets.yml`, are these 13. A new one shows up as an unexpected target;
- touchmark has no open sync pull request in any target;
- the packs and the libraries' copies stay as they are. A change to a pack makes the copies `outdated` and the plan `opened`; a library that changes a copy makes it `local`. Either way, write the expectation again.

The default branches it was checked at, on 2026-10-07:
The default branches it was checked at, on 2026-10-11:

| Repository | Commit |
|---|---|
| aiokafka-foundation-kit | `96acc288c91df791e883b4f2fd98e60559852f54` |
| alembic-gauntlet | `abb8759679f98a9c7a51244a7bf3549807d3936f` |
| clientwright | `5a7a166e6115261191c0ec1c7e7df4999a132210` |
| deadline-budget | `fceea8f3f066e1d9287996b868c02fd80a300318` |
| grpc-client-kit | `939008517ca847a7b25d61bfa87d4dcc39e5fcab` |
| grpc-server-kit | `53a87321e107bcfb6ec2794f8fabbac797a99f02` |
| idempotency-kit | `953b8ca33e80574058de40d8fa6b39ede50f359a` |
| mattermind | `b7293884c58e7c4fe5f396888ce4fe469ac365bc` |
| omni-box | `9afb6e3933124dea072feee03d0b0a8a8a228e53` |
| pg-partsmith | `a8ca8679e2b2b2f0b1acf6ff7773b250f1344fe1` |
| redis-client-kit | `8379b44851180fd8dec92c63c7b56b0355236e26` |
| servicewright | `c59cdace648413454aea9ee4d9187e42761d7c55` |
| sqlalchemy-foundation-kit | `d3879fdf261944ea5e54643db6297dd1b699958d` |
| aiokafka-foundation-kit | `3ba88e56975e9d607aa8ce7f05ce0d7566a0108a` |
| alembic-gauntlet | `50eb84e11c667105713d5632f690e24d67b6b2d4` |
| clientwright | `7cda21512ab41266e741006329c845adf7db10f8` |
| deadline-budget | `37e0656b7bb9329df53e8b2bd03979d4a8cf47ba` |
| grpc-client-kit | `db6452920a1a2b3a8550a64fab174b5bc963cd49` |
| grpc-server-kit | `90fce7b4759eae094caf8ba2b8f0f2aef5ac914d` |
| idempotency-kit | `af413605ddd8b72361330ef5459045cf6eaabfd8` |
| mattermind | `04344c77790073691d53e77d704665270d6701ef` |
| omni-box | `c36f99f395f3fe85856d5d22305f1177df83a201` |
| pg-partsmith | `55c483a01cef9f20e530b7a43f300e190cd833ed` |
| redis-client-kit | `823a116ac0b5be68599760f7c43df055f1332b5f` |
| servicewright | `c84440df7596fce04519f3ccc7237e58c7e00aae` |
| sqlalchemy-foundation-kit | `87e97aa6ea45ae4a681491df4d31eddcfeb56eb6` |

## Expectation

Expand All @@ -42,19 +44,19 @@ That is `defaults.packs` of `targets.yml`, with `agents` placed before the packs

| Repository | Outcome | Create | Update | Delete |
|---|---|---:|---:|---:|
| `bedrock-python/aiokafka-foundation-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/alembic-gauntlet` | unchanged | 0 | 0 | 0 |
| `bedrock-python/clientwright` | unchanged | 0 | 0 | 0 |
| `bedrock-python/deadline-budget` | unchanged | 0 | 0 | 0 |
| `bedrock-python/grpc-client-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/grpc-server-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/idempotency-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/mattermind` | unchanged | 0 | 0 | 0 |
| `bedrock-python/omni-box` | unchanged | 0 | 0 | 0 |
| `bedrock-python/pg-partsmith` | unchanged | 0 | 0 | 0 |
| `bedrock-python/redis-client-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/servicewright` | unchanged | 0 | 0 | 0 |
| `bedrock-python/sqlalchemy-foundation-kit` | unchanged | 0 | 0 | 0 |
| `bedrock-python/aiokafka-foundation-kit` | opened | 1 | 9 | 0 |
| `bedrock-python/alembic-gauntlet` | opened | 1 | 9 | 0 |
| `bedrock-python/clientwright` | opened | 1 | 9 | 0 |
| `bedrock-python/deadline-budget` | opened | 1 | 9 | 0 |
| `bedrock-python/grpc-client-kit` | opened | 1 | 9 | 0 |
| `bedrock-python/grpc-server-kit` | opened | 1 | 9 | 0 |
| `bedrock-python/idempotency-kit` | opened | 1 | 9 | 0 |
| `bedrock-python/mattermind` | opened | 1 | 9 | 0 |
| `bedrock-python/omni-box` | opened | 1 | 9 | 0 |
| `bedrock-python/pg-partsmith` | opened | 1 | 9 | 0 |
| `bedrock-python/redis-client-kit` | opened | 1 | 9 | 0 |
| `bedrock-python/servicewright` | opened | 1 | 9 | 0 |
| `bedrock-python/sqlalchemy-foundation-kit` | opened | 1 | 9 | 0 |

| Path | Pack | State | Exceptions | Sensitive |
|---|---|---|---|---|
Expand All @@ -68,20 +70,21 @@ That is `defaults.packs` of `targets.yml`, with `agents` placed before the packs
| `.github/workflows/release-please.yml` | bedrock-community | current | - | yes |
| `CODE_OF_CONDUCT.md` | bedrock-community | current | - | no |
| `.agents/project.md` | agents | local | - | no |
| `.agents/prompts/refactor-check.md` | agents | current | - | no |
| `.agents/prompts/review.md` | agents | current | - | no |
| `AGENTS.md` | agents | current | - | no |
| `.claude/agents/reviewer.md` | claude | current | - | yes |
| `.agents/prompts/pure-refactor.md` | agents | missing | - | no |
| `.agents/prompts/refactor-check.md` | agents | outdated | - | no |
| `.agents/prompts/review.md` | agents | outdated | - | no |
| `AGENTS.md` | agents | outdated | - | no |
| `.claude/agents/reviewer.md` | claude | outdated | - | yes |
| `.claude/settings.json` | claude | current | - | yes |
| `.claude/skills/commit/SKILL.md` | claude | current | - | yes |
| `.claude/skills/new-branch/SKILL.md` | claude | current | - | yes |
| `.claude/skills/pr/SKILL.md` | claude | current | - | yes |
| `.claude/skills/review-change/SKILL.md` | claude | current | - | yes |
| `.claude/skills/pr/SKILL.md` | claude | outdated | - | yes |
| `.claude/skills/review-change/SKILL.md` | claude | outdated | - | yes |
| `.claude/skills/spec/SKILL.md` | claude | current | - | yes |
| `CLAUDE.md` | claude | current | - | no |
| `CLAUDE.md` | claude | outdated | - | no |
| `.agents/guidelines/public-api.md` | python-library | current | - | no |
| `.agents/guidelines/python.md` | python-library | current | - | no |
| `.agents/guidelines/testing.md` | python-library | current | - | no |
| `.agents/guidelines/python.md` | python-library | outdated | - | no |
| `.agents/guidelines/testing.md` | python-library | outdated | - | no |

Sensitive files are those the pull request description lists under ⚠: touchmark's built-in list (workflows, `dependabot.yml`, `.claude/settings*.json`, `.claude/agents/**`, `.claude/skills/**`, ...) and `sensitive_paths` of `hub.yml`. Skills are on the list because a skill's `allowed-tools` lets Claude Code use those tools without asking.

Expand Down
2 changes: 1 addition & 1 deletion hub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ packs:
bedrock-community:
description: Code of conduct, editor settings, Dependabot and release-please settings of every bedrock-python library
agents:
description: AGENTS.md for every coding agent, a project profile to fill in, review and refactoring prompts
description: AGENTS.md for every coding agent, a project profile to fill in, prompts to review a change, to plan a refactoring and to check that a change keeps behaviour
claude:
description: Claude Code instructions, skills (review-change, spec, new-branch, commit, pr), a reviewer subagent and settings that deny reading secrets
requires: [agents]
Expand Down
30 changes: 30 additions & 0 deletions packs/agents/.agents/prompts/pure-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Check that a change keeps behaviour

Use this on a change that claims to change no behaviour: a refactoring, a move, a rename, a dependency swap. Assume it does change behaviour until you have traced every path. You are checking, not rewriting: do not edit files unless you are asked to.

## What to check

The change you were given; if none was named, the current branch against the default branch, plus uncommitted and untracked changes. Read every changed file in full, old and new, and find every caller of every changed function, including references by string: registries, entry points, configuration, templates, dynamic lookups. Behaviour most often changes at a call site the diff does not show.

## How to work through it

Split the change into slices small enough to trace completely: a function, a class, a group of related functions. If your tool can run sub-agents, give each slice to one and run them in parallel; otherwise work through them one at a time and write down each result before the next. Tell each sub-agent this prompt, its slice and how to get the whole change (a range, or the uncommitted and untracked changes); a sub-agent given one slice traces that slice only, and whoever split the change merges the results.

For every slice, compare the old code with the new, path by path:

- **Interface:** the same importable names and module paths, parameter names (callers may pass them by keyword), configuration keys and environment variables, command-line flags, routes, and names in stored data and events.
- **Inputs:** the same accepted arguments, types, defaults and validation; the same behaviour on `None`, empty and boundary values.
- **Outputs:** the same return values and types, the same order of collections, the same serialised form (field names, missing versus null, number and date formats).
- **Errors:** the same exceptions for the same conditions, the same error codes and messages reaching callers, the same log level and event.
- **Side effects:** the same writes to storage, the same outgoing requests (payload, headers, order, retries, timeouts), the same metrics and their labels.
- **Order and timing:** the same order of operations wherever it can be observed: transaction boundaries, when a lock is taken, when a stream yields, when a task starts.
- **Code that appeared or disappeared:** a check, a default, a conversion or a log line that runs now and did not before, or the other way round.
- **Tests:** a changed assertion or fixture in a change that claims to keep behaviour is a behaviour change until shown otherwise.

## How to report

- **Behaviour changes**: each as `file:line`, the old behaviour, the new one, and how a caller, a user or the stored data would notice.
- **Not fully traced**: what differs and what would settle it.
- **Unchanged**: each slice and what you traced in it.

End with a one-line verdict: behaviour kept, behaviour changes found, or not settled (and how many paths are not fully traced). A change the author intended still counts if the description does not say so.
2 changes: 1 addition & 1 deletion packs/agents/.agents/prompts/refactor-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Answer these questions before you change the structure of code. If an answer is
5. **Reach.** Does it stay inside the code the task is about? Shared modules, public interfaces and changes across many files need their owners' agreement.
6. **Timing.** Will it collide with open pull requests or a release in progress?

When you go ahead, keep refactoring commits apart from behaviour changes, run the tests after every step, and explain in the pull request what moved where and why behaviour is unchanged.
When you go ahead, keep refactoring commits apart from behaviour changes, run the tests after every step, and explain in the pull request what moved where and why behaviour is unchanged. Before you open it, check the refactoring commits with `.agents/prompts/pure-refactor.md`.
32 changes: 25 additions & 7 deletions packs/agents/.agents/prompts/review.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
# Review a change

Review the change as a careful senior engineer of this project would. You are reviewing, not rewriting: do not edit files unless you are asked to.
Review the change as a careful senior engineer of this project would. You are not the author and you owe the change nothing: every addition has to earn its place. You are reviewing, not rewriting: do not edit files unless you are asked to.

## What to review

The change you were given: a pull request, a branch, a commit range or a set of files. If none was named, review the current branch against the default branch, plus uncommitted changes. Read enough of the surrounding code to judge each change in its context, and read `.agents/project.md` for the project's conventions.
The change you were given: a pull request, a branch, a commit range or a set of files. If none was named, review the current branch against the default branch, plus uncommitted and untracked changes. Read `.agents/project.md` for the project's conventions, and the guidelines in `.agents/guidelines/` that cover the code the change touches.

Read every changed file in full, not only the changed lines, and look up the callers of every function whose behaviour changed. Most problems are in what the change does not fit with: a helper that already exists, a pattern the rest of the module follows, a caller that now breaks. Search for them and cite where they are instead of guessing.

## How to work through it

1. **Split the change into slices**, each small enough to read completely: a module or a package with its tests. A small change is one slice.
2. **Review each slice** against the list below. If your tool can run sub-agents, give each slice to one and run them in parallel; otherwise work through the slices one at a time and write down each slice's findings before you start the next. Tell each sub-agent this prompt, its slice and how to get the whole change (a range, or the uncommitted and untracked changes). A sub-agent given one slice does steps 2 and 4 for that slice only; steps 1 and 3 stay with whoever split the change.
3. **Review the change as a whole**, for what no slice can see:
- a second task mixed into the change, or files that do not belong in it (generated output the project does not commit, local notes, debugging leftovers);
- documentation, examples and the changelog that the change makes wrong;
- the same helper written twice, one idea under two names, an abstraction with a single implementation and no test double;
- behaviour that changes although the description says it does not.
4. **Check every finding** at the line you cite. Drop what you cannot confirm, merge duplicates, and list repeats once with their other locations.

## What to look for, most important first

1. **Correctness.** Does the change do what its description says? Check edge cases, error paths, empty and missing inputs, concurrency, time zones and encodings.
1. **Correctness.** Does the change do what its description says? Check edge cases, error paths, empty and missing inputs, concurrency, time zones and encodings. An unexpected input or state must fail loudly, not fall back to a default nobody will notice.
2. **Security.** Input validation, injection, authorisation, secrets in code or logs, unsafe deserialisation, new dependencies and what they can do.
3. **Compatibility and data.** Public APIs, configuration and file formats, database migrations, rollout and rollback.
4. **Tests.** Would a test fail without the change? Are the important cases covered? Do the tests check behaviour rather than implementation details?
5. **Operations.** Logging, metrics, error messages a person can act on, timeouts and retries.
6. **Readability.** Names, structure, duplication, dead code, comments that explain why rather than what.
5. **Necessity.** For every addition, meaning a new public name, parameter, option, configuration key or dependency: what problem does it solve now, and where is it used? "It might be useful later" is a reason to leave it out.
6. **Operations.** Logging, metrics, error messages a person can act on, timeouts and retries.
7. **Readability.** Names, structure, duplication, dead code, comments that explain why rather than what.

Skip style points that a formatter or linter already enforces.
Skip style points that a formatter or linter already enforces. Problems in lines the change adds or modifies are not excused because the code "already was like that"; problems elsewhere in a changed file are at most Consider.

## How to report

Expand All @@ -25,4 +39,8 @@ Group findings by severity:
- **Should fix**: likely problems, missing tests, confusing code.
- **Consider**: suggestions and questions.

For each finding give the file and line, what is wrong, why it matters, and a concrete fix. If you are not sure, say so and say what would settle it. End with a one-line verdict. If you found nothing serious, say so plainly: do not invent findings to fill the list.
For each finding give the file and line, what is wrong, why it matters, and a concrete fix. Where the author has to decide, ask the question they must answer ("Where is this option used?", "What happens when the list is empty?"). If you are not sure, say so and say what would settle it.

Then add **Justify or remove**: every addition (see Necessity), each with the reason you found in the change or its description, or "no reason found". Additions are judged here only, not again among the findings.

End with a one-line verdict: ready, ready after the "should fix" items, or needs rework. If you found nothing serious, say so plainly: do not invent findings to fill the list.
Loading
Loading