Skip to content

Releases

v0.5.3 — repo transfer to artificemachine

Choose a tag to compare

@celstnblacc celstnblacc released this 24 Jun 16:52
a1754c9

v0.5.3

Changes

  • Repository transferred to artificemachine/pencil-sync
  • Updated repository URL in package.json to reflect new home
  • Restored ./dist/ prefix on bin entries (regression fix from npm pkg fix stripping them)

No functional changes.

v0.5.2 — 10-iteration audit remediation

Choose a tag to compare

@celstnblacc celstnblacc released this 24 Jun 16:42
c417f3a

v0.5.2 — Audit Remediation (10 TDD iterations)

Security fixes

  • SSRF guard on apiBaseUrl: warn on non-HTTPS and localhost/private-IP targets
  • Symlink traversal guard in state-store.ts collectFiles() via resolve()+startsWith()
  • ShipGuard SAST: corrected disable_rules field; suppressed JS-002 (Array.prototype.join false positive) and JS-004 (array dedup false positive)

Bug fixes

  • pen-snapshot: diffPenSnapshots detects added/cleared props, whole-node deletions, and removed tokens
  • pen-to-code: hexToRgbChannels parses rgb()/rgba() and rejects invalid-length hex
  • pen-to-code: applyFillChanges single-pass keyed replacement prevents chained-diff corruption
  • pencil-mcp-client: batchGet/batchDesign throw on isError and non-JSON responses
  • code-to-pen: syncCodeToPenDirect returns failure on unreadable .pen or no-op
  • provider: honors settings.provider in runner creation and env-key resolution
  • ai-runners: claude-haiku-4-5 alias in pricing table; systemInstruction for Google; warn on OpenAI finish_reason:length
  • config: Zod v4 migration (message/error params); mcp-server null→undefined coercion

CI / tooling

  • .npmrc legacy-peer-deps=true resolves openai peerOptional zod v3 conflict on Node 22

v0.5.1 — penFile path fix

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 23:55
a1bae2d

Fix

Allow penFile to live outside the project directory.

penFile is a read-only input — it may point to a shared Pencil workspace anywhere on disk. The path traversal guard was incorrectly applied to it, causing pencil-sync doctor to reject valid configs (e.g. penFile: /Users/.../Downloads/design.pen).

Only write targets (codeDir, stateFile) are confined by the traversal guard.

Changes

2026-06-19: fix(config): allow penFile outside configDir — read-only input must not be traversal-guarded

Full Changelog

https://github.com/celstnblacc/pencil-sync/blob/main/CHANGELOG.md

v0.5.0 — .pen parser real-schema hardening

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 20:09
3c215bf

Fixed

  • Complex fill values (gradients, images, arrays) no longer collapse to [object Object] — distinct values diff correctly, identical objects with different key order produce zero diffs
  • Per-side cornerRadius arrays ([t,r,b,l]) now diff correctly against each other and against scalar values
  • Gradient/image/array fills route to Claude instead of the hex fast-path (no more spurious "could not convert hex" errors)

Added

  • Document-level design tokens (variables/themes) are now tracked in the snapshot and surface as diffs when changed
  • ref/reusable component instances are resolved during tree flattening — instance visual props are tracked and diff correctly
  • stableStringify() utility in utils.ts for sorted-key canonical JSON serialization
  • src/__tests__/fixtures/realistic.pen.ts — realistic Document fixture for all future real-schema tests

Notes

  • 560 tests passing (+26 new)
  • Migration-safe: complex values stored as canonical JSON strings (still string type), so existing persisted snapshots remain valid

v0.4.1 — TUI wiring fix

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 19:01
296e3e2

Fixed

  • pencil-sync tui no longer exits immediately with "TUI starting..."
  • Root cause: tui action did not pass config to startTui(); now loads config via initConfig(), builds state map from StateStore, and renders the ink <App> component

Notes

  • All 534 tests passing
  • Ink TUI dashboard (MappingPanel, EventFeed, BudgetMeter, keybinds s/d/q) fully functional

v0.4.0 — Live TUI dashboard + enhanced setup wizard

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 18:46
74a281e

v0.4.0

New features

Enhanced setup wizard (pencil-sync setup)

  • Step counter [1/7] through [7/7] before each question
  • Colored auto-detected framework/styling values (yellow)
  • Confirmation summary screen before writing config
  • Back navigation — type back at any step to return to the previous one; step 1 prints "Already at step 1."

Live TUI dashboard (pencil-sync tui)

  • Full-screen ink/React UI — one MappingPanel per mapping: last sync time, direction, tracked file count, "not yet synced" label
  • Scrollable EventFeed — color-coded OK/error/warning/conflict events from both SyncEngine.onEvent() and the logger TUI hook
  • BudgetMeter — 20-char progress bar with $used / $max, OVER BUDGET label when exceeded
  • Keybinds: s = manual sync all, d = run doctor, q = quit

SyncEngine.onEvent()

  • Register a callback that fires after every syncMapping() call (success and conflict paths)
  • Handler errors are silently swallowed — sync is never interrupted by a bad TUI handler

Internal

  • logger.ts — TuiEvent, setTuiEventHandler, clearTuiEventHandler for redirecting log output to the TUI
  • types.ts — TuiSyncEvent shape
  • JSX/TSX support in tsconfig + Vitest esbuild transform
  • Dependencies: ink, react (runtime); @types/react, ink-testing-library (dev)

Tests

534 tests passing (32 test files, +3 new TUI test files, +31 new tests)

Full changelog

See CHANGELOG.md for all entries.

v0.3.0 — .pencil-sync/ directory, doctor, auto-detection, setup wizard

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 17:54
a6e356a

What's new in v0.3.0

.pencil-sync/ per-project directory

  • Replaces flat .pencil-sync-state.json with .pencil-sync/state.json + .pencil-sync/last-run.json
  • Automatic migration on first load — existing projects just work
  • last-run.json written after every sync for inspection and tooling

pencil-sync doctor

Six preflight checks with a [✓]/[✗] checklist: Claude CLI on PATH, config valid, pen file accessible, code directory accessible, globs match files, budget > 0. Exits 0 when all pass, 1 when any fail.

Auto-detection helpers

  • detectStyling() now detects css-modules (via *.module.css scan) and plain css fallback
  • New findPenFiles() helper recursively finds .pen files, skipping node_modules and hidden directories

pencil-sync setup interactive wizard

Replaces the dumb init command with a seven-question wizard:

  • Auto-detects framework and styling, shows them as defaults
  • Finds .pen files recursively, lets you pick by number or enter manually
  • Writes pencil-sync.config.json, creates .pencil-sync/ directory
  • Reports next steps after writing config

pencil-sync init is kept as an alias.

Tests

435 → 471 passing (27 test files)

Changelog

  • feat(project-dir): replace flat state file with .pencil-sync/ directory
  • feat(doctor): add pencil-sync doctor preflight command
  • feat(detect): add detectStyling() css-modules/css detection and findPenFiles()
  • feat(setup): add interactive pencil-sync setup wizard replacing init command

v0.2.0 — MCP server + host-agnostic Executor

Choose a tag to compare

@celstnblacc celstnblacc released this 18 Jun 17:05
dae60c8

What's new

pencil-sync-mcp — host-agnostic MCP server

pencil-sync now ships a second binary pencil-sync-mcp that exposes sync primitives as MCP tools. Any MCP-compatible host agent (Claude Code, Codex CLI, OpenCode, Gemini CLI) can use pencil-sync without spawning a nested claude subprocess.

7 MCP tools:

  • pencil_get_config — load config
  • pencil_diff_design — diff .pen snapshot vs last synced state
  • pencil_diff_code — diff code dir hashes vs last synced state
  • pencil_detect_conflict — detect bidirectional conflict
  • pencil_build_prompt — build the full LLM prompt for the host to apply
  • pencil_apply_fill_changes — deterministic CSS color substitution (no LLM)
  • pencil_record_sync — persist sync state after edits

Executor interface (Option A)

All sync paths now go through an Executor interface (LocalClaudeExecutor is the only day-one implementation). Tests can inject a fake executor — no subprocess spawning in CI.

Stats

  • 402 tests passing (up from 300)
  • 0 TypeScript errors
  • @modelcontextprotocol/sdk + zod added as runtime dependencies

v0.1.5 — Glob unification, fast-path fix, ESLint, coverage

Choose a tag to compare

@celstnblacc celstnblacc released this 12 Jun 17:57
da4da8b

What's Changed

Fixed

  • P2-C: Color fast-path now returns success: false when fill diffs match zero CSS declarations (was silent success with 0 files). Partial matches surface as success: true with warnings[].
  • P2-B: New `src/glob-matcher.ts` unifies glob matching across watcher and hasher. Supports brace `{a,b}` expansion and `[..]` character classes. Watcher now watches `codeDir` directly (chokidar v4 dropped glob support) and filters events through `matches()`.
  • MODEL_PRICING: Added `claude-opus-4-8` pricing; `estimateCost` now warns when falling back to Sonnet pricing for an unknown model.

Added

  • ESLint: `eslint.config.js` flat config with `typescript-eslint`, `no-floating-promises` (error), `no-unused-vars`/`no-explicit-any` (warn). `npm run lint` exits 0.
  • Coverage: `@vitest/coverage-v8` provider with enforced thresholds: lines ≥81%, functions ≥83%, branches ≥77%, statements ≥80%.

Stats

  • 347 tests passing across 22 test files
  • Coverage baseline: Stmts 82.55%, Branch 79.5%, Funcs 85.87%, Lines 83.88%

v0.1.4

Choose a tag to compare

@celstnblacc celstnblacc released this 12 Jun 17:12
ec4263e

Refactor — P2-E + P2-D

Changes

  • Unified ignore list (src/ignored-dirs.ts): single IGNORED_DIRS set and IGNORED_GLOBS array shared by watcher and state-hasher. Closes the .next drift where Next.js build output was hashed but not watched.
  • Cross-platform path-traversal guard: replaced POSIX-only validatePathWithinDirectory in config.ts with validatePathWithin from utils.ts. Removes the duplicate 20-line function and fixes the guard on Windows.
  • 322 tests passing; 6 new tests added.