Skip to content

feat: Deno worktrunk hooks with lib/ and project surface - #1

Merged
ryanleecode merged 16 commits into
mainfrom
feat/deno-worktrunk-hooks
Aug 30, 2026
Merged

feat: Deno worktrunk hooks with lib/ and project surface#1
ryanleecode merged 16 commits into
mainfrom
feat/deno-worktrunk-hooks

Conversation

@systemfsoftware-maker

Copy link
Copy Markdown
Collaborator

Summary

The worktrunk-config repo becomes the Deno home for worktrunk worktree hooks: the 10 bash hooks from systemfsoftware/scripts/tools/worktrunk are ported to TypeScript at the repo root, sharing a lib/ of git/path/fs helpers, with a project surface (README, Apache-2.0 license, contributing guide, CI) and a review-hardening pass.

What changed

  • Hooks: 12 standalone CLI scripts (*.ts with #!/usr/bin/env -S deno run --allow-* shebang scopes). Ported behavior: gitdir absolute-to-relative conversion, shared-dir symlinking (.repos/.issues/wiki), codegraph warm-copy fallback chain (sqlite3 .backup -> reflink -> copy with integrity check), worktree MCP provisioning, lockfile-driven dependency install and build generation, pre-merge issue-symlink cleanup, post-switch GitKraken config unset.
  • Shared lib: lib/git.ts (resolvePrimaryRepo, runGit), lib/paths.ts (tryRelative), lib/fs.ts (isDirectory/File/Symlink). Hooks are plain CLIs with no exports.
  • Review hardening (found by 7-persona review):
    • Child exit codes now propagate — a failing npm ci or pnpm build aborts the hook (bash set -e parity) instead of logging and exiting 0. Verified: build failure exits 1.
    • pre-merge runs git add -A unconditionally so a retry repairs a partially-failed prior run, keeping the exit gate.
    • codegraph-worktree-mcp instance sanitization matches the bash original's non-overlapping dash collapse, and strips trailing slashes so .mcp.json points at the real volume.
    • worktree-to-relative uses lib/git.ts instead of a local re-implementation (fixes "not a git repo at null").
    • deno task check now typechecks; CI's typecheck step is a real gate (no silent || lint fallback).
  • Surface: evaluator-first README without brittle hook enumerations; Apache-2.0 LICENSE; minimal CONTRIBUTING; CI running dprint check, deno lint, and typecheck on push/PR.

Validation

  • deno task check (dprint + lint + deno check) passes.
  • Behavior smoke tests: pre-merge removes only matching symlinks and stages the deletion; worktree-to-relative converts gitdir paths idempotently; generate-artifacts exits 1 when the build fails; install-deps completes the successful install path.
  • MCP .mcp.json provisioning and the codegraph warm-copy chain skipped gracefully without codegraph/sqlite3 present (best-effort, logs, continues to codegraph init).

- Port 10 bash hooks from systemfsoftware/scripts/tools/worktrunk to Deno TypeScript at repo root (forward-looking, not 1:1 mirror)
- Split lib.ts into lib/git.ts, lib/paths.ts, lib/fs.ts, lib/mod.ts
- Scripts are plain CLIs (no exports) with exact --allow-* shebangs
- dprint config from systemfsoftware, tasks use dprint check + deno lint (non-brittle, no file enumeration)
- Remove mod.ts (not a library) and name field

Co-Authored-By: internal-model
- README: worktrunk hooks pitch, wt.toml wiring, hooks table, troubleshooting (5+ sections, fenced blocks, comparison table)
- CI: dprint check + deno lint on push/PR to main (basic, mirrors systemfsoftware dprint.json)

Co-Authored-By: internal-model
Co-Authored-By: internal-model
- Replace hardcoded 9-row hook table with generic pattern description pointing to *.ts at root
- Avoid stale README when hooks are added

Co-Authored-By: internal-model
- Replace hardcoded script listings and tables with clean architecture overview
- Reference generic *.ts CLI execution pattern and lib/ split
- Update clone URL to worktrunk-scripts and clarify wt.toml integration

Co-Authored-By: internal-model
- Describe root vs lib/ separation conceptually without enumerating individual files
- Prevents documentation drift as files are added or refactored

Co-Authored-By: internal-model
- LICENSE: Apache 2.0 (matching systemfsoftware)
- CONTRIBUTING: setup, structure invariants (standalone CLI root scripts, lib/ helpers), dprint gates, conventional commits

Co-Authored-By: internal-model
Co-Authored-By: internal-model
- Remove enumerated file lists, specific version requirements, dprint config values, and example commit listings
- Retain only core workflow tasks (deno task fmt/check) and structural conventions

Co-Authored-By: internal-model
- differential_test.ts: 7 paired tests running upstream bash (/tmp/upstream-bash)
  and Deno hooks on identical fixtures, asserting identical transformations:
  tryRelative vs realpath, resolvePrimaryRepo, convert-to-relative-paths,
  worktree-to-relative, post-switch, pre-merge, pre-start (symlink targets +
  gitdir content)
- pre-merge.ts: globToRegExp escaped [0-9] character classes, so issue
  symlink globs never matched; replace with explicit regexes
- deno.lock: generated by deno test

Co-Authored-By: internal-model
User does not want the differential tests.

Co-Authored-By: internal-model
- gate on git add -A exit status: staging failure now fails the hook
  instead of letting the merge proceed with unstaged symlinks
- split lstat race from remove failure: remove errors are logged, not
  swallowed, so a symlink that fails to delete is never silently merged
- single readDir pass (pattern.some) instead of one scan per glob
- skip git add entirely when nothing was removed
- reuse lib/fs isSymlink and lib/git runGit instead of inline duplicates
- CI: drop `2>/dev/null || deno lint` fallback that made the typecheck
  gate inert (type errors fell through to a green re-lint)

Co-Authored-By: internal-model
- install-deps/generate-artifacts: propagate child exit codes (upstream
  set -e contract) instead of logging and exiting 0 on build/install
  failure; pip fallback now gated too
- pre-merge: run git add -A unconditionally (repairs a partially-failed
  prior run) while keeping the exit gate
- codegraph-worktree-mcp: match bash instance sanitization exactly
  (non-overlapping -- collapse; bash leaves a--b from a---b) and strip
  trailing slash before basename so .mcp.json points at the real volume
- worktree-to-relative: use lib/git.ts resolvePrimaryRepo instead of the
  local re-implementation (drops the "not a git repo at null" message)
- deno task check: add deno check so the local gate typechecks like CI
- README: wt.toml variables are {{ primary_worktree_path }}, not
  {{ primary_path }} — the undefined variable aborted hook expansion

Co-Authored-By: internal-model
- 9 hook CLIs + lib/ moved from repo root to scripts/ (git mv; internal
  ./lib and ./codegraph-worktree-mcp.ts relative references unchanged)
- deno task check and CI typecheck glob updated to scripts/*.ts scripts/lib/*.ts
- README/CONTRIBUTING updated: wt.toml paths, design, conventions

Co-Authored-By: internal-model
@ryanleecode
ryanleecode merged commit 6aaa352 into main Aug 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants