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
11 changes: 9 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,28 @@ env/

# Testing
.pytest_cache/
.hypothesis/
.coverage
htmlcov/
.tox/
.nox/
coverage.xml
*.cover

# IDE / OS
# Type checkers / linters
.mypy_cache/
.ruff_cache/

# IDE / OS / local scratch
.idea/
.vscode/
.cursor-plan-tmp/
*.swp
*.swo
.DS_Store
Thumbs.db

# Local outputs (regenerated by demos/evals)
# Local outputs (regenerated by demos/evals/release tooling)
# Entire dist/ is ignored; demos write reconstructable_experiment/, pilot_bundle/, etc.
dist/pcs_artifacts/
dist/pf_obligations/
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@ All notable changes to AKTA are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased] — Admissibility-Stack hardening (AS-00–08) on 1.2.0

Additive hardening atop package **1.2.0**. Does not rewrite frozen PROTOCOL v1.0 required fields.

### Added

- Baseline freeze + ADRs (`docs/as_baseline.md`, `docs/adr/0001`–`0003`)
- Binding set schema and decision/record `bindings` digests (AS-01)
- `stack_profile` schema/validator and `akta validate-stack-profile` (AS-02)
- `decision_basis` structured artifact (AS-03)
- Uniform failure mapping + `failure` / `failures[]` surfaces (AS-04)
- Five `PilotMode` values, `policy/pilot_modes/`, `akta gate --mode` (AS-05; distinct from REST deployment `--mode`)
- SCOPE/PF/PCS binding hardening and AS-06 fixtures (AS-06)
- Append-only `outcome_ref`, `akta link-outcome`, `akta export-pilot-metrics` (AS-07)
- `akta reconstruct`, operator/reviewer pilot guides (AS-08)

### Changed

- VSA import prefers `vsa_bundle` and fail-closes on digest mismatch / ambiguous refs
- Legacy `PilotStage` / `AKTA_PILOT_STAGE` map into PilotMode (unknown values fail closed)

### Notes

- Additive CLI/API only; default `gate`/`record`/`export`/`eval` remain compatible when new flags are omitted
- Placeholder release signers remain fail-closed under institutional stack profiles
- Pilot metrics are operational aggregates only — not institution-wide scientific efficacy scores
- Admissibility decisions are not scientific truth certification (ADR 0001)

## [1.2.0] - 2026-07-23

### Added
Expand Down
9 changes: 6 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ Thank you for contributing to the Open Scientific Action Protocol.
```bash
git clone https://github.com/fraware/AKTA.git
cd AKTA
pip install -e ".[dev]"
pip install -e ".[dev,security]"
pytest tests/ -v
```

Full local gate: `make ci`. Do not commit regenerable `dist/` outputs, `__pycache__/`, or Hypothesis caches (see `.gitignore`).

## Pull request guidelines

1. Keep changes focused on scientific action admissibility — avoid scope creep into evidence retrieval, proof kernels, or release packaging.
2. All policy and schema changes must include updated tests.
3. Run `pytest tests/ -v` and `akta eval --scenarios scenarios/canonical_5.jsonl --expected scenarios/expected_decisions.jsonl` before submitting.
3. Run `pytest tests/ -v` and `akta eval --scenarios scenarios/canonical_5.jsonl --expected scenarios/expected_decisions.jsonl` before submitting. For AS surfaces, also run `pytest tests/test_as*.py -v`.
4. Do not add operational bio/chem protocol examples without domain expert review.
5. Follow existing naming conventions for action types (A0–A10), responsibility levels (R0–R9), and deployment profiles (P0–P6).
6. Disambiguate **PilotMode** (`akta gate --mode`) from REST deployment `--mode` and legacy `PilotStage` aliases. Preserve ADR non-claims (admissibility is not truth certification; pilot metrics are not efficacy scores).

## Policy changes

Expand All @@ -29,4 +32,4 @@ Policy files live in `policy/` and `overlays/`. Changes require:

## Code of conduct

Be respectful, precise, and evidence-oriented. AKTA governs claim-to-action transitions — contributions should preserve that boundary.
Be respectful, precise, and evidence-oriented. AKTA governs claim-to-action transitions — contributions should preserve that boundary. See [GOVERNANCE.md](GOVERNANCE.md) and [docs/adr/0001-admissibility-boundary.md](docs/adr/0001-admissibility-boundary.md).
2 changes: 1 addition & 1 deletion GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ AKTA is an open protocol with a reference implementation under the MIT license.

## Versioning

AKTA follows semantic versioning for the reference implementation package (`akta-protocol`, currently v1.0.0). Schema versions are embedded in artifact metadata (e.g., `akta-core-v1.0`, `akta-record-v0.5`).
AKTA follows semantic versioning for the reference implementation package (`akta-protocol`, currently **1.2.0**). Schema versions are embedded in artifact metadata (e.g., `akta-core-v1.0`, `akta-record-v0.5`).

See also `policy/scope_compatibility_manifest.json` for SCOPE contract pins and [docs/policy_integrity.md](docs/policy_integrity.md) for effective policy provenance.

Expand Down
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ akta record \

For the full integrated chain (evidence import through packaging), see [examples/integrated_weak_evidence](examples/integrated_weak_evidence/) and `python scripts/demo_integrated_weak_evidence.py`.

### Pilot modes and reconstruction (Admissibility-Stack)

Institutional pilots can pin a **PilotMode** on the gate (`akta gate --mode …`), validate a stack profile, link append-only outcomes, export privacy-preserving metrics, and reconstruct a release bundle:

```bash
akta gate --output examples/weak_evidence/ai_output.json \
--tool analysis.literature_summary \
--mode prospective_shadow \
--context examples/weak_evidence/context.json \
--out /tmp/shadow_decision.json
akta validate-stack-profile path/to/stack_profile.json
akta reconstruct --release path/to/pcs_bundle/ --out /tmp/reconstruction.json
```

`akta gate --mode` is **not** the REST server deployment `--mode`. See [operator pilot guide](docs/operator_pilot_guide.md) and [stack profile](docs/stack_profile.md).

---

## What you get
Expand Down Expand Up @@ -176,13 +192,20 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) for pull-request expectations, [GOVERNAN
- [Field thesis](docs/field_thesis.md) — problem framing
- [Integration guide](docs/integration_guide.md) — wiring AKTA into your stack
- [AKTA Card guide](docs/akta_card_guide.md) — institutional disclosure artifact
- [PROTOCOL v1.0](docs/PROTOCOL_v1.0.md) — frozen schema declaration

### Admissibility-Stack (AS-00–08)

- [AS baseline freeze](docs/as_baseline.md) · [ADR 0001 boundary](docs/adr/0001-admissibility-boundary.md) · [ADR 0002 pilot modes](docs/adr/0002-pilot-modes.md) · [ADR 0003 reconstruction](docs/adr/0003-artifact-immutability-and-reconstruction.md)
- [Operator pilot guide](docs/operator_pilot_guide.md) · [Reviewer pilot guide](docs/reviewer_pilot_guide.md)
- [Stack profile](docs/stack_profile.md) · [Failure taxonomy + uniform mapping](docs/failure_class_taxonomy.md)

### Integration

- [Review integration](docs/review_integration.md)
- [SCOPE bridge](docs/scope_bridge.md) · [Live SCOPE conformance](docs/scope_live_conformance.md)
- [PF-Core bridge](docs/pf_core_bridge.md) · [PCS export](docs/pcs_export.md) · [VSA import](docs/vsa_import.md)
- [AKTA v0.3 integration summary](docs/akta_v03_integration.md)
- [AKTA v0.3 integration summary](docs/akta_v03_integration.md) (historical; prefer integration guide)

### Policy and security

Expand All @@ -201,16 +224,16 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) for pull-request expectations, [GOVERNAN

## Project status

**v1.2.0** (`akta-protocol`) is the current reference kernel targeting native SCOPE 2.2 consumption.
**v1.2.0** (`akta-protocol`) is the current reference kernel targeting native SCOPE 2.2 consumption. Admissibility-Stack hardening (AS-00–08) adds reconstructable bindings, pilot modes, stack profiles, uniform failures, outcome linkage, and reconstruction CLI without rewriting frozen PROTOCOL v1.0 required fields.

| Claim | What CI proves | What requires local siblings |
|-------|----------------|------------------------------|
| Reference kernel + policy v1.2 | `make ci` on every PR (359+ tests, evals, demos) | — |
| AKTA-Bench v1 | `make eval-bench-v1` in release-gate (105 oracle scenarios, holdout, behavioral middleware) | — |
| Reference kernel + policy v1.2 | `make ci` on every PR (tests, evals, demos) | — |
| AKTA-Bench v1 | `make eval-bench-v1` in release-gate (oracle scenarios, holdout, behavioral middleware) | — |
| Live SCOPE pilot gate | Release-gate clones public SCOPE and runs python-import + pilot bundle | SCOPE CLI / akta-review modes need `scope` on runner |
| PF / PCS / VSA / Memory / PCS-Bench matrix | Release-gate sibling job when clone URLs or `*_REPO_PATH` vars set | Full matrix locally: `python scripts/verify_v1_release.py` |

Biology, chemistry, and clinical domain overlays remain experimental unless upgraded to institutional or expert-reviewed tiers. P7 autonomous operator profiles are taxonomy-only and refused at runtime. AKTA is a reference implementation — not a safety certification. See [docs/limitations.md](docs/limitations.md) and [docs/PROTOCOL_v1.0.md](docs/PROTOCOL_v1.0.md).
Biology, chemistry, and clinical domain overlays remain experimental unless upgraded to institutional or expert-reviewed tiers. P7 autonomous operator profiles are taxonomy-only and refused at runtime. Gate admissibility is not scientific truth certification, and pilot metrics are not efficacy scores. See [docs/limitations.md](docs/limitations.md), [docs/PROTOCOL_v1.0.md](docs/PROTOCOL_v1.0.md), and [ADR 0001](docs/adr/0001-admissibility-boundary.md).

---

Expand Down
30 changes: 24 additions & 6 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

| Version | Supported |
|---------|-----------|
| 0.7.x | Yes |
| 0.6.x | Yes |
| 0.5.x | Yes |
| 0.4.x | Yes |
| 0.3.x | Yes |
| 1.2.x | Yes |
| 1.0.x | Security fixes only |
| 0.8.x and earlier | Best effort; upgrade to 1.2.x |

## Reporting a vulnerability

Expand All @@ -22,7 +20,17 @@ AKTA is part of the agent supply chain. Threats include policy tampering, fake A

See [docs/threat_model.md](docs/threat_model.md).

### Policy integrity modes (v0.7)
### Admissibility-Stack controls (1.2.x)

- Digest bindings on decisions/records; `akta reconstruct` for release-bundle verification
- `akta validate-stack-profile` against institutional release pins (placeholder signers fail closed)
- Pilot modes via `akta gate --mode` (distinct from REST service `--mode`)
- Append-only `outcome_ref` linkage; pilot metrics exclude raw evidence/PII
- Uniform failure mapping (`failure` / `failures[]`) additive to existing local reason codes

See [docs/threat_model.md](docs/threat_model.md), [docs/adr/0001-admissibility-boundary.md](docs/adr/0001-admissibility-boundary.md).

### Policy integrity modes (v0.7+)

| Mode | Environment variables | Manifest | Verification |
|------|----------------------|----------|--------------|
Expand Down Expand Up @@ -79,3 +87,13 @@ See [docs/policy_integrity.md](docs/policy_integrity.md).
- Model truthfulness guarantees
- P7 fully autonomous scientific operator runtime
- Safety or regulatory certification
- Learning or updating policy from pilot outcome metrics
- Treating gate admissibility as scientific truth or efficacy certification

### Test fixtures

The following PEMs are **test-only** keys for deterministic CI. They are not production release or institutional SCOPE issuer keys; do not reuse them outside the test suite:

- `tests/fixtures/empirical/preregistration_signer.pem` — preregistration lock unit tests
- `tests/fixtures/trust_keys/issuer_ed25519.pem` — documented in `tests/fixtures/trust_keys/README.md`
- `evals/empirical/keys/preregistration_signer.pub.pem` — public verification material only
29 changes: 29 additions & 0 deletions adapters/generic_rest/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,35 @@ paths:
responses:
"200":
description: AKTA decision
"400":
description: Client error (includes additive failure mapping)
content:
application/json:
schema:
type: object
properties:
error_code:
type: string
error:
type: string
detail:
type: string
failure:
type: object
description: Uniform failure object (AS-04); clients may ignore
properties:
uniform_class:
type: string
local_reason_code:
type: string
detail:
type: string
layer:
type: string
recoverable:
type: boolean
error_code:
type: string
/v0/records:
post:
summary: Build AKTA record from decision
Expand Down
10 changes: 8 additions & 2 deletions adapters/generic_rest/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from collections import defaultdict, deque
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from importlib.metadata import version as pkg_version
from akta import __version__ as akta_version
from pathlib import Path
from typing import Any
from urllib.parse import urlparse
Expand Down Expand Up @@ -357,6 +357,12 @@ def _send_error_json(self, status: int, code: str, detail: str | None = None) ->
safe = _sanitize_error_detail(detail)
if safe:
payload["detail"] = safe
try:
from akta.failure_mapping import map_rest_error

payload["failure"] = map_rest_error(code, detail=safe or code)
except Exception:
pass
self._send_json(status, payload)

def _gate(self) -> AKTAGate:
Expand Down Expand Up @@ -419,7 +425,7 @@ def do_GET(self) -> None:
HTTPStatus.OK,
{
"status": "ok",
"version": pkg_version("akta-protocol"),
"version": akta_version,
"api_version": "v1.0",
"production_mode": self.production_mode,
"service_mode": self.service_mode,
Expand Down
24 changes: 23 additions & 1 deletion adapters/pcs/export_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def build_pcs_manifest(
"domain_overlay_hash": provenance.get("domain_overlay_hash"),
"tool_registry_hash": provenance.get("tool_registry_hash"),
"decision_id": (decision or {}).get("decision_id") or record.get("record_id", "").replace("SAR", "DEC"),
"record_id": record.get("record_id"),
"bindings": record.get("bindings") or (decision or {}).get("bindings"),
"files": sorted(files + ["manifest.json"]),
}
if file_hashes:
Expand Down Expand Up @@ -142,20 +144,40 @@ def export_pcs_bundle(
out_dir.mkdir(parents=True, exist_ok=True)

provenance = data.get("provenance", {})
bindings = data.get("bindings") or {}
decision_payload = decision or {
"decision_id": data.get("record_id", "").replace("SAR", "DEC"),
"decision_id": bindings.get("decision_id")
or data.get("record_id", "").replace("SAR", "DEC"),
"admissibility": data["decision"]["admissibility"],
"scientific_action_type": data["classification"]["scientific_action_type"],
"responsibility_level": data["classification"]["responsibility_level"],
"evidence_state": data["classification"]["evidence_state"],
"decision_reason": data["decision"]["decision_reason"],
"policy_hash": provenance.get("policy_hash"),
"consequentiality": data["decision"].get("consequentiality", False),
"bindings": bindings or None,
}

if validate and not provenance.get("policy_hash", "").startswith("sha256:"):
raise ValueError("PCS export requires valid policy_hash on record provenance")

# AS-06: fail closed on binding digest mismatch.
if bindings.get("policy_hash") and provenance.get("policy_hash"):
if bindings["policy_hash"] != provenance["policy_hash"]:
raise ValueError(
"PCS export digest mismatch: bindings.policy_hash != provenance.policy_hash"
)
if bindings.get("decision_id") and decision_payload.get("decision_id"):
if bindings["decision_id"] != decision_payload["decision_id"]:
raise ValueError(
"PCS export digest mismatch: bindings.decision_id != decision.decision_id"
)
mode = (data.get("pilot_mode") or (decision or {}).get("pilot_mode") or "")
if mode == "bounded_execution" and not data.get("decision_basis") and not bindings.get(
"decision_basis_digest"
):
raise ValueError("PCS export require decision_basis under bounded_execution")

if validate and scope_grant is not None:
from akta.scope_contract import (
_scope_grant_approved_scope,
Expand Down
Loading
Loading