Relationships
#3065 extension push: accept attestation-backed adversarial-review evidence (lookup by extension and content hash), generated provenance, and carry the evidence to the registry at confirm (design: Lab #3023)
Opened by skunk-ape · 10/6/2026
Problem
The adversarial-review-report rule checks for a file at a content-hash-named path and nothing else. The registry confirm payload carries no review data, so the review gate is author-asserted (push assessment finding S9), and a generated package can never satisfy the rule honestly because no one reviews 54 generated models per push. swamp-extensions is adding a verify-reviews step whose per-extension report rides in the commit-bound attestation (see the swamp-extensions issue filed beside this one); the short-term adapter writes that report into SWAMP_EXTENSION_REVIEW_DIR and needs no swamp change, but the push summary cannot tell an attestation-written report from a hand-written one. Design and facts are recorded on Lab #3023.
Change
- src/domain/extensions/extension_review_rules.ts: ExtensionReviewReportSchema gains an optional provenance object: {kind: author | attestation | generated, commit?, attestationId?, reviewedCommit?, generatedBy?: {codegen, commit}}. Reports without it parse as today (kind author). evaluateReviewReport gains two branches: kind attestation is accepted when the lookup below confirms the attestation carries this extension and contentHash with no pending verdicts; kind generated is accepted when the manifest's generated declaration names the same generator and commit and an attestation for that commit carried an adversarial review over the generator's path, producing an informational line instead of the warning. A distinct ruleId (adversarial-review-provenance) covers "evidence present but unverifiable or mismatched" so it is never confused with "missing review".
- src/libswamp/extensions/push.ts and the extension API client: an optional evidence lookup by extension name and content hash (hash convention repo dir = extension dir, stated in the request) against swamp-club, used when no local report exists or when the local report's provenance says attestation. Dry run keeps today's file-only behaviour unless credentials are present.
- ConfirmPushMetadata gains an optional top-level reviewEvidence field (attestation id, commit, content hash, or the generated declaration) so the registry can verify it server-side at confirm; the registry rejects or flags a confirm whose evidence does not match what swamp-club holds. This is the step that turns the gate from author-asserted to server-verified.
- src/presentation/renderers/extension_push.ts: dry-run and completed summaries render the review source (author, attestation, generated) in log and JSON; acceptedWarnings keeps listing a waived review warning.
- Manifest: the generated declaration proposed on Lab #3023 (generated: {by, source, commit}) is added to the manifest schema and to serializeManifestForHash so a changed declaration moves the content hash. Its shape must be agreed with #3020 (testing-completeness) and #3021 (declared acceptances); this issue depends on that agreement and does not decide it alone.
- swamp-club: index attestations by the extensionReviews entries (extension name, content hash) and serve the matching report; GET by commit stays. Body cap 256 KiB is sufficient for per-extension reports.
- Docs: the swamp skill's adversarial-review reference and the Adversarial Review Gate section, design/primitives/extensions.md (Adversarial Review Directory); tests in extension_review_rules_test.ts, push_test.ts, extension_push_test.ts, renderers/extension_push_test.ts.
Acceptance
- push --dry-run --json on an extension whose attestation carries a matching report (same name, version, content hash) emits no adversarial-review-report warning and the summary says source attestation.
- The same with a stale hash emits the warning, and the summary says why the evidence did not match.
- A package with a generated declaration whose generator commit has an attestation with a passed adversarial review emits an informational line, not a warning; without such an attestation it emits adversarial-review-provenance.
- The confirm payload carries reviewEvidence and the registry refuses a confirm whose evidence swamp-club cannot verify.
- Existing hand-written reports with no provenance keep working unchanged.
Side findings from the same investigation (separate, Seth's call)
- The report content hash is layout-bound: files are labelled relative to the swamp repo dir (extension_push.ts sets rootDir to repoDir), so the same extension hashes differently from different layouts. Either document the convention or hash relative to the manifest dir, which moves every cache key and report path.
- push --dry-run --json does not expose the content hash or report path as a field; consumers parse the finding's file name, and when a report already exists neither appears at all.
Out of scope
The swamp-extensions step itself; backing out or re-tightening --yes (#3047); declared acceptances for lint-style rules (#3021) beyond agreeing the generated field.
Open
No activity in this phase yet.
reset commented 10/23/2026, 5:23:27 PM
A smaller request that fits the lookup redesign here: let the report live beside the code by default. Today reviewBaseDir() is SWAMP_EXTENSION_REVIEW_DIR, then TMPDIR/TMP/TEMP, then /tmp, so without the environment variable the report that documents the review is outside the repository: not in the pull request, not in history, and absent on a second machine, which then prints No adversarial review recorded for the current code for code that was reviewed. Setting the variable works (#596), but it has to be set identically on every machine and in CI, and nothing in the push output says so when the report is missing.
Proposal: when SWAMP_EXTENSION_REVIEW_DIR is unset, look first for the content-hash-named report in a fixed directory under the extension (for example reviews/ beside manifest.yaml, packaged like quality.yaml or excluded from the archive, whichever the attestation design prefers), and fall back to the temp directory only when it is absent. The missing-report finding could name both paths. That keeps the hash binding from #3100 and the attestation lookup proposed here, and makes the committed layout the default rather than a per-machine setting.
Sign in to post a ripple.