diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..fe742ef --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,10 @@ +# Change tracking and task isolation + +Before opening or updating any PR, update the single root `CHAGELOG.md`, preserve +its history, link the PR and distinguish Unreleased work from actual publication. +Do not create a second differently named changelog. Source versions remain +sentinels until the repository's release workflow stamps a real immutable tag. + +Fetch and confirm remote main for each task, then use a separate branch/worktree. +Preserve unrelated dirty work. Remove a merged task worktree only after checking +it is clean, pushed and unused by another active task. diff --git a/CHAGELOG.md b/CHAGELOG.md new file mode 100644 index 0000000..7a61cd2 --- /dev/null +++ b/CHAGELOG.md @@ -0,0 +1,9 @@ +# AutoBot version history + +## Unreleased + +- Proposed client compatibility fix ([#14](https://github.com/BitterSecurity/AutoBot/pull/14)): declare AutoBot's observation purpose via + its installed role entry point, so clients do not require an attack scope for + its read-only investigation graph. AutoBot retains its own middleware and + sensor-only tools. Unknown roles keep the shared core's execution default. + No package version or release is claimed by this source change. diff --git a/packages/autobot/README.md b/packages/autobot/README.md index eed50da..082cbfc 100644 --- a/packages/autobot/README.md +++ b/packages/autobot/README.md @@ -22,3 +22,12 @@ full architecture. ## Status Phase 1 (contracts + substrate) in progress. Apache-2.0. + +## Client admission metadata + +The installed `bs-autobot` package contributes an `observation` role through +`decepticon.roles`, alongside its agent/subagent entry points. Clients can identify +the read-only investigator without treating it as an execution role requiring an +attack scope. AutoBot still owns its middleware and five read-only sensor tools; +this declaration does not grant mutation or execution capabilities. Unknown roles +retain the shared core's conservative execution default. diff --git a/packages/autobot/autobot/role.py b/packages/autobot/autobot/role.py new file mode 100644 index 0000000..821c2c8 --- /dev/null +++ b/packages/autobot/autobot/role.py @@ -0,0 +1,7 @@ +"""Trusted client metadata for the independently assembled read-only agent.""" + +from decepticon_core.registry.roles import RoleSpec + +# AutoBot owns its middleware stack. This declares the admission purpose; +# it does not install Decepticon's execution middleware or grant tool access. +ROLE_SPEC = RoleSpec(name="autobot", slots=frozenset(), purpose="observation") diff --git a/packages/autobot/pyproject.toml b/packages/autobot/pyproject.toml index 96c89bc..106f3d3 100644 --- a/packages/autobot/pyproject.toml +++ b/packages/autobot/pyproject.toml @@ -68,10 +68,11 @@ testing = ["pytest>=8.0.0"] [project.entry-points."decepticon.event_stores"] opensearch = "autobot.stores.opensearch_store:OpenSearchEventStore" -# The blue_cell graph export — discovered by the Decepticon server when the -# ``decepticon[blue]`` extra installs this package, so the blue agent is -# hosted by the Decepticon LangGraph server without in-tree blue code -# (migration plan stage 2c; Decepticon design doc §0.5 client guarantee). +# Trusted client admission metadata; the agent owns its read-only middleware. +[project.entry-points."decepticon.roles"] +autobot = "autobot.role:ROLE_SPEC" + +# The optional AutoBot graph is discovered without in-tree Blue implementations. [project.entry-points."decepticon.agents"] autobot = "autobot.agent.autobot:graph" diff --git a/packages/autobot/tests/unit/agent/test_role_metadata.py b/packages/autobot/tests/unit/agent/test_role_metadata.py new file mode 100644 index 0000000..b36372f --- /dev/null +++ b/packages/autobot/tests/unit/agent/test_role_metadata.py @@ -0,0 +1,9 @@ +"""Exercise installed plugin metadata consumed by client admission.""" + +from decepticon_core.plugin_loader import load_plugin_role_specs + + +def test_installed_autobot_declares_observation_without_execution_middleware(): + roles = {spec.name: spec for spec in load_plugin_role_specs()} + assert roles["autobot"].purpose == "observation" + assert not roles["autobot"].slots