docs(meta): repoint decisions/ paths to governance/ tree (pql migration)
Phase 1 follow-up: update the active instruction layer (CLAUDE.md, project
structure rule, DECISIONS.md redirect, agent personalities, skill docs) to
reference governance/{decisions,questions,rejected}/<domain>.md instead of the
retired flat decisions/*.md layout.
Path references only — command-surface references (tooling/db/decision*,
decisions-sync, Makefile targets, clerk) are repointed to the pql CLI in the
Phase 4 consumer cutover. Historical archives (docs/sprints, docs/discussions,
docs/workshops) keep their point-in-time decisions/ paths; the separate
whatsinagame/ template distribution is untouched. Agent-memory is gitignored
and out of scope.
The agent/skill repath was applied by tooling/pql-migrate/repath_references.py
(ordered, meaning-preserving replacements; bare-dir rule uses a negative
lookbehind so it can't corrupt a freshly-created governance/decisions/ path),
committed for provenance. CLAUDE.md, project-structure.md, and DECISIONS.md
were hand-edited (structural tree/table changes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Repoint decisions/ PATH references to the governance/ DQR tree (pql migration, Phase 1).
|
||||
|
||||
Operates on the active instruction layer (agent + skill markdown). Ordered, literal
|
||||
string replacements — most-specific first, bare `decisions/` last so per-file paths
|
||||
keep their decisions/ subdir. Does NOT touch command references (tooling/db/decision*,
|
||||
decisions-sync) — those belong to the Phase 4 command cutover. Does NOT touch
|
||||
historical archives (docs/sprints, docs/discussions, docs/workshops) or the separate
|
||||
whatsinagame/ template distribution.
|
||||
|
||||
Default is a dry run. Pass --apply to write.
|
||||
"""
|
||||
import glob
|
||||
import re
|
||||
import sys
|
||||
|
||||
APPLY = "--apply" in sys.argv
|
||||
|
||||
# Ordered: specific globs/files first, per-domain D files next, bare dir LAST.
|
||||
# The bare-dir rule is a regex with a negative lookbehind so it never re-matches
|
||||
# the `decisions/` inside a `governance/decisions/...` path created by an earlier
|
||||
# rule (which would corrupt it to `governance/governance/...`).
|
||||
REPLACEMENTS = [
|
||||
("decisions/questions-*.md", "governance/questions/*.md"),
|
||||
("decisions/*.md", "governance/**/*.md"),
|
||||
("decisions/README.md", "governance/README.md"),
|
||||
("decisions/questions.md", "governance/README.md"),
|
||||
("decisions/rejected.md", "governance/rejected/"),
|
||||
("decisions/architecture.md", "governance/decisions/architecture.md"),
|
||||
("decisions/content.md", "governance/decisions/content.md"),
|
||||
("decisions/economics.md", "governance/decisions/economics.md"),
|
||||
("decisions/perception.md", "governance/decisions/perception.md"),
|
||||
("decisions/process.md", "governance/decisions/process.md"),
|
||||
("decisions/scope.md", "governance/decisions/scope.md"),
|
||||
(re.compile(r"(?<!governance/)decisions/"), "governance/"), # bare dir — must be last
|
||||
]
|
||||
|
||||
TARGETS = sorted(set(
|
||||
glob.glob("/var/mnt/data/projects/settled-reach/main/.claude/agents/*.md")
|
||||
+ glob.glob("/var/mnt/data/projects/settled-reach/main/.claude/skills/**/*.md", recursive=True)
|
||||
))
|
||||
|
||||
|
||||
def transform(text):
|
||||
changes = []
|
||||
for old, new in REPLACEMENTS:
|
||||
if isinstance(old, re.Pattern):
|
||||
n = len(old.findall(text))
|
||||
if n:
|
||||
text = old.sub(new, text)
|
||||
changes.append((old.pattern, new, n))
|
||||
elif old in text:
|
||||
n = text.count(old)
|
||||
text = text.replace(old, new)
|
||||
changes.append((old, new, n))
|
||||
return text, changes
|
||||
|
||||
|
||||
def main():
|
||||
print(f"=== repath_references.py ({'APPLY' if APPLY else 'DRY-RUN'}) ===\n")
|
||||
total = 0
|
||||
for path in TARGETS:
|
||||
with open(path, encoding="utf-8") as fh:
|
||||
text = fh.read()
|
||||
new_text, changes = transform(text)
|
||||
if not changes:
|
||||
continue
|
||||
rel = path.split("/main/", 1)[-1]
|
||||
print(rel)
|
||||
for old, new, n in changes:
|
||||
print(f" {n}x {old!r} -> {new!r}")
|
||||
total += n
|
||||
if APPLY:
|
||||
with open(path, "w", encoding="utf-8") as fh:
|
||||
fh.write(new_text)
|
||||
print(f"\n{total} replacement(s)." + ("" if APPLY else " (dry run — pass --apply)"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user