gitnexus 1.6.13-rc.42 → 1.6.13-rc.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +2 -1
  2. package/dist/_shared/scope-resolution/types.d.ts +6 -0
  3. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  4. package/dist/cli/auto-sync.js +4 -1
  5. package/dist/cli/i18n/en.d.ts +1 -1
  6. package/dist/cli/i18n/en.js +1 -1
  7. package/dist/cli/i18n/resources.d.ts +1 -1
  8. package/dist/cli/i18n/zh-CN.js +1 -1
  9. package/dist/core/auto-sync/config.d.ts +15 -3
  10. package/dist/core/auto-sync/config.js +120 -13
  11. package/dist/core/auto-sync/repo.d.ts +1 -1
  12. package/dist/core/auto-sync/repo.js +2 -2
  13. package/dist/core/auto-sync/runner.d.ts +1 -1
  14. package/dist/core/auto-sync/runner.js +10 -6
  15. package/dist/core/ingestion/languages/c/header-scan.d.ts +2 -4
  16. package/dist/core/ingestion/languages/c/header-scan.js +4 -51
  17. package/dist/core/ingestion/languages/c/import-target.d.ts +57 -10
  18. package/dist/core/ingestion/languages/c/import-target.js +151 -36
  19. package/dist/core/ingestion/languages/c/interpret.js +5 -4
  20. package/dist/core/ingestion/languages/c/resolution-config.d.ts +74 -0
  21. package/dist/core/ingestion/languages/c/resolution-config.js +802 -0
  22. package/dist/core/ingestion/languages/c/scope-resolver.js +12 -10
  23. package/dist/core/ingestion/languages/cpp/header-scan.d.ts +2 -5
  24. package/dist/core/ingestion/languages/cpp/header-scan.js +4 -46
  25. package/dist/core/ingestion/languages/cpp/import-target.d.ts +2 -10
  26. package/dist/core/ingestion/languages/cpp/import-target.js +8 -10
  27. package/dist/core/ingestion/languages/cpp/interpret.d.ts +2 -1
  28. package/dist/core/ingestion/languages/cpp/interpret.js +4 -5
  29. package/dist/core/ingestion/languages/cpp/scope-resolver.js +11 -11
  30. package/dist/server/git-clone.d.ts +11 -0
  31. package/dist/server/git-clone.js +18 -14
  32. package/dist/storage/parse-cache.js +4 -1
  33. package/package.json +1 -1
package/README.md CHANGED
@@ -354,6 +354,7 @@ max_concurrency: 1
354
354
  repo_git_timeout: 10s
355
355
  analyze_timeout: 5m
356
356
  analyze_failure_threshold: 3
357
+ # allowed_hosts: [gitlab.mycompany.com]
357
358
  projects:
358
359
  - local_path: /abs/path/to/repos
359
360
  branches: [master, main]
@@ -368,7 +369,7 @@ projects:
368
369
  - git@gitee.com:owner/repo.git
369
370
  ```
370
371
 
371
- `sync_interval_minutes` must be an integer of at least `5`. `local_path` must be an absolute path without traversal; each remote is cloned below it as `host/namespace/repo`, preventing same-basename repositories from colliding. `remote_urls` may use SSH SCP form (`git@host:owner/repo.git`) or HTTPS (`https://host/owner/repo.git`) for github.com, gitlab.com, or gitee.com. The published CLI image includes `openssh-client` so SSH remotes can clone; mount keys and `known_hosts` yourself. An invalid `watch_config.yml` skips auto-sync immediately with the validation error. `repo_git_timeout` applies to each repo clone/pull and defaults to `10s`; a bare number such as `10` is interpreted as seconds, while `10000ms`, `10s`, and `1m` keep their explicit units. It must not exceed one hour or `sync_interval_minutes`, whichever is smaller — so a bare `600000` is rejected, because it means 600000 seconds rather than milliseconds. `analyze_timeout` applies to each isolated analysis worker and defaults to half of `sync_interval_minutes`, but it is independent of polling and may be longer, up to Node's timer limit (`2147483647ms`). A `5` minute poll with `analyze_timeout: 30m` is valid. Auto-sync analysis honors the cloned repo's `.gitnexusrc` embeddings settings; the CLI image still needs `GITNEXUS_EMBEDDING_URL` or a bind-mounted embedding stack because npm is stripped. A tick that arrives while the previous loop is active never overlaps it: ticks coalesce into one immediate follow-up run, which pulls and analyzes the newest commit. If the parent times out and leaves that worker running, the follow-up is deferred to the next interval so a leftover lock holder is not counted as a hard analyze failure. Timeout and `auto-sync stop` request safe cancellation; a worker already in native work exits after it returns to a JS-visible safe point. While waiting, auto-sync reports `cancelling` or `stopping` and keeps its ownership files so another auto-sync cannot take over. The parent waits up to 5 seconds for the worker to exit; after that it stops waiting, releases its ownership files, and leaves the worker to finish and exit on its own rather than killing it mid-write. `auto-sync stop` uses this same control path on macOS and Windows.
372
+ `sync_interval_minutes` must be an integer of at least `5`. `local_path` must be an absolute path without traversal; each remote is cloned below it as `host/namespace/repo`, preventing same-basename repositories from colliding. `remote_urls` may use SSH SCP form (`git@host:owner/repo.git`) or HTTPS (`https://host/owner/repo.git`). Hosts are limited to github.com, gitlab.com, and gitee.com unless listed in top-level `allowed_hosts` (exact DNS names, no wildcards). The published CLI image includes `openssh-client` so SSH remotes can clone; mount keys and `known_hosts` yourself. An invalid `watch_config.yml` skips auto-sync immediately with the validation error. `repo_git_timeout` applies to each repo clone/pull and defaults to `10s`; a bare number such as `10` is interpreted as seconds, while `10000ms`, `10s`, and `1m` keep their explicit units. It must not exceed one hour or `sync_interval_minutes`, whichever is smaller — so a bare `600000` is rejected, because it means 600000 seconds rather than milliseconds. `analyze_timeout` applies to each isolated analysis worker and defaults to half of `sync_interval_minutes`, but it is independent of polling and may be longer, up to Node's timer limit (`2147483647ms`). A `5` minute poll with `analyze_timeout: 30m` is valid. Auto-sync analysis honors the cloned repo's `.gitnexusrc` embeddings settings; the CLI image still needs `GITNEXUS_EMBEDDING_URL` or a bind-mounted embedding stack because npm is stripped. A tick that arrives while the previous loop is active never overlaps it: ticks coalesce into one immediate follow-up run, which pulls and analyzes the newest commit. If the parent times out and leaves that worker running, the follow-up is deferred to the next interval so a leftover lock holder is not counted as a hard analyze failure. Timeout and `auto-sync stop` request safe cancellation; a worker already in native work exits after it returns to a JS-visible safe point. While waiting, auto-sync reports `cancelling` or `stopping` and keeps its ownership files so another auto-sync cannot take over. The parent waits up to 5 seconds for the worker to exit; after that it stops waiting, releases its ownership files, and leaves the worker to finish and exit on its own rather than killing it mid-write. `auto-sync stop` uses this same control path on macOS and Windows.
372
373
 
373
374
  `pdg` is configured per project. `pdg: true` builds and maintains the full CFG, control-dependence, reaching-definition, and taint layers on both initial and incremental analyses. Auto-sync requests staged atomic incremental publication where the analyzer supports it: the old graph remains available to readers until the replacement succeeds, and analysis errors are recorded while the old graph remains intact. Unsupported paths retain the analyzer's existing in-place behavior. Untouched configs that omit `pdg` preserve the existing index mode and cannot silently strip PDG data. Do not paste `pdg: false` from this example onto an existing watch file unless you intend to drop PDG. An explicit `pdg: false` disables PDG and emits a warning before a successful rebuild removes those layers. `overwrite_local_changes` defaults to `false`; a dirty local clone is skipped with an error log, while `true` allows branch fallback to replace local changes and additionally discards untracked files and directories in the clone after checkout — ignored paths, including GitNexus's own `.gitnexus/` storage, are preserved. `max_concurrency` defaults to `1` and is capped at runtime by `floor(availableMemoryGB / 2)` with a minimum of `1`; the effective value is printed at the start of each loop. Each analysis worker's heap cap is the machine-wide cap divided by the number of repositories analyzed in parallel, so concurrent workers share one memory budget instead of each claiming the whole machine. `analyze_failure_threshold` defaults to `3`, must be at least `2`, and pauses repeated failures only for the same repo branch, commit, and requested PDG mode; a new commit, a PDG mode change, or `gitnexus auto-sync reset` clears the block and allows analysis again. Repositories are registered and added to groups by their full remote identity (`host/namespace/repo`), so repositories with the same basename remain distinct. Use `branches` to try branches in order; legacy `branch` remains supported, but the two fields cannot be set together. If all branches are unavailable or time out, watch logs an error, records the repo status, and skips that repo for the loop. Leave `group_name` empty or omit it to skip group add/sync for that project; otherwise create the group first with `gitnexus group create <name>`. `$GITNEXUS_HOME/watch/project_commit_info.txt` is for inspection only; GitNexus stores machine state separately in `$GITNEXUS_HOME/watch/auto-sync-state.json`.
374
375
 
@@ -355,6 +355,12 @@ type ParsedImportSyntax =
355
355
  * deferred — `use` does not execute
356
356
  * (`LanguageProvider.importsExecuteWhereWritten`). */
357
357
  readonly runsOnlyWhenCalled?: boolean;
358
+ /**
359
+ * C/C++ `#include <…>` (true) versus `#include "…"`.
360
+ * Angle includes resolve only on header search paths. Quoted includes
361
+ * may still use the including file's directory and the basename index.
362
+ */
363
+ readonly isSystem?: boolean;
358
364
  }
359
365
  /**
360
366
  * Runtime-computed target — the import path is not a static literal at
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,4FAA4F;AAC5F,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,0DAA0D;AAC1D,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC;AAE3B;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,WAAW,GACX,OAAO,GACP,UAAU,GACV,OAAO,GACP,YAAY,GACZ,QAAQ,CAAC;AAIb,qFAAqF;AACrF,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI7D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG;IAC9C;;0DAEsD;IACtD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,KAAK,kBAAkB;AACrB;;;;;;;GAOG;AACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;mEAI+D;IAC/D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AACH;;;;;;GAMG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5D;;8EAE0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;+DAE2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C,iDAAiD;IACjD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;sDACkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;kDAC8C;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;wFACoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;sDAQkD;IAClD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;;;;;;;;GAiBG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;2DAOuD;IACvD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;GASG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;8EAC0E;IAC1E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;;;;;;;GAgBG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;4EAEwE;IACxE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;uEAEmE;IACnE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;uDACmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC;AAMrC;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;CAC1C;AAED,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;iEAC6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAID;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;IAC7B,QAAQ,CAAC,IAAI,EACT,OAAO,GACP,OAAO,GACP,WAAW,GACX,mBAAmB,GACnB,UAAU,GACV,oBAAoB,GACpB,kBAAkB,GAClB,aAAa,CAAC;IAClB,oFAAoF;IACpF,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC;CACpC;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5E,sGAAsG;IACtG,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC;CAC9C;AAID;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,6FAA6F;IAC7F,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,EACX,YAAY,GACZ,sBAAsB,GACtB,mBAAmB,GACnB,MAAM,GACN,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,CAAC;IAC1B,iGAAiG;IACjG,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACxC;AAID;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC;IAE9D,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAEhD;;kDAE8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IAExC,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEpD;;uEAEmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE5C;;;;;;;;;;;gEAW4D;IAC5D,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EACT,OAAO,GACP,aAAa,GACb,QAAQ,GACR,cAAc,GACd,aAAa,GACb,YAAY,GACZ,aAAa,GACb,aAAa,GACb,kBAAkB,GAClB,2BAA2B,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACpC;AAID;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,IAAI,EACT,MAAM,GACN,MAAM,GACN,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,YAAY,GACZ,WAAW,GACX,OAAO,CAAC;IACZ;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;;8DAG0D;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAClD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IACnE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;CAChE;AAID;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE1C;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7C,wDAAwD;IACxD,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC5D,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;gFAE4E;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"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"}
@@ -96,6 +96,9 @@ function defaultSyncConfig(localPath) {
96
96
  'repo_git_timeout: 10s',
97
97
  'analyze_timeout: 5m',
98
98
  'analyze_failure_threshold: 3',
99
+ '# Extra SSH/HTTPS hosts beyond github.com, gitlab.com, and gitee.com.',
100
+ '# Exact DNS names only; wildcards are rejected.',
101
+ '# allowed_hosts: [gitlab.mycompany.com]',
99
102
  'projects:',
100
103
  ` - local_path: ${localPath}`,
101
104
  ' branches: [master, main]',
@@ -106,7 +109,7 @@ function defaultSyncConfig(localPath) {
106
109
  ' overwrite_local_changes: false',
107
110
  ' remote_urls:',
108
111
  ' - git@github.com:owner/repo.git',
109
- ' # HTTPS remotes on github.com, gitlab.com, or gitee.com are also allowed',
112
+ ' # HTTPS remotes are also allowed. Other hosts need top-level allowed_hosts.',
110
113
  ' # - https://github.com/owner/public-repo.git',
111
114
  '',
112
115
  ].join('\n');
@@ -170,7 +170,7 @@ export declare const en: {
170
170
  readonly 'help.command.setup.description': 'One-time setup: configure MCP for Cursor, Claude Code, Antigravity, OpenCode, CodeBuddy, Qoder, Codex, Factory Droid';
171
171
  readonly 'help.command.uninstall.description': 'Reverse `setup`: remove GitNexus MCP entries, skills, and hooks from all detected editors';
172
172
  readonly 'help.command.autoSync.description': 'Control scheduled repository clone/pull and analysis from GITNEXUS_HOME/watch_config.yml';
173
- readonly 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.';
173
+ readonly 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Other hosts need a top-level allowed_hosts list of exact DNS names. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.';
174
174
  readonly 'help.command.watch.description': 'Ambiguous: use `analyze --watch` for local files, or `auto-sync` for scheduled remotes';
175
175
  readonly 'help.watch.details': '\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n';
176
176
  readonly 'error.watch.ambiguous': '`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n';
@@ -172,7 +172,7 @@ export const en = {
172
172
  'help.command.setup.description': 'One-time setup: configure MCP for Cursor, Claude Code, Antigravity, OpenCode, CodeBuddy, Qoder, Codex, Factory Droid',
173
173
  'help.command.uninstall.description': 'Reverse `setup`: remove GitNexus MCP entries, skills, and hooks from all detected editors',
174
174
  'help.command.autoSync.description': 'Control scheduled repository clone/pull and analysis from GITNEXUS_HOME/watch_config.yml',
175
- 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.',
175
+ 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Other hosts need a top-level allowed_hosts list of exact DNS names. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.',
176
176
  'help.command.watch.description': 'Ambiguous: use `analyze --watch` for local files, or `auto-sync` for scheduled remotes',
177
177
  'help.watch.details': '\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n',
178
178
  'error.watch.ambiguous': '`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n',
@@ -171,7 +171,7 @@ export declare const cliResources: {
171
171
  readonly 'help.command.setup.description': 'One-time setup: configure MCP for Cursor, Claude Code, Antigravity, OpenCode, CodeBuddy, Qoder, Codex, Factory Droid';
172
172
  readonly 'help.command.uninstall.description': 'Reverse `setup`: remove GitNexus MCP entries, skills, and hooks from all detected editors';
173
173
  readonly 'help.command.autoSync.description': 'Control scheduled repository clone/pull and analysis from GITNEXUS_HOME/watch_config.yml';
174
- readonly 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.';
174
+ readonly 'help.autoSync.details': '\nActions: init, start (default), restart, stop, status, reset\nConfiguration: GITNEXUS_HOME/watch_config.yml\nRuntime files: GITNEXUS_HOME/watch/watch.pid, watch.mutex, watch.owner.json, watch.status.json, auto-sync-state.json\nRecovery: mutexes with verified dead owners are reclaimed automatically; invalid or legacy mutexes fail closed and require manual removal after confirming no watch process is running.\nWrites: GITNEXUS_HOME/watch/project_commit_info.txt\nRemote URLs: SSH or HTTPS URLs on github.com, gitlab.com, and gitee.com are allowed. Other hosts need a top-level allowed_hosts list of exact DNS names. Invalid watch_config.yml skips auto-sync immediately.\nRuns once immediately, then repeats on sync_interval_minutes.';
175
175
  readonly 'help.command.watch.description': 'Ambiguous: use `analyze --watch` for local files, or `auto-sync` for scheduled remotes';
176
176
  readonly 'help.watch.details': '\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n';
177
177
  readonly 'error.watch.ambiguous': '`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n';
@@ -170,7 +170,7 @@ export const zhCN = {
170
170
  'help.command.setup.description': '一次性设置:为 Cursor、Claude Code、Antigravity、OpenCode、CodeBuddy、Qoder、Codex、Factory Droid 配置 MCP',
171
171
  'help.command.uninstall.description': '撤销 `setup`:从所有检测到的编辑器中移除 GitNexus 的 MCP 配置、技能和钩子',
172
172
  'help.command.autoSync.description': '控制基于 GITNEXUS_HOME/watch_config.yml 的定时 clone/pull 和分析',
173
- 'help.autoSync.details': '\n操作:init、start(默认)、restart、stop、status、reset\n配置:GITNEXUS_HOME/watch_config.yml\n运行时文件:GITNEXUS_HOME/watch/watch.pid、watch.mutex、watch.owner.json、watch.status.json、auto-sync-state.json\n恢复:已验证 owner 退出的 mutex 会自动回收;无效或旧版 mutex 会安全拒绝,确认没有 watch 进程运行后再手动删除。\n写入:GITNEXUS_HOME/watch/project_commit_info.txt\n远程地址:允许 github.com、gitlab.com 和 gitee.com 上的 SSH 或 HTTPS 地址。无效的 watch_config.yml 会立即跳过 auto-sync。\n启动后立即运行一次,之后按 sync_interval_minutes 重复。',
173
+ 'help.autoSync.details': '\n操作:init、start(默认)、restart、stop、status、reset\n配置:GITNEXUS_HOME/watch_config.yml\n运行时文件:GITNEXUS_HOME/watch/watch.pid、watch.mutex、watch.owner.json、watch.status.json、auto-sync-state.json\n恢复:已验证 owner 退出的 mutex 会自动回收;无效或旧版 mutex 会安全拒绝,确认没有 watch 进程运行后再手动删除。\n写入:GITNEXUS_HOME/watch/project_commit_info.txt\n远程地址:允许 github.com、gitlab.com 和 gitee.com 上的 SSH 或 HTTPS 地址。其他主机需在顶层 allowed_hosts 中列出精确 DNS 名称。无效的 watch_config.yml 会立即跳过 auto-sync。\n启动后立即运行一次,之后按 sync_interval_minutes 重复。',
174
174
  'help.command.watch.description': '含义不明确:本地文件请用 `analyze --watch`,定时远程同步请用 `auto-sync`',
175
175
  'help.watch.details': '\n`gitnexus watch` 不会启动监视器。\n 本地工作区增量索引:gitnexus analyze --watch\n 定时远程 clone/pull 并分析:gitnexus auto-sync start\n',
176
176
  'error.watch.ambiguous': '`gitnexus watch` 含义不明确。\n 本地工作区增量索引:gitnexus analyze --watch\n 定时远程 clone/pull 并分析:gitnexus auto-sync start\n',
@@ -1,5 +1,12 @@
1
1
  export declare const AUTO_SYNC_CONFIG_FILE = "watch_config.yml";
2
2
  export declare const DEFAULT_ANALYZE_FAILURE_THRESHOLD = 3;
3
+ /**
4
+ * Name git should resolve. A trailing dot forces an absolute lookup, so a
5
+ * search list cannot answer `git` as `git.<domain>` or retry an FQDN under
6
+ * that domain after NXDOMAIN. A strict IPv4 literal stays undotted: `10.0.0.1.`
7
+ * is a DNS name, not that address.
8
+ */
9
+ export declare function absoluteAutoSyncRemoteUrl(remoteUrl: string): string;
3
10
  export interface AutoSyncProjectConfig {
4
11
  localPath: string;
5
12
  groupName?: string;
@@ -16,6 +23,11 @@ export interface AutoSyncConfig {
16
23
  analyzeTimeoutMs: number;
17
24
  maxConcurrency: number;
18
25
  analyzeFailureThreshold: number;
26
+ /**
27
+ * Extra remote hosts from top-level `allowed_hosts`, already lowercased.
28
+ * Omitted on hand-built configs; treated as none.
29
+ */
30
+ allowedHosts?: readonly string[];
19
31
  projects: AutoSyncProjectConfig[];
20
32
  }
21
33
  export type AutoSyncConfigLoadResult = {
@@ -30,12 +42,12 @@ export declare function getAutoSyncConfigPath(gitnexusDir?: string): string;
30
42
  export declare function parseBranchCandidates(branchValue: unknown): string[];
31
43
  export declare function loadAutoSyncConfig(configPath?: string): Promise<AutoSyncConfigLoadResult>;
32
44
  export declare function parseAutoSyncConfig(content: string, configPath: string): AutoSyncConfig;
33
- export declare function parseAutoSyncRemoteIdentity(remoteUrl: string): {
45
+ export declare function parseAutoSyncRemoteIdentity(remoteUrl: string, allowedHosts?: readonly string[]): {
34
46
  host: string;
35
47
  repoPath: string;
36
48
  };
37
49
  /** Canonical `host/owner/repo` key. Strips one trailing `.git`. Throws on an invalid remote. */
38
- export declare function getAutoSyncRepoIdentity(remoteUrl: string): string;
39
- export declare function validateAutoSyncRemoteUrl(remoteUrl: string): void;
50
+ export declare function getAutoSyncRepoIdentity(remoteUrl: string, allowedHosts?: readonly string[]): string;
51
+ export declare function validateAutoSyncRemoteUrl(remoteUrl: string, allowedHosts?: readonly string[]): void;
40
52
  export declare function validateAutoSyncBranchName(branch: string): void;
41
53
  export declare function parseDurationMs(value: unknown): number;
@@ -14,7 +14,69 @@ const DEFAULT_REPO_GIT_TIMEOUT_MS = 10_000;
14
14
  const DEFAULT_MAX_CONCURRENCY = 1;
15
15
  export const DEFAULT_ANALYZE_FAILURE_THRESHOLD = 3;
16
16
  const MIN_ANALYZE_FAILURE_THRESHOLD = 2;
17
- const ALLOWED_REMOTE_HOSTS = new Set(['github.com', 'gitlab.com', 'gitee.com']);
17
+ const BUILTIN_REMOTE_HOSTS = new Set(['github.com', 'gitlab.com', 'gitee.com']);
18
+ // Exact DNS names only. The host is a directory under local_path, so wildcards,
19
+ // ports, and path characters stay out. A label is 1-63 chars and cannot start
20
+ // or end with a hyphen; the whole name is at most 253 characters.
21
+ // One trailing dot is stripped before this runs: it marks an absolute lookup,
22
+ // it is not a different host.
23
+ const AUTO_SYNC_HOST_PATTERN = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/;
24
+ /** Lowercase, and drop one trailing root dot so `git.` and `git` are one host. */
25
+ function canonicalAutoSyncHost(host) {
26
+ return host.trim().toLowerCase().replace(/\.$/, '');
27
+ }
28
+ function isStrictDottedQuad(host) {
29
+ const labels = host.split('.');
30
+ if (labels.length !== 4)
31
+ return false;
32
+ return labels.every((label) => /^(0|[1-9]\d{0,2})$/.test(label) && Number(label) <= 255);
33
+ }
34
+ /**
35
+ * Spellings glibc inet_aton dials as a different address than the token
36
+ * (`192.168.1` → 192.168.0.1, `0x7f.0.0.1` / `2130706433` → 127.0.0.1).
37
+ * A strict four-octet address is the address written; listing it is opt-in.
38
+ */
39
+ function isAmbiguousNumericHost(host) {
40
+ const labels = host.split('.');
41
+ if (labels.some((label) => /^0x[0-9a-f]+$/i.test(label) || /^0\d/.test(label)))
42
+ return true;
43
+ return labels.every((label) => /^\d+$/.test(label)) && !isStrictDottedQuad(host);
44
+ }
45
+ function autoSyncHostProblem(host) {
46
+ if (!AUTO_SYNC_HOST_PATTERN.test(host))
47
+ return 'shape';
48
+ if (isAmbiguousNumericHost(host))
49
+ return 'numeric';
50
+ return null;
51
+ }
52
+ function autoSyncHostProblemMessage(problem) {
53
+ return problem === 'numeric'
54
+ ? 'must not use an ambiguous numeric spelling'
55
+ : 'must be a DNS hostname';
56
+ }
57
+ function rewriteAutoSyncRemoteHost(remoteUrl, mapHost) {
58
+ const ssh = /^(git@)([^:\s/]+)(:[^\s]+)$/.exec(remoteUrl);
59
+ if (ssh)
60
+ return `${ssh[1]}${mapHost(ssh[2])}${ssh[3]}`;
61
+ const https = /^(https:\/\/)([^/\s]+)(\/[^\s]+)$/.exec(remoteUrl);
62
+ if (https)
63
+ return `${https[1]}${mapHost(https[2])}${https[3]}`;
64
+ return remoteUrl;
65
+ }
66
+ /**
67
+ * Name git should resolve. A trailing dot forces an absolute lookup, so a
68
+ * search list cannot answer `git` as `git.<domain>` or retry an FQDN under
69
+ * that domain after NXDOMAIN. A strict IPv4 literal stays undotted: `10.0.0.1.`
70
+ * is a DNS name, not that address.
71
+ */
72
+ export function absoluteAutoSyncRemoteUrl(remoteUrl) {
73
+ return rewriteAutoSyncRemoteHost(remoteUrl.trim(), (host) => {
74
+ const canonical = canonicalAutoSyncHost(host);
75
+ if (isStrictDottedQuad(canonical))
76
+ return canonical;
77
+ return `${canonical}.`;
78
+ });
79
+ }
18
80
  /**
19
81
  * A single clone/pull must fit inside one sync interval and inside an hour.
20
82
  * This is also the guard for the unit slip the bare-number rule invites:
@@ -148,6 +210,7 @@ export function parseAutoSyncConfig(content, configPath) {
148
210
  analyzeFailureThreshold < MIN_ANALYZE_FAILURE_THRESHOLD) {
149
211
  errors.push(`analyze_failure_threshold must be an integer >= ${MIN_ANALYZE_FAILURE_THRESHOLD}`);
150
212
  }
213
+ const allowedHosts = parseAllowedAutoSyncHosts(raw.allowed_hosts, errors);
151
214
  const rawProjects = raw.projects;
152
215
  if (!Array.isArray(rawProjects) || rawProjects.length === 0) {
153
216
  errors.push('projects must contain at least one project');
@@ -180,7 +243,7 @@ export function parseAutoSyncConfig(content, configPath) {
180
243
  }
181
244
  for (let urlIndex = 0; urlIndex < remoteUrls.length; urlIndex += 1) {
182
245
  try {
183
- validateAutoSyncRemoteUrl(remoteUrls[urlIndex]);
246
+ validateAutoSyncRemoteUrl(remoteUrls[urlIndex], allowedHosts);
184
247
  }
185
248
  catch (err) {
186
249
  errors.push(`projects[${index}].remote_urls[${urlIndex}] ${err.message}`);
@@ -234,10 +297,39 @@ export function parseAutoSyncConfig(content, configPath) {
234
297
  analyzeTimeoutMs,
235
298
  maxConcurrency,
236
299
  analyzeFailureThreshold,
300
+ allowedHosts,
237
301
  projects,
238
302
  };
239
303
  }
240
- export function parseAutoSyncRemoteIdentity(remoteUrl) {
304
+ function parseAllowedAutoSyncHosts(value, errors) {
305
+ if (value === undefined)
306
+ return [];
307
+ if (!Array.isArray(value)) {
308
+ errors.push('allowed_hosts must be a list of DNS hostnames');
309
+ return [];
310
+ }
311
+ const hosts = [];
312
+ const seen = new Set();
313
+ for (let index = 0; index < value.length; index += 1) {
314
+ const entry = value[index];
315
+ if (typeof entry !== 'string') {
316
+ errors.push(`allowed_hosts[${index}] must be a DNS hostname`);
317
+ continue;
318
+ }
319
+ const host = canonicalAutoSyncHost(entry);
320
+ const problem = autoSyncHostProblem(host);
321
+ if (problem) {
322
+ errors.push(`allowed_hosts[${index}] ${autoSyncHostProblemMessage(problem)}`);
323
+ continue;
324
+ }
325
+ if (seen.has(host))
326
+ continue;
327
+ seen.add(host);
328
+ hosts.push(host);
329
+ }
330
+ return hosts;
331
+ }
332
+ export function parseAutoSyncRemoteIdentity(remoteUrl, allowedHosts) {
241
333
  const trimmed = remoteUrl.trim();
242
334
  if (trimmed.includes('?') || trimmed.includes('#')) {
243
335
  throw new Error('must not include query strings or fragments');
@@ -258,23 +350,38 @@ export function parseAutoSyncRemoteIdentity(remoteUrl) {
258
350
  }
259
351
  }
260
352
  else {
261
- throw new Error('must use an SSH or HTTPS URL on github.com, gitlab.com, or gitee.com');
353
+ throw new Error('must use an SSH or HTTPS URL (git@host:owner/repo or https://host/owner/repo)');
262
354
  }
263
- host = host.toLowerCase();
264
- assertAutoSyncRemotePath(host, repoPath);
355
+ host = canonicalAutoSyncHost(host);
356
+ assertAutoSyncRemotePath(host, repoPath, allowedHosts);
265
357
  return { host, repoPath };
266
358
  }
267
359
  /** Canonical `host/owner/repo` key. Strips one trailing `.git`. Throws on an invalid remote. */
268
- export function getAutoSyncRepoIdentity(remoteUrl) {
269
- const { host, repoPath } = parseAutoSyncRemoteIdentity(remoteUrl);
360
+ export function getAutoSyncRepoIdentity(remoteUrl, allowedHosts) {
361
+ const { host, repoPath } = parseAutoSyncRemoteIdentity(remoteUrl, allowedHosts);
270
362
  return `${host}/${repoPath.replace(/\.git$/i, '')}`;
271
363
  }
272
- export function validateAutoSyncRemoteUrl(remoteUrl) {
273
- parseAutoSyncRemoteIdentity(remoteUrl);
364
+ export function validateAutoSyncRemoteUrl(remoteUrl, allowedHosts) {
365
+ parseAutoSyncRemoteIdentity(remoteUrl, allowedHosts);
274
366
  }
275
- function assertAutoSyncRemotePath(host, repoPath) {
276
- if (!ALLOWED_REMOTE_HOSTS.has(host)) {
277
- throw new Error('host must be one of github.com, gitlab.com, or gitee.com');
367
+ function isPermittedAutoSyncHost(host, allowedHosts) {
368
+ if (BUILTIN_REMOTE_HOSTS.has(host))
369
+ return true;
370
+ if (!allowedHosts)
371
+ return false;
372
+ for (const entry of allowedHosts) {
373
+ if (canonicalAutoSyncHost(entry) === host)
374
+ return true;
375
+ }
376
+ return false;
377
+ }
378
+ function assertAutoSyncRemotePath(host, repoPath, allowedHosts) {
379
+ const problem = autoSyncHostProblem(host);
380
+ if (problem) {
381
+ throw new Error(`host ${autoSyncHostProblemMessage(problem)}`);
382
+ }
383
+ if (!isPermittedAutoSyncHost(host, allowedHosts)) {
384
+ throw new Error('host must be one of github.com, gitlab.com, or gitee.com, or listed in top-level allowed_hosts');
278
385
  }
279
386
  const pathParts = repoPath.split('/');
280
387
  // Every segment becomes a directory component: the namespace segments build
@@ -1 +1 @@
1
- export declare function extractRepoNameFromRemoteUrl(remoteUrl: string): string;
1
+ export declare function extractRepoNameFromRemoteUrl(remoteUrl: string, allowedHosts?: readonly string[]): string;
@@ -1,6 +1,6 @@
1
1
  import { extractRepoName } from '../../server/git-clone.js';
2
2
  import { validateAutoSyncRemoteUrl } from './config.js';
3
- export function extractRepoNameFromRemoteUrl(remoteUrl) {
4
- validateAutoSyncRemoteUrl(remoteUrl);
3
+ export function extractRepoNameFromRemoteUrl(remoteUrl, allowedHosts) {
4
+ validateAutoSyncRemoteUrl(remoteUrl, allowedHosts);
5
5
  return extractRepoName(remoteUrl);
6
6
  }
@@ -40,7 +40,7 @@ export declare function runAutoSyncOnce(config: AutoSyncConfig, options?: {
40
40
  signal?: AbortSignal;
41
41
  onAnalysisCancellationRequested?: () => void;
42
42
  }): Promise<AutoSyncRunResult>;
43
- export declare function getConfiguredRepoPath(project: Pick<AutoSyncProjectConfig, 'localPath'>, repoName: string, remoteUrl?: string): string;
43
+ export declare function getConfiguredRepoPath(project: Pick<AutoSyncProjectConfig, 'localPath'>, repoName: string, remoteUrl?: string, allowedHosts?: readonly string[]): string;
44
44
  export declare function addRepoToGroup(project: Pick<AutoSyncProjectConfig, 'groupName'>, groupPath: string, registryName?: string): Promise<boolean>;
45
45
  export { getAutoSyncRepoIdentity } from './config.js';
46
46
  export declare function syncGroupByName(groupName: string): Promise<void>;
@@ -86,6 +86,7 @@ export async function runAutoSyncOnce(config, options = {}) {
86
86
  repoName,
87
87
  targetDir,
88
88
  timeoutMs: config.repoGitTimeoutMs,
89
+ allowedHosts: config.allowedHosts,
89
90
  deps,
90
91
  logger,
91
92
  });
@@ -254,7 +255,7 @@ export async function runAutoSyncOnce(config, options = {}) {
254
255
  // on the documented branch-fallback path.
255
256
  const placement = await deps.resolveBranchPlacement(repoResult.targetDir, repoResult.branch);
256
257
  await deps.registerRepo(repoResult.targetDir, meta, {
257
- name: getAutoSyncRepoIdentity(repoResult.remoteUrl),
258
+ name: getAutoSyncRepoIdentity(repoResult.remoteUrl, config.allowedHosts),
258
259
  // Omitted rather than passed as undefined, so a primary index is
259
260
  // registered with the same option shape it had before this branch.
260
261
  ...(placement.branch ? { branch: placement.branch } : {}),
@@ -303,7 +304,7 @@ export async function runAutoSyncOnce(config, options = {}) {
303
304
  let groupMembershipOk = false;
304
305
  let membershipAdded = false;
305
306
  try {
306
- membershipAdded = await deps.addRepoToGroup(repoResult.project, getAutoSyncRepoIdentity(repoResult.remoteUrl), getAutoSyncRepoIdentity(repoResult.remoteUrl));
307
+ membershipAdded = await deps.addRepoToGroup(repoResult.project, getAutoSyncRepoIdentity(repoResult.remoteUrl, config.allowedHosts), getAutoSyncRepoIdentity(repoResult.remoteUrl, config.allowedHosts));
307
308
  groupMembershipOk = true;
308
309
  }
309
310
  catch (err) {
@@ -369,10 +370,10 @@ function isRetryableAnalyzeContention(err) {
369
370
  err.code === 'index-lock-timeout' &&
370
371
  err.retryable === true);
371
372
  }
372
- export function getConfiguredRepoPath(project, repoName, remoteUrl) {
373
+ export function getConfiguredRepoPath(project, repoName, remoteUrl, allowedHosts) {
373
374
  if (!remoteUrl)
374
375
  return path.resolve(project.localPath, repoName);
375
- const identity = getAutoSyncRepoIdentity(remoteUrl);
376
+ const identity = getAutoSyncRepoIdentity(remoteUrl, allowedHosts);
376
377
  return path.resolve(project.localPath, ...identity.split('/').slice(0, -1), repoName);
377
378
  }
378
379
  export async function addRepoToGroup(project, groupPath, registryName = groupPath) {
@@ -420,8 +421,8 @@ async function buildWorkItems(config, deps) {
420
421
  }
421
422
  for (const remoteUrl of project.remoteUrls) {
422
423
  try {
423
- const repoName = extractRepoNameFromRemoteUrl(remoteUrl);
424
- const targetDir = getConfiguredRepoPath({ localPath: cloneRoot.root }, repoName, remoteUrl);
424
+ const repoName = extractRepoNameFromRemoteUrl(remoteUrl, config.allowedHosts);
425
+ const targetDir = getConfiguredRepoPath({ localPath: cloneRoot.root }, repoName, remoteUrl, config.allowedHosts);
425
426
  const previous = targetOwners.get(targetDir);
426
427
  if (previous !== undefined) {
427
428
  throw new Error(`Duplicate auto-sync targetDir ${targetDir} for ${previous} and ${remoteUrl}`);
@@ -474,6 +475,9 @@ async function syncFirstAvailableBranch(input) {
474
475
  expectedRepoName: input.repoName,
475
476
  quarantineRoot: input.item.cloneRoot.quarantineRoot,
476
477
  allowAutoSyncSsh: true,
478
+ ...(input.allowedHosts && input.allowedHosts.length > 0
479
+ ? { autoSyncAllowedHosts: input.allowedHosts }
480
+ : {}),
477
481
  timeoutMs: input.timeoutMs,
478
482
  branch,
479
483
  overwriteLocalChanges: input.item.project.overwriteLocalChanges,
@@ -1,7 +1,5 @@
1
1
  /**
2
- * Walk `repoPath` recursively and return relative paths of all `.h` files.
3
- * Used by `loadResolutionConfig` so the C resolver can resolve `#include`
4
- * targets that live in `.h` files (classified as C++ by language detection
5
- * but importable from `.c` files).
2
+ * Walk `repoPath` and return relative paths of all `.h` files.
3
+ * Search paths stay on the workspace config; this is only the header set.
6
4
  */
7
5
  export declare function scanHeaderFiles(repoPath: string): ReadonlySet<string>;
@@ -1,55 +1,8 @@
1
- import { readdirSync } from 'fs';
2
- import { join, relative } from 'path';
3
- /** C header extensions to scan for in the workspace. */
4
- const HEADER_EXTENSIONS = new Set(['.h']);
1
+ import { C_HEADER_EXTENSIONS, scanCFamilyHeaders } from './resolution-config.js';
5
2
  /**
6
- * Walk `repoPath` recursively and return relative paths of all `.h` files.
7
- * Used by `loadResolutionConfig` so the C resolver can resolve `#include`
8
- * targets that live in `.h` files (classified as C++ by language detection
9
- * but importable from `.c` files).
3
+ * Walk `repoPath` and return relative paths of all `.h` files.
4
+ * Search paths stay on the workspace config; this is only the header set.
10
5
  */
11
6
  export function scanHeaderFiles(repoPath) {
12
- const headers = new Set();
13
- walk(repoPath, repoPath, headers);
14
- return headers;
15
- }
16
- function walk(dir, root, out) {
17
- let entries;
18
- try {
19
- entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' });
20
- }
21
- catch {
22
- return; // permission denied, etc.
23
- }
24
- for (const entry of entries) {
25
- const name = entry.name;
26
- const full = join(dir, name);
27
- if (entry.isDirectory()) {
28
- // Skip common non-source directories and build output dirs.
29
- // Build dirs (dist, build, out, target, _build, .next, cmake-build-*)
30
- // may contain generated headers that shadow source headers.
31
- if (name === 'node_modules' ||
32
- name === '.git' ||
33
- name === 'vendor' ||
34
- name === 'dist' ||
35
- name === 'build' ||
36
- name === 'out' ||
37
- name === 'target' ||
38
- name === '_build' ||
39
- name === '.next' ||
40
- name.startsWith('cmake-build')) {
41
- continue;
42
- }
43
- walk(full, root, out);
44
- }
45
- else if (entry.isFile()) {
46
- const ext = name.slice(name.lastIndexOf('.'));
47
- if (HEADER_EXTENSIONS.has(ext)) {
48
- // Normalize to forward slashes for cross-platform consistency.
49
- // path.relative() returns backslash-separated paths on Windows,
50
- // but the scope-resolution pipeline uses forward slashes uniformly.
51
- out.add(relative(root, full).replace(/\\/g, '/'));
52
- }
53
- }
54
- }
7
+ return scanCFamilyHeaders(repoPath, C_HEADER_EXTENSIONS).headers;
55
8
  }
@@ -1,14 +1,61 @@
1
+ import { type CTranslationUnitPaths } from './resolution-config.js';
2
+ /**
3
+ * A workspace file path pre-decomposed for the suffix-match fallback:
4
+ * `original` is returned verbatim (preserving the prior `bestMatch = filePath`
5
+ * contract); `normalized` and `depth` are precomputed so the hot path does no
6
+ * per-element regex/`split`.
7
+ */
8
+ export interface CSuffixCandidate {
9
+ original: string;
10
+ normalized: string;
11
+ depth: number;
12
+ }
13
+ export type CIncludeSuffixIndex = (allFilePaths: ReadonlySet<string>) => Map<string, CSuffixCandidate[]>;
14
+ /**
15
+ * Basename buckets for quoted `#include "…"` suffix fallback.
16
+ *
17
+ * The builder is shared. Each language keeps its own memo: C++ calls
18
+ * `resolveCFamilyImport` with the index it created here, so a C pass and a
19
+ * C++ pass never read each other's map even when handed the same set.
20
+ */
21
+ export declare function createCIncludeSuffixIndex(): CIncludeSuffixIndex;
22
+ /** Optional search roots. Absent means "quoted include, no declared paths". */
23
+ export interface CIncludeLookup {
24
+ /** `#include <…>`. Never suffix-matches the workspace. */
25
+ readonly isSystem?: boolean;
26
+ /** Fallback `-I` / `-isystem` / `/I` and implicit roots. */
27
+ readonly headerSearchPaths?: readonly string[];
28
+ /** Fallback `-iquote`. Quoted includes only. */
29
+ readonly userHeaderSearchPaths?: readonly string[];
30
+ /**
31
+ * Per translation unit. A hit replaces the fallback lists for that file.
32
+ * The map is the one built at config load — lookup does not copy it.
33
+ */
34
+ readonly translationUnits?: ReadonlyMap<string, CTranslationUnitPaths>;
35
+ /** Nearest-ancestor lists for a file with no database entry. */
36
+ readonly directoryScopes?: ReadonlyMap<string, CTranslationUnitPaths>;
37
+ /** Interface include roots from `target_link_libraries`, keyed by source file. */
38
+ readonly cmakeLinkHeaders?: ReadonlyMap<string, readonly string[]>;
39
+ }
1
40
  /**
2
41
  * Resolve a C #include path to a file in the workspace.
3
42
  *
4
- * Strategy:
5
- * 1. Check for a same-directory sibling relative to the including file
6
- * (matches C compiler `#include "…"` relative-lookup semantics).
7
- * 2. Check for an exact match (path as-is in the workspace).
8
- * 3. Fall back to suffix matching against all workspace file paths.
9
- * Tie-breaking: prefer the match with the fewest path components
10
- * (closest to root). On equal depth, break ties lexicographically
11
- * by normalized path to ensure deterministic resolution regardless
12
- * of filesystem iteration order.
43
+ * Quoted `#include "…"` (the default when `lookup` is omitted, which is
44
+ * what the import-target bench and the older unit tests call):
45
+ * 1. Same directory as the including file
46
+ * 2. User search paths, then header search paths
47
+ * 3. Exact path, then the basename bucket
48
+ *
49
+ * Angle `#include <…>` (`lookup.isSystem`): join the target onto each
50
+ * header search path and return that file, or null. A same-named header
51
+ * under `src/` is not a candidate when `src` is not a search path.
13
52
  */
14
- export declare function resolveCImportTarget(targetRaw: string, fromFile: string, allFilePaths: ReadonlySet<string>): string | null;
53
+ export declare function cIncludeLookupFromConfig(config: {
54
+ readonly headerSearchPaths?: readonly string[];
55
+ readonly userHeaderSearchPaths?: readonly string[];
56
+ readonly translationUnits?: ReadonlyMap<string, CTranslationUnitPaths>;
57
+ readonly directoryScopes?: ReadonlyMap<string, CTranslationUnitPaths>;
58
+ readonly cmakeLinkHeaders?: ReadonlyMap<string, readonly string[]>;
59
+ } | undefined, isSystem: boolean): CIncludeLookup;
60
+ export declare function resolveCImportTarget(targetRaw: string, fromFile: string, allFilePaths: ReadonlySet<string>, lookup?: CIncludeLookup): string | null;
61
+ export declare function resolveCFamilyImport(targetRaw: string, fromFile: string, allFilePaths: ReadonlySet<string>, lookup: CIncludeLookup | undefined, suffixIndex: CIncludeSuffixIndex): string | null;