.stamphog/ was a config directory at the repo root — policy.yml, review-guidance.md — read by the PR review agent. It is .stamp/ now, and the 34 files that name it follow: the workflows, tools/pr-approval-agent, tach.toml, the sandbox Dockerfile, bin/debrand. One behaviour change worth naming rather than burying: the agent finds its own previous PR comment by an HTML marker, `<!-- stamphog:v1 ... -->`, and that marker is now `<!-- stamp:v1 ... -->`. Open PRs will get one new comment instead of an edit, once, and then match again. insights/test/setup_receivers_baseline.txt records registered signal receivers by module path, so it names products.review.backend now. stamphog: zero occurrences anywhere in the tree. review_hog: only inside migration files, whose names are their identity in django_migrations. Co-authored-by: Hanzo Dev <[email protected]>
.stamp
Declarative policy for the stamp PR-approval merge gate (tools/pr-approval-agent/).
The engine loads these files from the checked-out working tree at run time.
Engine and policy are vendored into other repos (see the note in tools/pr-approval-agent/README.md), so format changes here need those copies re-synced too.
What lives here
policy.yml- the global machine policy: deny categories, allow-list, size gate, tier thresholds, dismiss-time triviality rules, the folder delegation contract, and the ownership source (theinsightscli-resolverinput that feeds the reviewer's advisory team context via the shared insightscli resolver). Trusted data. Each rule'srationalerecords why the rule became what it is (which false positives drove an exclusion, and when) - historical justification like a commit message, not a claim about the present.review-guidance.md- the trusted review-norms prose injected into the reviewer's system prompt. Ordinary repo-formatted markdown. Editing it changes the production prompt directly, so update deliberately - thestamp_policydeny guarantees a human reviews every change.
Proposing a policy change
Open a PR that edits these files.
Stamp can never auto-approve it: the stamp_policy deny category matches .stamp/**, any AGENT_APPROVALS.md, and tools/pr-approval-agent/**, so every change to the gate's own policy or engine routes to a human reviewer.
The loader also hard-fails if that self-governance entry is ever missing, so it cannot be dropped silently.
Per-folder overrides (AGENT_APPROVALS.md)
A folder may carry an AGENT_APPROVALS.md with a stamp: frontmatter block plus advisory prose.
Resolution:
- Every
AGENT_APPROVALS.mdat or above a changed file governs it: guidance accumulates outermost first, and a child file adds to its ancestors rather than replacing them. - For the delegated
size_gate.max_files, the nearest file on the chain with a valid grant wins for its files (within the contract ceiling); files whose chain grants nothing belong to the global pool. - The frontmatter is a positive allow-list: only keys named in the
overridescontract inpolicy.ymlare read, within their ceilings. Anything else (unknown key, out-of-bounds value, unparseable frontmatter) invalidates the whole file - frontmatter and prose. An invalid file contributes nothing itself, but it does not cancel its ancestors: files under it still ride an ancestor's grant, or fall to the global pool if the chain grants nothing. Rationale: an author who can write an invalid file could equally delete it, so treating invalid as absent grants no extra power, and everyAGENT_APPROVALS.mdedit is human-reviewed via thestamp_policydeny anyway. - The prose is untrusted advisory guidance. It is sanitized, length-capped, and injected inside the reviewer prompt's untrusted region; it can never override the deny rules or the refusal criteria.
Mixed PRs get mixed leniency
Each scope's files are counted against that scope's own file ceiling, so a grant covers exactly the files that resolve to it (the nearest valid grant on their chain) and nothing else.
Example: a PR changing 30 files under products/visual_review/ (ceiling 50) plus 19 files elsewhere (global ceiling 20) passes, because each budget fits.
Add a 21st global file and the PR is denied for the global budget, no matter how much headroom the folder still has.
Files whose chain grants no valid max_files (no folder file, prose-only, or only invalid grants) count against the global budget, so splitting files across pseudo-scopes can never inflate the allowance.
The line ceiling stays a single global total; it is not delegable.
Delegation contract
The set of keys a folder file may override lives under overrides in policy.yml (currently just size_gate.max_files, ceiling 50).
deny, allow, dismiss, tiers, and size_gate.max_lines are non-delegable by construction - they are absent from the contract and cannot be granted from a folder file.