Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Zynkr Ops Weekly

ASecurity

The weekly operations loop that keeps a Google Chat space and a weekly operations Google Doc in sync. Six scheduled modes run one beat each: `nudge` (Mon 09:00 — post the four-line template plus last week's decisions), `rollup` (Tue 09:00 — read the week's `#週報` posts, route each one to its department heading using the owner person-chips already in the Doc, and write a clearly-marked auto-summary block), `chase` (Tue 09:30 — @ the owners who did not post), `agenda` (Wed 17:00 — re-sweep for l...

20 stars
0 votes
0 copies
2 views
Added 9/19/2026
businessrustgobashrailsdebugginggitapi

Works with

cliapimcp

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add peter-tu-zynkr/zynkr-skill-builder --skill zynkr-ops-weekly --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Zynkr Ops Weekly?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Zynkr Ops Weekly
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/peter-tu-zynkr-zynkr-ops-weekly/badge)](https://www.skillsdirectory.com/skills/peter-tu-zynkr-zynkr-ops-weekly)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: zynkr-ops-weekly
sheetId: "3.19"
description: >-
  The weekly operations loop that keeps a Google Chat space and a weekly operations Google Doc
  in sync. Six scheduled modes run one beat each: `nudge` (Mon 09:00 — post the four-line
  template plus last week's decisions), `rollup` (Tue 09:00 — read the week's `#週報` posts,
  route each one to its department heading using the owner person-chips already in the Doc, and
  write a clearly-marked auto-summary block), `chase` (Tue 09:30 — @ the owners who did not
  post), `agenda` (Wed 17:00 — re-sweep for late arrivals, then produce carry-over, overdue,
  KPI-off-target and the ≤3 decisions the Thursday meeting must actually make), and `decisions`
  (Thu 22:00 — post the resolutions back to the space, send the recap mail, write the decisions
  register, and assert the send actually happened), and `tidy` (Fri 09:00 — keep the newest
  auto block under each department, archive the stacked older copies to the 封存 tab, and carry
  still-open items forward one per line). Routing is never hardcoded: it is read at
  run time from the Doc's own owner chips, so changing the Doc changes both the routing and the
  recap-mail recipient list. Trigger EAGERLY on "/zynkr-ops-weekly", "營運週報", "週報彙整",
  "把大廳的週報整理進 Doc", "roll up the chat updates", "誰還沒回報", "補件提醒", "週四議程",
  "產週會議程", "會後回貼決議", "recap 信", "weekly ops loop", "ops weekly rollup", or any ask to
  collect / chase / summarise the team's weekly updates, build the weekly meeting agenda, or
  publish the meeting's decisions. BOUNDARY — do NOT hijack: /zynkr-gm (the founder's own
  company-level Monday brief, reads this Doc but never writes it), /project-status-update (one
  project's status email from its own tracker), /planning-tracker-sync (the H2 tracker block and
  its own nudges), /consult-status-report (client-facing consulting status), /admin-meeting-prep
  (per-meeting packets for external meetings). This skill owns exactly one artefact — the weekly
  operations Doc's current week section — and one channel loop around it.
category: operations
project: zynkr-ops-weekly
platform: claude
status: WIP
author: Peter Tu
input: "A mode (nudge | rollup | chase | agenda | decisions | tidy | status) and an optional 'as of' date; all identifiers come from the private config at ~/.config/zynkr/ops-weekly.json."
process: "Anchor on today → resolve the target Thursday (Monday's posts belong to the NEXT Thursday) → load config → check idempotency → read routing from the Doc's owner chips → sweep Chat by createTime → parse the four lines → write a marked block → assert delivery."
output: "Per mode: a Chat post, a marked 〔自動彙整〕 block under each department heading of the current week's Doc section, a Wednesday agenda block, and a Thursday recap email."
synergy: [zynkr-gm, project-status-update, planning-tracker-sync, operations-flow-optimization, admin-governance]
executed_by: internal-user
house-style: bound

---

# zynkr-ops-weekly

```bash
npx skills add https://github.com/peter-tu-zynkr/zynkr-skill-builder --skill zynkr-ops-weekly
```

A small team posts its weekly update into a Google Chat space on Monday, and discusses
operations from a weekly Google Doc on Thursday. Nothing connects the two, so the Doc records
what people *intended* to do (week after week, near-verbatim) while the actual progress stays
in chat scrollback. This skill is the connective tissue: it collects, routes, chases, and
closes the loop — one scheduled beat at a time.

It is built around a single discovery about the Doc: **every department heading already carries
its owner's Google Docs person chip**, keyed by email. That is a routing table someone is
already maintaining by hand for other reasons. So this skill keeps **no department map of its
own** — it reads the chips at run time. Change the Doc, and routing *and* the recap-mail
recipient list both follow.

**It writes narrowly.** Auto-content only ever lands inside a block stamped
`〔自動彙整 WB 9/14 · 09-15 12:00〕`. It never edits a line a human wrote. A bot that silently
rewrites prose in a doc people are actively editing is a bot nobody trusts by week two.

---

## The cadence

| When | Mode | Who | What happens |
|---|---|---|---|
| Mon 09:00 | `nudge` | skill | Post the four-line template + last week's decisions + the Tue 09:00 cut-off |
| Mon (all day) | — | team | People post `#週報` in the space |
| **Tue 09:00** | `rollup` | skill | Read the window, route by owner chip, write the marked block, backfill metrics |
| **Tue 09:30** | `chase` | skill | Owners in the Doc − people who posted → @ the difference |
| Wed 17:00 | `agenda` | skill | Re-sweep for late arrivals, then carry-over · overdue · KPI · ≤3 decisions |
| **Thu 21:00** | — | team | The weekly meeting. Discuss exceptions and decisions only; edit the Doc live |
| **Thu 22:00** | `decisions` | skill | Resolutions → space (3 lines) + recap mail + decisions register + **assert the send** |
| Thu 23:00 | `scaffoldNextWeek` | **Apps Script** | Duplicate the newest week section, re-stamp next Thursday. Runs **after** `decisions` — see Step 4.1 |
| **Fri 09:00** | `tidy` | skill | Keep the newest auto block per department, archive the rest to the 封存 tab, carry still-open items one per line |

`chase` must run **after** `rollup` — it cannot know who is missing until the roll-up has
resolved who posted. Both beats sit on Tuesday morning so that the Doc's Thursday section is
already full two days before anyone opens it.

**Why the scaffold is not this skill's job.** The split is by *whether judgement is needed*, not
by preference. Duplicating a section is purely mechanical and must never fail, so it belongs to
Apps Script, whose authorisation does not expire. In the week this skill breaks entirely, the
skeleton still opens and Thursday still has a page. See `references/scaffold.md`.

> **Why the Doc used to grow without bound, and what actually stopped it.** Every writer here
> is insert-only and the scaffold copies the newest section *verbatim*, so each section inherits
> every `〔自動彙整〕` block ever written. Audited 2026-09-15: 34 sections / 5,325 lines, the
> newest section holding 22 blocks of which only 4 were that week's, sections grown 130 → 292
> lines in four weeks.
>
> Two fixes were attempted. Moving whole old **sections** to an archive tab was built and
> **rolled back the same day** (`SKB-029`) — it had to move human-written content, risked the
> owner person chips, and did not fit in one Apps Script run. Trimming the stacked **blocks**
> inside the newest section (`SKB-030`, the Friday `tidy` beat) does fit: it only ever touches
> this skill's own output, never reaches a chip, and deletes only copies whose originals sit in
> the frozen previous section. Section size is now stable instead of linear. **Read both specs
> before proposing a third.**

---

## Configuration (private — never in this repo)

This repository is public. The method is here; the **identifiers are not**. At runtime load
`~/.config/zynkr/ops-weekly.json` (schema in `references/config.example.json`, notes in
`references/config.README.md`; override the path with `ZYNKR_OPS_WEEKLY_CONFIG`).

| Config key | Role |
|---|---|
| `google_account` | account for every `google-workspace` MCP call |
| `space.id` | the Chat space, in `spaces/<id>` form — **the `spaces/` prefix is required** |
| `space.name` | human label, for report lines only |
| `doc.id` · `doc.tab_id` · `doc.tab_name` | the weekly operations Doc and the tab that holds the week sections |
| `doc.archive_tab_id` · `doc.archive_tab_name` | the **sibling tab** `tidy` moves old auto blocks into. It must be a tab in the *same* Doc: `carryover.py` reads all tabs as one stream to compute `↻N週`, so a separate file resets every streak and blinds the Wednesday agenda |
| `chat_ids` | **the only hardcoded map** — 6 rows of Chat `users/<id>` → email. See below |
| `reporters` | the emails expected to post each week (6 people; excludes non-reporting members) |
| `sources.main_tracker` · `sources.okr_kpi_tracker` | sheets read to backfill metrics and overdue items |
| `routine.*` | how the six beats are scheduled — mechanism, model, timezone, per-beat windows. See `references/scheduling.md` |

If a required value is missing or still a placeholder, **fail loud** (`config: doc.id unset`).
Never guess an id, and never fall back to a hardcoded department map.

### Why `chat_ids` has to exist

Chat and Docs do not share an identity space. The Chat payload **carries no email field at
all**; the Doc gives an email and no user id. Nothing bridges them automatically — the People
API resolves the id but exposes no name or email for domain profiles. So the bridge is six
hardcoded rows, and only six. Everything else is read from the Doc.

The map has **two key forms**, and a real space yields a mix of both: the MCP renders a sender
as a **display name** when that person is in the account's personal Contacts, and as
`users/<21-digit id>` when they are not. Key each person by the form their messages actually
arrive as, and keep both if unsure — a person joining Contacts later would otherwise silently
stop resolving.

---

## Required reading (before acting)

| File | Read when |
|---|---|
| `references/post-format.md` | Always — the four-line format, what each line feeds, and the parse rules |
| `references/routing.md` | Always — how to read owner chips out of the Doc, and the off-by-one |
| `references/doc-write-rules.md` | Any mode that writes — marked blocks, tab targeting, idempotency |
| `references/message-templates.md` | Composing any Chat post or the recap mail |
| `references/wording.md` | **Always, before writing any zh-TW the team will read** — house voice, per `/content-translator` |
| `references/scaffold.md` | Installing or debugging the Apps Script half |

---

## Step 0 — Anchor on today, and get the off-by-one right

Resolve today in `Asia/Taipei`. Compute:

- **Week label** — `WB 9/14`, the **Monday that opens the week**. This is what goes in every
  stamp, every Chat footer and the recap subject: it is the day the team posts, and it is a date
  a reader can place without counting. It replaced the ISO ordinal (`W38`) on 2026-09-15.
- **ISO week key** — `2026-W38`. Machine-only: the launchd state files and the receipt line's
  `week=` field. Never shown to the team. `references/wording.md` explains why both exist.
- **The window** — Monday 00:00 of the current ISO week → now.
- **The target Thursday** — the Doc names its sections by **Thursday** date (`Aug 27`,
  `Aug 20`, …), but the team reports on **Monday**.

> **Monday's posts belong to the Thursday that is coming, not the one that just passed.**
> This is the single easiest thing to get wrong, and it silently writes a whole week's
> updates into the previous meeting's section. Assert it: the target Thursday must be
> **≥ today**. If the newest section in the Doc is already in the past, the scaffold did not
> run — say so loudly rather than writing into a stale section.

## Step 1 — Load config and check idempotency

Load the private config; fail loud on placeholders. Then check whether this mode already ran
for this ISO week:

- Chat-delivering modes (`nudge`, `chase`, `agenda`, `decisions`) — list the space's messages
  for today and look for this skill's own marker line (each template ends with a
  `— zynkr-ops-weekly · <week>` footer). Found → stop and report "already ran".
- `rollup` — look for a `〔自動彙整 <week>` stamp inside the target Thursday section. Found →
  do not write a second block; re-run in *append-new-only* mode (Step 4.4).
- `tidy` — idempotent by construction, so no marker is needed: once a group holds a single
  block there is nothing left to archive and `tidy_blocks.py` returns an empty `archive` list.
  A second run in the same week is a no-op, which is what makes it safe to retry.

> **Until 2026-10-06, match the old week shape too.** The label changed from `W38` to
> `WB 9/14` on 2026-09-15, so a section written before then is stamped `〔自動彙整 2026-W38`
> and a footer posted before then reads `· W38`. Search for **either**. Matching only the new
> shape makes `rollup` write a duplicate block and makes `decisions` conclude the loop never
> ran and refuse to send the recap. `references/wording.md` → "The changeover".

## Step 2 — Read routing from the Doc (every run)

Fetch the Doc **as markdown** — `get_doc_as_markdown`. This matters:
`get_doc_content` returns plain text and **silently strips person chips**, which is exactly the
data the routing depends on. In markdown a chip arrives as `[Sam Rivera](mailto:owner-a@example.com)`.

Pipe it through `scripts/parse_routing.py` to get `{heading → owner email}`. Rules, precedence
and the heading-grouping details are in `references/routing.md`.

Sanity-check the result before using it: every email must appear in `reporters` or be a known
non-reporting owner. An unexpected address means a chip changed — surface it in the report
rather than dropping the section.

## Step 3 — Read the week's posts (`rollup`, `chase`, `agenda`)

Call `get_messages` with the **`space_id` and a `createTime` window**.

> Do **not** use `search_messages` to find the posts. It is a *client-side* scan bounded by
> `max_spaces` × `page_size`; the Chat API's underlying `spaces.messages.list` supports only
> `createTime` and `thread.name` filters and has no full-text search at all. Used for
> retrieval it under-scans silently and reports "nothing found" for messages that exist.

Paginate until the window is covered. Then `scripts/parse_reports.py` turns the raw messages
into records — one per reporter — resolving the sender through `chat_ids` and splitting the
four lines. Posts without the `#週報` tag are ignored: the space is a mixed channel and carries
plenty of other traffic.

**While the format is still being adopted**, pass `--accept-untagged`. The team's pre-tag
shapes (`上禮拜進度` … `本週待辦`, `這個禮拜我的 focus`) carry no tag, so a tag-only parse
returns nothing and the first roll-up reads as total non-compliance. Each record is stamped
`format: "tagged" | "legacy"`; report how many are still legacy, and drop the flag once that
number has been zero for two weeks. An optional format is not a format.

## Step 4 — Mode bodies

### 4.1 `nudge` (Mon 09:00)

Read **last week's** Doc section and extract its decisions — from the **Doc**, not from the
recap mail that was sent. Mail is a delivery channel, never a data dependency; a failed send
should cost an archive copy, not break the chain.

Post the template from `references/message-templates.md` with those decisions quoted above it
and the Tue 09:00 cut-off stated. Reference last week's decisions so people report *against*
something.

**Then assert the scaffold fired.** Confirm a section for the *upcoming* Thursday exists. This
is the "prove it fired" check for the Apps Script half. It lives here rather than in `decisions`
because the scaffold trigger runs later on Thursday evening than `decisions` does — checking at
that moment would fail every week for the wrong reason, and a notice that cries wolf weekly is
worse than no notice. Missing → post a failure notice and stop; do **not** create the section
here, because rebuilding it loses the owner person chips, which no API can recreate.

### 4.2 `rollup` (Tue 09:00)

1. Parse the window (Step 3).
2. Resolve routing (Step 2). For each record, its owner email selects the department heading(s)
   it belongs under. One owner may hold several headings — write the block under each, or under
   the primary one if the report names a department explicitly.
3. **Backfill metrics.** Reporters fill the `數字:` line only with what they have on hand. For
   the rest, read `sources.main_tracker` / `sources.okr_kpi_tracker` and fill the Doc's metric
   slots from there. Cite the source cell for every number written. Never invent a number and
   never carry one forward from a prior week — an empty slot is information.
4. **Compute carry-over.** `scripts/carryover.py` compares this week's items to prior sections
   and emits `↻N週` counts. An item at `↻3週` or higher is agenda material by default.

   Two things it deliberately does **not** count, both learned from the real Doc:
   **template rows** — a label like `Funnel` or `CTR` that appears in most sections carries no
   work and would otherwise dominate the agenda; and **drifting matches** — the walk-back
   requires a near-exact match, because loose matching chains across unrelated items and
   invents long streaks. Digits are stripped before comparison, so `90%` → `92%` is correctly
   one item rather than two.
5. Write one marked block per department under its heading — `references/doc-write-rules.md`.
6. Report: who posted, who did not, what was written where. The "did not" list is `chase`'s input.

### 4.3 `chase` (Tue 09:30)

`missing = reporters − posters`. Empty → post nothing and report full coverage; a chase message
that chases nobody teaches people to ignore chase messages.

Otherwise post one short message naming the missing people and the Wed 12:00 cut-off. Name them
in plain text — `send_message` posts text, and reliable programmatic @-mentions need the
annotation payload the MCP tool does not currently expose.

> If `chase` names the same person two weeks running, the problem is the format or the routing,
> not the person. Say that in the report.

### 4.4 `agenda` (Wed 17:00)

1. **Re-sweep the window first** (Mon 00:00 → now) to pick up anything that arrived after the
   chase. Append only records not already stamped in the Doc — match on reporter + ISO week so
   a re-run cannot duplicate.
2. Assemble, in this order, and cap it: **carry-over `↻N週`** · **overdue** (from the tracker)
   · **KPI off-target** · **≤3 decisions**. The decisions come from the reporters' `卡關:` line —
   that is the only field in the format that forces a decision, which is why it cannot be
   dropped.
3. Write the agenda at the **top of the target Thursday section**, in its own marked block.
4. Post a short pointer to the space with the Doc link — the agenda itself lives in the Doc.

If there are more than three candidate decisions, choose the three with the largest blast
radius and list the rest under a "not this week" line. An agenda that lists everything makes no
decisions.

### 4.5 `decisions` (Thu 22:00)

Runs **after** the meeting, against the section as the humans edited it live.

The hour is not arbitrary and is the one beat that must be re-timed if the meeting moves. It sits
in the gap between the meeting ending and the 23:00 scaffold: fire it *during* the meeting and it
recaps a section nobody has edited yet — and it does not merely write to the Doc, it mails every
owner-chip address, so a premature run is a wrong email to the whole team, not a stale line.

**Precondition — refuse to recap a week the loop never ran.** Before anything else, look for this
week's `〔自動彙整 W<week>` stamp in the target section. Missing → `rollup` never ran, so nothing in
that section has been through the loop and the meeting had nothing to work from. Post a one-line
notice to the space, send **no mail**, and stop. This is what makes the five triggers safe to
install on any day of the week: a mid-week install, a public holiday or a failed Tuesday can no
longer put a recap of a week that never happened in front of the whole team.

1. Extract resolutions: **decision · owner · date**. A resolution missing an owner or a date is
   not a resolution — list it as still open rather than promoting it.
2. `send_message` — three lines to the space. Short, because next Monday's `nudge` quotes it.
3. `send_gmail_message` — the full recap to **the owner-chip emails read in Step 2**, not to a
   list maintained here. Contents: decisions · owner · date / overdue and carry-over / KPI
   off-target / next week's focus per department / a link back to this week's Doc section.

   **Search `in:sent` for this week's subject BEFORE composing, and skip the send if it is
   already there.** A non-ok run is now retried up to three times inside its window, so this
   step can legitimately be reached more than once in one evening. Step 1's idempotency check
   guards the Chat post, not the mail, and this mail goes to the whole team: the one failure
   this loop must never produce is three copies of the same recap in six inboxes.
4. **Assert it fired.** Immediately search `in:sent` for the subject just used, within the last
   few minutes. Not found → post a one-line failure notice to the space and say so in the
   report. This is the SDD "prove it fired" rule, and it is here for a concrete reason: two
   consecutive weekly sends once failed unnoticed because nothing checked. A dead token must
   surface within a week, not five.
5. Write the resolutions into the tracker's decisions register.
6. **Do not check the scaffold here.** Apps Script fires within an *hour window*, and the
   scaffold trigger runs later on Thursday evening than this mode does — so at this point next
   week's section legitimately does not exist yet. Asserting it here produces a weekly false
   alarm, which trains everyone to ignore the notice that matters. The check lives in `nudge`
   (Step 4.1), which runs Monday: clear of the window, and a day before `rollup` needs it.

### 4.6 `tidy` (Fri 09:00)

Runs the morning after the scaffold. Its whole job is to undo the one thing the scaffold does
badly: it copies the week section forward **verbatim**, so the auto blocks travel with it and
`rollup` only ever prepends. By 2026-09-15 a single section carried **22 blocks in 7 groups**,
four deep under some departments. That is the growth engine of the Doc, and it is what the owner's
08-27 comment was about.

> **Why this is safe to delete, and the one assumption it rests on.** Every block `tidy`
> removes is a *copy* the scaffold made of a block that still sits in the **previous week's
> section**, which is frozen and never edited again. Removing it destroys nothing. If the
> scaffold ever stops copying forward, this argument dies and `tidy` must be re-proved before
> it runs again.

1. **Refuse to tidy a past section.** Resolve the target Thursday as in Step 0 and assert it is
   **≥ today**. On a Friday that is only true if Thursday's scaffold fired. If it did not, stop
   and report — and say so loudly, because this is the earliest the loop can detect a failed
   scaffold, three days before `rollup` needs the section.
2. Fetch the Doc as markdown and run `scripts/tidy_blocks.py`. It returns, per department
   group: the block to `keep`, the blocks to `archive`, and the still-open items to `carry`.
   It writes nothing and makes every judgement call — do not re-derive its decisions by hand.
3. **Copy the archived blocks to the 封存 tab first, and verify they landed.** Append under a
   `<section label>` heading so the trail stays readable. Only then delete. Copy → assert →
   delete, never the other order.
4. **Delete the archived blocks from the live tab, by descending index.** Use
   `inspect_doc_structure(tab_id, detailed=true)` to map each block line to its range, sort
   descending, and `batch_update_doc` with `tab_id` on **every** operation. The index rules and
   the tab trap are in `references/doc-write-rules.md`; they are not optional here.
5. **Write the carried items into the kept block**, one item per line, under a `· 還沒收掉的 —`
   line. They go *inside* the kept block because auto-content may only live inside a stamped
   block — that is what keeps the guardrail true.
6. Re-read the section and confirm: one stamp per group, the human lines below each block
   untouched, and the archived text present in the 封存 tab.

The archive tab is belt-and-braces, not load-bearing — the originals are already in the prior
section. If the copy fails, **stop before deleting** and report; a failed archive is a delayed
tidy, a failed delete after a successful archive is a duplicated section.

### 4.7 `status` (on demand)

Read-only. Print what the loop currently sees: target Thursday, who has posted, what is
already stamped in the Doc, which triggers ran this week. Writes nothing — use it to debug
before reaching for a mode that writes.

## Step 5 — Report, and receipt the run

Every run ends with a compact report: mode, ISO week, target Thursday, records parsed, who is
missing, what was written where, what was delivered, and — for `decisions` — the send
assertion result. If a step was skipped, say which and why.

**Then end the report with a receipt line, on its own line, exactly in this shape:**

```
ZYNKR-OPS-WEEKLY-RESULT: mode=<mode> week=<ISO week> status=ok|partial|failed delivered=<short>
```

`week=` here stays the **ISO key** (`2026-W38`), not the `WB 9/14` label the team reads. This
line is machine-facing, it needs to be year-qualified and sortable, and it sits next to the
`<week>.<mode>.done` state files that use the same key. See `references/wording.md`.

`status=ok` means **every** side effect this mode owes actually landed and you verified it —
the message is in the space, the block is in the Doc, the mail is in `in:sent`. Anything
short of that is `partial` (some landed) or `failed` (none did), with the reason in
`delivered=`. Examples:

```
ZYNKR-OPS-WEEKLY-RESULT: mode=rollup week=2026-W36 status=ok delivered=6-blocks-verified
ZYNKR-OPS-WEEKLY-RESULT: mode=agenda week=2026-W36 status=partial delivered=doc-written;chat-404-app-not-configured
ZYNKR-OPS-WEEKLY-RESULT: mode=nudge week=2026-W36 status=failed delivered=none;mcp-timeout
ZYNKR-OPS-WEEKLY-RESULT: mode=tidy week=2026-W38 status=ok delivered=15-archived;7-kept;28-carried
ZYNKR-OPS-WEEKLY-RESULT: mode=tidy week=2026-W38 status=failed delivered=none;scaffold-did-not-fire
```

This line is not decoration and it is not for humans. `run_ops_weekly.sh` parses it and stamps
the week done **only** on `status=ok`; anything else retries on the next tick inside the window
and gives up after three attempts. **Never write `status=ok` because the run finished — write it
because you checked.** The scheduler has no other way to tell a delivered beat from a beat that
politely explained why it could not run: `claude -p` exits 0 either way. It waved through a
silent Monday and a half-failed Wednesday in W36 before this line existed.

---

## Guardrails

- **Never edit a human's line.** Auto-content lives only inside `〔自動彙整 …〕` blocks. Promotion
  or deletion of that content is a human act, at Thursday's meeting.
- **Never rebuild the Doc's skeleton.** Person chips cannot be created by Apps Script or the
  Docs REST API — only copied. Rebuilding loses the routing table. Copy, or do nothing.
- **Never write to a past section.** If the target Thursday is behind today, stop and report.
- **Never invent a metric.** Cite the cell, or leave the slot empty.
- **Never treat mail as an input.** Every mode reads state from the Doc and the tracker.
- **Fail loud on config.** Placeholder id → stop; a wrong id writes into someone else's file.
- **Write like a colleague, not a report generator.** Every published line is zh-TW that six
  people read in a chat room. No 官腔 (`徵集`/`產出`/`決議候選`), no half-translated lines
  (`KPI off-target`, `carry-over`, `Not started`), no internal mode names (`rollup`, `骨架`)
  and no parenthetical explanations of your own filtering. `references/wording.md` carries
  the rules and the frozen strings; it applies to the free text you compose at run time,
  not just to the templates.

## Limitations

- `send_message` posts plain text; @-mentions render as names, not live mentions.
- Metric backfill only covers metrics that exist in the configured sheets; anything measured
  outside them stays a human line.
- The Apps Script half must be installed once by hand, and `installTriggers()` must actually be
  *run* — pasting the file does not schedule anything. See `references/scaffold.md`.
- **`tidy` bounds the newest section, not the whole Doc.** The 46 older sections keep whatever
  they accumulated before 2026-09-15 — they are frozen, so they no longer grow, but nothing
  shrinks them either. The Doc still grows by one (now lean) section a week. Trimming the
  historical backlog is a human cut-and-paste, and `SKB-029` is why it is not automated.
- **`tidy`'s carried list is only as good as the status words people write.** It reads
  `完成`/`Done` as closed and everything else as open. An item finished but never marked stays
  on the list; that is deliberate — the alternative is silently dropping live work.
- The skill half runs on **launchd**, not a claude.ai cloud routine: there is no Google Chat
  connector, the cloud sandbox cannot read the private config, and the Drive connector cannot do
  the chip-preserving Doc writes. See `references/scheduling.md`.
- Deliberately not built: writing to the H2 tracker's status column (that is
  `planning-tracker-sync`'s), and any auto-promotion of an auto-summary line into a human line.

## House style

Writing style is **not owned by this file**. The house voice lives in two Google Docs under
`[@] 寫作指南` (`12DBdFz3SK22ie9im_ThFMI7IBRXsTZsV`), read at runtime:

- 《[2.0] Zynkr 通用風格指南 House Voice》 `10bOIQwRm9Pxwgct4hlwCwK_B4Pipai1HqBPZKzyRHSE` —
  the universal core, plus the addendum for this surface
- 《[3.2] 禁用詞清單 Forbidden Words》 `1N5sHLP4qzmmhpCGsi6KElxi1z0MFe4QZ0Q_35T10Uyg`

Read both before producing client- or reader-facing text, and scan the draft against 《[3.2]》
before handing it over. If Drive is unreachable, say so in the output rather than proceeding
unchecked. Never re-implement either list inside this file.

Attribution

peter-tu-zynkrpeter-tu-zynkr
View sourceMore from peter-tu-zynkr →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Solution Architect

Designs system architecture, component specifications, and technical integration strategy. Use when: designing solutions, system architecture, technology stack, or integration approaches.

192 votes

Akorchak:Venture Assessment

Generate a comprehensive VC investment assessment report for a company

72 votes

Stock Analysis

Analyze stocks and cryptocurrencies using Yahoo Finance data. Supports portfolio management (create, add, remove assets), crypto analysis (Top 20 by market cap), and periodic performance reports (daily/weekly/monthly/quarterly/yearly). 8 analysis dimensions for stocks, 3 for crypto. Use for stock analysis, portfolio tracking, earnings reactions, or crypto monitoring.

6511 votes

Just Fucking Cancel

Find and cancel unwanted subscriptions by analyzing bank transactions. Detects recurring charges, calculates annual waste, and helps you cancel with direct URLs and browser automation. Use when: 'cancel subscriptions', 'audit subscriptions', 'find recurring charges', 'what am I paying for', 'save money', 'subscription cleanup', 'stop wasting money'. Supports CSV import (Apple Card, Chase, Amex, Citi, Bank of America, Capital One, Mint, Copilot) OR Plaid API for automatic transaction pull. Out...

6511 votes

Telegram Compose

Compose rich, readable Telegram messages using HTML formatting via direct Telegram API. Use when: (1) Sending any Telegram message beyond a simple one-line reply, (2) Creating structured messages with sections, lists, or status updates, (3) Need formatting unavailable via Clawdbot's Markdown conversion (underline, spoilers, expandable blockquotes, user mentions by ID), (4) Sending alerts, reports, summaries, or notifications to Telegram, (5) Want professional, scannable message formatting wit...

6511 votes
View all in business →