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
|
## 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
|
source-linked maps of `Ability → Capability → Feature → Evidence`. Deterministic
|
||||||
scanners establish observed facts; LLM-assisted extractors propose interpreted
|
scanners establish observed facts; LLM-assisted extractors propose interpreted
|
||||||
claims; humans or trusted agents approve registry truth.
|
claims; humans or trusted agents approve registry truth.
|
||||||
|
|
@ -154,7 +154,7 @@ Task description.
|
||||||
pip install -e ".[dev]"
|
pip install -e ".[dev]"
|
||||||
|
|
||||||
# Run dev server
|
# Run dev server
|
||||||
uvicorn src.repo_registry.app:app --reload
|
uvicorn repo_scoping.web_api.app:app --reload
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
pytest 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]"
|
pip install -e ".[dev]"
|
||||||
|
|
||||||
# Run dev server (port 8001)
|
# 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
|
# Run tests
|
||||||
pytest
|
pytest
|
||||||
|
|
@ -20,8 +20,6 @@ pytest tests/test_web_api.py # single file
|
||||||
curl http://127.0.0.1:8001/health
|
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
|
## Architecture
|
||||||
|
|
||||||
The service maps Git repositories to reviewable scope maps using a fixed hierarchy:
|
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.)
|
4. `DeterministicScanner` produces `ObservedFact` objects (files, languages, manifests, APIs, etc.)
|
||||||
5. `ContentExtractor` chunks files into searchable segments
|
5. `ContentExtractor` chunks files into searchable segments
|
||||||
6. `CandidateGraphGenerator` builds a draft ability→capability→feature→evidence tree from facts
|
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`
|
8. Candidates are stored; humans or agents review them via `POST .../candidate-graph/approve`
|
||||||
9. Approved characteristics feed `ScopeGenerator` to produce `SCOPE.md`
|
9. Approved characteristics feed `ScopeGenerator` to produce `SCOPE.md`
|
||||||
|
|
||||||
|
|
@ -46,17 +44,17 @@ Scope → Ability → Capability → Feature → Evidence → ObservedFact
|
||||||
|
|
||||||
| Component | Path |
|
| Component | Path |
|
||||||
|-----------|------|
|
|-----------|------|
|
||||||
| FastAPI routes + DI | `src/repo_registry/web_api/app.py` |
|
| FastAPI routes + DI | `src/repo_scoping/web_api/app.py` |
|
||||||
| Orchestration | `src/repo_registry/core/service.py` |
|
| Orchestration | `src/repo_scoping/core/service.py` |
|
||||||
| Frozen dataclasses | `src/repo_registry/core/models.py` |
|
| Frozen dataclasses | `src/repo_scoping/core/models.py` |
|
||||||
| Deterministic scanner | `src/repo_registry/repo_scanning/scanner.py` |
|
| Deterministic scanner | `src/repo_scoping/repo_scanning/scanner.py` |
|
||||||
| Candidate graph builder | `src/repo_registry/candidate_graph/generator.py` |
|
| Candidate graph builder | `src/repo_scoping/candidate_graph/generator.py` |
|
||||||
| SQLite store | `src/repo_registry/storage/sqlite.py` |
|
| SQLite store | `src/repo_scoping/storage/sqlite.py` |
|
||||||
| Schema migration | `migrations/0001_initial.sql` |
|
| 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.
|
**Semantic search** uses `HashingEmbeddingProvider` by default — deterministic, no external service required.
|
||||||
|
|
||||||
|
|
@ -64,12 +62,12 @@ Scope → Ability → Capability → Feature → Evidence → ObservedFact
|
||||||
|
|
||||||
| Variable | Default | Purpose |
|
| Variable | Default | Purpose |
|
||||||
|----------|---------|---------|
|
|----------|---------|---------|
|
||||||
| `REPO_REGISTRY_DATABASE_PATH` | `var/repo-registry.sqlite3` | SQLite file |
|
| `REPO_SCOPING_DATABASE_PATH` | `var/repo-scoping.sqlite3` | SQLite file |
|
||||||
| `REPO_REGISTRY_CHECKOUT_ROOT` | `var/checkouts` | Git clone cache |
|
| `REPO_SCOPING_CHECKOUT_ROOT` | `var/checkouts` | Git clone cache |
|
||||||
| `REPO_REGISTRY_LLM_ENABLED` | `true` | Enable LLM extraction |
|
| `REPO_SCOPING_LLM_ENABLED` | `true` | Enable LLM extraction |
|
||||||
| `REPO_REGISTRY_LLM_PROVIDER` | — | e.g. `gemini`, `anthropic` |
|
| `REPO_SCOPING_LLM_PROVIDER` | — | e.g. `gemini`, `anthropic` |
|
||||||
| `REPO_REGISTRY_LLM_MODEL` | — | e.g. `gemini-2.5-flash` |
|
| `REPO_SCOPING_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_STATE_HUB_BASE_URL` | `http://127.0.0.1:8000` | State Hub for coordination |
|
||||||
|
|
||||||
## State Hub & Workplans
|
## State Hub & Workplans
|
||||||
|
|
||||||
|
|
|
||||||
12
INTENT.md
12
INTENT.md
|
|
@ -136,11 +136,11 @@ characteristics support those claims.
|
||||||
## Getting Oriented
|
## Getting Oriented
|
||||||
|
|
||||||
- Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`.
|
- Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`.
|
||||||
- Key files / directories: `src/repo_registry/web_api/app.py`,
|
- Key files / directories: `src/repo_scoping/web_api/app.py`,
|
||||||
`src/repo_registry/core/service.py`, `src/repo_registry/scope/`,
|
`src/repo_scoping/core/service.py`, `src/repo_scoping/scope/`,
|
||||||
`src/repo_registry/candidate_graph/`, `src/repo_registry/repo_scanning/`,
|
`src/repo_scoping/candidate_graph/`, `src/repo_scoping/repo_scanning/`,
|
||||||
`docs/scope-md-spec.md`, and `workplans/`.
|
`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.
|
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 /
|
- The product and managed repository identity are Repository Scoping /
|
||||||
`repo-scoping`.
|
`repo-scoping`.
|
||||||
- The Python package name `repo_registry`, `REPO_REGISTRY_` environment prefix,
|
- The Python package name `repo_scoping`, `REPO_SCOPING_` environment prefix,
|
||||||
and default SQLite filename remain compatibility details.
|
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 \
|
@if [ -f $(PIDFILE) ] && kill -0 $$(cat $(PIDFILE)) 2>/dev/null; then \
|
||||||
echo "Already running (PID $$(cat $(PIDFILE)))"; \
|
echo "Already running (PID $$(cat $(PIDFILE)))"; \
|
||||||
else \
|
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 & \
|
>> $(LOGFILE) 2>&1 & \
|
||||||
PID=""; \
|
PID=""; \
|
||||||
for i in $$(seq 1 50); do \
|
for i in $$(seq 1 50); do \
|
||||||
|
|
|
||||||
19
README.md
19
README.md
|
|
@ -27,10 +27,12 @@ pytest
|
||||||
Run the API:
|
Run the API:
|
||||||
|
|
||||||
```bash
|
```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
|
## 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"}'
|
-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
|
```bash
|
||||||
curl http://127.0.0.1:8000/repos/1/ability-map
|
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
|
The FastAPI settings object also accepts `llm_provider` and `llm_model`. By
|
||||||
default `llm_provider` is unset, so analysis is fully offline and deterministic.
|
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
|
```bash
|
||||||
REPO_REGISTRY_LLM_PROVIDER=gemini
|
REPO_SCOPING_LLM_PROVIDER=gemini
|
||||||
REPO_REGISTRY_LLM_MODEL=gemini-2.5-flash
|
REPO_SCOPING_LLM_MODEL=gemini-2.5-flash
|
||||||
```
|
```
|
||||||
|
|
||||||
LLM assistance can also be disabled even when a provider is configured:
|
LLM assistance can also be disabled even when a provider is configured:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
REPO_REGISTRY_LLM_ENABLED=false
|
REPO_SCOPING_LLM_ENABLED=false
|
||||||
```
|
```
|
||||||
|
|
||||||
Individual analysis requests may opt out with `{"use_llm_assistance": 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
|
## Getting Oriented
|
||||||
|
|
||||||
- Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`.
|
- Start with: `README.md`, `AGENTS.md`, and this `SCOPE.md`.
|
||||||
- Key files / directories: `src/repo_registry/web_api/app.py`,
|
- Key files / directories: `src/repo_scoping/web_api/app.py`,
|
||||||
`src/repo_registry/core/service.py`, `src/repo_registry/scope/`,
|
`src/repo_scoping/core/service.py`, `src/repo_scoping/scope/`,
|
||||||
`src/repo_registry/candidate_graph/`, `src/repo_registry/repo_scanning/`,
|
`src/repo_scoping/candidate_graph/`, `src/repo_scoping/repo_scanning/`,
|
||||||
`docs/scope-md-spec.md`, and `workplans/`.
|
`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.
|
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 /
|
- The product and managed repository identity are Repository Scoping /
|
||||||
`repo-scoping`.
|
`repo-scoping`.
|
||||||
- The Python package name `repo_registry`, `REPO_REGISTRY_` environment prefix,
|
- The Python package name `repo_scoping`, `REPO_SCOPING_` environment prefix,
|
||||||
and default SQLite filename remain compatibility details.
|
and default SQLite filename are the current runtime names.
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@ Repository Scoping service.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Configuration is read from environment variables with the `REPO_REGISTRY_`
|
Configuration is read from environment variables with the `REPO_SCOPING_`
|
||||||
prefix. That prefix is retained as an implementation compatibility detail after
|
prefix. The same naming is used by the import package and default local
|
||||||
the product rename from Repository Ability Registry to Repository Scoping.
|
database path so service identity stays aligned with Repository Scoping.
|
||||||
|
|
||||||
| Variable | Default | Purpose |
|
| Variable | Default | Purpose |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `REPO_REGISTRY_DATABASE_PATH` | `var/repo-registry.sqlite3` | SQLite database file used by the default store. |
|
| `REPO_SCOPING_DATABASE_PATH` | `var/repo-scoping.sqlite3` | SQLite database file used by the default store. |
|
||||||
| `REPO_REGISTRY_CHECKOUT_ROOT` | `var/checkouts` | Local checkout cache used during repository ingestion. |
|
| `REPO_SCOPING_CHECKOUT_ROOT` | `var/checkouts` | Local checkout cache used during repository ingestion. |
|
||||||
| `REPO_REGISTRY_LLM_PROVIDER` | unset | Optional LLM provider name for candidate extraction. |
|
| `REPO_SCOPING_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_SCOPING_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_SCOPING_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_LOG_LEVEL` | `INFO` | Log level for the `repo_scoping.operations` structured event logger. |
|
||||||
|
|
||||||
## Health Checks
|
## Health Checks
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ be checked locally:
|
||||||
{
|
{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"database": {
|
"database": {
|
||||||
"path": "var/repo-registry.sqlite3",
|
"path": "var/repo-scoping.sqlite3",
|
||||||
"reachable": true,
|
"reachable": true,
|
||||||
"error": null
|
"error": null
|
||||||
},
|
},
|
||||||
|
|
@ -44,13 +44,13 @@ ingestion path.
|
||||||
|
|
||||||
## Structured Logs
|
## 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,
|
single-line JSON messages. Current events include repository registration,
|
||||||
analysis start/completion/failure, LLM extraction usage/failure, and review
|
analysis start/completion/failure, LLM extraction usage/failure, and review
|
||||||
decisions.
|
decisions.
|
||||||
|
|
||||||
Configure the Python or ASGI server logging stack to route this logger to the
|
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.
|
level used by API-created service instances.
|
||||||
|
|
||||||
## SQLite Backup And Restore
|
## SQLite Backup And Restore
|
||||||
|
|
@ -60,18 +60,18 @@ continue while the backup is created:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p backups
|
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
|
For the most conservative backup window, stop writes first, run the backup, then
|
||||||
resume the service. Verify a backup with:
|
resume the service. Verify a backup with:
|
||||||
|
|
||||||
```bash
|
```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
|
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
|
## PostgreSQL Migration Notes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -586,7 +586,7 @@
|
||||||
},
|
},
|
||||||
"contamination_sources": [
|
"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."
|
"reason": "Scanner rule vocabulary was treated as repo-owned capability evidence."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,16 @@
|
||||||
"name": "Create and update repository records",
|
"name": "Create and update repository records",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"src/repo_registry/web_ui/views.py"
|
"src/repo_scoping/web_ui/views.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Resolve local or remote Git checkouts",
|
"name": "Resolve local or remote Git checkouts",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/repo_ingestion/git.py",
|
"src/repo_scoping/repo_ingestion/git.py",
|
||||||
"tests/test_git_ingestion.py"
|
"tests/test_git_ingestion.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
"name": "Import repository metadata",
|
"name": "Import repository metadata",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/repo_ingestion/metadata.py",
|
"src/repo_scoping/repo_ingestion/metadata.py",
|
||||||
"tests/test_repository_metadata.py"
|
"tests/test_repository_metadata.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
"name": "Detect source languages, manifests, docs, tests, config, and interfaces",
|
"name": "Detect source languages, manifests, docs, tests, config, and interfaces",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/repo_scanning/scanner.py",
|
"src/repo_scoping/repo_scanning/scanner.py",
|
||||||
"tests/test_repository_scanner.py"
|
"tests/test_repository_scanner.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
"name": "Classify source roles for facts",
|
"name": "Classify source roles for facts",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/repo_scanning/scanner.py",
|
"src/repo_scoping/repo_scanning/scanner.py",
|
||||||
"docs/characteristic-evidence-model.md"
|
"docs/characteristic-evidence-model.md"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -77,7 +77,7 @@
|
||||||
"name": "Preserve analysis snapshots and fact records",
|
"name": "Preserve analysis snapshots and fact records",
|
||||||
"primary_class": "storage",
|
"primary_class": "storage",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/storage/sqlite.py",
|
"src/repo_scoping/storage/sqlite.py",
|
||||||
"migrations/0001_initial.sql"
|
"migrations/0001_initial.sql"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
"name": "Create source-linked content chunks from observed facts",
|
"name": "Create source-linked content chunks from observed facts",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/content_indexing/extractor.py",
|
"src/repo_scoping/content_indexing/extractor.py",
|
||||||
"tests/test_content_indexing.py"
|
"tests/test_content_indexing.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -100,8 +100,8 @@
|
||||||
"name": "Carry source-role metadata into downstream generation",
|
"name": "Carry source-role metadata into downstream generation",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/content_indexing/extractor.py",
|
"src/repo_scoping/content_indexing/extractor.py",
|
||||||
"src/repo_registry/llm_extraction/extractor.py"
|
"src/repo_scoping/llm_extraction/extractor.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -115,8 +115,8 @@
|
||||||
"name": "Build candidate abilities, capabilities, features, and evidence",
|
"name": "Build candidate abilities, capabilities, features, and evidence",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/candidate_graph/generator.py",
|
"src/repo_scoping/candidate_graph/generator.py",
|
||||||
"src/repo_registry/candidate_graph/normalization.py",
|
"src/repo_scoping/candidate_graph/normalization.py",
|
||||||
"tests/test_candidate_graph.py"
|
"tests/test_candidate_graph.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -124,8 +124,8 @@
|
||||||
"name": "Optionally map structured LLM extraction into candidates",
|
"name": "Optionally map structured LLM extraction into candidates",
|
||||||
"primary_class": "integration",
|
"primary_class": "integration",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/llm_extraction/extractor.py",
|
"src/repo_scoping/llm_extraction/extractor.py",
|
||||||
"src/repo_registry/llm_extraction/mapper.py",
|
"src/repo_scoping/llm_extraction/mapper.py",
|
||||||
"tests/test_llm_extraction.py"
|
"tests/test_llm_extraction.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -140,9 +140,9 @@
|
||||||
"name": "Edit, reject, merge, and relink candidate graph entries",
|
"name": "Edit, reject, merge, and relink candidate graph entries",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"src/repo_registry/web_ui/views.py",
|
"src/repo_scoping/web_ui/views.py",
|
||||||
"tests/test_registry_service.py"
|
"tests/test_registry_service.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -150,16 +150,16 @@
|
||||||
"name": "Publish approved characteristic maps after review",
|
"name": "Publish approved characteristic maps after review",
|
||||||
"primary_class": "storage",
|
"primary_class": "storage",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/storage/sqlite.py"
|
"src/repo_scoping/storage/sqlite.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Record review decisions and expectation gaps",
|
"name": "Record review decisions and expectation gaps",
|
||||||
"primary_class": "audit",
|
"primary_class": "audit",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/web_api/schemas.py"
|
"src/repo_scoping/web_api/schemas.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -173,8 +173,8 @@
|
||||||
"name": "Search approved abilities, capabilities, features, and evidence",
|
"name": "Search approved abilities, capabilities, features, and evidence",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/semantic/embeddings.py",
|
"src/repo_scoping/semantic/embeddings.py",
|
||||||
"tests/test_registry_service.py"
|
"tests/test_registry_service.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -182,15 +182,15 @@
|
||||||
"name": "Compare repositories and identify capability gaps",
|
"name": "Compare repositories and identify capability gaps",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/web_api/app.py"
|
"src/repo_scoping/web_api/app.py"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Export repository profiles",
|
"name": "Export repository profiles",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"docs/api-contract.md"
|
"docs/api-contract.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +205,7 @@
|
||||||
"name": "Render SCOPE.md from approved characteristics",
|
"name": "Render SCOPE.md from approved characteristics",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/scope/generator.py",
|
"src/repo_scoping/scope/generator.py",
|
||||||
"tests/test_scope_generator.py",
|
"tests/test_scope_generator.py",
|
||||||
"docs/scope-md-spec.md"
|
"docs/scope-md-spec.md"
|
||||||
]
|
]
|
||||||
|
|
@ -214,9 +214,9 @@
|
||||||
"name": "Diff, validate, and write scope files",
|
"name": "Diff, validate, and write scope files",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/scope/validator.py",
|
"src/repo_scoping/scope/validator.py",
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"src/repo_registry/web_ui/views.py"
|
"src/repo_scoping/web_ui/views.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -230,7 +230,7 @@
|
||||||
"name": "Model dependencies between facts, evidence, features, capabilities, abilities, and scope",
|
"name": "Model dependencies between facts, evidence, features, capabilities, abilities, and scope",
|
||||||
"primary_class": "backend",
|
"primary_class": "backend",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"docs/dependency-aware-scope-propagation.md",
|
"docs/dependency-aware-scope-propagation.md",
|
||||||
"docs/dependency-visualization-exploration.md"
|
"docs/dependency-visualization-exploration.md"
|
||||||
]
|
]
|
||||||
|
|
@ -239,7 +239,7 @@
|
||||||
"name": "Render dependency graph views and profiles",
|
"name": "Render dependency graph views and profiles",
|
||||||
"primary_class": "ui",
|
"primary_class": "ui",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/web_ui/views.py",
|
"src/repo_scoping/web_ui/views.py",
|
||||||
"tests/test_web_api.py"
|
"tests/test_web_api.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +254,7 @@
|
||||||
"name": "Return compact JSON scope context by repository slug",
|
"name": "Return compact JSON scope context by repository slug",
|
||||||
"primary_class": "api",
|
"primary_class": "api",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"docs/schemas/repo-scope-context-response.json",
|
"docs/schemas/repo-scope-context-response.json",
|
||||||
"tests/test_scope_context_api.py"
|
"tests/test_scope_context_api.py"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ development. It produces deterministic token-bucket vectors without any network
|
||||||
dependency. Configure it with:
|
dependency. Configure it with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
REPO_REGISTRY_EMBEDDING_PROVIDER=hashing
|
REPO_SCOPING_EMBEDDING_PROVIDER=hashing
|
||||||
```
|
```
|
||||||
|
|
||||||
When enabled, search combines:
|
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.
|
- Repository Scoping is the product and UI name.
|
||||||
- `repo-scoping` is the managed repository slug, Git remote identity, and State
|
- `repo-scoping` is the managed repository slug, Git remote identity, and State
|
||||||
Hub repository identity.
|
Hub repository identity.
|
||||||
- `repo_registry`, `REPO_REGISTRY_`, and `var/repo-registry.sqlite3` are retained
|
- `repo_scoping`, `REPO_SCOPING_`, and `var/repo-scoping.sqlite3` are the
|
||||||
compatibility names in code and local configuration.
|
current package, environment-prefix, and default SQLite names.
|
||||||
- Repository Ability Registry and `repo-registry` are historical names from
|
- Earlier registry-oriented names are historical only and should not be used in
|
||||||
before the scope-oriented rename.
|
runtime configuration, package imports, or new documentation.
|
||||||
|
|
||||||
## Characteristic Model
|
## Characteristic Model
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ requires = ["setuptools>=68"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "repo-registry"
|
name = "repo-scoping"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Repository Scoping"
|
description = "Repository Scoping"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
@ -22,7 +22,7 @@ dev = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
repo-scoping = "repo_registry.cli:main"
|
repo-scoping = "repo_scoping.cli:main"
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["src"]
|
where = ["src"]
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
from repo_registry.acceptance.agentic import (
|
from repo_scoping.acceptance.agentic import (
|
||||||
AgenticReviewer,
|
AgenticReviewer,
|
||||||
AgenticReviewDecision,
|
AgenticReviewDecision,
|
||||||
AgenticReviewRequest,
|
AgenticReviewRequest,
|
||||||
validate_agentic_review_decision,
|
validate_agentic_review_decision,
|
||||||
validate_agentic_review_decisions,
|
validate_agentic_review_decisions,
|
||||||
)
|
)
|
||||||
from repo_registry.acceptance.criteria import (
|
from repo_scoping.acceptance.criteria import (
|
||||||
active_quality_criteria_version,
|
active_quality_criteria_version,
|
||||||
criteria_registry_dict,
|
criteria_registry_dict,
|
||||||
criteria_registry_json,
|
criteria_registry_json,
|
||||||
criteria_registry_markdown,
|
criteria_registry_markdown,
|
||||||
load_quality_criteria,
|
load_quality_criteria,
|
||||||
)
|
)
|
||||||
from repo_registry.acceptance.gates import (
|
from repo_scoping.acceptance.gates import (
|
||||||
blocking_quality_gate_outcomes,
|
blocking_quality_gate_outcomes,
|
||||||
evaluate_candidate_capability_quality,
|
evaluate_candidate_capability_quality,
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
from repo_registry.acceptance.gates import QualityGateOutcome
|
from repo_scoping.acceptance.gates import QualityGateOutcome
|
||||||
from repo_registry.core.models import CandidateGraph, Repository
|
from repo_scoping.core.models import CandidateGraph, Repository
|
||||||
|
|
||||||
AGENTIC_REVIEW_ACTIONS = {
|
AGENTIC_REVIEW_ACTIONS = {
|
||||||
"approve",
|
"approve",
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import asdict, dataclass
|
from dataclasses import asdict, dataclass
|
||||||
|
|
||||||
from repo_registry.acceptance.criteria import (
|
from repo_scoping.acceptance.criteria import (
|
||||||
QualityCriteriaRegistry,
|
QualityCriteriaRegistry,
|
||||||
QualityCriterion,
|
QualityCriterion,
|
||||||
load_quality_criteria,
|
load_quality_criteria,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import (
|
from repo_scoping.core.models import (
|
||||||
CandidateCapability,
|
CandidateCapability,
|
||||||
CandidateFeature,
|
CandidateFeature,
|
||||||
CandidateGraph,
|
CandidateGraph,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field, replace
|
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)
|
@dataclass(frozen=True)
|
||||||
|
|
@ -59,18 +59,18 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [
|
||||||
(
|
(
|
||||||
"Create and update repository records",
|
"Create and update repository records",
|
||||||
"api",
|
"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",
|
"Resolve local or remote Git checkouts",
|
||||||
"backend",
|
"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",
|
"Import repository metadata",
|
||||||
"backend",
|
"backend",
|
||||||
[
|
[
|
||||||
"src/repo_registry/repo_ingestion/metadata.py",
|
"src/repo_scoping/repo_ingestion/metadata.py",
|
||||||
"tests/test_repository_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",
|
"Detect source languages, manifests, docs, tests, config, and interfaces",
|
||||||
"backend",
|
"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",
|
"Classify source roles for facts",
|
||||||
"backend",
|
"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",
|
"Preserve analysis snapshots and fact records",
|
||||||
"storage",
|
"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",
|
"Create source-linked content chunks from observed facts",
|
||||||
"backend",
|
"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",
|
"Carry source-role metadata into downstream generation",
|
||||||
"backend",
|
"backend",
|
||||||
[
|
[
|
||||||
"src/repo_registry/content_indexing/extractor.py",
|
"src/repo_scoping/content_indexing/extractor.py",
|
||||||
"src/repo_registry/llm_extraction/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",
|
"Build candidate abilities, capabilities, features, and evidence",
|
||||||
"backend",
|
"backend",
|
||||||
[
|
[
|
||||||
"src/repo_registry/candidate_graph/generator.py",
|
"src/repo_scoping/candidate_graph/generator.py",
|
||||||
"src/repo_registry/candidate_graph/normalization.py",
|
"src/repo_scoping/candidate_graph/normalization.py",
|
||||||
"tests/test_candidate_graph.py",
|
"tests/test_candidate_graph.py",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -136,8 +136,8 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [
|
||||||
"Optionally map structured LLM extraction into candidates",
|
"Optionally map structured LLM extraction into candidates",
|
||||||
"integration",
|
"integration",
|
||||||
[
|
[
|
||||||
"src/repo_registry/llm_extraction/extractor.py",
|
"src/repo_scoping/llm_extraction/extractor.py",
|
||||||
"src/repo_registry/llm_extraction/mapper.py",
|
"src/repo_scoping/llm_extraction/mapper.py",
|
||||||
"tests/test_llm_extraction.py",
|
"tests/test_llm_extraction.py",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -152,20 +152,20 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [
|
||||||
"Edit, reject, merge, and relink candidate graph entries",
|
"Edit, reject, merge, and relink candidate graph entries",
|
||||||
"api",
|
"api",
|
||||||
[
|
[
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"tests/test_registry_service.py",
|
"tests/test_registry_service.py",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Publish approved characteristic maps after review",
|
"Publish approved characteristic maps after review",
|
||||||
"storage",
|
"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",
|
"Record review decisions and expectation gaps",
|
||||||
"audit",
|
"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",
|
"Search approved abilities, capabilities, features, and evidence",
|
||||||
"api",
|
"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",
|
"Compare repositories and identify capability gaps",
|
||||||
"api",
|
"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",
|
"Export repository profiles",
|
||||||
"api",
|
"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",
|
"Render SCOPE.md from approved characteristics",
|
||||||
"backend",
|
"backend",
|
||||||
[
|
[
|
||||||
"src/repo_registry/scope/generator.py",
|
"src/repo_scoping/scope/generator.py",
|
||||||
"tests/test_scope_generator.py",
|
"tests/test_scope_generator.py",
|
||||||
"docs/scope-md-spec.md",
|
"docs/scope-md-spec.md",
|
||||||
],
|
],
|
||||||
|
|
@ -209,8 +209,8 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [
|
||||||
"Diff, validate, and write scope files",
|
"Diff, validate, and write scope files",
|
||||||
"api",
|
"api",
|
||||||
[
|
[
|
||||||
"src/repo_registry/scope/validator.py",
|
"src/repo_scoping/scope/validator.py",
|
||||||
"src/repo_registry/web_api/app.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",
|
"Model dependencies between facts, evidence, features, capabilities, abilities, and scope",
|
||||||
"backend",
|
"backend",
|
||||||
[
|
[
|
||||||
"src/repo_registry/core/service.py",
|
"src/repo_scoping/core/service.py",
|
||||||
"docs/dependency-aware-scope-propagation.md",
|
"docs/dependency-aware-scope-propagation.md",
|
||||||
"docs/dependency-visualization-exploration.md",
|
"docs/dependency-visualization-exploration.md",
|
||||||
],
|
],
|
||||||
|
|
@ -232,7 +232,7 @@ REPO_SCOPING_NATIVE_CAPABILITY_SEEDS = [
|
||||||
(
|
(
|
||||||
"Render dependency graph views and profiles",
|
"Render dependency graph views and profiles",
|
||||||
"ui",
|
"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",
|
"Return compact JSON scope context by repository slug",
|
||||||
"api",
|
"api",
|
||||||
[
|
[
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
"docs/schemas/repo-scope-context-response.json",
|
"docs/schemas/repo-scope-context-response.json",
|
||||||
"tests/test_scope_context_api.py",
|
"tests/test_scope_context_api.py",
|
||||||
],
|
],
|
||||||
|
|
@ -661,7 +661,7 @@ class CandidateGraphGenerator:
|
||||||
identity = f"{repository.name} {repository.url} {repository.description or ''}".lower()
|
identity = f"{repository.name} {repository.url} {repository.description or ''}".lower()
|
||||||
if "repo-scoping" in identity or "repository scoping" in identity:
|
if "repo-scoping" in identity or "repository scoping" in identity:
|
||||||
return True
|
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(
|
def _facts_for_paths(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ from __future__ import annotations
|
||||||
import re
|
import re
|
||||||
from dataclasses import replace
|
from dataclasses import replace
|
||||||
|
|
||||||
from repo_registry.candidate_graph.generator import (
|
from repo_scoping.candidate_graph.generator import (
|
||||||
CandidateAbilityDraft,
|
CandidateAbilityDraft,
|
||||||
CandidateCapabilityDraft,
|
CandidateCapabilityDraft,
|
||||||
CandidateEvidenceDraft,
|
CandidateEvidenceDraft,
|
||||||
CandidateFeatureDraft,
|
CandidateFeatureDraft,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import SourceReference
|
from repo_scoping.core.models import SourceReference
|
||||||
|
|
||||||
|
|
||||||
STOP_WORDS = {
|
STOP_WORDS = {
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,24 @@ from dataclasses import asdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
criteria_registry_json,
|
criteria_registry_json,
|
||||||
criteria_registry_markdown,
|
criteria_registry_markdown,
|
||||||
load_quality_criteria,
|
load_quality_criteria,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import CharacteristicRebuildResult, Repository
|
from repo_scoping.core.models import CharacteristicRebuildResult, Repository
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter
|
from repo_scoping.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.self_scoping.assessment import artifact_json, export_assessment_artifact
|
from repo_scoping.self_scoping.assessment import artifact_json, export_assessment_artifact
|
||||||
from repo_registry.self_scoping.comparison import (
|
from repo_scoping.self_scoping.comparison import (
|
||||||
compare_assessment_to_golden,
|
compare_assessment_to_golden,
|
||||||
comparison_json,
|
comparison_json,
|
||||||
comparison_markdown,
|
comparison_markdown,
|
||||||
load_json,
|
load_json,
|
||||||
)
|
)
|
||||||
from repo_registry.storage.sqlite import NotFoundError, RegistryStore
|
from repo_scoping.storage.sqlite import NotFoundError, RegistryStore
|
||||||
from repo_registry.web_api.app import Settings
|
from repo_scoping.web_api.app import Settings
|
||||||
|
|
||||||
|
|
||||||
def build_parser() -> argparse.ArgumentParser:
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
|
|
@ -56,8 +56,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Confirm a destructive all-repository rebuild.",
|
help="Confirm a destructive all-repository rebuild.",
|
||||||
)
|
)
|
||||||
rebuild.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.")
|
rebuild.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.")
|
||||||
rebuild.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.")
|
rebuild.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.")
|
||||||
export = subparsers.add_parser(
|
export = subparsers.add_parser(
|
||||||
"export-assessment",
|
"export-assessment",
|
||||||
help="Export a completed analysis run as a self-scoping assessment artifact.",
|
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("--reviewer", default="codex", help="Reviewer name recorded in the artifact.")
|
||||||
export.add_argument("--summary", help="Assessment summary override.")
|
export.add_argument("--summary", help="Assessment summary override.")
|
||||||
export.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.")
|
export.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.")
|
||||||
export.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.")
|
export.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.")
|
||||||
compare = subparsers.add_parser(
|
compare = subparsers.add_parser(
|
||||||
"compare-assessment",
|
"compare-assessment",
|
||||||
help="Compare a self-scoping assessment artifact against a golden profile.",
|
help="Compare a self-scoping assessment artifact against a golden profile.",
|
||||||
|
|
@ -155,8 +155,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Return exit code 1 only when comparison status is regression.",
|
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("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.")
|
||||||
self_assess.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.")
|
self_assess.add_argument("--checkout-root", help="Override REPO_SCOPING_CHECKOUT_ROOT.")
|
||||||
self_assess.set_defaults(no_llm=True)
|
self_assess.set_defaults(no_llm=True)
|
||||||
criteria = subparsers.add_parser(
|
criteria = subparsers.add_parser(
|
||||||
"list-quality-criteria",
|
"list-quality-criteria",
|
||||||
|
|
@ -177,8 +177,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||||
"list-legacy-auto-approvals",
|
"list-legacy-auto-approvals",
|
||||||
help="List historical trusted deterministic auto-approval records.",
|
help="List historical trusted deterministic auto-approval records.",
|
||||||
)
|
)
|
||||||
legacy.add_argument("--database-path", help="Override REPO_REGISTRY_DATABASE_PATH.")
|
legacy.add_argument("--database-path", help="Override REPO_SCOPING_DATABASE_PATH.")
|
||||||
legacy.add_argument("--checkout-root", help="Override REPO_REGISTRY_CHECKOUT_ROOT.")
|
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("--output", help="Write inventory output to this path instead of stdout.")
|
||||||
legacy.add_argument(
|
legacy.add_argument(
|
||||||
"--format",
|
"--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"]
|
__all__ = ["ContentChunkCandidate", "ContentExtractor"]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from repo_registry.core.models import ObservedFact
|
from repo_scoping.core.models import ObservedFact
|
||||||
|
|
||||||
|
|
||||||
INDEXED_FACT_KINDS = {
|
INDEXED_FACT_KINDS = {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
LOGGER_NAME = "repo_registry.operations"
|
LOGGER_NAME = "repo_scoping.operations"
|
||||||
|
|
||||||
|
|
||||||
def log_operation(event: str, **fields: Any) -> None:
|
def log_operation(event: str, **fields: Any) -> None:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from collections.abc import Sequence
|
||||||
from dataclasses import asdict, replace
|
from dataclasses import asdict, replace
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
AgenticReviewDecision,
|
AgenticReviewDecision,
|
||||||
AgenticReviewer,
|
AgenticReviewer,
|
||||||
AgenticReviewRequest,
|
AgenticReviewRequest,
|
||||||
|
|
@ -14,7 +14,7 @@ from repo_registry.acceptance import (
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
validate_agentic_review_decisions,
|
validate_agentic_review_decisions,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import (
|
from repo_scoping.core.models import (
|
||||||
AbilitySummary,
|
AbilitySummary,
|
||||||
AnalysisRunDiff,
|
AnalysisRunDiff,
|
||||||
AnalysisRunDiffItem,
|
AnalysisRunDiffItem,
|
||||||
|
|
@ -43,17 +43,17 @@ from repo_registry.core.models import (
|
||||||
TrustedAutoApprovalMigrationRecord,
|
TrustedAutoApprovalMigrationRecord,
|
||||||
enrich_review_decision,
|
enrich_review_decision,
|
||||||
)
|
)
|
||||||
from repo_registry.candidate_graph.generator import CandidateGraphGenerator
|
from repo_scoping.candidate_graph.generator import CandidateGraphGenerator
|
||||||
from repo_registry.candidate_graph.normalization import normalize_candidate_drafts
|
from repo_scoping.candidate_graph.normalization import normalize_candidate_drafts
|
||||||
from repo_registry.content_indexing.extractor import ContentExtractor
|
from repo_scoping.content_indexing.extractor import ContentExtractor
|
||||||
from repo_registry.core.logging import log_operation
|
from repo_scoping.core.logging import log_operation
|
||||||
from repo_registry.llm_extraction.extractor import LLMCandidateExtractor
|
from repo_scoping.llm_extraction.extractor import LLMCandidateExtractor
|
||||||
from repo_registry.llm_extraction.mapper import LLMExtractionMapper
|
from repo_scoping.llm_extraction.mapper import LLMExtractionMapper
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.repo_ingestion.metadata import RepositoryMetadataExtractor
|
from repo_scoping.repo_ingestion.metadata import RepositoryMetadataExtractor
|
||||||
from repo_registry.repo_scanning.scanner import DeterministicScanner
|
from repo_scoping.repo_scanning.scanner import DeterministicScanner
|
||||||
from repo_registry.semantic import EmbeddingProvider, cosine_similarity
|
from repo_scoping.semantic import EmbeddingProvider, cosine_similarity
|
||||||
from repo_registry.storage.sqlite import NotFoundError, RegistryStore
|
from repo_scoping.storage.sqlite import NotFoundError, RegistryStore
|
||||||
|
|
||||||
|
|
||||||
class RegistryService:
|
class RegistryService:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from repo_registry.llm_extraction.extractor import (
|
from repo_scoping.llm_extraction.extractor import (
|
||||||
ExtractedAbility,
|
ExtractedAbility,
|
||||||
ExtractedCapability,
|
ExtractedCapability,
|
||||||
ExtractedEvidence,
|
ExtractedEvidence,
|
||||||
|
|
@ -7,7 +7,7 @@ from repo_registry.llm_extraction.extractor import (
|
||||||
LLMExtractionError,
|
LLMExtractionError,
|
||||||
create_llm_connect_adapter,
|
create_llm_connect_adapter,
|
||||||
)
|
)
|
||||||
from repo_registry.llm_extraction.mapper import LLMExtractionMapper
|
from repo_scoping.llm_extraction.mapper import LLMExtractionMapper
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ExtractedAbility",
|
"ExtractedAbility",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import json
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Protocol
|
from typing import Any, Protocol
|
||||||
|
|
||||||
from repo_registry.core.models import ContentChunk, Repository
|
from repo_scoping.core.models import ContentChunk, Repository
|
||||||
|
|
||||||
|
|
||||||
class LLMExtractionError(ValueError):
|
class LLMExtractionError(ValueError):
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from repo_registry.candidate_graph.generator import (
|
from repo_scoping.candidate_graph.generator import (
|
||||||
CandidateAbilityDraft,
|
CandidateAbilityDraft,
|
||||||
CandidateCapabilityDraft,
|
CandidateCapabilityDraft,
|
||||||
CandidateEvidenceDraft,
|
CandidateEvidenceDraft,
|
||||||
CandidateFeatureDraft,
|
CandidateFeatureDraft,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import ContentChunk, ObservedFact, SourceReference
|
from repo_scoping.core.models import ContentChunk, ObservedFact, SourceReference
|
||||||
from repo_registry.llm_extraction.extractor import ExtractedAbility
|
from repo_scoping.llm_extraction.extractor import ExtractedAbility
|
||||||
|
|
||||||
|
|
||||||
class LLMExtractionMapper:
|
class LLMExtractionMapper:
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,16 @@ class RepositoryMetadataExtractor:
|
||||||
pyproject = self._from_pyproject(root)
|
pyproject = self._from_pyproject(root)
|
||||||
package = self._from_package_json(root)
|
package = self._from_package_json(root)
|
||||||
readme = self._from_readme(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(
|
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=(
|
description=(
|
||||||
pyproject.description
|
pyproject.description
|
||||||
or package.description
|
or package.description
|
||||||
|
|
@ -77,10 +83,13 @@ class RepositoryMetadataExtractor:
|
||||||
return RepositoryMetadata(name=title, description=None)
|
return RepositoryMetadata(name=title, description=None)
|
||||||
return RepositoryMetadata(name="", 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)
|
parsed = urlparse(value)
|
||||||
path = parsed.path if parsed.scheme else 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"):
|
if name.endswith(".git"):
|
||||||
name = name[:-4]
|
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_scoping.scope.generator import ScopeGenerator
|
||||||
from repo_registry.scope.validator import ScopeValidator
|
from repo_scoping.scope.validator import ScopeValidator
|
||||||
|
|
||||||
__all__ = ["ScopeGenerator", "ScopeValidator"]
|
__all__ = ["ScopeGenerator", "ScopeValidator"]
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ from __future__ import annotations
|
||||||
import re
|
import re
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
|
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.storage.sqlite import NotFoundError
|
from repo_scoping.storage.sqlite import NotFoundError
|
||||||
|
|
||||||
|
|
||||||
SCOPE_SECTIONS = [
|
SCOPE_SECTIONS = [
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import re
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
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)
|
@dataclass(frozen=True)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from repo_registry.self_scoping.assessment import export_assessment_artifact
|
from repo_scoping.self_scoping.assessment import export_assessment_artifact
|
||||||
from repo_registry.self_scoping.comparison import compare_assessment_to_golden
|
from repo_scoping.self_scoping.comparison import compare_assessment_to_golden
|
||||||
from repo_registry.self_scoping.review_store import (
|
from repo_scoping.self_scoping.review_store import (
|
||||||
record_assessment_outcome,
|
record_assessment_outcome,
|
||||||
record_assessment_pair_outcome,
|
record_assessment_pair_outcome,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ from importlib import metadata
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
active_quality_criteria_version,
|
active_quality_criteria_version,
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
quality_gate_outcome_dicts,
|
quality_gate_outcome_dicts,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import (
|
from repo_scoping.core.models import (
|
||||||
Ability,
|
Ability,
|
||||||
CandidateAbility,
|
CandidateAbility,
|
||||||
CandidateCapability,
|
CandidateCapability,
|
||||||
|
|
@ -26,7 +26,7 @@ from repo_registry.core.models import (
|
||||||
ReviewDecision,
|
ReviewDecision,
|
||||||
SourceReference,
|
SourceReference,
|
||||||
)
|
)
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
|
|
||||||
|
|
||||||
SCHEMA_VERSION = "self-scoping-assessment/v1"
|
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:
|
def _package_version() -> str:
|
||||||
try:
|
try:
|
||||||
return metadata.version("repo-registry")
|
return metadata.version("repo-scoping")
|
||||||
except metadata.PackageNotFoundError:
|
except metadata.PackageNotFoundError:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from typing import Any
|
||||||
from uuid import uuid4
|
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"
|
OUTCOME_SCHEMA_VERSION = "self-scoping-review-outcome/v1"
|
||||||
ALLOWED_OUTCOMES = {
|
ALLOWED_OUTCOMES = {
|
||||||
"prefer_golden",
|
"prefer_golden",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from repo_registry.semantic.embeddings import (
|
from repo_scoping.semantic.embeddings import (
|
||||||
EmbeddingProvider,
|
EmbeddingProvider,
|
||||||
HashingEmbeddingProvider,
|
HashingEmbeddingProvider,
|
||||||
cosine_similarity,
|
cosine_similarity,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import json
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from repo_registry.core.models import (
|
from repo_scoping.core.models import (
|
||||||
Ability,
|
Ability,
|
||||||
AbilitySummary,
|
AbilitySummary,
|
||||||
AnalysisRun,
|
AnalysisRun,
|
||||||
|
|
@ -30,10 +30,10 @@ from repo_registry.core.models import (
|
||||||
SourceReference,
|
SourceReference,
|
||||||
confidence_label,
|
confidence_label,
|
||||||
)
|
)
|
||||||
from repo_registry.core.logging import log_operation
|
from repo_scoping.core.logging import log_operation
|
||||||
from repo_registry.content_indexing.extractor import ContentChunkCandidate
|
from repo_scoping.content_indexing.extractor import ContentChunkCandidate
|
||||||
from repo_registry.candidate_graph.generator import CandidateAbilityDraft
|
from repo_scoping.candidate_graph.generator import CandidateAbilityDraft
|
||||||
from repo_registry.repo_scanning.scanner import FactCandidate, ScanResult
|
from repo_scoping.repo_scanning.scanner import FactCandidate, ScanResult
|
||||||
|
|
||||||
|
|
||||||
class NotFoundError(ValueError):
|
class NotFoundError(ValueError):
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,19 @@ from fastapi.responses import PlainTextResponse
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
criteria_registry_dict,
|
criteria_registry_dict,
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
load_quality_criteria,
|
load_quality_criteria,
|
||||||
quality_gate_outcome_dicts,
|
quality_gate_outcome_dicts,
|
||||||
)
|
)
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter
|
from repo_scoping.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.semantic import HashingEmbeddingProvider
|
from repo_scoping.semantic import HashingEmbeddingProvider
|
||||||
from repo_registry.scope import ScopeGenerator, ScopeValidator
|
from repo_scoping.scope import ScopeGenerator, ScopeValidator
|
||||||
from repo_registry.storage.sqlite import NotFoundError, RegistryStore
|
from repo_scoping.storage.sqlite import NotFoundError, RegistryStore
|
||||||
from repo_registry.web_api.schemas import (
|
from repo_scoping.web_api.schemas import (
|
||||||
AbilityCreate,
|
AbilityCreate,
|
||||||
AbilitySummaryResponse,
|
AbilitySummaryResponse,
|
||||||
AbilityUpdate,
|
AbilityUpdate,
|
||||||
|
|
@ -86,9 +86,9 @@ def slugify(value: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
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")
|
checkout_root: str = Field(default="var/checkouts")
|
||||||
llm_enabled: bool = Field(default=True)
|
llm_enabled: bool = Field(default=True)
|
||||||
llm_provider: str | None = Field(default=None)
|
llm_provider: str | None = Field(default=None)
|
||||||
|
|
@ -103,7 +103,7 @@ def get_settings() -> Settings:
|
||||||
|
|
||||||
|
|
||||||
def get_service(settings: Settings = Depends(get_settings)) -> RegistryService:
|
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)
|
getattr(logging, settings.log_level.upper(), logging.INFO)
|
||||||
)
|
)
|
||||||
database_path = Path(settings.database_path)
|
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)
|
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 import APIRouter, Depends, Form, HTTPException, Query
|
||||||
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
|
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
quality_gate_outcome_dicts,
|
quality_gate_outcome_dicts,
|
||||||
)
|
)
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.self_scoping.comparison import compare_assessment_to_golden
|
from repo_scoping.self_scoping.comparison import compare_assessment_to_golden
|
||||||
from repo_registry.self_scoping.review_store import (
|
from repo_scoping.self_scoping.review_store import (
|
||||||
ALLOWED_OUTCOMES,
|
ALLOWED_OUTCOMES,
|
||||||
list_assessment_artifacts,
|
list_assessment_artifacts,
|
||||||
list_golden_profiles,
|
list_golden_profiles,
|
||||||
|
|
@ -24,8 +24,8 @@ from repo_registry.self_scoping.review_store import (
|
||||||
record_assessment_outcome,
|
record_assessment_outcome,
|
||||||
record_assessment_pair_outcome,
|
record_assessment_pair_outcome,
|
||||||
)
|
)
|
||||||
from repo_registry.storage.sqlite import NotFoundError
|
from repo_scoping.storage.sqlite import NotFoundError
|
||||||
from repo_registry.web_api.app import get_service
|
from repo_scoping.web_api.app import get_service
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter(include_in_schema=False)
|
router = APIRouter(include_in_schema=False)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from repo_registry.acceptance import AgenticReviewDecision
|
from repo_scoping.acceptance import AgenticReviewDecision
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
class BoundaryApprovingReviewer:
|
class BoundaryApprovingReviewer:
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
AgenticReviewDecision,
|
AgenticReviewDecision,
|
||||||
validate_agentic_review_decision,
|
validate_agentic_review_decision,
|
||||||
)
|
)
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
class RecordingAgenticReviewer:
|
class RecordingAgenticReviewer:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from repo_registry.candidate_graph.generator import CandidateGraphGenerator
|
from repo_scoping.candidate_graph.generator import CandidateGraphGenerator
|
||||||
from repo_registry.core.models import ContentChunk, ObservedFact, Repository
|
from repo_scoping.core.models import ContentChunk, ObservedFact, Repository
|
||||||
|
|
||||||
|
|
||||||
def fact(id, kind, name, path="", value="", metadata=None):
|
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,
|
3,
|
||||||
"llm_provider",
|
"llm_provider",
|
||||||
"OpenRouter",
|
"OpenRouter",
|
||||||
"src/repo_registry/repo_scanning/scanner.py",
|
"src/repo_scoping/repo_scanning/scanner.py",
|
||||||
"openrouter",
|
"openrouter",
|
||||||
{"source_role": "implementation_source", "utility_relationship": "owned"},
|
{"source_role": "implementation_source", "utility_relationship": "owned"},
|
||||||
),
|
),
|
||||||
|
|
@ -541,7 +541,7 @@ def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capab
|
||||||
4,
|
4,
|
||||||
"provider_registry",
|
"provider_registry",
|
||||||
"LLM provider registry",
|
"LLM provider registry",
|
||||||
"src/repo_registry/repo_scanning/scanner.py",
|
"src/repo_scoping/repo_scanning/scanner.py",
|
||||||
metadata={
|
metadata={
|
||||||
"source_role": "implementation_source",
|
"source_role": "implementation_source",
|
||||||
"utility_relationship": "owned",
|
"utility_relationship": "owned",
|
||||||
|
|
@ -551,7 +551,7 @@ def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capab
|
||||||
5,
|
5,
|
||||||
"credential_config",
|
"credential_config",
|
||||||
"OpenRouter API key",
|
"OpenRouter API key",
|
||||||
"src/repo_registry/repo_scanning/scanner.py",
|
"src/repo_scoping/repo_scanning/scanner.py",
|
||||||
"OPENROUTER_API_KEY",
|
"OPENROUTER_API_KEY",
|
||||||
{"source_role": "implementation_source", "utility_relationship": "configure"},
|
{"source_role": "implementation_source", "utility_relationship": "configure"},
|
||||||
),
|
),
|
||||||
|
|
@ -619,7 +619,7 @@ def test_candidate_generator_recovers_repo_scoping_native_candidate_families():
|
||||||
17,
|
17,
|
||||||
"interface",
|
"interface",
|
||||||
"python route decorator",
|
"python route decorator",
|
||||||
"src/repo_registry/web_api/app.py",
|
"src/repo_scoping/web_api/app.py",
|
||||||
'@app.post("/repos")',
|
'@app.post("/repos")',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
from repo_registry.candidate_graph.generator import (
|
from repo_scoping.candidate_graph.generator import (
|
||||||
CandidateAbilityDraft,
|
CandidateAbilityDraft,
|
||||||
CandidateCapabilityDraft,
|
CandidateCapabilityDraft,
|
||||||
CandidateFeatureDraft,
|
CandidateFeatureDraft,
|
||||||
)
|
)
|
||||||
from repo_registry.candidate_graph.normalization import normalize_candidate_drafts
|
from repo_scoping.candidate_graph.normalization import normalize_candidate_drafts
|
||||||
from repo_registry.core.models import SourceReference
|
from repo_scoping.core.models import SourceReference
|
||||||
|
|
||||||
|
|
||||||
def ref(fact_id, path):
|
def ref(fact_id, path):
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from repo_registry.cli import main
|
from repo_scoping.cli import main
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def make_service(tmp_path):
|
def make_service(tmp_path):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from repo_registry.content_indexing.extractor import ContentExtractor
|
from repo_scoping.content_indexing.extractor import ContentExtractor
|
||||||
from repo_registry.core.models import ObservedFact
|
from repo_scoping.core.models import ObservedFact
|
||||||
|
|
||||||
|
|
||||||
def fact(id, kind, name, path="", line=None, source_role=""):
|
def fact(id, kind, name, path="", line=None, source_role=""):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
|
|
||||||
|
|
||||||
def run(command, cwd):
|
def run(command, cwd):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from datetime import date
|
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():
|
def test_scope_to_intent_text_replaces_scope_heading_and_marks_bootstrap():
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from repo_registry.core.models import ContentChunk, Repository
|
from repo_scoping.core.models import ContentChunk, Repository
|
||||||
from repo_registry.llm_extraction import (
|
from repo_scoping.llm_extraction import (
|
||||||
LLMCandidateExtractor,
|
LLMCandidateExtractor,
|
||||||
LLMExtractionError,
|
LLMExtractionError,
|
||||||
create_llm_connect_adapter,
|
create_llm_connect_adapter,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from repo_registry.core.models import ContentChunk, ObservedFact
|
from repo_scoping.core.models import ContentChunk, ObservedFact
|
||||||
from repo_registry.llm_extraction import (
|
from repo_scoping.llm_extraction import (
|
||||||
ExtractedAbility,
|
ExtractedAbility,
|
||||||
ExtractedCapability,
|
ExtractedCapability,
|
||||||
ExtractedEvidence,
|
ExtractedEvidence,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
active_quality_criteria_version,
|
active_quality_criteria_version,
|
||||||
criteria_registry_markdown,
|
criteria_registry_markdown,
|
||||||
load_quality_criteria,
|
load_quality_criteria,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
from repo_registry.acceptance import (
|
from repo_scoping.acceptance import (
|
||||||
blocking_quality_gate_outcomes,
|
blocking_quality_gate_outcomes,
|
||||||
evaluate_candidate_capability_quality,
|
evaluate_candidate_capability_quality,
|
||||||
evaluate_candidate_graph_quality,
|
evaluate_candidate_graph_quality,
|
||||||
quality_gate_outcome_dicts,
|
quality_gate_outcome_dicts,
|
||||||
)
|
)
|
||||||
from repo_registry.core.models import (
|
from repo_scoping.core.models import (
|
||||||
AnalysisRun,
|
AnalysisRun,
|
||||||
CandidateAbility,
|
CandidateAbility,
|
||||||
CandidateCapability,
|
CandidateCapability,
|
||||||
|
|
@ -13,9 +13,9 @@ from repo_registry.core.models import (
|
||||||
Repository,
|
Repository,
|
||||||
SourceReference,
|
SourceReference,
|
||||||
)
|
)
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def source_ref(path="src/app.py", kind="source"):
|
def source_ref(path="src/app.py", kind="source"):
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,17 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from repo_registry.core.logging import LOGGER_NAME
|
from repo_scoping.core.logging import LOGGER_NAME
|
||||||
from repo_registry.core.models import SourceReference
|
from repo_scoping.core.models import SourceReference
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.llm_extraction import (
|
from repo_scoping.llm_extraction import (
|
||||||
ExtractedAbility,
|
ExtractedAbility,
|
||||||
ExtractedCapability,
|
ExtractedCapability,
|
||||||
ExtractedFeature,
|
ExtractedFeature,
|
||||||
)
|
)
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.semantic import HashingEmbeddingProvider
|
from repo_scoping.semantic import HashingEmbeddingProvider
|
||||||
from repo_registry.storage.sqlite import NotFoundError, RegistryStore
|
from repo_scoping.storage.sqlite import NotFoundError, RegistryStore
|
||||||
from tests.fixtures import (
|
from tests.fixtures import (
|
||||||
write_dependency_only_repo,
|
write_dependency_only_repo,
|
||||||
write_empty_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 = tmp_path / "repo"
|
||||||
repo.mkdir()
|
repo.mkdir()
|
||||||
(repo / "pyproject.toml").write_text(
|
(repo / "pyproject.toml").write_text(
|
||||||
|
|
@ -15,7 +29,7 @@ def test_metadata_prefers_pyproject(tmp_path):
|
||||||
assert metadata.description == "Extract invoice data."
|
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 = tmp_path / "repo"
|
||||||
repo.mkdir()
|
repo.mkdir()
|
||||||
(repo / "package.json").write_text(
|
(repo / "package.json").write_text(
|
||||||
|
|
@ -29,8 +43,8 @@ def test_metadata_uses_package_json(tmp_path):
|
||||||
assert metadata.description == "Browse repository abilities."
|
assert metadata.description == "Browse repository abilities."
|
||||||
|
|
||||||
|
|
||||||
def test_metadata_falls_back_to_readme_title(tmp_path):
|
def test_metadata_uses_readme_title_when_source_name_is_generic(tmp_path):
|
||||||
repo = tmp_path / "repo-name"
|
repo = tmp_path / "repository"
|
||||||
repo.mkdir()
|
repo.mkdir()
|
||||||
(repo / "README.md").write_text(
|
(repo / "README.md").write_text(
|
||||||
"# Useful Registry\n\nExtra details follow.\n",
|
"# 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.name == "Useful Registry"
|
||||||
assert metadata.description == "Extra details follow."
|
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 (
|
from tests.fixtures import (
|
||||||
write_javascript_typescript_package_repo,
|
write_javascript_typescript_package_repo,
|
||||||
write_misleading_docs_repo,
|
write_misleading_docs_repo,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def test_llm_connect_provider_expectations_are_detected_without_llm(tmp_path):
|
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 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):
|
def override_settings(tmp_path):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.scope.generator import SCOPE_SECTIONS, ScopeGenerator
|
from repo_scoping.scope.generator import SCOPE_SECTIONS, ScopeGenerator
|
||||||
from repo_registry.scope.validator import ScopeValidator
|
from repo_scoping.scope.validator import ScopeValidator
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def make_service(tmp_path):
|
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)
|
service = make_service(tmp_path)
|
||||||
repository = service.register_repository(
|
repository = service.register_repository(
|
||||||
name="Repo Registry",
|
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.",
|
description="Generates repository scope files from approved characteristics.",
|
||||||
)
|
)
|
||||||
service.update_scope(
|
service.update_scope(
|
||||||
|
|
@ -46,10 +46,10 @@ def test_scope_generator_renders_canonical_sections_and_capability_blocks(tmp_pa
|
||||||
type="business-usecase",
|
type="business-usecase",
|
||||||
primary_class="business-usecase",
|
primary_class="business-usecase",
|
||||||
attributes=["scope", "preview"],
|
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")
|
assert content.startswith("# SCOPE\n")
|
||||||
for section in SCOPE_SECTIONS:
|
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 "Generates and validates SCOPE.md files" in content
|
||||||
assert "Maintain Repository Scope" in content
|
assert "Maintain Repository Scope" in content
|
||||||
assert "Preview generated SCOPE.md" 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 "```capability" in content
|
||||||
assert "type: api" in content
|
assert "type: api" in content
|
||||||
assert "title: Generate SCOPE.md" in content
|
assert "title: Generate SCOPE.md" in content
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.self_scoping.assessment import export_assessment_artifact
|
from repo_scoping.self_scoping.assessment import export_assessment_artifact
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def make_service(tmp_path):
|
def make_service(tmp_path):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from repo_registry.self_scoping.comparison import (
|
from repo_scoping.self_scoping.comparison import (
|
||||||
compare_assessment_to_golden,
|
compare_assessment_to_golden,
|
||||||
comparison_markdown,
|
comparison_markdown,
|
||||||
load_json,
|
load_json,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import json
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from repo_registry.self_scoping.review_store import (
|
from repo_scoping.self_scoping.review_store import (
|
||||||
list_assessment_artifacts,
|
list_assessment_artifacts,
|
||||||
list_golden_profiles,
|
list_golden_profiles,
|
||||||
load_json_artifact,
|
load_json_artifact,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import json
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
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):
|
def write_json(path, payload):
|
||||||
|
|
@ -47,7 +47,7 @@ def seed_review_artifacts(root):
|
||||||
{
|
{
|
||||||
"name": "HTTP API surface",
|
"name": "HTTP API surface",
|
||||||
"type": "API",
|
"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",
|
"name": "HTTP API surface",
|
||||||
"type": "API",
|
"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):
|
def test_self_scoping_ui_compares_and_records_outcome(tmp_path, monkeypatch):
|
||||||
root = tmp_path / "self-scoping"
|
root = tmp_path / "self-scoping"
|
||||||
seed_review_artifacts(root)
|
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)
|
client = TestClient(app)
|
||||||
|
|
||||||
index = client.get("/ui/self-scoping")
|
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):
|
def test_self_scoping_ui_compares_two_assessment_runs(tmp_path, monkeypatch):
|
||||||
root = tmp_path / "self-scoping"
|
root = tmp_path / "self-scoping"
|
||||||
seed_review_artifacts(root)
|
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)
|
client = TestClient(app)
|
||||||
|
|
||||||
review = client.get(
|
review = client.get(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def make_service(tmp_path):
|
def make_service(tmp_path):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
|
|
||||||
|
|
||||||
def make_service(tmp_path):
|
def make_service(tmp_path):
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ import sqlite3
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from repo_registry.core.service import RegistryService
|
from repo_scoping.core.service import RegistryService
|
||||||
from repo_registry.repo_ingestion.git import GitIngestionService
|
from repo_scoping.repo_ingestion.git import GitIngestionService
|
||||||
from repo_registry.storage.sqlite import RegistryStore
|
from repo_scoping.storage.sqlite import RegistryStore
|
||||||
from repo_registry.web_api import app as app_module
|
from repo_scoping.web_api import app as app_module
|
||||||
from repo_registry.web_api.app import Settings, app, get_service, get_settings
|
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):
|
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):
|
def test_settings_can_load_from_environment(monkeypatch):
|
||||||
monkeypatch.setenv("REPO_REGISTRY_DATABASE_PATH", "var/env.sqlite3")
|
monkeypatch.setenv("REPO_SCOPING_DATABASE_PATH", "var/env.sqlite3")
|
||||||
monkeypatch.setenv("REPO_REGISTRY_CHECKOUT_ROOT", "var/env-checkouts")
|
monkeypatch.setenv("REPO_SCOPING_CHECKOUT_ROOT", "var/env-checkouts")
|
||||||
monkeypatch.setenv("REPO_REGISTRY_LLM_PROVIDER", "mock")
|
monkeypatch.setenv("REPO_SCOPING_LLM_PROVIDER", "mock")
|
||||||
monkeypatch.setenv("REPO_REGISTRY_LLM_MODEL", "demo-model")
|
monkeypatch.setenv("REPO_SCOPING_LLM_MODEL", "demo-model")
|
||||||
monkeypatch.setenv("REPO_REGISTRY_EMBEDDING_PROVIDER", "hashing")
|
monkeypatch.setenv("REPO_SCOPING_EMBEDDING_PROVIDER", "hashing")
|
||||||
monkeypatch.setenv("REPO_REGISTRY_LOG_LEVEL", "DEBUG")
|
monkeypatch.setenv("REPO_SCOPING_LOG_LEVEL", "DEBUG")
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
|
|
@ -2696,7 +2696,7 @@ def test_ui_manual_registry_entry_loop(tmp_path):
|
||||||
|
|
||||||
delete_repository_response = client.post(
|
delete_repository_response = client.post(
|
||||||
f"{repository_path}/delete",
|
f"{repository_path}/delete",
|
||||||
data={"confirm_name": "Manual Repo"},
|
data={"confirm_name": "manual-repo"},
|
||||||
follow_redirects=False,
|
follow_redirects=False,
|
||||||
)
|
)
|
||||||
assert delete_repository_response.status_code == 303
|
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