# @kentcdodds/friction-log ## Intent Capture **durable friction** — recurring, clear-owner, reproducible contract gaps — and route each papercut to the right place: - **`host: 'github'`** → GitHub issue labeled `friction` on the caller’s `owner/repo` (dedupe/reuse by title). Use `repo: 'kody-hq/kody'` when the platform repo is the intended target. - **`host: 'kody'`** → wake **Patch** for that Kody package (no GitHub issue). Separately, every day at 5am America/Denver the package lists open `kody-hq/kody` friction issues and may spawn **one** Cursor Cloud Agent when any are eligible. Success for the daily hunt: an already-fixed or invalid issue is closed. An obvious low-or-medium-risk fix ships via the repo's `/ship-pr` skill. Anything else gets a recommended-fix comment plus the `friction-skipped` label, and stays skipped until that label is removed. ## What it does - **Qualify** — soft gates before create/file so one-off session confusion and “how do I use this once” reports get a clear skip path (principles, not a title deny-list) - **Create** — require `target: { host, repo }`; GitHub file/reuse or Patch wake - **File** — batch with one top-level `target` applied to all items; returns `filed` / `reused` / `woke` / `skipped` (`dryRun` supported) - **Scan** — read-only eligibility scan of the platform friction queue (never spawns) - **Sweep** — list open platform friction issues; spawn one Cloud Agent when eligible (`dryRun: true` previews without spawning) - **Daily job** — 5am America/Denver wrapper used by the scheduler - **Pause / resume** — kill switch for automatic spawns - **Status** — operator snapshot - **Record-outcome** — final report from the friction-log Cloud Agent ### Qualification bar (soft skip) Skip (do not throw) when any of: missing/invalid `target`; structured filing missing `preliminaryInvestigation` (and no `body`); missing reproducible gap (no `howToReproduce`, no `body`, structured fields too thin); looks transient/session-bound (heuristic: no `howToReproduce`, empty `cost`, short `whatHappened`); GitHub title empty after `Friction:` normalize. Prefer **durable, recurring, clear owner, reproducible contract/API/docs gap**. Every structured papercut should carry a short **preliminary investigation**: what was already looked at, plus `relevantFiles` when any paths look relevant. Do not invent a root cause. Do not require a file list when none is known. Keep it short — not a second copy of a full issue thread. A raw `body` may include the same section inline. Eligibility for the daily sweep remains rule-based (open `friction` without `friction-skipped`). At most one automatic Cloud Agent per Denver calendar day. ## Prerequisites / setup 1. Depends on `@kentcdodds/github` (default **`bot`** account → secret **`github-botAccessToken`**), `@kentcdodds/cursor` (secret **`cursorApiKey`**), and `@kentcdodds/grok-bot` (Patch wake). Approve host/package access if prompted. 2. Keep the package `daily` job enabled unless you intentionally pause with `./pause`. Do not disable live webhooks/jobs casually. 3. Agents must pass an explicit `target` on `./create` / `./file` — no silent default host, no aliases. Prefer those exports over `gh` so GitHub issues get the `friction` label. 4. Agents: see [`AGENTS.md`](./AGENTS.md) for import paths and dry-run smoke. ## Done when - `./status` shows `enabled: true` (or you intentionally paused) - `./scan` / `./sweep({ dryRun: true })` lists eligibility without spawning - `./create({ dryRun: true, target: { host: 'github', repo: 'kody-hq/kody' }, … })` previews without posting - A would-skip qualify case returns `{ ok: true, skipped: true, reason }` - `./create({ dryRun: true, target: { host: 'kody', repo: '@scope/leaf' }, … })` dry-runs Patch wake - `./file({ dryRun: true, target, items: […] })` previews a batch - Live daily sweep spawns at most one agent per Denver day when eligible