550c98f275
Reorganización física de crates/: - core/ (mezclaba 6 propósitos) se divide en protocol/, init/, runtime/, compat/ - shared/ (3 crates) se redistribuye en protocol/ e init/ - lapaloma (sub-módulo de ui_engine) se promueve a modules/pineal/ Renames de proyectos: - shipote → shuma (runtime de sandboxes) - nouser → akasha (explorador de Mónadas) - yahweh → nahual (motor GPUI, antes ui_engine/) - lapaloma → pineal (data-viz agnóstica) Fraccionamiento UI → core agnóstico: - vista-core (DeckState + snap, 175 LOC, 5 tests verdes) - barra-core (Task + render_html + sanitize, 90 LOC, 5 tests verdes) - vista-web y barra-web ahora son thin DOM bindings Documentación nueva: - 16 SDDs por subdirectorio (≤80 LOC c/u): protocol/init/runtime/compat + 10 módulos + apps/ - docs/STATUS.md con cifras reales por proyecto - docs/ROADMAP.md con plan a finalización (6 hitos, ~6-8 semanas) - CHANGELOG.md particionado en docs/changelog/<proyecto>.md (7 buckets) Automatización: - scripts/reorg.py — script idempotente que: git mv directorios, renombra package names, recomputa path = refs, reescribe imports rust, actualiza workspace Cargo.toml. Soporta --dry-run. - scripts/split-changelog.py — particiona CHANGELOG por componente. Validación: - cargo check --workspace pasa (124 crates + 2 nuevos cores). - 10 tests adicionales (5 en vista-core + 5 en barra-core) verdes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
148 lines
6.9 KiB
Python
148 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Particiona CHANGELOG.md raíz por proyecto/intención.
|
|
|
|
Cada sección `### tipo(componente):` se rutea a `docs/changelog/<proyecto>.md`
|
|
según el componente. CHANGELOG.md raíz queda como índice apuntando a las
|
|
particiones.
|
|
|
|
Reglas de ruteo:
|
|
brahman-* → protocol
|
|
ente-zero|kernel|soma|... → init
|
|
ente-bus|cas|wasm|brain|echo → runtime
|
|
ente-*-compat|policy-provider → compat
|
|
minga-* → minga
|
|
yahweh-*|nahual-* → nahual
|
|
lapaloma-*|pineal-* → pineal
|
|
nakui-* → nakui
|
|
nouser-*|akasha-* → akasha
|
|
shipote-*|shuma-* → shuma
|
|
gioser-* → gioser
|
|
pluma-* → pluma
|
|
vista-* → vista
|
|
barra-* → barra
|
|
cosmobiologia-* → cosmobiologia
|
|
"""
|
|
|
|
import re, sys
|
|
from pathlib import Path
|
|
from collections import defaultdict
|
|
|
|
ROOT = Path("/home/sergio/brahman")
|
|
CHANGELOG = ROOT / "CHANGELOG.md"
|
|
OUT_DIR = ROOT / "docs" / "changelog"
|
|
|
|
INIT_NAMES = {"ente-zero", "ente-kernel", "ente-soma",
|
|
"ente-snapshot", "ente-incarnate"}
|
|
RUNTIME_NAMES = {"ente-bus", "ente-cas", "ente-wasm",
|
|
"ente-brain", "ente-echo"}
|
|
|
|
PROTOCOL_BARE = {"card", "cards", "sidecar", "handshake", "broker",
|
|
"admin", "net", "card-wit", "core", "arje"}
|
|
|
|
def route_single(c: str) -> str | None:
|
|
"""Devuelve bucket o None si no matchea."""
|
|
c = c.strip()
|
|
if c.startswith("brahman-"): return "protocol"
|
|
if c in PROTOCOL_BARE: return "protocol"
|
|
if c in INIT_NAMES: return "init"
|
|
if c in RUNTIME_NAMES: return "runtime"
|
|
if c.startswith("ente-") and (c.endswith("-compat") or c == "ente-policy-provider"):
|
|
return "compat"
|
|
if c.startswith("ente-"): return "init"
|
|
if c.startswith("minga-") or c == "minga": return "minga"
|
|
if c.startswith("yahweh-") or c.startswith("nahual-") or c in {"yahweh", "nahual"}:
|
|
return "nahual"
|
|
if c.startswith("lapaloma-") or c.startswith("pineal-") or c in {"lapaloma", "pineal"}:
|
|
return "pineal"
|
|
if c.startswith("nakui-") or c == "nakui": return "nakui"
|
|
if c.startswith("nouser-") or c.startswith("akasha-") or c in {"nouser", "akasha", "nous", "nous-real", "nous-mock"}:
|
|
return "akasha"
|
|
if c.startswith("shipote-") or c.startswith("shuma-") or c in {"shipote", "shuma"}:
|
|
return "shuma"
|
|
if c.startswith("gioser-") or c == "gioser": return "gioser"
|
|
if c.startswith("pluma-") or c == "pluma": return "pluma"
|
|
if c.startswith("vista-") or c == "vista": return "vista"
|
|
if c.startswith("barra-") or c == "barra": return "barra"
|
|
if c.startswith("cosmobiologia-") or c == "cosmobiologia": return "cosmobiologia"
|
|
# explorer + daemon: dominio variable. "explorer" solo sugiere apps/X-explorer.
|
|
if c == "explorer" or c == "daemon": return None # forzar inspección de otro componente
|
|
return None
|
|
|
|
def route(components: str) -> str:
|
|
"""Componentes pueden venir como 'a+b' o 'a,b' o 'a'. Buscamos el
|
|
primero que matchee un bucket conocido."""
|
|
parts = re.split(r"[+,]", components)
|
|
for p in parts:
|
|
b = route_single(p)
|
|
if b is not None:
|
|
return b
|
|
return "misc"
|
|
|
|
# Notas de header por proyecto (incluyen el rename si aplica).
|
|
HEADERS = {
|
|
"protocol": "# Changelog — protocol/\n\nContratos canónicos + routing entre módulos. Antes: `core/brahman-*` + `shared/brahman-*`.\n",
|
|
"init": "# Changelog — init/\n\nInit (PID 1) + encarnación Linux. Antes: `core/ente-{zero,kernel,soma,snapshot}` + `shared/ente-incarnate`.\n",
|
|
"runtime": "# Changelog — runtime/\n\nInfraestructura de ejecución (bus + cas + wasm + brain + echo). Antes: `core/ente-{bus,cas,wasm,brain,echo}`.\n",
|
|
"compat": "# Changelog — compat/\n\nShims D-Bus systemd. Antes: `core/ente-*-compat`.\n",
|
|
"minga": "# Changelog — minga (semantic_dht)\n",
|
|
"nahual": "# Changelog — nahual\n\nMotor GPUI: libs + widgets. Renombrado de `yahweh` el 2026-05-19.\n",
|
|
"pineal": "# Changelog — pineal\n\nData-viz agnóstica con backends. Renombrado de `lapaloma` el 2026-05-19; promovido fuera de `ui_engine/`.\n",
|
|
"nakui": "# Changelog — nakui\n\nERP categórico.\n",
|
|
"akasha": "# Changelog — akasha\n\nExplorador semántico de Mónadas. Renombrado de `nouser` el 2026-05-19.\n",
|
|
"shuma": "# Changelog — shuma\n\nRuntime de espacios aislados. Renombrado de `shipote` el 2026-05-19.\n",
|
|
"gioser": "# Changelog — gioser\n\nLanding WASM (chacana + 4 elementos).\n",
|
|
"pluma": "# Changelog — pluma\n\nMarkdown agnóstico + visor web.\n",
|
|
"vista": "# Changelog — vista\n\nDeck horizontal swipe (PageView).\n",
|
|
"barra": "# Changelog — barra\n\nTaskbar agnóstica (Windows-like).\n",
|
|
"cosmobiologia": "# Changelog — cosmobiologia\n\nEstudio de astrología profesional.\n",
|
|
"misc": "# Changelog — misc\n\nEntradas que no encajan en otro proyecto (chore, ci, gitignore, etc.).\n",
|
|
}
|
|
|
|
def main():
|
|
text = CHANGELOG.read_text()
|
|
lines = text.splitlines(keepends=True)
|
|
|
|
# 1) Captura todas las secciones que empiezan con `### `
|
|
header_re = re.compile(r"^### (?:feat|fix|refactor|docs|chore|test|perf|build|ci|style)\(([^)]+)\):")
|
|
sections: list[tuple[int, str]] = [] # (line_index, component)
|
|
for i, line in enumerate(lines):
|
|
m = header_re.match(line)
|
|
if m:
|
|
sections.append((i, m.group(1)))
|
|
|
|
# 2) Construye los bloques: desde header hasta siguiente header (excl).
|
|
buckets: dict[str, list[str]] = defaultdict(list)
|
|
for j, (idx, comp) in enumerate(sections):
|
|
end = sections[j + 1][0] if j + 1 < len(sections) else len(lines)
|
|
block = "".join(lines[idx:end]).rstrip() + "\n\n"
|
|
proj = route(comp)
|
|
buckets[proj].append(block)
|
|
|
|
# 3) Escribe particiones
|
|
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
for proj, blocks in sorted(buckets.items()):
|
|
path = OUT_DIR / f"{proj}.md"
|
|
content = HEADERS.get(proj, f"# Changelog — {proj}\n") + "\n"
|
|
content += "".join(blocks)
|
|
path.write_text(content)
|
|
print(f" {path.relative_to(ROOT)}: {len(blocks)} entradas")
|
|
|
|
# 4) Reescribe CHANGELOG.md como índice
|
|
index_lines = [
|
|
"# Changelog\n",
|
|
"\n",
|
|
"Histórico particionado el 2026-05-19 por proyecto/intención. Cada\n",
|
|
"archivo bajo `docs/changelog/` consolida las entradas de un\n",
|
|
"subdirectorio del workspace.\n",
|
|
"\n",
|
|
]
|
|
for proj in sorted(buckets.keys()):
|
|
n = len(buckets[proj])
|
|
index_lines.append(f"- [`{proj}`](docs/changelog/{proj}.md) — {n} entradas\n")
|
|
CHANGELOG.write_text("".join(index_lines))
|
|
print(f"\nCHANGELOG.md reescrito como índice ({len(buckets)} proyectos)")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|