Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ pytest test_stop_machine.py -v
- All transitions explicit
- RED is terminal

## Docs

- [Geometry Export Spec v0.1](docs/geometry_export_spec_v0.1.md) — log schema, artefact paths, and determinism rules for Geometry Layer v0 (experimental, analysis-only)


## License

MIT
114 changes: 114 additions & 0 deletions docs/GEOMETRY_LAYER_V0_FIT_REPORT_dddc878.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Geometry Layer v0 — Build Fit Report

> **Repo:** LalaSkye/stop-machine
> **Commit pin:** dddc878
> **Date:** 2026-02-23
> **Status:** OK TO PROCEED
> **Scope:** NON_EXEC (design + integration check only)

---

## 1. Repo Layout (Actual @ dddc878)

```
stop-machine/
├── .github/workflows/ci.yml
├── examples/ (5 demo scripts)
├── primitives/
│ ├── ambiguity-detector/ (detector.py, test_detector.py)
│ ├── authority-gate-v0/ (STUB — raises RuntimeError)
│ ├── consistency-tester/ (tester.py, test_tester.py)
│ ├── envelope-gate/ (gate.py, rules.py, envelope_parser.py, cli.py, tests, conftest)
│ ├── invariant-lock/ (invariant_lock.py, test_invariant_lock.py)
│ ├── no-optimisation-wrapper/ (wrapper.py, test_wrapper.py)
│ └── stop-machine-v0/ (STUB — raises RuntimeError)
├── ALVIANTECH_COMMS_CENTER_v0.1.md
├── CANONICAL.md
├── GATE_LOG_v0.1.md
├── LICENSE (MIT)
├── README.md
├── stop_machine.py
└── test_stop_machine.py
```

**Key facts:**
- Pure Python, no packaging (no pyproject.toml, setup.cfg, requirements.txt)
- Only dependency: pytest (pip install pytest)
- No `__init__.py` anywhere; imports use `importlib.util.spec_from_file_location`
- No existing `docs/`, `analysis/`, or `scripts/` directories
- Two v0 stub folders raise RuntimeError on import; CI drift alarms enforce this

---

## 2. CI Structure (Actual)

Single workflow: `.github/workflows/ci.yml`
- Trigger: push/PR to main
- Matrix: Python 3.10, 3.11, 3.12 on ubuntu-latest
- Steps: checkout, setup-python, pip install pytest, 2 drift alarms (grep), run primitive tests, run root tests
- No artefact uploads; no continue-on-error jobs; everything gating
- CI status: GREEN on main (54 runs, latest passing in 12s)

---

## 3. Runtime Architecture

- `stop_machine.py`: 3-state FSM (GREEN/AMBER/RED), ~80 LOC, zero imports beyond enum
- `envelope-gate`: Most complex primitive (4 source files, 18 rules, ALLOW/HOLD/DENY/SILENCE exit algebra)
- All primitives: pure functions, frozen dataclasses, deterministic, no side effects
- Import pattern: `_load_local()` via importlib; sys.modules collision risk documented in conftest.py

---

## 4. Proposed Slot-In Paths

| Addition | Path | Rationale |
|----------|------|-----------|
| Analysis code | `analysis/` (new top-level) | No collision; not importable by runtime |
| Geometry spec | `docs/geometry_export_spec_v0.1.md` | Establishes docs/ pattern |
| Fit report | `docs/GEOMETRY_LAYER_V0_FIT_REPORT_dddc878.md` | This file |
| Adversarial tests | `primitives/envelope-gate/test_envelope_gate_adversarial.py` | Discovered by existing `pytest primitives -v` |
| Log schema | Defined in docs spec; emitted as JSONL | Separate from existing Markdown gate log |
| CI job | `geometry-analysis` in ci.yml | First non-gating job; first artefact upload |

---

## 5. Conflicts and Resolutions

| Conflict | Resolution |
|----------|------------|
| No docs/ folder exists | Creating it establishes the pattern cleanly |
| Existing Markdown gate log vs JSONL | Geometry logs are entirely separate path + format |
| sys.modules collision risk | Analysis operates on emitted logs only; if must load runtime, use unique module names |
| No continue-on-error precedent | geometry-analysis job will be documented as first non-gating job |
| No artefact upload precedent | Define canonical path in spec before first use |

---

## 6. Risk List

1. **Import collision via _load_local**: Analysis must not use bare module names like "gate" or "rules"
2. **Logging failures changing behaviour**: Emission wrapped in try/except; failure = no log, not altered gate result
3. **CI brittleness**: Missing logs treated as "no data"; geometry job uses continue-on-error
4. **Packaging leak**: No packaging exists currently; if added later, exclude analysis/
5. **Markdown log contamination**: Geometry JSONL uses completely separate path from GATE_LOG_v0.1.md

---

## 7. Absolute Invariants (Must Hold)

- No change to ALLOW/HOLD/DENY/SILENCE exit algebra
- Runtime code never imports from analysis/, docs/, or artifacts/
- Logging is side-effect free; absence of logs changes nothing
- CI geometry job is non-gating (continue-on-error: true)
- Deterministic output: same input = byte-identical JSONL

---

## 8. Verdict

**OK TO PROCEED.** No HOLD conditions triggered.

---

**END — GEOMETRY_LAYER_V0_FIT_REPORT_dddc878**
159 changes: 159 additions & 0 deletions docs/geometry_export_spec_v0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Geometry Export Spec v0.1

> **Repo:** LalaSkye/stop-machine
> **Commit pin:** dddc878
> **Status:** DRAFT
> **Scope:** Analysis-only instrumentation (no runtime semantic change)
> **MCCS dependency:** None

---

## 1. Purpose

Define the log schema, artefact path conventions, and determinism rules
for Geometry Layer v0. This layer emits structured events from the
envelope-gate conformance checker to enable offline transition-graph
reconstruction and optionality analysis.

**This spec covers logging and observability only. It does not change
ALLOW / HOLD / DENY / SILENCE outcomes.**

---

## 2. Artefact Path Convention

```
artifacts/geometry/v0/stop-machine/dddc878/${RUN_ID}/
```

- In CI: `RUN_ID = ${{ github.run_id }}`
- Local runs: `RUN_ID = "local"`

All artefacts within a run are JSON Lines (`.jsonl`) files.

---

## 3. Log Format

- **Format:** JSON Lines (one JSON object per line)
- **Encoding:** UTF-8
- **Key ordering:** Canonical (sorted keys via `json.dumps(sort_keys=True)`)
- **Timestamps:** No wall-clock timestamps. Use monotonic integer counter
or omit entirely. Analysis scripts may add external timestamps.

---

## 4. Event Schema (v0.1)

Each line in a `.jsonl` file MUST be a valid JSON object conforming to:

```json
{
"schema_version": "0.1",
"primitive": "envelope-gate",
"event": "gate_evaluated",
"envelope_id": "<string|null>",
"exit": "ALLOW|HOLD|DENY|SILENCE",
"violations": ["R0_MISSING_HEADER", "ENUM_INVALID_SENDER"],
"input_hash": "<sha256 hex digest>",
"result_hash": "<sha256 hex digest>"
}
```

### Field definitions

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `schema_version` | string | yes | Always `"0.1"` for this spec version |
| `primitive` | string | yes | Primitive that emitted the event |
| `event` | string | yes | Event type identifier |
| `envelope_id` | string or null | yes | `msg_id` from the envelope, or null |
| `exit` | string | yes | Gate exit decision (ALLOW/HOLD/DENY/SILENCE) |
| `violations` | array of strings | yes | Violation code identifiers (may be empty) |
| `input_hash` | string | yes | SHA-256 hex digest of canonical envelope raw text |
| `result_hash` | string | yes | SHA-256 hex digest of canonical result fields |

### Hashing rules

- `input_hash`: `sha256(envelope.raw.encode("utf-8")).hexdigest()`
- `result_hash`: `sha256(canonical_result_string.encode("utf-8")).hexdigest()`
where `canonical_result_string = json.dumps({"exit": exit, "violations": sorted_violations}, sort_keys=True)`

---

## 5. Emission Rules

- Emission is **OFF by default**.
- Enabled only when the environment variable `GEOMETRY_LOG_PATH` is set
to a writable file path.
- All writes are append-only.
- Emission is wrapped in `try/except Exception: pass`.
- If the path is invalid or the write fails: **do nothing**.
- Absence of logs MUST NOT change gate behaviour.

---

## 6. Determinism Requirements

- Same envelope raw text, same rules, same commit = identical JSONL output.
- No wall-clock time in emitted events.
- Key ordering is canonical (sorted).
- Violation lists are sorted.
- Hashes are computed from canonical representations.
- Replaying the same inputs twice MUST produce byte-identical JSONL.

---

## 7. Transition Graph Reconstruction (Analysis-Only)

Analysis scripts in `analysis/` may reconstruct a transition graph from
collected JSONL events:

- Each `gate_evaluated` event represents a node (state) and edge
(transition from input to exit decision).
- `|Omega(t)|` (reachable state count) is a candidate measure computed
offline from the collected graph.
- Interpretation of `|Omega(t)|` is **out of scope for v0**.

---

## 8. Runtime / Non-Runtime Boundary

| Path | Classification | May import from runtime? |
|------|---------------|-------------------------|
| `stop_machine.py` | Runtime | N/A |
| `primitives/**/*.py` | Runtime | N/A |
| `analysis/**` | Non-runtime | Yes (by file path only) |
| `docs/**` | Non-runtime | No |
| `artifacts/**` | Non-runtime | No |
| `examples/**` | Non-runtime | No |

**Runtime code MUST NOT import from analysis/, docs/, or artifacts/.**

If analysis code must load runtime modules, it MUST use file-path-based
loading with unique module names to avoid `sys.modules` collisions:
`module_name = "geom_" + sha256(path)[:12]`

---

## 9. CI Integration

- A `geometry-analysis` CI job runs after tests.
- It MUST use `continue-on-error: true` and `if: always()`.
- It uploads artefacts from `artifacts/geometry/**`.
- It does NOT gate merges.

---

## 10. What This Spec Does NOT Cover

- MCCS API hooks or certification handshake
- Metric branding or wrapper-vs-substrate equivalence
- FOI-specific reporting
- Any change to exit algebra or decision mapping

Those remain downstream and will reference this spec if needed.

---

**END — geometry_export_spec_v0.1**