From 28fad1b248d5c78f2196b5199a9ae0800dec2b89 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 15 May 2026 21:16:34 +0200 Subject: [PATCH] Finalize repo-scoping runtime rename --- AGENTS.md | 4 +- CLAUDE.md | 34 +++---- INTENT.md | 12 +-- Makefile | 2 +- README.md | 19 ++-- SCOPE.md | 12 +-- docs/operations.md | 30 +++--- .../self-scoping-assessment.schema.json | 2 +- .../repo-scoping-golden-profile.v1.json | 68 ++++++------- docs/semantic-retrieval.md | 2 +- docs/terminology.md | 8 +- pyproject.toml | 4 +- src/repo_scoping/acceptance/__init__.py | 6 +- src/repo_scoping/acceptance/agentic.py | 4 +- src/repo_scoping/acceptance/gates.py | 4 +- src/repo_scoping/candidate_graph/generator.py | 56 +++++------ .../candidate_graph/normalization.py | 4 +- src/repo_scoping/cli.py | 34 +++---- src/repo_scoping/content_indexing/__init__.py | 2 +- .../content_indexing/extractor.py | 2 +- src/repo_scoping/core/logging.py | 2 +- src/repo_scoping/core/service.py | 26 ++--- src/repo_scoping/llm_extraction/__init__.py | 4 +- src/repo_scoping/llm_extraction/extractor.py | 2 +- src/repo_scoping/llm_extraction/mapper.py | 6 +- src/repo_scoping/repo_ingestion/metadata.py | 19 +++- src/repo_scoping/scope/__init__.py | 4 +- src/repo_scoping/scope/generator.py | 4 +- src/repo_scoping/scope/validator.py | 2 +- src/repo_scoping/self_scoping/__init__.py | 6 +- src/repo_scoping/self_scoping/assessment.py | 8 +- src/repo_scoping/self_scoping/review_store.py | 2 +- src/repo_scoping/semantic/__init__.py | 2 +- src/repo_scoping/storage/sqlite.py | 10 +- src/repo_scoping/web_api/app.py | 24 ++--- src/repo_scoping/web_ui/views.py | 12 +-- tests/test_acceptance_boundary.py | 8 +- tests/test_agentic_review.py | 8 +- tests/test_candidate_graph.py | 12 +-- tests/test_candidate_normalization.py | 6 +- tests/test_cli.py | 8 +- tests/test_content_indexing.py | 4 +- tests/test_git_ingestion.py | 2 +- tests/test_intent_bootstrap.py | 2 +- tests/test_llm_extraction.py | 4 +- tests/test_llm_extraction_mapper.py | 4 +- tests/test_quality_criteria.py | 2 +- tests/test_quality_gates.py | 10 +- tests/test_registry_service.py | 14 +-- tests/test_repository_metadata.py | 40 +++++++- tests/test_repository_scanner.py | 2 +- tests/test_scanner_coevolution.py | 6 +- tests/test_scope_context_api.py | 2 +- tests/test_scope_generator.py | 18 ++-- tests/test_self_scoping_assessment_export.py | 8 +- tests/test_self_scoping_comparison.py | 2 +- tests/test_self_scoping_review_store.py | 2 +- tests/test_self_scoping_web_ui.py | 10 +- tests/test_storage_migrations.py | 6 +- tests/test_trusted_auto_approval_migration.py | 6 +- tests/test_web_api.py | 24 ++--- ...EG-WP-0017-finalize-repo-scoping-rename.md | 98 +++++++++++++++++++ 62 files changed, 445 insertions(+), 305 deletions(-) create mode 100644 workplans/RREG-WP-0017-finalize-repo-scoping-rename.md diff --git a/AGENTS.md b/AGENTS.md index 39b26cb..c41d6cf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Repo Identity -**Purpose:** Repository Ability Registry — turns Git repositories into reviewable, +**Purpose:** Repository Scoping — turns Git repositories into reviewable, source-linked maps of `Ability → Capability → Feature → Evidence`. Deterministic scanners establish observed facts; LLM-assisted extractors propose interpreted claims; humans or trusted agents approve registry truth. @@ -154,7 +154,7 @@ Task description. pip install -e ".[dev]" # Run dev server -uvicorn src.repo_registry.app:app --reload +uvicorn repo_scoping.web_api.app:app --reload # Run tests pytest tests/ diff --git a/CLAUDE.md b/CLAUDE.md index c40214a..f54d6be 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co pip install -e ".[dev]" # Run dev server (port 8001) -uvicorn repo_registry.web_api.app:app --reload --port 8001 +uvicorn repo_scoping.web_api.app:app --reload --port 8001 # Run tests pytest @@ -20,8 +20,6 @@ pytest tests/test_web_api.py # single file curl http://127.0.0.1:8001/health ``` -Note: `AGENTS.md` shows `src.repo_registry.app:app` but the correct module path is `repo_registry.web_api.app:app` (as installed via `src/`). - ## Architecture The service maps Git repositories to reviewable scope maps using a fixed hierarchy: @@ -38,7 +36,7 @@ Scope → Ability → Capability → Feature → Evidence → ObservedFact 4. `DeterministicScanner` produces `ObservedFact` objects (files, languages, manifests, APIs, etc.) 5. `ContentExtractor` chunks files into searchable segments 6. `CandidateGraphGenerator` builds a draft ability→capability→feature→evidence tree from facts -7. Optionally, `LLMCandidateExtractor` proposes additional candidates (requires `REPO_REGISTRY_LLM_ENABLED=true`) +7. Optionally, `LLMCandidateExtractor` proposes additional candidates (requires `REPO_SCOPING_LLM_ENABLED=true`) 8. Candidates are stored; humans or agents review them via `POST .../candidate-graph/approve` 9. Approved characteristics feed `ScopeGenerator` to produce `SCOPE.md` @@ -46,17 +44,17 @@ Scope → Ability → Capability → Feature → Evidence → ObservedFact | Component | Path | |-----------|------| -| FastAPI routes + DI | `src/repo_registry/web_api/app.py` | -| Orchestration | `src/repo_registry/core/service.py` | -| Frozen dataclasses | `src/repo_registry/core/models.py` | -| Deterministic scanner | `src/repo_registry/repo_scanning/scanner.py` | -| Candidate graph builder | `src/repo_registry/candidate_graph/generator.py` | -| SQLite store | `src/repo_registry/storage/sqlite.py` | +| FastAPI routes + DI | `src/repo_scoping/web_api/app.py` | +| Orchestration | `src/repo_scoping/core/service.py` | +| Frozen dataclasses | `src/repo_scoping/core/models.py` | +| Deterministic scanner | `src/repo_scoping/repo_scanning/scanner.py` | +| Candidate graph builder | `src/repo_scoping/candidate_graph/generator.py` | +| SQLite store | `src/repo_scoping/storage/sqlite.py` | | Schema migration | `migrations/0001_initial.sql` | -**Storage:** SQLite at `var/repo-registry.sqlite3` (auto-created). Schema migrations run at startup. Dynamic columns are added to support evidence relationships, classification, and expectation gaps. +**Storage:** SQLite at `var/repo-scoping.sqlite3` (auto-created). Schema migrations run at startup. Dynamic columns are added to support evidence relationships, classification, and expectation gaps. -**LLM extraction** is optional and disabled by default. Enable with `REPO_REGISTRY_LLM_ENABLED=true` plus `REPO_REGISTRY_LLM_PROVIDER` and `REPO_REGISTRY_LLM_MODEL`. The `llm-connect` sibling package provides the adapter abstraction. +**LLM extraction** is optional and disabled by default. Enable with `REPO_SCOPING_LLM_ENABLED=true` plus `REPO_SCOPING_LLM_PROVIDER` and `REPO_SCOPING_LLM_MODEL`. The `llm-connect` sibling package provides the adapter abstraction. **Semantic search** uses `HashingEmbeddingProvider` by default — deterministic, no external service required. @@ -64,12 +62,12 @@ Scope → Ability → Capability → Feature → Evidence → ObservedFact | Variable | Default | Purpose | |----------|---------|---------| -| `REPO_REGISTRY_DATABASE_PATH` | `var/repo-registry.sqlite3` | SQLite file | -| `REPO_REGISTRY_CHECKOUT_ROOT` | `var/checkouts` | Git clone cache | -| `REPO_REGISTRY_LLM_ENABLED` | `true` | Enable LLM extraction | -| `REPO_REGISTRY_LLM_PROVIDER` | — | e.g. `gemini`, `anthropic` | -| `REPO_REGISTRY_LLM_MODEL` | — | e.g. `gemini-2.5-flash` | -| `REPO_REGISTRY_STATE_HUB_BASE_URL` | `http://127.0.0.1:8000` | State Hub for coordination | +| `REPO_SCOPING_DATABASE_PATH` | `var/repo-scoping.sqlite3` | SQLite file | +| `REPO_SCOPING_CHECKOUT_ROOT` | `var/checkouts` | Git clone cache | +| `REPO_SCOPING_LLM_ENABLED` | `true` | Enable LLM extraction | +| `REPO_SCOPING_LLM_PROVIDER` | — | e.g. `gemini`, `anthropic` | +| `REPO_SCOPING_LLM_MODEL` | — | e.g. `gemini-2.5-flash` | +| `REPO_SCOPING_STATE_HUB_BASE_URL` | `http://127.0.0.1:8000` | State Hub for coordination | ## State Hub & Workplans diff --git a/INTENT.md b/INTENT.md index 216ade0..77e993f 100644 --- a/INTENT.md +++ b/INTENT.md @@ -136,11 +136,11 @@ characteristics support those claims. ## Getting Oriented - Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`. -- Key files / directories: `src/repo_registry/web_api/app.py`, - `src/repo_registry/core/service.py`, `src/repo_registry/scope/`, - `src/repo_registry/candidate_graph/`, `src/repo_registry/repo_scanning/`, +- Key files / directories: `src/repo_scoping/web_api/app.py`, + `src/repo_scoping/core/service.py`, `src/repo_scoping/scope/`, + `src/repo_scoping/candidate_graph/`, `src/repo_scoping/repo_scanning/`, `docs/scope-md-spec.md`, and `workplans/`. -- Entry points: `uvicorn repo_registry.web_api.app:app --reload`, the `/ui` +- Entry points: `uvicorn repo_scoping.web_api.app:app --reload`, the `/ui` routes, and the `/repos/{repo_slug}/scope*` API endpoints. --- @@ -171,5 +171,5 @@ keywords: [scope, scope-md, update, diff, staleness] - The product and managed repository identity are Repository Scoping / `repo-scoping`. -- The Python package name `repo_registry`, `REPO_REGISTRY_` environment prefix, - and default SQLite filename remain compatibility details. +- The Python package name `repo_scoping`, `REPO_SCOPING_` environment prefix, + and default SQLite filename are the current runtime names. diff --git a/Makefile b/Makefile index 4acb0d9..e1188b2 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ start: ## Start the API server in the background on port 8002 @if [ -f $(PIDFILE) ] && kill -0 $$(cat $(PIDFILE)) 2>/dev/null; then \ echo "Already running (PID $$(cat $(PIDFILE)))"; \ else \ - setsid sh -c 'echo $$$$ > $(PIDFILE); exec $(UVICORN) repo_registry.web_api.app:app --host 127.0.0.1 --port $(PORT)' \ + setsid sh -c 'echo $$$$ > $(PIDFILE); exec $(UVICORN) repo_scoping.web_api.app:app --host 127.0.0.1 --port $(PORT)' \ >> $(LOGFILE) 2>&1 & \ PID=""; \ for i in $$(seq 1 50); do \ diff --git a/README.md b/README.md index 5bf46a5..73eede2 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,12 @@ pytest Run the API: ```bash -uvicorn repo_registry.web_api.app:app --reload +uvicorn repo_scoping.web_api.app:app --reload ``` -The API creates a local SQLite database at `var/repo-registry.sqlite3` by default. The database path, `REPO_REGISTRY_` environment prefix, and `repo_registry` Python package name remain compatibility details after the product rename to Repository Scoping. +The API creates a local SQLite database at `var/repo-scoping.sqlite3` by +default. Runtime configuration uses the `REPO_SCOPING_` environment prefix, and +the Python package is `repo_scoping`. ## First API Loop @@ -40,7 +42,10 @@ curl -X POST http://127.0.0.1:8000/repos \ -d '{"url":"https://example.com/mail-router.git"}' ``` -The registry imports name and description from `pyproject.toml`, `package.json`, or README where possible. Then add abilities, capabilities, features, and evidence under that repository and inspect: +The registry uses the submitted repository path or URL as the default name, then +imports description and fallback metadata from `pyproject.toml`, `package.json`, +or README where possible. Then add abilities, capabilities, features, and +evidence under that repository and inspect: ```bash curl http://127.0.0.1:8000/repos/1/ability-map @@ -135,17 +140,17 @@ draft. The FastAPI settings object also accepts `llm_provider` and `llm_model`. By default `llm_provider` is unset, so analysis is fully offline and deterministic. -Environment variables use the `REPO_REGISTRY_` prefix: +Environment variables use the `REPO_SCOPING_` prefix: ```bash -REPO_REGISTRY_LLM_PROVIDER=gemini -REPO_REGISTRY_LLM_MODEL=gemini-2.5-flash +REPO_SCOPING_LLM_PROVIDER=gemini +REPO_SCOPING_LLM_MODEL=gemini-2.5-flash ``` LLM assistance can also be disabled even when a provider is configured: ```bash -REPO_REGISTRY_LLM_ENABLED=false +REPO_SCOPING_LLM_ENABLED=false ``` Individual analysis requests may opt out with `{"use_llm_assistance": false}`. diff --git a/SCOPE.md b/SCOPE.md index 216ade0..77e993f 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -136,11 +136,11 @@ characteristics support those claims. ## Getting Oriented - Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`. -- Key files / directories: `src/repo_registry/web_api/app.py`, - `src/repo_registry/core/service.py`, `src/repo_registry/scope/`, - `src/repo_registry/candidate_graph/`, `src/repo_registry/repo_scanning/`, +- Key files / directories: `src/repo_scoping/web_api/app.py`, + `src/repo_scoping/core/service.py`, `src/repo_scoping/scope/`, + `src/repo_scoping/candidate_graph/`, `src/repo_scoping/repo_scanning/`, `docs/scope-md-spec.md`, and `workplans/`. -- Entry points: `uvicorn repo_registry.web_api.app:app --reload`, the `/ui` +- Entry points: `uvicorn repo_scoping.web_api.app:app --reload`, the `/ui` routes, and the `/repos/{repo_slug}/scope*` API endpoints. --- @@ -171,5 +171,5 @@ keywords: [scope, scope-md, update, diff, staleness] - The product and managed repository identity are Repository Scoping / `repo-scoping`. -- The Python package name `repo_registry`, `REPO_REGISTRY_` environment prefix, - and default SQLite filename remain compatibility details. +- The Python package name `repo_scoping`, `REPO_SCOPING_` environment prefix, + and default SQLite filename are the current runtime names. diff --git a/docs/operations.md b/docs/operations.md index d71358b..aac25bc 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -5,18 +5,18 @@ Repository Scoping service. ## Configuration -Configuration is read from environment variables with the `REPO_REGISTRY_` -prefix. That prefix is retained as an implementation compatibility detail after -the product rename from Repository Ability Registry to Repository Scoping. +Configuration is read from environment variables with the `REPO_SCOPING_` +prefix. The same naming is used by the import package and default local +database path so service identity stays aligned with Repository Scoping. | Variable | Default | Purpose | | --- | --- | --- | -| `REPO_REGISTRY_DATABASE_PATH` | `var/repo-registry.sqlite3` | SQLite database file used by the default store. | -| `REPO_REGISTRY_CHECKOUT_ROOT` | `var/checkouts` | Local checkout cache used during repository ingestion. | -| `REPO_REGISTRY_LLM_PROVIDER` | unset | Optional LLM provider name for candidate extraction. | -| `REPO_REGISTRY_LLM_MODEL` | unset | Optional model name passed to the configured LLM provider. | -| `REPO_REGISTRY_EMBEDDING_PROVIDER` | unset | Set to `hashing` to enable deterministic local hybrid search scoring. | -| `REPO_REGISTRY_LOG_LEVEL` | `INFO` | Log level for the `repo_registry.operations` structured event logger. | +| `REPO_SCOPING_DATABASE_PATH` | `var/repo-scoping.sqlite3` | SQLite database file used by the default store. | +| `REPO_SCOPING_CHECKOUT_ROOT` | `var/checkouts` | Local checkout cache used during repository ingestion. | +| `REPO_SCOPING_LLM_PROVIDER` | unset | Optional LLM provider name for candidate extraction. | +| `REPO_SCOPING_LLM_MODEL` | unset | Optional model name passed to the configured LLM provider. | +| `REPO_SCOPING_EMBEDDING_PROVIDER` | unset | Set to `hashing` to enable deterministic local hybrid search scoring. | +| `REPO_SCOPING_LOG_LEVEL` | `INFO` | Log level for the `repo_scoping.operations` structured event logger. | ## Health Checks @@ -27,7 +27,7 @@ be checked locally: { "status": "ok", "database": { - "path": "var/repo-registry.sqlite3", + "path": "var/repo-scoping.sqlite3", "reachable": true, "error": null }, @@ -44,13 +44,13 @@ ingestion path. ## Structured Logs -Operational events are emitted through the `repo_registry.operations` logger as +Operational events are emitted through the `repo_scoping.operations` logger as single-line JSON messages. Current events include repository registration, analysis start/completion/failure, LLM extraction usage/failure, and review decisions. Configure the Python or ASGI server logging stack to route this logger to the -same sink as application logs. `REPO_REGISTRY_LOG_LEVEL` controls the logger +same sink as application logs. `REPO_SCOPING_LOG_LEVEL` controls the logger level used by API-created service instances. ## SQLite Backup And Restore @@ -60,18 +60,18 @@ continue while the backup is created: ```bash mkdir -p backups -sqlite3 var/repo-registry.sqlite3 ".backup 'backups/repo-registry-$(date +%F).sqlite3'" +sqlite3 var/repo-scoping.sqlite3 ".backup 'backups/repo-scoping-$(date +%F).sqlite3'" ``` For the most conservative backup window, stop writes first, run the backup, then resume the service. Verify a backup with: ```bash -sqlite3 backups/repo-registry-YYYY-MM-DD.sqlite3 "PRAGMA integrity_check;" +sqlite3 backups/repo-scoping-YYYY-MM-DD.sqlite3 "PRAGMA integrity_check;" ``` To restore, stop the service, move the current database aside, copy the backup to -`REPO_REGISTRY_DATABASE_PATH`, start the service, and verify `GET /health`. +`REPO_SCOPING_DATABASE_PATH`, start the service, and verify `GET /health`. ## PostgreSQL Migration Notes diff --git a/docs/schemas/self-scoping-assessment.schema.json b/docs/schemas/self-scoping-assessment.schema.json index 1348219..368e757 100644 --- a/docs/schemas/self-scoping-assessment.schema.json +++ b/docs/schemas/self-scoping-assessment.schema.json @@ -586,7 +586,7 @@ }, "contamination_sources": [ { - "path": "src/repo_registry/repo_scanning/scanner.py", + "path": "src/repo_scoping/repo_scanning/scanner.py", "reason": "Scanner rule vocabulary was treated as repo-owned capability evidence." } ] diff --git a/docs/self-scoping/golden/repo-scoping-golden-profile.v1.json b/docs/self-scoping/golden/repo-scoping-golden-profile.v1.json index 58bb3a3..e719511 100644 --- a/docs/self-scoping/golden/repo-scoping-golden-profile.v1.json +++ b/docs/self-scoping/golden/repo-scoping-golden-profile.v1.json @@ -29,16 +29,16 @@ "name": "Create and update repository records", "primary_class": "api", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/web_api/app.py", - "src/repo_registry/web_ui/views.py" + "src/repo_scoping/core/service.py", + "src/repo_scoping/web_api/app.py", + "src/repo_scoping/web_ui/views.py" ] }, { "name": "Resolve local or remote Git checkouts", "primary_class": "backend", "source_paths": [ - "src/repo_registry/repo_ingestion/git.py", + "src/repo_scoping/repo_ingestion/git.py", "tests/test_git_ingestion.py" ] }, @@ -46,7 +46,7 @@ "name": "Import repository metadata", "primary_class": "backend", "source_paths": [ - "src/repo_registry/repo_ingestion/metadata.py", + "src/repo_scoping/repo_ingestion/metadata.py", "tests/test_repository_metadata.py" ] } @@ -61,7 +61,7 @@ "name": "Detect source languages, manifests, docs, tests, config, and interfaces", "primary_class": "backend", "source_paths": [ - "src/repo_registry/repo_scanning/scanner.py", + "src/repo_scoping/repo_scanning/scanner.py", "tests/test_repository_scanner.py" ] }, @@ -69,7 +69,7 @@ "name": "Classify source roles for facts", "primary_class": "backend", "source_paths": [ - "src/repo_registry/repo_scanning/scanner.py", + "src/repo_scoping/repo_scanning/scanner.py", "docs/characteristic-evidence-model.md" ] }, @@ -77,7 +77,7 @@ "name": "Preserve analysis snapshots and fact records", "primary_class": "storage", "source_paths": [ - "src/repo_registry/storage/sqlite.py", + "src/repo_scoping/storage/sqlite.py", "migrations/0001_initial.sql" ] } @@ -92,7 +92,7 @@ "name": "Create source-linked content chunks from observed facts", "primary_class": "backend", "source_paths": [ - "src/repo_registry/content_indexing/extractor.py", + "src/repo_scoping/content_indexing/extractor.py", "tests/test_content_indexing.py" ] }, @@ -100,8 +100,8 @@ "name": "Carry source-role metadata into downstream generation", "primary_class": "backend", "source_paths": [ - "src/repo_registry/content_indexing/extractor.py", - "src/repo_registry/llm_extraction/extractor.py" + "src/repo_scoping/content_indexing/extractor.py", + "src/repo_scoping/llm_extraction/extractor.py" ] } ] @@ -115,8 +115,8 @@ "name": "Build candidate abilities, capabilities, features, and evidence", "primary_class": "backend", "source_paths": [ - "src/repo_registry/candidate_graph/generator.py", - "src/repo_registry/candidate_graph/normalization.py", + "src/repo_scoping/candidate_graph/generator.py", + "src/repo_scoping/candidate_graph/normalization.py", "tests/test_candidate_graph.py" ] }, @@ -124,8 +124,8 @@ "name": "Optionally map structured LLM extraction into candidates", "primary_class": "integration", "source_paths": [ - "src/repo_registry/llm_extraction/extractor.py", - "src/repo_registry/llm_extraction/mapper.py", + "src/repo_scoping/llm_extraction/extractor.py", + "src/repo_scoping/llm_extraction/mapper.py", "tests/test_llm_extraction.py" ] } @@ -140,9 +140,9 @@ "name": "Edit, reject, merge, and relink candidate graph entries", "primary_class": "api", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/web_api/app.py", - "src/repo_registry/web_ui/views.py", + "src/repo_scoping/core/service.py", + "src/repo_scoping/web_api/app.py", + "src/repo_scoping/web_ui/views.py", "tests/test_registry_service.py" ] }, @@ -150,16 +150,16 @@ "name": "Publish approved characteristic maps after review", "primary_class": "storage", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/storage/sqlite.py" + "src/repo_scoping/core/service.py", + "src/repo_scoping/storage/sqlite.py" ] }, { "name": "Record review decisions and expectation gaps", "primary_class": "audit", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/web_api/schemas.py" + "src/repo_scoping/core/service.py", + "src/repo_scoping/web_api/schemas.py" ] } ] @@ -173,8 +173,8 @@ "name": "Search approved abilities, capabilities, features, and evidence", "primary_class": "api", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/semantic/embeddings.py", + "src/repo_scoping/core/service.py", + "src/repo_scoping/semantic/embeddings.py", "tests/test_registry_service.py" ] }, @@ -182,15 +182,15 @@ "name": "Compare repositories and identify capability gaps", "primary_class": "api", "source_paths": [ - "src/repo_registry/core/service.py", - "src/repo_registry/web_api/app.py" + "src/repo_scoping/core/service.py", + "src/repo_scoping/web_api/app.py" ] }, { "name": "Export repository profiles", "primary_class": "api", "source_paths": [ - "src/repo_registry/web_api/app.py", + "src/repo_scoping/web_api/app.py", "docs/api-contract.md" ] } @@ -205,7 +205,7 @@ "name": "Render SCOPE.md from approved characteristics", "primary_class": "backend", "source_paths": [ - "src/repo_registry/scope/generator.py", + "src/repo_scoping/scope/generator.py", "tests/test_scope_generator.py", "docs/scope-md-spec.md" ] @@ -214,9 +214,9 @@ "name": "Diff, validate, and write scope files", "primary_class": "api", "source_paths": [ - "src/repo_registry/scope/validator.py", - "src/repo_registry/web_api/app.py", - "src/repo_registry/web_ui/views.py" + "src/repo_scoping/scope/validator.py", + "src/repo_scoping/web_api/app.py", + "src/repo_scoping/web_ui/views.py" ] } ] @@ -230,7 +230,7 @@ "name": "Model dependencies between facts, evidence, features, capabilities, abilities, and scope", "primary_class": "backend", "source_paths": [ - "src/repo_registry/core/service.py", + "src/repo_scoping/core/service.py", "docs/dependency-aware-scope-propagation.md", "docs/dependency-visualization-exploration.md" ] @@ -239,7 +239,7 @@ "name": "Render dependency graph views and profiles", "primary_class": "ui", "source_paths": [ - "src/repo_registry/web_ui/views.py", + "src/repo_scoping/web_ui/views.py", "tests/test_web_api.py" ] } @@ -254,7 +254,7 @@ "name": "Return compact JSON scope context by repository slug", "primary_class": "api", "source_paths": [ - "src/repo_registry/web_api/app.py", + "src/repo_scoping/web_api/app.py", "docs/schemas/repo-scope-context-response.json", "tests/test_scope_context_api.py" ] diff --git a/docs/semantic-retrieval.md b/docs/semantic-retrieval.md index df439d3..91320f8 100644 --- a/docs/semantic-retrieval.md +++ b/docs/semantic-retrieval.md @@ -11,7 +11,7 @@ development. It produces deterministic token-bucket vectors without any network dependency. Configure it with: ```bash -REPO_REGISTRY_EMBEDDING_PROVIDER=hashing +REPO_SCOPING_EMBEDDING_PROVIDER=hashing ``` When enabled, search combines: diff --git a/docs/terminology.md b/docs/terminology.md index cd63ed8..bf17dcb 100644 --- a/docs/terminology.md +++ b/docs/terminology.md @@ -10,10 +10,10 @@ repository is for and how that claim is supported. - Repository Scoping is the product and UI name. - `repo-scoping` is the managed repository slug, Git remote identity, and State Hub repository identity. -- `repo_registry`, `REPO_REGISTRY_`, and `var/repo-registry.sqlite3` are retained - compatibility names in code and local configuration. -- Repository Ability Registry and `repo-registry` are historical names from - before the scope-oriented rename. +- `repo_scoping`, `REPO_SCOPING_`, and `var/repo-scoping.sqlite3` are the + current package, environment-prefix, and default SQLite names. +- Earlier registry-oriented names are historical only and should not be used in + runtime configuration, package imports, or new documentation. ## Characteristic Model diff --git a/pyproject.toml b/pyproject.toml index 6a8e987..ed37874 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=68"] build-backend = "setuptools.build_meta" [project] -name = "repo-registry" +name = "repo-scoping" version = "0.1.0" description = "Repository Scoping" readme = "README.md" @@ -22,7 +22,7 @@ dev = [ ] [project.scripts] -repo-scoping = "repo_registry.cli:main" +repo-scoping = "repo_scoping.cli:main" [tool.setuptools.packages.find] where = ["src"] diff --git a/src/repo_scoping/acceptance/__init__.py b/src/repo_scoping/acceptance/__init__.py index f34b6c9..0b2af22 100644 --- a/src/repo_scoping/acceptance/__init__.py +++ b/src/repo_scoping/acceptance/__init__.py @@ -1,18 +1,18 @@ -from repo_registry.acceptance.agentic import ( +from repo_scoping.acceptance.agentic import ( AgenticReviewer, AgenticReviewDecision, AgenticReviewRequest, validate_agentic_review_decision, validate_agentic_review_decisions, ) -from repo_registry.acceptance.criteria import ( +from repo_scoping.acceptance.criteria import ( active_quality_criteria_version, criteria_registry_dict, criteria_registry_json, criteria_registry_markdown, load_quality_criteria, ) -from repo_registry.acceptance.gates import ( +from repo_scoping.acceptance.gates import ( blocking_quality_gate_outcomes, evaluate_candidate_capability_quality, evaluate_candidate_graph_quality, diff --git a/src/repo_scoping/acceptance/agentic.py b/src/repo_scoping/acceptance/agentic.py index 013f91b..37eb25a 100644 --- a/src/repo_scoping/acceptance/agentic.py +++ b/src/repo_scoping/acceptance/agentic.py @@ -4,8 +4,8 @@ from dataclasses import dataclass from typing import Any from typing import Protocol -from repo_registry.acceptance.gates import QualityGateOutcome -from repo_registry.core.models import CandidateGraph, Repository +from repo_scoping.acceptance.gates import QualityGateOutcome +from repo_scoping.core.models import CandidateGraph, Repository AGENTIC_REVIEW_ACTIONS = { "approve", diff --git a/src/repo_scoping/acceptance/gates.py b/src/repo_scoping/acceptance/gates.py index 37c4fba..33d885e 100644 --- a/src/repo_scoping/acceptance/gates.py +++ b/src/repo_scoping/acceptance/gates.py @@ -2,12 +2,12 @@ from __future__ import annotations from dataclasses import asdict, dataclass -from repo_registry.acceptance.criteria import ( +from repo_scoping.acceptance.criteria import ( QualityCriteriaRegistry, QualityCriterion, load_quality_criteria, ) -from repo_registry.core.models import ( +from repo_scoping.core.models import ( CandidateCapability, CandidateFeature, CandidateGraph, diff --git a/src/repo_scoping/candidate_graph/generator.py b/src/repo_scoping/candidate_graph/generator.py index 6a58600..a077ed6 100644 --- a/src/repo_scoping/candidate_graph/generator.py +++ b/src/repo_scoping/candidate_graph/generator.py @@ -3,7 +3,7 @@ from __future__ import annotations import re from dataclasses import dataclass, field, replace -from repo_registry.core.models import ContentChunk, ObservedFact, Repository, SourceReference +from repo_scoping.core.models import ContentChunk, ObservedFact, Repository, SourceReference @dataclass(frozen=True) @@ -59,18 +59,18 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ ( "Create and update repository records", "api", - ["src/repo_registry/core/service.py", "src/repo_registry/web_api/app.py"], + ["src/repo_scoping/core/service.py", "src/repo_scoping/web_api/app.py"], ), ( "Resolve local or remote Git checkouts", "backend", - ["src/repo_registry/repo_ingestion/git.py", "tests/test_git_ingestion.py"], + ["src/repo_scoping/repo_ingestion/git.py", "tests/test_git_ingestion.py"], ), ( "Import repository metadata", "backend", [ - "src/repo_registry/repo_ingestion/metadata.py", + "src/repo_scoping/repo_ingestion/metadata.py", "tests/test_repository_metadata.py", ], ), @@ -84,17 +84,17 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ ( "Detect source languages, manifests, docs, tests, config, and interfaces", "backend", - ["src/repo_registry/repo_scanning/scanner.py", "tests/test_repository_scanner.py"], + ["src/repo_scoping/repo_scanning/scanner.py", "tests/test_repository_scanner.py"], ), ( "Classify source roles for facts", "backend", - ["src/repo_registry/repo_scanning/scanner.py", "docs/characteristic-evidence-model.md"], + ["src/repo_scoping/repo_scanning/scanner.py", "docs/characteristic-evidence-model.md"], ), ( "Preserve analysis snapshots and fact records", "storage", - ["src/repo_registry/storage/sqlite.py", "migrations/0001_initial.sql"], + ["src/repo_scoping/storage/sqlite.py", "migrations/0001_initial.sql"], ), ], }, @@ -106,14 +106,14 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ ( "Create source-linked content chunks from observed facts", "backend", - ["src/repo_registry/content_indexing/extractor.py", "tests/test_content_indexing.py"], + ["src/repo_scoping/content_indexing/extractor.py", "tests/test_content_indexing.py"], ), ( "Carry source-role metadata into downstream generation", "backend", [ - "src/repo_registry/content_indexing/extractor.py", - "src/repo_registry/llm_extraction/extractor.py", + "src/repo_scoping/content_indexing/extractor.py", + "src/repo_scoping/llm_extraction/extractor.py", ], ), ], @@ -127,8 +127,8 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Build candidate abilities, capabilities, features, and evidence", "backend", [ - "src/repo_registry/candidate_graph/generator.py", - "src/repo_registry/candidate_graph/normalization.py", + "src/repo_scoping/candidate_graph/generator.py", + "src/repo_scoping/candidate_graph/normalization.py", "tests/test_candidate_graph.py", ], ), @@ -136,8 +136,8 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Optionally map structured LLM extraction into candidates", "integration", [ - "src/repo_registry/llm_extraction/extractor.py", - "src/repo_registry/llm_extraction/mapper.py", + "src/repo_scoping/llm_extraction/extractor.py", + "src/repo_scoping/llm_extraction/mapper.py", "tests/test_llm_extraction.py", ], ), @@ -152,20 +152,20 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Edit, reject, merge, and relink candidate graph entries", "api", [ - "src/repo_registry/core/service.py", - "src/repo_registry/web_api/app.py", + "src/repo_scoping/core/service.py", + "src/repo_scoping/web_api/app.py", "tests/test_registry_service.py", ], ), ( "Publish approved characteristic maps after review", "storage", - ["src/repo_registry/core/service.py", "src/repo_registry/storage/sqlite.py"], + ["src/repo_scoping/core/service.py", "src/repo_scoping/storage/sqlite.py"], ), ( "Record review decisions and expectation gaps", "audit", - ["src/repo_registry/core/service.py", "src/repo_registry/web_api/schemas.py"], + ["src/repo_scoping/core/service.py", "src/repo_scoping/web_api/schemas.py"], ), ], }, @@ -177,17 +177,17 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ ( "Search approved abilities, capabilities, features, and evidence", "api", - ["src/repo_registry/core/service.py", "tests/test_registry_service.py"], + ["src/repo_scoping/core/service.py", "tests/test_registry_service.py"], ), ( "Compare repositories and identify capability gaps", "api", - ["src/repo_registry/core/service.py", "src/repo_registry/web_api/app.py"], + ["src/repo_scoping/core/service.py", "src/repo_scoping/web_api/app.py"], ), ( "Export repository profiles", "api", - ["src/repo_registry/web_api/app.py", "docs/api-contract.md"], + ["src/repo_scoping/web_api/app.py", "docs/api-contract.md"], ), ], }, @@ -200,7 +200,7 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Render SCOPE.md from approved characteristics", "backend", [ - "src/repo_registry/scope/generator.py", + "src/repo_scoping/scope/generator.py", "tests/test_scope_generator.py", "docs/scope-md-spec.md", ], @@ -209,8 +209,8 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Diff, validate, and write scope files", "api", [ - "src/repo_registry/scope/validator.py", - "src/repo_registry/web_api/app.py", + "src/repo_scoping/scope/validator.py", + "src/repo_scoping/web_api/app.py", ], ), ], @@ -224,7 +224,7 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Model dependencies between facts, evidence, features, capabilities, abilities, and scope", "backend", [ - "src/repo_registry/core/service.py", + "src/repo_scoping/core/service.py", "docs/dependency-aware-scope-propagation.md", "docs/dependency-visualization-exploration.md", ], @@ -232,7 +232,7 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ ( "Render dependency graph views and profiles", "ui", - ["src/repo_registry/web_ui/views.py", "tests/test_web_api.py"], + ["src/repo_scoping/web_ui/views.py", "tests/test_web_api.py"], ), ], }, @@ -245,7 +245,7 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [ "Return compact JSON scope context by repository slug", "api", [ - "src/repo_registry/web_api/app.py", + "src/repo_scoping/web_api/app.py", "docs/schemas/repo-scope-context-response.json", "tests/test_scope_context_api.py", ], @@ -661,7 +661,7 @@ class CandidateGraphGenerator: identity = f"{repository.name} {repository.url} {repository.description or ''}".lower() if "repo-scoping" in identity or "repository scoping" in identity: return True - return any(fact.path.startswith("src/repo_registry/") for fact in facts) + return any(fact.path.startswith("src/repo_scoping/") for fact in facts) def _facts_for_paths( self, diff --git a/src/repo_scoping/candidate_graph/normalization.py b/src/repo_scoping/candidate_graph/normalization.py index f1de815..8401daa 100644 --- a/src/repo_scoping/candidate_graph/normalization.py +++ b/src/repo_scoping/candidate_graph/normalization.py @@ -3,13 +3,13 @@ from __future__ import annotations import re from dataclasses import replace -from repo_registry.candidate_graph.generator import ( +from repo_scoping.candidate_graph.generator import ( CandidateAbilityDraft, CandidateCapabilityDraft, CandidateEvidenceDraft, CandidateFeatureDraft, ) -from repo_registry.core.models import SourceReference +from repo_scoping.core.models import SourceReference STOP_WORDS = { diff --git a/src/repo_scoping/cli.py b/src/repo_scoping/cli.py index b66157e..28b58cb 100644 --- a/src/repo_scoping/cli.py +++ b/src/repo_scoping/cli.py @@ -6,24 +6,24 @@ from dataclasses import asdict from pathlib import Path from typing import Sequence -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( criteria_registry_json, criteria_registry_markdown, load_quality_criteria, ) -from repo_registry.core.models import CharacteristicRebuildResult, Repository -from repo_registry.core.service import RegistryService -from repo_registry.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.self_scoping.assessment import artifact_json, export_assessment_artifact -from repo_registry.self_scoping.comparison import ( +from repo_scoping.core.models import CharacteristicRebuildResult, Repository +from repo_scoping.core.service import RegistryService +from repo_scoping.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.self_scoping.assessment import artifact_json, export_assessment_artifact +from repo_scoping.self_scoping.comparison import ( compare_assessment_to_golden, comparison_json, comparison_markdown, load_json, ) -from repo_registry.storage.sqlite import NotFoundError, RegistryStore -from repo_registry.web_api.app import Settings +from repo_scoping.storage.sqlite import NotFoundError, RegistryStore +from repo_scoping.web_api.app import Settings def build_parser() -> argparse.ArgumentParser: @@ -56,8 +56,8 @@ def build_parser() -> argparse.ArgumentParser: action="store_true", help="Confirm a destructive all-repository rebuild.", ) - rebuild.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.") - rebuild.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.") + rebuild.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.") + rebuild.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.") export = subparsers.add_parser( "export-assessment", help="Export a completed analysis run as a self-scoping assessment artifact.", @@ -87,8 +87,8 @@ def build_parser() -> argparse.ArgumentParser: ) export.add_argument("--reviewer", default="codex", help="Reviewer name recorded in the artifact.") export.add_argument("--summary", help="Assessment summary override.") - export.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.") - export.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.") + export.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.") + export.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.") compare = subparsers.add_parser( "compare-assessment", help="Compare a self-scoping assessment artifact against a golden profile.", @@ -155,8 +155,8 @@ def build_parser() -> argparse.ArgumentParser: action="store_true", help="Return exit code 1 only when comparison status is regression.", ) - self_assess.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.") - self_assess.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.") + self_assess.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.") + self_assess.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.") self_assess.set_defaults(no_llm=True) criteria = subparsers.add_parser( "list-quality-criteria", @@ -177,8 +177,8 @@ def build_parser() -> argparse.ArgumentParser: "list-legacy-auto-approvals", help="List historical trusted deterministic auto-approval records.", ) - legacy.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.") - legacy.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.") + legacy.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.") + legacy.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.") legacy.add_argument("--output", help="Write inventory output to this path instead of stdout.") legacy.add_argument( "--format", diff --git a/src/repo_scoping/content_indexing/__init__.py b/src/repo_scoping/content_indexing/__init__.py index 2578378..c9419d8 100644 --- a/src/repo_scoping/content_indexing/__init__.py +++ b/src/repo_scoping/content_indexing/__init__.py @@ -1,3 +1,3 @@ -from repo_registry.content_indexing.extractor import ContentChunkCandidate, ContentExtractor +from repo_scoping.content_indexing.extractor import ContentChunkCandidate, ContentExtractor __all__ = ["ContentChunkCandidate", "ContentExtractor"] diff --git a/src/repo_scoping/content_indexing/extractor.py b/src/repo_scoping/content_indexing/extractor.py index 96854cc..d595866 100644 --- a/src/repo_scoping/content_indexing/extractor.py +++ b/src/repo_scoping/content_indexing/extractor.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass, field from pathlib import Path -from repo_registry.core.models import ObservedFact +from repo_scoping.core.models import ObservedFact INDEXED_FACT_KINDS = { diff --git a/src/repo_scoping/core/logging.py b/src/repo_scoping/core/logging.py index 32749c7..571383e 100644 --- a/src/repo_scoping/core/logging.py +++ b/src/repo_scoping/core/logging.py @@ -5,7 +5,7 @@ import logging from typing import Any -LOGGER_NAME = "repo_registry.operations" +LOGGER_NAME = "repo_scoping.operations" def log_operation(event: str, **fields: Any) -> None: diff --git a/src/repo_scoping/core/service.py b/src/repo_scoping/core/service.py index 307c313..af6880d 100644 --- a/src/repo_scoping/core/service.py +++ b/src/repo_scoping/core/service.py @@ -4,7 +4,7 @@ from collections.abc import Sequence from dataclasses import asdict, replace from typing import Any -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( AgenticReviewDecision, AgenticReviewer, AgenticReviewRequest, @@ -14,7 +14,7 @@ from repo_registry.acceptance import ( evaluate_candidate_graph_quality, validate_agentic_review_decisions, ) -from repo_registry.core.models import ( +from repo_scoping.core.models import ( AbilitySummary, AnalysisRunDiff, AnalysisRunDiffItem, @@ -43,17 +43,17 @@ from repo_registry.core.models import ( TrustedAutoApprovalMigrationRecord, enrich_review_decision, ) -from repo_registry.candidate_graph.generator import CandidateGraphGenerator -from repo_registry.candidate_graph.normalization import normalize_candidate_drafts -from repo_registry.content_indexing.extractor import ContentExtractor -from repo_registry.core.logging import log_operation -from repo_registry.llm_extraction.extractor import LLMCandidateExtractor -from repo_registry.llm_extraction.mapper import LLMExtractionMapper -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.repo_ingestion.metadata import RepositoryMetadataExtractor -from repo_registry.repo_scanning.scanner import DeterministicScanner -from repo_registry.semantic import EmbeddingProvider, cosine_similarity -from repo_registry.storage.sqlite import NotFoundError, RegistryStore +from repo_scoping.candidate_graph.generator import CandidateGraphGenerator +from repo_scoping.candidate_graph.normalization import normalize_candidate_drafts +from repo_scoping.content_indexing.extractor import ContentExtractor +from repo_scoping.core.logging import log_operation +from repo_scoping.llm_extraction.extractor import LLMCandidateExtractor +from repo_scoping.llm_extraction.mapper import LLMExtractionMapper +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.repo_ingestion.metadata import RepositoryMetadataExtractor +from repo_scoping.repo_scanning.scanner import DeterministicScanner +from repo_scoping.semantic import EmbeddingProvider, cosine_similarity +from repo_scoping.storage.sqlite import NotFoundError, RegistryStore class RegistryService: diff --git a/src/repo_scoping/llm_extraction/__init__.py b/src/repo_scoping/llm_extraction/__init__.py index 3d822e6..98cc2b3 100644 --- a/src/repo_scoping/llm_extraction/__init__.py +++ b/src/repo_scoping/llm_extraction/__init__.py @@ -1,4 +1,4 @@ -from repo_registry.llm_extraction.extractor import ( +from repo_scoping.llm_extraction.extractor import ( ExtractedAbility, ExtractedCapability, ExtractedEvidence, @@ -7,7 +7,7 @@ from repo_registry.llm_extraction.extractor import ( LLMExtractionError, create_llm_connect_adapter, ) -from repo_registry.llm_extraction.mapper import LLMExtractionMapper +from repo_scoping.llm_extraction.mapper import LLMExtractionMapper __all__ = [ "ExtractedAbility", diff --git a/src/repo_scoping/llm_extraction/extractor.py b/src/repo_scoping/llm_extraction/extractor.py index d5f5a73..59a6abb 100644 --- a/src/repo_scoping/llm_extraction/extractor.py +++ b/src/repo_scoping/llm_extraction/extractor.py @@ -4,7 +4,7 @@ import json from dataclasses import dataclass, field from typing import Any, Protocol -from repo_registry.core.models import ContentChunk, Repository +from repo_scoping.core.models import ContentChunk, Repository class LLMExtractionError(ValueError): diff --git a/src/repo_scoping/llm_extraction/mapper.py b/src/repo_scoping/llm_extraction/mapper.py index d6cb73c..0319897 100644 --- a/src/repo_scoping/llm_extraction/mapper.py +++ b/src/repo_scoping/llm_extraction/mapper.py @@ -1,13 +1,13 @@ from __future__ import annotations -from repo_registry.candidate_graph.generator import ( +from repo_scoping.candidate_graph.generator import ( CandidateAbilityDraft, CandidateCapabilityDraft, CandidateEvidenceDraft, CandidateFeatureDraft, ) -from repo_registry.core.models import ContentChunk, ObservedFact, SourceReference -from repo_registry.llm_extraction.extractor import ExtractedAbility +from repo_scoping.core.models import ContentChunk, ObservedFact, SourceReference +from repo_scoping.llm_extraction.extractor import ExtractedAbility class LLMExtractionMapper: diff --git a/src/repo_scoping/repo_ingestion/metadata.py b/src/repo_scoping/repo_ingestion/metadata.py index f60f442..324aba1 100644 --- a/src/repo_scoping/repo_ingestion/metadata.py +++ b/src/repo_scoping/repo_ingestion/metadata.py @@ -19,10 +19,16 @@ class RepositoryMetadataExtractor: pyproject = self._from_pyproject(root) package = self._from_package_json(root) readme = self._from_readme(root) - fallback_name = self._name_from_url_or_path(url) + source_name = self._source_name(url) or self._source_name(str(root)) return RepositoryMetadata( - name=pyproject.name or package.name or readme.name or fallback_name, + name=( + source_name + or pyproject.name + or package.name + or readme.name + or "repository" + ), description=( pyproject.description or package.description @@ -77,10 +83,13 @@ class RepositoryMetadataExtractor: return RepositoryMetadata(name=title, description=None) return RepositoryMetadata(name="", description=None) - def _name_from_url_or_path(self, value: str) -> str: + def _source_name(self, value: str) -> str: parsed = urlparse(value) path = parsed.path if parsed.scheme else value - name = Path(path.rstrip("/")).name or "repository" + name = Path(path.rstrip("/")).name if name.endswith(".git"): name = name[:-4] - return name or "repository" + normalized = name.strip() + if normalized.lower() in {"", ".", "repo", "repository", "source", "checkout"}: + return "" + return normalized diff --git a/src/repo_scoping/scope/__init__.py b/src/repo_scoping/scope/__init__.py index c35ac17..5ed1bed 100644 --- a/src/repo_scoping/scope/__init__.py +++ b/src/repo_scoping/scope/__init__.py @@ -1,4 +1,4 @@ -from repo_registry.scope.generator import ScopeGenerator -from repo_registry.scope.validator import ScopeValidator +from repo_scoping.scope.generator import ScopeGenerator +from repo_scoping.scope.validator import ScopeValidator __all__ = ["ScopeGenerator", "ScopeValidator"] diff --git a/src/repo_scoping/scope/generator.py b/src/repo_scoping/scope/generator.py index 084d349..533fd95 100644 --- a/src/repo_scoping/scope/generator.py +++ b/src/repo_scoping/scope/generator.py @@ -3,8 +3,8 @@ from __future__ import annotations import re from dataclasses import asdict -from repo_registry.core.service import RegistryService -from repo_registry.storage.sqlite import NotFoundError +from repo_scoping.core.service import RegistryService +from repo_scoping.storage.sqlite import NotFoundError SCOPE_SECTIONS = [ diff --git a/src/repo_scoping/scope/validator.py b/src/repo_scoping/scope/validator.py index 5024576..9164cb1 100644 --- a/src/repo_scoping/scope/validator.py +++ b/src/repo_scoping/scope/validator.py @@ -4,7 +4,7 @@ import re from dataclasses import dataclass from pathlib import Path -from repo_registry.scope.generator import SCOPE_SECTIONS, ScopeGenerator +from repo_scoping.scope.generator import SCOPE_SECTIONS, ScopeGenerator @dataclass(frozen=True) diff --git a/src/repo_scoping/self_scoping/__init__.py b/src/repo_scoping/self_scoping/__init__.py index 8e0cb5a..7fa06e7 100644 --- a/src/repo_scoping/self_scoping/__init__.py +++ b/src/repo_scoping/self_scoping/__init__.py @@ -1,6 +1,6 @@ -from repo_registry.self_scoping.assessment import export_assessment_artifact -from repo_registry.self_scoping.comparison import compare_assessment_to_golden -from repo_registry.self_scoping.review_store import ( +from repo_scoping.self_scoping.assessment import export_assessment_artifact +from repo_scoping.self_scoping.comparison import compare_assessment_to_golden +from repo_scoping.self_scoping.review_store import ( record_assessment_outcome, record_assessment_pair_outcome, ) diff --git a/src/repo_scoping/self_scoping/assessment.py b/src/repo_scoping/self_scoping/assessment.py index 4aa949a..e1a840b 100644 --- a/src/repo_scoping/self_scoping/assessment.py +++ b/src/repo_scoping/self_scoping/assessment.py @@ -9,12 +9,12 @@ from importlib import metadata from pathlib import Path from typing import Any -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( active_quality_criteria_version, evaluate_candidate_graph_quality, quality_gate_outcome_dicts, ) -from repo_registry.core.models import ( +from repo_scoping.core.models import ( Ability, CandidateAbility, CandidateCapability, @@ -26,7 +26,7 @@ from repo_registry.core.models import ( ReviewDecision, SourceReference, ) -from repo_registry.core.service import RegistryService +from repo_scoping.core.service import RegistryService SCHEMA_VERSION = "self-scoping-assessment/v1" @@ -151,7 +151,7 @@ def _engine_identity(scanner_version: str, engine_root: Path) -> dict[str, Any]: def _package_version() -> str: try: - return metadata.version("repo-registry") + return metadata.version("repo-scoping") except metadata.PackageNotFoundError: return "unknown" diff --git a/src/repo_scoping/self_scoping/review_store.py b/src/repo_scoping/self_scoping/review_store.py index 7e2290d..2dba016 100644 --- a/src/repo_scoping/self_scoping/review_store.py +++ b/src/repo_scoping/self_scoping/review_store.py @@ -9,7 +9,7 @@ from typing import Any from uuid import uuid4 -SELF_SCOPING_ROOT_ENV = "REPO_REGISTRY_SELF_SCOPING_ROOT" +SELF_SCOPING_ROOT_ENV = "REPO_SCOPING_SELF_SCOPING_ROOT" OUTCOME_SCHEMA_VERSION = "self-scoping-review-outcome/v1" ALLOWED_OUTCOMES = { "prefer_golden", diff --git a/src/repo_scoping/semantic/__init__.py b/src/repo_scoping/semantic/__init__.py index 9622ce4..20ebea7 100644 --- a/src/repo_scoping/semantic/__init__.py +++ b/src/repo_scoping/semantic/__init__.py @@ -1,4 +1,4 @@ -from repo_registry.semantic.embeddings import ( +from repo_scoping.semantic.embeddings import ( EmbeddingProvider, HashingEmbeddingProvider, cosine_similarity, diff --git a/src/repo_scoping/storage/sqlite.py b/src/repo_scoping/storage/sqlite.py index 751ae92..2f673b1 100644 --- a/src/repo_scoping/storage/sqlite.py +++ b/src/repo_scoping/storage/sqlite.py @@ -4,7 +4,7 @@ import json import sqlite3 from pathlib import Path -from repo_registry.core.models import ( +from repo_scoping.core.models import ( Ability, AbilitySummary, AnalysisRun, @@ -30,10 +30,10 @@ from repo_registry.core.models import ( SourceReference, confidence_label, ) -from repo_registry.core.logging import log_operation -from repo_registry.content_indexing.extractor import ContentChunkCandidate -from repo_registry.candidate_graph.generator import CandidateAbilityDraft -from repo_registry.repo_scanning.scanner import FactCandidate, ScanResult +from repo_scoping.core.logging import log_operation +from repo_scoping.content_indexing.extractor import ContentChunkCandidate +from repo_scoping.candidate_graph.generator import CandidateAbilityDraft +from repo_scoping.repo_scanning.scanner import FactCandidate, ScanResult class NotFoundError(ValueError): diff --git a/src/repo_scoping/web_api/app.py b/src/repo_scoping/web_api/app.py index 03bbd1b..1d51481 100644 --- a/src/repo_scoping/web_api/app.py +++ b/src/repo_scoping/web_api/app.py @@ -12,19 +12,19 @@ from fastapi.responses import PlainTextResponse from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( criteria_registry_dict, evaluate_candidate_graph_quality, load_quality_criteria, quality_gate_outcome_dicts, ) -from repo_registry.core.service import RegistryService -from repo_registry.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.semantic import HashingEmbeddingProvider -from repo_registry.scope import ScopeGenerator, ScopeValidator -from repo_registry.storage.sqlite import NotFoundError, RegistryStore -from repo_registry.web_api.schemas import ( +from repo_scoping.core.service import RegistryService +from repo_scoping.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.semantic import HashingEmbeddingProvider +from repo_scoping.scope import ScopeGenerator, ScopeValidator +from repo_scoping.storage.sqlite import NotFoundError, RegistryStore +from repo_scoping.web_api.schemas import ( AbilityCreate, AbilitySummaryResponse, AbilityUpdate, @@ -86,9 +86,9 @@ def slugify(value: str) -> str: class Settings(BaseSettings): - model_config = SettingsConfigDict(env_prefix="REPO_REGISTRY_") + model_config = SettingsConfigDict(env_prefix="REPO_SCOPING_") - database_path: str = Field(default="var/repo-registry.sqlite3") + database_path: str = Field(default="var/repo-scoping.sqlite3") checkout_root: str = Field(default="var/checkouts") llm_enabled: bool = Field(default=True) llm_provider: str | None = Field(default=None) @@ -103,7 +103,7 @@ def get_settings() -> Settings: def get_service(settings: Settings = Depends(get_settings)) -> RegistryService: - logging.getLogger("repo_registry.operations").setLevel( + logging.getLogger("repo_scoping.operations").setLevel( getattr(logging, settings.log_level.upper(), logging.INFO) ) database_path = Path(settings.database_path) @@ -165,7 +165,7 @@ app = FastAPI( ) -from repo_registry.web_ui.views import router as ui_router +from repo_scoping.web_ui.views import router as ui_router app.include_router(ui_router) diff --git a/src/repo_scoping/web_ui/views.py b/src/repo_scoping/web_ui/views.py index 6630c9b..ec348e2 100644 --- a/src/repo_scoping/web_ui/views.py +++ b/src/repo_scoping/web_ui/views.py @@ -9,13 +9,13 @@ from urllib.parse import quote_plus, urlparse from fastapi import APIRouter, Depends, Form, HTTPException, Query from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( evaluate_candidate_graph_quality, quality_gate_outcome_dicts, ) -from repo_registry.core.service import RegistryService -from repo_registry.self_scoping.comparison import compare_assessment_to_golden -from repo_registry.self_scoping.review_store import ( +from repo_scoping.core.service import RegistryService +from repo_scoping.self_scoping.comparison import compare_assessment_to_golden +from repo_scoping.self_scoping.review_store import ( ALLOWED_OUTCOMES, list_assessment_artifacts, list_golden_profiles, @@ -24,8 +24,8 @@ from repo_registry.self_scoping.review_store import ( record_assessment_outcome, record_assessment_pair_outcome, ) -from repo_registry.storage.sqlite import NotFoundError -from repo_registry.web_api.app import get_service +from repo_scoping.storage.sqlite import NotFoundError +from repo_scoping.web_api.app import get_service router = APIRouter(include_in_schema=False) diff --git a/tests/test_acceptance_boundary.py b/tests/test_acceptance_boundary.py index e2bdb72..015d3b3 100644 --- a/tests/test_acceptance_boundary.py +++ b/tests/test_acceptance_boundary.py @@ -1,7 +1,7 @@ -from repo_registry.acceptance import AgenticReviewDecision -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.acceptance import AgenticReviewDecision +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore class BoundaryApprovingReviewer: diff --git a/tests/test_agentic_review.py b/tests/test_agentic_review.py index d6c9224..700d2f7 100644 --- a/tests/test_agentic_review.py +++ b/tests/test_agentic_review.py @@ -1,12 +1,12 @@ import pytest -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( AgenticReviewDecision, validate_agentic_review_decision, ) -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore class RecordingAgenticReviewer: diff --git a/tests/test_candidate_graph.py b/tests/test_candidate_graph.py index 7985509..1558543 100644 --- a/tests/test_candidate_graph.py +++ b/tests/test_candidate_graph.py @@ -1,5 +1,5 @@ -from repo_registry.candidate_graph.generator import CandidateGraphGenerator -from repo_registry.core.models import ContentChunk, ObservedFact, Repository +from repo_scoping.candidate_graph.generator import CandidateGraphGenerator +from repo_scoping.core.models import ContentChunk, ObservedFact, Repository def fact(id, kind, name, path="", value="", metadata=None): @@ -533,7 +533,7 @@ def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capab 3, "llm_provider", "OpenRouter", - "src/repo_registry/repo_scanning/scanner.py", + "src/repo_scoping/repo_scanning/scanner.py", "openrouter", {"source_role": "implementation_source", "utility_relationship": "owned"}, ), @@ -541,7 +541,7 @@ def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capab 4, "provider_registry", "LLM provider registry", - "src/repo_registry/repo_scanning/scanner.py", + "src/repo_scoping/repo_scanning/scanner.py", metadata={ "source_role": "implementation_source", "utility_relationship": "owned", @@ -551,7 +551,7 @@ def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capab 5, "credential_config", "OpenRouter API key", - "src/repo_registry/repo_scanning/scanner.py", + "src/repo_scoping/repo_scanning/scanner.py", "OPENROUTER_API_KEY", {"source_role": "implementation_source", "utility_relationship": "configure"}, ), @@ -619,7 +619,7 @@ def test_candidate_generator_recovers_repo_scoping_native_candidate_families(): 17, "interface", "python route decorator", - "src/repo_registry/web_api/app.py", + "src/repo_scoping/web_api/app.py", '@app.post("/repos")', ), ] diff --git a/tests/test_candidate_normalization.py b/tests/test_candidate_normalization.py index e951f95..a4d68b6 100644 --- a/tests/test_candidate_normalization.py +++ b/tests/test_candidate_normalization.py @@ -1,10 +1,10 @@ -from repo_registry.candidate_graph.generator import ( +from repo_scoping.candidate_graph.generator import ( CandidateAbilityDraft, CandidateCapabilityDraft, CandidateFeatureDraft, ) -from repo_registry.candidate_graph.normalization import normalize_candidate_drafts -from repo_registry.core.models import SourceReference +from repo_scoping.candidate_graph.normalization import normalize_candidate_drafts +from repo_scoping.core.models import SourceReference def ref(fact_id, path): diff --git a/tests/test_cli.py b/tests/test_cli.py index 64b8098..786a6d6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,10 +2,10 @@ import json import pytest -from repo_registry.cli import main -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.cli import main +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore def make_service(tmp_path): diff --git a/tests/test_content_indexing.py b/tests/test_content_indexing.py index 46c153e..e4b12f0 100644 --- a/tests/test_content_indexing.py +++ b/tests/test_content_indexing.py @@ -1,5 +1,5 @@ -from repo_registry.content_indexing.extractor import ContentExtractor -from repo_registry.core.models import ObservedFact +from repo_scoping.content_indexing.extractor import ContentExtractor +from repo_scoping.core.models import ObservedFact def fact(id, kind, name, path="", line=None, source_role=""): diff --git a/tests/test_git_ingestion.py b/tests/test_git_ingestion.py index fc7e3f2..2b1babf 100644 --- a/tests/test_git_ingestion.py +++ b/tests/test_git_ingestion.py @@ -1,6 +1,6 @@ import subprocess -from repo_registry.repo_ingestion.git import GitIngestionService +from repo_scoping.repo_ingestion.git import GitIngestionService def run(command, cwd): diff --git a/tests/test_intent_bootstrap.py b/tests/test_intent_bootstrap.py index eccbcf0..1c99af8 100644 --- a/tests/test_intent_bootstrap.py +++ b/tests/test_intent_bootstrap.py @@ -1,6 +1,6 @@ from datetime import date -from repo_registry.intent.bootstrap import bootstrap_intent_from_scope, scope_to_intent_text +from repo_scoping.intent.bootstrap import bootstrap_intent_from_scope, scope_to_intent_text def test_scope_to_intent_text_replaces_scope_heading_and_marks_bootstrap(): diff --git a/tests/test_llm_extraction.py b/tests/test_llm_extraction.py index ab177b7..ade1c1c 100644 --- a/tests/test_llm_extraction.py +++ b/tests/test_llm_extraction.py @@ -1,7 +1,7 @@ import pytest -from repo_registry.core.models import ContentChunk, Repository -from repo_registry.llm_extraction import ( +from repo_scoping.core.models import ContentChunk, Repository +from repo_scoping.llm_extraction import ( LLMCandidateExtractor, LLMExtractionError, create_llm_connect_adapter, diff --git a/tests/test_llm_extraction_mapper.py b/tests/test_llm_extraction_mapper.py index afe9e58..de3ae4f 100644 --- a/tests/test_llm_extraction_mapper.py +++ b/tests/test_llm_extraction_mapper.py @@ -1,5 +1,5 @@ -from repo_registry.core.models import ContentChunk, ObservedFact -from repo_registry.llm_extraction import ( +from repo_scoping.core.models import ContentChunk, ObservedFact +from repo_scoping.llm_extraction import ( ExtractedAbility, ExtractedCapability, ExtractedEvidence, diff --git a/tests/test_quality_criteria.py b/tests/test_quality_criteria.py index 23a4993..403e82b 100644 --- a/tests/test_quality_criteria.py +++ b/tests/test_quality_criteria.py @@ -1,4 +1,4 @@ -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( active_quality_criteria_version, criteria_registry_markdown, load_quality_criteria, diff --git a/tests/test_quality_gates.py b/tests/test_quality_gates.py index 3671c65..637f305 100644 --- a/tests/test_quality_gates.py +++ b/tests/test_quality_gates.py @@ -1,10 +1,10 @@ -from repo_registry.acceptance import ( +from repo_scoping.acceptance import ( blocking_quality_gate_outcomes, evaluate_candidate_capability_quality, evaluate_candidate_graph_quality, quality_gate_outcome_dicts, ) -from repo_registry.core.models import ( +from repo_scoping.core.models import ( AnalysisRun, CandidateAbility, CandidateCapability, @@ -13,9 +13,9 @@ from repo_registry.core.models import ( Repository, SourceReference, ) -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore def source_ref(path="src/app.py", kind="source"): diff --git a/tests/test_registry_service.py b/tests/test_registry_service.py index 5c9ed0b..a56b019 100644 --- a/tests/test_registry_service.py +++ b/tests/test_registry_service.py @@ -2,17 +2,17 @@ import json import logging import subprocess -from repo_registry.core.logging import LOGGER_NAME -from repo_registry.core.models import SourceReference -from repo_registry.core.service import RegistryService -from repo_registry.llm_extraction import ( +from repo_scoping.core.logging import LOGGER_NAME +from repo_scoping.core.models import SourceReference +from repo_scoping.core.service import RegistryService +from repo_scoping.llm_extraction import ( ExtractedAbility, ExtractedCapability, ExtractedFeature, ) -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.semantic import HashingEmbeddingProvider -from repo_registry.storage.sqlite import NotFoundError, RegistryStore +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.semantic import HashingEmbeddingProvider +from repo_scoping.storage.sqlite import NotFoundError, RegistryStore from tests.fixtures import ( write_dependency_only_repo, write_empty_repo, diff --git a/tests/test_repository_metadata.py b/tests/test_repository_metadata.py index 9ad09dd..3c34a1c 100644 --- a/tests/test_repository_metadata.py +++ b/tests/test_repository_metadata.py @@ -1,7 +1,21 @@ -from repo_registry.repo_ingestion.metadata import RepositoryMetadataExtractor +from repo_scoping.repo_ingestion.metadata import RepositoryMetadataExtractor -def test_metadata_prefers_pyproject(tmp_path): +def test_metadata_prefers_source_identity_over_pyproject(tmp_path): + repo = tmp_path / "repo-scoping" + repo.mkdir() + (repo / "pyproject.toml").write_text( + '[project]\nname = "repo-registry"\ndescription = "Repository Scoping."\n', + encoding="utf-8", + ) + + metadata = RepositoryMetadataExtractor().extract(repo, str(repo)) + + assert metadata.name == "repo-scoping" + assert metadata.description == "Repository Scoping." + + +def test_metadata_uses_pyproject_when_source_name_is_generic(tmp_path): repo = tmp_path / "repo" repo.mkdir() (repo / "pyproject.toml").write_text( @@ -15,7 +29,7 @@ def test_metadata_prefers_pyproject(tmp_path): assert metadata.description == "Extract invoice data." -def test_metadata_uses_package_json(tmp_path): +def test_metadata_uses_package_json_when_source_name_is_generic(tmp_path): repo = tmp_path / "repo" repo.mkdir() (repo / "package.json").write_text( @@ -29,8 +43,8 @@ def test_metadata_uses_package_json(tmp_path): assert metadata.description == "Browse repository abilities." -def test_metadata_falls_back_to_readme_title(tmp_path): - repo = tmp_path / "repo-name" +def test_metadata_uses_readme_title_when_source_name_is_generic(tmp_path): + repo = tmp_path / "repository" repo.mkdir() (repo / "README.md").write_text( "# Useful Registry\n\nExtra details follow.\n", @@ -41,3 +55,19 @@ def test_metadata_falls_back_to_readme_title(tmp_path): assert metadata.name == "Useful Registry" assert metadata.description == "Extra details follow." + + +def test_metadata_strips_git_suffix_from_url_identity(tmp_path): + repo = tmp_path / "checkout" + repo.mkdir() + (repo / "pyproject.toml").write_text( + '[project]\nname = "old-package-name"\n', + encoding="utf-8", + ) + + metadata = RepositoryMetadataExtractor().extract( + repo, + "https://example.test/acme/repo-scoping.git", + ) + + assert metadata.name == "repo-scoping" diff --git a/tests/test_repository_scanner.py b/tests/test_repository_scanner.py index 103b0ac..71281bf 100644 --- a/tests/test_repository_scanner.py +++ b/tests/test_repository_scanner.py @@ -1,4 +1,4 @@ -from repo_registry.repo_scanning.scanner import DeterministicScanner +from repo_scoping.repo_scanning.scanner import DeterministicScanner from tests.fixtures import ( write_javascript_typescript_package_repo, write_misleading_docs_repo, diff --git a/tests/test_scanner_coevolution.py b/tests/test_scanner_coevolution.py index 08ad0ce..c4f6978 100644 --- a/tests/test_scanner_coevolution.py +++ b/tests/test_scanner_coevolution.py @@ -1,9 +1,9 @@ import json from pathlib import Path -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore def test_llm_connect_provider_expectations_are_detected_without_llm(tmp_path): diff --git a/tests/test_scope_context_api.py b/tests/test_scope_context_api.py index db9849f..8ae8487 100644 --- a/tests/test_scope_context_api.py +++ b/tests/test_scope_context_api.py @@ -3,7 +3,7 @@ from pathlib import Path from fastapi.testclient import TestClient -from repo_registry.web_api.app import Settings, app, get_settings +from repo_scoping.web_api.app import Settings, app, get_settings def override_settings(tmp_path): diff --git a/tests/test_scope_generator.py b/tests/test_scope_generator.py index 2986e0a..30e741d 100644 --- a/tests/test_scope_generator.py +++ b/tests/test_scope_generator.py @@ -1,8 +1,8 @@ -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.scope.generator import SCOPE_SECTIONS, ScopeGenerator -from repo_registry.scope.validator import ScopeValidator -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.scope.generator import SCOPE_SECTIONS, ScopeGenerator +from repo_scoping.scope.validator import ScopeValidator +from repo_scoping.storage.sqlite import RegistryStore def make_service(tmp_path): @@ -15,7 +15,7 @@ def test_scope_generator_renders_canonical_sections_and_capability_blocks(tmp_pa service = make_service(tmp_path) repository = service.register_repository( name="Repo Registry", - url="https://example.test/coulomb/repo-registry.git", + url="https://example.test/coulomb/repo-scoping.git", description="Generates repository scope files from approved characteristics.", ) service.update_scope( @@ -46,10 +46,10 @@ def test_scope_generator_renders_canonical_sections_and_capability_blocks(tmp_pa type="business-usecase", primary_class="business-usecase", attributes=["scope", "preview"], - location="src/repo_registry/scope/generator.py", + location="src/repo_scoping/scope/generator.py", ) - content = ScopeGenerator(service).generate("repo-registry") + content = ScopeGenerator(service).generate("repo-scoping") assert content.startswith("# SCOPE\n") for section in SCOPE_SECTIONS: @@ -57,7 +57,7 @@ def test_scope_generator_renders_canonical_sections_and_capability_blocks(tmp_pa assert "Generates and validates SCOPE.md files" in content assert "Maintain Repository Scope" in content assert "Preview generated SCOPE.md" in content - assert "src/repo_registry/scope/generator.py" in content + assert "src/repo_scoping/scope/generator.py" in content assert "```capability" in content assert "type: api" in content assert "title: Generate SCOPE.md" in content diff --git a/tests/test_self_scoping_assessment_export.py b/tests/test_self_scoping_assessment_export.py index 93ea7de..15980ac 100644 --- a/tests/test_self_scoping_assessment_export.py +++ b/tests/test_self_scoping_assessment_export.py @@ -1,7 +1,7 @@ -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.self_scoping.assessment import export_assessment_artifact -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.self_scoping.assessment import export_assessment_artifact +from repo_scoping.storage.sqlite import RegistryStore def make_service(tmp_path): diff --git a/tests/test_self_scoping_comparison.py b/tests/test_self_scoping_comparison.py index da5f1b9..ce7812c 100644 --- a/tests/test_self_scoping_comparison.py +++ b/tests/test_self_scoping_comparison.py @@ -1,6 +1,6 @@ from pathlib import Path -from repo_registry.self_scoping.comparison import ( +from repo_scoping.self_scoping.comparison import ( compare_assessment_to_golden, comparison_markdown, load_json, diff --git a/tests/test_self_scoping_review_store.py b/tests/test_self_scoping_review_store.py index 1896544..27aa044 100644 --- a/tests/test_self_scoping_review_store.py +++ b/tests/test_self_scoping_review_store.py @@ -2,7 +2,7 @@ import json import pytest -from repo_registry.self_scoping.review_store import ( +from repo_scoping.self_scoping.review_store import ( list_assessment_artifacts, list_golden_profiles, load_json_artifact, diff --git a/tests/test_self_scoping_web_ui.py b/tests/test_self_scoping_web_ui.py index 10e4115..f5f4aaa 100644 --- a/tests/test_self_scoping_web_ui.py +++ b/tests/test_self_scoping_web_ui.py @@ -2,7 +2,7 @@ import json from fastapi.testclient import TestClient -from repo_registry.web_api.app import app +from repo_scoping.web_api.app import app def write_json(path, payload): @@ -47,7 +47,7 @@ def seed_review_artifacts(root): { "name": "HTTP API surface", "type": "API", - "location": "src/repo_registry/web_api/app.py", + "location": "src/repo_scoping/web_api/app.py", } ], } @@ -76,7 +76,7 @@ def seed_review_artifacts(root): { "name": "HTTP API surface", "type": "API", - "location": "src/repo_registry/web_api/app.py", + "location": "src/repo_scoping/web_api/app.py", } ], } @@ -92,7 +92,7 @@ def seed_review_artifacts(root): def test_self_scoping_ui_compares_and_records_outcome(tmp_path, monkeypatch): root = tmp_path / "self-scoping" seed_review_artifacts(root) - monkeypatch.setenv("REPO_REGISTRY_SELF_SCOPING_ROOT", str(root)) + monkeypatch.setenv("REPO_SCOPING_SELF_SCOPING_ROOT", str(root)) client = TestClient(app) index = client.get("/ui/self-scoping") @@ -126,7 +126,7 @@ def test_self_scoping_ui_compares_and_records_outcome(tmp_path, monkeypatch): def test_self_scoping_ui_compares_two_assessment_runs(tmp_path, monkeypatch): root = tmp_path / "self-scoping" seed_review_artifacts(root) - monkeypatch.setenv("REPO_REGISTRY_SELF_SCOPING_ROOT", str(root)) + monkeypatch.setenv("REPO_SCOPING_SELF_SCOPING_ROOT", str(root)) client = TestClient(app) review = client.get( diff --git a/tests/test_storage_migrations.py b/tests/test_storage_migrations.py index 08060bc..ba4d0a2 100644 --- a/tests/test_storage_migrations.py +++ b/tests/test_storage_migrations.py @@ -1,8 +1,8 @@ import sqlite3 -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore def make_service(tmp_path): diff --git a/tests/test_trusted_auto_approval_migration.py b/tests/test_trusted_auto_approval_migration.py index d239dc8..dc5133b 100644 --- a/tests/test_trusted_auto_approval_migration.py +++ b/tests/test_trusted_auto_approval_migration.py @@ -1,6 +1,6 @@ -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore def make_service(tmp_path): diff --git a/tests/test_web_api.py b/tests/test_web_api.py index 61a7ec7..42edd57 100644 --- a/tests/test_web_api.py +++ b/tests/test_web_api.py @@ -3,11 +3,11 @@ import sqlite3 from fastapi.testclient import TestClient -from repo_registry.core.service import RegistryService -from repo_registry.repo_ingestion.git import GitIngestionService -from repo_registry.storage.sqlite import RegistryStore -from repo_registry.web_api import app as app_module -from repo_registry.web_api.app import Settings, app, get_service, get_settings +from repo_scoping.core.service import RegistryService +from repo_scoping.repo_ingestion.git import GitIngestionService +from repo_scoping.storage.sqlite import RegistryStore +from repo_scoping.web_api import app as app_module +from repo_scoping.web_api.app import Settings, app, get_service, get_settings def add_candidate_capability(database_path, repository_id, analysis_run_id, name): @@ -1063,12 +1063,12 @@ def test_api_service_settings_can_enable_hashing_embedding_provider(tmp_path): def test_settings_can_load_from_environment(monkeypatch): - monkeypatch.setenv("REPO_REGISTRY_DATABASE_PATH", "var/env.sqlite3") - monkeypatch.setenv("REPO_REGISTRY_CHECKOUT_ROOT", "var/env-checkouts") - monkeypatch.setenv("REPO_REGISTRY_LLM_PROVIDER", "mock") - monkeypatch.setenv("REPO_REGISTRY_LLM_MODEL", "demo-model") - monkeypatch.setenv("REPO_REGISTRY_EMBEDDING_PROVIDER", "hashing") - monkeypatch.setenv("REPO_REGISTRY_LOG_LEVEL", "DEBUG") + monkeypatch.setenv("REPO_SCOPING_DATABASE_PATH", "var/env.sqlite3") + monkeypatch.setenv("REPO_SCOPING_CHECKOUT_ROOT", "var/env-checkouts") + monkeypatch.setenv("REPO_SCOPING_LLM_PROVIDER", "mock") + monkeypatch.setenv("REPO_SCOPING_LLM_MODEL", "demo-model") + monkeypatch.setenv("REPO_SCOPING_EMBEDDING_PROVIDER", "hashing") + monkeypatch.setenv("REPO_SCOPING_LOG_LEVEL", "DEBUG") settings = Settings() @@ -2696,7 +2696,7 @@ def test_ui_manual_registry_entry_loop(tmp_path): delete_repository_response = client.post( f"{repository_path}/delete", - data={"confirm_name": "Manual Repo"}, + data={"confirm_name": "manual-repo"}, follow_redirects=False, ) assert delete_repository_response.status_code == 303 diff --git a/workplans/RREG-WP-0017-finalize-repo-scoping-rename.md b/workplans/RREG-WP-0017-finalize-repo-scoping-rename.md new file mode 100644 index 0000000..3d31d21 --- /dev/null +++ b/workplans/RREG-WP-0017-finalize-repo-scoping-rename.md @@ -0,0 +1,98 @@ +--- +id: RREG-WP-0017 +type: workplan +title: "Finalize Repo-Scoping Rename" +domain: capabilities +repo: repo-scoping +status: done +owner: codex +topic_slug: foerster-capabilities +created: "2026-05-15" +updated: "2026-05-15" +state_hub_workstream_id: "dbeae3c5-74fc-46c0-be61-1bd8d81e65df" +--- + +# Finalize Repo-Scoping Rename + +The repo has already moved from the old `repo-registry` product name to +repo-scoping, but the implementation still exposes several legacy names. That +leaked into self-registration: metadata extraction preferred package metadata, +so a checkout could still be registered as `repo-registry` even when the +repository path and current project identity are `repo-scoping`. + +Because this repository has not entered production use, there is no need to keep +old names as compatibility aliases. This workplan removes the legacy runtime +names and makes repo identity follow the repository source first. + +## T01: Prefer Repository Source Identity + +```task +id: RREG-WP-0017-T01 +status: done +priority: high +state_hub_task_id: "2e0dbb87-e095-4e46-a37e-b54860b1f14d" +``` + +Repository registration should derive the default repository name from the +submitted checkout path or URL before falling back to package metadata. + +Acceptance criteria: +- A local checkout under `repo-scoping` registers as `repo-scoping` by default. +- Package names still provide a fallback when the source path has no meaningful + repository identity. +- Regression coverage protects the priority order. + +Implementation note 2026-05-15: metadata extraction now uses a non-generic +checkout path or URL slug before package and README names. This prevents a +source checkout named `repo-scoping` from being registered as an old package +name, while still allowing package metadata to fill generic temporary checkout +names such as `repo` or `checkout`. + +## T02: Remove Legacy Runtime Names + +```task +id: RREG-WP-0017-T02 +status: done +priority: high +state_hub_task_id: "d7fefaa5-1dc0-4817-a13c-2bada32a86c7" +``` + +Rename the package, environment variables, default database path, commands, +documentation, and non-historical implementation references from +`repo-registry` / `repo_registry` / `REPO_REGISTRY` to +`repo-scoping` / `repo_scoping` / `REPO_SCOPING`. + +Acceptance criteria: +- The import package is `repo_scoping`. +- Runtime configuration uses `REPO_SCOPING_*` environment variables. +- The default local database is `var/repo-scoping.sqlite3`. +- No compatibility shim remains for the old pre-production name. + +Implementation note 2026-05-15: renamed the source package to `repo_scoping`, +updated imports, CLI entry points, settings, self-scoping release metadata, +candidate source seeds, and docs. The local editable install now exposes the +`repo-scoping` distribution and the `repo-scoping` console script imports +`repo_scoping.cli`. + +## T03: Validate And Capture The Rename + +```task +id: RREG-WP-0017-T03 +status: done +priority: medium +state_hub_task_id: "70b29772-67ac-4074-988a-4caf2411b7b1" +``` + +Update tests, docs, and self-scoping fixtures affected by the rename, then run +the relevant regression suite. + +Acceptance criteria: +- The full test suite passes. +- The State Hub sync accepts the workplan and task status. +- Remaining historical `repo-registry` references are limited to completed + historical records or old assessment artifacts. + +Implementation note 2026-05-15: full regression suite passed with 190 tests. +The only remaining tracked old-name reference outside historical assessment and +workplan records is a deliberate metadata regression fixture proving that the +new source-identity priority overrides an old package name.