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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ body:
id: version
attributes:
label: MARGINAL version
placeholder: "0.3.2"
placeholder: "0.3.3"
validations:
required: true
- type: input
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to MARGINAL are documented here. The project follows Semanti

## [Unreleased]

## [0.3.3] - 2026-08-13

### Fixed

- native hook and control launchers now replace an incompatible `python3` (including macOS Xcode
Python 3.9) with an available Python 3.10–3.13 interpreter;
- marketplace smoke now invokes the exact public `python3` launcher path and records its version,
preventing isolated test environments from masking interpreter-selection failures.

## [0.3.2] - 2026-08-13

### Added
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "MARGINAL: Economically Disciplined Compute Allocation for AI Agents"
type: software
authors:
- name: SignalLayer Labs
version: 0.3.2
version: 0.3.3
date-released: 2026-08-13
license: Apache-2.0
repository-code: "https://github.com/SignalLayerLabs/Marginal"
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ codex plugin marketplace add SignalLayerLabs/Marginal --ref main && codex plugin

Then open `/hooks` in Codex, review the exact commands, and grant trust only after inspection.
MARGINAL never bypasses the hook trust boundary. No Python package or global executable is needed.
In Codex, ask the bundled skill directly:
One local Python 3.10–3.13 interpreter is required; the launcher finds it automatically even when
`python3` points to an older macOS/Xcode runtime. In Codex, ask the bundled skill directly:

```text
Use $marginal to report whether a live hook service is active, whether hooks were observed, and whether this repository is in Shadow Mode or Tool Enforcement.
Expand All @@ -237,7 +238,7 @@ marginal install codex
Current tagged library install target:

```bash
pip install "marginal-ai @ git+https://github.com/SignalLayerLabs/Marginal.git@v0.3.2"
pip install "marginal-ai @ git+https://github.com/SignalLayerLabs/Marginal.git@v0.3.3"
```

Development checkout:
Expand Down
2 changes: 1 addition & 1 deletion codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"codeRepository": "https://github.com/SignalLayerLabs/Marginal",
"issueTracker": "https://github.com/SignalLayerLabs/Marginal/issues",
"license": "https://spdx.org/licenses/Apache-2.0",
"version": "0.3.2",
"version": "0.3.3",
"datePublished": "2026-08-06",
"programmingLanguage": "Python",
"runtimePlatform": "Python 3.10-3.13",
Expand Down
4 changes: 4 additions & 0 deletions docs/integrations/codex.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Open `/hooks` in Codex and inspect the four MARGINAL lifecycle commands before g
plugin never uses the bypass-trust flag. Until trust and runtime coverage are observed, MARGINAL is
unobserved or Shadow-only; lack of evidence alone does not prove that hooks are disabled.

The bundle has no third-party Python dependency, but requires one local Python 3.10–3.13 runtime.
Its launchers automatically select a compatible version even when `python3` resolves to macOS/Xcode
Python 3.9. If none is available, control commands return the exact requirement and hooks fail open.

An installed Python package can perform the same native transaction:

```bash
Expand Down
16 changes: 9 additions & 7 deletions docs/operations/codex-plugin-submission.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
```text
status: not_submitted
status_date: 2026-08-13
plugin_version: 0.3.2
plugin_version: 0.3.3
marketplace_selector: marginal@marginal
portal_submission_type: skills_only_zip
portal_access: authentication_required
Expand Down Expand Up @@ -32,9 +32,9 @@ and permits repository Tool Enforcement only after a versioned evidence gate pro
reviewed false stops, and governance overhead. It never reads prompts, source, raw commands, raw
outputs, transcripts, or Codex credentials for evidence.

**Release notes:** Adds a dependency-free native control plane, repository-scoped hook attestation,
local Shadow Mode, review workflow, Earned Enforcement gates, fail-open demotion, production logo,
eight reviewer cases, and a reproducible v0.3.2 archive.
**Release notes:** Adds automatic compatible-Python discovery, a dependency-free native control
plane, repository-scoped hook attestation, local Shadow Mode, review workflow, Earned Enforcement
gates, fail-open demotion, production logo, eight reviewer cases, and a reproducible v0.3.3 archive.

Starter prompts are the three `interface.defaultPrompt` entries in
`plugins/marginal/.codex-plugin/plugin.json`. The production logo is
Expand Down Expand Up @@ -63,14 +63,16 @@ coverage or identity changes.
- [x] Official plugin validator passes.
- [x] Skill validator passes.
- [x] Isolated Codex 0.147.0 marketplace add/install/remove smoke passes.
- [x] Public `python3` launcher smoke passes from macOS/Xcode Python 3.9.6 by selecting a compatible
bundled-runtime interpreter.
- [x] Four-event direct lifecycle smoke passes with 100% exercised coverage.
- [x] Secret-marker scan returns zero persisted occurrences.
- [x] Reproducible smoke evidence is committed with runtime SHA-256 provenance.
- [x] Privacy, terms, support, and eight reviewer cases exist.
- [ ] Canonical main contains v0.3.2 after merge and every public Pages URL resolves.
- [ ] Canonical main contains v0.3.3 after merge and every public Pages URL resolves.
- [x] A deterministic single-root ZIP builder covers the manifest, skill, hooks, runtime, and logo.
- [ ] SignalLayer Labs identity and Apps Management write permission are confirmed in Platform.
- [ ] The v0.3.2 archive is uploaded in Platform and external review is started.
- [ ] The v0.3.3 archive is uploaded in Platform and external review is started.

Build the exact upload artifact with:

Expand All @@ -89,4 +91,4 @@ verified SignalLayer Labs identity; none can be inferred from repository or GitH
external identifier, credential, or reviewer correspondence belongs in this repository.

Acceptance evidence:
[`codex-plugin-smoke-2026-08-13-v0.3.2.json`](evidence/codex-plugin-smoke-2026-08-13-v0.3.2.json).
[`codex-plugin-smoke-2026-08-13-v0.3.3.json`](evidence/codex-plugin-smoke-2026-08-13-v0.3.3.json).
2 changes: 1 addition & 1 deletion docs/operations/codex-plugin-test-cases.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema_version": 1,
"plugin_version": "0.3.2",
"plugin_version": "0.3.3",
"positive": [
{
"id": "positive-shadow-status",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"codex_version": "codex-cli 0.147.0",
"completed_sessions": 1,
"directory_archive_sha256": "42edc01ce21753ce9676426f6d89b0a249539545df0d3c2073c1c060e1b39f7b",
"evidence_records": 4,
"hook_coverage": 1.0,
"installed": true,
"launcher_python_version": "Python 3.9.6",
"marketplace_selector": "marginal@marginal",
"native_control_mode": "shadow",
"native_control_observed": true,
"plugin_version": "0.3.3",
"raw_secret_occurrences": 0,
"removed": true,
"runtime_sha256": "9843b084dd481f29762870e6e6f79a301bdd9c15b7a8c2dc1c4104abc332b259",
"shadow_block_count": 0
}
2 changes: 1 addition & 1 deletion plugins/marginal/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "marginal",
"version": "0.3.2",
"version": "0.3.3",
"description": "Evidence-gated compute governance for Codex, local-first and Shadow Mode by default.",
"author": {
"name": "SignalLayer Labs",
Expand Down
Binary file modified plugins/marginal/runtime/marginal_runtime.pyz
Binary file not shown.
2 changes: 1 addition & 1 deletion plugins/marginal/runtime/provenance.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"builder":"scripts/build_codex_plugin.py","python_requires":">=3.10","schema_version":1,"sha256":"7ea67b6a17d8f44c03b70e29ec29497a00edd0f9c4262e59cb9082f2015eafe6","source_hash":"ab9dfa18a1ddf72f65a64cc7aba86ca0bd1b4e79e0747c983078e5b8ee87e042"}
{"builder":"scripts/build_codex_plugin.py","python_requires":">=3.10","schema_version":1,"sha256":"9843b084dd481f29762870e6e6f79a301bdd9c15b7a8c2dc1c4104abc332b259","source_hash":"081703fe680da21b5d261dc1828071f8667c73ed74afe58399b33a25cf98360e"}
11 changes: 9 additions & 2 deletions plugins/marginal/scripts/marginal_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import sys
from pathlib import Path

from runtime_python import compatible_python


def _plugin_data() -> Path:
configured = os.environ.get("PLUGIN_DATA")
Expand Down Expand Up @@ -37,6 +39,11 @@ def main(argv: list[str] | None = None) -> int:
if not runtime.is_file():
print(f"MARGINAL runtime not found: {runtime}", file=sys.stderr)
return 1
try:
python = compatible_python()
except RuntimeError as exc:
print(str(exc), file=sys.stderr)
return 1

data = _plugin_data()
data.mkdir(parents=True, exist_ok=True, mode=0o700)
Expand All @@ -48,9 +55,9 @@ def main(argv: list[str] | None = None) -> int:
environment["PLUGIN_DATA"] = str(data)
environment["PLUGIN_ROOT"] = str(plugin_root)
os.execve(
sys.executable,
python[0],
[
sys.executable,
*python,
str(runtime),
"codex",
arguments[0],
Expand Down
9 changes: 7 additions & 2 deletions plugins/marginal/scripts/marginal_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from __future__ import annotations

import os
import sys
from pathlib import Path

from runtime_python import compatible_python


def main() -> int:
plugin_root = os.environ.get("PLUGIN_ROOT")
Expand All @@ -16,14 +17,18 @@ def main() -> int:
runtime = Path(plugin_root).resolve() / "runtime" / "marginal_runtime.pyz"
if not runtime.is_file():
return 0
try:
python = compatible_python()
except RuntimeError:
return 0
environment = {
name: value
for name in ("PATH", "LANG", "LC_ALL", "SYSTEMROOT")
if (value := os.environ.get(name)) is not None
}
environment["PLUGIN_DATA"] = str(Path(plugin_data).resolve())
environment["PLUGIN_ROOT"] = str(Path(plugin_root).resolve())
os.execve(sys.executable, [sys.executable, str(runtime)], environment)
os.execve(python[0], [*python, str(runtime)], environment)
return 0


Expand Down
63 changes: 63 additions & 0 deletions plugins/marginal/scripts/runtime_python.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Select a Python interpreter compatible with the bundled MARGINAL runtime."""

from __future__ import annotations

import os
import shutil
import subprocess
import sys

_MINIMUM_VERSION = (3, 10)
_VERSIONED_NAMES = ("python3.13", "python3.12", "python3.11", "python3.10")


def _probe(command: tuple[str, ...]) -> bool:
environment = {
name: value
for name in ("PATH", "SYSTEMROOT")
if (value := os.environ.get(name)) is not None
}
environment["PYTHONNOUSERSITE"] = "1"
try:
completed = subprocess.run(
[
*command,
"-I",
"-c",
"import sys; raise SystemExit(sys.version_info < (3, 10))",
],
check=False,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
env=environment,
timeout=2,
)
except (OSError, subprocess.TimeoutExpired):
return False
return completed.returncode == 0


def compatible_python() -> tuple[str, ...]:
"""Return an executable command for Python 3.10+ without importing user packages."""

if sys.version_info[:2] >= _MINIMUM_VERSION:
return (sys.executable,)

for name in _VERSIONED_NAMES:
executable = shutil.which(name)
if executable:
return (executable,)

if os.name == "nt":
launcher = shutil.which("py")
if launcher:
for version in ("-3.13", "-3.12", "-3.11", "-3.10"):
command = (launcher, version)
if _probe(command):
return command

python3 = shutil.which("python3")
if python3 and _probe((python3,)):
return (python3,)
raise RuntimeError("MARGINAL requires Python 3.10 or newer")
2 changes: 2 additions & 0 deletions plugins/marginal/skills/marginal/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Do not require a global `marginal` executable or a pip installation. Resolve the

Pass `--workspace <repository>` and `--json` when inspecting repository-scoped state. The launcher
uses Codex's native plugin data directory, so hook evidence and control commands share one state.
It automatically replaces an older `python3` with an available Python 3.10–3.13 interpreter. If
none is installed, report that exact runtime requirement and do not claim hooks are operational.

## Workflow

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "marginal-ai"
version = "0.3.2"
version = "0.3.3"
description = "Universal learning-loop and compute-governance foundation for economically disciplined AI agents."
readme = "README.md"
requires-python = ">=3.10"
Expand Down
9 changes: 6 additions & 3 deletions scripts/smoke_codex_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import json
import os
import subprocess
import sys
import time
from dataclasses import asdict, dataclass
from pathlib import Path
Expand All @@ -23,6 +22,7 @@ class CodexPluginSmokeResult:
completed_sessions: int
native_control_observed: bool
native_control_mode: str
launcher_python_version: str
raw_secret_occurrences: int
removed: bool
codex_version: str
Expand Down Expand Up @@ -131,6 +131,8 @@ def smoke_plugin(
}
_initialize_repository(workspace, environment)
version = _run([str(codex), "--version"], environment=environment, cwd=root).stdout.strip()
launcher = _run(["python3", "--version"], environment=environment, cwd=root)
launcher_python_version = (launcher.stdout or launcher.stderr).strip()
_run(
[str(codex), "plugin", "marketplace", "add", str(marketplace), "--json"],
environment=environment,
Expand Down Expand Up @@ -161,7 +163,7 @@ def smoke_plugin(
try:
for payload in _hook_payloads(workspace, secret):
result = _run(
[sys.executable, str(hook_script)],
["python3", str(hook_script)],
environment=hook_environment,
cwd=workspace,
input_text=json.dumps(payload),
Expand All @@ -177,7 +179,7 @@ def smoke_plugin(
time.sleep(0.02)
control = _run(
[
sys.executable,
"python3",
str(plugin_root / "scripts" / "marginal_control.py"),
"status",
"--workspace",
Expand Down Expand Up @@ -219,6 +221,7 @@ def smoke_plugin(
),
native_control_observed=native_control_observed,
native_control_mode=native_control_mode,
launcher_python_version=launcher_python_version,
raw_secret_occurrences=_count_secret(plugin_data, secret),
removed=removed,
codex_version=version,
Expand Down
2 changes: 1 addition & 1 deletion src/marginal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,4 @@
"validate_safe_telemetry_record",
]

__version__ = "0.3.2"
__version__ = "0.3.3"
2 changes: 1 addition & 1 deletion src/marginal/integrations/codex/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .installer import CommandRunner, SubprocessRunner, inspect_codex
from .promotion import PromotionIdentity

PLUGIN_VERSION = "0.3.2"
PLUGIN_VERSION = "0.3.3"
ADAPTER_VERSION = "1"
POLICY_HASH = hashlib.sha256(b"marginal:no-progress:v1:max-same-evidence=2").hexdigest()
DEFAULT_HOOK_HASH = "46b7a85a3a542957d055c615ab501f9fee284bb3193ac9ecfbe8951cce5a9942"
Expand Down
1 change: 1 addition & 0 deletions tests/integrations/codex/test_marketplace_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ def test_marketplace_install_and_remove(tmp_path: Path) -> None:
assert result.completed_sessions == 1
assert result.native_control_observed is True
assert result.native_control_mode == "shadow"
assert result.launcher_python_version.startswith("Python 3.")
assert result.raw_secret_occurrences == 0
assert result.removed is True
Loading