Skip to content

release: promote main to prod — v0.8.0 (betterleaks migration + ClawHub auto-publish + agent init --dry-run)#99

Merged
Raftersecurity merged 18 commits into
prodfrom
main
May 11, 2026
Merged

release: promote main to prod — v0.8.0 (betterleaks migration + ClawHub auto-publish + agent init --dry-run)#99
Raftersecurity merged 18 commits into
prodfrom
main

Conversation

@Rome-1
Copy link
Copy Markdown
Collaborator

@Rome-1 Rome-1 commented May 10, 2026

Summary

Second main→prod cut since #92 (v0.7.9). 16 commits land the betterleaks scanner migration (the reason for the minor bump on a 0.x line — removes the --with-gitleaks / --engine gitleaks / update-gitleaks CLI surface), ClawHub auto-publish on every prod deploy, and rafter agent init --dry-run, plus three quality fixes.

Headline changes since #92

Bead / PR Description
rc-ksy / rc-963 (#93) Secret-scanning engine migrated from gitleaks → betterleaks v1.1.2 (the gitleaks successor maintained by the same authors). Same JSON shape; new binary, new subcommand (detect --no-git -sdir <path>), new release URL. Supply-chain hardening: pinned SHA256 hashes, symlink/hardlink/device entries rejected, https-only downloads, --version regex-validated, -- arg separator. Breaking: --with-gitleaks, --engine gitleaks, rafter agent update-gitleaks now hard-error. Soft landing: verify and status detect leftover ~/.rafter/bin/gitleaks and tell users to run rafter agent update-betterleaks.
rf-hrtd (#98) rafter agent init --dry-run — print every file path the command would create/modify/download without making any changes. Closes the rf-v85b P0-1 review concern.
PR #94 ClawHub auto-publish on prod deploypublish.yml runs clawhub skill publish after every prod-branch deploy. validate-release.yml enforces SKILL.md version: matches package version. OpenClaw users can install rafter via clawhub skill install rafter-security.
rc-dmp (874a86a) Purge user-facing scan local references — .pre-commit-hooks.yaml, fixtures README, dev skill copies, --from-local help, CLI_SPEC.md baseline example. Alias plumbing and tests retained for backward compat.

Quality fixes in this PR

  • rf-cfjc (941879f) — Test Composite Action's detect secrets in fixture job had been failing on every push since the betterleaks merge. The composite action's jq count query ([.[].matches[]] | length) errored on the wrapped JSON shape introduced in v0.7.7 (rf-0pch: {_note, scan_mode, triage_applied, results: [...]}) and silently fell through to "0". Scanner detection itself was working — pure jq parser bug. Now type-aware so version: pins to either old or new rafter still work.
  • fix(ci): use 'rafter' as the ClawHub owner handle #96 ClawHub owner handle — actual handle is rafter, not raftersecurity. Without this the first real ClawHub publish would have failed.
  • rf-z6sv (docs(rf-z6sv): bump README pre-commit rev pins to v0.7.9 #97) — README pre-commit rev: pins bumped from v0.7.1 → v0.7.9 (now stale-chasing v0.8.0 too, but that's the next bump).
  • rf-ax2p (292e0eb) — tests/e2e-cli.test.ts --help advertises secrets-only scope was matching /secrets only/i with a literal space; Commander wraps the description at 80 cols, splitting Secrets\nonly. Test had been red on every push since cbfe354. Fixed regex to /secrets\s+only/i.

CHANGELOG cleanup (in 07e1bd8)

The PR #93 octopus merge parked the betterleaks bullets under main's ### Changed heading inside the [0.7.9] section in CHANGELOG.md — but the published v0.7.9 (dc81574) was tagged BEFORE PR #93 merged, so npm @rafter-security/cli@0.7.9 and PyPI rafter-cli==0.7.9 actually ship gitleaks. The release-bump commit moves the betterleaks bullets back into the new [0.8.0] section where they belong.

Out of scope (filed for follow-up)

  • rf-lyj9 (P1, from release: promote main to prod — v0.7.9 (8-platform deep parity + suppression + GitHub Action @v1 fix) #92's release prep) — rafter skill install --platform openclaw still uses the pre-rf-zgwj flat path. Two install entrypoints write to different locations on the same platform.
  • rc-mw0node/.claude/skills/ has drifted ~2 weeks behind canonical node/resources/skills/; rc-dmp only patched the scan local lines.
  • publish.yml smoke-test-python flakiness — fired once on v0.7.9 because PyPI hadn't propagated ==0.7.9 ~30s after publish. Worth a pip install --retries 5 --timeout 60 or a 60s sleep before the smoke step.

Test plan

  • Validate Release green on 292e0eb (test fix) → 1735 passing / 1 skipped (was 1735 passing / 1 failing pre-rf-ax2p)
  • validate-versions confirms Node 0.8.0 == Python 0.8.0
  • Test Composite Action green on 941879f after rf-cfjc fix — fixture-with-AKIA detection now correctly reports finding-count=1
  • CHANGELOG [0.8.0] entry exists; [0.7.9] cleaned up to reflect what actually shipped at dc81574
  • CI on the merge commit re-confirms before publish.yml fires

Post-merge actions (will be done by jack)

  1. Tag v0.8.0 on the merge commit
  2. Fast-forward v1 to that tag (git push origin :v1; git tag v1 v0.8.0; git push origin v1)
  3. Watch publish.yml push to npm (@rafter-security/cli@0.8.0) and PyPI (rafter-cli==0.8.0)
  4. Watch the new ClawHub auto-publish step (first real run — would have failed without fix(ci): use 'rafter' as the ClawHub owner handle #96 handle fix)

🤖 Generated with Claude Code

Rome-1 and others added 18 commits May 7, 2026 01:41
Replace the secret-scanning binary in both Node and Python with betterleaks
(github.com/betterleaks/betterleaks v1.1.2), maintained by the gitleaks
authors. JSON report shape is unchanged, so the result-mapping logic survives;
the wire-up changes are CLI subcommand (`detect --no-git -s` → `dir <path>`),
release URL pattern, and checksum filename.

Internal renames:
- GitleaksScanner → BetterleaksScanner (node + python)
- BinaryManager.get/is/verify/find/download_gitleaks → *_betterleaks
- GITLEAKS_VERSION → BETTERLEAKS_VERSION
- update-gitleaks command → update-betterleaks (with deprecated alias)

User-facing back-compat:
- `--with-gitleaks` accepted as alias of `--with-betterleaks`
- `--engine gitleaks` accepted as alias of `--engine betterleaks`
- `agent update-gitleaks` accepted as hidden alias

Dropped the parenthetical in the `rafter secrets` help description so the
"Secrets only" phrase no longer wraps mid-line at typer's default width.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Update README, CLAUDE.md, SKILL.md, llms.txt, shared-docs/CLI_SPEC.md, recipes/*,
and the bundled python skill/agent resources to refer to Betterleaks (the
gitleaks successor) as the canonical name. Each occurrence of the legacy
flag/value/subcommand explicitly notes the back-compat alias so existing
docs/scripts/agents that still say `gitleaks` keep working.

Historical docs under docs/ (audits, code reviews, proposals, research) are
left as-is — they describe state at a point in time.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ning)

Functional fixes (4 reviewers reported):
- Node BetterleaksScanner now falls back to PATH-installed binary (Homebrew
  users were silently demoted to regex; Python already did this).
- agent verify/status soft-degrade when only legacy gitleaks is present —
  emit "run rafter agent update-betterleaks" hint instead of hard-failing.
- Update remaining user-facing surfaces: action.yml, .pre-commit-hooks.yaml,
  Dockerfile (was `--with-gitleaks 2>/dev/null || true`), python/README.md,
  .github/copilot-instructions.md.
- Python scanner now logs warnings on JSON/timeout errors (was silent FN).

Supply-chain hardening:
- Pin SHA256 hashes for the bundled BETTERLEAKS_VERSION (1.1.2) in source.
  Default install no longer trusts the release-page checksums.txt to
  authenticate itself; --version <other> still falls back to the upstream
  file (TOFU at install time).
- Reject symlink/hardlink/device tar entries on extract — without this,
  a malicious release could ship `betterleaks` as a symlink to e.g.
  ~/.ssh/authorized_keys, and the subsequent chmod +x would mode-flip the
  target. Same defense for zip extraction (Unix mode bits in external_attr).
  Post-extract lstat confirms the result is a regular file.
- Refuse non-https redirects (Node) and non-https final URLs (Python).
- Validate `--version` against /^[A-Za-z0-9._-]+$/ to neutralize URL
  injection attempts like `1.1.2/../evil`.
- Add `--` separator before user-supplied paths in betterleaks invocations
  so a path beginning with `-` isn't parsed as a flag.

Aligns Node scanFile timeout with scanDirectory (60s, matches Python).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Parity:
- Python BetterleaksScanner.getSeverity now inspects Tags (key+secret =>
  critical, api => high, generic => medium) — matches Node behavior; same
  rule could classify differently across runtimes before this.
- Tighten Node BetterleaksResult interface: git-history-only fields
  (Commit/Author/Email/Date/Message/Fingerprint) are absent on `dir` mode
  output, so mark them optional rather than lying about the contract.
- Python User-Agent now uses rafter-cli __version__ instead of accidentally
  reusing BETTERLEAKS_VERSION.

Tests for the legacy alias surface (no coverage before this — would have
silently regressed on the next refactor):
- node: --engine gitleaks (scan), --with-gitleaks (init), legacy gitleaks
  detection in agent status with the upgrade hint.
- python: --engine gitleaks (secrets), --with-gitleaks (agent init).
- python: tag-based severity (critical/high/medium) parametrized.
- python: new test_binary_manager.py covers --version validation
  (URL-injection guards), pinned-hash table completeness for the bundled
  BETTERLEAKS_VERSION, and non-https refusal in _download_file.
- node: matching --version validation tests in binary-manager.test.ts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The migration kept --with-gitleaks, --engine gitleaks, and the
update-gitleaks subcommand as silent aliases. Per product direction,
move off gitleaks entirely.

Removed (now hard-error):
- `rafter agent init --with-gitleaks`            → "unknown option"
- `rafter agent scan --engine gitleaks`          → "Invalid engine"
- `rafter agent baseline create --engine gitleaks` → same
- `rafter agent update-gitleaks` (hidden alias)  → "unknown command"
- `gitleaks` value in mcp `scan_secrets` enum    → schema rejection

Kept (read-only legacy detection):
- `rafter agent verify` and `rafter agent status` continue to probe for
  ~/.rafter/bin/gitleaks and gitleaks on PATH so users with leftover
  installs see "legacy gitleaks at X; run: rafter agent update-betterleaks"
  instead of a confusing "not found". This is the soft-degrade that
  prevents a verify hard-fail regression on upgrade.

Docs scrubbed of "legacy alias accepted" copy across README, CLAUDE.md,
llms.txt, shared-docs/CLI_SPEC.md, recipes/gemini-cli.md, and the
bundled python skill cli-reference. Tests flipped from "alias is
accepted" to "alias is rejected".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Audit run by 2 codex agents and 2 claude agents on the
betterleaks-migration branch (post-alias-removal). Fixes:

Bundled Node skill resources (P0, both reviewers flagged):
The npm-bundled docs at node/resources/** still said "Gitleaks" and
documented the removed `update-gitleaks` subcommand and `--with-gitleaks`
flag — a clean install would land docs that recommend commands the CLI
now hard-rejects. Mirrored the rename across:
- node/resources/skills/rafter/SKILL.md
- node/resources/skills/rafter/docs/cli-reference.md
- node/resources/agents/rafter.md
- node/resources/rafter-security-skill.md
- node/.claude/skills/rafter/docs/cli-reference.md (dev-side mirror)
- fixtures/vulnerable-repo/README.md (`--engine gitleaks` example)

Python silent-failure bug (P1, codex-functional flagged):
`_run_scan()` ignored the betterleaks subprocess return code, so any
non-zero exit other than 1 (panic, OOM, malformed args) returned []
and the scan looked clean. Mirrored Node's contract: 0=clean, 1=findings,
anything else => RuntimeError with stderr tail. Catches OSError on the
subprocess call too.

Windows .exe extension parity (P2, codex-functional flagged):
Several legacy-detection / status / init paths hardcoded the binary
name without `.exe`, so a managed `~/.rafter/bin/betterleaks.exe` (or
leftover `gitleaks.exe`) was missed on Windows.
- python/rafter_cli/commands/agent.py: agent init, _check_betterleaks,
  status output all now select binary name by sys.platform.
- node/src/commands/agent/status.ts: same — derive `.exe` once and reuse.

Test cleanup (P2, codex-functional flagged):
node/tests/mcp-server.test.ts handler mock kept the
`engineRaw === "gitleaks" ? "betterleaks" : engineRaw` normalization that
production no longer has — removed so the test reflects current behavior.

Copy polish (both reviewers flagged):
- recipes/pre-commit.md sentence "21+ patterns via Betterleaks" wrongly
  attributed all 21 patterns to betterleaks. Now: "21+ built-in
  credential patterns plus optional Betterleaks integration".
- shared-docs/SHOW_HN_DRAFT.md, drafts/show-hn/post.md, drafts/show-hn/faq.md
  marketing drafts updated to mention Betterleaks (kept gitleaks references
  where they're historical comparisons or the original FAQ question).

CHANGELOG entry:
Added an [Unreleased] entry for the full migration: scanner change, breaking
removal of legacy aliases, soft-degrade detection, supply-chain hardening,
and the alias-removal-as-breaking note.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Security hardening (Claude security reviewer flagged 3 real issues; Codex
security review confirmed the layered hardening is otherwise solid):

- Node download: add MAX_REDIRECTS=10 (was unbounded recursion on 30x
  loops), MAX_BYTES=200MB body cap with Content-Length precheck + per-chunk
  enforcement (was a 50GB-mirror DoS), and REQUEST_TIMEOUT_MS=60s socket
  timeout (was slow-loris hang). All in node/src/utils/binary-manager.ts
  downloadFile.
- Python download: matching MAX_BYTES=200MB body cap. Python already had
  urllib's internal redirect cap and timeout=60.

Simplicity (Claude simplicity reviewer):

- Extract findLegacyGitleaks() onto BinaryManager (Node) and
  find_legacy_gitleaks() onto BinaryManager (Python). Was duplicated 3x
  per runtime (verify + status + agent init); now one canonical
  implementation each side, used everywhere. Drops the duplicated
  Windows .exe extension handling and the homedir traversal.
- Inline _update_betterleaks_impl() back into update_betterleaks() —
  the wrapper existed for the (now-removed) update-gitleaks alias and
  was only called once.

Functional correctness (Codex functional reviewer ran the full test
suite, blew context before completing the manual matrix):

- Confirmed: 73/73 node + 164/164 python tests pass.
- Confirmed live: aliases hard-error correctly (--with-gitleaks,
  --engine gitleaks, update-gitleaks), legacy detection emits the
  upgrade hint identically across both runtimes, real download still
  works end-to-end after the hardening additions.

Items deferred (low value or trade-off):
- Re-verify on-disk binary hash before each scan (TOFU drift) — local
  malware threat outside our model.
- Race on parallel agent init writing to same archive path — local DoS
  only, no security boundary.
- Switch Node verify_betterleaks_verbose from execAsync (shell quoted)
  to execFile (argv) — fragile but trusted inputs only.
- Drop post-extract lstat from Python tarball extract — kept for
  parity with Node where node-tar's filter typing is loose.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a publish-clawhub job to .github/workflows/publish.yml that
publishes the rafter-security SKILL.md to https://clawhub.ai (the
OpenClaw skill registry) after every prod-branch release. OpenClaw
users can then install rafter via `clawhub skill install rafter-security`
as an alternative to `rafter agent init --with-openclaw`.

Workflow design:
- Runs after publish-node so we have the canonical version output.
- Stages node/resources/rafter-security-skill.md as
  /tmp/rafter-skill/rafter-security/SKILL.md (clawhub expects a
  directory containing SKILL.md).
- Authenticates via CLAWHUB_TOKEN env var (stateless — no
  `clawhub login` persisting to disk).
- Runs `clawhub skill publish ... --version <package-version>
  --owner raftersecurity`. Idempotent: same version+fingerprint → no-op;
  same version, changed content → fail loudly.
- Verifies the publish landed via `clawhub skill show rafter-security`.

Guards:
- Skips when CLAWHUB_TOKEN secret isn't configured (forks).
- Gated on `github.repository == 'Raftersecurity/rafter-cli'` so
  pushes to forks of prod don't unexpectedly try to publish.

Version-sync enforcement (validate-release.yml):
- Adds a pre-deploy check that `version:` in both Node and Python
  copies of rafter-security-skill.md matches the package version.
  Without this, a release could silently ship a stale ClawHub version
  if the maintainer forgot to bump the SKILL.md frontmatter.

Recipe + release notes:
- recipes/openclaw.md now documents both install paths
  (rafter CLI and `clawhub skill install`) with a note about the
  `requires.bins: [rafter]` gate (the rafter CLI must still be on
  PATH regardless of which install path users take).
- The GitHub-release notes block in publish.yml now includes the
  `clawhub skill install rafter-security` install line.

Pre-flight notes for first run:
- The CLAWHUB_TOKEN secret needs to be configured on the repo before
  the next prod push. Until then the job logs a skip message; no
  release fails.
- The `raftersecurity` ClawHub org handle must exist (or `--owner`
  needs adjusting). First run will surface either issue clearly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…y') (#96)

The actual handle on clawhub.ai is `rafter`. Without this, the first
real publish would have failed with an "owner not found" error.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Both pre-commit examples in README.md (lines 246 and 433) pinned
rafter-cli at v0.7.1. Repo is at v0.7.9 since the rf-zfhj GitHub Action
fix shipped. Stale pins make new adopters fall back to old behavior
(missing the GA fix, the OpenClaw ClawHub-shape fix, the audit-log
hash-chain hardening, etc.).

Bumped both to v0.7.9 to match the latest published tag.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
… changes (#98)

Closes the rf-v85b P0-1 review concern: `rafter agent init --all` edits
up to 8 tools' global config files plus downloads betterleaks. Adds a
`--dry-run` flag that prints every file path the command would create,
modify, or download — without making any changes.

Node + Python both ship a `printDryRunPlan` / `_print_dry_run_plan`
helper. After detection + opt-in resolution (so the plan respects --all,
--with-*, --local, and presence detection), the helper iterates the
resolved want_* booleans and prints:
- Always: ~/.rafter/config.json + bin/patterns dirs.
- Per platform when enabled: header + WRITE lines with file path and
  short note (e.g. "PreToolUse + PostToolUse hooks merged",
  "rafter:start/end marker block", "shared with Codex").
- Betterleaks: DOWNLOAD line for the binary.
- OpenClaw: WRITE for the new ClawHub-shaped SKILL.md, plus REMOVE for
  the legacy ~/.openclaw/skills/rafter-security.md (rf-zgwj migration).

The plan is built from the same resolved booleans the install path
uses, so listing matches what would actually run. The dry-run branch
runs early in the action — before manager.initialize(), before any
fs.write — so even ~/.rafter/config.json is NOT created in dry-run mode.

Tests:
- 3 Node tests in agent-commands.test.ts: writes no files, lists all 8
  sections, betterleaks download line. Asserts ~/.rafter/config.json
  does NOT land.
- 3 Python tests in TestDryRun: same coverage. All green.
- Live smoke (Node + Python): --local --all --dry-run produces 39 WRITE
  lines, 0 DOWNLOADs, leaves cwd untouched.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
rafter ≥0.7.0 (since rf-0pch, 2026-04-27) wraps scan results as
{_note, scan_mode, triage_applied, results: [...]} instead of a bare
array. The composite action's count query [.[].matches[]] errored on
the new shape and silently fell through to "0", causing the Test
Composite Action 'detect secrets in fixture' job to fail with
"expected findings > 0, got 0" — even though the scanner correctly
detected the AKIA fixture.

Use a type-aware query that handles both the wrapped object (current)
and the bare array (older pinned versions).

Verified against both shapes locally; CI run #25598398886 log shows
the scanner already emits the correct match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Surfaces the bead asked for were mostly already migrated. This pass mops up:

- .pre-commit-hooks.yaml: 3 hook entries (rafter-scan, -node, -python)
- fixtures/vulnerable-repo/README.md: demo commands
- node/.claude/skills/* (stale dev copies): 9 SKILL.md / docs refs
- node/src/commands/issues/from-scan.ts: --from-local help text
- shared-docs/CLI_SPEC.md: baseline subcommand example

Intentionally LEFT (alias plumbing, history, or test surfaces): tests
exercising the alias, CHANGELOG/drafts/proposals, CLI_SPEC.md alias-
documentation lines, internal source comments describing the alias
mechanism, .github CI test that exercises the alias path.

Subcommand was already hidden in Commander + Typer; alias still works.

Discovered separate issue (filed as rc-mw0): node/.claude/skills/ has
drifted ~2 weeks behind canonical node/resources/skills/. This pass only
patches the 'scan local' lines — broader sync left to that bead.

Also closes rc-hzf and dup rc-49q (Cut SessionStart hook): verified
already done — no session-start command in Node or Python; init paths
only install PreToolUse + PostToolUse. Remaining SessionStart code in
components.ts / agent.py is migration cleanup that strips legacy entries
from <=0.7.4 user installs and must stay.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Minor bump (not patch) because the betterleaks migration removed
user-facing CLI surface — `--with-gitleaks`, `--engine gitleaks`, and
`rafter agent update-gitleaks` now hard-error. On a 0.x line, removing
documented CLI flags is the textbook MINOR trigger; burying it in a
patch would mislead anyone scripting against those flags.

Bumps:
- node/package.json: 0.7.9 → 0.8.0
- python/pyproject.toml: 0.7.9 → 0.8.0
- node/resources/rafter-security-skill.md: 0.7.9 → 0.8.0  (ClawHub publish)
- python/rafter_cli/resources/rafter-security-skill.md: 0.7.9 → 0.8.0
- recipes/openclaw.md example frontmatter: 0.7.9 → 0.8.0

CHANGELOG cleanup:
- Move betterleaks bullets from [0.7.9] (where the PR #93 octopus merge
  parked them under main's `### Changed` heading) into the new [0.8.0]
  section. The published v0.7.9 (dc81574) does not contain betterleaks
  code; npm/PyPI 0.7.9 still ships gitleaks.
- New [0.8.0] groups all unreleased bullets (rf-hrtd dry-run, ClawHub
  auto-publish) and adds three Fixed entries: rf-cfjc (action.yml jq
  parser, fixed in 941879f), #96 (ClawHub owner handle), rf-z6sv (#97,
  pre-commit rev pin bump).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tests/e2e-cli.test.ts asserted /secrets only/i (literal space) against
the rafter secrets --help output. Commander wraps the description at
terminal width (CI default 80 cols), splitting 'Secrets\nonly' across
a newline. The literal-space regex didn't match; the test had been red
on every push since the betterleaks merge (cbfe354). Allow any
whitespace between the words.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…skills/

The dev copies at node/.claude/skills/ were ~2 weeks stale vs the shipped
source-of-truth at node/resources/skills/. One commit (cdac956, 2026-04-26,
v0.7.6 publish prep) rewrote SKILL.md framing and added rafter-skill-review
in resources/ but never mirrored to .claude/. Today's purge (rc-dmp) patched
the 'scan local' strings; this commit removes the duplicate tree entirely so
the next 'forgot to mirror' can't happen.

Root .gitignore already lists .claude/, so the deletion sticks naturally.

Contributor workflow for dogfooding (documented in CONTRIBUTING.md):
  cd node && pnpm run build
  node dist/index.js agent init --with-claude-code --local
This invokes our own published install path, populating node/.claude/skills/
from node/resources/skills/ on demand. Eats own dog food; no second tree to
keep in sync.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…est suite

Three fixes that unblock PR #99's red comprehensive-test-suite jobs and
finish the rc-dmp 'scan local' → 'secrets' rename in test surfaces.

1. **test-comprehensive Verify build** (test-node + 6 cross-platform jobs):
   `node -e "import('./dist/index.js')..."` triggers `program.parse()`
   synchronously at module load. With no args, Commander 11 on Node 20
   prints help and exits 1 before the `.then(() => 'Build OK')` runs.
   Pre-existing failure since 2026-04-26. Replaced with
   `node ./dist/index.js --version` — exercises the same build, exits 0
   cleanly through a real Commander action.

2. **python test_suppresses_all_patterns_when_no_pattern_name**: test used
   `path_glob="node_modules/*"` and asserted it matches
   `"node_modules/pkg/index.js"`. The `*` glob doesn't cross `/` per
   standard glob semantics — the Node sister test in
   custom-patterns.test.ts uses `"node_modules/**"`. Implementation is
   correct; bumped the test to match Node.

3. **scan local → secrets in tests**: rc-dmp purged user-facing `scan
   local` references in product/docs but intentionally left tests
   exercising the alias. This pass migrates the scanner test calls to
   the canonical `secrets` command across:
     - node/tests/{e2e-cli,secret-scanning-e2e,cross-runtime-parity,
       formatter-commands,baseline}.test.ts
     - python/tests/{test_e2e_cli,test_agent_scan_history}.py
   The alias still works at runtime; coverage of the alias is
   consolidated into a dedicated back-compat block in each e2e file
   (`CLI e2e — \`scan local\` back-compat alias` / `TestScanLocalAliasBackCompat`)
   that pins three things: identical-output equivalence, routing, no
   deprecation warning. If `scan local` is ever formally removed,
   delete those blocks in the same commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Raftersecurity Raftersecurity merged commit cd6b378 into prod May 11, 2026
14 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants