- 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
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.tsgrowqr-backend/src/config.tsgrowqr-backend/src/routes/workflows.tsgrowqr-backend/src/routes/chat.tsgrowqr-backend/src/routes/agents.tsgrowqr-backend/src/routes/opencode.tsgrowqr-backend/src/actors/user-actor.tsgrowqr-backend/src/db/schema.tsgrowqr-backend/src/docker/manager.tsgrowqr-backend/src/lib/opencode.tsgrowqr-backend/src/lib/prompt-loader.tsgrowqr-backend/src/services/service-agents.tsgrowqr-backend/prompts/system.txtgrowqr-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.tsexposes only:GET /workflows/job-applicationPOST /workflows/job-applicationPOST /workflows/job-application/pausePOST /workflows/job-application/resumePOST /workflows/job-application/agents/:moduleId/runPOST /workflows/job-application/agents/:moduleId/score
user-actor.tssets IDs likejob-application:${userId}.prompt-loader.tshasjobApplicationModuleIds()hardcoded toresume,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.tshas users, stacks, actors, repos, sessions, events.- No
workflow_definitions,workflow_runs,workflow_steps,workflow_artifacts,workflow_approvals, orqscore_snapshotstables exist. user-actor.tskeeps 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:
interview-to-offercareer-transitionsalary-negotiation-war-roompromotion-readinesspersonal-brand-opportunity-engine- 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 noservicereturn summaries like:completed a local workflow step for ...completed a local workflow step.
service-agents.tsreturnsstatus: "local"for agents without a service.job-searchandjob-applycurrently act as local modules.
Target difference:
- No backend route should report real completion unless one of these happened:
- microservice executed,
- OpenCode executed and produced an artifact,
- user/human approval happened,
- module is explicitly marked
blocked/manual_required/coming_soon.
Required change:
- Replace local success with explicit statuses:
blocked_service_unavailablemanual_requiredwaiting_for_inputopencode_requiredcoming_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.tscan create sessions and send messages.routes/opencode.tsexposes session creation/message proxy.docker/manager.tsprovisions per-user OpenCode containers and syncs workspace to Git.user-actor.tsworkflow modules callrunServiceAgentProbe()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.txtis one global Grow Agent prompt.- Agent markdown files load into
{{MODULE_DESCRIPTIONS}}. user-actor.tsmanually defines tools and a specialstart_interview_to_offerpath.- 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_runsand artifacts.
Gap G — Chat route duplicates orchestration and infers workflow state
Current evidence:
routes/chat.tsfirst 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.tsalso 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.tsreturns session URLs usinghttp://localhost:8007andhttp://localhost:8008.routes/chat.tsdoes 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_URLROLEPLAY_PUBLIC_URLRESUME_PUBLIC_URLif needed
- Service adapters should return canonical
sessionUrlfields. - Actor/chat responses should pass through those URLs.
Gap I — Q Score is not yet a durable platform layer
Current evidence:
service-agents.tsuses static signal examples and can return an estimated Q Score fallback.- No durable
qscore_snapshotstable 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_snapshotsor store snapshots onworkflow_runsfor launch. - Add
qscore_signal_eventslater if needed. - Workflow module results should include
qscoreDeltametadata 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_requiredorlockedresponse 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:
- Workflow registry with launch workflow definitions.
GET /workflowsand generic workflow detail endpoint.- Generic workflow run routes.
- Minimal workflow run persistence tables.
- User actor updated to accept
workflowIdand use registry modules. - Replace local fake module success with blocked/manual/OpenCode statuses.
- Add OpenCode executor for artifact-producing modules.
- Add workflow-specific prompts and artifact contracts.
- Return service/session URLs from config or service response, not localhost constants.
- Keep
job-applicationroute aliases temporarily for old frontend calls.
Definition of done:
- Backend returns a real catalog of sellable workflows.
- A user can start
interview-to-offerand 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:
- Move long-running module execution toward Rivet workflow steps or one actor/action per run.
- Add retry policy and idempotency keys per module.
- Add approval gates:
- user input required,
- review artifact,
- approve next step,
- human escalation.
- Add event stream/poll endpoint for frontend progress.
- Add artifact browser API:
- list artifacts,
- read artifact metadata,
- get repo path/content.
- Add prompt/output validation:
- required files produced,
- required JSON keys,
- no empty success.
- 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:
- Real billing/entitlement integration.
- Workflow version rollout controls.
- Prompt version rollout controls.
- Admin observability:
- failed runs,
- blocked services,
- OpenCode container health,
- Gitea sync health.
- Service capability registry:
- which microservices are enabled,
- health,
- supported operations,
- public session URL patterns.
- 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:
- Add
src/workflows/types.tsandsrc/workflows/registry.ts. - Define the 5 launch workflow products.
- Add
GET /workflowsandGET /workflows/:workflowId. - Add minimal workflow run tables and migration.
- Generalize
routes/workflows.tswhile keepingjob-applicationaliases. - Update
user-actor.tssostartWorkflow({ workflowId, goal, input })uses registry modules. - Replace local success fallback with honest non-success statuses.
- Add OpenCode workflow executor for artifact modules.
- Add workflow prompt packs and output contracts.
- Remove localhost session URL construction from actor/chat responses.
- Simplify
routes/chat.tsso 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.