monoid-agent-kernel 0.16.1__py3-none-any.whl
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.
- monoid_agent_kernel/__init__.py +11 -0
- monoid_agent_kernel/_policy_util.py +40 -0
- monoid_agent_kernel/_proc.py +86 -0
- monoid_agent_kernel/builder.py +351 -0
- monoid_agent_kernel/cli.py +1244 -0
- monoid_agent_kernel/conformance/__init__.py +32 -0
- monoid_agent_kernel/conformance/harness.py +209 -0
- monoid_agent_kernel/conformance/profiles/__init__.py +55 -0
- monoid_agent_kernel/conformance/profiles/_metadata.py +16 -0
- monoid_agent_kernel/conformance/profiles/capability_security.py +216 -0
- monoid_agent_kernel/conformance/profiles/control_plane.py +41 -0
- monoid_agent_kernel/conformance/profiles/durable_runner.py +42 -0
- monoid_agent_kernel/conformance/profiles/message_fabric.py +42 -0
- monoid_agent_kernel/conformance/profiles/minimal_agent.py +13 -0
- monoid_agent_kernel/conformance/profiles/multi_agent.py +112 -0
- monoid_agent_kernel/conformance/profiles/provider_gateway.py +107 -0
- monoid_agent_kernel/conformance/profiles/reference_full.py +135 -0
- monoid_agent_kernel/conformance/profiles/side_effect_tool_agent.py +36 -0
- monoid_agent_kernel/conformance/profiles/tool_agent.py +39 -0
- monoid_agent_kernel/contracts.py +329 -0
- monoid_agent_kernel/core/__init__.py +1 -0
- monoid_agent_kernel/core/_util.py +145 -0
- monoid_agent_kernel/core/agents.py +883 -0
- monoid_agent_kernel/core/cancellation.py +16 -0
- monoid_agent_kernel/core/capability.py +376 -0
- monoid_agent_kernel/core/capability_revocation.py +92 -0
- monoid_agent_kernel/core/checkpoint.py +350 -0
- monoid_agent_kernel/core/content.py +101 -0
- monoid_agent_kernel/core/context.py +67 -0
- monoid_agent_kernel/core/control.py +124 -0
- monoid_agent_kernel/core/control_audit.py +99 -0
- monoid_agent_kernel/core/durable_metadata.py +116 -0
- monoid_agent_kernel/core/event_sequencing.py +164 -0
- monoid_agent_kernel/core/events.py +204 -0
- monoid_agent_kernel/core/external_agent_envelope.py +338 -0
- monoid_agent_kernel/core/frontmatter.py +140 -0
- monoid_agent_kernel/core/inbox.py +110 -0
- monoid_agent_kernel/core/lease_admission.py +57 -0
- monoid_agent_kernel/core/lifecycle.py +440 -0
- monoid_agent_kernel/core/manifest.py +88 -0
- monoid_agent_kernel/core/media.py +393 -0
- monoid_agent_kernel/core/outbox.py +212 -0
- monoid_agent_kernel/core/output_validator.py +103 -0
- monoid_agent_kernel/core/packages.py +742 -0
- monoid_agent_kernel/core/projections.py +213 -0
- monoid_agent_kernel/core/prompt.py +37 -0
- monoid_agent_kernel/core/proposal_file.py +84 -0
- monoid_agent_kernel/core/result.py +131 -0
- monoid_agent_kernel/core/schemas.py +1146 -0
- monoid_agent_kernel/core/scope.py +185 -0
- monoid_agent_kernel/core/side_effect_policy.py +153 -0
- monoid_agent_kernel/core/spec.py +325 -0
- monoid_agent_kernel/core/streaming.py +208 -0
- monoid_agent_kernel/core/subagent_runtime.py +187 -0
- monoid_agent_kernel/core/tool_approval.py +175 -0
- monoid_agent_kernel/core/tool_surface.py +505 -0
- monoid_agent_kernel/core/trace_context.py +76 -0
- monoid_agent_kernel/core/wire_validation.py +156 -0
- monoid_agent_kernel/core/workspace.py +161 -0
- monoid_agent_kernel/core/workspace_index.py +127 -0
- monoid_agent_kernel/env.py +32 -0
- monoid_agent_kernel/errors.py +105 -0
- monoid_agent_kernel/event_loader.py +47 -0
- monoid_agent_kernel/identifiers.py +50 -0
- monoid_agent_kernel/loop.py +4140 -0
- monoid_agent_kernel/loop_phases.py +561 -0
- monoid_agent_kernel/mcp/__init__.py +10 -0
- monoid_agent_kernel/mcp/client.py +227 -0
- monoid_agent_kernel/mcp/provider.py +407 -0
- monoid_agent_kernel/narration.py +92 -0
- monoid_agent_kernel/observability/__init__.py +9 -0
- monoid_agent_kernel/observability/otel.py +264 -0
- monoid_agent_kernel/permissions.py +74 -0
- monoid_agent_kernel/providers/__init__.py +7 -0
- monoid_agent_kernel/providers/_common.py +122 -0
- monoid_agent_kernel/providers/base.py +312 -0
- monoid_agent_kernel/providers/fake.py +76 -0
- monoid_agent_kernel/providers/gateway.py +474 -0
- monoid_agent_kernel/providers/openai.py +487 -0
- monoid_agent_kernel/public_view.py +173 -0
- monoid_agent_kernel/py.typed +0 -0
- monoid_agent_kernel/recorder.py +421 -0
- monoid_agent_kernel/reference/__init__.py +15 -0
- monoid_agent_kernel/reference/_shared/__init__.py +4 -0
- monoid_agent_kernel/reference/_shared/http_util.py +111 -0
- monoid_agent_kernel/reference/_shared/tokens.py +314 -0
- monoid_agent_kernel/reference/backend/__init__.py +21 -0
- monoid_agent_kernel/reference/backend/commands.py +375 -0
- monoid_agent_kernel/reference/backend/http.py +439 -0
- monoid_agent_kernel/reference/backend/jobs.py +68 -0
- monoid_agent_kernel/reference/backend/loop_factory.py +253 -0
- monoid_agent_kernel/reference/backend/outbox_dispatch.py +130 -0
- monoid_agent_kernel/reference/backend/ports.py +188 -0
- monoid_agent_kernel/reference/backend/projection.py +286 -0
- monoid_agent_kernel/reference/backend/proposal.py +220 -0
- monoid_agent_kernel/reference/backend/proposal_reader.py +16 -0
- monoid_agent_kernel/reference/backend/recovery.py +253 -0
- monoid_agent_kernel/reference/backend/run_execution.py +152 -0
- monoid_agent_kernel/reference/backend/run_preparation.py +197 -0
- monoid_agent_kernel/reference/backend/run_state.py +243 -0
- monoid_agent_kernel/reference/backend/run_types.py +128 -0
- monoid_agent_kernel/reference/backend/runtime_config.py +147 -0
- monoid_agent_kernel/reference/backend/service.py +1664 -0
- monoid_agent_kernel/reference/backend/session.py +280 -0
- monoid_agent_kernel/reference/backend/session_drive.py +231 -0
- monoid_agent_kernel/reference/capability.py +101 -0
- monoid_agent_kernel/reference/conformance.py +1777 -0
- monoid_agent_kernel/reference/llm_gateway/__init__.py +14 -0
- monoid_agent_kernel/reference/llm_gateway/http.py +225 -0
- monoid_agent_kernel/reference/llm_gateway/providers.py +96 -0
- monoid_agent_kernel/reference/llm_gateway/service.py +404 -0
- monoid_agent_kernel/reference/mcp_gateway/__init__.py +26 -0
- monoid_agent_kernel/reference/mcp_gateway/http.py +187 -0
- monoid_agent_kernel/reference/mcp_gateway/service.py +206 -0
- monoid_agent_kernel/reference/outbox.py +135 -0
- monoid_agent_kernel/reference/stores/__init__.py +20 -0
- monoid_agent_kernel/reference/stores/lease.py +116 -0
- monoid_agent_kernel/reference/stores/sqlite.py +295 -0
- monoid_agent_kernel/reference/studio/README.md +97 -0
- monoid_agent_kernel/reference/studio/__init__.py +21 -0
- monoid_agent_kernel/reference/studio/activity.py +53 -0
- monoid_agent_kernel/reference/studio/cli.py +481 -0
- monoid_agent_kernel/reference/studio/sample-skills/code-review-checklist/SKILL.md +25 -0
- monoid_agent_kernel/reference/studio/sample-skills/code-review-checklist/references/review-checklist.md +8 -0
- monoid_agent_kernel/reference/studio/sample-skills/commit-message/SKILL.md +32 -0
- monoid_agent_kernel/reference/studio/sample-skills/incident-summary/SKILL.md +24 -0
- monoid_agent_kernel/reference/studio/sample-skills/incident-summary/references/incident-template.md +32 -0
- monoid_agent_kernel/reference/studio/sample-skills/release-notes/SKILL.md +24 -0
- monoid_agent_kernel/reference/studio/sample-skills/release-notes/references/release-note-template.md +33 -0
- monoid_agent_kernel/reference/studio/sample-skills/release-notes/scripts/collect_changes.py +51 -0
- monoid_agent_kernel/reference/studio/server.py +1922 -0
- monoid_agent_kernel/reference/studio/web/index.html +1877 -0
- monoid_agent_kernel/reference/studio/web/settings.html +108 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/auto-render.min.js +1 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/katex.min.css +1 -0
- monoid_agent_kernel/reference/studio/web/vendor/katex/katex.min.js +1 -0
- monoid_agent_kernel/reference/studio/window.py +72 -0
- monoid_agent_kernel/reference/web_gateway/__init__.py +6 -0
- monoid_agent_kernel/reference/web_gateway/http.py +155 -0
- monoid_agent_kernel/reference/web_gateway/providers.py +807 -0
- monoid_agent_kernel/reference/web_gateway/service.py +559 -0
- monoid_agent_kernel/shell.py +722 -0
- monoid_agent_kernel/skills/__init__.py +20 -0
- monoid_agent_kernel/skills/definition.py +82 -0
- monoid_agent_kernel/skills/loader.py +55 -0
- monoid_agent_kernel/skills/provider.py +378 -0
- monoid_agent_kernel/subagent_loader.py +56 -0
- monoid_agent_kernel/tasks.py +1326 -0
- monoid_agent_kernel/tool_loader.py +51 -0
- monoid_agent_kernel/tool_services/__init__.py +8 -0
- monoid_agent_kernel/tool_services/base.py +25 -0
- monoid_agent_kernel/tool_services/jobs.py +47 -0
- monoid_agent_kernel/tool_services/shell.py +255 -0
- monoid_agent_kernel/tool_services/web.py +356 -0
- monoid_agent_kernel/tools/__init__.py +2 -0
- monoid_agent_kernel/tools/base.py +205 -0
- monoid_agent_kernel/tools/builtin.py +958 -0
- monoid_agent_kernel/tools/decorator.py +132 -0
- monoid_agent_kernel/tools/tool_ids.py +62 -0
- monoid_agent_kernel/web.py +171 -0
- monoid_agent_kernel/workspace/__init__.py +2 -0
- monoid_agent_kernel/workspace/local.py +1004 -0
- monoid_agent_kernel/workspace/paths.py +30 -0
- monoid_agent_kernel-0.16.1.dist-info/METADATA +709 -0
- monoid_agent_kernel-0.16.1.dist-info/RECORD +191 -0
- monoid_agent_kernel-0.16.1.dist-info/WHEEL +4 -0
- monoid_agent_kernel-0.16.1.dist-info/entry_points.txt +3 -0
- monoid_agent_kernel-0.16.1.dist-info/licenses/LICENSE +202 -0
- monoid_agent_kernel-0.16.1.dist-info/licenses/NOTICE +8 -0
- native_agent_runner/__init__.py +103 -0
- native_agent_runner/py.typed +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Conformance profile metadata and harness protocols."""
|
|
2
|
+
|
|
3
|
+
from .harness import (
|
|
4
|
+
BackendHarness,
|
|
5
|
+
CapabilityHarness,
|
|
6
|
+
ConformanceHarness,
|
|
7
|
+
ControlPlaneHarness,
|
|
8
|
+
DurableRunnerHarness,
|
|
9
|
+
GatewayHarness,
|
|
10
|
+
MessageFabricHarness,
|
|
11
|
+
MultiAgentBackendHarness,
|
|
12
|
+
SideEffectHarness,
|
|
13
|
+
ToolAgentHarness,
|
|
14
|
+
)
|
|
15
|
+
from .profiles import PROFILES, PROFILE_BY_ID, ProfileMetadata, get_profile
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"BackendHarness",
|
|
19
|
+
"CapabilityHarness",
|
|
20
|
+
"ConformanceHarness",
|
|
21
|
+
"ControlPlaneHarness",
|
|
22
|
+
"DurableRunnerHarness",
|
|
23
|
+
"GatewayHarness",
|
|
24
|
+
"MessageFabricHarness",
|
|
25
|
+
"MultiAgentBackendHarness",
|
|
26
|
+
"SideEffectHarness",
|
|
27
|
+
"ToolAgentHarness",
|
|
28
|
+
"PROFILES",
|
|
29
|
+
"PROFILE_BY_ID",
|
|
30
|
+
"ProfileMetadata",
|
|
31
|
+
"get_profile",
|
|
32
|
+
]
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""Protocols implemented by conformance test adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Mapping, Protocol, Sequence, runtime_checkable
|
|
6
|
+
|
|
7
|
+
JsonObject = Mapping[str, Any]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@runtime_checkable
|
|
11
|
+
class ConformanceHarness(Protocol):
|
|
12
|
+
"""Common metadata exposed by every conformance harness."""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def harness_id(self) -> str:
|
|
16
|
+
"""Stable identifier used in test output."""
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def supported_profiles(self) -> Sequence[str]:
|
|
20
|
+
"""Profile ids the harness intends to run."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@runtime_checkable
|
|
24
|
+
class BackendHarness(ConformanceHarness, Protocol):
|
|
25
|
+
"""Raw backend operations kept for compatibility and custom harnesses."""
|
|
26
|
+
|
|
27
|
+
def submit_run(self, request: JsonObject) -> JsonObject:
|
|
28
|
+
"""Submit a run and return a handle containing at least run id and token."""
|
|
29
|
+
|
|
30
|
+
def status(self, run_id: str, token: str) -> JsonObject:
|
|
31
|
+
"""Return the backend status projection for a run."""
|
|
32
|
+
|
|
33
|
+
def events(self, run_id: str, token: str, *, from_seq: int = 0, limit: int | None = None) -> JsonObject:
|
|
34
|
+
"""Return a page of run events."""
|
|
35
|
+
|
|
36
|
+
def descendant_events(
|
|
37
|
+
self,
|
|
38
|
+
run_id: str,
|
|
39
|
+
token: str,
|
|
40
|
+
descendant_run_id: str,
|
|
41
|
+
*,
|
|
42
|
+
from_seq: int = 0,
|
|
43
|
+
limit: int | None = None,
|
|
44
|
+
) -> JsonObject:
|
|
45
|
+
"""Return a page of events for one authorized descendant run."""
|
|
46
|
+
|
|
47
|
+
def diagnostics(self, run_id: str, token: str, *, event_limit: int = 50) -> JsonObject:
|
|
48
|
+
"""Return the diagnostics aggregate for a run."""
|
|
49
|
+
|
|
50
|
+
def result(self, run_id: str, token: str) -> JsonObject:
|
|
51
|
+
"""Return the backend run result projection."""
|
|
52
|
+
|
|
53
|
+
def runtime_config(self, run_id: str, token: str) -> JsonObject:
|
|
54
|
+
"""Return the current runtime config projection for a run."""
|
|
55
|
+
|
|
56
|
+
def replace_runtime_config(
|
|
57
|
+
self,
|
|
58
|
+
run_id: str,
|
|
59
|
+
token: str,
|
|
60
|
+
config: JsonObject,
|
|
61
|
+
*,
|
|
62
|
+
expected_version: int,
|
|
63
|
+
issuer: str,
|
|
64
|
+
reason: str,
|
|
65
|
+
) -> JsonObject:
|
|
66
|
+
"""Replace the runtime config for a live run."""
|
|
67
|
+
|
|
68
|
+
def resume_run(self, run_id: str, token: str) -> JsonObject:
|
|
69
|
+
"""Materialize and resume one run from durable recovery metadata."""
|
|
70
|
+
|
|
71
|
+
def recover_runs(self) -> Sequence[str]:
|
|
72
|
+
"""Recover all discoverable parked runs for this harness instance."""
|
|
73
|
+
|
|
74
|
+
def restart(self, *, local_state: str = "same") -> BackendHarness:
|
|
75
|
+
"""Return a fresh harness instance over the same durable state."""
|
|
76
|
+
|
|
77
|
+
def task_result(self, run_id: str, token: str, task_id: str) -> JsonObject:
|
|
78
|
+
"""Return the stored result for one backend task."""
|
|
79
|
+
|
|
80
|
+
def dispatch(self, command: JsonObject) -> JsonObject:
|
|
81
|
+
"""Dispatch one backend control command."""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@runtime_checkable
|
|
85
|
+
class ToolAgentHarness(ConformanceHarness, Protocol):
|
|
86
|
+
"""Tool-agent behavior cases."""
|
|
87
|
+
|
|
88
|
+
def run_tool_surface_admission_case(self) -> JsonObject:
|
|
89
|
+
"""Run a tool surface admission case with a denied unavailable/quota-limited tool."""
|
|
90
|
+
|
|
91
|
+
def run_generic_ask_approval_case(self) -> JsonObject:
|
|
92
|
+
"""Run generic authorization='ask' approval, denial, and stale replay cases."""
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@runtime_checkable
|
|
96
|
+
class ControlPlaneHarness(ConformanceHarness, Protocol):
|
|
97
|
+
"""Control-plane behavior cases."""
|
|
98
|
+
|
|
99
|
+
def run_control_decision_case(self) -> JsonObject:
|
|
100
|
+
"""Run approve/deny decision handling and decision audit behavior."""
|
|
101
|
+
|
|
102
|
+
def run_control_audit_sequence_case(self) -> JsonObject:
|
|
103
|
+
"""Run authorized, failed, unauthorized, and terminal audit sequencing behavior."""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@runtime_checkable
|
|
107
|
+
class DurableRunnerHarness(ConformanceHarness, Protocol):
|
|
108
|
+
"""Durable-runner behavior cases."""
|
|
109
|
+
|
|
110
|
+
def run_event_sequence_case(self) -> JsonObject:
|
|
111
|
+
"""Run event sequencing and diagnostics projection behavior."""
|
|
112
|
+
|
|
113
|
+
def run_recovery_metadata_case(self) -> JsonObject:
|
|
114
|
+
"""Run recovery metadata and restart materialization behavior."""
|
|
115
|
+
|
|
116
|
+
def run_subagent_diagnostics_case(self) -> JsonObject:
|
|
117
|
+
"""Run subagent diagnostics summary behavior."""
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@runtime_checkable
|
|
121
|
+
class MultiAgentBackendHarness(ConformanceHarness, Protocol):
|
|
122
|
+
"""Backend-visible multi-agent behavior cases."""
|
|
123
|
+
|
|
124
|
+
def run_subagent_boundary_case(self) -> JsonObject:
|
|
125
|
+
"""Run subagent identity, trace, diagnostics, and accounting behavior."""
|
|
126
|
+
|
|
127
|
+
def run_subagent_capability_boundary_case(self) -> JsonObject:
|
|
128
|
+
"""Run child capability-boundary behavior after parent revocation."""
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@runtime_checkable
|
|
132
|
+
class SideEffectHarness(ConformanceHarness, Protocol):
|
|
133
|
+
"""Backend operations used by side-effect-tool-agent profiles."""
|
|
134
|
+
|
|
135
|
+
def run_outbox_dispatched_case(self) -> JsonObject:
|
|
136
|
+
"""Run a strict outbox side-effect case that stages and dispatches one request."""
|
|
137
|
+
|
|
138
|
+
def run_pending_recovery_case(self) -> JsonObject:
|
|
139
|
+
"""Run a strict outbox side-effect case whose pending request survives restart."""
|
|
140
|
+
|
|
141
|
+
def run_strict_rejected_case(self) -> JsonObject:
|
|
142
|
+
"""Run a strict external side-effect case rejected before handler execution."""
|
|
143
|
+
|
|
144
|
+
def run_idempotent_inline_case(self) -> JsonObject:
|
|
145
|
+
"""Run an idempotent inline external side-effect case."""
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@runtime_checkable
|
|
149
|
+
class MessageFabricHarness(ConformanceHarness, Protocol):
|
|
150
|
+
"""Backend operations used by external agent message-fabric profiles."""
|
|
151
|
+
|
|
152
|
+
def run_two_peer_exchange_case(self) -> JsonObject:
|
|
153
|
+
"""Run a two-peer exchange over the external-agent message fabric."""
|
|
154
|
+
|
|
155
|
+
def run_malformed_envelope_case(self) -> JsonObject:
|
|
156
|
+
"""Run a malformed external-agent envelope rejection case."""
|
|
157
|
+
|
|
158
|
+
def run_duplicate_after_restart_case(self) -> JsonObject:
|
|
159
|
+
"""Run a duplicate message case that survives restart."""
|
|
160
|
+
|
|
161
|
+
def run_peer_unavailable_case(self) -> JsonObject:
|
|
162
|
+
"""Run a peer-unavailable case that leaves a retryable pending request."""
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@runtime_checkable
|
|
166
|
+
class GatewayHarness(ConformanceHarness, Protocol):
|
|
167
|
+
"""Gateway operation used by provider-gateway profiles."""
|
|
168
|
+
|
|
169
|
+
def call_gateway(
|
|
170
|
+
self,
|
|
171
|
+
capability: str,
|
|
172
|
+
payload: JsonObject,
|
|
173
|
+
*,
|
|
174
|
+
signed_capability: str | None = None,
|
|
175
|
+
signed_scope: JsonObject | None = None,
|
|
176
|
+
) -> JsonObject:
|
|
177
|
+
"""Call one gateway capability with a normalized payload."""
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@runtime_checkable
|
|
181
|
+
class CapabilityHarness(ConformanceHarness, Protocol):
|
|
182
|
+
"""Capability operations used by capability-security profiles."""
|
|
183
|
+
|
|
184
|
+
def request_capability(self, payload: JsonObject) -> JsonObject:
|
|
185
|
+
"""Create or simulate one capability request."""
|
|
186
|
+
|
|
187
|
+
def grant_capability(self, request_id: str, lease: JsonObject) -> JsonObject:
|
|
188
|
+
"""Grant a capability request with a lease payload."""
|
|
189
|
+
|
|
190
|
+
def deny_capability(self, request_id: str, result: JsonObject) -> JsonObject:
|
|
191
|
+
"""Deny a capability request with a result payload."""
|
|
192
|
+
|
|
193
|
+
def revoke_capability(self, payload: JsonObject) -> JsonObject:
|
|
194
|
+
"""Revoke capabilities according to the payload."""
|
|
195
|
+
|
|
196
|
+
def token_for(self, capability: str, *, now: float) -> str | None:
|
|
197
|
+
"""Return the currently usable token handle for one capability."""
|
|
198
|
+
|
|
199
|
+
def valid_lease(self, capability: str, scope: JsonObject, *, now: float) -> JsonObject | None:
|
|
200
|
+
"""Return a currently valid lease for one capability and scope."""
|
|
201
|
+
|
|
202
|
+
def export_revocations(self) -> JsonObject:
|
|
203
|
+
"""Return serialized revocation state."""
|
|
204
|
+
|
|
205
|
+
def import_revocations(self, payload: JsonObject) -> JsonObject:
|
|
206
|
+
"""Merge serialized revocation state and return the current export."""
|
|
207
|
+
|
|
208
|
+
def fork_child(self) -> CapabilityHarness:
|
|
209
|
+
"""Return a child capability harness sharing revocation state."""
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Conformance profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ._metadata import ProfileMetadata
|
|
6
|
+
from .capability_security import PROFILE as CAPABILITY_SECURITY
|
|
7
|
+
from .control_plane import PROFILE as CONTROL_PLANE
|
|
8
|
+
from .durable_runner import PROFILE as DURABLE_RUNNER
|
|
9
|
+
from .message_fabric import PROFILE as MESSAGE_FABRIC
|
|
10
|
+
from .minimal_agent import PROFILE as MINIMAL_AGENT
|
|
11
|
+
from .multi_agent import PROFILE as MULTI_AGENT
|
|
12
|
+
from .provider_gateway import PROFILE as PROVIDER_GATEWAY
|
|
13
|
+
from .reference_full import PROFILE as REFERENCE_FULL
|
|
14
|
+
from .side_effect_tool_agent import PROFILE as SIDE_EFFECT_TOOL_AGENT
|
|
15
|
+
from .tool_agent import PROFILE as TOOL_AGENT
|
|
16
|
+
|
|
17
|
+
PROFILES: tuple[ProfileMetadata, ...] = (
|
|
18
|
+
MINIMAL_AGENT,
|
|
19
|
+
TOOL_AGENT,
|
|
20
|
+
SIDE_EFFECT_TOOL_AGENT,
|
|
21
|
+
MESSAGE_FABRIC,
|
|
22
|
+
DURABLE_RUNNER,
|
|
23
|
+
CONTROL_PLANE,
|
|
24
|
+
CAPABILITY_SECURITY,
|
|
25
|
+
PROVIDER_GATEWAY,
|
|
26
|
+
MULTI_AGENT,
|
|
27
|
+
REFERENCE_FULL,
|
|
28
|
+
)
|
|
29
|
+
PROFILE_BY_ID: dict[str, ProfileMetadata] = {profile.profile_id: profile for profile in PROFILES}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_profile(profile_id: str) -> ProfileMetadata:
|
|
33
|
+
"""Return profile metadata by stable id."""
|
|
34
|
+
try:
|
|
35
|
+
return PROFILE_BY_ID[profile_id]
|
|
36
|
+
except KeyError as exc:
|
|
37
|
+
raise KeyError(f"unknown conformance profile: {profile_id}") from exc
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"CAPABILITY_SECURITY",
|
|
42
|
+
"CONTROL_PLANE",
|
|
43
|
+
"DURABLE_RUNNER",
|
|
44
|
+
"MINIMAL_AGENT",
|
|
45
|
+
"MESSAGE_FABRIC",
|
|
46
|
+
"MULTI_AGENT",
|
|
47
|
+
"PROFILES",
|
|
48
|
+
"PROFILE_BY_ID",
|
|
49
|
+
"PROVIDER_GATEWAY",
|
|
50
|
+
"ProfileMetadata",
|
|
51
|
+
"REFERENCE_FULL",
|
|
52
|
+
"SIDE_EFFECT_TOOL_AGENT",
|
|
53
|
+
"TOOL_AGENT",
|
|
54
|
+
"get_profile",
|
|
55
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Shared conformance profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class ProfileMetadata:
|
|
10
|
+
"""Static description of one conformance profile."""
|
|
11
|
+
|
|
12
|
+
profile_id: str
|
|
13
|
+
title: str
|
|
14
|
+
summary: str
|
|
15
|
+
rule_ids: tuple[str, ...]
|
|
16
|
+
harnesses: tuple[str, ...]
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Capability-security profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from monoid_agent_kernel.conformance.harness import CapabilityHarness
|
|
9
|
+
|
|
10
|
+
from ._metadata import ProfileMetadata
|
|
11
|
+
|
|
12
|
+
PROFILE = ProfileMetadata(
|
|
13
|
+
profile_id="capability-security",
|
|
14
|
+
title="Capability Security",
|
|
15
|
+
summary="Capability-gated runtime with scope narrowing, lease admission, denial, and revocation rules.",
|
|
16
|
+
rule_ids=(
|
|
17
|
+
"OR-01-SCOPE-RELATION",
|
|
18
|
+
"OR-02-CAPABILITY-BOUNDARY",
|
|
19
|
+
"OR-03-LEASE-ADMISSION",
|
|
20
|
+
"OR-04-REVOCATION-SCOPE",
|
|
21
|
+
"OR-06-CONTROL-AUDIT",
|
|
22
|
+
"OR-09-SUBAGENT-BOUNDARY",
|
|
23
|
+
),
|
|
24
|
+
harnesses=("backend", "capability", "gateway"),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def assert_capability_security_lease_admission(harness: CapabilityHarness) -> None:
|
|
29
|
+
"""Run the lease-admission conformance smoke matrix."""
|
|
30
|
+
request = harness.request_capability(
|
|
31
|
+
{
|
|
32
|
+
"capability": "web.search",
|
|
33
|
+
"scope": {"allowed_domains": ["*.example.test"], "max_results": 5},
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
request_id = str(request["request_id"])
|
|
37
|
+
lease = {
|
|
38
|
+
"lease_id": "lease_profile_ok",
|
|
39
|
+
"capability": "web.search",
|
|
40
|
+
"token_ref": "approved:web.search",
|
|
41
|
+
"expires_at": 4_102_444_800.0,
|
|
42
|
+
"issued_at": 1_700_000_000.0,
|
|
43
|
+
"max_expires_at": 4_102_445_000.0,
|
|
44
|
+
"durable": True,
|
|
45
|
+
"scope": {"allowed_domains": ["docs.example.test"], "max_results": 3},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
admitted = harness.grant_capability(request_id, lease)
|
|
49
|
+
assert admitted["lease_id"] == lease["lease_id"]
|
|
50
|
+
assert admitted["capability"] == lease["capability"]
|
|
51
|
+
assert admitted["token_ref"] == lease["token_ref"]
|
|
52
|
+
assert admitted["issued_at"] == lease["issued_at"]
|
|
53
|
+
assert admitted["max_expires_at"] == lease["max_expires_at"]
|
|
54
|
+
assert admitted["durable"] is True
|
|
55
|
+
assert admitted["scope"] == lease["scope"]
|
|
56
|
+
|
|
57
|
+
widened = harness.request_capability(
|
|
58
|
+
{"capability": "web.search", "scope": {"allowed_domains": ["docs.example.test"], "max_results": 2}}
|
|
59
|
+
)
|
|
60
|
+
_assert_raises(
|
|
61
|
+
lambda: harness.grant_capability(
|
|
62
|
+
str(widened["request_id"]),
|
|
63
|
+
{
|
|
64
|
+
"capability": "web.search",
|
|
65
|
+
"token_ref": "approved:web.search",
|
|
66
|
+
"expires_at": 4_102_444_800.0,
|
|
67
|
+
"scope": {"allowed_domains": ["*.example.test"], "max_results": 5},
|
|
68
|
+
},
|
|
69
|
+
),
|
|
70
|
+
"wider scope",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
mismatch = harness.request_capability({"capability": "web.search", "scope": {}})
|
|
74
|
+
_assert_raises(
|
|
75
|
+
lambda: harness.grant_capability(
|
|
76
|
+
str(mismatch["request_id"]),
|
|
77
|
+
{
|
|
78
|
+
"capability": "web.fetch",
|
|
79
|
+
"token_ref": "approved:web.fetch",
|
|
80
|
+
"expires_at": 4_102_444_800.0,
|
|
81
|
+
"scope": {},
|
|
82
|
+
},
|
|
83
|
+
),
|
|
84
|
+
"web.fetch",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
denial = harness.deny_capability(
|
|
88
|
+
request_id,
|
|
89
|
+
{
|
|
90
|
+
"answer": "Approve",
|
|
91
|
+
"approved": True,
|
|
92
|
+
"granted": True,
|
|
93
|
+
"lease": {"capability": "web.search", "token_ref": "secret-ref://lease"},
|
|
94
|
+
"token_ref": "secret-ref://lease",
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
assert denial["answer"] == "Deny"
|
|
98
|
+
assert denial["approved"] is False
|
|
99
|
+
assert denial["granted"] is False
|
|
100
|
+
assert denial["reason"]
|
|
101
|
+
assert "lease" not in denial
|
|
102
|
+
assert "token_ref" not in denial
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def assert_capability_security_revocation_profile(harness: CapabilityHarness) -> None:
|
|
106
|
+
"""Run the capability revocation conformance smoke matrix."""
|
|
107
|
+
_admit_profile_lease(
|
|
108
|
+
harness,
|
|
109
|
+
capability="web.search",
|
|
110
|
+
lease_id="lease_revoke_cap",
|
|
111
|
+
token_ref="token:web.search",
|
|
112
|
+
issued_at=100.0,
|
|
113
|
+
scope={"allowed_domains": ["docs.example.test"]},
|
|
114
|
+
)
|
|
115
|
+
assert harness.token_for("web.search", now=200.0) == "token:web.search"
|
|
116
|
+
assert harness.valid_lease("web.search", {"allowed_domains": ["docs.example.test"]}, now=200.0)
|
|
117
|
+
harness.revoke_capability({"capability": "web.search"})
|
|
118
|
+
assert harness.token_for("web.search", now=200.0) is None
|
|
119
|
+
assert harness.valid_lease("web.search", {"allowed_domains": ["docs.example.test"]}, now=200.0) is None
|
|
120
|
+
|
|
121
|
+
_admit_profile_lease(
|
|
122
|
+
harness,
|
|
123
|
+
capability="web.fetch",
|
|
124
|
+
lease_id="lease_revoke_id",
|
|
125
|
+
token_ref="token:web.fetch",
|
|
126
|
+
issued_at=200.0,
|
|
127
|
+
)
|
|
128
|
+
_admit_profile_lease(
|
|
129
|
+
harness,
|
|
130
|
+
capability="web.context",
|
|
131
|
+
lease_id="lease_revoke_other",
|
|
132
|
+
token_ref="token:web.context",
|
|
133
|
+
issued_at=200.0,
|
|
134
|
+
)
|
|
135
|
+
harness.revoke_capability({"lease_id": "lease_revoke_id"})
|
|
136
|
+
assert harness.token_for("web.fetch", now=300.0) is None
|
|
137
|
+
assert harness.token_for("web.context", now=300.0) == "token:web.context"
|
|
138
|
+
|
|
139
|
+
_admit_profile_lease(
|
|
140
|
+
harness,
|
|
141
|
+
capability="cap.old",
|
|
142
|
+
lease_id="lease_old",
|
|
143
|
+
token_ref="token:old",
|
|
144
|
+
issued_at=100.0,
|
|
145
|
+
)
|
|
146
|
+
_admit_profile_lease(
|
|
147
|
+
harness,
|
|
148
|
+
capability="cap.new",
|
|
149
|
+
lease_id="lease_new",
|
|
150
|
+
token_ref="token:new",
|
|
151
|
+
issued_at=200.0,
|
|
152
|
+
)
|
|
153
|
+
harness.revoke_capability({"before": 150.0})
|
|
154
|
+
assert harness.token_for("cap.old", now=300.0) is None
|
|
155
|
+
assert harness.token_for("cap.new", now=300.0) == "token:new"
|
|
156
|
+
harness.revoke_capability({"before": 50.0})
|
|
157
|
+
assert harness.export_revocations()["revoked_before"] == 150.0
|
|
158
|
+
|
|
159
|
+
_admit_profile_lease(
|
|
160
|
+
harness,
|
|
161
|
+
capability="cap.persist",
|
|
162
|
+
lease_id="lease_persist",
|
|
163
|
+
token_ref="token:persist",
|
|
164
|
+
issued_at=200.0,
|
|
165
|
+
)
|
|
166
|
+
harness.revoke_capability({"capability": "cap.persist", "lease_id": "lease_extra"})
|
|
167
|
+
exported = harness.export_revocations()
|
|
168
|
+
assert "cap.persist" in exported["revoked_capabilities"]
|
|
169
|
+
assert "lease_extra" in exported["revoked_lease_ids"]
|
|
170
|
+
assert harness.import_revocations(exported) == exported
|
|
171
|
+
|
|
172
|
+
_admit_profile_lease(
|
|
173
|
+
harness,
|
|
174
|
+
capability="cap.star",
|
|
175
|
+
lease_id="lease_star",
|
|
176
|
+
token_ref="token:star",
|
|
177
|
+
issued_at=200.0,
|
|
178
|
+
)
|
|
179
|
+
wildcard = harness.revoke_capability({"capability": "*"})
|
|
180
|
+
assert wildcard["capabilities"] == ["*"]
|
|
181
|
+
assert harness.token_for("cap.star", now=300.0) is None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _admit_profile_lease(
|
|
185
|
+
harness: CapabilityHarness,
|
|
186
|
+
*,
|
|
187
|
+
capability: str,
|
|
188
|
+
lease_id: str,
|
|
189
|
+
token_ref: str,
|
|
190
|
+
issued_at: float,
|
|
191
|
+
scope: dict[str, Any] | None = None,
|
|
192
|
+
durable: bool = False,
|
|
193
|
+
) -> dict[str, Any]:
|
|
194
|
+
request = harness.request_capability({"capability": capability, "scope": scope or {}})
|
|
195
|
+
return harness.grant_capability(
|
|
196
|
+
str(request["request_id"]),
|
|
197
|
+
{
|
|
198
|
+
"lease_id": lease_id,
|
|
199
|
+
"capability": capability,
|
|
200
|
+
"token_ref": token_ref,
|
|
201
|
+
"expires_at": 4_102_444_800.0,
|
|
202
|
+
"issued_at": issued_at,
|
|
203
|
+
"durable": durable,
|
|
204
|
+
"scope": scope or {},
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _assert_raises(operation: Callable[[], Any], message: str) -> None:
|
|
210
|
+
try:
|
|
211
|
+
operation()
|
|
212
|
+
except Exception as exc:
|
|
213
|
+
if message not in str(exc):
|
|
214
|
+
raise AssertionError(f"expected error containing {message!r}, got {exc!r}") from exc
|
|
215
|
+
return
|
|
216
|
+
raise AssertionError(f"expected error containing {message!r}")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Control-plane profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from monoid_agent_kernel.conformance.harness import ControlPlaneHarness
|
|
6
|
+
|
|
7
|
+
from ._metadata import ProfileMetadata
|
|
8
|
+
|
|
9
|
+
PROFILE = ProfileMetadata(
|
|
10
|
+
profile_id="control-plane",
|
|
11
|
+
title="Control Plane",
|
|
12
|
+
summary="Backend with external control commands, audit events, lifecycle policy, and stable results.",
|
|
13
|
+
rule_ids=(
|
|
14
|
+
"OR-03-LEASE-ADMISSION",
|
|
15
|
+
"OR-05-EVENT-SEQUENCING",
|
|
16
|
+
"OR-06-CONTROL-AUDIT",
|
|
17
|
+
"OR-07-DURABLE-METADATA",
|
|
18
|
+
),
|
|
19
|
+
harnesses=("control-plane",),
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def assert_control_plane_decision_profile(harness: ControlPlaneHarness) -> None:
|
|
24
|
+
"""Run the approve/deny control decision smoke matrix."""
|
|
25
|
+
result = harness.run_control_decision_case()
|
|
26
|
+
assert result["approve_delivered"] is True
|
|
27
|
+
assert result["deny_delivered"] is True
|
|
28
|
+
assert result["denied_result_sanitized"] is True
|
|
29
|
+
assert result["approve_audit_recorded"] is True
|
|
30
|
+
assert result["deny_audit_recorded"] is True
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def assert_control_plane_audit_sequence_profile(harness: ControlPlaneHarness) -> None:
|
|
34
|
+
"""Run the control audit sequencing smoke matrix."""
|
|
35
|
+
result = harness.run_control_audit_sequence_case()
|
|
36
|
+
assert result["authorized_completed"] is True
|
|
37
|
+
assert result["failed_audit_recorded"] is True
|
|
38
|
+
assert result["unauthorized_excluded"] is True
|
|
39
|
+
assert result["terminal_audit_appended"] is True
|
|
40
|
+
assert result["sequence_monotonic"] is True
|
|
41
|
+
assert result["secrets_redacted"] is True
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Durable runner profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from monoid_agent_kernel.conformance.harness import DurableRunnerHarness
|
|
6
|
+
|
|
7
|
+
from ._metadata import ProfileMetadata
|
|
8
|
+
|
|
9
|
+
PROFILE = ProfileMetadata(
|
|
10
|
+
profile_id="durable-runner",
|
|
11
|
+
title="Durable Runner",
|
|
12
|
+
summary="Backend that preserves run state, event sequence, diagnostics, and recovery metadata.",
|
|
13
|
+
rule_ids=("OR-05-EVENT-SEQUENCING", "OR-07-DURABLE-METADATA", "OR-09-SUBAGENT-BOUNDARY"),
|
|
14
|
+
harnesses=("durable-runner",),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def assert_durable_runner_event_sequence_profile(harness: DurableRunnerHarness) -> None:
|
|
19
|
+
"""Run the event sequence and diagnostics smoke matrix."""
|
|
20
|
+
result = harness.run_event_sequence_case()
|
|
21
|
+
assert result["sequence_monotonic"] is True
|
|
22
|
+
assert result["control_completed"] is True
|
|
23
|
+
assert result["diagnostics_latest_seq_projected"] is True
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def assert_durable_runner_recovery_metadata_profile(harness: DurableRunnerHarness) -> None:
|
|
27
|
+
"""Run the recovery metadata smoke matrix."""
|
|
28
|
+
result = harness.run_recovery_metadata_case()
|
|
29
|
+
assert result["same_restart_resumed"] is True
|
|
30
|
+
assert result["same_runtime_config_recovered"] is True
|
|
31
|
+
assert result["empty_restart_resumed"] is True
|
|
32
|
+
assert result["empty_runtime_config_recovered"] is True
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def assert_durable_runner_subagent_diagnostics_profile(harness: DurableRunnerHarness) -> None:
|
|
36
|
+
"""Run the subagent diagnostics projection smoke matrix."""
|
|
37
|
+
result = harness.run_subagent_diagnostics_case()
|
|
38
|
+
assert result["diagnostics_summary_present"] is True
|
|
39
|
+
assert result["identity_projected"] is True
|
|
40
|
+
assert result["trace_linked"] is True
|
|
41
|
+
assert result["status_completed"] is True
|
|
42
|
+
assert result["usage_rollup_matches"] is True
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""External agent message-fabric profile metadata and assertions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from monoid_agent_kernel.conformance.harness import MessageFabricHarness
|
|
6
|
+
|
|
7
|
+
from ._metadata import ProfileMetadata
|
|
8
|
+
|
|
9
|
+
PROFILE = ProfileMetadata(
|
|
10
|
+
profile_id="message-fabric",
|
|
11
|
+
title="Message Fabric",
|
|
12
|
+
summary="Agent integration that exchanges external-agent messages through durable inbox/outbox envelopes.",
|
|
13
|
+
rule_ids=("OR-13-EXTERNAL-AGENT-ENVELOPE",),
|
|
14
|
+
harnesses=("message-fabric",),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def assert_message_fabric_profile(harness: MessageFabricHarness) -> None:
|
|
19
|
+
"""Run the external-agent envelope and durable message-fabric smoke matrix."""
|
|
20
|
+
|
|
21
|
+
two_peer = harness.run_two_peer_exchange_case()
|
|
22
|
+
assert two_peer["planner_dispatched"] is True
|
|
23
|
+
assert two_peer["worker_replied"] is True
|
|
24
|
+
assert two_peer["planner_trace_preserved"] is True
|
|
25
|
+
assert two_peer["worker_trace_preserved"] is True
|
|
26
|
+
|
|
27
|
+
malformed = harness.run_malformed_envelope_case()
|
|
28
|
+
assert malformed["status"] == "rejected"
|
|
29
|
+
assert malformed["error_code"] == "external_agent_envelope_invalid"
|
|
30
|
+
|
|
31
|
+
duplicate = harness.run_duplicate_after_restart_case()
|
|
32
|
+
assert duplicate["first_status"] == "queued"
|
|
33
|
+
assert duplicate["duplicate_status_after_restart"] == "duplicate"
|
|
34
|
+
assert duplicate["message_id"] in duplicate["seen_inbox_ids_after_restart"]
|
|
35
|
+
|
|
36
|
+
unavailable = harness.run_peer_unavailable_case()
|
|
37
|
+
assert unavailable["pending"] is True
|
|
38
|
+
assert unavailable["status"] == "pending"
|
|
39
|
+
assert unavailable["attempts"] >= 1
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
__all__ = ["PROFILE", "assert_message_fabric_profile"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Minimal local agent profile metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ._metadata import ProfileMetadata
|
|
6
|
+
|
|
7
|
+
PROFILE = ProfileMetadata(
|
|
8
|
+
profile_id="minimal-agent",
|
|
9
|
+
title="Minimal Agent",
|
|
10
|
+
summary="Local loop or chatbot-style integration with basic lifecycle and model adapter behavior.",
|
|
11
|
+
rule_ids=(),
|
|
12
|
+
harnesses=("backend",),
|
|
13
|
+
)
|