Some checks are pending
CI / lint-and-test (push) Waiting to run
- Create guarded schema and links for governance gates and concept maps - Prove clone apply and rollback while production schema stays unchanged - Retain packet docs, state image, and focused tests for apply review `docs/reports/leo-working-state-20260709/current-truth-index.md` `docs/reports/leo-working-state-20260709/governance-concept-apply-authorized-commit.sql` `docs/reports/leo-working-state-20260709/governance-concept-apply-rollback-rehearsal.sql` `docs/reports/leo-working-state-20260709/governance-concept-clone-rehearsal-current.log` `docs/reports/leo-working-state-20260709/governance-concept-current.md` `docs/reports/leo-working-state-20260709/governance-concept-delete-rollback.sql` `docs/reports/leo-working-state-20260709/governance-concept-packet.json` `docs/reports/leo-working-state-20260709/governance-concept-postflight.sql` `docs/reports/leo-working-state-20260709/governance-concept-preflight.sql` `docs/reports/leo-working-state-20260709/leo-db-state-24-governance-concept-schema.svg` `docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md` `docs/reports/leo-working-state-20260709/working-leo-execution-plan-current.md` `scripts/kb_governance_concept_packet.py` `tests/test_kb_governance_concept_packet.py`
499 lines
18 KiB
Python
499 lines
18 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate a governance/concept-map companion packet for mapped KB proposals.
|
|
|
|
The current live schema has governance gate rows but no canonical table linking
|
|
claims to those gates, and it has no first-class concept-map table. This packet
|
|
creates the minimal schema needed for the remaining mapped proposal fragments,
|
|
then inserts exact row-level links after the mapped base packet has created the
|
|
required claim rows.
|
|
|
|
The packet builder is not an executor. Production apply remains a separate
|
|
authorization boundary.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import uuid
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
sys.path.insert(0, str(HERE))
|
|
|
|
from kb_rich_proposal_creation_plan import _sql_literal # noqa: E402
|
|
|
|
BASE_PACKET_REQUIRED_FIRST = "production-apply-packet-mapped-20260709"
|
|
|
|
PROPOSAL_CONCEPT_ID = "14fa5ecc-ac7a-41c1-807d-a2e85b936617"
|
|
PROPOSAL_GOVERNANCE_ID = "ac036c9d-20a0-4ffe-881f-57d6b7bacf22"
|
|
|
|
CLAIM_DISTRIBUTED_MARKET_INTELLIGENCE_ID = "d009dfc4-9755-58a7-affb-80e3e842a775"
|
|
CLAIM_NODES_NEED_BODIES_ID = "9bcf7e6b-4e98-52b1-91ef-96cfc15e3df0"
|
|
|
|
QUALITY_GATE_ID = "fa88e31b-6fca-4801-bf72-f5db81950a11"
|
|
EVIDENCE_BAR_ID = "45695897-2a9c-4279-ac25-e59f166dec6a"
|
|
|
|
CONCEPT_MAP_KEY = "distributed_market_intelligence"
|
|
ID_NAMESPACE = uuid.uuid5(uuid.NAMESPACE_URL, "teleo:working-leo:governance-concept-packet")
|
|
|
|
|
|
def stable_id(key: str) -> str:
|
|
return str(uuid.uuid5(ID_NAMESPACE, key))
|
|
|
|
|
|
CONCEPT_MAP_ID = stable_id("concept-map:distributed-market-intelligence")
|
|
CONCEPT_LINK_ID = stable_id("claim-concept-map-link:capital-allocation-distributed-knowledge")
|
|
QUALITY_GATE_LINK_ID = stable_id("claim-governance-link:claim-bodies:quality-gate")
|
|
EVIDENCE_BAR_LINK_ID = stable_id("claim-governance-link:claim-bodies:evidence-bar")
|
|
|
|
|
|
def _uuid_values(values: list[str], *, column_name: str = "id") -> str:
|
|
rows = ",\n ".join(f"('{value}'::uuid)" for value in values)
|
|
return f"(values\n {rows}\n ) as v({column_name})"
|
|
|
|
|
|
def _jsonb(value: Any) -> str:
|
|
return _sql_literal(json.dumps(value, sort_keys=True)) + "::jsonb"
|
|
|
|
|
|
def concept_map_row() -> dict[str, Any]:
|
|
return {
|
|
"id": CONCEPT_MAP_ID,
|
|
"key": CONCEPT_MAP_KEY,
|
|
"title": "Distributed market intelligence",
|
|
"body": (
|
|
"A concept map for how capital allocation depends on distributed knowledge, incentives, "
|
|
"liquidity, feedback loops, and market signals rather than a single central planner."
|
|
),
|
|
"status": "active",
|
|
"source_ref": "mapped-rich-proposal-14fa5ecc:concept_map:distributed_market_intelligence",
|
|
"metadata": {
|
|
"base_packet_required_first": BASE_PACKET_REQUIRED_FIRST,
|
|
"proposal_id": PROPOSAL_CONCEPT_ID,
|
|
"source_fragment": (
|
|
"capital_allocation_depends_on_distributed_market_intelligence draws_from "
|
|
"concept_map:distributed_market_intelligence"
|
|
),
|
|
},
|
|
}
|
|
|
|
|
|
def concept_links() -> list[dict[str, Any]]:
|
|
return [
|
|
{
|
|
"id": CONCEPT_LINK_ID,
|
|
"claim_id": CLAIM_DISTRIBUTED_MARKET_INTELLIGENCE_ID,
|
|
"concept_map_id": CONCEPT_MAP_ID,
|
|
"relation": "derives_from",
|
|
"weight": 0.75,
|
|
"rationale": (
|
|
"Mapped proposal 14fa5ecc: the capital-allocation distributed-knowledge claim draws "
|
|
"from the distributed market intelligence concept map."
|
|
),
|
|
"source_ref": "mapped-rich-proposal-14fa5ecc:concept_map:distributed_market_intelligence",
|
|
"metadata": {"proposal_id": PROPOSAL_CONCEPT_ID},
|
|
}
|
|
]
|
|
|
|
|
|
def governance_links() -> list[dict[str, Any]]:
|
|
return [
|
|
{
|
|
"id": QUALITY_GATE_LINK_ID,
|
|
"claim_id": CLAIM_NODES_NEED_BODIES_ID,
|
|
"governance_gate_id": QUALITY_GATE_ID,
|
|
"relation": "supports",
|
|
"weight": 0.85,
|
|
"rationale": (
|
|
"Specific enough to disagree with requires more than a compressed headline for ambiguous claims."
|
|
),
|
|
"source_ref": "mapped-rich-proposal-ac036c9d:governance_gate:quality-gate",
|
|
"metadata": {"proposal_id": PROPOSAL_GOVERNANCE_ID},
|
|
},
|
|
{
|
|
"id": EVIDENCE_BAR_LINK_ID,
|
|
"claim_id": CLAIM_NODES_NEED_BODIES_ID,
|
|
"governance_gate_id": EVIDENCE_BAR_ID,
|
|
"relation": "supports",
|
|
"weight": 0.85,
|
|
"rationale": "Bodies can state the true evidence tier and scope limits.",
|
|
"source_ref": "mapped-rich-proposal-ac036c9d:governance_gate:evidence-bar",
|
|
"metadata": {"proposal_id": PROPOSAL_GOVERNANCE_ID},
|
|
},
|
|
]
|
|
|
|
|
|
def build_schema_sql() -> str:
|
|
return """create table if not exists public.concept_maps (
|
|
id uuid primary key default gen_random_uuid(),
|
|
key text not null unique,
|
|
title text not null,
|
|
body text not null,
|
|
status text not null default 'active' check (status = any (array['draft'::text, 'active'::text, 'retired'::text])),
|
|
source_ref text,
|
|
metadata jsonb not null default '{}'::jsonb,
|
|
created_at timestamptz not null default now(),
|
|
updated_at timestamptz not null default now()
|
|
);
|
|
|
|
create table if not exists public.claim_concept_map_links (
|
|
id uuid primary key default gen_random_uuid(),
|
|
claim_id uuid not null references public.claims(id) on delete cascade,
|
|
concept_map_id uuid not null references public.concept_maps(id) on delete cascade,
|
|
relation text not null check (relation = any (array['derives_from'::text, 'supports'::text, 'contextualizes'::text, 'contains'::text, 'requires'::text, 'relates'::text])),
|
|
weight numeric check (weight >= 0 and weight <= 1),
|
|
rationale text not null,
|
|
source_ref text,
|
|
metadata jsonb not null default '{}'::jsonb,
|
|
created_at timestamptz not null default now(),
|
|
unique (claim_id, concept_map_id, relation)
|
|
);
|
|
|
|
create table if not exists public.claim_governance_gate_links (
|
|
id uuid primary key default gen_random_uuid(),
|
|
claim_id uuid not null references public.claims(id) on delete cascade,
|
|
governance_gate_id uuid not null references public.governance_gates(id) on delete cascade,
|
|
relation text not null check (relation = any (array['supports'::text, 'requires'::text, 'constrains'::text, 'documents'::text])),
|
|
weight numeric check (weight >= 0 and weight <= 1),
|
|
rationale text not null,
|
|
source_ref text,
|
|
metadata jsonb not null default '{}'::jsonb,
|
|
created_at timestamptz not null default now(),
|
|
unique (claim_id, governance_gate_id, relation)
|
|
);
|
|
|
|
create index if not exists claim_concept_map_links_claim
|
|
on public.claim_concept_map_links (claim_id, relation);
|
|
create index if not exists claim_concept_map_links_map
|
|
on public.claim_concept_map_links (concept_map_id, relation);
|
|
create index if not exists claim_governance_gate_links_claim
|
|
on public.claim_governance_gate_links (claim_id, relation);
|
|
create index if not exists claim_governance_gate_links_gate
|
|
on public.claim_governance_gate_links (governance_gate_id, relation);"""
|
|
|
|
|
|
def build_generated_counts_sql() -> str:
|
|
return f"""select
|
|
(select count(*) from public.concept_maps where id = {_sql_literal(CONCEPT_MAP_ID)}::uuid) as generated_concept_map_rows,
|
|
(select count(*) from public.claim_concept_map_links where id = {_sql_literal(CONCEPT_LINK_ID)}::uuid) as generated_concept_link_rows,
|
|
(select count(*) from public.claim_governance_gate_links where id in (select id from {_uuid_values([QUALITY_GATE_LINK_ID, EVIDENCE_BAR_LINK_ID])})) as generated_governance_link_rows;
|
|
"""
|
|
|
|
|
|
def _concept_map_insert_sql() -> str:
|
|
row = concept_map_row()
|
|
return f"""insert into public.concept_maps (id, key, title, body, status, source_ref, metadata)
|
|
values (
|
|
{_sql_literal(row['id'])}::uuid,
|
|
{_sql_literal(row['key'])},
|
|
{_sql_literal(row['title'])},
|
|
{_sql_literal(row['body'])},
|
|
{_sql_literal(row['status'])},
|
|
{_sql_literal(row['source_ref'])},
|
|
{_jsonb(row['metadata'])}
|
|
);"""
|
|
|
|
|
|
def _concept_link_insert_values() -> str:
|
|
rows = []
|
|
for row in concept_links():
|
|
rows.append(
|
|
"("
|
|
f"{_sql_literal(row['id'])}::uuid, "
|
|
f"{_sql_literal(row['claim_id'])}::uuid, "
|
|
f"{_sql_literal(row['concept_map_id'])}::uuid, "
|
|
f"{_sql_literal(row['relation'])}, "
|
|
f"{row['weight']}, "
|
|
f"{_sql_literal(row['rationale'])}, "
|
|
f"{_sql_literal(row['source_ref'])}, "
|
|
f"{_jsonb(row['metadata'])}"
|
|
")"
|
|
)
|
|
return ",\n ".join(rows)
|
|
|
|
|
|
def _governance_link_insert_values() -> str:
|
|
rows = []
|
|
for row in governance_links():
|
|
rows.append(
|
|
"("
|
|
f"{_sql_literal(row['id'])}::uuid, "
|
|
f"{_sql_literal(row['claim_id'])}::uuid, "
|
|
f"{_sql_literal(row['governance_gate_id'])}::uuid, "
|
|
f"{_sql_literal(row['relation'])}, "
|
|
f"{row['weight']}, "
|
|
f"{_sql_literal(row['rationale'])}, "
|
|
f"{_sql_literal(row['source_ref'])}, "
|
|
f"{_jsonb(row['metadata'])}"
|
|
")"
|
|
)
|
|
return ",\n ".join(rows)
|
|
|
|
|
|
def build_preflight_sql() -> str:
|
|
required_claim_ids = [CLAIM_DISTRIBUTED_MARKET_INTELLIGENCE_ID, CLAIM_NODES_NEED_BODIES_ID]
|
|
required_gate_ids = [QUALITY_GATE_ID, EVIDENCE_BAR_ID]
|
|
return f"""\\set ON_ERROR_STOP on
|
|
-- Governance/concept companion preflight. Read-only.
|
|
-- Run after the mapped rich proposal packet has been applied.
|
|
|
|
select 'schema_table' as check_name, name, to_regclass(name) as regclass
|
|
from (values
|
|
('public.concept_maps'),
|
|
('public.claim_concept_map_links'),
|
|
('public.claim_governance_gate_links')
|
|
) as v(name);
|
|
|
|
select 'required_base_claim' as check_name,
|
|
c.id::text,
|
|
c.status,
|
|
left(c.text, 220) as text
|
|
from public.claims c
|
|
where c.id in (select id from {_uuid_values(required_claim_ids)})
|
|
order by c.id;
|
|
|
|
select 'required_governance_gate' as check_name,
|
|
id::text,
|
|
name,
|
|
left(criteria, 180) as criteria,
|
|
left(evidence_bar, 180) as evidence_bar
|
|
from public.governance_gates
|
|
where id in (select id from {_uuid_values(required_gate_ids)})
|
|
order by name;
|
|
"""
|
|
|
|
|
|
def build_apply_sql(*, commit: bool) -> str:
|
|
terminator = "commit;" if commit else "rollback;"
|
|
required_claim_ids = [CLAIM_DISTRIBUTED_MARKET_INTELLIGENCE_ID, CLAIM_NODES_NEED_BODIES_ID]
|
|
required_gate_ids = [QUALITY_GATE_ID, EVIDENCE_BAR_ID]
|
|
return f"""\\set ON_ERROR_STOP on
|
|
begin;
|
|
|
|
{build_schema_sql()}
|
|
|
|
do $$
|
|
declare
|
|
inserted_concept_maps int;
|
|
inserted_concept_links int;
|
|
inserted_governance_links int;
|
|
begin
|
|
if (
|
|
select count(*) from public.claims where id in (select id from {_uuid_values(required_claim_ids)})
|
|
) <> {len(required_claim_ids)} then
|
|
raise exception 'governance/concept packet requires mapped base claims to exist before inserts';
|
|
end if;
|
|
|
|
if (
|
|
select count(*) from public.governance_gates where id in (select id from {_uuid_values(required_gate_ids)})
|
|
) <> {len(required_gate_ids)} then
|
|
raise exception 'governance/concept packet requires quality/evidence governance gates to exist';
|
|
end if;
|
|
|
|
if exists (select 1 from public.concept_maps where id = {_sql_literal(CONCEPT_MAP_ID)}::uuid or key = {_sql_literal(CONCEPT_MAP_KEY)}) then
|
|
raise exception 'governance/concept packet generated concept map already exists';
|
|
end if;
|
|
|
|
if exists (select 1 from public.claim_concept_map_links where id = {_sql_literal(CONCEPT_LINK_ID)}::uuid) then
|
|
raise exception 'governance/concept packet generated concept link already exists';
|
|
end if;
|
|
|
|
if exists (
|
|
select 1 from public.claim_governance_gate_links
|
|
where id in (select id from {_uuid_values([QUALITY_GATE_LINK_ID, EVIDENCE_BAR_LINK_ID])})
|
|
) then
|
|
raise exception 'governance/concept packet generated governance link already exists';
|
|
end if;
|
|
|
|
{_concept_map_insert_sql()}
|
|
get diagnostics inserted_concept_maps = row_count;
|
|
if inserted_concept_maps <> 1 then
|
|
raise exception 'governance/concept packet inserted % concept map row(s), expected 1', inserted_concept_maps;
|
|
end if;
|
|
|
|
insert into public.claim_concept_map_links
|
|
(id, claim_id, concept_map_id, relation, weight, rationale, source_ref, metadata)
|
|
values
|
|
{_concept_link_insert_values()};
|
|
get diagnostics inserted_concept_links = row_count;
|
|
if inserted_concept_links <> {len(concept_links())} then
|
|
raise exception 'governance/concept packet inserted % concept link row(s), expected {len(concept_links())}', inserted_concept_links;
|
|
end if;
|
|
|
|
insert into public.claim_governance_gate_links
|
|
(id, claim_id, governance_gate_id, relation, weight, rationale, source_ref, metadata)
|
|
values
|
|
{_governance_link_insert_values()};
|
|
get diagnostics inserted_governance_links = row_count;
|
|
if inserted_governance_links <> {len(governance_links())} then
|
|
raise exception 'governance/concept packet inserted % governance link row(s), expected {len(governance_links())}', inserted_governance_links;
|
|
end if;
|
|
end $$;
|
|
|
|
{terminator}
|
|
"""
|
|
|
|
|
|
def build_postflight_sql() -> str:
|
|
return f"""\\set ON_ERROR_STOP on
|
|
-- Governance/concept companion postflight row-level readback.
|
|
|
|
{build_generated_counts_sql()}
|
|
|
|
select id::text, key, title, status, source_ref, metadata::text
|
|
from public.concept_maps
|
|
where id = {_sql_literal(CONCEPT_MAP_ID)}::uuid;
|
|
|
|
select id::text,
|
|
claim_id::text,
|
|
concept_map_id::text,
|
|
relation,
|
|
weight,
|
|
left(rationale, 220) as rationale,
|
|
source_ref
|
|
from public.claim_concept_map_links
|
|
where id = {_sql_literal(CONCEPT_LINK_ID)}::uuid;
|
|
|
|
select id::text,
|
|
claim_id::text,
|
|
governance_gate_id::text,
|
|
relation,
|
|
weight,
|
|
left(rationale, 220) as rationale,
|
|
source_ref
|
|
from public.claim_governance_gate_links
|
|
where id in (select id from {_uuid_values([QUALITY_GATE_LINK_ID, EVIDENCE_BAR_LINK_ID])})
|
|
order by governance_gate_id;
|
|
"""
|
|
|
|
|
|
def build_delete_rollback_sql() -> str:
|
|
return f"""\\set ON_ERROR_STOP on
|
|
-- Emergency rollback for governance/concept generated rows only.
|
|
-- Drops generated schema only when the generated tables are empty after row delete.
|
|
begin;
|
|
|
|
delete from public.claim_governance_gate_links
|
|
where id in (select id from {_uuid_values([QUALITY_GATE_LINK_ID, EVIDENCE_BAR_LINK_ID])});
|
|
|
|
delete from public.claim_concept_map_links
|
|
where id = {_sql_literal(CONCEPT_LINK_ID)}::uuid;
|
|
|
|
delete from public.concept_maps
|
|
where id = {_sql_literal(CONCEPT_MAP_ID)}::uuid;
|
|
|
|
do $$
|
|
begin
|
|
if to_regclass('public.claim_governance_gate_links') is not null
|
|
and not exists (select 1 from public.claim_governance_gate_links) then
|
|
drop table public.claim_governance_gate_links;
|
|
end if;
|
|
|
|
if to_regclass('public.claim_concept_map_links') is not null
|
|
and not exists (select 1 from public.claim_concept_map_links) then
|
|
drop table public.claim_concept_map_links;
|
|
end if;
|
|
|
|
if to_regclass('public.concept_maps') is not null
|
|
and not exists (select 1 from public.concept_maps) then
|
|
drop table public.concept_maps;
|
|
end if;
|
|
end $$;
|
|
|
|
commit;
|
|
"""
|
|
|
|
|
|
def build_packet() -> dict[str, Any]:
|
|
return {
|
|
"packet_version": 1,
|
|
"purpose": "Companion packet for mapped rich proposal governance-gate and concept-map targets.",
|
|
"production_apply_status": "not_executed",
|
|
"base_packet_required_first": BASE_PACKET_REQUIRED_FIRST,
|
|
"schema_writes": [
|
|
"public.concept_maps",
|
|
"public.claim_concept_map_links",
|
|
"public.claim_governance_gate_links",
|
|
],
|
|
"generated_counts": {
|
|
"concept_maps": 1,
|
|
"claim_concept_map_links": len(concept_links()),
|
|
"claim_governance_gate_links": len(governance_links()),
|
|
},
|
|
"required_existing_rows": {
|
|
"public.claims": [
|
|
CLAIM_DISTRIBUTED_MARKET_INTELLIGENCE_ID,
|
|
CLAIM_NODES_NEED_BODIES_ID,
|
|
],
|
|
"public.governance_gates": [QUALITY_GATE_ID, EVIDENCE_BAR_ID],
|
|
},
|
|
"safe_writes": [
|
|
{
|
|
"table": "public.concept_maps",
|
|
"operation": "insert",
|
|
"rows": [concept_map_row()],
|
|
},
|
|
{
|
|
"table": "public.claim_concept_map_links",
|
|
"operation": "insert",
|
|
"rows": concept_links(),
|
|
},
|
|
{
|
|
"table": "public.claim_governance_gate_links",
|
|
"operation": "insert",
|
|
"rows": governance_links(),
|
|
},
|
|
],
|
|
"represented_fragments": [
|
|
"capital_allocation_depends_on_distributed_market_intelligence draws_from concept_map:distributed_market_intelligence",
|
|
"claim_nodes_need_bodies supports governance_gate:quality-gate",
|
|
"claim_nodes_need_bodies supports governance_gate:evidence-bar",
|
|
],
|
|
"sql": {
|
|
"preflight": build_preflight_sql(),
|
|
"apply_rollback_rehearsal": build_apply_sql(commit=False),
|
|
"apply_commit": build_apply_sql(commit=True),
|
|
"postflight": build_postflight_sql(),
|
|
"delete_rollback": build_delete_rollback_sql(),
|
|
},
|
|
}
|
|
|
|
|
|
def write_packet_files(packet: dict[str, Any], output_dir: Path) -> None:
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
sql = packet["sql"]
|
|
(output_dir / "governance-concept-preflight.sql").write_text(sql["preflight"], encoding="utf-8")
|
|
(output_dir / "governance-concept-apply-rollback-rehearsal.sql").write_text(
|
|
sql["apply_rollback_rehearsal"], encoding="utf-8"
|
|
)
|
|
(output_dir / "governance-concept-apply-authorized-commit.sql").write_text(
|
|
sql["apply_commit"], encoding="utf-8"
|
|
)
|
|
(output_dir / "governance-concept-postflight.sql").write_text(sql["postflight"], encoding="utf-8")
|
|
(output_dir / "governance-concept-delete-rollback.sql").write_text(sql["delete_rollback"], encoding="utf-8")
|
|
summary = {key: value for key, value in packet.items() if key != "sql"}
|
|
(output_dir / "governance-concept-packet.json").write_text(
|
|
json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
|
)
|
|
|
|
|
|
def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--output-dir", type=Path, help="directory to write packet files")
|
|
return parser.parse_args(argv)
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
args = parse_args(sys.argv[1:] if argv is None else argv)
|
|
packet = build_packet()
|
|
if args.output_dir:
|
|
write_packet_files(packet, args.output_dir)
|
|
print(json.dumps({key: value for key, value in packet.items() if key != "sql"}, indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|