Commit 6df14c0
Record the Cluster for Documenting a Cross-Owner Write Grant (#629)
**Disposition** `New entry`, as a new cluster under "Work Clusters".
Nothing in the file reasons about the write-safety kit's documentation,
so there was no entry to amend.
No closing keyword, since a feature to `develop` pull request never
fires one.
## The gap
The hook denies a `gh` write whose explicit target is under an owner
other than the checkout origin's, and the only way past it is a
maintainer grant in `GH_WRITE_GUARD_ALLOW`. Read against `develop` at
`92b9fc5`:
| Document | What it says about the variable |
| --- | --- |
| `docs/host-setup.md` "Agent Write-Safety Kit" | Nothing. This is the
section a developer follows to install the kit. |
| `host-setup/agent-safety/README.md` | Names it once, inside the bullet
describing what the hook *denies*. Gives the token format (`owner/repo`,
`owner/*` for a whole owner) and not how to set it. |
| `README.md` | No host-protection section, only a pointer to
`docs/host-setup.md`. |
So a reader who hits a denial is told a grant exists and never how to
make one.
## What the entry carries
- **The channel that works** is an `env` block in the checkout's
`.claude/settings.local.json`. It is per project rather than host wide,
so a grant made for one checkout does not follow the agent into another
repository's sessions.
- **The raising case is a fork**, where `origin` is under the
maintainer's own owner and `upstream` is the project it forked from.
Filing an issue or pull request against the upstream is the cross-owner
write and everything aimed at the fork is not, so the grant names the
upstream alone. That asymmetry is what a reader meets first, and it is
why the section wants a worked example rather than a definition.
- **The two forms a reader reaches for first cannot work**: an inline
`GH_WRITE_GUARD_ALLOW=owner/repo gh ...` prefix, and an `export` in a
shell call. The hook runs as its own process and reads only the
environment the session was launched with, which is exactly what makes a
grant a deliberate act taken outside the session rather than something
an agent can do for itself once blocked. `gh-write-guard.py` already
asserts the inline prefix denies, so the behavior is settled and only
the explanation is missing.
- **Two things to carry beside the example**: that a session restart
loads the grant, and a way to confirm one took, since inferring it from
a write that no longer denies means learning the answer by making the
write.
This change records the work. It does not do it, so both documents are
untouched here.
## Verification
`scripts/prose_lint.py` exit 0, `markdownlint-cli2` 0 issues,
`editorconfig-checker` exit 0, `TODO.md` at 507 of 507 CRLF lines. The
three new reference definitions sort by reference name, `[host-setup]`
after `[governance]`, `[readme]` before `[readme-structure]`, and
`[write-guard-readme]` after `[write-guard]`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 92b9fc5 commit 6df14c0
1 file changed
Lines changed: 18 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
318 | 318 | | |
319 | 319 | | |
320 | 320 | | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
321 | 336 | | |
322 | 337 | | |
323 | 338 | | |
| |||
468 | 483 | | |
469 | 484 | | |
470 | 485 | | |
| 486 | + | |
471 | 487 | | |
472 | 488 | | |
473 | 489 | | |
474 | 490 | | |
475 | 491 | | |
476 | 492 | | |
| 493 | + | |
477 | 494 | | |
478 | 495 | | |
479 | 496 | | |
| |||
487 | 504 | | |
488 | 505 | | |
489 | 506 | | |
| 507 | + | |
0 commit comments