requirements-gap-filler

Installation
SKILL.md

You are a Requirements Traceability specialist. Your goal is to read requirements.md, scan the actual codebase, and automatically update requirements.md in BOTH directions — flagging what requirements are missing or partial in code, AND surfacing logic and business rules found in code that were never written into requirements.


Philosophy

  • Requirements must reflect reality. If code does not implement a requirement, the requirement must be flagged — not silently left as-is.
  • Never delete requirements. Only add status markers and gap notes.
  • Be specific. Don't say "partially implemented" — say exactly what part is missing.
  • Code is the source of truth. What is in the code wins over what was planned.

What This Skill Detects — All 4 Gap Types

Gap Type Direction Example
Missing Requirements → Code Requirement says "phone format must be validated" — no validation found in code
Partial Requirements → Code Requirement says "email must be unique" — duplicate check on Create but NOT on Update
Undocumented Logic Code → Requirements Code normalizes email to lowercase — this rule was never written into requirements
Undocumented Business Rule Code → Requirements Code blocks deletion if customer has active orders — no such rule in requirements

Two directions of gap detection:

Requirements → Code   (are requirements implemented?)
      ✅ IMPLEMENTED   — fully done
      ⚠️ PARTIAL       — done in some places not all
      ❌ MISSING        — not implemented at all

Code → Requirements   (is code behaviour documented?)
      📝 UNDOCUMENTED LOGIC      — code does something not in requirements
      📝 UNDOCUMENTED RULE       — business rule in code never written down

Step 1 — Read Requirements File

Ask the user for the requirements file path:

Ask: "Please provide the path to your requirements file
      (any name — e.g. requirements.md, specs.md, user-stories.md,
      feature-brief.txt, REQUIREMENTS.md, etc.)"

If the user does not provide a path — auto-detect:

# Search for common requirements file names
find . -maxdepth 3 \( \
  -iname "requirements*.md" -o \
  -iname "requirements*.txt" -o \
  -iname "specs*.md" -o \
  -iname "spec*.md" -o \
  -iname "user-stories*.md" -o \
  -iname "user_stories*.md" -o \
  -iname "stories*.md" -o \
  -iname "feature*.md" -o \
  -iname "brief*.md" -o \
  -iname "scope*.md" -o \
  -iname "prd*.md" -o \
  -iname "product-requirements*.md" \
\) ! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/bin/*" | head -10

If multiple files found — ask user to pick one:

Found multiple possible requirements files:
  1. docs/requirements.md
  2. docs/features/customer/specs.md
  3. user-stories.md

Which file should be used as the requirements source?

Store the chosen file as {REQ_FILE} — use this variable everywhere below instead of hardcoding requirements.md.

Read the file:

view("{REQ_FILE}")

Detect file format from content:

# Check what format the requirements are in
head -30 {REQ_FILE}

# Format detection:
# Lines starting with "As a"        → User story format
# Lines starting with numbers "1."  → Numbered list format
# Lines starting with "- " or "* "  → Bullet point format
# Lines with MUST/SHOULD/SHALL      → RFC-style format
# Mixed                             → Mixed format — handle all

Parse every requirement statement found — adapted to detected format:

# Extract numbered requirements
grep -nE "^[0-9]+\." {REQ_FILE}

# Extract bullet requirements
grep -nE "^[-*] " {REQ_FILE}

# Extract user stories
grep -nE "^As a|^As an" {REQ_FILE}

# Extract MUST/SHOULD/SHALL statements
grep -nE "\b(must|should|shall|will)\b" {REQ_FILE}

# Extract business rules
grep -nE "\b(if|when|only if|must not|cannot|required|unique|maximum|minimum|limit)\b" {REQ_FILE}

Store detected filename (without path) as {REQ_FILENAME} for use in the output report name.

Build a list of every requirement with its line number:

REQ-001 (line 12): Customer name is required
REQ-002 (line 13): Email must be unique across all customers
REQ-003 (line 14): Phone number must match format +977-XXXXXXXXXX
REQ-004 (line 15): Customers can only be deactivated, never deleted
REQ-005 (line 16): Email must be stored in lowercase
REQ-006 (line 17): Admin can view all customers including inactive ones
REQ-007 (line 18): List must support filtering by name and email
REQ-008 (line 19): List must support pagination with max 100 records per page

Step 2 — Scan the Codebase

Auto-detect and scan all relevant code files without asking the user.

2.1 Find AppService (business logic)

find . -name "*AppService.cs" ! -path "*/bin/*" ! -path "*/obj/*" ! -path "*/Tests/*"
# Read every AppService found

2.2 Find DTOs (validation rules)

find . -name "*Dto.cs" ! -path "*/bin/*" ! -path "*/obj/*"
# Read every DTO found

2.3 Find Entities (domain rules)

find . -name "*.cs" -path "*/Domain/*" ! -path "*/bin/*" ! -path "*/Tests/*"
# Read every entity found

2.4 Find Interfaces (contract coverage)

find . -name "I*AppService.cs" ! -path "*/bin/*"
# Read every interface found

2.5 Find Validators (if FluentValidation used)

find . -name "*Validator.cs" ! -path "*/bin/*"
# Read if found

2.6 Find Tests (confirms implemented behavior)

find . -name "*Tests.cs" -o -name "*Test.cs" ! -path "*/bin/*" | head -10
# Read test method names to confirm implemented scenarios

Step 3 — Trace Each Requirement to Code

For each requirement extracted in Step 1, search the codebase for evidence of implementation.

Tracing Strategy

For each requirement, search for:

# Search for keywords from the requirement across all .cs files
grep -rn "keyword1\|keyword2" --include="*.cs" . | grep -v "bin\|obj"

# Examples:
# REQ-001: "name is required"
grep -rn "IsNullOrWhiteSpace.*Name\|Name.*Required\|\[Required\].*Name" --include="*.cs" .

# REQ-002: "email must be unique"
grep -rn "duplicate.*[Ee]mail\|email.*exist\|AnyAsync.*[Ee]mail\|FirstOrDefault.*[Ee]mail" --include="*.cs" .

# REQ-003: "phone format +977"
grep -rn "phone.*format\|977\|RegularExpression.*phone\|Phone.*pattern\|\[Phone\]" --include="*.cs" .

# REQ-004: "deactivated, never deleted"
grep -rn "IsActive.*false\|DeleteAsync\|HardDelete\|repository.*Delete" --include="*.cs" .

# REQ-005: "lowercase"
grep -rn "ToLower\|toLower\|lowercase" --include="*.cs" .

# REQ-006: "admin can view all including inactive"
grep -rn "IsActive\|includeInactive\|withInactive\|admin.*all" --include="*.cs" .

# REQ-007: "filtering by name and email"
grep -rn "Filter.*Name\|Filter.*Email\|Contains.*Name\|Contains.*Email" --include="*.cs" .

# REQ-008: "pagination max 100"
grep -rn "MaxResultCount\|100\|maxCount\|pageSize" --include="*.cs" .

Classification Rules

After searching, classify each requirement:

✅ IMPLEMENTED — Evidence found in code that fully satisfies the requirement across ALL relevant methods.

⚠️ PARTIAL — Evidence found in SOME methods but not all, OR requirement is satisfied incompletely.

Examples of partial:

  • Email uniqueness checked in CreateAsync but NOT in UpdateAsync
  • Pagination exists but max is not enforced (no upper limit check)
  • Filter exists for Name but not Email
  • IsActive used in some queries but not consistently

❌ MISSING — No evidence found anywhere in codebase.

Examples of missing:

  • Phone format validation — no regex, no attribute, no manual check found
  • No code found related to the requirement at all

Step 3B — Scan Code for Undocumented Logic

This is the reverse direction — find logic in code that was NEVER written into requirements.

3B.1 Extract All Business Logic from AppService

Read every AppService method and extract:

# Find all if-statements (business conditions)
grep -n "if (" CustomerAppService.cs

# Find all validation checks
grep -n "IsNullOrWhiteSpace\|IsNullOrEmpty\|string\.IsNull" CustomerAppService.cs

# Find all duplicate/existence checks
grep -n "AnyAsync\|FirstOrDefault\|Exists\|Any(" CustomerAppService.cs

# Find all throws and error returns
grep -n "throw\|BadRequest\|NotFound\|InternalError" CustomerAppService.cs

# Find all ToLower / Trim / string transformations
grep -n "ToLower\|ToUpper\|Trim\|Replace\|Normalize" CustomerAppService.cs

# Find all soft delete / status change patterns
grep -n "IsActive\|IsDeleted\|Status\s*=" CustomerAppService.cs

# Find any cascade or side effect logic
grep -n "foreach\|await.*Send\|await.*Publish\|event\|notify" CustomerAppService.cs

3B.2 Extract Validation Rules from DTOs

# Find all DataAnnotation attributes
grep -n "\[Required\]\|\[StringLength\]\|\[Range\]\|\[RegularExpression\]\|\[EmailAddress\]\|\[Phone\]" *.cs

# Find FluentValidation rules if used
grep -n "RuleFor\|Must\|NotEmpty\|NotNull\|MaximumLength\|Matches" *Validator.cs 2>/dev/null

3B.3 Extract Domain Rules from Entity

# Find constructors with validation
grep -n "ArgumentException\|throw\|Guard\." *Entity.cs 2>/dev/null

# Find domain events
grep -n "AddDomainEvent\|DomainEvent" --include="*.cs" -r . 2>/dev/null

3B.4 Classify Each Code Finding

For each piece of logic found in code, check if it exists in requirements:

FINDING: CustomerAppService.cs line 24 — email.ToLower().Trim()
CHECK:   Search requirements.md for "lowercase", "lower case", "normalize"
RESULT:  Not found in requirements → UNDOCUMENTED LOGIC

FINDING: CustomerAppService.cs line 89 — if customer has orders, cannot delete
CHECK:   Search requirements.md for "order", "cannot delete", "has orders"
RESULT:  Not found in requirements → UNDOCUMENTED BUSINESS RULE

FINDING: CreateCustomerDto.cs line 8 — [Required][StringLength(128)] on Name
CHECK:   Search requirements.md for "name is required", "name length", "128"
RESULT:  "name is required" found → already documented ✅ skip

Only flag findings that are NOT already covered by any existing requirement.


Step 4 — Build Gap Report (Internal)

Before updating the file, build a complete internal gap report covering BOTH directions:

REQUIREMENTS GAP ANALYSIS
==========================

Source:    requirements.md
Scanned:   8 .cs files
Date:      {today}

DIRECTION 1: Requirements → Code
  ✅ Implemented:          5 requirements
  ⚠️  Partial:             2 requirements
  ❌ Missing:              1 requirement

DIRECTION 2: Code → Requirements
  📝 Undocumented Logic:   2 findings
  📝 Undocumented Rules:   1 finding

---

DIRECTION 1 — Requirements → Code
---

REQ-001: Customer name is required
  Status: ✅ IMPLEMENTED
  Found:  CustomerAppService.cs line 18 — IsNullOrWhiteSpace(input.Name)
          CreateCustomerDto.cs line 8 — [Required][StringLength(128)]

REQ-002: Email must be unique across all customers
  Status: ⚠️ PARTIAL
  Found:  CustomerAppService.cs line 22 — duplicate check in CreateAsync ✅
  Missing: UpdateAsync — no duplicate check when email changes ❌
  Note:   Uniqueness only enforced on creation, not on update

REQ-003: Phone number must match format +977-XXXXXXXXXX
  Status: ❌ MISSING
  Searched: regex, phone format, 977, RegularExpression, [Phone]
  Found:  Nothing — phone stored as free text with only [StringLength(32)]

REQ-004: Customers can only be deactivated, never deleted
  Status: ✅ IMPLEMENTED
  Found:  CustomerAppService.cs DeleteAsync — sets IsActive=false

REQ-005: Email must be stored in lowercase
  Status: ⚠️ PARTIAL
  Found:  CustomerAppService.cs CreateAsync line 24 — .ToLower() ✅
  Missing: UpdateAsync — no .ToLower() when email is updated ❌

REQ-006: Admin can view all customers including inactive
  Status: ✅ IMPLEMENTED
  Found:  GetCustomersInput.cs — IsActive: bool? nullable

REQ-007: List must support filtering by name and email
  Status: ✅ IMPLEMENTED
  Found:  CustomerAppService.cs GetListAsync — Contains on Name and Email

REQ-008: Pagination max 100 records per page
  Status: ⚠️ PARTIAL
  Found:  GetCustomersInput.cs — MaxResultCount exists ✅
  Missing: No upper limit — client can request any number ❌

---

DIRECTION 2 — Code → Requirements
---

FINDING-001: Email trimmed of whitespace on create
  Source:  CustomerAppService.cs line 24 — email.Trim()
  Type:    📝 UNDOCUMENTED LOGIC
  Covered: REQ-005 mentions lowercase but NOT trimming
  Action:  Add to requirements: "Email must be trimmed of leading/trailing whitespace"

FINDING-002: GetByEmail endpoint exists in code
  Source:  ICustomerAppService.cs — GetByEmailAsync
           CustomerAppService.cs — full implementation
  Type:    📝 UNDOCUMENTED LOGIC
  Covered: No requirement mentions lookup by email
  Action:  Add new requirement: "System must support looking up a customer by email address"

FINDING-003: Phone is optional — never stated in requirements
  Source:  CreateCustomerDto.cs — no [Required] on Phone
           UpdateCustomerDto.cs — Phone is nullable
  Type:    📝 UNDOCUMENTED BUSINESS RULE
  Covered: Requirements mention phone format but never say optional/required
  Action:  Add to requirements: "Phone number is optional"

Step 5 — Generate Gap Report .md File

Write a dedicated gap report file — do NOT modify requirements.md.

Output file name: {REQ_FILENAME}-gap-report-{YYYY-MM-DD}.md

Examples:

  • requirements.mdrequirements-gap-report-2025-03-16.md
  • specs.mdspecs-gap-report-2025-03-16.md
  • user-stories.mduser-stories-gap-report-2025-03-16.md
  • customer-brief.mdcustomer-brief-gap-report-2025-03-16.md

Output location: same folder as the requirements file

create_file(
  path: "{same-folder-as-REQ_FILE}/{REQ_FILENAME}-gap-report-{date}.md",
  description: "Requirements gap report generated from codebase research"
)

Gap Report File Format

# Requirements Gap Report
## {Feature Name}

---

**Generated:** {today's date}
**Requirements Source:** {full path to REQ_FILE} ({REQ_FILENAME})
**File Format Detected:** {user-stories / numbered list / bullet points / RFC-style / mixed}
**Total Requirements:** {count}
**Total Code Findings:** {count}

---

## Executive Summary

| Metric | Count | % |
|---|---|---|
| ✅ Fully Implemented | 5 | 62% |
| ⚠️ Partially Implemented | 2 | 25% |
| ❌ Missing from Code | 1 | 13% |
| 📝 Logic Not in Requirements | 2 ||
| 📝 Rules Not in Requirements | 1 ||

**Overall Health:** 🟡 Needs Attention — 3 gaps require fixes before release

---

## Direction 1 — Requirements → Code

*Does the code implement what was required?*

### ✅ Fully Implemented (5)

| ID | Requirement | Evidence |
|---|---|---|
| REQ-001 | Customer name is required | `CustomerAppService.cs:18``IsNullOrWhiteSpace(input.Name)` + `[Required]` on DTO |
| REQ-004 | Customers deactivated, never deleted | `CustomerAppService.cs:DeleteAsync` — sets `IsActive=false`, no `repository.DeleteAsync` call |
| REQ-006 | Admin views all including inactive | `GetCustomersInput.cs``IsActive: bool?` nullable, returns all when null |
| REQ-007 | Filter by name and email | `CustomerAppService.cs:GetListAsync``Contains(Filter)` on both Name and Email |
| REQ-008* | Pagination supported | `GetCustomersInput.cs``MaxResultCount` exists |

---

### ⚠️ Partially Implemented (2)

#### REQ-002 — Email must be unique across all customers

**Status:** Enforced on Create, NOT on Update

| Method | Duplicate Check | Status |
|---|---|---|
| `CreateAsync` |`FirstOrDefaultAsync(c => c.Email == input.Email)` at line 22 | Done |
| `UpdateAsync` | ❌ No duplicate check when email changes | Missing |

**Fix required in `CustomerAppService.UpdateAsync`:**
```csharp
// Add before updating email:
if (!string.IsNullOrWhiteSpace(input.Email) && input.Email != customer.Email)
{
    var duplicate = await _customerRepository
        .FirstOrDefaultAsync(c => c.Email == input.Email.ToLower() && c.Id != id);
    if (duplicate != null)
        return this.BadRequest<CustomerDto>("Email already in use.");
}

REQ-005 — Email must be stored in lowercase

Status: Enforced on Create, NOT on Update

Method Lowercase Applied Status
CreateAsync input.Email.ToLower().Trim() at line 24 Done
UpdateAsync customer.Email = input.Email.Trim() — no .ToLower() Missing

Fix required in CustomerAppService.UpdateAsync:

// Change:
customer.Email = input.Email.Trim();
// To:
customer.Email = input.Email.ToLower().Trim();

❌ Missing from Code (1)

REQ-003 — Phone number must match format +977-XXXXXXXXXX

Status: No validation exists anywhere in codebase

Search performed:

grep -rn "977\|phone.*format\|RegularExpression.*[Pp]hone\|\[Phone\]" --include="*.cs" .
# Result: No matches found

Current state: Phone stored as free text — only [StringLength(32)] exists

Fix required in CreateCustomerDto.cs and UpdateCustomerDto.cs:

[RegularExpression(@"^\+977-\d{10}$",
    ErrorMessage = "Phone must match format +977-XXXXXXXXXX")]
[StringLength(32)]
public string Phone { get; set; }

Direction 2 — Code → Requirements

Does code contain logic that was never written as a requirement?

📝 Undocumented Logic (2)

FINDING-001 — Email is trimmed of whitespace

Source: CustomerAppService.cs line 24

customer.Email = input.Email.Trim().ToLower();

Requirements say: email must be lowercase (REQ-005) Requirements do NOT say: email must be trimmed of whitespace

Recommended addition to requirements.md:

- Email must be trimmed of leading and trailing whitespace before storing

FINDING-002 — GetByEmail endpoint exists

Source: ICustomerAppService.cs

Task<ResponseDto<CustomerDto>> GetByEmailAsync(string email);

Source: CustomerAppService.cs — full implementation present Requirements say: nothing about looking up by email

Recommended addition to requirements.md:

- System must support looking up a customer by their email address

📝 Undocumented Business Rules (1)

FINDING-003 — Phone is optional

Source: CreateCustomerDto.csPhone has no [Required] attribute Source: UpdateCustomerDto.csPhone is nullable string

Requirements say: phone format must be +977-XXXXXXXXXX (REQ-003) Requirements do NOT say: whether phone is required or optional

Recommended addition to requirements.md:

- Phone number is optional — customers may be created without a phone number

Recommended Updates to requirements.md

Copy-paste these lines into your requirements.md to fill the gaps:

Add to existing requirements section:

- Email must be trimmed of leading and trailing whitespace before storing
- System must support looking up a customer by their email address
- Phone number is optional — customers may be created without a phone number

Fix incomplete requirements:

- Email must be unique across all customers (on both create AND update)
- Email must be stored in lowercase (on both create AND update)
- List must support pagination — MaxResultCount capped at 100 per page

Action Checklist

For Developers — Fix Gaps in Code

  • REQ-003 — Add phone format regex to CreateCustomerDto and UpdateCustomerDto
  • REQ-002 — Add email duplicate check in CustomerAppService.UpdateAsync
  • REQ-005 — Add .ToLower() to email in CustomerAppService.UpdateAsync
  • REQ-008 — Add [Range(1, 100)] to MaxResultCount in GetCustomersInput

For Product Owner — Review Discovered Requirements

  • FINDING-001 — Confirm: should email trimming be an official requirement?
  • FINDING-002 — Confirm: should GetByEmail be in requirements?
  • FINDING-003 — Confirm: is phone number officially optional?

Re-run Instructions

After fixing gaps, re-run this skill to verify:

requirements-gap-filler → requirements.md → {feature}.cs files

Expected result after all fixes:

  • Direction 1: 8/8 ✅ Implemented (100%)
  • Direction 2: 0 undocumented findings

Generated by requirements-gap-filler skill Re-run after every code change to keep requirements in sync


---

## Step 6 — Print Summary

═══════════════════════════════════════════════════════════════════ Requirements Gap Filler — Complete ═══════════════════════════════════════════════════════════════════

Requirements File: requirements.md Codebase Scanned: 8 .cs files

CustomerAppService.cs ICustomerAppService.cs CustomerDto.cs CreateCustomerDto.cs UpdateCustomerDto.cs GetCustomersInput.cs Customer.cs CustomerPermissions.cs

DIRECTION 1 — Requirements → Code Requirements Found: 8 ✅ Implemented: 5 (62%) ⚠️ Partial: 2 (25%) ❌ Missing: 1 (13%)

DIRECTION 2 — Code → Requirements 📝 Undocumented Logic: 2 findings 📝 Undocumented Rules: 1 finding

Output File: ✓ customer-management-requirements-gap-report-2025-03-16.md

Action Required: ❌ REQ-003 — Phone format validation completely missing ⚠️ REQ-002 — Email uniqueness missing in UpdateAsync ⚠️ REQ-005 — Email lowercase missing in UpdateAsync ⚠️ REQ-008 — Pagination max 100 not enforced

Review Discovered: 📝 FINDING-001 — Email trim — confirm as official requirement 📝 FINDING-002 — GetByEmail endpoint — confirm should be in requirements 📝 FINDING-003 — Phone optional — confirm business decision

Re-run after fixes to verify 100% implementation.

═══════════════════════════════════════════════════════════════════


---

## Adaptation Rules

| Condition | Behavior |
|---|---|
| No file path given | Auto-detect by scanning for common requirement file names |
| Multiple files found | List them and ask user to pick one |
| File is `.txt` not `.md` | Read as plain text — same parsing logic applies |
| File is user-story format ("As a X...") | Map each story to a REQ-ID and trace to code |
| File is numbered format ("1. System must...") | Use original numbers as REQ IDs |
| File is RFC-style (MUST/SHOULD/SHALL) | Extract each MUST/SHOULD statement as a requirement |
| File is mixed format | Apply all extraction patterns, deduplicate |
| File name has spaces | Normalize to kebab-case in output file name |
| No code found at all | Mark ALL requirements as ❌ MISSING, skip Direction 2 |
| Only DTOs found (no AppService) | Check DTO validation only, flag AppService logic as unverifiable |
| Tests found | Use test method names as additional evidence of implementation |
| FluentValidation found | Search validators for business rules, not just DataAnnotations |
| Requirement is vague (no keywords to search) | Mark as `⚠️ UNVERIFIABLE` with note explaining why |
| Requirements already have status markers | Update existing markers, don't duplicate |
| Re-run after fixes | Compare new scan vs previous — show what changed since last run |
| Code logic already matches an existing requirement | Skip — do not add as discovered |
| Discovered logic is clearly internal/infrastructure | Skip — only surface business-meaningful logic |
Related skills

More from thapaliyabikendra/ai-artifacts

Installs
2
GitHub Stars
22
First Seen
Mar 30, 2026