Skip to content

State what a host must provide, and route the write-safety kit from it - #482

Merged
ptr727 merged 2 commits into
developfrom
feature/host-setup-contract
Jul 31, 2026
Merged

State what a host must provide, and route the write-safety kit from it#482
ptr727 merged 2 commits into
developfrom
feature/host-setup-contract

Conversation

@ptr727

@ptr727 ptr727 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

STANDUP.md step 0 (#481) now expects a configured host, but nothing stated what a host must actually provide. This adds the contract. The per-platform implementation is deliberately not here, and is tracked separately.

The gap

The repo invokes python3 at fifteen call sites, docker for the four linters, uvx for coverage, plus git and gh. None of that was written down, so a fresh host discovered each requirement by failure. Two other things were also missing:

  • The write-safety kit was unreachable from docs/host-setup.md, even though its own README calls it "the first thing on any new system". It lived in host-setup/agent-safety/ with no route from the host-setup procedure.
  • No mapping from host capability to repo procedure, so a missing tool read as a bare checklist item rather than "this blocks standing up a repo".

Contract, not implementation

The table names the tool, what needs it, and how to see it is present. It names no installer. winget, brew and apt differ per platform while the requirement does not, so keeping install commands out is what makes the table true on every host, and it keeps per-machine specifics out of a public repo.

Tool Needed by Present when
git everything, and the identity/signing contract in STANDUP.md step 0 git --version
gh the PR and review loop, gh api, repo-config/configure.sh gh --version
python3 scripts/ and spec/ (standard library only) python3 --version
docker the four linters, as pinned images docker --version
uv / uvx coverage, and the Python toolchain in a Python repo uv --version

Two consequences worth stating rather than leaving to be discovered: python3 needs no packages, and the linters need only docker, not node or a local markdownlint, which is what keeps a local run and CI the same check.

Also in this change

  • The write-safety kit is now a step in docs/host-setup.md, with the host-versus-repo distinction made explicit: the carried GOVERNANCE.md rules reach fleet repos, while the hook and the CLAUDE.md block cover every session on the machine, including ad-hoc work in no project at all, which is where the incident behind the kit happened.
  • A closing table maps the finished host to what it can then do, so a failing row names the procedure it blocks.

Follow-up, not in scope here

Per-platform install commands (winget / brew / apt / WSL2) are tracked in a separate issue, filled in per platform by whoever can actually test that platform. I can only verify Linux from this host, and writing untested Windows and macOS install commands into a doc is how a setup guide starts lying.

Verification

Every command was run as written before committing, including the full verify block, and the referenced installer paths were confirmed to exist. docs/host-setup.md reports zero on all prose rules, markdownlint and editorconfig-checker are clean, and the diff is additive (46 insertions, 0 deletions) with line endings intact.

STANDUP.md step 0 now expects a configured host, but nothing said what a
host must have. The repo invokes python3 at fifteen call sites, docker for
the four linters, uvx for coverage, plus git and gh, and a fresh host
discovered each of those by failure.

docs/host-setup.md gains the contract: which tool, which procedure stops
without it, and how to see it is present. It names no installer, because
winget, brew and apt differ per platform while the requirement does not,
which keeps the table true on every host and keeps per-OS specifics out of a
public repo. Two facts are worth reading off it rather than learning later:
python3 needs no packages, since every script here is standard library only,
and the linters need only docker, since each runs as the pinned image CI
uses.

The write-safety kit was unreachable from this document, even though its own
README calls it the first thing to deploy on a new system. It is now a step
here, with the host-versus-repo distinction stated: the carried GOVERNANCE.md
rules reach fleet repos, while the hook and the CLAUDE.md block cover every
session on the machine, including work in no project at all, which is where
the incident behind the kit happened.

A closing table maps the finished host to what it can then do, so a failed
row names the procedure it blocks rather than reading as a bare checklist.

Every command was run as written before committing, and the referenced
installer paths were confirmed to exist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the host onboarding documentation to explicitly define the required host toolchain contract and to link the agent write-safety kit from the host setup flow, aligning the doc with STANDUP.md’s expectations and reducing “discover by failure” setup friction.

Changes:

  • Adds a “What a Host Must Provide” contract table mapping required tools to the repo procedures they enable/block.
  • Routes the “Agent Write-Safety Kit” into docs/host-setup.md as a first-class host setup step, with platform entrypoints.
  • Adds a “What the host can do once this passes” table tying successful setup to enabled workflows.

Comment thread docs/host-setup.md
The doc opens by saying every command snippet below assumes a POSIX shell
and will not work as-is in PowerShell. The write-safety kit step then added
the first powershell block in the file, so the blanket claim became false in
exactly the place a Windows reader needs it to be true. Following the note
as written, that reader would run the Windows-native installer through Git
Bash, or skip it as not applying.

The note now carries the exception: a block marked powershell is the
Windows-native form of its step, meant to run in PowerShell rather than
translated. Verified that this is the only powershell fence in the file, and
that every other command fence is shell.

The same sentence carried a clause-joining semicolon, which the linter
exempts because a colon earlier in the line makes it read as a list. That is
the documented limit of the semicolon rule, caught by reading the diff
rather than by the gate, and fixed here since the line was being edited.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 21:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

docs/host-setup.md:150

  • The PowerShell install command is missing the ./-equivalent . prefix, so PowerShell may not execute it as a relative script path. The script itself documents invocation as .\install.ps1 (see host-setup/agent-safety/install.ps1 header), so this should be ./host-setup/... in PowerShell form.
host-setup\agent-safety\install.ps1       # Windows

@ptr727

ptr727 commented Jul 31, 2026

Copy link
Copy Markdown
Owner Author

Round 2 suppressed finding: declined, with the evidence and one honest limit on it.

The finding conflates two different invocation contexts, and the script header it cites is the other one.

What the header actually documents (host-setup/agent-safety/install.ps1, lines 3-4):

#   .\install.ps1
#   $env:CLAUDE_HOME = "C:\path"; .\install.ps1   # override the target (testing)

That is a bare filename run from inside the script's own directory, which does require .\, because PowerShell does not search the current directory for commands. My line is a multi-segment relative path from the repo root, which is a different case: a command token containing a directory separator is resolved as a path, so the .\ prefix is not required.

The kit's own README already documents my exact form (host-setup/agent-safety/README.md line 23):

# Windows
host-setup\agent-safety\install.ps1

So the line in this PR matches the invocation the kit has documented all along. Changing only mine would introduce the inconsistency round 1 of this review correctly flagged, and the suggested ./host-setup/... uses forward slashes, which is neither what the header shows nor the Windows convention the kit already uses.

The limit, stated rather than glossed. I cannot execute PowerShell on this host, so this rests on PowerShell's documented path resolution plus consistency with the kit's existing README, not on a run. If it turns out to be wrong, the kit README is wrong too and both change together.

That is exactly what #483 is for: it collects per-platform install commands, filled in only by someone who has run them on that platform. I have added a note there to verify this invocation on a real Windows host. If it fails, the fix lands in both places.

@ptr727
ptr727 merged commit 91e901b into develop Jul 31, 2026
7 checks passed
@ptr727
ptr727 deleted the feature/host-setup-contract branch July 31, 2026 21:38
ptr727 added a commit that referenced this pull request Jul 31, 2026
…rm (#484)

Two corrections from the #483 Windows and WSL2 testing, both of which
disproved something the contract merged in #482 asserted.

The PowerShell installer invocation needs the .\ prefix. PowerShell does not
load a command from a relative path without it, and warns that it does not
assume the current location. This was declined during the #482 review on the
argument that a multi-segment path resolves where a bare filename does not,
flagged at the time as reasoning rather than a run because PowerShell cannot
be executed from the Linux host. The maintainer's direct experience is that
both forms need either .\ or an absolute path. Both files that carried the
line are corrected, since docs/host-setup.md and the kit README shipped the
same unprefixed form. Worth recording that the Windows column of #483 was
filled by an agent, so the tool installs around install.ps1 were exercised
while the documented invocation itself never was.

The interpreter is not called python3 everywhere, so the contract's presence
check failed on the platform it most needed to be right about. On native
Windows the installer registers python, py and python3.13 but not python3,
where that name resolves to a Microsoft Store alias stub that reports the
interpreter as missing, so a correctly set-up host read as broken. Stock
Debian is the mirror image, carrying python3 and no bare python. The row now
names py -3 for native Windows, and the consolidated verify block carries
the same translation, including the Git Bash case: it inherits the Windows
PATH, so python3 reaches the stub there too, which the shell note's advice
to use WSL2 or Git Bash would otherwise appear to cover.

A PowerShell equivalent of the verify block is deliberately absent. It has
not been run on a Windows host, and this change exists because an unverified
PowerShell invocation shipped and was wrong. #483 carries the request under
its rule that a cell is filled only by someone who has run it.

Three findings from the same testing are deliberately not carried, recorded
so they are not re-proposed. Docker Desktop performs the WSL2 enabling
itself and exposes the per-distro integration toggle the matrix already
documents. The WSL interop credential-helper failure was an upstream bug
since fixed, leaving only that Docker Desktop must be quit rather than
paused before wsl --update. And the /mnt/c permission behavior does not
apply to a workflow that treats WSL2 as an ordinary Debian host.

The kit README's dash backlog is cleared, per the corrected-as-next-edited
rule. It is hub-only, so no re-vendor debt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Aug 1, 2026
Forward promotion of five commits. `main` carries no content beyond the
merge-base (`8771e62`, #478), so this is a clean forward merge with no
conflicts.

**This one has a consumer waiting.** The Blog standup (#456) is
mid-correction and has been told to carry its instruction set from
`main`, because `main` is the audit ground truth. Every fix for the
failure it just hit is currently on `develop` only: `main`'s
`STANDUP.md` still begins at "1. Classify and Catalog", with no step 0
and no step 1A, and `main` does not yet require `OPERATIONS.md`. Until
this promotes, a repo following the corrected instructions re-runs the
uncorrected procedure.

## What promotes

- **#480 - Name where repo-specific content goes.** `STANDUP.md` step 2
named no destination for content that is not a carried file. The three
destinations existed only in `spec/section-model.md`, which nothing on
the scaffolding path pointed at.
- **#481 - Verify commit identity before the first commit, and require
`OPERATIONS.md`.** Step 0 verifies identity and signing before `git
init`, framed **verify, never set**, because the host carries the
identity globally and a repo-local override shadows it silently.
`OPERATIONS.md` becomes required for an `operational` repo,
presence-checked like `README.md`.
- **#482 - State what a host must provide.** The tooling contract,
naming no installer so it stays true on every platform, plus a route to
the write-safety kit which the host-setup document never referenced.
- **#484 - Prefix the PowerShell invocation, and name the interpreter
per platform.** Both corrections came from real Windows and WSL2 testing
in #483 and disproved something #482 asserted.
- **#485 - Require the instruction set before any authoring.** Step 1A,
the direct fix for the Blog failure.

## Verification on the merged `develop`

The full 180-case `scripts/` suite, `scripts/repo_gate.py`,
`spec/validate.py` and `spec/audit.py --selftest` all pass. The blocking
prose run (charset, dupword, spelling) is clean tree-wide, markdownlint
reports 0 issues over 39 files, and editorconfig-checker is clean.

## Release

A human merge never auto-publishes, so this fires no release, as
designed. The latest release stays `2.0.108`.

## Re-vendor debt

#481 changed `GOVERNANCE.md` "Git and Commit Rules", a `verbatim`
section, so this promotion re-vendors it across the fleet. That was
accepted deliberately when the change was made. The debt is pre-existing
and still untracked, and `spec/audit.py --branch <ref>` checks a repo's
convergence before it promotes.

## Known backlog, not in this promotion

The hub's own `.editorconfig`, `.gitattributes` and `.gitignore` carry
44 comment-shape findings, which downstream repos inherit by copying
them and reading them for house style. #485 works around it by telling
agents to trust the rule text over a carried file's formatting. Cleaning
those three files is owed and deliberately separate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants