149 lines
7.9 KiB
Markdown
149 lines
7.9 KiB
Markdown
# 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.
|