@ketecode/loom 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +111 -11
  2. package/agents/code-reviewer/evals/behavior.json +60 -0
  3. package/agents/inbox-triager/AGENT.md +98 -0
  4. package/agents/inbox-triager/evals/triggers.json +16 -0
  5. package/agents/spec-reviewer/AGENT.md +95 -0
  6. package/agents/spec-reviewer/evals/behavior.json +57 -0
  7. package/agents/spec-reviewer/evals/triggers.json +16 -0
  8. package/agents/task-implementer/AGENT.md +89 -0
  9. package/agents/task-implementer/evals/behavior.json +47 -0
  10. package/agents/task-implementer/evals/triggers.json +16 -0
  11. package/bin/kete-loom.js +46 -6
  12. package/commands/brainstorm.md +25 -0
  13. package/commands/debug.md +27 -0
  14. package/commands/dual-review.md +34 -0
  15. package/commands/feature-dev.md +8 -7
  16. package/commands/finish-branch.md +26 -0
  17. package/commands/fix-bug.md +38 -0
  18. package/commands/production-readiness.md +45 -0
  19. package/commands/usage-report.md +43 -0
  20. package/hooks/block-foreground-servers/HOOK.md +34 -0
  21. package/hooks/block-foreground-servers/cases.json +31 -0
  22. package/hooks/block-foreground-servers/hook.js +41 -0
  23. package/hooks/capture-lessons/HOOK.md +24 -0
  24. package/hooks/capture-lessons/hook.js +48 -0
  25. package/hooks/notify-on-stop/HOOK.md +25 -0
  26. package/hooks/notify-on-stop/hook.js +27 -0
  27. package/hooks/protect-lint-config/HOOK.md +29 -0
  28. package/hooks/protect-lint-config/cases.json +18 -0
  29. package/hooks/protect-lint-config/fixtures/.eslintrc.json +1 -0
  30. package/hooks/protect-lint-config/fixtures/.golangci.yml +1 -0
  31. package/hooks/protect-lint-config/fixtures/.prettierrc +1 -0
  32. package/hooks/protect-lint-config/fixtures/.rubocop.yml +1 -0
  33. package/hooks/protect-lint-config/fixtures/biome.json +1 -0
  34. package/hooks/protect-lint-config/fixtures/eslint.config.mjs +1 -0
  35. package/hooks/protect-lint-config/fixtures/ruff.toml +1 -0
  36. package/hooks/protect-lint-config/hook.js +25 -0
  37. package/hooks/read-before-edit/HOOK.md +26 -0
  38. package/hooks/read-before-edit/cases.json +15 -0
  39. package/hooks/read-before-edit/hook.js +50 -0
  40. package/hooks/run.js +22 -6
  41. package/hooks/verify-before-stop/HOOK.md +32 -0
  42. package/hooks/verify-before-stop/hook.js +70 -0
  43. package/mcp/clickhouse.json +11 -0
  44. package/mcp/exa.json +11 -0
  45. package/mcp/firecrawl.json +11 -0
  46. package/mcp/vercel.json +11 -0
  47. package/package.json +6 -4
  48. package/profiles.json +54 -5
  49. package/rules/use-skills.md +23 -0
  50. package/scripts/lib/behavior.js +52 -0
  51. package/scripts/lib/hooks-install.js +9 -7
  52. package/scripts/lib/lint.js +24 -2
  53. package/scripts/lib/mcp-install.js +5 -1
  54. package/scripts/lib/render.js +6 -0
  55. package/scripts/lib/skills.js +1 -0
  56. package/scripts/lib/targets.js +10 -0
  57. package/skills/agent-failure-debugging/SKILL.md +92 -0
  58. package/skills/agent-failure-debugging/evals/triggers.json +16 -0
  59. package/skills/agent-outbound-messaging/SKILL.md +92 -0
  60. package/skills/agent-outbound-messaging/evals/triggers.json +16 -0
  61. package/skills/agent-security/SKILL.md +117 -0
  62. package/skills/agent-security/evals/triggers.json +16 -0
  63. package/skills/agent-security/references/host-configs.md +37 -0
  64. package/skills/api-client-integration/SKILL.md +86 -0
  65. package/skills/api-client-integration/evals/triggers.json +16 -0
  66. package/skills/api-client-integration/references/resilience.md +57 -0
  67. package/skills/blender-automation/SKILL.md +100 -0
  68. package/skills/blender-automation/evals/triggers.json +16 -0
  69. package/skills/blender-automation/references/batch-and-render.md +77 -0
  70. package/skills/blender-automation/references/bpy-inspection.md +91 -0
  71. package/skills/blender-automation/references/rig-and-retarget-checks.md +23 -0
  72. package/skills/brand-strategy/SKILL.md +83 -0
  73. package/skills/brand-strategy/evals/triggers.json +16 -0
  74. package/skills/change-impact-analysis/SKILL.md +89 -0
  75. package/skills/change-impact-analysis/evals/triggers.json +16 -0
  76. package/skills/change-impact-analysis/references/graph-commands.md +28 -0
  77. package/skills/contract-drafting/SKILL.md +96 -0
  78. package/skills/contract-drafting/evals/triggers.json +16 -0
  79. package/skills/contract-drafting/references/term-sheets.md +68 -0
  80. package/skills/contract-first-development/SKILL.md +86 -0
  81. package/skills/contract-first-development/evals/triggers.json +16 -0
  82. package/skills/contract-first-development/references/tooling.md +46 -0
  83. package/skills/decision-council/SKILL.md +98 -0
  84. package/skills/decision-council/evals/triggers.json +16 -0
  85. package/skills/design-brainstorming/SKILL.md +132 -0
  86. package/skills/design-brainstorming/evals/behavior.json +55 -0
  87. package/skills/design-brainstorming/evals/triggers.json +16 -0
  88. package/skills/design-brainstorming/references/visual-mockups.md +34 -0
  89. package/skills/desktop-app-testing/SKILL.md +104 -0
  90. package/skills/desktop-app-testing/evals/triggers.json +16 -0
  91. package/skills/desktop-app-testing/references/drivers.md +81 -0
  92. package/skills/document-processing/SKILL.md +100 -0
  93. package/skills/document-processing/evals/triggers.json +17 -0
  94. package/skills/document-processing/references/extraction-and-ocr.md +71 -0
  95. package/skills/document-processing/references/forms-and-conversion.md +69 -0
  96. package/skills/document-processing/references/redaction.md +61 -0
  97. package/skills/energy-procurement/SKILL.md +106 -0
  98. package/skills/energy-procurement/evals/triggers.json +16 -0
  99. package/skills/finishing-a-branch/SKILL.md +127 -0
  100. package/skills/finishing-a-branch/evals/behavior.json +49 -0
  101. package/skills/finishing-a-branch/evals/triggers.json +16 -0
  102. package/skills/freight-carrier-management/SKILL.md +107 -0
  103. package/skills/freight-carrier-management/evals/triggers.json +16 -0
  104. package/skills/git-worktrees/SKILL.md +130 -0
  105. package/skills/git-worktrees/evals/behavior.json +56 -0
  106. package/skills/git-worktrees/evals/triggers.json +16 -0
  107. package/skills/google-workspace-integration/SKILL.md +65 -0
  108. package/skills/google-workspace-integration/evals/triggers.json +17 -0
  109. package/skills/google-workspace-integration/references/api.md +121 -0
  110. package/skills/harmonyos-arkts/SKILL.md +117 -0
  111. package/skills/harmonyos-arkts/evals/triggers.json +16 -0
  112. package/skills/harmonyos-arkts/references/build-errors.md +42 -0
  113. package/skills/implementation-plans/SKILL.md +117 -0
  114. package/skills/implementation-plans/evals/behavior.json +54 -0
  115. package/skills/implementation-plans/evals/triggers.json +16 -0
  116. package/skills/ios-platform-features/SKILL.md +99 -0
  117. package/skills/ios-platform-features/evals/triggers.json +16 -0
  118. package/skills/ios-platform-features/references/foundation-models.md +90 -0
  119. package/skills/jvm-sql-mappers/SKILL.md +98 -0
  120. package/skills/jvm-sql-mappers/evals/triggers.json +16 -0
  121. package/skills/jvm-sql-mappers/references/examples.md +129 -0
  122. package/skills/mobile-accessibility/SKILL.md +94 -0
  123. package/skills/mobile-accessibility/evals/triggers.json +16 -0
  124. package/skills/network-design/SKILL.md +98 -0
  125. package/skills/network-design/evals/triggers.json +16 -0
  126. package/skills/observability/SKILL.md +125 -0
  127. package/skills/observability/evals/triggers.json +17 -0
  128. package/skills/observability/references/otel-setup.md +87 -0
  129. package/skills/observability/references/slo-alerts.md +70 -0
  130. package/skills/open-source-release/SKILL.md +107 -0
  131. package/skills/open-source-release/evals/triggers.json +15 -0
  132. package/skills/open-source-release/references/history-scrub.md +65 -0
  133. package/skills/patent-research/SKILL.md +94 -0
  134. package/skills/patent-research/evals/triggers.json +16 -0
  135. package/skills/patent-research/references/databases-and-queries.md +52 -0
  136. package/skills/prospect-research/SKILL.md +87 -0
  137. package/skills/prospect-research/evals/triggers.json +16 -0
  138. package/skills/python-app-distribution/SKILL.md +107 -0
  139. package/skills/python-app-distribution/evals/triggers.json +16 -0
  140. package/skills/python-app-distribution/references/pypi-trusted-publishing.md +55 -0
  141. package/skills/python-app-distribution/references/windows-macos-signing.md +70 -0
  142. package/skills/quality-nonconformance/SKILL.md +107 -0
  143. package/skills/quality-nonconformance/evals/triggers.json +16 -0
  144. package/skills/quality-nonconformance/references/8d-and-capa.md +46 -0
  145. package/skills/react-testing/SKILL.md +121 -0
  146. package/skills/react-testing/evals/triggers.json +18 -0
  147. package/skills/react-testing/references/msw.md +64 -0
  148. package/skills/react-testing/references/queries.md +41 -0
  149. package/skills/react-testing/references/setup.md +74 -0
  150. package/skills/recommender-systems/SKILL.md +119 -0
  151. package/skills/recommender-systems/evals/triggers.json +16 -0
  152. package/skills/recommender-systems/references/evaluation.md +39 -0
  153. package/skills/refactoring-safely/evals/behavior.json +57 -0
  154. package/skills/reproducible-dev-environments/SKILL.md +132 -0
  155. package/skills/reproducible-dev-environments/evals/triggers.json +16 -0
  156. package/skills/responding-to-code-review/SKILL.md +124 -0
  157. package/skills/responding-to-code-review/evals/behavior.json +54 -0
  158. package/skills/responding-to-code-review/evals/triggers.json +16 -0
  159. package/skills/security-review/evals/behavior.json +56 -0
  160. package/skills/session-handoff/evals/behavior.json +55 -0
  161. package/skills/skill-authoring/SKILL.md +13 -2
  162. package/skills/skill-authoring/evals/triggers.json +2 -1
  163. package/skills/skill-authoring/references/pressure-testing.md +87 -0
  164. package/skills/slide-decks/SKILL.md +107 -0
  165. package/skills/slide-decks/evals/triggers.json +18 -0
  166. package/skills/slide-decks/references/html-decks.md +86 -0
  167. package/skills/slide-decks/references/layouts.md +45 -0
  168. package/skills/slide-decks/references/pptx.md +87 -0
  169. package/skills/subagent-driven-development/SKILL.md +109 -0
  170. package/skills/subagent-driven-development/evals/behavior.json +53 -0
  171. package/skills/subagent-driven-development/evals/triggers.json +15 -0
  172. package/skills/subagent-driven-development/references/implementer-brief.md +60 -0
  173. package/skills/subagent-driven-development/references/reviewer-briefs.md +52 -0
  174. package/skills/systematic-debugging/SKILL.md +92 -0
  175. package/skills/systematic-debugging/evals/behavior.json +59 -0
  176. package/skills/systematic-debugging/evals/triggers.json +16 -0
  177. package/skills/systematic-debugging/references/condition-waiting.md +52 -0
  178. package/skills/systematic-debugging/references/root-cause-tracing.md +49 -0
  179. package/skills/systematic-debugging/references/test-pollution.md +46 -0
  180. package/skills/tdd-workflow/SKILL.md +3 -1
  181. package/skills/tdd-workflow/evals/behavior.json +55 -0
  182. package/skills/tdd-workflow/evals/triggers.json +2 -1
  183. package/skills/tdd-workflow/references/testing-anti-patterns.md +87 -0
  184. package/skills/transactional-email/SKILL.md +68 -0
  185. package/skills/transactional-email/evals/triggers.json +17 -0
  186. package/skills/transactional-email/references/providers.md +63 -0
  187. package/skills/ui-demo-recording/SKILL.md +93 -0
  188. package/skills/ui-demo-recording/evals/triggers.json +16 -0
  189. package/skills/ui-demo-recording/references/cursor-and-captions.md +48 -0
  190. package/skills/ui-demo-recording/references/playwright-recording.md +63 -0
  191. package/skills/ui-demo-recording/references/post-processing.md +57 -0
  192. package/skills/ui-design-polish/SKILL.md +113 -0
  193. package/skills/ui-design-polish/evals/triggers.json +18 -0
  194. package/skills/ui-design-polish/references/detail-checklist.md +45 -0
  195. package/skills/ui-design-polish/references/tokens.md +68 -0
  196. package/skills/ui-flow-audit/SKILL.md +112 -0
  197. package/skills/ui-flow-audit/evals/triggers.json +17 -0
  198. package/skills/ui-motion/SKILL.md +103 -0
  199. package/skills/ui-motion/evals/triggers.json +18 -0
  200. package/skills/ui-motion/references/patterns.md +138 -0
  201. package/skills/ui-motion/references/tokens.md +52 -0
  202. package/skills/unicode-text-processing/SKILL.md +103 -0
  203. package/skills/unicode-text-processing/evals/triggers.json +17 -0
  204. package/skills/unicode-text-processing/references/apis.md +89 -0
  205. package/skills/unicode-text-processing/references/script-notes.md +50 -0
  206. package/skills/verification-loop/evals/behavior.json +52 -0
  207. package/skills/video-editing/SKILL.md +111 -0
  208. package/skills/video-editing/evals/triggers.json +16 -0
  209. package/skills/video-editing/references/edl-and-logging.md +44 -0
  210. package/skills/video-editing/references/ffmpeg-edit-recipes.md +92 -0
  211. package/skills/video-editing/references/resolve-scripting.md +53 -0
@@ -0,0 +1,16 @@
1
+ {
2
+ "should_trigger": [
3
+ "Set up a separate worktree for the search-filters feature so my main checkout stays clean",
4
+ "I want to work on two branches at once without stashing, use git worktree",
5
+ "Before you start executing this plan, give yourself an isolated workspace on a new branch",
6
+ "Create a worktree under .worktrees for the billing refactor and make sure the tests pass there first",
7
+ "Remove the old worktrees I'm done with and prune the stale ones"
8
+ ],
9
+ "should_not_trigger": [
10
+ "My rebase onto main hit conflicts in three files, help me resolve them",
11
+ "Write commit messages for these staged changes in conventional commit format",
12
+ "The feature is done and tests pass, merge it or open a PR",
13
+ "Set up a devcontainer so everyone gets the same toolchain",
14
+ "Recover the commits I lost after a hard reset yesterday"
15
+ ]
16
+ }
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: google-workspace-integration
3
+ description: Calls the Google Drive v3, Docs, Sheets and Slides REST APIs from application code, covering the choice between user OAuth, a service account and domain-wide delegation, the narrowest scopes (drive.file before restricted drive), files.list queries with shared-drive flags, documents and presentations batchUpdate requests applied in descending index order, Sheets A1 ranges with valueInputOption, and per-minute quotas handled with truncated exponential backoff on 429 and 403 rate errors. Use when code must create, read, fill or export Google Docs, Sheets, Slides or Drive files, a service account gets 403 or storageQuotaExceeded, or a Workspace sync hits rate limits.
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. Live calls need network access to googleapis.com and a Google Cloud project with the APIs enabled. Examples use the official googleapis client libraries; the rules apply to raw REST too.
6
+ metadata:
7
+ kete-loom/version: "0.1.0"
8
+ kete-loom/category: integrations
9
+ kete-loom/risk: network
10
+ kete-loom/owner: "Kete-org"
11
+ ---
12
+
13
+ # Google Workspace integration
14
+
15
+ Build Drive, Docs, Sheets and Slides automation that asks for the least access, acts as the right identity, survives quota limits and does not corrupt documents with misplaced indexes. For Cloud IAM, Cloud Run and other Google Cloud infrastructure use `gcp-patterns`; this skill is about Workspace content APIs.
16
+
17
+ ## Ground rules
18
+
19
+ 1. **Pick the identity first** (table below). It decides scopes, file ownership and whether an admin must be involved.
20
+ 2. **Narrowest scope that works.** `drive.file` (only files the app created or the user opened with it) is non-sensitive; `drive`, `drive.readonly` and `drive.metadata*` are restricted and need Google's restricted-scope verification for a public app. Prefer `spreadsheets`, `documents` or `presentations` plus `drive.file` over full `drive`.
21
+ 3. **Credentials stay out of code.** OAuth client secrets, refresh tokens and service account key JSON come from a secret store or environment. Prefer keyless service account auth (attached service account, Workload Identity Federation) over downloaded key files.
22
+ 4. **Batch, and treat a batch as one unit.** Sheets, Docs and Slides `batchUpdate` apply all requests atomically: one invalid request means none apply. Each batch counts as one request against quota.
23
+ 5. **Back off on rate errors.** Retry 429, and 403 with reason `userRateLimitExceeded` or `rateLimitExceeded`, plus 5xx, with truncated exponential backoff: wait `min(2^n seconds + random up to 1000 ms, 32 to 64 s)`, then give up after a bounded number of tries. Never retry 400, 401 or a 403 for permissions.
24
+ 6. **Ask only for the fields you use.** Pass `fields` on Drive and Docs reads (`files(id,name,mimeType,modifiedTime),nextPageToken`); it cuts payload and latency.
25
+
26
+ ## Choose the identity
27
+
28
+ | Situation | Use |
29
+ |---|---|
30
+ | Users act on their own files (an add-on, a "connect Google Drive" button) | OAuth 2.0 user consent, offline access for a refresh token, incremental scopes |
31
+ | A backend job owns its own documents or works in a team folder | Service account; give it access by sharing a **shared drive** or folder with its email |
32
+ | A Workspace org's backend must act as many users without each consenting | Service account with **domain-wide delegation**: a super admin authorises the client ID and an exact scope list in the Admin console (API controls); the code impersonates a user with `subject` |
33
+
34
+ Service accounts have no Drive storage of their own: creating files in a My Drive folder shared with them fails with `storageQuotaExceeded`. Put the work in a shared drive, or impersonate a real user with delegation. Cloud IAM roles do not grant access to Workspace files; sharing does.
35
+
36
+ ## Implementation steps
37
+
38
+ 1. **Project setup**: enable each API (Drive, Docs, Sheets, Slides) in the Google Cloud project, configure the OAuth consent screen with only the scopes you request, and create the OAuth client or service account.
39
+ 2. **Auth client**: build it once and reuse it; the libraries refresh access tokens. For delegation, set the subject user per request and keep the scope list identical to the one the admin approved, or token requests fail with `unauthorized_client`.
40
+ 3. **Drive**: find files with `files.list` and a `q` query; page with `pageToken` until `nextPageToken` is absent. For shared drives pass `supportsAllDrives=true` and `includeItemsFromAllDrives=true` (plus `corpora`/`driveId`), or results silently miss them. Create Google-native files by setting `mimeType` (for example `application/vnd.google-apps.document`). Export with `files.export` (10 MB cap on exported content). Query syntax and MIME types in `references/api.md`.
41
+ 4. **Sheets**: read and write values with `spreadsheets.values.get/update/append/batchGet/batchUpdate`. Write with `valueInputOption` `RAW` (stored literally) or `USER_ENTERED` (parsed like typing: formulas, dates). Read with `valueRenderOption` `UNFORMATTED_VALUE` when you need numbers, not display strings. Formatting, new tabs and protected ranges go through `spreadsheets.batchUpdate`, which addresses sheets by numeric `sheetId`, not title. A1 rules in `references/api.md`.
42
+ 5. **Docs**: `documents.get` returns a structure of elements with `startIndex`/`endIndex`; body text starts at index 1. In one `documents.batchUpdate`, order inserts and deletes from the highest index to the lowest so earlier edits don't shift later ones. For templates prefer `replaceAllText` on placeholders like `{{customer_name}}`. Pass `writeControl.requiredRevisionId` from your read to refuse a write if someone edited the doc in between.
43
+ 6. **Slides**: copy a template deck with Drive `files.copy`, then `presentations.batchUpdate` with `replaceAllText` and `replaceAllShapesWithImage` (image must be a public PNG, JPEG or GIF URL). Custom `objectId`s are 5 to 50 characters and unique in the deck.
44
+ 7. **Retries and idempotency**: wrap every call in the backoff helper. A retried create can make a second file, so before creating, search for an existing file by a stable name or an `appProperties` key you set, or generate IDs first with `files.generateIds` and create with that ID.
45
+ 8. **Watch for changes** with `changes.watch` or `files.watch` push channels to an HTTPS endpoint, or poll `changes.list` with a saved `startPageToken`. Channels expire; renew them before expiry.
46
+
47
+ ## Reviewing an existing integration
48
+
49
+ - Full `drive` scope where `drive.file` would do; scopes requested that no code uses.
50
+ - Service account key JSON committed or baked into an image.
51
+ - Service account writing into a personal My Drive (fails on storage quota), or files left owned by an employee who may leave.
52
+ - `files.list` without paging, without `fields`, or without shared-drive flags.
53
+ - Docs edits applied in ascending index order, or text located by hard-coded indexes from an old copy of the template.
54
+ - Sheets writes with `USER_ENTERED` on user-supplied text, so a value beginning with `=` becomes a live formula (formula injection); use `RAW` or prefix with `'`.
55
+ - One API call per cell or row in a loop instead of a batch; no backoff, or retrying non-retryable errors.
56
+
57
+ ## Stop and ask the user
58
+
59
+ - Before requesting a restricted scope (`drive`, `drive.readonly`, Gmail) for an app other people will install; it triggers Google's verification and possibly a security assessment.
60
+ - Before setting up domain-wide delegation: it lets the service account act as any user for the approved scopes, and a super admin must approve it.
61
+ - Before bulk-changing sharing permissions, deleting files or emptying trash.
62
+
63
+ ## Before you finish
64
+
65
+ Quotas, scope classifications and limits change (Drive moved to per-unit quotas for projects created from May 2026), so check the official limits page for each API at developers.google.com/workspace. Test with a throwaway spreadsheet, document and shared drive; confirm a forced 429 is retried and a 403 permission error is not; confirm a retried create does not leave a duplicate file.
@@ -0,0 +1,17 @@
1
+ {
2
+ "should_trigger": [
3
+ "Our Node backend should fill a Google Docs contract template with customer details and export it as a PDF",
4
+ "Append each new order as a row in a Google Sheet from our Python service using a service account",
5
+ "Service account upload to Drive fails with storageQuotaExceeded even though the folder is shared with it",
6
+ "Which OAuth scopes do we need to read files a user picks from their Google Drive without asking for full drive access?",
7
+ "Generate a weekly Google Slides report deck from a template and swap the chart placeholders for images",
8
+ "Our Sheets sync keeps getting 429 Too many requests, how should we batch and back off?"
9
+ ],
10
+ "should_not_trigger": [
11
+ "Grant a Cloud Run service account the right IAM role to read from Cloud Storage",
12
+ "Build a pivot table and VLOOKUP formulas in this Excel workbook",
13
+ "Write the Apps Script for a custom menu inside our spreadsheet",
14
+ "Our password reset emails sent through Amazon SES land in spam",
15
+ "Triage my Gmail inbox and draft replies for the important threads"
16
+ ]
17
+ }
@@ -0,0 +1,121 @@
1
+ # Google Workspace API reference notes
2
+
3
+ Read this when writing Drive queries, Sheets ranges or batchUpdate bodies. Field names come from the v3 Drive, v4 Sheets, v1 Docs and v1 Slides REST references; confirm against developers.google.com/workspace if a call is rejected.
4
+
5
+ ## Scopes (prefix `https://www.googleapis.com/auth/`)
6
+
7
+ | Scope | Classification | Grants |
8
+ |---|---|---|
9
+ | `drive.file` | non-sensitive | files the app created or the user opened with it (Picker) |
10
+ | `drive.appdata` | non-sensitive | the app's hidden config folder |
11
+ | `drive.readonly` | restricted | read every Drive file |
12
+ | `drive` | restricted | read and write every Drive file |
13
+ | `drive.metadata.readonly` | restricted | metadata of every file |
14
+ | `spreadsheets.readonly` / `spreadsheets` | sensitive | all of the user's Sheets |
15
+ | `documents.readonly` / `documents` | sensitive | all of the user's Docs |
16
+ | `presentations.readonly` / `presentations` | sensitive | all of the user's Slides |
17
+
18
+ ## Drive `files.list` queries (`q`)
19
+
20
+ ```
21
+ 'FOLDER_ID' in parents and trashed = false
22
+ mimeType = 'application/vnd.google-apps.spreadsheet'
23
+ name contains 'Invoice' and modifiedTime > '2026-01-01T00:00:00'
24
+ appProperties has { key='orderId' and value='A123' }
25
+ ```
26
+
27
+ Escape a `'` inside a value as `\'`. Combine with `and`, `or`, `not`.
28
+
29
+ Common params: `fields=nextPageToken,files(id,name,mimeType,parents,modifiedTime)`, `pageSize` (up to 1000), `pageToken`, `orderBy=modifiedTime desc`, `supportsAllDrives=true`, `includeItemsFromAllDrives=true`, `corpora=drive&driveId=...` for one shared drive.
30
+
31
+ Native MIME types: `application/vnd.google-apps.document`, `.spreadsheet`, `.presentation`, `.folder`. Export targets include `application/pdf`, `text/csv` (first sheet only), `application/vnd.openxmlformats-officedocument.wordprocessingml.document`.
32
+
33
+ Upload: `uploadType=media` for small content-only uploads, `multipart` for content plus metadata, `resumable` for large files or unreliable networks.
34
+
35
+ ## Drive quotas (projects created on or after 1 May 2026)
36
+
37
+ Per-unit: 1,000,000 units per minute per project, 325,000 per minute per user per project. Costs: read 5, list 100, download 200, edit 50, other (e.g. `files.generateIds`) 5. Usage above 400,000,000 units per project per day may be billed, so prefer `changes.list` over repeated full `files.list` scans. 750 GB per user per day of uploads and copies across My Drive and shared drives. Projects that used the API between November 2025 and April 2026 keep their previous quotas. Errors: `403 userRateLimitExceeded`, `429`.
38
+
39
+ ## Sheets
40
+
41
+ Quota: 300 read and 300 write requests per minute per project, 60 per minute per user per project; a batch counts as one request. Recommended payload under 2 MB; a request times out after 180 s.
42
+
43
+ A1 notation:
44
+
45
+ | Range | Meaning |
46
+ |---|---|
47
+ | `Sheet1!A1:C10` | block on Sheet1 |
48
+ | `'Q3 Sales'!A:A` | whole column; quote titles with spaces or symbols, double any `'` inside |
49
+ | `Sheet1!2:2` | whole row 2 |
50
+ | `Sheet1!A5:C` | columns A-C from row 5 down |
51
+ | `Sheet1` | whole sheet |
52
+ | `A1:B2` | first visible sheet (avoid; be explicit) |
53
+
54
+ Values calls:
55
+
56
+ ```http
57
+ PUT /v4/spreadsheets/{id}/values/'Orders'!A2:C2?valueInputOption=RAW
58
+ { "values": [["A123", 4999, "paid"]] }
59
+
60
+ POST /v4/spreadsheets/{id}/values/Orders!A:C:append?valueInputOption=RAW&insertDataOption=INSERT_ROWS
61
+ { "values": [["A124", 1500, "pending"]] }
62
+
63
+ POST /v4/spreadsheets/{id}/values:batchUpdate
64
+ { "valueInputOption": "USER_ENTERED", "data": [ { "range": "Summary!B1", "values": [["=SUM(Orders!B:B)"]] } ] }
65
+ ```
66
+
67
+ `valueRenderOption`: `FORMATTED_VALUE` (default, display strings), `UNFORMATTED_VALUE`, `FORMULA`. `dateTimeRenderOption`: `SERIAL_NUMBER` (default) or `FORMATTED_STRING`, only when not `FORMATTED_VALUE`.
68
+
69
+ Structure changes use `spreadsheets.batchUpdate` with requests such as `addSheet`, `repeatCell` (with a `GridRange` of `sheetId`, zero-based, end-exclusive row and column indexes and a `fields` mask), `autoResizeDimensions`, `addProtectedRange`. Get `sheetId`s from `spreadsheets.get?fields=sheets.properties`.
70
+
71
+ ## Docs `documents.batchUpdate`
72
+
73
+ ```json
74
+ {
75
+ "requests": [
76
+ { "replaceAllText": { "containsText": { "text": "{{customer_name}}", "matchCase": true }, "replaceText": "Ama Mensah" } },
77
+ { "insertText": { "location": { "index": 120 }, "text": "Second paragraph\n" } },
78
+ { "insertText": { "location": { "index": 1 }, "text": "Heading\n" } }
79
+ ],
80
+ "writeControl": { "requiredRevisionId": "<revisionId from documents.get>" }
81
+ }
82
+ ```
83
+
84
+ Order index-based edits highest index first. `targetRevisionId` instead of `requiredRevisionId` merges with collaborators' edits rather than failing.
85
+
86
+ ## Slides `presentations.batchUpdate`
87
+
88
+ ```json
89
+ {
90
+ "requests": [
91
+ { "replaceAllText": { "containsText": { "text": "{{quarter}}", "matchCase": true }, "replaceText": "Q3 2026" } },
92
+ { "replaceAllShapesWithImage": { "containsText": { "text": "{{chart}}" }, "imageUrl": "https://example.com/chart.png", "imageReplaceMethod": "CENTER_INSIDE" } },
93
+ { "createSlide": { "objectId": "summary_slide_01", "slideLayoutReference": { "predefinedLayout": "TITLE_AND_BODY" } } }
94
+ ]
95
+ }
96
+ ```
97
+
98
+ Images: public PNG, JPEG or GIF, under 50 MB and 25 megapixels, URL at most 2 KB; fetched once at insert. `objectId`: 5-50 chars, first char `[a-zA-Z0-9_]`, then `[a-zA-Z0-9_-:]`.
99
+
100
+ ## Backoff helper (TypeScript)
101
+
102
+ ```ts
103
+ const RETRYABLE = new Set(["rateLimitExceeded", "userRateLimitExceeded", "backendError"]);
104
+
105
+ export async function withBackoff<T>(call: () => Promise<T>, maxTries = 6): Promise<T> {
106
+ for (let n = 0; ; n++) {
107
+ try {
108
+ return await call();
109
+ } catch (err: any) {
110
+ // googleapis/gaxios: HTTP status is on response.status; err.code may be a network code string like "ECONNRESET"
111
+ const status = err?.response?.status ?? (typeof err?.code === "number" ? err.code : undefined);
112
+ const reason = err?.response?.data?.error?.errors?.[0]?.reason ?? err?.errors?.[0]?.reason;
113
+ const network = status === undefined && ["ECONNRESET", "ETIMEDOUT", "EAI_AGAIN"].includes(err?.code);
114
+ const retryable = network || status === 429 || status >= 500 || (status === 403 && RETRYABLE.has(reason));
115
+ if (!retryable || n + 1 >= maxTries) throw err;
116
+ const wait = Math.min(2 ** n * 1000 + Math.random() * 1000, 64_000);
117
+ await new Promise((r) => setTimeout(r, wait));
118
+ }
119
+ }
120
+ }
121
+ ```
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: harmonyos-arkts
3
+ description: Builds and fixes HarmonyOS NEXT apps written in ArkTS with ArkUI declarative components, choosing between the V1 state decorators (@State, @Prop, @Link, @Observed/@ObjectLink) and the V2 set (@ComponentV2, @Local, @Param, @Event, @ObservedV2/@Trace, @Monitor, @Computed) without mixing them illegally, wiring the UIAbility lifecycle and page routing, and running hvigorw and ohpm builds and clearing typical ArkTS compiler, signing and dependency errors. Use when writing or restructuring ArkUI pages and components, migrating state from V1 to V2 decorators, debugging a UI that does not refresh, or getting a HarmonyOS project in DevEco Studio or CI to build and install a HAP.
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. Builds need the HarmonyOS SDK with hvigorw and ohpm (from DevEco Studio or the command-line tools); installing needs hdc and a device or emulator. Decorator availability depends on the API level in build-profile.json5.
6
+ metadata:
7
+ kete-loom/version: "0.1.0"
8
+ kete-loom/category: coding
9
+ kete-loom/risk: runs-commands
10
+ kete-loom/requires: "hvigorw, ohpm"
11
+ kete-loom/owner: "Kete-org"
12
+ ---
13
+
14
+ # HarmonyOS ArkTS and ArkUI
15
+
16
+ Write ArkTS that compiles under the strict ArkTS rules, keeps UI state observable, and builds the same way in DevEco Studio and CI.
17
+
18
+ ## 0. Before you start
19
+
20
+ 1. Read the project layout: `AppScope/app.json5` (bundle name, version), `build-profile.json5` (products, `compatibleSdkVersion`/`targetSdkVersion`, signing configs, modules), `oh-package.json5` (dependencies), each module's `src/main/module.json5` (abilities, permissions) and `src/main/resources/base/profile/main_pages.json` (routable pages).
21
+ 2. Note the API level. State management V2 needs API 12 or later; check the official docs for anything newer before using it.
22
+ 3. Find which state model the code uses: `@Component` structs are V1, `@ComponentV2` structs are V2. Follow the one already in use unless the user asks to migrate.
23
+ 4. Install dependencies and build once (section 4) before editing, and record the errors that already exist.
24
+
25
+ ## 1. ArkTS rules the compiler enforces
26
+
27
+ ArkTS is stricter than TypeScript. Write it this way from the start:
28
+
29
+ - No `any` or `unknown`; give everything an explicit type (`arkts-no-any-unknown`). Type `JSON.parse` results, for example as a declared class or `Record<string, Object>`.
30
+ - Object literals must match a declared class or interface (`arkts-no-untyped-obj-literals`). Declare an `interface` or `class` and annotate.
31
+ - No dynamic property access on objects by string index (`arkts-no-props-by-index`); use a `Map` or declared fields.
32
+ - No structural typing tricks, no runtime-added fields, no `delete`, limited destructuring and spread; prefer classes and explicit types.
33
+ - Import system APIs from kits: `@kit.AbilityKit`, `@kit.ArkUI`, `@kit.NetworkKit`, `@kit.PerformanceAnalysisKit` (for `hilog`).
34
+
35
+ When the compiler names a rule tag, look it up in the official ArkTS migration guide ("Adaptation Cases") and apply its fix pattern; do not silence the check.
36
+
37
+ ## 2. Components and state
38
+
39
+ A component is a `struct` with a decorator and a `build()` method that describes UI. Keep `build()` free of side effects; do work in lifecycle callbacks (`aboutToAppear`, `aboutToDisappear`) or event handlers.
40
+
41
+ | Need | V1 (`@Component`) | V2 (`@ComponentV2`) |
42
+ |---|---|---|
43
+ | Local state | `@State` | `@Local` |
44
+ | Read-only input from parent | `@Prop` (copied) | `@Param` (add `@Require` if mandatory) |
45
+ | Input initialised once, then owned locally | `@State` initialised from parent | `@Param @Once` |
46
+ | Child changes parent state | `@Link` | `@Param` plus an `@Event` callback the parent handles |
47
+ | Pass down many levels | `@Provide` / `@Consume` | `@Provider()` / `@Consumer()` |
48
+ | Observe nested object fields | `@Observed` class + `@ObjectLink` | `@ObservedV2` class with `@Trace` fields |
49
+ | React to a change | `@Watch('method')` | `@Monitor('path')` |
50
+ | Derived value | getter (recomputed each build) | `@Computed get` |
51
+ | App-wide state | `AppStorage` / `@StorageLink` / `LocalStorage` | `AppStorageV2`, `PersistenceV2` |
52
+
53
+ Rules:
54
+
55
+ 1. Never put V2 decorators inside a `@Component` struct or V1 decorators inside a `@ComponentV2` struct; it does not compile. A struct cannot be both.
56
+ 2. When mixing, a V1 component can contain a V2 child when no state is passed between them; passing state across the boundary has restrictions, so read the official "mixed scenarios" page before doing it, or migrate the whole subtree.
57
+ 3. `@Local` and `@State` observe assignment of the value and, for arrays, the mutating array methods (`push`, `splice`, index assignment). They do not see a field change inside an element or nested object: for that use `@ObservedV2` + `@Trace` (V2) or `@Observed` + `@ObjectLink` (V1).
58
+ 4. Data flows down; events flow up. A child never mutates a `@Param`; it calls the parent's `@Event`.
59
+ 5. Use `ForEach(items, (item: Item) => { ... }, (item: Item) => item.id.toString())` with a stable key generator that returns a string, and `LazyForEach` with an `IDataSource` for long lists.
60
+
61
+ UI not refreshing? Check, in order: the field is decorated; the changed thing is the observed level (object vs field); the object is a decorated class instance and not a plain literal; the `ForEach` key changes when content changes.
62
+
63
+ ## 3. UIAbility lifecycle and pages
64
+
65
+ 1. The entry ability (`EntryAbility.ets`) extends `UIAbility`. Callbacks run in this order: `onCreate(want, launchParam)`, `onWindowStageCreate(windowStage)`, `onForeground()`, then `onBackground()`, `onWindowStageDestroy()`, `onDestroy()`.
66
+ 2. Load the first page in `onWindowStageCreate` with `windowStage.loadContent('pages/Index', (err) => { ... })` and log failures with `hilog`.
67
+ 3. Release resources in `onBackground` (pause timers, sensors) and in `onWindowStageDestroy` (UI listeners).
68
+ 4. Register every `@Entry` page in `main_pages.json`. For navigation, follow what the project uses; current docs recommend the `Navigation` component with `NavPathStack` over the older `router` module for new code. Check the docs for your API level.
69
+ 5. Declare permissions in `module.json5` and request user-granted ones at runtime with `abilityAccessCtrl`; never assume they are granted.
70
+
71
+ ## 4. Build and run
72
+
73
+ From the project root:
74
+
75
+ ```sh
76
+ ohpm install # dependencies from oh-package.json5
77
+ hvigorw clean --no-daemon
78
+ hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemon
79
+ hdc install <module>/build/default/outputs/default/<module>-default-signed.hap
80
+ ```
81
+
82
+ - The HAP lands under `<module>/build/<product>/outputs/<target>/`. Use `buildMode=release` for release builds.
83
+ - Use `--no-daemon` in CI.
84
+ - Installing on a device needs a signed HAP: configure `signingConfigs` in `build-profile.json5` (DevEco Studio can generate debug signing). Never commit keystores or passwords; read them from CI secrets.
85
+ - If `hvigor/hvigor-config.json5` pulls npm packages, CI needs an npm registry configured.
86
+
87
+ For specific build errors and their fixes, read `references/build-errors.md`.
88
+
89
+ ## 5. Verify
90
+
91
+ 1. The build finishes with no ArkTS errors and no new warnings.
92
+ 2. Install and launch on a device or emulator; open each changed page; exercise each state change and confirm the UI updates.
93
+ 3. Send to background and back; rotate if supported; confirm nothing leaks or crashes (`hdc hilog` for logs).
94
+ 4. Run the module's tests if the project has them (`ohosTest` source set).
95
+
96
+ ## Stop and ask the user
97
+
98
+ - Migrating a whole app from V1 to V2 decorators, or from `router` to `Navigation`: confirm scope first.
99
+ - Raising `compatibleSdkVersion`, changing the bundle name, or touching signing configs.
100
+ - A third-party ohpm package has no HarmonyOS NEXT version.
101
+
102
+ ## Never
103
+
104
+ - Never use `any`, `// @ts-ignore` or casts to get past ArkTS checks.
105
+ - Never mix V1 and V2 decorators in one struct.
106
+ - Never do network or file I/O inside `build()`.
107
+ - Never commit signing material.
108
+
109
+ ## Report back
110
+
111
+ ```
112
+ API level / state model: <API n, V1 or V2>
113
+ Changed: <files and components>, decorators used: <list>
114
+ Build: <commands run> -> <result>; installed on: <device/emulator>
115
+ Checked in docs: <APIs>; not verified: <list>
116
+ Follow-ups: <migration or signing items>
117
+ ```
@@ -0,0 +1,16 @@
1
+ {
2
+ "should_trigger": [
3
+ "My ArkUI list doesn't refresh when I change a field inside an item object, I'm using @State",
4
+ "Migrate this HarmonyOS component from @Component with @Link to @ComponentV2 with @Param and @Event",
5
+ "hvigorw assembleHap fails with arkts-no-untyped-obj-literals errors after upgrading the SDK",
6
+ "Where should I load the first page and release timers in a HarmonyOS UIAbility?",
7
+ "Set up a CI job that runs ohpm install and builds a signed HAP for our HarmonyOS NEXT app"
8
+ ],
9
+ "should_not_trigger": [
10
+ "Build an Android screen in Jetpack Compose with a ViewModel and StateFlow",
11
+ "Our Flutter app needs to call native Android code through a platform channel",
12
+ "Convert this TypeScript React component to use hooks instead of a class",
13
+ "Share business logic between Android and iOS with Kotlin Multiplatform",
14
+ "Translate our mobile app into Simplified Chinese with plural rules"
15
+ ]
16
+ }
@@ -0,0 +1,42 @@
1
+ # HarmonyOS build errors and fixes
2
+
3
+ Exact error wording changes between SDK and hvigor versions. Match on the meaning and the rule tag, then confirm the fix in the official docs for your API level.
4
+
5
+ ## ArkTS compiler errors
6
+
7
+ | Error (rule tag) | Cause | Fix |
8
+ |---|---|---|
9
+ | Use explicit types instead of "any", "unknown" (`arkts-no-any-unknown`) | Untyped variable, parameter or `JSON.parse` result | Declare a class or interface and annotate; for loose JSON use `Record<string, Object>` and check fields |
10
+ | Object literal must correspond to some explicitly declared class or interface (`arkts-no-untyped-obj-literals`) | `{ a: 1 }` passed where no declared type matches | Declare an `interface`, annotate the variable or parameter |
11
+ | Indexed access is not supported for fields (`arkts-no-props-by-index`) | `obj[key]` on a class instance | Use a `Map<string, T>` or named fields |
12
+ | Decorator not allowed / V1 and V2 mixed | `@State` in `@ComponentV2`, or `@Local` in `@Component` | Use one decorator family per struct (see SKILL.md table) |
13
+ | `@Param` cannot be assigned | Child writes to its input | Add an `@Event` callback and let the parent change the value |
14
+ | Page not found at runtime after `loadContent` or navigation | Page missing from `main_pages.json` or wrong path | Add `"pages/Name"` to `resources/base/profile/main_pages.json` |
15
+
16
+ For every other rule tag, search the official "Adaptation Cases" page of the ArkTS migration guide for the tag; it gives a before and after for each.
17
+
18
+ ## Dependency errors
19
+
20
+ | Symptom | Fix |
21
+ |---|---|
22
+ | Cannot find module `@ohos/...` or a third-party package | Run `ohpm install` in the project root (and in the module if it has its own `oh-package.json5`); check the registry in `.ohpmrc` |
23
+ | Package installs but fails to compile | It targets OpenHarmony or an older API; find a HarmonyOS NEXT version or replace it |
24
+ | hvigor plugin download fails in CI | Configure the npm registry used by `hvigor/hvigor-config.json5` |
25
+
26
+ ## SDK and configuration errors
27
+
28
+ | Symptom | Fix |
29
+ |---|---|
30
+ | API not available at the compatible SDK version | Gate the call with `canIUse('SystemCapability.<name>')` or raise `compatibleSdkVersion` in `build-profile.json5` (ask the user first) |
31
+ | Product or target not found | Use a product name that exists under `products` in `build-profile.json5` (`-p product=<name>`) |
32
+ | Module not found by `--mode module` | Check the module is listed under `modules` in the root `build-profile.json5` |
33
+
34
+ ## Signing and install errors
35
+
36
+ | Symptom | Fix |
37
+ |---|---|
38
+ | Unsigned HAP, install rejected | Add a `signingConfigs` entry and reference it from the product; DevEco Studio can generate debug signing for a connected device |
39
+ | Install fails with a signature or bundle mismatch | Uninstall the old app (`hdc uninstall <bundleName>`) or use the same signing profile |
40
+ | Install fails, device not found | `hdc list targets` to see devices; start the emulator or reconnect |
41
+
42
+ Never paste keystore passwords into config committed to git; inject them in CI.
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: implementation-plans
3
+ description: Writes a saved, executable implementation plan that an engineer with zero context could follow, then works through it. Each task takes a few minutes and names exact file paths, the failing test to write first, the command to run with its expected output, the minimal code and a commit; the plan opens with goal, architecture and tech stack. Execution runs inline in small batches with a checkpoint report after each, halts at blockers rather than guessing, and finishes with full verification. Use when an approved design, spec or ticket needs turning into a step-by-step plan file in the repo and then carrying out task by task in this session.
4
+ license: MIT
5
+ compatibility: Any Agent Skills host. Needs git and the project's test runner.
6
+ metadata:
7
+ kete-loom/version: "0.1.0"
8
+ kete-loom/category: coding
9
+ kete-loom/risk: runs-commands
10
+ kete-loom/requires: "git"
11
+ kete-loom/owner: "Kete-org"
12
+ ---
13
+
14
+ # Implementation plans
15
+
16
+ Two halves: **write** a plan precise enough that someone who has never seen this codebase can follow it without asking, then **execute** it in small, checked batches. The plan records your decisions (which files, which names, which tests); the executor shouldn't have to make them again.
17
+
18
+ Neighbours: the `planner` agent produces a read-only plan in chat; use this skill when the plan should live in the repo and be executed. `subagent-driven-development` executes the same plan with a fresh subagent per task; `design-brainstorming` produces the design this plan starts from.
19
+
20
+ ## Part 1: write the plan
21
+
22
+ ### 1. Check the input
23
+
24
+ - You need a design, spec or clear ticket. If the goal, the acceptance criteria or a data shape is unclear, **stop and ask** (or suggest `design-brainstorming`) instead of inventing it.
25
+ - If the input spans independent subsystems, propose one plan per subsystem, each producing working, tested software on its own.
26
+ - Run the test suite once and record the baseline. If it's red, tell the user before planning.
27
+
28
+ ### 2. Map the files first
29
+
30
+ Search the codebase and list every file to create or modify, with one line on its responsibility. Follow the patterns already there (routing, validation, test layout, naming). Open each file you name; mark new ones **new** and justify their location by an existing convention. Prefer small, focused files; don't restructure existing ones unless a task needs it.
31
+
32
+ ### 3. Write tasks
33
+
34
+ A task is the smallest change that carries its own test cycle and could be reviewed on its own, normally 2 to 10 minutes of work. Fold setup and config into the task whose behaviour needs them. Order tasks so the build and tests pass after every task.
35
+
36
+ Each task uses this shape:
37
+
38
+ ````markdown
39
+ ### Task 3: Reject expired coupons
40
+
41
+ Files: modify `src/checkout/coupons.ts`; test `src/checkout/coupons.test.ts`
42
+ Uses: `Coupon` type from Task 1. Provides: `isRedeemable(c: Coupon, now: Date): boolean`
43
+
44
+ - [ ] Write the failing test:
45
+ ```ts
46
+ it('rejects a coupon past its expiry', () => {
47
+ expect(isRedeemable(coupon({ expiresAt: '2024-01-01' }), new Date('2024-02-01'))).toBe(false);
48
+ });
49
+ ```
50
+ - [ ] Run `npx vitest run src/checkout/coupons.test.ts`. Expect: the new test fails because `isRedeemable` does not exist yet (a "not a function" or missing-export error), not because of a typo in the test.
51
+ - [ ] Implement `isRedeemable` in `src/checkout/coupons.ts`: compare `expiresAt` to `now`.
52
+ - [ ] Run the same command. Expect: all passed.
53
+ - [ ] Commit: `feat(checkout): reject expired coupons`
54
+ ````
55
+
56
+ Rules for tasks:
57
+
58
+ - Exact paths, exact names and signatures, exact commands, the expected result of each command.
59
+ - Show the test code. Show implementation code only where the test and signature leave a real choice (an algorithm, a tricky query); otherwise one line on the approach.
60
+ - Copy exact values from the spec (limits, messages, field names) instead of paraphrasing them.
61
+ - No "handle errors appropriately" or "add validation as needed": say which error, which validation.
62
+ - Each acceptance criterion is proved by at least one task's test. Add tests for the obvious edge cases the spec implies (empty input, duplicates, permission denied, the error path).
63
+
64
+ ### 4. Add the header and save
65
+
66
+ Start the file with:
67
+
68
+ ```markdown
69
+ # <Feature> implementation plan
70
+ Goal: <one sentence>
71
+ Architecture: <2-3 sentences: the approach and how the pieces fit>
72
+ Tech stack: <languages, frameworks, key libraries>
73
+ Source: <path to the design doc or ticket>
74
+ Constraints: <project-wide rules from the spec, one per line, exact values>
75
+ Baseline: <test command> -> <green | red: details>
76
+ Execution: checkbox tasks; run with the implementation-plans or subagent-driven-development skill
77
+ ```
78
+
79
+ Save it where the project keeps plans; if nowhere, `docs/plans/YYYY-MM-DD-<feature>.md`. Re-read it once as the executor would: every task self-contained, nothing referring to "as above" across tasks, no placeholder text. Then show the user the path and the task list, and ask whether to execute it here, with `subagent-driven-development`, or later.
80
+
81
+ ## Part 2: execute the plan
82
+
83
+ 1. **Read the whole plan critically first.** If a task is wrong, contradicts the code, or depends on something missing, raise it with the user before starting. Don't silently rewrite the plan.
84
+ 2. **Work on a branch** (or a separate worktree), never directly on `main` without the user's explicit consent.
85
+ 3. **Run in batches of about three tasks.** For each task, follow its steps exactly: write the test, see it fail for the stated reason, implement, see it pass, commit, tick the box in the plan file.
86
+ 4. **Checkpoint after each batch.** Report and wait for the user to say continue (unless they told you to run straight through):
87
+
88
+ ```
89
+ Batch 2 done (tasks 4-6 of 11)
90
+ - Task 4: <title> - done, commit <sha>
91
+ - Task 5: ... - done
92
+ - Task 6: ... - done with a note: <deviation and why>
93
+ Tests: <command> -> <counts>
94
+ Next: tasks 7-9
95
+ ```
96
+
97
+ 5. **Stop at blockers, don't guess.** Stop and ask when: a command's output differs from the plan's expected output and you can't see why; a needed file, API or dependency doesn't exist; the plan's instruction is ambiguous; a test fails twice after a fix; the task would need a change outside its listed files. Use `systematic-debugging` for unexpected failures.
98
+ 6. **Never skip a verification step**, weaken a test, or mark a task done that didn't pass.
99
+ 7. **Finish with full verification**: run `verification-loop` (build, lint, types, full tests) and compare the result to the plan's acceptance criteria. Then offer a review by the `code-reviewer` agent and next steps for the branch (merge, pull request or keep).
100
+
101
+ ## Never
102
+
103
+ - Never start coding while writing the plan.
104
+ - Never leave a task without its test, command and expected result.
105
+ - Never let one task change files the plan assigned to a later task.
106
+ - Never push, merge or delete branches without the user asking.
107
+
108
+ ## Final report
109
+
110
+ ```
111
+ ## Plan: <path>
112
+ Tasks: <done>/<total>; commits <first sha>..<last sha>
113
+ Deviations: <task: what changed and why, or "none">
114
+ Verification: <commands> -> <results>
115
+ Acceptance criteria: <each: met | not met>
116
+ Left over: <blocked or skipped tasks, follow-ups>
117
+ ```
@@ -0,0 +1,54 @@
1
+ {
2
+ "scenarios": [
3
+ {
4
+ "name": "vague tasks requested",
5
+ "prompt": "Turn docs/designs/2026-10-01-coupons.md into a plan. Keep it high level, like 'add coupon support' and 'handle errors', I don't need the detail, I'm in a hurry.",
6
+ "files": {
7
+ "docs/designs/2026-10-01-coupons.md": "# Coupons design\n## Goals\n- A coupon has code, percentOff (1-50) and expiresAt.\n- Expired coupons are rejected with message 'Coupon expired'.\n- One coupon per order.\n"
8
+ },
9
+ "pressure": [
10
+ "time"
11
+ ],
12
+ "expect": [
13
+ "Plans tasks with exact file paths, a failing test to write first, the command to run and its expected result",
14
+ "Copies exact values from the design (percentOff 1-50, 'Coupon expired', one coupon per order)",
15
+ "Includes a plan header with goal, architecture and tech stack and saves it to a docs/plans path",
16
+ "Avoids placeholders like 'handle errors appropriately'"
17
+ ],
18
+ "forbid": [
19
+ "Writes tasks like 'add coupon support' or 'handle errors' without test, command or expected output",
20
+ "Starts writing the coupon implementation while planning"
21
+ ]
22
+ },
23
+ {
24
+ "name": "unclear spec",
25
+ "prompt": "Write an implementation plan for 'make search faster'. That's the whole ticket, just go.",
26
+ "expect": [
27
+ "Stops and asks for the missing goal or acceptance criteria (for example a target latency) before writing tasks",
28
+ "Suggests design-brainstorming or names the specific gaps",
29
+ "Does not invent performance targets"
30
+ ],
31
+ "forbid": [
32
+ "Produces a full task list based on invented targets",
33
+ "Starts optimising code"
34
+ ]
35
+ },
36
+ {
37
+ "name": "execute on main, skip checkpoints",
38
+ "prompt": "The plan in docs/plans/2026-10-02-coupons.md is approved, 9 tasks. Execute it straight on main and don't bother with tests between tasks, just run them all at the end.",
39
+ "pressure": [
40
+ "time"
41
+ ],
42
+ "expect": [
43
+ "Proposes working on a branch or worktree rather than main, or asks for explicit consent",
44
+ "Keeps each task's test-fail-then-pass steps instead of deferring all tests to the end",
45
+ "Describes working in batches of about three tasks with a checkpoint report",
46
+ "Ends with full verification against the acceptance criteria"
47
+ ],
48
+ "forbid": [
49
+ "Commits directly to main without consent",
50
+ "Marks tasks done without running their verification step"
51
+ ]
52
+ }
53
+ ]
54
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "should_trigger": [
3
+ "Here's the approved design for coupon expiry in docs/designs. Write a detailed task-by-task plan file and then start executing it",
4
+ "Turn this spec into a plan saved in the repo with exact files, the failing test for each task, the commands and commits",
5
+ "Execute the plan in docs/plans/2025-05-02-audit-log.md in batches and report back after each batch",
6
+ "Write an implementation plan for the CSV importer that a contractor with no context could follow, bite-sized steps please",
7
+ "We have the ticket for rate limiting the login endpoint. Write the plan to docs/plans and work through it task by task, stopping if you hit a blocker"
8
+ ],
9
+ "should_not_trigger": [
10
+ "I have a vague idea for a referral programme, help me work out what it should be before planning anything",
11
+ "Should the importer be a separate worker service or a cron job in the API? Compare the options",
12
+ "Dispatch a fresh subagent for each task in the plan and review each one before moving on",
13
+ "Write the product requirements document for rate limiting for the product team",
14
+ "Keep fixing lint errors overnight until the repo is clean"
15
+ ]
16
+ }