Files
docs/social_branding/plan-prd-implementation-audit.md
-Puter e6685203fe feat: initial docs repo with project inventory and all documentation
- Added REPO_INVENTORY.md with all repos, branches, remotes, and staging info
- Added .gitignore
- Synced all existing docs from local workspace
- Centralized documentation hub for GrowQR team
2026-06-22 15:04:27 +05:30

28 KiB

Social Branding Service Audit

Date: 2026-03-23

Purpose

This document compares:

  1. the product BRD / PRD in docs/PRD.md
  2. the narrowed execution plan in docs/plan.md
  3. the current implementation in app/ and tests/

It is intended as a handoff and presentation document so another engineer or stakeholder can answer:

  • what was planned
  • what was actually built
  • which decisions were taken to narrow scope
  • which assumptions phase one was built on
  • what is still missing versus the plan
  • what is still missing versus the PRD
  • what architecture should be used going forward

Auth is intentionally excluded from blocker status for this review. Future auth is assumed to be Clerk-issued JWT at the service boundary.

Executive Summary

The current repo is best understood as a narrowed, LinkedIn-first individual-user MVP that is substantially aligned with the overnight plan, but not aligned with the full PRD.

The implementation does support the plan's core demo loop:

  1. import a LinkedIn profile snapshot
  2. compute a LinkedIn audit and Brand Score v1
  3. infer or select a persona strategy
  4. generate a 2-week content calendar with an 80/20 split
  5. generate LinkedIn drafts
  6. move drafts through approval, rejection, regeneration, and manual publish confirmation
  7. expose dashboard and local event history

That flow is implemented and tested. uv run pytest passed with 4 passed, 1 warning on 2026-03-23.

However, the repo is not PRD-complete. The PRD describes a broader multi-platform, more automated system with richer scoring, profile rewrites, live collection, scheduled posting, analytics, engagement automation, and enterprise workflows. Those are not implemented here.

The biggest architectural mismatch with the desired next version is this:

  • the code already has some engine-like pure logic
  • but the engine is not yet separated as an explicit domain package or service boundary
  • orchestration, persistence, and business logic are still mixed inside one application service
  • surfaces are currently HTTP-only in practice
  • Redis and the worker exist as scaffolding, not as an active runtime path

Canonical Scope Hierarchy

The repo currently has three levels of scope, and they should not be confused during presentation.

1. PRD scope

The PRD is the broad product target:

  • individual plus enterprise
  • LinkedIn, Instagram, X, YouTube
  • automated connect -> collect -> analyze -> generate -> approve -> post -> track loop
  • Brand Score feeding RQx
  • richer content and analytics behavior

Relevant references:

  • docs/PRD.md:21-36
  • docs/PRD.md:42-70
  • docs/PRD.md:80-102
  • docs/PRD.md:183-248
  • docs/PRD.md:360-397

2. Plan scope

The plan is the locked overnight MVP and is the real governing doc for what this repo was trying to ship immediately:

  • individual only
  • LinkedIn only
  • manual import fallback instead of hard OAuth
  • Brand Score v1 from available LinkedIn data
  • content calendar, drafts, approval queue, manual publish confirmation
  • dashboard and local events
  • enterprise and multi-platform behavior deferred

Relevant references:

  • docs/plan.md:9-38
  • docs/plan.md:78-128
  • docs/plan.md:149-158

3. Current implementation scope

The code matches the narrowed plan much more closely than it matches the PRD. It is therefore more accurate to describe the current service as:

"A request-driven, LinkedIn-first social branding MVP for individual users with manual ingestion, simplified scoring, deterministic content generation, approval workflow, dashboard summaries, and local event persistence."

That description is also how the README frames it:

  • README.md:3-23
  • README.md:81-85

Current Architecture Assessment

What exists today

The current architecture is:

  • HTTP API surface in app/api/v1/
  • one application service in app/services/social_branding.py
  • several pure or mostly pure helper modules in:
    • app/services/brand_score.py
    • app/services/persona_strategy.py
    • app/services/content_calendar.py
  • persistence in SQLAlchemy models in app/models.py
  • queue abstraction in app/services/queue.py
  • a worker loop in app/worker/main.py

This is a valid MVP architecture, but it is not yet the target split you described.

Desired target architecture

For the next version, the clean split should be:

1. Social branding engine

A pure, platform-agnostic decision engine that takes normalized inputs and produces outputs such as:

  • audits
  • scores
  • persona strategy decisions
  • calendar plans
  • draft suggestions
  • recommendation bundles

This layer should not know about:

  • FastAPI
  • SQLAlchemy sessions
  • Clerk JWTs
  • Redis
  • Postgres
  • HTTP request shapes

2. Social branding service layer

An orchestration layer that:

  • receives authenticated user context
  • loads and stores data
  • calls the engine
  • persists outputs
  • emits events
  • coordinates approval and posting workflows
  • exposes use cases to surfaces

3. Surfaces

Adapters on top of the service layer, for example:

  • HTTP API
  • background worker consumers
  • Redis/event consumers
  • internal command handlers
  • future admin or operator surfaces

4. External adapters

Per-platform collectors and posters:

  • LinkedIn import adapter
  • Instagram connector
  • X connector
  • YouTube connector
  • GitHub connector (signals + content source)
  • manual upload/import adapter

See also: docs/external-adapters-plan.md for the platform-compliance contract and phased implementation plan.

5. Infrastructure

  • Postgres
  • Redis
  • storage
  • auth verification
  • observability

How close the current code is to that shape

Partially aligned:

  • app/services/brand_score.py already looks like engine logic.
  • app/services/persona_strategy.py already looks like engine logic.
  • app/services/content_calendar.py already looks like engine logic.

Not yet aligned:

  • app/services/social_branding.py combines orchestration, persistence, workflow rules, and business decisions in one class.
  • there is no explicit normalized engine contract
  • there is no repository layer
  • there are no platform adapter interfaces
  • surfaces are API routes only in practical use

Conclusion:

The repo contains the beginnings of an engine, but the engine is still embedded inside the service implementation rather than clearly separated.

What Was Implemented

Data model and persistence

The main persistence model is present and broadly follows the plan:

  • social_accounts
  • social_profile_snapshots
  • brand_scores
  • persona_strategies
  • content_calendar_items
  • content_drafts
  • approval_queue
  • posting_records
  • analytics_snapshots
  • engagement_drafts
  • integration_events

Reference:

  • app/models.py:58-235

Observations:

  • The model names mostly match the plan's domain model.
  • posting_records and integration_events were added beyond the explicit plan list and are useful.
  • engagement_drafts exists in schema only and is not actively used in the service flow.
  • Everything is stored through create_all() on startup; there is no migration system yet.

API surface

The HTTP routes listed in the README and plan are implemented:

  • LinkedIn import
  • persona select
  • brand score recalculate
  • content calendar generate/list
  • drafts generate
  • approval approve/reject/regenerate
  • publish confirm
  • dashboard
  • events
  • demo seed
  • health

References:

  • README.md:25-39
  • app/api/v1/__init__.py
  • app/api/v1/accounts.py
  • app/api/v1/brand_score.py
  • app/api/v1/content.py
  • app/api/v1/dashboard.py
  • app/api/v1/events.py
  • app/api/v1/demo.py
  • app/api/v1/health.py
  • app/api/v1/persona.py

LinkedIn ingest and audit

Implemented:

  • manual LinkedIn import payload
  • account upsert
  • profile snapshot persistence
  • section-level audit scoring
  • recommendation list persistence

References:

  • app/services/social_branding.py:190-239
  • app/services/brand_score.py:37-88

What it actually does:

  • scores headline, about, experience, skills, recommendations, featured, and activity
  • persists overall score and recommendations
  • uses simple heuristic thresholds, not benchmarked analysis

Brand Score v1

Implemented:

  • Brand Score computation on import
  • manual recalculation endpoint
  • score history persistence
  • event emission when score changes materially or when forced

References:

  • app/services/social_branding.py:134-188
  • app/services/social_branding.py:241-274
  • app/services/brand_score.py:91-142

What it actually does:

  • computes five components:
    • profile completeness
    • content consistency
    • engagement quality
    • visibility
    • audience growth
  • uses LinkedIn metrics only
  • stores local integration events in the service database

Persona strategy

Implemented:

  • six persona enums
  • heuristic persona inference from pathway context
  • manual persona override
  • cadence, tone, target role, and source context persistence

References:

  • app/models.py:35-41
  • app/services/persona_strategy.py:8-127
  • app/services/social_branding.py:67-96

What it actually does:

  • infers persona from role and goals
  • always assigns LinkedIn as the active platform
  • stores one active strategy at a time per user

Content calendar and drafts

Implemented:

  • 2-week calendar generation
  • 80/20 toolkit versus dynamic split
  • deterministic topic sequencing
  • LinkedIn draft generation

References:

  • app/services/social_branding.py:276-322
  • app/services/content_calendar.py:26-84
  • app/services/social_branding.py:360-459
  • app/services/content_calendar.py:97-144

What it actually does:

  • uses persona cadence to create slots over 14 days
  • marks some slots as dynamic using deterministic spacing
  • chooses from a fixed toolkit topic list per persona
  • generates simple template-based LinkedIn drafts

Approval and publish flow

Implemented:

  • queue item creation per draft
  • approve
  • reject
  • regenerate
  • posting state transitions
  • manual publish confirmation
  • local approval event emission

References:

  • app/services/social_branding.py:333-359
  • app/services/social_branding.py:360-418
  • app/services/social_branding.py:486-620

What it actually does:

  • every draft becomes an approval item and posting record
  • approving immediately transitions the posting record to ready_for_manual_publish
  • publish is confirmed manually by user-supplied external reference

Dashboard and events

Implemented:

  • latest brand score and recent trend
  • queue summary
  • posting state summary
  • latest analytics snapshot view
  • local event listing

References:

  • app/services/social_branding.py:622-705
  • app/services/social_branding.py:707-722

Worker and queue

Implemented in scaffold form:

  • queue backend abstraction
  • database no-op backend
  • Redis backend
  • worker loop

References:

  • app/services/queue.py:1-83
  • app/worker/main.py:14-36
  • README.md:83-85

Important reality:

  • the current product flow is request-driven
  • the worker does not execute domain jobs
  • the Redis queue is infrastructure-ready, not feature-ready

Test coverage

Implemented:

  • health check
  • happy path full MVP flow
  • limited-data import path
  • regenerate path state behavior

Reference:

  • tests/test_social_branding_flow.py:32-207

Observed verification:

  • command run: uv run pytest
  • result: 4 passed, 1 warning

Phase-One Foundations: Decisions and Assumptions

The user asked specifically for the assumptions and decisions behind the current phase-one implementation. Those are below.

Decision 1: Narrow to individual plus LinkedIn only

Why:

  • the PRD is much broader than can be implemented quickly
  • LinkedIn is the primary value surface in the PRD and plan
  • multi-platform plus enterprise would have blocked delivery

Where it shows up:

  • docs/plan.md:11-30
  • README.md:10-23
  • app/services/persona_strategy.py:124
  • app/services/social_branding.py:201-206
  • app/services/social_branding.py:313

Assumption:

  • proving one strong individual LinkedIn flow is more valuable than partial support across four platforms

Decision 2: Use manual import instead of OAuth-first collection

Why:

  • the PRD explicitly leaves data collection method to engineering
  • LinkedIn collection is the riskiest integration area
  • the overnight plan avoids blocking on OAuth and unstable APIs

Where it shows up:

  • docs/PRD.md:36
  • docs/PRD.md:240-248
  • docs/plan.md:13
  • docs/plan.md:35
  • app/schemas/social_branding.py:47-52
  • app/services/social_branding.py:190-239

Assumption:

  • GrowQR can seed or receive normalized LinkedIn data from a manual process, future adapter, or another service

Decision 3: Treat Brand Score as a simplified v1

Why:

  • the PRD's full seven-component score depends on data that does not exist in the narrowed MVP
  • the plan explicitly says not to block on unavailable cross-platform metrics

Where it shows up:

  • docs/plan.md:36
  • app/services/brand_score.py:18-24
  • app/services/brand_score.py:91-142

Assumption:

  • a meaningful but incomplete score is acceptable for v1 if it is stable, stored, and trendable

Decision 4: Use deterministic content generation instead of real AI orchestration

Why:

  • the plan prioritizes demonstrating flow and content structure over model sophistication
  • deterministic output is easy to test and explain

Where it shows up:

  • docs/plan.md:38
  • app/services/content_calendar.py:26-84
  • app/services/content_calendar.py:97-144

Assumption:

  • content templates and placeholders are enough for MVP validation

Decision 5: Make publish manual-confirmed

Why:

  • the plan explicitly allows manual publish confirmation
  • live posting would introduce platform API risk and auth complexity

Where it shows up:

  • docs/plan.md:37
  • app/services/social_branding.py:507-508
  • app/services/social_branding.py:591-620

Assumption:

  • for v1, it is enough to generate approved content and let the user confirm it was posted manually

Decision 6: Keep async infrastructure scaffolded but not operationally central

Why:

  • Postgres and Redis are useful for future scale and service consistency
  • the immediate flow can be run synchronously

Where it shows up:

  • README.md:75-85
  • .env.example
  • .env.docker
  • app/services/queue.py:1-83
  • app/worker/main.py:14-36

Assumption:

  • request-driven synchronous use cases are acceptable for phase one, with queue infrastructure reserved for later work

Decision 7: Trust caller-provided user_id

Why:

  • auth is intentionally out of scope

Where it shows up:

  • almost every request schema accepts user_id directly, for example app/schemas/social_branding.py:47-52, 87-91, 111-115, 153-157

Assumption:

  • an upstream system or future JWT layer will replace body-supplied identity

Implementation Status Versus Plan

The plan is mostly implemented, but some items are implemented in a thin MVP form rather than a durable production form.

Phase 1: Foundations

Plan status: implemented

Evidence:

  • social branding models exist in app/models.py:58-235
  • persona enums exist in app/models.py:35-41
  • brand score component model exists in app/models.py:89-99
  • persona topic libraries exist in app/services/persona_strategy.py:26-63

Assessment:

  • This phase is done for MVP purposes.
  • The main gap is architectural: these foundations are not yet separated into engine/service/adapters.

Phase 2: Profile ingest and audit

Plan status: implemented, simplified

Evidence:

  • import endpoint exists
  • manual payload fallback is the main supported path
  • audit scoring and recommendations are persisted
  • limited-data import test exists

Assessment:

  • Done for MVP.
  • Not equivalent to PRD-grade platform analysis.

Phase 3: Brand Score and persona strategy

Plan status: implemented, simplified

Evidence:

  • brand score is computed and stored
  • persona inference and manual selection work
  • score update events are persisted

Assessment:

  • Done for MVP.
  • The score model is intentionally reduced from the PRD.
  • Events are local persistence records, not cross-service integration delivery.

Phase 4: Content calendar and drafts

Plan status: implemented, partially shallow

Evidence:

  • 2-week calendar exists
  • 80/20 split exists
  • LinkedIn draft generation exists

Assessment:

  • Done for demo and workflow validation.
  • Dynamic triggers are represented as preselected topic types, not event-driven runtime behavior.
  • Drafts are deterministic templates, not model-generated or personalized beyond a few fields.

Phase 5: Approval and publish flow

Plan status: implemented

Evidence:

  • queue, approve, reject, regenerate, publish confirmation, and state transitions all exist

Assessment:

  • Strongly implemented for the narrowed MVP.
  • Still single-user only.
  • No scheduling engine or platform posting adapter exists.

Phase 6: Dashboard and hardening

Plan status: mostly implemented

Evidence:

  • dashboard endpoint exists
  • happy-path tests exist
  • deferred scope is documented

Assessment:

  • Done for MVP handoff and demo.
  • Not hardening-complete for production.
  • Missing migrations, background jobs, external integrations, auth, observability, and deeper test coverage.

Implementation Status Versus PRD

This is the most important presentation distinction:

  • plan alignment: mostly yes
  • PRD alignment: no, not yet

PRD items that are fully or mostly covered

Individual personas exist

  • six personas exist in the model
  • persona selection and switching are present

Caveat:

  • active platform mix is not implemented beyond LinkedIn

LinkedIn-first audit and content flow exists

  • LinkedIn import
  • audit
  • Brand Score v1
  • calendar
  • approval queue
  • manual publish confirmation

Brand Score history and dashboard exposure exist

  • score history is persisted
  • dashboard returns recent trend

PRD items that are only partially covered

Brand Score formula

PRD expectation:

  • seven components
  • RQx formula
  • downstream event to Assessment and Pathways services

Current implementation:

  • five components only
  • no RQx mapping
  • local event persistence only

References:

  • docs/PRD.md:82-102
  • app/services/brand_score.py:18-24
  • app/services/social_branding.py:174-188

Content model

PRD expectation:

  • rich toolkit catalog and multiple dynamic triggers
  • platform-aware formatting and platform mix rules

Current implementation:

  • reduced toolkit topics
  • three dynamic topic types
  • LinkedIn-only output

References:

  • docs/PRD.md:141-181
  • app/services/persona_strategy.py:26-63
  • app/services/content_calendar.py:38-43

Analytics

PRD expectation:

  • platform analytics per sync cycle
  • richer performance tracking and trend lines

Current implementation:

  • only snapshot summaries based on imported metrics
  • no real recurring sync
  • no per-content performance table

References:

  • docs/PRD.md:243-248
  • docs/PRD.md:371-381
  • app/models.py:198-211
  • app/services/social_branding.py:656-696

PRD items that are not implemented

Multi-platform runtime support

Not implemented:

  • Instagram runtime collection/generation/posting
  • X runtime collection/generation/posting
  • YouTube analysis/brief generation/posting pipeline

Even though platform enums exist, runtime behavior does not.

References:

  • docs/PRD.md:21-24
  • docs/PRD.md:198-235
  • app/models.py:28-32

OAuth connect and recurring sync

Not implemented:

  • platform OAuth flow
  • scheduled sync jobs
  • recurring collection cadence
  • delta-based collector jobs

References:

  • docs/PRD.md:63-70
  • docs/PRD.md:243-248
  • app/worker/main.py:14-36

Profile rewrites and application to platform

Not implemented:

  • rewrite generation for headline/about/experience
  • approval flow for profile updates
  • apply-to-platform action

References:

  • docs/PRD.md:190-193
  • no corresponding route or service use case exists

Recruiter visibility and keyword gap analysis

Not implemented beyond basic visibility scoring inputs.

Missing:

  • target-role benchmark
  • keyword gap detection
  • profile rewrite recommendations based on gaps

Auto-posting and scheduling

Not implemented.

Current system only records manual publish confirmation.

References:

  • docs/PRD.md:68-70
  • docs/PRD.md:179
  • docs/PRD.md:369-381
  • app/services/social_branding.py:591-620

Auto-approve mode

Not implemented.

The PRD explicitly calls for opt-in auto-approve.

References:

  • docs/PRD.md:179
  • docs/PRD.md:376

Sensitive-topic filter and tone lock

Not implemented.

Missing:

  • sensitive-topic classification before queueing
  • tone locking after initial brand establishment
  • policy-based regeneration or suppression

References:

  • docs/PRD.md:176-181

Engagement automation

Not implemented.

Notes:

  • the table engagement_drafts exists
  • no service flow populates it
  • no routes expose it

References:

  • docs/PRD.md:56
  • docs/PRD.md:168
  • docs/PRD.md:194-195
  • app/models.py:214-225

Enterprise social branding

Not implemented.

That entire scope is still absent.

References:

  • docs/PRD.md:250-397
  • docs/plan.md:25

Key Product and Technical Assumptions Embedded in the Current Repo

These assumptions should be stated explicitly in any presentation so the current implementation is not oversold.

Assumption: one service owns both business workflow and persistence

The code assumes one deployable service can hold:

  • workflow logic
  • persistence rules
  • local event persistence
  • API-facing use cases

This is acceptable for MVP, but it is why the engine is not yet truly reusable.

Assumption: normalized external data will eventually arrive

The import request shape assumes someone else can provide:

  • profile sections
  • aggregate metrics
  • pathway context

without this service solving collection first.

Assumption: demo readiness was more important than platform completeness

This is visible in:

  • deterministic content generation
  • manual publish confirmation
  • local event storage
  • request-driven flow

Assumption: Postgres and Redis are deployment options, not proof of async completeness

The repo can run on Postgres and Redis in Docker, but that should not be presented as meaning:

  • scheduled jobs are implemented
  • queue processing is meaningful
  • Redis is part of the live product loop today

Assumption: auth will be added upstream later

Today the service trusts request bodies for user_id.

For Clerk JWT integration, the service should move to:

  • derive subject from JWT
  • remove user_id from externally writable bodies where possible
  • enforce per-user access at the service layer

What Is Missing to Finish the Plan Properly

Strictly speaking, the plan's demo definition is met. But if "finish the plan properly" means "make the narrowed MVP robust and presentation-safe for handoff", the remaining work is:

1. Separate the engine from the service layer

Required:

  • create an explicit engine package
  • move pure decision logic out of application orchestration
  • define normalized engine input and output contracts

Why:

  • this is the biggest gap against the intended architecture
  • it makes later multi-surface work cleaner

2. Add repository and adapter boundaries

Required:

  • persistence repositories
  • platform import adapters
  • event publisher abstraction
  • posting adapter abstraction

Why:

  • right now platform, persistence, and workflow assumptions are tightly coupled

3. Replace startup create_all() with migrations

Required:

  • Alembic or equivalent

Why:

  • handoff and deployment reliability
  • production schema evolution

4. Turn queue and worker into real use-case execution paths

Required:

  • actual queued job types
  • background handlers
  • idempotency rules
  • retry behavior

Why:

  • the current worker is only scaffolded

5. Add stronger tests

Required:

  • service-layer unit tests for engine outputs
  • route-level error case tests
  • Postgres integration tests
  • Redis queue tests if worker becomes real

Why:

  • current tests prove happy-path MVP behavior only

What Is Missing to Reach the PRD

This is the longer roadmap beyond the narrowed MVP.

Individual PRD completion

Required work:

  • live or semi-live collection strategy per platform
  • recurring sync engine
  • full seven-component Brand Score
  • RQx mapping and real cross-service event delivery
  • profile rewrite generation and apply flow
  • richer toolkit library
  • real dynamic trigger ingestion
  • topic safety filtering
  • tone lock
  • optional auto-approve mode
  • scheduled posting adapters
  • platform-specific formatting
  • engagement queue generation
  • richer analytics model and trend views
  • platform activation recommendations per persona/archetype

Enterprise PRD completion

Required work:

  • enterprise account domain
  • company brand voice settings
  • governance rules and flags
  • multi-role approvals
  • enterprise content types
  • enterprise analytics
  • enterprise content calendar visibility and role actions

If the goal is to build toward the plan and finally the PRD while matching the desired split, the implementation sequence should be:

Work Package 1: Explicit engine extraction

Create a package such as app/engine/ or app/domain/engine/ with:

  • audit engine
  • score engine
  • persona engine
  • calendar engine
  • draft engine

Inputs should be normalized Python models, not SQLAlchemy rows.

Work Package 2: Application service boundary

Refactor SocialBrandingService into use cases such as:

  • import_profile
  • select_persona
  • recalculate_brand_score
  • generate_calendar
  • generate_drafts
  • approve_content
  • reject_content
  • regenerate_draft
  • confirm_publish
  • get_dashboard

Each use case should orchestrate repositories and engine calls.

Work Package 3: Adapter layer

Add adapter interfaces for:

  • profile collectors
  • posting executors
  • event publishers
  • analytics ingestors

Start with:

  • manual import adapter
  • LinkedIn placeholder adapter

Work Package 4: Surface layer cleanup

Keep surfaces thin:

  • HTTP API maps requests to use cases
  • worker consumes jobs and invokes use cases
  • Redis/event subscribers invoke the same use cases

Work Package 5: Auth integration

When Clerk JWT is added:

  • resolve user identity from token
  • remove body-driven identity where possible
  • add service-layer authorization guards

Work Package 6: Platform expansion

After the architecture split is in place:

  • add Instagram adapter
  • add X adapter
  • add YouTube adapter

Do not add those directly into the current SocialBrandingService shape, or the service will become harder to evolve.

Final Readout

What is done

The narrowed LinkedIn-first MVP is real and working:

  • ingest
  • audit
  • Brand Score v1
  • persona strategy
  • 2-week calendar
  • LinkedIn drafts
  • approval queue
  • manual publish confirmation
  • dashboard
  • local events
  • demo seed
  • tests passing

What decisions were taken

The implementation intentionally chose:

  • LinkedIn-only runtime
  • manual import over OAuth-first
  • simplified Brand Score
  • deterministic templates
  • manual publish confirmation
  • request-driven flow
  • local event persistence
  • deferred auth

What assumptions phase one was built on

Phase one assumes:

  • upstream or manual data can be provided
  • one-user flows are enough for validation
  • live posting is not required
  • local persistence is enough to prove the workflow
  • Redis/Postgres readiness is useful even without full async execution
  • the engine can be extracted later from the current helper modules and service logic

What is left versus the plan

Very little is left for the narrowed MVP feature set itself. The main unfinished work is structural and production-grade:

  • engine extraction
  • repository/adaptor boundaries
  • migrations
  • real worker jobs
  • broader tests

What is left versus the PRD

A large amount remains:

  • multi-platform support
  • real collection and sync
  • richer scoring and RQx integration
  • profile rewrites
  • scheduled posting
  • engagement automation
  • richer analytics
  • safety and policy logic
  • enterprise workflows

Bottom line

This repo should be presented as:

"Plan-complete for a narrowed LinkedIn-first MVP, but not PRD-complete. The next major step is not adding random features inside the current service. It is separating the engine from the service and surfaces so the PRD can be implemented cleanly."