hatchimera / .codex /hooks /scripts /wiki_session_start.py
arkai2025's picture
chore: integrate llm-project-wiki (auto write policy, English)
d41012e
Raw
History Blame Contribute Delete
4.59 kB
#!/usr/bin/env python3
"""Load project wiki context at session start."""
import json
import os
import subprocess
import sys
from pathlib import Path
def project_root() -> Path:
env_root = os.environ.get("CLAUDE_PROJECT_DIR")
if env_root:
return Path(env_root)
try:
output = subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
stderr=subprocess.DEVNULL,
text=True,
).strip()
if output:
return Path(output)
except Exception:
pass
return Path.cwd()
VALID_POLICIES = {"require_approval", "auto", "open"}
def resolve_write_policy(root: Path) -> str:
"""Resolve the active write policy. Fail closed: default to require_approval.
Resolution order:
1. A valid `write_policy` enum value.
2. Legacy `require_human_approval` boolean (true -> require_approval,
false -> open).
3. require_approval (fail-closed: missing/unreadable/invalid config).
"""
try:
config = json.loads((root / "wiki.config.json").read_text(encoding="utf-8"))
if isinstance(config, dict):
policy = config.get("write_policy")
if policy in VALID_POLICIES:
return policy
if "require_human_approval" in config:
return "require_approval" if config.get("require_human_approval") else "open"
except Exception:
pass
return "require_approval"
def write_policy_text(policy: str) -> str:
if policy == "open":
return (
"Wiki write policy (wiki.config.json): human approval NOT required "
"(open). When you find durable knowledge, you may write the wiki page "
"directly without waiting for approval — still update wiki/index.md, "
'append to wiki/log.md, and output a wiki evaluation marker (e.g. "Wiki '
'suggestion") so the Stop hook passes.'
)
if policy == "auto":
return (
"Wiki write policy (wiki.config.json): auto. NOTE: the deterministic "
"PreToolUse gate is Claude-only; Codex does not enforce it, so apply "
"these rules by self-discipline. You may write a wiki page directly "
"only when its resulting frontmatter confidence is `high`, and you must "
"then disclose the diff. If the resulting confidence would be `medium`, "
"`low`, or missing — or for any delete or wrong-location write — do not "
'write; propose it with the "Wiki suggestion" format instead. Still '
"update wiki/index.md, append to wiki/log.md, and emit a wiki evaluation "
"marker."
)
return (
"Wiki write policy (wiki.config.json): human approval REQUIRED. "
'Propose updates with the "Wiki suggestion" format and wait for '
"explicit approval before creating, updating, or deleting any wiki page."
)
def emit_context(text: str) -> None:
print(
json.dumps(
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": text,
}
}
)
)
def git_output(root: Path, args: list[str]) -> str:
try:
return subprocess.check_output(
["git", "-C", str(root), *args],
stderr=subprocess.DEVNULL,
text=True,
).rstrip()
except Exception:
return ""
def main() -> None:
mode = sys.argv[1] if len(sys.argv) > 1 else ""
root = project_root()
if mode == "wiki-index":
index_path = root / "wiki" / "index.md"
if not index_path.is_file():
print("{}")
return
emit_context(
"Project wiki index:\n\n"
f"{index_path.read_text(encoding='utf-8')}\n\n"
"Codex wiki review rule: every substantial final response must "
"evaluate whether the conversation produced durable project "
"knowledge. If yes, include a visible `Wiki suggestion`. If no, "
"do not add a visible no-op marker; keep the transcript clean.\n\n"
f"{write_policy_text(resolve_write_policy(root))}"
)
return
if mode == "git-context":
status = git_output(root, ["status", "-s"])
latest_commit = git_output(root, ["log", "-1", "--format=%h %s (%cr)"])
emit_context(f"Git status:\n{status}\n\nLatest commit:\n{latest_commit}\n")
return
print("{}")
if __name__ == "__main__":
main()