zynkr-gm · git:20260824.9c6da93 · 2026-08-24 · sha256 568ec433eb555929
zynkr-gm git:20260824.9c6da93A
Immutable. This exact content never changes and is served at /api/v1/blob/568ec433eb555929.
--- name: zynkr-gm sheetId: "0.02" description: >- The GM operating-rhythm skill for a small company run from Google Docs/Sheets. Reads the source-of-record chain in precedence order (strategy alignment section → H2 project tracker (status SOR) → the ops team's weekly log → OKR & KPI tracker → per-function progress sheets), derives per-item state (ends-soon · overdue · undated · propose-done · direction-unlabelled), and produces a fixed-shape WEEKLY GM BRIEF: runway line first, the ≤3 things only the GM can unblock, two clocks, P0/P1 status by LOB, per-owner rollup, KPI off-target + asks, decisions register, deliberately-not-this-week, machine health. Delivers as a Gmail draft (interactive) or an auto-sent email (the Monday cloud routine rendered from this skill). Trigger EAGERLY on "/zynkr-gm", "zynkr-gm week", "GM 週報", "這週重點", "本週 focus", "本月重點", "what should I focus on this week", "as a GM what will I do this week", "week focus", "month focus", "GM brief", "run the GM pass", "哪些 P0 delay 了", "KPI 有沒有 off target", "H2 進度盤點", "幫我盤一下 H2 專案", or any ask for a company-level (not one project's) week/month focus, progress roll-up, or KPI variance. BOUNDARY — do NOT hijack: /project-status-update (one project's weekly status email from its own tracker), /consult-status-report and /consult-governance (consulting portfolio), /admin-governance (file-level Drive↔local index drift), /admin-meeting-prep (per-meeting packets), /skill-finder (which skill for a task), /planning-tracker-sync (the TEAM weekly tracker block, nudges and snapshots — it consumes this skill's derived-state rules, but the founder brief stays here), the rest of the planning suite 0.03-0.10 (a planning CYCLE: pre-work, offsite synthesis, tracker build, OKR reconcile), /curate-livestream-transcripts (it produces the notes this skill only health-checks). This skill reads broadly and writes narrowly: it never edits the tracker, the onboarding master doc, or another owner's doc. category: strategy project: zynkr-gm platform: claude status: WIP author: Peter Tu input: "Optional sub-command (week | progress [LOB] | send) and an optional 'as of' date; identifiers come from the private config (~/.config/zynkr/gm.json) or the rendered routine prompt." process: "Anchor on today → load private config → idempotency check → read the SOR chain in precedence order (script-first) → derive per-item state + per-owner rollup → compose the fixed-shape brief, every number cited → draft or send → report." output: "Weekly GM brief (zh-TW) as an HTML email: runway line · ≤3 GM-only unblocks · two clocks · P0/P1 by LOB · owner rollup · KPI off-target + asks · decisions · skips · machine health." synergy: [admin-governance, project-status-update, consult-governance, skill-finder, curate-livestream-transcripts, admin-meeting-prep, planning-tracker-sync, planning-evidence-pack] --- # zynkr-gm ```bash npx skills add https://github.com/peter-tu-zynkr/zynkr-skill-builder --skill zynkr-gm ``` `zynkr-gm` is the general manager's Monday. It reads the company's source-of-record chain in the order the knowledge directory says wins (strategy alignment → project tracker → weekly ops log → OKR/KPI sheet → per-function progress sheets), works out which H2 items are moving, stuck, undated or about to expire, and turns that into one fixed-shape brief whose first line is always runway and whose second block is always the ≤3 things only the GM can unblock. It exists to replace a ~40-tool-call manual read pass, and to be the instrument for "we have no instrumentation": the KPI dashboard's Actual column, the missing decide-by dates, the P0s nobody put dates on. It **reads broadly and writes narrowly** — the brief is the only output; it never edits the tracker, the onboarding master doc, or another owner's document. --- ## Configuration (private — never in this repo) This repository is public. The skill's method is here; the **identifiers are not**. At runtime the skill loads `~/.config/zynkr/gm.json` (schema and placeholder values in `references/config.example.json`; see `references/config.README.md`). The cloud routine gets the same values baked into its prompt by `scripts/render_routine_prompt.py` from `references/routine-prompt.tmpl`. If the config file is missing in an interactive run, ask for it — do not guess IDs and do not proceed with placeholders. | Config key | Role (see `references/source-map.md`) | |---|---| | `google_account` | account for all `google-workspace` MCP calls | | `recipients[]` | who receives the brief (default: the GM only) | | `sources.main_tracker` | H2 project tracker sheet + tab — **the status source of record** | | `sources.ops_weekly` | the ops lead's weekly log doc (newest week on top) — read-only | | `sources.okr_kpi_tracker` | OKR & KPI tracker (tabs `okrs`, `kpi_dashboard`) — the metrics SOR | | `sources.ops_heal_tracker` | ops gap-heal action sheet (tabs `fixes`, `decisions`) | | `sources.course_tracker` | flagship course project tracker (milestone dates only) | | `sources.vms_v2` · `sources.integrated_refresh` | strategy docs — read the authoritative TOP section only | | `sources.plan_docs.<lob>` · `sources.eae_readme` | per-function H2 plan docs — Refresh block only, on change | | `sources.knowledge_directory` · `sources.org_taxonomy` | governance docs (SOR precedence table, DRIs) | | `sources.livestream_notes_folder` | health-check only: date of the newest weekly note | | `constraints.*` | runway floor (months), books-stale days, burn cap, Q3/H2 end dates | | `routine.*` | trigger id, cron, connectors, model, subject prefix — for `render_routine_prompt.py` | --- ## Required reading (before acting) | File | Read when | |---|---| | `references/source-map.md` | Always — what each source is, which section/tab is authoritative, precedence, read policy, cloud vs local availability | | `references/brief-template.md` | Always — the exact 00–08 anatomy, headings, HTML skeleton, evidence-citation rule | | `references/derived-state-rules.md` | Always — ENDS_SOON / OVERDUE / UNDATED / PROPOSE_DONE / DIRECTION_UNLABELLED / STALLED, priority weighting | | `references/kpi-map.md` | When composing block 05 — per-metric class (AUTO/SEMI/HUMAN), where an Actual comes from, cloud availability | | `references/lob-skills-seed.md` | When a "what's next" needs an instrument — chain order, which skill moves which P0, and the category-0 weekly boundary. **Which skills exist is NOT in this file** — read it from `sources.skills_knowledge_map` (the skills KB Doc), one category section per LOB | --- ## Sub-commands & cadence | Invocation | What runs | Cadence | |---|---|---| | `/zynkr-gm` (no arg) | Monday → `week`; 1st of month → `month` (P2, not yet built) then `week`; otherwise ask which | — | | `/zynkr-gm week` | full read pass → weekly brief → Gmail **draft** | interactive | | `/zynkr-gm week send` | same, but **sends** to `recipients` (idempotent per ISO week) | scheduled / explicit | | `/zynkr-gm progress [LOB]` | Steps 1–4 only, printed in chat; optional LOB filter (`1.0` … `8.0`) | on demand | | Monday cloud routine | `week send` rendered as a self-contained prompt for the claude.ai routine (Drive + Gmail connectors) | Mon 09:00 local | `kpi` (writes Actuals), `month` (monthly review + quarter/half escalation) and `learn` (knowledge-directory curation) are P1–P3 — see Limitations. --- ## Step 1 — Anchor on today and resolve the mode Determine today's date in `timezone` (default Asia/Taipei). The **ISO week** containing today is the brief's key (e.g. `2026-W34`); the week window is Monday→Sunday. If the user gave an "as of" date, use that instead. Resolve the sub-command from the args table above. Compute the two clocks up front: **cash clock** (runway months, from Step 3.4) and **calendar clock** (days to `constraints.q3_end` and `constraints.h2_end`, plus any P0/P1 whose 結束 falls within 30 days). ## Step 2 — Load config and check idempotency 1. Read `~/.config/zynkr/gm.json`. Missing → stop and ask for it (interactive) / fail loud (unattended). 2. Idempotency (only when the mode will **send**): search Gmail `in:sent newer_than:8d` and read subjects; if one starts with `routine.subject_prefix` and carries this ISO week's key, report `本週 GM 週報已寄出,略過(idempotent)` and stop. Do not search by CJK subject text — list recent sent mail and match the prefix + week key yourself. ## Step 3 — Read the source-of-record chain (precedence order, script-first) Never load a whole large doc into context. Big docs are dumped to a file by the harness when the tool result exceeds the limit — slice them with the scripts. Read in this order and stop reading a source once you have what the brief needs. ### 3.1 Tracker — the status source (every run) `mcp__google-workspace__read_sheet_values` on `sources.main_tracker.id`, range `<tab>!A1:M200`. Keep rows whose `#` looks like `N.NN` and whose 項目 is non-empty (rows like `1.0` with an empty 項目 are category headers). Save as JSON rows (keys = header cells) to the dump dir. Status vocabulary is 未開始 · 進行中 · 放棄 · 完成 · 暫停 (完成 · 暫停 added 2026-08-24). 完成 and 放棄 are **terminal** — exclude them from open-work counts and from owner load; 暫停 keeps its owner but carries no schedule. 延遲 still does not exist and stays **derived** (Step 4). ### 3.2 What actually happened — the ops weekly log (every run) `mcp__google-workspace__get_doc_as_markdown` on `sources.ops_weekly.id` with `include_comments=false`. The result is large and lands in a file → run `python3 scripts/extract_newest_block.py <file> --blocks 2 --json`. Block 1 = the newest week; block 2 is only for stall detection. The block has a fixed skeleton (Team update · Demand Marketing · AI consulting & Sales · Operation · Knowledge product · AI assistant dev · Tech/People/Finance, each with `Metrics` bullets, mostly bare `#` placeholders). Pull: event list with registration counts, course milestone checklist, anything under `#Team update`. **Never write to this doc.** ### 3.3 Measures — OKR & KPI tracker (every run) `read_sheet_values` on `sources.okr_kpi_tracker.id`, tabs `okrs` and `kpi_dashboard` (the `Initiatives` tab is a stale mirror of the tracker — ignore it). Resolve columns by header text (`Tracker #`, `Q3 target`, `Q4 target`, `Actual`, and — if present — `As of`, `Source`). Use `scripts/kpi_locate.py` when you need a specific row. ### 3.4 Function-specific progress sheets (every run) - `sources.ops_heal_tracker`: tabs `fixes` (修復清單: # · 波次 · 動作 · 嚴重度 · 目標 · 負責人 · 狀態) and `decisions` (待決事項: # · 事項 · 決策者 · 期限/備註 · 狀態 · 決議紀錄). Open 決策 rows feed block 06. - `sources.course_tracker`: tab per config; take stage/milestone rows with End dates and Status only (this skill does **not** produce that project's status email — /project-status-update does). - Local runs may add CRM (`mcp__zynkr__list_deals`, `list_tasks`) for sales/consulting evidence and the accounting database for runway/burn per `references/kpi-map.md`. In the cloud routine these are unavailable — the brief marks those lines `(排程執行無法讀取 · 待本地補)` rather than guessing. - Runway: from the KPI dashboard's runway/burn rows (`Actual` + `As of`) or the accounting read. If neither exists → the runway line reads **RED · 未計量** and says so. ### 3.5 Strategy + plan docs (only on change) Use `mcp__google-workspace__search_drive_files` (or file metadata) to get `modifiedTime` for `sources.vms_v2`, `sources.integrated_refresh`, each `sources.plan_docs.<lob>` and `sources.eae_readme` (key on the **target** doc IDs, not folder shortcuts). Read a doc only if it changed within the last 7 days (P0; the P1 `doc-watch` tab replaces this with last-seen timestamps) — and then read **only** the authoritative section named in `source-map.md` (the TOP alignment / Refresh block). Otherwise the fixed facts in config (`constraints.*`) and `references/` are enough. Any change here goes into block 08 as "SOR doc changed". ### 3.6 Machine health + calendar (cheap) - `sources.livestream_notes_folder`: list files, take the newest `逐字稿_*` date; if older than 8 days → flag "weekly curation did not run". - Calendar (local only, if the Calendar API is enabled): this week's events as anchors. Skip silently in unattended mode. ## Step 4 — Derive state, then roll up Run `python3 scripts/derive_state.py rows.json --today <YYYY-MM-DD> [--prev prev_rows.json] --json`. It emits per-item states (ENDS_SOON · OVERDUE · UNDATED · CHANGED · PROPOSE_DONE) and a per-owner rollup. Apply `references/derived-state-rules.md` for the judgement calls the script cannot make: DIRECTION_UNLABELLED (a P0 whose direction lacks 已定案/還在摸索), STALLED (needs two snapshots — mark "not available yet" until P1), and priority weighting (P0 UNDATED for >2 weeks → escalate into block 01; P2 issues → status table only). ## Step 5 — Compose the brief Follow `references/brief-template.md` **exactly**, in order: - **00 Runway line** — always first. Months · burn vs `constraints.burn_cap_ntd_per_month` · books as-of. RED if < `runway_floor_months` or as-of older than `books_stale_days`, or if un-metered. - **01 ≤3 things only the GM can unblock** — from open decisions past/near their decide-by, P0s owned by the GM with 結束 ≤14d, and P0 UNDATED >2 weeks. Three at most. This block is the test of whether the brief changes the week. - **02 Two clocks** — cash clock + calendar clock (Q3/H2 end + P0/P1 ending ≤30d). - **03 P0/P1 status by LOB** — state · evidence (tracker Δ / weekly-log mention / sheet activity) · next. Coarse on purpose. - **04 Per-owner rollup** — for each owner: their P0s · missing dates · asks · last heard from (newest weekly-log mention). Include a GM-load line (share of P0s held by the GM). - **05 KPI off-target + asks** — only rows with both a target and an Actual can be off-target; rows without an Actual are listed as asks to their owner (batch, don't nag). - **06 Decisions register** — open 決策 rows + strategy-doc open decisions + inferred ones, each with label (已定案/還在摸索/未標), owner, decide-by (or "無期限"), status. - **07 Deliberately not this week** — named skips. - **08 Machine health** — routines that did/didn't fire, SOR docs that changed, sources the run could not read. Rules while composing: zh-TW body with EN terms exactly as the source docs use them; every number carries its source + as-of date; never restate numbers from narrative docs; never invent a HUMAN metric; when a source could not be read, say so in 08 instead of filling in. ## Step 6 — Deliver Render the brief as an HTML email with **all CSS inline** (Gmail strips `<style>`), using the skeleton and palette notes in `references/brief-template.md`. Subject: `<routine.subject_prefix><YYYY-MM-DD>(W<ww>)— <one-line focus>`. - Interactive `week` → `mcp__google-workspace__draft_gmail_message` to `recipients` (draft, never send) **and** print the brief in chat. - `week send` (explicit or scheduled) → send exactly one message to `recipients`; if the send tool is refused, fall back to a draft and say so in the report. - `progress` → chat only. ## Step 7 — Report back One paragraph: ISO week · delivered as draft/sent (+ id) · the 01 list verbatim · counts (P0 overdue / undated / ends-soon) · anything unreadable. If idempotency skipped the send, say exactly that. --- ## Unattended / scheduled runs (the Monday routine) The cloud routine is this skill rendered into one self-contained prompt: `python3 scripts/render_routine_prompt.py --config ~/.config/zynkr/gm.json --template references/routine-prompt.tmpl --out <rendered.md>` — then create/update the claude.ai routine with that prompt (`routine.*` in config: cron, environment, Drive + Gmail connectors, model). Differences from a local run, by design: - Reads go through the **Google-Drive connector** (`read_file_content` returns Sheets as markdown tables and Docs as text; large docs may be truncated — the ops weekly log's newest week is at the top, so that is safe). No CRM, no accounting, no calendar → those lines are marked unavailable, never guessed. - Delivery is **send** via the Gmail connector (`send_message`); if refused → `create_draft` and the run report says so. Idempotent per ISO week via the sent-mail check. - Ask nothing; fail loud (a missing-data brief is worse than a visible failure); one message max. - When the skill changes, **re-render and update the routine** — the prompt is derived, not hand-edited. That is the whole point of the template. --- ## Guardrails - Never edit the H2 tracker's status, dates or owners — owners push schedules. - Never write to the onboarding master doc or any shared fact; propose to the GM instead. - Never write into another owner's doc (the ops weekly log is read-only for this skill). - Every number cites source + as-of; HUMAN metrics are asked, not invented. - Precedence is enforced, not debated: strategy alignment section > body; Refresh block > plan body; tracker > OKR sheet > plan docs. Deprecated paths in the knowledge directory stay deprecated. - Read caps: no whole-doc loads; plan docs only on change; target ≲100k tokens per run. - Unattended: draft-fallback, ask nothing, fail loud, idempotent per ISO week. ## Outputs - The weekly GM brief (HTML email: draft or sent) — see `references/brief-template.md`. - In chat: the same brief in markdown, plus the Step 7 report. - (P1+) rows in the OKR & KPI tracker's `gm-weekly` / `kpi-history` / `decisions` / `doc-watch` tabs; KPI `Actual` cells for AUTO/SEMI metrics. ## Reference files - `references/source-map.md` · `references/derived-state-rules.md` · `references/brief-template.md` · `references/kpi-map.md` · `references/lob-skills-seed.md` - `references/routine-prompt.tmpl` · `references/config.example.json` · `references/config.README.md` - `scripts/extract_newest_block.py` · `scripts/derive_state.py` · `scripts/tracker_diff.py` · `scripts/kpi_locate.py` · `scripts/render_routine_prompt.py` (all stdlib; `--selftest`) ## Limitations (v1 = P0) - **Read-only.** No KPI cell writes, no state tabs yet → STALLED cannot be computed (needs two snapshots) and "changed since last week" relies on `--prev` if you saved last week's rows. P1 adds the tabs and `kpi` writes; P2 adds `month` (+ Q3/H2 checkpoint scoring); P3 adds `learn` (knowledge-directory curation, propose → `--apply` interactive only). - The tracker's status vocabulary has no 延遲; overdue and undated are inferred from dates that are often placeholders — the brief makes that visible rather than hiding it. - Cloud runs cannot see CRM/accounting/calendar; those lines say so. - The brief is company-level. One project's status email is `/project-status-update`. ## Self-checks - Runway line present and first? Un-metered → RED, not blank? - Block 01 has ≤3 items, each something only the GM can do? - Every P0 appears in 03 exactly once, with a state? - Every number has source + as-of? Any HUMAN metric invented? (must be none) - Unattended: exactly one send or one draft; idempotency respected; nothing asked?