mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-07 02:58:02 +00:00
2155 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
07b5c27045 | fix(embeddings): defer staged checkpoint count until publication | ||
|
|
a47cd17f27
|
fix(config): honor nested .gitignore files during repository walks (#3440) | ||
|
|
d1971cf953
|
fix(communities): omit memberships for filtered singleton communities (#3447) | ||
|
|
4f298d0ac0
|
fix(staleness): detect rollback with one Git query (#3445) | ||
|
|
668fac7635
|
fix(search): report partially missing FTS indexes in query results (#3448) | ||
|
|
f99dde8aa3
|
fix(mcp): discover positional SDK tool registrations (#3450)
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 / 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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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
|
||
|
|
a8f18f00b9
|
fix(swift): avoid false calls for injected closure properties (#3434) | ||
|
|
64fd67388f
|
chore(deps)(deps): bump fast-xml-parser in /gitnexus (#3454) | ||
|
|
dad3b8f6f2
|
fix(mcp): reject invalid symbol identities before graph reads (#3451) | ||
|
|
412446408d
|
fix(index): guard graph integrity and fail closed on incomplete risk (#3442) | ||
|
|
ce79caaf86
|
chore(deps): bump the uv group across 1 directory with 3 updates (#3443)
Some checks failed
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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
Devcontainer Smoke / Build devcontainer image (push) Has been cancelled
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Skill copy sync / shipped skills drift guard (push) Has been cancelled
|
||
|
|
702eb9326a
|
chore(deps): consolidate pending dependency upgrades (#3441) | ||
|
|
74a1af71d4
|
chore(deps)(deps-dev): bump @types/node in /gitnexus (#3420) | ||
|
|
57bf8ee823
|
chore(deps)(deps): bump smol-toml from 1.8.0 to 1.9.0 in /gitnexus (#3419) | ||
|
|
e42122a0f6
|
feat(go): index gin/echo routes and report them in impact (#3402) (#3417) | ||
|
|
acb65b95b6
|
fix(fastapi): propagate package router mount prefixes (#3408)
Some checks failed
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Gitleaks / gitleaks (push) Has been cancelled
Publish / Classify release event (push) Has been cancelled
Scorecard / Scorecard analysis (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-cli) (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-web) (push) Has been cancelled
Publish / RC guard (marker + release-PR skip) (push) Has been cancelled
Publish / ci (push) Has been cancelled
Publish / Publish to npm (push) Has been cancelled
Publish / Build & Push RC Docker images (push) Has been cancelled
* fix(fastapi): carry package router mount prefixes to child routes * fix(fastapi): address review feedback on nested router prefixes (#3408) - Skip unprefixed includes in the parse-impl legacy loop so a bare include_router in another file no longer shadows the real prefix. - Union exact-file prefixes with legacy long/short prefixes via a shared mergeMountPrefixes helper in both ingestion and the group extractor. - Join the parent APIRouter(prefix=...) between the mount prefix and the child include prefix. - Resolve the group layer over every repo path (empty files included) so absolute-import ambiguity matches ingestion. - Memoize (file, prefix) frames so diamond-shaped include graphs stay linear; drop the stack.pop() non-null assertion. - Accept extra keyword arguments and a trailing comma in unprefixed include_router calls without double-firing on prefix= calls. - Document that pass-through is limited to a host named `router`. - Bump parse-cache SCHEMA_BUMP to 123 for the new capture fields. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(fastapi): seed prefix propagation from bare router mounts (#3408) - A router mounted without a prefix now seeds traversal with an empty prefix (only when no prefixed mount targets the same file), so its own APIRouter(prefix=...) reaches unprefixed children on both surfaces. - An all-empty chain records nothing and leaves the child on its legacy fallback. - The bare-mount integration test no longer asserts that the test app's unprefixed mount is absent; it pins only that the real prefix survives. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(fastapi): capture include prefixes after nested-call arguments (#3408) - Let the Shape A/B and unprefixed include_router patterns step over one level of nested calls such as dependencies=[Depends(auth)], so a prefix= written after them is captured by the worker (the group layer's tree-sitter patterns already handled this shape). - Replace the unit test that pinned the dropped prefix with one that pins the captured prefixes and the unprefixed Depends-only edge; add a group-layer parity test. - Correct the diamond test comment to 2^39 root-to-leaf paths. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
aa0f41e853
|
fix(python): model restoring helper calls in decorator identity (#3415)
* fix(python): model restoring helper calls in decorator identity (#3414) A bare module-level call to a same-file helper whose every global binding of a descriptor name is an unconditional del or builtins import now restores the builtin at the call site, matching CPython. A nonlocal rebind nested in the enclosing function now shadows an owned builtins import, closing a false builtin. Unprovable call orders stay fail-closed and are pinned against CPython 3.11. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(review): apply review findings Close three false-builtin paths the review found: a match-pattern capture now counts as a binding (at any scope, including inside a restoring helper), a call before the helper's def no longer counts as a restore, and the helper-name uniqueness check sees match captures. Pin the helper rejections (conditional restore, async, early and nested return, wildcard import) against CPython 3.11. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cache): bump parse-cache schema to v122 for #3414 Python decorator identity verdicts changed, so warm v121 ParsedFiles would replay stale receiver bindings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): require an argument-free call to a helper with no required parameters A call that fails to bind the helper's parameters raises TypeError before the body runs, so it proves no restore. Keep such calls fail-closed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): count only real captures and module bindings for decorator identity Match value patterns, class names and keyword keys read a name rather than capture it, so they no longer shadow a builtin descriptor. A local of the same name as a restoring helper no longer disqualifies the module-level helper; only a module binding or a global rebind does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(python): state the fail-closed contract of the descriptor identity table `false` means the resolver does not prove the builtin, not that CPython shadows it. Cases where CPython keeps the builtin but the resolver fails closed carry a comment saying so. 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> |
||
|
|
c2fab0a8d2
|
chore(deps)(deps): bump @modelcontextprotocol/sdk in /gitnexus (#3410)
Bumps [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) from 1.30.0 to 1.30.1. - [Release notes](https://github.com/modelcontextprotocol/typescript-sdk/releases) - [Commits](https://github.com/modelcontextprotocol/typescript-sdk/compare/1.30.0...1.30.1) --- updated-dependencies: - dependency-name: "@modelcontextprotocol/sdk" dependency-version: 1.30.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
821ffb2fcb
|
fix(python): resolve decorator identity like CPython (#3411)
* fix(python): resolve decorator identity like CPython Decorator identity was decided by two different predicates. One read the raw decorator text, so a trailing comment such as `@staticmethod # type: ignore` hid the builtin and turned an explicit first parameter into a fabricated receiver. The other trusted any `staticmethod` spelling, including a module-level rebinding and a `staticmethod(classmethod(f))` stack, which CPython cannot call. Read the decorator expression node only, and recognize a bare builtin descriptor only when the file does not rebind that name. Publish subtype capacity only for a plain function or a single builtin staticmethod or classmethod wrapper. Drop a no-op coverage guard, move the implicit classmethod comment next to the code it describes, and bump the parse cache to v121. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): shadow builtin descriptors only by visible bindings The whole-file identifier scan counted plain reads (`staticmethod(f)`), `from builtins import staticmethod`, and bindings that run after the decorator as rebindings. CPython evaluates a class-body decorator with LOAD_NAME when the `def` runs, so none of those change which object the decorator names. Methods decorated with the real builtin lost their subtype call shape, and static methods lost their first parameter in arity metadata. Move decorator identity into builtin-descriptors.ts and count only binding occurrences (assignment and loop targets, walrus, def/class, parameters, import aliases, except/with/match captures, del, type parameters, and wildcard imports) that are visible where the decorator runs: the class body or module before the definition, a repeating enclosing loop, any binding in an enclosing function, and any global/nonlocal rebind. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): model global and del like CPython's symbol table `global x` and `nonlocal x` bind nothing; they redirect the declaring function's own bindings of `x` to an outer scope. A bare declaration was treated as an unconditional rebinding, so `@staticmethod` anywhere in the file lost builtin recognition. A module- or class-level `del` restores the outer lookup rather than binding the name. Treat an unconditional `del` that runs after a binding and before the decorator as undoing that binding. A `del` inside control flow may not run, and a `del` inside a function still makes the name local there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): order global rebinds and honor builtins re-exports A function that declares `global staticmethod` and assigns it rebinds the module name only when called, and it cannot be called before the top-level statement that defines it runs. Treat such a rebind as visible only when that statement precedes the decorator, or when the decorator sits in a deferred class body. `nonlocal` rebinds stay visible anywhere in the enclosing function. `from builtins import staticmethod as staticmethod` binds the builtin to its own name, so it no longer counts as shadowing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(python): scope the descriptor-identity CPython claim The wildcard-import case expects the fail-closed resolver verdict, not a CPython outcome, because the imported module's exports are unknown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): resolve descriptor names as LOAD_NAME does Model each binding by its effect on the namespace (Language Reference 4.2.1): an import that binds the `builtins` object itself (plain, aliased to the same name, or `from builtins import *`) restores the builtin, a module- or class-level `del` unbinds so lookup falls through, and any other binding shadows. Resolve the decorator like LOAD_NAME (4.2.2): the class namespace, then module globals, then builtins, each as it stands when the `def` runs. A restoring effect counts only as an unconditional simple statement that runs before the decorator, so an import or `del` under `if`/`try` or a loop stays fail-closed. A helper's `global` delete depends on whether the helper is called, which the resolver does not model, so it keeps the override. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(python): simplify decorator descriptor lookup Derive the descriptor type and name set from one `as const` list, replace indexed non-null assertions with destructuring, build the scope chain without an assertion, and skip the enclosing-function owner lookup when the decorator has no enclosing function. Key the stacked-decorator verdicts by case name so a failure names its case. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(python): resolve enclosing-function and deferred descriptor lookups A class body reads a free name from the innermost enclosing function that binds it (Language Reference 4.2.2). Evaluate that function's namespace the same way as the class and module ones, so an unconditional `from builtins import staticmethod` there resolves to the builtin. Any other binding still shadows, including a local assigned only after the class, which raises NameError rather than falling back to the builtin. A class body inside a function runs whenever that function is called, which can be any time after its top-level statement starts. Read module state at that statement instead of after the whole module, so an earlier `del` restores the builtin, and treat any later module override as possibly visible. 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> |
||
|
|
0bcddec8e6
|
fix(python): keep uncertain decorated receivers unresolved (#3405)
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 / 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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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
* fix(python): suppress uncertain decorated receivers * fix(ci): keep uncertain Python receivers out of method arity Unrecognized decorators now leave the receiver kind unproven, but the first parameter is still the implicit receiver slot for ordinary bound calls. Method extraction stopped stripping it, so decorated methods reported one extra parameter and shifted capture arity metadata. Share the uncertain-receiver classification between type-binding synthesis and parameter extraction, then refresh the Python capture golden and benchmark fingerprint for the intended capture change. 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> |
||
|
|
4569910c79
|
fix(process): exclude Dart test entry points (#3407)
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
0ef3f28d0e
|
fix(python): avoid receiverless subtype targets
Fixes #3396 |
||
|
|
b20c8b6ef2
|
fix(python): guard decorated subtype targets
Fixes #3398 |
||
|
|
3d09c85ee3
|
fix(python): record partial subtype dispatch coverage
Fixes #3395 |
||
|
|
52581cd4e9
|
test(group): make bridge mtime fixture deterministic
Fixes #3397 |
||
|
|
2925cfc024
|
fix(analyze): revisit dirty snapshots after clean revert (#3389)
* fix(analyze): revisit dirty snapshots after clean revert * test(shared-store): cover clean revert publication * fix(analyze): clear hidden index flags after clean runs * fix(analyze): reconcile hidden dirty paths * fix(analyze): detect newly hidden edits * test(bench): record hidden-index fixture calls * fix(analyze): clear restored mode-only receipts * test(bench): restore receiver baseline after mode fixture --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
c744ce1dfd
|
fix(python): resolve mixin calls with CPython C3 order (#3393)
* fix(python): resolve mixin calls with CPython C3 order Breadth-first MRO bound a diamond mixin call to the wrong base, and dropping the site left the real method out of the graph. Use C3 and take the first compatible method in that order. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(python): correct mixin receiver baseline counts * fix(python): guard incomplete mixin inheritance * fix(python): record unresolved MRO tail coverage (#3393) Track a missing subtype target when the last indexed MRO owner has an unindexed parent, and cover the case with an integration test. Correct the C3 fixture description. Note: local full npm test timed out amid parse-worker startup failures; focused tests and benchmark baseline passed. --------- 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> |
||
|
|
f6e70016d6
|
fix(python): resolve mixin self calls to subtype implementations (#3390)
* fix(python): resolve missing mixin self members through subtypes * fix: honor Python effective MRO and static mixin targets * fix: bind Python subtype dispatch to receiver provenance * fix(python): limit mixin fanout to instance receivers * fix(python): capture call arity and invalidate stale parsed facts * fix(python): count bound receivers by method context Preserve static, free, nested and typed variadic parameters; test renamed target receivers without weakening incompatible-arity rejection. Regenerate capture goldens for receiver metadata and eight mixin fixtures. Record the deliberate missing_target coverage outcome: CI measured Python call drops 5->6 and total call drops 113->114; no shape or scaling threshold relaxed. * test(python): require a call capture before checking unknown arity * fix(python): bind subtype dispatch to receiver definition * test(python): include conditional renamed-receiver target * fix(python): prove positional mixin targets and report partial coverage Preserve upstream notebook coordinate mapping and maintainer changes. Reject incompatible/implicit-class targets, retain proven targets across ambiguous alternatives, and report capped or unresolved coverage without confusing edge deduplication. * fix(python): isolate subtype call proof and preserve lookup boundaries --------- Co-authored-by: Eva <eva@100yen.org> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
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> |
||
|
|
86a39202cf
|
fix(#2965): system headers must not resolve to in-repo files (#3341)
* fix(#2965): system headers must not resolve to in-repo files C and C++ use two syntactically distinct include forms: #include <x.h> -- angle-bracket: search system include paths only #include "x.h" -- quoted: search relative to the including file first The old suffix-match fallback in resolveCImportTarget had no awareness of this distinction, so a repo containing its own stdio.h would capture every #include <stdio.h> and resolve it to the local file. Fix: - Add isSystem?: boolean to the wildcard variant of ParsedImportSyntax - interpretCImport / interpretCppImport now set isSystem from the @import.system tree-sitter capture (present for angle-bracket form) - resolveImportTarget in both cScopeResolver and cppScopeResolver short-circuits to null when context.parsedImport.isSystem is true, refusing to suffix-match system headers against workspace files - Remove C and C++ from KNOWN_GAPS in the conformance test; add proper test cases with a parsedImport factory that distinguishes angle-bracket (isSystem:true) from quoted (isSystem:false) includes Test: all 36 external-import-conformance cases pass, including the two new c/cpp arms that were previously in KNOWN_GAPS. * fix(#2965): update cpp-imports unit tests for isSystem field Two test assertions were broken by the interpreter change: 1. Local include: the wildcard ParsedImport now always includes isSystem (false for quoted includes). Updated expected object to include isSystem:false. 2. System header: the old test asserted interpretCppImport returned null for system headers. The refactored design moves the null decision to the resolver layer (cppScopeResolver.resolveImportTarget) so the call graph and resolution stay separate concerns. The interpreter now returns { kind:'wildcard', isSystem:true } and the test name/assertion are updated to reflect this. * fix(#2965): resolve C and C++ includes on search paths Angle includes follow each translation unit's include roots, so a local stdio.h no longer captures system headers or another file's -I list. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3341) - Accept in-repo include roots whose names start with `..` while still rejecting parent escapes. - Correct the import-target bench comments so CONTEXT_LANGS and newPass match C/C++ header passes. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(c,cpp): read include config per directory for monorepos (#2965) Angle includes now resolve only against declared search roots, so config read only at the repo root left monorepo sub-projects with nothing declared. - compile_commands.json, compile_flags.txt, .ccls, .clangd and c_cpp_properties.json are read in every directory; a file takes the nearest one, and a nearer database's entry beats a shallower one (clangd). - CMake include_directories / target_include_directories are read: directory-scoped and PRIVATE roots reach their subtree, PUBLIC and INTERFACE roots reach every file. ${CMAKE_CURRENT_SOURCE_DIR} and friends expand; unresolvable variables and generator expressions are dropped. - Declared roots win: implicit include/Headers/inc roots apply only when no config speaks for the file, and never to a database-listed file. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(c,cpp): give CMake PUBLIC includes only to linked targets (#3341) target_link_libraries now decides who sees PUBLIC and INTERFACE roots, so an unrelated target no longer resolves another package's headers. --------- 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: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
e137daf63b
|
fix(auto-sync): allow self-hosted remotes via allowed_hosts (#3391)
* fix(auto-sync): allow self-hosted remotes via allowed_hosts Auto-sync skipped any remote whose host was not github.com, gitlab.com, or gitee.com. Operators can now name exact extra DNS hosts in watch_config.yml without opening the default set. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3391) - Dial auto-sync DNS names as absolute hosts and store that URL so a later fetch cannot follow a search domain. - Reject ambiguous numeric host spellings; an exact dotted IPv4 the operator listed stays opt-in. - Document allowed_hosts on the root auto-sync contract. Note: pre-existing failure in unit tests that require dist/cli/index.js and parse-worker.js (this worktree has no build); not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
274ec3df6e
|
feat: index Jupyter notebooks as Python (#3381) | ||
|
|
51fb64c976
|
fix(swift): model Swift modules like the compiler (nested packages, Xcode targets, linear visibility) (#3387)
* fix(swift): discover nested Package.swift manifests for module grouping A Swift monorepo laid out as Core/<pkg>/Package.swift has no root manifest and no root Sources/, so every Swift file fell into one __default__ module. The Swift resolver now walks the repo (bounded, skipping dot, ignored, and Xcode bundle directories) and adds each nested package's targets, keyed by repo-relative directory and ordered deepest-first so first-match grouping picks the most specific target. Import resolution keeps the root view. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): bound implicit IMPORTS edges by a total budget Implicit same-module IMPORTS are n*(n-1) edges per module, and the graph keeps every relationship in one Map capped by V8 at 2^24 entries. Emission now fills a 4M-edge budget smallest module first and skips, with a warning, any module that does not fit, so no module layout can crash analyze. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): skip pairwise sibling passes for oversized modules The target-siblings and sibling-type-bindings passes copy every file's declarations into every other file of a module, so heap grows as n^2: about 3.8 GB at 1,000 files with 15 defs each, about 15 GB at 2,000. Modules over 1,000 files now skip both passes with a warning and resolve through the global name fallback. GITNEXUS_SWIFT_MAX_MODULE_FILES changes the ceiling. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(swift): cover nested SwiftPM packages end to end A fixture with three nested Package.swift manifests (two declaring a target named Net) and no root manifest. Each target gets its own implicit IMPORTS, none cross packages, and Config() resolves to the caller's own package. The Swift capture golden and scope-capture fingerprint grow with the new fixture corpus only. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(review): apply review findings - Rebase nested target paths with the existing Zig path helpers, which also reject Windows drive paths and paths that resolve to the repo root (whose empty prefix would group every file into one target). - Document GITNEXUS_SWIFT_MAX_MODULE_FILES in the README env table. - State that skipped modules resolve through lower-confidence fallback edges, why nested-type fragments still run for oversized modules, and fix a stale loader name in the target-grouping header. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(swift): cover every skipped Xcode bundle suffix in the package walk Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): model modules the way the compiler does Replace the caps from the first round with representations that stay linear, and derive module identity from the same sources the compiler uses. - Same-module visibility is one File -> Module IMPORTS edge per file (reason `module-membership`) instead of an edge per ordered file pair. Incremental importer expansion treats files sharing a Module hub as importers of each other. The 4M edge budget is gone. - Sibling declarations and type bindings live in one shared table per module in the namespace channel C# uses since #1871, instead of being copied into every file. The 1,000-file ceiling and GITNEXUS_SWIFT_MAX_MODULE_FILES are gone. - Modules come from root and nested SwiftPM manifests (Sources, Source, src, srcs; plugins under Plugins; the newest Package@swift-X.Y.swift) and from Xcode native targets in project.pbxproj, including Xcode 16 synchronized folders. Target paths are matched from the repo root, so a vendored copy of the same layout is no longer grouped into a root target (this reverses #2931's floating match). - `import X` resolves to the modules named X instead of any folder named X. A name no module carries is external when every manifest and project was read completely. - The global-name-fallback veto uses the same membership, so test targets, custom-path targets and Xcode targets have module identity. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(bench): move the Swift package bench to module grouping The bench still imported the removed groupSwiftFilesBySpmTarget. Its first-wins probe keeps its meaning under root-anchored grouping: the clash file sits under Sources/Mod0, and the Sources/Mod1 further down its path is a vendored copy. Plugins are now non-importable modules under Plugins/, so parse_targets counts importable source targets (still 3) and parse_binary_skipped also checks that the plugin is recorded that way. Baseline values unchanged; the notes say why the definitions moved. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): match compiler module names, manifests, and target filters - Module names follow the compiler's c99 mangling (`my-lib` imports as `my_lib`); Xcode targets use a literal PRODUCT_MODULE_NAME or PRODUCT_NAME when the project sets one. - Package manifests are one-file modules, as SwiftPM compiles them. Files outside every target are one-file modules once every manifest and project was read; otherwise they keep the shared __default__ module. - Xcode 16 synchronized-folder exceptions add a file to a target that does not list the folder, and remove it from one that does. - SwiftPM `sources:` / `exclude:` narrow a target; a computed list marks the manifest unreadable. - The default target folder is chosen once per package, as SwiftPM does, instead of per target. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback (#3387) - Inferred Swift folders keep SwiftPM's first predefined parent when a target name repeats (Sources before srcs). - The pbxproj parser rejects a \U escape without four hex digits instead of decoding garbage, so the project reads as incomplete. - Extension owners are stamped in every Xcode membership of a shared file. - A plugin name never reaches a plugin: neither the fallback veto nor the folder-index fallback treats a known non-importable module as imported. - A file an Xcode target compiles keeps that membership even when it also lies under a SwiftPM target directory. - The workspace scan bounds the queue, not only the directories read. - Integration tests require each module hub to exist before comparing. 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> |
||
|
|
0261982d9a
|
fix(analyze): make --memory-budget set the real heap and report rebuild reasons once (#3386)
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 / 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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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(analyze): --memory-budget flag with heap-limit override and worker-pool degradation (#3137) Adds an explicit `--memory-budget <mb>` CLI flag that overrides the RAM/cgroup auto-sized main-thread heap ceiling for the parse phase: - CLI validation (integer >= 200 MB) before bar.start(), matching the --workers pattern - Threaded CLI → runFullAnalysis → PipelineOptions → parse-impl as memoryBudgetBytes - parse-impl resolves the heap limit as budget ?? v8.heap_size_limit, so both the preflight projection warning and the #2649 mid-loop abort probe honor the budget - Graceful degradation: when the projected heap need exceeds the budget at the computed pool size, the pool shrinks (never below 1, never above the operator's --workers) before sub-batch math and pool construction, so all downstream consumers see the degraded size Omitting the flag keeps the auto-sizer path byte-identical. Refs #3137 * feat(analyze): collapse rebuild-gate log into one summary + persist needsFullRebuild verdict (#3137) The nine meta-mismatch rebuild gates (pdg mode, content retention, schema fingerprint, graph-write collapse, analysis features, Spring vendor prefixes, runner identity, FTS CJK mode, embedding dims) each logged individually and set force:true independently. An upgrade that trips several at once printed a scattered wall of near-identical warnings. - Gates now collect into rebuildReasons[]; a single summary block prints them (inline for one, numbered for many) and sets force once. Per-gate Tip text is preserved verbatim inside the entries. - The verdict persists to meta (needsFullRebuild: {reasons, recordedAt}) BEFORE the rebuild starts. If the rebuild is interrupted, the next run announces the recorded reasons up front instead of quietly attempting an incremental write on a half-rebuilt index — the gates may not all re-fire against a wiped DB. - The verdict is cleared on the next successful completion (the final meta does not carry the field forward). Semantics unchanged: every gate was already evaluated (none early-returns), force is idempotent, and a rebuild happens iff at least one reason fired. Refs #3137 * refactor(cli): share one integer flag parser across analyze, watch, and wiki Replace the duplicated Number.isInteger checks for --workers, --embeddings, the positive env-backed analyze flags, the watch interval flags, and wiki's --timeout/--retries with parseIntegerOption (per-flag minimum, optional scale for the safe-integer bound). User-facing messages are unchanged. * fix(analyze): make --memory-budget set the real V8 heap through the respawn The budget now drives ensureHeap's existing respawn instead of a parse-phase override, so the #2649 preflight, mid-loop abort, remedy text, and GC pacing all see one heap limit. The respawn sizes old space plus three semi-spaces to equal the budget, the child resolves as already at the budget (no second respawn), and GITNEXUS_HEAP_LIMIT_SOURCE drives budget-aware OOM advice. Budget validation moves to the preAction hook so analyze and watch reject a bad value before any respawn. Removes the pool-shrink block and the memoryBudgetBytes plumbing through PipelineOptions and run-analyze. * docs(analyze): describe --memory-budget accurately and translate its help The help text claimed graceful worker-pool degradation, which no longer exists; it now says the flag sets the main-thread V8 heap and that parse workers keep their own caps. Wires the option through the help i18n map with en and zh-CN strings, and documents it in both READMEs and the out-of-memory troubleshooting section. * feat(analyze): add a pure rebuild-reason collector One collector per run holds keyed rebuild reasons, merges by key, flattens reasons stored by an interrupted rebuild into one recovery entry, validates stored reasons on read, and formats the single up-front summary plus one follow-up line for reasons added after the pipeline. * fix(analyze): route every forced rebuild through one reason collector Every path that forces a full rebuild (the nine meta gates, --force, --skills, --no-parse-cache, --drop-embeddings, --repair-fts retention, Spring Actuator, AsyncAPI, shared-store graph gaps, dirty-flag recovery, the post-pipeline capability gate, and the #2409 escalation) now adds a keyed reason to one collector. The rebuild decision is applied from the collector at fixed checkpoints, one summary prints right before the pipeline, and late reasons print one follow-up line. The escalation stays non-forcing. runFullAnalysis returns the collected keys, which replaces the runner-identity source-regex test with a behavior test. Removes the separate needsFullRebuild field and its announcement, and stops folding --skills and --no-parse-cache into --force. * fix(analyze): persist rebuild reasons on the existing crash marker Every incrementalInProgress writer (the full-rebuild stamp before the wipe, the incremental pre-write, saveIncrementalDirtyState including the #2409 escalation, and buildFtsDirtyStamp) now carries the collected reasons into the active slot's metaDir, so an interrupted rebuild explains itself on the next run through one merged recovery entry. A successful run still clears the marker and its reasons; the FTS-park recovery clears them without forcing. * test(analyze): cover every rebuild-reason key through runFullAnalysis Add a coverage table that the typechecker keeps complete: every RebuildReasonKey maps to a test file that drives it through runFullAnalysis and asserts the returned key. Adds the missing graph-write-collapse and drop-embeddings drivers, asserts the key in the existing pdg-mode, spring-vendor-prefixes, cjk-segmentation, and embedding-dims tests, and removes plan-local IDs from test names and comments. * fix(review): apply review findings - A --max-old-space-size pin equal to --memory-budget no longer counts as the exact budget heap (V8 adds the young generation on top); only the budget-respawned child skips the respawn, so the limit really equals the budget. - Snapshot the analyze env before ensureHeap and restore GITNEXUS_HEAP_LIMIT_SOURCE, so a kept process does not leak its heap source into a later programmatic analyzeCommand call. - --skills and --no-parse-cache keep the forced storage requirements they had before force stopped being folded from them. - Merge the duplicated follow-up announcement into one helper and fix a stale --drop-embeddings comment. - The rebuild-reason coverage table no longer greps driver files for the key string; add tests for a programmatic invalid budget and the multi-cause interrupted-rebuild text. * fix(review): don't announce the escalated write as a full rebuild The #2409 escalation is a non-forcing reason, but its follow-up line used the 'Full rebuild also required' lead. A follow-up that carries only non-forcing reasons now leads with 'Write plan changed'. * docs(analyze): document GITNEXUS_HEAP_LIMIT_SOURCE in the env table CONTRIBUTING requires every new GITNEXUS_* variable to have a row; this one is internal (set by analyze itself) and exists so OOM advice points at --memory-budget. * fix(review): address GitNexus review threads on #3386 - heapPressureRemedy measures pressure against the real auto-sized cap (heapCapMbFor) instead of a flat 0.75 x RAM, and no longer tells a GITNEXUS_MEMORY=off run with no pin to drop a pin that does not exist. - toStored() persists the interrupted rebuild's reasons first, as documented. - ensureHeap's doc names which paths leave GITNEXUS_HEAP_LIMIT_SOURCE unset. - The heap-respawn suite restores the caller's GITNEXUS_MEMORY. - The non-forcing follow-up test rejects any 'full rebuild' wording. * fix(review): require both budget flags and check key coverage at runtime - A budget-respawned child is recognized only when the inherited heap-source marker comes with both the budget's old-space and semi-space flags; the marker alone is an inherited env var, not proof. The old-space parser is generalized to any V8 size flag instead of copying its regex. - REBUILD_REASON_KEYS is exported and RebuildReasonKey derives from it, so the coverage table is checked at runtime (CI does not type-check test files). * fix(review): don't claim a full rebuild in a non-forcing summary formatSummary and formatFollowUp now share one leadFor helper, so a block of only non-forcing reasons reads 'Write plan changed' in both. --------- Co-authored-by: ChunxueLi <mecoloud@users.noreply.gitee.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
5fc518d2cb
|
fix(dart): resolve package imports by pubspec identity (#3369)
* fix(dart): resolve package imports by pubspec identity * fix(dart): keep package-identity edges out of the cycle check Pubspec identity edges invalidate importers when a manifest changes. They cannot form an init cycle, so the cycle query excludes them before the row cap. Discovery reads each manifest once, with a size bound, and resolution shares one package-URI parser with those edges. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3369) - Reject package URIs with an empty library path so they do not emit identity edges - Skip the pubspec permission test where chmod cannot deny reads - Document that the Dart heap probe is not a uniqueTarget spelling Note: pre-existing failure in test/unit/incremental-index-extension-dml-gate.test.ts not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): list package directories through a no-follow descriptor A directory replaced by a symlink between the parent listing and the next visit must not be traversed. The walk opens it with O_DIRECTORY|O_NOFOLLOW and lists that inode. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(mcp): keep the Dart identity reason out of MCP startup The cycle query still excludes the same reason string. The constant now lives with the other non-initializing import reasons, so MCP startup does not load a language provider. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3369) Open discovered pubspecs and child directories through the parent directory inode on Linux, so replacing that directory with a symlink cannot redirect the walk. Note: pre-existing failure in test/unit/incremental-index-extension-dml-gate.test.ts (worker pool startup timeout) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): reject Windows junctions during pubspec walk * Address PR review feedback (#3369) Refuse pubspec discovery that cannot set O_NOFOLLOW, and verify macOS child opens against the pinned directory chain instead of reopening a mutable path. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): bound live pubspec descriptors and close the macOS check-then-open A deep directory chain held one descriptor per level until open failed with EMFILE, and macOS child opens statted the path before using it. Refuse the next directory at 64 live handles, and stat only the descriptor opened with O_NOFOLLOW. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): open pubspecs non-blocking so a FIFO cannot hang discovery A listed pubspec can be replaced by a FIFO before open. O_RDONLY alone waits inside open for a writer, so the file-type check never runs. O_NONBLOCK returns immediately and the walk rejects the non-regular file. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): cap names read from each pubspec directory readdir kept every entry before the visit budget could run, so one huge directory could allocate without bound. Read the listing one name at a time and fail closed past 100,000 entries. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): reject a pubspec that grows while its descriptor is read The size cap was taken from the stat before the read, so a file that grew in that window could be parsed from a short prefix. Re-stat the same descriptor afterward and fail closed when the size no longer matches the bytes captured. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): rebaseline the Dart scope-capture fingerprint for package-import fixtures The benchmark hashes every dart-* fixture. The new package-import corpus adds six Dart files and 33 capture groups. Parking that directory restores the previous fingerprint, so this is corpus growth, not a capture change. 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> |
||
|
|
4d262dd7d4
|
chore(deps)(deps): bump mnemonist from 0.40.4 to 0.40.5 in /gitnexus (#3384) | ||
|
|
06ce60beb6
|
chore(deps)(deps): bump ignore from 7.0.9 to 7.0.10 in /gitnexus (#3383)
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 / 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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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
Bumps [ignore](https://github.com/kaelzhang/node-ignore) from 7.0.9 to 7.0.10. - [Release notes](https://github.com/kaelzhang/node-ignore/releases) - [Commits](https://github.com/kaelzhang/node-ignore/compare/7.0.9...7.0.10) --- updated-dependencies: - dependency-name: ignore dependency-version: 7.0.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
e06c2dd13e
|
fix(impact): fail closed on id-less targets and follow ??/||/?: callable values (#3354) (#3373)
* fix(impact): fail closed on id-less targets and follow ??/||/?: callable values (#3354) #3354 reports `impact` returning a byte-identical 1037/CRITICAL/`exact` result for three unrelated targets, with only `target.name` differing. The reporter's `target` had no `id` and no `filePath`, which the traversal path always emits, and a synthetic reproduction of their monorepo (pnpm, Cloudflare worker-configuration.d.ts in five packages, Hono, a Durable Object) resolves every target correctly on main. So the identical result was not reproduced. The repro did surface two real gaps and one hardening point: - `_runImpactBFS` now throws when the target has no node id. Every caller already catches, so impact reports `impactedCount: null, risk: UNKNOWN` instead of a normal-looking blast radius that cannot be about this symbol. - Callable-value flow followed only a single designator on the RHS, so `const sweep = env.__sweep ?? runSweep; await sweep(env)` produced no flow and `scheduled` was missing as a caller of `runSweep`, while the result still claimed `epistemic: exact`. Each branch of `??`, `||`, `or`, and `?:` now flows into the binding (language-neutral: operator and field names, no language checks). Parse cache bumped 104 -> 112 (105-111 are claimed by open PR #3326). - A whitespace-only `target_uid` (strict adapters materialize omitted optional strings) is treated as omitted and falls back to the name. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): treat a non-string uid as omitted instead of throwing (#3354) Review follow-up on #3373. `query.uid?.trim()` called `.trim()` on a client-supplied value, and the MCP envelope is not type-validated, so `context({uid: 42})` threw a TypeError that `context()` does not catch. Before #3373 the same input ended as a structured not_found. A non-string uid now counts as omitted, which matches how normalizeToolParams already treats a non-string `target_uid`. The impact and trace not-found messages print a trimmed uid only when it is a non-blank string, so a strict adapter sending " " sees the name it searched for instead of `' '`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): expand ??/?:/ternary branches through a provider hook (#3354) Review follow-up on #3373. The shared value-alternatives rule keys on tree-sitter field names, and several grammars spell the same construct differently, so the expansion never fired for them: - Kotlin `elvis_expression` has no fields. - Swift uses `value`/`if_nil` and `if_true`/`if_false`. - Dart uses `first`/`second`, and its conditional has no `condition` field. - Python `a if c else b` has no fields. The `'?:'` operator entry was dead, since no bundled grammar emits it. Add an optional `valueAlternatives` hook to CallableFlowCaptureOptions, consulted before the shared rule, and implement it in the Kotlin, Swift, Dart, Python and Ruby providers. Shared code still names no language. Ruby's statement-bodied `if`/`unless`/`elsif` also carries `condition`/`consequence`/`alternative`, so the shared ternary rule dug an identifier out of an arbitrary statement (`g = h; 0` flowed `h`) and produced a wrong CALLS edge. The Ruby hook now keeps a multi-statement branch as one opaque source, as before #3373. Tests: new provider fixtures for Python, Kotlin, Swift, Dart and Ruby (including a Ruby negative), and TS chain, parenthesized, callable-left and `&&` negative cases. Captures goldens gain one entry each for the new fixtures. SCHEMA_BUMP stays 112 (same unreleased PR). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): keep long ||/??/?: chains linear in callable-flow capture (#3354) Expanding value-selecting sources into per-branch flows made long chains super-linear and, past a few thousand operands, a stack overflow. A generated `w === "k0" || w === "k1" || ...` keyword table took 6.7 s at 1000 operands and 48 s at 2000, and threw RangeError at 8000. Two causes, both fixed without changing any emitted capture: - valueAlternatives recursed once per operator level and spread the partial results at every level. It is now an explicit stack that writes to one output array. The left-to-right order, the paren unwrapping, and the provider-hook contract (`[node]` means opaque) are unchanged. - Every alternative ran its visibility walks from its own leaf, which can be as deep as the chain is long, all the way to the root. Also, tree-sitter's `parent` re-descends from the root, so each step costs the node's depth. The walks now jump between "anchor" nodes, the only nodes any check can match: region ids and formal owners. The nearest anchor is memoized per node across the file, and parents come from a map recorded by the one DFS the synthesizer already does. After the fix: 0.34 s / 0.23 s / 1.6 s at 1000 / 2000 / 8000 operands. That is within about 1.2x of main without the expansion; what remains is tree-sitter query time. Capture fingerprints are byte-identical before and after the fix for all 16 scope-capture bench languages and for the Python harness. A `typescript-deep-chain` case added to the scope-capture bench guards the scaling: 1.11-1.22 now, 7.5-8.0 before. A unit test pins a 10000-operand chain: it must still yield the seed for a callable operand, the copy for a formal at the deepest leaf, and the invoke. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(kotlin): see through braced if-branches in callable alternatives (#3354) tree-sitter-kotlin wraps a braced branch as `control_structure_body > statements > <expr>`, so for any non-empty block kotlinValueAlternatives saw exactly one named child (`statements`) and pushed the wrapper itself as the branch value. operandSyntax emits nothing for a `statements` node, so `val run = if (c) { ::f } else { ::g }; run()` produced no flow edges, and the "multi-statement block stays opaque" guard could never fire. Descend one level through `statements` and require exactly one non-comment expression there. Empty blocks (`{}` has no named children), multi-statement blocks, and `if` without `else` still return the whole `if` as one opaque source. The doc comment now describes that. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ruby): skip only the multi-statement branch in callable alternatives (#3354) rubyValueAlternatives returned `[node]` (opaque) as soon as one branch held more than one statement. Two things went wrong because of that: - At the top level, `run = if c then g = h; 0 else method(:f) end` dropped the single-statement `else`, so `f` got no flow edge. - In an elsif chain, the outer `if` pushed the `elsif` node as a branch. The shared loop called the hook on it again, got `[elsif]` back, and used the whole elsif subtree as one source. So in `if a then method(:run_a) elsif b then g = h; 0 else method(:run_b) end` the `run_b` edge was lost. The hook now walks the elsif chain itself and skips each multi-statement branch, while every single-statement branch still becomes an alternative. This cannot add a wrong edge: each emitted alternative is a value the conditional really evaluates to, and nothing is taken from the skipped branch. Before, that branch did not contribute a resolvable value either. A whole conditional used as a source becomes a qualified-name seed, which resolves to nothing when it has more than one identifier leaf. With a single identifier leaf, it could even seed the condition variable. When no branch is a single statement, the conditional still stays one opaque source, as before. Ruby captures golden: ruby-callable-alternatives/app.rb goes from 33 to 58 capture groups. 23 of them come from the new fixture functions (checked against the old source). The other 2 are the new branch alternatives, `statement_if -> run_sweep` and `elsif_chain -> run_b`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): flow the right operand of && / and into callable bindings (#3354) `a && b` / `a and b` yields `a` when it is falsy and `b` otherwise. A falsy value is never a callable, so the right operand is the only one that can be invoked later. The capture left `&&` unexpanded, and the compound source became a qualified seed that resolves to nothing: `const run = x && f; run()` gained no edge to `f` while impact claimed `exact`. Python `x and f or g` reached only `g`. The shared expansion now maps `&&` / `and` to the right branch only. It recurses, so `x and f or g` reaches both `f` and `g`. Where `&&` yields a boolean (Java, C#, Go, Rust, C, C++, PHP, Zig), the destination cannot be invoked, so the flow never meets a call. A before/after CALLS diff over all 83 lang-resolution fixtures that contain `&&` or `and` shows exactly one new edge, logicalAnd -> runAndRight. PHP and Ruby bind low-precedence `and` looser than `=`, so `$g = $x and $y` never reaches this rule. The Python golden digest changes only for the extended python-callable-alternatives fixture. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): keep operator branches of a value-selecting source opaque (#3354) The fan-out sent every branch of `??` / `||` / `or` / `?:` to emitAssignmentFact on its own, including branches that compute a value. `Handlers.fallback === run || fb` then emitted the comparison as a seed whose qualified text sliced to receiver `Handlers`, member `run`, and resolveBoundMemberCandidates minted a CALLS edge to `Handlers.run`. The same happened for `this.state !== run ?? this.fallback`, `this.state + run || this.fallback`, and Python `self.state != run or self.fallback`. Before the fan-out, the whole compound source was one opaque seed. A branch that is a binary operator expression now contributes nothing. The check uses the field vocabulary valueBranches already reads (a `left`/`right` pair, or an `operator`/`operators`/`op` token after the expression start), not grammar type names. Member accesses that field their `.`/`->` as `operator` (Ruby `call`, C/C++ `field_expression`) also field a member name through the list memberParts uses, now shared as memberNameNode, so they stay designators. Unary `&f`/`*fp` lead with their operator and stay designators. Call results were already dropped by emitAssignmentFact, and lambdas and callable references are unchanged. CALLS-edge diff over 87 lang-resolution fixtures (505 -> 501 edges): only the four false edges above were removed, and none were added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(ingestion): pin the LEFT operand of ?? / or / elvis per provider (#3354) The Python, Kotlin, Swift and Dart "override ?? fn" cases put an unresolvable parameter on the left, so a fan-out that kept only the last operand still passed them. Each fixture now adds a callableLeft case with a real function on the left and a parameter on the right (`run_left or fallback`, `::runLeft ?: fallback`, `runLeft ?? fallback`), and each language asserts `callableLeft → runLeft`. Mutation check: dropping the left branch from the shared `??`/`||`/`or` rule and making the four provider hooks return only their last operand fails all four new tests, while the existing right-operand tests still pass. Capture goldens were regenerated with UPDATE_GOLDEN=1: - python app.py: 35 -> 85 groups. 35 -> 75 is stale drift from |
||
|
|
6bb99767ff
|
fix(auto-sync): HTTPS remotes, OpenSSH image, and rc embeddings (#3378)
* fix(docker): install OpenSSH in the CLI runtime image Auto-sync requires git SSH remotes, but the published image omitted openssh-client so every clone failed with ssh: not found. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(auto-sync): accept HTTPS remotes and reclone failed checkouts Allowlisted HTTPS URLs can clone without SSH keys, and a timed-out clone with no remote.origin is quarantined instead of blocking forever. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(auto-sync): honor .gitnexusrc embeddings and warn on empty vectors Auto-sync analyze now reads embeddings from the clone's project config, and query reports when an index has no vectors so keyword fallback is visible. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(review): warn when CodeEmbedding table is missing (U5) Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): wrap long openssh-client test line for prettier Co-authored-by: Cursor <cursoragent@cursor.com> * fix(query): keep keyword-only indexes off query.warning Empty or missing CodeEmbedding is the default index. Put the #3372 notice in a once-per-backend log line so FTS-success query results stay warning-free. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(review): bound rc reads and quarantine only a missing origin Drop the implementation plan from the branch. Auto-sync reads .gitnexusrc through the bounded control-file reader, and a git config failure no longer relocates a live checkout. The same allowlisted repo can switch between SSH and HTTPS without a refused pull. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(auto-sync): share repo identity and skip a second origin read Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): clean temp fixtures and cover nested embeddings precedence Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): skip the symlink rc fixture on Windows Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): reject symlink rc files on every platform Co-authored-by: Cursor <cursoragent@cursor.com> * test(ci): run auto-sync symlink and clone tests on Windows and macOS Co-authored-by: Cursor <cursoragent@cursor.com> * test(git-clone): keep Windows CI on file URLs and POSIX permission checks Co-authored-by: Cursor <cursoragent@cursor.com> * test(git-clone): keep the SSH-to-HTTPS origin check offline Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
233ca28492
|
fix(ruby): model block-taking class factories (#3376)
* fix(ruby): model block-taking class factories * fix(ruby): cover braced factory blocks * handle brace factory blocks * fix nested Ruby factory ownership * test(ruby): pin factory ownership by node id * test(ruby): cover brace factory variants --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
ad5c7364e1
|
feat(storage): share one index store across linked worktrees and sibling clones (#3374)
* feat(storage): resolve the shared sibling-store identity and layout (#3352) Linked worktrees of one repository resolve to one store under GITNEXUS_HOME/stores/<key>, keyed by the canonical git common dir. The resolver reads the .git entry directly, so hot paths spawn no git. Slot naming moves to a leaf module so storage-resolver and shared-store do not import each other. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(storage): resolve a shared checkout's graph and existing store slot (#3352) getStoragePaths reads a flat slot's recorded graphPath only for checkout slots under the stores directory; other paths keep <storagePath>/lbug with no I/O. A recorded path outside the store's commit graphs is ignored. resolveStoragePath falls back to an existing store slot for an unregistered checkout, so reads never move to an empty slot. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(analyze): share one immutable commit graph across clean worktrees (#3352) A linked worktree writes its own slot in the shared store. A new slot is seeded with a pointer to the nearest commit graph, so a clean checkout at an indexed commit takes the up-to-date path and writes no graph. A checkout with local changes gets a copy-on-write private graph before its first write. After a successful run, a clean checkout at HEAD publishes its graph into commits/ under a store lock, or drops it when that commit graph already exists. Commit graphs are never written after publish. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(analyze): seed a worktree's graph from the nearest index (#3352) A new shared slot is seeded from the store's commit graph nearest to HEAD, else from this checkout's or the main checkout's repository-local index (copied under that index's lock, source left in place). The run that follows is up to date or incremental instead of a full build. If a pointed-at shared graph has been removed, analyze falls back to a full build instead of an incremental update over a missing baseline. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(analyze): keep one parse cache per shared store (#3352) Linked worktrees read and write the parse cache and durable ParsedFile store under the store's caches/ directory. Before pruning, a run folds in the chunk keys recorded by every member slot and commit graph, and the fold, prune and save run under a store-wide cache lock so one member never evicts another's live chunks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(clean): remove only what no shared-store member references (#3352) Deleting a shared checkout slot (clean, clean --all, remove, and the server delete route) recounts references under the store's publish lock and deletes commit graphs no member points at, then the store itself once empty. A graph that cannot be deleted (open on Windows) is reported and kept for the next pass. clean --gc also drops member slots whose worktree is gone or no longer resolves to the store. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(analyze): let a clone opt in to a shared store with --share-with (#3352) An independent clone joins a linked worktree's shared store only with analyze --share-with <repo>, and only when its normalized origin URL matches that member's (credentials stripped, as #2054 compares). The registry remembers the choice. --no-share moves an opted-in clone back to its own .gitnexus and reclaims its old slot; linked worktrees always share and are pointed at GITNEXUS_SHARED_STORE=off instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): count a shared checkout's commit graph as its code index (#3352) A clean shared checkout reads a commit graph and owns no graph file, so the code-index presence check made status report it unindexed and registry validation skip it. The check now follows the slot's validated graphPath. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(storage): adopt existing worktree indexes and report shared-store state (#3352) A shared checkout gets <repo>/.gitnexus/store.json pointing at its store slot; resolution follows it only when it names that checkout's own slot. An existing local index seeds the slot and is left in place. status (text and --json) and doctor report the store, whether the graph is shared or private, and any leftover local index, which clean --local-index removes while keeping the pointer. With GITNEXUS_SHARED_STORE=off a previously shared checkout indexes into its own .gitnexus again and never writes a commit graph. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(mcp): read the graph a shared checkout points at (#3352) MCP, the HTTP API, group sync, augmentation, and the Claude hook (all three byte-identical copies) resolve a flat slot's graph through resolveGraphPath instead of joining 'lbug' onto the storage path, so checkouts at one commit share one open database. The embeddings writers (embeddings sync and the server embed job) take a private copy first and never write an immutable commit graph. The post-analyze settle probe accepts fresh metadata that points at an existing commit graph. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: describe the shared worktree index store (#3352) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(storage): reuse helpers across the shared-store code (#3352) One graph-clone helper replaces two copy-then-rename blocks; clean and status reuse formatSlotSize; leaving a store reuses removeSharedStorePointer; withStoreLock is imported from its own module instead of a re-export. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): address review findings in the shared store (#3352) - Never publish a graph whose build saw dirty files, and never trust a local-index seed on the up-to-date path; it may hold reverted edits. - Record slot pointers and reclaim under the publish lock, and reclaim right after each publish, so a commit graph is never deleted between publish and pointer save and superseded graphs don't pile up. - clean --gc decides membership from the registry, so opted-in clones and a main checkout without worktrees are not dropped. - Leaving a store re-registers first, so an up-to-date run cannot leave the registry pointing at a deleted slot. - Drop pinned branch summaries when an entry moves into a store slot. - Keep run.cjs and the AGENTS.md runner path inside the checkout. - MCP handles follow the slot's current graph, and branch scoping reads the slot's own metadata. - Cache resolveGraphPath by metadata file identity; look up opted-in entries with canonical registry paths. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): localize help for the shared-store flags (#3352) --help renders option text from the i18n catalog, so --share-with, --no-share, clean --gc and clean --local-index need keys in both locales, not just index.ts literals. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): lock the embed-job graph copy and skip it on forced rebuilds (#3352) The server embed job copies a shared checkout's graph under the slot's index lock, so a CLI analyze in another process cannot interleave. A forced rebuild with no embeddings to carry over drops the pointer without copying a graph it would discard unread. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(agents): bump AGENTS.md version for the shared store notes (#3352) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): keep shared-store file reads inside checked paths (#3374) Address CodeQL js/path-injection and js/file-system-race on shared-store.ts: every filesystem read rebuilds its path under a fixed parent with an inline path.relative barrier, the .git probe is one read (EISDIR marks a directory) instead of stat-then-read, and the graph pointer cache stats and reads through one file descriptor. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): address review feedback on the shared store (#3374) - Hold the slot index lock for the whole server embedding job, not just the graph copy. - --no-share re-registers and deletes the old slot under that slot's index lock, so a running shared analyze cannot re-register it. - clean --gc previews without --force, like every other destructive arm. - status reports a pinned branch index as private. - Slot names prefix Windows device names that carry an extension. - A slot or store named ..<name> is a legal direct child. - Shared-store suites run in the serialized lbug-db vitest project and clear an inherited GITNEXUS_SHARED_STORE. - Doc and test accuracy fixes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(storage): pin shared-store behavior for worktrees of a bare repository (#3374) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): address second review round on the shared store (#3374) - Reject --no-share in a linked worktree before taking any lock or indexing anything. - clean --all and remove also delete each shared checkout's pointer. - Delete an empty store only while also holding its cache lock, and re-check emptiness under it. - A store pointer is trusted only when the slot's own metadata names this checkout; the editable pointer file just says where to look. - Device names with an extension are prefixed on Windows only, so POSIX slot names stay stable. - Test fixtures use the gitnexus-test- prefix the stale-sidecar sweep recognizes; help text and the private-graph label are accurate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(storage): address third review round on the shared store (#3374) - clean --gc never collects a slot whose index lock is held: an analyze holds it until it registers the checkout, so a seeded but not yet registered slot is busy, not orphaned. - Reclaim compares absolute paths, so a relative GITNEXUS_HOME does not make live commit graphs look unreferenced. - graphPath is followed only into a published <commit>-<featureKey> dir, never .publish-* staging (TS and all three hook copies). - clean --gc fails on an unreadable stores root instead of reporting nothing to collect. - --no-share help states it is for opted-in clones. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): land the English --no-share help and private-graph label (#3374) These two strings were meant for |
||
|
|
b92c14cdd0
|
feat: add Factory AI (Droid) integration (#2543)
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 / 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
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (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(setup): add Factory Droid (MCP + skills) to gitnexus setup Register 'droid' in the editor-targets abstraction so `gitnexus setup -c droid` writes the MCP server to ~/.factory/mcp.json and installs skills to ~/.factory/skills/ from the single canonical skills/ source (no per-editor copies). uninstall.ts is target-driven, so removal is covered automatically. Adds unit + round-trip coverage. * feat(plugin): add gitnexus-factory-plugin for droid plugin install * docs: add Factory Droid to editor support table and setup docs * fix(factory-plugin): guard augment hook against fan-out and DB contention Reuse the Claude adapter's acquireHookSlot and LadybugDB owner probe (bundled byte-identical, kept in lockstep by a drift test) instead of running an unguarded augment. Add direct tests for the hook and manifests. * docs: align Factory row in editor support table * fix(factory-plugin): honor GITNEXUS_HOOK_CLI_PATH so augment runs on Windows * docs(hooks): point bundled guard copies at their drift tests * docs(factory-plugin): note the Execute tokenizer's quoting limit * docs(readme): clarify the Full tier and group the Factory row * docs(hooks): trim drift note to a single line * test(ci): run factory-plugin tests on the windows cross-platform lane * refactor(hooks): drop the drift-note comments, the tests already enforce it * fix(factory-plugin): pin CLI version and parse quoted shell patterns - Pin mcp.json and the hook's npx fallback to gitnexus@<version> from the plugin manifest, registered with the release sync script so a mutable @latest can never execute on MCP connect or augment fallback - Port the #2938 shell tokenizer (tokenizeShellWords + parseRgGrepPattern) so quoted, backslash-escaped, --regexp=, -eVALUE, and -- patterns survive - Add the #2938 regression matrix and pin assertions to factory-plugin.test.ts * docs: add Factory Droid to published npm README * fix(factory-plugin): wire marketplace so droid installs the Factory plugin Add .factory-plugin/marketplace.json sourcing ./gitnexus-factory-plugin. Droid reads it before .claude-plugin/marketplace.json, so `droid plugin install` now delivers the Factory plugin (Execute matcher, pinned mcp.json) instead of the translated Claude plugin (Bash matcher, gitnexus@latest). Register the surface in the version-sync script and cover the wiring in the factory and sync test suites. * fix(factory-plugin): use registry lookup for index resolution Bundle registry-query.cjs so external indexes resolve (#3060); re-pin to 1.6.12. * fix(factory-plugin): sync Execute parser with Cursor hook Fixes echo-rg and -f false positives; tighten test env isolation. * fix(factory-plugin): stop no-match augment from re-running via npx A PATH `gitnexus` that finds no match exits 0 with empty stderr, which fell through to a second `npx -y gitnexus@<pin> augment` with its own 8s timeout (16s worst case vs the 10s hook budget). Fall through to npx only when the PATH launcher is missing (ENOENT); any launched PATH binary, including a timeout or non-zero exit, now ends the augment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(factory-plugin): filter augment stderr to the [GitNexus] block runAugment returned raw child stderr, so npm/Node/LadybugDB warnings leaked into additionalContext and noise-only stderr counted as success. Port the Claude adapter's extractAugmentContext (verbatim, with isDebugEnabled) and apply it on every launch tier before the success decision. Adds a drift test against the Claude copy and PATH-tier noise/noise-only behavior tests. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(factory-plugin): quote DROID_PLUGIN_ROOT in hook command An unquoted plugin root containing spaces (e.g. a Windows user profile path) split into multiple argv words, so the PostToolUse hook silently never ran. Quote it like the Claude plugin does, and pin the exact quoted command in the hooks.json wiring test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(release): stage Factory plugin manifests in the release commit The rc release job stages only the original four manifest surfaces in the detached release commit, so the v<version> tag tree carried the Factory plugin.json, mcp.json and marketplace.json at the previous version while --check (working tree) passed. Stage them too, and guard the git add block against the synced surfaces in sync-plugin-manifests.test.ts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(factory-plugin): simplify hook gates, spawn tiers and tests - main(): resolve the repo only after the tool-name and pattern gates, matching the Claude/Cursor hook order (skips fs/git work on no-op calls). - runAugment(): share one spawnAugment helper between the GITNEXUS_HOOK_CLI_PATH and npx tiers; PATH tier ENOENT logic unchanged. - factory-plugin test: pre-filter comment lines instead of `continue`. - sync-plugin-manifests test: hoist EXECUTABLE_MCP_FILES and derive TOTAL_SURFACES from its length. - fnSource(): throw when the function or its closing brace is not found. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): list Factory Droid in localized setup help `localizeCliHelp` overwrites the `setup` command description with the `help.command.setup.description` i18n key, so the literal edited in index.ts never reached `gitnexus setup --help`. Add Factory Droid to the en and zh-CN keys. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback (#2543) - factory hook: run every augment tier under the bundled Unix timeout guard (npx tier group-kills), keeping exactly-one-tier fall-through - hook-db-lock-probe: trim GITNEXUS_HOOK_{LSOF,PS}_PATH once so a padded override is used, not silently replaced (all 3 copies) - hook-lock: evict a stale slot via rename-to-tombstone + identity check, so a concurrently recreated fresh lock is never deleted (all 4 copies) - registry-query: a set-but-invalid storage override resolves no repo instead of falling back to the registry storagePath (all 4 copies) - publish.yml: stage the ten skill mcp.json manifests in the rc release commit; the staging test now requires every synced surface Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback round 2 (#2543) - hook-lock: replace rename-to-tombstone eviction with an O_EXCL per-slot `.evicting` marker plus an identity re-check before unlink, so a live lock is never moved, and a crashed evictor leaves only a self-expiring marker (all 4 copies) - hook-db-lock-probe: clamp GITNEXUS_HOOK_PROC_CMDLINE_MAX to a named 256 KiB ceiling and require an integer, so an oversized override can no longer fail the buffer allocation and miss a live owner (all 3 copies) - registry-query: treat an empty GITNEXUS_STORAGE_PATH/ROOT as set but invalid, matching the CLI's `!== undefined` rule (all 4 copies); the factory test env now deletes those keys instead of blanking them Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback round 3 (#2543) - hook-db-lock-probe: a capped /proc cmdline read stops early only once both the GitNexus token and the mcp/serve mode are present (or at EOF, the ceiling, or the budget), so a mode word such as `--require mcp` before the GitNexus path no longer hides a live owner (all 3 copies) - registry-query: correct the override comment; a filesystem root is invalid only for GITNEXUS_STORAGE_PATH, not GITNEXUS_STORAGE_ROOT (all 4 copies, comment only) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback round 4 (#2543) - hook-db-lock-probe: an fd-directory read error other than ENOENT or ENOTDIR on an identified server candidate now fails closed ('timeout') instead of reporting not-owned (EMFILE/ENFILE/ENOMEM/EINTR) - hook-db-lock-probe: resolve GITNEXUS_HOOK_TIMEOUT_PATH to an absolute path before validating and caching it, so callers that spawn with a request cwd can still execute the guard - hook-db-lock-probe: document the chunked cmdline read's actual stop conditions (all 3 copies) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Harden hook-lock eviction marker lifecycle (#2543) Per the chosen option (B) for the stale-slot eviction race: - `.evicting` markers carry a per-call owner token (pid + random hex) - an evictor re-reads its token immediately before the slot identity check and unlink; a stalled evictor whose marker was broken backs off - `finally` removes the marker only while it still holds our token - an orphaned marker is broken only if, re-checked just before unlink, its bigint identity and token are unchanged from when judged stale - doc comment states the two remaining two-syscall windows (slot lstat->unlink, marker token->unlink); POSIX has no conditional unlink, and the worst case is one extra concurrent augment All four byte-identical hook-lock copies updated. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Fix CodeQL file-system race in hook-lock orphan-marker check (#2543) breakOrphanedMarker stat'd the marker by path and then read it by path, which CodeQL flags (js/file-system-race): the file could be replaced between the two calls. Take the stat and the token from one open descriptor (readMarkerSnapshot, O_NOFOLLOW where available) for both the "judged stale" snapshot and the pre-unlink re-check. All four hook-lock copies updated. The replaced-marker test injected its swap via a readFileSync(path) spy, which no longer fires; it now swaps the marker just before its second open, counting opens of the marker path only (a per-path counter fired early on slot-0 and let a mutant pass). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Unregister hook-lock exit listener on release (#2543) Each acquireHookSlot registered `release` as a process 'exit' listener that was never removed, so a long-lived process acquiring and releasing slots repeatedly would accumulate listeners (MaxListenersExceededWarning) and retain every closure. release() now removes itself. All four hook-lock copies updated; a test asserts 12 acquire/release cycles leave the 'exit' listener count unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
3d24743241
|
chore(deps)(deps): bump lucide-react in /gitnexus-web (#3359)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.44.0 to 1.46.0. - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/1.46.0/packages/lucide-react) --- updated-dependencies: - dependency-name: lucide-react dependency-version: 1.46.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
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>
|
||
|
|
49c37092da
|
chore(deps)(deps): bump zod from 4.5.4 to 4.6.5 in /gitnexus-web (#3365)
Bumps [zod](https://github.com/colinhacks/zod) from 4.5.4 to 4.6.5. - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v4.5.4...v4.6.5) --- updated-dependencies: - dependency-name: zod dependency-version: 4.6.5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
57bd9e5229
|
chore(deps)(deps-dev): bump tsx from 4.23.13 to 4.23.15 in /gitnexus (#3364)
Bumps [tsx](https://github.com/privatenumber/tsx) from 4.23.13 to 4.23.15. - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.23.13...v4.23.15) --- updated-dependencies: - dependency-name: tsx dependency-version: 4.23.15 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
1d79571de9
|
chore(deps): bump docker/setup-qemu-action from 4.3.0 to 4.4.0 (#3368)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](
|
||
|
|
63a8dcc9b5
|
chore(deps)(deps-dev): bump @vercel/node in /gitnexus-web (#3363)
Bumps [@vercel/node](https://github.com/vercel/vercel/tree/HEAD/packages/node) from 5.10.2 to 7.0.0. - [Release notes](https://github.com/vercel/vercel/releases) - [Changelog](https://github.com/vercel/vercel/blob/main/packages/node/CHANGELOG.md) - [Commits](https://github.com/vercel/vercel/commits/7.0.0/packages/node) --- updated-dependencies: - dependency-name: "@vercel/node" dependency-version: 7.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
ce5831e342
|
chore(deps): bump docker/setup-buildx-action from 4.3.0 to 4.4.1 (#3367)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 4.3.0 to 4.4.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](
|
||
|
|
0b050a2a33
|
chore(deps)(deps-dev): bump @types/node in /gitnexus (#3366)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 26.6.0 to 26.6.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.6.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |