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/workflows/reusable-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ jobs:

- name: pytest skillware
if: inputs.skillware == true
run: pytest tests/test_skillware_integration.py -v
run: pytest tests/test_skillware_integration.py tests/test_host_stress_sim.py -v
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- **Integrations layout ([#19](https://github.com/ARPAHLS/aura/issues/19))** — top-level `integrations/README.md` stack index; Skillware `mock_tools.py` / `live_tools.py` entrypoints; LangGraph stub; doc links from getting-started and provider READMEs.

### Added

- **Audit pipeline example ([#23](https://github.com/ARPAHLS/aura/issues/23))** — `examples/audit_pipeline.py`: two sessions, audit report receipt, programmatic compare, hash-chain verify, CLI follow-ups (mock ToolHost; no Skillware required).

- **Tailored metrics snapshot example** — `examples/10-observer-metrics-snapshot/`: AURA-native Monitor preset + `metrics_snapshot` observer note; documents export hook for playbooks without third-party KPI skills.

- **Profile `spectrum` block (preview)** — optional agent profile field; ingress summary; `Spectrum.coat()` / `planes()` helpers ([#27](https://github.com/ARPAHLS/aura/issues/27) docs preview).

- **Host stress simulation** — `scripts/aura_host_stress_sim.py` + `tests/test_host_stress_sim.py`: multi-scenario AURA+Skillware host runs (coats, observers, chains, sequencer, export).

### Changed

- **Skillware compatibility** — optional extra `skillware>=0.5.4,<0.6` (auto patch within 0.5.x; conscious bump at 0.6); docs for `SkillContext`, named chains vs AURA sequencer, version policy in [skillware-integration.md](docs/skillware-integration.md).

- **`docs/comparison.md` ([#39](https://github.com/ARPAHLS/aura/issues/39))** — refresh for shipped egress, audit report, and hash chain; loose / tight / tailored coat section; host-agnostic ToolHost framing (Skillware as reference adapter); trim stale v0.1 / intercept-roadmap voice; fix Gatekeeper roadmap link ([#56](https://github.com/ARPAHLS/aura/issues/56)); INDEX and getting-started link blurbs.

- **Verified operator identity ([#55](https://github.com/ARPAHLS/aura/issues/55))** — optional identity adapters (manual, mock, OIDC, Auth0); `identity.bound` spine event; `ids.operator` on all event trailers; export redaction; `aura identity show`; profile `types` with `role: identity`.
Expand Down
3 changes: 3 additions & 0 deletions aura/agents/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AgentProfile:
skills: list[str] = field(default_factory=list)
sequencer: dict[str, Any] | None = None
observers: list[dict[str, Any]] = field(default_factory=list)
spectrum: dict[str, Any] | None = None
types: list[dict[str, Any]] = field(default_factory=list)
default_mode: str = "script"
archived: bool = False
Expand All @@ -38,6 +39,7 @@ def to_dict(self) -> dict[str, Any]:
"skills": self.skills,
"sequencer": self.sequencer,
"observers": self.observers,
"spectrum": self.spectrum,
"types": self.types,
"default_mode": self.default_mode,
"archived": self.archived,
Expand All @@ -57,6 +59,7 @@ def from_dict(cls, data: dict[str, Any]) -> AgentProfile:
skills=list(data.get("skills") or []),
sequencer=data.get("sequencer"),
observers=list(data.get("observers") or []),
spectrum=dict(data["spectrum"]) if isinstance(data.get("spectrum"), dict) else None,
types=list(data.get("types") or []),
default_mode=data.get("default_mode", "script"),
archived=bool(data.get("archived", False)),
Expand Down
5 changes: 5 additions & 0 deletions aura/agents/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def create(
skills: list[str] | None = None,
sequencer: dict[str, Any] | None = None,
observers: list[dict[str, Any]] | None = None,
spectrum: dict[str, Any] | None = None,
types: list[dict[str, Any]] | None = None,
ids: dict[str, Any] | None = None,
default_mode: str = "script",
Expand Down Expand Up @@ -118,6 +119,7 @@ def create(
skills=skills or [],
sequencer=sequencer,
observers=observers or [],
spectrum=dict(spectrum) if isinstance(spectrum, dict) else None,
types=types or [],
default_mode=default_mode,
)
Expand Down Expand Up @@ -176,6 +178,9 @@ def update_profile(self, key: str, **updates: Any) -> AgentProfile:
profile.ids.update(dict(updates["ids"]))
if updates.get("rules") is not None:
profile.rules = list(updates["rules"])
if "spectrum" in updates:
raw = updates["spectrum"]
profile.spectrum = dict(raw) if isinstance(raw, dict) else None

self.save(profile)
return profile
Expand Down
35 changes: 34 additions & 1 deletion aura/core/spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
from dataclasses import dataclass, field
from typing import Any

COAT_BY_LEVEL: dict[str, str] = {
"low": "loose",
"mid": "tight",
"high": "tight",
"full": "tailored",
}


@dataclass
class Spectrum:
Expand All @@ -15,8 +22,34 @@ class Spectrum:
def from_manifest(cls, manifest: dict[str, Any]) -> "Spectrum":
raw = manifest.get("spectrum") or {}
return cls(
level=raw.get("level", "mid"),
level=str(raw.get("level", "mid")),
services=list(raw.get("services") or ["monitor", "audit"]),
output=list(raw.get("output") or ["aura-json"]),
budgets=dict(raw.get("budgets") or {}),
)

@classmethod
def from_profile(cls, profile: dict[str, Any]) -> "Spectrum":
return cls.from_manifest(profile)

def coat(self) -> str:
"""Map spectrum level to loose / tight / tailored coat metaphor."""
return COAT_BY_LEVEL.get(self.level.lower(), "tight")

def planes(self) -> dict[str, bool]:
"""Three planes: audit (always), enforce, escalate — docs + #27 preview."""
level = self.level.lower()
return {
"audit": True,
"enforce": level in {"mid", "high", "full"},
"escalate": level in {"high", "full"} or "break" in self.services,
}

def summary(self) -> dict[str, Any]:
planes = self.planes()
return {
"level": self.level,
"coat": self.coat(),
"services": list(self.services),
"planes": planes,
}
6 changes: 5 additions & 1 deletion aura/membrane/ingress.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any

from aura.agents.profile import AgentProfile
from aura.core.spectrum import Spectrum


def build_ingress_context(
Expand Down Expand Up @@ -32,7 +33,7 @@ def ingress_event_payload(
mode: str,
snapshot_hash: str | None,
) -> dict[str, Any]:
return {
payload = {
"membrane": "ingress",
"mode": mode,
"snapshot_hash": snapshot_hash,
Expand All @@ -42,6 +43,9 @@ def ingress_event_payload(
"agent_ref": profile.agent_ref,
"policy_version": profile.policy_version,
}
if profile.spectrum:
payload["spectrum"] = Spectrum.from_profile({"spectrum": profile.spectrum}).summary()
return payload


def skill_registered_payload(
Expand Down
1 change: 1 addition & 0 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ The workflow also emits a gate job named **`lint-test`** that succeeds only when
- **New behavior needs a test** — extend the closest file (`test_core.py`, `test_v02.py`, `test_v03.py`, `test_cli.py`, or `test_core_gaps.py`).
- Shared fixtures live in **`tests/conftest.py`** — do not duplicate `aura_home` in test modules.
- Optional Skillware registry tests: `tests/test_skillware_integration.py` (`@pytest.mark.skillware`) — run in CI via the **skillware-live** job when `[skillware]` is installed ([#36](https://github.com/ARPAHLS/aura/issues/36)).
- **Host stress simulation:** `python scripts/aura_host_stress_sim.py` — eleven scenarios (loose/tight/tailored coats, single/multi/chain Skillware paths, sequencer, observers, export compare). CI: `tests/test_host_stress_sim.py` (`@pytest.mark.skillware`).
- **Real integration tests** live in **`tests/integration/`** (Skillware + Ollama, example 06 live). Default CI **excludes** them (`--ignore=tests/integration`). Run locally:

```bash
Expand Down
35 changes: 26 additions & 9 deletions docs/aura-levels.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
# AURA Levels

> **Optional / roadmap** — autonomy tiers; enforcement UX tracked in [#27](https://github.com/ARPAHLS/aura/issues/27). Today use postures in [using-aura.md](using-aura.md) and sequencer gates.
> **Optional / roadmap** — autonomy tiers; runtime enforcement UX tracked in [#27](https://github.com/ARPAHLS/aura/issues/27). Today use postures in [using-aura.md](using-aura.md), sequencer gates, and profile `spectrum`.

**Permissioned autonomy** — not binary on/off.

From [narrative.md](narrative.md). Enforced by Spectrum + conformance engine + hook pipeline.
From [narrative.md](narrative.md). Enforced by Spectrum + conformance engine + hook pipeline (enforcement wiring expands in #27).

---

| Level | Posture |
|---|---|
| **Low** | Suggest only. Human approves before action. |
| **Mid** | Act within defined scope. Escalate at boundaries. |
| **High** | Independent within enforced guardrails. Periodic human oversight. |
| **Full** | Self-directed within constitution. Accountability via Live ID + audit — not per-action supervision. |
## Three planes (always / enforce / escalate)

| Plane | Coat | What runs |
|---|---|---|
| **Audit** | Loose | Spine + export receipt — always on in production profiles |
| **Enforce** | Tight | Egress rules, sequencer gates, constitution at `tool.call` |
| **Escalate** | Tailored | Observers (Monitor, Break), metrics snapshots, future playbooks ([#38](https://github.com/ARPAHLS/aura/issues/38)) |

AURA-native tailored patterns use **observers + export** — see [example 10](../../examples/10-observer-metrics-snapshot/). Third-party registry skills may consume exports optionally; AURA does not require them for SLO visibility.

---

| Level | Posture | Typical coat |
|---|---|---|
| **Low** | Suggest only. Human approves before action. | Loose |
| **Mid** | Act within defined scope. Escalate at boundaries. | Tight |
| **High** | Independent within enforced guardrails. Periodic human oversight. | Tight + observers |
| **Full** | Self-directed within constitution. Accountability via audit — not per-action supervision. | Tailored |

---

Expand All @@ -37,13 +49,18 @@ Sequencer and hooks consult level for:

---

## Spec
## Profile spec (preview)

```yaml
spectrum:
level: mid # low | mid | high | full
services:
- monitor
- audit
```

Stored on agent profiles; summarized on `membrane.ingress` when set. Full level→deny behavior wiring: [#27](https://github.com/ARPAHLS/aura/issues/27).

Schema: [manifest.schema.json](../spec/manifest.schema.json)

---
Expand Down
4 changes: 3 additions & 1 deletion docs/guides/aura-on-skillware.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ Each script demonstrates the same architecture: **LLM body + Skillware egress un

## Sequencer: skill chaining

For fixed SOPs (scan → transform → budget check), declare steps instead of imperative calls:
For fixed SOPs (scan → transform → budget check), declare steps instead of imperative calls.

Skillware **0.5.4+** also offers [`run_chain()`](https://github.com/arpahls/skillware/blob/main/docs/usage/skill_chaining.md) and **`SkillContext`** for body-side tool discovery. Prefer **AURA sequencer** when the session receipt must prove step order and policy; use Skillware chains for standalone scripts — always route skill calls through `SkillwareHost`.

```yaml
sequencer:
Expand Down
2 changes: 2 additions & 0 deletions docs/guides/skillware-follow-ups.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Track these **after** closing the reference ToolHost epic ([#12](https://github.
| **Skill catalog appendix** | Table of bundled Skillware skills: offline vs API, suggested AURA guardrails |
| **Docs sweep** ([#14](https://github.com/ARPAHLS/aura/issues/14)) | Cross-link INDEX, ROADMAP — onboarding ([#13](https://github.com/ARPAHLS/aura/issues/13)) shipped |
| ~~Integrations layout + Ollama~~ | **Shipped** ([#19](https://github.com/ARPAHLS/aura/issues/19), [#20](https://github.com/ARPAHLS/aura/issues/20), PRs #51/#53) |
| **Skillware 0.5.4 sync** | **Shipped** — semver range, chains vs sequencer docs, example 10 metrics snapshot |
| **Audit pipeline example** | **Shipped** ([#23](https://github.com/ARPAHLS/aura/issues/23)) — `examples/audit_pipeline.py` |

---

Expand Down
2 changes: 2 additions & 0 deletions docs/onboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ Run in order from repo root after `pip install -e .`:
| 6 | [06-skillware-sequencer-chain](../examples/06-skillware-sequencer-chain/) | Declarative chain + conditional `when` |
| 7 | [07-observer-presets](../examples/07-observer-presets/) | Monitor + Break observer presets |
| 8 | [08-emit-only-loop](../examples/08-emit-only-loop/) | Loose coat — no tool host |
| 9 | [audit_pipeline.py](../examples/audit_pipeline.py) | Export slice — report, compare, verify |
| 10 | [10-observer-metrics-snapshot](../examples/10-observer-metrics-snapshot/) | Tailored coat — observer metrics snapshot |

Capstone checklist: [reference-tool-host-capstone.md](guides/reference-tool-host-capstone.md).

Expand Down
2 changes: 2 additions & 0 deletions docs/sequencer.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Ordered **prescriptive** pipelines inside a session — steps, retries, gates, p

The sequencer is **not** the runtime. It structures work **inside** a session while your **body** (Skillware host, script) executes each step.

**Skillware 0.5.4+** also ships host-level [`run_chain()`](https://github.com/arpahls/skillware/blob/main/docs/usage/skill_chaining.md) and `SkillContext` for model tool routing. Use Skillware chains for scripts and CI; use **AURA sequencer** when you need gates, conformance proof, and session export. Example 06 mirrors Skillware's `sanitize_input` chain with full audit spine.

→ Usage: [using-aura.md](using-aura.md) · Skillware: [skillware-integration.md](skillware-integration.md)

---
Expand Down
40 changes: 39 additions & 1 deletion docs/skillware-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,45 @@ AURA Harness wraps Skillware skills at **egress** — policy, approval, and audi
| **AURA membrane** | Ingress context, egress guard on every tool call |
| **Audit trail** | JSONL spine + session export |

Skillware is **optional**: `pip install "aura-harness[skillware]"` (requires Skillware ≥ 0.5.1). Tests and examples use `MockSkill` when Skillware is not installed.
Skillware is **optional**: `pip install "aura-harness[skillware]"` (see [Version compatibility](#version-compatibility) below). Tests and examples use `MockSkill` when Skillware is not installed.

---

## Version compatibility

AURA pins a **semver range**, not an exact patch — so `pip install -U` picks up Skillware **0.5.x** fixes without editing AURA on every patch release:

```text
skillware>=0.5.4,<0.6
```

| Policy | Meaning |
|---|---|
| **Floor (`>=0.5.4`)** | Minimum tested API — `SkillContext`, named `chains:`, security support window ([Skillware SECURITY.md](https://github.com/arpahls/skillware/blob/main/SECURITY.md)) |
| **Ceiling (`<0.6`)** | Conscious bump when Skillware ships breaking 0.6 API — update floor + docs in one PR |
| **What's new** | Read [Skillware CHANGELOG](https://github.com/arpahls/skillware/blob/main/CHANGELOG.md) — we do not duplicate every skill release in AURA |

CI **`skillware-live`** installs the latest compatible release from PyPI on each run. Local dev checkout: `pip install -e ../skillware` alongside AURA.

---

## Skillware chains vs AURA sequencer

Skillware **0.5.4+** adds host-level orchestration that complements (does not replace) AURA's audited sequencer:

| | **Skillware `run_chain()` / `SkillContext`** | **AURA sequencer** |
|---|---|---|
| **Owner** | Skillware host / body script | Agent profile or session spec |
| **Audit** | None by default | Full spine: `sequencer.step.*`, `tool.*`, export receipt |
| **Policy** | Host code | Egress gates, constitution, conformance on close |
| **Conditional skip** | Step `when:` in `chains:` YAML | Step `when:` on prior step result |
| **Best for** | Scripts, CI, model tool routing | Compliance SOPs, regulated pipelines |

**Rule:** Route every skill `execute()` through **`SkillwareHost`** so AURA records egress regardless of whether ordering comes from Skillware chains or AURA sequencer.

Reference parity: Skillware's `sanitize_input` chain (firewall → rewriter when `is_safe`) matches [example 06](../../examples/06-skillware-sequencer-chain/) — AURA adds the session receipt.

→ Skillware docs: [skill_chaining.md](https://github.com/arpahls/skillware/blob/main/docs/usage/skill_chaining.md) (`SkillContext`, `run_chain`, `chains:` in `.skillware.yaml`)

---

Expand Down
14 changes: 13 additions & 1 deletion docs/using-aura.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ How to attach AURA to your agent loop — from lightweight audit logging to pres

See [comparison.md](comparison.md) for loose / tight / tailored framing and competitor positioning.

### Spectrum (preview)

Optional profile block selects autonomy posture — maps to coat metaphor; full enforcement wiring [#27](https://github.com/ARPAHLS/aura/issues/27):

```yaml
spectrum:
level: mid
services: [monitor, audit]
```

`aura agent show` includes `spectrum` when set. Ingress events carry a summary when present.

AURA is the **harness (coat)**, not the runtime. Your **body** owns the loop; AURA wraps it with **membrane** boundaries and an **audit trail**.

---
Expand Down Expand Up @@ -207,7 +219,7 @@ Schema: [sequencer.schema.json](../spec/sequencer.schema.json)
pip install "aura-harness[skillware]"
```

Skillware ≥ 0.5.1 runs inside the body; AURA wraps `execute()` at egress. See [skillware-integration.md](skillware-integration.md).
Skillware ≥ 0.5.4 (see [skillware-integration.md](skillware-integration.md#version-compatibility)) runs inside the body; AURA wraps `execute()` at egress.

---

Expand Down
2 changes: 2 additions & 0 deletions examples/06-skillware-sequencer-chain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ Inspect `.aura/sessions/*.jsonl` for the full spine: `skill.registered`, `tool.i
| Compliance needs step order proof | Open-ended chat |
| Human confirm on specific steps | Ad-hoc tool use |

→ Skillware named chain equivalent: `sanitize_input` — [skill_chaining.md](https://github.com/arpahls/skillware/blob/main/docs/usage/skill_chaining.md)

→ [sequencer.md](../../docs/sequencer.md) · [aura-on-skillware.md](../../docs/guides/aura-on-skillware.md)
18 changes: 18 additions & 0 deletions examples/10-observer-metrics-snapshot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Example 10 — Observer metrics snapshot (tailored coat)

**AURA-native** tailored-coat pattern — no third-party KPI skills required.

| Piece | Role |
|---|---|
| **Monitor preset** | Aggregates tool calls and timing on the spine |
| **`metrics_snapshot` note** | Structured payload at session close for playbooks / export consumers |
| **Session export** | `.summary.json` + JSONL for external schedulers (optional) |

Use when you need SLO-style visibility before building **Limit** preset ([#46](https://github.com/ARPAHLS/aura/issues/46)) or escalation playbooks ([#38](https://github.com/ARPAHLS/aura/issues/38)). Third-party registry skills may *read* the export later; AURA enforcement stays on **observers + egress rules**.

```powershell
.venv\Scripts\activate
python examples/10-observer-metrics-snapshot/main.py
```

→ [07-observer-presets](../07-observer-presets/) · [using-aura.md](../../docs/using-aura.md) · [aura-levels.md](../../docs/aura-levels.md)
Loading
Loading