Finalize repo-scoping runtime rename
This commit is contained in:
parent
084159e51c
commit
28fad1b248
62 changed files with 445 additions and 305 deletions
|
|
@ -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/
|
||||
|
|
|
|||
34
CLAUDE.md
34
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
|
||||
|
||||
|
|
|
|||
12
INTENT.md
12
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.
|
||||
|
|
|
|||
2
Makefile
2
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 \
|
||||
|
|
|
|||
19
README.md
19
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}`.
|
||||
|
|
|
|||
12
SCOPE.md
12
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from repo_registry.semantic.embeddings import (
|
||||
from repo_scoping.semantic.embeddings import (
|
||||
EmbeddingProvider,
|
||||
HashingEmbeddingProvider,
|
||||
cosine_similarity,
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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")',
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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=""):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from repo_registry.acceptance import (
|
||||
from repo_scoping.acceptance import (
|
||||
active_quality_criteria_version,
|
||||
criteria_registry_markdown,
|
||||
load_quality_criteria,
|
||||
|
|
|
|||
|
|
@ -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"):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
98
workplans/RREG-WP-0017-finalize-repo-scoping-rename.md
Normal file
98
workplans/RREG-WP-0017-finalize-repo-scoping-rename.md
Normal file
|
|
@ -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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue