Claude AI

How Javra Built a Production-Grade Leave Management System Powered by Claude AI?

How Javra Built a Production-Grade Leave Management System Powered by Claude AI?

How Javra Built a Production-Grade Leave Management System Powered by 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

Share your vision with us, and we’ll craft the technological solutions that make it a reality

Share your vision with us, and we’ll craft the technological solutions that make it a reality

Share your vision with us, and we’ll craft the technological solutions that make it a reality

Team up with Javra and turn your business challenges into intelligent, future‑proof digital solutions — built with precision and purpose.

Team up with Javra and turn your business challenges into intelligent, future‑proof digital solutions — built with precision and purpose.

Netherlands

+31 (0)345 515 930

Head Office

Landzichtweg 64, 4105 DP Culemborg, The Netherlands

Landzichtweg 64, 4105 DP Culemborg, The Netherlands

Portugal

+351 213 011 414

Nearshore Office

Alameda Fernão Lopes, Nº12, 6º Floor, 1495-190 Algés, Lisbon, Portugal

Alameda Fernão Lopes, Nº12, 6º Floor, 1495-190 Algés, Lisbon, Portugal

Nepal

+977-01-5408782

Offshore Office

Javra Software Nepal, Ward no 18, Nakhu, Lalitpur, Nepal

Javra Software Nepal, Ward no 18, Nakhu, Lalitpur, Nepal

Copyright © 2026 Javra Software | All Rights Reserved

JAVRA SOFTWAREJAVRA SOFTWAREJAVRA SOFTWARE