tensor-grep 1.76.4__tar.gz → 1.76.6__tar.gz

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 (135) hide show
  1. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/PKG-INFO +1 -1
  2. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/pyproject.toml +3 -1
  3. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/Cargo.lock +1 -1
  4. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/Cargo.toml +3 -1
  5. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/agent_capsule.py +26 -18
  6. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/orient_capsule.py +42 -3
  7. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/repo_map.py +12 -2
  8. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/LICENSE +0 -0
  9. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/NOTICE +0 -0
  10. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/README.md +0 -0
  11. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/deny.toml +0 -0
  12. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/rust-toolchain.toml +0 -0
  13. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/backend_ast.rs +0 -0
  14. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/backend_ast_workflow.rs +0 -0
  15. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/backend_cpu.rs +0 -0
  16. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/bin/tg_search_fast.rs +0 -0
  17. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/cli.rs +0 -0
  18. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/crossover.rs +0 -0
  19. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/editor_plane.rs +0 -0
  20. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/gpu_native.rs +0 -0
  21. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/index.rs +0 -0
  22. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/index_lock.rs +0 -0
  23. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/lib.rs +0 -0
  24. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/main.rs +0 -0
  25. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/mmap_arrow.rs +0 -0
  26. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/native_search.rs +0 -0
  27. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/python_sidecar.rs +0 -0
  28. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/rg_passthrough.rs +0 -0
  29. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/routing.rs +0 -0
  30. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/src/runtime_paths.rs +0 -0
  31. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_ast_backend.rs +0 -0
  32. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_ast_cache.rs +0 -0
  33. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_ast_grep_embed.rs +0 -0
  34. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_ast_rewrite.rs +0 -0
  35. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_audit_manifest_symlink_unix.rs +0 -0
  36. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native.rs +0 -0
  37. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native_error_handling.rs +0 -0
  38. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native_graphs.rs +0 -0
  39. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native_integration.rs +0 -0
  40. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native_long_lines.rs +0 -0
  41. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_gpu_native_streams.rs +0 -0
  42. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_index.rs +0 -0
  43. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_index_lock_concurrency.rs +0 -0
  44. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_mmap_arrow.rs +0 -0
  45. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_native_search.rs +0 -0
  46. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_output.rs +0 -0
  47. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_public_native_cli_parity.rs +0 -0
  48. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_python_bootstrap.rs +0 -0
  49. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_release_profile.rs +0 -0
  50. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_replace.rs +0 -0
  51. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_resident_worker.rs +0 -0
  52. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_routing.rs +0 -0
  53. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_runtime_path_resolution.rs +0 -0
  54. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_schema_compat.rs +0 -0
  55. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_search.rs +0 -0
  56. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_search_golden.rs +0 -0
  57. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_sidecar_ipc.rs +0 -0
  58. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/rust_core/tests/test_smart_routing.rs +0 -0
  59. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/__init__.py +0 -0
  60. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/__main__.py +0 -0
  61. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/__init__.py +0 -0
  62. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/ast_backend.py +0 -0
  63. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/ast_wrapper_backend.py +0 -0
  64. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/base.py +0 -0
  65. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/cpu_backend.py +0 -0
  66. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/cudf_backend.py +0 -0
  67. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/cybert_backend.py +0 -0
  68. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/ripgrep_backend.py +0 -0
  69. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/rust_backend.py +0 -0
  70. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/stringzilla_backend.py +0 -0
  71. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/backends/torch_backend.py +0 -0
  72. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/__init__.py +0 -0
  73. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/_index_lock.py +0 -0
  74. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/apply_policy.py +0 -0
  75. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/ast_workflows.py +0 -0
  76. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/audit_manifest.py +0 -0
  77. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/bootstrap.py +0 -0
  78. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/checkpoint_store.py +0 -0
  79. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/codemap.py +0 -0
  80. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/commands.py +0 -0
  81. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/docs_coverage.py +0 -0
  82. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/dogfood.py +0 -0
  83. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/evidence_receipt.py +0 -0
  84. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/evidence_signing.py +0 -0
  85. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/__init__.py +0 -0
  86. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/base.py +0 -0
  87. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/csv_fmt.py +0 -0
  88. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/json_fmt.py +0 -0
  89. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/ripgrep_fmt.py +0 -0
  90. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/formatters/table_fmt.py +0 -0
  91. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/inventory.py +0 -0
  92. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/lang_go.py +0 -0
  93. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/lang_registry.py +0 -0
  94. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/lsp_external_provider.py +0 -0
  95. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/lsp_provider_setup.py +0 -0
  96. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/lsp_server.py +0 -0
  97. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/main.py +0 -0
  98. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/mcp_server.py +0 -0
  99. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/progress.py +0 -0
  100. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/rg_contract.py +0 -0
  101. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/rule_packs.py +0 -0
  102. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/runtime_paths.py +0 -0
  103. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/scan_guardrails.py +0 -0
  104. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/session_daemon.py +0 -0
  105. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/session_store.py +0 -0
  106. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/cli/subprocess_policy.py +0 -0
  107. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/__init__.py +0 -0
  108. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/config.py +0 -0
  109. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/hardware/__init__.py +0 -0
  110. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/hardware/device_detect.py +0 -0
  111. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/hardware/device_inventory.py +0 -0
  112. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/hardware/memory_manager.py +0 -0
  113. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/observability.py +0 -0
  114. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/pipeline.py +0 -0
  115. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/query_analyzer.py +0 -0
  116. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/registration_check.py +0 -0
  117. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/reranker.py +0 -0
  118. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/result.py +0 -0
  119. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_bm25.py +0 -0
  120. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_chunker.py +0 -0
  121. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_dense.py +0 -0
  122. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_fusion.py +0 -0
  123. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_late.py +0 -0
  124. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_lexical.py +0 -0
  125. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/retrieval_scoring.py +0 -0
  126. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/core/semantic_index.py +0 -0
  127. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/__init__.py +0 -0
  128. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/base.py +0 -0
  129. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/directory_scanner.py +0 -0
  130. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/reader_cudf.py +0 -0
  131. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/reader_dstorage.py +0 -0
  132. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/reader_fallback.py +0 -0
  133. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/io/reader_kvikio.py +0 -0
  134. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/perf_guard.py +0 -0
  135. {tensor_grep-1.76.4 → tensor_grep-1.76.6}/src/tensor_grep/sidecar.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensor-grep
3
- Version: 1.76.4
3
+ Version: 1.76.6
4
4
  Requires-Dist: typer>=0.12,<0.26
5
5
  Requires-Dist: rich>=13.0
6
6
  Requires-Dist: mcp>=1.2.0
@@ -532,12 +532,14 @@ version_variables = [
532
532
 
533
533
 
534
534
 
535
+
536
+
535
537
 
536
538
 
537
539
 
538
540
  [project]
539
541
  name = "tensor-grep"
540
- version = "1.76.4"
542
+ version = "1.76.6"
541
543
  description = "High-performance grep-compatible CLI with Rust, GPU, and AST/NLP routing"
542
544
  readme = { file = "rust_core/README.md", content-type = "text/markdown" }
543
545
  requires-python = ">=3.11"
@@ -1579,7 +1579,7 @@ dependencies = [
1579
1579
 
1580
1580
  [[package]]
1581
1581
  name = "tensor_grep_rs"
1582
- version = "1.76.4"
1582
+ version = "1.76.6"
1583
1583
  dependencies = [
1584
1584
  "aho-corasick",
1585
1585
  "anyhow",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "tensor_grep_rs"
3
- version = "1.76.4"
3
+ version = "1.76.6"
4
4
  edition = "2021"
5
5
  description = "Rust core engine for tensor-grep"
6
6
  license = "Apache-2.0"
@@ -440,6 +440,8 @@ path = "src/bin/tg_search_fast.rs"
440
440
 
441
441
 
442
442
 
443
+
444
+
443
445
 
444
446
 
445
447
 
@@ -2341,9 +2341,19 @@ def build_agent_capsule_from_map(
2341
2341
  # Local import avoids a module-level circular import (orient_capsule imports repo_map, which
2342
2342
  # this module also imports) -- same discipline repo_map.build_context_render's own reuse of
2343
2343
  # this helper uses, and the same reasoning as the _suggested_scope_from_map import below.
2344
- from tensor_grep.cli.orient_capsule import _apply_ignore_globs
2344
+ from tensor_grep.cli.orient_capsule import _apply_ignore_globs, _detect_vendored_subtrees
2345
2345
 
2346
2346
  rm = _apply_ignore_globs(rm, ignore)
2347
+ # #179: compute the SAME auto-detected vendor/skill/tool-config tree set ONCE, here, against the
2348
+ # final (already `--ignore`-filtered) `rm`, and thread it through every `_suggested_scope_from_map`
2349
+ # call below plus the `suggested_ignore` build near the end of this function. Previously each
2350
+ # `_suggested_scope_from_map(rm)` call below ran with no exclusion set at all (defaulting to
2351
+ # "nothing excluded"), while `suggested_ignore` independently re-ran `_detect_vendored_subtrees(rm)`
2352
+ # for the SAME `rm` -- so `suggested_scope` could point an agent straight at a tree `suggested_
2353
+ # ignore` already flagged in the very same capsule (#179, the tg-agent/context-render sibling of
2354
+ # orient's #168/#606 fix). Sourcing both fields from one shared call makes them provably
2355
+ # consistent, not just coincidentally so, and also drops a redundant second detection pass.
2356
+ deweighted_trees = _detect_vendored_subtrees(rm)
2347
2357
  resolved_path = str(rm["path"])
2348
2358
  requested_semantic_provider = semantic_provider
2349
2359
  effective_semantic_provider = (
@@ -2374,7 +2384,7 @@ def build_agent_capsule_from_map(
2374
2384
  ):
2375
2385
  from tensor_grep.cli.orient_capsule import _suggested_scope_from_map
2376
2386
 
2377
- suggested_scope_from_map = _suggested_scope_from_map(rm)
2387
+ suggested_scope_from_map = _suggested_scope_from_map(rm, deweighted_trees=deweighted_trees)
2378
2388
  if suggested_scope_from_map is not None:
2379
2389
  payload["suggested_scope"] = suggested_scope_from_map
2380
2390
  # PR-1 (1D): whether the underlying repo scan itself (not the capsule's own snippet/token
@@ -2617,7 +2627,7 @@ def build_agent_capsule_from_map(
2617
2627
  if ambiguity.get("requires_confirmation") and not payload.get("suggested_scope"):
2618
2628
  from tensor_grep.cli.orient_capsule import _suggested_scope_from_map
2619
2629
 
2620
- tie_suggested_scope = _suggested_scope_from_map(rm)
2630
+ tie_suggested_scope = _suggested_scope_from_map(rm, deweighted_trees=deweighted_trees)
2621
2631
  if tie_suggested_scope is None:
2622
2632
  # `tied_alternatives` (not `ambiguity["tied_alternative_targets"]`) is the definitive
2623
2633
  # source: `requires_confirmation` is only ever True from the `if tied_alternatives:`
@@ -2874,21 +2884,19 @@ def build_agent_capsule_from_map(
2874
2884
  # skill/tool-config subtree roots as ready-to-paste `--ignore` globs. `tg agent` already runs
2875
2885
  # the SAME de-weight during ranking (`_build_context_pack_from_map`'s own `auto_deweight` pass,
2876
2886
  # repo_map.py) but, pre-M2, never surfaced the glob hint itself -- an agent had to hand-derive
2877
- # `--ignore` globs or fall back to `tg orient` first. Recompute `_detect_vendored_subtrees`
2878
- # against the SAME (already `--ignore`-filtered) `rm` the ranking pass used above, and reuse
2879
- # orient's exact glob-builder (`_suggested_ignore_from_deweighted_trees`) -- never a second,
2880
- # independently hand-rolled hint that could drift from what `tg orient` would say for the same
2881
- # repo. `_detect_vendored_subtrees` reads only `rm`'s already-in-hand file/import lists plus a
2882
- # bounded number of manifest-marker existence checks (no new directory walk), so this is cheap
2883
- # relative to the rest of the capsule build. Additive + conditional, same shape as
2884
- # `suggested_scope` above: present only when non-empty, so a capsule with nothing deweighted
2885
- # stays byte-identical to a pre-M2 build.
2886
- from tensor_grep.cli.orient_capsule import (
2887
- _detect_vendored_subtrees,
2888
- _suggested_ignore_from_deweighted_trees,
2889
- )
2890
-
2891
- suggested_ignore = _suggested_ignore_from_deweighted_trees(_detect_vendored_subtrees(rm))
2887
+ # `--ignore` globs or fall back to `tg orient` first. Reuse the `deweighted_trees` set already
2888
+ # computed once, near the top of this function (#179), against the SAME (already
2889
+ # `--ignore`-filtered) `rm` the ranking pass used above, and feed it into orient's exact
2890
+ # glob-builder (`_suggested_ignore_from_deweighted_trees`) -- never a second, independently
2891
+ # hand-rolled hint that could drift from what `tg orient` would say for the same repo, and never
2892
+ # a second `_detect_vendored_subtrees` walk over the same `rm` (#179 dedupes what was previously
2893
+ # two independent calls into one shared result, which is also what makes `suggested_scope` above
2894
+ # provably consistent with this hint rather than coincidentally so). Additive + conditional, same
2895
+ # shape as `suggested_scope` above: present only when non-empty, so a capsule with nothing
2896
+ # deweighted stays byte-identical to a pre-M2 build.
2897
+ from tensor_grep.cli.orient_capsule import _suggested_ignore_from_deweighted_trees
2898
+
2899
+ suggested_ignore = _suggested_ignore_from_deweighted_trees(deweighted_trees)
2892
2900
  if suggested_ignore:
2893
2901
  result["suggested_ignore"] = suggested_ignore
2894
2902
  # DAR: additive CONDITIONAL keys, same pattern as scan_limit/partial above -- zero deps (or
@@ -589,19 +589,52 @@ def _top_level_dir(file_path: str, root: Path) -> str | None:
589
589
  return parts[0]
590
590
 
591
591
 
592
- def _suggested_scope_from_map(rm: dict[str, Any]) -> dict[str, Any] | None:
592
+ def _file_in_any_tree(file_path: str, tree_roots: list[str]) -> bool:
593
+ """True if `file_path` lives inside any of `tree_roots` (absolute directory paths -- the
594
+ ``_detect_vendored_subtrees`` dict keys). Standalone helper (#168) rather than reusing
595
+ `_central_files_from_map`'s inline tree-membership loop, so that function's existing,
596
+ already-tested de-weight logic is left untouched."""
597
+ candidate = Path(file_path)
598
+ for tree_root in tree_roots:
599
+ try:
600
+ candidate.relative_to(tree_root)
601
+ except ValueError:
602
+ continue
603
+ return True
604
+ return False
605
+
606
+
607
+ def _suggested_scope_from_map(
608
+ rm: dict[str, Any],
609
+ *,
610
+ deweighted_trees: dict[str, dict[str, Any]] | None = None,
611
+ ) -> dict[str, Any] | None:
593
612
  """Centrality-weighted directory rollup: sum each code file's composite centrality
594
613
  (`_file_centrality_scores`) up to its top-level directory, rank directories, and suggest the
595
614
  top one only when it clearly outranks the runner-up. Returns None (never a guess) when there
596
615
  are no candidate subdirectories, the signal is entirely flat (all zero), or the top two
597
616
  directories are tied/near-tied. Callers gate the call itself on the repo map's
598
- ``scan_limit.possibly_truncated`` -- a complete scan has nothing left to narrow."""
617
+ ``scan_limit.possibly_truncated`` -- a complete scan has nothing left to narrow.
618
+
619
+ ``deweighted_trees`` (#168): the same auto-detected vendor/skill/tool-config subtree set
620
+ ``_detect_vendored_subtrees`` produces for ``suggested_ignore`` (e.g. ``.claude/**`` on a
621
+ Claude-Code-harness repo whose scan truncates). A file inside any of these trees is EXCLUDED
622
+ from the directory rollup entirely -- not merely de-weighted -- so `suggested_scope` can never
623
+ point an agent at the exact tree `suggested_ignore` already says to ignore; the two fields must
624
+ never contradict each other. This only shrinks the candidate set: whatever directory remains is
625
+ still ranked on the raw, un-de-weighted score (preserving the SUB-2 design -- see
626
+ `_central_files_from_map`'s docstring). ``None``/omitted -- the default -- means "nothing to
627
+ exclude" and reproduces the pre-#168 behavior exactly; the `agent_capsule.py` and `repo_map.py`
628
+ call sites do not thread a deweight set through yet and are unaffected by this parameter."""
599
629
  code_files, centrality = _file_centrality_scores(rm)
600
630
  if not code_files:
601
631
  return None
602
632
  root = Path(str(rm.get("path", ".")))
633
+ tree_roots = list(deweighted_trees.keys()) if deweighted_trees else []
603
634
  dir_scores: dict[str, float] = {}
604
635
  for file_path in code_files:
636
+ if tree_roots and _file_in_any_tree(file_path, tree_roots):
637
+ continue # #168: never roll an ignored tree's files into a scope candidate
605
638
  top_dir = _top_level_dir(file_path, root)
606
639
  if top_dir is None:
607
640
  continue
@@ -770,7 +803,13 @@ def build_orient_capsule_from_map(
770
803
  scan_possibly_truncated = bool(
771
804
  isinstance(scan_limit_info, dict) and scan_limit_info.get("possibly_truncated")
772
805
  )
773
- suggested_scope = _suggested_scope_from_map(rm) if scan_possibly_truncated else None
806
+ # `deweighted_trees` (#168) is threaded through so suggested_scope can never point an agent at
807
+ # the same tree suggested_ignore (below) already says to ignore -- the two fields must agree.
808
+ suggested_scope = (
809
+ _suggested_scope_from_map(rm, deweighted_trees=deweighted_trees)
810
+ if scan_possibly_truncated
811
+ else None
812
+ )
774
813
  # The capsule's own simplified `scan_limit` int (see the docstring above): the cap that
775
814
  # produced `rm`, read back off the map itself rather than threaded through as a second,
776
815
  # independently-suppliable parameter.
@@ -12470,11 +12470,21 @@ def build_context_render(
12470
12470
  # import avoids the module-level cycle (orient_capsule imports this module), exactly like the
12471
12471
  # `_apply_ignore_globs` reuse above. Additive + conditional: absent unless the scan was
12472
12472
  # truncated AND a clear winner exists, so a non-truncated render stays byte-identical.
12473
+ #
12474
+ # #179: also thread in the SAME auto-detected vendor/skill/tool-config tree set `tg orient`
12475
+ # (#168/#606) and `tg agent` (agent_capsule.py's own #179 fix) exclude from their own
12476
+ # suggested_scope rollup -- otherwise this wrapper (behind `tg context-render`, and any other
12477
+ # `include_suggested_scope=True` caller) could point an agent at a tree the sibling commands
12478
+ # already know to avoid, on the exact same repo map.
12473
12479
  scan_limit = repo_map.get("scan_limit")
12474
12480
  if isinstance(scan_limit, dict) and scan_limit.get("possibly_truncated"):
12475
- from tensor_grep.cli.orient_capsule import _suggested_scope_from_map
12481
+ from tensor_grep.cli.orient_capsule import (
12482
+ _detect_vendored_subtrees,
12483
+ _suggested_scope_from_map,
12484
+ )
12476
12485
 
12477
- suggested_scope = _suggested_scope_from_map(repo_map)
12486
+ deweighted_trees = _detect_vendored_subtrees(repo_map)
12487
+ suggested_scope = _suggested_scope_from_map(repo_map, deweighted_trees=deweighted_trees)
12478
12488
  if suggested_scope is not None:
12479
12489
  render["suggested_scope"] = suggested_scope
12480
12490
  return render
File without changes
File without changes