Claude AI

Leave Management Migration
Spec-Driven Legacy Migration with Claude Code
The Legacy System
An internal Leave Management System serving ~580 employees across three countries, built on a stack that's becoming a liability.
· OpenEdge ABL + proprietary XFiles framework (2009-era, no documentation)
· Two tightly coupled databases (framework config + business data)
· Thick-client admin app + jQuery web portal from 2011
· 27 database tables, 98 business rules, country-specific logic for Nepal, Netherlands, Portugal
· Hiring OpenEdge developers is nearly impossible
· License renewal approaching – migrating eliminates recurring cost
Why This Matters
This isn't a greenfield build. It's replacing a running production system that 580 people depend on daily.
· Every business rule must be preserved – Nepal's monthly accrual, NL's statutory expiry, Portugal's carry-forward
· Data must migrate cleanly – years of leave history, balances, attendance records
· Zero downtime expectation – parallel run before cutover
· The old system has no tests, no documentation – all knowledge lives in procedure code
· Getting a single rule wrong means someone's leave balance is incorrect
The Approach
Spec-Driven Development with Claude Code
What Is Claude Code?
Claude Code is Anthropic's AI coding agent that runs in your terminal. It reads files, writes code, runs commands, and executes tests – guided by project-level configuration.
· Not a chatbot – it operates directly on your codebase, running real commands
· Configurable – project instructions, rules, hooks, skills, and agents define its behavior
· Persistent memory – remembers decisions and conventions across sessions
· One developer + Claude Code built this entire system in 9 days (137 commits)
What Is Spec-Driven Development?
Instead of coding first and documenting later, we write specifications first and use them as the contract between human decisions and AI implementation.
· Product spec (product.md, 250 lines) – what and why, 73 requirements across 14 areas
· System spec (system.md, 2,250 lines) – how, full architecture, schemas, algorithms
· Legacy spec (legacy.md, 700 lines) – reverse-engineered from source code and live databases
· Task plan (tasks.md) – ordered implementation tasks mapped to spec sections
· Design spec (design.md) – visual patterns, tokens, accessibility rules
Total spec surface: ~3,200 lines. Every line of code traces back to a spec section.
Specifications Drive Everything
Every implementation file starts with a @spec traceability comment linking back to the specification.

· No orphan code – if it can't reference a spec section, it shouldn't exist
· No undocumented behavior – if the spec doesn't describe it, don't build it
· Reviewable contracts – management can read product.md and know exactly what's being built
· AI stays on track – Claude Code reads the specs before writing any code
The Journey: From Legacy Black Box to Running System
Phase 1 — Understand:
1. Discovery Agent – legacy DBs+Source
2. Legacy.md- 27 tables,98 rules
3. Product.md- 73 requirements
4. System.md- full architecture
5. tasks.md + design.md (self-learning loop arrow back to Discovery Agent)- plam+tokens
Phase 2 — Configure:
6. CLAUDE.md +11 rules + 8 hooks+ permissions
Phase 3 — Build (repeats)
7. /discovery - deep extraction
8. /task-prep –checklist contract
9. Implement – hooks catch drift
10. /task-review – PASS/FAIL per item
11. /retro -evolve config
12. /milestone-reviewer - integration
Key properties
Understand first, code second
Config is version-controlled
Build loop has quality gates
System teaches itself via retro
Human decides, AI executes
How We Set It Up
Teaching the AI the Project
Configuring Claude Code
Claude Code is configured through a layered system of instructions, rules, and automation.
Layer | File(s) | Purpose |
Project instructions | CLAUDE.md | Commands, ports, connection strings, directory map |
Rules | .claude/rules/*.md (11 files) | Constraints: testing, security, services, DB, TypeScript |
Agents | .claude/agents/*.md (7 agents) | Specialized reviewers: architecture, DB, frontend, security |
Skills | .claude/skills/ (5 skills) | Reusable workflows: task-prep, task-review, CRUD scaffold |
Hooks | .claude/hooks/*.sh (8 hooks) | Automated checks: drift detection, structure validation |
Memory | .claude/memory/ | Persistent context across sessions |
All configuration is version-controlled alongside the code -- the AI's instructions evolve with the project.
The Bootstrap Sequence
The configuration wasn't written all at once. It evolved over the first few days.
1. Day 1: Specs first – wrote product.md, system.md, legacy.md from stakeholder interviews + legacy DB exploration
2. Day 1: Scaffold – CLAUDE.md with commands and ports; first rules (structure.md, database.md, typescript.md)
3. Day 2: Discovery agent – built to extract legacy business rules; ran against each domain before coding
4. Day 2-3: First CRUD cycle – built Employees manually, noticed the repeating 16-file pattern
5. Day 3: Skills emerge – codified CRUD into /crud-scaffold; created /task-prep and /task-review
6. Day 4+: Rules from corrections – every time Claude Code was corrected, the correction became a rule file
The Self-Learning Loop
The discovery agent teaches itself project conventions across sessions via persistent memory.

Each correction in Session N becomes a know pattern in Session N+1. Fewer corrections needed over time.
Legacy Discovery
Extracting Knowledge from a System with No Documentation
The Discovery Challenge
The legacy system has no tests, no documentation, no API contracts. Business rules exist only as OpenEdge ABL procedures, database triggers, and framework event handlers.
· 98 business rules spread across ~70 procedure files
· Logic dispatched through a framework event system (xevent table in DB)
· Country-specific branches buried in conditionals (IF xmcon = 8 THEN /* Nepal */)
· Balance calculations involve 12-month arrays, carry-forward chains, pro-rata rules
· Leave day counting depends on schedules, holidays, half-days, and country-specific inclusions
How Discovery Works
The discovery agent connects to live legacy databases and reads source code to produce structured artifacts.
1. Dump data first – query every table the domain touches; data IS the business rules
2. Read ABL source – every line of the relevant procedures, not skimming
3. Trace event handlers – follow the framework dispatch chain to find all code paths
4. Annotate every branch – what each conditional does, which country it applies to
5. Cross-reference – verify code understanding against actual data dumps
6. Produce per-domain artifacts – saved to artifacts/discovery/ for persistence
Artifacts are not summaries-they're annotated function-level extractions with brancehes, edge cases, and test scenarios.
Discovery Domains Extracted
Domain | Key Findings |
Schema | 27 tables mapped, column-level types, relationships, orphaned tables identified |
Framework | XFiles dispatch mechanism decoded, event lifecycle documented |
Leave Core | Day calculation, overlap detection, duplicate checking, fiscal year rules |
Balance Management | Monthly accrual arrays, carry-forward chains, pro-rata, NL expiry rules |
Leave Application | State machine (6 states), validation gates, approval chain logic |
Balance Accrual | Nepal: 0.5 days/month (Annual), 1.0 days/month (Casual); NL: full allocation |
Each domain extraction directly feeds into the task checklists for implementation.
Developer Workflow
The Day-to-Day Loop with Claude Code
The Full task Lifecycle

Step 1: Task Prep – The Checklist Contract
/task-prep reads three sources and produces a numbered checklist.
Source | What it extracts |
specs/tasks.md | Task description, spec refs, dependencies |
product.md + system.md | Requirements and architecture sections |
artifacts/discovery/ | Legacy extraction – code, edge cases, test scenarios |
· Hard gate: no legacy extraction = task-prep stops (run /discovery first)
· Each requirement gets a test tier tag ([unit], [integration], [e2e])
· Edge cases from legacy code become explicit checklist items
· Output saved to artifacts/checklists/T[n]-checklist.md
Step 2: Implement – Hooks in the Loop
During implementation, hooks run automatically on every action.
· Before shell commands – validate-command.sh blocks npx, npm, bare tsc; suggests bun equivalent
· After every file edit – post-edit.sh auto-formats with Biome, checks schema consistency
· CRUD entities – /crud-scaffold generates all 16 files across the full stack in one pass
Layer | /crud-scaffold generates |
Shared | Zod schemas + TypeScript types |
Server | SQL queries, service, routes, test factory |
Tests | Service tests (mock DB), route tests (mock session) |
Web | API client, list page, form page, nav entry |
Docs | Endpoint contracts in contracts.md |
Step 3: Task Review – Verify the Checklist
/task-review is not a general code review – it's a point-by-point verification against the checklist.
· Each R-item: implemented? Correct vs legacy? Tested at tagged tier?
· Traceability – every new file has @spec on line 1
· Cross-layer agreement – shared schema = DB row type = service = route = web client
· Automated checks – typecheck -> lint -> test -> integration -> e2e -> drift
· Verdict: DONE or NEEDS WORK (loops back to implement)
Step 4: Retro – The System Evolves
/retro runs at session end and proposes improvements to the configuration itself.
What it checks | Example outcome |
Repeated corrections | User fixed undefined vs null twice -> new rule update-queries.md |
Repeated workflows | Third CRUD entity followed same pattern -> new skill /crud-scaffold |
Spec drift | 3 endpoints added but not in contracts.md -> flagged for update |
CLAUDE.md staleness | New env var introduced -> flagged for documentation |
· The human reviews every proposal – nothing is auto-applied
· This is how the AI's configuration gets smarter over time
· 11 rule files and 5 skills were all born from this loop
Test Pyramid
Each requirement gets one primary test tier – the lowest tier that verifies the behavior.
Tier | Runner | What belongs here |
Unit | bun test / vitest | Pure logic, schema validation, mapping functions |
Integration | bun test (real DB) | Service + DB, queries, constraints, state transitions |
E2E | Playwright | User-visible flows: forms, navigation, multi-page
|
| Server | Web | E2E | SQL migrations |
Source files | 119 | 126 | – | 857 lines |
Test files | 46 | 19 | 11 | – |
Results
1 Developer + AI Agent, 9 Days, 137 Commits
Progress at a Glance
20 of 35 tasks complete. Three milestones shipped, three remaining.
Milestone | Scope | Status |
M1: Foundation | Scaffold, auth, employee/leave-type/holiday/schedule CRUD | Complete |
M2: Leave Core | Day calc, balances, application, approval, delegation, notifications | Complete |
M2.5: Self-Service | Employee read-only views (balances, holidays, schedule) | Complete |
M3: Secondary Workflows | Compensatory, WFH, lateness, worklog | Next up |
M4: Reporting | Door records, exit tracking, reports, batch notifications | Planned |
M5: Data Migration | Extract, transform, load, verify, parallel run, cutover | Planned |
What's Been Built – Foundation (M1)
· Monorepo scaffold (shared / server / web / e2e packages)
· Entra ID OIDC authentication with role derivation
· Employee, Leave Type, Holiday, Schedule CRUD – full API + admin UI
· AppShell layout with role-based navigation
· Shared UI component library (DataTable, FormField, Modal, StatusBadge)
· Settings and fiscal year administration
What's Been Built – Leave Core (M2)
· Leave day calculation engine – half-days, holidays, schedules, cross-month spans
· Balance management – allocation, carry-forward, pro-rata, monthly accrual, NL expiry
· Leave application – overlap/duplicate detection, balance preview
· Approval workflow – approve/reject/withdraw/cancel with balance deduction and restoration
· Supervisor delegation – transfer approval role during absence
· Notifications – in-app + email via Azure Communication Services
· Admin balance management – adjustments, monthly accrual detail view
· Employee self-service – read-only views for balances, holidays, schedules
Key Design Decisions
Decision | Choice | Why |
Stack | TypeScript + Bun + Hono + React | Shared language, fast runtime, lightweight server |
Database | PostgreSQL, raw SQL (no ORM) | Full control, matches legacy complexity |
Auth | Entra ID OIDC | Existing SSO infrastructure |
Monthly accrual | On-the-fly computation | No batch job, simpler than legacy's 12-month arrays |
Withdraw from approved | Allowed (balance restored) | Legacy behavior preserved |
Specs | Written before code | AI can't drift if the contract is explicit |
Test strategy | Integration-heavy | Business rules depend on DB behavior |
Takeaways
What Makes This Different
Aspect | Traditional Migration | Spec-Driven + AI Agent |
Discovery | Manual reverse-engineering, scattered notes | Automated extraction with annotated artifacts |
Specification | Written after or during implementation | Written first, drives everything |
Implementation | Developer interprets requirements | AI implements against concrete checklist |
Quality gates | Manual code review | Automated hooks + specialized review agents |
Drift | Specs and code diverge over time | Hooks enforce sync on every change |
Knowledge | In people's heads | In version-controlled specs and rules |
Onboarding | Weeks of context gathering | Read the specs, read the rules |
The Human-AI Division of Labor
The human makes all architectural and business decisions. The AI executes with high fidelity.
· Human decides: what to build, how to structure it, which business rules to preserve, design direction
· AI executes: writes code, runs tests, catches drift, applies patterns consistently
· Human reviews: task-review output, milestone-review findings, design choices
· AI remembers: project conventions, past decisions, patterns – across sessions via persistent memory
The specs are the interface between human judgment and AI execution.
Risk Mitigation
· Business rule fidelity – every legacy rule has a spec reference, a checklist item, and a test
· Data migration – planned parallel run (M5) to verify before cutover
· Security – defense-in-depth enforced by rules; every action checked at backend and frontend
· Knowledge retention – all decisions live in specs and rules, not in anyone's head
· Quality – 76 test files, automated drift checks, specialized review agents
· Rollback – parallel run period means legacy system stays available
What's Next
· M3: Secondary workflows – compensatory claims, WFH requests, lateness tracking, worklog integration
· M4: Reporting & attendance – door records, exit tracking, Excel export, batch notifications
· M5: Data migration & cutover – extract from OpenEdge, transform, load, verify, parallel run
· Cross-cutting – audit trail, GDPR data erasure, OWASP security pass, WCAG accessibility pass
Q&A
Leave Management System Migration
Spec-Driven Development with Claude Code
TypeScript · Bun · React · PostgreSQL
Share Blog

Building the future of intelligent automation with AI agents that think, act, and deliver real business results.
Life at Javra
Products
Our Solutions
Others
Netherlands
+31 (0)345 515 930
Head Office
Portugal
+351 213 011 414
Nearshore Office
Nepal
+977-01-5408782
Offshore Office
Copyright © 2026 Javra Software | All Rights Reserved


