Skip to main content

Client Document Kit

This is the single source of truth for the client profile lifecycle: how profiles are authored in the repo, how PDFs are generated and pushed to Google Drive, how the SC Client Dashboard (Google Sheet) is fed, and how to refresh any link in that chain. If you're trying to figure out "where is X for client Y" or "how do I update Z", start here.

Scope: Both a human reference and the configuration source for SC Doc Sync (FR-013, OR-006).


1. The big picture (one diagram)

                                   AUTHORING (this repo)
04-operations/templates/ ──┐
09-clients/<slug>/*.md │ Edit profile markdown
│ git commit + push

┌─────────────────────────────────────────────────┐
│ PROFILE = canonical source of truth │
│ 09-clients/<slug>/<slug>-client-profile.md │
└────────────┬────────────────────────────────────┘

┌────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
PDF GENERATION VALIDATION TRACKING REGISTRY SYNC
(manual, today) (manual, today) (daily cron)
│ │ │
│ ┌───────┼──────────┐ │
▼ ▼ ▼ ▼ ▼
scripts/publish- ClickUp Repo dashboard symphony-flow/scripts/
client-profiles.ps1 tasks status.md sync-registry-to-sheet.ts
│ │
▼ ▼
PDF → H:\Shared drives\Client_Delivery\<slug>\ SC Client Dashboard
\client-reference\<slug>-client-profile.pdf (Google Sheet)
(drops into Drive)

Three downstream consumers, one source. A profile change in the repo eventually flows to: (a) the PDF in Drive, (b) the validation surface in ClickUp, (c) the Sheet (only for fields the registry mirrors). Each path needs a different trigger to refresh — see §5 below.


2. Required and optional documents per client

Required (every client must have)

Document TypeNaming PatternTemplateSync Direction
Client Profile[slug]-client-profile.mdclient-profile-template.mdRepo → Drive (PDF)

v3.0 consolidation (2026-03-02): Brand voice and design kit content live inside the client profile under ## Brand Voice & Positioning and ## Brand Design System. The standalone brand-voice-template.md and design-kit-template.md are deprecated.

Optional standard documents

Document TypeNaming PatternTemplateSync Direction
Engagement Brief[slug]-engagement-brief.mdclient-engagement-brief-template.mdRepo → Drive (PDF)
Digital Presence Summary[slug]-digital-presence-summary.mdclient-digital-presence-summary-template.mdRepo → Drive (PDF)
Discovery Audit[slug]-discovery-audit.mdclient-discovery-audit-template.mdRepo only
Business AI Context[slug]-business-ai-context.mdbusiness-ai-context-template.mdRepo only
Validation Quick-Start (auto-generated)[slug]-validation-quickstart.pdf (Drive only)client-validation-quickstart-template.mdRepo template + script → Drive PDF

Repo path: 09-clients/[slug]/[slug]-[type].md Drive path: Client_Delivery/[slug]/client-reference/[slug]-[type].pdf


3. The profile-to-PDF pipeline (concrete)

What runs

scripts/publish-client-profiles.ps1 — PowerShell. Renders each profile markdown to PDF using pandoc + wkhtmltopdf, styled by scripts/profile-pdf-style.css, and writes the output to the client's client-reference folder on the Client_Delivery shared drive.

Dependencies (one-time install on the publishing machine)

winget install JohnMacFarlane.Pandoc wkhtmltopdf.wkhtmltox
# wkhtmltopdf does NOT auto-add itself to PATH — append C:\Program Files\wkhtmltopdf\bin to your user PATH

Run modes

CommandWhat it does
.\scripts\publish-client-profiles.ps1Re-publishes all active client profiles
.\scripts\publish-client-profiles.ps1 -Client moots-lawRe-publishes a single client
.\scripts\publish-client-profiles.ps1 -DryRunLists output paths without writing PDFs

What "publish" means

  1. Read 09-clients/<slug>/<slug>-client-profile.md from your local working tree (so commit first if you want the committed version to land)
  2. Render to PDF via pandoc + wkhtmltopdf, applying scripts/profile-pdf-style.css
  3. Write to H:\Shared drives\Client_Delivery\<slug>\client-reference\<slug>-client-profile.pdf (overwriting any existing file)
  4. Write a per-client provenance marker: client-reference\_last-published.txt (timestamp + source path)
  5. Google Drive desktop sync uploads the new file in ~30–60 seconds — watch your tray icon

Slug → Drive folder mapping

Most clients have a 1:1 slug ↔ Drive folder mapping. The script's $SlugMap hashtable covers exceptions:

Repo slugDrive folder nameWhy
open-wizeOpenWizeDrive folder predates the kebab-case slug standard

If the script can't find a client's Drive folder, it skips with a warning rather than creating a new folder. This protects against the script being run on a machine where Drive sync hasn't propagated.

Quick-Start (Top-3) PDFs — publish-client-quickstart.ps1

A second script renders the per-client "validation quick-start" PDF from client-validation-quickstart-template.md, populating each client's top-3 priorities from a hardcoded data table in the script. Same input/output pattern as publish-client-profiles.ps1. Use it when validation priorities change.

.\scripts\publish-client-quickstart.ps1 -Client moots-law

Architecture note — where these scripts will live long-term

These PowerShell scripts violate the repo-architecture rule (content/standards in symphony-core-documents, tooling in symphony-flow). They were added 2026-05-14/15 before the rule was crystallized. Migration to symphony-flow (likely rewritten in TypeScript) is tracked in symphony-flow#41do not add new scripts here; new tooling belongs in symphony-flow.


4. Validation pass + the SC Client Dashboard (Google Sheet)

The two surfaces

SurfaceWhat it showsWho edits
SC Client Dashboard (Google Sheet) — tab PrimaryLive per-client row showing identity, GHL fields, validation status. Some columns synced from registry/GHL; some freeformMixed (see column inventory in client-document-kit-status.md §2)
ClickUp validation listOne task per client with the 10-section uber checklist + Top-3 prioritiesTanu (validator), Rohit (audit lead)

How they feed each other

  • Sheet → ClickUp: ClickUp parent task (86ahfhbbh) links each child to the corresponding Sheet row
  • Profile → ClickUp: Per-client ClickUp tasks link to the profile PDF and markdown source
  • Profile → Sheet (indirect): Through symphony-flow:client-registry.yaml (managed columns) — see §5 below
  • Validation status → Sheet: Freeform columns Validation Status, Last Validated, Validation Notes — Tanu updates manually after a validation pass

The compliance + validation snapshot mirror lives in client-document-kit-status.md — that file is the in-repo permanent reference to the Sheet's schema and the latest known validation state.


5. Refresh triggers — decision table

Use this when you need to know "what do I run after I change X?"

What changedWhat needs to refreshHow to trigger
Profile markdown content (typo, field update, new value)The PDF in Drive.\scripts\publish-client-profiles.ps1 -Client <slug> from local repo. Drive desktop sync uploads the new file in ~30–60 sec.
Validation Top-3 priorities for a clientThe quickstart PDFEdit the $ClientData table in scripts/publish-client-quickstart.ps1, then .\scripts\publish-client-quickstart.ps1 -Client <slug>.
Profile structure (sections, frontmatter shape)The template + all profiles + manifestEdit 04-operations/templates/client-profile-template.md and client-document-kit-manifest.yaml, propagate to each 09-clients/<slug>/<slug>-client-profile.md, re-publish all PDFs (.\scripts\publish-client-profiles.ps1 with no -Client flag).
Client name / display labelProfile + registry + SheetEdit the profile + open a PR against symphony-flow:config/clients/client-registry.yaml (display_name field). Next 06:00 ET sync updates the Sheet's Location Name column.
GHL Location ID drift detectedProfile in this repo + (sometimes) registry in symphony-flowSource of truth is GHL. Update the profile here; if registry is also wrong, open a PR against symphony-flow:client-registry.yaml. The 2026-05-15 moots-law audit triggered this — see #37.
Client moves from Starter to Growth tierRegistry only — Sheet's Service Tier column comes from client-registry.yaml:clients.<slug>.tierPR against symphony-flow updating the registry. Sheet updates on next daily sync.
GHL agency_location fields blank in Sheet (Auth Rep, address, phone, etc.)The GHL sub-account directly — NOT the repo profileOpen the GHL sub-account → Settings → Business Info → fill in the fields. Next 06:00 ET sync of dashboard-sync-daily picks them up.
New active clientAll four artifacts (profile, manifest, registry, Sheet row appended on next sync)Follow §7 below.
Validation status changes ("Validated", "Drift", etc.)Sheet (Validation Status column) + repo dashboard mirrorEdit the freeform Validation Status cell in the Sheet directly. Then update the snapshot in client-document-kit-status.md §3 when you next commit.
ClickUp validation task contentJust ClickUp — no PDF regen needed unless Top-3 changedEdit the ClickUp task.
Validation comments / discoveriesProfile or upstream registry, depending on root causeSee the 2026-05-15 audit cycle .claude/plans/... for the model: per-client content in the profile, systemic / cross-repo issues filed in symphony-flow.

Common refresh sequences

"I just edited a profile and want to see the change in Drive":

git add 09-clients/<slug>/<slug>-client-profile.md
git commit -m "docs(09-clients/<slug>): <what changed>"
git push origin master
.\scripts\publish-client-profiles.ps1 -Client <slug>
# wait ~30-60s for Drive desktop sync to upload

"I just edited ALL profiles":

.\scripts\publish-client-profiles.ps1   # no -Client flag = all

"I want to confirm what would happen without writing":

.\scripts\publish-client-profiles.ps1 -DryRun

6. Document lifecycle (high-level, for orientation)

Template                  Client Folder               Google Drive
(04-operations/ (09-clients/[slug]/) (Client_Delivery/[slug]/
templates/) client-reference/)

[type]-template.md ---> [slug]-[type].md -.->|pub| [slug]-[type].pdf
(copy) (populate) (export)
  1. Create: Copy template to 09-clients/[slug]/, rename with client slug
  2. Populate: Fill in client-specific data, remove placeholder text
  3. Publish: .\scripts\publish-client-profiles.ps1 -Client [slug] exports to Drive
  4. Maintain: Update in the repo as data changes; re-publish when ready

Future state: SC Doc Sync (still under development) will replace step 3 with daily auto-sync. Today it's manual.


7. How to add a new client

  1. Create the client directory:

    mkdir 09-clients/[slug]
  2. Copy the required template:

    cp 04-operations/templates/client-profile-template.md 09-clients/[slug]/[slug]-client-profile.md
  3. Populate the profile with client-specific data

  4. Add the client to the manifest: Edit client-document-kit-manifest.yaml — add an entry under clients

  5. Update the status dashboard: Edit client-document-kit-status.md — add a row to the compliance + validation table

  6. Update the clients index: Add a row to the active clients table in 09-clients/README.md

  7. Open a PR against symphony-flow:config/clients/client-registry.yaml adding the client — the daily sync will then append a row to the SC Client Dashboard

  8. Publish the first PDF:

    .\scripts\publish-client-profiles.ps1 -Client [slug]

    The script will skip with a warning if the client's Drive folder doesn't exist yet — make sure H:\Shared drives\Client_Delivery\[slug]\ is created first (manually or via the Google Drive Client Folder Setup SOP).


8. How to add a new document type

  1. Create the template in 04-operations/templates/ following the Template Creation Guide
  2. Add the document type to client-document-kit-manifest.yaml under document_types
  3. Update the Required or Optional table in §2 above
  4. Update sc-template-inventory.md
  5. If the new type is required, update the compliance dashboard for all existing clients
  6. If the new type should be auto-published to Drive, decide whether publish-client-profiles.ps1 needs extending OR whether a new sibling script is warranted — note that long-term, both belong in symphony-flow per #41

9. Machine-readable configuration

client-document-kit-manifest.yaml is the canonical machine-readable definition of:

  • Document types: Required and optional document definitions with template paths, naming patterns, and sync rules
  • Client registry: Active clients with slugs, display names, and Drive folder mappings
  • Sync settings: Base paths, export format, conflict policy, and exclude patterns

SC Doc Sync reads this manifest to determine what to sync, where, and how (FR-013).

Note: This manifest mirrors but is not identical to symphony-flow:config/clients/client-registry.yaml (which feeds the Sheet sync). They overlap by design; consolidation is tracked as a future cycle. See client-document-kit-status.md §4.


10. Compliance + validation dashboard

client-document-kit-status.md tracks:

  • Existence compliance (which clients have which documents)
  • Validation snapshot (which clients are Validated / Ready to Test / In Progress / Blocked / N/A)
  • Schema reference (managed vs freeform Sheet columns)
  • Sheet-vs-repo reconciliation

Refresh procedure for the dashboard itself: see §5 of that file.


11. Troubleshooting

SymptomCauseFix
publish-client-profiles.ps1 errors: "Missing required tools: pandoc, wkhtmltopdf"Tools not installed or not on PATHwinget install JohnMacFarlane.Pandoc wkhtmltopdf.wkhtmltox. wkhtmltopdf installer doesn't add itself to PATH — manually append C:\Program Files\wkhtmltopdf\bin to user PATH and open a new shell.
Script runs, says "SKIPPED (no Drive folder)" for a clientClient's Client_Delivery/<slug>/ folder doesn't exist on the local Drive syncEither create the folder via the Google Drive Client Folder Setup SOP, OR wait for Drive sync to pull a folder created elsewhere.
PDF generated locally but not appearing in Drive web UIDrive desktop sync isn't running or is queuedCheck the Drive tray icon — sync queue may be backed up. Force a sync via right-click → "Sync now" if available.
Sheet row shows old data after a registry changeThe 06:00 ET daily sync hasn't run yetWait, or trigger a manual sync from symphony-flow (npx ts-node scripts/sync-registry-to-sheet.ts).
Sheet column unexpectedly blankThe column is managed (synced from GHL/registry), and the upstream source is emptyCheck whether it's a managed column (per client-document-kit-status.md §2); if so, fix the upstream (GHL Business Info or registry). If it's a freeform column, edit the Sheet directly.
Profile and Sheet disagree on Location ID (or any other managed field)Drift between sources of truthTrust the Sheet (it pulls from GHL canonical). Update the profile. The 2026-05-15 moots-law audit caught this class — long-term fix is the drift linter in #40.
Two profiles share the same ghl_location_idCopy-paste error during profile creationSame as above — trust the Sheet, fix the profile. Drift linter #40 catches this automatically once landed.

DocumentRelationship
09-clients/README.mdClient directory conventions, lifecycle, security
client-document-kit-status.mdCompliance + validation snapshot (in-repo mirror of Sheet)
client-document-kit-manifest.yamlMachine-readable client + document-type registry
SC Doc Sync PRDProduct that will eventually auto-publish (today this is manual)
client-profile-template.mdCanonical profile structure (v3.1)
client-validation-quickstart-template.mdTop-3 quick-start PDF template
Quarterly Freshness SOPWhen to revalidate; staleness scoring
Google Drive Organization StandardDrive folder structure and naming
Google Drive Client Folder Setup SOPDrive folder creation procedure
Client Input Checklist (Master)Uber checklist (10 sections, ~90 items) used by the validation pass
SC Client Dashboard Guide (external)How the Sheet syncs (in symphony-flow)

13. Open follow-ups (tracked in symphony-flow)

IssueWhat
#37Registry tier reconciliation (moots-law Growth)
#38Dashboard guide: Onboarding Date semantics
#39Dashboard guide: field-semantics glossary
#40Profile↔Sheet↔registry drift linter + uniqueness check
#41Migrate publish-client-*.ps1 scripts from this repo to symphony-flow

Each one originates from a real validation finding or architectural decision documented above.


Changelog

VersionDateChanges
1.02026-02-10Initial creation — required documents, manifest, lifecycle
1.12026-03-02v3.0 consolidation (brand voice + design kit folded into client profile)
1.22026-05-19Promoted to single-source-of-truth for the entire profile lifecycle: added pipeline mechanics (§3), validation/dashboard integration (§4), refresh-triggers decision table (§5), troubleshooting (§11), open follow-ups (§13). Added publish_to: [internal-wiki] to frontmatter so this surfaces on team.symphonycore.com.

Document Owner: Symphony Core Operations Team Last Updated: 2026-05-19