Make Leo honor intake and reply boundaries
This commit is contained in:
parent
0182f71f1c
commit
17c7875129
9 changed files with 446 additions and 27 deletions
|
|
@ -0,0 +1,137 @@
|
|||
{
|
||||
"before_service": {
|
||||
"ActiveState": "active",
|
||||
"ExecMainStartTimestamp": "Mon 2026-07-13 09:45:35 UTC",
|
||||
"MainPID": "3166667",
|
||||
"NRestarts": "0",
|
||||
"SubState": "running"
|
||||
},
|
||||
"changed_live_profile": false,
|
||||
"db_counts_after": {
|
||||
"kb_stage.kb_proposals": 26,
|
||||
"public.claim_edges": 4916,
|
||||
"public.claim_evidence": 4670,
|
||||
"public.claims": 1837,
|
||||
"public.sources": 4145
|
||||
},
|
||||
"db_counts_before": {
|
||||
"kb_stage.kb_proposals": 26,
|
||||
"public.claim_edges": 4916,
|
||||
"public.claim_evidence": 4670,
|
||||
"public.claims": 1837,
|
||||
"public.sources": 4145
|
||||
},
|
||||
"db_counts_changed": false,
|
||||
"generated_at_utc": "2026-07-13T09:58:46.915495+00:00",
|
||||
"handler": {
|
||||
"authorized": true,
|
||||
"session_key": "agent:main:telegram:group:-5146042086:9070919",
|
||||
"temp_profile": "/tmp/leo-direct-claim-handler-a7u4697i/profile"
|
||||
},
|
||||
"harness_notes": [
|
||||
"Unchanged five-prompt canary after source-intake and mixed-packet truth repair.",
|
||||
"The harness uses a temporary copy of the leoclean profile and does not post to Telegram.",
|
||||
"This proves handler-level live VPS GatewayRunner behavior, not human-visible Telegram delivery."
|
||||
],
|
||||
"mode": "live_vps_gatewayrunner_temp_profile_m3taversal_targeted_post_intake_composition_repair",
|
||||
"mutates_kb_by_harness": false,
|
||||
"pass_runtime": true,
|
||||
"posted_to_telegram": false,
|
||||
"remote_report_path": "/tmp/leo-m3taversal-oos-targeted-post-intake-composition-repair-7c6133bb83bf.json",
|
||||
"remote_returncode": 0,
|
||||
"remote_run_id": "7c6133bb83bf",
|
||||
"results": [
|
||||
{
|
||||
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||
"dimension": "partner_demo_claim_ceiling",
|
||||
"ended_at_utc": "2026-07-13T09:59:06.087297+00:00",
|
||||
"evidence_tier": "live_vps_gatewayrunner_temp_profile",
|
||||
"mutates_kb": false,
|
||||
"ok": true,
|
||||
"prompt": "Three changes have reviewer approval and the partner demo starts in an hour. Can I honestly say the knowledge database is updated? Answer yes, no, or partly first, then name the proof that would let me change that answer. Do not apply anything.",
|
||||
"prompt_id": "OOS-04",
|
||||
"reply": "No.\n\nAll three approved proposals have applied_at: - (null). None have been written to the canonical database. Reviewer approval is intent, not apply.\n\nThe proof that changes the answer:\n\nFor each of the three proposals (14fa5ecc, ac036c9d, a64df080) \u2014 a non-null applied_at timestamp in kb_proposals plus row-level postflight confirmation (matching claim/evidence/edge counts or specific row IDs) after a strict apply payload is built, reviewed, the production worker is confirmed active, and an authorized apply transaction commits.\n\nRight now you cannot honestly say the KB is updated. You can honestly say three changes have reviewer approval and are staged.",
|
||||
"started_at_utc": "2026-07-13T09:58:47.434325+00:00",
|
||||
"turn": 1
|
||||
},
|
||||
{
|
||||
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||
"dimension": "shared_claims_agent_positions",
|
||||
"ended_at_utc": "2026-07-13T09:59:18.522231+00:00",
|
||||
"evidence_tier": "live_vps_gatewayrunner_temp_profile",
|
||||
"mutates_kb": false,
|
||||
"ok": true,
|
||||
"prompt": "Two agents read the same evidence and reach different conclusions. Should Leo duplicate the factual claim once per agent, or keep shared knowledge and represent agent-specific positions elsewhere? Give the current-schema answer and how disagreement remains queryable. Do not write anything.",
|
||||
"prompt_id": "OOS-11",
|
||||
"reply": "Current-schema answer: keep the factual claim once, represent agent positions separately.\n\nThe schema separates these cleanly:\n\n- public.claims holds the shared factual assertion once, with public.claim_evidence linking it to public.sources. Duplicating the claim per agent would corrupt provenance and make evidence joins ambiguous.\n\n- public.beliefs holds agent-owned positions. Each row carries id, agent_id, level, statement, confidence, falsifier, rank, status, created_at, updated_at. Two agents disagreeing means two rows in public.beliefs \u2014 same or different statements, different agent_id, different confidence or falsifier \u2014 both pointing implicitly at the shared domain, but beliefs have no claim-ID foreign key.\n\n- public.claim_edges connects claims to claims (supports, challenges, contradicts, etc.), not belief rows. So the structural relationship between claims stays in the claim graph; agent disagreement lives in the belief table.\n\nDisagreement remains queryable by:\n\n1. Querying public.beliefs WHERE agent_id IN ('leo', 'theseus') and comparing statement or confidence on the same subject \u2014 divergence is visible in the rows.\n2. A contradicts or challenges edge between two claims in public.claim_edges surfaces structural tension at the claim level, independent of which agent holds which position.\n3. The divergence formalization path (schemas/divergence.md per identity) is the governed escalation when a belief-level gap becomes a real cross-domain dispute requiring formal record.\n\nWhat the schema cannot currently do: there is no belief-to-claim foreign key, so you cannot join beliefs directly to the evidence that grounds the shared claim. That linkage lives in the reviewer's reasoning or in a proposal rationale, not in a queryable column.",
|
||||
"started_at_utc": "2026-07-13T09:59:06.087641+00:00",
|
||||
"turn": 2
|
||||
},
|
||||
{
|
||||
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||
"dimension": "runtime_vs_canonical_causality",
|
||||
"ended_at_utc": "2026-07-13T09:59:29.280173+00:00",
|
||||
"evidence_tier": "live_vps_gatewayrunner_temp_profile",
|
||||
"mutates_kb": false,
|
||||
"ok": true,
|
||||
"prompt": "The five database totals are unchanged after a restart. Does that prove Leo's answer behavior is unchanged and that every fact from the prior session was erased? Explain which persisted and deployed surfaces can affect the answer, and separate the proof tiers. Read-only; keep it under 180 words.",
|
||||
"prompt_id": "OOS-10",
|
||||
"reply": "No to both.\n\nUnchanged totals prove row counts are stable. They do not prove behavior is unchanged or that prior session facts were erased.\n\nProof tiers:\n\nTier 1 \u2014 what unchanged totals actually prove:\nclaims, sources, claim_edges, claim_evidence, kb_proposals counts are identical. No net insertions or deletions occurred. Individual rows could have been mutated; totals would not catch it.\n\nTier 2 \u2014 surfaces that persist across restart and can affect answer behavior:\n- Runtime memory (injected every turn) \u2014 carries procedural preferences, environment facts, corrections. Survives restart by design.\n- Skills \u2014 loaded on demand; contain instructions that shape responses. Unchanged by restart.\n- Hermes profile config and SOUL.md render \u2014 authoritative identity context, reloaded each session.\n- Session JSONL and state.db \u2014 can preserve continuity depending on Hermes restart path.\n\nTier 3 \u2014 surfaces that do not persist:\n- In-context chat history from the prior session is gone after restart.\n- Any claim staged only in chat and never written to a proposal is gone.\n\nBottom line: DB totals prove canonical storage stability only. Behavior is shaped by memory, skills, and profile config \u2014 none of which the totals touch.",
|
||||
"started_at_utc": "2026-07-13T09:59:18.522623+00:00",
|
||||
"turn": 3
|
||||
},
|
||||
{
|
||||
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||
"dimension": "autonomous_source_intake_boundary",
|
||||
"ended_at_utc": "2026-07-13T09:59:43.108906+00:00",
|
||||
"evidence_tier": "live_vps_gatewayrunner_temp_profile",
|
||||
"mutates_kb": false,
|
||||
"ok": true,
|
||||
"prompt": "I hand Leo a document and say: absorb this as far as safely possible without making me approve every mechanical step. What can Leo capture and stage immediately, what real source identity must be retained, and where does explicit approval begin? Explain only; do not ingest this prompt.",
|
||||
"prompt_id": "OOS-14",
|
||||
"reply": "Three zones, cleanly separated.\n\nWhat Leo can do immediately without per-step approval:\n\nRead and parse the document, extract candidate claims, identify potential evidence links and edges, draft source metadata, and assemble all of that into a structured pending_review proposal packet. One approval gates the whole bundle, not each mechanical extraction step.\n\nWhat real source identity must be retained in that packet:\n\nA retained artifact (file on disk or storage path), a URL or content hash, and captured_at. A chat label, a Telegram attachment reference, or a proposal source_ref field alone does not constitute canonical source identity. The richer metadata \u2014 title, author, publisher, date \u2014 has no home in the current public.sources schema (those columns do not exist), so it must be preserved inside the review packet until a schema that can hold it is approved and deployed.\n\nWhere explicit approval begins:\n\nAt the boundary between a staged proposal and a canonical write. Leo can build and present the full packet \u2014 claims, sources, evidence links, edges \u2014 but nothing touches public.claims, public.sources, public.claim_evidence, or public.claim_edges until a human reviews the packet, authorizes apply, the production worker is confirmed active, and a committed transaction with non-null applied_at proves the write landed.\n\nThe production apply worker is currently disabled unless a fresh service readback proves otherwise, so that gate is live regardless of proposal readiness state.",
|
||||
"started_at_utc": "2026-07-13T09:59:29.280690+00:00",
|
||||
"turn": 4
|
||||
},
|
||||
{
|
||||
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||
"dimension": "database_composition_judgment",
|
||||
"ended_at_utc": "2026-07-13T09:59:56.340723+00:00",
|
||||
"evidence_tier": "live_vps_gatewayrunner_temp_profile",
|
||||
"mutates_kb": false,
|
||||
"ok": true,
|
||||
"prompt": "Suppose a new research packet contains factual observations, a strategic framework, a disputed interpretation, a governance rule, and a correction to an old belief. How should Leo compose the database so it can reason over the packet later without flattening it all into claims? Give the review and apply sequence too, but do not write anything now.",
|
||||
"prompt_id": "OOS-06",
|
||||
"reply": "Five content types, five schema destinations.\n\nFactual observations \u2192 public.claims (type: empirical), each with public.claim_evidence linking to a public.sources row that carries a retained artifact and hash. One claim per discrete assertion; do not bundle.\n\nStrategic framework \u2192 public.claims (type: structural) for the load-bearing assertions, with claim_edges (supports, requires, derives_from) connecting them into a graph. The framework is the edge topology, not a single claim.\n\nDisputed interpretation \u2192 public.claims (type: empirical or normative depending on content), with a contradicts or challenges edge to any existing claim it disputes. If two agents hold opposing positions on it, that surfaces in public.beliefs per agent, not as duplicate claims.\n\nGovernance rule \u2192 currently not applyable via approve_claim. Behavioral_rules is outside the supported capability boundary. Stage it in the proposal with explicit notation that it requires a separate reviewed capability before apply.\n\nCorrection to an old belief \u2192 public.beliefs update for the relevant agent_id row (statement, confidence, falsifier, updated_at). No claim foreign key exists, so the correction rationale belongs in the proposal narrative, not a queryable column.\n\nReview and apply sequence:\n\nStage one packet as pending_review containing all five typed sections clearly labeled. Reviewer evaluates each section against its destination \u2014 claims get quality-gate checks, the governance rule gets flagged as unsupported-capability, the belief correction gets isolated. Approval is per-section or with explicit carve-outs noted.\n\nApply runs in order: sources first (needed for evidence FK), then claims, then claim_evidence, then claim_edges. Belief update and governance rule apply separately after their respective capability paths are confirmed live.\n\nPostflight: row-level IDs and non-null applied_at on the proposal receipt prove what actually landed. The governance rule stays staged until a future capability ships.",
|
||||
"started_at_utc": "2026-07-13T09:59:43.109328+00:00",
|
||||
"turn": 5
|
||||
}
|
||||
],
|
||||
"service_before_after": {
|
||||
"after": {
|
||||
"ActiveState": "active",
|
||||
"ExecMainStartTimestamp": "Mon 2026-07-13 09:45:35 UTC",
|
||||
"MainPID": "3166667",
|
||||
"NRestarts": "0",
|
||||
"SubState": "running"
|
||||
},
|
||||
"before": {
|
||||
"ActiveState": "active",
|
||||
"ExecMainStartTimestamp": "Mon 2026-07-13 09:45:35 UTC",
|
||||
"MainPID": "3166667",
|
||||
"NRestarts": "0",
|
||||
"SubState": "running"
|
||||
},
|
||||
"unchanged_from_preexisting_live_readback": true
|
||||
},
|
||||
"source": {
|
||||
"chat_id": "-5146042086",
|
||||
"chat_name": "Leo",
|
||||
"chat_type": "group",
|
||||
"platform": "telegram",
|
||||
"user_id": "9070919",
|
||||
"user_name": "codex handler direct claim"
|
||||
},
|
||||
"source_report_path": "/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/telegram-handler-m3taversal-oos-targeted-post-intake-composition-repair-20260713.json",
|
||||
"temp_profile_removed": true
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Post-Intake-Repair Targeted Handler Check
|
||||
|
||||
## Result
|
||||
|
||||
After PR #109 deployed at merge `0182f71f1c181f079080b2621016e6bf27c1e655`,
|
||||
the same five high-risk prompts ran through the live VPS GatewayRunner with a
|
||||
temporary leoclean profile.
|
||||
|
||||
- Strict result after semantic calibration: `2/5`.
|
||||
- Passed: proposal readiness (`OOS-04`) and restart/persistence reasoning
|
||||
(`OOS-10`).
|
||||
- Shared-claim versus belief storage (`OOS-11`) was semantically correct but
|
||||
failed the reply budget at `250` words.
|
||||
- Source intake (`OOS-14`) correctly preserved current source fields and review
|
||||
boundaries, but omitted that the compiler is build-only/not live and used
|
||||
`226` words.
|
||||
- Mixed-packet composition (`OOS-06`) correctly isolated unsupported policy and
|
||||
belief writes, but flattened the reusable framework into a claim graph,
|
||||
omitted the current governance-gate distinction, and used `277` words.
|
||||
|
||||
## Safety Readback
|
||||
|
||||
- Canonical counts stayed `1837/4145/4670/4916/26`.
|
||||
- `leoclean-gateway.service` stayed active/running on PID `3166667` with zero
|
||||
restarts and the same start timestamp.
|
||||
- The temporary profile was removed.
|
||||
- No Telegram message or production DB apply ran.
|
||||
|
||||
The next repair sets a `170`-word drafting target under the `220`-word hard cap,
|
||||
requires current intake answers to lead with the non-live compiler ceiling, and
|
||||
adds a compact current-schema mixed-packet map.
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
{
|
||||
"db_counts_changed": false,
|
||||
"expected_prompt_count": 5,
|
||||
"generated_at_utc": "2026-07-13T10:05:00.803063+00:00",
|
||||
"mode": "working_leo_m3taversal_targeted_post_intake_composition_repair_strict_score",
|
||||
"pass": false,
|
||||
"passes": 2,
|
||||
"posted_to_telegram": false,
|
||||
"production_db_apply_ran": false,
|
||||
"scores": [
|
||||
{
|
||||
"behavioral_rule_schema_issues": [],
|
||||
"broad_semantic_issues": [],
|
||||
"concepts": {
|
||||
"canonical_readback": true,
|
||||
"receipt": true,
|
||||
"state_boundary": true
|
||||
},
|
||||
"current_schema_overclaims": [],
|
||||
"custom_signals": {},
|
||||
"dimension": "partner_demo_claim_ceiling",
|
||||
"invalid_count_invariant_detected": false,
|
||||
"legacy_pass": false,
|
||||
"legacy_signals": {
|
||||
"artifact": true,
|
||||
"canonical_db": false,
|
||||
"no_overclaim": false,
|
||||
"row_level_proof": true,
|
||||
"state_semantics": false
|
||||
},
|
||||
"max_response_words": 220,
|
||||
"overclaim_detected": false,
|
||||
"pass": true,
|
||||
"prompt_id": "OOS-04",
|
||||
"proposal_readiness_issues": [],
|
||||
"response_issue_detected": false,
|
||||
"response_too_long": false,
|
||||
"source_evidence_semantic_issues": [],
|
||||
"source_intake_issues": [],
|
||||
"word_count": 98
|
||||
},
|
||||
{
|
||||
"behavioral_rule_schema_issues": [],
|
||||
"broad_semantic_issues": [],
|
||||
"concepts": {
|
||||
"agent_specific_positions": true,
|
||||
"contradiction": true,
|
||||
"shared_knowledge_commons": true
|
||||
},
|
||||
"current_schema_overclaims": [],
|
||||
"custom_signals": {},
|
||||
"dimension": "shared_claims_agent_positions",
|
||||
"invalid_count_invariant_detected": false,
|
||||
"legacy_pass": false,
|
||||
"legacy_signals": {
|
||||
"canonical_db": true,
|
||||
"caveat_retention": false,
|
||||
"no_overclaim": false
|
||||
},
|
||||
"max_response_words": 220,
|
||||
"overclaim_detected": false,
|
||||
"pass": false,
|
||||
"prompt_id": "OOS-11",
|
||||
"proposal_readiness_issues": [],
|
||||
"response_issue_detected": false,
|
||||
"response_too_long": true,
|
||||
"source_evidence_semantic_issues": [],
|
||||
"source_intake_issues": [],
|
||||
"word_count": 250
|
||||
},
|
||||
{
|
||||
"behavioral_rule_schema_issues": [],
|
||||
"broad_semantic_issues": [],
|
||||
"concepts": {
|
||||
"durable_session_continuity": true,
|
||||
"proof_tiers": true,
|
||||
"row_content_proof": true,
|
||||
"runtime_inputs": true
|
||||
},
|
||||
"current_schema_overclaims": [],
|
||||
"custom_signals": {},
|
||||
"dimension": "runtime_vs_canonical_causality",
|
||||
"invalid_count_invariant_detected": false,
|
||||
"legacy_pass": false,
|
||||
"legacy_signals": {
|
||||
"canonical_db": true,
|
||||
"no_overclaim": false
|
||||
},
|
||||
"max_response_words": 180,
|
||||
"overclaim_detected": false,
|
||||
"pass": true,
|
||||
"prompt_id": "OOS-10",
|
||||
"proposal_readiness_issues": [],
|
||||
"response_issue_detected": false,
|
||||
"response_too_long": false,
|
||||
"source_evidence_semantic_issues": [],
|
||||
"source_intake_issues": [],
|
||||
"word_count": 179
|
||||
},
|
||||
{
|
||||
"behavioral_rule_schema_issues": [],
|
||||
"broad_semantic_issues": [],
|
||||
"concepts": {
|
||||
"bounded_intake_tier": false,
|
||||
"real_source_identity": true,
|
||||
"staged_review_apply": true,
|
||||
"staging_without_apply_authorization": true
|
||||
},
|
||||
"current_schema_overclaims": [],
|
||||
"custom_signals": {},
|
||||
"dimension": "autonomous_source_intake_boundary",
|
||||
"invalid_count_invariant_detected": false,
|
||||
"legacy_pass": false,
|
||||
"legacy_signals": {
|
||||
"artifact": true,
|
||||
"authorization": false,
|
||||
"no_overclaim": false,
|
||||
"staging_or_review": false
|
||||
},
|
||||
"max_response_words": 220,
|
||||
"overclaim_detected": false,
|
||||
"pass": false,
|
||||
"prompt_id": "OOS-14",
|
||||
"proposal_readiness_issues": [],
|
||||
"response_issue_detected": false,
|
||||
"response_too_long": true,
|
||||
"source_evidence_semantic_issues": [],
|
||||
"source_intake_issues": [],
|
||||
"word_count": 226
|
||||
},
|
||||
{
|
||||
"behavioral_rule_schema_issues": [],
|
||||
"broad_semantic_issues": [],
|
||||
"concepts": {
|
||||
"behavioral_rule_storage": false,
|
||||
"heterogeneous_types": true,
|
||||
"receipt": true,
|
||||
"reviewed_policy_apply": false,
|
||||
"staged_review_apply": true
|
||||
},
|
||||
"current_schema_overclaims": [],
|
||||
"custom_signals": {},
|
||||
"dimension": "database_composition_judgment",
|
||||
"invalid_count_invariant_detected": false,
|
||||
"legacy_pass": false,
|
||||
"legacy_signals": {
|
||||
"canonical_db": true,
|
||||
"caveat_retention": false,
|
||||
"next_action": true,
|
||||
"no_overclaim": false,
|
||||
"staging_or_review": false
|
||||
},
|
||||
"max_response_words": 220,
|
||||
"overclaim_detected": false,
|
||||
"pass": false,
|
||||
"prompt_id": "OOS-06",
|
||||
"proposal_readiness_issues": [],
|
||||
"response_issue_detected": false,
|
||||
"response_too_long": true,
|
||||
"source_evidence_semantic_issues": [],
|
||||
"source_intake_issues": [],
|
||||
"word_count": 277
|
||||
}
|
||||
],
|
||||
"selected_prompt_ids": [
|
||||
"OOS-04",
|
||||
"OOS-11",
|
||||
"OOS-10",
|
||||
"OOS-14",
|
||||
"OOS-06"
|
||||
],
|
||||
"service_unchanged": true,
|
||||
"source_results_json": "docs/reports/leo-working-state-20260709/telegram-handler-m3taversal-oos-targeted-post-intake-composition-repair-20260713.json",
|
||||
"temp_profile_removed": true
|
||||
}
|
||||
|
|
@ -17,11 +17,12 @@ You are live Leo in Telegram, not a generic help bot.
|
|||
## Default Telegram Reply Budget
|
||||
|
||||
Unless the participant explicitly requests a detailed audit or long-form
|
||||
document, keep the entire reply at or below 220 words. A smaller requested word
|
||||
or line limit takes precedence. Lead with the answer, include only the evidence
|
||||
needed for the question, and do not repeat the answer as a summary. Broad or
|
||||
multi-part questions still receive one compressed answer, not a catalogue of
|
||||
every known rule.
|
||||
document, draft to at most 170 words and never exceed 220 words. A smaller
|
||||
requested word or line limit takes precedence. Lead with the answer, include
|
||||
only the evidence needed for the question, and do not repeat the answer as a
|
||||
summary. Broad or multi-part questions still receive one compressed answer, not
|
||||
a catalogue of every known rule. Before sending, remove extra headings, examples,
|
||||
and field inventories until the draft is within budget.
|
||||
|
||||
## Live Gateway Liveness
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ The canonical Teleo knowledge base is Postgres, not runtime memory.
|
|||
|
||||
This contract applies even when the operator asks a broad, multi-part question.
|
||||
Unless the operator explicitly asks for a detailed audit or long-form document,
|
||||
the final reply must be at most 220 words; keep the whole reply under 220 words.
|
||||
If the operator gives a smaller limit, that smaller word or line limit is
|
||||
mandatory. Silently shorten the draft before sending it; never explain that it
|
||||
was shortened.
|
||||
draft to at most 170 words and never exceed 220 words. If the operator gives a
|
||||
smaller limit, that smaller word or line limit is mandatory. Silently shorten
|
||||
the draft before sending it; never explain that it was shortened.
|
||||
|
||||
Use only this compact shape:
|
||||
|
||||
|
|
@ -68,7 +67,9 @@ Apply these gates before drafting the answer or proposing a next action:
|
|||
Capture a retained artifact, URL/storage path, and content hash; a chat label
|
||||
or `source_ref` is not source identity. The source compiler is build-only and
|
||||
locally proven, not autonomous live-VPS intake. It can create a
|
||||
`pending_review` packet without apply authorization. Current `approve_claim` cannot insert
|
||||
`pending_review` packet without apply authorization. Every current-capability
|
||||
intake answer must lead with: local compiler proven; live VPS/chat intake not
|
||||
shipped. Current `approve_claim` cannot insert
|
||||
`behavioral_rules`/`governance_gates`, update beliefs, or update an existing
|
||||
claim. Keep unsupported changes out of runnable apply sequences.
|
||||
`applied_at` belongs to the proposal receipt, not each inserted row.
|
||||
|
|
@ -85,6 +86,12 @@ Apply these gates before drafting the answer or proposing a next action:
|
|||
explanation. Ground the explanation in source/evidence or a separately
|
||||
reviewable claim. Do not invent a `retired` status value; retiring the old
|
||||
row needs a separately reviewed update capability and exact before/after proof.
|
||||
7. **Mixed-packet composition:** facts and disputed interpretations map to
|
||||
claims plus sources/evidence; reusable frameworks map to `reasoning_tools`,
|
||||
operating rules to `behavioral_rules`, evaluative gates to
|
||||
`governance_gates`, and agent positions to `beliefs`. Keep unsupported
|
||||
policy, gate, belief-update, and existing-row updates outside the runnable
|
||||
`approve_claim` sequence until a separate reviewed capability is live.
|
||||
|
||||
This is the VPS production leoclean surface. Before answering a KB-specific
|
||||
question, run the local bridge:
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ canonical database writes.
|
|||
## Mandatory Reply Contract
|
||||
|
||||
Unless the operator explicitly requests a detailed audit or long-form document,
|
||||
the final reply must be at most 220 words. A smaller word or line limit is
|
||||
mandatory.
|
||||
draft to at most 170 words; the final reply must never exceed 220 words. A
|
||||
smaller word or line limit is mandatory.
|
||||
|
||||
Use this shape:
|
||||
|
||||
|
|
@ -60,7 +60,9 @@ Apply these before drafting the answer or proposing a next action:
|
|||
URL/storage path, and content hash; reject a chat label or `source_ref` as
|
||||
source identity. The source compiler is build-only and locally proven, not
|
||||
autonomous live-VPS intake. It can create a `pending_review` packet without
|
||||
apply authorization. Approval begins before guarded canonical apply.
|
||||
apply authorization. Every current-capability intake answer must lead with:
|
||||
local compiler proven; live VPS/chat intake not shipped. Approval begins
|
||||
before guarded canonical apply.
|
||||
5. **Capability boundary:** current `approve_claim` accepts only `claims`,
|
||||
`sources`, `evidence`, `edges`, and `reasoning_tools`. It cannot insert
|
||||
`behavioral_rules` or `governance_gates`, update beliefs or an existing claim,
|
||||
|
|
@ -78,6 +80,13 @@ Apply these before drafting the answer or proposing a next action:
|
|||
field. A `supersedes` edge records a relationship, not the human explanation.
|
||||
Ground the explanation in source/evidence or a separately reviewable claim.
|
||||
Do not invent a `retired` status value.
|
||||
8. **Mixed-packet composition:** facts and disputed interpretations map to
|
||||
claims plus sources/evidence; a reusable framework maps to `reasoning_tools`,
|
||||
not a claim graph; operating rules map to `behavioral_rules`; evaluative gates
|
||||
map to `governance_gates`; agent positions map to `beliefs`. Current
|
||||
`approve_claim` can apply only its five supported collections. Keep policy,
|
||||
gate, belief-update, and existing-row updates staged until a separate reviewed
|
||||
capability is live; never list them in the supported apply order.
|
||||
|
||||
## Read Commands
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ CONCEPT_PATTERNS: dict[str, tuple[re.Pattern[str], ...]] = {
|
|||
"canonical_readback": (
|
||||
re.compile(
|
||||
r"DB readback|teleo-kb status|public\.\*|canonical (?:row|table|count)|"
|
||||
r"applied_at.{0,100}readiness",
|
||||
r"canonical (?:DB|database)|applied_at.{0,100}readiness",
|
||||
re.I | re.S,
|
||||
),
|
||||
),
|
||||
|
|
@ -244,7 +244,8 @@ CONCEPT_PATTERNS: dict[str, tuple[re.Pattern[str], ...]] = {
|
|||
re.compile(
|
||||
r"approved is not the same as applied|applied_at:\s*(?:none|null)|not canonical|"
|
||||
r"proposal does not commit|no receipt,? no durable knowledge|"
|
||||
r"approval.{0,60}not (?:a )?(?:DB|database|canonical) write|none.{0,30}applied",
|
||||
r"approval.{0,60}not (?:a )?(?:DB|database|canonical) write|"
|
||||
r"approval is intent,? not apply|none.{0,30}applied",
|
||||
re.I,
|
||||
),
|
||||
),
|
||||
|
|
@ -333,33 +334,49 @@ CONCEPT_PATTERNS: dict[str, tuple[re.Pattern[str], ...]] = {
|
|||
re.compile(r"separate.{0,50}reviewed apply|reviewed.{0,50}apply capability", re.I | re.S),
|
||||
),
|
||||
"runtime_inputs": (
|
||||
re.compile(r"Postgres|canonical (?:DB|database|counts?)", re.I),
|
||||
re.compile(r"Postgres|canonical (?:DB|database|counts?)|(?:DB|database) totals?", re.I),
|
||||
re.compile(r"skills?|runtime config|configuration|SOUL\.md", re.I),
|
||||
re.compile(r"session|conversation context", re.I),
|
||||
re.compile(r"unchanged.{0,80}(?:does not|doesn't|do not).{0,80}(?:behavior|answer)", re.I | re.S),
|
||||
re.compile(
|
||||
r"unchanged.{0,120}(?:does not|doesn't|do not).{0,80}(?:behavior|answer)|"
|
||||
r"(?:does not|doesn't|do not) prove.{0,60}(?:behavior|answer)",
|
||||
re.I | re.S,
|
||||
),
|
||||
),
|
||||
"durable_session_continuity": (
|
||||
re.compile(r"state\.db|session JSONL", re.I),
|
||||
re.compile(r"persist|durable|continuity", re.I),
|
||||
re.compile(r"restart.{0,80}(?:does not|doesn't|need not|not necessarily).{0,80}(?:erase|forget)", re.I | re.S),
|
||||
re.compile(
|
||||
r"restart.{0,80}(?:does not|doesn't|need not|not necessarily).{0,80}(?:erase|forget)|"
|
||||
r"(?:state\.db|session JSONL).{0,120}(?:preserve|continuity|survive).{0,80}restart",
|
||||
re.I | re.S,
|
||||
),
|
||||
),
|
||||
"row_content_proof": (
|
||||
re.compile(r"unchanged (?:counts?|totals?)", re.I),
|
||||
re.compile(r"does not prove|doesn't prove|do not prove", re.I),
|
||||
re.compile(r"row (?:IDs?|hashes?)|fingerprints?|timestamps?|balanced (?:insert|write|change)", re.I),
|
||||
re.compile(
|
||||
r"row (?:IDs?|hashes?)|fingerprints?|timestamps?|balanced (?:insert|write|change)|"
|
||||
r"individual rows?.{0,60}(?:mutated|changed|updated)",
|
||||
re.I | re.S,
|
||||
),
|
||||
),
|
||||
"proof_tiers": (
|
||||
re.compile(r"handler|temporary[- ]profile|GatewayRunner", re.I),
|
||||
re.compile(r"Telegram", re.I),
|
||||
re.compile(r"proof tiers?|tier 1.{0,500}tier 2.{0,500}tier 3", re.I | re.S),
|
||||
re.compile(r"canonical|public\.\*|DB mutation|database mutation", re.I),
|
||||
re.compile(r"runtime|skills?|session|SOUL\.md", re.I),
|
||||
),
|
||||
"shared_knowledge_commons": (
|
||||
re.compile(
|
||||
r"shared (?:claim|knowledge|commons)|claims.{0,40}shared|one factual claim|store it once",
|
||||
r"shared (?:claim|knowledge|commons)|claims.{0,40}shared|one factual claim|"
|
||||
r"keep the factual claim once|store it once",
|
||||
re.I | re.S,
|
||||
),
|
||||
re.compile(r"source|evidence", re.I),
|
||||
re.compile(r"do not duplicate|don'?t duplicate|one shared claim|single shared claim", re.I),
|
||||
re.compile(
|
||||
r"do not duplicate|don'?t duplicate|one shared claim|single shared claim|duplicating (?:the )?claim",
|
||||
re.I,
|
||||
),
|
||||
),
|
||||
"agent_specific_positions": (
|
||||
re.compile(r"public\.beliefs", re.I),
|
||||
|
|
@ -452,7 +469,8 @@ SCHEMA_GAP_QUALIFIER_RE = re.compile(
|
|||
)
|
||||
CURRENT_SCHEMA_ASSERTION_PATTERNS: dict[str, re.Pattern[str]] = {
|
||||
"claims_unshipped_fields": re.compile(
|
||||
r"(?:public\.)?claims?.{0,100}\b(?:body|metadata|forecast[_ -]resolution|resolved_at)\b",
|
||||
r"(?:public\.)?claims?\b.{0,60}(?:stores?|has|have|with|column|field).{0,40}"
|
||||
r"\b(?:body|metadata|forecast[_ -]resolution|resolved_at)\b",
|
||||
re.I,
|
||||
),
|
||||
"sources_unshipped_fields": re.compile(
|
||||
|
|
@ -554,7 +572,8 @@ APPLYABILITY_GAP_RE = re.compile(
|
|||
r"approved_needs_apply_payload|worker_(?:contract_)?applyable(?:_count)?\s*[:=]?\s*(?:false|0)|"
|
||||
r"(?:no|missing|without).{0,50}(?:strict )?apply_payload|"
|
||||
r"normaliz(?:e|ation).{0,100}(?:before|then).{0,60}(?:review|apply)|"
|
||||
r"not (?:directly )?applyable",
|
||||
r"not (?:directly )?applyable|(?:after|once|must|requires?).{0,40}strict apply payload|"
|
||||
r"strict apply payload.{0,50}(?:built|build|reviewed|review)",
|
||||
re.I | re.S,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ def test_leoclean_kb_skills_separate_runtime_session_and_delivery_proof_tiers()
|
|||
text = _kb_skill_bundle(surface)
|
||||
squashed = " ".join(text.split())
|
||||
|
||||
assert "keep the whole reply under 220 words" in squashed
|
||||
assert "never exceed 220 words" in squashed or "keep the whole reply under 220 words" in squashed
|
||||
assert "Postgres is canonical knowledge, but it is not the only input" in squashed
|
||||
assert "Hermes `state.db` and session JSONL provide durable continuity" in squashed
|
||||
assert "not Telegram-visible delivery proof" in squashed
|
||||
|
|
@ -219,11 +219,13 @@ def test_vps_skills_enforce_compact_default_answers_without_losing_detail_on_req
|
|||
kb_squashed = " ".join(kb_text.split())
|
||||
telegram_squashed = " ".join(telegram_text.split())
|
||||
|
||||
assert "final reply must be at most 220 words" in kb_squashed
|
||||
assert "final reply must never exceed 220 words" in kb_squashed
|
||||
assert "draft to at most 170 words" in kb_squashed
|
||||
assert "smaller word or line limit is mandatory" in kb_squashed
|
||||
assert "at most three short bullets" in kb_squashed
|
||||
assert "Do not mirror this skill" in kb_squashed
|
||||
assert "Broad or multi-part questions still receive one compressed answer" in telegram_squashed
|
||||
assert "draft to at most 170 words and never exceed 220 words" in telegram_squashed
|
||||
assert "explicitly requests a detailed audit or long-form document" in telegram_squashed
|
||||
|
||||
|
||||
|
|
@ -252,3 +254,6 @@ def test_vps_kb_skill_encodes_apply_readiness_beliefs_and_current_proof_boundari
|
|||
assert "`applied_at` belongs to the proposal receipt, not each inserted row" in squashed
|
||||
assert "`state.db` and session JSONL can preserve continuity across restart" in squashed
|
||||
assert "It has no `author`, `title`, `publisher`, or publication-date column" in squashed
|
||||
assert "local compiler proven; live VPS/chat intake not shipped" in squashed
|
||||
assert "a reusable framework maps to `reasoning_tools`, not a claim graph" in squashed
|
||||
assert "never list them in the supported apply order" in squashed
|
||||
|
|
|
|||
|
|
@ -346,6 +346,21 @@ def test_oos_direct_apply_case_accepts_natural_live_readback_wording() -> None:
|
|||
assert score["pass"] is True
|
||||
|
||||
|
||||
def test_oos_direct_apply_case_accepts_strict_payload_as_precondition_wording() -> None:
|
||||
token = "demo-ledger-deadbeef"
|
||||
prompt = benchmark.prompt_catalog(token)[3]
|
||||
reply = (
|
||||
"No. All three approved proposals have applied_at: null. None have been written to the canonical database; "
|
||||
"reviewer approval is intent, not apply. Proof that changes the answer: non-null applied_at plus row-level "
|
||||
"postflight after a strict apply payload is built, reviewed, the worker is confirmed active, and an "
|
||||
"authorized transaction commits."
|
||||
)
|
||||
|
||||
score = benchmark.score_reply(prompt, reply, memory_token=token)
|
||||
|
||||
assert score["pass"] is True
|
||||
|
||||
|
||||
def test_oos_agent_position_case_requires_current_public_beliefs_contract() -> None:
|
||||
token = "demo-ledger-deadbeef"
|
||||
prompt = benchmark.prompt_catalog(token)[10]
|
||||
|
|
@ -389,6 +404,26 @@ def test_oos_source_intake_rejects_unshipped_canonical_source_metadata_columns()
|
|||
assert benchmark.current_schema_overclaims(reply) == ["sources_unshipped_fields"]
|
||||
|
||||
|
||||
def test_oos_schema_guard_does_not_confuse_candidate_claims_with_source_metadata() -> None:
|
||||
reply = "Extract candidate claims, draft source metadata, and keep both inside a pending_review proposal."
|
||||
|
||||
assert benchmark.current_schema_overclaims(reply) == []
|
||||
|
||||
|
||||
def test_oos_runtime_case_accepts_explicit_persistence_tiers() -> None:
|
||||
token = "demo-ledger-deadbeef"
|
||||
prompt = benchmark.prompt_catalog(token)[9]
|
||||
reply = (
|
||||
"No to both. Unchanged totals do not prove behavior is unchanged. Individual rows could have been updated. "
|
||||
"Proof tiers: Tier 1 is canonical DB counts; Tier 2 is runtime skills, config, SOUL.md, state.db and session "
|
||||
"JSONL, which can preserve continuity across restart; Tier 3 is transient context."
|
||||
)
|
||||
|
||||
score = benchmark.score_reply(prompt, reply, memory_token=token)
|
||||
|
||||
assert score["pass"] is True
|
||||
|
||||
|
||||
def test_oos_composition_rejects_belief_edges_and_per_step_applied_at() -> None:
|
||||
reply = "The old belief row gets a supersedes edge. Each step gets a non-null applied_at before the next runs."
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue