A log of design decisions made in this repository and any intentional divergences from earlier-stated specs. Append-only. When two implementations of related ideas look different, the entry on this page explains why.
The repository MacFall7/M87-Spine-lite is a Python governance framework that addresses a related but different problem: deterministic classification of Claude Code shell commands. Its taxonomy is six classes drawn on the shell-vs-file axis (SAFE_READ, SHELL_SAFE, SHELL_MUTATING, SCOPED_WRITE, RESTRICTED_WRITE, SHELL_DANGEROUS) with numeric risk-delta scores and a five-step ordered match pipeline (deny list → network egress → safe → mutating → fail-closed default).
spine-lite-python is a sibling implementation, not a port. Its taxonomy is six classes drawn on the state × boundary × reversibility axes (READ, WRITE, NETWORK, EXECUTE, SPAWN, DESTRUCTIVE) with ordinal precedence and a most_restrictive collapse function. It is designed to classify any LLM tool call, not only bash commands.
The two taxonomies are categorically different — neither maps cleanly onto the other:
- The sibling distinguishes
SAFE_READ(file read) fromSHELL_SAFE(read-only shell command);spine-lite-pythoncollapses both intoREAD/EXECUTEbased on whether a subprocess was invoked. spine-lite-pythoncarves outNETWORKas its own class; the sibling rolls outbound network calls intoSHELL_DANGEROUSvia the deny-list step.- The sibling encodes risk numerically (0.00 to 0.10);
spine-lite-pythonencodes dominance ordinally and resolves throughPRECEDENCE. spine-lite-python's invariants inCLAUDE.mdare about implementation discipline (purity, type strictness, public API gates); the sibling's invariants are about governance philosophy (separation of proposal from execution, model interchangeability, narrative-vs-runtime separation).
Both designs are coherent for their respective scopes. spine-lite-python's scope is broader (any tool call, not just bash) and its invariants are canonical for this repository.
This entry records the §9 halt that opened Phase 2 and its resolution.
Probed the sibling repository for the manifest schema and classifier logic referenced as the "TS reference" by the original blueprint. Findings:
- The sibling repository is publicly accessible and is implemented in Python, not TypeScript. The blueprint's "TS reference" framing is stale.
- Its six-class taxonomy is categorically different from what shipped in Phase 1. The taxonomies are not relabelings of each other; they draw axes on different dimensions.
- Phase 1 had already shipped
v0.1.0a0underspine-lite-python's action-centric taxonomy with operator sign-off. Re-aligning to the sibling's taxonomy would invalidate the public release and rewrite the docs site.
Phase 2 proceeds with spine-lite-python as canonical:
- Sibling project is informational. Citable in this file but not a parity target. Parity tests in Phase 2 round-trip authored fixtures with byte-stability invariants; they do not cross-check against external fixtures.
- Posture enum lands in Phase 2. One-line
__all__extension so the manifest schema can validate posture constraints against a closed enum. Members and string values are pinned bydocs/concepts/posture-and-hooks.md:INTERACTIVE,AUTONOMOUS,DRY_RUN,LOCKED. - Blueprint corrections.
CLAUDE.mdrewords the mission to drop the "TS reference" framing. This page reframes from "translation log" to "design history."
The §9 halt and this resolution are mirrored in RECEIPTS.md as the Phase 2 Day 1 opening entry.
The closed six-class effects taxonomy and precedence ordering were authored from the architectural invariants in CLAUDE.md. The local pre-staged scaffold referenced in the original migration brief did not exist, so the entire Phase 1 scaffold was authored from spec.
The taxonomy READ / WRITE / NETWORK / EXECUTE / SPAWN / DESTRUCTIVE and the precedence ordering DESTRUCTIVE > SPAWN > EXECUTE > NETWORK > WRITE > READ are spine-lite-python's spec, not derived from any external repository.
Even though this isn't a port, the language and library choices are worth pinning:
from __future__ import annotationsat the top of every module. PEP 563 stringified annotations +if TYPE_CHECKING:guards for cycle-prone imports.- Frozen, slotted, kw-only dataclasses for value types.
@dataclass(frozen=True, slots=True, kw_only=True). StrEnumfor closed enumerations.Effect(StrEnum)and (Phase 2)Posture(StrEnum).- Pydantic v2 for the manifest schema. Fast Rust-backed validation, JSON round-trip,
model_config = ConfigDict(frozen=True, extra="forbid")for immutability and strictness.
Once a design decision or divergence is settled, it stays in this file forever. Don't delete entries when implementations evolve — annotate them with the convergence date instead. The archive is the value.
- Architecture — the design this repository follows.
- Invariants — the rules nothing in this repo gets to break.
- Sibling project: MacFall7/M87-Spine-lite.