Class: Insika::Demo::Seeder

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/demo/seeder.rb

Overview

Populates one instance with enough realistic-looking data to see every loop working at once: a funnel with a frozen baseline, follow-ups in all four states, refinement runs across the lifecycle, pending + resolved approvals, distillation proposals/facts, and a golden set with a baseline. Writes ONLY through the same domain-store APIs a real turn would use (OutcomeStore#create + FunnelFold, FollowupStore#create + transitions, ...) — there is no bulk/bypass path, by design (D1: the engine never hard-codes a shortcut for its own demo).

force: false (default) is a no-op once the demo agent exists — safe to run more than once. force: true re-seeds on top: it re-recomputes the funnel cleanly (FunnelFold#recompute always wipes its own pair first) but APPENDS a fresh batch of followups/refinement runs/ approvals/proposals/goldens, because none of those stores expose a scoped bulk-delete that a shared "platform" tenant could safely call without risking another agent's data (FollowupStore#purge/ ProposalStore#purge are TENANT-wide, not per-agent).

Constant Summary collapse

FUNNEL_DAYS =
40

Instance Method Summary collapse

Constructor Details

#initialize(profiles:, store:, session_store:, task_store:, outcome_store:, funnel_store:, followup_store:, refinement_store:, pending_action_store:, proposal_store:, memory_store:, golden_store:, baseline_store:, event_stream:) ⇒ Seeder

Returns a new instance of Seeder.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/insika/demo/seeder.rb', line 28

def initialize(profiles:, store:, session_store:, task_store:, outcome_store:,
               funnel_store:, followup_store:, refinement_store:,
               pending_action_store:, proposal_store:, memory_store:,
               golden_store:, baseline_store:, event_stream:)
  @profiles = profiles
  @store = store
  @session_store = session_store
  @task_store = task_store
  @outcome_store = outcome_store
  @funnel_store = funnel_store
  @followup_store = followup_store
  @refinement_store = refinement_store
  @pending_action_store = pending_action_store
  @proposal_store = proposal_store
  @memory_store = memory_store
  @golden_store = golden_store
  @baseline_store = baseline_store
  @event_stream = event_stream
end

Instance Method Details

#seed!(force: false) ⇒ Object

-> { seeded: false, reason:, agent: } | { seeded: true, agent:, counts: … }



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/insika/demo/seeder.rb', line 49

def seed!(force: false)
  existing = @profiles.fetch(Demo::AGENT_ID)
  return { seeded: false, reason: "already_seeded", agent: Demo::AGENT_ID } if existing && !force

  # A distinct suffix per call: `force: true` on top of an existing
  # batch would otherwise collide on FollowupStore's own dedup rule (one
  # pending record per tenant+agent+customer+reason) and raise.
  @batch = SecureRandom.hex(3)
  seed_agent!(existing)
  # `funnel_outcomes` runs LAST: `seed_followups!` writes one extra
  # "purchased" outcome (the nudge's conversion, for the A/B card) —
  # the fold has to see it, or it sits un-folded until some later pass.
  counts = {
    followups: seed_followups!,
    refinement_runs: seed_refinement!,
    approvals: seed_approvals!,
    distillation_proposals: seed_distillation!,
    golden_cases: seed_evals!,
    funnel_outcomes: seed_sessions_and_funnel!
  }
  { seeded: true, agent: Demo::AGENT_ID, counts: counts }
end