loom-tool 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- loom_tool-0.1.0/.env.example +34 -0
- loom_tool-0.1.0/.gitattributes +22 -0
- loom_tool-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +25 -0
- loom_tool-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- loom_tool-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- loom_tool-0.1.0/.github/pull_request_template.md +7 -0
- loom_tool-0.1.0/.github/workflows/ci.yml +58 -0
- loom_tool-0.1.0/.github/workflows/loom-full-index.yml +34 -0
- loom_tool-0.1.0/.github/workflows/loom-index.yml +37 -0
- loom_tool-0.1.0/.github/workflows/publish-pypi.yml +41 -0
- loom_tool-0.1.0/.gitignore +11 -0
- loom_tool-0.1.0/.mcp.json +12 -0
- loom_tool-0.1.0/.python-version +1 -0
- loom_tool-0.1.0/CHANGELOG.md +48 -0
- loom_tool-0.1.0/CLAUDE.md +224 -0
- loom_tool-0.1.0/CODE_OF_CONDUCT.md +26 -0
- loom_tool-0.1.0/CONTRIBUTING.md +44 -0
- loom_tool-0.1.0/LICENSE +21 -0
- loom_tool-0.1.0/PKG-INFO +371 -0
- loom_tool-0.1.0/README.md +335 -0
- loom_tool-0.1.0/SECURITY.md +19 -0
- loom_tool-0.1.0/docker-compose.yml +13 -0
- loom_tool-0.1.0/docs/ARCHITECTURE.md +412 -0
- loom_tool-0.1.0/docs/MANUAL_INTERVENTION_ERRORS.md +61 -0
- loom_tool-0.1.0/docs/TECHNICAL_CAPABILITIES.md +224 -0
- loom_tool-0.1.0/docs/USAGE.md +355 -0
- loom_tool-0.1.0/pyproject.toml +103 -0
- loom_tool-0.1.0/pytest.ini +5 -0
- loom_tool-0.1.0/scripts/check_deps.py +142 -0
- loom_tool-0.1.0/scripts/check_env.py +46 -0
- loom_tool-0.1.0/scripts/diagnose_vector_query.py +64 -0
- loom_tool-0.1.0/src/loom/__init__.py +32 -0
- loom_tool-0.1.0/src/loom/analysis/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/analysis/code/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/analysis/code/calls.py +232 -0
- loom_tool-0.1.0/src/loom/analysis/code/calls_java.py +132 -0
- loom_tool-0.1.0/src/loom/analysis/code/calls_ts.py +136 -0
- loom_tool-0.1.0/src/loom/analysis/code/communities.py +261 -0
- loom_tool-0.1.0/src/loom/analysis/code/coupling.py +205 -0
- loom_tool-0.1.0/src/loom/analysis/code/extractor.py +78 -0
- loom_tool-0.1.0/src/loom/analysis/code/noise_filter.py +251 -0
- loom_tool-0.1.0/src/loom/analysis/code/parser.py +58 -0
- loom_tool-0.1.0/src/loom/cli.py +1157 -0
- loom_tool-0.1.0/src/loom/config.py +86 -0
- loom_tool-0.1.0/src/loom/core/__init__.py +13 -0
- loom_tool-0.1.0/src/loom/core/content_hash.py +20 -0
- loom_tool-0.1.0/src/loom/core/edge.py +88 -0
- loom_tool-0.1.0/src/loom/core/falkor/__init__.py +3 -0
- loom_tool-0.1.0/src/loom/core/falkor/cypher.py +92 -0
- loom_tool-0.1.0/src/loom/core/falkor/edge_type_adapter.py +91 -0
- loom_tool-0.1.0/src/loom/core/falkor/gateway.py +107 -0
- loom_tool-0.1.0/src/loom/core/falkor/mappers.py +119 -0
- loom_tool-0.1.0/src/loom/core/falkor/repositories.py +306 -0
- loom_tool-0.1.0/src/loom/core/falkor/schema.py +87 -0
- loom_tool-0.1.0/src/loom/core/graph.py +145 -0
- loom_tool-0.1.0/src/loom/core/node.py +98 -0
- loom_tool-0.1.0/src/loom/core/protocols.py +32 -0
- loom_tool-0.1.0/src/loom/devtools.py +123 -0
- loom_tool-0.1.0/src/loom/drift/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/drift/detector.py +160 -0
- loom_tool-0.1.0/src/loom/embed/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/embed/embedder.py +150 -0
- loom_tool-0.1.0/src/loom/ingest/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/ingest/code/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/_ts_utils.py +27 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/constants.py +224 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/go_lang.py +185 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/java.py +344 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/javascript.py +242 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/markup.py +601 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/python.py +399 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/ruby.py +214 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/rust.py +178 -0
- loom_tool-0.1.0/src/loom/ingest/code/languages/typescript.py +442 -0
- loom_tool-0.1.0/src/loom/ingest/code/registry.py +290 -0
- loom_tool-0.1.0/src/loom/ingest/code/walker.py +104 -0
- loom_tool-0.1.0/src/loom/ingest/differ.py +53 -0
- loom_tool-0.1.0/src/loom/ingest/docs/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/ingest/docs/base.py +121 -0
- loom_tool-0.1.0/src/loom/ingest/docs/markdown.py +87 -0
- loom_tool-0.1.0/src/loom/ingest/docs/pdf.py +41 -0
- loom_tool-0.1.0/src/loom/ingest/git.py +102 -0
- loom_tool-0.1.0/src/loom/ingest/helpers.py +36 -0
- loom_tool-0.1.0/src/loom/ingest/incremental.py +606 -0
- loom_tool-0.1.0/src/loom/ingest/integrations/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/ingest/integrations/jira.py +224 -0
- loom_tool-0.1.0/src/loom/ingest/pipeline.py +677 -0
- loom_tool-0.1.0/src/loom/ingest/result.py +56 -0
- loom_tool-0.1.0/src/loom/ingest/utils.py +158 -0
- loom_tool-0.1.0/src/loom/linker/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/linker/_text_utils.py +15 -0
- loom_tool-0.1.0/src/loom/linker/embed_match.py +100 -0
- loom_tool-0.1.0/src/loom/linker/linker.py +92 -0
- loom_tool-0.1.0/src/loom/linker/llm_match.py +104 -0
- loom_tool-0.1.0/src/loom/linker/name_match.py +60 -0
- loom_tool-0.1.0/src/loom/linker/prompts.py +20 -0
- loom_tool-0.1.0/src/loom/linker/reranker.py +84 -0
- loom_tool-0.1.0/src/loom/llm/__init__.py +0 -0
- loom_tool-0.1.0/src/loom/llm/client.py +35 -0
- loom_tool-0.1.0/src/loom/mcp/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/mcp/server.py +301 -0
- loom_tool-0.1.0/src/loom/py.typed +0 -0
- loom_tool-0.1.0/src/loom/query/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/query/blast_radius.py +109 -0
- loom_tool-0.1.0/src/loom/query/node_lookup.py +66 -0
- loom_tool-0.1.0/src/loom/query/traceability.py +176 -0
- loom_tool-0.1.0/src/loom/search/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/search/searcher.py +156 -0
- loom_tool-0.1.0/src/loom/watch/__init__.py +1 -0
- loom_tool-0.1.0/src/loom/watch/watcher.py +105 -0
- loom_tool-0.1.0/tests/__init__.py +1 -0
- loom_tool-0.1.0/tests/fixtures/__init__.py +1 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/controller/PaymentController.java +48 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/domain/BankTransferPayment.java +31 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/domain/CreditCardPayment.java +53 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/domain/Payment.java +46 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/domain/PaymentStatus.java +9 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/domain/PaymentType.java +9 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/dto/PaymentRequest.java +39 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/dto/PaymentResponse.java +33 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/repository/InMemoryPaymentRepository.java +33 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/repository/PaymentRepository.java +15 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/service/CreditCardProcessor.java +41 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/service/PaymentProcessor.java +11 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/service/PaymentService.java +46 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/java/com/example/payment/util/ReflectionExample.java +46 -0
- loom_tool-0.1.0/tests/fixtures/java_springboot/src/main/resources/application.properties +31 -0
- loom_tool-0.1.0/tests/fixtures/python_flask_app/.env.example +33 -0
- loom_tool-0.1.0/tests/fixtures/python_flask_app/app.py +160 -0
- loom_tool-0.1.0/tests/fixtures/python_flask_app/models.py +88 -0
- loom_tool-0.1.0/tests/fixtures/python_flask_app/reflection_example.py +72 -0
- loom_tool-0.1.0/tests/fixtures/python_flask_app/utils.py +125 -0
- loom_tool-0.1.0/tests/fixtures/sample_graph.py +179 -0
- loom_tool-0.1.0/tests/fixtures/sample_repo/auth.py +45 -0
- loom_tool-0.1.0/tests/fixtures/sample_repo/flask_app.py +24 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/.env.example +23 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/components/TaskCard.tsx +113 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/components/TaskList.tsx +66 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/composables/useTaskManager.ts +95 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/types/Task.ts +36 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/utils/dynamicPatterns.ts +82 -0
- loom_tool-0.1.0/tests/fixtures/vue_tsx_app/src/utils/taskHelpers.ts +62 -0
- loom_tool-0.1.0/tests/integration/__init__.py +0 -0
- loom_tool-0.1.0/tests/integration/test_communities.py +196 -0
- loom_tool-0.1.0/tests/integration/test_edge_type_storage.py +269 -0
- loom_tool-0.1.0/tests/integration/test_graph_crud_and_neighbors.py +66 -0
- loom_tool-0.1.0/tests/integration/test_graph_e2e.py +99 -0
- loom_tool-0.1.0/tests/integration/test_graph_upsert_metadata_edges.py +169 -0
- loom_tool-0.1.0/tests/integration/test_incremental.py +326 -0
- loom_tool-0.1.0/tests/integration/test_java_springboot_e2e.py +364 -0
- loom_tool-0.1.0/tests/integration/test_markup_config_e2e.py +419 -0
- loom_tool-0.1.0/tests/integration/test_python_flask_e2e.py +253 -0
- loom_tool-0.1.0/tests/integration/test_schema_init.py +41 -0
- loom_tool-0.1.0/tests/integration/test_search_query_e2e.py +89 -0
- loom_tool-0.1.0/tests/integration/test_semantic_linker_rerank_e2e.py +69 -0
- loom_tool-0.1.0/tests/integration/test_vue_tsx_e2e.py +267 -0
- loom_tool-0.1.0/tests/unit/test_calls.py +293 -0
- loom_tool-0.1.0/tests/unit/test_calls_ts_java.py +43 -0
- loom_tool-0.1.0/tests/unit/test_cli_accuracy.py +288 -0
- loom_tool-0.1.0/tests/unit/test_cli_analyze.py +254 -0
- loom_tool-0.1.0/tests/unit/test_cli_calls.py +133 -0
- loom_tool-0.1.0/tests/unit/test_cli_entrypoints.py +42 -0
- loom_tool-0.1.0/tests/unit/test_cli_help_query.py +14 -0
- loom_tool-0.1.0/tests/unit/test_cli_query.py +40 -0
- loom_tool-0.1.0/tests/unit/test_cli_sync.py +94 -0
- loom_tool-0.1.0/tests/unit/test_cli_trace.py +63 -0
- loom_tool-0.1.0/tests/unit/test_communities.py +141 -0
- loom_tool-0.1.0/tests/unit/test_content_hash.py +69 -0
- loom_tool-0.1.0/tests/unit/test_coupling.py +379 -0
- loom_tool-0.1.0/tests/unit/test_differ.py +58 -0
- loom_tool-0.1.0/tests/unit/test_docs_markdown.py +88 -0
- loom_tool-0.1.0/tests/unit/test_drift_detector.py +116 -0
- loom_tool-0.1.0/tests/unit/test_edge.py +113 -0
- loom_tool-0.1.0/tests/unit/test_edge_more_cases.py +31 -0
- loom_tool-0.1.0/tests/unit/test_edge_origin_mapper.py +25 -0
- loom_tool-0.1.0/tests/unit/test_edge_type_adapter.py +153 -0
- loom_tool-0.1.0/tests/unit/test_embed_match.py +111 -0
- loom_tool-0.1.0/tests/unit/test_embedder.py +45 -0
- loom_tool-0.1.0/tests/unit/test_gateway_config.py +27 -0
- loom_tool-0.1.0/tests/unit/test_git.py +115 -0
- loom_tool-0.1.0/tests/unit/test_imports.py +12 -0
- loom_tool-0.1.0/tests/unit/test_incremental_sync.py +1010 -0
- loom_tool-0.1.0/tests/unit/test_index_repo_docs.py +112 -0
- loom_tool-0.1.0/tests/unit/test_index_repo_incremental.py +227 -0
- loom_tool-0.1.0/tests/unit/test_index_repo_semantic_linker.py +94 -0
- loom_tool-0.1.0/tests/unit/test_ingest_utils.py +34 -0
- loom_tool-0.1.0/tests/unit/test_jira_connector.py +104 -0
- loom_tool-0.1.0/tests/unit/test_linker.py +64 -0
- loom_tool-0.1.0/tests/unit/test_llm_match.py +76 -0
- loom_tool-0.1.0/tests/unit/test_mappers.py +111 -0
- loom_tool-0.1.0/tests/unit/test_markup_parser.py +281 -0
- loom_tool-0.1.0/tests/unit/test_mcp_server.py +183 -0
- loom_tool-0.1.0/tests/unit/test_mcp_tools.py +48 -0
- loom_tool-0.1.0/tests/unit/test_multilang_parser.py +468 -0
- loom_tool-0.1.0/tests/unit/test_name_match.py +83 -0
- loom_tool-0.1.0/tests/unit/test_neighbors_kind_lookup.py +116 -0
- loom_tool-0.1.0/tests/unit/test_node.py +116 -0
- loom_tool-0.1.0/tests/unit/test_node_lookup.py +99 -0
- loom_tool-0.1.0/tests/unit/test_node_repository.py +98 -0
- loom_tool-0.1.0/tests/unit/test_noise_filter.py +28 -0
- loom_tool-0.1.0/tests/unit/test_parser.py +346 -0
- loom_tool-0.1.0/tests/unit/test_parser_metadata.py +59 -0
- loom_tool-0.1.0/tests/unit/test_pipeline_jira.py +100 -0
- loom_tool-0.1.0/tests/unit/test_registry.py +16 -0
- loom_tool-0.1.0/tests/unit/test_repositories.py +28 -0
- loom_tool-0.1.0/tests/unit/test_reranker.py +87 -0
- loom_tool-0.1.0/tests/unit/test_searcher.py +196 -0
- loom_tool-0.1.0/tests/unit/test_semantic_linker.py +238 -0
- loom_tool-0.1.0/tests/unit/test_semantic_linker_rerank.py +53 -0
- loom_tool-0.1.0/tests/unit/test_smoke.py +2 -0
- loom_tool-0.1.0/tests/unit/test_traceability.py +235 -0
- loom_tool-0.1.0/tests/unit/test_traversal_ppr.py +140 -0
- loom_tool-0.1.0/tests/unit/test_vector_embedding_storage.py +93 -0
- loom_tool-0.1.0/tests/unit/test_vector_index_fix.py +142 -0
- loom_tool-0.1.0/tests/unit/test_walk_repo.py +133 -0
- loom_tool-0.1.0/tests/unit/test_watcher.py +181 -0
- loom_tool-0.1.0/uv.lock +3651 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Loom Configuration
|
|
2
|
+
# Copy this file to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# Required
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
# Database configuration
|
|
9
|
+
LOOM_DB_HOST=localhost
|
|
10
|
+
LOOM_DB_PORT=6379
|
|
11
|
+
|
|
12
|
+
# Embedding model (must match LOOM_EMBED_DIM)
|
|
13
|
+
LOOM_EMBED_MODEL=nomic-ai/nomic-embed-text-v1.5
|
|
14
|
+
LOOM_EMBED_DIM=768
|
|
15
|
+
LOOM_EMBED_BATCH_SIZE=64
|
|
16
|
+
|
|
17
|
+
# ============================================================================
|
|
18
|
+
# Optional — enables LLM-assisted semantic linking (higher quality IMPLEMENTS edges)
|
|
19
|
+
# Leave unset to use static extraction only (recommended for getting started)
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
# Examples:
|
|
23
|
+
# LOOM_LLM_MODEL=ollama/llama3.2
|
|
24
|
+
# LOOM_LLM_MODEL=openai/gpt-4o-mini
|
|
25
|
+
# LOOM_LLM_MODEL=anthropic/claude-3-haiku-20240307
|
|
26
|
+
LOOM_LLM_MODEL=
|
|
27
|
+
|
|
28
|
+
# ============================================================================
|
|
29
|
+
# Optional — Jira integration
|
|
30
|
+
# ============================================================================
|
|
31
|
+
|
|
32
|
+
LOOM_JIRA_URL=
|
|
33
|
+
LOOM_JIRA_EMAIL=
|
|
34
|
+
LOOM_JIRA_API_TOKEN=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Enforce LF line endings to keep ruff format --check consistent across OS
|
|
2
|
+
|
|
3
|
+
# Default to LF for all text
|
|
4
|
+
* text=auto eol=lf
|
|
5
|
+
|
|
6
|
+
# Explicit common text formats
|
|
7
|
+
*.py text eol=lf
|
|
8
|
+
*.pyi text eol=lf
|
|
9
|
+
*.md text eol=lf
|
|
10
|
+
*.yml text eol=lf
|
|
11
|
+
*.yaml text eol=lf
|
|
12
|
+
*.toml text eol=lf
|
|
13
|
+
*.ini text eol=lf
|
|
14
|
+
*.cfg text eol=lf
|
|
15
|
+
*.txt text eol=lf
|
|
16
|
+
*.json text eol=lf
|
|
17
|
+
*.sh text eol=lf
|
|
18
|
+
|
|
19
|
+
# Keep Windows scripts with CRLF if you add them later
|
|
20
|
+
*.bat text eol=crlf
|
|
21
|
+
*.cmd text eol=crlf
|
|
22
|
+
*.ps1 text eol=crlf
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a problem in Loom
|
|
4
|
+
title: "bug: "
|
|
5
|
+
labels: [bug]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What happened
|
|
9
|
+
|
|
10
|
+
## What you expected
|
|
11
|
+
|
|
12
|
+
## Steps to reproduce
|
|
13
|
+
|
|
14
|
+
## Environment
|
|
15
|
+
|
|
16
|
+
- OS:
|
|
17
|
+
- Python version:
|
|
18
|
+
- uv version:
|
|
19
|
+
- FalkorDB image/tag:
|
|
20
|
+
|
|
21
|
+
## Logs / output
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
(paste relevant output here)
|
|
25
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
timeout-minutes: 10
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
16
|
+
python-version: ['3.12']
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v4
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v3
|
|
28
|
+
with:
|
|
29
|
+
version: "latest"
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: |
|
|
33
|
+
uv sync --dev
|
|
34
|
+
|
|
35
|
+
- name: Run linting
|
|
36
|
+
run: |
|
|
37
|
+
uv run ruff check .
|
|
38
|
+
uv run mypy src/
|
|
39
|
+
|
|
40
|
+
- name: Check formatting
|
|
41
|
+
run: |
|
|
42
|
+
uv run ruff format --check .
|
|
43
|
+
|
|
44
|
+
- name: Run tests
|
|
45
|
+
run: |
|
|
46
|
+
if [ "${{ matrix.os }}" = "windows-latest" ]; then
|
|
47
|
+
uv run pytest tests/unit/ -v --tb=short
|
|
48
|
+
else
|
|
49
|
+
uv run pytest -v --tb=short
|
|
50
|
+
fi
|
|
51
|
+
shell: bash
|
|
52
|
+
|
|
53
|
+
- name: Test package build
|
|
54
|
+
run: |
|
|
55
|
+
uv build --wheel
|
|
56
|
+
uv pip install dist/*.whl
|
|
57
|
+
uv run loom --version
|
|
58
|
+
shell: bash
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Loom Full Index
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
loom-full-index:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v5
|
|
21
|
+
|
|
22
|
+
- name: Install Loom
|
|
23
|
+
run: |
|
|
24
|
+
uv sync
|
|
25
|
+
|
|
26
|
+
- name: Start FalkorDB
|
|
27
|
+
run: |
|
|
28
|
+
docker run -d -p 6379:6379 --name loom-db falkordb/falkordb
|
|
29
|
+
|
|
30
|
+
- name: Loom full index
|
|
31
|
+
run: |
|
|
32
|
+
uv run loom analyze . \
|
|
33
|
+
--graph-name "${{ github.repository }}" \
|
|
34
|
+
--force
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Loom Incremental Sync
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
loom-sync:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
with:
|
|
13
|
+
fetch-depth: 2
|
|
14
|
+
|
|
15
|
+
- name: Set up Python
|
|
16
|
+
uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v5
|
|
22
|
+
|
|
23
|
+
- name: Install Loom
|
|
24
|
+
run: |
|
|
25
|
+
uv sync
|
|
26
|
+
|
|
27
|
+
- name: Start FalkorDB
|
|
28
|
+
run: |
|
|
29
|
+
docker run -d -p 6379:6379 --name loom-db falkordb/falkordb
|
|
30
|
+
|
|
31
|
+
- name: Loom incremental sync
|
|
32
|
+
run: |
|
|
33
|
+
uv run loom sync \
|
|
34
|
+
--old-sha "${{ github.event.before }}" \
|
|
35
|
+
--new-sha "${{ github.sha }}" \
|
|
36
|
+
--graph-name "${{ github.repository }}" \
|
|
37
|
+
--repo-path .
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*'
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v4
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v3
|
|
27
|
+
with:
|
|
28
|
+
version: "latest"
|
|
29
|
+
|
|
30
|
+
- name: Build package
|
|
31
|
+
run: |
|
|
32
|
+
uv build
|
|
33
|
+
|
|
34
|
+
- name: Check package
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
python -m pip install twine
|
|
38
|
+
python -m twine check dist/*
|
|
39
|
+
|
|
40
|
+
- name: Publish to PyPI
|
|
41
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Vector index DDL correctness and schema init error visibility
|
|
12
|
+
- Embedding persistence via `vecf32()` for FalkorDB `VECTOR` type
|
|
13
|
+
- Lexical context in `loom calls` (parents/children via `CONTAINS` edges)
|
|
14
|
+
- Graph expansion includes `CONTAINS` edges in search
|
|
15
|
+
- CLI ambiguity handling for `loom calls` target resolution
|
|
16
|
+
- Comprehensive unit tests for vector indexing and embedding storage
|
|
17
|
+
- QA diagnostic script for DB-level vector query validation
|
|
18
|
+
- Open-source readiness: LICENSE (MIT), CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, GitHub templates, CI
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- Vector index never created due to DDL syntax errors
|
|
22
|
+
- `loom query` always falling back to brute-force vector search
|
|
23
|
+
- Ambiguous names in `loom calls` failing with generic “Target not found”
|
|
24
|
+
|
|
25
|
+
## [0.1.0] - 2026-03-09
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Initial release of Loom
|
|
29
|
+
- Repository indexing into FalkorDB graph
|
|
30
|
+
- Multi-language code understanding (Python, TS/JS, Java, Go, Rust, Ruby, markup)
|
|
31
|
+
- Call graph extraction
|
|
32
|
+
- Document ingestion (Markdown, PDF)
|
|
33
|
+
- Jira and traceability workflows
|
|
34
|
+
- Semantic linking (name match, embedding match, LLM match)
|
|
35
|
+
- Incremental sync and watch mode
|
|
36
|
+
- Semantic search with query-time graph expansion
|
|
37
|
+
- MCP server for editor/agent integration
|
|
38
|
+
- CLI commands: analyze, enrich, query, trace, calls, entrypoints, watch, sync, serve
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Release process
|
|
43
|
+
|
|
44
|
+
1. Update version in `pyproject.toml`
|
|
45
|
+
2. Add a new section to `CHANGELOG.md` under `[Unreleased]`
|
|
46
|
+
3. Commit and push
|
|
47
|
+
4. Create a GitHub Release with the changelog for that version
|
|
48
|
+
5. Tag the release: `git tag v0.1.0 && git push --tags`
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Loom — Claude Code Context
|
|
2
|
+
|
|
3
|
+
This file tells Claude Code everything it needs to know to work effectively in this repo.
|
|
4
|
+
Read this before touching any file.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What this project is
|
|
9
|
+
|
|
10
|
+
Loom is a **unified code + document knowledge graph**. It reads a codebase (via tree-sitter AST parsing) and documentation files (PDFs, DOCX, Markdown, Confluence) and stores everything as nodes and edges in FalkorDB — a graph database.
|
|
11
|
+
|
|
12
|
+
The key innovation: **code symbols and document sections are the same node type**, connected by semantic edges (`IMPLEMENTS`, `SPECIFIES`, `VIOLATES`). This enables queries like "does checkout_flow() satisfy PCI-DSS §3.4?" — something no existing tool can answer.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Architecture — read this first
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
src/loom/
|
|
20
|
+
├── core/ ← START HERE. Node, Edge, Graph. Every module uses these.
|
|
21
|
+
├── ingest/ ← Source connectors. Code repos + doc files → raw data.
|
|
22
|
+
├── analysis/ ← Intelligence. AST parsing, call tracing, communities, summaries.
|
|
23
|
+
├── embed/ ← nomic-embed-text (unified embedding space for code AND docs).
|
|
24
|
+
├── linker/ ← THE CORE INNOVATION. Creates IMPLEMENTS edges between code+docs.
|
|
25
|
+
├── search/ ← Dual-traversal search across code graph + doc tree.
|
|
26
|
+
├── watch/ ← watchfiles-based incremental re-indexer.
|
|
27
|
+
├── drift/ ← Detects spec violations when code changes.
|
|
28
|
+
├── llm/ ← LiteLLM wrapper. Routes to Ollama, OpenAI, Groq etc.
|
|
29
|
+
└── mcp/ ← FastMCP server. 5 tools for Claude Code/Cursor/Copilot.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Dependency flow:** `core` ← `ingest` ← `analysis` ← `embed` ← `linker` ← `search/watch/drift` ← `mcp`
|
|
33
|
+
|
|
34
|
+
Never import from a downstream module into an upstream one. `core` has zero internal imports.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The data model — understand this deeply
|
|
39
|
+
|
|
40
|
+
Everything is a `Node` or an `Edge`. That's it.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
# A function in code:
|
|
44
|
+
Node(id="function:src/auth.py:validate_user", kind=NodeKind.FUNCTION, source=NodeSource.CODE, ...)
|
|
45
|
+
|
|
46
|
+
# A section in a spec document:
|
|
47
|
+
Node(id="doc:specs/auth.pdf:3.2.4", kind=NodeKind.SECTION, source=NodeSource.DOC, ...)
|
|
48
|
+
|
|
49
|
+
# The link between them (created by SemanticLinker):
|
|
50
|
+
Edge(from_id="function:src/auth.py:validate_user",
|
|
51
|
+
to_id="doc:specs/auth.pdf:3.2.4",
|
|
52
|
+
kind=EdgeType.LOOM_IMPLEMENTS,
|
|
53
|
+
confidence=0.87,
|
|
54
|
+
link_method="embed_match")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Node ID convention — never break this:**
|
|
58
|
+
- Code: `"{kind}:{file_path}:{symbol_name}"` → `"function:src/auth.py:validate_user"`
|
|
59
|
+
- Doc: `"doc:{doc_path}:{section_id}"` → `"doc:specs/auth.pdf:chapter_3.2.4"`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Tech stack — key decisions
|
|
64
|
+
|
|
65
|
+
| What | Tool | Why it matters |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Graph DB | FalkorDB | Redis-based. Run: `docker compose up -d`. Port 6379. |
|
|
68
|
+
| Embeddings | fastembed + nomic-embed-text-v1.5 | Local ONNX, no API key, 768-dim, works for both code and prose |
|
|
69
|
+
| LLM | LiteLLM | `LOOM_LLM_MODEL=ollama/llama3.2` for local/free, `gpt-4o-mini` for fast |
|
|
70
|
+
| Code parsing | tree-sitter | AST-based. Never use regex to parse code. |
|
|
71
|
+
| Async | asyncio + winloop (Windows) / uvloop (Linux/Mac) | See platform check in `src/loom/__init__.py` |
|
|
72
|
+
| Communities | igraph + leidenalg | Leiden algorithm on the call graph |
|
|
73
|
+
| File watching | watchfiles | Rust-based, 500ms debounce |
|
|
74
|
+
| MCP | FastMCP | `@mcp.tool()` decorator pattern |
|
|
75
|
+
|
|
76
|
+
**Windows note:** uvloop doesn't support Windows. We use winloop instead. The platform check in `config.py` handles this automatically — don't remove it.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Environment setup
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# 1. Install dependencies
|
|
84
|
+
uv sync
|
|
85
|
+
|
|
86
|
+
# 2. Start FalkorDB
|
|
87
|
+
docker compose up -d
|
|
88
|
+
|
|
89
|
+
# 3. Copy env file
|
|
90
|
+
cp .env.example .env
|
|
91
|
+
|
|
92
|
+
# 4. Set your LLM (use Ollama for free local inference):
|
|
93
|
+
# LOOM_LLM_MODEL=ollama/llama3.2
|
|
94
|
+
# or:
|
|
95
|
+
# LOOM_LLM_MODEL=gpt-4o-mini
|
|
96
|
+
# LOOM_LLM_API_KEY=sk-...
|
|
97
|
+
|
|
98
|
+
# 5. Run tests
|
|
99
|
+
uv run pytest
|
|
100
|
+
|
|
101
|
+
# 6. Verify graph connection
|
|
102
|
+
uv run python scripts/check_env.py
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Running Loom
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Index a repo
|
|
111
|
+
uv run loom analyze /path/to/repo --docs /path/to/docs
|
|
112
|
+
|
|
113
|
+
# Query
|
|
114
|
+
uv run loom query "how does authentication work?"
|
|
115
|
+
|
|
116
|
+
# Start MCP server
|
|
117
|
+
uv run loom serve
|
|
118
|
+
|
|
119
|
+
# Watch mode
|
|
120
|
+
uv run loom watch /path/to/repo
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Coding conventions
|
|
126
|
+
|
|
127
|
+
**Async everywhere.** All I/O — graph queries, LLM calls, file reads — must be async. Use `asyncio.gather()` for concurrent operations. Never `time.sleep()` — always `await asyncio.sleep()`.
|
|
128
|
+
|
|
129
|
+
**Semaphore for LLM calls.** Always wrap concurrent LLM calls with a semaphore:
|
|
130
|
+
```python
|
|
131
|
+
sem = asyncio.Semaphore(10)
|
|
132
|
+
async def call_with_limit(prompt):
|
|
133
|
+
async with sem:
|
|
134
|
+
return await llm.complete(prompt)
|
|
135
|
+
results = await asyncio.gather(*[call_with_limit(p) for p in prompts])
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**MERGE not CREATE in FalkorDB.** Re-indexing must be idempotent. Always:
|
|
139
|
+
```cypher
|
|
140
|
+
MERGE (n:Node {id: $id}) SET n += $props
|
|
141
|
+
```
|
|
142
|
+
Never `CREATE` a node directly — it will create duplicates on re-index.
|
|
143
|
+
|
|
144
|
+
**Bulk over N+1.** Never loop individual FalkorDB inserts. Always `UNWIND`:
|
|
145
|
+
```python
|
|
146
|
+
graph.query("UNWIND $nodes AS n MERGE (node:Node {id: n.id}) SET node += n",
|
|
147
|
+
{"nodes": [n.model_dump() for n in nodes]})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**LiteLLM for all LLM calls.** Never call OpenAI/Anthropic SDKs directly. Always go through `src/loom/llm/client.py` which wraps LiteLLM. This ensures Ollama/Groq/OpenAI all work with one config change.
|
|
151
|
+
|
|
152
|
+
**Pydantic v2.** All data models use Pydantic v2 `BaseModel`. Use `model_dump()` and `model_validate()`. Never use `.dict()` (v1 API).
|
|
153
|
+
|
|
154
|
+
**Type hints everywhere.** Every function must have complete type hints. `mypy --strict` must pass.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Testing
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
uv run pytest # all tests
|
|
162
|
+
uv run pytest tests/unit/ # unit tests only (no DB needed)
|
|
163
|
+
uv run pytest tests/integration/ # integration tests (requires Docker)
|
|
164
|
+
uv run pytest --cov=loom # with coverage
|
|
165
|
+
uv run pytest -k "test_node" # specific test
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Test fixtures are in `tests/fixtures/`.**
|
|
169
|
+
- `sample_graph.py` — 15 nodes, 20 edges, a realistic auth module. Reuse this everywhere.
|
|
170
|
+
- `sample_repo/auth.py` — the Python file the parser tests run against.
|
|
171
|
+
- `sample_docs/sample_spec.pdf` — the PDF the doc pipeline tests run against.
|
|
172
|
+
|
|
173
|
+
**Integration tests require FalkorDB running.** They're marked with `@pytest.mark.integration` and skipped if the DB is unreachable.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Current sprint: Sprint 1 — Graph Foundation
|
|
178
|
+
|
|
179
|
+
**What we're building right now:**
|
|
180
|
+
|
|
181
|
+
| Ticket | File | Status |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| LOOM-001 | Project init | ✅ Done |
|
|
184
|
+
| LOOM-002 | Dependencies + env | ✅ Done |
|
|
185
|
+
| LOOM-003 | `src/loom/core/node.py` | 🔄 In progress |
|
|
186
|
+
| LOOM-004 | `src/loom/core/edge.py` | ⬜ Todo |
|
|
187
|
+
| LOOM-005 | `src/loom/core/graph.py` | ⬜ Todo |
|
|
188
|
+
| LOOM-006 | `src/loom/core/schema.py` | ⬜ Todo |
|
|
189
|
+
| LOOM-007 | E2E test | ⬜ Todo |
|
|
190
|
+
|
|
191
|
+
**Sprint goal:** `pytest tests/integration/test_graph_e2e.py` passes cleanly.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## What NOT to do
|
|
196
|
+
|
|
197
|
+
- **Don't use regex to parse code.** tree-sitter exists for this. Regex breaks on nested structures.
|
|
198
|
+
- **Don't call LLM APIs directly.** Always use `src/loom/llm/client.py`.
|
|
199
|
+
- **Don't touch FalkorDB directly** outside of `src/loom/core/graph.py`. All DB access through `LoomGraph`.
|
|
200
|
+
- **Don't create duplicate node IDs.** The ID convention is strict — use `MERGE`.
|
|
201
|
+
- **Don't add uvloop directly on Windows.** Use the platform check in config.
|
|
202
|
+
- **Don't run LLM calls sequentially in a loop.** Always `asyncio.gather()` with semaphore.
|
|
203
|
+
- **Don't hardcode the LLM model.** Always read from config/env.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Key algorithms (planned for v0.2+)
|
|
208
|
+
|
|
209
|
+
These are NOT implemented yet but are planned. Don't implement them in v0.1:
|
|
210
|
+
|
|
211
|
+
- **Personalized PageRank** (igraph) — for impact scoring instead of BFS
|
|
212
|
+
- **Cross-encoder reranking** (sentence-transformers) — for better linker precision
|
|
213
|
+
- **GumTree AST diffing** — for precise drift detection
|
|
214
|
+
- **RAPTOR hierarchical summaries** — for multi-level doc intelligence
|
|
215
|
+
- **HippoRAG search** — PPR-based retrieval over the unified graph
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Getting help
|
|
220
|
+
|
|
221
|
+
- Architecture decisions → see `docs/architecture.md`
|
|
222
|
+
- Ticket details → GitHub Issues (LOOM-XXX labels)
|
|
223
|
+
- Graph queries → see `docs/cypher-examples.md`
|
|
224
|
+
- LLM prompts used in the linker → see `src/loom/linker/prompts.py`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We pledge to make participation in this project a harassment-free experience for everyone.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
Examples of behavior that contributes to a positive environment include:
|
|
10
|
+
|
|
11
|
+
- Using welcoming and inclusive language
|
|
12
|
+
- Being respectful of differing viewpoints and experiences
|
|
13
|
+
- Gracefully accepting constructive criticism
|
|
14
|
+
|
|
15
|
+
Examples of unacceptable behavior include:
|
|
16
|
+
|
|
17
|
+
- Harassment, discrimination, or insulting/derogatory comments
|
|
18
|
+
- Trolling or personal attacks
|
|
19
|
+
|
|
20
|
+
## Enforcement
|
|
21
|
+
|
|
22
|
+
Project maintainers are responsible for clarifying standards and taking appropriate action.
|
|
23
|
+
|
|
24
|
+
## Scope
|
|
25
|
+
|
|
26
|
+
This Code of Conduct applies within project spaces and in public spaces when representing the project.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing to Loom.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
### Requirements
|
|
8
|
+
|
|
9
|
+
- Python 3.12+
|
|
10
|
+
- uv
|
|
11
|
+
- Docker (for FalkorDB)
|
|
12
|
+
|
|
13
|
+
### Setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv sync
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Start FalkorDB:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
docker run -d -p 6379:6379 --name loom-db falkordb/falkordb
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Run tests:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv run pytest -q
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Pull requests
|
|
32
|
+
|
|
33
|
+
- Keep changes focused and incremental.
|
|
34
|
+
- Add or update tests for behavioral changes.
|
|
35
|
+
- Run the test suite before submitting.
|
|
36
|
+
|
|
37
|
+
## Reporting bugs
|
|
38
|
+
|
|
39
|
+
Please include:
|
|
40
|
+
|
|
41
|
+
- What you expected vs what happened
|
|
42
|
+
- Your OS and Python version
|
|
43
|
+
- Loom commands run (and relevant logs)
|
|
44
|
+
- FalkorDB version (Docker image tag)
|
loom_tool-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Devashish
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|