Skip to main content

Event System

Local, typed, calm domain events — the nervous system of the Career OS.

Parent: OVERVIEW.md · Packages: PACKAGE_BOUNDARIES.md


Purpose​

Events let Agent, Queue, Send, Follow-ups, Timeline, Scheduler, and UI stay loosely coupled while preserving:

  • Inspectability — progress is observable without a cockpit of polling.
  • Privacy audit — egress-related events feed Timeline (“what left / what stayed”).
  • Calm UX — UI subscribes and batches; no siren for every tick.

Events never stream career payloads to a JobJitsu cloud by default.


Design laws​

  1. On-device bus — in-process (host) event bus; optional durable log in Timeline storage.
  2. Typed contracts — event names and payloads live in packages/events.
  3. PII minimization — payloads carry IDs and coarse metadata; avoid résumé bodies on high-volume events.
  4. Batching at the edge — UI and notifications collapse bursts (“3 applications queued”).
  5. No urgency semantics — event types do not encode streaks, guilt, or “you’re behind.”
  6. Egress events are special — send attempted/succeeded/failed/unknown always recorded.
  7. UI never calls AI — the renderer subscribes to facts; the host invokes providers inside event handlers.

Startup cascade (demo)​

Host runtime (app/src/host) owns this chain with fake providers. See Agent activity view.


Event catalog (core)​

Naming: Domain.Action in past tense where possible (facts that happened).

App / identity / mail (host lifecycle)​

EventMeaning
App.StartedDesktop host finished boot wiring
Plugin.LoadedPlugin module loaded into host (may still be disabled)
Resume.ImportedUser imported a résumé (ID only)
Resume.AttachedReviewed import attached to identity and/or path (IDs only; not send)
Resume.GeneratedOn-device résumé prepared (ID only on bus)
Job.ImportedSingle role ingested
Jobs.SyncedJob Provider sync batch finished (counts)
Email.SyncedMailbox channel sync finished (counts only; fake or real)

Agent / Workflow​

EventMeaning
Agent.StartedRun began under preferences
Agent.PausedUser or policy paused; review queue intact
Agent.ResumedRun continued
Agent.ProgressCoarse progress (counts, stage) — batchable
Agent.IdleBelt tied — waiting for signal
Agent.FailedPreparative failure (not send)
Workflow.StartedWorkflow run began
Workflow.CompletedWorkflow run finished successfully
Workflow.FailedWorkflow run failed

Discovery​

EventMeaning
Discovery.RolesFoundCandidates fetched (count + source id)
Discovery.RolesCuratedFiltered toward fit

Applications​

EventMeaning
Application.DraftCreatedNew draft
Application.TailoredLocal intelligence applied
Application.UpdatedUser or agent edited
Application.StageChangedTracking status changed (see DATA_MODELS.md)
Application.SubmittedDomain outcome after approved egress (also emit Send.*)

Knowledge​

EventMeaning
Knowledge.UpdatedKnowledge Base entry created/updated (ID + kind only)

Queue​

EventMeaning
Queue.EnqueuedAwaiting review / approval
Queue.ApprovedUser approved send
Queue.RejectedUser declined / returned to draft
Queue.ClearedRemoved without send

Send (egress)​

EventMeaning
Send.AttemptedOutbound started (destination class)
Send.SucceededConfirmed leave
Send.FailedDid not complete; draft retained policy
Send.UnknownCannot confirm — must not treat as success

Follow-ups​

EventMeaning
FollowUp.ScheduledReminder armed (“Follow-up Created”)
FollowUp.DuePolite nudge ready (caution, not error)
FollowUp.SentNudge egress via send channel
FollowUp.DismissedUser deferred/cancelled

AI / Privacy​

EventMeaning
Ai.StartedInference / AI task unit began
Ai.FinishedAI task unit finished successfully
Ai.ValidationCompletedValidation report summary (pass|warn|fail counts)
Ai.LocalModelLoadingWarm-up
Ai.LocalModelReadyAgent · On-device may show ready
Ai.LocalModelFailedPreferences / path recovery
Privacy.EgressRecordedTimeline audit written

Extensions / Plugins / Preferences / System​

EventMeaning
Preferences.ChangedPolicy inputs changed
Scheduler.JobRanLocal job executed
Plugin.Enabled / Plugin.DisabledUser toggled agent skill
Extension.RegisteredExtension contribution registered
Extension.Enabled / Extension.DisabledUser toggled extension
Extension.UnloadedExtension removed from host
Extension.FailedExtension load/run failure

SSOT: packages/events must match this catalog when coded. Illustrative chains elsewhere (e.g. .cursor/rules/architecture.mdc) use these names only.


Payload guidelines​

✅ GOOD: { applicationId, stage, count }
❌ BAD: { fullResumeText, coverLetterBody } on Agent.Progress

Full documents stay in storage; events reference them. Egress events may note destination class (board | mail | file export) without logging secrets.


Flow examples​

Preparative path (no egress)​

Sovereign send​

Honest failure​


Consumers​

ConsumerInterest
TimelinePersist audit & craft history
Desktop UIStatus, toasts (batched), badge
SchedulerArm/cancel jobs from domain facts
NotificationsFollowUp.Due, approval needed — calm
PluginsOnly events allowed by capability

Durability​

  • Ephemeral bus: UI live updates.
  • Durable allowlist (normative): Send.Attempted|Succeeded|Failed|Unknown, Privacy.EgressRecorded, Queue.Approved|Rejected, Agent.Paused, Preferences.Changed, Plugin.Enabled|Disabled, Extension.Enabled|Disabled, Application.Submitted.
  • Optional durable: FollowUp.Sent, Workflow.Failed, Ai.ValidationCompleted (fail) — product may expand without removing the allowlist.
  • Retention is user-local; export is an explicit Future module (portability), not ambient sync.

Sovereignty acceptance criteria​

FlowAC
Approval onNo Send.Attempted without Queue.Approved (unless Trusted Automation Experimental enabled)
PauseAgent.Paused leaves review Queue intact; AI Task Queue cancels/freezes Running
Unknown sendSend.Unknown never shown as success
Validation failNo Queue.Enqueued for send from failed validation
Trusted AutomationDefault off; Timeline still records egress

Trusted Automation exception path (Experimental)​

Default: off. When user enables Trusted Automation in Preferences:

  1. Host may call send.approveAndSend for allowlisted intents without a separate UI queue.approve click.
  2. Implementation must still record an internal approval fact equivalent to Queue.Approved (auto-approve) or document a single Preferences.TrustedAutomation policy check before Send — never a silent network call with no audit.
  3. Always emit Send.* and Privacy.EgressRecorded.
  4. User can disable anytime; in-flight Running AI tasks follow pause/cancel policy.
  5. AC: With TA off, missing Queue.Approved fails closed. With TA on, egress still appears on Timeline; UI never shows Unknown as success.

Failure emission matrix​

SituationEmitDo not
Preparative agent errorAgent.FailedSend.*
Workflow run failsWorkflow.Failed (+ optional Agent.Failed)Enqueue for send
Model load/inference infra failAi.LocalModelFailedFake Agent · On-device ready
Validation fail/warnAi.ValidationCompletedQueue.Enqueued on fail
Send pathSend.* + durable auditTreat Unknown as Succeeded

Local scale notes​

  • Timeline retention: user-local; prefer compaction of ephemeral progress; durable allowlist retained until user export/delete.
  • AI Task Queue default concurrency = 1 (configurable later); avoid unbounded parallel model loads.
  • Embeddings indexes stay on-device; rebuild/gc is local maintenance, not cloud sync.

Anti-patterns​

  • Remote event gateways for résumé-related streams.
  • Per-keystroke agent events flooding the UI.
  • Using events to drive guilt notifications (“no Apply in 5 days”).
  • Plugins subscribing to all events without capability review.