Commit graph

40 commits

Author SHA1 Message Date
Jorrin
96578aa4a8
feat: add optional limit arg to --embeddings flag (closes #382) (#1375) 2026-05-06 16:31:28 +01:00
Copilot
6372b0bfeb
fix(cli): --skip-git treats cwd as index root instead of walking up to parent git repo (#1245) 2026-05-01 09:49:48 +01:00
Gergő Magyar
2a0c97c178
fix: add platform-aware semantic fallback (#1150)
* fix: add platform-aware semantic fallback

Make VECTOR an optional capability so Windows analysis remains stable while semantic embeddings can fall back to exact scan when native vector indexing is unavailable.

Made-with: Cursor

* fix: remove stale vector pool import

Keep the merge with main lint-clean after VECTOR loading moved out of the read pool.
2026-04-28 12:21:25 +01:00
Gergő Magyar
38ccf7ceb1
fix: recover worker parse stalls (#1121)
* fix(ingestion): recover worker parse stalls

Made-with: Cursor

* test(ingestion): cover worker timeout controls

Made-with: Cursor

* docs: document analyze worker timeout controls

Made-with: Cursor

* fix(ingestion): fail fast after worker pool hard failure

Made-with: Cursor

* test(ingestion): stabilize worker stall recovery tests

Made-with: Cursor

---------

Co-authored-by: GitNexus Maintainer <maintainer@gitnexus.local>
2026-04-27 20:07:03 +01:00
Copilot
2b0392cd83
feat(analyze): preserve existing embeddings by default; --force regenerates them; add --drop-embeddings opt-out (CLI + HTTP API) (#1055)
* Initial plan

* fix(analyze): preserve existing embeddings by default; add --drop-embeddings opt-out

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/da1da041-afcd-4d38-8a2f-39ca52a462ff

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* analyze: --force on embedded repo now regenerates embeddings (preserve+top-up)

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/e2759765-b8f6-453a-8c28-595439d23cb4

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* analyze: wire dropEmbeddings into HTTP API; log cache-load failures; extract pure deriveEmbeddingMode + behavioral tests; sync GUARDRAILS.md

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/7d88e595-cbd8-47b2-ba4f-fb5b9a60cda4

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
2026-04-24 13:07:40 +01:00
azizur100389
ee871419e1
feat(ingestion): GITNEXUS_INDEX_TEST_DIRS opt-in for __tests__ / __mocks__ (#771) (#1046)
* feat(ingestion): GITNEXUS_INDEX_TEST_DIRS opt-in for __tests__ / __mocks__ (#771)

The DEFAULT_IGNORE_LIST hardcodes __tests__ and __mocks__ as
auto-filtered directory names. The comment at ignore-service.ts:273
explicitly documents this as intentional — .gitnexusignore negation
cannot override hardcoded entries. That default is right for the
majority of users, but for Quality Engineering workflows where test
files are the primary index target (tracing coverage via CALLS
edges), there was no escape hatch short of patching the installed
package.

Add an opt-in env var mirroring the GITNEXUS_NO_GITIGNORE /
GITNEXUS_MAX_FILE_SIZE precedent:
`GITNEXUS_INDEX_TEST_DIRS=1` removes __tests__ / __mocks__ from the
effective ignore set. Scope is deliberately limited to these two
names — the issue asked for these specifically, and other
test-adjacent entries (__snapshots__, snapshots, fixtures, .jest)
remain auto-filtered unchanged. .gitnexusignore negation semantics
are not touched; the env var is the orthogonal escape hatch.

Implementation: new `isEffectivelyIgnoredDirectory` helper in
ignore-service.ts wraps the `DEFAULT_IGNORE_LIST.has(name)` check
with the env-var opt-out. Two call-sites swap: shouldIgnorePath
(affects filesystem walker and wiki generator) and
createIgnoreFilter.childrenIgnored (affects directory pruning
during traversal). `isHardcodedIgnoredDirectory` export unchanged —
its contract is "is in the raw list", which remains true for
__tests__ / __mocks__ regardless of env var state (locked in by a
test).

Default behaviour is byte-identical for users who don't set the env
var. 9 new unit tests cover default-unset, opt-in-set, scoped scope
(other hardcoded entries unaffected), and the scope-discipline
guard (future expansion beyond the two named dirs fails loudly).
Env state restored by afterEach to prevent leakage.

Closes #771.

* feat(ingestion): .gitnexusignore negation overrides hardcoded DEFAULT_IGNORE_LIST (#771)

Per @magyargergo's review feedback: rather than add a special-case
GITNEXUS_INDEX_TEST_DIRS env var to unlock __tests__ / __mocks__,
let .gitnexusignore use !pattern negation to override the hardcoded
DEFAULT_IGNORE_LIST — mirroring the .gitignore mental model users
already know.

Implementation:
- New private hasExplicitUnignore(ig, rel) helper that walks ancestor
  segments and uses ignore.test(path)'s `unignored` flag to detect
  explicit negation. Ancestor-walk is required because .gitignore
  negation propagates — !__tests__/ implicitly unignores every
  descendant, but ignore.test() only reports unignored: true on the
  directly-matched path.
- createIgnoreFilter.ignored() and .childrenIgnored() now check
  hasExplicitUnignore BEFORE applying the hardcoded DEFAULT_IGNORE_LIST.
  If any ancestor (or the path itself) was explicitly unignored in
  .gitnexusignore, the hardcoded block is bypassed.
- shouldIgnorePath stays pure hardcoded-list — the wiki generator and
  other callers without per-repo config context keep deterministic
  behavior. The #771 override lives only inside createIgnoreFilter,
  which IS called with config.

Dropped:
- GITNEXUS_INDEX_TEST_DIRS env var (superseded by the more general
  negation mechanism)
- isEffectivelyIgnoredDirectory helper
- Associated env-var help text and unit tests

Added:
- Tip in analyze --help pointing users at .gitnexusignore with
  !__tests__/ as the example
- 8 new unit tests covering default behaviour, directory-level
  negation, selective overrides, generalisation (!node_modules/),
  non-leakage across hardcoded entries, standard non-negation rules
  still layering on top, and preservation of shouldIgnorePath /
  isHardcodedIgnoredDirectory contracts

Default behaviour (no .gitnexusignore or no negation pattern) is
byte-identical to pre-#771. Users who want to index an auto-filtered
directory add a single !pattern line — no env var, no flag, no
re-install.

Closes #771.

* fix(ingestion): honour re-ignore rules after .gitnexusignore negation (#771)

When .gitnexusignore contains both `!__tests__/` and
`__tests__/generated/`, the parent negation previously short-circuited
and allowed the re-ignored child through. Consult `ig.ignores(rel)`
after `hasExplicitUnignore` so a more-specific rule in the same file
correctly re-ignores a subset — matching .gitignore's last-match-wins
semantics. Adds a compound-pattern test locking this in.
2026-04-23 13:49:06 +01:00
Sonu Verma
253f9cae37
feat(ingestion): make large-file skip threshold configurable (#1044)
* feat(ingestion): make large-file skip threshold configurable

The walker previously hardcoded a 512KB skip threshold, which silently dropped legitimate large source files (e.g. ~900KB hand-written Java service classes) during analysis with no way to override short of editing source.

Allow overrides via the GITNEXUS_MAX_FILE_SIZE env var (KB) — consistent with the existing GITNEXUS_NO_GITIGNORE / GITNEXUS_VERBOSE patterns — and a matching --max-file-size <kb> flag on gitnexus analyze.

- New utility getMaxFileSizeBytes() in core/ingestion/utils/max-file-size.ts parses the env var, falls back to the 512KB default for missing/invalid values, and clamps against TREE_SITTER_MAX_BUFFER (32MB) to keep the downstream parser safe.
- filesystem-walker.ts now resolves the threshold per call and drops the 'likely generated/vendored' editorial when the user has explicitly raised the limit.
- analyze CLI wires --max-file-size to the env var and echoes a one-line notice when the threshold is overridden, mirroring how --no-gitignore is handled.
- index.ts documents the new flag and env var under the analyze help text.
- Warnings for invalid or out-of-range values are emitted exactly once per distinct value to avoid log spam.

Tests:
- New test/unit/max-file-size.test.ts covers defaults, KB parsing, clamp-at-ceiling, invalid-input fallback + warn-once, and distinct-value warnings.
- test/integration/filesystem-walker.test.ts gains a 'large file skip threshold (#991)' block: 600KB fixture skipped by default, included under GITNEXUS_MAX_FILE_SIZE=1024, invalid values fall back and warn once, and the 'generated/vendored' suffix is only emitted under the default threshold.

Closes #991

* fix(cli): show effective clamped max-file-size in banner

Addresses the PR #1044 review finding: the startup banner printed the raw GITNEXUS_MAX_FILE_SIZE value rather than the clamped effective threshold, producing misleading telemetry when the value exceeded the 32 MB tree-sitter ceiling.

The banner is also suppressed when the effective threshold equals the default, removing log noise when operators explicitly set the value to the current default.

Extracted the logic into a new getMaxFileSizeBannerMessage() helper and pinned the behavior with unit tests covering default, raised override, invalid fallback, and above-ceiling clamp cases.
2026-04-23 11:07:37 +01:00
azizur100389
bd271da7b7
feat(cli): gitnexus remove <target> to unindex a registered repo by name or path (#664) (#1003)
* feat(cli): gitnexus remove <target> to unindex a registered repo by name or path (#664)

Add a `remove` CLI command that deletes the `.gitnexus/` index AND
unregisters a repo from the global registry (~/.gitnexus/registry.json),
addressing the lifecycle gap flagged in #664: previously users had to
cd into the repo to run `clean`, and there was no path-based or
alias-based remove for an already-deleted working tree.

- New command `gitnexus remove <target> [-f|--force]`. `<target>` is
  alias / basename-derived name / remote-inferred name / absolute path.
- New helper `resolveRegistryEntry(entries, target)` in repo-manager.ts
  with path > name precedence; throws RegistryNotFoundError or
  RegistryAmbiguousTargetError (typed, `kind`-discriminated).
- Atomicity mirrors `clean`: fs.rm first, then unregisterRepo; partial
  failures self-heal on next `listRegisteredRepos({ validate: true })`.
- Idempotent on unknown targets (exit 0 with warning) per the #664
  spec: "behave atomically and idempotently so retries are safe".
- `--force` uses `clean`-style confirmation-skip semantics — distinct
  from `analyze --force` (pipeline re-index); here there is no pipeline
  so no conflation.
- 7 new unit tests cover resolver precedence, case sensitivity,
  ambiguity, and not-found hints; 2 integration tests cover the real
  CLI -> registry -> filesystem chain including the --allow-duplicate-name
  (#829) ambiguity case.

* fix(cli): canonicalize repo paths so remove/register match across platforms (#1003 review)

Address review feedback from @evander-wang and @magyargergo on PR #1003
plus the Windows + macOS CI failure (same root cause).

Problem:
- macOS: /var is a symlink to /private/var. `path.resolve` does NOT
  follow symlinks, so a child running analyze in /var/folders/X stores
  /private/var/folders/X (realpath from OS cwd) but an outer caller
  passing the symlink form misses.
- Windows: GitHub runners surface tmpdirs in 8.3 short-name form
  (RUNNERA~1) while process.cwd() returns the long form (runneradmin).
  Same divergence.

Fix: new `canonicalizePath(p)` helper wraps `path.resolve` plus
`fs.realpathSync.native`, falling back to `path.resolve` when the path
doesn't exist (preserves idempotent-on-missing semantics needed by
`remove <unknown>`). Applied at 3 call-sites — registerRepo,
unregisterRepo, resolveRegistryEntry — canonicalising BOTH the input
and each stored `entry.path` at compare time. That last bit is the
backward-compat story: registries written by older versions
(pre-canonicalisation) still match correctly, so we don't need a
migration script.

Test side: the ambiguous-target integration test now reads the path
from the registry snapshot rather than passing the outer `repoA`
variable directly, so it exercises the registry contract regardless of
which path form the platform stores. 4 new unit tests cover the helper
(idempotent, fallback-on-missing, absolute-for-relative) plus the
backward-compat resolver path.

* fix(cli): store resolved (non-canonical) path, compare via canonicalizePath (#1003 CI)

Follow-up to c5eceba0. The previous commit canonicalised the repo path
at BOTH write-time AND compare-time in registerRepo — that expanded
Windows 8.3 short names (RUNNER~1) to long names (runneradmin) when
storing `entry.path`. Pre-existing #829 unit tests that assert
`path.resolve(err.existingPath) === path.resolve(tmpPath)` then broke
because `tmpPath` is still short-form (path.resolve doesn't expand
8.3) while `entry.path` was long-form (canonicalizePath does).

Fix: split storage from comparison.
- entry.path stores `path.resolve(repoPath)` — whatever form the
  caller passed. `list` output and error messages show the path the
  user typed.
- All compare points (existing-entry lookup in registerRepo, the
  collision guard, unregisterRepo, resolveRegistryEntry path tier)
  canonicalise BOTH sides via `canonicalizePath`. That is where the
  /var ↔ /private/var and RUNNER~1 ↔ runneradmin divergence actually
  matters.

Net effect: storage is tolerant (preserves user input), matching is
strict (canonical-vs-canonical). Pre-existing #829 tests stay green
because `err.existingPath` is unchanged from what `path.resolve` gives
back; the cross-platform CI failure from #1003 stays fixed because
every comparison path goes through `canonicalizePath`.

* fix(cli): refuse destructive fs.rm when registry storagePath isn't <repo>/.gitnexus (#1003 review)

Address @magyargergo's inline review finding on remove.ts:89 and the
sibling vulnerability in clean.ts --all (caught during a pre-commit
safety audit). ~/.gitnexus/registry.json is a user-writable plain-text
file, so a corrupted or hand-edited entry could point storagePath at
the repo root (catastrophic: rm the working tree), an empty string
(→ cwd), a parent dir, or anywhere else. fs.rm(recursive: true,
force: true) on any of those is a runtime disaster.

- New UnsafeStoragePathError + exported assertSafeStoragePath() in
  repo-manager.ts. Pure lexical string check (Windows-case-
  insensitive) asserting entry.storagePath === path.join(entry.path,
  '.gitnexus').
- Guard wired into BOTH destructive registry-trusting sites:
  - remove.ts: exit 1 with actionable hint
  - clean.ts --all: skip the poisoned entry with a warning and
    continue (preserves existing per-repo error tolerance — one bad
    entry doesn't halt the batch)
- clean.ts default path and server/api.ts are safe-by-construction
  (they recompute storagePath from findRepo / getStoragePath rather
  than trusting the registry field).
- 8 unit tests cover the guard (valid, repo-root, parent, empty,
  unrelated, sibling, error payload, Windows case).
- 2 integration tests prove the full CLI path: remove-poisoned exits
  1 without touching the working tree; clean --all with a poisoned
  sibling entry cleans the good entry, skips the bad one, and leaves
  the poisoned repo intact.

* test(cli): assert full remove dry-run + success output shape (#1003 NIT)

Address the one NIT from the senior-reviewer pass on PR #1003: the
integration test was only checking for the "Run with --force" hint in
dry-run output, not verifying that the three actual console.log lines
(alias, repo path, storage path) appear. Same weak check on the
success-branch "Removed" output.

Tighten both assertions to toContain(alias), toContain(entry.path),
toContain(storagePath). Catches silent format regressions — e.g. a
future refactor that drops a console.log line or swaps
entry.name/entry.path in the output.

No code change; +20 test lines. All assertions in the happy-path
integration test now fire for a meaningful reason.
2026-04-21 11:52:59 +01:00
Sam Fakhreddine
c24bcc3bf1
fix: expose detect-changes in direct CLI (#892)
Squashed commits:
- test: fix risk_level mock case and prettier formatting in tool-direct-cli.test
- test: add edge-case coverage for detectChangesCommand formatter
2026-04-20 17:12:25 +01:00
azizur100389
dae7bd3b3f
feat(cli): analyze --name <alias> + duplicate-name guard for the repo registry (#955) 2026-04-19 07:23:48 +01:00
Mr. WorldwideBrown
7c983d798f
Fix OpenCode config path, FTS extension load order, error messages, and CLAUDE.md stats (#781) 2026-04-11 06:18:14 +01:00
ivkond
4fed097abb feat(group): add sync pipeline, CLI, MCP tools, and monorepo fixture
Wire extractors into the sync pipeline with service boundary detection.
GroupService provides high-level API for all group operations.

- Sync pipeline: orchestrates extraction (HTTP, gRPC, topics) with
  service boundary assignment and exact matching
- GroupService: groupList, groupSync, groupContracts, groupQuery,
  groupStatus (groupImpact deferred to cross-repo follow-up PR)
- CLI: group create/add/remove/list/sync/contracts/query/status
- MCP tools: group_list, group_sync, group_contracts, group_query,
  group_status
- Monorepo fixture: 3 services (auth/orders/gateway) connected via
  gRPC + Kafka + HTTP — all intra-repo cross-links discovered
- Documentation: CLI commands and MCP tools added to both READMEs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 00:40:31 +03:00
Gabriel J Campbell
b03413dcf9
feat: added skip-agents-md cli flag (#517)
* feat: added skip-agents-md cli flag

* fix: apply prettier formatting

* feat: added skip-agents-md cli flag

* fix: apply prettier formatting

* feat: add skipAgentsMd option to skip AGENTS.md and CLAUDE.md updates

* fixed bad merge
2026-03-28 21:23:59 +00:00
Abhigyan Patwari
9f69c43100
feat(wiki): Azure OpenAI support for wiki command (#562)
* feat(wiki): extend LLMConfig/CLIConfig with Azure and reasoning model fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): restore cursor model resolution, fix LLMProvider type, clean up regex

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(wiki): remove stale LLMProvider type alias from repo-manager

* fix(wiki): fix Azure auth header, api-version param, reasoning model params, content_filter error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): tighten Azure detection, reasoning model regex, content_filter gating

- isReasoningModel: new regex matches only o1/o3 bare + any oN-mini/oN-preview; bare o4/o5/etc now return false
- isAzureProvider: use URL hostname matching to block spoofed subdomain URLs
- callLLM: warn on Azure legacy /deployments/ URL without api-version
- callLLM: gate content_filter error to azure===true; also catch ResponsibleAIPolicyViolation
- tests: add afterEach stub cleanup, spoofed-URL, bare-o4, non-Azure content_filter, and URL-only Azure auto-detect tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): detect content_filter finish_reason in SSE stream and throw clear error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): skip delta accumulation after content_filter, use provider-neutral error message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(wiki): add Azure OpenAI option to interactive setup wizard

Inserts Azure as option [3] in the provider menu (shifting Custom to [4]
and Cursor to [5]), adds guided Azure setup flow with resource/deployment
prompts, v1/legacy URL format selection, reasoning-model flag, and
content_filter error handling in the catch block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): store explicit false for non-reasoning Azure deployments, trim resource name inputs

- isReasoningModelDeployment now stores false (not undefined) when user says no
- Always include isReasoningModel in saved azureConfig (no conditional guard needed)
- Trim resourceName and deploymentName prompt inputs to avoid whitespace issues
- Improve reasoning model note to mention Azure requirement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(wiki): add --api-version and --reasoning-model CLI flags for Azure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(wiki): include apiVersion and reasoningModel in hasCLIOverrides guard

* fix(wiki): default provider to 'openai' in resolveLLMConfig when not configured

* style: apply prettier formatting

* fix(wiki): address PR review — remove unrelated files, harden inputs

- Remove evidence/, fix-adapter.js, and planning doc accidentally included
- URL-encode apiVersion in buildRequestUrl to prevent query string injection
- Add --no-reasoning-model flag to allow CLI override of saved config
- Simplify verbose ternary in Azure wizard prompt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(wiki): use execFileSync for EDITOR to prevent shell injection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 00:23:41 +05:30
Gergő Magyar
bf09eab95b
feat: configure prettier with pre-commit hook (#563)
* feat: configure prettier with pre-commit hook integration

Add prettier, lint-staged, and prettier-plugin-tailwindcss at the repo
root with husky pre-commit hook integration. Moves husky from
gitnexus/ to root package.json for reliable hook installation.

- Root package.json with prepare/format/format:check scripts
- .prettierrc with endOfLine:lf and tailwindStylesheet for TW v4
- .prettierignore excluding fixtures, vendor, generated, *.d.ts, *.md
- .gitattributes enforcing LF line endings for Windows consistency
- Pre-commit hook uses direct node_modules/.bin/ paths (no npx)

* style: apply prettier formatting to entire codebase

One-time bulk format. No logic changes.
Use .git-blame-ignore-revs to skip this commit in git blame.

* chore: add .git-blame-ignore-revs for prettier format commit

* perf: pre-commit hook runs only tests related to staged files

Use vitest --related to scope test execution to tests that import
the changed files, instead of running the full suite on every commit.

* perf: remove vitest from pre-commit hook, keep in CI only

Pre-commit now runs lint-staged + tsc only. Tests run in CI
(ci-tests.yml) where they belong — keeps commits fast.

* ci: add prettier format check to quality workflow

PRs will now fail if code isn't formatted with prettier.
2026-03-28 14:58:04 +00:00
Zander Raycraft
6fabd7a2df
Merge pull request #402 from adonisdoda/feat/index-cli 2026-03-25 20:22:21 -05:00
chirag-nighut
fca7815c16 feat(wiki): add Cursor CLI as LLM provider option
Add Cursor headless CLI as a 4th provider option for wiki generation,
allowing users to leverage their Cursor subscription for wiki pages.

- Add --provider cursor flag and cursor-client.ts
- Add --review flag for interactive module tree editing
- Add --verbose flag for debugging
- Improve module tree generation (flatten single-child, unique slugs)
- Prevent DB timeout during long LLM calls

Usage: gitnexus wiki --provider cursor --model claude-4.5-opus-high
Made-with: Cursor
2026-03-25 11:39:37 +05:30
Shunsuke Hayashi
09e3609376 fix(analyze): address review — rename --no-git to --skip-git, fix stale cache
Addresses all review items from @magyargergo and Copilot:

1. **Rename --no-git to --skip-git**: Commander.js treats --no-X flags
   as negation of --X (stores as options.git = false, not options.noGit).
   --skip-git maps correctly to options.skipGit.

2. **Fix false " Already up to date\ on non-git folders**: When
 currentCommit is empty string, skip the cache check — we cannot
 detect changes without git, so always rebuild.

3. **Replace isGitRepo() with hasGitDir()**: Use filesystem check
 (statSync on .git) instead of shelling out to git CLI. Consistent,
 faster, and works when git is not installed.

4. **Fix misleading warning**: Message now only fires when .git
 directory is actually absent (not when git CLI fails).

5. **Add CLI integration tests**: Verify Commander maps --skip-git
 correctly and that non-git folders are rejected without the flag.
2026-03-22 17:40:02 +09:00
Shunsuke Hayashi
f0f384aab7 fix(analyze): address Copilot review — ESM import, CLI option, .gitignore guard
- Replace require(" fs\) with ESM-compatible top-level import (statSync)
- Register --no-git option in Commander CLI definition
- Use hasGitDir() instead of isGitRepo() for .gitignore update guard
 to match the PR intent (filesystem check vs git CLI invocation)
2026-03-22 16:24:21 +09:00
adonis
3567ef5794 feat(cli): add --allow-non-git option to index command and update tests 2026-03-20 19:46:47 -03:00
adonis
c1996f45d8 feat(cli): add 'index' command to register existing .gitnexus/ folder 2026-03-20 19:16:09 -03:00
Dmytro Semchuk
a7b8c302d4
Merge branch 'main' into feat/codex-support 2026-03-19 10:24:45 +01:00
ivkond
fbff6d08c0
feat(ingestion): respect .gitignore and .gitnexusignore during file discovery (#231)
* feat(ingestion): respect .gitignore and .gitnexusignore during file discovery

Add support for excluding files from indexing based on .gitignore and
.gitnexusignore patterns. Previously, GitNexus used only a hardcoded
ignore list, causing significant index pollution in repositories with
git-ignored directories containing code (e.g., Docker-mounted volumes).

Changes:
- Add `ignore` package for gitignore-spec pattern matching
- Add `loadIgnoreRules()` to parse .gitignore + .gitnexusignore
- Add `createIgnoreFilter()` returning glob-compatible IgnoreLike object
- Integrate filter into glob's `ignore` option for directory-level pruning
- Remove post-glob `.filter()` call (now handled during traversal)

The hardcoded DEFAULT_IGNORE_LIST remains as fallback for non-git repos.

Closes #228

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ingestion): address review feedback on ignore filtering

- Distinguish ENOENT vs EACCES in loadIgnoreRules (warn on permission errors)
- Add GITNEXUS_NO_GITIGNORE env var to bypass .gitignore parsing
- Fix bare-name pattern matching in childrenIgnored (check both with/without trailing slash)
- Rename isIgnoredDirectory to isHardcodedIgnoredDirectory for clarity
- Add clarifying comments for design decisions (D2 negation, D3 dot:false redundancy)
- Add tests for bare-name patterns, file-glob patterns, EACCES handling, env var

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ingestion): address second round of review feedback

- G1: Document GITNEXUS_NO_GITIGNORE in `analyze --help` and log when active
- G2: Add comment clarifying path-scurry POSIX normalization contract
- G3: Add IgnoreOptions interface — env var now falls back, callers can
  pass `noGitignore` explicitly for testability and future CLI flag
- G4: Add integration test verifying walkRepositoryPaths respects the env var

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(ingestion): gracefully skip files with unavailable tree-sitter grammars

Port unsupported language resilience from PR #301 by @jecanore.
- Make Kotlin import optional (like Swift) in parser-loader and parse-worker
- Add worker-local isLanguageAvailable() with filePath param for tsx distinction
- Track and log skipped files per language in both sequential and worker paths
- Add skippedLanguages to ParseWorkerResult for worker→main aggregation
- Add isLanguageAvailable unit tests

Refs: #301, #155, #228

Co-Authored-By: jecanore <juan@housingbase.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(e2e): add ignore + language-skip end-to-end test with fixture repo

Add a fixture repo (test/fixtures/ignore-and-skip-repo/) with .gitignore,
.gitnexusignore, TypeScript source files, and a Swift file to exercise
all three features end-to-end:

- File discovery: verifies .gitignore excludes data/ and *.log,
  .gitnexusignore excludes vendor/, source files are discovered
- Parsing: verifies TypeScript files produce Function nodes and DEFINES
  relationships, Swift files are skipped gracefully when grammar is
  unavailable

Add the test to the standalone group in ci-integration.yml and coverage job.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ci): move ignore-and-skip-e2e test to e2e group per review feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(test): use temp directory instead of fixture for e2e ignore test

The fixture's .gitignore prevented data/seed.json and debug.log from
being committed — these files would be missing after checkout in CI.

Switch to creating the entire test structure in a temp directory via
beforeAll (matching filesystem-walker.test.ts pattern). This ensures
all files exist regardless of git ignore rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(test): correct graph API usage in e2e ignore test

Use graph.nodes property getter instead of graph.getNodes(), and check
Function node filePath instead of non-existent File nodes (File nodes
are created by processStructure, not processParsing).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: add workflows permission to ci-integration.yml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: change workflows permission to write per review

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: move workflows permission from ci-integration.yml to ci.yml caller

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ci): fix Claude workflows for fork PRs, remove misplaced workflows perm

Three issues prevented Claude from running on fork PRs:

1. claude-code-review.yml lacked workflows:write — push failed when
   fork PRs modify .github/workflows/ files
2. claude.yml had no fork PR support — checked out main and couldn't
   fetch the fork's branch from origin
3. Cleanup step unconditionally deleted branches even when push failed,
   breaking the concurrent claude.yml workflow

Also removes workflows:write from ci.yml's integration job — CI tests
don't need that permission. The permission belongs on the claude
workflows that push fork branches.

Changes:
- Add workflows:write to both claude workflow permissions blocks
- Add fork PR detection + branch push/cleanup to claude.yml
- Add step id to push-fork; cleanup only runs if push succeeded
- Pass branch names via env vars to prevent shell injection (security)
- Add concurrency groups to prevent race conditions between workflows
- Remove misplaced workflows:write from ci.yml integration job

* fix(ci): use GitHub API for fork branch refs instead of git push

GITHUB_TOKEN cannot have 'workflows' permission — it's only valid for
PATs and GitHub Apps. This means git push fails whenever a fork PR
modifies .github/workflows/ files.

Replace git push with the GitHub REST API (POST/PATCH /git/refs) to
create temporary branch refs. The API creates a pointer to the
already-existing PR head commit without triggering the workflow file
push protection. Similarly, cleanup uses DELETE /git/refs instead of
git push --delete.

Also removes the invalid 'workflows: write' from permissions blocks.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: jecanore <juan@housingbase.io>
Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
2026-03-16 13:26:20 +00:00
Zander Raycraft
03bfa3c4d9
FEAT: Added support for optional skill generation based on KuzuDB after initial repo analysis (npx gitnexus analyze --skills) (#171)
* calm fix 4 adding skills to repo [ISSUE #140]

* inspect

* unit and integration tests

* fixed hardcoded cohesion miss

* e2e tests for --skills flag for langauge/repo support

* Cohesion test e2e tests
2026-03-13 08:29:13 +00:00
Ryanba
1be910f54a
fix: skip unavailable native Swift parsers in sequential ingestion (#188)
* fix: skip unavailable native Swift parsers in sequential ingestion

* fix: warn when ingestion skips languages in verbose mode

* test: cover verbose skip warnings

* docs: update analyze flags

* docs: clarify verbose default

---------

Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
2026-03-10 14:26:36 +00:00
Shockang
9d5ec5d19a
Improve MCP startup compatibility and lazy-load CLI commands (#207)
* Fix MCP startup transport compatibility

* Preserve CLI flags in MCP startup fix

* Harden MCP transport error handling

* Harden transport security and improve type safety

Transport hardening:
- Add MAX_BUFFER_SIZE (10 MB) cap to prevent OOM from oversized
  Content-Length or unbounded newline-delimited input
- Replace recursive readNewlineMessage with iterative loop to prevent
  stack overflow from consecutive empty lines
- Tighten looksLikeContentLength to require 14+ bytes before matching
- Add closed-state guard and error handling to send()
- Simplify processReadBuffer loop to break on error
- Fix loose equality (==) to strict (===)
- Widen constructor param types to ReadableStream/WritableStream

Type safety:
- Constrain createLazyAction generics so export name is validated
  against the module's actual exports at compile time
- Use proper type guard instead of lint suppression
- Fix test tsconfig type errors

Regression tests for all hardening fixes (13 tests passing).

---------

Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
2026-03-07 07:47:09 +00:00
abhigyanpatwari
20ebd6b781 feat: security hardening, MCP improvements, skills, hooks, and CLI updates
- Export security primitives (CYPHER_WRITE_RE, isWriteQuery, isTestFilePath,
  VALID_NODE_LABELS, VALID_RELATION_TYPES) from local-backend
- Improve MCP kuzu-adapter with better query handling
- Add PR review skill for Claude, Cursor, and npm package
- Add CLI guide and CLI skills
- Update hooks for Claude plugin and Cursor integration
- Remove deprecated claude-hooks.ts CLI module
- Update eval-server, setup, and analyze CLI commands
- Improve CSV generator and ingestion processors
- Update CLAUDE.md and AGENTS.md configs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:13:42 +05:30
abhigyanpatwari
eb48c7352e fix: read CLI version from package.json instead of hardcoding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:32:28 +05:30
abhigyanpatwari
7fe8830402 merge: resolve conflicts with main for remote server mode (PR #66)
Keep main's barLog implementation, preserve both currentDbPath and
ftsLoaded reset in closeKuzu, take PR's new resolveRepo pattern
for /api/query. Path traversal guard confirmed intact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:40:25 +05:30
Nico Prieto
f047a84d82 fix(server): restore security guards and error handling
Address code review feedback on the server-mode PR:

Critical fixes:
- Restore CORS whitelist (localhost + gitnexus.vercel.app only)
- Bind to 127.0.0.1 by default; add --host CLI flag for opt-in remote access
- Restore path traversal guard on /api/file (resolve + startsWith check)
- Restore try/catch on all route handlers + global error middleware
- Restore SIGINT/SIGTERM graceful shutdown handlers

Bug fixes:
- Add mutex to core initKuzu to prevent race conditions on concurrent
  DB switches (two requests for different repos no longer corrupt state)
- Track ftsLoaded flag and reset on DB switch / close so FTS extension
  is reloaded for each new database connection
- Restore input validation on /api/query (cypher required) and
  /api/search (query required)

Improvements:
- Add TTL-based cleanup for orphaned MCP sessions (30min idle eviction)
  to prevent memory leaks from network drops that skip onclose

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 12:42:00 +01:00
abhigyanpatwari
bef319491a feat(gitnexus): large-repo optimizations, multi-language support, bug fixes
Optimize ingestion pipeline for massive codebases (Linux kernel ~75K files):
- Worker pool: 8 threads, 1500 sub-batch, 30s per-batch timeout
- Streaming CSV generation with per-stream MaxListeners fix
- FileContentCache 3000 entries, resolveCache LRU eviction (20% at 100K cap)
- Leiden 60s timeout with single-community fallback
- SIGINT graceful shutdown, FTS dedup flag

Multi-language node support (Struct, Enum, Macro, Impl, Trait, etc.):
- Add 16 multi-language types to NodeLabel union
- Separate CSV writers with correct schema (no isExported)
- KuzuDB schema: backtick-escape reserved words (Macro, Union, Enum)
- Add all FROM/TO pairs for multi-language relationship edges

Fix bugs: getKuzuStats/deleteNodesForFile backtick escaping,
insertNodeToKuzu/batchInsertNodesToKuzu missing escaping + isExported,
progress bar flickering and timer display

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 10:23:23 +05:30
Dmytro
984316d260 feat: add Codex MCP and skills support 2026-02-25 15:43:12 +01:00
abhigyanpatwari
302c7ba7f0 fix: disable embeddings by default, fix segfault on macOS/Linux
Embeddings (ONNX Runtime) caused segfaults on macOS (#38) and CUDA
install failures on Linux (#40). Since embeddings only power semantic
vector search in query() and BM25 + graph traversal already provide
strong retrieval, disable embeddings by default with minimal quality
impact.

Changes:
- Replace --skip-embeddings with --embeddings opt-in flag
- Remove disposeEmbedder() call (ONNX native cleanup segfaults)
- Add process.exit(0) when embeddings are used to bypass ONNX atexit hooks
- Suppress ONNX session warnings via logSeverityLevel
- Fix progress bar duplication by routing console output through bar.log()
- Add elapsed time indicator for long-running phases

Fixes #38
Fixes #40
2026-02-23 03:47:34 +05:30
abhigyanpatwari
79501abb6c fixed MCP concurrency issue with connection pool on kuzu 2026-02-17 16:31:05 +05:30
abhigyanpatwari
6ce715b62c repowiki CLI command implemented 2026-02-17 02:25:07 +05:30
abhigyanpatwari
eca55aacd7 fixed resource count multiplying issue ( using resource templates now ) 2026-02-13 21:28:36 +05:30
abhigyanpatwari
dda8de41a3 MCP and cli fixes 2026-02-07 06:21:21 +05:30
abhigyanpatwari
1735c0ffcd gitnexus wal cleanup preventing reindexing issue fixed 2026-02-06 06:35:15 +05:30
abhigyanpatwari
e480888cf0 fix: clean command --force flag, hide debug logs in production 2026-02-04 03:06:19 +05:30
abhigyanpatwari
c90576442e feat: merge gitnexus-mcp into gitnexus package - unified CLI+MCP 2026-02-04 01:12:41 +05:30
Renamed from gitnexus-cli/src/cli/index.ts (Browse further)