Add Leo production apply authorization packet
Some checks are pending
CI / lint-and-test (push) Waiting to run
Some checks are pending
CI / lint-and-test (push) Waiting to run
This commit is contained in:
parent
45bec0ed84
commit
427a9f1a1e
7 changed files with 529 additions and 3 deletions
|
|
@ -78,6 +78,8 @@ Use this file before making status claims. Prefer fresh VPS/GCP readbacks when c
|
|||
- Working Leo authorized apply operator runbook JSON: `docs/reports/leo-working-state-20260709/working-leo-authorized-apply-runbook-current.json`
|
||||
- Working Leo authorized apply session plan, not executed: `docs/reports/leo-working-state-20260709/working-leo-authorized-apply-session-plan-current.md`
|
||||
- Working Leo authorized apply session plan JSON: `docs/reports/leo-working-state-20260709/working-leo-authorized-apply-session-plan-current.json`
|
||||
- Working Leo production apply authorization packet, not executed: `docs/reports/leo-working-state-20260709/working-leo-production-apply-authorization-packet-current.md`
|
||||
- Working Leo production apply authorization packet JSON: `docs/reports/leo-working-state-20260709/working-leo-production-apply-authorization-packet-current.json`
|
||||
- Working Leo live production preflight baseline, read-only: `docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md`
|
||||
- Working Leo live production preflight baseline JSON: `docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.json`
|
||||
- Working Leo production apply receipt template, not executed: `docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.md`
|
||||
|
|
@ -131,6 +133,7 @@ Use this file before making status claims. Prefer fresh VPS/GCP readbacks when c
|
|||
- The authorized-apply readiness verifier now passes: packet files exist and hash, apply/rollback order matches the manifest, expected counts match, clone apply/rollback markers are ordered, clone cleanup is proven, service stayed stable, and `production_apply_executed=false`.
|
||||
- The authorized apply operator runbook is generated and ready-not-executed: it gives preflight/apply/postflight/rollback command templates in manifest order, requires `TELEO_DATABASE_URL`, and now also includes a post-apply regression command bundle plus required production-apply receipt fields and an offline receipt validator. It still does not authorize or execute production SQL.
|
||||
- The authorized apply session plan is generated and ready-not-executed: it maps concrete output log paths for pre-apply validation, preflight, apply, postflight, post-apply regression, service readback, cleanup readback, receipt validation, and rollback. Apply and rollback steps require explicit authorization; non-apply steps are marked non-mutating.
|
||||
- The production apply authorization packet is generated and ready-to-request, not authorized/executed: all evidence gates pass, it names the exact integrated packet order and the operator authorization template, requires a fresh deployed-SHA readback at apply time, and keeps `production_apply_executed=false` plus `production_apply_authorization_present=false`.
|
||||
- The live production preflight baseline now passes through the read-only collector: `5/5` preflight files executed on the VPS with `begin transaction read only`, `mutates_production_db=false`, `applies_production_packet=false`, and `production_apply_executed=false`. Current production still has generated base rows `0/0/0/0`, Helmer rows `0/0/0/0/0`, no generated governance/concept tables, and dependent Rio/cross-surface/governance base rows absent before any apply, as expected.
|
||||
- The production apply receipt template is generated but intentionally invalid as a final receipt: `production_apply_executed=false`, `valid_production_receipt=false`, and it names the fields that must only be filled after authorized apply execution (`explicit_authorization_record`, `operator_identity`, `apply_output_paths`, `postflight_output_paths`, `actual_after_apply_counts`, `telegram_or_handler_regression_paths`, `service_readback`, `cleanup_readback`).
|
||||
- The production-apply receipt validator currently reports `missing_receipt`, which is correct because no production apply has been authorized or executed.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Working Leo Current State - 2026-07-09
|
||||
|
||||
Generated UTC: `2026-07-10T01:57:56Z`
|
||||
Generated UTC: `2026-07-10T02:02:21Z`
|
||||
|
||||
## Current Working Definition
|
||||
|
||||
|
|
@ -148,6 +148,13 @@ A working Leo, for Cory/m3taversal's current expectation, is a Telegram-facing a
|
|||
- planned output paths exist for pre-apply validation, preflight, apply, postflight, post-apply regression, service readback, cleanup readback, receipt validation, and rollback logs
|
||||
- all apply steps and all rollback steps require explicit authorization
|
||||
- non-apply steps are marked non-mutating, so the plan can be used to audit an apply window without itself changing production
|
||||
- Production apply authorization packet is now retained:
|
||||
- `mode=production_apply_authorization_packet_not_executed`
|
||||
- `ready_to_request_authorization=true`
|
||||
- `production_apply_executed=false`
|
||||
- `production_apply_authorization_present=false`
|
||||
- evidence gates pass for runbook readiness, gated session plan, read-only production preflight, direct-claim score, receipt template, and missing-receipt validator status
|
||||
- the operator authorization template is retained, but it must use a fresh deployed-SHA readback at apply time, and the packet itself does not authorize or execute SQL
|
||||
- Live production preflight baseline is now retained:
|
||||
- the collector ran on the VPS with `--transport local-docker`, `execute_requested=true`, `mutates_production_db=false`, `applies_production_packet=false`, `production_apply_executed=false`, and `readonly_transaction_wrapper=true`
|
||||
- `5/5` preflight SQL files returned `ok=True`
|
||||
|
|
@ -207,6 +214,7 @@ A working Leo, for Cory/m3taversal's current expectation, is a Telegram-facing a
|
|||
- Authorized-apply readiness verifier: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-apply-readiness-current.md`
|
||||
- Authorized apply operator runbook: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-authorized-apply-runbook-current.md`
|
||||
- Authorized apply session plan: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-authorized-apply-session-plan-current.md`
|
||||
- Production apply authorization packet: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-apply-authorization-packet-current.md`
|
||||
- Live production preflight baseline: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md`
|
||||
- Production apply receipt template: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.md`
|
||||
- Production apply receipt validation: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-validation-current.md`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Working Leo Execution Plan - 2026-07-09
|
||||
|
||||
Claim ceiling: VPS Telegram memory/KB audit, full live-safe open-ended Telegram suite, full mixed-evidence Cory-style outcome/direct-claim sandbox benchmark, live VPS GatewayRunner no-context direct-claim suite, Telegram-to-`kb_stage` proposal staging, and strict existing-ID apply are working. The live VPS handler suite for exact `DC-01` through `DC-06` prompts strict-scores `6/6` after the authorized-session-plan deploy and scorer refresh, with no Telegram post, no live profile write, no production DB apply, unchanged DB counts, temp profile cleanup, and unchanged gateway service state during the harness. The full prepared DB packet set is integrated-clone-proven in dependency order: mapped rich base, cross-surface anchor, Rio strategy context, governance/concept schema, and Helmer 7 Powers. A read-only live production preflight baseline now passes `5/5`, an authorized apply operator runbook is generated, and an authorized apply session plan now maps every apply-window output path with authorization gates, but none of those packets are production-applied. GCP parity remains pending.
|
||||
Claim ceiling: VPS Telegram memory/KB audit, full live-safe open-ended Telegram suite, full mixed-evidence Cory-style outcome/direct-claim sandbox benchmark, live VPS GatewayRunner no-context direct-claim suite, Telegram-to-`kb_stage` proposal staging, and strict existing-ID apply are working. The live VPS handler suite for exact `DC-01` through `DC-06` prompts strict-scores `6/6` after the authorized-session-plan deploy and scorer refresh, with no Telegram post, no live profile write, no production DB apply, unchanged DB counts, temp profile cleanup, and unchanged gateway service state during the harness. The full prepared DB packet set is integrated-clone-proven in dependency order: mapped rich base, cross-surface anchor, Rio strategy context, governance/concept schema, and Helmer 7 Powers. A read-only live production preflight baseline now passes `5/5`, an authorized apply operator runbook is generated, an authorized apply session plan maps every apply-window output path with authorization gates, and a production apply authorization packet is ready-to-request, but none of those packets are production-applied or authorized. GCP parity remains pending.
|
||||
|
||||
## WL-EXEC-01 - VPS Telegram-visible memory + KB audit
|
||||
- Status: `done`
|
||||
|
|
@ -96,7 +96,7 @@ Claim ceiling: VPS Telegram memory/KB audit, full live-safe open-ended Telegram
|
|||
|
||||
## WL-EXEC-06B - Integrated production-order packet rehearsal
|
||||
- Status: `done_integrated_clone_ready_not_executed`
|
||||
- Result: Applied the full prepared packet set in one disposable clone in dependency order: mapped base, cross-surface anchor, Rio strategy context, governance/concept schema, and Helmer 7 Powers. Expected integrated footprint was `12` claims, `28` sources, `18` claim edges, `34` claim evidence rows, `1` reasoning tool, `2` Rio strategy nodes, `5` Rio strategy anchors, `1` concept map, `1` concept link, `2` governance links, one Helmer ledger row marked applied, and one cross-surface anchor update. Reverse rollback restored all generated rows/schema to zero/absent, restored the cross-surface anchor to the old claim, restored the Helmer ledger to `approved`, dropped the disposable DB, removed temp files, and left production unchanged. The apply-readiness verifier now passes over the retained manifest/files/logs with `ready_for_authorized_production_apply_packet=true`, `production_apply_executed=false`, and `production_apply_authorization_present=false`. The authorized apply runbook now emits preflight/apply/postflight/rollback command templates in manifest order, a read-only pre-apply production baseline collector, a post-apply regression command bundle, a required production-apply receipt schema, and an offline receipt validator with `status=ready_not_executed`. The authorized apply session plan maps concrete output paths for pre-apply validation, preflight, apply, postflight, post-apply regression, service readback, cleanup readback, receipt validation, and rollback; apply and rollback steps require explicit authorization, non-apply steps are non-mutating, and `production_apply_executed=false`. The live production preflight baseline ran through `begin transaction read only` and passed `5/5` with no production apply executed.
|
||||
- Result: Applied the full prepared packet set in one disposable clone in dependency order: mapped base, cross-surface anchor, Rio strategy context, governance/concept schema, and Helmer 7 Powers. Expected integrated footprint was `12` claims, `28` sources, `18` claim edges, `34` claim evidence rows, `1` reasoning tool, `2` Rio strategy nodes, `5` Rio strategy anchors, `1` concept map, `1` concept link, `2` governance links, one Helmer ledger row marked applied, and one cross-surface anchor update. Reverse rollback restored all generated rows/schema to zero/absent, restored the cross-surface anchor to the old claim, restored the Helmer ledger to `approved`, dropped the disposable DB, removed temp files, and left production unchanged. The apply-readiness verifier now passes over the retained manifest/files/logs with `ready_for_authorized_production_apply_packet=true`, `production_apply_executed=false`, and `production_apply_authorization_present=false`. The authorized apply runbook now emits preflight/apply/postflight/rollback command templates in manifest order, a read-only pre-apply production baseline collector, a post-apply regression command bundle, a required production-apply receipt schema, and an offline receipt validator with `status=ready_not_executed`. The authorized apply session plan maps concrete output paths for pre-apply validation, preflight, apply, postflight, post-apply regression, service readback, cleanup readback, receipt validation, and rollback; apply and rollback steps require explicit authorization, non-apply steps are non-mutating, and `production_apply_executed=false`. The production apply authorization packet now passes all evidence gates and retains the operator authorization template plus fresh deployed-SHA requirement while keeping `production_apply_executed=false` and `production_apply_authorization_present=false`. The live production preflight baseline ran through `begin transaction read only` and passed `5/5` with no production apply executed.
|
||||
- Next action: If production apply is explicitly authorized, use the generated runbook order, run every postflight SQL file, run the post-apply regression bundle, retain the production receipt, and then rerun any user-visible Telegram canary needed for the demo/meeting tier.
|
||||
- Not done condition: Production canonical rows/schema remain unapplied until explicit production apply authorization.
|
||||
- Evidence:
|
||||
|
|
@ -105,6 +105,7 @@ Claim ceiling: VPS Telegram memory/KB audit, full live-safe open-ended Telegram
|
|||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-apply-readiness-current.md`
|
||||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-authorized-apply-runbook-current.md`
|
||||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-authorized-apply-session-plan-current.md`
|
||||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-apply-authorization-packet-current.md`
|
||||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md`
|
||||
- `/Users/user/Documents/Codex/2026-07-09/019f34eb-d297-72d0-b7e2-b222d5515ab9-load/work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-validation-current.md`
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"authorization_commit_sha_rule": "Use the fresh deployed SHA read back immediately before apply.",
|
||||
"authorization_gate_status": "ready_to_request_explicit_authorization",
|
||||
"authorization_scope": {
|
||||
"apply_order": [
|
||||
"mapped-rich-base",
|
||||
"cross-surface-anchor",
|
||||
"rio-strategy-context",
|
||||
"governance-concept-schema",
|
||||
"helmer-7powers"
|
||||
],
|
||||
"expected_after_apply_counts": {
|
||||
"claim_concept_map_links": 1,
|
||||
"claim_edges": 18,
|
||||
"claim_evidence": 34,
|
||||
"claim_governance_gate_links": 2,
|
||||
"claims": 12,
|
||||
"concept_maps": 1,
|
||||
"cross_surface_anchor_updates": 1,
|
||||
"helmer_ledger_rows_marked_applied": 1,
|
||||
"reasoning_tools": 1,
|
||||
"rio_strategy_anchors": 5,
|
||||
"rio_strategy_nodes": 2,
|
||||
"sources": 28
|
||||
},
|
||||
"gcp_parity_in_scope": false,
|
||||
"packet_set": "integrated Working Leo packet set",
|
||||
"target": "VPS production Postgres canonical Working Leo packet apply",
|
||||
"telegram_visible_post_authorized": false
|
||||
},
|
||||
"checks": {
|
||||
"all_evidence_paths_exist": true,
|
||||
"direct_claim_score_passed": true,
|
||||
"read_only_preflight_passed": true,
|
||||
"receipt_template_not_final_receipt": true,
|
||||
"receipt_validator_still_missing_receipt": true,
|
||||
"runbook_ready_not_executed": true,
|
||||
"session_plan_not_executed_and_gated": true
|
||||
},
|
||||
"claim_ceiling": "This packet requests explicit authorization and proves the request is bounded by retained evidence. It does not authorize production apply, does not run SQL, does not mutate production, and does not prove canonical rows were changed.",
|
||||
"clear_CTA": "If you want this production DB apply to run, first let Codex re-read the deployed SHA, then reply with the authorization sentence in `explicit_operator_authorization_text_template` after replacing `<DEPLOYED_SHA_READBACK>` with that SHA, plus the operator identity to record in the receipt.",
|
||||
"do_not_run_without": [
|
||||
"Exact operator authorization text naming production DB apply scope.",
|
||||
"Operator identity for the production receipt.",
|
||||
"Fresh preflight immediately before apply."
|
||||
],
|
||||
"evidence_paths": {
|
||||
"direct_claim_score": {
|
||||
"bytes": 15659,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/telegram-handler-direct-claim-suite-score-current.json"
|
||||
},
|
||||
"preflight": {
|
||||
"bytes": 12496,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.json"
|
||||
},
|
||||
"receipt_template": {
|
||||
"bytes": 4889,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.json"
|
||||
},
|
||||
"receipt_validation": {
|
||||
"bytes": 986,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-validation-current.json"
|
||||
},
|
||||
"runbook": {
|
||||
"bytes": 18329,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/working-leo-authorized-apply-runbook-current.json"
|
||||
},
|
||||
"session_plan": {
|
||||
"bytes": 28799,
|
||||
"exists": true,
|
||||
"path": "docs/reports/leo-working-state-20260709/working-leo-authorized-apply-session-plan-current.json"
|
||||
}
|
||||
},
|
||||
"explicit_operator_authorization_text_template": "I authorize production DB apply for the integrated Working Leo packet set on VPS using deployed commit <DEPLOYED_SHA_READBACK> in this order: mapped-rich-base, cross-surface-anchor, rio-strategy-context, governance-concept-schema, helmer-7powers. Run preflight immediately before each phase, run the authorized apply SQL, run every postflight, run the non-posting direct-claim regression and scorer, capture service and cleanup readbacks, validate the production receipt, and do not post Telegram-visible messages unless separately authorized.",
|
||||
"generated_at_utc": "2026-07-10T02:04:20.678937+00:00",
|
||||
"mode": "production_apply_authorization_packet_not_executed",
|
||||
"next_non_user_action_after_authorization": [
|
||||
"Re-read deployed SHA, service state, and production preflight baseline.",
|
||||
"Run each packet phase in manifest order: preflight, authorized apply SQL, postflight.",
|
||||
"Run the non-posting direct-claim handler suite and strict scorer.",
|
||||
"Capture service readback, cleanup readback, and production receipt.",
|
||||
"Run the offline production receipt validator and retain the validation artifacts."
|
||||
],
|
||||
"packet_generation_git_sha": "45bec0ed84846ae92a53993e5337313014538206",
|
||||
"production_apply_authorization_present": false,
|
||||
"production_apply_executed": false,
|
||||
"ready_to_request_authorization": true
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# Working Leo Production Apply Authorization Packet
|
||||
|
||||
Generated UTC: `2026-07-10T02:04:20.678937+00:00`
|
||||
Mode: `production_apply_authorization_packet_not_executed`
|
||||
Production apply executed: `False`
|
||||
Production apply authorization present: `False`
|
||||
Ready to request authorization: `True`
|
||||
Authorization gate status: `ready_to_request_explicit_authorization`
|
||||
Packet generation git SHA: `45bec0ed84846ae92a53993e5337313014538206`
|
||||
Authorization commit SHA rule: `Use the fresh deployed SHA read back immediately before apply.`
|
||||
|
||||
## Scope
|
||||
|
||||
- Target: `VPS production Postgres canonical Working Leo packet apply`
|
||||
- Packet set: `integrated Working Leo packet set`
|
||||
- Apply order: `mapped-rich-base, cross-surface-anchor, rio-strategy-context, governance-concept-schema, helmer-7powers`
|
||||
- Telegram-visible post authorized: `False`
|
||||
- GCP parity in scope: `False`
|
||||
|
||||
## Checks
|
||||
|
||||
- `all_evidence_paths_exist`: `True`
|
||||
- `direct_claim_score_passed`: `True`
|
||||
- `read_only_preflight_passed`: `True`
|
||||
- `receipt_template_not_final_receipt`: `True`
|
||||
- `receipt_validator_still_missing_receipt`: `True`
|
||||
- `runbook_ready_not_executed`: `True`
|
||||
- `session_plan_not_executed_and_gated`: `True`
|
||||
|
||||
## Explicit Operator Authorization Text
|
||||
|
||||
I authorize production DB apply for the integrated Working Leo packet set on VPS using deployed commit <DEPLOYED_SHA_READBACK> in this order: mapped-rich-base, cross-surface-anchor, rio-strategy-context, governance-concept-schema, helmer-7powers. Run preflight immediately before each phase, run the authorized apply SQL, run every postflight, run the non-posting direct-claim regression and scorer, capture service and cleanup readbacks, validate the production receipt, and do not post Telegram-visible messages unless separately authorized.
|
||||
|
||||
## Clear CTA
|
||||
|
||||
If you want this production DB apply to run, first let Codex re-read the deployed SHA, then reply with the authorization sentence in `explicit_operator_authorization_text_template` after replacing `<DEPLOYED_SHA_READBACK>` with that SHA, plus the operator identity to record in the receipt.
|
||||
|
||||
## Next Non-User Action After Authorization
|
||||
|
||||
- Re-read deployed SHA, service state, and production preflight baseline.
|
||||
- Run each packet phase in manifest order: preflight, authorized apply SQL, postflight.
|
||||
- Run the non-posting direct-claim handler suite and strict scorer.
|
||||
- Capture service readback, cleanup readback, and production receipt.
|
||||
- Run the offline production receipt validator and retain the validation artifacts.
|
||||
|
||||
## Do Not Run Without
|
||||
|
||||
- Exact operator authorization text naming production DB apply scope.
|
||||
- Operator identity for the production receipt.
|
||||
- Fresh preflight immediately before apply.
|
||||
|
||||
## Claim Ceiling
|
||||
|
||||
This packet requests explicit authorization and proves the request is bounded by retained evidence. It does not authorize production apply, does not run SQL, does not mutate production, and does not prove canonical rows were changed.
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Build the Working Leo production-apply authorization packet.
|
||||
|
||||
This is an operator packet, not an executor. It composes the retained runbook,
|
||||
session plan, preflight baseline, direct-claim score, and receipt template into
|
||||
one auditable authorization request. It never opens a database connection,
|
||||
never runs SQL, and never authorizes production apply by itself.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
REPORT_DIR = Path("docs/reports/leo-working-state-20260709")
|
||||
DEFAULT_RUNBOOK = REPORT_DIR / "working-leo-authorized-apply-runbook-current.json"
|
||||
DEFAULT_SESSION_PLAN = REPORT_DIR / "working-leo-authorized-apply-session-plan-current.json"
|
||||
DEFAULT_PREFLIGHT = REPORT_DIR / "working-leo-production-preflight-current.json"
|
||||
DEFAULT_DIRECT_CLAIM_SCORE = REPORT_DIR / "telegram-handler-direct-claim-suite-score-current.json"
|
||||
DEFAULT_RECEIPT_TEMPLATE = REPORT_DIR / "working-leo-production-apply-receipt-template-current.json"
|
||||
DEFAULT_RECEIPT_VALIDATION = REPORT_DIR / "working-leo-production-apply-receipt-validation-current.json"
|
||||
DEFAULT_OUT = REPORT_DIR / "working-leo-production-apply-authorization-packet-current.json"
|
||||
DEFAULT_MARKDOWN_OUT = REPORT_DIR / "working-leo-production-apply-authorization-packet-current.md"
|
||||
|
||||
|
||||
def _load_json(path: Path) -> dict[str, Any]:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _path_status(path: Path) -> dict[str, Any]:
|
||||
exists = path.exists()
|
||||
return {"path": str(path), "exists": exists, "bytes": path.stat().st_size if exists else 0}
|
||||
|
||||
|
||||
def current_git_sha(repo_root: Path = Path(".")) -> str:
|
||||
proc = subprocess.run(
|
||||
["git", "rev-parse", "HEAD"],
|
||||
cwd=repo_root,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
return proc.stdout.strip() if proc.returncode == 0 else ""
|
||||
|
||||
|
||||
def _apply_order(runbook: dict[str, Any]) -> list[str]:
|
||||
return [str(item["packet_id"]) for item in runbook["phases"]["apply_order"]]
|
||||
|
||||
|
||||
def _expected_counts(runbook: dict[str, Any]) -> dict[str, Any]:
|
||||
return dict(runbook["expected_after_apply_counts"])
|
||||
|
||||
|
||||
def _score_passes(score: dict[str, Any]) -> bool:
|
||||
score_block = score.get("score", {})
|
||||
return (
|
||||
score_block.get("pass") is True
|
||||
and score_block.get("passes") == score_block.get("expected_prompt_count") == 6
|
||||
and score_block.get("failures") == []
|
||||
and score_block.get("missing_prompt_ids") == []
|
||||
and score_block.get("unexpected_prompt_ids") == []
|
||||
)
|
||||
|
||||
|
||||
def _template_has_required_after_fields(template: dict[str, Any], runbook: dict[str, Any]) -> bool:
|
||||
required = set(runbook["production_apply_receipt_required_fields"])
|
||||
receipt = template.get("receipt_template", {})
|
||||
must_fill = set(template.get("must_fill_after_authorized_apply", []))
|
||||
required_after = {
|
||||
"explicit_authorization_record",
|
||||
"operator_identity",
|
||||
"apply_output_paths",
|
||||
"postflight_output_paths",
|
||||
"actual_after_apply_counts",
|
||||
"telegram_or_handler_regression_paths",
|
||||
"service_readback",
|
||||
"cleanup_readback",
|
||||
}
|
||||
return required.issubset(receipt.keys()) and required_after.issubset(must_fill)
|
||||
|
||||
|
||||
def build_packet(
|
||||
*,
|
||||
runbook_path: Path = DEFAULT_RUNBOOK,
|
||||
session_plan_path: Path = DEFAULT_SESSION_PLAN,
|
||||
preflight_path: Path = DEFAULT_PREFLIGHT,
|
||||
direct_claim_score_path: Path = DEFAULT_DIRECT_CLAIM_SCORE,
|
||||
receipt_template_path: Path = DEFAULT_RECEIPT_TEMPLATE,
|
||||
receipt_validation_path: Path = DEFAULT_RECEIPT_VALIDATION,
|
||||
git_sha: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
runbook = _load_json(runbook_path)
|
||||
session_plan = _load_json(session_plan_path)
|
||||
preflight = _load_json(preflight_path)
|
||||
direct_claim_score = _load_json(direct_claim_score_path)
|
||||
receipt_template = _load_json(receipt_template_path)
|
||||
receipt_validation = _load_json(receipt_validation_path) if receipt_validation_path.exists() else {}
|
||||
sha = git_sha if git_sha is not None else current_git_sha()
|
||||
apply_order = _apply_order(runbook)
|
||||
|
||||
evidence_paths = {
|
||||
"runbook": _path_status(runbook_path),
|
||||
"session_plan": _path_status(session_plan_path),
|
||||
"preflight": _path_status(preflight_path),
|
||||
"direct_claim_score": _path_status(direct_claim_score_path),
|
||||
"receipt_template": _path_status(receipt_template_path),
|
||||
"receipt_validation": _path_status(receipt_validation_path),
|
||||
}
|
||||
|
||||
checks = {
|
||||
"runbook_ready_not_executed": runbook.get("ready_for_authorized_operator") is True
|
||||
and runbook.get("production_apply_executed") is False
|
||||
and runbook.get("production_apply_authorization_present") is False,
|
||||
"session_plan_not_executed_and_gated": session_plan.get("production_apply_executed") is False
|
||||
and session_plan.get("all_apply_steps_require_authorization") is True
|
||||
and session_plan.get("all_rollback_steps_require_authorization") is True
|
||||
and session_plan.get("non_apply_steps_do_not_mutate_db") is True,
|
||||
"read_only_preflight_passed": preflight.get("status") == "pass"
|
||||
and preflight.get("production_apply_executed") is False
|
||||
and preflight.get("mutates_production_db") is False
|
||||
and preflight.get("applies_production_packet") is False,
|
||||
"direct_claim_score_passed": _score_passes(direct_claim_score),
|
||||
"receipt_template_not_final_receipt": receipt_template.get("production_apply_executed") is False
|
||||
and receipt_template.get("valid_production_receipt") is False
|
||||
and _template_has_required_after_fields(receipt_template, runbook),
|
||||
"receipt_validator_still_missing_receipt": receipt_validation.get("status") == "missing_receipt"
|
||||
and receipt_validation.get("valid") is False,
|
||||
"all_evidence_paths_exist": all(item["exists"] and item["bytes"] > 0 for item in evidence_paths.values()),
|
||||
}
|
||||
ready_to_request = all(checks.values())
|
||||
|
||||
authorization_sentence_template = (
|
||||
"I authorize production DB apply for the integrated Working Leo packet set on VPS using deployed commit "
|
||||
f"<DEPLOYED_SHA_READBACK> in this order: {', '.join(apply_order)}. Run preflight immediately before each "
|
||||
"phase, run the authorized apply SQL, run every postflight, run the non-posting direct-claim regression and "
|
||||
"scorer, capture service and cleanup readbacks, validate the production receipt, and do not post "
|
||||
"Telegram-visible messages unless separately authorized."
|
||||
)
|
||||
|
||||
return {
|
||||
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
|
||||
"mode": "production_apply_authorization_packet_not_executed",
|
||||
"production_apply_executed": False,
|
||||
"production_apply_authorization_present": False,
|
||||
"ready_to_request_authorization": ready_to_request,
|
||||
"authorization_gate_status": "ready_to_request_explicit_authorization" if ready_to_request else "not_ready",
|
||||
"packet_generation_git_sha": sha,
|
||||
"authorization_commit_sha_rule": "Use the fresh deployed SHA read back immediately before apply.",
|
||||
"authorization_scope": {
|
||||
"target": "VPS production Postgres canonical Working Leo packet apply",
|
||||
"packet_set": "integrated Working Leo packet set",
|
||||
"apply_order": apply_order,
|
||||
"expected_after_apply_counts": _expected_counts(runbook),
|
||||
"telegram_visible_post_authorized": False,
|
||||
"gcp_parity_in_scope": False,
|
||||
},
|
||||
"checks": checks,
|
||||
"evidence_paths": evidence_paths,
|
||||
"explicit_operator_authorization_text_template": authorization_sentence_template,
|
||||
"clear_CTA": (
|
||||
"If you want this production DB apply to run, first let Codex re-read the deployed SHA, then reply with "
|
||||
"the authorization sentence in `explicit_operator_authorization_text_template` after replacing "
|
||||
"`<DEPLOYED_SHA_READBACK>` with that SHA, plus the operator identity to record in the receipt."
|
||||
),
|
||||
"next_non_user_action_after_authorization": [
|
||||
"Re-read deployed SHA, service state, and production preflight baseline.",
|
||||
"Run each packet phase in manifest order: preflight, authorized apply SQL, postflight.",
|
||||
"Run the non-posting direct-claim handler suite and strict scorer.",
|
||||
"Capture service readback, cleanup readback, and production receipt.",
|
||||
"Run the offline production receipt validator and retain the validation artifacts.",
|
||||
],
|
||||
"do_not_run_without": [
|
||||
"Exact operator authorization text naming production DB apply scope.",
|
||||
"Operator identity for the production receipt.",
|
||||
"Fresh preflight immediately before apply.",
|
||||
],
|
||||
"claim_ceiling": (
|
||||
"This packet requests explicit authorization and proves the request is bounded by retained evidence. It "
|
||||
"does not authorize production apply, does not run SQL, does not mutate production, and does not prove "
|
||||
"canonical rows were changed."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def write_json(path: Path, data: dict[str, Any]) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def write_markdown(path: Path, data: dict[str, Any]) -> None:
|
||||
lines = [
|
||||
"# Working Leo Production Apply Authorization Packet",
|
||||
"",
|
||||
f"Generated UTC: `{data['generated_at_utc']}`",
|
||||
f"Mode: `{data['mode']}`",
|
||||
f"Production apply executed: `{data['production_apply_executed']}`",
|
||||
f"Production apply authorization present: `{data['production_apply_authorization_present']}`",
|
||||
f"Ready to request authorization: `{data['ready_to_request_authorization']}`",
|
||||
f"Authorization gate status: `{data['authorization_gate_status']}`",
|
||||
f"Packet generation git SHA: `{data['packet_generation_git_sha']}`",
|
||||
f"Authorization commit SHA rule: `{data['authorization_commit_sha_rule']}`",
|
||||
"",
|
||||
"## Scope",
|
||||
"",
|
||||
f"- Target: `{data['authorization_scope']['target']}`",
|
||||
f"- Packet set: `{data['authorization_scope']['packet_set']}`",
|
||||
f"- Apply order: `{', '.join(data['authorization_scope']['apply_order'])}`",
|
||||
f"- Telegram-visible post authorized: `{data['authorization_scope']['telegram_visible_post_authorized']}`",
|
||||
f"- GCP parity in scope: `{data['authorization_scope']['gcp_parity_in_scope']}`",
|
||||
"",
|
||||
"## Checks",
|
||||
"",
|
||||
]
|
||||
for key, value in sorted(data["checks"].items()):
|
||||
lines.append(f"- `{key}`: `{value}`")
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
"## Explicit Operator Authorization Text",
|
||||
"",
|
||||
data["explicit_operator_authorization_text_template"],
|
||||
"",
|
||||
"## Clear CTA",
|
||||
"",
|
||||
data["clear_CTA"],
|
||||
"",
|
||||
"## Next Non-User Action After Authorization",
|
||||
"",
|
||||
]
|
||||
)
|
||||
lines.extend(f"- {item}" for item in data["next_non_user_action_after_authorization"])
|
||||
lines.extend(["", "## Do Not Run Without", ""])
|
||||
lines.extend(f"- {item}" for item in data["do_not_run_without"])
|
||||
lines.extend(["", "## Claim Ceiling", "", data["claim_ceiling"], ""])
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text("\n".join(lines), encoding="utf-8")
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--runbook", type=Path, default=DEFAULT_RUNBOOK)
|
||||
parser.add_argument("--session-plan", type=Path, default=DEFAULT_SESSION_PLAN)
|
||||
parser.add_argument("--preflight", type=Path, default=DEFAULT_PREFLIGHT)
|
||||
parser.add_argument("--direct-claim-score", type=Path, default=DEFAULT_DIRECT_CLAIM_SCORE)
|
||||
parser.add_argument("--receipt-template", type=Path, default=DEFAULT_RECEIPT_TEMPLATE)
|
||||
parser.add_argument("--receipt-validation", type=Path, default=DEFAULT_RECEIPT_VALIDATION)
|
||||
parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
|
||||
parser.add_argument("--markdown-out", type=Path, default=DEFAULT_MARKDOWN_OUT)
|
||||
parser.add_argument("--git-sha", default=None)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(argv)
|
||||
data = build_packet(
|
||||
runbook_path=args.runbook,
|
||||
session_plan_path=args.session_plan,
|
||||
preflight_path=args.preflight,
|
||||
direct_claim_score_path=args.direct_claim_score,
|
||||
receipt_template_path=args.receipt_template,
|
||||
receipt_validation_path=args.receipt_validation,
|
||||
git_sha=args.git_sha,
|
||||
)
|
||||
write_json(args.out, data)
|
||||
write_markdown(args.markdown_out, data)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"out": str(args.out),
|
||||
"markdown_out": str(args.markdown_out),
|
||||
"authorization_gate_status": data["authorization_gate_status"],
|
||||
"production_apply_executed": data["production_apply_executed"],
|
||||
"ready_to_request_authorization": data["ready_to_request_authorization"],
|
||||
},
|
||||
indent=2,
|
||||
sort_keys=True,
|
||||
)
|
||||
)
|
||||
return 0 if data["ready_to_request_authorization"] else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
"""Tests for scripts/build_working_leo_production_apply_authorization_packet.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
||||
|
||||
import build_working_leo_production_apply_authorization_packet as packet # noqa: E402
|
||||
|
||||
|
||||
def test_authorization_packet_is_ready_but_not_executed():
|
||||
report = packet.build_packet(git_sha="45bec0e")
|
||||
|
||||
assert report["mode"] == "production_apply_authorization_packet_not_executed"
|
||||
assert report["production_apply_executed"] is False
|
||||
assert report["production_apply_authorization_present"] is False
|
||||
assert report["ready_to_request_authorization"] is True
|
||||
assert report["authorization_gate_status"] == "ready_to_request_explicit_authorization"
|
||||
assert all(report["checks"].values())
|
||||
assert report["packet_generation_git_sha"] == "45bec0e"
|
||||
assert report["authorization_commit_sha_rule"] == "Use the fresh deployed SHA read back immediately before apply."
|
||||
assert report["authorization_scope"]["telegram_visible_post_authorized"] is False
|
||||
assert report["authorization_scope"]["gcp_parity_in_scope"] is False
|
||||
assert report["authorization_scope"]["apply_order"] == [
|
||||
"mapped-rich-base",
|
||||
"cross-surface-anchor",
|
||||
"rio-strategy-context",
|
||||
"governance-concept-schema",
|
||||
"helmer-7powers",
|
||||
]
|
||||
assert "I authorize production DB apply" in report["explicit_operator_authorization_text_template"]
|
||||
assert "<DEPLOYED_SHA_READBACK>" in report["explicit_operator_authorization_text_template"]
|
||||
assert "do not post Telegram-visible messages unless separately authorized" in report[
|
||||
"explicit_operator_authorization_text_template"
|
||||
]
|
||||
assert "re-read the deployed SHA" in report["clear_CTA"]
|
||||
assert "does not run SQL" in report["claim_ceiling"]
|
||||
assert "does not mutate production" in report["claim_ceiling"]
|
||||
|
||||
|
||||
def test_authorization_packet_markdown_preserves_clear_cta(tmp_path: Path):
|
||||
report = packet.build_packet(git_sha="45bec0e")
|
||||
out = tmp_path / "authorization.md"
|
||||
|
||||
packet.write_markdown(out, report)
|
||||
|
||||
text = out.read_text(encoding="utf-8")
|
||||
assert "Working Leo Production Apply Authorization Packet" in text
|
||||
assert "Ready to request authorization: `True`" in text
|
||||
assert "Production apply executed: `False`" in text
|
||||
assert "Packet generation git SHA: `45bec0e`" in text
|
||||
assert "Explicit Operator Authorization Text" in text
|
||||
assert "Clear CTA" in text
|
||||
assert "Do Not Run Without" in text
|
||||
assert "I authorize production DB apply" in text
|
||||
|
||||
|
||||
def test_authorization_packet_not_ready_when_direct_claim_score_fails(monkeypatch):
|
||||
real_load = packet._load_json
|
||||
|
||||
def fake_load(path: Path):
|
||||
data = real_load(path)
|
||||
if path == packet.DEFAULT_DIRECT_CLAIM_SCORE:
|
||||
data = dict(data)
|
||||
data["score"] = dict(data["score"])
|
||||
data["score"]["pass"] = False
|
||||
data["score"]["passes"] = 5
|
||||
data["score"]["failures"] = [{"prompt_id": "DC-06"}]
|
||||
return data
|
||||
|
||||
monkeypatch.setattr(packet, "_load_json", fake_load)
|
||||
|
||||
report = packet.build_packet(git_sha="45bec0e")
|
||||
|
||||
assert report["ready_to_request_authorization"] is False
|
||||
assert report["authorization_gate_status"] == "not_ready"
|
||||
assert report["checks"]["direct_claim_score_passed"] is False
|
||||
Loading…
Reference in a new issue