--- name: bundle-safety description: Bundle transform safety — minification variant selection, consumer-constraint verification, identifier preservation, and namespace re-export coverage for build output. triggers: - minify - minification - bundle - esbuild - build size - re-export - identifier - namespace re-export - exportLines - exportRanges - dist/index.js generated_from_knowledge: - 5746c5c9-1330-4fbe-b62e-f564deb1ff77 - 5d99affe-bdd1-4945-8cd8-fcf37abb8c84 - 9323a8f0-c07e-41c2-9857-11a24c55dca2 source_knowledge_ids: - 5746c5c9-1330-4fbe-b62e-f564deb1ff77 - 5d99affe-bdd1-4945-8cd8-fcf37abb8c84 - 9323a8f0-c07e-41c2-9857-11a24c55dca2 generated_at: 2026-07-02T20:47:50.522Z confidence: 0.60 status: active version: 1 skill_origin: generated --- # Bundle Safety ## Trigger - minify / minification / bundle / esbuild / build size - re-export / namespace re-export / exportLines / exportRanges - dist/index.js conformance checks - identifier preservation / stack trace readability - consumer-constraint verification before transforms ## Required Procedure ### (a) Minification Variant Selection The standard minification configuration for the plugin bundle is **identifier-preserving**: ``` --minify-whitespace --minify-syntax ``` This yields ~22.3% size reduction on the main bundle (~1.28 MB absolute). The reduction is below the optimistic 35–43% range because **identifier mangling is deliberately skipped**. **Full identifier mangling (`--minify-identifiers`) is REJECTED.** It breaks two hard constraints: 1. **13 grep guardrail assertions** — split across `tests/unit/build/full-auto-toolbefore-fail-closed.test.ts` (fail-closed hook substring/wrapping checks) and `tests/unit/turbo/lean/runtime-conformance.test.ts` (Lean Turbo identifier-preservation checks). Mangling would rename these identifiers and cause all 13 assertions to fail. 2. **Stack-trace readability** — preserved identifier names are required for runtime debugging. The release-gate test `tests/unit/build/throw-and-verify-located.test.ts` asserts that thrown errors carry readable stack frames with recognizable function names (e.g. `initializeOpenCodeSwarm`). **Decision is final:** identifier-preserving minify is the standard. Do not enable `--minify-identifiers` without a documented exception approved by the team. ### (b) Consumer-Constraint Verification Before Transforms Before merging any minification or transform change: 1. **Build the smallest possible test bundle** with the proposed transform flags. 2. **Run the consumer's exact constraint check first** — the 13 grep guardrails are split across `tests/unit/build/full-auto-toolbefore-fail-closed.test.ts` (fail-closed hook constraints) and `tests/unit/turbo/lean/runtime-conformance.test.ts` (Lean Turbo identifier-preservation checks). Together they are the authoritative consumer constraint. 3. **Run the full build conformance suite** (`tests/unit/build/throw-and-verify-located.test.ts`, `tests/unit/turbo/lean/runtime-conformance.test.ts`) to verify runtime integrity and stack-trace readability. 4. **Only merge if all guardrail assertions pass.** A single grep guardrail failure blocks the change. This procedure applies to any transform that could rename, inline, or remove identifiers — not just minification flags. ### (c) Identifier-Preservation Testing Verify identifier names survive the transform via the layered test stack: **Static (grep) layer:** - `tests/unit/build/full-auto-toolbefore-fail-closed.test.ts` — fail-closed hook substring/wrapping checks verifying that specific identifier substrings (e.g. `fullAutoPermissionHook.toolBefore`, `guardrailsHooks.toolBefore`, `scopeGuardHook.toolBefore`, `delegationGateHooks.toolBefore`) are present and that fail-closed hooks are not wrapped in `safeHook(...)`. - `tests/unit/turbo/lean/runtime-conformance.test.ts` — `distContains()` checks verifying that Lean Turbo integration-point identifiers (`verifyLeanTurboPhaseReady`, `verifyLeanTurboTaskCompletion`, `LEAN_TURBO_BANNER`, `enableLeanTurbo`, `hasActiveTurboMode`) survive the build. **Runtime layer:** - `tests/unit/build/throw-and-verify-located.test.ts` — asserts that thrown errors carry readable stack frames with preserved function names (e.g. `initializeOpenCodeSwarm`). This is the runtime complement to the static grep assertions. **Before enabling `--minify-identifiers`, confirm ALL of the following:** - No `eval()` or `Function('...')` dispatch in the bundle (mangled identifiers break dynamic dispatch). - No `constructor.name` or `Function.name` introspection in production paths. - No `@__PURE__` annotations or side-effectful top-level patterns that depend on identifier stability. - All 13 grep guardrails still pass. - Stack-trace readability is verified at runtime. If any of these checks fail, `--minify-identifiers` must not be enabled. ### (d) Namespace Re-Export Coverage When modifying re-export or export-tracking logic (e.g. `exportLines`, `exportRanges`, `parseFileImports`): **Test both forms of namespace re-export — they are distinct AST forms that require separate tracking:** 1. **Regular namespace re-export:** `export * from './module'` 2. **Aliased namespace re-export:** `export * as ns from './module'` The regex in `src/tools/repo-graph/builder.ts` (`parseFileImports`) handles both via the pattern `export\s+\*(?:\s+as\s+\w+)?\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]`. Both forms must be tested when modifying export tracking because: - They produce different `importType` values in the parsed output (`namespace` for both, but the aliased form carries a local binding name). - They require separate tracking in `exportLines`/`exportRanges` — the aliased form creates a local binding (`ns`) that must be recorded alongside the re-exported symbols. - Missing either form causes silent graph gaps in `repo-graph` callers/dead-exports analysis. **Test file:** `tests/unit/tools/repo-graph-reexports.test.ts` covers both forms (see test case "4. export * as ns from './bar' — TypeScript namespace re-export → importType: namespace"). Run this test alongside any export-tracking change. ## Forbidden Shortcuts - Enabling `--minify-identifiers` without confirming all 13 grep guardrails pass and runtime stack-trace readability is verified. - Merging a minification/transform change without first running the consumer-constraint check (the 13 grep guardrails) against the smallest possible bundle. - Modifying re-export/export tracking without testing `export * as ns from '...'` (aliased namespace) alongside `export * from '...'` (regular namespace). - Assuming identifier preservation is "good enough" without running the full grep guardrail stack plus runtime stack-trace inspection. ## Delegation Template When delegating a task affected by this skill, include: ``` SKILLS: file:.opencode/skills/generated/bundle-safety/SKILL.md ``` ## Reviewer Checks - Verify the minification config in the build script matches `--minify-whitespace --minify-syntax` (no `--minify-identifiers`). - Verify `tests/unit/build/full-auto-toolbefore-fail-closed.test.ts` passes against the built `dist/index.js` (fail-closed hook guardrails green). - Verify `tests/unit/turbo/lean/runtime-conformance.test.ts` passes (Lean Turbo identifier-preservation guardrails green). - Verify `tests/unit/build/throw-and-verify-located.test.ts` passes (runtime stack-trace readability). - If re-export tracking was modified, verify `tests/unit/tools/repo-graph-reexports.test.ts` covers both `export * from '...'` and `export * as ns from '...'`. - Verify `dist/index.js` size is under the packaging gate (`MAIN_BUNDLE_MAX_BYTES = 8.0 MiB` in `tests/smoke/packaging.test.ts`). ## Source Knowledge IDs - 5746c5c9-1330-4fbe-b62e-f564deb1ff77 — Before enabling any minification or transform flag, verify it doesn't break a hard consumer constraint by testing the smallest possible bundle against the exact constraint check. Required actions: test build output against consumer constraints before merging minification changes; build a minimal test bundle and run the consumer's validation first. - 5d99affe-bdd1-4945-8cd8-fcf37abb8c84 — Identifier-preserving minify (--minify-whitespace --minify-syntax) yields 22.3% on this bundle (1.28MB absolute) — substantial but below the optimistic 35-43% because identifier mangling is deliberately skipped to keep stack traces readable. The standard is identifier-preserving; full mangling is REJECTED because it breaks the 13 identifier-grepping guardrail assertions and stack-trace readability. - 9323a8f0-c07e-41c2-9857-11a24c55dca2 — When re-export handling is modified, verify aliased namespace re-exports (`export * as ns from '...'`) are preserved alongside regular re-exports — they are distinct AST forms that require separate tracking in exportLines/exportRanges. Required: test namespace re-exports alongside regular re-exports when modifying export tracking.