Ground Leo composition in live Postgres constraints
This commit is contained in:
parent
5bc78a2a5a
commit
e3af44772e
9 changed files with 417 additions and 6 deletions
|
|
@ -67,6 +67,18 @@ if ! git merge --ff-only "$DEPLOY_REMOTE/main" --quiet 2>&1; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A running shell keeps the old script body after git updates this file. Re-exec
|
||||||
|
# once from the merged checkout so newly added sync/restart paths take effect in
|
||||||
|
# the same deploy instead of writing a false-success stamp.
|
||||||
|
if [ "${TELEO_AUTO_DEPLOY_REEXECED:-0}" != "1" ] \
|
||||||
|
&& [ "$OLD_SHA" != "none" ] \
|
||||||
|
&& git diff --name-only "$OLD_SHA" "$NEW_SHA" -- deploy/auto-deploy.sh deploy/leoclean-gateway-restart-required.sh \
|
||||||
|
| grep -q .; then
|
||||||
|
log "Deploy logic changed; re-executing merged deploy script"
|
||||||
|
export TELEO_AUTO_DEPLOY_REEXECED=1
|
||||||
|
exec bash "$DEPLOY_CHECKOUT/deploy/auto-deploy.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
# Syntax check all Python files before copying
|
# Syntax check all Python files before copying
|
||||||
ERRORS=0
|
ERRORS=0
|
||||||
for f in lib/*.py *.py diagnostics/*.py telegram/*.py tests/*.py hermes-agent/leoclean-plugins/vps/*/*.py; do
|
for f in lib/*.py *.py diagnostics/*.py telegram/*.py tests/*.py hermes-agent/leoclean-plugins/vps/*/*.py; do
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"database_context_all_ok": true,
|
||||||
|
"database_context_injection_count": 2,
|
||||||
|
"database_context_trace_ok": true,
|
||||||
|
"db_counts_changed": false,
|
||||||
|
"generated_at_utc": "2026-07-13T10:46:31.408830+00:00",
|
||||||
|
"mode": "working_leo_m3taversal_targeted_live_database_context_rescore",
|
||||||
|
"posted_to_telegram": false,
|
||||||
|
"production_db_apply_ran": false,
|
||||||
|
"safe_pass": false,
|
||||||
|
"score": {
|
||||||
|
"expected_prompt_count": 2,
|
||||||
|
"failures": [
|
||||||
|
{
|
||||||
|
"behavioral_rule_schema_issues": [],
|
||||||
|
"broad_semantic_issues": [],
|
||||||
|
"concepts": {
|
||||||
|
"behavioral_rule_storage": false,
|
||||||
|
"heterogeneous_types": true,
|
||||||
|
"receipt": false,
|
||||||
|
"reviewed_policy_apply": false,
|
||||||
|
"staged_review_apply": true
|
||||||
|
},
|
||||||
|
"current_schema_overclaims": [
|
||||||
|
"unreviewed_claim_type"
|
||||||
|
],
|
||||||
|
"custom_signals": {},
|
||||||
|
"dimension": "database_composition_judgment",
|
||||||
|
"invalid_count_invariant_detected": false,
|
||||||
|
"legacy_pass": false,
|
||||||
|
"legacy_signals": {
|
||||||
|
"canonical_db": false,
|
||||||
|
"caveat_retention": false,
|
||||||
|
"next_action": true,
|
||||||
|
"no_overclaim": true,
|
||||||
|
"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": false,
|
||||||
|
"source_evidence_semantic_issues": [],
|
||||||
|
"source_intake_issues": [],
|
||||||
|
"word_count": 207
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pass": false,
|
||||||
|
"passes": 1,
|
||||||
|
"scores": [
|
||||||
|
{
|
||||||
|
"behavioral_rule_schema_issues": [],
|
||||||
|
"broad_semantic_issues": [],
|
||||||
|
"concepts": {
|
||||||
|
"bounded_intake_tier": true,
|
||||||
|
"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": true,
|
||||||
|
"staging_or_review": true
|
||||||
|
},
|
||||||
|
"max_response_words": 220,
|
||||||
|
"overclaim_detected": false,
|
||||||
|
"pass": true,
|
||||||
|
"prompt_id": "OOS-14",
|
||||||
|
"proposal_readiness_issues": [],
|
||||||
|
"response_issue_detected": false,
|
||||||
|
"response_too_long": false,
|
||||||
|
"source_evidence_semantic_issues": [],
|
||||||
|
"source_intake_issues": [],
|
||||||
|
"word_count": 201
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"behavioral_rule_schema_issues": [],
|
||||||
|
"broad_semantic_issues": [],
|
||||||
|
"concepts": {
|
||||||
|
"behavioral_rule_storage": false,
|
||||||
|
"heterogeneous_types": true,
|
||||||
|
"receipt": false,
|
||||||
|
"reviewed_policy_apply": false,
|
||||||
|
"staged_review_apply": true
|
||||||
|
},
|
||||||
|
"current_schema_overclaims": [
|
||||||
|
"unreviewed_claim_type"
|
||||||
|
],
|
||||||
|
"custom_signals": {},
|
||||||
|
"dimension": "database_composition_judgment",
|
||||||
|
"invalid_count_invariant_detected": false,
|
||||||
|
"legacy_pass": false,
|
||||||
|
"legacy_signals": {
|
||||||
|
"canonical_db": false,
|
||||||
|
"caveat_retention": false,
|
||||||
|
"next_action": true,
|
||||||
|
"no_overclaim": true,
|
||||||
|
"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": false,
|
||||||
|
"source_evidence_semantic_issues": [],
|
||||||
|
"source_intake_issues": [],
|
||||||
|
"word_count": 207
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"selected_prompt_ids": [
|
||||||
|
"OOS-14",
|
||||||
|
"OOS-06"
|
||||||
|
],
|
||||||
|
"service_unchanged": true,
|
||||||
|
"source_results_json": "docs/reports/leo-working-state-20260709/telegram-handler-m3taversal-oos-targeted-post-live-db-context-injection-20260713.json",
|
||||||
|
"temp_profile_removed": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
{
|
||||||
|
"before_service": {
|
||||||
|
"ActiveState": "active",
|
||||||
|
"ExecMainStartTimestamp": "Mon 2026-07-13 10:40:20 UTC",
|
||||||
|
"MainPID": "3520287",
|
||||||
|
"NRestarts": "0",
|
||||||
|
"SubState": "running"
|
||||||
|
},
|
||||||
|
"changed_live_profile": false,
|
||||||
|
"database_context_all_ok": true,
|
||||||
|
"database_context_injection_count": 2,
|
||||||
|
"database_context_trace": [
|
||||||
|
{
|
||||||
|
"contract_ids": [
|
||||||
|
"reply_budget",
|
||||||
|
"source_intake"
|
||||||
|
],
|
||||||
|
"contract_sha256": "9815d85fdd1dc8145d9db79207d7fe37b0df3c81e82b69075f009880d8bf6cd2",
|
||||||
|
"generated_at_utc": "2026-07-13T10:41:17.892279+00:00",
|
||||||
|
"injected": true,
|
||||||
|
"query_sha256": "45141620c3405af992012e2bd5000cabd8a6bffbc784082e856ea1a18b6aec06",
|
||||||
|
"source": "kb_tool.py --local context",
|
||||||
|
"status": "ok"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contract_ids": [
|
||||||
|
"reply_budget",
|
||||||
|
"mixed_packet_composition"
|
||||||
|
],
|
||||||
|
"contract_sha256": "f93791c5c0c04895d0bc3080a9eb869d175b61c48e7baa0df19e7ecbddbd7d0a",
|
||||||
|
"generated_at_utc": "2026-07-13T10:41:32.752160+00:00",
|
||||||
|
"injected": true,
|
||||||
|
"query_sha256": "13c255fda3a35cd913ba92960bcda1b4dbcf55a38f3301bdc2a74a8eb040df23",
|
||||||
|
"source": "kb_tool.py --local context",
|
||||||
|
"status": "ok"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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-13T10:41:14.394965+00:00",
|
||||||
|
"handler": {
|
||||||
|
"authorized": true,
|
||||||
|
"session_key": "agent:main:telegram:group:-5146042086:9070919",
|
||||||
|
"temp_profile": "/tmp/leo-direct-claim-handler-v9i4nyxp/profile"
|
||||||
|
},
|
||||||
|
"harness_notes": [
|
||||||
|
"Unchanged broad OOS-14 and OOS-06 prompts; current behavior is injected from live teleo-kb operational contracts.",
|
||||||
|
"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_live_database_context",
|
||||||
|
"mutates_kb_by_harness": false,
|
||||||
|
"pass_runtime": true,
|
||||||
|
"posted_to_telegram": false,
|
||||||
|
"remote_report_path": "/tmp/leo-m3taversal-oos-targeted-live-db-context-a40b57083d5b.json",
|
||||||
|
"remote_returncode": 0,
|
||||||
|
"remote_run_id": "a40b57083d5b",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||||
|
"database_context_trace": [
|
||||||
|
{
|
||||||
|
"contract_ids": [
|
||||||
|
"reply_budget",
|
||||||
|
"source_intake"
|
||||||
|
],
|
||||||
|
"contract_sha256": "9815d85fdd1dc8145d9db79207d7fe37b0df3c81e82b69075f009880d8bf6cd2",
|
||||||
|
"generated_at_utc": "2026-07-13T10:41:17.892279+00:00",
|
||||||
|
"injected": true,
|
||||||
|
"query_sha256": "45141620c3405af992012e2bd5000cabd8a6bffbc784082e856ea1a18b6aec06",
|
||||||
|
"source": "kb_tool.py --local context",
|
||||||
|
"status": "ok"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dimension": "autonomous_source_intake_boundary",
|
||||||
|
"ended_at_utc": "2026-07-13T10:41:32.657308+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": "What Leo captures immediately, no approval gate:\n\n- Artifact content, a stable storage_path or URL, and a content hash \u2014 those three are the real source identity per the schema (public.sources columns). Chat label, filename, or attachment ref are not source identity and must not be treated as such.\n- Candidate claims extracted into a pending_review proposal packet \u2014 staged, not applied.\n\nWhere approval begins:\n\nAny write to a guarded canonical public.* table (applying a proposal, committing a source row, landing a KB claim) requires explicit authorization. Staging and extraction run free; canonical apply does not.\n\nOne constraint to name plainly:\n\nThe local compiler is proven; live VPS/chat intake is not shipped. Leo cannot invoke the compiler from this chat session. What I can do right now is reason over a document you paste and produce a structured proposal packet in the reply \u2014 you then route that output through the compiler manually. That gap is the honest ceiling on \"absorb without approval.\"\n\nSo the practical boundary is: paste the document, I extract and structure candidates, you get a reviewable packet, you authorize the apply run. Everything upstream of that apply is mechanical and safe; everything at or past it is yours to gate.",
|
||||||
|
"started_at_utc": "2026-07-13T10:41:15.113487+00:00",
|
||||||
|
"turn": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"claim_ceiling": "Live VPS GatewayRunner reply from temp leoclean profile; no Telegram post; no production DB apply authorized.",
|
||||||
|
"database_context_trace": [
|
||||||
|
{
|
||||||
|
"contract_ids": [
|
||||||
|
"reply_budget",
|
||||||
|
"mixed_packet_composition"
|
||||||
|
],
|
||||||
|
"contract_sha256": "f93791c5c0c04895d0bc3080a9eb869d175b61c48e7baa0df19e7ecbddbd7d0a",
|
||||||
|
"generated_at_utc": "2026-07-13T10:41:32.752160+00:00",
|
||||||
|
"injected": true,
|
||||||
|
"query_sha256": "13c255fda3a35cd913ba92960bcda1b4dbcf55a38f3301bdc2a74a8eb040df23",
|
||||||
|
"source": "kb_tool.py --local context",
|
||||||
|
"status": "ok"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dimension": "database_composition_judgment",
|
||||||
|
"ended_at_utc": "2026-07-13T10:41:49.261157+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 elements, five destinations \u2014 nothing flattened:\n\n- Factual observations \u2192 claims rows (type: observation, status: review) backed by a sources row and evidence rows linking evidence to claim. Disputed interpretation \u2192 claims row (status: disputed) plus a claim_edges row pointing from the dispute to the observation it contests \u2014 edges connect claim IDs only, never beliefs or reasoning_tools.\n- Strategic framework \u2192 reasoning_tools row (name, description, category). No scope field exists; scope goes in description.\n- Governance rule and belief correction \u2192 staged but not applied. Both behavioral_rules and beliefs are guards-protected; keep in proposal packet flagged keep_staged until a separate apply capability is authorized.\n\nReview and apply sequence:\n\n1. Reviewer inspects the full packet \u2014 five distinct sections, each mapped to its table, schema guards checked (no falsifier on claims, no status on behavioral_rules, edge endpoints are claim IDs).\n2. On approval: apply in dependency order \u2014 sources first, then claims, then evidence, then claim_edges, then reasoning_tools. That order ensures foreign keys resolve.\n3. Governance rule and belief correction surface as a second review gate, separate PR. Reviewer confirms the belief row to update (by ID) and the exact old text before any write lands.\n\nNothing in the packet shares a row type. Later reasoning can query each layer independently without untangling a flat claim pile.",
|
||||||
|
"started_at_utc": "2026-07-13T10:41:32.660716+00:00",
|
||||||
|
"turn": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"service_before_after": {
|
||||||
|
"after": {
|
||||||
|
"ActiveState": "active",
|
||||||
|
"ExecMainStartTimestamp": "Mon 2026-07-13 10:40:20 UTC",
|
||||||
|
"MainPID": "3520287",
|
||||||
|
"NRestarts": "0",
|
||||||
|
"SubState": "running"
|
||||||
|
},
|
||||||
|
"before": {
|
||||||
|
"ActiveState": "active",
|
||||||
|
"ExecMainStartTimestamp": "Mon 2026-07-13 10:40:20 UTC",
|
||||||
|
"MainPID": "3520287",
|
||||||
|
"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-live-db-context-injection-20260713.json",
|
||||||
|
"temp_profile_removed": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Working Leo Targeted Live Database Context
|
||||||
|
|
||||||
|
Generated UTC: `2026-07-13T10:46:31.408830+00:00`
|
||||||
|
Safe pass: `False`
|
||||||
|
Prompts: `1/2`
|
||||||
|
Database context injections: `2`
|
||||||
|
Database context all OK: `True`
|
||||||
|
DB counts changed: `False`
|
||||||
|
Service unchanged: `True`
|
||||||
|
Temporary profile removed: `True`
|
||||||
|
Posted to Telegram: `False`
|
||||||
|
|
||||||
|
## Prompt Scores
|
||||||
|
|
||||||
|
- `OOS-14`: `pass=True`, words=`201`
|
||||||
|
- `OOS-06`: `pass=False`, words=`207`
|
||||||
|
|
||||||
|
## Claim Ceiling
|
||||||
|
|
||||||
|
This proves the live VPS GatewayRunner received query-specific current database contracts before reasoning. OOS-14 passed; OOS-06 still invented unsupported claim values and omitted the apply receipt. No Telegram post or production DB apply ran.
|
||||||
|
|
@ -330,12 +330,16 @@ def with_proposal_readiness(proposal: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
|
||||||
|
|
||||||
def operational_contracts(
|
def operational_contracts(
|
||||||
query: str, *, current_schema: dict[str, list[str] | tuple[str, ...]] | None = None
|
query: str,
|
||||||
|
*,
|
||||||
|
current_schema: dict[str, list[str] | tuple[str, ...]] | None = None,
|
||||||
|
current_constraints: dict[str, dict[str, str]] | None = None,
|
||||||
) -> list[dict[str, Any]]:
|
) -> list[dict[str, Any]]:
|
||||||
"""Return question-specific current-runtime truth, not recalled architecture."""
|
"""Return question-specific current-runtime truth, not recalled architecture."""
|
||||||
|
|
||||||
lowered = query.lower()
|
lowered = query.lower()
|
||||||
schema = current_schema if current_schema is not None else CURRENT_PUBLIC_SCHEMA
|
schema = current_schema if current_schema is not None else CURRENT_PUBLIC_SCHEMA
|
||||||
|
constraints = current_constraints or {}
|
||||||
contracts: list[dict[str, Any]] = [
|
contracts: list[dict[str, Any]] = [
|
||||||
{
|
{
|
||||||
"id": "reply_budget",
|
"id": "reply_budget",
|
||||||
|
|
@ -399,6 +403,8 @@ def operational_contracts(
|
||||||
"claims has no falsifier field",
|
"claims has no falsifier field",
|
||||||
"behavioral_rules has no status field",
|
"behavioral_rules has no status field",
|
||||||
"applied_at belongs to the proposal receipt, not each row",
|
"applied_at belongs to the proposal receipt, not each row",
|
||||||
|
"use only claim type/status values allowed by the current Postgres CHECK constraints",
|
||||||
|
"pending_review is a proposal state, not a public.claims status",
|
||||||
],
|
],
|
||||||
"current_columns": {
|
"current_columns": {
|
||||||
name: list(schema.get(name, ()))
|
name: list(schema.get(name, ()))
|
||||||
|
|
@ -411,6 +417,16 @@ def operational_contracts(
|
||||||
"beliefs",
|
"beliefs",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
"current_constraints": {
|
||||||
|
name: constraints.get(name, {})
|
||||||
|
for name in ("claims", "claim_edges", "beliefs")
|
||||||
|
},
|
||||||
|
"review_apply_sequence": [
|
||||||
|
"stage one typed pending_review proposal packet without canonical writes",
|
||||||
|
"review mappings, evidence, unsupported changes, and exact row values",
|
||||||
|
"apply only supported collections after explicit authorization and keep unsupported changes staged",
|
||||||
|
"record proposal-level applied_at plus created/updated row IDs and postflight readback",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -475,6 +491,25 @@ def load_current_public_schema(args: argparse.Namespace, table_names: set[str])
|
||||||
return {row["table_name"]: row["columns"] for row in psql_json(args, sql)}
|
return {row["table_name"]: row["columns"] for row in psql_json(args, sql)}
|
||||||
|
|
||||||
|
|
||||||
|
def load_current_public_constraints(args: argparse.Namespace, table_names: set[str]) -> dict[str, dict[str, str]]:
|
||||||
|
if not table_names:
|
||||||
|
return {}
|
||||||
|
sql = f"""
|
||||||
|
select jsonb_build_object(
|
||||||
|
'table_name', t.relname,
|
||||||
|
'constraints', jsonb_object_agg(c.conname, pg_get_constraintdef(c.oid) order by c.conname)
|
||||||
|
)::text
|
||||||
|
from pg_constraint c
|
||||||
|
join pg_class t on t.oid = c.conrelid
|
||||||
|
join pg_namespace n on n.oid = t.relnamespace
|
||||||
|
where n.nspname = 'public'
|
||||||
|
and t.relname = any({sql_array(sorted(table_names))})
|
||||||
|
group by t.relname
|
||||||
|
order by t.relname;
|
||||||
|
"""
|
||||||
|
return {row["table_name"]: row["constraints"] for row in psql_json(args, sql)}
|
||||||
|
|
||||||
|
|
||||||
def context_operational_contracts(args: argparse.Namespace, query: str) -> list[dict[str, Any]]:
|
def context_operational_contracts(args: argparse.Namespace, query: str) -> list[dict[str, Any]]:
|
||||||
initial = operational_contracts(query)
|
initial = operational_contracts(query)
|
||||||
contract_ids = {contract["id"] for contract in initial}
|
contract_ids = {contract["id"] for contract in initial}
|
||||||
|
|
@ -487,7 +522,11 @@ def context_operational_contracts(args: argparse.Namespace, query: str) -> list[
|
||||||
)
|
)
|
||||||
if not table_names:
|
if not table_names:
|
||||||
return initial
|
return initial
|
||||||
return operational_contracts(query, current_schema=load_current_public_schema(args, table_names))
|
return operational_contracts(
|
||||||
|
query,
|
||||||
|
current_schema=load_current_public_schema(args, table_names),
|
||||||
|
current_constraints=load_current_public_constraints(args, table_names),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def claim_base_url() -> str:
|
def claim_base_url() -> str:
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,11 @@ CONCEPT_PATTERNS: dict[str, tuple[re.Pattern[str], ...]] = {
|
||||||
),
|
),
|
||||||
"bounded_intake_tier": (
|
"bounded_intake_tier": (
|
||||||
re.compile(r"build-only|local(?:ly)?|clone", re.I),
|
re.compile(r"build-only|local(?:ly)?|clone", re.I),
|
||||||
re.compile(r"not yet.{0,80}(?:live|autonomous|production)|not.{0,80}live-VPS", re.I | re.S),
|
re.compile(
|
||||||
|
r"not yet.{0,80}(?:live|autonomous|production)|not.{0,80}live-VPS|"
|
||||||
|
r"live.{0,80}(?:not shipped|not live|unavailable)",
|
||||||
|
re.I | re.S,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
"valid_supersession": (
|
"valid_supersession": (
|
||||||
re.compile(r"new|replacement", re.I),
|
re.compile(r"new|replacement", re.I),
|
||||||
|
|
@ -671,8 +675,13 @@ def broad_semantic_issues(reply: str) -> list[str]:
|
||||||
findings.add("belief_row_given_claim_edge")
|
findings.add("belief_row_given_claim_edge")
|
||||||
if ROW_LEVEL_APPLIED_AT_RE.search(reply):
|
if ROW_LEVEL_APPLIED_AT_RE.search(reply):
|
||||||
findings.add("applied_at_assigned_to_each_apply_step")
|
findings.add("applied_at_assigned_to_each_apply_step")
|
||||||
if REASONING_TOOL_CLAIM_EDGE_RE.search(reply):
|
for segment in re.split(r"(?<=[.!?])\s+|\n+", reply):
|
||||||
|
if not REASONING_TOOL_CLAIM_EDGE_RE.search(segment):
|
||||||
|
continue
|
||||||
|
if re.search(r"(?:never|do not|don't|must not|cannot).{0,100}reasoning_tools?", segment, re.I | re.S):
|
||||||
|
continue
|
||||||
findings.add("claim_edge_pointed_at_reasoning_tool")
|
findings.add("claim_edge_pointed_at_reasoning_tool")
|
||||||
|
break
|
||||||
return sorted(findings)
|
return sorted(findings)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,11 @@ def test_vps_bridge_context_contract_reads_current_schema_from_postgres(monkeypa
|
||||||
|
|
||||||
def fake_psql_json(_args, sql):
|
def fake_psql_json(_args, sql):
|
||||||
captured_sql.append(sql)
|
captured_sql.append(sql)
|
||||||
return [{"table_name": "sources", "columns": ["id", "source_type", "url", "hash", "new_live_column"]}]
|
if "information_schema.columns" in sql:
|
||||||
|
return [
|
||||||
|
{"table_name": "sources", "columns": ["id", "source_type", "url", "hash", "new_live_column"]}
|
||||||
|
]
|
||||||
|
return [{"table_name": "sources", "constraints": {"sources_pkey": "PRIMARY KEY (id)"}}]
|
||||||
|
|
||||||
monkeypatch.setattr(module, "psql_json", fake_psql_json)
|
monkeypatch.setattr(module, "psql_json", fake_psql_json)
|
||||||
contracts = {
|
contracts = {
|
||||||
|
|
@ -270,9 +274,41 @@ def test_vps_bridge_context_contract_reads_current_schema_from_postgres(monkeypa
|
||||||
"hash",
|
"hash",
|
||||||
"new_live_column",
|
"new_live_column",
|
||||||
]
|
]
|
||||||
assert len(captured_sql) == 1
|
assert len(captured_sql) == 2
|
||||||
assert "information_schema.columns" in captured_sql[0]
|
assert "information_schema.columns" in captured_sql[0]
|
||||||
assert "table_name = any" in captured_sql[0]
|
assert "table_name = any" in captured_sql[0]
|
||||||
|
assert "pg_constraint" in captured_sql[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_vps_bridge_mixed_contract_reads_live_postgres_constraints(monkeypatch) -> None:
|
||||||
|
module = _load_module(BRIDGE_DIR / "kb_tool.py")
|
||||||
|
|
||||||
|
def fake_psql_json(_args, sql):
|
||||||
|
if "information_schema.columns" in sql:
|
||||||
|
return [{"table_name": "claims", "columns": ["id", "type", "text", "status"]}]
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"table_name": "claims",
|
||||||
|
"constraints": {
|
||||||
|
"claims_type_check": "CHECK ((type = ANY (ARRAY['empirical', 'structural'])))",
|
||||||
|
"claims_status_check": "CHECK ((status = ANY (ARRAY['open', 'retired'])))",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
monkeypatch.setattr(module, "psql_json", fake_psql_json)
|
||||||
|
|
||||||
|
contracts = {
|
||||||
|
item["id"]: item
|
||||||
|
for item in module.context_operational_contracts(
|
||||||
|
SimpleNamespace(),
|
||||||
|
"Compose a packet with factual observations, a strategic framework, and a governance rule.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mixed = contracts["mixed_packet_composition"]
|
||||||
|
assert "'empirical'" in mixed["current_constraints"]["claims"]["claims_type_check"]
|
||||||
|
assert "'open'" in mixed["current_constraints"]["claims"]["claims_status_check"]
|
||||||
|
assert "proposal-level applied_at" in mixed["review_apply_sequence"][-1]
|
||||||
|
|
||||||
|
|
||||||
def test_vps_bridge_decision_matrix_status_checks_schema_tables(monkeypatch) -> None:
|
def test_vps_bridge_decision_matrix_status_checks_schema_tables(monkeypatch) -> None:
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,8 @@ def test_deploy_scripts_sync_leoclean_skills_and_restart_gateway_for_runtime_cha
|
||||||
assert 'hermes-agent/leoclean-skills/vps/' in auto_deploy
|
assert 'hermes-agent/leoclean-skills/vps/' in auto_deploy
|
||||||
assert 'hermes-agent/leoclean-plugins/vps/' in auto_deploy
|
assert 'hermes-agent/leoclean-plugins/vps/' in auto_deploy
|
||||||
assert 'deploy/leoclean-gateway-restart-required.sh' in auto_deploy
|
assert 'deploy/leoclean-gateway-restart-required.sh' in auto_deploy
|
||||||
|
assert 'TELEO_AUTO_DEPLOY_REEXECED' in auto_deploy
|
||||||
|
assert 'exec bash "$DEPLOY_CHECKOUT/deploy/auto-deploy.sh"' in auto_deploy
|
||||||
assert 'add_restart_if_unit_active leoclean-gateway' in auto_deploy
|
assert 'add_restart_if_unit_active leoclean-gateway' in auto_deploy
|
||||||
assert 'sudo systemctl restart "$svc"' in auto_deploy
|
assert 'sudo systemctl restart "$svc"' in auto_deploy
|
||||||
assert "sudo systemctl restart $RESTART" not in auto_deploy
|
assert "sudo systemctl restart $RESTART" not in auto_deploy
|
||||||
|
|
|
||||||
|
|
@ -441,6 +441,17 @@ def test_oos_composition_rejects_claim_edge_to_reasoning_tool() -> None:
|
||||||
assert benchmark.broad_semantic_issues(reply) == ["claim_edge_pointed_at_reasoning_tool"]
|
assert benchmark.broad_semantic_issues(reply) == ["claim_edge_pointed_at_reasoning_tool"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_oos_composition_accepts_explicit_reasoning_tool_edge_prohibition() -> None:
|
||||||
|
reply = "claim_edges connect claim IDs only; they must never point at beliefs or reasoning_tools."
|
||||||
|
assert benchmark.broad_semantic_issues(reply) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_oos_source_intake_accepts_live_not_shipped_wording() -> None:
|
||||||
|
patterns = benchmark.CONCEPT_PATTERNS["bounded_intake_tier"]
|
||||||
|
reply = "The local compiler is proven; live VPS/chat intake is not shipped."
|
||||||
|
assert all(pattern.search(reply) for pattern in patterns)
|
||||||
|
|
||||||
|
|
||||||
def test_oos_runtime_case_accepts_explicit_persistence_tiers() -> None:
|
def test_oos_runtime_case_accepts_explicit_persistence_tiers() -> None:
|
||||||
token = "demo-ledger-deadbeef"
|
token = "demo-ledger-deadbeef"
|
||||||
prompt = benchmark.prompt_catalog(token)[9]
|
prompt = benchmark.prompt_catalog(token)[9]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue