# Service and module map This is an ownership map, not an API dump. Read the owning implementation and tests before changing behavior. ## Lifecycle and account ownership | Module | Owns | Important constraints | | --- | --- | --- | | `src/bootstrap.ts` | Dependency composition and startup wiring | Keep business policy in services; preserve initialization order and test seams. | | `src/main-loop.ts` | Shared discovery/screening/dispatch workers and legacy loop | Loops are abortable; queue transitions and shutdown must remain recoverable. | | `services/reddit-account-runtime.ts` | Immutable account runtime/factory/manager lifecycle | Same-account operations serialize; session refresh replaces one runtime. | | `services/reddit-user-messenger.ts` | Account selection for explicit API/MCP messages | Prefer the newest existing conversation owner; otherwise choose the authenticated running account with the fewest hourly sends. | | `services/reddit-account-runtime-builder.ts` | Concrete account dependency graph and account loop | Account-specific browser, Matrix, repos, limiter, automation, chat, and media live here. | | `services/reddit-accounts.ts` | Account import/activation orchestration | Verification must bind Reddit cookies and Matrix identity before activation. | | `services/account-auth-context.ts` | Current verified identity snapshot | Account work pauses unless both sides authenticate. | | `services/session-bound-runtime.ts` | Legacy auth-bound background lifecycle | Prevents background work while logged out. | ## Discovery, preparation, and delivery | Module | Owns | Important constraints | | --- | --- | --- | | `services/monitor.ts` | Subreddit ordering, candidate fetching, age/gender/seller screening, rejection summaries | Cheap checks first; preserve exact rejection/deferred counts; listing 404 disables the subreddit. | | `reddit/api.ts` | Reddit JSON calls, post parsing, seller/profile evidence, username resolution, error types | All reads must use the coordinator; redact error metadata. | | `reddit/request-coordinator.ts` | Process-wide Reddit request spacing and cooldown | Space failed requests too; 429 cooldown is global. | | `services/processor.ts` | Source-specific AI preparation and outbound safety | Returns prepared or explicit skip; performs no remote chat send. | | `services/physique-targeting.ts` | Pure optional score-range decision for image candidates | Disabled means pass; enabled ranges reject unknown and out-of-range scores before opener generation. | | `services/strategy-selector.ts` | Weighted explore/exploit selection and experiment metadata | Separate image/chat strategy sections; respect mature response window and sample floor. | | `services/recipient-deduplicator.ts` | Global recipient history plus live reservation | Case-insensitive; release failures, commit successes, recover stale claims. | | `utils/rate-limiter.ts` | Per-account send spacing/hour limits/jitter | Increment only for confirmed sends; reply priority may use the same limiter. | | `database/candidate-queue-repository.ts` | Durable candidate state machine, leases, retries, counts | Mutations require the expected worker lease; recover expired/interrupted work. | ## Account growth Comment-based growth exists so a new account accumulates the age/karma history Reddit requires before it will accept chat invitations. It is account-scoped rather than part of the shared outreach funnel, it is the lowest-priority work an account runtime performs, and it deliberately keeps running while the account is held out of outbound messaging — building that history is what lifts the hold. | Module | Owns | Important constraints | | --- | --- | --- | | `services/account-growth.ts` | Per-account discovery, generation, posting, verification, and trust updates | Auto-posts without operator review, so both screening stages fail closed; due retries and existing queue work run before discovery; an interrupted post is never retried. | | `services/growth-pacer.ts` | Adaptive allowance ladder, the operator limit override, promote/demote/pause decisions, quiet hours, spacing | Pure and clock-injected. Pause beats demote beats promote; an operator limit replaces the earned allowance but never the pause; jitter is derived from the previous post so the gate cannot flap. | | `services/growth-thread-screening.ts` | Pure thread eligibility (age window, comment count, locked/stickied/NSFW) | A comment on a dead or saturated thread wastes a scarce daily allowance. | | `services/growth-comment-safety.ts` | Deterministic pre-publication gate on generated comment text | Rejects links, contact solicitation, user tags, filler, and any text revealing the generator. Independent of prompt wording. | | `reddit/comment-client.ts` | Comment submission and comment-state lookups for one account | Classifies Reddit's error codes into retry/abandon/disable/re-auth/stop; runs inside the account's own browser session and shares the request coordinator. | | `database/growth-repository.ts` | Growth settings, per-account community list, durable comment records | One comment per thread across every account; mutations require the expected worker lease; queue clearing deletes only unposted discovered/retryable rows. | | `services/account-browsing-simulation.ts` | Durable pacing, eligibility, post/comment weighting, selection, and optional vote dispatch | Runs below comment growth; votes require the per-account opt-in plus running mode outside dry-run, and uncertain writes are never retried. | | `database/browsing-simulation-repository.ts` | Per-account browsing policy, cross-account selection checks, and minimal decision audit | Stores identity/permalink, reasons, and whether Reddit confirmed a vote without copying Reddit content; browsing never feeds comment trust. | Verification is the safety mechanism that matters most. Posted comments are swept at roughly 15 minutes, 2 hours, and 24 hours using one batched `info.json` request, and a single signed-out probe on the second sweep decides whether the comment is publicly visible at all. Two consecutive removals, or one invisible comment, hard-pauses the account until an operator clears it; a failed probe never pauses anything. ## Conversation, chat, and media | Module | Owns | Important constraints | | --- | --- | --- | | `services/chat/service.ts` | Matrix conversation sync, cache updates, starts/replies, scoped cooldowns | Room-creation limits pause new outreach without blocking existing-room replies; Matrix acceptance and UI visibility are distinct. | | `services/chat/matrix/client.ts` | Matrix HTTP protocol and error classification | Authentication/rate-limit errors need typed handling. | | `services/chat/cache.ts` | Account-scoped cached conversations and sync state | SQLite is durable; do not share caches across accounts. | | `services/chat/matrix/username-resolver.ts` | Matrix/Reddit identity mapping | Preserve unresolved internal IDs without leaking them in operator text. | | `services/chat/matrix/token-refresher.ts` | Explicit refresh-unavailable behavior | New credentials come from verified extension dumps, not token sniffing. | | `services/recipient-account-status.ts` | Periodic cached-conversation recipient profile checks | Only definitive Reddit results replace durable state; checks are authentication-bound and must not block the reply loop. | | `services/conversation-automation.ts` | Reply-first policy, claims, retries, send-time refresh, handoffs, turn budgets | Snapshot policy; claim before send; supersede stale queued work; reconcile pending claims; fail closed. | | `services/conversation-state.ts` | Pure conversation parsing/state/safety helpers | Conversation text is untrusted data; keep prompt boundaries explicit. | | `services/conversation-boundaries.ts` | Sequence-aware media requests, refusals, and full-stop detection | Short ambiguous replies become boundaries only in the matching request context. | | `services/outbound-message-safety.ts` | Final no-proximity/no-meeting rule | This is defense in depth beyond prompts. | | `services/conversation-outcome*.ts` | Response outcome classification/recording | Keep analytics attribution account/message scoped. | | `services/response-checker.ts` | Inbox/performance response checks and successful examples | Non-overlapping; do not confuse chat sync with outcome maturity. | | `services/media.ts` | Download, verify, index, and list private media occurrences while reusing asset files | Preserve account ownership, retryable download failures, and authenticated serving. | | `services/media-sync.ts` | Periodic authenticated media sync and operator-visible completion status | Stop while auth is unavailable and on runtime shutdown; do not report partial work as success. | | `services/media-library.ts` | Shared operator uploads, image validation/re-encoding, classification state, and private files | Require consent confirmation; received media never enters this store. | | `services/media-library-exchange.ts` | Inbound request detection, progressive selection, reservation, and image-first exchange | Never offer proactively; exact tags do not substitute; no asset reuse per conversation. | | `database/media-library-repository.ts` | Shared asset metadata and durable account/conversation send audit | Reserve before remote send; uncertain sends stay consumed. | ## Persistence | Module | Owns | | --- | --- | | `database/client.ts` | Database open settings and ordered migrations. | | `database/repositories.ts` | Posts, messages, successes, activity, outbox, states, claims, outcomes, users, recipient history. | | `database/account-repositories.ts` | Verified account records, conversations, sync cursors, and media content. | | `database/ai-usage-repository.ts` | Model request/cost/reliability records. | | `database/legacy-content-import.ts` | One-time ownership of legacy file-backed chat/media data. | | `config/persistence.ts` | Secret-free application configuration in SQLite. | Repositories should expose domain operations rather than raw SQL to callers. Multi-step state transitions belong in SQLite transactions when partial completion would break invariants. ## Web and agent surfaces | Module | Owns | | --- | --- | | `web/server.ts` | Express lifecycle, middleware order, route registration, static dashboard/media. | | `web/auth.ts` | Dashboard session and bearer-token authorization. | | `web/context.ts` | Narrow route dependency container. | | `web/routes/*.ts` | Focused endpoint families. | | `web/api-catalog.ts` | Operation metadata, OpenAPI, and capability discovery. | | `web/agent-job-manager.ts` | Bounded async sync jobs and job status. | | `web/events/*` | Typed event publication, replay, subscriptions, and Express SSE. | | `web/log-broadcaster.ts` | Recent logs plus legacy/typed stream adapters. | | `mcp/api-client.ts`, `mcp/server.ts` | HTTP-backed stdio MCP tools. | Authorization is semantic, not just authentication: read and control agent tokens intentionally cannot import sessions, send messages, activate accounts, mutate legacy config, or use debug routes. ## Frontend | Area | Owns | | --- | --- | | `apps/dashboard/src/app/` | Shell, routing, providers, auth status, notifications, realtime repair. | | `apps/dashboard/src/api/` | HTTP client, schema parsing, query keys/hooks. | | `apps/dashboard/src/features/` | Route-level feature slices. | | `apps/dashboard/src/components/` | Reusable domain-aware UI elements. | | `packages/api-contracts/` | Shared strict transport schemas and inferred types. | ## Utility boundaries - `utils/logger.ts`: Winston creation, child context, and attachable sinks. No production `console.log`. - `utils/retry.ts`: bounded retry behavior for operations that are safe to repeat. - `utils/image.ts`: download/MIME/size helpers. - `utils/gender-tag.ts`: deterministic self-declared tag parsing. - `utils/fetch-with-timeout.ts`: abortable HTTP timeout wrapper. - `utils/json-safe.ts`: safe serialization for log/event data. When a module starts owning two independent reasons to change, extract a narrow collaborator and inject it. Do not solve size alone by moving methods into a generic utility file.