v0.4.6
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_khadhroony_workspace_rules.py
|
||||
# version: 12
|
||||
# version: 13
|
||||
|
||||
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
|
||||
|
||||
@@ -210,7 +210,7 @@ def audit_kb_lib_symbol_prefixes(root: pathlib.Path) -> list[Violation]:
|
||||
|
||||
|
||||
def audit_reserved_decoder_scaffolds(root: pathlib.Path) -> list[Violation]:
|
||||
"""Reject temporary decoder migration markers and incomplete reserved decoders."""
|
||||
"""Reject incomplete reserved decoder contracts."""
|
||||
|
||||
violations: list[Violation] = []
|
||||
decoder_root = root / "kb-lib/src/decoder"
|
||||
@@ -281,7 +281,7 @@ def audit_reserved_decoder_scaffolds(root: pathlib.Path) -> list[Violation]:
|
||||
|
||||
|
||||
def audit_reserved_materializer_scaffolds(root: pathlib.Path) -> list[Violation]:
|
||||
"""Reject temporary materializer markers and incomplete reserved materializers."""
|
||||
"""Reject incomplete reserved materializer contracts."""
|
||||
|
||||
violations: list[Violation] = []
|
||||
materializer_root = root / "kb-lib/src/materializer"
|
||||
@@ -362,7 +362,7 @@ def audit_reserved_materializer_scaffolds(root: pathlib.Path) -> list[Violation]
|
||||
|
||||
|
||||
def audit_reserved_executor_scaffolds(root: pathlib.Path) -> list[Violation]:
|
||||
"""Reject temporary executor markers and incomplete reserved executors."""
|
||||
"""Reject incomplete reserved executor contracts."""
|
||||
|
||||
violations: list[Violation] = []
|
||||
executor_root = root / "kb-lib/src/executor"
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_pre_0_4_6_static_contracts.py
|
||||
# version: 4
|
||||
|
||||
"""Audit static contracts that must remain true before the 0.4.6 alignment."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import tomllib
|
||||
|
||||
def fail(code: str, message: str) -> None:
|
||||
"""Print one violation."""
|
||||
|
||||
print(f"{code}: {message}")
|
||||
|
||||
def frontend_invokes(root: pathlib.Path) -> set[str]:
|
||||
"""Return literal Tauri commands invoked by the frontend."""
|
||||
|
||||
commands: set[str] = set()
|
||||
pattern = re.compile(r"invoke(?:<[^>]+>)?\(\s*[\"']([A-Za-z0-9_]+)[\"']")
|
||||
for suffix in ("*.ts", "*.html"):
|
||||
for path in (root / "kb-app-demo-desktop" / "frontend").rglob(suffix):
|
||||
commands.update(pattern.findall(path.read_text(encoding="utf-8")))
|
||||
return commands
|
||||
|
||||
def registered_commands(root: pathlib.Path) -> set[str]:
|
||||
"""Return commands registered in generate_handler."""
|
||||
|
||||
path = root / "kb-app-demo-desktop" / "src" / "tauri.rs"
|
||||
text = path.read_text(encoding="utf-8")
|
||||
match = re.search(r"generate_handler!\[(.*?)\]\);", text, re.DOTALL)
|
||||
if match is None:
|
||||
return set()
|
||||
return set(re.findall(r"([A-Za-z_][A-Za-z0-9_]*)[ \t]*,", match.group(1)))
|
||||
|
||||
def main() -> int:
|
||||
"""Run the pre-0.4.6 static audit."""
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--root", default=".")
|
||||
parser.add_argument("--report-only", action="store_true")
|
||||
arguments = parser.parse_args()
|
||||
root = pathlib.Path(arguments.root).resolve()
|
||||
violations = 0
|
||||
|
||||
dotenv_crates: list[str] = []
|
||||
for cargo in sorted(root.glob("*/Cargo.toml")):
|
||||
data = tomllib.loads(cargo.read_text(encoding="utf-8"))
|
||||
dependencies = data.get("dependencies", {})
|
||||
if "dotenvy" in dependencies:
|
||||
dotenv_crates.append(cargo.parent.name)
|
||||
if dotenv_crates != ["kb-config"]:
|
||||
fail("ALIGN001", f"dotenvy must be owned only by kb-config, found {dotenv_crates}")
|
||||
violations += 1
|
||||
|
||||
missing = sorted(frontend_invokes(root) - registered_commands(root))
|
||||
if missing:
|
||||
fail("ALIGN002", f"frontend commands missing from Tauri registration: {missing}")
|
||||
violations += 1
|
||||
|
||||
tauri_path = root / "kb-app-demo-desktop" / "src" / "tauri.rs"
|
||||
tauri_text = tauri_path.read_text(encoding="utf-8")
|
||||
forbidden_tauri_dependencies = (
|
||||
"kb_pipeline::",
|
||||
"kb_pipeline_demo_scenarios::",
|
||||
"kb_store::",
|
||||
)
|
||||
direct_dependencies = [
|
||||
dependency for dependency in forbidden_tauri_dependencies if dependency in tauri_text
|
||||
]
|
||||
if direct_dependencies:
|
||||
fail(
|
||||
"ALIGN009",
|
||||
f"tauri.rs must remain a thin IPC/runtime layer, direct domain dependencies: {direct_dependencies}",
|
||||
)
|
||||
violations += 1
|
||||
if 'window.label() != "main"' not in tauri_text or "disconnect_demo_ws_app_state" not in tauri_text:
|
||||
fail("ALIGN003", "global WebSocket shutdown must be tied to main-window destruction")
|
||||
violations += 1
|
||||
if re.search(r'window\.label\(\)\s*==\s*"demo_ws".*disconnect_demo_ws', tauri_text, re.DOTALL):
|
||||
fail("ALIGN004", "demo_ws window destruction must not disconnect the application session")
|
||||
violations += 1
|
||||
|
||||
app_state = (root / "kb-app-demo-desktop" / "src" / "app_state.rs").read_text(encoding="utf-8")
|
||||
if "demo_ws_session" not in app_state:
|
||||
fail("ALIGN005", "AppState must own the persistent demo WebSocket session")
|
||||
violations += 1
|
||||
|
||||
forbidden_crates = (
|
||||
"kb_decoder_",
|
||||
"kb_executor_",
|
||||
"kb_materializer_",
|
||||
"kb_store_core",
|
||||
"kb_store_pg",
|
||||
)
|
||||
for path in sorted(root.rglob("*.rs")):
|
||||
if any(part in {"olddocs", "target"} for part in path.parts):
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for name in forbidden_crates:
|
||||
if name in text:
|
||||
fail("ALIGN006", f"legacy crate identity {name!r} found in {path.relative_to(root)}")
|
||||
violations += 1
|
||||
|
||||
required_docs = ("README.md", "TODO.md", "USAGE.md", "CHANGELOG.md")
|
||||
for cargo in sorted(root.glob("*/Cargo.toml")):
|
||||
for document in required_docs:
|
||||
if not (cargo.parent / document).is_file():
|
||||
fail("ALIGN007", f"missing {document} in {cargo.parent.name}")
|
||||
violations += 1
|
||||
|
||||
matrix = root / "test-fixtures" / "contract-matrices" / "OPERATION_NAMING_MATRIX.json"
|
||||
if not matrix.is_file():
|
||||
fail("ALIGN008", "operation naming matrix is missing")
|
||||
violations += 1
|
||||
|
||||
tauri_source = (root / "kb-app-demo-desktop/src/tauri.rs").read_text(encoding="utf-8")
|
||||
command_files = []
|
||||
for command_path in (root / "kb-app-demo-desktop/src").glob("*.rs"):
|
||||
command_source = command_path.read_text(encoding="utf-8")
|
||||
if "#[tauri::command]" in command_source:
|
||||
command_files.append(command_path.name)
|
||||
if command_files != ["tauri.rs"]:
|
||||
fail("ALIGN009", f"#[tauri::command] must exist only in tauri.rs, found: {command_files}")
|
||||
violations += 1
|
||||
forbidden_files = [
|
||||
"tauri_backfill.rs",
|
||||
"tauri_core_extraction.rs",
|
||||
"tauri_decode_replay.rs",
|
||||
"tauri_execution.rs",
|
||||
"tauri_general_commands.rs",
|
||||
"tauri_http.rs",
|
||||
"tauri_sql.rs",
|
||||
"tauri_support.rs",
|
||||
"tauri_ws.rs",
|
||||
]
|
||||
for forbidden in forbidden_files:
|
||||
if (root / "kb-app-demo-desktop/src" / forbidden).exists():
|
||||
fail("ALIGN010", f"obsolete Tauri adapter module still exists: {forbidden}")
|
||||
violations += 1
|
||||
if "return crate::demo_decode_replay_options(state);" not in tauri_source:
|
||||
fail("ALIGN011", "tauri.rs must delegate demo_decode_replay_options through the crate façade")
|
||||
violations += 1
|
||||
if violations == 0:
|
||||
print("Pre-0.4.6 static contract audit: clean")
|
||||
return 0
|
||||
|
||||
print(f"Pre-0.4.6 static contract audit: {violations} violation(s)")
|
||||
return 0 if arguments.report_only else 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_export_completeness.py
|
||||
# version: 3
|
||||
# version: 4
|
||||
|
||||
"""Audit missing crate-root exports and replaceable long internal paths.
|
||||
|
||||
@@ -131,10 +131,7 @@ def audit_crate(workspace: pathlib.Path, crate: pathlib.Path) -> list[Candidate]
|
||||
for declaration in declaration_candidates(crate, path):
|
||||
key = (declaration.module, declaration.name)
|
||||
declarations[key] = declaration
|
||||
is_migration_scaffold = declaration.name.endswith(
|
||||
("_LEGACY_CRATE", "_MIGRATION_BOUNDARIES", "_MIGRATION_STATUS")
|
||||
)
|
||||
if key not in exports and not is_migration_scaffold:
|
||||
if key not in exports:
|
||||
relative = path.relative_to(workspace).as_posix()
|
||||
candidates.append(
|
||||
Candidate(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_general_rules.py
|
||||
# version: 8
|
||||
# version: 9
|
||||
|
||||
"""Audit mechanically verifiable Rust rules shared by all Rust projects."""
|
||||
|
||||
@@ -32,9 +32,6 @@ def rust_files(root: pathlib.Path) -> list[pathlib.Path]:
|
||||
if "target" not in path.parts
|
||||
and ".git" not in path.parts
|
||||
and "mnt" not in path.relative_to(root).parts
|
||||
and path.relative_to(root).parts[:2]
|
||||
!= ("migration", "khadhroony-bot2-reference")
|
||||
and not any(part.startswith("pre035_") for part in path.relative_to(root).parts)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_workspace_rules.py
|
||||
# version: 4
|
||||
# version: 5
|
||||
|
||||
"""Run the general, export-completeness and khadhroony workspace audits."""
|
||||
|
||||
@@ -22,7 +22,6 @@ def main() -> int:
|
||||
["python3", str(script_dir / "audit_rust_general_rules.py"), "--root", arguments.root],
|
||||
["python3", str(script_dir / "audit_rust_export_completeness.py"), "--root", arguments.root],
|
||||
["python3", str(script_dir / "audit_khadhroony_workspace_rules.py"), "--root", arguments.root],
|
||||
["python3", str(script_dir / "audit_pre_0_4_6_static_contracts.py"), "--root", arguments.root],
|
||||
]
|
||||
if arguments.report_only:
|
||||
for command in commands:
|
||||
|
||||
Reference in New Issue
Block a user