You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore: phase 2 blueprint correction — sibling, not parity target
Probe of MacFall7/M87-Spine-lite found a sibling Python project with a
categorically different six-class taxonomy (SAFE_READ/SHELL_*/SCOPED_WRITE/
RESTRICTED_WRITE/SHELL_DANGEROUS on shell-vs-file lines with numeric risk
scores and a 5-step pipeline). spine-lite-python's taxonomy stays
canonical: state × boundary × reversibility axes with ordinal precedence,
authored from spec.
CLAUDE.md mission reworded; halt + operator resolution appended verbatim
to RECEIPTS.md as the Phase 2 day 1 opening entry; porting-notes reframed
from translation log to design history; surgical edits across nine docs
pages drop the stale TS-reference framing. Posture enum members pinned
in posture-and-hooks.md ahead of the Phase 2 ship.
Copy file name to clipboardExpand all lines: CLAUDE.md
+4-5Lines changed: 4 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ Operating manual for Claude Code sessions in this repo.
4
4
5
5
## Mission
6
6
7
-
Python port of M87-Spine-lite (TypeScript). Deterministic policy and effects runtime for LLM tool calls. Public API and observable semantics must mirror the TypeScript reference within the closed six-class taxonomy.
7
+
Deterministic policy and effects runtime for LLM tool calls. Public API and observable semantics are defined by the architectural invariants below; the sibling project at [MacFall7/M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite) is informational and not a parity target. See `docs/explanation/porting-notes.md` for the relationship.
8
8
9
9
## Authority
10
10
@@ -19,7 +19,6 @@ Mac decides — halt and ask:
19
19
- Anything in `src/spine_lite/__init__.py`'s `__all__`.
20
20
- New dependencies beyond `pyproject.toml`.
21
21
- Phase boundary transitions (1→2, 2→3).
22
-
- Semantic divergence from the TypeScript reference.
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@
7
7
8
8
Deterministic policy and effects runtime for LLM tool calls.
9
9
10
-
A Python port of [M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite). Same closed effects taxonomy, same precedence rules, same posture state machine — typed, tested, packaged.
10
+
Six-class effects taxonomy on state × boundary × reversibility axes. Ordinal precedence. Content-addressable receipts. Wires into Claude Code as a PreToolUse hook (Phase 3); usable anywhere you can shell out to a subprocess. Sibling project to [M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite) — see [Porting Notes](docs/explanation/porting-notes.md) for the relationship.
- None. Phase 2 (manifest + classifier, ~5 working days, target `v0.2.0a0`) is gated on operator go per `CLAUDE.md`.
113
113
114
114
**Next:** Halt for Mac at the Phase 1 → Phase 2 transition. Per blueprint §11, completion of Phase 1 unblocks the Braintrust application thread on the operator's side.
115
+
116
+
---
117
+
118
+
### Phase 2 Day 1 Opening — 2026-05-08
119
+
120
+
Phase 2 opened with a §9 halt. The halt and the operator's resolution are recorded here verbatim for the run-registry trail.
121
+
122
+
**§9 HALT (verbatim):**
123
+
124
+
```
125
+
HALT: Reference repo's spec diverges from Phase 1's invariants in ways that make
126
+
a straight parity port mechanically impossible.
127
+
128
+
Context:
129
+
- The blueprint and CLAUDE.md describe a "TS reference" at MacFall7/M87-Spine-lite.
130
+
- WebFetch confirms the repo exists and is public, but it's implemented in Python
131
+
(hooks/guard.py, hooks/governor.py), not TypeScript. The "TS reference" framing
132
+
in the blueprint is stale.
133
+
- Bigger issue: the reference's six-class taxonomy is *categorically different*
5-step pipeline) was reviewed and explicitly not adopted
217
+
218
+
Coverage 100% on manifest.py, classifier.py, posture.py (enum scope only).
219
+
Six-commit Conventional Commits shape preserved (the blueprint correction is
220
+
commit 1, then 5 functional commits).
221
+
222
+
Begin from blueprint correction commit. Halt at exit gate.
223
+
```
224
+
225
+
**What landed in commit 1 of Phase 2:**
226
+
227
+
-`CLAUDE.md` mission rewritten to drop "TS reference" framing; sibling project recorded as informational, not a parity target.
228
+
-`docs/explanation/porting-notes.md` reframed from "translation log" to "design history" with a Sibling Project section, a Phase 2 opening entry recording this halt and resolution, and a Phase 1 entry pinning the taxonomy as `spine-lite-python`'s spec.
229
+
-`docs/concepts/posture-and-hooks.md` updated to remove the "subject to refinement" caveat from the posture table and pin the four members (`INTERACTIVE`, `AUTONOMOUS`, `DRY_RUN`, `LOCKED`) with their string values.
230
+
-`docs/explanation/architecture.md` reference-implementation paragraph rewritten as a sibling-project note.
231
+
-`docs/explanation/faq.md` "Why Python after TypeScript?" question replaced with "How does this relate to M87-Spine-lite?", plus three other in-place corrections.
232
+
-`docs/concepts/effects-taxonomy.md`, `docs/concepts/overview.md`, `docs/how-to/contribute.md`, `docs/how-to/use-the-api.md`, `docs/reference/glossary.md`: surgical edits to drop TS-reference framing.
233
+
-`README.md` and `docs/index.md` headlines reworded: `spine-lite-python` is described directly, sibling project credited but not framed as a port target.
Copy file name to clipboardExpand all lines: docs/concepts/overview.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,7 +38,7 @@ The PreToolUse **hook** is just an I/O wrapper that maps stdin/stdout to and fro
38
38
39
39
## What's closed
40
40
41
-
The effects taxonomy is closed at six classes. Adding a class is a project-level decision that requires updating the precedence ordering, the parity tests against the TypeScript reference, and the docstrings. It is not a runtime extension point.
41
+
The effects taxonomy is closed at six classes. Adding a class is a project-level decision that requires updating the precedence ordering, the parity tests, the porting-notes log, and the docstrings. It is not a runtime extension point.
42
42
43
43
This is a feature, not a limitation. A taxonomy that grows at runtime is a taxonomy that drifts. The six classes were chosen to cover every observable side effect a tool call can produce. If something looks like a seventh class, it's probably an existing class with new arguments.
Copy file name to clipboardExpand all lines: docs/explanation/architecture.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -70,9 +70,11 @@ Adding a class is permitted but expensive. The process is in [Effects Taxonomy /
70
70
71
71
The architecture stays the same across phases. Each phase fills in pure modules that adhere to the same purity contract.
72
72
73
-
## Reference implementation
73
+
## Sibling project
74
74
75
-
The TypeScript reference lives at [MacFall7/M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite). Treat it as the spec for semantic behaviour. Where Python idiom diverges from TypeScript (typing, dataclass shape, exception names), prefer the Python form and document the call in [Porting Notes](porting-notes.md). Anything that changes observable behaviour is a divergence and needs project-level sign-off.
75
+
[MacFall7/M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite) is a Python sibling project: a governance framework for Claude Code shell commands with a different six-class taxonomy drawn on shell-vs-file lines. It's informational and citable, not a parity target. See [Porting Notes](porting-notes.md) for the full relationship.
76
+
77
+
`spine-lite-python`'s spec is canonical and lives in this repository: the architectural invariants in `CLAUDE.md`, the [Invariants](invariants.md) page, and the design rationale recorded as decisions are made.
Copy file name to clipboardExpand all lines: docs/explanation/faq.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Six lines that matter for safety review. `READ` vs. `WRITE` (did anything change
6
6
7
7
## Why is the taxonomy closed?
8
8
9
-
A taxonomy that grows at runtime is a taxonomy that drifts. Adding a class would require updating the precedence ordering, the parity tests against the TypeScript reference, every consumer that exhaustively matches on `Effect`, and every receipt that hashed under the old ordering. The cost is real; the benefit (better fit for one new use case) is local. So: closed by default, with an explicit project-level process for extension.
9
+
A taxonomy that grows at runtime is a taxonomy that drifts. Adding a class would require updating the precedence ordering, the parity tests, the porting-notes log, every consumer that exhaustively matches on `Effect`, and every receipt that hashed under the old ordering. The cost is real; the benefit (better fit for one new use case) is local. So: closed by default, with an explicit project-level process for extension.
10
10
11
11
## Why no LLM calls inside the runtime?
12
12
@@ -16,13 +16,13 @@ The runtime's job is to classify and decide. Calling a model to second-guess tha
16
16
17
17
Receipts are content-addressable. Two operators replaying the same session see byte-identical receipts. That property only holds if the runtime is deterministic — same input → same output, every time. The cost is that wall-clock time can only enter at the I/O boundary (the hook); the benefit is that "what happened?" has a SHA-stable answer.
18
18
19
-
## Why Python after TypeScript?
19
+
## How does this relate to M87-Spine-lite?
20
20
21
-
The TypeScript reference is the spec. The Python port is what you install in environments where Python is already the language of choice — Claude Code agents written in Python, internal CLIs, CI pipelines, Jupyter sessions. Both implementations target the same observable behaviour.
21
+
[MacFall7/M87-Spine-lite](https://github.com/MacFall7/M87-Spine-lite) is a sibling project with a different scope: a governance framework for Claude Code shell commands, with a six-class taxonomy drawn on shell-vs-file lines and numeric risk-delta scores. `spine-lite-python` is broader (any LLM tool call, not just bash) and uses ordinal precedence rather than numeric scores. The two designs are categorically different, not relabelings of each other. See [Porting Notes](porting-notes.md) for the full story.
22
22
23
23
## Why Pydantic v2 for the manifest?
24
24
25
-
Pydantic v2 is the de facto standard for typed Python schemas, has fast Rust-backed validation, and round-trips JSON cleanly. The TypeScript reference uses Zod; Pydantic v2 is the closest match in the Python ecosystem.
25
+
Pydantic v2 is the de facto standard for typed Python schemas, has fast Rust-backed validation, and round-trips JSON cleanly. The frozen + extra-forbid model config gives us schema strictness without writing a custom validator.
26
26
27
27
## What happens when a tool call has no declared effects?
0 commit comments