Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions conformance/sequence-v1/events.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{"session_id":"case-01-within-299","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-01-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-01-within-299","seq":1,"observed_at":"2026-08-11T12:00:10+00:00","kind":"agent_output","tool_name":null,"tool_role":null,"source_trust":null,"tool_call_id":null,"arguments":null,"result":"VALUE_002","outcome":null}
{"session_id":"case-01-within-299","seq":2,"observed_at":"2026-08-11T12:00:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-01-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-01-within-299","seq":3,"observed_at":"2026-08-11T12:01:00+00:00","kind":"tool_call","tool_name":"unrelated_tool","tool_role":"other","source_trust":null,"tool_call_id":"case-01-call-3","arguments":{},"result":null,"outcome":null}
{"session_id":"case-01-within-299","seq":4,"observed_at":"2026-08-11T12:04:59+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-01-call-4","arguments":{},"result":null,"outcome":null}
{"session_id":"case-02-boundary-300","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-02-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-02-boundary-300","seq":1,"observed_at":"2026-08-11T12:02:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-02-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-02-boundary-300","seq":2,"observed_at":"2026-08-11T12:05:00+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-02-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-03-outside-301","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-03-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-03-outside-301","seq":1,"observed_at":"2026-08-11T12:02:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-03-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-03-outside-301","seq":2,"observed_at":"2026-08-11T12:05:01+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-03-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-04-missing-time","seq":0,"observed_at":null,"kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-04-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-04-missing-time","seq":1,"observed_at":null,"kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-04-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-04-missing-time","seq":2,"observed_at":null,"kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-04-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-05-wrong-order","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-05-call-0","arguments":{},"result":null,"outcome":null}
{"session_id":"case-05-wrong-order","seq":1,"observed_at":"2026-08-11T12:00:10+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-05-call-1","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-05-wrong-order","seq":2,"observed_at":"2026-08-11T12:00:20+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-05-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-06-multiple-candidates","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external_first","tool_role":"external_input","source_trust":"external","tool_call_id":"case-06-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-06-multiple-candidates","seq":1,"observed_at":"2026-08-11T12:00:10+00:00","kind":"tool_result","tool_name":"retrieve_external_second","tool_role":"external_input","source_trust":"external","tool_call_id":"case-06-call-1","arguments":{},"result":"VALUE_002","outcome":"success"}
{"session_id":"case-06-multiple-candidates","seq":2,"observed_at":"2026-08-11T12:00:20+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-06-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-06-multiple-candidates","seq":3,"observed_at":"2026-08-11T12:00:30+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-06-call-3","arguments":{},"result":null,"outcome":null}
{"session_id":"case-07-later-valid-source","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external_expired","tool_role":"external_input","source_trust":"external","tool_call_id":"case-07-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-07-later-valid-source","seq":1,"observed_at":"2026-08-11T12:15:00+00:00","kind":"tool_result","tool_name":"retrieve_external_current","tool_role":"external_input","source_trust":"external","tool_call_id":"case-07-call-1","arguments":{},"result":"VALUE_002","outcome":"success"}
{"session_id":"case-07-later-valid-source","seq":2,"observed_at":"2026-08-11T12:15:50+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-07-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-07-later-valid-source","seq":3,"observed_at":"2026-08-11T12:16:40+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-07-call-3","arguments":{},"result":null,"outcome":null}
{"session_id":"case-08-tied-time","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-08-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-08-tied-time","seq":1,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-08-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-08-tied-time","seq":2,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-08-call-2","arguments":{},"result":null,"outcome":null}
{"session_id":"case-09-source-only","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-09-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-10-tail-only","seq":0,"observed_at":"2026-08-11T12:00:10+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-10-call-0","arguments":{},"result":null,"outcome":null}
{"session_id":"case-10-tail-only","seq":1,"observed_at":"2026-08-11T12:00:20+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-10-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-11-gapped-seq","seq":10,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-11-call-10","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-11-gapped-seq","seq":20,"observed_at":"2026-08-11T12:00:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-11-call-20","arguments":{},"result":null,"outcome":null}
{"session_id":"case-11-gapped-seq","seq":30,"observed_at":"2026-08-11T12:01:00+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"case-11-call-30","arguments":{},"result":null,"outcome":null}
{"session_id":"case-12-no-external-write","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"case-12-call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"case-12-no-external-write","seq":1,"observed_at":"2026-08-11T12:00:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"case-12-call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"case-12-no-external-write","seq":2,"observed_at":"2026-08-11T12:01:00+00:00","kind":"tool_call","tool_name":"change_internal_state","tool_role":"state_change","source_trust":null,"tool_call_id":"case-12-call-2","arguments":{},"result":null,"outcome":null}
3 changes: 3 additions & 0 deletions conformance/sequence-v1/fixtures/window/tn/expired.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{"session_id":"fixture-window-expired","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"fixture-window-expired","seq":1,"observed_at":"2026-08-11T12:02:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"fixture-window-expired","seq":2,"observed_at":"2026-08-11T12:05:01+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"call-2","arguments":{},"result":null,"outcome":null}
3 changes: 3 additions & 0 deletions conformance/sequence-v1/fixtures/window/tp/boundary.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{"session_id":"fixture-window-boundary","seq":0,"observed_at":"2026-08-11T12:00:00+00:00","kind":"tool_result","tool_name":"retrieve_external","tool_role":"external_input","source_trust":"external","tool_call_id":"call-0","arguments":{},"result":"VALUE_001","outcome":"success"}
{"session_id":"fixture-window-boundary","seq":1,"observed_at":"2026-08-11T12:02:30+00:00","kind":"tool_call","tool_name":"read_sensitive","tool_role":"sensitive_read","source_trust":null,"tool_call_id":"call-1","arguments":{},"result":null,"outcome":null}
{"session_id":"fixture-window-boundary","seq":2,"observed_at":"2026-08-11T12:05:00+00:00","kind":"tool_call","tool_name":"write_external","tool_role":"external_write","source_trust":null,"tool_call_id":"call-2","arguments":{},"result":null,"outcome":null}
17 changes: 17 additions & 0 deletions conformance/sequence-v1/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"events_file": "conformance/sequence-v1/events.jsonl",
"events_sha256": "fabc944cfff284beb1da58f79eb6f861a2ec3e7b8fca75929e832aed34eb97b4",
"result_file": "results/conformance-sequence-v1.json",
"rules": [
{
"path": "rules/TW-001.yaml",
"purpose": "measured_rule"
},
{
"path": "conformance/sequence-v1/rules/TW-CONFORMANCE-WINDOW.yaml",
"purpose": "test_only_window_semantics"
}
],
"schema_version": 1,
"suite_id": "sequence-v1"
}
34 changes: 34 additions & 0 deletions conformance/sequence-v1/rules/TW-CONFORMANCE-WINDOW.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
schema_version: 1
id: TW-CONFORMANCE-WINDOW
title: Test-only bounded sequence semantics
status: test
severity: informational

scope:
corpus: sequence-v1

sequence:
- as: source
kind: tool_result
tool_role: external_input
source_trust: external
- as: sensitive
kind: tool_call
tool_role: sensitive_read
- as: sink
kind: tool_call
tool_role: external_write

match:
group_by: [session_id]
order: [source, sensitive, sink]
within: 300

tests:
true_positives:
- conformance/sequence-v1/fixtures/window/tp/*.jsonl
true_negatives:
- conformance/sequence-v1/fixtures/window/tn/*.jsonl

references:
- Provider-neutral timestamp-window conformance only; not a measured detection rule
47 changes: 47 additions & 0 deletions docs/adr-002-backend-conformance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ADR-002: Local-engine backend conformance contract

## Status

Accepted on 2026-08-11.

## Context

The measured `TW-001` result uses historic AgentDojo events without per-event timestamps. It
establishes ordering behaviour, but it cannot establish elapsed-time behaviour. A future provider
query also needs an exact reference result before its status can move from rendered or executed to
conformant.

## Decision

The local engine is the reference implementation. The fixed `sequence-v1` suite supplies 37
synthetic, normalised events across 12 sessions and commits the exact local result for two rules:

- the unchanged, measured `TW-001` rule for ordering parity;
- a test-only 300-second rule for timestamp-window parity.

The test-only rule is not a published detector and carries no effectiveness or performance claim.
It exists outside `rules/` so that `TW-001` remains the only measured rule.

Conformance is exact. A provider implementation must reproduce each rule identifier and hash,
session identifier, matched event ordinal and matched tool name. The suite also fixes these
semantics:

- events are partitioned by session and ordered by non-negative `seq` values;
- sequence order is strict, while ordinal values may contain gaps;
- a window includes its exact boundary;
- missing timestamps fail a bounded match;
- candidate search may skip an expired earlier event to find a later valid sequence;
- events from different sessions cannot complete one sequence.

Rules and suite inputs reject unknown or malformed fields. This prevents a misspelled or wrongly
typed field from silently broadening a rendered query or changing timestamp-window semantics.

No provider interface or placeholder backend is added now. The first real provider consumer will
define its mapping and rendering contract. Backend status remains per rule: `unsupported`,
`rendered`, `executed` or `conformant`. Only exact parity on this fixed suite permits `conformant`.

## Consequences

`uv run tripwire verify` now checks both the frozen AgentDojo measurement and the provider-neutral
conformance result without credentials. Provider-specific rendering, ingestion, execution,
alerting, latency and cost evidence remain later work.
6 changes: 6 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ The canonical split groups by `(suite, user task, injection task)`, so it isolat
## 2026-08-03: Naive-sequence stop-condition check

The naive external-result then external-write diagnostic matched 4 of 74 development negatives and 1 of 37 holdout negatives. `TW-001` matched 3 of 74 and 1 of 37 respectively. The documented stop condition was not reached because `TW-001` has better specificity on the frozen development data, although the improvement did not repeat on holdout. This limitation is reported without changing the rule after holdout evaluation.

## 2026-08-11: Freeze the provider-neutral conformance boundary before M3

The local engine is the reference for future provider implementations. The committed `sequence-v1` suite separately fixes ordering and elapsed-time semantics using synthetic normalised events, while the measured `TW-001` rule and its spent holdout remain unchanged. A test-only bounded rule lives outside the published rule directory and makes no detection-effectiveness claim.

No generic backend interface is introduced before a real provider consumer exists. A provider earns `conformant` status per rule only after its executed result exactly matches the committed session identifiers, rule hashes, event ordinals and tool names. Provider rendering, ingestion, execution, alerting, latency and cost evidence begin after this boundary.
Loading
Loading