Files
docs/growqr-backend-launch-gap-plan.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

16 KiB

GrowQR Backend Launch Gap Plan

This document only lists the differences between the current backend and the target sellable-workflow platform. It is written so a backend agent can work independently from the frontend/UI agent.

Target assumption: workflows are sellable products; services are reusable capability engines; OpenCode is the per-user agentic execution workspace; Gitea is version-backed career memory; Rivet provides durable actor/workflow orchestration.


1. Current backend state observed

Relevant backend files inspected:

  • growqr-backend/src/index.ts
  • growqr-backend/src/config.ts
  • growqr-backend/src/routes/workflows.ts
  • growqr-backend/src/routes/chat.ts
  • growqr-backend/src/routes/agents.ts
  • growqr-backend/src/routes/opencode.ts
  • growqr-backend/src/actors/user-actor.ts
  • growqr-backend/src/db/schema.ts
  • growqr-backend/src/docker/manager.ts
  • growqr-backend/src/lib/opencode.ts
  • growqr-backend/src/lib/prompt-loader.ts
  • growqr-backend/src/services/service-agents.ts
  • growqr-backend/prompts/system.txt
  • growqr-backend/agents/*.md

Already aligned / do not rewrite now

  • Clerk-authenticated backend routes exist.
  • Central Gitea + per-user repo model exists.
  • Per-user OpenCode container lifecycle exists.
  • Custom OpenCode image support exists.
  • OpenCode workspace cloning/syncing exists.
  • Prompt/agent markdown loading exists.
  • Password is stripped from public stack responses.
  • User actor exists and can manage chat, workflow state, service calls, Gitea memory, and stack provisioning.
  • Basic microservice adapters exist for resume, interview, roleplay, and Q Score.

2. Critical backend gaps

Gap A — Workflow API is hardcoded to job-application

Current evidence:

  • routes/workflows.ts exposes only:
    • GET /workflows/job-application
    • POST /workflows/job-application
    • POST /workflows/job-application/pause
    • POST /workflows/job-application/resume
    • POST /workflows/job-application/agents/:moduleId/run
    • POST /workflows/job-application/agents/:moduleId/score
  • user-actor.ts sets IDs like job-application:${userId}.
  • prompt-loader.ts has jobApplicationModuleIds() hardcoded to resume, job-search, job-apply, sara, emily, qscore.

Target difference:

  • Backend owns a real workflow product catalog.
  • Routes are parameterized by workflow ID.
  • The current route surface can stay as compatibility aliases, but the canonical API should be generic.

Required change:

Add backend workflow registry:

src/workflows/
  types.ts
  registry.ts
  definitions/
    interview-to-offer.ts
    career-transition.ts
    salary-negotiation-war-room.ts
    promotion-readiness.ts
    personal-brand-opportunity-engine.ts
    first-job-launchpad.ts

Add routes:

GET  /workflows
GET  /workflows/:workflowId
POST /workflows/:workflowId/runs
GET  /workflows/:workflowId/runs/current
GET  /workflow-runs/:runId
POST /workflow-runs/:runId/pause
POST /workflow-runs/:runId/resume
POST /workflow-runs/:runId/modules/:moduleId/run
POST /workflow-runs/:runId/approvals/:approvalId

Keep temporary aliases:

/workflows/job-application → /workflows/interview-to-offer or /workflows/job-fit-apply-autopilot

Gap B — Workflow state is only actor memory, not a production run model

Current evidence:

  • db/schema.ts has users, stacks, actors, repos, sessions, events.
  • No workflow_definitions, workflow_runs, workflow_steps, workflow_artifacts, workflow_approvals, or qscore_snapshots tables exist.
  • user-actor.ts keeps one workflow state in actor state: workflowId, workflowStatus, workflowGoal, modules, timeline.

Target difference:

  • Workflow runs should be queryable, auditable, resumable, and visible even if the actor is unavailable.
  • Actor state can stay as the fast durable executor, but Postgres needs product/run records.

Required change:

Add minimal launch tables:

workflow_runs
  id
  user_id
  workflow_id
  workflow_version
  status
  goal
  input jsonb
  current_step_id
  progress_percent
  qscore_before jsonb
  qscore_after jsonb
  created_at
  updated_at
  completed_at

workflow_run_modules
  id
  run_id
  module_id
  title
  status
  service
  output_summary
  output jsonb
  error
  started_at
  completed_at

workflow_artifacts
  id
  run_id
  module_id
  type
  title
  repo_path
  public_url
  metadata jsonb
  created_at

workflow_events
  id
  run_id
  user_id
  type
  payload jsonb
  created_at

For tomorrow, these can be simple Drizzle tables plus migration, not a full enterprise workflow engine.


Gap C — No backend-owned sellable workflow definitions

Current evidence:

  • Agent markdown files exist, but workflow products do not.
  • Workflow metadata such as title, promise, pricing, outputs, visual theme, required inputs, score dimensions, and artifact specs is absent.
  • Frontend currently fills this gap with hardcoded workflow cards.

Target difference:

  • Backend should return workflow products directly to frontend.

Required launch definitions:

  1. interview-to-offer
  2. career-transition
  3. salary-negotiation-war-room
  4. promotion-readiness
  5. personal-brand-opportunity-engine
  6. optional: first-job-launchpad

Each definition should include:

type WorkflowDefinition = {
  id: string;
  version: string;
  title: string;
  shortTitle: string;
  promise: string;
  segment: string[];
  urgency: "low" | "medium" | "high";
  estimatedDuration: string;
  priceTier: "free" | "starter" | "premium";
  visual: {
    icon: string;
    color: string;
    mascotAgentIds: string[];
  };
  requiredInputs: Array<{ id: string; label: string; type: string; required: boolean }>;
  modules: WorkflowModuleDefinition[];
  outputs: ArtifactDefinition[];
  qscoreDimensions: string[];
  approvalGates: ApprovalDefinition[];
}

Gap D — Workflow modules can still complete as local placeholders

Current evidence:

  • In user-actor.ts, modules with no service return summaries like:
    • completed a local workflow step for ...
    • completed a local workflow step.
  • service-agents.ts returns status: "local" for agents without a service.
  • job-search and job-apply currently act as local modules.

Target difference:

  • No backend route should report real completion unless one of these happened:
    1. microservice executed,
    2. OpenCode executed and produced an artifact,
    3. user/human approval happened,
    4. module is explicitly marked blocked / manual_required / coming_soon.

Required change:

  • Replace local success with explicit statuses:
    • blocked_service_unavailable
    • manual_required
    • waiting_for_input
    • opencode_required
    • coming_soon
  • For launch workflows, every module must either call a real service, call OpenCode, or return a non-success blocked/manual status.

Gap E — OpenCode exists but is not yet the workflow execution engine

Current evidence:

  • lib/opencode.ts can create sessions and send messages.
  • routes/opencode.ts exposes session creation/message proxy.
  • docker/manager.ts provisions per-user OpenCode containers and syncs workspace to Git.
  • user-actor.ts workflow modules call runServiceAgentProbe() directly and do not use OpenCode for artifact generation.

Target difference:

  • OpenCode should execute prompt-backed career artifact work when a module needs generated files or memory writes.

Required change:

Create a backend adapter:

src/workflows/executors/opencode-executor.ts

Responsibilities:

  • ensure/provision stack,
  • create OpenCode session per workflow module,
  • send workflow-specific prompt,
  • require structured JSON or markdown outputs,
  • write artifacts under /workspace/artifacts/...,
  • sync workspace to Git,
  • return artifact metadata to workflow_artifacts.

Launch use cases for OpenCode:

  • interview prep plan,
  • likely questions,
  • behavioral story bank,
  • negotiation script,
  • promotion evidence packet,
  • LinkedIn/profile rewrite draft,
  • weekly brand content plan.

Gap F — Prompt system is global, not workflow/product optimized

Current evidence:

  • prompts/system.txt is one global Grow Agent prompt.
  • Agent markdown files load into {{MODULE_DESCRIPTIONS}}.
  • user-actor.ts manually defines tools and a special start_interview_to_offer path.
  • No workflow-specific prompt packs, output schemas, or eval checks exist.

Target difference:

  • Each sellable workflow should have prompt packs and artifact contracts.

Required change:

Add workflow prompt files:

prompts/workflows/
  interview-to-offer/
    orchestrator.md
    resume-analysis.md
    interview-plan.md
    story-bank.md
    final-readiness-report.md
  career-transition/
  salary-negotiation-war-room/
  promotion-readiness/
  personal-brand-opportunity-engine/

Each module prompt should specify:

  • role,
  • inputs,
  • user tone,
  • output artifact path,
  • required sections,
  • JSON metadata contract,
  • Q Score dimensions affected,
  • what must be saved to memory.

For prompt optimization tomorrow:

  • Add a small local prompt smoke test that verifies each workflow prompt produces required sections/JSON keys.
  • Version prompts with PROMPT_VERSION.
  • Store prompt version on workflow_runs and artifacts.

Gap G — Chat route duplicates orchestration and infers workflow state

Current evidence:

  • routes/chat.ts first tries Rivet actor, then falls back to direct LLM/tool dispatch.
  • The fallback has its own tool list, service calls, hardcoded localhost demo URLs, and inferWorkflowStep() heuristic.
  • user-actor.ts also has tool dispatch and workflow logic.

Target difference:

  • Backend chat should not maintain a separate workflow engine.
  • Direct fallback may answer conversationally, but should not fabricate workflow state or duplicate module execution.

Required change:

  • Make userActor / workflow service the only workflow mutation path.
  • In routes/chat.ts, fallback options should be limited to:
    • simple LLM response with no workflow state, or
    • call backend workflow service APIs, not duplicate logic.
  • Remove inferWorkflowStep() as product state source.
  • Replace session URL construction with service-provided/public configured URLs.

Gap H — Session URLs are hardcoded to localhost

Current evidence:

  • user-actor.ts returns session URLs using http://localhost:8007 and http://localhost:8008.
  • routes/chat.ts does the same.

Target difference:

  • Backend should return service URLs configured for the current environment.
  • Frontend should never construct or guess microservice URLs.

Required change:

  • Add config values:
    • INTERVIEW_PUBLIC_URL
    • ROLEPLAY_PUBLIC_URL
    • RESUME_PUBLIC_URL if needed
  • Service adapters should return canonical sessionUrl fields.
  • Actor/chat responses should pass through those URLs.

Gap I — Q Score is not yet a durable platform layer

Current evidence:

  • service-agents.ts uses static signal examples and can return an estimated Q Score fallback.
  • No durable qscore_snapshots table exists in backend.
  • Frontend QX page is mostly static.

Target difference:

  • Every workflow should read baseline Q Score, update signals, and save before/after snapshots.

Required change:

  • Add qscore_snapshots or store snapshots on workflow_runs for launch.
  • Add qscore_signal_events later if needed.
  • Workflow module results should include qscoreDelta metadata when relevant.
  • Do not claim score improvement unless Q Score service or explicit estimate contract returns it.

Gap J — No entitlement/billing gate around sellable workflows

Current evidence:

  • No workflow SKU/entitlement model in schema.
  • Routes allow authenticated users to start workflows without plan checks.

Target difference:

  • Sellable workflows need at least a launch-ready entitlement boundary.

Required launch change:

Add simple fields to workflow definition:

priceTier
sku
isPurchasable
isFreePreview

Add minimal backend checks:

  • Free workflows can start.
  • Paid workflows return 402/payment_required or locked response if no entitlement.
  • For tomorrow, this can be stubbed with env/config allowlist while payment is wired later.

3. Big backend phases

Phase 1 — Tomorrow sellable workflow control plane

Goal: make backend safe to sell real workflows even if some specialized services are still evolving.

Must build/change:

  1. Workflow registry with launch workflow definitions.
  2. GET /workflows and generic workflow detail endpoint.
  3. Generic workflow run routes.
  4. Minimal workflow run persistence tables.
  5. User actor updated to accept workflowId and use registry modules.
  6. Replace local fake module success with blocked/manual/OpenCode statuses.
  7. Add OpenCode executor for artifact-producing modules.
  8. Add workflow-specific prompts and artifact contracts.
  9. Return service/session URLs from config or service response, not localhost constants.
  10. Keep job-application route aliases temporarily for old frontend calls.

Definition of done:

  • Backend returns a real catalog of sellable workflows.
  • A user can start interview-to-offer and get a durable run ID.
  • Modules either execute a real service/OpenCode task or show an honest blocked/manual status.
  • Generated artifacts are written to user repo and recorded in backend.
  • Frontend can render run state without hardcoded workflow knowledge.

Phase 2 — Production-grade orchestration and memory

Goal: make workflow runs reliable, resumable, and supportable.

Must build/change:

  1. Move long-running module execution toward Rivet workflow steps or one actor/action per run.
  2. Add retry policy and idempotency keys per module.
  3. Add approval gates:
    • user input required,
    • review artifact,
    • approve next step,
    • human escalation.
  4. Add event stream/poll endpoint for frontend progress.
  5. Add artifact browser API:
    • list artifacts,
    • read artifact metadata,
    • get repo path/content.
  6. Add prompt/output validation:
    • required files produced,
    • required JSON keys,
    • no empty success.
  7. Add run history and completed workflow summaries.

Definition of done:

  • A workflow can survive backend restarts and actor restarts.
  • Support can inspect run events/artifacts.
  • Users can resume an interrupted workflow.

Phase 3 — Scale, entitlements, and product ops

Goal: make the backend ready for paid launch scale and operational control.

Must build/change:

  1. Real billing/entitlement integration.
  2. Workflow version rollout controls.
  3. Prompt version rollout controls.
  4. Admin observability:
    • failed runs,
    • blocked services,
    • OpenCode container health,
    • Gitea sync health.
  5. Service capability registry:
    • which microservices are enabled,
    • health,
    • supported operations,
    • public session URL patterns.
  6. Analytics events:
    • workflow viewed,
    • run started,
    • module started/completed/failed,
    • artifact generated,
    • score updated.

Definition of done:

  • Workflows are measurable, billable, versioned, and operationally safe.

4. Backend agent handoff checklist

Work in this order:

  1. Add src/workflows/types.ts and src/workflows/registry.ts.
  2. Define the 5 launch workflow products.
  3. Add GET /workflows and GET /workflows/:workflowId.
  4. Add minimal workflow run tables and migration.
  5. Generalize routes/workflows.ts while keeping job-application aliases.
  6. Update user-actor.ts so startWorkflow({ workflowId, goal, input }) uses registry modules.
  7. Replace local success fallback with honest non-success statuses.
  8. Add OpenCode workflow executor for artifact modules.
  9. Add workflow prompt packs and output contracts.
  10. Remove localhost session URL construction from actor/chat responses.
  11. Simplify routes/chat.ts so workflow mutation only goes through actor/workflow service.

Do not spend this pass on rewriting specialized microservices. Treat them as capability adapters behind stable workflow module contracts.