From 077227c8abb7eae12eebd75c6bf3a2be4d75d76a Mon Sep 17 00:00:00 2001 From: Svrnty Date: Thu, 18 Jun 2026 13:52:34 -0400 Subject: [PATCH] Reject CTO generated cache residue --- docs/LEGACY-INGEST.md | 13 +++++++++++++ tools/validate_cto_child.py | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/docs/LEGACY-INGEST.md b/docs/LEGACY-INGEST.md index a8c75a1..ae1d3fd 100644 --- a/docs/LEGACY-INGEST.md +++ b/docs/LEGACY-INGEST.md @@ -73,6 +73,19 @@ Decision: keep the intention with caution. The useful idea is explicit provider admission and metadata-only retention hygiene. Do not copy secrets, raw transcripts, or provider runtime behavior into CTO. Archive and deletion remain approval-gated. +### Generated Cache Custody + +Reference cluster: + +- ignored `tools/__pycache__/` observed on `2026-06-18` +- `/home/svrnty/workspaces/cortex-os-retired/2026-06-18/cto-python-cache-preserved-135154/MANIFEST.md` + +Decision: archive-only custody. + +The useful idea is none; this is generated Python bytecode residue. Keep the +manifest reference only. Do not treat cache files as CTO source, evidence, +backend state, target-repo state, provider state, or historical intention. + ### Stage 5 Target Sandbox Reference cluster: diff --git a/tools/validate_cto_child.py b/tools/validate_cto_child.py index 6b8ac60..4c20af9 100644 --- a/tools/validate_cto_child.py +++ b/tools/validate_cto_child.py @@ -5,10 +5,17 @@ from __future__ import annotations import json import re +import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] +sys.dont_write_bytecode = True + +GENERATED_ARTIFACT_DIRS = [ + "tools/__pycache__", + ".pytest_cache", +] REQUIRED_FILES = [ "AGENTS.md", @@ -180,6 +187,7 @@ REQUIRED_LEGACY_INGEST_PHRASES = [ "Source Clusters Assessed By Intention", "Do not activate Case as default backend.", "Do not mutate target repositories.", + "Generated Cache Custody", ] REQUIRED_ARCHITECTURE_CLOSEOUT_PRD_PHRASES = [ @@ -1903,6 +1911,15 @@ def workboard_status(text: str, issue_id: str) -> str | None: return match.group(1).strip() if match else None +def validate_no_generated_artifact_residue(checked: list[str]) -> list[str]: + errors: list[str] = [] + for relpath in GENERATED_ARTIFACT_DIRS: + checked.append(f"generated_artifact_absent:{relpath}") + if (ROOT / relpath).exists(): + errors.append(f"generated_artifact_residue:{relpath}") + return errors + + def main() -> int: checked: list[str] = [] errors: list[str] = [] @@ -1945,6 +1962,8 @@ def main() -> int: if phrase not in text: errors.append(f"missing_legacy_ingest_phrase:{phrase}") + errors.extend(validate_no_generated_artifact_residue(checked)) + brief = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-BACKEND-BRIEF.md" if brief.is_file(): text = brief.read_text(encoding="utf-8")