@veewo/gitnexus 1.5.7 → 1.5.9

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 (77) hide show
  1. package/dist/cli/ai-context.js +1 -7
  2. package/dist/cli/analyze-options.d.ts +4 -0
  3. package/dist/cli/analyze-options.js +14 -1
  4. package/dist/cli/analyze-options.test.js +23 -0
  5. package/dist/cli/analyze-runtime-summary.js +0 -1
  6. package/dist/cli/analyze-runtime-summary.test.js +0 -2
  7. package/dist/cli/analyze-summary.d.ts +0 -2
  8. package/dist/cli/analyze-summary.js +0 -24
  9. package/dist/cli/analyze-summary.test.js +1 -65
  10. package/dist/cli/analyze.d.ts +1 -0
  11. package/dist/cli/analyze.js +26 -18
  12. package/dist/cli/clean.js +23 -2
  13. package/dist/cli/index.js +3 -3
  14. package/dist/cli/repo-manager-alias.test.js +2 -0
  15. package/dist/core/ingestion/pipeline.js +0 -43
  16. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
  17. package/dist/core/ingestion/tree-sitter-queries.js +3 -3
  18. package/dist/mcp/local/agent-safe-response.js +1 -1
  19. package/dist/mcp/local/local-backend.d.ts +0 -23
  20. package/dist/mcp/local/local-backend.js +69 -248
  21. package/dist/mcp/local/runtime-chain-verify.test.js +0 -49
  22. package/dist/mcp/local/runtime-claim-rule-registry.d.ts +0 -11
  23. package/dist/mcp/local/runtime-claim-rule-registry.js +0 -159
  24. package/dist/mcp/local/runtime-claim-rule-registry.test.js +67 -214
  25. package/dist/mcp/tools.js +0 -70
  26. package/dist/storage/repo-manager.d.ts +1 -0
  27. package/dist/types/pipeline.d.ts +0 -3
  28. package/package.json +4 -4
  29. package/skills/gitnexus-cli.md +5 -2
  30. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +0 -60
  31. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +0 -395
  32. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.d.ts +0 -1
  33. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +0 -41
  34. package/dist/cli/rule-lab.d.ts +0 -38
  35. package/dist/cli/rule-lab.js +0 -148
  36. package/dist/cli/rule-lab.test.d.ts +0 -1
  37. package/dist/cli/rule-lab.test.js +0 -31
  38. package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +0 -26
  39. package/dist/core/ingestion/unity-runtime-binding-rules.js +0 -408
  40. package/dist/rule-lab/analyze.d.ts +0 -13
  41. package/dist/rule-lab/analyze.js +0 -125
  42. package/dist/rule-lab/analyze.test.d.ts +0 -1
  43. package/dist/rule-lab/analyze.test.js +0 -246
  44. package/dist/rule-lab/compile.d.ts +0 -5
  45. package/dist/rule-lab/compile.js +0 -51
  46. package/dist/rule-lab/compiled-bundles.d.ts +0 -30
  47. package/dist/rule-lab/compiled-bundles.js +0 -36
  48. package/dist/rule-lab/curate.d.ts +0 -33
  49. package/dist/rule-lab/curate.js +0 -155
  50. package/dist/rule-lab/curate.test.d.ts +0 -1
  51. package/dist/rule-lab/curate.test.js +0 -137
  52. package/dist/rule-lab/curation-input-builder.d.ts +0 -45
  53. package/dist/rule-lab/curation-input-builder.js +0 -133
  54. package/dist/rule-lab/discover.d.ts +0 -13
  55. package/dist/rule-lab/discover.js +0 -74
  56. package/dist/rule-lab/discover.test.d.ts +0 -1
  57. package/dist/rule-lab/discover.test.js +0 -42
  58. package/dist/rule-lab/paths.d.ts +0 -21
  59. package/dist/rule-lab/paths.js +0 -37
  60. package/dist/rule-lab/paths.test.d.ts +0 -1
  61. package/dist/rule-lab/paths.test.js +0 -46
  62. package/dist/rule-lab/promote.d.ts +0 -26
  63. package/dist/rule-lab/promote.js +0 -387
  64. package/dist/rule-lab/promote.test.d.ts +0 -1
  65. package/dist/rule-lab/promote.test.js +0 -314
  66. package/dist/rule-lab/regress.d.ts +0 -60
  67. package/dist/rule-lab/regress.js +0 -122
  68. package/dist/rule-lab/regress.test.d.ts +0 -1
  69. package/dist/rule-lab/regress.test.js +0 -68
  70. package/dist/rule-lab/review-pack.d.ts +0 -34
  71. package/dist/rule-lab/review-pack.js +0 -165
  72. package/dist/rule-lab/review-pack.test.d.ts +0 -1
  73. package/dist/rule-lab/review-pack.test.js +0 -116
  74. package/dist/rule-lab/types.d.ts +0 -135
  75. package/dist/rule-lab/types.js +0 -1
  76. package/skills/_shared/unity-rule-authoring-contract.md +0 -64
  77. package/skills/gitnexus-unity-rule-gen.md +0 -107
@@ -11,6 +11,6 @@ export declare const RUST_QUERIES = "\n; Functions & Items\n(function_item name:
11
11
  export declare const PHP_QUERIES = "\n; \u2500\u2500 Namespace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(namespace_definition\n name: (namespace_name) @name) @definition.namespace\n\n; \u2500\u2500 Classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @name) @definition.class\n\n; \u2500\u2500 Interfaces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(interface_declaration\n name: (name) @name) @definition.interface\n\n; \u2500\u2500 Traits \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(trait_declaration\n name: (name) @name) @definition.trait\n\n; \u2500\u2500 Enums (PHP 8.1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(enum_declaration\n name: (name) @name) @definition.enum\n\n; \u2500\u2500 Top-level functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(function_definition\n name: (name) @name) @definition.function\n\n; \u2500\u2500 Methods (including constructors) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(method_declaration\n name: (name) @name) @definition.method\n\n; \u2500\u2500 Class properties (including Eloquent $fillable, $casts, etc.) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(property_declaration\n (property_element\n (variable_name\n (name) @name))) @definition.property\n\n; \u2500\u2500 Imports: use statements \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Simple: use App\\Models\\User;\n(namespace_use_declaration\n (namespace_use_clause\n (qualified_name) @import.source)) @import\n\n; \u2500\u2500 Function/method calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Regular function call: foo()\n(function_call_expression\n function: (name) @call.name) @call\n\n; Method call: $obj->method()\n(member_call_expression\n name: (name) @call.name) @call\n\n; Nullsafe method call: $obj?->method()\n(nullsafe_member_call_expression\n name: (name) @call.name) @call\n\n; Static call: Foo::bar() (php_only uses scoped_call_expression)\n(scoped_call_expression\n name: (name) @call.name) @call\n\n; Constructor call: new User()\n(object_creation_expression (name) @call.name) @call\n\n; \u2500\u2500 Heritage: extends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n (base_clause\n [(name) (qualified_name)] @heritage.extends)) @heritage\n\n; \u2500\u2500 Heritage: implements \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n (class_interface_clause\n [(name) (qualified_name)] @heritage.implements)) @heritage.impl\n\n; \u2500\u2500 Heritage: use trait (must capture enclosing class name) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n body: (declaration_list\n (use_declaration\n [(name) (qualified_name)] @heritage.trait))) @heritage\n";
12
12
  export declare const RUBY_QUERIES = "\n; \u2500\u2500 Modules \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(module\n name: (constant) @name) @definition.module\n\n; \u2500\u2500 Classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class\n name: (constant) @name) @definition.class\n\n; \u2500\u2500 Instance methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(method\n name: (identifier) @name) @definition.method\n\n; \u2500\u2500 Singleton (class-level) methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(singleton_method\n name: (identifier) @name) @definition.method\n\n; \u2500\u2500 All calls (require, include, attr_*, and regular calls routed in JS) \u2500\u2500\u2500\u2500\u2500\n(call\n method: (identifier) @call.name) @call\n\n; \u2500\u2500 Bare calls without parens (identifiers at statement level are method calls) \u2500\n; NOTE: This may over-capture variable reads as calls (e.g. 'result' at\n; statement level). Ruby's grammar makes bare identifiers ambiguous \u2014 they\n; could be local variables or zero-arity method calls. Post-processing via\n; isBuiltInOrNoise and symbol resolution filtering suppresses most false\n; positives, but a variable name that coincidentally matches a method name\n; elsewhere may produce a false CALLS edge.\n(body_statement\n (identifier) @call.name @call)\n\n; \u2500\u2500 Heritage: class < SuperClass \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class\n name: (constant) @heritage.class\n superclass: (superclass\n (constant) @heritage.extends)) @heritage\n";
13
13
  export declare const KOTLIN_QUERIES = "\n; \u2500\u2500 Interfaces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; tree-sitter-kotlin (fwcd) has no interface_declaration node type.\n; Interfaces are class_declaration nodes with an anonymous \"interface\" keyword child.\n(class_declaration\n \"interface\"\n (type_identifier) @name) @definition.interface\n\n; \u2500\u2500 Classes (regular, data, sealed, enum) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; All have the anonymous \"class\" keyword child. enum class has both\n; \"enum\" and \"class\" children \u2014 the \"class\" child still matches.\n(class_declaration\n \"class\"\n (type_identifier) @name) @definition.class\n\n; \u2500\u2500 Object declarations (Kotlin singletons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(object_declaration\n (type_identifier) @name) @definition.class\n\n; \u2500\u2500 Companion objects (named only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(companion_object\n (type_identifier) @name) @definition.class\n\n; \u2500\u2500 Functions (top-level, member, extension) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(function_declaration\n (simple_identifier) @name) @definition.function\n\n; \u2500\u2500 Properties \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(property_declaration\n (variable_declaration\n (simple_identifier) @name)) @definition.property\n\n; \u2500\u2500 Enum entries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(enum_entry\n (simple_identifier) @name) @definition.enum\n\n; \u2500\u2500 Type aliases \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(type_alias\n (type_identifier) @name) @definition.type\n\n; \u2500\u2500 Imports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(import_header\n (identifier) @import.source) @import\n\n; \u2500\u2500 Function calls (direct) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(call_expression\n (simple_identifier) @call.name) @call\n\n; \u2500\u2500 Method calls (via navigation: obj.method()) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(call_expression\n (navigation_expression\n (navigation_suffix\n (simple_identifier) @call.name))) @call\n\n; \u2500\u2500 Constructor invocations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(constructor_invocation\n (user_type\n (type_identifier) @call.name)) @call\n\n; \u2500\u2500 Infix function calls (e.g., a to b, x until y) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(infix_expression\n (simple_identifier) @call.name) @call\n\n; \u2500\u2500 Heritage: extends / implements via delegation_specifier \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Interface implementation (bare user_type): class Foo : Bar\n(class_declaration\n (type_identifier) @heritage.class\n (delegation_specifier\n (user_type (type_identifier) @heritage.extends))) @heritage\n\n; Class extension (constructor_invocation): class Foo : Bar()\n(class_declaration\n (type_identifier) @heritage.class\n (delegation_specifier\n (constructor_invocation\n (user_type (type_identifier) @heritage.extends)))) @heritage\n";
14
- export declare const GDSCRIPT_QUERIES = "\n; \u2500\u2500 Class Name (file-level class) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_name_statement\n (name) @name) @definition.class\n\n; \u2500\u2500 Inner Class Definition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_definition\n name: (name) @name) @definition.class\n\n; \u2500\u2500 Functions & Methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(function_definition\n name: (name) @name) @definition.function\n\n; \u2500\u2500 Constructor (_init) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(constructor_definition) @definition.constructor\n\n; \u2500\u2500 Constructor with name capture for symbol extraction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(constructor_definition\n parameters: (parameters)) @definition.constructor\n\n; \u2500\u2500 Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(signal_statement\n name: (name) @name) @definition.signal\n\n; \u2500\u2500 Enums \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(enum_definition\n name: (name) @name) @definition.enum\n\n; \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(const_statement\n (name) @name) @definition.const\n\n; \u2500\u2500 Extends (inheritance) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(extends_statement\n (type (identifier) @heritage.extends)) @heritage\n\n; \u2500\u2500 Class with extends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_definition\n name: (name) @heritage.class\n extends: (extends_statement\n (type (identifier) @heritage.extends))) @heritage\n\n; \u2500\u2500 Preload/Load (imports) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Only preload(\"res://...\") and load(\"res://...\") are real imports.\n; Generic call expressions must NOT be tagged @import to avoid double-classifying\n; call sites as imports (which corrupts import resolution and call routing).\n(call\n function: (identifier) @_preload\n arguments: (arguments (string) @import.source)) @import\n(#eq? @_preload \"preload\")\n\n(call\n function: (identifier) @_load\n arguments: (arguments (string) @import.source)) @import\n(#eq? @_load \"load\")\n\n; \u2500\u2500 Function Calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(call\n function: (identifier) @call.name) @call\n\n";
14
+ export declare const GDSCRIPT_QUERIES = "\n; \u2500\u2500 Class Name (file-level class) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_name_statement\n (name) @name) @definition.class\n\n; \u2500\u2500 Inner Class Definition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_definition\n name: (name) @name) @definition.class\n\n; \u2500\u2500 Functions & Methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(function_definition\n name: (name) @name) @definition.function\n\n; \u2500\u2500 Constructor (_init) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(constructor_definition) @definition.constructor\n\n; \u2500\u2500 Constructor with name capture for symbol extraction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(constructor_definition\n parameters: (parameters)) @definition.constructor\n\n; \u2500\u2500 Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(signal_statement\n name: (name) @name) @definition.signal\n\n; \u2500\u2500 Enums \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(enum_definition\n name: (name) @name) @definition.enum\n\n; \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(const_statement\n (name) @name) @definition.const\n\n; \u2500\u2500 Extends (inheritance) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(extends_statement\n (type (identifier) @heritage.extends)) @heritage\n\n; \u2500\u2500 Class with extends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_definition\n name: (name) @heritage.class\n extends: (extends_statement\n (type (identifier) @heritage.extends))) @heritage\n\n; \u2500\u2500 Preload/Load (imports) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Only preload(\"res://...\") and load(\"res://...\") are real imports.\n; Generic call expressions must NOT be tagged @import to avoid double-classifying\n; call sites as imports (which corrupts import resolution and call routing).\n(call\n (identifier) @_preload\n arguments: (arguments (string) @import.source)) @import\n(#eq? @_preload \"preload\")\n\n(call\n (identifier) @_load\n arguments: (arguments (string) @import.source)) @import\n(#eq? @_load \"load\")\n\n; \u2500\u2500 Function Calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(call\n (identifier) @call.name) @call\n\n";
15
15
  export declare const SWIFT_QUERIES = "\n; Classes\n(class_declaration \"class\" name: (type_identifier) @name) @definition.class\n\n; Structs\n(class_declaration \"struct\" name: (type_identifier) @name) @definition.struct\n\n; Enums\n(class_declaration \"enum\" name: (type_identifier) @name) @definition.enum\n\n; Extensions (mapped to class \u2014 no dedicated label in schema)\n(class_declaration \"extension\" name: (user_type (type_identifier) @name)) @definition.class\n\n; Actors\n(class_declaration \"actor\" name: (type_identifier) @name) @definition.class\n\n; Protocols (mapped to interface)\n(protocol_declaration name: (type_identifier) @name) @definition.interface\n\n; Type aliases\n(typealias_declaration name: (type_identifier) @name) @definition.type\n\n; Functions (top-level and methods)\n(function_declaration name: (simple_identifier) @name) @definition.function\n\n; Protocol method declarations\n(protocol_function_declaration name: (simple_identifier) @name) @definition.method\n\n; Initializers\n(init_declaration) @definition.constructor\n\n; Properties (stored and computed)\n(property_declaration (pattern (simple_identifier) @name)) @definition.property\n\n; Imports\n(import_declaration (identifier (simple_identifier) @import.source)) @import\n\n; Calls - direct function calls\n(call_expression (simple_identifier) @call.name) @call\n\n; Calls - member/navigation calls (obj.method())\n(call_expression (navigation_expression (navigation_suffix (simple_identifier) @call.name))) @call\n\n; Heritage - class/struct/enum inheritance and protocol conformance\n(class_declaration name: (type_identifier) @heritage.class\n (inheritance_specifier inherits_from: (user_type (type_identifier) @heritage.extends))) @heritage\n\n; Heritage - protocol inheritance\n(protocol_declaration name: (type_identifier) @heritage.class\n (inheritance_specifier inherits_from: (user_type (type_identifier) @heritage.extends))) @heritage\n\n; Heritage - extension protocol conformance (e.g. extension Foo: SomeProtocol)\n; Extensions wrap the name in user_type unlike class/struct/enum declarations\n(class_declaration \"extension\" name: (user_type (type_identifier) @heritage.class)\n (inheritance_specifier inherits_from: (user_type (type_identifier) @heritage.extends))) @heritage\n";
16
16
  export declare const LANGUAGE_QUERIES: Record<SupportedLanguages, string>;
@@ -662,18 +662,18 @@ export const GDSCRIPT_QUERIES = `
662
662
  ; Generic call expressions must NOT be tagged @import to avoid double-classifying
663
663
  ; call sites as imports (which corrupts import resolution and call routing).
664
664
  (call
665
- function: (identifier) @_preload
665
+ (identifier) @_preload
666
666
  arguments: (arguments (string) @import.source)) @import
667
667
  (#eq? @_preload "preload")
668
668
 
669
669
  (call
670
- function: (identifier) @_load
670
+ (identifier) @_load
671
671
  arguments: (arguments (string) @import.source)) @import
672
672
  (#eq? @_load "load")
673
673
 
674
674
  ; ── Function Calls ──────────────────────────────────────────────────────────
675
675
  (call
676
- function: (identifier) @call.name) @call
676
+ (identifier) @call.name) @call
677
677
 
678
678
  `;
679
679
  export const SWIFT_QUERIES = `
@@ -416,7 +416,7 @@ function buildResourceChains(resourceChains) {
416
416
  }
417
417
  : undefined,
418
418
  }))
419
- .filter((chain) => Boolean(chain.sourceResourcePath && chain.intermediateResourcePath && chain.targetSymbol));
419
+ .filter((chain) => Boolean(chain.sourceResourcePath && chain.targetSymbol));
420
420
  }
421
421
  function buildUpgradeHints(input) {
422
422
  const repoArg = input.repoName ? ` --repo "${input.repoName}"` : '';
@@ -46,11 +46,6 @@ interface NextHopPayload {
46
46
  why: string;
47
47
  next_command: string;
48
48
  }
49
- interface RetrievalRuleHint {
50
- id: string;
51
- next_action: string;
52
- host_base_type?: string[];
53
- }
54
49
  export declare function pickVerificationTarget(input: {
55
50
  seedMode: ResourceSeedMode;
56
51
  seedPath?: string;
@@ -71,23 +66,10 @@ export declare function buildNextHops(input: {
71
66
  mappedSeedTargets: string[];
72
67
  resourceBindings: ResolvedUnityBinding[];
73
68
  verificationHint?: VerificationHint;
74
- retrievalRule?: RetrievalRuleHint;
75
69
  repoName?: string;
76
70
  symbolName: string;
77
71
  queryForSymbol: string;
78
72
  }): NextHopPayload[];
79
- export declare function pickRetrievalRuleHintFromBundle(input: {
80
- queryText?: string;
81
- symbolName?: string;
82
- seedPath?: string;
83
- rules: Array<{
84
- id: string;
85
- trigger_tokens?: string[];
86
- host_base_type?: string[];
87
- resource_types?: string[];
88
- next_action: string;
89
- }>;
90
- }): RetrievalRuleHint | undefined;
91
73
  export declare function resolveSeedTargetsFromResourceFile(repoPath: string, seedPath: string): Promise<string[]>;
92
74
  export declare function filterBm25ResultsByScopePreset<T extends {
93
75
  filePath?: string;
@@ -178,11 +160,6 @@ export declare class LocalBackend {
178
160
  }>>;
179
161
  callTool(method: string, params: any): Promise<any>;
180
162
  private unityUiTrace;
181
- private ruleLabAnalyze;
182
- private ruleLabReviewPack;
183
- private ruleLabCurate;
184
- private ruleLabPromote;
185
- private ruleLabRegress;
186
163
  /**
187
164
  * Query tool — process-grouped search.
188
165
  *
@@ -24,12 +24,6 @@ import { adjustRuntimeClaimForPolicy } from './runtime-claim.js';
24
24
  // git utilities available if needed
25
25
  // import { isGitRepo, getCurrentCommit, getGitRoot } from '../../storage/git.js';
26
26
  import { listRegisteredRepos, cleanupOldKuzuFiles, } from '../../storage/repo-manager.js';
27
- import { analyzeRuleLabSlice } from '../../rule-lab/analyze.js';
28
- import { buildReviewPack } from '../../rule-lab/review-pack.js';
29
- import { curateRuleLabSlice } from '../../rule-lab/curate.js';
30
- import { promoteCuratedRules } from '../../rule-lab/promote.js';
31
- import { runRuleLabRegress } from '../../rule-lab/regress.js';
32
- import { loadCompiledRuleBundle } from '../../rule-lab/compiled-bundles.js';
33
27
  // AI context generation is CLI-only (gitnexus analyze)
34
28
  // import { generateAIContextFiles } from '../../cli/ai-context.js';
35
29
  /**
@@ -246,10 +240,28 @@ async function loadSeedUnityResourceChains(input) {
246
240
  }
247
241
  catch (e) {
248
242
  logQueryError('unity-resource-chains:seed-second-hop', e);
249
- return [];
243
+ }
244
+ // One-hop query: direct UNITY_GRAPH_NODE_SCRIPT_REF from seed to Class
245
+ let oneHopRows = [];
246
+ try {
247
+ oneHopRows = await executeParameterized(input.repoId, `
248
+ MATCH (source:File {filePath: $seedPath})-[r:CodeRelation {type: 'UNITY_GRAPH_NODE_SCRIPT_REF'}]->(target)
249
+ WHERE labels(target)[0] = 'Class'
250
+ RETURN source.filePath AS sourceResourcePath,
251
+ r.type AS relationType,
252
+ r.reason AS relationReason,
253
+ target.id AS targetUid,
254
+ target.name AS targetName,
255
+ labels(target)[0] AS targetKind,
256
+ target.filePath AS targetFilePath
257
+ LIMIT 200
258
+ `, { seedPath });
259
+ }
260
+ catch (e) {
261
+ logQueryError('unity-resource-chains:seed-one-hop', e);
250
262
  }
251
263
  const seen = new Set();
252
- const chains = rows
264
+ const twoHopEntries = rows
253
265
  .map((row, index) => {
254
266
  const targetUid = String(row?.targetUid || row?.[6] || '').trim();
255
267
  const targetName = String(row?.targetName || row?.[7] || '').trim();
@@ -268,18 +280,35 @@ async function loadSeedUnityResourceChains(input) {
268
280
  ...(targetFilePath ? { filePath: targetFilePath } : {}),
269
281
  },
270
282
  };
271
- return {
272
- chain,
273
- index,
274
- score: scoreUnityResourceChainTarget(chain, targetSymbols),
283
+ return { chain, index, score: scoreUnityResourceChainTarget(chain, targetSymbols) };
284
+ });
285
+ const oneHopEntries = oneHopRows
286
+ .map((row, index) => {
287
+ const targetUid = String(row?.targetUid || row?.[4] || '').trim();
288
+ const targetName = String(row?.targetName || row?.[5] || '').trim();
289
+ const targetFilePath = normalizePath(String(row?.targetFilePath || row?.[7] || '').trim());
290
+ const chain = {
291
+ sourceResourcePath: normalizePath(String(row?.sourceResourcePath || row?.[0] || '').trim()),
292
+ relationType: 'UNITY_GRAPH_NODE_SCRIPT_REF',
293
+ relationReason: String(row?.relationReason || row?.[2] || '').trim() || undefined,
294
+ targetSymbol: {
295
+ ...(targetUid ? { uid: targetUid } : {}),
296
+ ...(targetName ? { name: targetName } : {}),
297
+ kind: String(row?.targetKind || row?.[6] || '').trim() || undefined,
298
+ ...(targetFilePath ? { filePath: targetFilePath } : {}),
299
+ },
275
300
  };
276
- })
301
+ return { chain, index: rows.length + index, score: scoreUnityResourceChainTarget(chain, targetSymbols) };
302
+ });
303
+ const chains = [...twoHopEntries, ...oneHopEntries]
277
304
  .filter(({ chain, score }) => {
278
- if (!chain.sourceResourcePath || !chain.intermediateResourcePath || !chain.targetSymbol?.name)
305
+ if (!chain.sourceResourcePath || !chain.targetSymbol?.name)
279
306
  return false;
280
307
  if (targetSymbols.length > 0 && score <= 0)
281
308
  return false;
282
- const key = `${chain.sourceResourcePath}->${chain.intermediateResourcePath}->${chain.targetSymbol.uid || chain.targetSymbol.name}`;
309
+ const key = chain.intermediateResourcePath
310
+ ? `${chain.sourceResourcePath}->${chain.intermediateResourcePath}->${chain.targetSymbol.uid || chain.targetSymbol.name}`
311
+ : `${chain.sourceResourcePath}->${chain.targetSymbol.uid || chain.targetSymbol.name}`;
283
312
  if (seen.has(key))
284
313
  return false;
285
314
  seen.add(key);
@@ -473,14 +502,7 @@ export function buildNextHops(input) {
473
502
  const mappedRemainder = input.mappedSeedTargets
474
503
  .map((value) => normalizePath(value))
475
504
  .filter((value) => value && !bindingSet.has(value));
476
- const retrievalHostScope = (input.retrievalRule?.host_base_type || [])
477
- .map((value) => String(value || '').trim().toLowerCase())
478
- .filter(Boolean);
479
- const currentSymbolMatchesRetrievalScope = retrievalHostScope.length === 0
480
- || retrievalHostScope.includes(String(input.symbolName || '').trim().toLowerCase());
481
- const shouldSuppressRawResourceHops = !input.seedPath
482
- && mappedIntersectBindings.length === 0
483
- && currentSymbolMatchesRetrievalScope === false;
505
+ const shouldSuppressRawResourceHops = false;
484
506
  const candidateResources = shouldSuppressRawResourceHops ? [] : rankCandidateResources([
485
507
  ...(input.seedPath ? [{ target: normalizePath(input.seedPath), bucket: 0 }] : []),
486
508
  ...mappedIntersectBindings.map((target) => ({ target, bucket: 1 })),
@@ -506,14 +528,6 @@ export function buildNextHops(input) {
506
528
  next_command: `gitnexus query${repoArg} --unity-resources on --unity-hydration parity --resource-path-prefix "${target}" "${input.queryForSymbol}"`,
507
529
  });
508
530
  }
509
- if (input.retrievalRule?.next_action) {
510
- addHop({
511
- kind: 'verify',
512
- target: input.seedPath || input.symbolName,
513
- why: `Retrieval rule ${input.retrievalRule.id} configured this follow-up action.`,
514
- next_command: withRepoInCommand(input.retrievalRule.next_action),
515
- });
516
- }
517
531
  if (input.verificationHint?.target
518
532
  && !(shouldSuppressRawResourceHops && isUnityResourcePathLike(String(input.verificationHint.target)))) {
519
533
  addHop({
@@ -579,69 +593,6 @@ function scoreResourcePathNoise(resourcePath) {
579
593
  penalty += 6;
580
594
  return penalty;
581
595
  }
582
- async function resolveRetrievalRuleHint(input) {
583
- const bundle = await loadCompiledRuleBundle(input.repoPath, 'retrieval_rules');
584
- if (!bundle)
585
- return undefined;
586
- return pickRetrievalRuleHintFromBundle({
587
- queryText: input.queryText,
588
- symbolName: input.symbolName,
589
- seedPath: input.seedPath,
590
- rules: bundle.rules,
591
- });
592
- }
593
- export function pickRetrievalRuleHintFromBundle(input) {
594
- const haystack = [
595
- String(input.queryText || ''),
596
- String(input.symbolName || ''),
597
- String(input.seedPath || ''),
598
- ].join(' ').toLowerCase();
599
- const rank = (rule) => {
600
- let score = 0;
601
- let matchedTrigger = false;
602
- let matchedEvidence = false;
603
- for (const token of rule.trigger_tokens || []) {
604
- const normalized = String(token || '').trim().toLowerCase();
605
- if (!normalized)
606
- continue;
607
- if (haystack.includes(normalized)) {
608
- matchedTrigger = true;
609
- matchedEvidence = true;
610
- score += 10 + normalized.length;
611
- }
612
- }
613
- for (const token of rule.host_base_type || []) {
614
- const normalized = String(token || '').trim().toLowerCase();
615
- if (normalized && haystack.includes(normalized)) {
616
- matchedEvidence = true;
617
- score += 20 + normalized.length;
618
- }
619
- }
620
- for (const token of rule.resource_types || []) {
621
- const normalized = String(token || '').trim().toLowerCase();
622
- if (normalized && haystack.includes(normalized)) {
623
- matchedEvidence = true;
624
- score += 4 + normalized.length;
625
- }
626
- }
627
- if (!matchedEvidence)
628
- return Number.NEGATIVE_INFINITY;
629
- if (!matchedTrigger)
630
- score -= 3;
631
- return score;
632
- };
633
- const matched = [...input.rules]
634
- .map((rule) => ({ rule, score: rank(rule) }))
635
- .filter((entry) => Number.isFinite(entry.score))
636
- .sort((a, b) => (b.score - a.score) || a.rule.id.localeCompare(b.rule.id))[0]?.rule;
637
- if (!matched || !String(matched.next_action || '').trim())
638
- return undefined;
639
- return {
640
- id: matched.id,
641
- next_action: matched.next_action,
642
- host_base_type: matched.host_base_type,
643
- };
644
- }
645
596
  export async function resolveSeedTargetsFromResourceFile(repoPath, seedPath) {
646
597
  if (!isUnityResourcePath(seedPath))
647
598
  return [];
@@ -1072,16 +1023,6 @@ export class LocalBackend {
1072
1023
  return this.detectChanges(repo, params);
1073
1024
  case 'rename':
1074
1025
  return this.rename(repo, params);
1075
- case 'rule_lab_analyze':
1076
- return this.ruleLabAnalyze(repo, params);
1077
- case 'rule_lab_review_pack':
1078
- return this.ruleLabReviewPack(repo, params);
1079
- case 'rule_lab_curate':
1080
- return this.ruleLabCurate(repo, params);
1081
- case 'rule_lab_promote':
1082
- return this.ruleLabPromote(repo, params);
1083
- case 'rule_lab_regress':
1084
- return this.ruleLabRegress(repo, params);
1085
1026
  // Legacy aliases for backwards compatibility
1086
1027
  case 'search':
1087
1028
  return this.query(repo, params);
@@ -1118,136 +1059,6 @@ export class LocalBackend {
1118
1059
  return { error: err?.message || 'unity_ui_trace failed' };
1119
1060
  }
1120
1061
  }
1121
- async ruleLabAnalyze(repo, params) {
1122
- const runId = String(params?.run_id || params?.runId || '').trim();
1123
- const sliceId = String(params?.slice_id || params?.sliceId || '').trim();
1124
- if (!runId || !sliceId) {
1125
- return { error: 'run_id and slice_id are required for rule_lab_analyze' };
1126
- }
1127
- try {
1128
- const out = await analyzeRuleLabSlice({
1129
- repoPath: repo.repoPath,
1130
- runId,
1131
- sliceId,
1132
- });
1133
- return {
1134
- ...out,
1135
- artifact_paths: {
1136
- candidates: out.paths.candidatesPath,
1137
- },
1138
- };
1139
- }
1140
- catch (err) {
1141
- return { error: err?.message || 'rule_lab_analyze failed' };
1142
- }
1143
- }
1144
- async ruleLabReviewPack(repo, params) {
1145
- const runId = String(params?.run_id || params?.runId || '').trim();
1146
- const sliceId = String(params?.slice_id || params?.sliceId || '').trim();
1147
- if (!runId || !sliceId) {
1148
- return { error: 'run_id and slice_id are required for rule_lab_review_pack' };
1149
- }
1150
- const maxTokens = Number.isFinite(Number(params?.max_tokens ?? params?.maxTokens))
1151
- ? Number(params?.max_tokens ?? params?.maxTokens)
1152
- : 6000;
1153
- try {
1154
- const out = await buildReviewPack({
1155
- repoPath: repo.repoPath,
1156
- runId,
1157
- sliceId,
1158
- maxTokens,
1159
- });
1160
- return {
1161
- ...out,
1162
- artifact_paths: {
1163
- review_pack: out.paths.reviewCardsPath,
1164
- },
1165
- };
1166
- }
1167
- catch (err) {
1168
- return { error: err?.message || 'rule_lab_review_pack failed' };
1169
- }
1170
- }
1171
- async ruleLabCurate(repo, params) {
1172
- const runId = String(params?.run_id || params?.runId || '').trim();
1173
- const sliceId = String(params?.slice_id || params?.sliceId || '').trim();
1174
- const inputPath = String(params?.input_path || params?.inputPath || '').trim();
1175
- if (!runId || !sliceId || !inputPath) {
1176
- return { error: 'run_id, slice_id, and input_path are required for rule_lab_curate' };
1177
- }
1178
- try {
1179
- const out = await curateRuleLabSlice({
1180
- repoPath: repo.repoPath,
1181
- runId,
1182
- sliceId,
1183
- inputPath,
1184
- });
1185
- return {
1186
- ...out,
1187
- artifact_paths: {
1188
- curated: out.paths.curatedPath,
1189
- },
1190
- };
1191
- }
1192
- catch (err) {
1193
- return { error: err?.message || 'rule_lab_curate failed' };
1194
- }
1195
- }
1196
- async ruleLabPromote(repo, params) {
1197
- const runId = String(params?.run_id || params?.runId || '').trim();
1198
- const sliceId = String(params?.slice_id || params?.sliceId || '').trim();
1199
- if (!runId || !sliceId) {
1200
- return { error: 'run_id and slice_id are required for rule_lab_promote' };
1201
- }
1202
- try {
1203
- const out = await promoteCuratedRules({
1204
- repoPath: repo.repoPath,
1205
- runId,
1206
- sliceId,
1207
- version: typeof params?.version === 'string' ? params.version : undefined,
1208
- });
1209
- return {
1210
- ...out,
1211
- artifact_paths: {
1212
- catalog: path.join(out.paths.rulesRoot, 'catalog.json'),
1213
- promoted_files: out.promotedFiles,
1214
- compiled_bundles: out.compiledPaths,
1215
- },
1216
- };
1217
- }
1218
- catch (err) {
1219
- return { error: err?.message || 'rule_lab_promote failed' };
1220
- }
1221
- }
1222
- async ruleLabRegress(repo, params) {
1223
- const precision = Number(params?.precision);
1224
- const coverage = Number(params?.coverage);
1225
- if (!Number.isFinite(precision) || !Number.isFinite(coverage)) {
1226
- return { error: 'precision and coverage are required numeric fields for rule_lab_regress' };
1227
- }
1228
- try {
1229
- let probes = Array.isArray(params?.probes) ? params.probes : undefined;
1230
- const probesPath = String(params?.probes_path || params?.probesPath || '').trim();
1231
- if (!probes && probesPath) {
1232
- const raw = await fs.readFile(path.isAbsolute(probesPath) ? probesPath : path.join(repo.repoPath, probesPath), 'utf-8');
1233
- probes = JSON.parse(raw);
1234
- }
1235
- const out = await runRuleLabRegress({
1236
- precision,
1237
- coverage,
1238
- probes,
1239
- repoPath: repo.repoPath,
1240
- runId: String(params?.run_id || params?.runId || '').trim() || undefined,
1241
- });
1242
- return {
1243
- ...out,
1244
- artifact_paths: out.reportPath ? { report: out.reportPath } : {},
1245
- };
1246
- }
1247
- catch (err) {
1248
- return { error: err?.message || 'rule_lab_regress failed' };
1249
- }
1250
- }
1251
1062
  // ─── Tool Implementations ────────────────────────────────────────
1252
1063
  /**
1253
1064
  * Query tool — process-grouped search.
@@ -1692,18 +1503,23 @@ export class LocalBackend {
1692
1503
  const firstResourceBindings = Array.isArray(firstSymbolForHops?.resourceBindings)
1693
1504
  ? firstSymbolForHops.resourceBindings
1694
1505
  : [];
1695
- const retrievalRule = await resolveRetrievalRuleHint({
1696
- repoPath: repo.repoPath,
1697
- queryText: params.query,
1698
- symbolName: String(firstSymbolForHops?.name || searchQuery),
1699
- seedPath,
1700
- });
1506
+ // Bindings→chains fallback: if resource_chains is empty but bindings exist, generate one-hop chains
1507
+ if ((!result.resource_chains || result.resource_chains.length === 0) && firstResourceBindings.length > 0) {
1508
+ result.resource_chains = firstResourceBindings.slice(0, 20).map((binding) => ({
1509
+ sourceResourcePath: binding.resourcePath,
1510
+ relationType: 'UNITY_GRAPH_NODE_SCRIPT_REF',
1511
+ targetSymbol: {
1512
+ uid: firstSymbolForHops?.id || undefined,
1513
+ name: firstSymbolForHops?.name || undefined,
1514
+ filePath: firstSymbolForHops?.filePath || undefined,
1515
+ },
1516
+ }));
1517
+ }
1701
1518
  result.next_hops = buildNextHops({
1702
1519
  seedPath,
1703
1520
  mappedSeedTargets,
1704
1521
  resourceBindings: firstResourceBindings,
1705
1522
  verificationHint: firstVerificationHint,
1706
- retrievalRule,
1707
1523
  repoName: repo.name,
1708
1524
  symbolName: String(firstSymbolForHops?.name || searchQuery),
1709
1525
  queryForSymbol: String(firstSymbolForHops?.name || searchQuery),
@@ -2462,18 +2278,23 @@ export class LocalBackend {
2462
2278
  }],
2463
2279
  });
2464
2280
  }
2465
- const retrievalRule = await resolveRetrievalRuleHint({
2466
- repoPath: repo.repoPath,
2467
- queryText: name,
2468
- symbolName: symName || String(name || uid || ''),
2469
- seedPath,
2470
- });
2281
+ // Bindings→chains fallback: if resource_chains is empty but bindings exist, generate one-hop chains
2282
+ if ((!result.resource_chains || result.resource_chains.length === 0) && contextResourceBindings.length > 0) {
2283
+ result.resource_chains = contextResourceBindings.slice(0, 20).map((binding) => ({
2284
+ sourceResourcePath: binding.resourcePath,
2285
+ relationType: 'UNITY_GRAPH_NODE_SCRIPT_REF',
2286
+ targetSymbol: {
2287
+ uid: symNodeId || undefined,
2288
+ name: symName || undefined,
2289
+ filePath: symFilePath || undefined,
2290
+ },
2291
+ }));
2292
+ }
2471
2293
  result.next_hops = buildNextHops({
2472
2294
  seedPath,
2473
2295
  mappedSeedTargets,
2474
2296
  resourceBindings: contextResourceBindings,
2475
2297
  verificationHint: topVerificationHint,
2476
- retrievalRule,
2477
2298
  repoName: repo.name,
2478
2299
  symbolName: symName || String(name || uid || ''),
2479
2300
  queryForSymbol: symName || String(name || uid || ''),
@@ -3,7 +3,6 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { describe, expect, it } from 'vitest';
5
5
  import { verifyRuntimeChainOnDemand, verifyRuntimeClaimOnDemand } from './runtime-chain-verify.js';
6
- import { promoteCuratedRules } from '../../rule-lab/promote.js';
7
6
  async function makeTempRepo() {
8
7
  const repoPath = await fs.mkdtemp(path.join(os.tmpdir(), 'runtime-chain-verify-'));
9
8
  await fs.mkdir(path.join(repoPath, 'Assets/NEON/DataAssets/Powerups/1_newWeapon/0_pick/法器_Orb'), { recursive: true });
@@ -590,52 +589,4 @@ describe('runtime chain verify', () => {
590
589
  expect(String(out.next_action || '')).toContain('Reload runtime start sequence');
591
590
  await fs.rm(repoPath, { recursive: true, force: true });
592
591
  });
593
- it('phase5 promote artifacts do not alter query-time graph-only rule identity', async () => {
594
- const repoPath = await fs.mkdtemp(path.join(os.tmpdir(), 'runtime-chain-rule-lab-promote-'));
595
- const sliceDir = path.join(repoPath, '.gitnexus', 'rules', 'lab', 'runs', 'run-x', 'slices', 'slice-a');
596
- await fs.mkdir(sliceDir, { recursive: true });
597
- await fs.writeFile(path.join(sliceDir, 'curated.json'), JSON.stringify({
598
- run_id: 'run-x',
599
- slice_id: 'slice-a',
600
- curated: [
601
- {
602
- id: 'candidate-startup-1',
603
- rule_id: 'demo.startup.v1',
604
- title: 'startup startup graph',
605
- confirmed_chain: {
606
- steps: [{ hop_type: 'resource', anchor: 'Assets/Rules/startup.asset:1', snippet: 'Startup Graph Trigger' }],
607
- },
608
- guarantees: ['startup trigger matching is confirmed'],
609
- non_guarantees: ['does not prove full runtime ordering'],
610
- },
611
- ],
612
- }, null, 2), 'utf-8');
613
- await promoteCuratedRules({ repoPath, runId: 'run-x', sliceId: 'slice-a', version: '1.0.0' });
614
- const out = await verifyRuntimeClaimOnDemand({
615
- repoPath,
616
- queryText: 'Startup Graph Trigger',
617
- symbolName: 'StartupNode',
618
- symbolFilePath: 'Assets/Rules/StartupNode.cs',
619
- resourceSeedPath: 'Assets/Rules/startup.asset',
620
- executeParameterized: async (query) => {
621
- if (String(query || '').includes('WHERE n.name IN $symbolNames')) {
622
- return [{
623
- id: 'Class:Assets/Rules/StartupNode.cs:StartupNode',
624
- name: 'StartupNode',
625
- type: 'Class',
626
- filePath: 'Assets/Rules/StartupNode.cs',
627
- startLine: 1,
628
- }];
629
- }
630
- return [];
631
- },
632
- resourceBindings: [{ resourcePath: 'Assets/Rules/startup.asset' }],
633
- });
634
- expect(out.rule_id).toBe('graph-only.runtime-closure.v1');
635
- expect(out.rule_id).not.toBe('demo.startup.v1');
636
- expect(out.status).toBe('verified_partial');
637
- expect(out.evidence_level).toBe('verified_segment');
638
- expect(out.reason).toBeUndefined();
639
- await fs.rm(repoPath, { recursive: true, force: true });
640
- });
641
592
  });
@@ -1,10 +1,8 @@
1
- import type { UnityResourceBinding, LifecycleOverrides } from '../../rule-lab/types.js';
2
1
  export interface RuntimeClaimRuleCatalogEntry {
3
2
  id: string;
4
3
  version: string;
5
4
  file?: string;
6
5
  enabled?: boolean;
7
- family?: 'analyze_rules' | 'verification_rules';
8
6
  }
9
7
  export interface RuntimeClaimRule {
10
8
  id: string;
@@ -24,9 +22,6 @@ export interface RuntimeClaimRule {
24
22
  guarantees: string[];
25
23
  non_guarantees: string[];
26
24
  next_action?: string;
27
- family?: 'analyze_rules' | 'verification_rules';
28
- resource_bindings?: UnityResourceBinding[];
29
- lifecycle_overrides?: LifecycleOverrides;
30
25
  file_path: string;
31
26
  topology?: Array<{
32
27
  hop: string;
@@ -60,9 +55,3 @@ export declare class RuleRegistryLoadError extends Error {
60
55
  constructor(code: RuleRegistryLoadErrorCode, message: string, details?: Record<string, string>);
61
56
  }
62
57
  export declare function parseRuleYaml(raw: string, filePath: string): RuntimeClaimRule;
63
- /**
64
- * Runtime claim rule registry remains the source for analyze-time synthetic-edge production
65
- * and offline governance/report workflows. Query-time runtime closure verification is graph-only.
66
- */
67
- export declare function loadRuleRegistry(repoPath: string, rulesRoot?: string): Promise<RuntimeClaimRuleRegistry>;
68
- export declare function loadAnalyzeRules(repoPath: string, rulesRoot?: string): Promise<RuntimeClaimRule[]>;