Skip to content

4+1 Logical View

The Logical View captures what FCC knows. Personas, workflows, plugins, events, and governance data form the core of the logical model. This page is the first of Philippe Kruchten's 4+1 views; it complements the Process View (runtime), the Development View (packaging), the Physical View (deployment), and the Scenarios View (+1) that validates all four against concrete use cases.

The three diagrams below focus on the three most load-bearing static structures in the framework: the persona model, the plugin taxonomy, and the compliance + governance stack.

Core persona and workflow model

The primary logical abstraction is the PersonaSpec frozen dataclass. Every agent in the 147-persona catalog is an instance of PersonaSpec, aggregating a RISCEARSpec contract, a six-trait discernment matrix, a six-factor design-target profile, and an optional 56-dimension profile. Workflows reference personas by ID via WorkflowNode entries; the ActionEngine consumes both a PersonaSpec and a WorkflowAction when it renders a prompt for the simulation layer.

Figure 1 shows the composition between PersonaSpec, RISCEARSpec, PersonaRegistry, WorkflowGraph, WorkflowAction, and ActionEngine.

classDiagram
    class PersonaSpec {
        <<frozen dataclass>>
        +id : str
        +name : str
        +fcc_phase : str
        +category : str
        +champion_of : str | None
        +orchestrates : list[str]
        +doc_context : dict | None
    }

    class RISCEARSpec {
        <<frozen dataclass>>
        +role : str
        +inputs : list[str]
        +style : str
        +constraints : list[str]
        +expected_output : str
        +archetype : str
        +responsibilities : list[str]
        +role_skills : list[str]
        +role_collaborators : list[str]
        +role_adoption_checklist : list[str]
    }

    class PersonaRegistry {
        +load_directory(path) PersonaRegistry
        +by_id(id) PersonaSpec
        +by_category(cat) list~PersonaSpec~
        +champions() list~PersonaSpec~
        +merge(other) PersonaRegistry
    }

    class WorkflowGraph {
        +nodes : dict
        +edges : list
        +start_node : str
        +load_json(path) WorkflowGraph
        +get_node(id) WorkflowNode
    }

    class WorkflowNode {
        +id : str
        +persona_id : str
        +action_id : str
    }

    class WorkflowAction {
        +id : str
        +action_type : WorkflowActionType
        +expected_output : str
        +prompt_template : str
    }

    class ActionEngine {
        +registry : WorkflowActionRegistry
        +run(persona, action, payload) ActionResult
        +get_action_prompt(persona, action) tuple
    }

    PersonaSpec "1" *-- "1" RISCEARSpec : riscear
    PersonaRegistry "1" o-- "many" PersonaSpec : stores
    WorkflowGraph "1" *-- "many" WorkflowNode : nodes
    WorkflowNode "1" ..> "1" WorkflowAction : references
    WorkflowNode "1" ..> "1" PersonaSpec : references
    ActionEngine "1" ..> "1" PersonaSpec : consumes
    ActionEngine "1" ..> "1" WorkflowAction : consumes

The flat composition keeps serialisation symmetric and the loader stateless.

Plugin taxonomy

FCC's extensibility surface is 11 plugin types, each an abstract base class under src/fcc/plugins/base.py. At import time the PluginRegistry discovers concrete plugins through setuptools entry points; every plugin participates in a uniform lifecycle (name(), version(), initialize(), teardown()).

Figure 2 is a PlantUML class diagram of the 11-type plugin taxonomy and their shared interface.

@startuml
abstract class FCCPlugin {
  +name() : str
  +version() : str
  +initialize(ctx) : None
  +teardown() : None
}

class PersonaPlugin
class EnginePlugin
class TemplatePlugin
class ScorerPlugin
class ValidatorPlugin
class AIProviderPlugin {
  +get_env_var_hint() : str
  +build_client(cfg) : BaseAIClient
}
class GovernancePlugin
class ScenarioPlugin
class WorkflowPlugin
class EventSubscriberPlugin {
  +subscribe(bus) : None
}
class VocabularyProviderPlugin {
  +provides() : list
  +load_mappings() : list
}

FCCPlugin <|-- PersonaPlugin
FCCPlugin <|-- EnginePlugin
FCCPlugin <|-- TemplatePlugin
FCCPlugin <|-- ScorerPlugin
FCCPlugin <|-- ValidatorPlugin
FCCPlugin <|-- AIProviderPlugin
FCCPlugin <|-- GovernancePlugin
FCCPlugin <|-- ScenarioPlugin
FCCPlugin <|-- WorkflowPlugin
FCCPlugin <|-- EventSubscriberPlugin
FCCPlugin <|-- VocabularyProviderPlugin
@enduml

VocabularyProviderPlugin (v1.2.1+) is the newest member and the primary seam for cross-project entity resolution.

Compliance and governance

FCC v1.3.x ships an EU AI Act + NIST AI RMF compliance pipeline on top of 58 quality gates. The compliance model is a pure-data stack that the ComplianceAuditor walks per persona.

Figure 3 shows the core compliance classes and their relationship to the governance constitution registry.

classDiagram
    class ComplianceAuditor {
        +registry : RequirementRegistry
        +classifier : AIActClassifier
        +audit(persona_registry) ComplianceReport
    }

    class RequirementRegistry {
        +requirements : dict
        +load() RequirementRegistry
        +by_category(cat) list
    }

    class AIActClassifier {
        +classify(persona) RiskCategory
    }

    class ComplianceRequirement {
        <<frozen dataclass>>
        +id : str
        +regulation : str
        +article : str
        +risk_category : RiskCategory
        +description : str
    }

    class QualityGate {
        <<frozen dataclass>>
        +id : str
        +severity : str
        +persona_scope : list
        +check_fn : str
    }

    class ConstitutionRegistry {
        +lookup(persona_id) PersonaConstitution
        +tiers() list
    }

    class PersonaConstitution {
        +hard_stops : list
        +mandatory : list
        +preferred : list
    }

    ComplianceAuditor "1" o-- "1" RequirementRegistry : uses
    ComplianceAuditor "1" o-- "1" AIActClassifier : uses
    RequirementRegistry "1" *-- "many" ComplianceRequirement
    ConstitutionRegistry "1" *-- "many" PersonaConstitution
    ComplianceAuditor "1" ..> "many" QualityGate : evaluates
    ComplianceAuditor "1" ..> "1" ConstitutionRegistry : consults

How the pieces interact

At load time the CLI builds a PersonaRegistry from src/fcc/personas/registry.py:62, a WorkflowActionRegistry from the 312 action YAML files under src/fcc/data/personas/actions/, and seven WorkflowGraph instances from src/fcc/data/workflows/. The ActionEngine at src/fcc/workflow/action_engine.py:51 is the pure function that turns a (PersonaSpec, WorkflowAction) pair into a renderable prompt; it holds no mutable state. The simulation layer aggregates these, publishes events, and records turns.

The compliance path is structurally parallel: ComplianceAuditor at src/fcc/compliance/auditor.py:28 pulls personas from the same PersonaRegistry, classifies each against EU AI Act risk tiers via AIActClassifier at src/fcc/compliance/classifier.py:19, and emits a ComplianceReport that the dashboard and evidence-graph builders can consume without needing to re-load anything.

The three diagrams above show three views of the same intuition: FCC's data is all frozen dataclasses, its registries are plain collections, and its engines are stateless transformers. That uniformity is what keeps the docs-as-code generator, the model-card pipeline, and the evidence-graph builder deterministic.

See also

  • src/fcc/personas/models.py:104 (RISCEARSpec), src/fcc/personas/models.py:168 (PersonaSpec)
  • src/fcc/workflow/graph.py (WorkflowGraph, WorkflowNode)
  • src/fcc/workflow/action_engine.py:51 (ActionEngine.run)
  • src/fcc/compliance/auditor.py:28 (ComplianceAuditor.audit)
  • src/fcc/plugins/base.py (11 plugin ABCs)
  • Process View
  • Class diagrams deep-dive

v1.5.0 Logical Impact

v1.5.0 added five new first-class modules to the Logical View without disturbing any existing class. Each addition landed behind a stable fcc.api.* re-export so the Logical View now has two layers: the original pure-data aggregates (persona / workflow / compliance) and the new capability bridges (archive, knowledge, rag.graphrag, collaboration.crdt, collaboration.multi_user, federation.bidirectional).

Module Key classes Anchor diagram
src/fcc/rag/graphrag.py GraphRAG, GraphRAGResult, assemble_context, retriever_from_graph ../sequence-diagrams/graphrag-zachman-filter.md
src/fcc/collaboration/crdt.py CRDTBackend (Protocol), InMemoryBackend, YPyBackend, CollaborativeDocument, _LwwOp, _PresenceEntry, get_crdt_backend ../sequence-diagrams/crdt-multi-user-merge.md
src/fcc/collaboration/multi_user.py MultiUserSession, MultiUserEngine, Edit, EditKind, PresenceInfo, envelope helpers ../use-case-diagrams/multi-user-session.md
src/fcc/federation/bidirectional.py BidirectionalSync, Conflict, SyncReport, Resolution enum ../sequence-diagrams/bidirectional-federation-sync.md
src/fcc/archive/polaris_bridge.py re-exports: PolarisBridgeProtocol, PolarisMockBridge, NoOpPolarisBridge, get_polaris_bridge ../class-diagrams/polaris-bridge.md
src/fcc/knowledge/lyra_bridge.py re-exports: LyraBridgeProtocol, LyraMockBridge, NoOpLyraBridge, get_lyra_bridge ../class-diagrams/lyra-bridge.md

Three structural observations for the Logical View. First, every addition keeps the "frozen dataclasses + plain registries + stateless engines" shape the view codified — GraphRAGResult, Conflict, SyncReport, PresenceInfo, and Edit are all frozen dataclasses. Second, two new Protocols (CRDTBackend, PolarisBridgeProtocol, LyraBridgeProtocol) extend the plugin taxonomy's structural-typing idiom without adding new plugin types. Third, the fcc.api.* re-export layer is the new public promotion contract — the old single-import paths still work through v1.5.x with a DeprecationWarning and go away in v1.6.0. See ../class-diagrams/six-pillars-overview.md for the full module map and ADR-006..013 for the decision trail.

v1.6.0 Impact

v1.6.0 executed three of the six pillars that v1.5.0 introduced — A (seed data), C (i18n translation), and the live half of B's LYRA bridge — without adding a new top-level subpackage. The Logical View therefore grows new modules inside existing subpackages plus new script-level helpers that are not part of the Python import graph but are part of the logical architecture of the publishable deliverable.

Module / artifact Key classes / symbols Role
publications/scripts/seed_canonical.py CanonicalSource (frozen dataclass), SUPPORTED_VERTICALS, seed_canonical(vertical, dry_run) Pillar A — intent + license registry (v1.5.0 scaffold, stable in v1.6.0)
publications/scripts/fetch_canonical_seeds.py FileResult (frozen dataclass), fetch_all(accept_flag), _sha256, _record_manifest_entry Pillar A — owner-gated downloader; emits seed_canonical_manifest.json
docs/i18n/glossary.csv + scripts/verify_glossary_preservation.py load_do_not_translate_terms, verify_locale(path) Pillar C — do-not-translate glossary enforcer (R.I.S.C.E.A.R., Zachman row/column names, persona IDs)
frontend/src/i18n/locales/{en,fr,es,de}/common.json + config.ts i18n locale resolver + runtime language switch Pillar C — React/i18next consumer of the translated strings
src/fcc/knowledge/lyra_bridge.pyget_lyra_bridge() LyraAdapter resolution path (live branch), LyraMockBridge (fallback) Pillar B — live LYRA adapter resolution; sentinel-probed at call time
scripts/verify_codename_decoder.py extract_table_rows, check_paths, check_placeholders Ecosystem docs — enforces that every codename in docs/ecosystem/codename-decoder.md resolves to a real local path or an explicit "not cloned locally" sentinel

Three structural observations for v1.6.0. First, the seed-canonical fetch pipeline is a Logical-View citizen even though it lives under publications/scripts/ — it produces a committed artifact (publications/_output/seed_canonical_manifest.json) that downstream consumers (vertical plugins, tutorials, the test harness) treat as the canonical corpus manifest; the SHA-256-keyed entries are a first-class data contract. Second, the i18n locale resolver is a runtime module on the frontend side and a build-time gate on the Python side — the glossary preservation check runs in CI against the four packaged common.json files and fails a release if any do-not-translate term has been mutated. Third, the LYRA adapter resolution is the only module whose behaviour changes in v1.6.0 even though the source file did not move: get_lyra_bridge() continues to probe lyra.api at call time, and the private lyra_ext repo is the first environment where that probe returns True; LyraMockBridge remains the default in unlocked environments.

The v1.5.x preview-path namespace (fcc.plugins.v1_5_preview.*) is removed in v1.6.0 per the v1.5.0 migration notice; every caller must now import through fcc.knowledge.lyra_bridge / fcc.archive.polaris_bridge or the flat fcc.api re-export. See ADR-014 (render-pipeline Chromium sandbox) for the v1.6.0 documentation-build story, and ../pillar-a-seed-lifecycle-v160.md, ../pillar-c-translation-flow-v160.md, and ../lyra-live-integration-v160.md for the per-pillar diagrams.