Skip to content

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 identifier
  • brand_id: Brand the team is bound to
  • name: Human-readable name
  • description: Team identity description
  • slogans: Catalog of available slogans
  • max_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 catalog
  • team_id: Owning team
  • text: Projection text ("We sweep together.")
  • allowed_contexts: List of permitted contexts (empty = all)
  • ttl_frames: Optional frame lifetime
  • coherence_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-in
  • detach(): Revoke attachment
  • is_attached(): Check membership
  • teams_for_agent(): List agent's teams
  • agents_for_team(): List team's members
  • can_project(): Check projection rights

ProjectionRequest

Request from an agent to emit a slogan into a context.

Fields:

  • agent_id: Requesting agent
  • team_id: Acting team
  • slogan_id: Slogan to emit
  • context: Target context

validate_projection()

Pure validation function checking all rules:

  1. Agent is attached to team (NotAttached if not)
  2. Slogan exists in team's catalog (SloganNotFound if not)
  3. Slogan permits requested context (ContextNotPermitted if not)
  4. Agent hasn't exceeded cap, if set (CapExceeded if over)

Returns ProjectionOutcome::Accepted or Rejected(reason).

TeamConfig

Compile-time constants for static team setup.

Fields:

  • team_id: &'static str
  • display_name: &'static str
  • brand_id: &'static str
  • league_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_band crate
  • 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, TeamRegistry
  • TeamAttachment, TeamAttachmentRegistry
  • ProjectionRequest, ProjectionOutcome, RejectionReason
  • validate_projection()
  • TeamConfig, TeamParticipationRegistry

The forge pipeline components are separate and may evolve independently.