Add strict read-only source and database investigation tools
This commit is contained in:
1 parent
798925d25d
commit
66c76a9930
14 files changed
+2069
-2
No files matched your search
@@ -0,0 +1,148 @@
|
||||
# Investigation tools v1
|
||||
|
||||
This milestone provides the read-only Investigation Tool Router and initial
|
||||
source/database queries. The architecture is unchanged. No shell, arbitrary SQL,
|
||||
live database access, source edits, web UI, bot/client steering, EvidenceStore or
|
||||
autonomous Investigation Loop is introduced.
|
||||
|
||||
## API and controller boundary
|
||||
|
||||
```python
|
||||
from viano_bug_analysis.tools import InvestigationToolRouter
|
||||
|
||||
router = InvestigationToolRouter()
|
||||
result = router.query(package_path, {
|
||||
"format": "viano-investigation-request", "format_version": 1,
|
||||
"case_id": case_id, "package_id": package_id, "analysis_revision": revision,
|
||||
"requests": [{
|
||||
"request_id": "Q0001", "hypothesis_id": "H1", "action_id": "query-0001",
|
||||
"operation": "source.find_text",
|
||||
"arguments": {"source_refs": [source_ref], "text": "activate",
|
||||
"case_sensitive": True, "offset": 0, "limit": 20},
|
||||
}],
|
||||
})
|
||||
```
|
||||
|
||||
`request_schema()` exposes the bundled strict `investigation-request-v1` schema
|
||||
for future prompting. Unknown operations/fields, invalid arguments, duplicate
|
||||
request IDs and repeated hypothesis/action pairs are rejected. The router checks
|
||||
manifest identity/revision, known initial hypothesis IDs, active generation or
|
||||
investigation phase, and a fresh canonical case. Blocked cases cannot query.
|
||||
|
||||
The entire batch is validated and preflighted before any query handler executes.
|
||||
Preflight includes declared roles, bounded source reads, encoding, ranges,
|
||||
database structure and known columns. A rejected batch returns no partial result.
|
||||
Preflight itself necessarily reads the selected snapshots; it has no writes or
|
||||
external effects. Runtime errors are controlled `ToolError` codes without raw
|
||||
source data in diagnostic text.
|
||||
|
||||
Tools read only the ZIP snapshots declared by `case.json` in `source_context` and
|
||||
`database_context`. Each read verifies its existing case hash and size. Arbitrary
|
||||
package members, unknown/unclassified attachments, absolute server paths and
|
||||
manifest pointers are not alternative query targets. Server path strings inside
|
||||
wowsrc data remain metadata. Nothing is extracted or executed.
|
||||
|
||||
The router returns a versioned `investigation-result-v1` document with manifest
|
||||
identity, source package generation, canonical case ref/hash, batch hash,
|
||||
per-request hash and typed operation-specific results. It does not update the
|
||||
manifest, write checkpoints, charge/refund credits or persist evidence.
|
||||
The future trusted controller must reserve budget **before** dispatch, persist
|
||||
the request and result, verify that the case generation has not changed, and
|
||||
apply BudgetManager result/settlement rules. Retries of these deterministic
|
||||
snapshot queries have no tool side effects; billing idempotence remains in the
|
||||
controller/BudgetManager. Future controller hypothesis eligibility, reservations
|
||||
and updates require their own full validation; a known birth ID alone does not
|
||||
authorize spending against a terminal account.
|
||||
|
||||
## Initial allowlist
|
||||
|
||||
| Operation | Arguments and behavior |
|
||||
| --- | --- |
|
||||
| `source.find_text` | Explicit `source_refs`, literal `text`, `case_sensitive`, `offset`, `limit`; matches lines, not regex |
|
||||
| `source.find_symbol` | Explicit `source_refs`, one identifier `symbol`, `offset`, `limit`; token-boundary occurrences |
|
||||
| `source.read_context` | `source_ref`, inclusive 1-based `start_line` and `end_line` |
|
||||
| `database.describe` | `source_ref` selecting a verified schema/snapshot descriptor |
|
||||
| `database.lookup` | `source_ref`, nonempty `filters` map of exact scalar equality, projection `columns`, `offset`, `limit` |
|
||||
| `database.find_references` | `source_ref`, explicit `search_columns`, scalar `value`, projection `columns`, `offset`, `limit` |
|
||||
|
||||
Source results include actual source SHA-256, 1-based line numbers and line text.
|
||||
Symbol matches can be uses, declarations, definitions, comments or strings: this
|
||||
is not a language parser or verified definition/registration resolver. Text
|
||||
search is literal and may explicitly ignore case. Source encoding is UTF-8 with
|
||||
optional BOM; binary/NUL or undecodable sources reject the batch.
|
||||
|
||||
Database results include original source SHA-256 and an actual JSON Pointer to
|
||||
each original row (for example `/rows/2` or `/2`). Projection never changes the
|
||||
pointer. Equality does not coerce booleans, strings or numeric types; `true`, `1`,
|
||||
`"1"` and `1.0` remain different typed values. Reference search only finds equal
|
||||
values in specified columns; it does not assert foreign-key relationships.
|
||||
SQL-like text in a scalar value is ordinary data, never executable SQL.
|
||||
|
||||
All searches expose checked sources, total matches, `truncated` and a stable
|
||||
`next_offset`. Sorting follows requested file order and original row/line order.
|
||||
Individual source lines have separate `text_truncated` markers. Limits reject
|
||||
excessive input/output rather than quietly dropping queried files. A no-match
|
||||
result applies only to the selected packaged snapshot; it proves neither absence
|
||||
from an entire repository nor absence from the current server/database.
|
||||
|
||||
## Database snapshot contract and profile adapter
|
||||
|
||||
The neutral `database-snapshot-v1` format is:
|
||||
|
||||
```json
|
||||
{
|
||||
"format": "viano-database-snapshot", "format_version": 1,
|
||||
"table": "switches",
|
||||
"columns": [{"name": "id", "type": "integer"}],
|
||||
"rows": [{"id": 42}], "coverage": "partial"
|
||||
}
|
||||
```
|
||||
|
||||
Coverage is explicit: `partial`, `complete_snapshot`, `unknown` or `schema_only`.
|
||||
Even a complete snapshot is a packaged point-in-time claim, not a live query.
|
||||
Duplicate column names, rows containing undeclared columns and schema-only
|
||||
descriptors containing rows are rejected. Raw arrays of row objects can be
|
||||
queried without inventing table identity or schema: their coverage is `unknown`,
|
||||
and columns must occur in stored rows. An empty raw array cannot validate a
|
||||
column name; querying unknown columns rejects. A schema-only descriptor may have
|
||||
known columns and no rows, but that absence is not evidence of a missing DB row.
|
||||
|
||||
wowsrc's native `{table, columns:[{column_name, column_type, ...}], ...}` descriptors
|
||||
are normalized explicitly in `profiles/vcore/db_tools.py`:
|
||||
|
||||
```python
|
||||
from viano_bug_analysis.profiles.vcore.db_tools import normalize_schema_descriptor
|
||||
from viano_bug_analysis.tools.database_query import DatabaseQueryTool
|
||||
|
||||
router = InvestigationToolRouter(
|
||||
database_tool=DatabaseQueryTool(normalize_schema_descriptor),
|
||||
)
|
||||
```
|
||||
|
||||
This mapping reports `schema_only`. It does not infer table ownership from file
|
||||
names, numeric IDs, ambiguous artifact rankings or `schema_table_matches`. Other
|
||||
projects can supply their own trusted descriptor adapter or use the neutral
|
||||
format. Live DB connectors, symbol parsers, registration discovery, timeline/log
|
||||
queries and actual external research providers are later extensions.
|
||||
|
||||
## Limits and asynchronous testing
|
||||
|
||||
`ToolLimits` provides adjustable operational defaults, not permanent v1 format
|
||||
caps: request 64 KiB, batch 16 requests, 64 distinct selected files, 8 MiB per file,
|
||||
32 MiB combined selected bytes, 100,000 database rows, 100 returned matches per
|
||||
query, 200 context lines, 4,096 characters per returned source line and 2 MiB per
|
||||
result batch. Existing package and CaseBuilder limits apply separately when
|
||||
validating the package and canonical case inventory.
|
||||
|
||||
Asynchronous human/automated tests remain in the separate controller handoff
|
||||
described in [async-tests-v1.md](async-tests-v1.md). They are deliberately not
|
||||
executed by this snapshot query router. The future Investigation Loop can combine
|
||||
both interfaces: fast read-only query results and persisted external test waits.
|
||||
No deadline, waiting state or budget preservation behavior changes here.
|
||||
|
||||
Tests cover generic snapshots, allowlist and path safety, whole-batch preflight,
|
||||
type distinctions, pagination, provenance, input/output limits, blocked/stale
|
||||
contexts and byte-for-byte read-only behavior. The actual BUG-20 regression reads
|
||||
three lines of packaged source, its quest table schema using the Vcore adapter,
|
||||
and the actual stored quest row through an explicit ID filter;
|
||||
it does not inject a known fix or claim to test model reasoning.
|
||||
Reference in new issue
Block a user