workflow vis-coauthorship-community-evolution
  template: define-unit (extract authors) ->
            define-unit (network construction: windows & anchor) ->
            loop(define-unit (community-detection) -> contextualise (projection) ->
                 visualise -> assess) ->
            characterise (cross-time overlap) -> define-unit (trace threads) ->
            contextualise (alluvial) -> visualise -> abstract (detect events) ->
            characterise (author role metrics) -> define-unit (classify roles) ->
            loop(contextualise (drill-down layouts) -> visualise -> assess) ->
            characterise (text encoding) ->
            loop(build-model (topic model) -> characterise (topic profiles) ->
                 visualise -> abstract (interpret) -> assess) ->
            characterise (aggregate community topic profiles) ->
            visualise (topic evolution) ->
            characterise (period overlap matrix) -> visualise (overlap matrix) ->
            generate-knowledge
  description: "Human-in-the-loop visual analytics workflow for identifying
    communities of collaborating VIS researchers, tracing their evolution
    (stability, drift, merges, splits, dissolution), characterising core
    leadership, and linking communities to their evolving research foci."

# ============================================================================
# INPUT
# ============================================================================

artifact D_papers : entities
  origin: given
  internal structure: elementary
  embedment: {set, time}
  features:
    - id: f_title
      value structure: atomic
      value type: text
      description: "Paper title"
    - id: f_abstract
      value structure: atomic
      value type: text
      description: "Paper abstract"
    - id: f_keywords
      value structure: list
      value type: categorical
      description: "Author/venue keywords"
    - id: f_authors
      value structure: list
      value type: reference
      description: "Disambiguated author identifiers"
    - id: f_citations
      value structure: list
      value type: reference
      description: "References to other papers"
  description: "3596 IEEE VIS (Vis/InfoVis/VAST/SciVis) papers, 1990-2024"

artifact K_prior_domain_knowledge : knowledge(D_papers)
  origin: given
  representation form: "informal domain expertise"
  description: "Analyst's prior knowledge of known VIS research groups,
    leading researchers, institutional moves, and historical events, used
    throughout to validate detected communities, threads, and topics"

# ============================================================================
# STEP 1: EXTRACT AUTHOR ENTITIES
# ============================================================================

transform T_extract_authors :
  intent: define-unit
  manner: "extract distinct entities (disambiguated authors)"
  input: D_papers
  output: D_authors
  actor: machine
  description: "Extract the set of distinct disambiguated authors referenced
    across the paper corpus"

artifact D_authors : entities
  internal structure: elementary
  embedment: {set, time}
  features:
    - id: f_active_years
      value structure: list
      value type: temporal
      description: "Years in which the author published at IEEE VIS"
  description: "Disambiguated VIS authors, 1990-2024"

# ============================================================================
# STEP 2: CONSTRUCT NETWORK SNAPSHOTS AND FULL-PERIOD ANCHOR NETWORK
# ============================================================================

artifact S_windowing : specification
  origin: given
  representation form: "parameter settings"
  description: "Window length and stride for overlapping time windows
    (e.g., 5-year windows advancing by 2 years)"

transform T_build_windows :
  intent: define-unit
  manner: "time-partitioning with overlapping windows; aggregate
    co-authorship edges per window"
  input: D_papers, D_authors, S_windowing
  output: D_networks
  actor: machine
  description: "Partition the publication timeline into overlapping windows
    and build one weighted co-authorship network snapshot per window"

artifact D_networks : entities
  internal structure: formation
  embedment: time
  features:
    - id: f_edge_weight
      value structure: atomic
      value type: numeric
      description: "Number of co-authored papers between two authors within
        the window"
    - id: f_window_span
      value structure: atomic
      value type: temporal
      description: "Time span covered by the window"
  description: "Co-authorship network snapshots, one per overlapping time
    window"

transform T_build_anchor :
  intent: define-unit
  manner: "aggregate co-authorship edges across the full period"
  input: D_papers, D_authors
  output: D_network_full
  actor: machine
  description: "Build a single full-period co-authorship network to serve
    as a stable long-run reference structure"

artifact D_network_full : entities
  internal structure: formation
  features:
    - id: f_edge_weight
      value structure: atomic
      value type: numeric
      description: "Number of co-authored papers between two authors across
        the full 1990-2024 period"
  description: "Full-period reference co-authorship network (single entity)"

# ============================================================================
# STEP 3: COMMUNITY-DETECTION RESOLUTION LOOP
# ============================================================================

artifact S_community_params : specification
  origin: given
  representation form: "method choice and parameter settings"
  description: "Initial community-detection algorithm (e.g., Leiden) and
    resolution parameter, applied identically to anchor and windowed
    networks"

loop L_community_detection:
  purpose: "Detect communities on the anchor network and on each windowed
    snapshot at a resolution that yields analytically meaningful,
    interpretable community structure"
  until: "Community counts and sizes are neither over-fragmented nor overly
    coarse, and communities are visually cohesive and consistent with
    known VIS research groups"
  body:

    transform T_detect_anchor_communities :
      intent: define-unit
      manner: "cluster-by-similarity (community detection on full-period
        network)"
      input: D_network_full, S_community_params
      output: D_anchor_communities, F_anchor_membership
      actor: machine
      description: "Detect long-run reference communities on the full-period
        network"

    artifact D_anchor_communities : entities
      internal structure: group/cluster
      embedment: set
      description: "Long-term reference communities detected on the
        full-period network"

    artifact F_anchor_membership : feature(D_authors)
      value structure: atomic
      value type: categorical
      description: "Anchor community assignment for each author"

    transform T_detect_window_communities :
      intent: define-unit
      manner: "cluster-by-similarity (community detection per window)"
      input: D_networks, S_community_params
      output: D_window_communities, F_community_members
      actor: machine
      description: "Detect communities independently within each windowed
        network snapshot"

    artifact D_window_communities : entities
      internal structure: group/cluster
      embedment: {set, time}
      description: "Communities detected within each time-window network
        snapshot"

    artifact F_community_members : feature(D_window_communities)
      value structure: list
      value type: reference
      description: "Author members belonging to each community instance"

    transform T_contextualise_projection :
      intent: contextualise
      manner: "projection-based (embed community-window instances by member
        similarity)"
      input: D_window_communities, F_community_members
      output: D_projection_space, A_projection_communities
      actor: machine
      description: "Compute a 2D projection space in which community-window
        instances close in membership/time appear near each other, and
        arrange instances within it"

    artifact D_projection_space : entities
      internal structure: elementary
      features:
        - id: f_dimensions
          value structure: atomic
          value type: numeric
          description: "Number of projection dimensions (2)"
      description: "Computed 2D projection space for community-window
        instances"

    artifact A_projection_communities : arrangement(D_window_communities)
      context: D_projection_space
      principle: "similarity-preserving projection based on member overlap"
      description: "Positions of community-window instances in projection
        space"

    transform T_vis_overview :
      intent: visualise
      manner: "2D projection with temporal trails"
      input: A_projection_communities, D_anchor_communities, F_anchor_membership
      output: V_community_states
      actor: machine
      description: "Show community-window instances in projection space,
        coloured by anchor community, to assess granularity and cohesion"

    artifact V_community_states : visualisation(A_projection_communities,
        F_anchor_membership)
      layout: "2D projection"
      form: "coloured points with temporal trail lines"
      encoding: "position from A_projection_communities; colour from
        F_anchor_membership; trails connect same-authorship-dominant
        instances across adjacent windows"
      description: "Overview for judging whether detected communities are
        cohesive, distinct, and stable across time"

    transform T_assess_resolution :
      intent: assess
      manner: "evaluate community granularity and cohesion"
      input: V_community_states, D_window_communities, D_anchor_communities,
             K_prior_domain_knowledge
      output: K_resolution_quality
      actor: human
      description: "Judge whether the current resolution parameter yields
        interpretable, stable communities consistent with known VIS
        research groups"

    artifact K_resolution_quality : knowledge(D_window_communities,
        D_anchor_communities)
      representation form: "quality judgment"
      description: "Judgment of whether community granularity is adequate
        or requires adjustment"

    if K_resolution_quality indicates refinement needed:
      then:
        transform T_refine_resolution :
          intent: generate-knowledge
          manner: "formulate revised community-detection specification"
          input: K_resolution_quality, S_community_params
          output: S_community_params_r
          actor: human
          description: "Decide on a revised resolution parameter or
            algorithm variant"

        artifact S_community_params_r : specification
          representation form: "method choice and parameter settings"
          description: "Revised community-detection configuration"

        assign:
          S_community_params := S_community_params_r
      else:
        exit loop L_community_detection

end loop L_community_detection

# ============================================================================
# STEP 4: CROSS-TIME MATCHING AND COMMUNITY THREADS
# ============================================================================

transform T_characterise_overlap :
  intent: characterise
  manner: "define-relations (membership overlap between temporally adjacent
    community instances)"
  input: D_window_communities, F_community_members
  output: F_community_overlap
  actor: machine
  description: "Compute Jaccard-style member overlap between every pair of
    community instances in temporally adjacent windows"

artifact F_community_overlap : feature(D_window_communities)
  value structure: relational configuration
  value type: numeric
  representation form: "weighted directed graph linking community instances
    in adjacent time windows by member-overlap weight"
  description: "Overlap-based linkage used to trace community continuity"

transform T_trace_threads :
  intent: define-unit
  manner: "trace continuity chains across time (merge-groups via overlap
    linkage)"
  input: D_window_communities, F_community_overlap
  output: D_community_threads
  actor: hybrid
  description: "Chain community-window instances into long-run trajectories
    wherever member overlap is strong; propose thread identities for
    analyst review"

artifact D_community_threads : entities
  internal structure: sequence
  embedment: set
  features:
    - id: f_thread_span
      value structure: atomic
      value type: temporal
      description: "First and last window of the thread"
    - id: f_thread_size_trend
      value structure: vector
      value type: numeric
      description: "Member count per window along the thread"
  description: "Long-run community trajectories chained from per-window
    community instances"

# ============================================================================
# STEP 5: VISUALISE EVOLUTION AND DETECT STRUCTURAL EVENTS
# ============================================================================

transform T_contextualise_alluvial :
  intent: contextualise
  manner: "flow-based layout (alluvial ordering by time and thread)"
  input: D_community_threads, D_window_communities
  output: A_alluvial
  actor: machine
  description: "Order community instances along a temporal flow layout
    grouped by thread"

artifact A_alluvial : arrangement(D_window_communities)
  context: D_community_threads
  principle: "temporal flow ordering; vertical position by thread membership,
    ribbon width by community size"
  description: "Layout underlying an alluvial/stream diagram of community
    evolution"

transform T_vis_alluvial :
  intent: visualise
  manner: "alluvial/stream diagram"
  input: A_alluvial, F_community_overlap
  output: V_alluvial
  actor: machine
  description: "Display community size and flow of membership across time,
    exposing persistence, merges, splits, emergence, and dissolution"

artifact V_alluvial : visualisation(A_alluvial, F_community_overlap)
  layout: "alluvial/stream diagram"
  form: "flow ribbons with width encoding community size"
  encoding: "horizontal axis: time windows; ribbons: F_community_overlap
    linkage strength between adjacent-window communities"
  description: "Primary overview for answering how many communities exist
    and how they merge, split, or dissolve over time"

transform T_detect_events :
  intent: abstract
  manner: "perception-and-interpretation (identify merge/split/emergence/
    dissolution events)"
  input: V_alluvial, F_community_overlap, D_community_threads,
         K_prior_domain_knowledge
  output: P_evolution_events
  actor: human
  description: "Visually identify and label points where threads merge,
    split, newly emerge, or dissolve, cross-checked against known VIS
    community history"

artifact P_evolution_events : pattern(D_community_threads)
  representation form: "labelled structural events (merge, split, emergence,
    dissolution) with time windows and involved thread IDs"
  description: "Identified structural transition events in the community
    evolution"

# ============================================================================
# STEP 6: CORE STABILITY AND LEADERSHIP CHARACTERISATION
# ============================================================================

transform T_characterise_author_roles :
  intent: characterise
  manner: "compute tenure, centrality, and cross-membership per author"
  input: D_authors, D_community_threads, D_networks, F_community_members
  output: F_author_role_metrics
  actor: machine
  description: "For each author and each thread they belong to, compute
    tenure (fraction of thread windows present), average network centrality
    within the community, and count of distinct threads/communities joined"

artifact F_author_role_metrics : feature(D_authors)
  value structure: vector
  value type: numeric
  description: "Per-author tenure, centrality, and cross-membership metrics"

transform T_classify_roles :
  intent: define-unit
  manner: "cluster-by-similarity / rule-based classification (core,
    peripheral, boundary-spanning)"
  input: D_authors, F_author_role_metrics
  output: D_author_roles, F_role_label
  actor: hybrid
  description: "Classify authors into core (high tenure, high centrality),
    peripheral (short tenure, low centrality), or boundary-spanning
    (member of multiple communities) role categories"

artifact D_author_roles : entities
  internal structure: group/cluster
  embedment: set
  description: "Groups of authors sharing similar role profiles"

artifact F_role_label : feature(D_authors)
  value structure: atomic
  value type: categorical
  description: "Assigned role category per author"

# ============================================================================
# STEP 7: STRUCTURAL DRILL-DOWN AND CORRECTION LOOP
# ============================================================================

loop L_structure_inspection:
  purpose: "Inspect the internal structure and leadership of selected
    community threads to validate thread linkage and role classification"
  until: "The analyst has examined a representative sample of threads and
    periods and is satisfied that thread continuity and role labels are
    consistent with domain knowledge"
  body:

    transform T_select_instance :
      intent: define-unit
      manner: "filter (analyst selects a thread and time window of
        interest)"
      input: D_community_threads, V_alluvial
      output: D_selected_window_community
      actor: human
      description: "Select a single community-window instance for detailed
        inspection"

    artifact D_selected_window_community : entities
      internal structure: group/cluster
      embedment: set
      description: "Single community instance selected for detailed
        inspection"

    transform T_contextualise_nodetrix :
      intent: contextualise
      manner: "hybrid matrix/node-link layout (dense core as matrix,
        bridging ties as node-link)"
      input: D_selected_window_community, D_networks, F_role_label
      output: A_nodetrix
      actor: machine
      description: "Arrange the selected community's dense collaboration
        core as an adjacency matrix while rendering bridging ties to other
        communities as node-link edges"

    artifact A_nodetrix : arrangement(D_selected_window_community)
      context: D_networks
      principle: "NodeTrix-style layout: densely connected core as matrix,
        sparser bridging ties as node-link edges"
      description: "Hybrid layout exposing core/leader structure and
        boundary-spanning ties"

    transform T_vis_nodetrix :
      intent: visualise
      manner: "node-link + matrix hybrid diagram"
      input: A_nodetrix, F_role_label, F_author_role_metrics
      output: V_nodetrix
      actor: machine
      description: "Display the selected community's internal structure,
        coloured by role classification"

    artifact V_nodetrix : visualisation(A_nodetrix, F_role_label)
      layout: "hybrid matrix/node-link"
      form: "adjacency matrix cells for the core, node-link edges for
        bridging ties"
      encoding: "matrix/edge presence from A_nodetrix; node colour from
        F_role_label"
      description: "Detailed view of a single community's core and
        boundary-spanning structure"

    transform T_contextualise_timeline :
      intent: contextualise
      manner: "relative time alignment (one track per author)"
      input: D_authors, D_community_threads, F_community_members, D_networks
      output: A_author_timeline
      actor: machine
      description: "Arrange authors as parallel tracks positioned along
        the shared time axis defined by the network windows, coloured
        segments indicating which thread the author belongs to at each
        window"

    artifact A_author_timeline : arrangement(D_authors)
      context: D_networks
      principle: "one horizontal track per author positioned along time
        windows"
      description: "Per-author community-membership timeline arrangement"

    transform T_vis_timeline :
      intent: visualise
      manner: "scarf-plot / aligned timeline diagram"
      input: A_author_timeline, F_role_label
      output: V_author_timeline
      actor: machine
      description: "Show each author's community membership over time,
        revealing loyal core members versus movers"

    artifact V_author_timeline : visualisation(A_author_timeline, F_role_label)
      layout: "aligned per-author timelines"
      form: "coloured segments per time window"
      encoding: "track position: author; colour: community/thread
        membership per window; opacity: role from F_role_label"
      description: "Author-level view of membership stability and drift"

    transform T_assess_structure :
      intent: assess
      manner: "judge consistency of thread linkage and role labels with
        domain knowledge"
      input: V_nodetrix, V_author_timeline, P_evolution_events,
             K_prior_domain_knowledge
      output: K_structure_assessment
      actor: human
      description: "Decide whether the selected thread's continuity or role
        labels need manual correction"

    artifact K_structure_assessment : knowledge(D_community_threads,
        F_role_label)
      representation form: "quality judgment with diagnostic notes"
      description: "Judgment on whether thread linkage or role
        classification requires correction for the inspected instance"

    if K_structure_assessment indicates correction needed:
      then:
        transform T_correct_threads :
          intent: define-unit
          manner: "manual correction of thread linkage"
          input: D_community_threads, K_structure_assessment,
                 F_community_overlap
          output: D_community_threads_r
          actor: human
          description: "Manually relink, split, or merge thread segments
            based on domain knowledge"

        artifact D_community_threads_r : entities
          internal structure: sequence
          embedment: set
          description: "Corrected community threads"

        transform T_correct_roles :
          intent: define-unit
          manner: "manual correction of role classification"
          input: D_author_roles, F_role_label, K_structure_assessment
          output: D_author_roles_r, F_role_label_r
          actor: human
          description: "Manually adjust role labels found inconsistent with
            domain knowledge"

        artifact D_author_roles_r : entities
          internal structure: group/cluster
          embedment: set
          description: "Corrected author role groups"

        artifact F_role_label_r : feature(D_authors)
          value structure: atomic
          value type: categorical
          description: "Corrected role labels"

        assign:
          D_community_threads := D_community_threads_r
          D_author_roles := D_author_roles_r
          F_role_label := F_role_label_r
      else:
        # No correction needed for this instance; analyst continues
        # inspecting further threads/periods, or stops when satisfied.
        assign:
          D_community_threads := D_community_threads

end loop L_structure_inspection

# ============================================================================
# STEP 8: RESEARCH-FOCUS EXTRACTION VIA TOPIC MODELLING
# ============================================================================

transform T_characterise_text :
  intent: characterise
  manner: "encode (text feature extraction from title/abstract/keywords)"
  input: D_papers
  output: F_text_features
  actor: machine
  description: "Encode each paper's title, abstract, and keywords as a
    numeric text representation"

artifact F_text_features : feature(D_papers)
  value structure: vector
  value type: numeric
  representation form: "TF-IDF or embedding vector per paper"
  description: "Numeric text representation of each paper"

artifact S_topic_params : specification
  origin: given
  representation form: "parameter settings"
  description: "Initial number of topics and NMF configuration"

loop L_topic_modelling:
  purpose: "Fit and refine a topic model whose topics are interpretable as
    recognisable VIS research foci"
  until: "Topics are coherent, mutually distinct, and readily nameable by
    the analyst"
  body:

    transform T_fit_topics :
      intent: build-model
      manner: "fit-topic-model (NMF)"
      input: F_text_features, S_topic_params
      output: M_topic_model
      actor: machine
      description: "Fit a non-negative matrix factorisation topic model
        over the paper corpus"

    artifact M_topic_model : model(F_text_features)
      model type: "topic model"
      representation form: "non-negative matrix factorisation (W,H)"
      description: "Topic model over the VIS paper corpus"

    transform T_compute_paper_topics :
      intent: characterise
      manner: "project (compute per-paper topic-mixture from model)"
      input: D_papers, M_topic_model
      output: F_paper_topic_mixture
      actor: machine
      description: "Compute each paper's topic-mixture weights"

    artifact F_paper_topic_mixture : feature(D_papers)
      value structure: vector
      value type: numeric
      description: "Topic-mixture weights per paper"

    transform T_vis_topics :
      intent: visualise
      manner: "ranked term lists / topic-word matrix"
      input: M_topic_model, F_paper_topic_mixture
      output: V_topics
      actor: machine
      description: "Display top terms and representative papers per topic"

    artifact V_topics : visualisation(M_topic_model, F_paper_topic_mixture)
      layout: "topic-word matrix with representative-paper lists"
      form: "ranked term lists, bar charts"
      encoding: "topic ranked by weight from M_topic_model; representative
        papers ranked by F_paper_topic_mixture"
      description: "View for judging topic coherence and interpretability"

    transform T_interpret_topics :
      intent: abstract
      manner: "name-patterns (assign labels to topics)"
      input: V_topics
      output: P_topics
      actor: human
      description: "Interpret and name topics based on top terms and
        representative papers"

    artifact P_topics : pattern(M_topic_model)
      representation form: "named topic descriptions (label + representative
        terms/papers)"
      description: "Interpreted research-focus topics"

    transform T_assess_topics :
      intent: assess
      manner: "judge topic coherence and distinctiveness"
      input: V_topics, P_topics
      output: K_topic_quality
      actor: human
      description: "Decide whether the topic model needs refinement (merge,
        split, or change topic count)"

    artifact K_topic_quality : knowledge(M_topic_model, P_topics)
      representation form: "quality judgment"
      description: "Judgment on topic coherence and whether refinement is
        needed"

    if K_topic_quality indicates refinement needed:
      then:
        transform T_refine_topic_params :
          intent: generate-knowledge
          manner: "formulate revised topic-model specification"
          input: K_topic_quality, S_topic_params
          output: S_topic_params_r
          actor: human
          description: "Decide on a revised topic count or model
            configuration"

        artifact S_topic_params_r : specification
          representation form: "parameter settings"
          description: "Revised topic-model configuration"

        assign:
          S_topic_params := S_topic_params_r
      else:
        exit loop L_topic_modelling

end loop L_topic_modelling

# ============================================================================
# STEP 9: COMMUNITY RESEARCH-FOCUS PROFILES AND THEIR EVOLUTION
# ============================================================================

transform T_aggregate_community_topics :
  intent: characterise
  manner: "aggregate (average paper topic-mixtures per community instance)"
  input: D_window_communities, F_community_members, F_paper_topic_mixture
  output: F_community_topic_profile
  actor: machine
  description: "Aggregate the topic-mixtures of papers authored within each
    community instance into a single topic profile"

artifact F_community_topic_profile : feature(D_window_communities)
  value structure: vector
  value type: numeric
  description: "Aggregated topic-mixture profile per community instance"

transform T_contextualise_topic_matrix :
  intent: contextualise
  manner: "grid-based (community threads x time windows)"
  input: D_community_threads, D_networks
  output: A_topic_matrix
  actor: machine
  description: "Arrange community threads and time windows into a matrix
    grid for small-multiples display of topic evolution"

artifact A_topic_matrix : arrangement(D_community_threads)
  context: D_networks
  principle: "rows = community threads; columns = time windows"
  description: "Grid layout for topic-evolution small multiples"

transform T_vis_topic_evolution :
  intent: visualise
  manner: "matrix/small-multiples plot of topic profiles"
  input: A_topic_matrix, F_community_topic_profile, P_topics
  output: V_topic_evolution
  actor: machine
  description: "Show each community thread's topic profile per time window
    as small multiples, labelled with named topics"

artifact V_topic_evolution : visualisation(A_topic_matrix,
    F_community_topic_profile, P_topics)
  layout: "matrix grid (threads x windows)"
  form: "small-multiple stacked bar/area charts"
  encoding: "cell position from A_topic_matrix; bar segments from
    F_community_topic_profile; segment labels from P_topics"
  description: "Primary view for answering what each community's research
    foci are and how they evolve"

# ============================================================================
# STEP 10: CROSS-COMMUNITY MEMBERSHIP OVERLAP
# ============================================================================

transform T_characterise_period_overlap :
  intent: characterise
  manner: "define-relations (pairwise membership overlap within the same
    time window)"
  input: D_window_communities, F_community_members
  output: F_period_overlap_matrix
  actor: machine
  description: "Compute pairwise Jaccard overlap among communities
    coexisting within the same time window"

artifact F_period_overlap_matrix : feature(D_window_communities)
  value structure: matrix
  value type: numeric
  representation form: "pairwise overlap matrix among co-existing
    communities per window"
  description: "Within-period membership overlap between communities"

transform T_vis_overlap_matrix :
  intent: visualise
  manner: "matrix-plot"
  input: F_period_overlap_matrix
  output: V_overlap_matrix
  actor: machine
  description: "Display the within-period community overlap matrix,
    faceted by time window"

artifact V_overlap_matrix : visualisation(F_period_overlap_matrix)
  layout: "matrix grid, one facet per time window"
  form: "coloured matrix cells"
  encoding: "cell colour from F_period_overlap_matrix overlap value"
  description: "View for identifying converging, diverging, or
    near-duplicate communities within a period"

transform T_assess_overlap :
  intent: assess
  manner: "identify candidate merges or eroding distinctiveness"
  input: V_overlap_matrix, K_prior_domain_knowledge
  output: K_overlap_assessment
  actor: human
  description: "Flag community pairs with persistently high overlap as
    candidates for merger or loss of distinct identity"

artifact K_overlap_assessment : knowledge(F_period_overlap_matrix)
  representation form: "quality judgment with flagged pairs"
  description: "Judgment identifying community pairs at risk of merging or
    losing distinctiveness"

# ============================================================================
# STEP 11: SYNTHESISE FINDINGS
# ============================================================================

transform T_synthesise :
  intent: generate-knowledge
  manner: "formulate-statements"
  input: P_evolution_events, F_author_role_metrics, F_role_label, P_topics,
         V_topic_evolution, K_overlap_assessment, K_structure_assessment
  output: K_findings
  actor: human
  description: "Synthesise the analyst's answers regarding the number and
    stability of communities, their core leadership, their research foci
    and evolution, cross-community membership overlap, and merge/split/
    dissolution events"

artifact K_findings : knowledge(D_community_threads, P_topics)
  representation form: "statements and insights"
  description: "Consolidated findings on the intellectual structure and
    evolution of the IEEE VIS collaboration community"