Release 1.3.0 (2026-04-26)¶
Bug fixes¶
- scope markdownlint to docs/site and README.md only (#197) (#200)
Revert markdownlint from
markdownlint .back to an explicit file list targeting only MkDocs sources (docs/site/, docs/sphinx/) and README.md.
The markdownlint . approach introduced in #190 expanded the blast
radius to include CLAUDE.md, AGENTS.md, skills/, agents/, fragments/,
and other operational files that were never intended to be linted. This
caused recurring CI failures on every PR across all repos.
The explicit file list matches the structural check scope exactly, ensuring markdownlint and ToC/H1 checks audit the same set of files.
- accept st-docker-test entry point in validate-local preflight (#218)
- fix: accept st-docker-test entry point in validate-local preflight
st-validate-local now checks for st-docker-test (installed entry point) in addition to docker-test (legacy bash wrapper) when verifying that docker-test is available.
_find_validator also prefers st-{name} entry points over bare names, ensuring validators are found when standard-tooling is pip-installed and scripts/bin/ is not on PATH.
- use GHCR image URLs as default dev container references (#232)
- update docker-test references to st-docker-test (#234)
- mount host .gitconfig into container for git identity (#245)
- fix: mount host .gitconfig into container for git identity
Bind-mount ~/.gitconfig read-only at /root/.gitconfig so git commands inside the container pick up the host user's name and email. Skipped gracefully if ~/.gitconfig does not exist. Fixes #244.
-
mock Path.home in docker_test empty volumes test (#246) The .gitconfig mount added in #244 introduced a second -v flag when ~/.gitconfig exists. The empty_extra_volumes test in test_docker_test.py was not updated to mock Path.home. Ref #244.
-
remove individual validation commands from CLAUDE.md (#250) Replace individual linter/formatter command listings with the single st-validate-local entry point. Listing individual commands implicitly authorized agents to run arbitrary tools ad-hoc (see RTFM #248). Ref #248
-
refuse to run from a secondary worktree (#278)
- fix(finalize): refuse to run from a secondary worktree
Hit live after merging #276: st-finalize-repo from the worktree
blew up with git checkout develop returned non-zero exit status
128 because develop was already checked out in the main tree.
- set ST_COMMIT_CONTEXT=1 in git.run for commit calls (#295) (#296)
CI¶
- use dev-docs container for docs CI (#210)
- ci: use dev-docs container for docs CI
Run docs workflow inside ghcr.io/wphillipmoore/dev-docs:latest, removing the manual Python setup step and updating docs-deploy ref to @develop.
- restore standards-compliance after wrapper fallback landed (#219) The wrapper fallback fix from #218 is now on develop, so standards-compliance can run successfully again.
Documentation¶
- add consolidated git-workflow guide as canonical entry point (#271)
- docs: add consolidated git-workflow guide as canonical entry point
Adds docs/site/docs/guides/git-workflow.md as the single canonical
entry point for how git works across every managed repository. This
is Phase 1 of #270 — consolidates guidance that was previously
scattered across six documents with overlap and drift.
The new guide covers:
- At-a-glance one-screen view of the branch → commit → PR → finalize cycle.
- Branching model (the three supported variants from repository-standards.md, protected branches, issue-number-in-branch rule).
- The two enforcement layers (pre-commit git hook and standard-tooling-plugin PreToolUse hooks), with a table of what each catches and why both exist.
- Per-change cycle reflecting today's state:
st-commit,st-submit-prwith the manual-merge-is-the-default caveat from #268,st-finalize-repo. - Parallel work with worktrees, framed as a user-facing how-to that links to the spec for rationale.
- High-level release-flow overview linking to the existing
releasing.md. - Troubleshooting — what each blocked-hook signal means and how to recover.
Supporting refactors:
docs/site/mkdocs.yml: adds Git Workflow as the first entry under the Guides nav so it's the expected starting point.docs/git-hooks-and-validation.md: adds a prominent pointer to the new guide at the top; expands the validation matrix from a 2-column (pre-commit / CI) to a 3-column (pre-commit / plugin / CI) table reflecting today's three enforcement layers. Notes thatblock-memory-writes.shwas removed on 2026-04-23.
Out of scope, tracked separately:
- Rewrites of
getting-started.mdandconsuming-repo-setup.mdto reflect Docker-first + plugin-aware + worktree-aware onboarding (Phase 2 follow-up — to be filed once this lands). - Plugin-side cross-ref from
hooks/index.mdto the new guide (separate small PR in the plugin repo). - Pre-commit/plugin hook symmetry work (explicit accepted debt).
Dogfooded the worktree convention for authoring this PR — work
happened in .worktrees/issue-270-git-workflow-doc/.
- rewrite onboarding docs for Docker/plugin/worktree reality (#273) Phase 2 of #270. Rewrites both onboarding docs to reflect the Docker-first + plugin-aware + worktree-aware state that the rest of the repo now documents in CLAUDE.md, the canonical git-workflow guide (#271), and the worktree convention spec (#258).
getting-started.md (quickstart, one-screen)¶
Target audience: new consumer, five to ten minutes to a running setup. Structured as eight numbered steps:
- Prerequisites (Docker, uv, gh, macOS/Linux)
- Clone standard-tooling as a sibling
- Bootstrap the host venv with
UV_PROJECT_ENVIRONMENT=.venv-host uv sync --group dev - PATH setup for
.venv-host/binandscripts/bin - Git hook configuration
- Enable the Claude Code plugin via
.claude/settings.json - Create
docs/repository-standards.md(minimal example) - Adopt the worktree convention
- Verify — three sanity-checks (host bridge, plugin, git hook)
Ends with next-steps links into the full walkthrough, git-workflow guide, and worktree spec.
consuming-repo-setup.md (full walkthrough)¶
Target audience: same new consumer, wants to understand why each step exists and pick up CI + markdownlint + plugin configuration in detail. Structured as ten numbered steps plus mental-model intro, verification protocol, update procedure, and troubleshooting.
Key differences from the old content:
- Opens with a three-surface mental model (host bridge / dev container / plugin) plus two scripted layers (local git hook + CI composite action) so the reader can orient.
- The dual-venv rationale (
.venvin container vs.venv-hoston host) is spelled out where it matters — bootstrapping and keeping up to date. Both point atUV_PROJECT_ENVIRONMENT=.venv-hostand warn against dropping the override. - Repository-profile section gets the full attribute-value table
and notes values with
<,>,|are rejected as placeholders. - Plugin section carries an explicit warning pointing at standard-tooling-plugin#46 (release setup) rather than pretending the install flow is smooth.
- Markdownlint config documents the MD013 tables/code_blocks exemption and the MD060 disable we set in Phase 1.
- CI section uses the
dev-basecontainer image (not the renamed- awaydev-docs), matching #252. - Troubleshooting section addresses the common new-user failures
(
.venv-hostbuilt wrong, plugin not loaded, worktree commit blocked, auto-merge CalledProcessError from #268).
git-workflow.md¶
Removed the "Setup docs are being refreshed" caveat block that pointed at Phase 2 as future work. Updated the adoption-path section to link both the quickstart and the full walkthrough as explicit entry points.
Dogfooded the worktree convention — work happened in
.worktrees/issue-272-onboarding-rewrite/.
-
add git-URL dev-dependency convention spec (#285) Documents the convention that replaces the sibling-checkout plus manual-PATH model for making
standard-tooling's host-side CLI tools available in consuming managed repositories. -
reject git-URL dev-dep approach; add pushback report (#287) The [tool.uv.sources] pattern assumed all consumers are uv-managed Python projects, but only 1 of 5 non-deferred in-scope repos (ARM) has a pyproject.toml. Plugin, docker, and both docs repos have no pyproject.toml and cannot adopt the pattern. The plugin repo specifically was the driver per plugin#69 — the approach cannot solve the problem it was created to solve.
Adds a pushback report at paad/pushback-reviews/ capturing the rejection reasons and the replacement direction (standard-tooling as a host-level developer tool). Marks the spec landed via #285 as superseded so future readers don't rely on it.
Replacement tracked in #286.
- add host-level-tool spec, plan, pushback, and alignment artifacts (#290) Replaces the rejected git-URL dev-dependency approach (#284, #285, PR #287) with a host-level-tool distribution model. Three coordinated deployment targets — developer host, Python project .venv, and dev container image — share a single source of truth (the rolling v{major.minor} tag).
Artifacts in this PR (no implementation yet):
-
docs/specs/host-level-tool.md — the spec. Six principles, three deployment targets, canonical install via
uv tool install,.venv-hostretained for dev-tree override, Python consumers MUST declare standard-tooling as a dev dep, dev container images MUST rebuild on each release, git-hook becomes a five-line env-var-plus-GIT_REFLOG_ACTION gate with checks moved into st-commit. -
docs/plans/host-level-tool-plan.md — seven-phase implementation plan. Phase 1 code work in this repo; Phase 2 cuts v1.3.0; Phase 3 owns standard-tooling-docker#51; Phase 4 owns a new standard-actions issue; Phases 5-6 migrate consumers; Phase 7 is the docs sweep (#288). Phase 1 tasks rewritten in red/green/ refactor TDD format per paad:alignment.
-
paad/pushback-reviews/2026-04-24-host-level-tool-pushback.md — pushback review record. 9 issues found, 8 resolved by spec edits, 1 dismissed (rollback plan; fleet-of-one fail-forward).
-
paad/alignment-reviews/2026-04-25-host-level-tool-alignment.md — alignment review record. 5 issues found, all resolved by plan edits. Plan now covers every spec acceptance criterion; no orphaned tasks.
Features¶
- add Rust/Cargo ecosystem support to st-prepare-release (#176)
-
feat(release): add Rust/Cargo ecosystem support to st-prepare-release
-
add claude-plugin ecosystem detector (#186)
- feat(prepare-release): add claude-plugin ecosystem detector
Add _detect_claude_plugin() that reads version from .claude-plugin/plugin.json. This unblocks changelog and release-notes generation for the standard-tooling-plugin repo.
- run st-validate-local after finalization (#201)
- feat: run st-validate-local after finalization (#198)
st-finalize-repo now runs st-validate-local after switching to the target branch and pulling latest. This catches validation failures on develop immediately after a merge, before the next PR is created.
Validation failures return exit code 1 with a warning — the git finalization (branch switch, pull, prune) still completes. If st-validate-local is not on PATH, a warning is printed and validation is skipped.
-
add single-file mode and remove sphinx references (#203) markdown-standards now accepts optional file arguments. When given, each file is classified by path (docs/site/ = lint-only, README.md = lint + structural, else = skip) and validated with the same checks as discovery mode. This enables the PostToolUse hook to use markdown-standards directly, keeping CI and hook validation in sync. Also removes all sphinx references.
-
container-first validation infrastructure (#205) Rewrite validate-local-{common,python,go,java,rust} scripts to delegate to repo scripts/dev/*.sh which run inside containers via docker-test. This makes containers the single source of truth for all validation.
-
docker-test: add DOCKER_EXTRA_VOLUMES support and allow explicit DOCKER_DEV_IMAGE when language auto-detection fails
- validate-local-common: containerise via docker-test with mounted standard-tooling scripts
- validate-local-{python,go,java,rust}: replace host-based tool execution with thin orchestrators calling scripts/dev/*.sh
- validate_local.py: add Docker pre-flight check
-
scripts/dev/*.sh: remove fallback docker run blocks, require docker-test on PATH; add uv sync --check to audit.sh
-
add docker-docs wrapper for containerised docs preview (#209)
- feat: add docker-docs wrapper for containerised docs preview
New script paralleling docker-test that runs mkdocs serve/build inside the dev-docs container. Auto-mounts mq-rest-admin-common fragments and detects Python repos for mkdocstrings support via uv.
- port all bash scripts to Python entry points (#216) Port 11 bash scripts from scripts/bin/ and scripts/lib/git-hooks/ to Python modules in src/standard_tooling/bin/, registered as 13 new [project.scripts] entry points in pyproject.toml.
Each original bash script is replaced with a thin wrapper that calls the new Python entry point, providing backward compatibility during the migration.
New modules: pr_issue_linkage, repo_profile_cli, pre_commit_hook, markdown_standards, docker_test, docker_docs, validate_local_lang (shared by 4 entry points), validate_local_common, and validate_local_common_container.
115 new tests with 100% branch coverage on all new modules. Full suite: 364 tests, 100% coverage, mypy strict, ruff clean.
- pass GH_TOKEN through to dev containers (#223)
- feat: pass GH_TOKEN through to dev containers
Extend the docker_test.py environment passthrough to forward GH_ and GITHUB_ prefixed variables so gh CLI authenticates inside containers. Add documentation for the GH_TOKEN setup in getting-started and submit-pr reference pages.
Ref wphillipmoore/mq-rest-admin-common#222
- add st-docker-run general-purpose container command wrapper (#239)
- feat: add st-docker-run general-purpose container command wrapper
Extract shared docker logic into lib/docker.py and add st-docker-run entry point that runs arbitrary commands inside dev containers. Falls back to dev-docs:latest when no language detected. Refactor st-docker-test to use the shared module.
-
add dual-venv host bootstrap for st-docker-run (#240) Add .venv-host to .gitignore and update CLAUDE.md to document the dual-venv model: .venv for containers, .venv-host for host bootstrap. Update development commands to use st-docker-run.
-
mount ~/.ssh in container for git SSH remote operations (#253)
- feat: mount ~/.ssh in container for git SSH remote operations
Bind-mount the host SSH directory read-only at /root/.ssh so git push/fetch over SSH works inside containers. Ref #247
- run validation via st-docker-run in st-finalize-repo (#254)
- feat: run validation via st-docker-run in st-finalize-repo
Prefer st-docker-run for post-finalization validation, falling back to direct st-validate-local when st-docker-run is not available. Ref #241
- adopt git worktree convention for parallel AI agent development (#264)
- docs: add worktree convention spec, plan, and PAAD review artifacts
Adds the design spec and implementation plan for the parallel AI agent worktree convention, plus the pushback and alignment review records that shaped them. No behavior change in this commit — the convention itself lands in the follow-up commit that updates .gitignore and CLAUDE.md.
- add st-merge-when-green and stop auto-merging PRs in st-submit-pr/st-prepare-release (#276)
Step 1 of 3 for the poll-and-merge rework tracked by
wphillipmoore/standard-tooling-plugin#57 (the release skill
predates the org-wide auto-merge ban; every
gh pr merge --autocall in the release path has been silently failing since auto- merge was disabled).
New CLI: st-merge-when-green¶
Added src/standard_tooling/bin/merge_when_green.py (entry point st-merge-when-green in pyproject.toml). Wraps two gh calls:
gh pr checks
Default strategy is merge (release/bump PRs use merge commits).
Intentionally dumb — on any check failure, exit non-zero and
surface the error to the caller. The caller (release skill) owns
the "what to do on failure" context; this tool owns the task.
Remove auto-merge calls¶
- st-submit-pr (submit_pr.py): removed the final github.auto_merge() call. The PR gets created; the tool exits. Also fixes #268.
- st-prepare-release (prepare_release.py): same. Now prints a hint pointing at st-merge-when-green once the PR is live.
Prune the dead helper¶
- refuse feature-branch commits from main worktree (#259) (#275)
- feat: refuse feature-branch commits from main worktree (#259)
Extends the repo pre-commit hook to enforce rule 3 of the worktree convention: when a .worktrees/ directory is present, commits on feature/, bugfix/, hotfix/, or chore/ branches are refused from the main worktree. This catches out-of-worktree edits that would otherwise slip past the agent-prompt contract.
The opt-in signal is the presence of .worktrees/ at the repo root, so consuming repos that have not yet adopted the convention are unaffected until they do.
Refactoring¶
- normalize validation stack to one container per run (#282)
- refactor(validation): normalize validation stack to one container per run
Normalize the validation stack so Docker is invoked exactly once per validation pass, not once per inner script.
Before¶
st-validate-local required docker + st-docker-test on PATH.
It dispatched to per-language validators which called
scripts/dev/{lint,test,typecheck,audit}.sh; each of those
scripts re-containerized via st-docker-test. The result was a
doubly-containerized invocation that couldn't actually work via
st-docker-run -- uv run st-validate-local (docker-in-docker
unavailable inside the dev-python container).
After¶
Two clean layers:
- Outer:
st-docker-runlaunches the dev container once and runsst-validate-localinside it. - Inner:
scripts/dev/*.share tiny, container-local scripts that invoke tooling directly (uv run ruff check, etc.). They do NOT containerize themselves.
Changes¶
scripts/dev/{lint,test,typecheck,audit}.shrewritten as simple container-local bash:uv sync, then the actual tool.validate_local_common.pystops launching a container viadocker-test; it delegates directly tovalidate_local_common_container.main()(both modules kept so entry points and tests are minimally disturbed).validate_local.pydrops thedocker/st-docker-testprecondition check —st-validate-localnow expects to run inside a container, and a caller who mis-runs it on the host will get clear errors from the inner scripts about missinguv/ruff/etc.- Tests updated to match the simplified control flow.
CLAUDE.md"Three-Tier CI Model" and "Docker-First Testing" sections rewritten to reflect the new single-container design. Thescripts/dev/*.shfiles are now documented as the per-repo customization point.
Verification¶
st-docker-run -- uv run pytest tests/ ...passes all 420 tests with 100% coverage.- Direct invocation from a worktree crashed at git.repo_root()
inside the container because the worktree's
.gitfile points at an absolute host path not mounted inside. Filed as #281; not caused by this PR and orthogonal to its scope.
Scope¶
This PR normalizes this repo only. Parallel work tracked in other tooling repos (standard-actions, standard-tooling-plugin, standard-tooling-docker, standards-and-conventions, infrastructure-mindset, ai-research-methodology) per #280. mq-rest-admin-* repos get tracking issues but no code change yet (they're not under active development).
- consolidate pre-commit checks into st-commit; add env-var gate (#292)
- refactor(commit): consolidate pre-commit checks into st-commit; add env-var gate
Implements Phase 1 of the host-level-tool plan (docs/plans/host-level-tool-plan.md). Closes #291.
Code changes:
- src/standard_tooling/bin/commit.py: ports the five branch / context
checks (detached HEAD, protected branches, branch prefix, issue
number, worktree convention) verbatim from the now-deleted
pre_commit_hook.py. Sets ST_COMMIT_CONTEXT=1 before invoking
git commit --file so the new gate admits the commit.
- src/standard_tooling/bin/pre_commit_hook.py: deleted.
- pyproject.toml: removes the st-pre-commit-hook console-script entry
point. Strict semver would warrant v2.0.0; in practice no in-fleet
consumer invokes the entry point directly (all wire core.hooksPath
at scripts/lib/git-hooks/pre-commit, also deleted here). Release
notes for v1.3.0 will call out the removal as a clean break.
- scripts/lib/git-hooks/pre-commit: deleted.
- .githooks/pre-commit: new env-var-plus-GIT_REFLOG_ACTION gate.
Admits ST_COMMIT_CONTEXT=1, admits derived workflows (amend,
cherry-pick, revert, rebase, merge), rejects raw git commit.
- CLAUDE.md, README.md: updated to reference .githooks/, host-level
install model, and the new gate semantics. Stale scripts/bin/
bash-validators section removed (those tools have been Python
entry points since #216).
Test changes: - tests/standard_tooling/test_commit.py: 21 new tests pinning the five validation checks (one rejection + one happy path each, plus edge cases) and the ST_COMMIT_CONTEXT=1 env-var contract. Two pre-existing tests adjusted to mock current_branch / is_main_worktree now that validation runs in commit.main(). - tests/standard_tooling/test_pre_commit_hook.py: deleted (logic migrated; coverage preserved by the new tests in test_commit.py). - tests/standard_tooling/test_pre_commit_gate.py: 14 new subprocess tests pinning the gate's three branches (admit-by-env, admit-by-GIT_REFLOG_ACTION across the five admitted patterns, reject for everything else; plus precedence and value-narrowness cases).
All 432 tests pass; 100% coverage maintained.