attemp to develop rig in spr without an actual use case
This commit is contained in:
111
soleprint/station/tools/histgen/brief.py
Normal file
111
soleprint/station/tools/histgen/brief.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
One pack per commit, for whoever writes the message.
|
||||
|
||||
This is the interface to the expensive reader, and it is a directory of
|
||||
markdown rather than a network call. The tool does not know how to reach a
|
||||
model and does not want to: an agent already in this repo reads the briefs and
|
||||
writes titles and bodies back into plan.json, which keeps the messages editable
|
||||
before a single commit exists and keeps an API key out of a tool that otherwise
|
||||
runs offline.
|
||||
|
||||
What travels is the reasoning already in the code — each file's opening
|
||||
comment — and not the file. That is both what makes the pack cheap and what
|
||||
makes the message right: a commit message reconstructed from a diff restates
|
||||
the diff, and the thing worth recording was never in the diff. It was in the
|
||||
comment explaining why the port offsets have to match another project's, or why
|
||||
the ignore rules exist before the code they exclude.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from .census import INDEX_FILE, state_dir
|
||||
from .order import plan_path
|
||||
|
||||
BRIEF_DIR = "briefs"
|
||||
|
||||
WHY_CHARS = 700 # an opening comment past this is an essay; the head carries it
|
||||
MAX_LISTED = 40
|
||||
|
||||
|
||||
HEADER = """# {n:02d} — {slug}
|
||||
|
||||
**{count} file(s), commit {n} of {total}.**
|
||||
|
||||
Write a title and a body for this commit, then put them in
|
||||
`{plan}` under group {n} as `"title"` and `"body"`.
|
||||
|
||||
- The title says what this commit establishes, in the repo's own words.
|
||||
- The body carries the **why** — take it from the reasoning already in the
|
||||
comments below. Do not restate the diff; the diff is already in the commit.
|
||||
- If a file below does not belong in this commit, move its path to another
|
||||
group in plan.json. The grouping is a proposal.
|
||||
"""
|
||||
|
||||
|
||||
def _fmt_why(text):
|
||||
text = (text or "").strip()
|
||||
if not text:
|
||||
return "_(no opening comment)_"
|
||||
if len(text) > WHY_CHARS:
|
||||
text = text[:WHY_CHARS].rsplit("\n", 1)[0] + "\n…"
|
||||
return "\n".join("> " + line if line.strip() else ">" for line in text.split("\n"))
|
||||
|
||||
|
||||
def write_briefs(out, quiet=False):
|
||||
state = state_dir(out)
|
||||
plan = json.loads(plan_path(out).read_text())
|
||||
index = json.loads((state / INDEX_FILE).read_text())
|
||||
files = index["files"]
|
||||
groups = plan["groups"]
|
||||
|
||||
# Which commit each path lands in, so a dependency can be named by the
|
||||
# commit that introduced it rather than by a bare path. "stands on 04" is
|
||||
# the sentence the ordering exists to make true.
|
||||
landed = {p: g["n"] for g in groups for p in g["paths"]}
|
||||
|
||||
out_dir = state / BRIEF_DIR
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
for stale in out_dir.glob("*.md"):
|
||||
stale.unlink()
|
||||
|
||||
for g in groups:
|
||||
lines = [HEADER.format(n=g["n"], slug=g["slug"], count=len(g["paths"]),
|
||||
total=len(groups), plan=plan_path(out))]
|
||||
|
||||
earlier, later = {}, set()
|
||||
for p in g["paths"]:
|
||||
for dep in files.get(p, {}).get("refs", []):
|
||||
n = landed.get(dep)
|
||||
if n is None or dep in g["paths"]:
|
||||
continue
|
||||
(earlier.setdefault(n, set()).add(dep) if n < g["n"] else later.add(dep))
|
||||
|
||||
if earlier:
|
||||
lines.append("\n## Stands on\n")
|
||||
for n in sorted(earlier):
|
||||
names = ", ".join(f"`{d}`" for d in sorted(earlier[n])[:MAX_LISTED])
|
||||
lines.append(f"- commit {n:02d}: {names}")
|
||||
if later:
|
||||
# Worth stating plainly rather than hiding: it is the one thing a
|
||||
# reader of the finished history would notice and the tool cannot
|
||||
# fix, because the fix is a judgement about which comes first.
|
||||
names = ", ".join(f"`{d}`" for d in sorted(later)[:MAX_LISTED])
|
||||
lines.append("\n## Forward references (this commit names things not yet committed)\n")
|
||||
lines.append(f"- {names}")
|
||||
|
||||
lines.append("\n## Files\n")
|
||||
for p in g["paths"]:
|
||||
e = files.get(p, {})
|
||||
meta = f"{e.get('role', '?')}, {e.get('lines', 0)} lines"
|
||||
if e.get("binary"):
|
||||
meta += ", binary"
|
||||
lines.append(f"\n### `{p}`\n\n_{meta}_\n")
|
||||
lines.append(_fmt_why(e.get("why")))
|
||||
|
||||
path = out_dir / f"{g['n']:02d}-{g['slug']}.md"
|
||||
path.write_text("\n".join(lines) + "\n")
|
||||
|
||||
if not quiet:
|
||||
print(f"Wrote {len(groups)} briefs -> {out_dir}")
|
||||
print(f"Read them, then write title and body into {plan_path(out)}.")
|
||||
return out_dir
|
||||
Reference in New Issue
Block a user