---
phase: 42-wallpapers-social-format-conversion-voice
plan: 01
subsystem: api
tags: [file-type, xlsx, csv-parse, pandoc, libreoffice, content-jobs, renderers, typescript]

# Dependency graph
requires:
  - phase: 40-content-job-infra
    provides: content_jobs table, renderContent switch stub, async job pattern
provides:
  - WallpaperBundle, AppIconBundle, SocialPostBundle, ConvertBundle type definitions in types.ts
  - wallpaper, social-post, convert cases in renderContent switch
  - converter-capabilities.ts startup probe for pandoc/libreoffice with cached result
  - execFileNoThrow utility for safe binary execution
  - Stub renderers for wallpaper, social-post, convert (Plans 02-04 replace)
affects:
  - 42-02 (wallpaper renderer uses WallpaperBundle type)
  - 42-03 (social renderer uses SocialPostBundle type)
  - 42-04 (convert renderer uses ConvertBundle type, converter-capabilities)
  - 42-05 (voice renderer)
  - 42-06 (UI wiring)

# Tech tracking
tech-stack:
  added: [file-type@22.0.0, xlsx@0.18.5, csv-parse@6.2.1]
  patterns:
    - execFileNoThrow pattern for safe binary probing (no throw on exit code !=0)
    - Startup probe with module-level cache for binary availability

key-files:
  created:
    - server/src/services/converter-capabilities.ts
    - server/src/services/renderers/wallpaper-renderer.ts
    - server/src/services/renderers/social-renderer.ts
    - server/src/services/renderers/convert-renderer.ts
    - server/src/utils/execFileNoThrow.ts
  modified:
    - server/src/services/renderers/types.ts
    - server/src/services/content-job-runner.ts
    - server/package.json
    - pnpm-lock.yaml

key-decisions:
  - "execFileNoThrow utility created as new server/src/utils/ helper — plan referenced it as 'project standard' but it did not exist yet; created as Rule 2 (missing critical functionality)"
  - "Stub renderers import and return RenderResult type to satisfy tsc module resolution — Plans 02-04 replace with real implementations"
  - "converter-capabilities.ts caches capabilities in module-level variable after first probe"

patterns-established:
  - "execFileNoThrow: safe binary probe returning status 0|1, never throwing — use for all optional binary checks"
  - "Startup probe pattern: probe() called lazily on first get(), result cached in module-level variable"
  - "Stub renderer pattern: export async function that throws 'Not implemented', satisfies tsc"

requirements-completed: [CONV-08]

# Metrics
duration: 3min
completed: 2026-04-04
---

# Phase 42 Plan 01: Foundation — Bundle Types, Job Runner Switch, Converter Capabilities

**file-type/xlsx/csv-parse installed, four bundle types added to types.ts, wallpaper/social-post/convert cases wired in content-job-runner, and converter-capabilities service probing pandoc/libreoffice via new execFileNoThrow utility**

## Performance

- **Duration:** 3 min
- **Started:** 2026-04-04T22:06:42Z
- **Completed:** 2026-04-04T22:09:28Z
- **Tasks:** 2
- **Files modified:** 9 (3 modified, 5 created, 1 lockfile)

## Accomplishments
- Installed file-type@22.0.0, xlsx@0.18.5, csv-parse@6.2.1 in server/ workspace
- Added WallpaperBundle, AppIconBundle, SocialPostBundle, ConvertBundle interfaces to types.ts; updated ContentBundle union
- Wired wallpaper, social-post, convert cases in renderContent switch with dynamic imports of stub renderers
- Created converter-capabilities.ts probing pandoc/libreoffice at startup, caching result for all subsequent calls
- Created execFileNoThrow utility for safe binary probing without exceptions

## Task Commits

Each task was committed atomically:

1. **Task 1: Install dependencies and define bundle types** - `e809b706` (feat)
2. **Task 2: Wire content-job-runner switch and create converter capabilities service** - `3ba09889` (feat)

**Plan metadata:** (docs commit — see below)

## Files Created/Modified
- `server/src/services/renderers/types.ts` - Added WallpaperBundle, AppIconBundle, SocialPostBundle, ConvertBundle; updated ContentBundle union
- `server/src/services/content-job-runner.ts` - Added wallpaper, social-post, convert cases to renderContent switch
- `server/src/services/converter-capabilities.ts` - Startup probe for pandoc/libreoffice, cached capability map
- `server/src/utils/execFileNoThrow.ts` - Safe binary execution utility (no throw on non-zero exit)
- `server/src/services/renderers/wallpaper-renderer.ts` - Stub renderer (throws "Not implemented")
- `server/src/services/renderers/social-renderer.ts` - Stub renderer (throws "Not implemented")
- `server/src/services/renderers/convert-renderer.ts` - Stub renderer (throws "Not implemented")
- `server/package.json` - Added file-type, xlsx, csv-parse dependencies
- `pnpm-lock.yaml` - Updated lockfile

## Decisions Made
- Created `execFileNoThrow` utility in `server/src/utils/` — the plan referenced it as "project standard" but it did not exist. Created it as a Rule 2 auto-fix (missing critical functionality for the converter-capabilities probe).
- Stub renderers import `RenderResult` type but use `_input` naming convention for unused parameter to satisfy TypeScript strict mode.

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 2 - Missing Critical] Created execFileNoThrow utility**
- **Found during:** Task 2 (converter capabilities service)
- **Issue:** Plan referenced `src/utils/execFileNoThrow.ts` as "project standard" but the file did not exist in the codebase
- **Fix:** Created `server/src/utils/execFileNoThrow.ts` implementing promisify(execFile) wrapper that returns `{ stdout, stderr, status: 0|1 }` without throwing
- **Files modified:** server/src/utils/execFileNoThrow.ts (created)
- **Verification:** tsc --noEmit passes with zero errors; converter-capabilities.ts imports and uses it correctly
- **Committed in:** 3ba09889 (Task 2 commit)

---

**Total deviations:** 1 auto-fixed (1 missing critical)
**Impact on plan:** Auto-fix necessary for the converter-capabilities probe to compile and run. No scope creep.

## Issues Encountered
None beyond the missing execFileNoThrow utility (handled above).

## User Setup Required
None - no external service configuration required.

## Next Phase Readiness
- All foundation types available for Plans 02-04
- content-job-runner dispatches wallpaper/social-post/convert jobs to stub renderers
- Plans 02 (wallpaper), 03 (social), 04 (convert) can now proceed in parallel
- execFileNoThrow utility available for any future binary-probe needs

---
*Phase: 42-wallpapers-social-format-conversion-voice*
*Completed: 2026-04-04*
