Skip to content

Commit 8d1f27e

Browse files
committed
fix(spec): resolve multi-line and .js imports in skill-reference resolver (#3139)
`extractLocalImports` in build-skill-references.ts under-reported a skill's transitive schema deps because of two blind spots in the import scan: - The regex `/^import\s+.*\s+from\s+.../` used `.`, which does not cross newlines, so any multi-line named import (`import {\n … \n} from './x'`) was silently dropped and never queued into the closure. - `.js`-suffixed ESM specifiers were mangled: the resolver appended `.ts` unconditionally, turning `./types.js` into a non-existent `./types.js.ts` that then failed the `fs.existsSync` check and was discarded. Replace the pattern with a multi-line-tolerant scan that excludes `;`, quotes, and `(` between `import` and `from` — this keeps the non-greedy span from bridging across statement boundaries, side-effect imports, or a dynamic `import(...)`. Normalize `.js` specifiers to `.ts` before resolving. Regenerated the indexes with the fix in place: the platform skill now surfaces `system/tenant.zod.ts`, reached through the previously-invisible `.js` import in `kernel/context.zod.ts`. The `check:skill-refs` gate added in #3138 passes with the regenerated output. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YTjm38Bo2xUv1UUPWu4mC5
1 parent 3a18b60 commit 8d1f27e

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

packages/spec/scripts/build-skill-references.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,24 @@ const SKILL_MAP: Record<string, string[]> = {
122122
function extractLocalImports(filePath: string): string[] {
123123
const content = fs.readFileSync(filePath, 'utf-8');
124124
const imports: string[] = [];
125-
const re = /^import\s+.*\s+from\s+['"](\.[^'"]+)['"]/gm;
125+
const dir = path.dirname(filePath);
126+
// Match `import … from '<relative>'`, tolerating a multi-line import clause.
127+
// The clause between `import` and `from` never contains a `;`, quote, or `(`,
128+
// so excluding those keeps the non-greedy span from bridging across a
129+
// statement boundary, a side-effect import (`import './x'`), or a dynamic
130+
// `import(...)` into the wrong specifier. A plain `.` (the old pattern) does
131+
// not cross newlines, so multi-line named imports were silently dropped.
132+
const re = /^import\b[^;'"()]*?\bfrom\s*['"](\.[^'"]+)['"]/gm;
126133
let match: RegExpExecArray | null;
127134
while ((match = re.exec(content)) !== null) {
128135
const importSpec = match[1];
129-
const dir = path.dirname(filePath);
130136
let resolved = path.resolve(dir, importSpec);
131-
if (!resolved.endsWith('.ts')) resolved += '.ts';
137+
// ESM specifiers may carry a `.js` extension that maps to a `.ts` source
138+
// (`./types.js` → `./types.ts`); otherwise append `.ts` for an
139+
// extensionless local specifier. Blindly appending `.ts` turned `.js`
140+
// imports into a non-existent `foo.js.ts` that was then dropped.
141+
if (resolved.endsWith('.js')) resolved = resolved.slice(0, -3) + '.ts';
142+
else if (!resolved.endsWith('.ts')) resolved += '.ts';
132143
if (fs.existsSync(resolved)) {
133144
imports.push(path.relative(SPEC_SRC, resolved));
134145
}

skills/objectstack-platform/references/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ from `node_modules` — there is no local copy in the skill bundle.
3333
- `node_modules/@objectstack/spec/src/shared/identifiers.zod.ts` — System Identifier Schema
3434
- `node_modules/@objectstack/spec/src/shared/lazy-schema.ts` — Wrap a Zod schema constructor so its body is only evaluated on first use.
3535
- `node_modules/@objectstack/spec/src/shared/protection.zod.ts` — Package-level metadata protection (ADR-0010 §3.7 — Phase 4.3)
36+
- `node_modules/@objectstack/spec/src/system/tenant.zod.ts` — Tenant Schema (Multi-Tenant Architecture)
3637
- `node_modules/@objectstack/spec/src/ui/action.zod.ts` — Action Parameter Schema
3738
- `node_modules/@objectstack/spec/src/ui/app.zod.ts` — Base Navigation Item Schema
3839
- `node_modules/@objectstack/spec/src/ui/i18n.zod.ts` — I18n Object Schema

0 commit comments

Comments
 (0)