Commit graph

20 commits

Author SHA1 Message Date
Abhigyan Patwari
faa453c528
fix: reduce MCP token overhead and correct cost comparisons (#3645)
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-20 16:04:10 +01:00
Gergő Magyar
62f86ea068
feat(mcp): reduce response size and query overhead (#3621)
* docs(mcp): document focused response filters

* feat(mcp): add opt-in response section and relation filters

* test(mcp): verify response filters and compatibility

* test(mcp): add deterministic response-size benchmark

* docs(skills): teach focused MCP calls and safe filter use

* docs(skills): update debugging response-filter guidance

* docs(skills): update exploration response-filter guidance

* docs(skills): explain focused MCP response options

* docs(plugin): mirror focused debugging guidance

* docs(plugin): mirror focused exploration guidance

* docs(plugin): mirror focused MCP tool guide

* docs(cursor): mirror focused debugging guidance

* docs(cursor): mirror focused exploration guidance

* test(mcp): give filter cases unique identities

Use named cases to keep array inputs intact and let the CI execution audit distinguish every malformed-filter test.

* perf(mcp): batch BM25 symbol hydration

* test(mcp): serialize native hydration coverage

* test(eval): publish child PID atomically

* test(mcp): cover hydration on native platforms

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Abhigyan Patwari <126312502+abhigyanpatwari@users.noreply.github.com>
2026-10-18 17:32:09 +01:00
Gergő Magyar
30676685e0
fix(rename): apply the exact reviewed edit plan (#3617)
* fix(rename): bind apply to reviewed plans (U7)

Retain exact semantic edits behind single-use preview tokens and reject
source, target, inventory and graph drift before application. Preserve
explicit partial-write accounting and keep large unedited sources covered
with hashes instead of retained text.

Refs #2973

* fix(rename): cover unindexed sources (U7)

Address PR #3617 review by binding every supported source to streamed byte
hashes and canonical targets, including tracked and untracked files absent
from the graph. Keep the exact reviewed edits and bound evidence memory.

Use conventional even-sample medians and extend the existing CI benchmark
to capture and validate unindexed sources without relaxing timing gates.

Note: pre-existing packed Tree-sitter GLIBCXX_3.4.31 host failure in
parse-cache-identity-package.test.ts is not addressed by this PR.

* fix(rename): preserve lazy startup (U7)

Keep language providers off the MCP startup path; load their existing
classification only when rename inventory is requested. The existing
12 startup closure checks now pass.

Address PR #3617 review by including token validation in reviewed apply
timing and growing indexed evidence before preview, preserving the
20MiB controls under a 256MiB native pool. Migrate dispatch and retention
tests to the preview token contract, keeping write-failure oracles.

Note: pre-existing auto-sync /tmp fixture security and installed ARM64
grammar-header failures remain outside this PR; the packed Tree-sitter
GLIBCXX_3.4.31 host failure also reproduces on unchanged main.

* test(rename): always remove apply fixture (U7)

Own the temporary directory from creation in an outer finally so setup
and preview assertions cannot bypass cleanup. Keep spy restoration in
its inner finally and preserve all write-failure assertions.

Address PR #3617 cleanup feedback.

* fix(rename): retain targets and config evidence

* test(rename): verify approved physical output

* test(rename): cover native filesystem matrix

* test(rename): align preview contract fixtures

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 19:38:01 +01:00
Gergő Magyar
8fa8e64388
fix(rename): extend safe refactoring and flow coverage across languages (#3557) 2026-10-13 08:38:17 +03:00
Gergő Magyar
c474a811ba
fix(test): align fixtures and mocks with current types (#3471) 2026-10-05 04:47:37 +01:00
svjack
ccf6b4743d
feat(mcp): add read_file + grep tools (REST parity for /api/file slice + /api/grep) (#3377)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* feat(mcp): add read_file + grep tools (REST parity for /api/file slice + /api/grep)

* chore(autofix): apply prettier + eslint fixes via /autofix command

* Address PR review feedback (#3377)

- Fail read_file and grep when full source is unavailable, matching the HTTP 410 contract instead of an empty grep or a not-found on a missing checkout.
- Reject branch on those tools so a pinned index is not labeled onto checkout bytes, and stop advertising branch in their schemas.
- Point the grep hint at a 0-based read_file window, pass caseSensitive and literal through, and test the handlers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3377)

- Keep read_file and grep in the multi-repo schema requirement without advertising branch.
- Reject negative maxLines and return integer slice bounds for fractional line positions.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3377)

- Reject a negative read_file endLine before slicing so JavaScript does not treat it as an offset from the end of the file.
- Drop the fractional startLine/endLine claim so the integer schema is the advertised contract.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3377)

- Skip indexed grep paths whose realpath leaves the checkout so a symlink cannot return lines from outside the repo.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(bench): record the 19-tool MCP roster

read_file and grep are real tools, so tools/list and GITNEXUS_TOOLS both
moved from 17 to 19. The timing ratios were already inside budget.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(mcp): share read_file and grep contracts with existing helpers

Boolean grep flags go through isFlagTrue, the whole-file cap is one constant, and checkout tools stay on the per-repo schema without advertising branch.

---------

Co-authored-by: svjack <svjack@example.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-27 13:16:11 +00:00
Gergő Magyar
084ac4514d
fix(query): send hub content once across process_symbols rows (#3356)
* fix(query): send hub content once across process_symbols rows

With include_content, a symbol in several execution flows carried its
full source text on every (id, process_id) row. Keep content on the
first row for each symbol id and omit it from later rows. Membership
fields, is_entry_point, and symbol_count are unchanged.

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

* fix(query): point agents to the content row and lock the dedup in tests

The query tool text now says content is kept once per symbol id across
the whole process_symbols array, possibly under a different process_id,
and names context({uid, include_content: true}) as the fallback.

Tests: the integration suite asserts func:validate has two rows with
content on exactly one. Unit tests cover a later entry-point row that
is flagged and stripped, a hub in three processes, and that the shaper
does not mutate its input.

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

* fix(query): state the content-once rule on include_content and in the query hint

The query tool's include_content property now says content is sent once
per symbol id, on its first process_symbols row, and that
context({uid: "<id>", include_content: true}) returns it for any row.
When a query asked for content, the Next hint adds that same fallback;
without include_content the hint is unchanged. The example call now
uses the "<id>" placeholder style used elsewhere in the tool text.

Tests: pin the property sentence, check the hint with and without
include_content, and cover a max_symbols slice that moves the content
row to a later process and a first row that is also the entry point.

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

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 07:58:51 +01:00
Gergő Magyar
21a52af1d4
fix(lbug): ship FTS per-platform and recover in-place native aborts (#3274)
* fix(lbug): pin Ladybug core so Dependabot cannot ship a skewed FTS artifact

The extension version is a separate upstream constant. Ignore daily core bumps and fail the pairing gate when the committed manifest does not name the installed core.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): make doctor and CI FTS gates resolve the packaged artifact

Doctor and the REQUIRE_FTS file gates still treated an empty ~/.lbdb as
unavailable, which would turn three CI jobs red once analyze stops
installing into that tree.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): name native-abort and tuple-missing so analyze cannot mis-advise

The CLI summary's trailing else treated every unknown skip reason as a
missing extension. New crash and platform causes must get their own
remedies, not a network-install hint.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): delete the dead read-path FTS index create

ensureFTSIndex had no production callers and swallowed read-only
CREATE_FTS_INDEX failures, which hid the only signal that a reader
tried to write.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): vendor per-platform FTS artifacts so analyze needs no host install

Keyword search depended on a CDN fetch into ~/.lbdb. Shipping the five
published tuples inside the package makes air-gapped and ignore-scripts
installs load the same artifact the publish gate checksums.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): load the packaged FTS artifact before any network install

Analyze still required a CDN fetch into ~/.lbdb even when the package
already shipped the file. FTS now path-loads the vendored tuple first
and records source labels so a later truncated home copy cannot steal
the diagnosis.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): diagnose a core/extension version skew instead of a missing runtime

A structurally valid FTS artifact whose path version disagrees with the
packaged pin must name both versions, not prescribe VC++ or OpenSSL.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): stamp an FTS phase so repair stays usable after an in-place abort

A native CREATE_FTS_INDEX abort leaves no skip reason; the next run infers
it from the dirty flag, and --repair-fts must not treat that phase as a
half-written graph.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): park an in-place FTS crash WAL without wiping the graph

An FTS abort after a successful checkpoint must reopen the live index on
macOS, Windows, and Linux. Staging never parks the live WAL; readers keep
today's large-WAL refusal.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): refuse read-only opens of an FTS-poisoned WAL

MCP and serve cannot repair a leftover in-place abort. Fail before the
native open and name --repair-fts, on macOS, Windows, and Linux.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): name a vendor-neutral Windows OpenSSL prerequisite

OQ1 is unanswered here so GitNexus does not ship OpenSSL DLLs. Windows
FTS now asks for a system OpenSSL 3 runtime instead of Git Bash PATH.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): inject the FTS vendor root and redact it on HTTP and MCP

Path-loaded artifacts no longer vary with HOME. Tests pass an injected
vendor tree and assert search warnings never leak a filesystem path.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(lbug): document load-only as the global FTS install default

Analyze still overrides to auto. Packaged per-platform artifacts load
before any network install on macOS, Windows, and Linux.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(lbug): format the FTS install-policy README table

Prettier does not run on Markdown in pre-commit, so the U10 table wrap
needs its own formatting commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): skip FTS CREATE after a persisted native abort

A recovered analyze run was retrying CREATE_FTS_INDEX from skipReason
alone. Keep that skip until --repair-fts, fail closed on unsupported
tuples, and honor the checkpoint warrant for park/repair.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): honor checkpoint flushed warrant and align FTS tests with packaged vendor

A no-op CHECKPOINT must not satisfy the FTS park warrant, and CI still asserted HOME-only FTS isolation after analyze started path-LOADing the packaged artifact.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): accept a nonempty incremental write set in the #2790 recovery check

FTS-phase recovery can incremental-add files (changed=0, added=1). That is not the #2790 empty-diff wipe skip.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): compare FTS home versions to the core pin and tighten the publish filename gate

Ladybug's ~/.lbdb/extension directory is the runtime/core version; treating it as the artifact version false-diagnosed skew. The publish guard now rejects a path-escaping filename the same way the fetch script does.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): seed FTS e2e fixtures from the packaged vendor artifact

A machine with no ~/.lbdb copy should still run the vendor-survivorship cases; the seed no longer depends on HOME or a network install.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3274)

Keep in-place FTS abort evidence after persist so a second CREATE abort
cannot fail-open readers, and close the CLI, loader, embed, and e2e gaps
the review called out.

Note: full npm test hit Ladybug worker-pool startup failures under memory
pressure; tsc and 180 targeted unit tests passed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3274)

Run the vendored-path symlink guard on the OS matrix, put e2e HOME
fixtures on Ladybug's real extension layout, pin the embed crash-WAL
gate before the writable open, and let analyze writers park through
missing-shadow recovery.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): keep --repair-fts CI green after vendored-first FTS

Never-installed warning fixtures must not inspect a packaged vendor binary, and a failed dirty restamp must not abort an otherwise successful --repair-fts run.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(cli): give the #1169 analyze e2e the same 90s Windows budget as its sibling

The first #1169 persist-meta case was still on a 60s spawn/it budget and was killed banner-only on windows-latest after the FTS warning fixture no longer failed the shard first.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(ci): reweight Windows shards after the FTS e2e grew

Vendored-first HOME fixtures pushed fts-extension-e2e to ~6 minutes on windows-latest, so the old 146s weight packed it with skills-e2e and blew the 20-minute watchdog.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 08:52:24 +01:00
Gergő Magyar
1f64becb30
fix(mcp): reject unknown tool arguments and honor depth (#3267) 2026-09-12 06:55:14 +00:00
Aakash Sharma
d1a3edd333
perf(mcp): avoid O(n) git spawns on tools/list with many repos (#3259)
* perf(mcp): avoid O(n) git spawns on tools/list with many repos

toolSchemaRepoRequirements called listAllowedRepos -> listRepos -> checkStalenessAsync for every registered repo. With ~200 repos, this spawned 200 parallel git rev-list processes on every tools/list discovery call, causing a ~30s delay.

Replaced with a lightweight countRepos() method that reads the registry file once without spawning git processes, preserving full staleness checks for list_repos.

* Address PR review feedback (#3259)

Count the validated registry in countRepos so tools/list cannot advertise a multi-repo schema for ENOENT ghosts, and update the unrestricted listTools mocks to that contract.

Note: pre-existing failure in update-notice.test.ts (missing dist/cli/mcp.js) not addressed by this PR.
Co-authored-by: Cursor <cursoragent@cursor.com>

* Add a 200-repo tools/list bench for the countRepos path (#3259)

Pin the #1363 comparison (listRepos git fan-out vs validated countRepos / listTools) in-tree so the latency claim can be re-run. Also drop the change-history comments on the unrestricted schema arm.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Gate the tools/list bench with baselines and CI --check (#3259)

Exact registry/schema floors plus ratio timing, no millisecond ceiling, so restoring listRepos() on tools/list fails CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3259)

Align unrestricted tools/list schema flags with the refreshed registry snapshot, and make the bench reject a non-positive BENCH_REPS and isolate fixtures by N.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(autofix): apply prettier + eslint fixes via /autofix command

* Address PR review feedback (#3259)

Isolate the tools/list bench from GITNEXUS_MCP_READ_ONLY and create the default fixture under mkdtempSync so CodeQL is not looking at a predictable /tmp path.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-11 13:18:28 +01:00
简律纯
5bad2d8b0b
fix(mcp): resolve omitted repo from cwd (#3085)
* fix(mcp): resolve omitted repo from cwd

* test(mcp): cover cwd repository routing gaps

* fix(mcp): harden cwd repository routing

* docs(mcp): clarify cwd repository boundary

* fix(mcp): preserve resolver compatibility

* fix(mcp): align restricted repository routing

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-08-29 21:07:43 +00:00
Void Freud
7be6d29ca0
fix: require repo in multi-repo MCP tool schemas (#2717)
* fix: require repo in multi-repo MCP schemas

* style(mcp): fix server test formatting

* chore(autofix): apply prettier + eslint fixes via /autofix command

* test(mcp): cover repository schema policy

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-28 20:04:04 +01:00
Eva
0506f91eb9 docs(mcp): explain response budget guardrails 2026-07-16 09:26:19 +07:00
Eva
627ec5a5aa feat(mcp): add deterministic output budgets 2026-07-14 01:48:17 +07:00
jwcrystal
22304cd4a4
fix(mcp): prevent orphan processes by handling stdin close/end and startup race condition (#2049)
* fix(mcp): prevent orphan processes by handling stdin close/end and startup race condition

Three gaps in stdin EOF handling:

1. Startup race: parent can die before `process.stdin.on("end", ...)` is
   registered, so the event is missed entirely.
2. Missing "close" event: when pipe is forcibly closed (parent SIGKILL),
   "close" fires without "end" on some platforms.
3. Transport layer did not propagate stdin termination to its onclose
   callback.

Fixes:
- Check readableEnded/destroyed in start() before registering listeners.
- Register stdin end+close listeners in CompatibleStdioServerTransport.
- Add _closed guard for idempotent close().
- Throw if start() is called after close().
- Add process.stdin.on("close") in server.ts alongside existing handlers.
- Add 5 regression tests.

* fix(mcp): register stdin shutdown before server connect
2026-06-05 08:36:28 +01:00
Gergő Magyar
2a5bbbeaae
fix: make extension installs offline-first (#1161)
* feat(review): add PR reviewer swarm agents

Seven read-only subagents coordinated by an orchestration skill for
structured, evidence-grounded production-readiness PR reviews.

Agents: facts-historian, branch-hygiene, risk-architect, test-ci-verifier,
security-boundary, docs-dod, synthesis-critic. All use Read/Grep/Glob/Bash
only — no edit tools.

Skill invoked as /gitnexus-pr-swarm-review <PR>.

* fix: patch vector extension and uncaughtException for review findings

- Add { policy: 'auto' } to both loadVectorExtension() calls in
  embedding-pipeline.ts so analyze --embeddings auto-installs VECTOR
- Add void to uncaughtException shutdown(1) call for Node v20+ safety
- Re-add getExtensionInstallPolicy export + default change + 4 tests

* fix(mcp,lbug): graceful shutdown exit codes + complete offline-first VECTOR policy

Completes the two live issues PR #1161 only partially addressed.

#1132 — MCP shutdown crash: SIGINT/SIGTERM were registered with `shutdown`
directly, so Node passed the signal NAME string into process.exit(), crashing
with ERR_INVALID_ARG_TYPE ('SIGTERM'). Map signals to numeric exit codes
(SIGINT->130, SIGTERM->143) via a testable installSignalShutdown(); add an
unref'd force-exit watchdog so a hung disconnect()/close() cannot wedge
shutdown; and void the stdin/stdout handlers so event payloads never reach
process.exit() as a non-number.

#1153 — offline-first extension loading:
- semanticSearch (a query/read path) no longer forces policy:'auto'; queries
  use load-only and never spawn a network INSTALL (extension.ladybugdb.com).
- the analyze embedding WRITE path resolves the policy from
  GITNEXUS_LBUG_EXTENSION_INSTALL (honoring never/load-only/auto; default auto)
  instead of hard-forcing 'auto', so an offline/locked-down operator's override
  is respected (the regression that re-broke #1153 for the VECTOR path).
- surface the active install policy in `gitnexus doctor` (was claimed but never
  delivered; also gives the previously-dead getExtensionInstallPolicy a caller).
- emit an actionable message when VECTOR is unavailable.

Tests: regression for the signal->numeric mapping (reproduces the signal-string
crash condition) and for embedding install-policy resolution. tsc/prettier clean,
eslint 0 errors, 55 unit tests pass.

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

* fix(analyze): degrade gracefully when FTS extension is unavailable

The load-only default made `gitnexus analyze` throw when the FTS
extension was not pre-installed, breaking CI and offline use. Make the
analyze write path opt into the `auto` install policy (LOAD-first then
bounded INSTALL — symmetric with the VECTOR/embeddings path and the #726
contract) and degrade gracefully when the extension still cannot load:
skip search-index creation, log a warning, and complete with a fully
queryable graph (only full-text/BM25 search is disabled). `--repair-fts`
still fails loudly.

- Surface the degraded state instead of reporting healthy:
  AnalyzeResult.ftsSkipped, a persistent CLI summary warning, and
  meta.json capabilities.fts.status = "unavailable".
- Skip the FTS-primitive integration tests when the extension is
  unavailable (shared skipUnlessFtsAvailable helper).
- Add a unit test for the degradation branch; fix the existing
  full-analyze test mock that omitted loadFTSExtension.

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

* test(lbug): skip FTS-seeding suites when extension is unavailable

The withTestLbugDB helper seeds FTS indexes in beforeAll via createFTSIndex,
which throws when the optional FTS extension cannot load — failing the whole
suite on machines where it is neither pre-installed nor installable (the
macOS platform-sensitive CI runner). Probe the extension once (mirroring the
analyze write path's `auto` policy), bypass FTS seeding when it is
unavailable, and skip the suite's tests via beforeEach with a one-time
warning so the skip is visible rather than a setup crash.

Fixes the macOS failures in search-core, search-pool, local-backend-calltool,
and staleness-and-stability. Suites still run normally where FTS is available.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 20:04:41 +01:00
Temirkhan
1fe3bf9399
feat(mcp): add tool safety annotations (#1127)
* feat(mcp): add tool safety annotations

* test(mcp): address PR #1127 review follow-ups

- Replace private `_requestHandlers` SDK access in server.test.ts with
  `Client` + `InMemoryTransport.createLinkedPair()` for the tools/list
  annotation propagation test. The new path uses supported public APIs
  and surfaces SDK changes loudly instead of silently degrading.
- Extract `OPEN_WORLD_READ_ONLY_TOOLS` set in tools.test.ts so future
  read-only open-world tools can be added without rewriting the
  invariant; preserves the current "only `query` is open-world" guard.
- Add inline rationale on `group_sync` annotations explaining the
  conservative `idempotentHint: false` (writes contracts.json on every
  call even when output is deterministic).

No runtime behavior change. Annotations themselves and tools/list shape
are unchanged.

---------

Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
2026-05-03 09:06:41 +01:00
Gergő Magyar
acf6fbdd39
feat: configure eslint with unused import removal (#564)
* feat: configure eslint with unused import removal

Add ESLint v9 (flat config) for code quality:
- eslint-plugin-unused-imports for auto-removing dead imports
- @typescript-eslint for TypeScript-aware linting
- eslint-plugin-react-hooks for React hooks rules
- eslint-config-prettier to avoid formatting conflicts
- lint-staged runs eslint --fix before prettier on .ts/.tsx
- CI lint job added to ci-quality.yml

* refactor: remove unused imports via eslint --fix

Auto-fixed by eslint-plugin-unused-imports. No logic changes.

* chore: add eslint fix commit to .git-blame-ignore-revs
2026-03-28 15:28:09 +00:00
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
abhigyanpatwari
8a100a76d3 test: add test suite with vitest (unit + integration + fixtures)
- 59 test files covering unit and integration tests
- vitest config with coverage thresholds and fork pooling
- Test fixtures (mini-repo + multi-language sample code)
- Add vitest + coverage-v8 to devDependencies
- Add test scripts (test, test:integration, test:all, test:watch, test:coverage)
- Move typescript to devDependencies where it belongs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:07:02 +05:30