resultseal 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- resultseal-0.1.1/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- resultseal-0.1.1/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- resultseal-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +31 -0
- resultseal-0.1.1/.github/workflows/ci.yml +44 -0
- resultseal-0.1.1/.github/workflows/publish.yml +61 -0
- resultseal-0.1.1/.gitignore +37 -0
- resultseal-0.1.1/CHANGELOG.md +71 -0
- resultseal-0.1.1/CODE_OF_CONDUCT.md +4 -0
- resultseal-0.1.1/CONTRIBUTING.md +8 -0
- resultseal-0.1.1/LICENSE +21 -0
- resultseal-0.1.1/Makefile +22 -0
- resultseal-0.1.1/PKG-INFO +104 -0
- resultseal-0.1.1/README.md +57 -0
- resultseal-0.1.1/ROADMAP.md +14 -0
- resultseal-0.1.1/SECURITY.md +6 -0
- resultseal-0.1.1/docs/decision-log.md +183 -0
- resultseal-0.1.1/docs/specs/ADAPTERS.md +20 -0
- resultseal-0.1.1/docs/specs/ARCHITECTURE.md +40 -0
- resultseal-0.1.1/docs/specs/CLI_CONTRACT.md +19 -0
- resultseal-0.1.1/docs/specs/CONFIG_CONTRACT.md +8 -0
- resultseal-0.1.1/docs/specs/ERROR_CODES.md +14 -0
- resultseal-0.1.1/docs/specs/FIXTURE_CATALOG.md +15 -0
- resultseal-0.1.1/docs/specs/NON_GOALS.md +4 -0
- resultseal-0.1.1/docs/specs/PRODUCT_SPEC.md +32 -0
- resultseal-0.1.1/docs/specs/PROMOTION_RULES.md +27 -0
- resultseal-0.1.1/docs/specs/PROTOCOL_SPEC.md +34 -0
- resultseal-0.1.1/docs/specs/REPORT_FORMAT.md +21 -0
- resultseal-0.1.1/docs/specs/THREAT_MODEL.md +22 -0
- resultseal-0.1.1/examples/customer_contract.json +8 -0
- resultseal-0.1.1/examples/http_empty.json +7 -0
- resultseal-0.1.1/examples/mcp_result.json +8 -0
- resultseal-0.1.1/examples/minimal_contract.json +11 -0
- resultseal-0.1.1/fixtures/complete-fresh-result.yaml +31 -0
- resultseal-0.1.1/fixtures/empty-result.yaml +25 -0
- resultseal-0.1.1/fixtures/explicit-not-found.yaml +26 -0
- resultseal-0.1.1/fixtures/malformed-json.yaml +26 -0
- resultseal-0.1.1/fixtures/no-dispatch-success-claim.yaml +23 -0
- resultseal-0.1.1/fixtures/partial-response.yaml +28 -0
- resultseal-0.1.1/fixtures/stale-response.yaml +30 -0
- resultseal-0.1.1/fixtures/unsafe-input.yaml +11 -0
- resultseal-0.1.1/fixtures/unverified-write.yaml +27 -0
- resultseal-0.1.1/fixtures/wrong-target.yaml +29 -0
- resultseal-0.1.1/pyproject.toml +70 -0
- resultseal-0.1.1/schemas/contract.v1.json +20 -0
- resultseal-0.1.1/schemas/observation-envelope.v1.json +25 -0
- resultseal-0.1.1/scripts/clean_install_check.sh +26 -0
- resultseal-0.1.1/src/resultseal/__init__.py +13 -0
- resultseal-0.1.1/src/resultseal/canonical.py +62 -0
- resultseal-0.1.1/src/resultseal/cli.py +288 -0
- resultseal-0.1.1/src/resultseal/contracts.py +46 -0
- resultseal-0.1.1/src/resultseal/errors.py +80 -0
- resultseal-0.1.1/src/resultseal/fixtures.py +200 -0
- resultseal-0.1.1/src/resultseal/limits.py +65 -0
- resultseal-0.1.1/src/resultseal/models.py +451 -0
- resultseal-0.1.1/src/resultseal/normalize.py +355 -0
- resultseal-0.1.1/src/resultseal/report.py +103 -0
- resultseal-0.1.1/src/resultseal/rules.py +217 -0
- resultseal-0.1.1/src/resultseal/safeio.py +113 -0
- resultseal-0.1.1/tests/test_canonical.py +64 -0
- resultseal-0.1.1/tests/test_cli.py +213 -0
- resultseal-0.1.1/tests/test_contracts.py +114 -0
- resultseal-0.1.1/tests/test_determinism.py +53 -0
- resultseal-0.1.1/tests/test_examples.py +51 -0
- resultseal-0.1.1/tests/test_fixture_matrix.py +46 -0
- resultseal-0.1.1/tests/test_fixtures.py +106 -0
- resultseal-0.1.1/tests/test_integration.py +87 -0
- resultseal-0.1.1/tests/test_models.py +204 -0
- resultseal-0.1.1/tests/test_normalize.py +145 -0
- resultseal-0.1.1/tests/test_normalize_http.py +97 -0
- resultseal-0.1.1/tests/test_normalize_mcp.py +76 -0
- resultseal-0.1.1/tests/test_normalize_stdio.py +72 -0
- resultseal-0.1.1/tests/test_purity.py +101 -0
- resultseal-0.1.1/tests/test_report.py +118 -0
- resultseal-0.1.1/tests/test_rules.py +317 -0
- resultseal-0.1.1/tests/test_rules_metamorphic.py +140 -0
- resultseal-0.1.1/tests/test_safe_inputs.py +90 -0
- resultseal-0.1.1/tests/test_schemas.py +82 -0
- resultseal-0.1.1/tests/test_smoke.py +22 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: A decision, classification, or report that contradicts the specifications
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**What happened**
|
|
8
|
+
|
|
9
|
+
State the observed decision (`sealed` / `blocked`), truth state, and reason codes, and what the specifications in [docs/specs/](../blob/master/docs/specs/) require instead.
|
|
10
|
+
|
|
11
|
+
**Minimal reproduction**
|
|
12
|
+
|
|
13
|
+
The smallest contract plus input (or fixture) that produces it:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<paste YAML/JSON, CLI command, or fixture here>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Expected behavior**
|
|
20
|
+
|
|
21
|
+
What the promotion rules should have produced, citing `docs/specs/PROMOTION_RULES.md` where applicable.
|
|
22
|
+
|
|
23
|
+
**Environment**
|
|
24
|
+
|
|
25
|
+
- OS:
|
|
26
|
+
- Python version:
|
|
27
|
+
- resultseal version:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: A capability within ResultSeal's scope
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Problem to solve**
|
|
8
|
+
|
|
9
|
+
What observation-integrity failure mode or workflow does this address? Check [docs/specs/NON_GOALS.md](../blob/master/docs/specs/NON_GOALS.md) first — agent frameworks, proxies, dashboards, policy engines, retry middleware, signed receipts, and LLM judges are out of scope.
|
|
10
|
+
|
|
11
|
+
**Proposed behavior**
|
|
12
|
+
|
|
13
|
+
What should the new capability do, and how does it fit the existing contract → normalize → evaluate pipeline?
|
|
14
|
+
|
|
15
|
+
**Determinism impact**
|
|
16
|
+
|
|
17
|
+
Confirm the feature keeps decisions byte-deterministic given identical inputs and a pinned reference clock, and justify any new dependency.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
One line describing the change.
|
|
4
|
+
|
|
5
|
+
## Failure mode addressed
|
|
6
|
+
|
|
7
|
+
Link the issue, or state the failure mode: what was promoted, blocked, classified, or reported incorrectly?
|
|
8
|
+
|
|
9
|
+
## Tests
|
|
10
|
+
|
|
11
|
+
- [ ] Regression test or fixture included
|
|
12
|
+
|
|
13
|
+
## Determinism
|
|
14
|
+
|
|
15
|
+
- [ ] Decisions stay deterministic given identical inputs and a pinned reference clock
|
|
16
|
+
- [ ] Reports and fingerprints carry no wall-clock values
|
|
17
|
+
|
|
18
|
+
## Gates
|
|
19
|
+
|
|
20
|
+
Exact results from the documented commands:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
ruff check src tests:
|
|
24
|
+
mypy src:
|
|
25
|
+
pytest:
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Docs
|
|
29
|
+
|
|
30
|
+
- [ ] Relevant specs under `docs/specs/` updated if behavior changed
|
|
31
|
+
- [ ] `docs/decision-log.md` entry added if a documented invariant changed
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install
|
|
21
|
+
run: python -m pip install -e ".[dev]"
|
|
22
|
+
- name: Test
|
|
23
|
+
run: python -m pytest -q
|
|
24
|
+
- name: Lint
|
|
25
|
+
run: ruff check .
|
|
26
|
+
- name: Type check
|
|
27
|
+
run: mypy src
|
|
28
|
+
|
|
29
|
+
build:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.12"
|
|
36
|
+
- name: Build sdist and wheel
|
|
37
|
+
run: |
|
|
38
|
+
python -m pip install build
|
|
39
|
+
python -m build
|
|
40
|
+
- name: Clean-install smoke
|
|
41
|
+
run: |
|
|
42
|
+
python -m pip install dist/*.whl
|
|
43
|
+
resultseal version
|
|
44
|
+
resultseal replay fixtures/empty-result.yaml
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions: {}
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
gate:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: true
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install
|
|
22
|
+
run: python -m pip install -e ".[dev]"
|
|
23
|
+
- name: Test
|
|
24
|
+
run: python -m pytest -q
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: ruff check .
|
|
27
|
+
- name: Type check
|
|
28
|
+
run: mypy src
|
|
29
|
+
|
|
30
|
+
build:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
needs: gate
|
|
33
|
+
environment: pypi
|
|
34
|
+
permissions:
|
|
35
|
+
# Required for trusted publishing to PyPI and creating the release.
|
|
36
|
+
id-token: write
|
|
37
|
+
contents: write
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- uses: actions/setup-python@v5
|
|
41
|
+
with:
|
|
42
|
+
python-version: "3.12"
|
|
43
|
+
- name: Install build tooling
|
|
44
|
+
run: python -m pip install build twine
|
|
45
|
+
- name: Build sdist and wheel
|
|
46
|
+
run: python -m build
|
|
47
|
+
- name: Check distribution metadata
|
|
48
|
+
run: python -m twine check dist/*
|
|
49
|
+
- name: Clean-install smoke (install the exact artifact, run it)
|
|
50
|
+
run: |
|
|
51
|
+
python -m venv /tmp/smoke-venv
|
|
52
|
+
/tmp/smoke-venv/bin/pip install dist/*.whl
|
|
53
|
+
/tmp/smoke-venv/bin/resultseal version
|
|
54
|
+
/tmp/smoke-venv/bin/resultseal replay fixtures/empty-result.yaml
|
|
55
|
+
- name: Publish to PyPI via trusted publishing
|
|
56
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
57
|
+
- name: Create GitHub release with artifacts
|
|
58
|
+
uses: softprops/action-gh-release@v2
|
|
59
|
+
with:
|
|
60
|
+
files: dist/*
|
|
61
|
+
body: See CHANGELOG.md for the release notes.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.pytest_cache/
|
|
4
|
+
.ruff_cache/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.venv/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.coverage
|
|
11
|
+
htmlcov/
|
|
12
|
+
.env
|
|
13
|
+
.DS_Store
|
|
14
|
+
|
|
15
|
+
resultseal_claude_code_handoff/
|
|
16
|
+
|
|
17
|
+
# --- Local-only working documents -----------------------------------------
|
|
18
|
+
# Internal planning, AI-workflow, and session-state files. They stay on the
|
|
19
|
+
# maintainer's machine and are deliberately excluded from the public
|
|
20
|
+
# repository (decision log D17).
|
|
21
|
+
/ACCEPTANCE_CHECKLIST.md
|
|
22
|
+
/CLAUDE.md
|
|
23
|
+
/CLAUDE_CODE_HANDOFF.md
|
|
24
|
+
/GITHUB_DISCOVERY_PLAYBOOK.md
|
|
25
|
+
/IMPLEMENTATION_ORDER.md
|
|
26
|
+
/IMPLEMENTATION_STATUS.md
|
|
27
|
+
/MANIFEST.txt
|
|
28
|
+
/MASTER_BUILD_PROMPT.md
|
|
29
|
+
/PROBLEM_AND_RESEARCH.md
|
|
30
|
+
/RELEASE_PLAN.md
|
|
31
|
+
/RESEARCH_*
|
|
32
|
+
/STATESEAL_CHAT_HANDOFF.md
|
|
33
|
+
/TEST_STRATEGY.md
|
|
34
|
+
/prompts/
|
|
35
|
+
/docs/superpowers/
|
|
36
|
+
/docs/test-evidence.md
|
|
37
|
+
/docs/requirements-matrix.md
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.1 — 2026-08-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Shipped examples now work end to end: `examples/http_empty.json` carries
|
|
8
|
+
its body under the field name the HTTP adapter actually hashes (`body`,
|
|
9
|
+
previously the unread `response_body`, so the envelope hashed null);
|
|
10
|
+
`examples/mcp_result.json` gained the `source_ref`/`target_ref` identity
|
|
11
|
+
fields every adapter input requires; and new
|
|
12
|
+
`examples/customer_contract.json` makes both runnable through
|
|
13
|
+
`resultseal check`. Example validation no longer skips raw-response
|
|
14
|
+
shapes — each must normalize into an envelope satisfying
|
|
15
|
+
`schemas/observation-envelope.v1.json` (D21).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Tag-driven publish workflow: a `v*` tag runs the full gate suite,
|
|
20
|
+
builds and smoke-installs the wheel, then uploads to PyPI via trusted
|
|
21
|
+
publishing and attaches artifacts to a GitHub Release.
|
|
22
|
+
- A naive-but-parseable `observed_at` under `max_age_seconds` freshness
|
|
23
|
+
now blocks as `unknown`/`SCHEMA_INVALID` instead of escaping `evaluate`
|
|
24
|
+
as an unclassified `TypeError` (D18).
|
|
25
|
+
- `resultseal replay --format json --redact` now redacts before
|
|
26
|
+
fingerprinting, matching `resultseal check`, so the printed
|
|
27
|
+
`deterministic_fingerprint` verifies against the printed record.
|
|
28
|
+
Redacted replay output differs byte-wise from 0.1.0; unredacted output
|
|
29
|
+
is unchanged (D19).
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Internal readability cleanups with no behavior change: shared
|
|
34
|
+
expectation-matching and record-pipeline helpers, single homes for
|
|
35
|
+
`format_clock` and the fingerprint key, unused parameters removed (D20).
|
|
36
|
+
|
|
37
|
+
## 0.1.0 — 2026-08-22 (public alpha)
|
|
38
|
+
|
|
39
|
+
First implementation release. Offline, deterministic observation-integrity
|
|
40
|
+
gate for AI-agent tool results.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- Typed, frozen observation envelope and contract models with strict
|
|
45
|
+
construction (`models.py`); stable error taxonomy mapping failures to
|
|
46
|
+
public reason codes and CLI exit codes (`errors.py`).
|
|
47
|
+
- Canonical JSON serialization, `content_hash`, and self-excluding decision
|
|
48
|
+
fingerprints (`canonical.py`).
|
|
49
|
+
- Pure promotion rules engine with documented precedence, natural-order
|
|
50
|
+
source-version comparison, and injected clock (`rules.py`).
|
|
51
|
+
- Bounded safe input loading: size/depth/node/string limits before parse;
|
|
52
|
+
YAML restricted to an explicit tag allowlist with anchors/aliases rejected;
|
|
53
|
+
path containment helpers (`limits.py`, `safeio.py`).
|
|
54
|
+
- Contract and self-contained fixture loaders (`contracts.py`,
|
|
55
|
+
`fixtures.py`); shipped fixtures embed their contracts inline.
|
|
56
|
+
- HTTP/JSON, MCP-style, and stdio normalizers establishing structural facts
|
|
57
|
+
only (`normalize.py`).
|
|
58
|
+
- CLI: `resultseal version | validate | check | replay` with stable exit
|
|
59
|
+
codes (0/1/2/3) and deterministic JSON or Markdown reports (`cli.py`,
|
|
60
|
+
`report.py`).
|
|
61
|
+
- Reason-code `PROTOCOL_CONFLICT` for self-contradicting protocol results
|
|
62
|
+
(e.g. MCP `isError: true` alongside success-shaped content), added per the
|
|
63
|
+
ERROR_CODES extension process.
|
|
64
|
+
- Contract schema v1 gains optional `min_source_version` (additive D8).
|
|
65
|
+
|
|
66
|
+
### Guarantee scope
|
|
67
|
+
|
|
68
|
+
Deterministic given identical inputs and a pinned reference clock. Reports
|
|
69
|
+
and fingerprints never contain wall-clock values. Max-age freshness uses the
|
|
70
|
+
injected clock only. See docs/specs/THREAT_MODEL.md for the security boundary: this
|
|
71
|
+
tool protects the local promotion decision, not external systems.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
Participants must be respectful, constructive, and focused on improving the software. Harassment, discrimination, doxxing, malicious reports, and hostile behavior are not welcome. Maintainers may remove content or participation that violates these expectations.
|
|
4
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Keep changes narrow and evidence-driven. A contribution should state the failure mode it addresses, include a regression test or fixture, preserve determinism, and update relevant protocol or CLI documentation. New adapters must not convert transport success into semantic success. Do not add network access, dynamic execution, or hidden model calls.
|
|
4
|
+
|
|
5
|
+
A change that touches a documented invariant — a promotion rule, an error code, a schema field, an adapter behavior — adds a new dated entry to [docs/decision-log.md](docs/decision-log.md): a `## D<number> — <date> — <title>` heading after the last entry, followed by a concise statement of what was decided and why, in the style of the existing entries. The log is append-only; a superseded decision is corrected by a newer entry, never by rewriting an old one.
|
|
6
|
+
|
|
7
|
+
Before opening a pull request, run the documented test, lint, type, and build commands. Include exact results and explain any platform-specific behavior.
|
|
8
|
+
|
resultseal-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ResultSeal contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.PHONY: install test lint typecheck build demo all
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
python -m pip install -e ".[dev]"
|
|
5
|
+
|
|
6
|
+
test:
|
|
7
|
+
python -m pytest -q
|
|
8
|
+
|
|
9
|
+
lint:
|
|
10
|
+
ruff check .
|
|
11
|
+
|
|
12
|
+
typecheck:
|
|
13
|
+
mypy src
|
|
14
|
+
|
|
15
|
+
build:
|
|
16
|
+
python -m build || uv build
|
|
17
|
+
|
|
18
|
+
demo:
|
|
19
|
+
resultseal replay fixtures/empty-result.yaml
|
|
20
|
+
resultseal replay fixtures/explicit-not-found.yaml
|
|
21
|
+
|
|
22
|
+
all: test lint typecheck build
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: resultseal
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Deterministic observation-integrity contracts for AI-agent tool results
|
|
5
|
+
Author: ResultSeal contributors
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 ResultSeal contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Keywords: ai-agents,contract-testing,determinism,llm,mcp,tool-calling
|
|
29
|
+
Classifier: Development Status :: 3 - Alpha
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
37
|
+
Classifier: Topic :: Software Development :: Testing
|
|
38
|
+
Requires-Python: >=3.11
|
|
39
|
+
Requires-Dist: pyyaml<7,>=6
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
42
|
+
Requires-Dist: jsonschema<5,>=4; extra == 'dev'
|
|
43
|
+
Requires-Dist: mypy<2,>=1.13; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
45
|
+
Requires-Dist: ruff<1,>=0.8; extra == 'dev'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# ResultSeal
|
|
49
|
+
|
|
50
|
+
[](https://github.com/sx4im/resultseal/actions/workflows/ci.yml)
|
|
51
|
+
[](LICENSE)
|
|
52
|
+
[](https://www.python.org/downloads/)
|
|
53
|
+
|
|
54
|
+
**HTTP 200 is not an observation. Empty is not not-found. A tool call is not an effect.**
|
|
55
|
+
|
|
56
|
+
ResultSeal is a small, framework-neutral Python toolkit that prevents AI-agent workflows from promoting empty, partial, stale, source-mismatched, or unverified tool results into factual claims. Shipped adapters cover raw JSON, HTTP responses, MCP-style tool results (`structuredContent` / `isError` / `outputSchema`), and stdio process output — each establishing structural facts only (see [docs/specs/ADAPTERS.md](docs/specs/ADAPTERS.md)).
|
|
57
|
+
|
|
58
|
+
## What it does
|
|
59
|
+
|
|
60
|
+
ResultSeal normalizes a tool result, applies a declarative contract, and produces a deterministic decision. Unknown and incomplete evidence is blocked by default.
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
Not on PyPI yet — install from a clone:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/sx4im/resultseal.git
|
|
68
|
+
cd resultseal
|
|
69
|
+
pip install .
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Requires Python 3.11+.
|
|
73
|
+
|
|
74
|
+
## Try it
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Replay a self-contained fixture bundle against its recorded expectation
|
|
78
|
+
resultseal replay fixtures/empty-result.yaml # empty response -> blocked/empty
|
|
79
|
+
resultseal replay fixtures/explicit-not-found.yaml # approved sentinel -> sealed/not_found
|
|
80
|
+
|
|
81
|
+
# Evaluate a shipped example against a shipped contract (exit 0 = sealed, 1 = blocked)
|
|
82
|
+
resultseal check examples/mcp_result.json --contract examples/customer_contract.json
|
|
83
|
+
resultseal check examples/http_empty.json --contract examples/customer_contract.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The last two are the toolkit's thesis side by side: a complete MCP result seals,
|
|
87
|
+
while an HTTP 200 carrying an empty body blocks as `empty` — it can never be
|
|
88
|
+
promoted to `not_found`. All four commands print the decision record with a
|
|
89
|
+
verifiable `deterministic_fingerprint`.
|
|
90
|
+
|
|
91
|
+
## Scope
|
|
92
|
+
|
|
93
|
+
ResultSeal is not an agent framework, proxy, dashboard, policy engine, retry middleware, signed receipt system, or LLM judge. It is an executable semantic boundary for tool observations.
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
make install # editable install with dev tools
|
|
99
|
+
make all # test, lint, typecheck, build
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
Bug reports, fixes, and spec feedback are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for what a change is expected to include. The normative specifications live in [docs/specs/](docs/specs/), and changes that touch a documented invariant add a dated entry to the [decision log](docs/decision-log.md).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ResultSeal
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sx4im/resultseal/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
**HTTP 200 is not an observation. Empty is not not-found. A tool call is not an effect.**
|
|
8
|
+
|
|
9
|
+
ResultSeal is a small, framework-neutral Python toolkit that prevents AI-agent workflows from promoting empty, partial, stale, source-mismatched, or unverified tool results into factual claims. Shipped adapters cover raw JSON, HTTP responses, MCP-style tool results (`structuredContent` / `isError` / `outputSchema`), and stdio process output — each establishing structural facts only (see [docs/specs/ADAPTERS.md](docs/specs/ADAPTERS.md)).
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
ResultSeal normalizes a tool result, applies a declarative contract, and produces a deterministic decision. Unknown and incomplete evidence is blocked by default.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
Not on PyPI yet — install from a clone:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/sx4im/resultseal.git
|
|
21
|
+
cd resultseal
|
|
22
|
+
pip install .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Requires Python 3.11+.
|
|
26
|
+
|
|
27
|
+
## Try it
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Replay a self-contained fixture bundle against its recorded expectation
|
|
31
|
+
resultseal replay fixtures/empty-result.yaml # empty response -> blocked/empty
|
|
32
|
+
resultseal replay fixtures/explicit-not-found.yaml # approved sentinel -> sealed/not_found
|
|
33
|
+
|
|
34
|
+
# Evaluate a shipped example against a shipped contract (exit 0 = sealed, 1 = blocked)
|
|
35
|
+
resultseal check examples/mcp_result.json --contract examples/customer_contract.json
|
|
36
|
+
resultseal check examples/http_empty.json --contract examples/customer_contract.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The last two are the toolkit's thesis side by side: a complete MCP result seals,
|
|
40
|
+
while an HTTP 200 carrying an empty body blocks as `empty` — it can never be
|
|
41
|
+
promoted to `not_found`. All four commands print the decision record with a
|
|
42
|
+
verifiable `deterministic_fingerprint`.
|
|
43
|
+
|
|
44
|
+
## Scope
|
|
45
|
+
|
|
46
|
+
ResultSeal is not an agent framework, proxy, dashboard, policy engine, retry middleware, signed receipt system, or LLM judge. It is an executable semantic boundary for tool observations.
|
|
47
|
+
|
|
48
|
+
## Development
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
make install # editable install with dev tools
|
|
52
|
+
make all # test, lint, typecheck, build
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
Bug reports, fixes, and spec feedback are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for what a change is expected to include. The normative specifications live in [docs/specs/](docs/specs/), and changes that touch a documented invariant add a dated entry to the [decision log](docs/decision-log.md).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
## Public alpha
|
|
4
|
+
|
|
5
|
+
The public alpha is the offline deterministic core: envelope models, promotion rules, safe fixture loading, three normalizers, CLI, reports, tests, and CI.
|
|
6
|
+
|
|
7
|
+
## Later, only with user evidence
|
|
8
|
+
|
|
9
|
+
Possible follow-up work includes more adapters, a plugin protocol, optional cryptographic evidence references, and integrations with existing test frameworks. These are not part of the MVP and must not be added until the core semantics are stable and users request them.
|
|
10
|
+
|
|
11
|
+
## Forbidden expansion
|
|
12
|
+
|
|
13
|
+
Do not expand into a hosted service, general agent runtime, dashboard, policy engine, transaction manager, or universal evaluator.
|
|
14
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
ResultSeal is designed to process untrusted result data locally. Do not put production secrets in fixtures or issue reports. Report a vulnerability privately through the repository’s configured security contact rather than opening a public issue with exploit details.
|
|
4
|
+
|
|
5
|
+
Security-critical behavior includes safe parsing, bounded inputs, path containment, no dynamic execution, no network access, redaction, deterministic decisions, and fail-closed promotion. Security fixes require a regression test and a changelog entry.
|
|
6
|
+
|