Classify review-only claim proposals correctly (#186)
Some checks are pending
CI / lint-and-test (push) Waiting to run

This commit is contained in:
twentyOne2x 2026-07-18 01:14:58 +02:00 committed by GitHub
parent a6569214a3
commit 20e2f60b0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 9 deletions

View file

@ -468,6 +468,22 @@ def _has_unnegated_action(query: str, actions: tuple[str, ...]) -> bool:
return False
def _has_unnegated_source_action(query: str) -> bool:
"""Detect source-intake verbs without treating a prohibition as intent."""
action_pattern = re.compile(
r"\b(?:send|hand|drop|upload|learn|absorb|ingest|extract|stage|add)(?:s|ed|ing)?\b|"
r"\bmake it part\b"
)
for segment in re.split(r"(?<=[.!?;])\s+|\n+", query.lower()):
if not action_pattern.search(segment):
continue
if "read-only" in segment or re.search(r"\b(?:do not|don't|dont|must not|without)\b", segment):
continue
return True
return False
def _has_unnegated_database_state_request(query: str) -> bool:
"""Detect an actual DB-state question instead of incidental lifecycle vocabulary."""
@ -705,9 +721,16 @@ def operational_contracts(
candidate_claim_composition_question = bool(
any(
term in lowered
for term in ("candidate claim", "reviewable candidate", "candidate only", "revised exact claim body")
for term in (
"candidate claim",
"reviewable candidate",
"candidate only",
"revised exact claim body",
"review-only proposal",
"review only proposal",
)
)
and any(term in lowered for term in ("draft", "propose", "revise", "rewrite", "narrow", "return"))
and any(term in lowered for term in ("draft", "propose", "revise", "rewrite", "narrow", "return", "turn"))
and not existing_claim_audit_question
)
claim_evidence_challenge_question = bool(
@ -826,13 +849,7 @@ def operational_contracts(
)
source_terms = ("document", "pdf", "tweet", "attachment", "ingest", "intake", "absorb", "extract")
broad_source_object = bool(re.search(r"\b(?:report|article|file|url|link)s?\b", normalized))
broad_source_action = bool(
re.search(
r"\b(?:send|hand|drop|upload|learn|absorb|ingest|extract|stage|add)(?:s|ed|ing)?\b|"
r"\bmake it part\b",
normalized,
)
)
broad_source_action = _has_unnegated_source_action(query)
source_intake_question = any(term in lowered for term in source_terms) or (
broad_source_object and broad_source_action
)

View file

@ -1968,6 +1968,15 @@ def test_vps_bridge_direct_intents_reject_unrelated_and_resolve_overlaps() -> No
}
assert reasoning_followup_ids & direct_ids == set()
review_only_proposal_ids = {
item["id"]
for item in module.operational_contracts(
"Turn the surviving claim into a review-only proposal: exact body, confidence, falsifier, required "
"sources, and links to claims that support or contradict it. Do not stage or write anything."
)
}
assert review_only_proposal_ids == {"reply_budget"}
chat_memory_ids = {
item["id"]
for item in module.operational_contracts(