Commit Graph

2 Commits

Author SHA1 Message Date
Tom Boucher
5292bc5477 refactor(3597): extract captureConsole + toPosixPath to helpers; dedup makeTmp wrappers; CLAUDE.md MemPalace
## Helper deduplication (16 files)

Two genuinely-duplicated test helpers extracted to tests/helpers.cjs:

- captureConsole(fn) → {stdout, stderr} with ANSI strip + exception
  re-throw after console restore (preserves the #2775 CR contract).
  Removed from 6 bug-N test files (bug-2775, bug-2829, bug-3033,
  bug-3211, bug-3231, bug-3359) where the implementation was either
  byte-identical or trivially-different. installer-migration-install-
  integration's captureConsole has a different signature ({value,
  output}) and stays as-is.

- toPosixPath(p) → p with path.sep → '/'. Returns input unchanged if
  null/undefined for safe optional-chain composition. Replaces the
  local normalizePath in bug-3491-nested-git-worktree (the
  prune-orphaned-worktrees inline normalizeSlashes was already swapped
  for canonicalPath in the cluster-J batch).

## makeTmp/mkScratch wrappers (8 files)

Reduced each local wrapper from a 3-line fs.mkdtempSync(path.join(
os.tmpdir(), ...)) block to a 1-line arrow delegating to
createTempDir (already in helpers.cjs). Bug-number prefix conventions
stay local for readability:

  - bug-2256, bug-2794, feat-3023, feat-3024 → `gsd-<bug>-${prefix}-`
  - bug-3288 → makeTmpDir = createTempDir (identity)
  - bug-3571 → 'gsd-3571-' (no parameter)
  - feat-3595 → mkScratch = `fs-fault-${name}-`
  - project-root-generator → 'gsd-parity-'

bug-3288 also collapsed local rmTmpDir into `cleanup` from helpers
(removes a separate inline rmSync site).

## CLAUDE.md — MemPalace protocol

Adds explicit instruction to call mempalace_status at session start
and mempalace_search / mempalace_kg_query before answering questions
about people, past work, or prior decisions in this project.

## Why this is a real consolidation

Initial survey suggested the bug-N test files could be parameterized
into one install-end-to-end.test.cjs — that turned out to oversell the
savings (~200 LOC on 2238) and to bury per-bug fixture context in a
table. The genuinely duplicated surface was the helpers themselves:
captureConsole copy-pasted ~6×, makeTmp variant copy-pasted ~8×.
Extracting them retires ~170 LOC of pure copy-paste without changing
any test semantics.

Validated: holodeck (ubuntu docker) 11232/0 pass; ratchet guard
still 7/7 at baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 12:52:46 -04:00
Tom Boucher
a3ca6ff6d6 feat(3553): Project-Root Resolution Module via generator (Phase 4 of #3524)
Phase 4 of the CJS↔SDK hard-seam migration (parent #3524).
Eliminates the `findProjectRoot` duplication that lived at
bin/lib/core.cjs:74-140 and sdk/src/query/helpers.ts:497-590,
the drift carrier behind historical bugs #1362 and #2561.

- sdk/src/project-root/index.ts — source of truth (120 lines,
  pure-with-sync-fs). Exports findProjectRoot(startDir: string)
  and FIND_PROJECT_ROOT_MAX_DEPTH constant.
- sdk/src/project-root/index.test.ts — 13 vitest pinning fixtures
  covering all four heuristics, the #1362 guard, malformed
  config fallback, empty sub_repos, deep nesting, and depth-limit
  enforcement.
- sdk/scripts/gen-project-root.mjs — generator. Captures
  function body via Function.prototype.toString() from compiled
  sdk/dist/. Emits CJS preamble for destructured node:fs /
  node:path / node:os imports.
- sdk/scripts/check-project-root-fresh.mjs — freshness check.
  Imports the generator function directly (Phase 3's cleaner
  pattern).
- get-shit-done/bin/lib/project-root.generated.cjs — generator-
  emitted CJS mirror.
- tests/project-root-generator.test.cjs — 11 parity assertions
  comparing SDK source and generated CJS for every fixture.

- sdk/src/query/helpers.ts: -127 lines. The 94-line inline
  findProjectRoot plus the FIND_PROJECT_ROOT_MAX_DEPTH constant
  (originally at line 471) replaced by a single re-export:
  `export { findProjectRoot } from '../project-root/index.js';`
  Removed unused `parse as parsePath` import.
- get-shit-done/bin/lib/core.cjs: -83 lines net. The 67-line
  inline findProjectRoot replaced by a single
  `require('./project-root.generated.cjs')`. The detectSubRepos
  helper at lines 40-56 stays (used by loadConfig migration).

- sdk/package.json: gen:project-root + check:project-root-fresh
  scripts.
- package.json: proxy for the freshness check.
- .githooks/pre-commit: drift block.
- .github/workflows/test.yml: drift check step after the
  state-document drift step.
- CONTEXT.md: Project-Root Resolution Module entry.
- docs/INVENTORY.md, docs/INVENTORY-MANIFEST.json:
  +1 module count, +1 row.

- Full suite: 9226/9226 pass (baseline 9215 + 11 new parity
  fixtures).
- SDK vitest: 1804/1804 pass.
- Reader shrink: -127 SDK + -83 CJS = 210 lines of duplication
  deleted across the two Readers. New shared Module is 120 lines.

1. Depth limit canonicalization. CJS findProjectRoot previously
   had no explicit walk-up bound (walked until dir === root or
   homedir). The new Module uses FIND_PROJECT_ROOT_MAX_DEPTH = 10,
   matching the SDK's pre-existing value. Only affects paths
   nested more than 10 levels deep from a .planning/ root — a
   pathological case in practice. None of the existing 22 CJS
   findProjectRoot tests covered this; the new parity test does.
2. platformReadSync → readFileSync. The old CJS findProjectRoot
   used the platformReadSync wrapper from
   shell-command-projection.cjs for reading .planning/config.json,
   which returns null on read failure. The Module uses raw
   readFileSync, which throws — caught by the surrounding
   try/catch that already swallowed errors. Functionally
   equivalent for the existing code path; no test exercises the
   null-return semantic.

Closes #3553.
2026-05-15 10:07:10 -04:00