fix: three more measured false positives, all reported the same day v0.1.2 shipped
- extractChangelogTop truncated PEP 440 pre-release versions (0.5.0a2 -> 0.5.0), so VERSION-CHANGELOG disagreed with VERSION-TAG over a version everything already agreed on. Reported by llm-ingestion-okf with a repro. - BADGE-STATIC-CLAIM treated a bare `status` badge as a run claim, same as tests/build/CI. A self-declared maturity label asserts no run, same class as version/licence/platform. Reported by llm-ingestion-pipeline-security. - BOILERPLATE flagged FIXME when a scanner's own docs named the TODO/FIXME convention rather than an instance of it. Reported by config-audit. 92 tests green, up from 86. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uwwfdmrfnp7FuGQ4z25RKH
This commit is contained in:
parent
3c2a535297
commit
5eba10acdd
7 changed files with 110 additions and 7 deletions
|
|
@ -427,7 +427,12 @@ export function checkVersionConsistency({ pluginVersion, readmeBadge, changelogT
|
|||
|
||||
// A static image asserting "tests: 642 passing" is a claim dressed as evidence.
|
||||
// Version, licence and platform badges assert no run, so they are fine static.
|
||||
const CLAIM_BADGE = /(tests?|build|ci|coverage|passing|status)/i;
|
||||
// Bare `status` used to be in this list and caught a self-declared maturity
|
||||
// badge ("status: alpha") as if it were a run claim — reported by
|
||||
// llm-ingestion-pipeline-security. `build`/`ci`/`passing` already catch the
|
||||
// run-asserting compounds ("build status", "CI status"), so dropping the bare
|
||||
// word loses no real detection.
|
||||
const CLAIM_BADGE = /(tests?|build|ci|coverage|passing)/i;
|
||||
|
||||
export function checkBadges({ readme }) {
|
||||
const findings = [];
|
||||
|
|
@ -453,6 +458,7 @@ export function checkBadges({ readme }) {
|
|||
|
||||
// Template text that was never filled in. A visible unfinished template costs
|
||||
// more trust than the missing document would have.
|
||||
const FIXME_RE = /FIXME/;
|
||||
const BOILERPLATE = [
|
||||
/your-project-name/i,
|
||||
/\byour-org\b/i,
|
||||
|
|
@ -460,16 +466,24 @@ const BOILERPLATE = [
|
|||
/<your[- ][a-z]+>/i,
|
||||
/TODO:\s*(fill|replace|update)/i,
|
||||
/example@example\.(com|org)/i,
|
||||
/FIXME/,
|
||||
FIXME_RE,
|
||||
];
|
||||
|
||||
// "TODO/FIXME" named together names the convention, not a live instance of
|
||||
// one — reported by config-audit: a scanner whose job is finding these
|
||||
// markers names its own detection target in its own docs, unquoted. A lone
|
||||
// FIXME is still caught; only the paired reference is exempt.
|
||||
const NAMES_THE_CONVENTION = /\bTODO\s*\/\s*FIXME\b|\bFIXME\s*\/\s*TODO\b/i;
|
||||
|
||||
export function checkBoilerplate({ files }) {
|
||||
const findings = [];
|
||||
for (const [path, text] of Object.entries(files ?? {})) {
|
||||
// Same discipline as the link check: code spans and fenced blocks are where
|
||||
// a document ABOUT placeholders keeps its examples.
|
||||
stripCode(text).split('\n').forEach((line, i) => {
|
||||
const namesTheConvention = NAMES_THE_CONVENTION.test(line);
|
||||
for (const re of BOILERPLATE) {
|
||||
if (re === FIXME_RE && namesTheConvention) continue;
|
||||
if (re.test(line)) {
|
||||
findings.push({
|
||||
level: 'WARN',
|
||||
|
|
@ -788,7 +802,13 @@ export function extractBadgeVersion(readmeText) {
|
|||
// design — it is not a claim that anything shipped.
|
||||
export function extractChangelogTop(changelogText) {
|
||||
for (const line of String(changelogText || '').split('\n')) {
|
||||
const m = /^##\s*\[?v?(\d+\.\d+\.\d+)\]?/.exec(line.trim());
|
||||
// The suffix class stops at `]`, whitespace or end of string, so a
|
||||
// pre-release token (PEP 440 `a2`, semver `-beta.1`) is kept without
|
||||
// reaching into a trailing `] — DATE`. Reported by llm-ingestion-okf:
|
||||
// truncating this to X.Y.Z made VERSION-CHANGELOG disagree with
|
||||
// VERSION-TAG, which compares the untruncated tag and does not have
|
||||
// this problem — a repo on a pre-release could never reach 0 ERROR.
|
||||
const m = /^##\s*\[?v?(\d+\.\d+\.\d+[0-9A-Za-z.+-]*)\]?/.exec(line.trim());
|
||||
if (m) return m[1];
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue