Skip to content

Commit 7538eb8

Browse files
author
Codex Agent
committed
chore: preserve recovered worktree changes
Created by Codex during automated worktree cleanup.
1 parent 2e85e97 commit 7538eb8

2 files changed

Lines changed: 53 additions & 15 deletions

File tree

src/cli-helpers.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ export async function suggestPrepareHook(cwd: string = process.cwd()): Promise<b
468468
if (existing?.includes('skilld'))
469469
return true
470470

471-
const prepareCmd = buildPrepareScript(existing)
471+
const prepareCmd = buildPrepareScript(existing, cwd)
472472

473473
if (!isInteractive()) {
474474
p.log.info(
@@ -505,8 +505,9 @@ export async function suggestPrepareHook(cwd: string = process.cwd()): Promise<b
505505
/**
506506
* Build the full prepare script value, safely appending to any existing command.
507507
*/
508-
export function buildPrepareScript(existing: string | undefined): string {
509-
const cmd = 'skilld prepare || true'
508+
export function buildPrepareScript(existing: string | undefined, cwd: string = process.cwd()): string {
509+
const bin = isSkilldInstalled(cwd) ? 'skilld' : 'npx skilld'
510+
const cmd = `${bin} prepare || true`
510511
if (!existing || !existing.trim())
511512
return cmd
512513

@@ -520,6 +521,17 @@ export function buildPrepareScript(existing: string | undefined): string {
520521
return `${cleaned} && (${cmd})`
521522
}
522523

524+
/**
525+
* Check if skilld is listed as a dependency (dev or regular) in the project's package.json.
526+
*/
527+
function isSkilldInstalled(cwd: string): boolean {
528+
const pkg = readPackageJsonSafe(join(cwd, 'package.json'))
529+
if (!pkg)
530+
return false
531+
const deps = pkg.parsed as Record<string, any>
532+
return !!(deps.dependencies?.skilld || deps.devDependencies?.skilld)
533+
}
534+
523535
export function getRepoHint(name: string, cwd: string): string | undefined {
524536
const result = readPackageJsonSafe(join(cwd, 'node_modules', name, 'package.json'))
525537
if (!result)

test/unit/prepare-hook.test.ts

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,70 @@
1+
import { mkdtempSync, writeFileSync } from 'node:fs'
2+
import { tmpdir } from 'node:os'
3+
import { join } from 'node:path'
14
import { describe, expect, it } from 'vitest'
25
import { buildPrepareScript } from '../../src/cli-helpers.ts'
36
import { editJsonProperty } from '../../src/core/package-json.ts'
47

8+
function makeTempCwd(hasSkilld: boolean): string {
9+
const dir = mkdtempSync(join(tmpdir(), 'prepare-hook-'))
10+
const pkg: Record<string, any> = { name: 'test-pkg' }
11+
if (hasSkilld)
12+
pkg.devDependencies = { skilld: '^1.0.0' }
13+
writeFileSync(join(dir, 'package.json'), JSON.stringify(pkg))
14+
return dir
15+
}
16+
517
describe('prepare hook script building', () => {
6-
const buildPrepare = buildPrepareScript
18+
const cwdWithSkilld = makeTempCwd(true)
19+
const cwdWithout = makeTempCwd(false)
720
const standalone = 'skilld prepare || true'
21+
const npxStandalone = 'npx skilld prepare || true'
22+
23+
it('uses skilld when installed as dependency', () => {
24+
expect(buildPrepareScript(undefined, cwdWithSkilld)).toBe(standalone)
25+
})
26+
27+
it('uses npx skilld when not installed as dependency', () => {
28+
expect(buildPrepareScript(undefined, cwdWithout)).toBe(npxStandalone)
29+
})
830

931
it('returns standalone when no existing script', () => {
10-
expect(buildPrepare(undefined)).toBe(standalone)
32+
expect(buildPrepareScript(undefined, cwdWithSkilld)).toBe(standalone)
1133
})
1234

1335
it('returns standalone when existing script is empty', () => {
14-
expect(buildPrepare('')).toBe(standalone)
15-
expect(buildPrepare(' ')).toBe(standalone)
36+
expect(buildPrepareScript('', cwdWithSkilld)).toBe(standalone)
37+
expect(buildPrepareScript(' ', cwdWithSkilld)).toBe(standalone)
1638
})
1739

1840
it('appends with && and parens to existing script', () => {
19-
expect(buildPrepare('husky')).toBe('husky && (skilld prepare || true)')
41+
expect(buildPrepareScript('husky', cwdWithSkilld)).toBe('husky && (skilld prepare || true)')
2042
})
2143

2244
it('handles existing script with multiple commands', () => {
23-
expect(buildPrepare('husky && lint-staged')).toBe('husky && lint-staged && (skilld prepare || true)')
45+
expect(buildPrepareScript('husky && lint-staged', cwdWithSkilld)).toBe('husky && lint-staged && (skilld prepare || true)')
2446
})
2547

2648
it('strips trailing && from existing script', () => {
27-
expect(buildPrepare('husky &&')).toBe('husky && (skilld prepare || true)')
28-
expect(buildPrepare('husky && ')).toBe('husky && (skilld prepare || true)')
49+
expect(buildPrepareScript('husky &&', cwdWithSkilld)).toBe('husky && (skilld prepare || true)')
50+
expect(buildPrepareScript('husky && ', cwdWithSkilld)).toBe('husky && (skilld prepare || true)')
2951
})
3052

3153
it('strips trailing ; from existing script', () => {
32-
expect(buildPrepare('husky;')).toBe('husky && (skilld prepare || true)')
54+
expect(buildPrepareScript('husky;', cwdWithSkilld)).toBe('husky && (skilld prepare || true)')
3355
})
3456

3557
it('strips trailing || from existing script', () => {
36-
expect(buildPrepare('husky ||')).toBe('husky && (skilld prepare || true)')
58+
expect(buildPrepareScript('husky ||', cwdWithSkilld)).toBe('husky && (skilld prepare || true)')
3759
})
3860

3961
it('handles only operators as existing script', () => {
40-
expect(buildPrepare('&&')).toBe(standalone)
41-
expect(buildPrepare(';')).toBe(standalone)
62+
expect(buildPrepareScript('&&', cwdWithSkilld)).toBe(standalone)
63+
expect(buildPrepareScript(';', cwdWithSkilld)).toBe(standalone)
64+
})
65+
66+
it('appends npx variant to existing script when not installed', () => {
67+
expect(buildPrepareScript('husky', cwdWithout)).toBe('husky && (npx skilld prepare || true)')
4268
})
4369

4470
describe('surgical package.json editing', () => {

0 commit comments

Comments
 (0)