Skip to content

Claude/setup project structure 3 yei t#3

Merged
MacFall7 merged 7 commits into
mainfrom
claude/setup-project-structure-3YeiT
May 8, 2026
Merged

Claude/setup project structure 3 yei t#3
MacFall7 merged 7 commits into
mainfrom
claude/setup-project-structure-3YeiT

Conversation

@MacFall7
Copy link
Copy Markdown
Owner

@MacFall7 MacFall7 commented May 8, 2026

Decisions noted. Phase 2 plan locked:

  • Commit 1: chore: phase 2 blueprint correction (CLAUDE.md, porting-notes, architecture, posture-and-hooks, README, RECEIPTS halt+resolution opening)
  • Commit 2: feat: Posture enum + __all__ extension
  • Commit 3: feat: pydantic v2 manifest schema
  • Commit 4: feat: classifier with Decision dataclass
  • Commit 5: test: authored fixtures, parametrized parity, hypothesis property tests (≥1000 examples)
  • Commit 6: release: bump to v0.2.0a0 + Phase 2 exit receipt

Posture values from posture-and-hooks.md are pinned: INTERACTIVE, AUTONOMOUS, DRY_RUN, LOCKED — proceeding without halting on the secondary gate.

claude added 7 commits May 8, 2026 23:25
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.
Closed StrEnum with four members pinned by docs/concepts/posture-and-hooks.md:
INTERACTIVE / AUTONOMOUS / DRY_RUN / LOCKED. Added to spine_lite.__all__
under the Phase 2 sub-option (a) decision recorded in RECEIPTS.md.

Phase 3 will add the transition functions; the enum is what the manifest
schema validates against in commit 3.
ToolDefinition (frozen, extra="forbid") declares a tool's name, optional
description, non-empty effects tuple, optional permitted_postures, an
operator-confirmation flag, and free-form metadata. Effects and postures
are canonicalised on construction — deduplicated and sorted by enum
declaration order — so JSON round-trip is byte-stable across runs and
platforms.

Manifest holds the dict[str, ToolDefinition] with a validator that
enforces name == key. parse_manifest() wraps pydantic.ValidationError as
ManifestError so callers catch a single typed exception rooted at
SpineLiteError. Accepts dicts, JSON strings, or JSON bytes.

Manifest, ToolDefinition, parse_manifest added to __all__. Tests cover
canonicalisation, frozen-model immutability, schema rejection
(unknown effects, unknown postures, extra fields, name/key mismatch,
empty effects, empty postures), JSON round-trip, and byte-stable
serialisation.
classify(tool_call, manifest) -> Decision is a pure function: same
input, same output, every time. ToolCall and Decision are frozen +
slotted + kw-only dataclasses. The Decision carries the tool name, a
canonical effects tuple (PRECEDENCE-ordered, byte-stable), the dominant
class, and a deterministic rationale string.

Tool not declared → ManifestError. Tool declared → Decision with the
manifest's stored effects. Phase 2 doesn't refine on the tool call's
arguments — manifest is the spec; argument-aware classification is a
later phase if needed.

ToolCall, Decision, classify added to __all__. Tests cover the happy
paths, dominance, canonical ordering, byte-stable rationale, frozen
immutability, and the undeclared-tool error path. Module remains pure;
Manifest import is TYPE_CHECKING-only to keep the import graph clean.
…ties

Four authored fixtures in tests/fixtures/:
- manifest_minimal.json     — single READ tool
- manifest_basic.json       — six tools across the taxonomy with postures
- manifest_full.json        — all 6 effects, all 4 postures, metadata
- decisions_basic.json      — six expected (call, decision) pairs

Parametrized tests confirm every fixture loads and round-trips JSON
byte-stably (parse → dump → parse → dump → equal). Decision parity test
walks each case in decisions_basic.json against manifest_basic.json and
asserts effects + most_restrictive match.

Hypothesis property tests at 1,000 examples each cover:
- determinism: classify(call, manifest) yields the same Decision every call
- dominance: most_restrictive is in the effects tuple
- manifest fidelity: Decision.effects == ToolDefinition.effects
- byte-stable rationale
- round-trip stability: classify(call, M) == classify(call, parse(M.dump()))
- argument independence: arguments don't influence Phase 2 classification

mypy override added for tests.* to disable disallow_untyped_decorators —
hypothesis's @given/@settings don't satisfy strict-decorator typing.
Runtime modules stay strict. 99 tests passing, 100% coverage on every
runtime module.
Version bumped in pyproject.toml and src/spine_lite/__init__.py; smoke
test pinned to 0.2.0a0. CHANGELOG [0.2.0a0] section enumerates Posture,
manifest, classifier, fixtures + property tests, the sibling-vs-parity
reframing, and the docs-site moves. README status grid marks Phase 2
shipped. New docs/history/phase-2.md narrates the build (commit timeline,
design choices recorded, verification, exit gate). RECEIPTS.md gains the
Phase 2 exit receipt with the full gate table. mkdocs nav extended to
include the Phase 2 history page.

11 of 11 exit-gate items clear in the sandbox; CI verification on push
remains operator-side. Phase 3 gated on operator go.
@MacFall7 MacFall7 merged commit e5e37bf into main May 8, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants