Focus investigation context and recall archived evidence on demand
This commit is contained in:
1 parent
f4e85070c8
commit
5e29254b8d
9 files changed
+259
-11
No files matched your search
@@ -0,0 +1,59 @@
|
||||
import copy
|
||||
import json
|
||||
from jsonschema import Draft202012Validator
|
||||
from test_investigation_consolidation import populated
|
||||
from viano_bug_analysis.analysis.investigation_view import working_view
|
||||
from viano_bug_analysis.analysis.investigation_focus import focused_view
|
||||
from viano_bug_analysis.analysis.investigation_blocks import restore_blocks, block_view
|
||||
from viano_bug_analysis.analysis.investigation_prompt import build_prompt, output_schema
|
||||
from viano_bug_analysis.analysis.model_context import model_json
|
||||
|
||||
|
||||
def fixture():
|
||||
c = populated()
|
||||
c['prompt_version'] = 'investigation_project_v8'
|
||||
c['recalled_evidence'] = []
|
||||
c['budget']['accounts']['H1']['actions'] = {}
|
||||
return c
|
||||
|
||||
|
||||
def test_index_omits_old_payloads_but_preserves_predicates_and_scope():
|
||||
c = fixture(); before = copy.deepcopy(c)
|
||||
v = focused_view(c)
|
||||
assert set(v['evidence']) == {'E000001'}
|
||||
assert len(v['evidence_index']['rows']) == 2
|
||||
row = v['evidence_index']['rows'][1]
|
||||
assert row[0:2] == ['E000002','H2']
|
||||
assert row[3][0]['query']['start_line'] == 41
|
||||
assert row[3][0]['result_scope'] == {'coverage':'selected_lines','truncated':False}
|
||||
assert 'code line 120' not in model_json(v)
|
||||
assert c == before and focused_view(c) == v
|
||||
assert set(v['hypotheses']['H2']) == {'proposal','confidence','disposition'}
|
||||
assert set(v['hypotheses']['H2']['proposal']) == {'title','mechanism'}
|
||||
assert len(model_json(v)) < len(model_json(block_view(c)))
|
||||
|
||||
|
||||
def test_recall_exact_contents_including_cross_hypothesis_counterevidence():
|
||||
c = fixture(); c['recalled_evidence'] = ['E000002']
|
||||
v = restore_blocks(focused_view(c))
|
||||
assert v['evidence']['E000002']['content'] == working_view(c)['evidence']['E000002']['content']
|
||||
c['recalled_evidence'] = []
|
||||
assert 'E000002' not in focused_view(c)['evidence']
|
||||
|
||||
|
||||
def test_unassessed_other_hypothesis_result_stays_visible():
|
||||
c = fixture()
|
||||
c['budget']['accounts']['H2'] = {'actions':{'A1':{'status':'result_stored'}}}
|
||||
assert set(focused_view(c)['evidence']) == {'E000001','E000002'}
|
||||
|
||||
|
||||
def test_recall_schema_is_bounded_and_legacy_prompt_is_unchanged():
|
||||
c = fixture(); new = output_schema(c)
|
||||
schema = new['properties']['next']
|
||||
validator = Draft202012Validator(schema)
|
||||
assert validator.is_valid({'kind':'recall','evidence_refs':['E000002']})
|
||||
for refs in ([], ['E000002']*2, ['E000001','E000002','E000003','E000004','E000005']):
|
||||
assert not validator.is_valid({'kind':'recall','evidence_refs':refs})
|
||||
assert json.loads(build_prompt(c)['messages'][1]['content'])['input'] == focused_view(c)
|
||||
c['prompt_version'] = 'investigation_project_v7'
|
||||
assert not Draft202012Validator(output_schema(c)['properties']['next']).is_valid({'kind':'recall','evidence_refs':['E000001']})
|
||||
@@ -189,7 +189,8 @@ def test_case_builder_provider_outage_blocks_without_sealing(case_setup):
|
||||
assert reader.manifest["state"]=="BLOCKED" and reader.manifest["artifacts"].get("case") is None
|
||||
|
||||
|
||||
def test_model_loop_uses_project_tools_and_compact_previous_result(tool_case):
|
||||
@pytest.mark.parametrize("recall", [False, True, "unknown"])
|
||||
def test_model_loop_uses_project_tools_and_compact_previous_result(tool_case, recall):
|
||||
store=tool_case[0]
|
||||
with PackageReader(tool_case[1]) as reader:project=reader.manifest["project"]
|
||||
service=ProjectResearch(project,database=FakeDB([{"row":{"id":1}}]))
|
||||
@@ -203,16 +204,37 @@ def test_model_loop_uses_project_tools_and_compact_previous_result(tool_case):
|
||||
if previous:
|
||||
assert context["evidence"][eid]["content"]["items"]
|
||||
assert "inputs" not in context["case"]
|
||||
assert request["prompt_version"]=="investigation_project_v7"
|
||||
assert request["prompt_version"]=="investigation_project_v8"
|
||||
reply={"assessment":{"semantic_score":50,"reason":"Scoped fact","evidence_refs":[eid]} if previous else None,
|
||||
"update":{"confidence":"plausible","evidence_refs":[eid] if previous else [],"resolve_questions":[],"add_questions":[],"note":"Query typed identity"},
|
||||
"next":{"kind":"finish","reason":"Check complete"} if previous else {"kind":"tool","operation":"project.query","arguments":rows()}}
|
||||
if recall:
|
||||
if previous:
|
||||
reply['next'] = {'kind':'recall','evidence_refs':['E999999' if recall == 'unknown' else eid]}
|
||||
elif any(e['record']['hypothesis_id'] == context['selected_hypothesis'] for e in context.get('evidence', {}).values()):
|
||||
recalled = next(eid for eid,e in context['evidence'].items() if e['record']['hypothesis_id'] == context['selected_hypothesis'])
|
||||
assert context['evidence'][recalled]['content']['items']
|
||||
reply['update']['evidence_refs'] = [recalled]
|
||||
reply['next'] = {'kind':'finish','reason':'Recalled exact evidence; uncertainty remains'}
|
||||
return ProviderResponse(reply,"fixture",100,10)
|
||||
adapter=Adapter()
|
||||
loop=Investigator(store,gateway(adapter),router=InvestigationToolRouter(project_research=service))
|
||||
if recall is True:
|
||||
partial=asyncio.run(loop.run("case-A","stable-package",max_steps=4))
|
||||
assert partial.status == 'YIELDED'
|
||||
loop=Investigator(store,gateway(adapter),router=InvestigationToolRouter(project_research=service))
|
||||
result=asyncio.run(loop.run("case-A","stable-package",max_steps=20))
|
||||
assert result.status=="COMPLETED" and len(adapter.contexts)==6
|
||||
if recall == 'unknown':
|
||||
assert result.status == 'BLOCKED' and result.code == 'INVESTIGATION_EVIDENCE_UNKNOWN'
|
||||
else:
|
||||
assert result.status=="COMPLETED" and len(adapter.contexts)==(9 if recall else 6)
|
||||
assert len(EvidenceStore(store).snapshot("case-A","stable-package").record_refs)==3
|
||||
accounts=BudgetManager(store).snapshot("case-A","stable-package").state['accounts']
|
||||
assert sum(len(a['actions']) for a in accounts.values()) == 3
|
||||
if recall == 'unknown':
|
||||
assert any(a['status'] != 'settled' for a in accounts['H1']['actions'].values())
|
||||
else:
|
||||
assert all(a['status'] == 'settled' for account in accounts.values() for a in account['actions'].values())
|
||||
|
||||
|
||||
def test_provider_outage_blocks_without_ending_hypothesis(tool_case):
|
||||
|
||||
Reference in new issue
Block a user