test: add cross-package export smoke test to catch missing imports#875
test: add cross-package export smoke test to catch missing imports#875tamirdresher merged 4 commits intoinsiderfrom
Conversation
…tles to PR readiness (#813) - Add file list table with per-file +additions/-deletions stats - Add PR scope classification (Product/Infrastructure/Mixed) - Rename Architectural Review and Security Review checks with descriptive subtitles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add CI check that fails when repo-health PRs include product source code changes under packages/*/src/. Prevents scope creep where infrastructure PRs accidentally touch product code. - Add squad-scope-check.yml workflow - Document PR scope rules in copilot-instructions.md - Fail loudly on git diff errors instead of silently passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validates every value import squad-cli uses from squad-sdk resolves to a defined export at runtime. Covers 15 SDK subpaths and 50+ named exports including FSStorageProvider, SquadClient, CastingEngine, RalphMonitor, and all resolution/config/platform helpers. Also verifies that every entry in the SDK package.json exports map points to a file that actually exists on disk. Motivation: v0.9.3-insider.1 shipped with FSStorageProvider missing from the SDK barrel — broke users at runtime while all TS-level tests passed (TypeScript resolves from source, not compiled output). Refs: #836
🟢 Impact Analysis — PR #875Risk tier: 🟢 LOW 📊 Summary
🎯 Risk Factors
📦 Modules Affectedtests (1 file)
This report is generated automatically for every PR. See #733 for details. |
🛫 PR Readiness Check
PR Scope: 🔧 Infrastructure
|
| Status | Check | Details |
|---|---|---|
| ❌ | Single commit | 4 commits — consider squashing before review |
| ✅ | Not in draft | Ready for review |
| ❌ | Branch up to date | insider is 1 commit(s) ahead — rebase recommended |
| ❌ | Copilot review | No Copilot review yet — it may still be processing |
| ✅ | Changeset present | Changeset file found |
| ✅ | Scope clean | No .squad/ or docs/proposals/ files |
| ✅ | No merge conflicts | No merge conflicts |
| ❌ | Copilot threads resolved | 2 unresolved Copilot thread(s) — fix and resolve before merging |
| ❌ | CI passing | 10 check(s) still running |
| ❌ | Issue linked | No issue reference — add Closes #N to PR body or commit message |
| ✅ | Protected files | No protected bootstrap files changed |
Files Changed (11 files, +880 −7)
| File | +/− |
|---|---|
.changeset/readiness-file-list.md |
+7 −0 |
.changeset/scope-boundary-check.md |
+8 −0 |
.changeset/smart-pr-nudge.md |
+8 −0 |
.github/copilot-instructions.md |
+4 −0 |
.github/workflows/squad-pr-nudge.yml |
+184 −0 |
.github/workflows/squad-repo-health.yml |
+2 −2 |
.github/workflows/squad-scope-check.yml |
+31 −0 |
CONTRIBUTING.md |
+2 −0 |
scripts/pr-readiness.mjs |
+99 −4 |
test/cross-package-exports.test.ts |
+287 −0 |
test/pr-readiness.test.ts |
+248 −1 |
Total: +880 −7
This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.
There was a problem hiding this comment.
Pull request overview
Adds a Vitest smoke test to prevent runtime breakages caused by missing/incorrect @bradygaster/squad-sdk re-exports (e.g., SDK barrel/export-map drift that TypeScript may not catch during development).
Changes:
- Introduces
test/cross-package-exports.test.tsto dynamically import the SDK root barrel + key subpaths and assert required named exports are defined at runtime. - Adds an additional check that every
packages/squad-sdk/package.jsonexportsentry points to an existing file on disk.
| const pkg = JSON.parse( | ||
| fs.readFileSync(resolve(sdkRoot!, 'package.json'), 'utf8'), | ||
| ); | ||
| const exportsMap = pkg.exports as Record<string, Record<string, string>>; | ||
| const missing: string[] = []; | ||
|
|
||
| for (const [subpath, targets] of Object.entries(exportsMap)) { | ||
| if (typeof targets === 'string') { | ||
| if (!existsSync(resolve(sdkRoot!, targets))) { | ||
| missing.push(`${subpath} → ${targets}`); | ||
| } | ||
| continue; | ||
| } | ||
| for (const [condition, file] of Object.entries(targets)) { | ||
| if (!existsSync(resolve(sdkRoot!, file))) { | ||
| missing.push(`${subpath}[${condition}] → ${file}`); |
There was a problem hiding this comment.
pkg.exports is being cast to Record<string, Record<string, string>>, but Node’s package.json exports field can be either a string or a nested condition object. This cast makes the typeof targets === 'string' branch type-inconsistent (and would fail if tests are ever type-checked) and also masks the possibility of nested/non-string conditions. Prefer typing exportsMap as unknown (or a union of string | Record<string, unknown>) and narrowing/recursing on leaf string targets before calling resolve()/existsSync().
| * add a corresponding assertion here. The grep one-liner in the test | ||
| * description shows how to audit. |
There was a problem hiding this comment.
The header comment mentions “The grep one-liner in the test description shows how to audit”, but this file doesn’t currently include that one-liner. Either add the referenced command here (so the maintenance instructions are self-contained) or remove that sentence to avoid stale documentation.
| * add a corresponding assertion here. The grep one-liner in the test | |
| * description shows how to audit. | |
| * add a corresponding assertion here. Audit current usage with: | |
| * grep -RhoE "from '@bradygaster/squad-sdk[^']*'" packages/squad-cli/src |
✅ Verified: Test catches the exact FSStorageProvider bugWe manually reproduced the insider.1 failure and confirmed this test catches it: Reproduction steps
Result` ✅ 19 passed | 1 failed (20 total) The exact test case that checks What this prevents going forward
Coverage
|
🧪 Post-Merge Review — Simon (Tester)Verdict: 🟡 Conditional Approve — Core test is valuable, follow-ups needed. What's GoodThe cross-package export smoke test directly targets the v0.9.3-insider.1 Concerns
Recommended Follow-Ups
Review by Squad AI team (Simon — Tester) · requested by Dina Berry |
…#900, bradygaster#875) - Add YAML value escaping helper for skill metadata - Replace catch(err: any) with catch(err: unknown) + narrowing - Add type guards to replace unsafe type assertions - Standardize deprecation messages on `gh copilot` - Fix unsafe exports type cast in cross-package test Closes bradygaster#924, bradygaster#925, bradygaster#926 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add YAML value escaping helper for skill metadata - Replace catch(err: any) with catch(err: unknown) + narrowing - Add type guards to replace unsafe type assertions - Standardize deprecation messages on `gh copilot` - Fix unsafe exports type cast in cross-package test Closes #924, #925, #926 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address post-merge review findings (#876, #900, #875) - Add YAML value escaping helper for skill metadata - Replace catch(err: any) with catch(err: unknown) + narrowing - Add type guards to replace unsafe type assertions - Standardize deprecation messages on `gh copilot` - Fix unsafe exports type cast in cross-package test Closes #924, #925, #926 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: add changeset for review findings fix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: trigger CI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(.squad): EECOM history — PR #942 rebase learnings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: update changeset to accurately reflect PR changes (drop YAML escaping reference) Agent-Logs-Url: https://github.com/bradygaster/squad/sessions/54f41407-61bf-4977-85b7-572341c47b62 Co-authored-by: bradygaster <41929050+bradygaster@users.noreply.github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
) * feat(ci): add file list with line stats, scope badge, and check subtitles to PR readiness (#813) - Add file list table with per-file +additions/-deletions stats - Add PR scope classification (Product/Infrastructure/Mixed) - Rename Architectural Review and Security Review checks with descriptive subtitles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: scope boundary enforcement for repo-health PRs (#826) Add CI check that fails when repo-health PRs include product source code changes under packages/*/src/. Prevents scope creep where infrastructure PRs accidentally touch product code. - Add squad-scope-check.yml workflow - Document PR scope rules in copilot-instructions.md - Fail loudly on git diff errors instead of silently passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: smart PR nudge for stale PRs (#827) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add cross-package export smoke test to catch missing imports Validates every value import squad-cli uses from squad-sdk resolves to a defined export at runtime. Covers 15 SDK subpaths and 50+ named exports including FSStorageProvider, SquadClient, CastingEngine, RalphMonitor, and all resolution/config/platform helpers. Also verifies that every entry in the SDK package.json exports map points to a file that actually exists on disk. Motivation: v0.9.3-insider.1 shipped with FSStorageProvider missing from the SDK barrel — broke users at runtime while all TS-level tests passed (TypeScript resolves from source, not compiled output). Refs: #836 --------- Co-authored-by: Dina Berry (MSFT) <diberry@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <copilot@github.com>
* fix: address post-merge review findings (#876, #900, #875) - Add YAML value escaping helper for skill metadata - Replace catch(err: any) with catch(err: unknown) + narrowing - Add type guards to replace unsafe type assertions - Standardize deprecation messages on `gh copilot` - Fix unsafe exports type cast in cross-package test Closes #924, #925, #926 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: add changeset for review findings fix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: trigger CI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(.squad): EECOM history — PR #942 rebase learnings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: update changeset to accurately reflect PR changes (drop YAML escaping reference) Agent-Logs-Url: https://github.com/bradygaster/squad/sessions/54f41407-61bf-4977-85b7-572341c47b62 Co-authored-by: bradygaster <41929050+bradygaster@users.noreply.github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
What
Adds a vitest smoke test (\ est/cross-package-exports.test.ts) that validates every value import \squad-cli\ uses from \squad-sdk\ resolves to a defined export at runtime.
Why
v0.9.3-insider.1 shipped with \FSStorageProvider\ missing from the SDK barrel — broke users at runtime while all TypeScript-level tests passed (TS resolves from source, not compiled output). This test would have caught that.
What it covers
20 test cases across 15 SDK subpaths and 50+ named exports:
How to maintain
When adding a new import from @bradygaster/squad-sdk\ to \squad-cli, add a corresponding assertion in this test.
Refs #836