Dentolize · Dynamic Clinic Seeder Walkthrough
On this pageBusiness viewTechnical view

Sandbox & CI wiring

Business view

The seeder is only half the story; the other half is how the CI/sandbox system runs it and surfaces the results. This PR:

  • Teaches the PR preview comment to advertise a rich demo dataset (when the

dynamic seeder ran) vs a basic auto-seed, and to list the whole staff roster plus a docs site link.

  • Adds a Sandbox Ops workflow to reseed / reset / redeploy / destroy / refresh

a preview on demand.

  • Adds a Sandbox QA workflow that runs an AI agent to plan and (optionally)

execute test "stories" against the sandbox.

Technical view

How the seeder talks to the sandbox CLI · report.js:32-51

The summary printer emits two machine-readable blocks the homelab sandbox CLI parses out of the captured seed log:

=== SANDBOX_SEED_INFO ===         # report.js:32-39
SEED_MODE=rich
SEED_COMPANY=<companyLoginName>
SEED_COMPANY_ID=<uuid>
SEED_EMAIL=<ownerEmail>
SEED_USERNAME=owner
SEED_PASSWORD=<password>
=== END_SANDBOX_SEED_INFO ===

=== SANDBOX_SEED_USERS ===        # report.js:49-51, owner first
owner            Owner · All Permissions
doctor1          Dr 1 · 45% Commission · Salary 4000
…
=== END_SANDBOX_SEED_USERS ===

These marker lines and the KEY=VALUE format are a contractreport.js:4-7 warns to keep them stable. SEED_MODE is always rich from the dynamic seeder; the "basic" path comes from a different (overlay) seeder.

The PR comment · .github/workflows/sandbox.yml

The Sandbox workflow runs on the self-hosted runner and (deliberately) does not use actions/checkout — the sandbox CLI manages its own checkout tree; a checkout step would grow the runner's persistent volume every PR (new header comment, sandbox.yml). Changes in this PR:

  • New "Generate branch docs site" step, PR-open only, detached, best-effort

(sandbox-docs … generate --detach || true) — the site this walkthrough is part of, appearing at https://<slug>.docs.anastawfik.com after ~15–40 min.

  • The comment now reads SEED_MODE, SEED_USERNAME, and SEED_USERS outputs and:
  • labels the clinic user block "rich demo dataset — dynamic seed" vs

"basic auto-seed, idempotent" based on seedMode === "rich";

  • shows the username ("works instead of email") when present;
  • appends an "All clinic logins" block from the roster (same password for

everyone), when SEED_USERS is non-empty;

  • adds a Docs link line.

Sandbox Ops · .github/workflows/sandbox-ops.yml (new)

A workflow_dispatch with an action choice: reseed, reset-data, redeploy, destroy, update-docs. It invokes the sandbox CLI for the chosen branch and then refreshes the same <!-- sandbox-preview-comment --> on the PR. This is the "refresh via Sandbox Ops → update-docs" the PR comment points to.

Sandbox QA · .github/workflows/sandbox-qa.yml (new)

A workflow_dispatch with a mode choice: full-auto, plan-only, execute. It runs a QA agent against the live sandbox and then, depending on mode:

  • plan-only → posts the full plan for human review as a

<!-- sandbox-qa-plan --> comment.

  • full-auto / execute → creates labeled GitHub "story" issues

(labels ai-automated and a per-PR label) and posts a short <!-- sandbox-qa-report --> summary comment, uploading run artifacts.

These workflows are the automation layer that a rich, deterministic dataset makes possible: predictable data is what lets an agent write and check test stories reliably.

The one-line fix that unblocks it · seedFeatureFlags.js

seedFeatureFlags.js changed its import from ../prisma to ./prisma (seedFeatureFlags.js:1) — a corrected relative path to the Prisma client so the feature-flag seeder resolves correctly in this layout. Small, but it's part of the same "make the sandbox seed cleanly" effort.