pr-publication-safety
kunchenguid/no-mistakes/.agents/skills/pr-publication-safety/SKILL.md
Use when changing PR body rendering, home-path redaction, artifact path publication, pipeline-attestation markers, or pre-push attestation.
Skill8.8k starsChanged yesterday
--- name: pr-publication-safety description: Use when changing PR body rendering, home-path redaction, artifact path publication, pipeline-attestation markers, or pre-push attestation. user-invocable: false metadata: internal: true --- **Home-Path Redaction in Published PR Content (security)** - `internal/safepath` is the one owner of home-directory redaction, the path analogue of `internal/safeurl`. `RedactText` rewrites the process's own home plus `/home/<user>`, `/Users/<user>`, and `C:\Users\<user>` to `~`, unconditionally and for every occurrence. Add new shapes there rather than scrubbing paths at a call site. Candidate resolution must stay free of `filepath.IsAbs`/`VolumeName` and of any reliance on `filepath.Clean`'s separator normalisation: those answer for the build platform, and on Windows `IsAbs` discards the POSIX-rooted `HOME` that Git Bash, MSYS2, and Cygwin set - silently disabling redaction instead of failing. Regression: `TestUsableHomeCandidate_AcceptsBothPlatformSpellings`, `TestHomeCandidates_AreSeparatorSpellingIndependent`. - `redactPRContent` in `pr.go` owns the publication redaction boundary. `PRStep.buildPRContent` uses it for ordinary drafts; template creation and live author-preserving updates use it through `composeOwnedPRContent` before stamping their byte-integrity guard. Every source that can reach a PR body - agent prose, extracted intent, findings, fix summaries, step errors, artifact `path`, artifact captions, and captured output embedded from evidence files - is covered there, so a new rendering path cannot reintroduce the leak. Ordinary drafts redact after length caps (the placeholder never grows a path); template composition redacts before its integrity guard and fail-closed size check. `pr_ownership.go` owns that marked-appendix contract: never feed live author text through heading-based stripping/clamping, and keep `rebindOwnedPRAttestation` in the pre-push restamp path so its integrity guard remains valid. Regressions: `pr_template_test.go`, `pr_ownership_test.go`. - The `artifacts[].path` description in `testFindingsSchema` (`common.go`) must not solicit absolute paths, and must not forbid them either. The renderer's allowlist is the worktree or the run's evidence directory and a path under neither is dropped, while the evidence directory defaults under the operator's home - so soliciting more just re-supplies what the boundary has to strip, and a blanket "never report a home directory path" clause makes an obedient agent drop its own evidence. Publication safety is the `pr.go` boundary's job; the schema only stops soliciting paths from elsewhere on the machine. Regressions: `TestTestFindingsSchema_DoesNotSolicitAbsolutePaths`, `TestTestFindingsSchema_KeepsEvidenceDirectoryPathsReportable`. - Two other public surfaces deliberately do NOT share this rendering and are not covered: agent-authored commit subjects (`commitAgentFixes` -> `Commit.RenderFixMessage`) and their trailers (`withCommitTrailers` -> `Commit.RenderTrailers`, whose agent and model values are reduced to one safe token), which reach the remote through Push, and the opt-in evidence branch (`test.evidence.store_in_repo`), which copies artifact files verbatim. Keep the `internal/safepath` package doc honest about that scope. - The PR body must contain exactly ONE live pipeline-attestation marker, the run's own. `require-no-mistakes` (`.github/actions/require-no-mistakes/verify.py`) binds the FIRST marker in the RAW body to the PR head, so a foreign copy placed earlier fails a PR the pipeline did produce - and a code fence is no defense, because that scan is raw text. Step agents embed foreign markers routinely, by capturing a generated PR body as evidence. - A CI repair that publishes a new head rewrites only that live marker's `head_sha` in the current PR body (`restampPublishedAttestation`) and does not send a title. It never inserts a marker that was not already there. Hosts without a PR content reader skip the restamp instead of failing the push. Regressions: `TestCIStep_PublishRepairRebindsAttestationAcrossRepairPushes`, `TestCIStep_PublishRepairDoesNotMintAttestation`, `TestCIStep_PublishRepairSkipsRestampWithoutReader`, `TestRestampPRAttestation_PreservesContentEditedWhilePreparingRewrite`, `TestUpdatePROmitsTitleWhenEmpty`. - Neutralize at the assembly choke point (`appendGeneratedSectionsToCleanBodyWithinLimit` plus the two intent paths), never per render path. `pipelineMD` alone carries the real marker and is left intact; `BuildPipelineSummaryFor` neutralizes its own step-detail blocks, which quote agent text. A first attempt put this in `escapePipelineFoldMarkers` - per-render-path - and shipped three live foreign markers to #831 anyway. Regressions: `TestPRStep_ForeignAttestationsInEveryComponentDoNotShadowTheRealOne` (all components at once), plus the per-component guards in `pr_test.go`. - Regressions: `internal/safepath/redact_test.go`, `internal/pipeline/steps/pr_homepath_test.go`. **Pre-Push Pipeline Attestation** - `publishRunHead` must write an existing PR attestation for the proposed head before pushing it on every supported provider with raw content reads. `docs/src/content/docs/reference/repo-config.md` (`pr.template`) owns provider-specific ownership/budget and visible Bitbucket metadata caveats. The protocol has single-publisher scope because the daemon enforces one active run per repository branch; do not add cross-publisher coordination without a separate requirement. Detailed behavior is owned by `docs/src/content/docs/reference/pipeline-steps.md`; local rationale lives in `attestHeadBeforePush` and `publishRunHead`. Regressions: `TestPushStep_AttestsHeadBeforePush`, `TestPushStep_AttestationWriteFailureAbortsBeforePush`, `TestPushStep_UnavailableSCMLeavesStaleAttestationFailingClosed`, `TestPushStep_PushFailureAfterAttestationLeavesBodyAhead`, and `TestCIStep_PublishRepairRebindsAttestationAcrossRepairPushes`.
More agent context in kunchenguid/no-mistakes
17 other files this repository gives its agents.
AGENTS.md
CLAUDE.md
Skill
- agent-tuning.agents/skills/agent-tuning/SKILL.md
- branch-sync-and-push-safety.agents/skills/branch-sync-and-push-safety/SKILL.md
- ci-monitor.agents/skills/ci-monitor/SKILL.md
- daemon-runtime.agents/skills/daemon-runtime/SKILL.md
- documentation-guidance.agents/skills/documentation-guidance/SKILL.md
- eval-corpus.agents/skills/eval-corpus/SKILL.md
- gate-worktree-git-safety.agents/skills/gate-worktree-git-safety/SKILL.md
- pipeline-review-and-agents.agents/skills/pipeline-review-and-agents/SKILL.md
- pr-enforcement-action.agents/skills/pr-enforcement-action/SKILL.md
- process-lifecycle.agents/skills/process-lifecycle/SKILL.md
- release-signing.agents/skills/release-signing/SKILL.md
- repository-routing-security.agents/skills/repository-routing-security/SKILL.md
- test-evidence-storage.agents/skills/test-evidence-storage/SKILL.md
- testing-conventions.agents/skills/testing-conventions/SKILL.md
- no-mistakesskills/no-mistakes/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
Reports can't be read right now.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

