|
| 1 | +--- |
| 2 | +status: planned |
| 3 | +created: '2025-12-18' |
| 4 | +tags: |
| 5 | + - architecture |
| 6 | + - rust |
| 7 | + - typescript |
| 8 | + - migration |
| 9 | + - deprecation |
| 10 | +priority: high |
| 11 | +created_at: '2025-12-18T09:33:42.792888425+00:00' |
| 12 | +depends_on: |
| 13 | + - 170-cli-mcp-core-rust-migration-evaluation |
| 14 | + - 172-rust-cli-mcp-npm-distribution |
| 15 | + - 173-rust-binaries-ci-cd-pipeline |
| 16 | +--- |
| 17 | + |
| 18 | +# Deprecate TypeScript Core in Favor of Rust Implementation |
| 19 | + |
| 20 | +> **Status**: 🗓️ Planned · **Created**: 2025-12-18 |
| 21 | +
|
| 22 | +## Overview |
| 23 | + |
| 24 | +With Rust implementations of CLI and MCP server now complete (specs 170, 172, 173), we need to deprecate all TypeScript core code and ensure TypeScript packages become thin wrappers around Rust binaries rather than reimplementing features. |
| 25 | + |
| 26 | +**Current Problem:** |
| 27 | +- `@leanspec/core` (TypeScript) still contains core logic |
| 28 | +- `@leanspec/ui` imports from `@leanspec/core` causing build dependencies |
| 29 | +- TypeScript and Rust implementations diverge over time |
| 30 | +- Double maintenance burden for features |
| 31 | +- CI workflows must build both TypeScript and Rust |
| 32 | + |
| 33 | +**Goal:** Single source of truth in Rust. TypeScript packages either deleted or become minimal adapters. |
| 34 | + |
| 35 | +## Current State |
| 36 | + |
| 37 | +### TypeScript Packages Using Core Logic |
| 38 | + |
| 39 | +**@leanspec/core** (`packages/core/src/`): |
| 40 | +- Frontmatter parsing/updating (`createUpdatedFrontmatter`) |
| 41 | +- File I/O utilities (`atomicWriteFile`) |
| 42 | +- Token counting (tiktoken-based) |
| 43 | +- Spec validation |
| 44 | +- Search utilities |
| 45 | + |
| 46 | +**@leanspec/ui** uses `@leanspec/core` for: |
| 47 | +- `createUpdatedFrontmatter` - updating spec frontmatter in API routes |
| 48 | +- `atomicWriteFile` - safe file writing |
| 49 | +- Files: `packages/ui/src/app/api/projects/[id]/specs/[spec]/metadata/route.ts` |
| 50 | +- Files: `packages/ui/src/app/api/projects/[id]/specs/[spec]/status/route.ts` |
| 51 | + |
| 52 | +**@leanspec/cli** (TypeScript version): |
| 53 | +- Entire CLI implementation wraps `@leanspec/core` |
| 54 | + |
| 55 | +**@leanspec/mcp** (TypeScript version): |
| 56 | +- MCP server wraps `@leanspec/core` |
| 57 | + |
| 58 | +### Rust Implementations (Already Complete) |
| 59 | + |
| 60 | +- `rust/leanspec-cli/` - Full CLI in Rust |
| 61 | +- `rust/leanspec-mcp/` - Full MCP server in Rust |
| 62 | +- `rust/leanspec-core/` - Core functionality library |
| 63 | +- Distribution via npm with platform-specific binaries (spec 172) |
| 64 | + |
| 65 | +## Migration Strategy |
| 66 | + |
| 67 | +### Phase 1: Remove TypeScript CLI/MCP Packages |
| 68 | +- [ ] Delete `packages/cli/` (TypeScript version) |
| 69 | +- [ ] Delete `packages/mcp/` (TypeScript version) |
| 70 | +- [ ] Update root `package.json` scripts to use Rust binaries |
| 71 | +- [ ] Update monorepo workspace config to remove these packages |
| 72 | +- [ ] Update documentation to reference Rust binaries only |
| 73 | + |
| 74 | +### Phase 2: Inline Minimal Functions in @leanspec/ui |
| 75 | +- [ ] Identify the 2 functions UI needs from `@leanspec/core`: |
| 76 | + - `createUpdatedFrontmatter` - Update spec frontmatter fields |
| 77 | + - `atomicWriteFile` - Safe file writing |
| 78 | +- [ ] Create `packages/ui/src/lib/spec-utils/frontmatter.ts` with inline implementation |
| 79 | +- [ ] Create `packages/ui/src/lib/spec-utils/file-ops.ts` with inline implementation |
| 80 | +- [ ] Update imports in affected files: |
| 81 | + - `packages/ui/src/app/api/projects/[id]/specs/[spec]/metadata/route.ts` |
| 82 | + - `packages/ui/src/app/api/projects/[id]/specs/[spec]/status/route.ts` |
| 83 | +- [ ] Remove `@leanspec/core` from UI's `devDependencies` |
| 84 | +- [ ] Test metadata/status update endpoints work correctly |
| 85 | + |
| 86 | +### Phase 3: Delete @leanspec/core Package |
| 87 | +- [ ] Mark `@leanspec/core` as deprecated in npm (publish final version) |
| 88 | +- [ ] Add deprecation notice to README |
| 89 | +- [ ] Publish final version with deprecation notice |
| 90 | +- [ ] Delete `packages/core/` directory entirely |
| 91 | +- [ ] Remove from monorepo workspace configuration |
| 92 | +- [ ] Update `pnpm-workspace.yaml` to remove core package |
| 93 | + |
| 94 | +### Phase 4: Update CI/CD |
| 95 | +- [ ] Remove TypeScript build from CI (except UI) |
| 96 | +- [ ] Simplify CI to: Rust build → UI build (inline utils) |
| 97 | +- [ ] Update publish workflows |
| 98 | +- [ ] Remove `pnpm build` from copilot-setup-steps (except UI) |
| 99 | + |
| 100 | +### Phase 5: Documentation Updates |
| 101 | +- [ ] Update AGENTS.md to clarify Rust is primary |
| 102 | +- [ ] Update CONTRIBUTING.md |
| 103 | +- [ ] Update architecture diagrams |
| 104 | +- [ ] Remove references to TypeScript CLI/MCP/core |
| 105 | +- [ ] Add migration guide for contributors |
| 106 | + |
| 107 | +## Decision: Inline Functions in UI Package |
| 108 | + |
| 109 | +**Approach: Inline 2 Functions Directly in @leanspec/ui** |
| 110 | + |
| 111 | +Only 2 functions from `@leanspec/core` are used by UI: |
| 112 | +- `createUpdatedFrontmatter` (used in 2 API routes) |
| 113 | +- `atomicWriteFile` (used in 1 API route) |
| 114 | + |
| 115 | +**Implementation:** |
| 116 | +```typescript |
| 117 | +// packages/ui/src/lib/spec-utils/frontmatter.ts |
| 118 | +import matter from 'gray-matter'; |
| 119 | + |
| 120 | +export function createUpdatedFrontmatter(content: string, updates: Record<string, any>) { |
| 121 | + const { data, content: body } = matter(content); |
| 122 | + const updated = { ...data, ...updates }; |
| 123 | + return matter.stringify(body, updated); |
| 124 | +} |
| 125 | + |
| 126 | +// packages/ui/src/lib/spec-utils/file-ops.ts |
| 127 | +import { writeFile, rename } from 'fs/promises'; |
| 128 | +import { join } from 'path'; |
| 129 | + |
| 130 | +export async function atomicWriteFile(filePath: string, content: string): Promise<void> { |
| 131 | + const tmpPath = `${filePath}.tmp`; |
| 132 | + await writeFile(tmpPath, content, 'utf-8'); |
| 133 | + await rename(tmpPath, filePath); |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +**Rationale:** |
| 138 | +- Only ~20 lines of code total |
| 139 | +- No point maintaining entire package for 2 functions |
| 140 | +- UI already has `gray-matter` as dependency |
| 141 | +- Simpler architecture, fewer packages to manage |
| 142 | +- Desktop already uses Rust directly (no TypeScript core) |
| 143 | + |
| 144 | +## Verification |
| 145 | + |
| 146 | +- [ ] `pnpm build` works with only Rust + UI |
| 147 | +- [ ] UI functionality unchanged (metadata updates, etc.) |
| 148 | +- [ ] CI passes without TypeScript CLI/MCP/core |
| 149 | +- [ ] No imports from deleted packages |
| 150 | +- [ ] Documentation updated |
| 151 | +- [ ] Deprecation notices published |
| 152 | + |
| 153 | +## Risks |
| 154 | + |
| 155 | +1. **Breaking changes for contributors** - Clear communication needed |
| 156 | +2. **Build system changes** - Need to update CI/CD pipelines |
| 157 | +3. **Complex migration** - Incremental approach mitigates |
| 158 | + |
| 159 | +## Related Specs |
| 160 | + |
| 161 | +- 170-cli-mcp-core-rust-migration-evaluation |
| 162 | +- 172-rust-cli-mcp-npm-distribution |
| 163 | +- 173-rust-binaries-ci-cd-pipeline |
| 164 | +- 180-rust-distribution-workflow-alignment |
0 commit comments