v0.1.0-pre.011-fix-01

This commit is contained in:
2026-07-24 15:06:27 +02:00
parent 42e8a203ec
commit 60660ca555
161 changed files with 10665 additions and 977 deletions

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# file: scripts/audit_khadhroony_workspace_rules.py
# version: 4
# version: 5
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
@@ -66,16 +66,16 @@ def audit_tracing(root: pathlib.Path) -> list[Violation]:
if not crate_root.exists():
crate_root = crate / "src/main.rs"
relative_root = crate_root.relative_to(root).as_posix()
if not crate_root.exists() or "pub(crate) use crate::constants::TRACING_TARGET;" not in crate_root.read_text(encoding="utf-8"):
if not crate_root.exists() or "pub(crate) use self::constants::TRACING_TARGET;" not in crate_root.read_text(encoding="utf-8"):
violations.append(Violation("KH_TRACE002", relative_root, 1, "missing crate-root TRACING_TARGET re-export"))
for path in crate.glob("src/**/*.rs"):
relative = path.relative_to(root).as_posix()
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if "khbot." in line:
violations.append(Violation("KH_TRACE003", relative, index, "legacy khbot tracing target is forbidden"))
if "crate::constants::TRACING_TARGET" in line and path.name not in {"lib.rs", "main.rs"}:
if "crate::constants::TRACING_TARGET" in line:
violations.append(Violation("KH_TRACE004", relative, index, "use crate::TRACING_TARGET outside crate root"))
if re.search(r"(?:crate::[A-Za-z0-9_]+::|(?<!crate::))TRACING_TARGET", line) and "const TRACING_TARGET" not in line and "use crate::constants::TRACING_TARGET" not in line:
if re.search(r"(?:crate::[A-Za-z0-9_]+::|(?<!crate::))TRACING_TARGET", line) and "const TRACING_TARGET" not in line and "use self::constants::TRACING_TARGET" not in line:
if "crate::TRACING_TARGET" not in line:
violations.append(Violation("KH_TRACE005", relative, index, "non-canonical TRACING_TARGET path"))
return violations
@@ -90,18 +90,17 @@ def audit_kb_lib_tracing(root: pathlib.Path) -> list[Violation]:
if not crate_root.exists():
return violations
root_text = crate_root.read_text(encoding="utf-8")
aliases = set()
alias_pattern = re.compile(
r"^pub\(crate\) use crate::[A-Za-z0-9_:]+::"
r"([A-Z][A-Z0-9_]+)(?: as ([A-Z][A-Z0-9_]+))?;$",
re_exports = set()
re_export_pattern = re.compile(
r"^pub\(crate\) use self::[A-Za-z0-9_:]+::"
r"([A-Z][A-Z0-9_]+);$",
re.MULTILINE,
)
for match in alias_pattern.finditer(root_text):
exported_name = match.group(2) if match.group(2) is not None else match.group(1)
if exported_name.endswith("_TRACING_TARGET"):
aliases.add(exported_name)
for match in re_export_pattern.finditer(root_text):
if match.group(1).endswith("_TRACING_TARGET"):
re_exports.add(match.group(1))
target_pattern = re.compile(
r'^pub\(crate\) const TRACING_TARGET: &str = "([^"]+)";$',
r'^pub\(crate\) const ([A-Z][A-Z0-9_]+_TRACING_TARGET): &str = "([^"]+)";$',
re.MULTILINE,
)
for constants in sorted((crate / "src").rglob("constants.rs")):
@@ -112,13 +111,13 @@ def audit_kb_lib_tracing(root: pathlib.Path) -> list[Violation]:
component = constants.parent.relative_to(crate / "src")
expected = "kb-lib." + ".".join(component.parts)
relative = constants.relative_to(root).as_posix()
if match.group(1) != expected:
if match.group(2) != expected:
violations.append(
Violation(
"KH_TRACE101",
relative,
text[: match.start()].count("\n") + 1,
f"expected hierarchical target `{expected}`",
f"`{match.group(1)}` must use hierarchical target `{expected}`",
)
)
macro_pattern = re.compile(
@@ -138,7 +137,7 @@ def audit_kb_lib_tracing(root: pathlib.Path) -> list[Violation]:
)
)
for match in macro_pattern.finditer(text):
if match.group(1) not in aliases:
if match.group(1) not in re_exports:
violations.append(
Violation(
"KH_TRACE103",
@@ -164,6 +163,85 @@ def audit_solana_types(root: pathlib.Path) -> list[Violation]:
return violations
def audit_kb_lib_symbol_prefixes(root: pathlib.Path) -> list[Violation]:
"""Require stable family prefixes on non-method kb-lib declarations."""
violations: list[Violation] = []
families = {
"decoder": ("DC_", "Dc", "decoder_"),
"executor": ("EX_", "Ex", "executor_"),
"materializer": ("MT_", "Mt", "materializer_"),
"model": ("MD_", "Md", "model_"),
}
declaration = re.compile(
r"^pub(?:\(crate\))?\s+"
r"(?:(?:async|const|unsafe)\s+)*"
r"(const|static|type|struct|enum|trait|union|fn)\s+"
r"([A-Za-z_][A-Za-z0-9_]*)"
)
for family, prefixes in families.items():
family_root = root / "kb-lib/src" / family
paths = [family_root.with_suffix(".rs")]
if family_root.is_dir():
paths.extend(sorted(family_root.rglob("*.rs")))
for path in paths:
if not path.is_file():
continue
relative = path.relative_to(root).as_posix()
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
match = declaration.match(line)
if match is None:
continue
kind = match.group(1)
name = match.group(2)
expected = prefixes[0] if kind in {"const", "static"} else prefixes[2] if kind == "fn" else prefixes[1]
if not name.startswith(expected):
violations.append(
Violation(
"KH_NAME001",
relative,
index,
f"`{name}` must start with `{expected}` for the {family} family",
)
)
return violations
def audit_token2022_naming(root: pathlib.Path) -> list[Violation]:
"""Reject obsolete internal Token2022 spellings while preserving legacy evidence."""
violations: list[Violation] = []
obsolete = (
"kb-lib.decoder.spl.token_2022",
"docs/SPL_TOKEN_2022_",
"`core_spl_token_2022",
"`spl_token_2022`",
)
candidates = [
root / "README.md",
root / "ROADMAP.md",
root / "RULES.md",
root / "kb-lib/README.md",
]
candidates.extend(sorted((root / "docs").glob("*.md")))
for path in candidates:
if not path.is_file() or path.name == "RUST_WORKSPACE_RULE_AUDIT.md":
continue
relative = path.relative_to(root).as_posix()
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
for spelling in obsolete:
if spelling in line:
violations.append(
Violation(
"KH_NAME002",
relative,
index,
f"obsolete internal Token2022 spelling `{spelling}`",
)
)
return violations
def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]:
"""Require the currently compatible Solana wincode dependency family."""
@@ -238,6 +316,8 @@ def main() -> int:
violations = (
audit_tracing(root)
+ audit_kb_lib_tracing(root)
+ audit_kb_lib_symbol_prefixes(root)
+ audit_token2022_naming(root)
+ audit_solana_types(root)
+ audit_wincode_resolution(root)
)