cgraphx 2.0.2 → 2.0.6
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.
- package/dist/.claude-template/FLOW-MAP.md +13 -3
- package/dist/.claude-template/agents/task-history.md +186 -0
- package/dist/.claude-template/commands/end.md +1 -0
- package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +5 -3
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +8 -8
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.md +8 -8
- package/dist/.claude-template/skills/clarify-requirements/SKILL.md +13 -9
- package/dist/.claude-template/skills/db-query/SKILL.md +19 -2
- package/dist/.claude-template/skills/iboc-check/SKILL.md +51 -23
- package/dist/.claude-template/skills/iboc-check/filler-prompt.md +3 -4
- package/dist/.claude-template/skills/run-api-test/SKILL.md +15 -15
- package/dist/.claude-template/skills/run-api-test/assets/{template-test-report.md → template-/346/216/245/345/217/243/346/265/213/350/257/225/346/212/245/345/221/212.md} +4 -4
- package/dist/.claude-template/skills/run-api-test/references/bru-run.md +1 -1
- package/dist/.claude-template/skills/run-api-test/references/db-verification.md +2 -2
- package/dist/.claude-template/skills/run-api-test/references/report-format.md +6 -6
- package/dist/.claude-template/skills/run-api-test/references/service-readiness.md +1 -1
- package/dist/.claude-template/skills/run-api-test/references/test-scope.md +6 -6
- package/dist/.claude-template/skills/run-ui-test/SKILL.md +186 -0
- package/dist/.claude-template/skills/run-ui-test/references/report-format.md +77 -0
- package/dist/.claude-template/skills/subagent-implement/SKILL.md +3 -2
- package/dist/.claude-template/skills/write-api/SKILL.md +18 -18
- package/dist/.claude-template/skills/write-api/assets/{template-api-spec.md → template-/346/216/245/345/217/243/346/265/213/350/257/225-spec.md} +1 -1
- package/dist/.claude-template/skills/write-api/references/{api-spec-format.md → /346/216/245/345/217/243/346/265/213/350/257/225-spec-format.md} +3 -3
- package/dist/.claude-template/skills/write-plan/SKILL.md +4 -2
- package/dist/.claude-template/skills/write-ui-test/SKILL.md +125 -0
- package/dist/.claude-template/skills/write-ui-test/references//347/224/250/344/276/213/350/247/204/346/240/274-format.md +94 -0
- package/dist/core/code/engine/cli/analyze-config.js +320 -0
- package/dist/core/code/engine/cli/analyze.js +1086 -0
- package/dist/core/code/engine/cli/cli-message.js +83 -0
- package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
- package/dist/core/code/engine/cli/embedding-dims.js +43 -0
- package/dist/core/code/engine/cli/format-elapsed.js +12 -0
- package/dist/core/code/engine/cli/help-i18n.js +144 -0
- package/dist/core/code/engine/cli/i18n/en.js +110 -0
- package/dist/core/code/engine/cli/i18n/index.js +47 -0
- package/dist/core/code/engine/cli/i18n/resources.js +9 -0
- package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
- package/dist/core/code/engine/cli/lazy-action.js +67 -0
- package/dist/core/code/engine/cli/optional-grammars.js +136 -0
- package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
- package/dist/core/code/engine/cli/status.js +156 -0
- package/dist/core/code/engine/cli/tool.js +384 -0
- package/dist/core/code/engine/config/ignore-service.js +511 -0
- package/dist/core/code/engine/config/supported-languages.js +17 -0
- package/dist/core/code/engine/core/analysis-features.js +64 -0
- package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
- package/dist/core/code/engine/core/git-staleness.js +180 -0
- package/dist/core/code/engine/core/graph/graph.js +180 -0
- package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
- package/dist/core/code/engine/core/graph/types.js +2 -0
- package/dist/core/code/engine/core/index-freshness.js +12 -0
- package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
- package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
- package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
- package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
- package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
- package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
- package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
- package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
- package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
- package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
- package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
- package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
- package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
- package/dist/core/code/engine/core/ingestion/constants.js +26 -0
- package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
- package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
- package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
- package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
- package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
- package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
- package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
- package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
- package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
- package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
- package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
- package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
- package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
- package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
- package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
- package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
- package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
- package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
- package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
- package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
- package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
- package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
- package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
- package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
- package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
- package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
- package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
- package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
- package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
- package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
- package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
- package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
- package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
- package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
- package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
- package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
- package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
- package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
- package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
- package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
- package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
- package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
- package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
- package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
- package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
- package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
- package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
- package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
- package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
- package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
- package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
- package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
- package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
- package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
- package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
- package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
- package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
- package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
- package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
- package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
- package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
- package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
- package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
- package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
- package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
- package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
- package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
- package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
- package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
- package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
- package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
- package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
- package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
- package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
- package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
- package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
- package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
- package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
- package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
- package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
- package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
- package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
- package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
- package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
- package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
- package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
- package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
- package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
- package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
- package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
- package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
- package/dist/core/code/engine/core/lbug/native-check.js +435 -0
- package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
- package/dist/core/code/engine/core/lbug/query-params.js +25 -0
- package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
- package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
- package/dist/core/code/engine/core/lbug/schema.js +771 -0
- package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
- package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
- package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
- package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
- package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
- package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
- package/dist/core/code/engine/core/logger.js +339 -0
- package/dist/core/code/engine/core/platform/capabilities.js +91 -0
- package/dist/core/code/engine/core/run-analyze.js +1098 -0
- package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
- package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
- package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
- package/dist/core/code/engine/lib/utils.js +121 -0
- package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
- package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
- package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
- package/dist/core/code/engine/mcp/local/limits.js +15 -0
- package/dist/core/code/engine/mcp/local/line-display.js +6 -0
- package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
- package/dist/core/code/engine/storage/branch-index.js +72 -0
- package/dist/core/code/engine/storage/file-hash.js +95 -0
- package/dist/core/code/engine/storage/fs-atomic.js +34 -0
- package/dist/core/code/engine/storage/git.js +555 -0
- package/dist/core/code/engine/storage/index-lock.js +664 -0
- package/dist/core/code/engine/storage/parse-cache.js +650 -0
- package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
- package/dist/core/code/engine/storage/repo-manager.js +1061 -0
- package/dist/core/code/engine/storage/scope-index-store.js +247 -0
- package/dist/core/code/engine/types/pipeline.js +2 -0
- package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
- package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
- package/dist/core/code/shared/graph/types.js +8 -0
- package/dist/core/code/shared/index.js +105 -0
- package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
- package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
- package/dist/core/code/shared/integrations/retry.js +70 -0
- package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
- package/dist/core/code/shared/language-detection.js +162 -0
- package/dist/core/code/shared/languages.js +27 -0
- package/dist/core/code/shared/lbug/schema-constants.js +98 -0
- package/dist/core/code/shared/mro-strategy.js +2 -0
- package/dist/core/code/shared/pipeline.js +5 -0
- package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
- package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
- package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
- package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
- package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
- package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
- package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
- package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
- package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
- package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
- package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
- package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
- package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
- package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
- package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
- package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
- package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
- package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
- package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
- package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
- package/dist/core/code/shared/scope-resolution/types.js +25 -0
- package/dist/core/code/shared/test-helpers.js +17 -0
- package/dist/core/code/vendor/leiden/index.cjs +355 -0
- package/dist/core/code/vendor/leiden/utils.cjs +419 -0
- package/dist/core/dbquery/cli.d.ts.map +1 -1
- package/dist/core/dbquery/cli.js +5 -4
- package/dist/core/dbquery/cli.js.map +1 -1
- package/dist/core/dbquery/config.d.ts.map +1 -1
- package/dist/core/dbquery/config.js +39 -3
- package/dist/core/dbquery/config.js.map +1 -1
- package/dist/core/dbquery/drivers/http.d.ts +23 -0
- package/dist/core/dbquery/drivers/http.d.ts.map +1 -0
- package/dist/core/dbquery/drivers/http.js +125 -0
- package/dist/core/dbquery/drivers/http.js.map +1 -0
- package/dist/core/dbquery/drivers/mysql.js +1 -1
- package/dist/core/dbquery/drivers/mysql.js.map +1 -1
- package/dist/core/dbquery/drivers/postgres.js +1 -1
- package/dist/core/dbquery/drivers/postgres.js.map +1 -1
- package/dist/core/dbquery/executor.d.ts.map +1 -1
- package/dist/core/dbquery/executor.js +46 -12
- package/dist/core/dbquery/executor.js.map +1 -1
- package/dist/core/dbquery/format.d.ts.map +1 -1
- package/dist/core/dbquery/format.js +2 -1
- package/dist/core/dbquery/format.js.map +1 -1
- package/dist/core/dbquery/init.d.ts.map +1 -1
- package/dist/core/dbquery/init.js +7 -0
- package/dist/core/dbquery/init.js.map +1 -1
- package/dist/core/dbquery/types.d.ts +55 -7
- package/dist/core/dbquery/types.d.ts.map +1 -1
- package/dist/core/directory.d.ts +17 -0
- package/dist/core/directory.d.ts.map +1 -1
- package/dist/core/directory.js +37 -0
- package/dist/core/directory.js.map +1 -1
- package/dist/core/features/cli.d.ts.map +1 -1
- package/dist/core/features/cli.js +3 -2
- package/dist/core/features/cli.js.map +1 -1
- package/dist/core/features/scanner.d.ts +1 -1
- package/dist/core/features/scanner.d.ts.map +1 -1
- package/dist/core/features/scanner.js +20 -4
- package/dist/core/features/scanner.js.map +1 -1
- package/dist/core/markdown/cli.d.ts.map +1 -1
- package/dist/core/markdown/cli.js +9 -8
- package/dist/core/markdown/cli.js.map +1 -1
- package/dist/core/timeline/cli.d.ts.map +1 -1
- package/dist/core/timeline/cli.js +13 -6
- package/dist/core/timeline/cli.js.map +1 -1
- package/dist/core/timeline/debris.d.ts +20 -0
- package/dist/core/timeline/debris.d.ts.map +1 -0
- package/dist/core/timeline/debris.js +124 -0
- package/dist/core/timeline/debris.js.map +1 -0
- package/dist/core/timeline/hook-runner.d.ts.map +1 -1
- package/dist/core/timeline/hook-runner.js +3 -1
- package/dist/core/timeline/hook-runner.js.map +1 -1
- package/dist/core/timeline/hooks.d.ts.map +1 -1
- package/dist/core/timeline/hooks.js +13 -5
- package/dist/core/timeline/hooks.js.map +1 -1
- package/dist/core/timeline/installer.d.ts +2 -0
- package/dist/core/timeline/installer.d.ts.map +1 -1
- package/dist/core/timeline/installer.js +12 -0
- package/dist/core/timeline/installer.js.map +1 -1
- package/dist/core/timeline/project-root.d.ts +21 -0
- package/dist/core/timeline/project-root.d.ts.map +1 -0
- package/dist/core/timeline/project-root.js +83 -0
- package/dist/core/timeline/project-root.js.map +1 -0
- package/dist/web/register.d.ts.map +1 -1
- package/dist/web/register.js +2 -1
- package/dist/web/register.js.map +1 -1
- package/package.json +1 -1
- package/dist/.claude-template/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-deck/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-deck/references/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-sketch-engine/.cgraphx/timeline-current-turn.json +0 -1
- /package/dist/.claude-template/skills/run-api-test/assets/{template-test-verify.jsonl → template-/346/216/245/345/217/243/346/265/213/350/257/225/351/252/214/350/257/201.jsonl"} +0 -0
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.acquireIndexLock = exports.sweepStagingArtifacts = exports.isLockUnwritableCode = exports.LOCK_UNWRITABLE_CODES = exports.IndexLockTimeoutError = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Cross-process single-writer lock for a GitNexus index directory (#2658).
|
|
9
|
+
*
|
|
10
|
+
* `analyze` is the only writer of a `.cgraphx/code/` (or `branches/<slug>/`) slot,
|
|
11
|
+
* but nothing stopped two `analyze` runs — e.g. two editor/agent SessionStart
|
|
12
|
+
* hooks firing on the same repo at once — from wiping and rebuilding the same
|
|
13
|
+
* store concurrently. They raced on `lbug` and its sidecars, wasted N× CPU
|
|
14
|
+
* producing one index, and left orphaned WAL fragments (#2637). This module
|
|
15
|
+
* gives the write path an exclusive, index-directory-scoped lock so a second
|
|
16
|
+
* writer waits for the first instead of colliding; after acquiring, the caller
|
|
17
|
+
* re-runs its normal freshness check, so a run whose work the holder already
|
|
18
|
+
* did exits up-to-date rather than rebuilding (single-flight coalescing).
|
|
19
|
+
*
|
|
20
|
+
* Ownership lives with the process that runs the pipeline (the heap-respawn
|
|
21
|
+
* child when a respawn happens, the original otherwise) — NOT a supervising
|
|
22
|
+
* parent — so the entity the OS tracks for liveness is always the real writer.
|
|
23
|
+
* See run-analyze.ts for the acquire site.
|
|
24
|
+
*
|
|
25
|
+
* TWO BACKENDS behind the {@link acquireIndexLock} seam:
|
|
26
|
+
*
|
|
27
|
+
* - **socket** (Windows named pipe / Linux abstract socket, via `net`) — the
|
|
28
|
+
* preferred, KERNEL-OWNED lock. Holding it = holding a listening endpoint the
|
|
29
|
+
* kernel binds to this process; `EADDRINUSE` therefore means a *live* holder,
|
|
30
|
+
* and the kernel drops the binding the instant the holder exits for ANY reason
|
|
31
|
+
* (clean exit, crash, OOM, SIGKILL). That makes it provably race-free: no
|
|
32
|
+
* stale detection, no pid-reuse guess, no takeover, and — since the endpoint
|
|
33
|
+
* lives outside the index dir — no filesystem write, so it works unchanged on
|
|
34
|
+
* a read-only index mount. This is the same class of kernel object as the
|
|
35
|
+
* Windows named mutex the issue's reporter used as an external workaround, but
|
|
36
|
+
* built from Node's stdlib `net`, so it adds NO native dependency and cannot
|
|
37
|
+
* break `npx cgraph` install anywhere.
|
|
38
|
+
*
|
|
39
|
+
* - **file** (`O_EXCL` pidfile) — the portable fallback for macOS/BSD (no
|
|
40
|
+
* abstract sockets; filesystem sockets don't release cleanly on death) and
|
|
41
|
+
* for any environment where the socket backend can't bind. It uses pid-
|
|
42
|
+
* liveness staleness, an atomic rename-steal reclaim, bounded malformed-file
|
|
43
|
+
* handling, read-only tolerance, and a finite wait timeout (a reused pid can
|
|
44
|
+
* masquerade as live where process start-time isn't verifiable, so waiting is
|
|
45
|
+
* bounded rather than a hang). Its stale-takeover has an irreducible narrow
|
|
46
|
+
* race — inherent to file-based advisory locks — which is precisely why the
|
|
47
|
+
* socket backend is preferred; only a kernel primitive closes it.
|
|
48
|
+
*
|
|
49
|
+
* Scope: cross-process, same logical index dir. The file backend never steals a
|
|
50
|
+
* foreign-host lock (pid liveness is meaningless across hosts); the socket
|
|
51
|
+
* backend is single-host by nature. The motivating case (local hook-driven
|
|
52
|
+
* re-index) is single-host. See AcquireOptions.timeoutMs for the wait ceiling.
|
|
53
|
+
*/
|
|
54
|
+
const node_fs_1 = require("node:fs");
|
|
55
|
+
const node_net_1 = __importDefault(require("node:net"));
|
|
56
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
57
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
58
|
+
const node_crypto_1 = require("node:crypto");
|
|
59
|
+
const LOCK_FILENAME = 'analyze.lock';
|
|
60
|
+
const LOCK_RECORD_VERSION = 1;
|
|
61
|
+
/** Base poll interval while waiting for a live holder; jittered per attempt. */
|
|
62
|
+
const DEFAULT_POLL_MS = 250;
|
|
63
|
+
/** How often to re-emit the "still waiting for pid N" diagnostic. */
|
|
64
|
+
const DIAGNOSTIC_INTERVAL_MS = 15_000;
|
|
65
|
+
/**
|
|
66
|
+
* Default wait ceiling (10 min). Generous enough to sit behind a normal
|
|
67
|
+
* analyze, finite so a pid-reuse ghost on a platform without start-time
|
|
68
|
+
* verification can't wedge acquisition forever (see AcquireOptions.timeoutMs).
|
|
69
|
+
* A repo whose analyze legitimately runs longer can raise
|
|
70
|
+
* CGRAPH_INDEX_LOCK_TIMEOUT_MS (or set it ≤ 0 for unbounded).
|
|
71
|
+
*/
|
|
72
|
+
const DEFAULT_TIMEOUT_MS = 600_000;
|
|
73
|
+
/**
|
|
74
|
+
* How long a lock file must stay unreadable (empty/partial JSON) before we
|
|
75
|
+
* treat it as a crash orphan and reclaim it. Tolerates the microsecond
|
|
76
|
+
* create→write→close window of a *live* owner (see acquireIndexLock), so we
|
|
77
|
+
* never steal a lock that is a poll-interval away from being written. Scaled
|
|
78
|
+
* off the poll interval, floored at 1s.
|
|
79
|
+
*/
|
|
80
|
+
const malformedGraceMs = (pollMs) => Math.max(1000, pollMs * 2);
|
|
81
|
+
class IndexLockTimeoutError extends Error {
|
|
82
|
+
holder;
|
|
83
|
+
/**
|
|
84
|
+
* Whether `holder` carries a real, identifiable owner. False on the socket
|
|
85
|
+
* backend (and the file backend's malformed/vanished-lock timeouts), where the
|
|
86
|
+
* holder is a placeholder (`pid -1`) — the OS socket lock exposes no owner
|
|
87
|
+
* metadata (#2658 review M3). Consumers must not present `holder.pid` as a real
|
|
88
|
+
* pid when this is false.
|
|
89
|
+
*/
|
|
90
|
+
holderKnown;
|
|
91
|
+
constructor(holder, waitedMs, holderKnown = true) {
|
|
92
|
+
super(holderKnown
|
|
93
|
+
? `Timed out after ${waitedMs}ms waiting for another cgraph analyze ` +
|
|
94
|
+
`(pid ${holder.pid} on ${holder.hostname}, invocation ${holder.invocationId}) ` +
|
|
95
|
+
`to release the index lock.`
|
|
96
|
+
: `Timed out after ${waitedMs}ms waiting for another cgraph analyze ` +
|
|
97
|
+
`(holder identity unknown) to release the index lock.`);
|
|
98
|
+
this.name = 'IndexLockTimeoutError';
|
|
99
|
+
this.holder = holder;
|
|
100
|
+
this.holderKnown = holderKnown;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.IndexLockTimeoutError = IndexLockTimeoutError;
|
|
104
|
+
const HOSTNAME = node_os_1.default.hostname();
|
|
105
|
+
/** Linux: field 22 of /proc/<pid>/stat (starttime). null elsewhere / on error. */
|
|
106
|
+
const readProcStartTime = (pid) => {
|
|
107
|
+
if (process.platform !== 'linux')
|
|
108
|
+
return null;
|
|
109
|
+
try {
|
|
110
|
+
const stat = (0, node_fs_1.readFileSync)(`/proc/${pid}/stat`, 'utf8');
|
|
111
|
+
// comm (field 2) is parenthesized and may contain spaces/')' — split after
|
|
112
|
+
// the last ')' so the remaining fields align to their documented numbers.
|
|
113
|
+
const afterComm = stat
|
|
114
|
+
.slice(stat.lastIndexOf(') ') + 2)
|
|
115
|
+
.trim()
|
|
116
|
+
.split(' ');
|
|
117
|
+
// afterComm[0] is field 3 (state); starttime is field 22 → index 19.
|
|
118
|
+
return afterComm[19] ?? null;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/** true if the pid exists (signal 0). EPERM means it exists but isn't ours. */
|
|
125
|
+
const pidAlive = (pid) => {
|
|
126
|
+
try {
|
|
127
|
+
process.kill(pid, 0);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
return err.code === 'EPERM';
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const buildRecord = () => ({
|
|
135
|
+
v: LOCK_RECORD_VERSION,
|
|
136
|
+
pid: process.pid,
|
|
137
|
+
hostname: HOSTNAME,
|
|
138
|
+
startTime: readProcStartTime(process.pid),
|
|
139
|
+
token: (0, node_crypto_1.randomBytes)(16).toString('hex'),
|
|
140
|
+
invocationId: (0, node_crypto_1.randomUUID)(),
|
|
141
|
+
acquiredAt: new Date().toISOString(),
|
|
142
|
+
});
|
|
143
|
+
const readRecord = (lockPath) => {
|
|
144
|
+
try {
|
|
145
|
+
const raw = (0, node_fs_1.readFileSync)(lockPath, 'utf8');
|
|
146
|
+
const parsed = JSON.parse(raw);
|
|
147
|
+
// `typeof NaN === 'number'`, so a bare number check lets NaN/0/-1/Infinity/
|
|
148
|
+
// fractional pids reach process.kill (#2658 review L4): a garbled or crafted
|
|
149
|
+
// lock file with `{"pid":0}` reads as a live holder and wedges a real analyze
|
|
150
|
+
// for the full wait timeout. A real pid is a positive integer.
|
|
151
|
+
if (!Number.isInteger(parsed.pid) || parsed.pid <= 0)
|
|
152
|
+
return null;
|
|
153
|
+
if (typeof parsed.token !== 'string')
|
|
154
|
+
return null;
|
|
155
|
+
return parsed;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Missing (won the race, file gone) or malformed/half-written → treat as
|
|
159
|
+
// "no readable holder"; the caller retries the O_EXCL create.
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* A same-host holder is stale iff its process is gone, or (Linux) its pid is
|
|
165
|
+
* alive but was reused — a different start time. A live holder is never stolen
|
|
166
|
+
* on age alone (a large repo legitimately analyzes for many minutes), and a
|
|
167
|
+
* foreign-host holder is never stale (its liveness is unknowable here). Where
|
|
168
|
+
* start-time verification is unavailable (non-Linux), a reused pid cannot be
|
|
169
|
+
* distinguished from a genuine live holder, so it is NOT stolen — the finite
|
|
170
|
+
* acquire timeout is what bounds that case instead (see AcquireOptions).
|
|
171
|
+
*/
|
|
172
|
+
const isStale = (holder) => {
|
|
173
|
+
if (holder.hostname !== HOSTNAME)
|
|
174
|
+
return false;
|
|
175
|
+
if (!pidAlive(holder.pid))
|
|
176
|
+
return true;
|
|
177
|
+
const now = readProcStartTime(holder.pid);
|
|
178
|
+
if (holder.startTime && now && holder.startTime !== now)
|
|
179
|
+
return true; // pid reused
|
|
180
|
+
return false;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Reclaim a lock file we judged reclaimable — a dead holder (`expected` = its
|
|
184
|
+
* record) or a malformed/unreadable crash-orphan (`expected` = null) — moving
|
|
185
|
+
* the exact inode aside in ONE `rename` syscall to a token-unique name so two
|
|
186
|
+
* waiters reclaiming the same orphan can't both win (the loser's rename ENOENTs).
|
|
187
|
+
*
|
|
188
|
+
* CRITICAL (#2658 review): the reclaim must not act on a STALE judgment. The
|
|
189
|
+
* staleness decision (`isStale` / malformed-grace) happened a few syscalls ago;
|
|
190
|
+
* a live writer may have O_EXCL-created its own lock at `lockPath` since. Blindly
|
|
191
|
+
* renaming that live lock aside would delete it and admit a SECOND writer — the
|
|
192
|
+
* exact double-writer this lock exists to prevent (reproduced: ~18%/round under
|
|
193
|
+
* 4-way reclaim contention on the file backend). So:
|
|
194
|
+
* 1. re-read `lockPath` immediately BEFORE the rename and confirm it still holds
|
|
195
|
+
* exactly what we judged (same token, or still-unreadable) — shrinking the
|
|
196
|
+
* window to the single gap between this read and the rename;
|
|
197
|
+
* 2. after the rename, confirm what we ACTUALLY moved matches the judgment; if a
|
|
198
|
+
* live lock slipped into that residual gap, RESTORE it (rename back) so its
|
|
199
|
+
* holder is never displaced, and lose the reclaim.
|
|
200
|
+
* A concurrent creator whose fresh lock the restore overwrites is caught by the
|
|
201
|
+
* acquire loop's post-write read-back verify (see acquireViaFile), so it backs
|
|
202
|
+
* off rather than proceeding as a second writer.
|
|
203
|
+
*
|
|
204
|
+
* Returns true if we won the reclaim (caller retries the create), false if we
|
|
205
|
+
* lost the race or the judgment went stale (caller re-loops and re-reads).
|
|
206
|
+
*/
|
|
207
|
+
const matchesJudgment = (record, expected) => expected === null ? record === null : record?.token === expected.token;
|
|
208
|
+
const stealLock = (lockPath, me, expected) => {
|
|
209
|
+
// (1) Re-verify the judgment still holds right before we move anything.
|
|
210
|
+
if (!matchesJudgment(readRecord(lockPath), expected))
|
|
211
|
+
return false;
|
|
212
|
+
if (expected === null && !(0, node_fs_1.existsSync)(lockPath))
|
|
213
|
+
return false; // malformed → but now vanished
|
|
214
|
+
const aside = `${lockPath}.dead.${me.token}`;
|
|
215
|
+
try {
|
|
216
|
+
(0, node_fs_1.renameSync)(lockPath, aside);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
if (err.code === 'ENOENT')
|
|
220
|
+
return false; // another stealer won
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
// (2) Confirm what we moved is what we judged; if a live lock slipped into the
|
|
224
|
+
// read→rename gap, put it back — a live holder must never be displaced.
|
|
225
|
+
if (!matchesJudgment(readRecord(aside), expected)) {
|
|
226
|
+
try {
|
|
227
|
+
(0, node_fs_1.renameSync)(aside, lockPath); // restore; an overwritten concurrent creator's read-back backs it off
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
/* slot re-taken between our move and restore — leave it; we lost the reclaim */
|
|
231
|
+
}
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
(0, node_fs_1.unlinkSync)(aside); // uniquely ours by token → safe; best-effort
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
/* leftover .dead.<token> is inert (not analyze.lock, not swept) — harmless */
|
|
239
|
+
}
|
|
240
|
+
return true;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Placeholder holder for an {@link IndexLockTimeoutError} thrown while the lock
|
|
244
|
+
* file exists but no valid record can be read (malformed/partial), or it keeps
|
|
245
|
+
* vanishing — there is no real holder to name, but the error still needs one so
|
|
246
|
+
* the CLI's `err.holder.pid` stays defined. This path is a rare backstop:
|
|
247
|
+
* malformed files are reclaimed within {@link MALFORMED_GRACE_MS}.
|
|
248
|
+
*/
|
|
249
|
+
const unknownHolder = () => ({
|
|
250
|
+
v: LOCK_RECORD_VERSION,
|
|
251
|
+
pid: -1,
|
|
252
|
+
hostname: HOSTNAME,
|
|
253
|
+
startTime: null,
|
|
254
|
+
token: '',
|
|
255
|
+
invocationId: '<unreadable>',
|
|
256
|
+
acquiredAt: '',
|
|
257
|
+
});
|
|
258
|
+
/**
|
|
259
|
+
* Filesystem-create error codes we tolerate by proceeding lock-free: a
|
|
260
|
+
* read-only mount (EROFS) or a denied create (EACCES/EPERM). Such a filesystem
|
|
261
|
+
* rejects every index WRITE in the same directory too, so no concurrent writer
|
|
262
|
+
* can exist and the lock is moot — an already-indexed repo on a `:ro` mount
|
|
263
|
+
* must still reach its `alreadyUpToDate` fast path (#2658). A genuinely-needed
|
|
264
|
+
* write fails later exactly as it would have without the lock.
|
|
265
|
+
*/
|
|
266
|
+
exports.LOCK_UNWRITABLE_CODES = new Set(['EROFS', 'EACCES', 'EPERM']);
|
|
267
|
+
const isLockUnwritableCode = (code) => code !== undefined && exports.LOCK_UNWRITABLE_CODES.has(code);
|
|
268
|
+
exports.isLockUnwritableCode = isLockUnwritableCode;
|
|
269
|
+
/** A lock handle that owns nothing — returned when the filesystem refuses to
|
|
270
|
+
* create the lock file (see {@link LOCK_UNWRITABLE_CODES}). Release is a no-op. */
|
|
271
|
+
const noopHandle = (record) => ({ record, release: () => { } });
|
|
272
|
+
/**
|
|
273
|
+
* Delete orphaned build/staging artifacts left in the lock directory by a
|
|
274
|
+
* crashed prior writer. Safe precisely because we hold the exclusive lock: no
|
|
275
|
+
* other writer can be creating these here right now, so anything present is a
|
|
276
|
+
* crash orphan. Matches this slot's staging files ONLY — never `lbug` itself,
|
|
277
|
+
* never `lbug.wal`/`lbug.shadow` (the LIVE index's own sidecars), and never a
|
|
278
|
+
* `branches/<slug>/` sub-slot (which owns its own lock + sweep). Non-recursive.
|
|
279
|
+
*/
|
|
280
|
+
const sweepStagingArtifacts = (lockDir, log) => {
|
|
281
|
+
// Matches `lbug.new`, `lbug.new.wal`, `lbug.staging.<id>`, `lbug.staging.<id>.wal`, …
|
|
282
|
+
// Does NOT match `lbug`, `lbug.wal`, `lbug.shadow`.
|
|
283
|
+
const stagingRe = /^lbug\.(staging\..+|new(\..+)?)$/;
|
|
284
|
+
let removed = 0;
|
|
285
|
+
let entries;
|
|
286
|
+
try {
|
|
287
|
+
entries = (0, node_fs_1.readdirSync)(lockDir);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
for (const name of entries) {
|
|
293
|
+
if (!stagingRe.test(name))
|
|
294
|
+
continue;
|
|
295
|
+
try {
|
|
296
|
+
(0, node_fs_1.unlinkSync)(node_path_1.default.join(lockDir, name));
|
|
297
|
+
removed++;
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
/* best-effort */
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (removed > 0) {
|
|
304
|
+
log?.(`Cleared ${removed} orphaned index-staging file(s) from a prior interrupted analyze.`);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
exports.sweepStagingArtifacts = sweepStagingArtifacts;
|
|
308
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
309
|
+
/** Poll delay with jitter (avoids two waiters lock-stepping), clamped so it
|
|
310
|
+
* never overshoots the remaining timeout budget. Callers guarantee
|
|
311
|
+
* `waited < timeoutMs`, so the result is ≥ 1. */
|
|
312
|
+
const jitteredDelay = (pollMs, timeoutMs, waited) => {
|
|
313
|
+
const jitter = Math.floor(Math.random() * pollMs);
|
|
314
|
+
const remaining = timeoutMs - waited;
|
|
315
|
+
return Math.max(1, Math.min(pollMs + jitter, remaining));
|
|
316
|
+
};
|
|
317
|
+
/**
|
|
318
|
+
* Resolve the wait ceiling. Explicit `opt` wins; else
|
|
319
|
+
* CGRAPH_INDEX_LOCK_TIMEOUT_MS; else {@link DEFAULT_TIMEOUT_MS}. A value ≤ 0
|
|
320
|
+
* (from either source) means unbounded.
|
|
321
|
+
*/
|
|
322
|
+
const resolveTimeoutMs = (opt) => {
|
|
323
|
+
const raw = typeof opt === 'number'
|
|
324
|
+
? opt
|
|
325
|
+
: (() => {
|
|
326
|
+
const env = process.env.CGRAPH_INDEX_LOCK_TIMEOUT_MS;
|
|
327
|
+
if (env === undefined || env === '')
|
|
328
|
+
return DEFAULT_TIMEOUT_MS;
|
|
329
|
+
const n = Number(env);
|
|
330
|
+
return Number.isFinite(n) ? n : DEFAULT_TIMEOUT_MS;
|
|
331
|
+
})();
|
|
332
|
+
return raw <= 0 ? Number.POSITIVE_INFINITY : raw;
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Acquire the exclusive write lock for `lockDir` (the resolved index slot
|
|
336
|
+
* directory, e.g. `<repo>/.cgraphx/code` or `<repo>/.cgraphx/code/branches/<slug>`).
|
|
337
|
+
*
|
|
338
|
+
* Blocks until the lock is held (waiting only on live holders, stealing dead
|
|
339
|
+
* ones immediately), then sweeps orphaned staging files under the lock and
|
|
340
|
+
* returns a handle. Rejects with `IndexLockTimeoutError` if `timeoutMs` is
|
|
341
|
+
* exceeded while a live holder still holds the lock.
|
|
342
|
+
*/
|
|
343
|
+
/**
|
|
344
|
+
* File-based (O_EXCL pidfile) backend. The portable fallback used on platforms
|
|
345
|
+
* without the socket backend (macOS/BSD) or when the OS socket lock is
|
|
346
|
+
* unavailable. Carries the pid-liveness staleness, atomic rename-steal reclaim,
|
|
347
|
+
* bounded malformed-file handling, and read-only tolerance. Its stale-takeover
|
|
348
|
+
* has an irreducible (narrow) race — see the module header — which is why the
|
|
349
|
+
* socket backend is preferred where available.
|
|
350
|
+
*/
|
|
351
|
+
const acquireViaFile = async (lockDir, me, opts) => {
|
|
352
|
+
try {
|
|
353
|
+
(0, node_fs_1.mkdirSync)(lockDir, { recursive: true });
|
|
354
|
+
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
// Read-only / denied filesystem → proceed lock-free (see LOCK_UNWRITABLE_CODES).
|
|
357
|
+
if ((0, exports.isLockUnwritableCode)(err.code))
|
|
358
|
+
return noopHandle(me);
|
|
359
|
+
throw err;
|
|
360
|
+
}
|
|
361
|
+
const lockPath = node_path_1.default.join(lockDir, LOCK_FILENAME);
|
|
362
|
+
const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
|
|
363
|
+
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
|
364
|
+
const startedAt = Date.now();
|
|
365
|
+
let announcedWait = false;
|
|
366
|
+
let lastDiagnosticAt = 0;
|
|
367
|
+
// When the lock file exists but has no readable record, the timestamp we
|
|
368
|
+
// first observed it unreadable — used to reclaim a crash-orphan after a grace.
|
|
369
|
+
let malformedSince = null;
|
|
370
|
+
for (;;) {
|
|
371
|
+
try {
|
|
372
|
+
// O_WRONLY | O_CREAT | O_EXCL — the atomic arbiter of ownership.
|
|
373
|
+
const fd = (0, node_fs_1.openSync)(lockPath, 'wx');
|
|
374
|
+
try {
|
|
375
|
+
(0, node_fs_1.writeSync)(fd, JSON.stringify(me));
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
(0, node_fs_1.closeSync)(fd);
|
|
379
|
+
}
|
|
380
|
+
// Read-back verify (#2658 review L5): if this process stalled (a >graceMs
|
|
381
|
+
// GC pause) between the O_EXCL create of the *empty* file and the write
|
|
382
|
+
// above, a waiter could have reclaimed the empty file (renamed it aside)
|
|
383
|
+
// and O_EXCL-created its own lock at `lockPath`. Our write then landed on
|
|
384
|
+
// the renamed-aside inode, not `lockPath`. Confirm `lockPath` still carries
|
|
385
|
+
// our token before claiming ownership; if it was stolen, contend normally.
|
|
386
|
+
const confirmed = readRecord(lockPath);
|
|
387
|
+
if (!confirmed || confirmed.token !== me.token)
|
|
388
|
+
continue;
|
|
389
|
+
return {
|
|
390
|
+
record: me,
|
|
391
|
+
release: () => {
|
|
392
|
+
const current = readRecord(lockPath);
|
|
393
|
+
if (current && current.token !== me.token)
|
|
394
|
+
return; // no longer ours
|
|
395
|
+
try {
|
|
396
|
+
(0, node_fs_1.unlinkSync)(lockPath);
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
/* already gone */
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
const code = err.code;
|
|
406
|
+
if (code === 'EEXIST') {
|
|
407
|
+
// fall through to holder inspection / wait / reclaim below
|
|
408
|
+
}
|
|
409
|
+
else if ((0, exports.isLockUnwritableCode)(code)) {
|
|
410
|
+
return noopHandle(me); // read-only / denied → proceed lock-free
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
throw err;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const holder = readRecord(lockPath);
|
|
417
|
+
const waited = Date.now() - startedAt;
|
|
418
|
+
if (holder) {
|
|
419
|
+
malformedSince = null;
|
|
420
|
+
if (isStale(holder)) {
|
|
421
|
+
opts.log?.(`Reclaiming stale index lock from dead analyze (pid ${holder.pid}, ` +
|
|
422
|
+
`invocation ${holder.invocationId}).`);
|
|
423
|
+
stealLock(lockPath, me, holder); // reclaim ONLY this dead record; live locks are never stolen
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
// Live holder → wait.
|
|
427
|
+
if (!announcedWait) {
|
|
428
|
+
announcedWait = true;
|
|
429
|
+
opts.onWaitStart?.(holder);
|
|
430
|
+
opts.log?.(`Another cgraph analyze (pid ${holder.pid} on ${holder.hostname}) is ` +
|
|
431
|
+
`refreshing this index — waiting for it to finish.`);
|
|
432
|
+
}
|
|
433
|
+
if (waited >= timeoutMs)
|
|
434
|
+
throw new IndexLockTimeoutError(holder, waited);
|
|
435
|
+
if (Date.now() - lastDiagnosticAt >= DIAGNOSTIC_INTERVAL_MS) {
|
|
436
|
+
lastDiagnosticAt = Date.now();
|
|
437
|
+
if (waited >= DIAGNOSTIC_INTERVAL_MS) {
|
|
438
|
+
opts.log?.(`Still waiting for analyze pid ${holder.pid} (${Math.round(waited / 1000)}s elapsed).`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
await sleep(jitteredDelay(pollMs, timeoutMs, waited));
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
// holder === null: the lock file is either gone (vanished between the failed
|
|
445
|
+
// create and our read) or present-but-unreadable (a crash between the
|
|
446
|
+
// O_EXCL create and the record write, or a partial write). NEVER hot-loop
|
|
447
|
+
// here — both branches are bounded by sleep + timeout.
|
|
448
|
+
if (!(0, node_fs_1.existsSync)(lockPath)) {
|
|
449
|
+
malformedSince = null; // genuinely vanished → the next create likely wins
|
|
450
|
+
if (waited >= timeoutMs)
|
|
451
|
+
throw new IndexLockTimeoutError(unknownHolder(), waited, false);
|
|
452
|
+
await sleep(jitteredDelay(pollMs, timeoutMs, waited));
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
// Malformed orphan present. Reclaim only after a grace, so a live owner's
|
|
456
|
+
// microsecond create→write window is never mistaken for a crash.
|
|
457
|
+
if (malformedSince === null)
|
|
458
|
+
malformedSince = Date.now();
|
|
459
|
+
if (Date.now() - malformedSince >= malformedGraceMs(pollMs)) {
|
|
460
|
+
opts.log?.('Reclaiming a malformed/partial index lock file (no readable owner record).');
|
|
461
|
+
stealLock(lockPath, me, null); // reclaim ONLY while still unreadable; a live lock written since is left
|
|
462
|
+
malformedSince = null;
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (waited >= timeoutMs)
|
|
466
|
+
throw new IndexLockTimeoutError(unknownHolder(), waited, false);
|
|
467
|
+
await sleep(jitteredDelay(pollMs, timeoutMs, waited));
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
/** Signals that the OS socket backend can't be used here (e.g. abstract
|
|
471
|
+
* namespace disabled, sandbox, or an unexpected bind error) so the caller
|
|
472
|
+
* should fall back to the file backend. NOT thrown for EADDRINUSE (that is a
|
|
473
|
+
* live holder → wait) or timeouts (those propagate as IndexLockTimeoutError). */
|
|
474
|
+
class SocketLockUnavailable extends Error {
|
|
475
|
+
cause;
|
|
476
|
+
constructor(cause) {
|
|
477
|
+
super(`OS socket lock unavailable: ${cause.code ?? cause.message}`);
|
|
478
|
+
this.cause = cause;
|
|
479
|
+
this.name = 'SocketLockUnavailable';
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Canonicalize a path to its real filesystem identity so lexical aliases of the
|
|
484
|
+
* same directory (a symlink, a bind-mount path, a Windows junction, a `\\?\`
|
|
485
|
+
* prefix) map to ONE name (#2658 review H1). `lockDir` (the index slot) often
|
|
486
|
+
* does not exist yet, so `realpathSync` the deepest existing ancestor and
|
|
487
|
+
* re-append the not-yet-created remainder. A path with no symlink components
|
|
488
|
+
* realpaths to itself, so the common (non-aliased) case is unchanged — a holder
|
|
489
|
+
* that used the old resolved name is never orphaned.
|
|
490
|
+
*/
|
|
491
|
+
const canonicalizeDir = (p) => {
|
|
492
|
+
const resolved = node_path_1.default.resolve(p);
|
|
493
|
+
const tail = [];
|
|
494
|
+
let dir = resolved;
|
|
495
|
+
for (;;) {
|
|
496
|
+
try {
|
|
497
|
+
const real = (0, node_fs_1.realpathSync)(dir);
|
|
498
|
+
return tail.length ? node_path_1.default.join(real, ...tail.reverse()) : real;
|
|
499
|
+
}
|
|
500
|
+
catch {
|
|
501
|
+
const parent = node_path_1.default.dirname(dir);
|
|
502
|
+
if (parent === dir)
|
|
503
|
+
return resolved; // reached the root with nothing to resolve
|
|
504
|
+
tail.push(node_path_1.default.basename(dir));
|
|
505
|
+
dir = parent;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
/**
|
|
510
|
+
* Stable OS-IPC endpoint name for an index directory. The name is derived from
|
|
511
|
+
* the REAL path (case-folded on Windows), so two processes targeting the same
|
|
512
|
+
* physical slot — even via different lexical aliases — collide, and separate
|
|
513
|
+
* worktrees/branches never do. The endpoint lives OUTSIDE the index directory
|
|
514
|
+
* (abstract namespace / pipe namespace), so the lock needs no filesystem write
|
|
515
|
+
* and is unaffected by a read-only index mount.
|
|
516
|
+
*/
|
|
517
|
+
const socketLockName = (lockDir) => {
|
|
518
|
+
const resolved = canonicalizeDir(lockDir);
|
|
519
|
+
const key = (0, node_crypto_1.createHash)('sha256')
|
|
520
|
+
.update(process.platform === 'win32' ? resolved.toLowerCase() : resolved)
|
|
521
|
+
.digest('hex')
|
|
522
|
+
.slice(0, 32);
|
|
523
|
+
return process.platform === 'win32'
|
|
524
|
+
? `\\\\.\\pipe\\gitnexus-idx-${key}`
|
|
525
|
+
: `\0gitnexus-idx-${key}`; // Linux abstract socket (no filesystem entry)
|
|
526
|
+
};
|
|
527
|
+
/** Attempt to listen; resolve to null on success or the error on failure. */
|
|
528
|
+
const tryListen = (server, name) => new Promise((resolve) => {
|
|
529
|
+
const onError = (err) => {
|
|
530
|
+
server.removeListener('listening', onListening);
|
|
531
|
+
resolve(err);
|
|
532
|
+
};
|
|
533
|
+
const onListening = () => {
|
|
534
|
+
server.removeListener('error', onError);
|
|
535
|
+
resolve(null);
|
|
536
|
+
};
|
|
537
|
+
server.once('error', onError);
|
|
538
|
+
server.once('listening', onListening);
|
|
539
|
+
server.listen(name);
|
|
540
|
+
});
|
|
541
|
+
/**
|
|
542
|
+
* OS-owned socket/pipe backend (Windows named pipe, Linux abstract socket).
|
|
543
|
+
* Holding the lock = holding a listening endpoint the kernel binds to this
|
|
544
|
+
* process; `EADDRINUSE` therefore means a *live* holder, and the kernel drops
|
|
545
|
+
* the binding the instant the holder exits (clean exit, crash, OOM, SIGKILL) —
|
|
546
|
+
* so there is no stale detection, no reclaim, and no takeover race. See the
|
|
547
|
+
* module header for why this is preferred over the file backend.
|
|
548
|
+
*/
|
|
549
|
+
const acquireViaSocket = async (lockDir, me, opts) => {
|
|
550
|
+
const name = socketLockName(lockDir);
|
|
551
|
+
const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
|
|
552
|
+
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
|
553
|
+
const startedAt = Date.now();
|
|
554
|
+
let announcedWait = false;
|
|
555
|
+
let lastDiagnosticAt = 0;
|
|
556
|
+
for (;;) {
|
|
557
|
+
const server = node_net_1.default.createServer();
|
|
558
|
+
// Never keep the process alive on the lock's account, and never hold an
|
|
559
|
+
// incoming connection (nothing should connect; drop any stray peer).
|
|
560
|
+
server.unref();
|
|
561
|
+
server.on('connection', (sock) => sock.destroy());
|
|
562
|
+
const listenErr = await tryListen(server, name);
|
|
563
|
+
if (!listenErr) {
|
|
564
|
+
return {
|
|
565
|
+
record: me,
|
|
566
|
+
release: () => {
|
|
567
|
+
try {
|
|
568
|
+
server.close();
|
|
569
|
+
}
|
|
570
|
+
catch {
|
|
571
|
+
/* already closed / releasing on exit */
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
// This server never bound (listen failed); release its handle before the
|
|
577
|
+
// next poll or the fallback, so a long contended wait doesn't churn one
|
|
578
|
+
// unclosed net.Server per iteration (#2658 review L3).
|
|
579
|
+
try {
|
|
580
|
+
server.close();
|
|
581
|
+
}
|
|
582
|
+
catch {
|
|
583
|
+
/* never listened */
|
|
584
|
+
}
|
|
585
|
+
// Only EADDRINUSE means "held by a live holder → wait". Anything else means
|
|
586
|
+
// this environment can't use the socket backend → fall back to the file one.
|
|
587
|
+
if (listenErr.code !== 'EADDRINUSE')
|
|
588
|
+
throw new SocketLockUnavailable(listenErr);
|
|
589
|
+
if (!announcedWait) {
|
|
590
|
+
announcedWait = true;
|
|
591
|
+
opts.onWaitStart?.(me);
|
|
592
|
+
opts.log?.('Another cgraph analyze is refreshing this index — waiting for it to finish.');
|
|
593
|
+
}
|
|
594
|
+
const waited = Date.now() - startedAt;
|
|
595
|
+
// Socket backend exposes no owner metadata → holder identity is unknown (M3).
|
|
596
|
+
if (waited >= timeoutMs)
|
|
597
|
+
throw new IndexLockTimeoutError(unknownHolder(), waited, false);
|
|
598
|
+
if (Date.now() - lastDiagnosticAt >= DIAGNOSTIC_INTERVAL_MS) {
|
|
599
|
+
lastDiagnosticAt = Date.now();
|
|
600
|
+
if (waited >= DIAGNOSTIC_INTERVAL_MS) {
|
|
601
|
+
opts.log?.(`Still waiting for another analyze (${Math.round(waited / 1000)}s elapsed).`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
await sleep(jitteredDelay(pollMs, timeoutMs, waited));
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
/** Platforms whose OS IPC namespace gives a clean, auto-releasing lock via
|
|
608
|
+
* `net`: Windows named pipes and Linux abstract sockets. Elsewhere (macOS/BSD)
|
|
609
|
+
* the file backend is used (no abstract namespace; filesystem sockets don't
|
|
610
|
+
* release cleanly on death). Override for tests via CGRAPH_INDEX_LOCK_BACKEND
|
|
611
|
+
* = 'socket' | 'file'.
|
|
612
|
+
*
|
|
613
|
+
* Scope caveat: the socket backend's mutual-exclusion domain is NOT uniform.
|
|
614
|
+
* Windows `\\.\pipe\` names are machine-wide (all sessions); Linux abstract
|
|
615
|
+
* sockets are network-namespace-scoped (network_namespaces(7)). So two writers
|
|
616
|
+
* that share a bind-mounted index dir but sit in separate netns (e.g. two
|
|
617
|
+
* containers, Docker's default) do NOT collide on Linux — "single-host" is
|
|
618
|
+
* really "single-netns" here. That cross-netns-shared-mount case is the one
|
|
619
|
+
* the file backend (shared-filesystem O_EXCL) would cover; set
|
|
620
|
+
* CGRAPH_INDEX_LOCK_BACKEND=file there. The motivating case (local hook-
|
|
621
|
+
* driven re-index) is single-netns, so the default socket backend covers it. */
|
|
622
|
+
const selectBackend = () => {
|
|
623
|
+
const override = process.env.CGRAPH_INDEX_LOCK_BACKEND;
|
|
624
|
+
if (override === 'socket' || override === 'file')
|
|
625
|
+
return override;
|
|
626
|
+
return process.platform === 'win32' || process.platform === 'linux' ? 'socket' : 'file';
|
|
627
|
+
};
|
|
628
|
+
/**
|
|
629
|
+
* Acquire the exclusive write lock for `lockDir` (the resolved index slot
|
|
630
|
+
* directory). Uses the OS socket/pipe backend where available (Windows/Linux),
|
|
631
|
+
* falling back to the file backend otherwise or if the socket backend is
|
|
632
|
+
* unusable in this environment. After acquiring, sweeps orphaned staging files
|
|
633
|
+
* under the lock (best-effort; a no-op on a read-only mount). Rejects with
|
|
634
|
+
* `IndexLockTimeoutError` if `timeoutMs` elapses while another live holder holds
|
|
635
|
+
* the lock.
|
|
636
|
+
*/
|
|
637
|
+
const acquireIndexLock = async (lockDir, opts = {}) => {
|
|
638
|
+
const me = buildRecord();
|
|
639
|
+
let handle;
|
|
640
|
+
if (selectBackend() === 'socket') {
|
|
641
|
+
try {
|
|
642
|
+
handle = await acquireViaSocket(lockDir, me, opts);
|
|
643
|
+
}
|
|
644
|
+
catch (err) {
|
|
645
|
+
if (!(err instanceof SocketLockUnavailable))
|
|
646
|
+
throw err; // timeout etc. propagate
|
|
647
|
+
opts.log?.('Index lock: OS socket lock unavailable here — using the file lock.');
|
|
648
|
+
handle = await acquireViaFile(lockDir, me, opts);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
handle = await acquireViaFile(lockDir, me, opts);
|
|
653
|
+
}
|
|
654
|
+
// Reclaim crashed-build staging orphans while we hold the lock. Best-effort:
|
|
655
|
+
// a read-only mount (no orphans reachable) just no-ops.
|
|
656
|
+
try {
|
|
657
|
+
(0, exports.sweepStagingArtifacts)(lockDir, opts.log);
|
|
658
|
+
}
|
|
659
|
+
catch {
|
|
660
|
+
/* best-effort */
|
|
661
|
+
}
|
|
662
|
+
return handle;
|
|
663
|
+
};
|
|
664
|
+
exports.acquireIndexLock = acquireIndexLock;
|