Skip to content

fix(build): exclude internal docs/superpowers and docs/plans from wheels-core artifact - #3186

Closed
wheels-bot[bot] wants to merge 1 commit into
developfrom
fix/bot-3179-forgebox-wheels-core-artifact-ships-internal-docs
Closed

fix(build): exclude internal docs/superpowers and docs/plans from wheels-core artifact#3186
wheels-bot[bot] wants to merge 1 commit into
developfrom
fix/bot-3179-forgebox-wheels-core-artifact-ships-internal-docs

Conversation

@wheels-bot

@wheels-bot wheels-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

The published wheels-core ForgeBox artifact shipped internal AI planning documents into every app's vendor/wheels/docs/. tools/build/scripts/prepare-core.sh did an unfiltered cp -r docs/*, sweeping docs/superpowers/ (planning specs, draft PR.md/ISSUE.md files, .patch artifacts) and docs/plans/ into the package — 75 internal files in the 4.0.3 zip. These are working documents, not user documentation. This PR removes both internal trees from the build dir immediately after the docs copy and pins the contract with a structural guard spec so the exposure cannot reappear.

Related Issue

Fixes #3179

Type of Change

  • Bug fix

What changed

  • tools/build/scripts/prepare-core.sh — after cp -r docs/* "${BUILD_DIR}/wheels/docs/", add rm -rf "${BUILD_DIR}/wheels/docs/superpowers" "${BUILD_DIR}/wheels/docs/plans".
  • vendor/wheels/tests/specs/security/PackageDocsHygieneSpec.cfc — structural source-scan guard (mirrors the existing buildArtifactLicenseSpec.cfc pattern) asserting that any prepare script which copies the full docs tree also excludes the internal trees. The three sibling scripts (prepare-base.sh, prepare-cli.sh, prepare-starterApp.sh) do not copy docs/* today, so they pass vacuously — the guard covers them so a copy-paste can't reintroduce the leak.
  • changelog.d/3179-core-package-internal-docs.fixed.md — changelog fragment.

TDD: failing → passing

The spec is a pure source-scan, so the fail→pass transition was validated deterministically by running its exact regex logic against the script before and after the fix:

  • Before (unfixed prepare-core.sh): cp -r docs/* present (line 39), no rm -rf … docs/superpowers and no rm -rf … docs/plans → the two prepare-core assertions fail.
  • After (line 46 adds the exclusion): both rm -rf … docs/{superpowers,plans} present → prepare-core passes; siblings short-circuit (no docs/* copy) → pass.

Note: the live CFML runner (bash tools/test-local.sh security) could not execute in this sandbox — the wheels CLI is not installed here (only Java 21). The spec follows the established buildArtifactLicenseSpec.cfc source-scan precedent exactly for cross-engine-safe syntax; a human/CI run on a full toolchain will exercise it.

Feature Completeness Checklist

  • DCO sign-off -- commit carries Signed-off-by:
  • Tests -- PackageDocsHygieneSpec.cfc, failing-then-passing (validated via the spec's regex logic; see above)
  • Framework Docs -- handled separately by bot-update-docs.yml
  • AI Reference Docs -- handled separately by bot-update-docs.yml
  • CLAUDE.md -- handled separately by bot-update-docs.yml
  • Changelog fragment -- changelog.d/3179-core-package-internal-docs.fixed.md
  • Test runner passes -- spec logic verified; full runner unavailable in this sandbox (no wheels CLI)

Test Plan

  1. bash tools/test-local.sh security (or full suite) — PackageDocsHygieneSpec passes on the fixed script.
  2. Optional defense-in-depth follow-up suggested by the issue: add a guard to release.yml's "Validate Package Structure" step that fails if docs/superpowers appears in any build dir. Left out here to keep scope tight; tracked as a follow-up.

…els-core artifact

The wheels-core ForgeBox artifact shipped internal AI planning documents
(specs, draft PR.md/ISSUE.md files, patches under docs/superpowers/, plus
docs/plans/) into every app's vendor/wheels/docs/ because prepare-core.sh
did an unfiltered cp -r docs/*. Remove the internal trees from the build
dir after the copy, and pin the contract with a structural guard spec.

Fixes #3179

Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
@wheels-bot

wheels-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Wheels Bot — No doc updates

Reviewed this PR's diff and found no docs that need updating (purely internal build tooling fix — removes docs/superpowers/ and docs/plans/ from the ForgeBox artifact and pins the contract with a source-scan guard spec; no user-visible behavior, public API, CLI commands, or framework conventions changed).

@wheels-bot wheels-bot Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wheels Bot — Reviewer

TL;DR: This PR stops the wheels-core ForgeBox artifact from shipping the internal docs/superpowers/ and docs/plans/ trees by deleting them from the build dir right after the cp -r docs/* in tools/build/scripts/prepare-core.sh, and pins the contract with a structural source-scan spec. The fix is correct and verified: I confirmed both internal trees exist in docs/, that prepare-core.sh:39 is the only cp -r docs/* site across the four prepare scripts, and that the new exclusion at prepare-core.sh:46 satisfies both of the spec's regexes (I replicated the spec's exact regex logic against all four scripts — prepare-core matches the copy gate and both exclusions; the three siblings correctly short-circuit). Every spec idiom has CI-passing prior art: the IIFE loop-capture, expandPath("/wheels/../.."), and [[:space:]] regexes mirror vendor/wheels/tests/specs/buildArtifactLicenseSpec.cfc:22-59 line-for-line, and [^\n]* inside reFindNoCase matches BotResolveConflictsLoopSafeSpec.cfc:62. Commit conforms to commitlint (fix(build), subject 87 chars, DCO sign-off present); the changelog fragment is in the right place with a valid type. Verdict: comment — no blocking findings, two non-blocking robustness nits on the guard spec below.

Tests

  1. vendor/wheels/tests/specs/security/PackageDocsHygieneSpec.cfc:57-62 — the guard asserts presence of the exclusion, not its position relative to the copy.

    var excludesTree = reFindNoCase(
        "rm[[:space:]]+-rf[^\n]*docs/" & tree,
        src
    ) > 0;

    A future refactor that moves the rm -rf above the cp -r docs/* (where it becomes a no-op against a not-yet-populated build dir) would still pass this guard while re-shipping the leak. Since reFindNoCase returns a position, the check can pin ordering for free:

    var copyPos = reFindNoCase("cp[[:space:]]+-r[[:space:]]+docs/\*", src);
    var rmPos = reFindNoCase("rm[[:space:]]+-rf[^\n]*docs/" & tree, src);
    expect(rmPos > copyPos).toBeTrue(...);

    Non-blocking — the precedent spec (buildArtifactLicenseSpec.cfc) is also presence-only, but there ordering doesn't matter, whereas here it does.

  2. PackageDocsHygieneSpec.cfc:50-53 — the copy-detection gate is narrow, and a non-match passes silently.

    var copiesDocs = reFindNoCase(
        "cp[[:space:]]+-r[[:space:]]+docs/\*",
        src
    ) > 0;

    Variants like cp -rf docs/*, cp -a docs/*, or rsync -a docs/ wouldn't match the gate, so a script using one of them would take the vacuous-pass branch while still shipping the internal trees. Broadening the flag match (e.g. cp[[:space:]]+-[a-z]*r[a-z]*[[:space:]]+docs/) would close the most likely drift. Non-blocking — structural guards are inherently approximate and this pins the canonical form, but unlike the LICENSE precedent (where a non-match fails the assertion), here a non-match silently passes, so the gate's narrowness is the guard's weakest point.

Everything else checked out: the spec is BDD wheels.WheelsTest (not RocketUnit), ## is correctly escaped in string literals, there is no inline-closure-as-constructor-arg, no reserved-scope parameter names, and the PR body honestly discloses that the live CFML runner wasn't executed in the author sandbox (the regex logic was independently re-verified here against the actual scripts).

@bpamiri

bpamiri commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #3194 (merged): a propose-fix draft that raced the ForgeBox path-repair campaign for the same issue; the campaign PR landed first and closed the underlying issue. Closing the duplicate.

@bpamiri bpamiri closed this Jun 13, 2026
@bpamiri
bpamiri deleted the fix/bot-3179-forgebox-wheels-core-artifact-ships-internal-docs branch June 13, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ForgeBox wheels-core artifact ships internal docs/superpowers planning files (specs, PR drafts, patches)

1 participant