No description
Find a file
DJP 8e25914939 Run page liveness: heartbeat banner + fix Apify $0 + Stage 4 budget cap
Three bugs surfaced by the Dove2 demo run on prod and addressed together
because they all conspire to make the run page look dead:

1. Apify cost events were never persisted. Stage 2 imported onApifyCost
   and registered an empty no-op callback inside its run loop, silently
   overwriting the CLI's DB-writing handler set in cli.ts:logCost(). The
   APIFY total stuck at $0.00 even though Stage 2 had spent $5+ in real
   billing. Removed the override; the CLI's callback now wins.

2. Stage 4 inherited Stage 2's Pass-1 soft cap and skipped every actor.
   resetBudget() sets a hard ceiling (95% of brief.budget_usd) and
   setSoftCap() sets the Pass-1 cap (50%). Stage 2 fills the soft cap,
   but Stage 4 never released it — every TIKTOK_TRANSCRIPTS / COMMENTS /
   PROFILE call returned "budget reached — skipping" and the manifest
   gate failed at 0% coverage. Stage 4 now calls setSoftCap(null) at
   entry so it stays bounded only by the hard ceiling.

3. Even between cost events the run page had no liveness signal. Apify
   actors run 1-3 minutes per scrape with no DB writes in flight, so the
   UI looked frozen. Added a best-effort heartbeat: apify_client writes
   .state/live_activity.json on every Apify status poll (every 5s),
   GET /reports/:id includes it on the response, and the run page shows
   a live banner with the current activity, elapsed time, last
   heartbeat age (flags as suspicious past 90s), and running Apify
   spend.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:12:53 -04:00
v2 Run page liveness: heartbeat banner + fix Apify $0 + Stage 4 budget cap 2026-04-29 21:12:53 -04:00
.gitignore Stop .gitignore from swallowing src/routes/briefs/ 2026-04-29 18:44:08 -04:00
DEVELOPER_BRIEF_V2.md Add V2: multi-team social-reporting platform with manifest-gated linking 2026-04-29 17:39:07 -04:00
README.md README: document the cd /opt/social-reporting && git pull && cutover-in-place flow 2026-04-29 18:40:55 -04:00

Social Reporting

V2 lives in v2/. All commands run from there.

cd v2
docker compose -f docker-compose.v2.yml --env-file .env up -d --build
npm install
npm test                       # 62 unit tests
npm run pipe seed --report <brief-id>

For the full V2 spec see DEVELOPER_BRIEF_V2.md.

Deploying V2 over an existing V1 install

If V1 is already deployed at /opt/social-reporting, cut over in place:

ssh you@optical-dev.oliver.solutions
cd /opt/social-reporting
git pull origin main                          # pulls in v2/, removes V1 dirs
bash v2/deploy/cutover-in-place.sh            # stops V1, migrates secrets, starts V2

The script prompts before doing anything destructive, migrates APIFY/Anthropic/Azure secrets from V1's .env into a fresh v2/.env, swaps the Apache conf to V2's, and starts the V2 docker stack. It also prompts for the email that will be auto-promoted to super-admin on first SSO sign-in (BOOTSTRAP_SUPER_ADMIN_EMAIL).

The Azure-registered redirect URI https://optical-dev.oliver.solutions/social-reports/login.html is preserved by V2 (Vite base: /social-reports/, React Router basename, and an explicit /login.html route alias).

V1 archive

V1 source is preserved on the v1-archive branch (frozen at the last V1 commit) and is no longer kept on the deployed server. To roll back from V2 to V1, the rollback script will re-clone v1-archive if needed:

# On the server
export REPO_URL="https://x-token-auth:YOUR_TOKEN@bitbucket.org/zlalani/social-reporting-tool.git"
bash /opt/social-reporting-v2/v2/deploy/rollback-to-v1.sh

To inspect or check out V1 source locally:

git checkout v1-archive