Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLIPublic
Assigneesskunk-ape

Relationships

↔ sibling #3020

#3021 extension push: declare accepted lint warnings where the finding is (inline swamp-review-ignore comments, a sidecar review file beside the manifest), reported in quality, push and the registry

Opened by skunk-ape · 10/5/2026· Shipped 10/6/2026

Status

Rewritten 2026-10-06 to the design Seth settled on 2026-10-05 (see the ripples below for the history). The first version proposed a manifest-only suppression list. Withdrawn: most manifests are regenerated and would clobber hand edits, and a run-time flag (#3015, reverted by #3047) proved to be the wrong place for a standing decision.

Problem

The push-time review and safety checks are explicit lints: schema-strictness, testing-completeness, credentials-sensitive-field, bare-specifiers, the Deno.Command substring, base64 runs, long lines, IPv4 literals. When one fires on something the author has judged acceptable, there is no way to say so where the finding is. The only recourse is --yes, which waives every warning in the run and records nothing about why. Across 42 dry-runs in the assessment: 262 testing-completeness warnings on generated models, 18 Deno.Command hits in comments and strings, 18 long-line and base64 hits on embedded assets. Authors learn to read past warnings, and the one that matters is missed.

Design

Acceptances live where the finding is, as lint ignores do, and are reviewed in the pull request with the code. Push writes nothing.

Site-scoped rules (credentials-sensitive-field, schema-strictness, Deno.Command, base64, long line, IPv4): an inline comment on the line, scoped to that identifier or match, with a required reason:

// swamp-review-ignore credentials-sensitive-field: reference to a Secret, not a secret

A new field elsewhere still warns. The rule's own suppression marker (.meta({ sensitive) stays.

Extension-scoped findings (bare-specifiers; a package-level generated declaration): a sidecar file beside the manifest (working name review.yaml), discovered by quality and push by location or named from the manifest, packaged into the archive like the README so the registry sees it. It survives manifest regeneration.

testing-completeness folds into those two: a header comment on a model file that is deliberately untested, or the generated declaration for a codegen package (the shape of that declaration is agreed with #3020 and #3065, not decided here).

Not acceptable by any means: error-level findings (file type, hidden file, symlink, size caps, dynamic code, deprecated npm, HIGH/CRITICAL OSV, fmt, lint, upgrade chain). The adversarial-review family is evidence, not a lint, and is handled by #3023/#3064/#3065.

Reporting. quality and push --dry-run --json print the exact comment or sidecar entry to paste for each unaccepted finding (as the review skeleton is printed today). Accepted findings are listed with their reasons in quality, in the push summary and --json, and travel in contentMetadata so the registry page can show what the author acknowledged. An acceptance that matches nothing is itself a warning, so they do not accumulate.

Flags. --yes keeps waiving unaccepted warnings for the run (per #3047) and the acceptedWarnings record keeps listing them. Whether --yes is ever tightened is decided after this lands, with a deprecation window.

Acceptance

  • A swamp-review-ignore credentials-sensitive-field: <reason> comment on secretName: z.string() silences that line; an unmarked apiKey: z.string() in another file still warns; the acceptance appears in the quality and push summaries with its reason.
  • A review.yaml beside a generated manifest declaring generated silences testing-completeness for the package and survives deno task generate:<provider>.
  • An ignore comment with no reason is a lint error. An ignore for an error-level rule is a lint error. An ignore that matches nothing warns.
  • push --dry-run --json output carries the acceptances; the registry listing shows them (contentMetadata).

#3015/#3047 (flag semantics), #3020 (generated declaration), #3023/#3064/#3065 (adversarial-review evidence), #2965 (Deno.Command substring), #3019 (sensitive-field whole identifiers, shipped).

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 6 MOREREVIEW+ 29 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/6/2026, 8:35:22 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
skunk-ape assigned skunk-ape10/6/2026, 6:13:19 PM
skunk-ape linked sibling of #302010/6/2026, 6:37:23 PM
Editable. Press Enter to edit.

skunk-ape commented 10/5/2026, 2:34:56 PM

Guardrail: only warning-level rules are suppressible; error-level (safety, dependency-trust HIGH/CRITICAL, dynamic-code, file-type, size) never are. Every suppression carries a reason and is printed in the summary, carried in --json, and should travel in the archive or contentMetadata so the registry and scorecard can show what was waived. Suppression makes a waiver visible, it does not make the rule go away.

skunk-ape commented 10/5/2026, 9:59:58 PM

Redesign (Seth, 2026-10-05), replacing the manifest-only proposal above: acceptances live where the finding is, like lint ignores. Site-scoped rules (credentials-sensitive-field, schema-strictness, Deno.Command, base64, long line, IPv4) take an inline comment on the line, e.g. // swamp-review-ignore credentials-sensitive-field: , scoped to that identifier. Extension-scoped findings (bare-specifiers, the adversarial-review family) and a package-level generated declaration go in a sidecar file beside the manifest (working name review.yaml) that is packaged into the archive, because most manifests are regenerated and would clobber hand edits. testing-completeness folds into those two: a header comment on a deliberately untested model file, or the generated declaration for a codegen package. Push writes nothing: quality and push --dry-run --json print the exact comment or entry to paste for each unaccepted finding. Acceptances are reported in quality, in the push summary and JSON, and travel in contentMetadata so the registry can show them. Error-level findings have no ignore form. A stale ignore that matches nothing is itself a warning. The run-time flag question (#3047) is decided after this lands, with a deprecation window if --yes is ever tightened.

skunk-ape commented 10/5/2026, 10:12:06 PM

Dependency note: the adversarial-review family of findings is handled by #3023's attestation design, not by a declared acceptance. Declared acceptances here cover the lint-style rules (site-scoped comments, sidecar file for bare-specifiers and the generated declaration).

skunk-ape commented 10/6/2026, 6:15:26 PM

Addition (Seth and Paul, 2026-10-06): after a successful publish, and after a dry run, the summary reports the waived warnings as advice: a 'For next time' section with, per finding, how to fix it properly and, if the finding is not correct for this extension, the exact acceptance to paste (the inline comment or sidecar entry). Same in --json as a structured field beside acceptedWarnings. Each warning-level rule gains a short remediation text, in the shape the quality rubric's factors already use. Declared acceptances are listed separately and briefly, so the report shrinks as acceptances accumulate. Open design question, to be answered by the implementing session: whether the pre-publish warnings prompt stays for interactive runs (current view: yes, for a person at a terminal) with the report as the primary channel for non-interactive runs.

Sign in to post a ripple.