feat(agent): add executor gatekeeper hook
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
## Context
|
||||
|
||||
Stage one introduced `executor_evidence_v2`, but `VerifierInputHook` still only parses JSON and passes the structured object to Verifier. A valid JSON object can still contain:
|
||||
|
||||
- removed fields such as `diagnosis_summary` or `user_facing_answer`
|
||||
- missing or wrong `answer_version`
|
||||
- empty `claims[].evidence_bindings`
|
||||
- fabricated `source_invocation_ids`
|
||||
- `tool_name` values that do not match the real `tool_invocation`
|
||||
|
||||
Gatekeeper handles these deterministic failures before Verifier performs semantic reasoning.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
Goals:
|
||||
|
||||
- Add Gatekeeper into `VerifierInputHook`.
|
||||
- Produce a small `gatekeeper_result` object.
|
||||
- Add `gatekeeper_result` to Verifier payload.
|
||||
- Persist `gatekeeper_result` in verifier evaluation.
|
||||
- Implement initial rules: schema and invocation reference.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- No Executor retry on Gatekeeper failure.
|
||||
- No excerpt similarity rule in this phase.
|
||||
- No hallucination phrase or evidence utilization rule in this phase.
|
||||
- No Verifier V2 `claim_checks`.
|
||||
- No Composer.
|
||||
- No database schema changes.
|
||||
|
||||
## Gatekeeper Output
|
||||
|
||||
Gatekeeper returns:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "fail",
|
||||
"failed_rules": ["evidence.invocation_ref"],
|
||||
"warnings": [],
|
||||
"errors": [
|
||||
{
|
||||
"rule_id": "evidence.invocation_ref",
|
||||
"target": "claims[0].evidence_bindings[0]",
|
||||
"message": "source_invocation_ids not found in current session"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Status calculation:
|
||||
|
||||
```text
|
||||
any fail -> fail
|
||||
else any warning -> warn
|
||||
else pass
|
||||
```
|
||||
|
||||
## Initial Rules
|
||||
|
||||
### schema.executor_v2
|
||||
|
||||
Fail when:
|
||||
|
||||
- structured output is absent after parse status is valid
|
||||
- `answer_version` is not `executor_evidence_v2`
|
||||
- `claims` is not an array
|
||||
- removed fields `diagnosis_summary` or `user_facing_answer` are present
|
||||
- any claim misses required fields
|
||||
- any claim has empty `evidence_bindings`
|
||||
- `hypotheses`, `recommended_actions`, or `missing_info` are missing or non-array
|
||||
|
||||
For this phase, missing optional arrays may be normalized only if implementation remains simple. If not normalized, missing arrays fail schema to keep behavior deterministic.
|
||||
|
||||
### evidence.invocation_ref
|
||||
|
||||
Fail when:
|
||||
|
||||
- `claims[].evidence_bindings[].source_invocation_ids` is missing or empty
|
||||
- any referenced invocation id is not in the current session's `tool_invocation` rows
|
||||
- `tool_name` does not match the referenced invocation's real `tool_name`
|
||||
|
||||
Recommended action evidence bindings remain optional and are not hard-fail checked in this phase.
|
||||
|
||||
## Integration
|
||||
|
||||
`VerifierInputHook.beforeModel(...)` flow becomes:
|
||||
|
||||
```text
|
||||
parse Executor output
|
||||
build tool_trace_summary
|
||||
Gatekeeper.validate(sessionId, structuredOutput, parseStatus)
|
||||
put gatekeeper_result into verifier payload
|
||||
store gatekeeper_result in VerifierContextHolder
|
||||
```
|
||||
|
||||
`ChatService.persistVerifierEvaluation(...)` adds:
|
||||
|
||||
```text
|
||||
gatekeeper_result: VerifierContextHolder.getGatekeeperResult()
|
||||
```
|
||||
|
||||
If Gatekeeper throws unexpectedly, hook should fail closed with a minimal `fail` result in payload rather than dropping validation silently.
|
||||
|
||||
## Interface Impact
|
||||
|
||||
- Verifier payload: L2 internal contract extension with `gatekeeper_result`.
|
||||
- Persistence JSON: L2 internal audit extension under existing `self_evaluation`.
|
||||
- No external API or database schema change.
|
||||
|
||||
## Risks / Mitigations
|
||||
|
||||
- Risk: tests or code instantiate `VerifierInputHook` with the old constructor.
|
||||
- Mitigation: keep a compatibility constructor that uses a no-op/pass Gatekeeper, or update tests explicitly.
|
||||
- Risk: Gatekeeper fails because no session id exists.
|
||||
- Mitigation: return fail with a clear `schema.executor_v2` or `evidence.invocation_ref` error only when validation cannot establish current-session references.
|
||||
- Risk: Verifier prompt may ignore Gatekeeper.
|
||||
- Mitigation: payload and audit are still authoritative for later phases; Verifier prompt update can be minimal in this phase.
|
||||
|
||||
Reference in New Issue
Block a user