diff --git a/docs/reports/leo-working-state-20260709/current-truth-index.md b/docs/reports/leo-working-state-20260709/current-truth-index.md index e6f8419..4a5b0a3 100644 --- a/docs/reports/leo-working-state-20260709/current-truth-index.md +++ b/docs/reports/leo-working-state-20260709/current-truth-index.md @@ -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 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` +- Working Leo production apply receipt template JSON: `docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.json` - Working Leo production apply receipt validation, currently missing receipt: `docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-validation-current.md` - Working Leo production apply receipt validation JSON: `docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-validation-current.json` - Working Leo cleanup readback: `docs/reports/leo-working-state-20260709/working-leo-cleanup-readback-current.md` @@ -127,6 +129,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 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. - DB-first identity rendering is now documented from the July 9 PDFs plus VPS readback: canonical identity rows feed rendered `SOUL.md`, direct SOUL edits are not canonical DB updates, and no active renderer/timer/hook is proven in the current VPS readback. - The decision-matrix approval schema is still a target design on the current VPS: `kb_stage.matrix_voters`, `kb_stage.proposal_votes`, and `kb_stage.proposal_decisions` were not present in live schema readback. diff --git a/docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md b/docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md index 8500b6f..2170f34 100644 --- a/docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md +++ b/docs/reports/leo-working-state-20260709/working-leo-current-state-20260709.md @@ -1,6 +1,6 @@ # Working Leo Current State - 2026-07-09 -Generated UTC: `2026-07-10T01:42:00Z` +Generated UTC: `2026-07-10T01:46:00Z` ## Current Working Definition @@ -149,6 +149,12 @@ A working Leo, for Cory/m3taversal's current expectation, is a Telegram-facing a - Helmer proposal `a64df080` remains `approved`, required existing claims are present, and generated rows remain `0/0/0/0/0` - cross-surface/Rio/governance preflights show the expected before-apply baseline: dependent generated base rows are still absent and governance/concept tables are still absent - this is read-only production preflight evidence, not production apply authorization or proof of canonical mutation +- Production apply receipt template is now retained: + - `production_apply_executed=false` + - `valid_production_receipt=false` + - pre-filled/baseline fields are current git SHA, preflight output paths, expected counts, current direct-claim score path, rollback packet paths, and known residual risks + - after-apply fields still required are explicit authorization record, operator identity, apply outputs, postflight outputs, actual counts, post-apply regression paths, service readback, and cleanup readback + - this is a template, not a receipt and not a substitute for `working-leo-production-apply-receipt-current.json` - VPS/Hermes/DB identity and document-linking map is now documented: - the supplied July 9 master/build and database-reference PDFs confirm the intended architecture is DB-first identity: canonical Postgres identity graph rows render to `SOUL.md`, and evidence depth remains on demand through `teleo-kb` - direct `SOUL.md` edits are profile/runtime artifact edits, not canonical DB updates; they can drift or be overwritten unless represented in canonical rows first @@ -195,6 +201,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` - 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` - Cleanup readback: `work/teleo-infra-main/docs/reports/leo-working-state-20260709/working-leo-cleanup-readback-current.md` - VPS/Hermes/DB mapping: `outputs/vps-hermes-db-mapping-20260709.md` diff --git a/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.json b/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.json new file mode 100644 index 0000000..88bdadb --- /dev/null +++ b/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.json @@ -0,0 +1,107 @@ +{ + "claim_ceiling": "This is a receipt template only. It proves the operator knows which evidence must be captured, but it does not authorize production apply and does not prove canonical rows were changed.", + "field_status": { + "actual_after_apply_counts": "must_fill_after_postflight_execution", + "apply_output_paths": "must_fill_after_apply_execution", + "cleanup_readback": "must_fill_after_post_apply_cleanup_readback", + "direct_claim_score_path": "baseline_available_but_must_rerun_after_apply", + "expected_after_apply_counts": "pre_filled_from_authorized_runbook", + "explicit_authorization_record": "must_fill_after_explicit_authorization", + "git_commit_sha": "pre_filled_current_head_verify_at_apply_time", + "known_residual_risks": "pre_filled_review_after_apply", + "operator_identity": "must_fill_after_explicit_authorization", + "postflight_output_paths": "must_fill_after_postflight_execution", + "preflight_output_paths": "baseline_available_rerun_immediately_before_apply", + "rollback_packet_paths": "pre_filled_from_authorized_runbook", + "service_readback": "must_fill_after_post_apply_service_readback", + "telegram_or_handler_regression_paths": "must_fill_after_post_apply_regression_rerun" + }, + "generated_at_utc": "2026-07-10T01:46:12.932110+00:00", + "mode": "receipt_template_not_executed", + "must_fill_after_authorized_apply": [ + "explicit_authorization_record", + "operator_identity", + "apply_output_paths", + "postflight_output_paths", + "actual_after_apply_counts", + "telegram_or_handler_regression_paths", + "service_readback", + "cleanup_readback" + ], + "postflight_sql_paths_to_run_after_apply": [ + "docs/reports/leo-working-state-20260709/production-postflight.sql", + "docs/reports/leo-working-state-20260709/cross-surface-postflight.sql", + "docs/reports/leo-working-state-20260709/rio-strategy-postflight.sql", + "docs/reports/leo-working-state-20260709/governance-concept-postflight.sql", + "docs/reports/leo-working-state-20260709/helmer-7powers-production-postflight.sql" + ], + "preflight_artifacts": [ + { + "bytes": 12496, + "exists": true, + "path": "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.json" + }, + { + "bytes": 10047, + "exists": true, + "path": "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md" + } + ], + "production_apply_executed": false, + "ready_or_baseline_fields": [ + "git_commit_sha", + "preflight_output_paths", + "expected_after_apply_counts", + "direct_claim_score_path", + "rollback_packet_paths", + "known_residual_risks" + ], + "receipt_template": { + "actual_after_apply_counts": {}, + "apply_output_paths": [], + "cleanup_readback": {}, + "direct_claim_score_path": "docs/reports/leo-working-state-20260709/telegram-handler-direct-claim-suite-score-current.md", + "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 + }, + "explicit_authorization_record": { + "authorized": false, + "fill_after_authorization": true, + "required_scope": "integrated Working Leo packet set in runbook dependency order" + }, + "git_commit_sha": "57bd705079b2cb5f8cdc7a0a734083cf888177ff", + "known_residual_risks": [ + "GCP parity remains separate until access is restored and read-only parity proof is captured.", + "Any Telegram-visible post-apply proof must be separately authorized at action time." + ], + "operator_identity": "", + "postflight_output_paths": [], + "preflight_output_paths": [ + "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.json", + "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md" + ], + "rollback_packet_paths": [ + "docs/reports/leo-working-state-20260709/helmer-7powers-production-delete-rollback.sql", + "docs/reports/leo-working-state-20260709/governance-concept-delete-rollback.sql", + "docs/reports/leo-working-state-20260709/rio-strategy-delete-rollback.sql", + "docs/reports/leo-working-state-20260709/cross-surface-delete-rollback.sql", + "docs/reports/leo-working-state-20260709/production-delete-rollback.sql" + ], + "service_readback": {}, + "telegram_or_handler_regression_paths": [] + }, + "receipt_validation_status_before_apply": "missing_receipt", + "runbook_path": "docs/reports/leo-working-state-20260709/working-leo-authorized-apply-runbook-current.json", + "valid_production_receipt": false +} diff --git a/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.md b/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.md new file mode 100644 index 0000000..b892b9e --- /dev/null +++ b/docs/reports/leo-working-state-20260709/working-leo-production-apply-receipt-template-current.md @@ -0,0 +1,56 @@ +# Working Leo Production Apply Receipt Template + +Generated UTC: `2026-07-10T01:46:12.932110+00:00` +Mode: `receipt_template_not_executed` +Production apply executed: `False` +Valid production receipt: `False` +Receipt validation status before apply: `missing_receipt` + +## Field Status + +- `explicit_authorization_record`: `must_fill_after_explicit_authorization` +- `operator_identity`: `must_fill_after_explicit_authorization` +- `git_commit_sha`: `pre_filled_current_head_verify_at_apply_time` +- `preflight_output_paths`: `baseline_available_rerun_immediately_before_apply` +- `apply_output_paths`: `must_fill_after_apply_execution` +- `postflight_output_paths`: `must_fill_after_postflight_execution` +- `expected_after_apply_counts`: `pre_filled_from_authorized_runbook` +- `actual_after_apply_counts`: `must_fill_after_postflight_execution` +- `telegram_or_handler_regression_paths`: `must_fill_after_post_apply_regression_rerun` +- `direct_claim_score_path`: `baseline_available_but_must_rerun_after_apply` +- `service_readback`: `must_fill_after_post_apply_service_readback` +- `cleanup_readback`: `must_fill_after_post_apply_cleanup_readback` +- `rollback_packet_paths`: `pre_filled_from_authorized_runbook` +- `known_residual_risks`: `pre_filled_review_after_apply` + +## Ready Or Baseline Fields + +- `git_commit_sha` +- `preflight_output_paths` +- `expected_after_apply_counts` +- `direct_claim_score_path` +- `rollback_packet_paths` +- `known_residual_risks` + +## Must Fill After Authorized Apply + +- `explicit_authorization_record` +- `operator_identity` +- `apply_output_paths` +- `postflight_output_paths` +- `actual_after_apply_counts` +- `telegram_or_handler_regression_paths` +- `service_readback` +- `cleanup_readback` + +## Postflight SQL Paths + +- `docs/reports/leo-working-state-20260709/production-postflight.sql` +- `docs/reports/leo-working-state-20260709/cross-surface-postflight.sql` +- `docs/reports/leo-working-state-20260709/rio-strategy-postflight.sql` +- `docs/reports/leo-working-state-20260709/governance-concept-postflight.sql` +- `docs/reports/leo-working-state-20260709/helmer-7powers-production-postflight.sql` + +## Claim Ceiling + +This is a receipt template only. It proves the operator knows which evidence must be captured, but it does not authorize production apply and does not prove canonical rows were changed. diff --git a/scripts/build_working_leo_production_receipt_template.py b/scripts/build_working_leo_production_receipt_template.py new file mode 100644 index 0000000..4632798 --- /dev/null +++ b/scripts/build_working_leo_production_receipt_template.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +"""Build a non-executed Working Leo production-apply receipt template. + +The real production apply receipt must be written only after explicit +authorization and actual apply/postflight/regression execution. This script +prepares the operator-facing template before that boundary: it identifies which +receipt fields are already backed by retained artifacts and which fields must be +filled after the authorized apply window. +""" + +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_PREFLIGHT_JSON = REPORT_DIR / "working-leo-production-preflight-current.json" +DEFAULT_PREFLIGHT_MD = REPORT_DIR / "working-leo-production-preflight-current.md" +DEFAULT_VALIDATION = REPORT_DIR / "working-leo-production-apply-receipt-validation-current.json" +DEFAULT_OUT = REPORT_DIR / "working-leo-production-apply-receipt-template-current.json" +DEFAULT_MARKDOWN_OUT = REPORT_DIR / "working-leo-production-apply-receipt-template-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 _regression_artifacts(runbook: dict[str, Any]) -> dict[str, str]: + result: dict[str, str] = {} + for command in runbook.get("post_apply_regression_commands", []): + artifact = str(command.get("expected_artifact") or "") + if artifact and artifact != "terminal pytest output": + result[str(command.get("id"))] = artifact + return result + + +def _rollback_paths(runbook: dict[str, Any]) -> list[str]: + return [str(entry["path"]) for entry in runbook["phases"]["rollback_order"]] + + +def _postflight_paths(runbook: dict[str, Any]) -> list[str]: + return [str(entry["path"]) for entry in runbook["phases"]["postflight_order"]] + + +def build_template( + *, + runbook_path: Path = DEFAULT_RUNBOOK, + preflight_json_path: Path = DEFAULT_PREFLIGHT_JSON, + preflight_markdown_path: Path = DEFAULT_PREFLIGHT_MD, + validation_path: Path = DEFAULT_VALIDATION, + git_sha: str | None = None, +) -> dict[str, Any]: + runbook = _load_json(runbook_path) + preflight = _load_json(preflight_json_path) if preflight_json_path.exists() else {} + validation = _load_json(validation_path) if validation_path.exists() else {} + regressions = _regression_artifacts(runbook) + sha = git_sha if git_sha is not None else current_git_sha() + + receipt_template = { + "explicit_authorization_record": { + "authorized": False, + "fill_after_authorization": True, + "required_scope": "integrated Working Leo packet set in runbook dependency order", + }, + "operator_identity": "", + "git_commit_sha": sha, + "preflight_output_paths": [str(preflight_json_path), str(preflight_markdown_path)], + "apply_output_paths": [], + "postflight_output_paths": [], + "expected_after_apply_counts": runbook["expected_after_apply_counts"], + "actual_after_apply_counts": {}, + "telegram_or_handler_regression_paths": [], + "direct_claim_score_path": regressions.get("direct_claim_strict_score", ""), + "service_readback": {}, + "cleanup_readback": {}, + "rollback_packet_paths": _rollback_paths(runbook), + "known_residual_risks": [ + "GCP parity remains separate until access is restored and read-only parity proof is captured.", + "Any Telegram-visible post-apply proof must be separately authorized at action time.", + ], + } + + field_status = { + "explicit_authorization_record": "must_fill_after_explicit_authorization", + "operator_identity": "must_fill_after_explicit_authorization", + "git_commit_sha": "pre_filled_current_head_verify_at_apply_time", + "preflight_output_paths": ( + "baseline_available_rerun_immediately_before_apply" + if preflight.get("status") == "pass" + else "missing_or_failed_preflight_baseline" + ), + "apply_output_paths": "must_fill_after_apply_execution", + "postflight_output_paths": "must_fill_after_postflight_execution", + "expected_after_apply_counts": "pre_filled_from_authorized_runbook", + "actual_after_apply_counts": "must_fill_after_postflight_execution", + "telegram_or_handler_regression_paths": "must_fill_after_post_apply_regression_rerun", + "direct_claim_score_path": "baseline_available_but_must_rerun_after_apply", + "service_readback": "must_fill_after_post_apply_service_readback", + "cleanup_readback": "must_fill_after_post_apply_cleanup_readback", + "rollback_packet_paths": "pre_filled_from_authorized_runbook", + "known_residual_risks": "pre_filled_review_after_apply", + } + + ready_now = [ + field + for field, status in field_status.items() + if status.startswith("pre_filled") or status.startswith("baseline_available") + ] + must_fill = [field for field, status in field_status.items() if status.startswith("must_fill")] + + return { + "generated_at_utc": datetime.now(timezone.utc).isoformat(), + "mode": "receipt_template_not_executed", + "production_apply_executed": False, + "valid_production_receipt": False, + "runbook_path": str(runbook_path), + "preflight_artifacts": [_path_status(preflight_json_path), _path_status(preflight_markdown_path)], + "receipt_validation_status_before_apply": validation.get("status", "missing_validation_artifact"), + "receipt_template": receipt_template, + "field_status": field_status, + "ready_or_baseline_fields": ready_now, + "must_fill_after_authorized_apply": must_fill, + "postflight_sql_paths_to_run_after_apply": _postflight_paths(runbook), + "claim_ceiling": ( + "This is a receipt template only. It proves the operator knows which evidence must be captured, but it " + "does not authorize production apply 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 Receipt Template", + "", + f"Generated UTC: `{data['generated_at_utc']}`", + f"Mode: `{data['mode']}`", + f"Production apply executed: `{data['production_apply_executed']}`", + f"Valid production receipt: `{data['valid_production_receipt']}`", + f"Receipt validation status before apply: `{data['receipt_validation_status_before_apply']}`", + "", + "## Field Status", + "", + ] + for field, status in data["field_status"].items(): + lines.append(f"- `{field}`: `{status}`") + lines.extend(["", "## Ready Or Baseline Fields", ""]) + lines.extend(f"- `{field}`" for field in data["ready_or_baseline_fields"]) + lines.extend(["", "## Must Fill After Authorized Apply", ""]) + lines.extend(f"- `{field}`" for field in data["must_fill_after_authorized_apply"]) + lines.extend(["", "## Postflight SQL Paths", ""]) + lines.extend(f"- `{path}`" for path in data["postflight_sql_paths_to_run_after_apply"]) + 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("--preflight-json", type=Path, default=DEFAULT_PREFLIGHT_JSON) + parser.add_argument("--preflight-markdown", type=Path, default=DEFAULT_PREFLIGHT_MD) + parser.add_argument("--validation", type=Path, default=DEFAULT_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_template( + runbook_path=args.runbook, + preflight_json_path=args.preflight_json, + preflight_markdown_path=args.preflight_markdown, + validation_path=args.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), + "production_apply_executed": data["production_apply_executed"], + "valid_production_receipt": data["valid_production_receipt"], + "must_fill_after_authorized_apply": data["must_fill_after_authorized_apply"], + }, + indent=2, + sort_keys=True, + ) + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_build_working_leo_production_receipt_template.py b/tests/test_build_working_leo_production_receipt_template.py new file mode 100644 index 0000000..0a3ec8a --- /dev/null +++ b/tests/test_build_working_leo_production_receipt_template.py @@ -0,0 +1,66 @@ +"""Tests for scripts/build_working_leo_production_receipt_template.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_authorized_apply_runbook as runbook_builder # noqa: E402 +import build_working_leo_production_receipt_template as template # noqa: E402 + + +def test_template_contains_required_receipt_fields_without_claiming_execution(): + runbook = runbook_builder.build_runbook() + result = template.build_template(git_sha="57bd705") + receipt = result["receipt_template"] + + assert result["mode"] == "receipt_template_not_executed" + assert result["production_apply_executed"] is False + assert result["valid_production_receipt"] is False + assert set(runbook["production_apply_receipt_required_fields"]).issubset(receipt.keys()) + assert receipt["explicit_authorization_record"]["authorized"] is False + assert receipt["git_commit_sha"] == "57bd705" + assert receipt["expected_after_apply_counts"] == runbook["expected_after_apply_counts"] + assert receipt["actual_after_apply_counts"] == {} + assert receipt["apply_output_paths"] == [] + assert receipt["postflight_output_paths"] == [] + + +def test_template_marks_after_apply_fields_as_not_ready(): + result = template.build_template(git_sha="57bd705") + + assert "apply_output_paths" in result["must_fill_after_authorized_apply"] + assert "postflight_output_paths" in result["must_fill_after_authorized_apply"] + assert "actual_after_apply_counts" in result["must_fill_after_authorized_apply"] + assert "service_readback" in result["must_fill_after_authorized_apply"] + assert "cleanup_readback" in result["must_fill_after_authorized_apply"] + assert "expected_after_apply_counts" in result["ready_or_baseline_fields"] + assert "rollback_packet_paths" in result["ready_or_baseline_fields"] + + +def test_template_uses_live_preflight_baseline_as_baseline_not_apply_proof(): + result = template.build_template(git_sha="57bd705") + + assert result["field_status"]["preflight_output_paths"] == "baseline_available_rerun_immediately_before_apply" + assert result["receipt_template"]["preflight_output_paths"] == [ + "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.json", + "docs/reports/leo-working-state-20260709/working-leo-production-preflight-current.md", + ] + assert "does not authorize production apply" in result["claim_ceiling"] + assert "does not prove canonical rows were changed" in result["claim_ceiling"] + + +def test_markdown_preserves_non_executed_boundary(tmp_path: Path): + result = template.build_template(git_sha="57bd705") + out = tmp_path / "template.md" + + template.write_markdown(out, result) + + text = out.read_text() + assert "Production apply executed: `False`" in text + assert "Valid production receipt: `False`" in text + assert "`apply_output_paths`: `must_fill_after_apply_execution`" in text + assert "Claim Ceiling" in text