Skip to content

refactor: ponytail lean pass — delete dead FP layer (Either/Railway)#74

Merged
m2ux merged 4 commits into
mainfrom
ponytail/lean-pass
Jun 30, 2026
Merged

refactor: ponytail lean pass — delete dead FP layer (Either/Railway)#74
m2ux merged 4 commits into
mainfrom
ponytail/lean-pass

Conversation

@m2ux

@m2ux m2ux commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Ponytail lean-coding pass (ultra · repo)

Drives the codebase toward its leanest form: climb to rung 1 (delete/YAGNI) for the high-confidence cuts, then properly refactor the one structural issue that a deletion couldn't fix — while holding the safety floor (esp. error handling).

Cumulative: 20 files, +219 / −1353. Four independently-reviewable commits.

Commits

# Commit Change
1 refactor: ponytail lean pass — delete dead FP layer Delete either.ts (316) + railway.ts (412); trim the functional/ barrel + README to Result+Option; delete 5 stale .gitkeep. No code consumed any Either/Railway symbol.
2 chore(deps): drop unused epub2 dependency epub2 declared but imported nowhere (the EPUB loader uses epub).
3 refactor: delete 4 dead classes from legacy exceptions Remove the 4 zero-reference classes from the flat domain/exceptions.ts.
4 refactor: unify exception hierarchies under ConceptRAGError Re-home the 3 live legacy exceptions into a new DataIntegrityError category under ConceptRAGError; delete the flat file. One hierarchy.

The exception unification (commit 4)

The two parallel hierarchies are now one. The 3 read-path errors (ConceptNotFoundError, InvalidEmbeddingsError, SchemaValidationError) move into domain/exceptions/data-integrity.ts as a DataIntegrityError category under ConceptRAGError.

  • Constructor signatures, properties, messages, and error codes preserved verbatim → the ~10 throw sites and the repo instanceof checks change only their import path.
  • Deliberate, tested behaviour change: these errors are now instanceof ConceptRAGError, so BaseTool.handleError emits their structured form (code + context + timestamp) instead of a bare message — the consistency win. This is exactly what made a blind migration unsafe before; it's now pinned by tests.
  • Removed a vestigial export * from '../exceptions.js' leak in domain/models/index.ts (nothing consumed exceptions via the models barrel).

New test coverage for paths that previously had none:

  • domain/exceptions/__tests__/data-integrity.test.ts — props/codes/instanceof.
  • tools/base/__tests__/tool.test.ts — pins the structured boundary output.

Investigated and intentionally left alone

  • scripts/ — documented operational tooling (CONTRIBUTING/FAQ/SETUP/TROUBLESHOOTING/USAGE, ADRs, a dedicated diagnostics/README.md), not dead code.
  • WordNet SynsetSelectionStrategy — has two real, separately-tested implementations + a public setStrategy() seam; meets the "second concrete case exists" bar, so the abstraction is earned.

Checked and cleared: EmbeddingProviderFactory (4 providers), DocumentLoaderFactory (multi-loader), the DI interfaces (real impls + test doubles), Result/Option.

Verification

  • tsc -p tsconfig.build.json typecheck — clean (after each commit)
  • Unit suite (vitest run, excl. service-dependent integration/e2e/ail) — 63 files, 1213 tests, all pass
  • error-handling.integration.test.ts16 tests pass

Ponytail workflow artifacts were produced locally but are intentionally not committed to this branch.

🤖 Generated with Claude Code

Ultra-intensity, repo-scope Ponytail lean-coding pass. Climbs to rung 1
(delete/YAGNI) for the high-confidence cuts and leaves the rest as decisions.

Applied (provably zero behaviour change):
- Delete src/domain/functional/either.ts (316 LOC) and railway.ts (412 LOC):
  no non-test, non-barrel code consumed any Either or Railway symbol. Result
  and Option carry all real error/nullable handling and are kept.
- Trim the functional barrel (index.ts) and README to Result + Option only.
- Delete 5 stale .gitkeep placeholders in now-populated dirs.
- Mark the deliberate ceiling with one ponytail: marker in index.ts.

Not applied (left as deliberate decisions):
- Two parallel exception hierarchies (crosses the error-handling safety floor).
- WordNet single-production-strategy abstraction (owner judgement call).

Verified: tsc -p tsconfig.build.json typecheck clean; 1207 unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@m2ux m2ux force-pushed the ponytail/lean-pass branch from 137c14e to f790de0 Compare June 30, 2026 07:08
m2ux and others added 3 commits June 30, 2026 08:24
epub2 was declared in dependencies but imported nowhere — the EPUB loader
uses the separate epub package. Removing it drops a dead runtime dependency.

Verified: tsc -p tsconfig.build.json typecheck clean; 1207 unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The flat domain/exceptions.ts hierarchy declared 8 classes but only 3 are
referenced anywhere: SchemaValidationError, InvalidEmbeddingsError, and
ConceptNotFoundError (LanceDB read path). Delete the 4 with zero references:
SourceNotFoundError, InvalidQueryError, DatabaseOperationError, and
MissingParameterError. (The live InvalidQueryError is the one in
domain/exceptions/search.ts, which is unaffected.)

The 3 live classes are kept on the standalone DomainException base rather than
merged into the ConceptRAGError hierarchy: that migration would change
tool-boundary error formatting and error codes, and no test (unit or
integration) covers these throw paths. A ponytail: marker records the ceiling
and its upgrade trigger.

Verified: tsc -p tsconfig.build.json typecheck clean; 1207 unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves the two-parallel-hierarchies issue properly, instead of leaving the
legacy flat exceptions on a separate base.

- Add domain/exceptions/data-integrity.ts: a DataIntegrityError category under
  ConceptRAGError for the read-path errors (stored data doesn't match
  expectations), with ConceptNotFoundError, InvalidEmbeddingsError, and
  SchemaValidationError. Constructor signatures, public properties, messages,
  and error codes are preserved verbatim, so the ~10 throw sites and the repo
  instanceof checks change only their import path.
- Repoint the 3 importers (schema-validators + 2 LanceDB repos) at
  domain/exceptions/index.js and merge the duplicate same-module imports.
- Delete the flat domain/exceptions.ts and its vestigial re-export from
  domain/models/index.ts (nothing imported exceptions via the models barrel).

Behaviour change, made deliberate and now tested: these 3 errors are now
instanceof ConceptRAGError, so BaseTool.handleError emits their structured form
(code + context + timestamp) at the tool boundary instead of a bare message.

Adds the coverage these throw paths never had:
- domain/exceptions/__tests__/data-integrity.test.ts (props/codes/instanceof)
- tools/base/__tests__/tool.test.ts (pins the structured boundary output)

Verified: tsc -p tsconfig.build.json clean; unit suite 63 files / 1213 tests
pass; error-handling.integration.test.ts (16 tests) passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@m2ux m2ux merged commit 6223136 into main Jun 30, 2026
5 checks 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.

1 participant