Team Infrastructure Architecture
Overview
The Plantangenet team system provides a lightweight, non-hierarchical identity projection model for coordinating agents in specific domains. Teams are brand-bound influencers that publish slogans (lightweight projection units) which attached agents may emit into permitted contexts.
Core Design Principles
1. No Mandate
- Multiple teams can coexist in the same domain
- Teams have no authority over each other
- Agents can be attached to multiple teams simultaneously
- No global team registry or arbitration
2. Opt-In Attachment
- Agents voluntarily attach to teams
- Attachment is cheap to enter and exit
- Detachment immediately revokes projection rights
- Attachment doesn't mutate agent state
3. Non-Binding Slogans
- Slogans carry no enforcement weight
- Emitting a slogan creates no obligation
- Multiple agents can emit the same slogan without conflict
- Slogans are purely expressive
4. Context Filtering
- Each slogan specifies which contexts permit it
- Empty context list = all contexts permitted
- Validation checks context compatibility per slogan
- Contexts are domain-specific (e.g., "curling", "rally")
5. Soft Caps
- Teams can declare a soft cap on per-agent active slogans
- Model validates against cap; enforcement is coordinator's responsibility
- No cap = unlimited slogans
- Enables progressive constraint without hard limits
Core Components
Team
A brand-bound identity with a catalog of slogans.
Fields:
team_id: Stable unique identifierbrand_id: Brand the team is bound toname: Human-readable namedescription: Team identity descriptionslogans: Catalog of available slogansmax_active_slogans: Optional per-agent cap
Operations:
- Create teams with
new() - Add/remove/list slogans
- Set soft caps with
with_max_active_slogans()
Slogan
A lightweight, portable projection unit.
Fields:
slogan_id: Stable ID within team's catalogteam_id: Owning teamtext: Projection text ("We sweep together.")allowed_contexts: List of permitted contexts (empty = all)ttl_frames: Optional frame lifetimecoherence_hint: 0.0-1.0 indicating identity assertion strength
Operations:
- Create with
new() - Restrict contexts with
with_contexts() - Set lifetime with
with_ttl() - Adjust coherence with
with_coherence() - Check permission with
permits_context()
TeamAttachmentRegistry
Bidirectional index of agent ↔ team relationships.
Data Structure:
by_agent: HashMap> by_team: HashMap>
Operations:
attach(): Record opt-indetach(): Revoke attachmentis_attached(): Check membershipteams_for_agent(): List agent's teamsagents_for_team(): List team's memberscan_project(): Check projection rights
ProjectionRequest
Request from an agent to emit a slogan into a context.
Fields:
agent_id: Requesting agentteam_id: Acting teamslogan_id: Slogan to emitcontext: Target context
validate_projection()
Pure validation function checking all rules:
- Agent is attached to team (
NotAttachedif not) - Slogan exists in team's catalog (
SloganNotFoundif not) - Slogan permits requested context (
ContextNotPermittedif not) - Agent hasn't exceeded cap, if set (
CapExceededif over)
Returns ProjectionOutcome::Accepted or Rejected(reason).
TeamConfig
Compile-time constants for static team setup.
Fields:
team_id: &'static strdisplay_name: &'static strbrand_id: &'static strleague_enrollments: &'static [&'static str]
Usage:
- Declare once per team crate as
const TEAM: TeamConfig - Delegate structural logic to it
- Zero runtime cost (all static)
Dependency Graph
plant_team (core infrastructure)
├── Uses: plant_atom (for ManagedItem), serde, anyhow
└── No dependencies on game/* or domain-specific code
game/src/classic/team/ (classic game adapter)
├── Re-exports from plant_team
└── Extends with league integration (TeamInfluencer)
Domain-specific crates (future)
├── Can depend on plant_team
└── Extend with domain-specific models
Use Cases
1. Classic Game Teams
Multiple teams ("Slug Bears", "Bear Slugs") in curling/rally domains.
- Teams represent competitive groups
- Slogans express group identity
- Agents attach as supporters
- Projection validates team membership
2. Band/Music Coordination
- Band identity separate from individual musicians
- Could use team infrastructure for ensemble coordination
- Slogans could express musical strategies
- Attachments would track ensemble membership
3. League Integration
- TeamConfig supports league enrollments
- Teams can be registered in leagues
- League integration is domain-specific (via classic game)
Design Rationale
Why Lightweight?
- No state mutations
- No authority checks
- No conflict arbitration
- Model is purely informational
Why Per-Agent Caps Instead of Global?
- Each agent has different capacity
- Coordinator has domain-specific constraints
- Model validates; coordinator enforces
- Enables progressive constraint
Why Soft Caps?
- Hard limits could cause failures
- Soft caps signal intent
- Coordinator decides enforcement
- Respects coordinator's authority
Why Context Filtering Per-Slogan?
- Different slogans fit different contexts
- No need for global context restrictions
- Coordinator can define meaningful contexts
- More granular than team-level control
Future Extensions
Band/Musician System
- Create
plant_bandcrate - Extend with musical domain types
- Use team infrastructure for coordination
- Keep music logic isolated
Custom Team Extensions
- Implement by creating domain-specific crate
- Depend on
plant_team - Add domain-specific fields/methods
- Re-export and adapt
League Framework
- Already integrated in classic game
- Could be generalized
- Supports team enrollment
- Coordinator-specific implementation
Testing
Unit Tests
- Team operations (add/remove/list slogans)
- Attachment operations (attach/detach)
- Projection validation (all rejection reasons)
- Serialization roundtrips
- ManagedItem trait implementation
Integration Tests
- Classic game integration
- Multiple teams coexistence
- Cross-agent projections
- Registry state consistency
Macro-Generated Tests
- Identity stability
- League enrollment verification
- Attachment revocability
Files and Organization
plant_team/
├── Cargo.toml
├── src/
│ ├── lib.rs (main exports)
│ ├── model.rs (Team, Slogan, TeamRegistry)
│ ├── attachment.rs (TeamAttachment, TeamAttachmentRegistry)
│ ├── projection.rs (ProjectionRequest/Outcome, validate_projection)
│ ├── config.rs (TeamConfig, TeamParticipationRegistry)
│ ├── macros.rs (impl_standard_team_tests!)
│ ├── brand.rs (ForgeTeamBrand - forge pipeline)
│ ├── compiler/ (forge compilation)
│ ├── graph_spec.rs (forge graph specification)
│ ├── seed.rs (DomainSeed)
│ ├── service.rs (DomainForgeService)
│ └── spec.rs (TeamSpec, parsing)
game/src/classic/team/
├── mod.rs (re-exports from plant_team)
├── config.rs (classic-specific TeamInfluencer integration)
└── macros.rs (macro re-exports)
API Stability
The core team types are stable:
Team,Slogan,TeamRegistryTeamAttachment,TeamAttachmentRegistryProjectionRequest,ProjectionOutcome,RejectionReasonvalidate_projection()TeamConfig,TeamParticipationRegistry
The forge pipeline components are separate and may evolve independently.