Skip to content

refactor(cli): trim duplicated ai-context CLAUDE.md block#904

Merged
magyargergo merged 1 commit into
abhigyanpatwari:mainfrom
azizur100389:refactor/trim-ai-context-claude-md-block
Apr 18, 2026
Merged

refactor(cli): trim duplicated ai-context CLAUDE.md block#904
magyargergo merged 1 commit into
abhigyanpatwari:mainfrom
azizur100389:refactor/trim-ai-context-claude-md-block

Conversation

@azizur100389

Copy link
Copy Markdown
Contributor

Closes #856.

Summary

The block that `npx gitnexus analyze` injects between `` and `` into every project's CLAUDE.md and AGENTS.md is currently ~101 lines / ~5465 characters. Six sub-sections duplicate content that is already present in the installed skill files at `.claude/skills/gitnexus/*/SKILL.md`:

Section Already lives in
Tools Quick Reference gitnexus-guide.md
Impact Risk Levels gitnexus-impact-analysis.md
Self-Check Before Finishing gitnexus-refactoring.md
When Debugging step list gitnexus-debugging.md
When Refactoring step list gitnexus-refactoring.md
Keeping the Index Fresh detail block one-line freshness warning retained at top + gitnexus-cli.md

Both the CLAUDE.md block and every skill file are loaded into every Claude Code session, so this duplication costs tokens on every turn of every conversation in every indexed repo.

What changed

Rewrote the template literal inside `generateGitNexusContent()` at gitnexus/src/cli/ai-context.ts. Kept only content that is genuinely unique-per-repo or load-bearing for the agent before it picks a skill:

Retained:

  • Header + `projectName` + stats line
  • One-line freshness warning
  • `## Always Do` (imperatives the agent must know up-front)
  • `## Never Do` (safety constraints the agent must know up-front)
  • `## Resources` table (URI patterns interpolated with `projectName`)
  • `## Cross-Repo Groups` (conditional, unique per repo)
  • `## CLI` header + skills routing table (the load-bearing pointer that tells the agent which skill to read for each task)

Removed:

  • `## Tools Quick Reference`, `## Impact Risk Levels`, `## Self-Check Before Finishing`, `## When Debugging`, `## When Refactoring`, `## Keeping the Index Fresh`

Net reduction: 58 lines / ~2900 characters (~52% smaller). Post-trim block is ~40 lines / ~2580 characters.

Backward compatibility

  • `` / `` markers unchanged → the idempotent block-replacement logic continues to work on re-runs.
  • `generateAIContextFiles()` signature, export surface, and caller contracts unchanged — called from analyze.ts and run-analyze.ts with the same arguments.
  • All six skill files continue to be installed unchanged; they are now the single source of truth for the trimmed content.
  • `skipAgentsMd` and `noStats` flags are unaffected (they operate outside the template body).
  • No graph/index/storage schema change. Revert is a pure text rollback with no side effects.

Tests

Three new assertions added to gitnexus/test/unit/ai-context.test.ts:

  1. KEEP invariant — block still contains the freshness warning, `## Always Do`, `## Never Do`, `## Resources`, the `projectName`-interpolated URI (`gitnexus://repo/TestProject/context`), and the four skills-routing targets (impact-analysis, refactoring, debugging, cli).
  2. TRIM invariant — block does NOT contain any of the six removed headers.
  3. BUDGET invariant — block length < 2700 chars (catches any regression that pads the block back toward the original 5465 size; current post-trim is 2582).

All 6 existing tests still pass — including `updates existing CLAUDE.md without duplicating` (single `gitnexus:start` marker on re-run).

Test plan

  • `npx vitest run test/unit/ai-context.test.ts` → 9 pass (6 existing + 3 new)
  • `npm run test:unit` → 3770 pass (same 4 pre-existing env failures unchanged — `skip-git-cli.test.ts` needs built `dist/`, `git-utils.test.ts` Windows worktree tmpdir)
  • `npx tsc --noEmit` → clean
  • Pre-commit hook (lint-staged + eslint + prettier + tsc) → passed

The block that `npx gitnexus analyze` injects between
`<!-- gitnexus:start -->` and `<!-- gitnexus:end -->` into every
project's CLAUDE.md and AGENTS.md is ~101 lines / ~5465 characters.
Six sub-sections duplicate content that is already present in the
installed skill files at `.claude/skills/gitnexus/*/SKILL.md`:

  - Tools Quick Reference     -> gitnexus-guide/SKILL.md
  - Impact Risk Levels        -> gitnexus-impact-analysis/SKILL.md
  - Self-Check Before Finish  -> gitnexus-refactoring/SKILL.md
  - When Debugging step list  -> gitnexus-debugging/SKILL.md
  - When Refactoring steps    -> gitnexus-refactoring/SKILL.md
  - Keeping the Index Fresh   -> gitnexus-cli/SKILL.md (plus the
                                 one-line freshness warning retained
                                 at the top)

Both the CLAUDE.md block and every skill file are loaded into every
Claude Code session, so the duplication costs tokens on every turn
of every conversation in every indexed repo.

This PR trims to a ~40-line / ~2580-char block that keeps only
what is genuinely unique-per-repo or load-bearing for the agent
before it picks a skill:

  KEEP:
    - Header + projectName + stats line
    - One-line freshness warning
    - Always Do (imperatives the agent must know up-front)
    - Never Do (safety constraints the agent must know up-front)
    - Resources table (URI patterns interpolated with projectName)
    - Cross-Repo Groups (conditional, unique per repo)
    - CLI skills routing table (the load-bearing pointer)

Net reduction: 58 lines / ~2900 characters (~52% smaller). The
skills routing table already tells the agent which SKILL.md to
read for each task, so the trimmed sections are still reachable --
just no longer duplicated into every session.

Backward compat:

 - `<!-- gitnexus:start -->` / `<!-- gitnexus:end -->` markers
   unchanged -> the idempotent block-replacement logic keeps
   working on re-runs.
 - Function signature, export surface, and caller contracts
   unchanged -- generateAIContextFiles() is called from analyze.ts
   and run-analyze.ts with the same arguments.
 - All six skill files continue to be installed unchanged; they
   are now the single source of truth for the trimmed content.
 - skipAgentsMd and noStats flags are unaffected (they operate
   outside the template body).
 - No graph/index/storage schema change; revert is a pure text
   rollback with no side effects.

Tests: three new assertions layered on the existing ai-context
test suite:
  - KEEP: block still contains freshness warning, Always Do,
    Never Do, Resources URIs, and the four skills-routing
    targets (impact-analysis, refactoring, debugging, cli).
  - TRIM: block does NOT contain the six removed headers.
  - BUDGET: block length < 2700 chars (catches any regression
    that pads back toward the original 5465 size).

Verification:
  npx vitest run test/unit/ai-context.test.ts  -> 9 pass
  npm run test:unit                             -> 3770 pass
    (4 pre-existing env failures unchanged:
     skip-git-cli.test.ts needs built dist/,
     git-utils.test.ts Windows worktree tmpdir)
  npx tsc --noEmit                              -> clean

Closes abhigyanpatwari#856
@vercel

vercel Bot commented Apr 17, 2026

Copy link
Copy Markdown

@azizur100389 is attempting to deploy a commit to the NexusCore Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown
Contributor

CI Report

All checks passed

Pipeline Status

Stage Status Details
✅ Typecheck success tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
6606 6509 0 97 256s

✅ All 6509 tests passed

97 test(s) skipped — expand for details
  • Swift MethodExtractor > isTypeDeclaration > recognizes class_declaration
  • Swift MethodExtractor > isTypeDeclaration > recognizes protocol_declaration
  • Swift MethodExtractor > isTypeDeclaration > rejects import_declaration
  • Swift MethodExtractor > visibility > extracts public method
  • Swift MethodExtractor > visibility > extracts private method
  • Swift MethodExtractor > visibility > defaults to internal when no modifier
  • Swift MethodExtractor > protocol methods > marks protocol method as abstract
  • Swift MethodExtractor > static and class methods > detects static func as isStatic
  • Swift MethodExtractor > static and class methods > detects class func as isStatic
  • Swift MethodExtractor > parameters > extracts parameters with types and default values
  • Swift MethodExtractor > return type > extracts return type from -> annotation
  • Swift MethodExtractor > annotations > extracts @objc attribute
  • Swift MethodExtractor > isFinal > detects final func
  • Swift MethodExtractor > isFinal > is false when not final
  • Swift MethodExtractor > isAsync > detects async func
  • Swift MethodExtractor > isOverride > detects override method
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift cross-file constructor inference uses lookupClassByName
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift explicit init inference uses lookupClassByName
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift cross-file constructor inference does not bind plain functions
  • buildTypeEnv > known limitations (documented skip tests) > Ruby block parameter: users.each { |user| } — closure param inference, different feature
  • Swift constructor-inferred type resolution > detects User and Repo classes, both with save methods
  • Swift constructor-inferred type resolution > resolves user.save() to Models/User.swift via constructor-inferred type
  • Swift constructor-inferred type resolution > resolves repo.save() to Models/Repo.swift via constructor-inferred type
  • Swift constructor-inferred type resolution > emits exactly 2 save() CALLS edges (one per receiver type)
  • Swift self resolution > detects User and Repo classes, each with a save function
  • Swift self resolution > resolves self.save() inside User.process to User.save, not Repo.save
  • Swift parent resolution > detects BaseModel and User classes plus Serializable protocol
  • Swift parent resolution > emits EXTENDS edge: User → BaseModel
  • Swift parent resolution > emits IMPLEMENTS edge: User → Serializable (protocol conformance)
  • Swift cross-file User.init() inference > resolves user.save() via User.init(name:) inference
  • Swift cross-file User.init() inference > resolves user.greet() via User.init(name:) inference
  • Swift return type inference > detects User class and getUser function
  • Swift return type inference > detects save function on User (Swift class methods are Function nodes)
  • Swift return type inference > resolves user.save() to User#save via return type of getUser() -> User
  • Swift return-type inference via function return type > resolves user.save() to User#save via return type of getUser()
  • Swift return-type inference via function return type > user.save() does NOT resolve to Repo#save
  • Swift return-type inference via function return type > resolves repo.save() to Repo#save via return type of getRepo()
  • Swift implicit imports (cross-file visibility) > detects UserService class in Models.swift
  • Swift implicit imports (cross-file visibility) > resolves UserService() constructor call across files (no explicit import)
  • Swift implicit imports (cross-file visibility) > resolves service.fetchUser() member call across files
  • Swift implicit imports (cross-file visibility) > creates IMPORTS edges between files in the same module
  • Swift extension deduplication > detects Product class
  • Swift extension deduplication > resolves Product() constructor despite extension creating duplicate class node
  • Swift extension deduplication > resolves product.save() to Product.swift (primary definition)
  • Swift constructor call fallback (no new keyword) > resolves OCRService() as constructor call across files
  • Swift constructor call fallback (no new keyword) > resolves ocr.recognize() member call via constructor-inferred type
  • Swift export visibility (internal vs private) > resolves PublicService() constructor across files
  • Swift export visibility (internal vs private) > resolves internalHelper() across files (internal = module-scoped)
  • Swift if let / guard let binding resolution > detects User and Repo classes
  • Swift if let / guard let binding resolution > resolves user.save() inside if-let to User#save
  • Swift if let / guard let binding resolution > resolves repo.save() inside guard-let to Repo#save
  • Swift if let / guard let binding resolution > user.save() in if-let does NOT resolve to Repo#save
  • Swift await / try expression unwrapping > resolves user.save() via await fetchUser() return type
  • Swift await / try expression unwrapping > resolves repo.save() via try parseRepo() return type
  • Swift await / try expression unwrapping > detects fetchUser and parseRepo as functions
  • Swift for-in loop element type inference > detects User and Repo classes
  • Swift for-in loop element type inference > creates implicit import edges between files
  • Swift field-type resolution > detects classes and their properties
  • Swift field-type resolution > emits HAS_PROPERTY edges from class to field
  • Swift field-type resolution > resolves field-chain call user.address.save() → Address#save
  • Swift field-type resolution > emits ACCESSES edges for field reads in chains
  • Swift field-type resolution > populates field metadata (visibility, declaredType) on Property nodes
  • Swift call-result binding > resolves call-result-bound method call user.save() → User#save
  • Swift call-result binding > getUser() is present as a defined function
  • Swift call-result binding > emits processUser -> getUser CALLS edge for let-assigned free function call
  • Swift method enrichment > detects Animal protocol and Dog class
  • Swift method enrichment > emits IMPLEMENTS edge Dog -> Animal
  • Swift method enrichment > emits HAS_METHOD edges for Dog methods
  • Swift method enrichment > marks protocol Animal.speak as isAbstract
  • Swift method enrichment > marks Dog.speak as NOT isAbstract
  • Swift method enrichment > marks breathe as isFinal
  • Swift method enrichment > marks classify as isStatic
  • Swift method enrichment > captures @objc annotation on breathe
  • Swift method enrichment > populates parameterTypes for classify(_ name: String)
  • Swift method enrichment > records parameterCount for classify
  • Swift method enrichment > records returnType for speak
  • Swift method enrichment > resolves dog.speak() CALLS edge
  • Swift method enrichment > resolves Dog.classify("dog") CALLS edge
  • Swift abstract dispatch > detects Repository protocol and SqlRepository class
  • Swift abstract dispatch > emits IMPLEMENTS edge SqlRepository -> Repository
  • Swift abstract dispatch > emits HAS_METHOD edges for Repository.find and Repository.save
  • Swift abstract dispatch > emits HAS_METHOD edges for SqlRepository.find and SqlRepository.save
  • Swift abstract dispatch > marks base Repository.find as isAbstract
  • Swift abstract dispatch > marks base Repository.save as isAbstract
  • Swift abstract dispatch > marks concrete SqlRepository.find as NOT isAbstract
  • Swift abstract dispatch > resolves repo.find(id: 42) CALLS edge
  • Swift abstract dispatch > resolves repo.save(entity: user) CALLS edge
  • Swift abstract dispatch > populates parameterTypes for Repository.find
  • Swift abstract dispatch > populates parameterTypes for Repository.save
  • Swift abstract dispatch > records returnType for SqlRepository.find
  • Swift abstract dispatch > emits METHOD_IMPLEMENTS edges from SqlRepository methods → Repository protocol methods
  • Swift overloaded method disambiguation > detects 2 distinct find Method nodes on SqlRepository
  • Swift overloaded method disambiguation > emits METHOD_IMPLEMENTS edges for both find overloads
  • Swift overloaded method disambiguation > emits METHOD_IMPLEMENTS edge for save
  • Swift overloaded method disambiguation > emits exactly 3 METHOD_IMPLEMENTS edges total
  • Swift Child extends Parent — inherited method resolution (SM-9) > detects Parent and Child classes
  • Swift Child extends Parent — inherited method resolution (SM-9) > resolves c.parentMethod() to Parent.parentMethod via first-wins MRO walk

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 73.22% 17852/24380 73.22% = 0.0 🟢 ██████████████░░░░░░
Branches 62.24% 11340/18218 62.24% = 0.0 🟢 ████████████░░░░░░░░
Functions 77.82% 1688/2169 77.82% = 0.0 🟢 ███████████████░░░░░
Lines 75.78% 16185/21356 75.78% = 0.0 🟢 ███████████████░░░░░

📋 View full run · Generated by CI

@magyargergo magyargergo merged commit 925460a into abhigyanpatwari:main Apr 18, 2026
17 of 18 checks passed
@magyargergo magyargergo mentioned this pull request Apr 18, 2026
5 tasks
github714801013 pushed a commit to github714801013/GitNexus that referenced this pull request Apr 28, 2026
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.

ai-context: CLAUDE.md generated block duplicates content already in skill files

2 participants