@desplega.ai/agent-swarm 1.147.0 → 1.149.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 (185) hide show
  1. package/README.md +13 -1
  2. package/dist/{acp-adapter-9n319wqc.js → acp-adapter-4jncb126.js} +12 -5
  3. package/dist/{actions-2vxqvpr9.js → actions-31vp3ae7.js} +10 -9
  4. package/dist/{app-w066xfy0.js → app-1hh67x8w.js} +6 -6
  5. package/dist/{assistant-kt31dj2h.js → assistant-z66dmz6p.js} +13 -11
  6. package/dist/{boot-reembed-az5rassp.js → boot-reembed-fqzxxzjh.js} +7 -7
  7. package/dist/{boot-reembed-j3mm3rfz.js → boot-reembed-wxa8ya0s.js} +8 -8
  8. package/dist/{boot-scrub-logs-b6h54817.js → boot-scrub-logs-jnyndh79.js} +5 -5
  9. package/dist/{claude-adapter-w1z04ann.js → claude-adapter-3qpa9w0j.js} +9 -9
  10. package/dist/{claude-managed-adapter-sactwn31.js → claude-managed-adapter-qvsmh6mv.js} +2 -2
  11. package/dist/{claude-sdk-session-f0cc1kec.js → claude-sdk-session-2yxgjs5d.js} +9 -9
  12. package/dist/{cli-y6b6fb76.js → cli-08b07b4r.js} +1 -1
  13. package/dist/{cli-8fc8de14.js → cli-0z2v4nhw.js} +1 -1
  14. package/dist/{cli-de14znh8.js → cli-19f354qr.js} +2 -2
  15. package/dist/{cli-hbv0kq6w.js → cli-2qts1hys.js} +3 -3
  16. package/dist/{cli-kpv03zhj.js → cli-3apbzgyk.js} +27 -15
  17. package/dist/{cli-1th1728g.js → cli-3q5ejx9p.js} +2 -2
  18. package/dist/{cli-d8brzxjb.js → cli-4wtq5jjv.js} +2 -2
  19. package/dist/{cli-ct0et58h.js → cli-5my3bjsd.js} +1 -1
  20. package/dist/{cli-cn6mmc7f.js → cli-6664w7y4.js} +1 -1
  21. package/dist/{cli-yz3djrm0.js → cli-6pqcb4q0.js} +53 -13
  22. package/dist/{cli-719k9j2c.js → cli-7smrsr25.js} +3 -3
  23. package/dist/{cli-rw51bq3j.js → cli-9fy6nk6g.js} +1 -1
  24. package/dist/{cli-zhjmqxzh.js → cli-9hspd3dp.js} +2 -2
  25. package/dist/{cli-3tgwnf43.js → cli-aae6hz6a.js} +4 -4
  26. package/dist/{cli-89xfd7f9.js → cli-cr12paw2.js} +5 -5
  27. package/dist/{cli-b5bq9crk.js → cli-d8ftsp62.js} +8 -8
  28. package/dist/{cli-4nr988h6.js → cli-e95cx1eb.js} +3 -3
  29. package/dist/{cli-n8508nre.js → cli-gjhjfeeg.js} +1 -1
  30. package/dist/{cli-p1d5b073.js → cli-gv88e1vf.js} +1 -1
  31. package/dist/{cli-rvqz34y5.js → cli-jecc01cb.js} +1 -1
  32. package/dist/{cli-8v0g1yc8.js → cli-k0cr4kat.js} +1 -1
  33. package/dist/{cli-mmemxxdc.js → cli-kgz4np97.js} +4 -4
  34. package/dist/{cli-w9kb3bk1.js → cli-kjwt6hdf.js} +3 -1
  35. package/dist/{cli-f7dsy61y.js → cli-mnmsfd1w.js} +6 -2
  36. package/dist/{cli-54wwve05.js → cli-n3dz2942.js} +37 -26
  37. package/dist/{cli-12fz972k.js → cli-nye12xk5.js} +8 -5
  38. package/dist/{cli-tzvk9haz.js → cli-phsxnkp6.js} +20 -20
  39. package/dist/{cli-53s590z8.js → cli-q50ef8g0.js} +1 -1
  40. package/dist/{cli-f146mn5s.js → cli-qaacms9y.js} +7 -6
  41. package/dist/{cli-xqcq9y5e.js → cli-r2ap2czm.js} +1 -0
  42. package/dist/{cli-m8yrsg97.js → cli-sd5pv3b1.js} +3 -3
  43. package/dist/{cli-0b6y7kxm.js → cli-xm87hzbw.js} +1 -1
  44. package/dist/{cli-ftht3zzj.js → cli-yab68w40.js} +285 -11
  45. package/dist/{cli-atcve9y8.js → cli-yb9qhqam.js} +227 -59
  46. package/dist/{cli-smby5m17.js → cli-ygweqcn4.js} +133 -22
  47. package/dist/{cli-dttph1bw.js → cli-ykxrnd1q.js} +2 -2
  48. package/dist/{cli-m9sxbkhm.js → cli-zvz62chv.js} +3 -3
  49. package/dist/cli.js +16 -14
  50. package/dist/{codex-adapter-zw4dwsx7.js → codex-adapter-8meawydj.js} +4 -4
  51. package/dist/{codex-hook-bw8p5nh4.js → codex-hook-hfrt9shr.js} +2 -2
  52. package/dist/{codex-session-runner-k981s65v.js → codex-session-runner-gjgxyp5j.js} +4 -4
  53. package/dist/{commands-sykrxx7e.js → commands-hz3nb95f.js} +5 -5
  54. package/dist/{db-sfbsc8wt.js → db-ggz97zbm.js} +5 -5
  55. package/dist/{e2b-6hb103d8.js → e2b-p04vmtx0.js} +1 -1
  56. package/dist/{handlers-0aspcejm.js → handlers-nbzdzn9k.js} +14 -11
  57. package/dist/{hook-hxccs7m5.js → hook-bks2q1f6.js} +7 -7
  58. package/dist/{hook-4nvqj2sb.js → hook-kq9wp0ep.js} +8 -8
  59. package/dist/{http-y06z517d.js → http-hrf77v87.js} +96 -45
  60. package/dist/{index-tce1rss4.js → index-6nsbg88z.js} +443 -144
  61. package/dist/{index-x5j894zf.js → index-8hmeg8j1.js} +14 -14
  62. package/dist/{index-k8znfx0z.js → index-cqtebbhb.js} +13 -13
  63. package/dist/{index-hssww7kj.js → index-n28pw1zt.js} +15 -15
  64. package/dist/{keepalive-w733ax66.js → keepalive-dxc12gvg.js} +7 -7
  65. package/dist/{lead-75bjqa9d.js → lead-yckfn18d.js} +32 -32
  66. package/dist/{maintenance-w4f1zjck.js → maintenance-6kfb2m5e.js} +8 -8
  67. package/dist/{oauth-refresh-sweep-wdetky26.js → oauth-refresh-sweep-1x1ac722.js} +6 -6
  68. package/dist/{onboard-bb5net8s.js → onboard-dcyt1609.js} +4 -3
  69. package/dist/{opencode-adapter-fef1mrn2.js → opencode-adapter-dce4wskd.js} +2 -2
  70. package/dist/{otel-impl-0w7c14ap.js → otel-impl-tbk3e5dr.js} +2 -2
  71. package/dist/{pi-mono-adapter-2has4gnp.js → pi-mono-adapter-zvshk5cj.js} +2 -2
  72. package/dist/{pricing-refresh-9nzsrgcq.js → pricing-refresh-kaqg567e.js} +7 -7
  73. package/dist/{rbac-roles-z1jrffbt.js → rbac-roles-ammq6rd2.js} +5 -5
  74. package/dist/{rbac-roles-r3hqjp09.js → rbac-roles-cf97v1vd.js} +6 -6
  75. package/dist/{render-v2-vbr89fnb.js → render-v2-80w603vy.js} +6 -6
  76. package/dist/{seed-pricing-g62hy1pk.js → seed-pricing-zbrn83xv.js} +6 -6
  77. package/dist/{setup-gnfqnptp.js → setup-fe66kczs.js} +2 -2
  78. package/dist/{worker-kznxp4qm.js → worker-qmb2d1e2.js} +32 -32
  79. package/dist/{x-n2phr5vm.js → x-n3e0v3xa.js} +2 -2
  80. package/openapi.json +46 -4
  81. package/package.json +3 -1
  82. package/src/agentmail/handlers.ts +5 -0
  83. package/src/automation-preflight-alert.ts +41 -0
  84. package/src/be/automation-preflight.ts +3 -3
  85. package/src/be/budget-refusal-notify.ts +1 -0
  86. package/src/be/db/tasks/read.ts +5 -0
  87. package/src/be/db.ts +132 -2
  88. package/src/be/migrations/150_deferred_task_waits.sql +18 -0
  89. package/src/be/migrations/151_repair_scheduled_task_required_params.sql +39 -0
  90. package/src/be/migrations/152_routing_decisions.sql +44 -0
  91. package/src/be/scripts/typecheck.ts +33 -22
  92. package/src/be/seed-scripts/catalog/delegate.ts +5 -1
  93. package/src/be/seed-skills/bundled-files.generated.json +10 -0
  94. package/src/be/seed-skills/index.ts +3 -0
  95. package/src/be/steering.ts +1 -0
  96. package/src/be/swarm-config-guard.ts +11 -0
  97. package/src/commands/onboard/steps/post-task.tsx +1 -0
  98. package/src/github/handlers.ts +9 -0
  99. package/src/gitlab/handlers.ts +4 -0
  100. package/src/heartbeat/heartbeat.ts +8 -0
  101. package/src/http/approval-requests.ts +1 -0
  102. package/src/http/apps.ts +1 -0
  103. package/src/http/config.ts +15 -6
  104. package/src/http/mcp.ts +31 -4
  105. package/src/http/script-runs.ts +6 -0
  106. package/src/http/tasks.ts +52 -30
  107. package/src/integrations/kapso/inbound.ts +1 -0
  108. package/src/jira/sync.ts +2 -0
  109. package/src/linear/sync.ts +2 -0
  110. package/src/prompts/session-templates.ts +29 -15
  111. package/src/scheduler/deferred-task-waits.ts +123 -0
  112. package/src/scheduler/schedule-task.ts +42 -0
  113. package/src/scheduler/scheduler.ts +22 -31
  114. package/src/script-workflows/workflow-ctx.ts +2 -0
  115. package/src/scripts-runtime/types/stdlib.d.ts +38 -24
  116. package/src/scripts-runtime/types/swarm-sdk.d.ts +38 -24
  117. package/src/server.ts +10 -1
  118. package/src/slack/actions.ts +1 -0
  119. package/src/slack/assistant.ts +2 -0
  120. package/src/slack/handlers.ts +3 -0
  121. package/src/slack/thread-buffer.ts +2 -0
  122. package/src/tasks/worker-follow-up.ts +9 -0
  123. package/src/tests/acp-adapter.test.ts +35 -6
  124. package/src/tests/acp-session-token.test.ts +67 -0
  125. package/src/tests/asset-key-api.test.ts +15 -2
  126. package/src/tests/asset-key-mcp.test.ts +2 -0
  127. package/src/tests/automation-preflight-alert.test.ts +91 -0
  128. package/src/tests/claude-worker-parity.test.ts +3 -0
  129. package/src/tests/config-session-auth.test.ts +143 -0
  130. package/src/tests/defer-task.test.ts +117 -6
  131. package/src/tests/deferred-task-wake.test.ts +456 -0
  132. package/src/tests/heartbeat-reroute-decision.test.ts +1 -0
  133. package/src/tests/http-api-integration.test.ts +33 -4
  134. package/src/tests/mcp-input-ergonomics.test.ts +386 -0
  135. package/src/tests/model-control.test.ts +18 -5
  136. package/src/tests/opencode-adapter.test.ts +2 -2
  137. package/src/tests/promote-draft-task-route.test.ts +4 -0
  138. package/src/tests/prompt-template-session.test.ts +13 -4
  139. package/src/tests/rbac-wire-e2e.test.ts +2 -2
  140. package/src/tests/routing-decision-persistence.test.ts +520 -0
  141. package/src/tests/routing-reason-contract.test.ts +89 -0
  142. package/src/tests/routing-reason-inventory.test.ts +55 -0
  143. package/src/tests/schedule-target-type.test.ts +48 -1
  144. package/src/tests/scheduled-task-required-params-migration.test.ts +182 -0
  145. package/src/tests/scheduled-tasks.test.ts +9 -5
  146. package/src/tests/script-connections.test.ts +4 -0
  147. package/src/tests/script-runs-http.test.ts +31 -0
  148. package/src/tests/scripts-typecheck.test.ts +11 -0
  149. package/src/tests/secret-scrubber.test.ts +12 -0
  150. package/src/tests/send-task-output-schema.test.ts +66 -1
  151. package/src/tests/send-task-requested-by.test.ts +1 -0
  152. package/src/tests/send-task-slack-routing-guard.test.ts +2 -0
  153. package/src/tests/store-progress-blocked-waiting-gate.test.ts +151 -0
  154. package/src/tests/swarm-tool-result-gate.test.ts +24 -0
  155. package/src/tests/task-tool-manifest.test.ts +47 -0
  156. package/src/tests/task-tool-preload-mcp.test.ts +125 -0
  157. package/src/tests/task-tools-ctx.test.ts +2 -0
  158. package/src/tests/tool-output-agent-id.test.ts +1 -0
  159. package/src/tests/ui-followup-lead-delegation.test.ts +6 -1
  160. package/src/tests/workflow-agent-task.test.ts +24 -1
  161. package/src/tests/workflow-engine-v2.test.ts +58 -2
  162. package/src/tools/accept-steer.ts +0 -1
  163. package/src/tools/defer-task.ts +73 -21
  164. package/src/tools/memory-get.ts +10 -3
  165. package/src/tools/memory-rate.ts +19 -7
  166. package/src/tools/memory-search.ts +2 -1
  167. package/src/tools/memory-store.ts +25 -5
  168. package/src/tools/send-task.ts +40 -2
  169. package/src/tools/skills/skill-publish.ts +1 -0
  170. package/src/tools/store-progress.ts +78 -4
  171. package/src/tools/templates.ts +2 -1
  172. package/src/tools/utils.ts +33 -2
  173. package/src/types.ts +14 -1
  174. package/src/utils/acp-session-token.ts +14 -4
  175. package/src/utils/secret-scrubber.ts +2 -0
  176. package/src/utils/task-tool-manifest.ts +33 -0
  177. package/src/workflows/engine.ts +4 -1
  178. package/src/workflows/executors/agent-task.ts +7 -1
  179. package/templates/ai-toolbox.manifest.json +6 -1
  180. package/templates/skills/comms/config.json +18 -0
  181. package/templates/skills/comms/content.md +74 -0
  182. package/templates/skills/comms/files/references/ste-rules.md +73 -0
  183. package/templates/skills/comms/files/references/visual-shapes.md +112 -0
  184. package/templates/skills/swarm-scripts/SKILL.md +3 -2
  185. package/templates/skills/swarm-scripts/content.md +3 -2
@@ -6,8 +6,8 @@ import {
6
6
  extractArgsJsonSchema,
7
7
  extractScriptSignature,
8
8
  typecheckScript
9
- } from "./cli-54wwve05.js";
10
- import"./cli-de14znh8.js";
9
+ } from "./cli-n3dz2942.js";
10
+ import"./cli-19f354qr.js";
11
11
  import {
12
12
  require_dist
13
13
  } from "./cli-qgm2pfpq.js";
@@ -16,14 +16,14 @@ import {
16
16
  upsertScriptByName,
17
17
  validateDefinition,
18
18
  validateScriptImports
19
- } from "./cli-3tgwnf43.js";
19
+ } from "./cli-aae6hz6a.js";
20
20
  import"./cli-epan13p1.js";
21
- import"./cli-hbv0kq6w.js";
22
- import"./cli-1th1728g.js";
21
+ import"./cli-2qts1hys.js";
22
+ import"./cli-3q5ejx9p.js";
23
23
  import"./cli-y89t4nca.js";
24
24
  import"./cli-f14fvzag.js";
25
- import"./cli-m9sxbkhm.js";
26
- import"./cli-zhjmqxzh.js";
25
+ import"./cli-zvz62chv.js";
26
+ import"./cli-9hspd3dp.js";
27
27
  import"./cli-aehm1rbq.js";
28
28
  import"./cli-9d8ntetj.js";
29
29
  import {
@@ -42,16 +42,16 @@ import {
42
42
  updateSkill,
43
43
  updateWorkflow,
44
44
  upsertSkillFiles
45
- } from "./cli-ftht3zzj.js";
46
- import"./cli-y6b6fb76.js";
47
- import"./cli-kpv03zhj.js";
45
+ } from "./cli-yab68w40.js";
46
+ import"./cli-08b07b4r.js";
47
+ import"./cli-3apbzgyk.js";
48
48
  import"./cli-e29gmdmw.js";
49
49
  import"./cli-c2mk1kgf.js";
50
50
  import"./cli-ej6gbxfb.js";
51
51
  import"./cli-sd0mxa3c.js";
52
52
  import"./cli-w5e1d1vv.js";
53
- import"./cli-w9kb3bk1.js";
54
- import"./cli-xqcq9y5e.js";
53
+ import"./cli-kjwt6hdf.js";
54
+ import"./cli-r2ap2czm.js";
55
55
  import"./cli-zf8jjwex.js";
56
56
  import {
57
57
  __toESM
@@ -2099,6 +2099,8 @@ var delegate_default = `import { z } from "zod";
2099
2099
 
2100
2100
  export const argsSchema = z.object({
2101
2101
  agentName: z.string().describe("Target agent's name (case-insensitive) — resolved to its id"),
2102
+ routingReason: z.enum(["skill", "continuity", "overflow", "human_pinned", "reroute_fault"]),
2103
+ routingNote: z.string().max(200).optional(),
2102
2104
  task: z.string().describe("Full task prompt for the target agent"),
2103
2105
  parentTaskId: z
2104
2106
  .string()
@@ -2112,7 +2114,7 @@ export const argsSchema = z.object({
2112
2114
  export default async function delegate(args: any, ctx: any) {
2113
2115
  const parsed = argsSchema.safeParse(args);
2114
2116
  if (!parsed.success) return { ok: false, error: "invalid args: " + parsed.error.message };
2115
- const { agentName, task, parentTaskId, priority, tags } = parsed.data;
2117
+ const { agentName, task, routingReason, routingNote, parentTaskId, priority, tags } = parsed.data;
2116
2118
 
2117
2119
  const res: any = await ctx.swarm.swarm_get({ includeFull: true });
2118
2120
  const agents: any[] = res?.data?.agents ?? res?.agents ?? [];
@@ -2123,6 +2125,8 @@ export default async function delegate(args: any, ctx: any) {
2123
2125
 
2124
2126
  const sent: any = await ctx.swarm.task_send({
2125
2127
  agentId: agent.id,
2128
+ routingReason,
2129
+ routingNote,
2126
2130
  task,
2127
2131
  ...(parentTaskId ? { parentTaskId } : {}),
2128
2132
  ...(priority != null ? { priority } : {}),
@@ -6440,8 +6444,106 @@ Severities: **Critical** (must fix before merge/phase close) / **Important** (sh
6440
6444
  - No slash command on purpose — Claude Code ships a built-in \`/code-review\`; this skill is invoked by name (\`desplega:code-reviewing\`) or automatically by the implementing skills.
6441
6445
  `;
6442
6446
 
6443
- // templates/skills/composio/config.json
6447
+ // templates/skills/comms/config.json
6444
6448
  var config_default10 = `{
6449
+ "category": "skills",
6450
+ "description": "Re-express something so it lands — re-explain your last reply in plain casual language, show the current topic visually (diagram, code-shape sketch, HTML artifact), do both at once, or rewrite artifact text into unambiguous ASD-STE100 English. Use when the user runs /desplega:comms, types /bro, says 'say it simpler', 'bro what', 'I don't follow', 'show me', 'draw this', 'visualize', 'disambiguate this', or 'STE100 rewrite'. Not for creative or marketing copy.",
6451
+ "displayName": "Comms",
6452
+ "kind": "skill",
6453
+ "name": "comms",
6454
+ "placeholders": [],
6455
+ "runAllSeedersCandidate": true,
6456
+ "slug": "comms",
6457
+ "systemDefault": true,
6458
+ "tags": [
6459
+ "ai-toolbox",
6460
+ "agents",
6461
+ "workflow"
6462
+ ],
6463
+ "title": "Comms",
6464
+ "version": "1.0.0"
6465
+ }
6466
+ `;
6467
+
6468
+ // templates/skills/comms/content.md
6469
+ var content_default10 = `# /comms — make it land
6470
+
6471
+ Merged from three MIT sources: [bro-skill](https://github.com/luchasarie/bro-skill) (Simpler), the local show-me skill (Visual), and [asd-ste100-skill](https://github.com/desplega-ai/asd-ste100-skill) (Precise).
6472
+
6473
+ One skill, three base modes plus a joint one. Pick from the **target** of the request, not from the wording alone.
6474
+
6475
+ ## Dispatch
6476
+
6477
+ | Target of the request | Mode |
6478
+ |---|---|
6479
+ | Your own previous message — "simpler", "bro what", "didn't get it", "rephrase" | **Simpler** |
6480
+ | A concept, flow, architecture, or change — "show me", "draw", "diagram", "what does this look like" | **Visual** |
6481
+ | Your previous message AND it describes structure (a flow, a tree, an architecture, a sequence) — or the user asks for both ("simpler, and draw it") | **Joint** |
6482
+ | Artifact text a machine or reader must parse without a back-channel — tool description, error message, prompt, doc paragraph — "disambiguate", "rewrite", "STE" | **Precise** |
6483
+
6484
+ Dispatch rules:
6485
+
6486
+ - If the request names a mode, obey it.
6487
+ - If the target is your previous message and it is plain prose, use Simpler. If it describes structure, prefer Joint — a small visual usually lands faster than more words.
6488
+ - Never mix registers: no casual flavor in Precise output, no STE flatness in Simpler output. Precise never combines with the other modes.
6489
+ - If there is nothing to re-express (no previous message, no artifact, no topic), say so in one line.
6490
+
6491
+ ## Mode: Simpler
6492
+
6493
+ Re-explain YOUR most recent assistant message like you're explaining it to a smart friend over a beer.
6494
+
6495
+ 1. **Re-explain, don't re-answer.** Never answer a new question, never add new information, never use tools. You are only re-expressing what you already said.
6496
+ 2. **Simpler, not necessarily shorter.** The goal is "impossible to misunderstand", not "fewer words". Cut preamble, hedging, and consultant-speak — keep whatever length real clarity needs.
6497
+ 3. **Facts survive verbatim.** Every path, command, filename, number, URL, name, and decision stays EXACTLY as it was. Simplify the explanation around the facts, never the facts themselves.
6498
+ 4. **Light casual flavor.** Direct and informal ("basically...", "the point is...", "ok so..."). A touch of personality — don't turn it into a meme.
6499
+ 5. **Same language.** If the original message was in another language, the simpler version stays in that language.
6500
+ 6. **Flatten structure.** Drop headers and ceremony. Tables become plain sentences. Keep a short list only if the original genuinely had multiple parts.
6501
+
6502
+ ## Mode: Visual
6503
+
6504
+ Help the user understand the current topic visually. Skip the preamble and keep prose brief. Pick the smallest view that makes the key point clear:
6505
+
6506
+ - **Pseudocode** for logic or an algorithm.
6507
+ - **Call tree** for runtime control flow.
6508
+ - **Component tree** for UI structure, including the state and module boundaries that matter.
6509
+ - **Shallow file tree** for file responsibility or a broad refactor.
6510
+ - **Mermaid** for component interaction, control flow, or data flow.
6511
+ - **\`diff\`** when the point is what changes and the surrounding shape already exists — diff the tree or pseudocode itself, not raw code. Match the diff shape to the topic.
6512
+ - **Whole code block** when most of it is new, when omitted context would hide ownership or order, or when the user needs a copyable target shape.
6513
+ - **One focused HTML file** for a visual UI, layout, state comparison, or concept too dense for Mermaid — a diagram, infographic, or short slide deck. Match the product's colors, type, spacing, and components; use real labels and data; support desktop and mobile. Then \`Bash(open path/to/comms-{description}.html)\`.
6514
+
6515
+ Place each visual next to the short text it supports. Keep only the calls, files, props, states, and boundaries needed to answer the current question. Use one shape, maybe several — never all. Concrete example shapes: \`references/visual-shapes.md\`.
6516
+
6517
+ **Delivery:** write the visual explanation to \`/tmp/YYYY-MM-DD-HHMM-comms-<topic>.md\` and open it with \`file-review\` (via Bash, \`run_in_background: true\`, \`timeout: 600000\`) — it rich-renders the markdown and lets the user leave inline comments; process their comments when the window closes. If \`file-review\` is not on PATH, put the visual in chat instead. Keep \`Bash(open ...)\` for HTML artifacts. Skip file-review only for a single small visual that reads fine in chat.
6518
+
6519
+ ## Mode: Joint
6520
+
6521
+ Simpler + Visual in one document: Simpler-mode prose with Visual-mode shapes placed right after the sentence each one supports. Follow both rule sets — casual register for the words, smallest-view discipline for the visuals. Deliver via file-review, like Visual mode.
6522
+
6523
+ ## Mode: Precise
6524
+
6525
+ Rewrite the given text under ASD-STE100 structural discipline so no reader — human or agent — can misparse it. Full rule tables, sub-mode detail, and process: \`references/ste-rules.md\`.
6526
+
6527
+ Core rules:
6528
+
6529
+ - Active voice. Simple tenses ("we received", not "we have received").
6530
+ - One instruction per sentence. ≤20 words for instructions, ≤25 for descriptions.
6531
+ - No semicolons. No phrasal verbs ("start", not "spin up"). No noun stacks over 3 words. No dropped words.
6532
+ - One name per thing — never rotate synonyms for the same referent.
6533
+ - Verb over nominalization ("analyze the log", not "perform an analysis of the log").
6534
+ - **Keep every hedge and qualifier.** "May have failed" never becomes "failed". A rewrite that changes confidence is a different claim, not a simplification.
6535
+ - Never add a fact the source did not state.
6536
+
6537
+ Two sub-modes:
6538
+
6539
+ - **Strict** — tool descriptions, error messages, prompts, procedures, safety text: every rule.
6540
+ - **STE-flavored** — READMEs, PR text, explanatory prose: structural rules in full, lexical rules advisory.
6541
+
6542
+ Output: the rewritten text and nothing else — no preamble, no mode announcement, no change summary. If you deliberately kept a longer phrasing to preserve precision, add one line prefixed \`Kept as-is:\`. When asked to "show the diff" or "explain the changes", output the before/after rule table from \`references/ste-rules.md\` instead.
6543
+ `;
6544
+
6545
+ // templates/skills/composio/config.json
6546
+ var config_default11 = `{
6445
6547
  "kind": "skill",
6446
6548
  "name": "composio",
6447
6549
  "displayName": "Composio",
@@ -6458,7 +6560,7 @@ var config_default10 = `{
6458
6560
  `;
6459
6561
 
6460
6562
  // templates/skills/composio/content.md
6461
- var content_default10 = `# Composio
6563
+ var content_default11 = `# Composio
6462
6564
 
6463
6565
  Hub skill for Composio-managed third-party app access from the swarm. Three call
6464
6566
  surfaces are available when the deployment has enabled them:
@@ -6700,7 +6802,7 @@ agent-swarm x composio POST /tools/execute/GOOGLEDRIVE_LIST_FILES \\
6700
6802
  `;
6701
6803
 
6702
6804
  // templates/skills/composio-gmail/config.json
6703
- var config_default11 = `{
6805
+ var config_default12 = `{
6704
6806
  "kind": "skill",
6705
6807
  "name": "composio-gmail",
6706
6808
  "displayName": "Composio Gmail",
@@ -6717,10 +6819,10 @@ var config_default11 = `{
6717
6819
  `;
6718
6820
 
6719
6821
  // templates/skills/composio-gmail/content.md
6720
- var content_default11 = '# Composio · Gmail\n\nToolkit slug: **`gmail`**. Read the [[composio]] hub first for the call model\n(`agent-swarm x composio …`, user_id, connected accounts, the 4302 gotcha).\nTool `arguments` go inside the request body; `user_id` defaults to `"me"` (the\nauthorized account) — you usually don\'t need to set it.\n\n```bash\n# Direct execute (reliable path — pin the ACTIVE ca_… from the hub Recipe B)\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `gmail` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GMAIL_FETCH_EMAILS` | List/search emails | `query`, `max_results` (def **1** — set it!), `include_payload` (def true), `verbose` (def true), `ids_only`, `label_ids`, `page_token` |\n| `GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID` | Full single message | `message_id`, `include_payload` |\n| `GMAIL_FETCH_MESSAGE_BY_THREAD_ID` | All messages in a thread | `thread_id` |\n| `GMAIL_LIST_THREADS` | List threads | `query`, `max_results`, `page_token` |\n| `GMAIL_SEND_EMAIL` | Send | `recipient_email`, `subject`, `body`, `is_html` (def false), `cc`, `bcc`, `extra_recipients`, `attachment` |\n| `GMAIL_REPLY_TO_THREAD` | Reply in-thread | `thread_id`, `message_body`, `recipient_email` |\n| `GMAIL_CREATE_EMAIL_DRAFT` / `GMAIL_SEND_DRAFT` | Draft then send | `body`, `subject`, `recipient_email` / `draft_id` |\n| `GMAIL_GET_PROFILE` | Whose mailbox is this? | — |\n| `GMAIL_LIST_LABELS` / `GMAIL_CREATE_LABEL` / `GMAIL_ADD_LABEL_TO_EMAIL` | Labels | `message_id`, `label_ids` (use LIST_LABELS for custom IDs) |\n| `GMAIL_GET_CONTACTS` / `GMAIL_SEARCH_PEOPLE` | Contacts | `query` |\n| `GMAIL_GET_ATTACHMENT` | Download attachment | `message_id`, `attachment_id` |\n\nFull set: 63 tools — list with\n`agent-swarm x composio GET "/tools?toolkit_slug=gmail&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\nAvoid the ones marked Deprecated (`GMAIL_LIST_MESSAGES`, `GMAIL_REMOVE_LABEL`).\n\n## Read recipe (metadata-first)\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_FETCH_EMAILS \\\n --body \'{"connected_account_id":"ca_…","arguments":{"max_results":5,"include_payload":false,"verbose":false}}\'\n```\n- **Always set `max_results`** — the default is `1`.\n- Use Gmail `query` syntax: `"is:unread"`, `"from:foo@bar.com newer_than:7d"`,\n `"subject:invoice has:attachment"`.\n- Keep `include_payload:false` + `verbose:false` unless the user needs full bodies\n (token-heavy). Use `ids_only:true` for the cheapest listing.\n\n## Send recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_SEND_EMAIL \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "recipient_email":"someone@example.com",\n "subject":"Hello",\n "body":"<p>Hi there</p>",\n "is_html":true,\n "cc":["cc@example.com"]\n }}\'\n```\n- Set `is_html:true` when `body` contains HTML, otherwise it sends as literal text.\n- `recipient_email` is the primary; add more via `extra_recipients` / `cc` / `bcc`.\n- **Sending is a write action** — only do it when the task explicitly asks.\n\n## Reply in a thread\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_REPLY_TO_THREAD \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "thread_id":"<thread_id>","recipient_email":"someone@example.com","message_body":"thanks!"\n }}\'\n```\n\n## Gotchas\n\n- Default `max_results` is `1` — forgetting it makes "list my emails" return a\n single message.\n- Bodies/attachments are token-heavy and may contain secrets — default to\n metadata; the secret-scrubber doesn\'t run on Composio tool output.\n- If you get `ToolRouterV2_NoActiveConnection`, switch to direct execute with the\n pinned `connected_account_id` (hub Gotchas).\n';
6822
+ var content_default12 = '# Composio · Gmail\n\nToolkit slug: **`gmail`**. Read the [[composio]] hub first for the call model\n(`agent-swarm x composio …`, user_id, connected accounts, the 4302 gotcha).\nTool `arguments` go inside the request body; `user_id` defaults to `"me"` (the\nauthorized account) — you usually don\'t need to set it.\n\n```bash\n# Direct execute (reliable path — pin the ACTIVE ca_… from the hub Recipe B)\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `gmail` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GMAIL_FETCH_EMAILS` | List/search emails | `query`, `max_results` (def **1** — set it!), `include_payload` (def true), `verbose` (def true), `ids_only`, `label_ids`, `page_token` |\n| `GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID` | Full single message | `message_id`, `include_payload` |\n| `GMAIL_FETCH_MESSAGE_BY_THREAD_ID` | All messages in a thread | `thread_id` |\n| `GMAIL_LIST_THREADS` | List threads | `query`, `max_results`, `page_token` |\n| `GMAIL_SEND_EMAIL` | Send | `recipient_email`, `subject`, `body`, `is_html` (def false), `cc`, `bcc`, `extra_recipients`, `attachment` |\n| `GMAIL_REPLY_TO_THREAD` | Reply in-thread | `thread_id`, `message_body`, `recipient_email` |\n| `GMAIL_CREATE_EMAIL_DRAFT` / `GMAIL_SEND_DRAFT` | Draft then send | `body`, `subject`, `recipient_email` / `draft_id` |\n| `GMAIL_GET_PROFILE` | Whose mailbox is this? | — |\n| `GMAIL_LIST_LABELS` / `GMAIL_CREATE_LABEL` / `GMAIL_ADD_LABEL_TO_EMAIL` | Labels | `message_id`, `label_ids` (use LIST_LABELS for custom IDs) |\n| `GMAIL_GET_CONTACTS` / `GMAIL_SEARCH_PEOPLE` | Contacts | `query` |\n| `GMAIL_GET_ATTACHMENT` | Download attachment | `message_id`, `attachment_id` |\n\nFull set: 63 tools — list with\n`agent-swarm x composio GET "/tools?toolkit_slug=gmail&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\nAvoid the ones marked Deprecated (`GMAIL_LIST_MESSAGES`, `GMAIL_REMOVE_LABEL`).\n\n## Read recipe (metadata-first)\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_FETCH_EMAILS \\\n --body \'{"connected_account_id":"ca_…","arguments":{"max_results":5,"include_payload":false,"verbose":false}}\'\n```\n- **Always set `max_results`** — the default is `1`.\n- Use Gmail `query` syntax: `"is:unread"`, `"from:foo@bar.com newer_than:7d"`,\n `"subject:invoice has:attachment"`.\n- Keep `include_payload:false` + `verbose:false` unless the user needs full bodies\n (token-heavy). Use `ids_only:true` for the cheapest listing.\n\n## Send recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_SEND_EMAIL \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "recipient_email":"someone@example.com",\n "subject":"Hello",\n "body":"<p>Hi there</p>",\n "is_html":true,\n "cc":["cc@example.com"]\n }}\'\n```\n- Set `is_html:true` when `body` contains HTML, otherwise it sends as literal text.\n- `recipient_email` is the primary; add more via `extra_recipients` / `cc` / `bcc`.\n- **Sending is a write action** — only do it when the task explicitly asks.\n\n## Reply in a thread\n\n```bash\nagent-swarm x composio POST /tools/execute/GMAIL_REPLY_TO_THREAD \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "thread_id":"<thread_id>","recipient_email":"someone@example.com","message_body":"thanks!"\n }}\'\n```\n\n## Gotchas\n\n- Default `max_results` is `1` — forgetting it makes "list my emails" return a\n single message.\n- Bodies/attachments are token-heavy and may contain secrets — default to\n metadata; the secret-scrubber doesn\'t run on Composio tool output.\n- If you get `ToolRouterV2_NoActiveConnection`, switch to direct execute with the\n pinned `connected_account_id` (hub Gotchas).\n';
6721
6823
 
6722
6824
  // templates/skills/composio-google-calendar/config.json
6723
- var config_default12 = `{
6825
+ var config_default13 = `{
6724
6826
  "kind": "skill",
6725
6827
  "name": "composio-google-calendar",
6726
6828
  "displayName": "Composio Google Calendar",
@@ -6737,10 +6839,10 @@ var config_default12 = `{
6737
6839
  `;
6738
6840
 
6739
6841
  // templates/skills/composio-google-calendar/content.md
6740
- var content_default12 = '# Composio · Google Calendar\n\nToolkit slug: **`googlecalendar`**. Read the [[composio]] hub first for the call\nmodel. `calendarId` defaults to `"primary"`. Times are **RFC3339**\n(`2026-06-02T15:00:00Z` or with offset).\n\n```bash\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `googlecalendar` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GOOGLECALENDAR_EVENTS_LIST` | List events on a calendar | `calendarId` (def `primary`), **`timeMin`**, `timeMax`, `singleEvents`, `orderBy`, `q`, `maxResults`, `timeZone`, `pageToken` |\n| `GOOGLECALENDAR_EVENTS_LIST_ALL_CALENDARS` | List across all calendars | `timeMin`, `timeMax`, `singleEvents`, `orderBy` |\n| `GOOGLECALENDAR_FIND_EVENT` | Search for an event | `query`, `timeMin`, `timeMax` |\n| `GOOGLECALENDAR_EVENTS_GET` | One event by id | `calendar_id`, `event_id` |\n| `GOOGLECALENDAR_CREATE_EVENT` | Create event | **`start_datetime`** (required), `end_datetime` / `event_duration_minutes` (def 30), `summary`, `description`, `location`, `attendees`, `timezone`, `calendar_id`, `send_updates`, `create_meeting_room` (def true) |\n| `GOOGLECALENDAR_QUICK_ADD` | NL event ("lunch tmrw 1pm") | `calendar_id`, `text` |\n| `GOOGLECALENDAR_UPDATE_EVENT` / `GOOGLECALENDAR_PATCH_EVENT` | Edit event | `calendar_id`, `event_id`, fields |\n| `GOOGLECALENDAR_DELETE_EVENT` | Delete | `calendar_id`, `event_id` |\n| `GOOGLECALENDAR_FIND_FREE_SLOTS` | Free slots | `items` (def `["primary"]`), `time_min`, `time_max`, `timezone` |\n| `GOOGLECALENDAR_LIST_CALENDARS` | List the user\'s calendars | — |\n| `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` | Server "now" (use for timeMin) | `timezone` |\n\nFull set: 48 tools — `agent-swarm x composio GET "/tools?toolkit_slug=googlecalendar&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\n\n## ⚠️ The "events from a year ago" trap\n\n`GOOGLECALENDAR_EVENTS_LIST` has **no default `timeMin`**. Calling it with no time\nwindow returns old/arbitrary events (this is exactly how "what\'s on my calendar?"\ncame back with stuff from a year ago). To get **upcoming** events you MUST set the\nwindow and ordering explicitly:\n\n```bash\nNOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)\nagent-swarm x composio POST /tools/execute/GOOGLECALENDAR_EVENTS_LIST \\\n --body "{\\"connected_account_id\\":\\"ca_…\\",\\"arguments\\":{\n \\"calendarId\\":\\"primary\\",\n \\"timeMin\\":\\"$NOW\\",\n \\"singleEvents\\":true,\n \\"orderBy\\":\\"startTime\\",\n \\"maxResults\\":10\n }}"\n```\n- `timeMin` = now (or the start of the window you care about).\n- `singleEvents:true` expands recurring events into individual instances — required\n for `orderBy:"startTime"` to be valid.\n- Add `timeMax` to bound the window (e.g. next 7 days).\n- For "today/this week" prefer computing `timeMin`/`timeMax` locally, or call\n `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` first to anchor to the server\'s clock.\n\n## Create an event\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLECALENDAR_CREATE_EVENT \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "summary":"Project planning",\n "start_datetime":"2026-06-05T15:00:00+02:00",\n "event_duration_minutes":30,\n "timezone":"Europe/Madrid",\n "attendees":["someone@example.com"],\n "send_updates":"all"\n }}\'\n```\n- Either `end_datetime` OR `event_duration_minutes` (default 30).\n- `create_meeting_room` defaults true (adds Google Meet) — set false to skip.\n- Create/update/delete are **write actions** — only on explicit request.\n\n## Gotchas\n\n- The year-ago trap above is the #1 issue. `timeMin` is not optional in practice.\n- `orderBy:"startTime"` requires `singleEvents:true` or the API errors.\n- Output uses the event\'s own timezone; pass `timeZone` to normalize display.\n';
6842
+ var content_default13 = '# Composio · Google Calendar\n\nToolkit slug: **`googlecalendar`**. Read the [[composio]] hub first for the call\nmodel. `calendarId` defaults to `"primary"`. Times are **RFC3339**\n(`2026-06-02T15:00:00Z` or with offset).\n\n```bash\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `googlecalendar` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GOOGLECALENDAR_EVENTS_LIST` | List events on a calendar | `calendarId` (def `primary`), **`timeMin`**, `timeMax`, `singleEvents`, `orderBy`, `q`, `maxResults`, `timeZone`, `pageToken` |\n| `GOOGLECALENDAR_EVENTS_LIST_ALL_CALENDARS` | List across all calendars | `timeMin`, `timeMax`, `singleEvents`, `orderBy` |\n| `GOOGLECALENDAR_FIND_EVENT` | Search for an event | `query`, `timeMin`, `timeMax` |\n| `GOOGLECALENDAR_EVENTS_GET` | One event by id | `calendar_id`, `event_id` |\n| `GOOGLECALENDAR_CREATE_EVENT` | Create event | **`start_datetime`** (required), `end_datetime` / `event_duration_minutes` (def 30), `summary`, `description`, `location`, `attendees`, `timezone`, `calendar_id`, `send_updates`, `create_meeting_room` (def true) |\n| `GOOGLECALENDAR_QUICK_ADD` | NL event ("lunch tmrw 1pm") | `calendar_id`, `text` |\n| `GOOGLECALENDAR_UPDATE_EVENT` / `GOOGLECALENDAR_PATCH_EVENT` | Edit event | `calendar_id`, `event_id`, fields |\n| `GOOGLECALENDAR_DELETE_EVENT` | Delete | `calendar_id`, `event_id` |\n| `GOOGLECALENDAR_FIND_FREE_SLOTS` | Free slots | `items` (def `["primary"]`), `time_min`, `time_max`, `timezone` |\n| `GOOGLECALENDAR_LIST_CALENDARS` | List the user\'s calendars | — |\n| `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` | Server "now" (use for timeMin) | `timezone` |\n\nFull set: 48 tools — `agent-swarm x composio GET "/tools?toolkit_slug=googlecalendar&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\n\n## ⚠️ The "events from a year ago" trap\n\n`GOOGLECALENDAR_EVENTS_LIST` has **no default `timeMin`**. Calling it with no time\nwindow returns old/arbitrary events (this is exactly how "what\'s on my calendar?"\ncame back with stuff from a year ago). To get **upcoming** events you MUST set the\nwindow and ordering explicitly:\n\n```bash\nNOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)\nagent-swarm x composio POST /tools/execute/GOOGLECALENDAR_EVENTS_LIST \\\n --body "{\\"connected_account_id\\":\\"ca_…\\",\\"arguments\\":{\n \\"calendarId\\":\\"primary\\",\n \\"timeMin\\":\\"$NOW\\",\n \\"singleEvents\\":true,\n \\"orderBy\\":\\"startTime\\",\n \\"maxResults\\":10\n }}"\n```\n- `timeMin` = now (or the start of the window you care about).\n- `singleEvents:true` expands recurring events into individual instances — required\n for `orderBy:"startTime"` to be valid.\n- Add `timeMax` to bound the window (e.g. next 7 days).\n- For "today/this week" prefer computing `timeMin`/`timeMax` locally, or call\n `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` first to anchor to the server\'s clock.\n\n## Create an event\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLECALENDAR_CREATE_EVENT \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "summary":"Project planning",\n "start_datetime":"2026-06-05T15:00:00+02:00",\n "event_duration_minutes":30,\n "timezone":"Europe/Madrid",\n "attendees":["someone@example.com"],\n "send_updates":"all"\n }}\'\n```\n- Either `end_datetime` OR `event_duration_minutes` (default 30).\n- `create_meeting_room` defaults true (adds Google Meet) — set false to skip.\n- Create/update/delete are **write actions** — only on explicit request.\n\n## Gotchas\n\n- The year-ago trap above is the #1 issue. `timeMin` is not optional in practice.\n- `orderBy:"startTime"` requires `singleEvents:true` or the API errors.\n- Output uses the event\'s own timezone; pass `timeZone` to normalize display.\n';
6741
6843
 
6742
6844
  // templates/skills/composio-google-docs/config.json
6743
- var config_default13 = `{
6845
+ var config_default14 = `{
6744
6846
  "kind": "skill",
6745
6847
  "name": "composio-google-docs",
6746
6848
  "displayName": "Composio Google Docs",
@@ -6757,10 +6859,10 @@ var config_default13 = `{
6757
6859
  `;
6758
6860
 
6759
6861
  // templates/skills/composio-google-docs/content.md
6760
- var content_default13 = '# Composio · Google Docs\n\nToolkit slug: **`googledocs`**. Read the [[composio]] hub first for the call model.\nA document is identified by its `document_id` (the id in the Docs URL).\n\n```bash\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `googledocs` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GOOGLEDOCS_SEARCH_DOCUMENTS` | Find docs (Drive search) | `query`, `max_results` (def 10), `order_by` (def `modifiedTime desc`), `modified_after`, `created_after`, `starred_only`, `shared_with_me`, `response_detail` (def `minimal`) |\n| `GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT` | Read doc as text | **`document_id`**, `include_tables` (def true), `include_headers`, `include_footers`, `include_footnotes`, `include_tabs_content` |\n| `GOOGLEDOCS_GET_DOCUMENT_BY_ID` | Full structured doc JSON | `document_id` |\n| `GOOGLEDOCS_CREATE_DOCUMENT` | Create blank/with text | `title`, `text` |\n| `GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN` | Create from markdown | **`title`**, `markdown_text`, `image_assets` |\n| `GOOGLEDOCS_UPDATE_DOCUMENT_MARKDOWN` | Replace body with markdown | `document_id`, `markdown_text` |\n| `GOOGLEDOCS_INSERT_TEXT_ACTION` | Insert text at index | `document_id`, `text`, `index` |\n| `GOOGLEDOCS_REPLACE_ALL_TEXT` | Find & replace | `document_id`, `find`, `replace` |\n| `GOOGLEDOCS_COPY_DOCUMENT` | Duplicate a doc | `document_id`, `title` |\n| `GOOGLEDOCS_EXPORT_DOCUMENT_AS_PDF` | Export to PDF | `document_id` |\n\nFull set: 35 tools — `agent-swarm x composio GET "/tools?toolkit_slug=googledocs&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\nPrefer the `*_MARKDOWN` create/update tools for authoring; the granular\n`INSERT_*`/`DELETE_*`/table tools are for surgical structural edits.\n\n## Search recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_SEARCH_DOCUMENTS \\\n --body \'{"connected_account_id":"ca_…","arguments":{"query":"workshop","max_results":5}}\'\n# → results under .data.files[] (id, name, modifiedTime …)\n```\n- Results are Drive file entries at **`.data.files[]`** — grab `.id` to read.\n- `order_by` defaults to `modifiedTime desc` (most recent first).\n- Use `modified_after` / `shared_with_me` to narrow.\n\n## Read recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT \\\n --body \'{"connected_account_id":"ca_…","arguments":{"document_id":"<id>","include_tables":true}}\'\n```\nUse `GET_DOCUMENT_PLAINTEXT` for reading content; only reach for\n`GET_DOCUMENT_BY_ID` when you need the structured JSON (styles, indices) for an\nedit.\n\n## Create-from-markdown recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "title":"Weekly updates","markdown_text":"# Heading\\n\\n- point one\\n- point two"\n }}\'\n```\n\n## Google Doc to agent-fs\n\n1. Read the source with `GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT` and retain its\n returned title and display URL as provenance.\n2. Write the converted content to your own agent-fs namespace with a short\n provenance header naming the source document and import method.\n3. Resolve the destination org and drive from the environment or\n `agent-fs stat <path> --json`; the `artifacts` skill documents the canonical\n storage and share-link workflow. Never copy org or drive IDs from an example.\n4. Read the stored file back and assert several markers: the title, a middle\n phrase, and the final sentence. A successful byte-count response alone does\n not prove fidelity.\n\nPlaintext is intentionally lossy. Inline images may become bare `[IMAGE]`\nmarkers, and headings may be flattened into adjacent paragraphs. If those\nfeatures matter, use `GOOGLEDOCS_GET_DOCUMENT_BY_ID` for structured JSON or a\nGoogle Drive export, then preserve or reconstruct the structure explicitly.\nThere is no `GET_DOCUMENT_MARKDOWN` tool; markdown exists on create/update, not\non read.\n\n## Gotchas\n\n- Search returns Drive metadata, not document content — do a second\n `GET_DOCUMENT_PLAINTEXT` call with the `.id` to read.\n- Doc bodies can be long/token-heavy and may contain secrets — read only what you\n need (`include_headers/footers/footnotes` default off for a reason).\n- Create/update/replace are **write actions** — only on explicit request.\n';
6862
+ var content_default14 = '# Composio · Google Docs\n\nToolkit slug: **`googledocs`**. Read the [[composio]] hub first for the call model.\nA document is identified by its `document_id` (the id in the Docs URL).\n\n```bash\nagent-swarm x composio POST /tools/execute/<SLUG> \\\n --body \'{"user_id":"<connected-account-email>","connected_account_id":"<active-connected-account-id>","arguments":{ … }}\'\n```\n\nFollow the hub\'s **Resolve the user and connected account** procedure, then\nselect the resolved user\'s `googledocs` account whose status is `ACTIVE`.\n\n## Headline tools\n\n| Slug | What | Key args |\n|---|---|---|\n| `GOOGLEDOCS_SEARCH_DOCUMENTS` | Find docs (Drive search) | `query`, `max_results` (def 10), `order_by` (def `modifiedTime desc`), `modified_after`, `created_after`, `starred_only`, `shared_with_me`, `response_detail` (def `minimal`) |\n| `GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT` | Read doc as text | **`document_id`**, `include_tables` (def true), `include_headers`, `include_footers`, `include_footnotes`, `include_tabs_content` |\n| `GOOGLEDOCS_GET_DOCUMENT_BY_ID` | Full structured doc JSON | `document_id` |\n| `GOOGLEDOCS_CREATE_DOCUMENT` | Create blank/with text | `title`, `text` |\n| `GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN` | Create from markdown | **`title`**, `markdown_text`, `image_assets` |\n| `GOOGLEDOCS_UPDATE_DOCUMENT_MARKDOWN` | Replace body with markdown | `document_id`, `markdown_text` |\n| `GOOGLEDOCS_INSERT_TEXT_ACTION` | Insert text at index | `document_id`, `text`, `index` |\n| `GOOGLEDOCS_REPLACE_ALL_TEXT` | Find & replace | `document_id`, `find`, `replace` |\n| `GOOGLEDOCS_COPY_DOCUMENT` | Duplicate a doc | `document_id`, `title` |\n| `GOOGLEDOCS_EXPORT_DOCUMENT_AS_PDF` | Export to PDF | `document_id` |\n\nFull set: 35 tools — `agent-swarm x composio GET "/tools?toolkit_slug=googledocs&limit=100" | jq -r \'.items[]|"\\(.slug)\\t\\(.name)"\'`.\nPrefer the `*_MARKDOWN` create/update tools for authoring; the granular\n`INSERT_*`/`DELETE_*`/table tools are for surgical structural edits.\n\n## Search recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_SEARCH_DOCUMENTS \\\n --body \'{"connected_account_id":"ca_…","arguments":{"query":"workshop","max_results":5}}\'\n# → results under .data.files[] (id, name, modifiedTime …)\n```\n- Results are Drive file entries at **`.data.files[]`** — grab `.id` to read.\n- `order_by` defaults to `modifiedTime desc` (most recent first).\n- Use `modified_after` / `shared_with_me` to narrow.\n\n## Read recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT \\\n --body \'{"connected_account_id":"ca_…","arguments":{"document_id":"<id>","include_tables":true}}\'\n```\nUse `GET_DOCUMENT_PLAINTEXT` for reading content; only reach for\n`GET_DOCUMENT_BY_ID` when you need the structured JSON (styles, indices) for an\nedit.\n\n## Create-from-markdown recipe\n\n```bash\nagent-swarm x composio POST /tools/execute/GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN \\\n --body \'{"connected_account_id":"ca_…","arguments":{\n "title":"Weekly updates","markdown_text":"# Heading\\n\\n- point one\\n- point two"\n }}\'\n```\n\n## Google Doc to agent-fs\n\n1. Read the source with `GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT` and retain its\n returned title and display URL as provenance.\n2. Write the converted content to your own agent-fs namespace with a short\n provenance header naming the source document and import method.\n3. Resolve the destination org and drive from the environment or\n `agent-fs stat <path> --json`; the `artifacts` skill documents the canonical\n storage and share-link workflow. Never copy org or drive IDs from an example.\n4. Read the stored file back and assert several markers: the title, a middle\n phrase, and the final sentence. A successful byte-count response alone does\n not prove fidelity.\n\nPlaintext is intentionally lossy. Inline images may become bare `[IMAGE]`\nmarkers, and headings may be flattened into adjacent paragraphs. If those\nfeatures matter, use `GOOGLEDOCS_GET_DOCUMENT_BY_ID` for structured JSON or a\nGoogle Drive export, then preserve or reconstruct the structure explicitly.\nThere is no `GET_DOCUMENT_MARKDOWN` tool; markdown exists on create/update, not\non read.\n\n## Gotchas\n\n- Search returns Drive metadata, not document content — do a second\n `GET_DOCUMENT_PLAINTEXT` call with the `.id` to read.\n- Doc bodies can be long/token-heavy and may contain secrets — read only what you\n need (`include_headers/footers/footnotes` default off for a reason).\n- Create/update/replace are **write actions** — only on explicit request.\n';
6761
6863
 
6762
6864
  // templates/skills/db-query-guidance/config.json
6763
- var config_default14 = `{
6865
+ var config_default15 = `{
6764
6866
  "kind": "skill",
6765
6867
  "name": "db-query-guidance",
6766
6868
  "displayName": "DB Query Guidance",
@@ -6777,7 +6879,7 @@ var config_default14 = `{
6777
6879
  `;
6778
6880
 
6779
6881
  // templates/skills/db-query-guidance/content.md
6780
- var content_default14 = `# DB Query Guidance
6882
+ var content_default15 = `# DB Query Guidance
6781
6883
 
6782
6884
  The swarm database is SQLite, reachable read-only through the \`db-query\` MCP
6783
6885
  tool and the \`POST /api/db-query\` HTTP route (same executor underneath).
@@ -6837,7 +6939,7 @@ returned \`rows\` are capped — compare the two to detect truncation.
6837
6939
  `;
6838
6940
 
6839
6941
  // templates/skills/delegate-work/config.json
6840
- var config_default15 = `{
6942
+ var config_default16 = `{
6841
6943
  "category": "skills",
6842
6944
  "description": "Executor routing policy for ALL delegated work — pick the right model for every sub-agent and the right Codex variant for every implementation slice. Use whenever you are about to spawn a sub-agent/Task (research, review, QA, UI, search), whenever a desplega skill (implement-plan, v-implement, run-phase, run-step, research) is choosing executors for phases/steps, or when the user says \\"implement with codex\\", \\"delegate this\\", \\"which model should do this\\", or similar. Supersedes codex-implement (its worktree/exec mechanics live here).",
6843
6945
  "displayName": "Delegate Work",
@@ -6858,10 +6960,10 @@ var config_default15 = `{
6858
6960
  `;
6859
6961
 
6860
6962
  // templates/skills/delegate-work/content.md
6861
- var content_default15 = "# delegate-work\n\nClaude (Fable 5) is the **orchestrator**: it thinks, designs, schedules, reviews, commits, and talks to the user. Everything else is delegated to the **cheapest executor that clears the quality bar**. Codex types; Claude judges.\n\nThis skill applies in BOTH modes:\n- **Ad-hoc**: any time you'd spawn an `Agent`/Task, pick its model from the matrix below instead of the default.\n- **Plan execution**: inside `desplega:implementing` / `desplega:v-implementing` (and `run-phase` / `run-step`), keep ALL of their orchestration semantics (autonomy modes, checkpoints, plan bookkeeping, commit strategy) — only the executor choice changes: instead of default phase-running/step-running sub-agents, route each phase/step per the matrix.\n\n## The matrix\n\nRankings 1–10, higher = better. Cost = subscription quota burned — both Claude and Codex run on flat-rate subs, so higher = lighter on that plan's rate limits (Fable burns the Claude quota fastest; Codex quota is comparatively abundant). Code = how hard a coding problem you can hand it unsupervised. Taste = UI/UX, code quality, API design, copy.\n\n| executor | cost | code | taste | speed | role |\n|-------------------------|------|------|-------|-------|------|\n| fable-5 | 2 | 9 | 9 | 4 | orchestration, deep reasoning, architecture, final judgment |\n| opus-5 | 4 | 7 | 8 | 5 | UI implementation, complex review, browser E2E |\n| sonnet-5 | 5 | 5 | 7 | 7 | routine review, API QA agents, standard sub-agent work |\n| haiku-4.5 | 9 | 3 | 4 | 9 | search, locate, digest, mechanical sweeps — NEVER for writing code |\n| codex gpt-5.6-sol | 8 | 10 | 6 | 6 | hard/long-horizon implementation, gnarly debugging |\n| codex gpt-5.6-terra | 9 | 8 | 5 | 8 | everyday implementation from a frozen spec |\n| codex gpt-5.6-luna | 10 | 6 | 4 | 10 | mechanical code: migrations, renames, test fills, dep bumps |\n\n(Context for the Codex rows, from the 5.6 release: Sol-max is SOTA on the AA Coding Agent Index, ~3 pts above Fable 5 at ~⅓ the cost; Terra lands just above Fable 5; Luna outperforms Opus 5 — each in ~⅓ the time. Claude keeps the edge on taste and judgment; that's why review and UI stay Claude-side.)\n\n**Defaults, not limits.** Standing permission to override: if a cheaper executor's output doesn't meet the bar, rerun or redo with a smarter one without asking. Judge the output, not the price tag. Escalating costs less than shipping mediocre work.\n\n## Routing table\n\n| work | executor | how |\n|------|----------|-----|\n| orchestration, deep reasoning, spec-writing, architecture | **Fable 5** | stay in the main session; never delegated |\n| UI implementation (pages, components, styles, UX flows) | **Opus 5** | `Agent` with `model: \"opus\"`, background |\n| code review — routine / per-phase | **Sonnet 5** | `Agent` with `model: \"sonnet\"` |\n| code review — complex, security-sensitive, cross-cutting, or reviewing Sol output | **Opus 5** (+ optional parallel Codex review, see Verify ↓) | `Agent` with `model: \"opus\"` |\n| API-level QA / E2E agents, plan-verification agents | **Sonnet 5** | `Agent` with `model: \"sonnet\"` |\n| browser E2E / driving the real UI | **Opus 5** | `Agent` with `model: \"opus\"`; use a browser-automation agent for local URLs unless stated differently |\n| search, locate, pattern-find, doc digests | **Haiku 4.5** | `Explore` / locator agents with `model: \"haiku\"` |\n| bulk mechanical call-sequences (~10+ similar tool/API calls, any fan-out over a list) | **a script** | `desplega:script-builder` — cheapest executor of all; one summary re-enters context, raw payloads never do |\n| raw code implementation from a frozen spec | **Codex** | variant by scope ↓, via `codex-exec.sh` |\n\n**Codex variant by scope** (effort in parentheses):\n\n- `gpt-5.6-luna` (`medium`→`high`) — mechanical & bounded: renames, mechanical migrations, test/coverage fills, CI fixes, dep bumps, single-file bug fix with known repro.\n- `gpt-5.6-terra` (`high`) — the default for a well-specified phase/step: single vertical slice, clear verification, few unknowns.\n- `gpt-5.6-sol` (`high`; `xhigh` for hard, `max` only for the gnarliest long-horizon work) — multi-file backend phases, cross-package changes, subtle debugging, anything where the spec has known-unknowns.\n- Never use Codex `ultra` (its own multi-agent mode) — parallelism is the orchestrator's job, via worktrees.\n\n**Keep in Claude regardless of matrix**: tasks where writing the spec IS the work (ambiguity = design); tiny edits (<~20 lines) where delegation overhead loses; anything needing session tools (MCP, browser, secrets); destructive/irreversible ops, pushes, GitHub mutations; judging delegated output — executors may contribute reviews, but the join and final verdict are never delegated, never skipped.\n\nHeuristic: if the prompt reads as a work order → delegate; if writing it forces decisions → it's design, keep it.\n\n## Workflow-tool orchestration\n\nWhen the harness exposes the `Workflow` tool AND the user has opted in (the desplega skills ask during setup — that answer IS the explicit opt-in the tool requires), fan-out runs as a workflow script instead of ad-hoc `Agent` calls. The matrix above still routes every executor; it just maps onto `agent()` opts:\n\n- **Model tiers** → `model: \"haiku\" | \"sonnet\" | \"opus\"`; omit `model` for work that must stay at orchestrator quality (it inherits the session model). `effort` follows the same logic: `low` for mechanical stages, higher tiers only for verify/judge stages.\n- **Named agents** (locators, analyzers, pattern-finders) → the `agentType` opt.\n- **Codex rows** still apply inside a workflow: an `agent()` can drive `codex-exec.sh` in its own worktree. Plan bookkeeping and commits stay orchestrator-side, as always.\n- **The join stays Claude-side**: the workflow returns data (findings, reports, file lists) — reading the diff, deduping findings, and the final verdict happen in the main session, never inside the script.\n- **Pause points sit between Workflow invocations** — one workflow per wave/stage, orchestrator judges and checkpoints in between. Never bury a human checkpoint inside a script.\n\n## Codex: the one primitive\n\n> **Prerequisite**: the `codex` CLI on PATH, authenticated, with access to the gpt-5.6 models. If it's missing, the Codex rows of the matrix are unavailable — route implementation work to Claude executors instead (Opus for hard slices, Sonnet for routine ones) and tell the user why.\n\n`bash ~/.claude/skills/delegate-work/scripts/codex-exec.sh`\n\n```\nprintf '%s' \"$PROMPT\" | bash ~/.claude/skills/delegate-work/scripts/codex-exec.sh -m gpt-5.6-terra -e high \\\n -C <workdir> -o <report-file> -l <log-file>\n```\n\n- `-m` model / `-e` reasoning effort — from the scope table above (script defaults: `gpt-5.6-sol` + `high`; env overrides `CODEX_MODEL`/`CODEX_EFFORT` still work).\n- `-C` working root — a **git worktree** for parallel work, repo root for sequential.\n- `-o` report file — Codex's final message; read THIS back, not the log.\n- `-l` log file — for monitoring only; keep raw logs out of the session.\n- Sandbox defaults to `workspace-write` (edits inside `-C`, reads anywhere). `CODEX_BYPASS=1` only when a task genuinely must write outside its worktree.\n- **Always background** (`run_in_background: true`, `timeout: 600000`).\n- **Prompt via stdin/temp file, never inline arg** — the inline form can silently drop the prompt and hang on stdin (observed). A ~39-byte log means it hung.\n- Follow-up fixes: `codex exec resume --last` from the same dir is cheaper than a fresh run and keeps its context — use for review-fix rounds and crash recovery (\"assess partial state via git status/diff first; don't redo, don't trust\").\n- After **2 failed rounds** on the same task: stop delegating, take over directly (or escalate the model one rung).\n\n## Codex prompt contract\n\nCodex starts with zero session context. Every prompt: goal, exact repo/paths (absolute plan path in the MAIN repo — worktrees don't contain untracked `thoughts/`), scope fence (\"ONLY Phase N / step-N, don't touch X\"), non-goals, verification commands to run, the standards line (\"smallest diff that solves the problem; no speculative abstractions\" — per `desplega:engineering-standards`), and the report shape (status completed/blocked/failed, files changed, verification output, notes). Codex must NOT edit the plan file — the orchestrator owns all plan bookkeeping.\n\n## Worktrees & parallelism\n\n**Always clean up after use** — the moment a slice is merged or abandoned: `git worktree remove <path>` + `git branch -d codex/<slug>`. Never leave stragglers; before ending a session, `git worktree list` must show only the main tree (and any worktree the user created themselves).\n\n- Sequential (linear plan): repo root or one dedicated worktree; one phase at a time; orchestrator verifies, ticks boxes, commits `[Phase N] <name>`, honors checkpoints.\n- Parallel (DAG plan / independent slices): one worktree per slice — `git worktree add -b codex/<slug> <path> <integration-branch>`; fan out one Codex per ready step; merge back sequentially with `--no-ff`; remove worktree + branch after merge.\n- **`bun install` (or equivalent) in every fresh worktree BEFORE launching** — a deps-less sandbox \"verifies\" nothing and ships unproven code.\n- Codex cannot `git commit` inside linked worktrees (index lives under the main repo's `.git` → EPERM). Tell it not to commit; the orchestrator commits.\n- Parallel Claude agents sharing ONE tree need strict file fences: commit only their own paths, never `git add -A`.\n\n## Verify (Claude judges, always)\n\n- Read the full diff and judge it like a contributor PR; Codex/sub-agent claims are advisory.\n- Re-run the phase/step verification commands yourself when the report is ambiguous.\n- After web service-layer changes: probe the running dev server — unit tests miss RSC import crashes.\n- UI touched by anything non-Opus (or by Codex at all): hands-on polish pass — drive the real UI, screenshot, fix spacing/copy/empty-states yourself.\n- Then the per-phase review round before closing the phase: `desplega:code-reviewing` — two axes (Standards per `desplega:engineering-standards`, Spec against the phase body), parallel sub-agents Sonnet/Opus per the table, reported separately and never merged.\n- **Codex can review too**: for complex/high-stakes phases, add a Codex review (`codex exec review`, or a sol review prompt via `codex-exec.sh`) in parallel with the two Claude axes, then join — dedupe findings, discard false positives, rank the rest. The JOIN and the final verdict stay Claude-side; a review is never delegated to a single executor and never skipped.\n\n## Failure & mismatch handling\n\nSame as `implementing`/`v-implementing`: on blocked/failed or plan-vs-reality mismatch, `AskUserQuestion` (Adapt / Retry / Skip / Stop); in Autopilot use judgment and document it. Cleanup on abort: `git worktree list` → `git worktree remove --force` stragglers, delete `codex/*` branches.\n";
6963
+ var content_default16 = "# delegate-work\n\nClaude (Fable 5) is the **orchestrator**: it thinks, designs, schedules, reviews, commits, and talks to the user. Everything else is delegated to the **cheapest executor that clears the quality bar**. Codex types; Claude judges.\n\nThis skill applies in BOTH modes:\n- **Ad-hoc**: any time you'd spawn an `Agent`/Task, pick its model from the matrix below instead of the default.\n- **Plan execution**: inside `desplega:implementing` / `desplega:v-implementing` (and `run-phase` / `run-step`), keep ALL of their orchestration semantics (autonomy modes, checkpoints, plan bookkeeping, commit strategy) — only the executor choice changes: instead of default phase-running/step-running sub-agents, route each phase/step per the matrix.\n\n## The matrix\n\nRankings 1–10, higher = better. Cost = subscription quota burned — both Claude and Codex run on flat-rate subs, so higher = lighter on that plan's rate limits (Fable burns the Claude quota fastest; Codex quota is comparatively abundant). Code = how hard a coding problem you can hand it unsupervised. Taste = UI/UX, code quality, API design, copy.\n\n| executor | cost | code | taste | speed | role |\n|-------------------------|------|------|-------|-------|------|\n| fable-5 | 2 | 9 | 9 | 4 | orchestration, deep reasoning, architecture, final judgment |\n| opus-5 | 4 | 7 | 8 | 5 | UI implementation, complex review, browser E2E |\n| sonnet-5 | 5 | 5 | 7 | 7 | routine review, API QA agents, standard sub-agent work |\n| haiku-4.5 | 9 | 3 | 4 | 9 | search, locate, digest, mechanical sweeps — NEVER for writing code |\n| codex gpt-5.6-sol | 8 | 10 | 6 | 6 | hard/long-horizon implementation, gnarly debugging |\n| codex gpt-5.6-terra | 9 | 8 | 5 | 8 | everyday implementation from a frozen spec |\n| codex gpt-5.6-luna | 10 | 6 | 4 | 10 | mechanical code: migrations, renames, test fills, dep bumps |\n\n(Context for the Codex rows, from the 5.6 release: Sol-max is SOTA on the AA Coding Agent Index, ~3 pts above Fable 5 at ~⅓ the cost; Terra lands just above Fable 5; Luna outperforms Opus 5 — each in ~⅓ the time. Claude keeps the edge on taste and judgment; that's why review and UI stay Claude-side.)\n\n**Defaults, not limits.** Standing permission to override: if a cheaper executor's output doesn't meet the bar, rerun or redo with a smarter one without asking. Judge the output, not the price tag. Escalating costs less than shipping mediocre work.\n\n## Routing table\n\n| work | executor | how |\n|------|----------|-----|\n| orchestration, deep reasoning, spec-writing, architecture | **Fable 5** | stay in the main session; never delegated |\n| UI implementation (pages, components, styles, UX flows) | **Opus 5** | `Agent` with `model: \"opus\"`, background |\n| code review — routine / per-phase | **Sonnet 5** | `Agent` with `model: \"sonnet\"` |\n| code review — complex, security-sensitive, cross-cutting, or reviewing Sol output | **Opus 5** (+ optional parallel Codex review, see Verify ↓) | `Agent` with `model: \"opus\"` |\n| API-level QA / E2E agents, plan-verification agents | **Sonnet 5** | `Agent` with `model: \"sonnet\"` |\n| browser E2E / driving the real UI | **Opus 5** | `Agent` with `model: \"opus\"`; use a browser-automation agent for local URLs unless stated differently |\n| search, locate, pattern-find, doc digests | **Haiku 4.5** | `Explore` / locator agents with `model: \"haiku\"` |\n| bulk mechanical call-sequences (~10+ similar tool/API calls, any fan-out over a list) | **a script** | `desplega:script-builder` — cheapest executor of all; one summary re-enters context, raw payloads never do |\n| raw code implementation from a frozen spec | **Codex** | variant by scope ↓, via `codex-exec.sh` |\n\n**Codex variant by scope** (effort in parentheses):\n\n- `gpt-5.6-luna` (`medium`→`high`) — mechanical & bounded: renames, mechanical migrations, test/coverage fills, CI fixes, dep bumps, single-file bug fix with known repro.\n- `gpt-5.6-terra` (`high`) — the default for a well-specified phase/step: single vertical slice, clear verification, few unknowns.\n- `gpt-5.6-sol` (`high`; `xhigh` for hard, `max` only for the gnarliest long-horizon work) — multi-file backend phases, cross-package changes, subtle debugging, anything where the spec has known-unknowns.\n- Never use Codex `ultra` (its own multi-agent mode) — parallelism is the orchestrator's job, via worktrees.\n\n**Keep in Claude regardless of matrix**: tasks where writing the spec IS the work (ambiguity = design); tiny edits (<~20 lines) where delegation overhead loses; anything needing session tools (MCP, browser, secrets); destructive/irreversible ops, pushes, GitHub mutations; judging delegated output — executors may contribute reviews, but the join and final verdict are never delegated, never skipped.\n\nHeuristic: if the prompt reads as a work order → delegate; if writing it forces decisions → it's design, keep it.\n\n## Workflow-tool orchestration\n\nWhen the harness exposes the `Workflow` tool AND the user has opted in (the desplega skills ask during setup — that answer IS the explicit opt-in the tool requires), fan-out runs as a workflow script instead of ad-hoc `Agent` calls. The matrix above still routes every executor; it just maps onto `agent()` opts:\n\n- **Model tiers** → `model: \"haiku\" | \"sonnet\" | \"opus\"`; omit `model` for work that must stay at orchestrator quality (it inherits the session model). `effort` follows the same logic: `low` for mechanical stages, higher tiers only for verify/judge stages.\n- **Named agents** (locators, analyzers, pattern-finders) → the `agentType` opt.\n- **Codex rows** still apply inside a workflow: an `agent()` can drive `codex-exec.sh` in its own worktree. Plan bookkeeping and commits stay orchestrator-side, as always.\n- **The join stays Claude-side**: the workflow returns data (findings, reports, file lists) — reading the diff, deduping findings, and the final verdict happen in the main session, never inside the script.\n- **Pause points sit between Workflow invocations** — one workflow per wave/stage, orchestrator judges and checkpoints in between. Never bury a human checkpoint inside a script.\n\n## Codex: the one primitive\n\n> **Prerequisite**: the `codex` CLI on PATH, authenticated, with access to the gpt-5.6 models. If it's missing, the Codex rows of the matrix are unavailable — route implementation work to Claude executors instead (Opus for hard slices, Sonnet for routine ones) and tell the user why.\n\n`bash ~/.claude/skills/delegate-work/scripts/codex-exec.sh`\n\n```\nprintf '%s' \"$PROMPT\" | bash ~/.claude/skills/delegate-work/scripts/codex-exec.sh -m gpt-5.6-terra -e high \\\n -C <workdir> -o <report-file> -l <log-file>\n```\n\n- `-m` model / `-e` reasoning effort — from the scope table above (script defaults: `gpt-5.6-sol` + `high`; env overrides `CODEX_MODEL`/`CODEX_EFFORT` still work).\n- `-C` working root — a **git worktree** for parallel work, repo root for sequential.\n- `-o` report file — Codex's final message; read THIS back, not the log.\n- `-l` log file — for monitoring only; keep raw logs out of the session.\n- Sandbox defaults to `workspace-write` (edits inside `-C`, reads anywhere). `CODEX_BYPASS=1` only when a task genuinely must write outside its worktree.\n- **Always background** (`run_in_background: true`, `timeout: 600000`).\n- **Prompt via stdin/temp file, never inline arg** — the inline form can silently drop the prompt and hang on stdin (observed). A ~39-byte log means it hung.\n- Follow-up fixes: `codex exec resume --last` from the same dir is cheaper than a fresh run and keeps its context — use for review-fix rounds and crash recovery (\"assess partial state via git status/diff first; don't redo, don't trust\").\n- After **2 failed rounds** on the same task: stop delegating, take over directly (or escalate the model one rung).\n\n## Codex prompt contract\n\nCodex starts with zero session context. Every prompt: goal, exact repo/paths (absolute plan path in the MAIN repo — worktrees don't contain untracked `thoughts/`), scope fence (\"ONLY Phase N / step-N, don't touch X\"), non-goals, verification commands to run, the standards line (\"smallest diff that solves the problem; no speculative abstractions\" — per `desplega:engineering-standards`), and the report shape (status completed/blocked/failed, files changed, verification output, notes). Codex must NOT edit the plan file — the orchestrator owns all plan bookkeeping.\n\n## Worktrees & parallelism\n\n**Always clean up after use** — the moment a slice is merged or abandoned: `git worktree remove <path>` + `git branch -d codex/<slug>`. Never leave stragglers; before ending a session, `git worktree list` must show only the main tree (and any worktree the user created themselves).\n\n- Sequential (linear plan): repo root or one dedicated worktree; one phase at a time; orchestrator verifies, ticks boxes, commits `[Phase N] <name>`, honors checkpoints.\n- Parallel (DAG plan / independent slices): one worktree per slice — `git worktree add -b codex/<slug> <path> <integration-branch>`; fan out one Codex per ready step; merge back sequentially with `--no-ff`; remove worktree + branch after merge.\n- **`bun install` (or equivalent) in every fresh worktree BEFORE launching** — a deps-less sandbox \"verifies\" nothing and ships unproven code.\n- Codex cannot `git commit` inside linked worktrees (index lives under the main repo's `.git` → EPERM). Tell it not to commit; the orchestrator commits.\n- Parallel Claude agents sharing ONE tree need strict file fences: commit only their own paths, never `git add -A`.\n\n## Verify (Claude judges, always)\n\n- Read the full diff and judge it like a contributor PR; Codex/sub-agent claims are advisory.\n- Re-run the phase/step verification commands yourself when the report is ambiguous.\n- After web service-layer changes: probe the running dev server — unit tests miss RSC import crashes.\n- UI touched by anything non-Opus (or by Codex at all): hands-on polish pass — drive the real UI, screenshot, fix spacing/copy/empty-states yourself.\n- Then the per-phase review round before closing the phase: `desplega:code-reviewing` — two axes (Standards per `desplega:engineering-standards`, Spec against the phase body), parallel sub-agents Sonnet/Opus per the table, reported separately and never merged.\n- **Codex can review too**: for complex/high-stakes phases, add a Codex review (`codex exec review`, or a sol review prompt via `codex-exec.sh`) in parallel with the two Claude axes, then join — dedupe findings, discard false positives, rank the rest. The JOIN and the final verdict stay Claude-side; a review is never delegated to a single executor and never skipped.\n\n## Failure & mismatch handling\n\nSame as `implementing`/`v-implementing`: on blocked/failed or plan-vs-reality mismatch, `AskUserQuestion` (Adapt / Retry / Skip / Stop); in Autopilot use judgment and document it. Cleanup on abort: `git worktree list` → `git worktree remove --force` stragglers, delete `codex/*` branches.\n";
6862
6964
 
6863
6965
  // templates/skills/design-docs/config.json
6864
- var config_default16 = `{
6966
+ var config_default17 = `{
6865
6967
  "category": "skills",
6866
6968
  "description": "Create and maintain living per-system design docs at thoughts/*/design-docs/<system-slug>.md — Purpose, Glossary, numbered testable Invariants (normative for the code-reviewing Spec axis), Boundaries & Non-goals, Interfaces, Decision log, Amendment log. Use when the user says \\"create a design doc\\", \\"write down the invariants\\", \\"document the design/contract of X\\", or when researching/planning/one-shot finds a design doc for the touched system and needs the read-and-abide rules.",
6867
6969
  "displayName": "Design Docs",
@@ -6882,7 +6984,7 @@ var config_default16 = `{
6882
6984
  `;
6883
6985
 
6884
6986
  // templates/skills/design-docs/content.md
6885
- var content_default16 = `# Design Docs
6987
+ var content_default17 = `# Design Docs
6886
6988
 
6887
6989
  A design doc is the durable statement of intent for **one system**: what it's for, what words mean, what must always hold, and what it deliberately doesn't do. It lives at \`thoughts/<username|shared>/design-docs/<system-slug>.md\` — **no date prefix**; it's a living doc, amended in place, never superseded by a new dated file.
6888
6990
 
@@ -6922,7 +7024,7 @@ Wired into: \`desplega:researching\` and \`desplega:planning\` (read-and-abide r
6922
7024
  `;
6923
7025
 
6924
7026
  // templates/skills/download-task-attachment/config.json
6925
- var config_default17 = `{
7027
+ var config_default18 = `{
6926
7028
  "kind": "skill",
6927
7029
  "name": "download-task-attachment",
6928
7030
  "displayName": "Download Task Attachment",
@@ -6939,10 +7041,10 @@ var config_default17 = `{
6939
7041
  `;
6940
7042
 
6941
7043
  // templates/skills/download-task-attachment/content.md
6942
- var content_default17 = '# Download a Task Attachment\n\nTask attachments (files uploaded via the UI or API onto a task) are served\nthrough a single **provider-agnostic** REST route — regardless of whether the\nbacking storage is `local-fs` or `agent-fs`. You do not need to know or care\nwhich provider is active, and you do not need `agent-fs org`/`agent-fs drive`\ndiscovery.\n\n## The one-call recipe\n\n```bash\ncurl "$MCP_BASE_URL/api/fs/tasks/$AGENT_SWARM_TASK_ID/files/<attachmentId>/raw" \\\n -H "X-Agent-ID: $AGENT_ID" \\\n -H "Authorization: Bearer ${AGENT_SWARM_API_KEY:-$API_KEY}" \\\n --create-dirs -o "/tmp/attachments/<attachmentId>/<name>"\n```\n\n- `$MCP_BASE_URL`, `$AGENT_ID`, `$AGENT_SWARM_TASK_ID` (or `$AGENT_SWARM_AGENT_ID`/`TASK_FILE`-derived taskId), and `$AGENT_SWARM_API_KEY`/`$API_KEY` are already present in every worker container\'s env — no new plumbing needed.\n- `<attachmentId>` and `<name>`/`mimeType` come from the task\'s attachment list (see below).\n- One directory per attachment: two attachments can share a name (every pasted screenshot is `image.png`), and `/tmp/<name>` would let one overwrite the other.\n- The route resolves the active file-storage provider (`local-fs` in dev, `agent-fs` in prod) server-side and streams the raw bytes back with the correct `Content-Type` — you get one call no matter which provider is behind it.\n\n## Finding the attachment ID\n\nIf the dispatch prompt already injected an `## Attachments` section with the\ncurl command pre-filled, just run it — that\'s the fast path (see\n`buildAttachmentsSection()` in `src/commands/runner.ts`).\n\nOtherwise, pull it from the task:\n\n```\nget-task-details taskId=<your task id>\n```\n\nThe response includes an `attachments` array: `{id, name, mimeType, sizeBytes}`.\nUse `id` as `<attachmentId>` in the curl above.\n\n## Why not the `agent-fs` CLI directly?\n\n`agent-fs` is a general-purpose CLI for the swarm\'s own agent-fs filesystem —\nit requires you to already know the org/drive a file lives in, and task\nattachments don\'t always carry that (older rows, or attachments stored via\n`local-fs` in dev have no org/drive at all). Reaching for `agent-fs cat` /\n`agent-fs download` on a task attachment means guessing subcommand names,\ndiscovering the right org via `agent-fs org list`, and re-trying — several\ntool calls where one `curl` suffices. This was root-caused from a real\nsession that burned 7 tool calls (~64s) doing exactly that detour before\nsucceeding; see `runbooks/harness-providers.md` and PR that added\n`buildAttachmentsSection()` for the full trace.\n\n## Gotchas\n\n- The route requires `X-Agent-ID` + bearer auth like any other swarm API call — same headers you\'d use for any MCP-adjacent REST call.\n- `mimeType` on the attachment record reflects the real upload `Content-Type` (not a filename-extension guess) — trust it when deciding how to handle the downloaded bytes (image vs PDF vs text).\n- If you get a 404, double-check you\'re using the **attachment ID** (from `attachments[].id`), not the display `name`.\n';
7044
+ var content_default18 = '# Download a Task Attachment\n\nTask attachments (files uploaded via the UI or API onto a task) are served\nthrough a single **provider-agnostic** REST route — regardless of whether the\nbacking storage is `local-fs` or `agent-fs`. You do not need to know or care\nwhich provider is active, and you do not need `agent-fs org`/`agent-fs drive`\ndiscovery.\n\n## The one-call recipe\n\n```bash\ncurl "$MCP_BASE_URL/api/fs/tasks/$AGENT_SWARM_TASK_ID/files/<attachmentId>/raw" \\\n -H "X-Agent-ID: $AGENT_ID" \\\n -H "Authorization: Bearer ${AGENT_SWARM_API_KEY:-$API_KEY}" \\\n --create-dirs -o "/tmp/attachments/<attachmentId>/<name>"\n```\n\n- `$MCP_BASE_URL`, `$AGENT_ID`, `$AGENT_SWARM_TASK_ID` (or `$AGENT_SWARM_AGENT_ID`/`TASK_FILE`-derived taskId), and `$AGENT_SWARM_API_KEY`/`$API_KEY` are already present in every worker container\'s env — no new plumbing needed.\n- `<attachmentId>` and `<name>`/`mimeType` come from the task\'s attachment list (see below).\n- One directory per attachment: two attachments can share a name (every pasted screenshot is `image.png`), and `/tmp/<name>` would let one overwrite the other.\n- The route resolves the active file-storage provider (`local-fs` in dev, `agent-fs` in prod) server-side and streams the raw bytes back with the correct `Content-Type` — you get one call no matter which provider is behind it.\n\n## Finding the attachment ID\n\nIf the dispatch prompt already injected an `## Attachments` section with the\ncurl command pre-filled, just run it — that\'s the fast path (see\n`buildAttachmentsSection()` in `src/commands/runner.ts`).\n\nOtherwise, pull it from the task:\n\n```\nget-task-details taskId=<your task id>\n```\n\nThe response includes an `attachments` array: `{id, name, mimeType, sizeBytes}`.\nUse `id` as `<attachmentId>` in the curl above.\n\n## Why not the `agent-fs` CLI directly?\n\n`agent-fs` is a general-purpose CLI for the swarm\'s own agent-fs filesystem —\nit requires you to already know the org/drive a file lives in, and task\nattachments don\'t always carry that (older rows, or attachments stored via\n`local-fs` in dev have no org/drive at all). Reaching for `agent-fs cat` /\n`agent-fs download` on a task attachment means guessing subcommand names,\ndiscovering the right org via `agent-fs org list`, and re-trying — several\ntool calls where one `curl` suffices. This was root-caused from a real\nsession that burned 7 tool calls (~64s) doing exactly that detour before\nsucceeding; see `runbooks/harness-providers.md` and PR that added\n`buildAttachmentsSection()` for the full trace.\n\n## Gotchas\n\n- The route requires `X-Agent-ID` + bearer auth like any other swarm API call — same headers you\'d use for any MCP-adjacent REST call.\n- `mimeType` on the attachment record reflects the real upload `Content-Type` (not a filename-extension guess) — trust it when deciding how to handle the downloaded bytes (image vs PDF vs text).\n- If you get a 404, double-check you\'re using the **attachment ID** (from `attachments[].id`), not the display `name`.\n';
6943
7045
 
6944
7046
  // templates/skills/engineering-standards/config.json
6945
- var config_default18 = `{
7047
+ var config_default19 = `{
6946
7048
  "category": "skills",
6947
7049
  "description": "Code-shape policy for ALL code that gets written or reviewed — the senior-engineer bar for minimal complexity. Use whenever you are about to write code, design a module or abstraction, draft a plan phase that shapes code, or review a diff; also when the user asks \\"is this over-engineered\\", \\"can this be simpler\\", or pushes back on complexity. Sibling of desplega:delegate-work (which picks WHO executes; this skill defines WHAT good output looks like).",
6948
7050
  "displayName": "Engineering Standards",
@@ -6963,7 +7065,7 @@ var config_default18 = `{
6963
7065
  `;
6964
7066
 
6965
7067
  // templates/skills/engineering-standards/content.md
6966
- var content_default18 = `# engineering-standards
7068
+ var content_default19 = `# engineering-standards
6967
7069
 
6968
7070
  The goal is always the same: **solve the problem with the least code and the least complexity that actually solves it.** Not the cleverest solution, not the most extensible one — the one a senior engineer would defend in review. Every rule below is phrased as a *checkable test*, not a slogan: if you can't run the test, the rule doesn't apply; if the test fails, change the code.
6969
7071
 
@@ -7034,7 +7136,7 @@ runbooks/<name>/<slug>.md # …or grouped by area when they multiply
7034
7136
  `;
7035
7137
 
7036
7138
  // templates/skills/heartbeat-runbook/config.json
7037
- var config_default19 = `{
7139
+ var config_default20 = `{
7038
7140
  "kind": "skill",
7039
7141
  "name": "heartbeat-runbook",
7040
7142
  "displayName": "Heartbeat Runbook",
@@ -7051,7 +7153,7 @@ var config_default19 = `{
7051
7153
  `;
7052
7154
 
7053
7155
  // templates/skills/heartbeat-runbook/content.md
7054
- var content_default19 = `# Heartbeat runbook
7156
+ var content_default20 = `# Heartbeat runbook
7055
7157
 
7056
7158
  Lead only. The heartbeat runbook is your \`heartbeatMd\` profile field. The server reads it every 30 minutes.
7057
7159
 
@@ -7113,7 +7215,7 @@ Two kinds of sections:
7113
7215
  `;
7114
7216
 
7115
7217
  // templates/skills/implementing/config.json
7116
- var config_default20 = `{
7218
+ var config_default21 = `{
7117
7219
  "category": "skills",
7118
7220
  "description": "Plan implementation skill. Executes approved technical plans phase by phase with verification checkpoints.",
7119
7221
  "displayName": "Implementing",
@@ -7134,7 +7236,7 @@ var config_default20 = `{
7134
7236
  `;
7135
7237
 
7136
7238
  // templates/skills/implementing/content.md
7137
- var content_default20 = `# Implementing
7239
+ var content_default21 = `# Implementing
7138
7240
 
7139
7241
  You are implementing an approved technical plan, executing it phase by phase with verification at each step. Each phase is executed as a background sub-agent via \`desplega:phase-running\` — the main session acts as an orchestrator.
7140
7242
 
@@ -7327,7 +7429,7 @@ File-review is on by default (unless Autopilot):
7327
7429
  `;
7328
7430
 
7329
7431
  // templates/skills/improve-agents-md/config.json
7330
- var config_default21 = `{
7432
+ var config_default22 = `{
7331
7433
  "category": "skills",
7332
7434
  "description": "Improve (or bootstrap) an AGENTS.md / CLAUDE.md file using \`<important if>\` conditional blocks so the agent actually attends to the right guidance at the right time. Use this skill whenever the user mentions AGENTS.md, CLAUDE.md, agent instructions, project rules for AI, \\"my claude config\\", onboarding docs for agents, or asks to tighten / shorten / audit / rewrite an existing one — even if they don't explicitly say the filename. Also use when the user complains that an agent keeps ignoring their project rules.",
7333
7435
  "displayName": "Improve AGENTS.md",
@@ -7348,7 +7450,7 @@ var config_default21 = `{
7348
7450
  `;
7349
7451
 
7350
7452
  // templates/skills/improve-agents-md/content.md
7351
- var content_default21 = `# improve-agents-md
7453
+ var content_default22 = `# improve-agents-md
7352
7454
 
7353
7455
  Progressively improve (or bootstrap from scratch) a project's agent-instruction file. Works on both \`AGENTS.md\` (vendor-neutral convention from OpenAI Codex, also read by Cursor, Claude Code, and others) and \`CLAUDE.md\` (Claude-specific). Keeps one canonical file on disk and symlinks the other, so every agent reads the same source of truth.
7354
7456
 
@@ -7768,7 +7870,7 @@ Run with \`turbo\` from the repo root.
7768
7870
  `;
7769
7871
 
7770
7872
  // templates/skills/kv-storage/config.json
7771
- var config_default22 = `{
7873
+ var config_default23 = `{
7772
7874
  "kind": "skill",
7773
7875
  "name": "kv-storage",
7774
7876
  "displayName": "KV Storage",
@@ -7785,7 +7887,7 @@ var config_default22 = `{
7785
7887
  `;
7786
7888
 
7787
7889
  // templates/skills/kv-storage/content.md
7788
- var content_default22 = `# KV Storage
7890
+ var content_default23 = `# KV Storage
7789
7891
 
7790
7892
  Namespaced key/value store inside the swarm SQLite DB. Auto-scoped to your
7791
7893
  calling context — same string used by \`agent_tasks.contextKey\`.
@@ -8082,7 +8184,7 @@ value so you can detect a clobber.
8082
8184
  `;
8083
8185
 
8084
8186
  // templates/skills/learning/config.json
8085
- var config_default23 = `{
8187
+ var config_default24 = `{
8086
8188
  "category": "skills",
8087
8189
  "description": "Compounding knowledge across projects and teams. Captures, searches, and promotes institutional learnings via tiered backends (local/qmd/agent-fs).",
8088
8190
  "displayName": "Learning",
@@ -8103,7 +8205,7 @@ var config_default23 = `{
8103
8205
  `;
8104
8206
 
8105
8207
  // templates/skills/learning/content.md
8106
- var content_default23 = `# Learning
8208
+ var content_default24 = `# Learning
8107
8209
 
8108
8210
  You are managing institutional knowledge — capturing insights, searching prior learnings, and promoting important patterns into CLAUDE.md for permanent reference.
8109
8211
 
@@ -8371,13 +8473,13 @@ The config file lives at \`~/.agentic-learnings.json\`:
8371
8473
  `;
8372
8474
 
8373
8475
  // templates/skills/memory/config.json
8374
- var config_default24 = '{\n "kind": "skill",\n "name": "memory",\n "displayName": "Memory",\n "slug": "memory",\n "title": "Memory",\n "description": "Remember, recall, learning, memory: how swarm memory works and how to store, search, edit, rate, and delete memories with `memory-store`, `memory-search`, `memory-get`, `memory-edit`, `memory_rate`, and `memory-delete`, plus lead promotion with `inject-learning`. Use before you store, edit, or delete a memory.",\n "version": "1.0.0",\n "category": "skills",\n "placeholders": [],\n "runAllSeedersCandidate": true,\n "systemDefault": true,\n "tags": ["memory", "recall", "learning"]\n}\n';
8476
+ var config_default25 = '{\n "kind": "skill",\n "name": "memory",\n "displayName": "Memory",\n "slug": "memory",\n "title": "Memory",\n "description": "Remember, recall, learning, memory: how swarm memory works and how to store, search, edit, rate, and delete memories with `memory-store`, `memory-search`, `memory-get`, `memory-edit`, `memory_rate`, and `memory-delete`, plus lead promotion with `inject-learning`. Use before you store, edit, or delete a memory.",\n "version": "1.0.0",\n "category": "skills",\n "placeholders": [],\n "runAllSeedersCandidate": true,\n "systemDefault": true,\n "tags": ["memory", "recall", "learning"]\n}\n';
8375
8477
 
8376
8478
  // templates/skills/memory/content.md
8377
- var content_default24 = '# Memory\n\nSwarm memory is a store of short texts with embeddings, searchable by meaning and by keyword. Recall is automatic: the runner puts the best matches for your task in the task message under "Relevant Past Knowledge". Everything else is a tool call.\n\n## What is stored without you\n\n| Source | When | Scope |\n|---|---|---|\n| `task_completion` | `store-progress` with status `completed` or `failed` | `agent`, or `swarm` for research tasks and tasks tagged `knowledge` or `shared` |\n| `session_summary` | your session ends | `agent` |\n| `file_index` | a file written under `/workspace/personal/memory/` or `/workspace/shared/memory/<agentId>/` on a harness with the file hook (claude, pi, opencode) | by path |\n\nAutomatic tasks (schedules, heartbeat, monitors) skip the `task_completion` write unless `store-progress` gets `persistMemory: true`.\n\nPrefer `memory-store` over memory files. It works on every harness, including the remote ones.\n\n## Tools\n\n| Tool | Use |\n|---|---|\n| `memory-store` | create a memory: `content`, `name`, `scope`, optional `tags`, `taskId`, `intent` |\n| `memory-search` | find memories: `query`, `intent` (required, why you search), `scope` (`all`, `agent`, `swarm`), `limit` |\n| `memory-get` | the full content of one memory by ID |\n| `memory-edit` | change a memory in place: mode `replace` (whole content) or `exact` (one unique substring), `intent` required |\n| `memory-delete` | remove a memory by ID |\n| `memory_rate` | mark a memory you used in this task as useful or misleading |\n| `inject-learning` | lead only: push a learning into a worker\'s memory at swarm scope |\n\nSeed scripts (`script-run` with `name` and `args`):\n\n- `task-context-gathering` `{ taskId, queries: [...] }`: the task plus a deduplicated multi-query recall in one call.\n- `smart-recall` `{ queries: [...] }`: multi-query recall without the task.\n- `memory-dedup-check` `{ text, threshold? }`: near-duplicates of a candidate memory, default threshold 0.85.\n\n## What makes a good memory\n\n- One fact per memory: a fix, a pattern, a gotcha, a preference of a person, a fact about a repo or a host.\n- The context it applies to: repo, host, tool, version.\n- The evidence: what you saw, where.\n- A searchable `name`: "Linear API rejects issue updates without teamId", not "notes".\n- Under 2,000 characters stores as one chunk. Longer content splits on headings, one memory per chunk.\n\nSkip what a tool returns on demand (paths, tool lists, task status), what the repo already records (README, CLAUDE.md, git history), and what only mattered for this one task.\n\nA memory must not contain a token, password, key, or connection string. Remove the value and keep the reference ("the Linear token lives in config key LINEAR_API_KEY").\n\n## Scope\n\n- `agent` (default): only you recall it. Your own setup, your working notes, your mistakes.\n- `swarm`: every agent recalls it. Facts about shared repos, hosts, people, and processes. Choose `swarm` when a second agent would hit the same thing.\n\n## Before you store\n\n1. Run `memory-dedup-check` with the text, or `memory-search` with one or two queries and `intent: "dedup before store"`.\n2. A near-duplicate exists: `memory-edit` it. Mode `replace` for a rewrite, mode `exact` for a one-line correction. Say why in `intent`.\n3. Nothing close exists: `memory-store`.\n\n## Triage\n\n- A memory is wrong: `memory-edit` with the correction.\n- A memory is stale and nobody needs it: `memory-delete`.\n- A recalled memory helped or misled you: `memory_rate` with `useful` true or false and a short `note`. The call needs a task context and counts once per memory per task. Ratings move the memory up or down in future searches.\n\n## Lead: promote a learning\n\nWhen a worker\'s output or failure holds a lesson other workers need, call `inject-learning` with the worker\'s `agentId`, the `learning`, and a `category`: `mistake-pattern`, `best-practice`, `codebase-knowledge`, or `preference`. It lands at swarm scope and every agent recalls it.\n';
8479
+ var content_default25 = '# Memory\n\nSwarm memory is a store of short texts with embeddings, searchable by meaning and by keyword. Recall is automatic: the runner puts the best matches for your task in the task message under "Relevant Past Knowledge". Everything else is a tool call.\n\n## What is stored without you\n\n| Source | When | Scope |\n|---|---|---|\n| `task_completion` | `store-progress` with status `completed` or `failed` | `agent`, or `swarm` for research tasks and tasks tagged `knowledge` or `shared` |\n| `session_summary` | your session ends | `agent` |\n| `file_index` | a file written under `/workspace/personal/memory/` or `/workspace/shared/memory/<agentId>/` on a harness with the file hook (claude, pi, opencode) | by path |\n\nAutomatic tasks (schedules, heartbeat, monitors) skip the `task_completion` write unless `store-progress` gets `persistMemory: true`.\n\nPrefer `memory-store` over memory files. It works on every harness, including the remote ones.\n\n## Tools\n\n| Tool | Use |\n|---|---|\n| `memory-store` | create a memory: `content`, `name`, `scope`, optional `tags`, `taskId`, `intent` |\n| `memory-search` | find memories: `query`, `intent` (required, why you search), `scope` (`all`, `agent`, `swarm`), `limit` |\n| `memory-get` | the full content of one memory by ID |\n| `memory-edit` | change a memory in place: mode `replace` (whole content) or `exact` (one unique substring), `intent` required |\n| `memory-delete` | remove a memory by ID |\n| `memory_rate` | mark a memory you used in this task as useful or misleading |\n| `inject-learning` | lead only: push a learning into a worker\'s memory at swarm scope |\n\nSeed scripts (`script-run` with `name` and `args`):\n\n- `task-context-gathering` `{ taskId, queries: [...] }`: the task plus a deduplicated multi-query recall in one call.\n- `smart-recall` `{ queries: [...] }`: multi-query recall without the task.\n- `memory-dedup-check` `{ text, threshold? }`: near-duplicates of a candidate memory, default threshold 0.85.\n\n## What makes a good memory\n\n- One fact per memory: a fix, a pattern, a gotcha, a preference of a person, a fact about a repo or a host.\n- The context it applies to: repo, host, tool, version.\n- The evidence: what you saw, where.\n- A searchable `name`: "Linear API rejects issue updates without teamId", not "notes".\n- Under 2,000 characters stores as one chunk. Longer content splits on headings, one memory per chunk.\n\nSkip what a tool returns on demand (paths, tool lists, task status), what the repo already records (README, CLAUDE.md, git history), and what only mattered for this one task.\n\nA memory must not contain a token, password, key, or connection string. Remove the value and keep the reference ("the Linear token lives in config key LINEAR_API_KEY").\n\n## Scope\n\n- `agent` (default): only you recall it. Your own setup, your working notes, your mistakes.\n- `swarm`: every agent recalls it. Facts about shared repos, hosts, people, and processes. Choose `swarm` when a second agent would hit the same thing.\n\n## Before you store\n\n1. Run `memory-dedup-check` with the text, or `memory-search` with one or two queries and `intent: "dedup before store"`.\n2. A near-duplicate exists: `memory-edit` it. Mode `replace` for a rewrite, mode `exact` for a one-line correction. Say why in `intent`.\n3. Nothing close exists: `memory-store`.\n\n## Triage\n\n- A memory is wrong: `memory-edit` with the correction.\n- A memory is stale and nobody needs it: `memory-delete`.\n- A recalled memory helped or misled you: `memory_rate` with `useful` true or false and a short `note`. The call needs a task context and counts once per memory per task. Ratings move the memory up or down in future searches.\n\n## Lead: promote a learning\n\nWhen a worker\'s output or failure holds a lesson other workers need, call `inject-learning` with the worker\'s `agentId`, the `learning`, and a `category`: `mistake-pattern`, `best-practice`, `codebase-knowledge`, or `preference`. It lands at swarm scope and every agent recalls it.\n';
8378
8480
 
8379
8481
  // templates/skills/one-shot/config.json
8380
- var config_default25 = `{
8482
+ var config_default26 = `{
8381
8483
  "category": "skills",
8382
8484
  "description": "Small-scope plan+implement in one session. Assess the prompt, optionally one bundled round of questions, maintain a lightweight yolo plan while implementing, verify, quick code review, commit. Use when the user invokes /one-shot, or asks to \\"just build/fix/add\\" something small without the full create-plan → implement-plan pipeline. Small means ≤ ~3 phases inside one subsystem — anything bigger escalates to /desplega:create-plan.",
8383
8485
  "displayName": "One Shot",
@@ -8398,7 +8500,7 @@ var config_default25 = `{
8398
8500
  `;
8399
8501
 
8400
8502
  // templates/skills/one-shot/content.md
8401
- var content_default25 = `# One-Shot
8503
+ var content_default26 = `# One-Shot
8402
8504
 
8403
8505
  Plan and implement a small task in a single session. This is the lightweight sibling of the \`create-plan\` → \`implement-plan\` pipeline: same discipline (written plan, verification, code review), a fraction of the ceremony.
8404
8506
 
@@ -8467,7 +8569,7 @@ Commit with a concise message referencing the change (only if the user hasn't sa
8467
8569
  `;
8468
8570
 
8469
8571
  // templates/skills/pages/config.json
8470
- var config_default26 = `{
8572
+ var config_default27 = `{
8471
8573
  "kind": "skill",
8472
8574
  "name": "pages",
8473
8575
  "displayName": "Pages",
@@ -8490,7 +8592,7 @@ var config_default26 = `{
8490
8592
  `;
8491
8593
 
8492
8594
  // templates/skills/pages/content.md
8493
- var content_default26 = `# Pages — DB-backed Static Artifacts
8595
+ var content_default27 = `# Pages — DB-backed Static Artifacts
8494
8596
 
8495
8597
  DB-backed static content (HTML or JSON) served by the API directly. Cheap,
8496
8598
  versioned, share-able by URL. The lighter-weight cousin of \`artifacts\` —
@@ -9141,7 +9243,7 @@ Channels cannot access internal workflow topics. The socket closes when its auth
9141
9243
  `;
9142
9244
 
9143
9245
  // templates/skills/phase-running/config.json
9144
- var config_default27 = `{
9246
+ var config_default28 = `{
9145
9247
  "category": "skills",
9146
9248
  "description": "Execute individual plan phases as background sub-agents for context-efficient implementation.",
9147
9249
  "displayName": "Phase Running",
@@ -9162,7 +9264,7 @@ var config_default27 = `{
9162
9264
  `;
9163
9265
 
9164
9266
  // templates/skills/phase-running/content.md
9165
- var content_default27 = `# Phase Running
9267
+ var content_default28 = `# Phase Running
9166
9268
 
9167
9269
  You are executing a single phase of an implementation plan as an atomic background sub-agent. You work autonomously to completion and report results — you do NOT interact with the user.
9168
9270
 
@@ -9294,7 +9396,7 @@ Phase agents are atomic — they run to completion or stop:
9294
9396
  `;
9295
9397
 
9296
9398
  // templates/skills/planning/config.json
9297
- var config_default28 = `{
9399
+ var config_default29 = `{
9298
9400
  "category": "skills",
9299
9401
  "description": "Implementation planning skill. Creates detailed technical plans through interactive research and iteration.",
9300
9402
  "displayName": "Planning",
@@ -9315,7 +9417,7 @@ var config_default28 = `{
9315
9417
  `;
9316
9418
 
9317
9419
  // templates/skills/planning/content.md
9318
- var content_default28 = `# Planning
9420
+ var content_default29 = `# Planning
9319
9421
 
9320
9422
  You create detailed implementation plans through an interactive, iterative process. Be skeptical, thorough, collaborative.
9321
9423
 
@@ -9390,7 +9492,7 @@ Canonical format and heading hierarchy lives in \`template.md\`. Structure valid
9390
9492
  `;
9391
9493
 
9392
9494
  // templates/skills/qa/config.json
9393
- var config_default29 = `{
9495
+ var config_default30 = `{
9394
9496
  "category": "skills",
9395
9497
  "description": "Functional validation skill. Captures test evidence (screenshots, recordings, links) and produces QA reports in thoughts/*/qa/.",
9396
9498
  "displayName": "QA",
@@ -9411,7 +9513,7 @@ var config_default29 = `{
9411
9513
  `;
9412
9514
 
9413
9515
  // templates/skills/qa/content.md
9414
- var content_default29 = `# QA
9516
+ var content_default30 = `# QA
9415
9517
 
9416
9518
  You are performing functional validation of a feature, bugfix, or deployment. Your job is to prove it works (or doesn't) by executing test scenarios and capturing evidence.
9417
9519
 
@@ -9597,7 +9699,7 @@ Based on the answer:
9597
9699
  `;
9598
9700
 
9599
9701
  // templates/skills/questioning/config.json
9600
- var config_default30 = `{
9702
+ var config_default31 = `{
9601
9703
  "category": "skills",
9602
9704
  "description": "One-shot question answering using the research process. Answers inline without generating documents, then offers handoff to brainstorm or research.",
9603
9705
  "displayName": "Questioning",
@@ -9618,7 +9720,7 @@ var config_default30 = `{
9618
9720
  `;
9619
9721
 
9620
9722
  // templates/skills/questioning/content.md
9621
- var content_default30 = `# Questioning
9723
+ var content_default31 = `# Questioning
9622
9724
 
9623
9725
  You are answering a question directly and concisely using the research process. No documents are created by default — the answer is the deliverable.
9624
9726
 
@@ -9729,7 +9831,7 @@ Each iteration is independent — no state accumulates between questions unless
9729
9831
  `;
9730
9832
 
9731
9833
  // templates/skills/researching/config.json
9732
- var config_default31 = `{
9834
+ var config_default32 = `{
9733
9835
  "category": "skills",
9734
9836
  "description": "Comprehensive codebase research skill. Documents codebase as-is by spawning parallel sub-agents and synthesizing findings into research documents.",
9735
9837
  "displayName": "Researching",
@@ -9750,7 +9852,7 @@ var config_default31 = `{
9750
9852
  `;
9751
9853
 
9752
9854
  // templates/skills/researching/content.md
9753
- var content_default31 = `# Researching
9855
+ var content_default32 = `# Researching
9754
9856
 
9755
9857
  You are conducting comprehensive research across the codebase to answer questions by spawning parallel sub-agents and synthesizing their findings.
9756
9858
 
@@ -9919,7 +10021,7 @@ File-review is on by default (unless Autopilot):
9919
10021
  `;
9920
10022
 
9921
10023
  // templates/skills/review-offered-task/config.json
9922
- var config_default32 = `{
10024
+ var config_default33 = `{
9923
10025
  "kind": "skill",
9924
10026
  "name": "review-offered-task",
9925
10027
  "displayName": "Review Offered Task",
@@ -9936,10 +10038,10 @@ var config_default32 = `{
9936
10038
  `;
9937
10039
 
9938
10040
  // templates/skills/review-offered-task/content.md
9939
- var content_default32 = '# Review Offered Task\n\nYou have been offered a task. Your job is to review it and decide whether to accept or reject it based on your capabilities and current workload.\n\n## Workflow\n\n1. **Get task details**: Call the `get-task-details` tool with the provided `taskId` to understand what the task involves.\n\n2. **Evaluate the task**: Consider:\n - Does this task match your capabilities?\n - Do you have the necessary context or access to complete it?\n - Is the task description clear enough to proceed?\n\n3. **Make a decision**:\n - **Accept**: If you can complete this task, call `task-action` with `action: "accept"` and `taskId: "<taskId>"`. Then immediately use the `work-on-task` skill with the taskId to start working on it.\n - **Reject**: If you cannot complete this task, call `task-action` with `action: "reject"`, `taskId: "<taskId>"`, and provide a `reason` explaining why you\'re rejecting it (e.g., "Task requires Python expertise which I don\'t have", "Task description is too vague").\n\n## Example Accept Flow\n\n```\n1. get-task-details taskId="abc-123"\n2. [Review the task details]\n3. task-action action="accept" taskId="abc-123"\n4. /work-on-task abc-123\n```\n\n## Example Reject Flow\n\n```\n1. get-task-details taskId="abc-123"\n2. [Review the task details]\n3. task-action action="reject" taskId="abc-123" reason="Task requires access to production database which I don\'t have"\n4. Stop\n```\n\n## Important Notes\n\n- Always provide a clear reason when rejecting a task - this helps the lead agent reassign it appropriately\n- If you accept, you must immediately start working on the task using the `work-on-task` skill\n- If you reject, the task returns to the unassigned pool for reassignment\n';
10041
+ var content_default33 = '# Review Offered Task\n\nYou have been offered a task. Your job is to review it and decide whether to accept or reject it based on your capabilities and current workload.\n\n## Workflow\n\n1. **Get task details**: Call the `get-task-details` tool with the provided `taskId` to understand what the task involves.\n\n2. **Evaluate the task**: Consider:\n - Does this task match your capabilities?\n - Do you have the necessary context or access to complete it?\n - Is the task description clear enough to proceed?\n\n3. **Make a decision**:\n - **Accept**: If you can complete this task, call `task-action` with `action: "accept"` and `taskId: "<taskId>"`. Then immediately use the `work-on-task` skill with the taskId to start working on it.\n - **Reject**: If you cannot complete this task, call `task-action` with `action: "reject"`, `taskId: "<taskId>"`, and provide a `reason` explaining why you\'re rejecting it (e.g., "Task requires Python expertise which I don\'t have", "Task description is too vague").\n\n## Example Accept Flow\n\n```\n1. get-task-details taskId="abc-123"\n2. [Review the task details]\n3. task-action action="accept" taskId="abc-123"\n4. /work-on-task abc-123\n```\n\n## Example Reject Flow\n\n```\n1. get-task-details taskId="abc-123"\n2. [Review the task details]\n3. task-action action="reject" taskId="abc-123" reason="Task requires access to production database which I don\'t have"\n4. Stop\n```\n\n## Important Notes\n\n- Always provide a clear reason when rejecting a task - this helps the lead agent reassign it appropriately\n- If you accept, you must immediately start working on the task using the `work-on-task` skill\n- If you reject, the task returns to the unassigned pool for reassignment\n';
9940
10042
 
9941
10043
  // templates/skills/reviewing/config.json
9942
- var config_default33 = `{
10044
+ var config_default34 = `{
9943
10045
  "category": "skills",
9944
10046
  "description": "Structured critique of research, plan, and brainstorm documents for completeness, gaps, and quality.",
9945
10047
  "displayName": "Reviewing",
@@ -9960,7 +10062,7 @@ var config_default33 = `{
9960
10062
  `;
9961
10063
 
9962
10064
  // templates/skills/reviewing/content.md
9963
- var content_default33 = `# Reviewing
10065
+ var content_default34 = `# Reviewing
9964
10066
 
9965
10067
  You are performing a structured critique of a document (research, plan, or brainstorm) to identify gaps, weaknesses, and quality issues. (For reviewing a code diff, use \`desplega:code-reviewing\` instead — this skill reviews documents.)
9966
10068
 
@@ -10212,7 +10314,7 @@ File-review is on by default (unless Autopilot):
10212
10314
  `;
10213
10315
 
10214
10316
  // templates/skills/scheduled-task-resilience/config.json
10215
- var config_default34 = `{
10317
+ var config_default35 = `{
10216
10318
  "kind": "skill",
10217
10319
  "name": "scheduled-task-resilience",
10218
10320
  "displayName": "Scheduled Task Resilience",
@@ -10229,7 +10331,7 @@ var config_default34 = `{
10229
10331
  `;
10230
10332
 
10231
10333
  // templates/skills/scheduled-task-resilience/content.md
10232
- var content_default34 = `# Scheduled Task Resilience
10334
+ var content_default35 = `# Scheduled Task Resilience
10233
10335
 
10234
10336
  Use these rules whenever a scheduled or regular task polls or waits on a long-running operation. They prevent heartbeat collisions, lost work, duplicate delivery, and sessions that fail after holding an external job open too long.
10235
10337
 
@@ -10329,7 +10431,7 @@ When historical incident detail is useful, search the deployment's memory regist
10329
10431
  `;
10330
10432
 
10331
10433
  // templates/skills/scheduling/config.json
10332
- var config_default35 = `{
10434
+ var config_default36 = `{
10333
10435
  "kind": "skill",
10334
10436
  "name": "scheduling",
10335
10437
  "displayName": "Scheduling",
@@ -10346,10 +10448,10 @@ var config_default35 = `{
10346
10448
  `;
10347
10449
 
10348
10450
  // templates/skills/scheduling/content.md
10349
- var content_default35 = '# Scheduling\n\nUse a schedule when work repeats on a clock, or when it must run once at a later time. On each tick the schedule creates one run. The run is a workflow, a catalog script, or an agent task.\n\n## Tools\n\n`list-schedules`, `create-schedule`, `update-schedule`, `patch-schedule`, `delete-schedule`, `run-schedule-now`. They are deferred. Load them with your harness tool search before the first call.\n\n## Pick the target type\n\n| The tick should | `targetType` | Required fields |\n|---|---|---|\n| Start a workflow | `workflow` | `workflowId` |\n| Run a catalog script | `script` | `scriptName`, optional `scriptArgs` |\n| Put a reasoning agent in the loop | `agent-task` (default) | `taskTemplate` |\n\nChoose `agent-task` only when the run needs judgment, open-ended work, or tool orchestration that no workflow or script covers. An `agent-task` whose template says "trigger workflow X" or "run script Y" is wrong: use the direct target instead.\n\nThe agent-task fields `targetAgentId`, `model`, `modelTier`, `taskTemplate`, `priority`, and `tags` do not apply to workflow or script targets. Workflow cooldowns still gate workflow targets.\n\n## Pick the timing\n\n| Shape | Fields |\n|---|---|\n| Recurring on a cron | `scheduleType: "recurring"`, `cronExpression` (for example `0 9 * * 1-5`), `timezone` (default `UTC`) |\n| Recurring on an interval | `scheduleType: "recurring"`, `intervalMs` (for example `3600000` for hourly) |\n| Once, at a time | `scheduleType: "one_time"`, `runAt` (ISO datetime) |\n| Once, after a delay | `scheduleType: "one_time"`, `delayMs` |\n\nGive the schedule a unique `name` and a one-line `description` that says what a human gets from it.\n\n## Write the task template (agent-task target)\n\nThe template is the whole task the agent receives. It must state:\n\n- the goal and the inputs (IDs, repo, channel),\n- where the result goes (a page, agent-fs, a Slack thread, a task output),\n- what done looks like.\n\n`targetAgentId` pins the task to one agent. Omit it to use the pool. `modelTier` (`smol`, `regular`, `smart`, `ultra`) is the portable way to pick a model. `model` is a provider-specific override.\n\nTasks created by a schedule are automatic tasks. Their completed output is not stored as memory unless the agent calls `store-progress` with `persistMemory: true`.\n\n## Check back later\n\nA task whose answer needs time (a build, a deploy, a reply) calls `defer-task` with `delayMs` or `runAt`, a `summary` of what you did so far, and a `note` that says what is pending. The tool completes the task and creates the one-off schedule for you. The task reaches its final state (`completed`) on this call, and the `summary` becomes its output. The wake-up task carries the deferred task as its parent, so you receive that task\'s context. Add `checks` to list what to verify on wake-up. Do not hand-roll this with `create-schedule`.\n\n## Secrets\n\nA `taskTemplate` and `scriptArgs` are stored as plain text and replayed on every run. They must not contain a token, password, or key. Call the external API from a script through a registered connection or a credential binding instead. See the `swarm-scripts` skill, section Secrets.\n\n## Verify before you leave\n\n1. `run-schedule-now` once and read the run result.\n2. `list-schedules` with `name` to confirm `nextRunAt` and `enabled`.\n3. For a script target, the script must exist at global scope: `script-search` by name.\n\n## Repair a failing schedule\n\n`list-schedules` with `lastRunStatus: "failed"` or `consecutiveErrorsMin: 3` lists the failing ones. Fix the cause, then `run-schedule-now` to confirm. A schedule you cannot fix now: `patch-schedule` with `enabled: false` and say so in your task output. A second schedule next to a broken one is not a fix.\n\n## Related skills\n\n- `scheduled-task-resilience`: waiting on CI, builds, deploys, or other slow jobs inside a scheduled task.\n- `swarm-scripts`: writing the script a `script` target runs.\n- `workflow-iterate`: building and testing the workflow a `workflow` target starts.\n';
10451
+ var content_default36 = '# Scheduling\n\nUse a schedule when work repeats on a clock, or when it must run once at a later time. On each tick the schedule creates one run. The run is a workflow, a catalog script, or an agent task.\n\n## Tools\n\n`list-schedules`, `create-schedule`, `update-schedule`, `patch-schedule`, `delete-schedule`, `run-schedule-now`. They are deferred. Load them with your harness tool search before the first call.\n\n## Pick the target type\n\n| The tick should | `targetType` | Required fields |\n|---|---|---|\n| Start a workflow | `workflow` | `workflowId` |\n| Run a catalog script | `script` | `scriptName`, optional `scriptArgs` |\n| Put a reasoning agent in the loop | `agent-task` (default) | `taskTemplate` |\n\nChoose `agent-task` only when the run needs judgment, open-ended work, or tool orchestration that no workflow or script covers. An `agent-task` whose template says "trigger workflow X" or "run script Y" is wrong: use the direct target instead.\n\nThe agent-task fields `targetAgentId`, `model`, `modelTier`, `taskTemplate`, `priority`, and `tags` do not apply to workflow or script targets. Workflow cooldowns still gate workflow targets.\n\n## Pick the timing\n\n| Shape | Fields |\n|---|---|\n| Recurring on a cron | `scheduleType: "recurring"`, `cronExpression` (for example `0 9 * * 1-5`), `timezone` (default `UTC`) |\n| Recurring on an interval | `scheduleType: "recurring"`, `intervalMs` (for example `3600000` for hourly) |\n| Once, at a time | `scheduleType: "one_time"`, `runAt` (ISO datetime) |\n| Once, after a delay | `scheduleType: "one_time"`, `delayMs` |\n\nGive the schedule a unique `name` and a one-line `description` that says what a human gets from it.\n\n## Write the task template (agent-task target)\n\nThe template is the whole task the agent receives. It must state:\n\n- the goal and the inputs (IDs, repo, channel),\n- where the result goes (a page, agent-fs, a Slack thread, a task output),\n- what done looks like.\n\n`targetAgentId` pins the task to one agent. Omit it to use the pool. `modelTier` (`smol`, `regular`, `smart`, `ultra`) is the portable way to pick a model. `model` is a provider-specific override.\n\nTasks created by a schedule are automatic tasks. Their completed output is not stored as memory unless the agent calls `store-progress` with `persistMemory: true`.\n\n## Check back later\n\nA task whose answer needs time (a build, a deploy, a reply) calls `defer-task` with `delayMs` or `runAt`, a `summary` of what you did so far, and a `note` that says what is pending. The tool completes the task and creates the one-off schedule for you. The task reaches its final state (`completed`) on this call, and the `summary` becomes its output. The wake-up task carries the deferred task as its parent, so you receive that task\'s context. Add `checks` to list what to verify on wake-up. Do not hand-roll this with `create-schedule`.\n\n## Secrets\n\nA `taskTemplate` and `scriptArgs` are stored as plain text and replayed on every run. They must not contain a token, password, or key. Call the external API from a script through a registered connection or a credential binding instead. See the `swarm-scripts` skill, section Secrets.\n\n## Verify before you leave\n\n1. `run-schedule-now` once and read the run result.\n2. `list-schedules` with `name` to confirm `nextRunAt` and `enabled`.\n3. For a script target, the script must exist at global scope: `script-search` by name.\n\n## Repair a failing schedule\n\n`list-schedules` with `lastRunStatus: "failed"` or `consecutiveErrorsMin: 3` lists the failing ones. Fix the cause, then `run-schedule-now` to confirm. A schedule you cannot fix now: `patch-schedule` with `enabled: false` and say so in your task output. A second schedule next to a broken one is not a fix.\n\n## Related skills\n\n- `scheduled-task-resilience`: waiting on CI, builds, deploys, or other slow jobs inside a scheduled task.\n- `swarm-scripts`: writing the script a `script` target runs.\n- `workflow-iterate`: building and testing the workflow a `workflow` target starts.\n';
10350
10452
 
10351
10453
  // templates/skills/script-builder/config.json
10352
- var config_default36 = `{
10454
+ var config_default37 = `{
10353
10455
  "category": "skills",
10354
10456
  "description": "Generate durable, re-runnable scripts from session intent — validation scripts (PASS/FAIL contract) AND gather/bulk scripts (many API/tool calls in code, one derived summary out). Supports TypeScript, Python, Bash with auto-detection, enforces context-optimal output, and auto-documents scripts in CLAUDE.md. Triggers on \\"turn this into a script\\", \\"I want to test/validate X end-to-end\\", \\"wrap this in a re-runnable script\\" — and, critically, whenever you are about to make (or just made) ~10+ similar tool/API calls or any bulk fan-out over a list: that mechanical middle belongs in a script, not in context.",
10355
10457
  "displayName": "Script Builder",
@@ -10370,10 +10472,10 @@ var config_default36 = `{
10370
10472
  `;
10371
10473
 
10372
10474
  // templates/skills/script-builder/content.md
10373
- var content_default36 = "# script-builder\n\nYou are converting session intent into a durable, re-runnable script committed to the target project's `scripts/` directory. Two script classes share one principle — **only the derived answer re-enters context; raw payloads never do**:\n\n- **Validation scripts** (`check-*`, `e2e-*`, `smoke-*`, …): a single PASS/FAIL line + `/tmp` log path on success, full verbose output redirected to a timestamped log file.\n- **Gather/bulk scripts** (`gather-*`, `bulk-*`): replace N similar tool/API calls with one script that loops, filters, and aggregates *in code* — stdout is one compact summary block (JSON or table), raw responses go to the `/tmp` log. Rubric (from production code-mode data): past ~10 items or any fan-out over a list, a script beats individual tool calls by ~100x on context and roughly halves end-to-end cost. Offer the script *before* the fan-out happens when you can see it coming, not just retrospectively.\n\nBoth classes get an `<important if>` block in `CLAUDE.md`/`AGENTS.md` so future agents discover the script when the intent recurs — durable scripts are reusable agent memory: import, don't re-derive.\n\n**Schema discovery happens in code, too**: when scripting against an unfamiliar API, grep/filter its OpenAPI spec or typed client programmatically to find the few relevant endpoints — never paste the full schema into context.\n\n## Working Agreement\n\nThese instructions establish a working agreement between you and the user. The key principles are:\n\n1. **AskUserQuestion is your primary communication tool** - Whenever you need to ask the user anything (clarifications, preferences, decisions, confirmations), use the **AskUserQuestion tool**. Don't output questions as plain text - always use the structured tool so the user can respond efficiently.\n\n2. **Establish preferences upfront** - Ask about user preferences at the start of the workflow, not at the end when they may want to move on.\n\n3. **Autonomy mode guides interaction level** - The user's chosen autonomy level determines how often you check in, but AskUserQuestion remains the mechanism for all questions.\n\n## When to Use\n\nThis skill activates when:\n- User invokes `/script-builder` command\n- Another skill references `**OPTIONAL SUB-SKILL:** desplega:script-builder`\n- A `planning`, `qa`, or `verifying` flow needs a re-runnable validation script that doesn't yet exist\n- The user expresses intent to \"turn X into a script\", \"wrap this validation into something reusable\", or \"I want to test X end-to-end\" with no existing script\n\n## Autonomy Mode\n\nAdapt your behavior based on the autonomy mode:\n\n| Mode | Behavior |\n|------|----------|\n| **Autopilot** | Detect mode, draft, syntax-check, document, and (if escalation tier) run + iterate without intermediate confirmations. Pause only at hard blockers or destructive side-effects. |\n| **Critical** (Default) | Confirm at each tier boundary (after draft, before doc edit, before run). Use AskUserQuestion for fix application during iterate loop. |\n| **Verbose** | Confirm before each step. Show every diff. Walk through detection reasoning out loud. |\n\nThe autonomy mode is passed by the invoking command. If not specified, default to **Critical**.\n\n## Process Steps\n\n### Step 1: Detect Mode (Retrospective vs Forward-Declared)\n\nDecide silently — **do not** ask the user \"which mode?\". Use the following heuristics:\n\n1. **Scan recent session tool-use history** (the last ~20 tool calls in the current conversation) for test/validation-shaped activity: `curl`/`fetch` calls, `bun run`/`python`/`pytest`, database queries, `agent-browser` actions, repeated `grep`/log inspection of a single endpoint or table. If ≥2 such actions targeting the same area exist → **retrospective mode**. Separately, if the history (or the task ahead) shows the *same call shape repeated ~10+ times or a fan-out over a list* → **gather-script mode**: propose replacing the repetition with one `gather-*` script before continuing.\n2. **Parse the user's invocation message** for cues:\n - Narrative cues → retrospective: *\"we just figured out\"*, *\"turn this into a script\"*, *\"wrap that in\"*, *\"that thing we just did\"*.\n - Intent cues → forward-declared: *\"I want to test\"*, *\"validate that\"*, *\"smoke check\"*, *\"check before deploy\"*.\n3. **Fallback**: when ambiguous, default to **forward-declared**.\n\n**Retrospective first action**: summarize the observed activity back to the user as plain text (≤6 lines: what was probed, against what, with what success signal), then go to Step 3 with a confirmation prompt instead of Q&A.\n\n**Forward first action**: skip directly to Step 3's Q&A.\n\n### Step 2: Scan Existing Scripts for Overlap\n\n**Resolve the scripts directory** in this order:\n1. Check `CLAUDE.md` for a `<!-- script-builder:dir=<path> -->` marker. If present, use that path.\n2. If `scripts/` exists at the repo root, use it.\n3. Use **AskUserQuestion** with options: `scripts/ (Recommended) | custom path | skip dir persistence for this run`.\n\n**Edge case — directory absent**: if the resolved path doesn't exist, skip the dedup scan, print a one-line note (`No existing scripts directory at <path> — proceeding to intent gathering`), and remember to optionally offer to create the directory before Step 5.\n\n**When the directory exists**:\n1. List files in the scripts directory (top-level only for v1).\n2. For each file, read the top of the file (header comment) and capture the file-name tokens.\n3. Read `CLAUDE.md`/`AGENTS.md` for `<important if=\"...\">` blocks that point at scripts in this directory and capture the trigger phrases.\n4. Fuzzy-match the current intent string against (file-name tokens ∪ header keywords ∪ trigger phrases). A \"plausible match\" is shared keyword + same area noun (e.g., `auth`, `health`, `webhook`).\n5. If ≥1 plausible match → use **AskUserQuestion** with options: `Reuse <name> as-is | Extend <name> | Generate new anyway`.\n\nNever silently skip dedup on borderline matches — surface and let the user decide. The **Extend** branch appends a sub-command/flag to the existing script (do not create a new file); document the new flag in the script's header comment and the existing `<important if>` block.\n\n### Step 3: Gather Intent\n\nBoth modes converge on the same internal intent structure: `{ what, success_signal, failure_signal, inputs, env, side_effects }`.\n\n**Forward mode** — use **AskUserQuestion** (one or two questions, not five):\n\n| Question | Options |\n|----------|---------|\n| \"What are we validating, and what's the success signal?\" | [Free text — collect what + success signal in one answer] |\n| \"Any required env vars, inputs, or side-effects to flag (e.g., writes to prod, costs money)?\" | [Free text — optional; skip if forward intent already specified them] |\n\n**Retrospective mode** — present the summary from Step 1 and use **AskUserQuestion** with: `That's the flow | Close but fix X | Start over`. On *Close but fix X*, ask for the correction inline; on *Start over*, fall through to forward-mode Q&A.\n\nPersist the resolved intent in working memory (do not write to disk yet).\n\n### Step 4: Detect Language\n\nPriority order — first match wins, with override paths:\n\n1. **TypeScript** — `package.json` + `tsconfig.json` exist.\n - **Bun** if `bun.lock` or `bunfig.toml` is present.\n - else **tsx** if `tsx` appears in `package.json` devDependencies.\n - else **compiled Node** (note in script header: requires `tsc` build).\n2. **Python** — `pyproject.toml` or `uv.lock` or `requirements.txt` exists.\n - **uv** if `uv.lock` exists or `pyproject.toml` has `[tool.uv]` configured (sets `{{UV_METADATA}}`).\n - else **vanilla python3** (`{{UV_METADATA}}` substituted with empty string).\n3. **Both TS and Python detected** — count source files in `src/`/top-level and ask **AskUserQuestion** tiebreaker with the dominant one Recommended.\n4. `Cargo.toml` / `go.mod` only → fall back to **bash** (note: TS/Python/Bash only in v1).\n5. Nothing matched → **bash**.\n\n**Task-driven override**: if the gathered intent is clearly shell-y (\"verify three docker containers respond\", \"tail this log file for an error\"), propose **bash** even in a TS/Python project.\n\nConfirm via **AskUserQuestion** with the detected language as the first option (Recommended). Skip in Autopilot.\n\n### Step 5: Draft the Script\n\n1. **Pick the template**: `templates/{typescript.ts.tmpl|python.py.tmpl|bash.sh.tmpl}`.\n2. **Resolve substitution markers** from gathered intent:\n - `{{SCRIPT_NAME}}` ← proposed file-name stem (see naming table).\n - `{{WHAT}}` / `{{WHEN}}` / `{{ENV}}` / `{{EXAMPLE}}` ← intent fields.\n - `{{UV_METADATA}}` ← per Step 4.\n3. **Generate `{{TEST_BODY}}`** from the intent. Keep it minimal: a single concrete probe + assertion, not a battery. Re-read the templates' README (`templates/README.md`) for the contract — the body must respect the PASS/FAIL surface. Throw/raise/`exit 1` on failure; let the template's outer try/trap convert it into the FAIL line.\n **Gather-class bodies** adapt the same template: the loop/aggregation replaces the probe, raw per-item responses go to the log only, and the final `console.log`/`print` emits one compact summary (JSON or aligned table) instead of the PASS line — exit non-zero only on operational failure (auth, network), not on \"found problems\" (problems ARE the output).\n4. **Propose a file name** matching the intent shape — see the prefix table below. Use **AskUserQuestion** with the proposed name first (Recommended) and `custom name` as the alternative.\n\n**Naming conventions** (advisory — skill proposes, user overrides):\n\n| Prefix | When | Example |\n|--------|------|---------|\n| `e2e-*` | End-to-end flows across multiple components | `e2e-auth-flow.ts` |\n| `check-*` | Idempotent single-probe verifications | `check-db-boundary.sh` |\n| `smoke-*` | Minimal-viability post-deploy checks | `smoke-prod-api.ts` |\n| `measure-*` | Performance / size / token measurements | `measure-tool-tokens.ts` |\n| `seed-*` / `generate-*` | Data seeding or artifact generation (rare for validation) | `seed-api-keys.sh` |\n| `gather-*` / `bulk-*` | Bulk data-gathering or bulk mutation replacing N tool calls; stdout = one summary block, not PASS/FAIL | `gather-workflow-health.ts` |\n\nIf the intent doesn't match any prefix cleanly, propose a free-form name like `validate-<area>.<ext>`.\n\n5. **Write the file** to the resolved scripts directory. Make it executable (`chmod +x`).\n\n### Step 6: Syntax/Type-Check\n\nRun the appropriate checker:\n\n| Language | Checker (in priority order) |\n|----------|-----------------------------|\n| TypeScript | `bunx tsc --noEmit <file>` if Bun present, else `npx tsc --noEmit <file>` |\n| Python | `python3 -m py_compile <file>` (always) + `ruff check <file>` if `ruff` is on PATH |\n| Bash | `shellcheck <file>` if available, else `bash -n <file>` |\n\n**On success**: log a single line (`syntax check OK`) and proceed to Step 7.\n\n**On failure**:\n1. Print the error (≤10 lines, not the full output).\n2. Propose a concrete one-edit fix (the exact `Edit` you'd apply).\n3. Use **AskUserQuestion** with `Apply fix | Investigate | Stop`.\n - **Apply fix** → edit the script and re-run the checker (loop, no hardcoded cap).\n - **Investigate** → drop into discussion with the user; do not auto-apply anything.\n - **Stop** → leave script in place at its path; print the path; do not delete.\n\n### Step 7: Document the Script\n\nAuto-edit the target project's `CLAUDE.md` and/or `AGENTS.md` so future agents discover this script when the matching intent recurs.\n\n**Block template** (the literal markdown the skill emits):\n\n```markdown\n<important if=\"[TRIGGER: e.g., you are testing the auth flow]\">\n\n## [Area] validation\n\nRun `scripts/<name>` to [one-liner]. Requires [env/deps]. Example: `<cmd>`. Full log at `/tmp/<name>-*.log`.\n\nGenerated/maintained via `/script-builder`.\n\n</important>\n```\n\n**Behavior**:\n\n1. **Target file selection**: edit `CLAUDE.md` and `AGENTS.md` if both exist; edit only what exists. **Never** create either file from scratch — if neither exists, print a one-line note (`No CLAUDE.md or AGENTS.md found — script generated but not documented`) and skip this step.\n2. **Placement heuristic**: search the file for the first heading matching `Test|Testing|Validation|Scripts` (case-insensitive). If found, append the new block within/after that section. Otherwise, append a new `## Scripts for testing & validation` section near the end of the file but **before** any heading matching `License|Acknowledg|Maintain|Contributors`.\n3. **Idempotency**: if a block referencing `scripts/<name>` already exists (i.e., a prior `/script-builder` run for the same script name), update it in place — replace the entire `<important if=...>...</important>` block, do not append a duplicate.\n4. **Scripts-dir marker**: if Step 2 resolved the scripts directory by user choice (not from an existing marker), insert `<!-- script-builder:dir=<path> -->` near the top of `CLAUDE.md` (after the title) so subsequent runs are silent. Skip if the marker already exists.\n5. **Scale gate — `scripts/index.md`**: if the scripts directory holds **>10 documented scripts**, per-script `<important if>` blocks become their own context bloat. Generate/maintain a `scripts/index.md` hub instead (one line + link per script, mirroring the `runbooks/` convention from `desplega:engineering-standards`), collapse the CLAUDE.md/AGENTS.md blocks into ONE pointer block referencing the hub, and add new scripts to the hub only.\n6. **Show the diff**: run the equivalent of `git diff CLAUDE.md AGENTS.md` and print a 5-line summary of what changed. **Never auto-stage** — the user commits.\n\n### Step 8: Offer Escalation\n\nAfter the doc edit, decide whether to proceed to the run-and-iterate tier.\n\n| Autonomy | Behavior |\n|----------|----------|\n| **Autopilot** | Auto-escalate to Step 9 unless the intent flagged side-effects (writes to prod, sends real money, mutates a shared resource). On flagged side-effects, fall through to Critical behavior. |\n| **Critical** (Default) | Use **AskUserQuestion**: `Run it now to confirm it works | I'll run it myself later | Just generate, don't run`. |\n| **Verbose** | Same as Critical, plus offer the proposed run command for review before executing. |\n\nIf the user picks \"I'll run it myself later\" or \"Just generate, don't run\" → skip directly to Step 10.\n\n### Step 9: Iterate on Failures (Escalated Tier Only)\n\nA bounded-by-the-human loop. **Never auto-apply a fix** outside Autopilot.\n\n1. **Run the script** with the proposed example invocation (no `--verbose`, no `--json`). Capture exit code and `tail -n 40` of the `/tmp` log.\n2. **If exit code 0** → report PASS (echo the script's PASS line) and proceed to Step 10.\n3. **If exit code non-zero**:\n - Summarize the failure in **1–3 lines**: error class (timeout / 4xx / 5xx / assertion / dependency-missing / etc.) + likely cause (grep the log for known signatures: `ECONNREFUSED`, `Traceback`, `non-zero exit`, `command not found`, etc.).\n - **Propose a concrete diff** — the exact `Edit` you would apply to the script. Show old → new.\n - Use **AskUserQuestion**: `Apply fix | Investigate differently | Stop`.\n - **Apply fix** → edit the script, log the change, loop back to (1).\n - **Investigate differently** → drop into discussion; do not auto-apply.\n - **Stop** → leave the script in place, print its path; do not revert.\n\n**No hardcoded retry cap** — the human is the implicit bound.\n\n**Side-effect flag**: if the intent declared side-effects (Step 3) and Autopilot is active, surface a one-line `WARNING: this script <does X> against <target>` before the first run and require explicit confirmation via **AskUserQuestion** even in Autopilot mode.\n\n### Step 10: Handoff\n\nHow the skill exits depends on how it was invoked:\n\n**Invoked as a sub-skill** (from `planning`, `qa`, `verifying`):\nReturn control to the parent skill with a structured summary: `{ script_path, status: \"pass\"|\"fail\"|\"unrun\", log_path?, doc_files_edited: [...] }`.\n\n**Invoked directly** (`/script-builder`):\nUse **AskUserQuestion**: `Run it with /qa | Run /verify-plan | Commit the script and doc changes | Done`.\n- **Run with /qa** → invoke `desplega:qa` with the script path as the source.\n- **Run /verify-plan** → invoke `desplega:verifying` if a plan path is in current context.\n- **Commit** → propose a commit message (`feat(scripts): add scripts/<name> for <area> validation`) and stage only the generated script + the CLAUDE.md/AGENTS.md edits. Do not auto-commit; show the proposed `git add` and `git commit` commands and require user confirmation.\n- **Done** → print the script path + log path (if escalation ran) and exit.\n\n**Abort path** (Stop selected at any earlier gate): leave the generated script in place, leave any CLAUDE.md/AGENTS.md edit in place if Step 7 ran, and print a one-liner: `Aborted. Script: <path>. Doc edits: <files or \"none\">. Re-run /script-builder or git checkout to discard.` Do not `git restore` on the user's behalf.\n\n## Learning Capture\n\n**OPTIONAL SUB-SKILL:** If significant insights, patterns, gotchas, or decisions emerged during this workflow, consider using `desplega:learning` to capture them via `/learning capture`. Focus on learnings that would help someone else in a future session.\n";
10475
+ var content_default37 = "# script-builder\n\nYou are converting session intent into a durable, re-runnable script committed to the target project's `scripts/` directory. Two script classes share one principle — **only the derived answer re-enters context; raw payloads never do**:\n\n- **Validation scripts** (`check-*`, `e2e-*`, `smoke-*`, …): a single PASS/FAIL line + `/tmp` log path on success, full verbose output redirected to a timestamped log file.\n- **Gather/bulk scripts** (`gather-*`, `bulk-*`): replace N similar tool/API calls with one script that loops, filters, and aggregates *in code* — stdout is one compact summary block (JSON or table), raw responses go to the `/tmp` log. Rubric (from production code-mode data): past ~10 items or any fan-out over a list, a script beats individual tool calls by ~100x on context and roughly halves end-to-end cost. Offer the script *before* the fan-out happens when you can see it coming, not just retrospectively.\n\nBoth classes get an `<important if>` block in `CLAUDE.md`/`AGENTS.md` so future agents discover the script when the intent recurs — durable scripts are reusable agent memory: import, don't re-derive.\n\n**Schema discovery happens in code, too**: when scripting against an unfamiliar API, grep/filter its OpenAPI spec or typed client programmatically to find the few relevant endpoints — never paste the full schema into context.\n\n## Working Agreement\n\nThese instructions establish a working agreement between you and the user. The key principles are:\n\n1. **AskUserQuestion is your primary communication tool** - Whenever you need to ask the user anything (clarifications, preferences, decisions, confirmations), use the **AskUserQuestion tool**. Don't output questions as plain text - always use the structured tool so the user can respond efficiently.\n\n2. **Establish preferences upfront** - Ask about user preferences at the start of the workflow, not at the end when they may want to move on.\n\n3. **Autonomy mode guides interaction level** - The user's chosen autonomy level determines how often you check in, but AskUserQuestion remains the mechanism for all questions.\n\n## When to Use\n\nThis skill activates when:\n- User invokes `/script-builder` command\n- Another skill references `**OPTIONAL SUB-SKILL:** desplega:script-builder`\n- A `planning`, `qa`, or `verifying` flow needs a re-runnable validation script that doesn't yet exist\n- The user expresses intent to \"turn X into a script\", \"wrap this validation into something reusable\", or \"I want to test X end-to-end\" with no existing script\n\n## Autonomy Mode\n\nAdapt your behavior based on the autonomy mode:\n\n| Mode | Behavior |\n|------|----------|\n| **Autopilot** | Detect mode, draft, syntax-check, document, and (if escalation tier) run + iterate without intermediate confirmations. Pause only at hard blockers or destructive side-effects. |\n| **Critical** (Default) | Confirm at each tier boundary (after draft, before doc edit, before run). Use AskUserQuestion for fix application during iterate loop. |\n| **Verbose** | Confirm before each step. Show every diff. Walk through detection reasoning out loud. |\n\nThe autonomy mode is passed by the invoking command. If not specified, default to **Critical**.\n\n## Process Steps\n\n### Step 1: Detect Mode (Retrospective vs Forward-Declared)\n\nDecide silently — **do not** ask the user \"which mode?\". Use the following heuristics:\n\n1. **Scan recent session tool-use history** (the last ~20 tool calls in the current conversation) for test/validation-shaped activity: `curl`/`fetch` calls, `bun run`/`python`/`pytest`, database queries, `agent-browser` actions, repeated `grep`/log inspection of a single endpoint or table. If ≥2 such actions targeting the same area exist → **retrospective mode**. Separately, if the history (or the task ahead) shows the *same call shape repeated ~10+ times or a fan-out over a list* → **gather-script mode**: propose replacing the repetition with one `gather-*` script before continuing.\n2. **Parse the user's invocation message** for cues:\n - Narrative cues → retrospective: *\"we just figured out\"*, *\"turn this into a script\"*, *\"wrap that in\"*, *\"that thing we just did\"*.\n - Intent cues → forward-declared: *\"I want to test\"*, *\"validate that\"*, *\"smoke check\"*, *\"check before deploy\"*.\n3. **Fallback**: when ambiguous, default to **forward-declared**.\n\n**Retrospective first action**: summarize the observed activity back to the user as plain text (≤6 lines: what was probed, against what, with what success signal), then go to Step 3 with a confirmation prompt instead of Q&A.\n\n**Forward first action**: skip directly to Step 3's Q&A.\n\n### Step 2: Scan Existing Scripts for Overlap\n\n**Resolve the scripts directory** in this order:\n1. Check `CLAUDE.md` for a `<!-- script-builder:dir=<path> -->` marker. If present, use that path.\n2. If `scripts/` exists at the repo root, use it.\n3. Use **AskUserQuestion** with options: `scripts/ (Recommended) | custom path | skip dir persistence for this run`.\n\n**Edge case — directory absent**: if the resolved path doesn't exist, skip the dedup scan, print a one-line note (`No existing scripts directory at <path> — proceeding to intent gathering`), and remember to optionally offer to create the directory before Step 5.\n\n**When the directory exists**:\n1. List files in the scripts directory (top-level only for v1).\n2. For each file, read the top of the file (header comment) and capture the file-name tokens.\n3. Read `CLAUDE.md`/`AGENTS.md` for `<important if=\"...\">` blocks that point at scripts in this directory and capture the trigger phrases.\n4. Fuzzy-match the current intent string against (file-name tokens ∪ header keywords ∪ trigger phrases). A \"plausible match\" is shared keyword + same area noun (e.g., `auth`, `health`, `webhook`).\n5. If ≥1 plausible match → use **AskUserQuestion** with options: `Reuse <name> as-is | Extend <name> | Generate new anyway`.\n\nNever silently skip dedup on borderline matches — surface and let the user decide. The **Extend** branch appends a sub-command/flag to the existing script (do not create a new file); document the new flag in the script's header comment and the existing `<important if>` block.\n\n### Step 3: Gather Intent\n\nBoth modes converge on the same internal intent structure: `{ what, success_signal, failure_signal, inputs, env, side_effects }`.\n\n**Forward mode** — use **AskUserQuestion** (one or two questions, not five):\n\n| Question | Options |\n|----------|---------|\n| \"What are we validating, and what's the success signal?\" | [Free text — collect what + success signal in one answer] |\n| \"Any required env vars, inputs, or side-effects to flag (e.g., writes to prod, costs money)?\" | [Free text — optional; skip if forward intent already specified them] |\n\n**Retrospective mode** — present the summary from Step 1 and use **AskUserQuestion** with: `That's the flow | Close but fix X | Start over`. On *Close but fix X*, ask for the correction inline; on *Start over*, fall through to forward-mode Q&A.\n\nPersist the resolved intent in working memory (do not write to disk yet).\n\n### Step 4: Detect Language\n\nPriority order — first match wins, with override paths:\n\n1. **TypeScript** — `package.json` + `tsconfig.json` exist.\n - **Bun** if `bun.lock` or `bunfig.toml` is present.\n - else **tsx** if `tsx` appears in `package.json` devDependencies.\n - else **compiled Node** (note in script header: requires `tsc` build).\n2. **Python** — `pyproject.toml` or `uv.lock` or `requirements.txt` exists.\n - **uv** if `uv.lock` exists or `pyproject.toml` has `[tool.uv]` configured (sets `{{UV_METADATA}}`).\n - else **vanilla python3** (`{{UV_METADATA}}` substituted with empty string).\n3. **Both TS and Python detected** — count source files in `src/`/top-level and ask **AskUserQuestion** tiebreaker with the dominant one Recommended.\n4. `Cargo.toml` / `go.mod` only → fall back to **bash** (note: TS/Python/Bash only in v1).\n5. Nothing matched → **bash**.\n\n**Task-driven override**: if the gathered intent is clearly shell-y (\"verify three docker containers respond\", \"tail this log file for an error\"), propose **bash** even in a TS/Python project.\n\nConfirm via **AskUserQuestion** with the detected language as the first option (Recommended). Skip in Autopilot.\n\n### Step 5: Draft the Script\n\n1. **Pick the template**: `templates/{typescript.ts.tmpl|python.py.tmpl|bash.sh.tmpl}`.\n2. **Resolve substitution markers** from gathered intent:\n - `{{SCRIPT_NAME}}` ← proposed file-name stem (see naming table).\n - `{{WHAT}}` / `{{WHEN}}` / `{{ENV}}` / `{{EXAMPLE}}` ← intent fields.\n - `{{UV_METADATA}}` ← per Step 4.\n3. **Generate `{{TEST_BODY}}`** from the intent. Keep it minimal: a single concrete probe + assertion, not a battery. Re-read the templates' README (`templates/README.md`) for the contract — the body must respect the PASS/FAIL surface. Throw/raise/`exit 1` on failure; let the template's outer try/trap convert it into the FAIL line.\n **Gather-class bodies** adapt the same template: the loop/aggregation replaces the probe, raw per-item responses go to the log only, and the final `console.log`/`print` emits one compact summary (JSON or aligned table) instead of the PASS line — exit non-zero only on operational failure (auth, network), not on \"found problems\" (problems ARE the output).\n4. **Propose a file name** matching the intent shape — see the prefix table below. Use **AskUserQuestion** with the proposed name first (Recommended) and `custom name` as the alternative.\n\n**Naming conventions** (advisory — skill proposes, user overrides):\n\n| Prefix | When | Example |\n|--------|------|---------|\n| `e2e-*` | End-to-end flows across multiple components | `e2e-auth-flow.ts` |\n| `check-*` | Idempotent single-probe verifications | `check-db-boundary.sh` |\n| `smoke-*` | Minimal-viability post-deploy checks | `smoke-prod-api.ts` |\n| `measure-*` | Performance / size / token measurements | `measure-tool-tokens.ts` |\n| `seed-*` / `generate-*` | Data seeding or artifact generation (rare for validation) | `seed-api-keys.sh` |\n| `gather-*` / `bulk-*` | Bulk data-gathering or bulk mutation replacing N tool calls; stdout = one summary block, not PASS/FAIL | `gather-workflow-health.ts` |\n\nIf the intent doesn't match any prefix cleanly, propose a free-form name like `validate-<area>.<ext>`.\n\n5. **Write the file** to the resolved scripts directory. Make it executable (`chmod +x`).\n\n### Step 6: Syntax/Type-Check\n\nRun the appropriate checker:\n\n| Language | Checker (in priority order) |\n|----------|-----------------------------|\n| TypeScript | `bunx tsc --noEmit <file>` if Bun present, else `npx tsc --noEmit <file>` |\n| Python | `python3 -m py_compile <file>` (always) + `ruff check <file>` if `ruff` is on PATH |\n| Bash | `shellcheck <file>` if available, else `bash -n <file>` |\n\n**On success**: log a single line (`syntax check OK`) and proceed to Step 7.\n\n**On failure**:\n1. Print the error (≤10 lines, not the full output).\n2. Propose a concrete one-edit fix (the exact `Edit` you'd apply).\n3. Use **AskUserQuestion** with `Apply fix | Investigate | Stop`.\n - **Apply fix** → edit the script and re-run the checker (loop, no hardcoded cap).\n - **Investigate** → drop into discussion with the user; do not auto-apply anything.\n - **Stop** → leave script in place at its path; print the path; do not delete.\n\n### Step 7: Document the Script\n\nAuto-edit the target project's `CLAUDE.md` and/or `AGENTS.md` so future agents discover this script when the matching intent recurs.\n\n**Block template** (the literal markdown the skill emits):\n\n```markdown\n<important if=\"[TRIGGER: e.g., you are testing the auth flow]\">\n\n## [Area] validation\n\nRun `scripts/<name>` to [one-liner]. Requires [env/deps]. Example: `<cmd>`. Full log at `/tmp/<name>-*.log`.\n\nGenerated/maintained via `/script-builder`.\n\n</important>\n```\n\n**Behavior**:\n\n1. **Target file selection**: edit `CLAUDE.md` and `AGENTS.md` if both exist; edit only what exists. **Never** create either file from scratch — if neither exists, print a one-line note (`No CLAUDE.md or AGENTS.md found — script generated but not documented`) and skip this step.\n2. **Placement heuristic**: search the file for the first heading matching `Test|Testing|Validation|Scripts` (case-insensitive). If found, append the new block within/after that section. Otherwise, append a new `## Scripts for testing & validation` section near the end of the file but **before** any heading matching `License|Acknowledg|Maintain|Contributors`.\n3. **Idempotency**: if a block referencing `scripts/<name>` already exists (i.e., a prior `/script-builder` run for the same script name), update it in place — replace the entire `<important if=...>...</important>` block, do not append a duplicate.\n4. **Scripts-dir marker**: if Step 2 resolved the scripts directory by user choice (not from an existing marker), insert `<!-- script-builder:dir=<path> -->` near the top of `CLAUDE.md` (after the title) so subsequent runs are silent. Skip if the marker already exists.\n5. **Scale gate — `scripts/index.md`**: if the scripts directory holds **>10 documented scripts**, per-script `<important if>` blocks become their own context bloat. Generate/maintain a `scripts/index.md` hub instead (one line + link per script, mirroring the `runbooks/` convention from `desplega:engineering-standards`), collapse the CLAUDE.md/AGENTS.md blocks into ONE pointer block referencing the hub, and add new scripts to the hub only.\n6. **Show the diff**: run the equivalent of `git diff CLAUDE.md AGENTS.md` and print a 5-line summary of what changed. **Never auto-stage** — the user commits.\n\n### Step 8: Offer Escalation\n\nAfter the doc edit, decide whether to proceed to the run-and-iterate tier.\n\n| Autonomy | Behavior |\n|----------|----------|\n| **Autopilot** | Auto-escalate to Step 9 unless the intent flagged side-effects (writes to prod, sends real money, mutates a shared resource). On flagged side-effects, fall through to Critical behavior. |\n| **Critical** (Default) | Use **AskUserQuestion**: `Run it now to confirm it works | I'll run it myself later | Just generate, don't run`. |\n| **Verbose** | Same as Critical, plus offer the proposed run command for review before executing. |\n\nIf the user picks \"I'll run it myself later\" or \"Just generate, don't run\" → skip directly to Step 10.\n\n### Step 9: Iterate on Failures (Escalated Tier Only)\n\nA bounded-by-the-human loop. **Never auto-apply a fix** outside Autopilot.\n\n1. **Run the script** with the proposed example invocation (no `--verbose`, no `--json`). Capture exit code and `tail -n 40` of the `/tmp` log.\n2. **If exit code 0** → report PASS (echo the script's PASS line) and proceed to Step 10.\n3. **If exit code non-zero**:\n - Summarize the failure in **1–3 lines**: error class (timeout / 4xx / 5xx / assertion / dependency-missing / etc.) + likely cause (grep the log for known signatures: `ECONNREFUSED`, `Traceback`, `non-zero exit`, `command not found`, etc.).\n - **Propose a concrete diff** — the exact `Edit` you would apply to the script. Show old → new.\n - Use **AskUserQuestion**: `Apply fix | Investigate differently | Stop`.\n - **Apply fix** → edit the script, log the change, loop back to (1).\n - **Investigate differently** → drop into discussion; do not auto-apply.\n - **Stop** → leave the script in place, print its path; do not revert.\n\n**No hardcoded retry cap** — the human is the implicit bound.\n\n**Side-effect flag**: if the intent declared side-effects (Step 3) and Autopilot is active, surface a one-line `WARNING: this script <does X> against <target>` before the first run and require explicit confirmation via **AskUserQuestion** even in Autopilot mode.\n\n### Step 10: Handoff\n\nHow the skill exits depends on how it was invoked:\n\n**Invoked as a sub-skill** (from `planning`, `qa`, `verifying`):\nReturn control to the parent skill with a structured summary: `{ script_path, status: \"pass\"|\"fail\"|\"unrun\", log_path?, doc_files_edited: [...] }`.\n\n**Invoked directly** (`/script-builder`):\nUse **AskUserQuestion**: `Run it with /qa | Run /verify-plan | Commit the script and doc changes | Done`.\n- **Run with /qa** → invoke `desplega:qa` with the script path as the source.\n- **Run /verify-plan** → invoke `desplega:verifying` if a plan path is in current context.\n- **Commit** → propose a commit message (`feat(scripts): add scripts/<name> for <area> validation`) and stage only the generated script + the CLAUDE.md/AGENTS.md edits. Do not auto-commit; show the proposed `git add` and `git commit` commands and require user confirmation.\n- **Done** → print the script path + log path (if escalation ran) and exit.\n\n**Abort path** (Stop selected at any earlier gate): leave the generated script in place, leave any CLAUDE.md/AGENTS.md edit in place if Step 7 ran, and print a one-liner: `Aborted. Script: <path>. Doc edits: <files or \"none\">. Re-run /script-builder or git checkout to discard.` Do not `git restore` on the user's behalf.\n\n## Learning Capture\n\n**OPTIONAL SUB-SKILL:** If significant insights, patterns, gotchas, or decisions emerged during this workflow, consider using `desplega:learning` to capture them via `/learning capture`. Focus on learnings that would help someone else in a future session.\n";
10374
10476
 
10375
10477
  // templates/skills/script-workflows/config.json
10376
- var config_default37 = `{
10478
+ var config_default38 = `{
10377
10479
  "kind": "skill",
10378
10480
  "name": "script-workflows",
10379
10481
  "displayName": "Script Workflows",
@@ -10390,16 +10492,16 @@ var config_default37 = `{
10390
10492
  `;
10391
10493
 
10392
10494
  // templates/skills/script-workflows/content.md
10393
- var content_default37 = "Use this skill when a user asks to launch, monitor, inspect, or debug a durable script workflow run. This is for the Script Workflows v1 runtime: one-off TypeScript workflow source with journaled `swarm-script`, `raw-llm`, and `agent-task` steps.\n\n## Tool Flow\n\nLoad the script workflow tools with ToolSearch when they are not already visible:\n\n```text\nlaunch-script-run\nget-script-run\nlist-script-runs\n```\n\nUse `launch-script-run` to start a one-off run. It calls the same `/api/script-runs` API as the dashboard, preserves the invoking agent identity, and starts the run in the background.\n\nUse `get-script-run` to read terminal status and journal entries. Poll it when needed, but keep polling bounded and report progress for long runs.\n\nUse `list-script-runs` to find recent runs or filter by `status` / `agentId`.\n\nDo not hand-roll raw HTTP for this flow unless the tool itself is broken and you are explicitly debugging the API. The tool handles auth and `X-Agent-ID` like the existing inline `script-run` tool family.\n\n## Source Shape\n\nAuthor TypeScript workflow source as a default export. The runtime provides `args` and `ctx`.\n\n```ts\nexport default async function main(args, ctx) {\n const lookup = await ctx.step.swarmScript(\"lookup-data\", {\n scriptName: \"fetch-readable\",\n args: { url: args.url },\n });\n\n const summary = await ctx.step.rawLlm(\"summarize\", {\n prompt: `Summarize this for an operator:\\n${JSON.stringify(lookup)}`,\n });\n\n const task = await ctx.step.agentTask(\"operator-review\", {\n task: `Review this summary and flag risks:\\n${JSON.stringify(summary)}`,\n tags: [\"script-run\"],\n priority: 50,\n });\n\n return { lookup, summary, task };\n}\n```\n\n`ctx.step.agentTask` blocks until the dispatched task reaches a terminal status (default `waitForCompletion: true`, default `timeoutMs` 2h) and journals its real output — a sequential `plan → implement → review` chain will not fan out. Pass `waitForCompletion: false` for the legacy fire-and-poll-yourself shape, or `failOnTaskFailure: false` to receive `{taskId, status: \"failed\", error}` instead of a throw when the task fails/is cancelled.\n\n## Label Rules\n\nStep labels are durability keys. They must be stable and unique for each logical step. Do not reuse the same literal label inside a loop; launch will fail with `label_lint_violation`.\n\nFor looped work, include an item identifier in the label:\n\n```ts\nfor (const item of args.items) {\n await ctx.step.agentTask(`review-${item.id}`, { task: item.prompt });\n}\n```\n\n## Statuses\n\nTerminal statuses to surface clearly:\n\n- `completed` — run finished and `output` may be present.\n- `failed` — run ended with `error`.\n- `cancelled` — run was cancelled before completion.\n- `aborted_limit` — runtime guardrail stopped the run, usually step count, agent-task count, or wall-clock cap.\n- `label_lint_violation` — launch-time rejection, not a persisted run status.\n\nWhen a run is not terminal, report the current status, journal count, and latest heartbeat if present.\n";
10495
+ var content_default38 = "Use this skill when a user asks to launch, monitor, inspect, or debug a durable script workflow run. This is for the Script Workflows v1 runtime: one-off TypeScript workflow source with journaled `swarm-script`, `raw-llm`, and `agent-task` steps.\n\n## Tool Flow\n\nLoad the script workflow tools with ToolSearch when they are not already visible:\n\n```text\nlaunch-script-run\nget-script-run\nlist-script-runs\n```\n\nUse `launch-script-run` to start a one-off run. It calls the same `/api/script-runs` API as the dashboard, preserves the invoking agent identity, and starts the run in the background.\n\nUse `get-script-run` to read terminal status and journal entries. Poll it when needed, but keep polling bounded and report progress for long runs.\n\nUse `list-script-runs` to find recent runs or filter by `status` / `agentId`.\n\nDo not hand-roll raw HTTP for this flow unless the tool itself is broken and you are explicitly debugging the API. The tool handles auth and `X-Agent-ID` like the existing inline `script-run` tool family.\n\n## Source Shape\n\nAuthor TypeScript workflow source as a default export. The runtime provides `args` and `ctx`.\n\n```ts\nexport default async function main(args, ctx) {\n const lookup = await ctx.step.swarmScript(\"lookup-data\", {\n scriptName: \"fetch-readable\",\n args: { url: args.url },\n });\n\n const summary = await ctx.step.rawLlm(\"summarize\", {\n prompt: `Summarize this for an operator:\\n${JSON.stringify(lookup)}`,\n });\n\n const task = await ctx.step.agentTask(\"operator-review\", {\n task: `Review this summary and flag risks:\\n${JSON.stringify(summary)}`,\n tags: [\"script-run\"],\n priority: 50,\n });\n\n return { lookup, summary, task };\n}\n```\n\n`ctx.step.agentTask` blocks until the dispatched task reaches a terminal status (default `waitForCompletion: true`, default `timeoutMs` 2h) and journals its real output — a sequential `plan → implement → review` chain will not fan out. Pass `waitForCompletion: false` for the legacy fire-and-poll-yourself shape, or `failOnTaskFailure: false` to receive `{taskId, status: \"failed\", error}` instead of a throw when the task fails/is cancelled.\n\n## Label Rules\n\nStep labels are durability keys. They must be stable and unique for each logical step. Do not reuse the same literal label inside a loop; launch will fail with `label_lint_violation`.\n\nFor looped work, include an item identifier in the label:\n\n```ts\nfor (const item of args.items) {\n await ctx.step.agentTask(`review-${item.id}`, { task: item.prompt });\n}\n```\n\n## Statuses\n\nTerminal statuses to surface clearly:\n\n- `completed` — run finished and `output` may be present.\n- `failed` — run ended with `error`.\n- `cancelled` — run was cancelled before completion.\n- `aborted_limit` — runtime guardrail stopped the run, usually step count, agent-task count, or wall-clock cap.\n- `label_lint_violation` — launch-time rejection, not a persisted run status.\n\nWhen a run is not terminal, report the current status, journal count, and latest heartbeat if present.\n";
10394
10496
 
10395
10497
  // templates/skills/slack-interaction/config.json
10396
- var config_default38 = '{\n "kind": "skill",\n "name": "slack-interaction",\n "displayName": "Slack Interaction",\n "slug": "slack-interaction",\n "title": "Slack Interaction",\n "description": "Slack: reply, post, read, upload, and the thread rules. What the engine already posts, the one-message rule, `slack-reply`, `slack-post`, `slack-start-thread`, `slack-read`, `slack-upload-file`, `slack-download-file`, `slack-list-channels`, `slack-update`, `slack-delete`, unknown-user registration with `manage-user`, and Slack standing orders. Use before any Slack message.",\n "version": "1.0.0",\n "category": "skills",\n "placeholders": [],\n "runAllSeedersCandidate": true,\n "systemDefault": true,\n "tags": ["slack", "communication"]\n}\n';
10498
+ var config_default39 = '{\n "kind": "skill",\n "name": "slack-interaction",\n "displayName": "Slack Interaction",\n "slug": "slack-interaction",\n "title": "Slack Interaction",\n "description": "Slack: reply, post, read, upload, and the thread rules. What the engine already posts, the one-message rule, `slack-reply`, `slack-post`, `slack-start-thread`, `slack-read`, `slack-upload-file`, `slack-download-file`, `slack-list-channels`, `slack-update`, `slack-delete`, unknown-user registration with `manage-user`, and Slack standing orders. Use before any Slack message.",\n "version": "1.0.0",\n "category": "skills",\n "placeholders": [],\n "runAllSeedersCandidate": true,\n "systemDefault": true,\n "tags": ["slack", "communication"]\n}\n';
10397
10499
 
10398
10500
  // templates/skills/slack-interaction/content.md
10399
- var content_default38 = '# Slack interaction\n\n## What the engine posts\n\nFor every task that came from Slack, the engine owns the thread tree and the top-level outcome card. It posts the start, the completion, and the failure. You do not.\n\n## Your one message\n\n- At most one message per task, and only when the outcome card will not carry it: a question, a decision the requester must make, a link to a page or file with one line of context.\n- Progress, receipts, acknowledgments, and relayed worker output stay out of Slack.\n- Concrete content. The length matches what the requester asked for.\n- The "How you write" rules of your system prompt apply. Slack renders mrkdwn: `*bold*`, `_italic_`, `` `code` ``, `<url|text>` for links. Markdown headings and tables do not render.\n\n## Where to post\n\nThe task carries `slackChannelId` and `slackThreadTs` in its metadata. A follow-up task with `parentTaskId` inherits them.\n\n- Reply in the task\'s thread: `slack-reply` with `taskId` and `message`.\n- Reply to an inbox message: `slack-reply` with `inboxMessageId`.\n- New top-level message in a channel (lead): `slack-start-thread` with `channelId`, then `slack-post` with the returned `ts` as `threadTs` for replies under it.\n- Fix your own message: `slack-update` (text) or `slack-delete` (lead). Both work only on messages this bot authored.\n\n## Tools\n\n| Tool | Use |\n|---|---|\n| `slack-reply` | reply in a thread by `taskId` or `inboxMessageId` |\n| `slack-post` | post to a channel, optional `threadTs` (lead) |\n| `slack-start-thread` | post a top-level message and get its `ts` (lead) |\n| `slack-read` | read a thread by `taskId` or `inboxMessageId`, or a channel by `channelId` (lead) |\n| `slack-list-channels` | channels the bot is a member of |\n| `slack-upload-file` | upload a file to a thread or channel, up to 1 GB |\n| `slack-download-file` | attach a Slack file (by ID or URL) to your task; run the `fetchCommand` it returns to get the bytes |\n| `slack-update` | edit your own message |\n| `slack-delete` | delete your own message (lead) |\n| `slack-create-channel`, `slack-invite-to-channel`, `slack-archive-channel` | channel lifecycle (lead) |\n\nFiles attached to your task already come with download commands in the task message. Use those before `slack-download-file`. `slack-read` on your task also attaches the files in the thread and gives each one a `fetchCommand`. Don\'t look for Slack files under `/app/shared` or `/workspace/shared/downloads`: those paths are the API server\'s disk.\n\n## Unknown user\n\nA task without `requestedByUserId` came from a Slack user the swarm does not know. Register them with `manage-user`, using the Slack user ID and display name from the task metadata, then continue. When you learn a requester\'s stable preferences (language, tone, verbosity), the lead stores them in the user\'s `comms` field with `manage-user`.\n\n## Lead standing orders\n\nWhen your heartbeat runbook says so, check for unaddressed requests older than one hour: `slack-list-channels`, then `slack-read` per channel, then create a task for each open request.\n\n## Scripts-only mode\n\nThe named Slack tools are not registered. Use `script-run` with inline source: `ctx.swarm.slack_reply({ taskId, message })`. The task ID carries the thread context.\n';
10501
+ var content_default39 = '# Slack interaction\n\n## What the engine posts\n\nFor every task that came from Slack, the engine owns the thread tree and the top-level outcome card. It posts the start, the completion, and the failure. You do not.\n\n## Your one message\n\n- At most one message per task, and only when the outcome card will not carry it: a question, a decision the requester must make, a link to a page or file with one line of context.\n- Progress, receipts, acknowledgments, and relayed worker output stay out of Slack.\n- Concrete content. The length matches what the requester asked for.\n- The "How you write" rules of your system prompt apply. Slack renders mrkdwn: `*bold*`, `_italic_`, `` `code` ``, `<url|text>` for links. Markdown headings and tables do not render.\n\n## Where to post\n\nThe task carries `slackChannelId` and `slackThreadTs` in its metadata. A follow-up task with `parentTaskId` inherits them.\n\n- Reply in the task\'s thread: `slack-reply` with `taskId` and `message`.\n- Reply to an inbox message: `slack-reply` with `inboxMessageId`.\n- New top-level message in a channel (lead): `slack-start-thread` with `channelId`, then `slack-post` with the returned `ts` as `threadTs` for replies under it.\n- Fix your own message: `slack-update` (text) or `slack-delete` (lead). Both work only on messages this bot authored.\n\n## Tools\n\n| Tool | Use |\n|---|---|\n| `slack-reply` | reply in a thread by `taskId` or `inboxMessageId` |\n| `slack-post` | post to a channel, optional `threadTs` (lead) |\n| `slack-start-thread` | post a top-level message and get its `ts` (lead) |\n| `slack-read` | read a thread by `taskId` or `inboxMessageId`, or a channel by `channelId` (lead) |\n| `slack-list-channels` | channels the bot is a member of |\n| `slack-upload-file` | upload a file to a thread or channel, up to 1 GB |\n| `slack-download-file` | attach a Slack file (by ID or URL) to your task; run the `fetchCommand` it returns to get the bytes |\n| `slack-update` | edit your own message |\n| `slack-delete` | delete your own message (lead) |\n| `slack-create-channel`, `slack-invite-to-channel`, `slack-archive-channel` | channel lifecycle (lead) |\n\nFiles attached to your task already come with download commands in the task message. Use those before `slack-download-file`. `slack-read` on your task also attaches the files in the thread and gives each one a `fetchCommand`. Don\'t look for Slack files under `/app/shared` or `/workspace/shared/downloads`: those paths are the API server\'s disk.\n\n## Unknown user\n\nA task without `requestedByUserId` came from a Slack user the swarm does not know. Register them with `manage-user`, using the Slack user ID and display name from the task metadata, then continue. When you learn a requester\'s stable preferences (language, tone, verbosity), the lead stores them in the user\'s `comms` field with `manage-user`.\n\n## Lead standing orders\n\nWhen your heartbeat runbook says so, check for unaddressed requests older than one hour: `slack-list-channels`, then `slack-read` per channel, then create a task for each open request.\n\n## Scripts-only mode\n\nThe named Slack tools are not registered. Use `script-run` with inline source: `ctx.swarm.slack_reply({ taskId, message })`. The task ID carries the thread context.\n';
10400
10502
 
10401
10503
  // templates/skills/step-running/config.json
10402
- var config_default39 = `{
10504
+ var config_default40 = `{
10403
10505
  "category": "skills",
10404
10506
  "description": "Execute a single DAG step as an autonomous background sub-agent. Sibling of phase-running for DAG plans produced by v-planning. Reads a step-<n>.md file directly, atomically claims it via frontmatter status, runs the three-bucket Success Criteria, and reports back. Spawned by v-implementing or by /run-step.",
10405
10507
  "displayName": "Step Running",
@@ -10420,10 +10522,10 @@ var config_default39 = `{
10420
10522
  `;
10421
10523
 
10422
10524
  // templates/skills/step-running/content.md
10423
- var content_default39 = "# Step Running\n\nYou execute a single step of a DAG plan as an atomic background sub-agent. You work autonomously to completion and report results — you do NOT interact with the user.\n\nThis is the DAG sibling of `phase-running`. The execution model and atomicity contract are identical; the differences are:\n- You receive a **step file path** (`step-<n>.md`), not a plan path + phase number.\n- You **claim the step atomically** via the step's frontmatter `status` field before doing work, and release it on completion / failure. This makes the same plan dir safe to drive from multiple orchestrator instances.\n\n## Execution Model\n\nThis skill runs inside a background `Agent` (sub-agent). v-implementing (or a user invoking `/run-step`) spawns it via the Agent tool with `run_in_background: true`.\n\nThe step agent receives:\n- **Step path**: full path to `step-<n>.md`\n- **Plan dir**: full path to the parent plan directory (read `root.md` from here for plan-level context)\n- **Agent ID**: unique identifier for this sub-agent (e.g. orchestrator session ID + step ID + timestamp). Used for atomic claim + stale-claim detection.\n- **Relevant context**: any extra context from the caller\n\n## Concurrency: Atomic Claim\n\nBefore doing any work, claim the step:\n\n1. Read the step file's frontmatter.\n2. **If `status: done`** — report `Status: skipped` and exit. The step is already finished.\n3. **If `status: claimed`** and `assignee` differs from your agent ID:\n - Fresh claim (`claimed_at` within last hour): report `Status: blocked` (reason: `claimed by <other-id>`) and exit.\n - Stale claim (>1h): proceed and overwrite — the previous worker likely died.\n4. **Otherwise** (`status: ready`, or stale `claimed`): rewrite the frontmatter block in a single `Edit` so the write is atomic-enough for filesystem-based coordination. Set:\n - `status: claimed`\n - `assignee: <your-agent-id>`\n - `claimed_at: <ISO timestamp UTC>`\n5. Re-read the file. If `assignee` is not yours, another worker raced you — report `Status: blocked` (reason: `lost claim race`) and exit.\n\nOn terminal transitions, set frontmatter:\n- **Completed**: `status: done`, clear `assignee` and `claimed_at`.\n- **Blocked or failed (retry-able)**: `status: ready`, clear `assignee` and `claimed_at`. The orchestrator (or another worker) can retry.\n- **Failed (non-retry-able)**: leave `status: claimed` so the orchestrator can investigate; include the reason in the report.\n\nFor true cross-machine atomicity (NFS, etc.), the caller is responsible for rendezvous (e.g. a shared lock service). The single-Edit pattern is good-enough for local filesystem and well-behaved network filesystems.\n\n## Autonomy\n\nStep agents always run as **Autopilot** within the sub-agent. The calling context controls outer autonomy and human checkpoints.\n\n**CRITICAL**: Step agents do NOT use AskUserQuestion. If something is ambiguous, report `Status: blocked` with details. The caller handles all user interaction.\n\n## Process Steps\n\n### Step 1: Load Context\n\n1. **Claim the step** (see \"Concurrency: Atomic Claim\"). Stop here on any non-claim outcome.\n2. Read the full step file.\n3. Read `root.md` from the plan dir for plan-level context: Overview, Current State, Desired End State, Implementation Approach, Global Verification.\n4. Read all files mentioned in the step's \"Changes Required\" section.\n\n### Step 2: Pre-flight Check\n\n| Check | Action if failed |\n|-------|-----------------|\n| All `depends_on` steps have `status: done` | Scheduler bug — release claim, report `blocked` |\n| No merge conflicts in target files | Release claim, report `blocked` |\n| Files/dirs from depended-on steps exist | Release claim, report `blocked` |\n\n### Step 3: Execute Step\n\nImplement the changes described in the step's \"Changes Required\" section. Adapt to minor mismatches; report `blocked` for significant ones.\n\n### Step 4: Run Verification\n\nSame three-bucket pattern as `phase-running`:\n1. **Automated Verification** (runnable commands): run each, record pass/fail. On failure, attempt one fix-and-retry.\n2. **Automated QA** (agent-driven scenarios — browser-use, screenshot diff, CLI walkthrough): execute, record pass/fail per item.\n3. **Manual Verification**: leave unchecked. Caller handles with the user.\n4. **QA Spec (linked doc)**: if present, report `QA Doc: <path>`. Do not execute scenarios inline.\n\n### Step 5: Update Step File\n\n- Check off (`- [x]`) Automated Verification + Automated QA items that passed.\n- Do NOT check off Manual Verification items.\n- Update frontmatter `status` per \"Concurrency: Atomic Claim\" terminal-transition rules.\n- Update `last_updated` / `last_updated_by` frontmatter fields if present.\n\n### Step 6: Report Results\n\n**Completed:**\n```\nStatus: completed\nStep: step-N - <Name>\nFinal frontmatter status: done\nFiles changed: [list]\nAutomated Verification: N/M passed\n- [x] [Check 1] — passed\nAutomated QA: N/M passed\n- [x] [Scenario 1] — passed\nQA Doc: <path> | n/a\nManual verification needed:\n- [ ] [Manual check 1]\n```\n\n**Blocked / failed:** mirror `phase-running`'s shape, plus a `Final frontmatter status:` line so the orchestrator knows whether the step is released for retry (`ready`) or held for investigation (`claimed`).\n\n## Atomicity Contract\n\n- No interactive questions.\n- No partial states left unexplained.\n- Frontmatter `status` always reflects the final state at exit.\n- Report includes enough detail for the caller to decide next steps.\n\n## Context Handoff Pattern\n\n| Direction | Data |\n|-----------|------|\n| **Caller → Step Agent** | Step path + plan dir + agent ID + autonomy mode |\n| **Step Agent reads** | Step file + root.md + files in Changes Required |\n| **Step Agent writes** | Frontmatter status transitions + checkboxes + code changes |\n| **Step Agent → Caller** | Status + changed files + verification results + final frontmatter status |\n| **Caller handles** | Manual verification, cross-step coordination, QA doc execution, human checkpoints |\n";
10525
+ var content_default40 = "# Step Running\n\nYou execute a single step of a DAG plan as an atomic background sub-agent. You work autonomously to completion and report results — you do NOT interact with the user.\n\nThis is the DAG sibling of `phase-running`. The execution model and atomicity contract are identical; the differences are:\n- You receive a **step file path** (`step-<n>.md`), not a plan path + phase number.\n- You **claim the step atomically** via the step's frontmatter `status` field before doing work, and release it on completion / failure. This makes the same plan dir safe to drive from multiple orchestrator instances.\n\n## Execution Model\n\nThis skill runs inside a background `Agent` (sub-agent). v-implementing (or a user invoking `/run-step`) spawns it via the Agent tool with `run_in_background: true`.\n\nThe step agent receives:\n- **Step path**: full path to `step-<n>.md`\n- **Plan dir**: full path to the parent plan directory (read `root.md` from here for plan-level context)\n- **Agent ID**: unique identifier for this sub-agent (e.g. orchestrator session ID + step ID + timestamp). Used for atomic claim + stale-claim detection.\n- **Relevant context**: any extra context from the caller\n\n## Concurrency: Atomic Claim\n\nBefore doing any work, claim the step:\n\n1. Read the step file's frontmatter.\n2. **If `status: done`** — report `Status: skipped` and exit. The step is already finished.\n3. **If `status: claimed`** and `assignee` differs from your agent ID:\n - Fresh claim (`claimed_at` within last hour): report `Status: blocked` (reason: `claimed by <other-id>`) and exit.\n - Stale claim (>1h): proceed and overwrite — the previous worker likely died.\n4. **Otherwise** (`status: ready`, or stale `claimed`): rewrite the frontmatter block in a single `Edit` so the write is atomic-enough for filesystem-based coordination. Set:\n - `status: claimed`\n - `assignee: <your-agent-id>`\n - `claimed_at: <ISO timestamp UTC>`\n5. Re-read the file. If `assignee` is not yours, another worker raced you — report `Status: blocked` (reason: `lost claim race`) and exit.\n\nOn terminal transitions, set frontmatter:\n- **Completed**: `status: done`, clear `assignee` and `claimed_at`.\n- **Blocked or failed (retry-able)**: `status: ready`, clear `assignee` and `claimed_at`. The orchestrator (or another worker) can retry.\n- **Failed (non-retry-able)**: leave `status: claimed` so the orchestrator can investigate; include the reason in the report.\n\nFor true cross-machine atomicity (NFS, etc.), the caller is responsible for rendezvous (e.g. a shared lock service). The single-Edit pattern is good-enough for local filesystem and well-behaved network filesystems.\n\n## Autonomy\n\nStep agents always run as **Autopilot** within the sub-agent. The calling context controls outer autonomy and human checkpoints.\n\n**CRITICAL**: Step agents do NOT use AskUserQuestion. If something is ambiguous, report `Status: blocked` with details. The caller handles all user interaction.\n\n## Process Steps\n\n### Step 1: Load Context\n\n1. **Claim the step** (see \"Concurrency: Atomic Claim\"). Stop here on any non-claim outcome.\n2. Read the full step file.\n3. Read `root.md` from the plan dir for plan-level context: Overview, Current State, Desired End State, Implementation Approach, Global Verification.\n4. Read all files mentioned in the step's \"Changes Required\" section.\n\n### Step 2: Pre-flight Check\n\n| Check | Action if failed |\n|-------|-----------------|\n| All `depends_on` steps have `status: done` | Scheduler bug — release claim, report `blocked` |\n| No merge conflicts in target files | Release claim, report `blocked` |\n| Files/dirs from depended-on steps exist | Release claim, report `blocked` |\n\n### Step 3: Execute Step\n\nImplement the changes described in the step's \"Changes Required\" section. Adapt to minor mismatches; report `blocked` for significant ones.\n\n### Step 4: Run Verification\n\nSame three-bucket pattern as `phase-running`:\n1. **Automated Verification** (runnable commands): run each, record pass/fail. On failure, attempt one fix-and-retry.\n2. **Automated QA** (agent-driven scenarios — browser-use, screenshot diff, CLI walkthrough): execute, record pass/fail per item.\n3. **Manual Verification**: leave unchecked. Caller handles with the user.\n4. **QA Spec (linked doc)**: if present, report `QA Doc: <path>`. Do not execute scenarios inline.\n\n### Step 5: Update Step File\n\n- Check off (`- [x]`) Automated Verification + Automated QA items that passed.\n- Do NOT check off Manual Verification items.\n- Update frontmatter `status` per \"Concurrency: Atomic Claim\" terminal-transition rules.\n- Update `last_updated` / `last_updated_by` frontmatter fields if present.\n\n### Step 6: Report Results\n\n**Completed:**\n```\nStatus: completed\nStep: step-N - <Name>\nFinal frontmatter status: done\nFiles changed: [list]\nAutomated Verification: N/M passed\n- [x] [Check 1] — passed\nAutomated QA: N/M passed\n- [x] [Scenario 1] — passed\nQA Doc: <path> | n/a\nManual verification needed:\n- [ ] [Manual check 1]\n```\n\n**Blocked / failed:** mirror `phase-running`'s shape, plus a `Final frontmatter status:` line so the orchestrator knows whether the step is released for retry (`ready`) or held for investigation (`claimed`).\n\n## Atomicity Contract\n\n- No interactive questions.\n- No partial states left unexplained.\n- Frontmatter `status` always reflects the final state at exit.\n- Report includes enough detail for the caller to decide next steps.\n\n## Context Handoff Pattern\n\n| Direction | Data |\n|-----------|------|\n| **Caller → Step Agent** | Step path + plan dir + agent ID + autonomy mode |\n| **Step Agent reads** | Step file + root.md + files in Changes Required |\n| **Step Agent writes** | Frontmatter status transitions + checkboxes + code changes |\n| **Step Agent → Caller** | Status + changed files + verification results + final frontmatter status |\n| **Caller handles** | Manual verification, cross-step coordination, QA doc execution, human checkpoints |\n";
10424
10526
 
10425
10527
  // templates/skills/swarm-scripts/config.json
10426
- var config_default40 = `{
10528
+ var config_default41 = `{
10427
10529
  "kind": "skill",
10428
10530
  "name": "swarm-scripts",
10429
10531
  "displayName": "Swarm Scripts",
@@ -10440,7 +10542,7 @@ var config_default40 = `{
10440
10542
  `;
10441
10543
 
10442
10544
  // templates/skills/swarm-scripts/content.md
10443
- var content_default40 = `# Swarm Scripts
10545
+ var content_default41 = `# Swarm Scripts
10444
10546
 
10445
10547
  A swarm script is TypeScript that runs out of process with a typed Swarm SDK. Only its return value enters your context. Use one when direct tool calls would repeat, flood your context, or need deterministic processing over many records.
10446
10548
 
@@ -10474,7 +10576,7 @@ The swarm ships named scripts at global scope. Each one replaces a multi-step to
10474
10576
  | \`task-context-gathering\` | \`{ taskId, queries: [...] }\` | the task plus a deduplicated multi-query memory recall |
10475
10577
  | \`smart-recall\` | \`{ queries: [...] }\` | multi-query memory recall without the task |
10476
10578
  | \`memory-dedup-check\` | \`{ text, threshold? }\` | near-duplicates before you store a memory |
10477
- | \`delegate\` | \`{ agentName, task, parentTaskId? }\` | a subtask for an agent by name, returns \`{ taskId }\` |
10579
+ | \`delegate\` | \`{ agentName, task, routingReason, parentTaskId? }\` | a subtask for an agent by name, returns \`{ taskId }\` |
10478
10580
  | \`wait-for-task\` | \`{ taskId }\` | waits up to about 25 s for a terminal state, returns \`{ done, status, output }\`; call again while \`done\` is false |
10479
10581
  | \`get-child-outputs\` | \`{ parentTaskId }\` | every child with status and output |
10480
10582
  | \`complete-task\` | \`{ taskId, output }\` | finish a task from inside a script |
@@ -10511,6 +10613,7 @@ export default async function (args: z.infer<typeof argsSchema>, ctx: ScriptCont
10511
10613
  ### What \`ctx\` holds
10512
10614
 
10513
10615
  - \`ctx.swarm.*\`: the swarm SDK. \`task_get\`, \`task_send\`, \`task_storeProgress\`, \`task_action\`, \`task_list\`, \`slack_reply\`, \`memory_search\`, \`memory_store\`, \`kv_get\`, \`kv_getOrNull\`, \`kv_set\`, \`kv_delete\`, \`kv_incr\`, \`kv_list\`, \`swarm_get\`, \`agent_info\`, \`db_query\`, and more. \`kv_getOrNull\` returns the entry, \`null\` on a missing key, and throws on other errors.
10616
+ - \`ctx.swarm.task_send\` requires \`routingReason\` whenever \`agentId\` is present. Use \`human_pinned\` for an explicit/configured choice, \`skill\` for a role or specialization match, \`continuity\` for the same worker/session, \`reroute_fault\` for a fault handoff, or \`overflow\` for capacity/pool escalation. Omit both \`agentId\` and routing fields for the pool.
10514
10617
  - \`ctx.swarm.config\`: \`apiKey\`, \`agentId\`, \`mcpBaseUrl\`, and \`ctx.swarm.config.get("KEY")\` for user config values. All are \`Redacted\` wrappers that stringify to \`<redacted>\`. Never unwrap one into a return value, a log line, or a request body you build by hand.
10515
10618
  - \`ctx.api.<slug>\` and \`ctx.mcp.<slug>\`: typed clients for registered connections. They exist only for registered connections. Introspect with \`Object.keys(ctx.api ?? {})\` and \`Object.keys(ctx.mcp ?? {})\`.
10516
10619
  - \`ctx.stdlib\`: \`fetch\`, \`fetchJson\` (retries, 30 s timeout), \`grep\`, \`glob\`, \`table\`, \`Redacted\`.
@@ -10518,7 +10621,7 @@ export default async function (args: z.infer<typeof argsSchema>, ctx: ScriptCont
10518
10621
 
10519
10622
  ### Durable workflow scripts
10520
10623
 
10521
- \`launch-script-run\` runs a script as a durable, journaled run with a different \`ctx\`: \`ctx.run\` (\`id\`, \`agentId\`, \`args\`) and \`ctx.step.rawLlm(label, config)\`, \`ctx.step.agentTask(label, config)\`, \`ctx.step.swarmScript(label, config)\`, plus \`ctx.swarm.*\`, \`ctx.stdlib\`, \`ctx.logger\`. Durable runs have no \`ctx.api\`, no \`ctx.mcp\`, and no \`ctx.swarm.config\`. Call a connection from an inner script through \`ctx.step.swarmScript\`. See the \`script-workflows\` skill.
10624
+ \`launch-script-run\` runs a script as a durable, journaled run with a different \`ctx\`: \`ctx.run\` (\`id\`, \`agentId\`, \`args\`) and \`ctx.step.rawLlm(label, config)\`, \`ctx.step.agentTask(label, config)\`, \`ctx.step.swarmScript(label, config)\`, plus \`ctx.swarm.*\`, \`ctx.stdlib\`, \`ctx.logger\`. Durable runs have no \`ctx.api\`, no \`ctx.mcp\`, and no \`ctx.swarm.config\`. A configured \`ctx.step.agentTask\` \`agentId\` records \`human_pinned\` unless \`routingReason\` is supplied. Call a connection from an inner script through \`ctx.step.swarmScript\`. See the \`script-workflows\` skill.
10522
10625
 
10523
10626
  ## Inline script pattern
10524
10627
 
@@ -10595,7 +10698,7 @@ A named script can serve \`POST /api/x/script/<id>\` for callers outside the swa
10595
10698
  `;
10596
10699
 
10597
10700
  // templates/skills/tackle-gh-comments/config.json
10598
- var config_default41 = `{
10701
+ var config_default42 = `{
10599
10702
  "category": "skills",
10600
10703
  "description": "Work through every review comment on a GitHub PR — fetch the threads, verify each claim against the code, fix what is real, then reply and mark each thread resolved before pushing. Use when the user says \\"tackle the PR comments\\", \\"address the review\\", \\"handle the bot comments\\", \\"check the comments on the PR\\", \\"resolve the review threads\\", or invokes /tackle-gh-comments. Project-agnostic; works in any repo with a GitHub remote.",
10601
10704
  "displayName": "Tackle GH Comments",
@@ -10616,7 +10719,7 @@ var config_default41 = `{
10616
10719
  `;
10617
10720
 
10618
10721
  // templates/skills/tackle-gh-comments/content.md
10619
- var content_default41 = `# Tackle GitHub PR comments
10722
+ var content_default42 = `# Tackle GitHub PR comments
10620
10723
 
10621
10724
  Review threads and their resolved state live **only in GraphQL**. The REST API
10622
10725
  cannot read \`isResolved\` and cannot resolve a thread, and \`gh pr view --comments\`
@@ -10735,7 +10838,7 @@ committed, and the branch is pushed.
10735
10838
  `;
10736
10839
 
10737
10840
  // templates/skills/taste-minimalist-skill/config.json
10738
- var config_default42 = `{
10841
+ var config_default43 = `{
10739
10842
  "kind": "skill",
10740
10843
  "name": "taste-minimalist-skill",
10741
10844
  "displayName": "Taste Minimalist Skill",
@@ -10757,7 +10860,7 @@ var config_default42 = `{
10757
10860
  `;
10758
10861
 
10759
10862
  // templates/skills/taste-minimalist-skill/content.md
10760
- var content_default42 = `> Vendored from [taste-skill](https://github.com/Leonxlnx/taste-skill) / [tasteskill.dev](https://www.tasteskill.dev/) at commit 06d6028b5c623016c59ce8536f578e5a1127b499.
10863
+ var content_default43 = `> Vendored from [taste-skill](https://github.com/Leonxlnx/taste-skill) / [tasteskill.dev](https://www.tasteskill.dev/) at commit 06d6028b5c623016c59ce8536f578e5a1127b499.
10761
10864
  > Upstream license: MIT, Copyright (c) 2026 Leonxlnx. See ../TASTE-SKILL-LICENSE.
10762
10865
 
10763
10866
  # Protocol: Premium Utilitarian Minimalism UI Architect
@@ -10843,7 +10946,7 @@ When tasked with writing frontend code (HTML, React, Tailwind, Vue) or designing
10843
10946
  `;
10844
10947
 
10845
10948
  // templates/skills/tdd-planning/config.json
10846
- var config_default43 = `{
10949
+ var config_default44 = `{
10847
10950
  "category": "skills",
10848
10951
  "description": "TDD-focused implementation planning. Creates plans with strict Red-Green-Commit/Rollback cycles for each step.",
10849
10952
  "displayName": "TDD Planning",
@@ -10864,7 +10967,7 @@ var config_default43 = `{
10864
10967
  `;
10865
10968
 
10866
10969
  // templates/skills/tdd-planning/content.md
10867
- var content_default43 = `# TDD Planning
10970
+ var content_default44 = `# TDD Planning
10868
10971
 
10869
10972
  You are creating implementation plans that follow a strict Test-Driven Development approach. Every implementation step follows the TDD cycle: **RED → GREEN → COMMIT/ROLLBACK**.
10870
10973
 
@@ -11126,7 +11229,7 @@ Before finalizing any TDD plan, verify:
11126
11229
  `;
11127
11230
 
11128
11231
  // templates/skills/v-implementing/config.json
11129
- var config_default44 = `{
11232
+ var config_default45 = `{
11130
11233
  "category": "skills",
11131
11234
  "description": "Parallel DAG-plan implementation skill. Reads a v-planning plan directory (root.md + step-<n>.md files), topologically schedules ready steps, and fans them out as parallel sub-agents. Use whenever the user invokes /v-implement, points at a plan directory produced by /v-plan, or asks to \\"run the parallel plan\\", \\"implement the DAG\\", or \\"fan out the steps\\" — even without those exact words. For linear plans (single .md file), use \`implementing\` instead.",
11132
11235
  "displayName": "V-Implementing",
@@ -11147,10 +11250,10 @@ var config_default44 = `{
11147
11250
  `;
11148
11251
 
11149
11252
  // templates/skills/v-implementing/content.md
11150
- var content_default44 = "# v-implementing\n\nYou are implementing an approved DAG-structured plan produced by `v-planning`. The plan is a directory with `root.md` + one `step-<n>.md` per node. Your job is to act as a **topological scheduler**: at each tick, find steps whose dependencies are all done, fan them out as parallel sub-agents (one per ready step), wait, repeat — until the DAG is drained. Then run Global Verification.\n\nThis is the parallel sibling of `implementing`. The orchestration model is the same (sub-agents do the work, main session coordinates), only the scheduler is different.\n\n## Working Agreement\n\n**All user-facing questions go through `AskUserQuestion`** — see `desplega:ask-user` for conventions. Never ask in chat as plain bullets.\n\n**All read/research/validation work goes through sub-agents** — keep raw tool output out of the main session. Default to `run_in_background: true`. The fan-out scheduler below is built on this.\n\nThe autonomy mode (below) controls how often you check in. AskUserQuestion is always the mechanism.\n\nFile-review is on by default — when significant changes land in a step (or wave), invoke `/file-review:file-review <path>` for inline feedback (skip only if Autopilot).\n\n## Autonomy Mode\n\n| Mode | Behavior |\n|------|----------|\n| **Autopilot** | Drain the DAG without pausing. Only stop on blocker / failed step. |\n| **Critical** (Default) | Pause when each *wave* of parallel steps completes; wait for manual verification before unlocking the next wave. |\n| **Verbose** | Pause after each individual step (even within a wave). |\n\n## Initial Setup Questions\n\nAfter understanding the plan and before the scheduler loop starts, gather implementation-specific details (skip in Autopilot):\n\n### 1. Branch / Worktree Setup\n\nCheck the current branch: `git branch --show-current`. Then check if the `wts` plugin is installed (look for `wts:wts` in available skills).\n\n**If wts is installed**, use **AskUserQuestion**:\n\n| Question | Options |\n|----------|---------|\n| \"You're on `<current-branch>`. Where would you like to implement?\" | 1. Continue on current branch, 2. Create a new branch, 3. Create a wts worktree |\n\n**If wts is not installed**, drop the worktree option.\n\n### 2. Commit Strategy\n\nUse **AskUserQuestion**:\n\n| Question | Options |\n|----------|---------|\n| \"How would you like to handle commits during parallel implementation?\" | 1. Commit after each step completes (Recommended), 2. Commit at the end (single commit), 3. Let me decide as I go |\n\nIf \"Commit after each step\" is selected, after a step's manual verification passes, create a commit: `[step-N] <step name>`.\n\n### 3. Orchestration Mode (only if the `Workflow` tool is available)\n\n| Question | Options |\n|----------|---------|\n| \"Run the DAG waves as Workflow scripts? (deterministic scheduling, parallel steps as agent() calls)\" | 1. Yes — Workflow waves, 2. No — Agent fan-out (Default) |\n\nA \"yes\" is the explicit opt-in the Workflow tool requires. If opted in, each wave of the scheduler loop below runs as one Workflow script — a `parallel()` of `agent()` calls, one per ready step, with `model`/`effort` per `desplega:delegate-work`. Everything else is unchanged: step agents still follow the `step-running` contract (atomic frontmatter claim, three-bucket verification), and autonomy-mode pause points sit **between** Workflow invocations, never inside one. In Autopilot these questions are skipped, so there is no opt-in — use Agent fan-out unless the user pre-authorized workflows.\n\n### 4. Code Review Mode\n\n| Question | Options |\n|----------|---------|\n| \"Run an automatic code review after each wave?\" | 1. Automatic two-axis review per wave (Recommended), 2. Only at the end (single review after the DAG drains), 3. Off — I'll review myself |\n\nIn **Autopilot**, skip the question and default to automatic per-wave review.\n\n## Getting Started\n\nGiven a plan directory path:\n\n1. **Read `root.md` fully** (no `limit`/`offset`). Capture: Overview, Current State, Desired End State, Implementation Approach, Global Verification.\n2. **Read every `step-<n>.md`'s frontmatter** to build the dependency graph (`id`, `depends_on`). You don't need to read step bodies up front — the sub-agents will do that.\n3. **Validate the DAG:**\n - No cycles\n - Every `depends_on` ID exists as a step file\n - At least one step has `depends_on: []` (otherwise nothing can start)\n4. **Set `root.md` frontmatter `status: in-progress`.**\n5. **Build a TodoWrite list** with one entry per step, marked `pending`.\n6. **Resume support:** if any step's body has `- [x]` boxes already (or its frontmatter says `status: completed` if the user added it), trust them and treat that step as `done`.\n\nIf no path given, ask via AskUserQuestion.\n\n## The Scheduler Loop\n\nThe scheduler reads each step's frontmatter `status` (`ready` | `claimed` | `done`) and `depends_on`. The frontmatter `status` field is the **single source of truth** — multiple orchestrator instances on the same plan dir coordinate through it (each `desplega:step-running` sub-agent atomically claims its step before doing work).\n\n```\nwhile any step has status != done:\n ready = [step for step in steps\n if step.status == \"ready\"\n and all(dep.status == \"done\" for dep in step.depends_on)]\n if not ready:\n # DAG drained, OR every remaining undone step is claimed by another worker\n if any step has status == claimed: wait for in-flight claims to resolve\n else: report stuck (likely cycle or unrecoverable failure)\n continue\n fan out each step in `ready` as a parallel `desplega:step-running` sub-agent\n wait for the wave to complete\n review reports; step-running has already updated frontmatter\n (status: done on success, status: ready on retry-able failure, status: claimed if held for investigation)\n if Critical mode: pause for manual verification of newly-completed steps\n if any failed: stop and ask user how to proceed\n```\n\n### Spawning a Step Sub-agent\n\nUse the `Agent` tool with `run_in_background: true`, invoking `desplega:step-running`. Pass:\n\n- **Step path**: full path to `step-<n>.md`\n- **Plan dir**: full path to the parent plan directory\n- **Agent ID**: unique ID for this sub-agent (e.g. orchestrator session ID + step ID + timestamp). step-running uses this for atomic claim + stale-claim detection.\n- **Plan-level context** (optional): a quick brief from `root.md`. step-running re-reads `root.md` itself, so this is just to reduce round-trips.\n\n`step-running` owns:\n- Atomic claim (rewrite frontmatter `status: ready` → `status: claimed, assignee: <agent-id>, claimed_at: <ts>`)\n- Three-bucket verification (Automated Verification, Automated QA, QA Doc identification)\n- Terminal status transition (`status: done` on success, `status: ready` on retry-able failure)\n- Reporting back\n\nThe orchestrator does NOT do step work itself — it delegates. See `desplega:step-running` for the full sub-agent contract.\n\n**Executor routing**: if the `desplega:delegate-work` skill is available, pick each step's executor per its routing matrix instead of defaulting to a `step-running` sub-agent — a step may route to a Codex variant (one worktree per parallel slice) or a specific Claude model tier. Only the executor choice changes; the scheduler, frontmatter claim protocol, and all other semantics here stay unchanged. When a step routes to Codex, the orchestrator owns the frontmatter bookkeeping that `step-running` would normally do (Codex must not edit plan files).\n\n### Wave Completion\n\nWhen a wave finishes:\n1. **Review each agent's report.** Mark steps `done` only if `completed` was reported.\n2. **Run the wave code review** (unless review mode is Off) — invoke `desplega:code-reviewing` on the wave's combined diff: Standards + Spec axes as parallel background sub-agents (routed per `desplega:delegate-work`), spec source = the completed steps' bodies and Success Criteria. Critical findings block those steps' commits — fix and re-verify first. If \"Only at the end\" was selected, run one review over the full diff after the DAG drains instead.\n3. **Handle `QA Doc: <path>`** — for each step that reported a QA doc, invoke `desplega:qa` against that path. The Automated QA bucket inside the step is already handled by the sub-agent; only the linked doc needs separate orchestration here. (`QA: n/a` → proceed normally.)\n4. **Manual verification (if not Autopilot)** — present manual verification items from each completed step's body. Wait for user confirmation. Don't tick manual boxes until confirmed.\n5. **Commits (if commit-per-step was selected)** — after a step's manual verification passes, create a commit: `[step-N] <step name>`.\n6. **Loop** — recompute `ready` and start the next wave.\n\n## Handling Failures and Mismatches\n\nIf a sub-agent reports `failed` or `blocked`, or you spot a mismatch between plan and reality:\n\n| Question | Options |\n|----------|---------|\n| \"[step-N] [issue]. How should I proceed?\" | 1. Adapt step (edit step-N.md and retry), 2. Retry as-is, 3. Skip and continue (mark step blocked), 4. Stop the run |\n\nIn Autopilot mode, use best judgment, document the decision in the step file, and continue if non-fatal.\n\n## After the DAG Drains\n\nWhen every step is `done`:\n\n1. Run **Global Verification** from `root.md`. Tick automated checks; surface manual checks to the user.\n2. Set `root.md` frontmatter `status: completed`.\n3. Offer post-implementation auditing: \"Would you like me to run `/verify-plan` and `/review` on the plan directory?\"\n4. If commit-per-step was off, offer to create a single bundled commit now.\n5. If the work ships as a GitHub PR: once review comments land, address them with `desplega:tackle-gh-comments` (fetch threads, verify each claim, fix, reply, resolve — push last).\n\n## Important Guidelines\n\n1. **One step = one sub-agent.** Don't bundle steps into a single agent even if they're in the same wave — fan-out is the whole point.\n2. **Plan-level context goes to every sub-agent.** Sibling step bodies do not.\n3. **The DAG is canonical via step frontmatter** — if `root.md`'s table is out of sync, trust the frontmatter.\n4. **Resume works step-granular.** If the user re-runs `/v-implement` mid-DAG, completed steps stay completed; only undone ones rerun.\n5. **Don't tick manual checkboxes** until the user confirms — automated boxes can be ticked by the sub-agent or the orchestrator.\n\n## Review Integration\n\nIf `file-review` is available and the user opted in:\n- After each step's significant code changes, invoke `/file-review:file-review <changed-file>`.\n- Process feedback with `file-review:process-review` before treating the step as done.\n- Skip in Autopilot.\n";
11253
+ var content_default45 = "# v-implementing\n\nYou are implementing an approved DAG-structured plan produced by `v-planning`. The plan is a directory with `root.md` + one `step-<n>.md` per node. Your job is to act as a **topological scheduler**: at each tick, find steps whose dependencies are all done, fan them out as parallel sub-agents (one per ready step), wait, repeat — until the DAG is drained. Then run Global Verification.\n\nThis is the parallel sibling of `implementing`. The orchestration model is the same (sub-agents do the work, main session coordinates), only the scheduler is different.\n\n## Working Agreement\n\n**All user-facing questions go through `AskUserQuestion`** — see `desplega:ask-user` for conventions. Never ask in chat as plain bullets.\n\n**All read/research/validation work goes through sub-agents** — keep raw tool output out of the main session. Default to `run_in_background: true`. The fan-out scheduler below is built on this.\n\nThe autonomy mode (below) controls how often you check in. AskUserQuestion is always the mechanism.\n\nFile-review is on by default — when significant changes land in a step (or wave), invoke `/file-review:file-review <path>` for inline feedback (skip only if Autopilot).\n\n## Autonomy Mode\n\n| Mode | Behavior |\n|------|----------|\n| **Autopilot** | Drain the DAG without pausing. Only stop on blocker / failed step. |\n| **Critical** (Default) | Pause when each *wave* of parallel steps completes; wait for manual verification before unlocking the next wave. |\n| **Verbose** | Pause after each individual step (even within a wave). |\n\n## Initial Setup Questions\n\nAfter understanding the plan and before the scheduler loop starts, gather implementation-specific details (skip in Autopilot):\n\n### 1. Branch / Worktree Setup\n\nCheck the current branch: `git branch --show-current`. Then check if the `wts` plugin is installed (look for `wts:wts` in available skills).\n\n**If wts is installed**, use **AskUserQuestion**:\n\n| Question | Options |\n|----------|---------|\n| \"You're on `<current-branch>`. Where would you like to implement?\" | 1. Continue on current branch, 2. Create a new branch, 3. Create a wts worktree |\n\n**If wts is not installed**, drop the worktree option.\n\n### 2. Commit Strategy\n\nUse **AskUserQuestion**:\n\n| Question | Options |\n|----------|---------|\n| \"How would you like to handle commits during parallel implementation?\" | 1. Commit after each step completes (Recommended), 2. Commit at the end (single commit), 3. Let me decide as I go |\n\nIf \"Commit after each step\" is selected, after a step's manual verification passes, create a commit: `[step-N] <step name>`.\n\n### 3. Orchestration Mode (only if the `Workflow` tool is available)\n\n| Question | Options |\n|----------|---------|\n| \"Run the DAG waves as Workflow scripts? (deterministic scheduling, parallel steps as agent() calls)\" | 1. Yes — Workflow waves, 2. No — Agent fan-out (Default) |\n\nA \"yes\" is the explicit opt-in the Workflow tool requires. If opted in, each wave of the scheduler loop below runs as one Workflow script — a `parallel()` of `agent()` calls, one per ready step, with `model`/`effort` per `desplega:delegate-work`. Everything else is unchanged: step agents still follow the `step-running` contract (atomic frontmatter claim, three-bucket verification), and autonomy-mode pause points sit **between** Workflow invocations, never inside one. In Autopilot these questions are skipped, so there is no opt-in — use Agent fan-out unless the user pre-authorized workflows.\n\n### 4. Code Review Mode\n\n| Question | Options |\n|----------|---------|\n| \"Run an automatic code review after each wave?\" | 1. Automatic two-axis review per wave (Recommended), 2. Only at the end (single review after the DAG drains), 3. Off — I'll review myself |\n\nIn **Autopilot**, skip the question and default to automatic per-wave review.\n\n## Getting Started\n\nGiven a plan directory path:\n\n1. **Read `root.md` fully** (no `limit`/`offset`). Capture: Overview, Current State, Desired End State, Implementation Approach, Global Verification.\n2. **Read every `step-<n>.md`'s frontmatter** to build the dependency graph (`id`, `depends_on`). You don't need to read step bodies up front — the sub-agents will do that.\n3. **Validate the DAG:**\n - No cycles\n - Every `depends_on` ID exists as a step file\n - At least one step has `depends_on: []` (otherwise nothing can start)\n4. **Set `root.md` frontmatter `status: in-progress`.**\n5. **Build a TodoWrite list** with one entry per step, marked `pending`.\n6. **Resume support:** if any step's body has `- [x]` boxes already (or its frontmatter says `status: completed` if the user added it), trust them and treat that step as `done`.\n\nIf no path given, ask via AskUserQuestion.\n\n## The Scheduler Loop\n\nThe scheduler reads each step's frontmatter `status` (`ready` | `claimed` | `done`) and `depends_on`. The frontmatter `status` field is the **single source of truth** — multiple orchestrator instances on the same plan dir coordinate through it (each `desplega:step-running` sub-agent atomically claims its step before doing work).\n\n```\nwhile any step has status != done:\n ready = [step for step in steps\n if step.status == \"ready\"\n and all(dep.status == \"done\" for dep in step.depends_on)]\n if not ready:\n # DAG drained, OR every remaining undone step is claimed by another worker\n if any step has status == claimed: wait for in-flight claims to resolve\n else: report stuck (likely cycle or unrecoverable failure)\n continue\n fan out each step in `ready` as a parallel `desplega:step-running` sub-agent\n wait for the wave to complete\n review reports; step-running has already updated frontmatter\n (status: done on success, status: ready on retry-able failure, status: claimed if held for investigation)\n if Critical mode: pause for manual verification of newly-completed steps\n if any failed: stop and ask user how to proceed\n```\n\n### Spawning a Step Sub-agent\n\nUse the `Agent` tool with `run_in_background: true`, invoking `desplega:step-running`. Pass:\n\n- **Step path**: full path to `step-<n>.md`\n- **Plan dir**: full path to the parent plan directory\n- **Agent ID**: unique ID for this sub-agent (e.g. orchestrator session ID + step ID + timestamp). step-running uses this for atomic claim + stale-claim detection.\n- **Plan-level context** (optional): a quick brief from `root.md`. step-running re-reads `root.md` itself, so this is just to reduce round-trips.\n\n`step-running` owns:\n- Atomic claim (rewrite frontmatter `status: ready` → `status: claimed, assignee: <agent-id>, claimed_at: <ts>`)\n- Three-bucket verification (Automated Verification, Automated QA, QA Doc identification)\n- Terminal status transition (`status: done` on success, `status: ready` on retry-able failure)\n- Reporting back\n\nThe orchestrator does NOT do step work itself — it delegates. See `desplega:step-running` for the full sub-agent contract.\n\n**Executor routing**: if the `desplega:delegate-work` skill is available, pick each step's executor per its routing matrix instead of defaulting to a `step-running` sub-agent — a step may route to a Codex variant (one worktree per parallel slice) or a specific Claude model tier. Only the executor choice changes; the scheduler, frontmatter claim protocol, and all other semantics here stay unchanged. When a step routes to Codex, the orchestrator owns the frontmatter bookkeeping that `step-running` would normally do (Codex must not edit plan files).\n\n### Wave Completion\n\nWhen a wave finishes:\n1. **Review each agent's report.** Mark steps `done` only if `completed` was reported.\n2. **Run the wave code review** (unless review mode is Off) — invoke `desplega:code-reviewing` on the wave's combined diff: Standards + Spec axes as parallel background sub-agents (routed per `desplega:delegate-work`), spec source = the completed steps' bodies and Success Criteria. Critical findings block those steps' commits — fix and re-verify first. If \"Only at the end\" was selected, run one review over the full diff after the DAG drains instead.\n3. **Handle `QA Doc: <path>`** — for each step that reported a QA doc, invoke `desplega:qa` against that path. The Automated QA bucket inside the step is already handled by the sub-agent; only the linked doc needs separate orchestration here. (`QA: n/a` → proceed normally.)\n4. **Manual verification (if not Autopilot)** — present manual verification items from each completed step's body. Wait for user confirmation. Don't tick manual boxes until confirmed.\n5. **Commits (if commit-per-step was selected)** — after a step's manual verification passes, create a commit: `[step-N] <step name>`.\n6. **Loop** — recompute `ready` and start the next wave.\n\n## Handling Failures and Mismatches\n\nIf a sub-agent reports `failed` or `blocked`, or you spot a mismatch between plan and reality:\n\n| Question | Options |\n|----------|---------|\n| \"[step-N] [issue]. How should I proceed?\" | 1. Adapt step (edit step-N.md and retry), 2. Retry as-is, 3. Skip and continue (mark step blocked), 4. Stop the run |\n\nIn Autopilot mode, use best judgment, document the decision in the step file, and continue if non-fatal.\n\n## After the DAG Drains\n\nWhen every step is `done`:\n\n1. Run **Global Verification** from `root.md`. Tick automated checks; surface manual checks to the user.\n2. Set `root.md` frontmatter `status: completed`.\n3. Offer post-implementation auditing: \"Would you like me to run `/verify-plan` and `/review` on the plan directory?\"\n4. If commit-per-step was off, offer to create a single bundled commit now.\n5. If the work ships as a GitHub PR: once review comments land, address them with `desplega:tackle-gh-comments` (fetch threads, verify each claim, fix, reply, resolve — push last).\n\n## Important Guidelines\n\n1. **One step = one sub-agent.** Don't bundle steps into a single agent even if they're in the same wave — fan-out is the whole point.\n2. **Plan-level context goes to every sub-agent.** Sibling step bodies do not.\n3. **The DAG is canonical via step frontmatter** — if `root.md`'s table is out of sync, trust the frontmatter.\n4. **Resume works step-granular.** If the user re-runs `/v-implement` mid-DAG, completed steps stay completed; only undone ones rerun.\n5. **Don't tick manual checkboxes** until the user confirms — automated boxes can be ticked by the sub-agent or the orchestrator.\n\n## Review Integration\n\nIf `file-review` is available and the user opted in:\n- After each step's significant code changes, invoke `/file-review:file-review <changed-file>`.\n- Process feedback with `file-review:process-review` before treating the step as done.\n- Skip in Autopilot.\n";
11151
11254
 
11152
11255
  // templates/skills/v-planning/config.json
11153
- var config_default45 = `{
11256
+ var config_default46 = `{
11154
11257
  "category": "skills",
11155
11258
  "description": "Vertical / parallel implementation planning skill. Creates DAG-structured plan directories where each step is an independent, QA-able vertical slice that sub-agents can pick up and implement in parallel. Use whenever the user wants a plan that fans out (multiple independent features), invokes /v-plan, or asks for a \\"parallel plan\\", \\"DAG plan\\", \\"vertical plan\\", or \\"plan that can be parallelized\\" — even if they don't say those exact words. Prefer the linear \`planning\` skill for strictly sequential work.",
11156
11259
  "displayName": "V-Planning",
@@ -11171,7 +11274,7 @@ var config_default45 = `{
11171
11274
  `;
11172
11275
 
11173
11276
  // templates/skills/v-planning/content.md
11174
- var content_default45 = `# v-planning
11277
+ var content_default46 = `# v-planning
11175
11278
 
11176
11279
  You create implementation plans as a **DAG of vertical steps** — each step a complete, QA-able slice of value (DB + API + UI + tests for one feature). The DAG captures feature-level dependencies, so independent steps can be implemented in parallel by sub-agents.
11177
11280
 
@@ -11262,7 +11365,7 @@ Structure validation runs automatically (rule 9, Haiku sub-agent).
11262
11365
  `;
11263
11366
 
11264
11367
  // templates/skills/verifying/config.json
11265
- var config_default46 = `{
11368
+ var config_default47 = `{
11266
11369
  "category": "skills",
11267
11370
  "description": "Post-implementation plan verification. Cross-references plans against actual changes for completeness and accuracy.",
11268
11371
  "displayName": "Verifying",
@@ -11283,7 +11386,7 @@ var config_default46 = `{
11283
11386
  `;
11284
11387
 
11285
11388
  // templates/skills/verifying/content.md
11286
- var content_default46 = `# Verifying
11389
+ var content_default47 = `# Verifying
11287
11390
 
11288
11391
  You are performing a post-implementation audit of a plan, cross-referencing it against actual changes to ensure nothing was missed, nothing is stale, and the implementation matches what was planned.
11289
11392
 
@@ -11431,7 +11534,7 @@ File-review is on by default (unless Autopilot):
11431
11534
  `;
11432
11535
 
11433
11536
  // templates/skills/work-on-task/config.json
11434
- var config_default47 = `{
11537
+ var config_default48 = `{
11435
11538
  "kind": "skill",
11436
11539
  "name": "work-on-task",
11437
11540
  "displayName": "Work On Task",
@@ -11448,10 +11551,10 @@ var config_default47 = `{
11448
11551
  `;
11449
11552
 
11450
11553
  // templates/skills/work-on-task/content.md
11451
- var content_default47 = "# Working on a task\n\nThe taskId follows the command. Without one, call `get-tasks` with `mineOnly: true` and take your `pending` or `in_progress` task. If there is none, say so and stop.\n\nThis message carries the task text, its attachments, its output format, and memories from past sessions. If it does not (you invoked this command yourself, or the context was compacted), run the `task-context-gathering` script with the taskId.\n\nWhen the task names a skill (`researching`, `planning`, `implementing`), use it. Otherwise work directly.\n\nFinish the task with one of the four endings in your operating contract: `completed`, `defer-task`, `request-human-input`, or `failed`. Then stop.\n\nIf the user interrupts, follow their instructions. To resume, call `/work-on-task <taskId>` again.\n";
11554
+ var content_default48 = "# Working on a task\n\nThe taskId follows the command. Without one, call `get-tasks` with `mineOnly: true` and take your `pending` or `in_progress` task. If there is none, say so and stop.\n\nThis message carries the task text, its attachments, its output format, and memories from past sessions. If it does not (you invoked this command yourself, or the context was compacted), run the `task-context-gathering` script with the taskId.\n\nWhen the task names a skill (`researching`, `planning`, `implementing`), use it. Otherwise work directly.\n\nFinish the task with one of the four endings in your operating contract: `completed`, `defer-task`, `request-human-input`, or `failed`. Then stop.\n\nIf the user interrupts, follow their instructions. To resume, call `/work-on-task <taskId>` again.\n";
11452
11555
 
11453
11556
  // templates/skills/workflow-iterate/config.json
11454
- var config_default48 = `{
11557
+ var config_default49 = `{
11455
11558
  "kind": "skill",
11456
11559
  "name": "workflow-iterate",
11457
11560
  "displayName": "Workflow Iteration",
@@ -11473,7 +11576,7 @@ var config_default48 = `{
11473
11576
  `;
11474
11577
 
11475
11578
  // templates/skills/workflow-iterate/content.md
11476
- var content_default48 = `# Workflow Iteration
11579
+ var content_default49 = `# Workflow Iteration
11477
11580
 
11478
11581
  Use this skill when you need to change an existing workflow without breaking live runs. The goal is to make small, verified revisions: inspect the current workflow, diagnose the failing step, patch only the required node or edge, trigger a realistic run, and keep iterating until the run reaches the intended terminal state.
11479
11582
 
@@ -11615,7 +11718,7 @@ Use these shapes as a starting point, then confirm them against the current exec
11615
11718
  `;
11616
11719
 
11617
11720
  // templates/skills/workflow-structured-output/config.json
11618
- var config_default49 = `{
11721
+ var config_default50 = `{
11619
11722
  "kind": "skill",
11620
11723
  "name": "workflow-structured-output",
11621
11724
  "displayName": "Workflow Structured Output",
@@ -11632,10 +11735,10 @@ var config_default49 = `{
11632
11735
  `;
11633
11736
 
11634
11737
  // templates/skills/workflow-structured-output/content.md
11635
- var content_default49 = '# Workflow Structured Output\n\n> **Companion skill — `workflow-iterate` (author-side).** This skill is for *workers* assigned a task spawned by an `agent-task` workflow node with an `outputSchema`. The author-side counterpart `workflow-iterate` covers how the workflow defines that schema, why gates downstream depend on it, and how to debug failed runs. If you ever need to understand *why* a particular schema is shaped the way it is — or you\'re switching from worker to author mode — read `workflow-iterate`.\n\n## Failure reason → fix (read this first)\n\nIf you see this failure reason on a task, the fix is always the same:\n\n| failureReason contains | What it means | Fix |\n|---|---|---|\n| `Task has an outputSchema but no output was provided` | You called `store-progress` without an `output` when the task required a JSON object matching `outputSchema` | Re-call `store-progress` with `status: "completed"` and `output` = a **stringified JSON** matching the schema exactly |\n| `Task output must be valid JSON` / `Task output does not match the outputSchema` | You passed invalid JSON, omitted required fields, or used the wrong types | Re-read the schema, include every `required` field with the exact key names, re-call `store-progress` |\n\n**You can re-call `store-progress` even after a rejection.** Your prior progress updates do not count as the final output. Fix the JSON and try again.\n\n## Pre-flight checklist (run through before calling store-progress)\n\n1. **Do the task details contain an actual `outputSchema`?** If yes, runtime\n enforcement is active: continue with that exact schema.\n2. **If there is no `outputSchema`, does the user provide an explicit JSON Output\n Format or interface?** Honor it as the requested output contract even though\n the runner is not enforcing an `outputSchema`.\n3. **Are workflow origin or tags such as `deterministic`, `litmus`, `validation`,\n or `context` the only signals?** They are heuristics only. Re-read the task\n details for an actual schema or explicit format. If neither exists, do not\n invent one; plain-text output is allowed.\n4. **Can I quote the exact required shape from the task details?** Use its exact\n keys and types, with every required field and no guessed renames.\n5. **Is my `output` a string (stringified JSON), not an object?** For a structured\n contract, `store-progress.output` should be a JSON string.\n6. **Only after the applicable contract is clear:** call `store-progress` with\n `status: "completed"` and the stringified JSON, or use plain text when no\n structured contract exists.\n\nIf the required shape is unclear, re-read the task details. Never synthesize a\nschema from tags or workflow origin.\n\n## Why this exists\n\nWhen a task has an actual `outputSchema`, the runner validates\n`store-progress.output` against it and rejects missing output, invalid JSON, or\nschema mismatches with one of the current messages listed above. A JSON Output\nFormat or interface without `task.outputSchema` remains a user instruction, but\nit is not the same runtime enforcement mechanism. Missing the distinction can\nturn completed work into a rejected terminal update, so check the task contract\nbefore reporting completion.\n\n## How to spot a structured-output task\n\nTreat these signals differently:\n\n- An actual `task.outputSchema` means JSON is runtime-enforced.\n- An explicit "Output Format", "Return a JSON object", or TypeScript/JSON\n interface is a user contract to return that shape, even without runtime\n enforcement.\n- Tags such as `deterministic`, `litmus`, `validation`, `releases`, or `context`,\n and `source = workflow`, only tell you to inspect the task details carefully.\n They do not prove a schema exists.\n\nWhen in doubt, re-read the task details and its `outputSchema`. Do not invent a\nschema or required fields.\n\n## How to complete correctly\n\n1. **Build the JSON object** that matches the actual `outputSchema` or explicit\n user-provided JSON format. Include every required field and use the exact key\n names from that contract.\n2. **Stringify it** — `store-progress.output` must be a string, not an object. Use `JSON.stringify(obj)` in your head.\n3. **Call store-progress** with `status: "completed"` and that JSON string as `output`.\n\n### Example — skip case\n\nTask has schema `{skip: bool, reason?: str, contextPath?: str, ...}` and you\'re skipping because the release already exists:\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"skip":true,"reason":"Release already exists for this week"}\'\n)\n```\n\n### Example — full run\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"skip":false,"contextPath":"release-runs/2026-04-20/context.json","commitCount":42,"repos":["example-repo"],"repoPatternsSource":"cache","dateRange":"2026-04-13 to 2026-04-20"}\'\n)\n```\n\n### Example — litmus / validation verdict\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"verdict":"publish","reason":"5 user-facing changes; threshold met"}\'\n)\n```\n\n## Anti-patterns for an `outputSchema` task\n\n- `output: "Done. Context written to agent-fs at release-runs/2026-04-20/context.json"`\n- `output: "Published release notes for week of 2026-04-20"`\n- `output: "Verdict: publish"`\n- Calling `store-progress` with `status: "completed"` and no `output` at all\n- JSON that\'s missing any `required` field from the schema\n- JSON with extra keys instead of the schema\'s exact keys\n\n## Recovery if you realize mid-task\n\nIf you\'ve done all the work but forgot the JSON contract, just call `store-progress` again with the correct JSON string in `output`. Your prior progress updates don\'t count as the final output.\n\n## Verify before completing\n\nRead your task description once more. Find the schema. Build the JSON. Then complete. Takes 30 seconds. Saves a workflow re-run.\n\n## See also\n\n- **`workflow-iterate`** — the author-side counterpart of this skill. Read it if you\'re editing the workflow that produced this task, or want to understand why this particular schema is shaped the way it is (which gates downstream depend on it, etc.).\n';
11738
+ var content_default50 = '# Workflow Structured Output\n\n> **Companion skill — `workflow-iterate` (author-side).** This skill is for *workers* assigned a task spawned by an `agent-task` workflow node with an `outputSchema`. The author-side counterpart `workflow-iterate` covers how the workflow defines that schema, why gates downstream depend on it, and how to debug failed runs. If you ever need to understand *why* a particular schema is shaped the way it is — or you\'re switching from worker to author mode — read `workflow-iterate`.\n\n## Failure reason → fix (read this first)\n\nIf you see this failure reason on a task, the fix is always the same:\n\n| failureReason contains | What it means | Fix |\n|---|---|---|\n| `Task has an outputSchema but no output was provided` | You called `store-progress` without an `output` when the task required a JSON object matching `outputSchema` | Re-call `store-progress` with `status: "completed"` and `output` = a **stringified JSON** matching the schema exactly |\n| `Task output must be valid JSON` / `Task output does not match the outputSchema` | You passed invalid JSON, omitted required fields, or used the wrong types | Re-read the schema, include every `required` field with the exact key names, re-call `store-progress` |\n\n**You can re-call `store-progress` even after a rejection.** Your prior progress updates do not count as the final output. Fix the JSON and try again.\n\n## Pre-flight checklist (run through before calling store-progress)\n\n1. **Do the task details contain an actual `outputSchema`?** If yes, runtime\n enforcement is active: continue with that exact schema.\n2. **If there is no `outputSchema`, does the user provide an explicit JSON Output\n Format or interface?** Honor it as the requested output contract even though\n the runner is not enforcing an `outputSchema`.\n3. **Are workflow origin or tags such as `deterministic`, `litmus`, `validation`,\n or `context` the only signals?** They are heuristics only. Re-read the task\n details for an actual schema or explicit format. If neither exists, do not\n invent one; plain-text output is allowed.\n4. **Can I quote the exact required shape from the task details?** Use its exact\n keys and types, with every required field and no guessed renames.\n5. **Is my `output` a string (stringified JSON), not an object?** For a structured\n contract, `store-progress.output` should be a JSON string.\n6. **Only after the applicable contract is clear:** call `store-progress` with\n `status: "completed"` and the stringified JSON, or use plain text when no\n structured contract exists.\n\nIf the required shape is unclear, re-read the task details. Never synthesize a\nschema from tags or workflow origin.\n\n## Why this exists\n\nWhen a task has an actual `outputSchema`, the runner validates\n`store-progress.output` against it and rejects missing output, invalid JSON, or\nschema mismatches with one of the current messages listed above. A JSON Output\nFormat or interface without `task.outputSchema` remains a user instruction, but\nit is not the same runtime enforcement mechanism. Missing the distinction can\nturn completed work into a rejected terminal update, so check the task contract\nbefore reporting completion.\n\n## How to spot a structured-output task\n\nTreat these signals differently:\n\n- An actual `task.outputSchema` means JSON is runtime-enforced.\n- An explicit "Output Format", "Return a JSON object", or TypeScript/JSON\n interface is a user contract to return that shape, even without runtime\n enforcement.\n- Tags such as `deterministic`, `litmus`, `validation`, `releases`, or `context`,\n and `source = workflow`, only tell you to inspect the task details carefully.\n They do not prove a schema exists.\n\nWhen in doubt, re-read the task details and its `outputSchema`. Do not invent a\nschema or required fields.\n\n## How to complete correctly\n\n1. **Build the JSON object** that matches the actual `outputSchema` or explicit\n user-provided JSON format. Include every required field and use the exact key\n names from that contract.\n2. **Stringify it** — `store-progress.output` must be a string, not an object. Use `JSON.stringify(obj)` in your head.\n3. **Call store-progress** with `status: "completed"` and that JSON string as `output`.\n\n### Example — skip case\n\nTask has schema `{skip: bool, reason?: str, contextPath?: str, ...}` and you\'re skipping because the release already exists:\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"skip":true,"reason":"Release already exists for this week"}\'\n)\n```\n\n### Example — full run\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"skip":false,"contextPath":"release-runs/2026-04-20/context.json","commitCount":42,"repos":["example-repo"],"repoPatternsSource":"cache","dateRange":"2026-04-13 to 2026-04-20"}\'\n)\n```\n\n### Example — litmus / validation verdict\n\n```\nstore-progress(\n taskId,\n status="completed",\n output=\'{"verdict":"publish","reason":"5 user-facing changes; threshold met"}\'\n)\n```\n\n## Anti-patterns for an `outputSchema` task\n\n- `output: "Done. Context written to agent-fs at release-runs/2026-04-20/context.json"`\n- `output: "Published release notes for week of 2026-04-20"`\n- `output: "Verdict: publish"`\n- Calling `store-progress` with `status: "completed"` and no `output` at all\n- JSON that\'s missing any `required` field from the schema\n- JSON with extra keys instead of the schema\'s exact keys\n\n## Recovery if you realize mid-task\n\nIf you\'ve done all the work but forgot the JSON contract, just call `store-progress` again with the correct JSON string in `output`. Your prior progress updates don\'t count as the final output.\n\n## Verify before completing\n\nRead your task description once more. Find the schema. Build the JSON. Then complete. Takes 30 seconds. Saves a workflow re-run.\n\n## See also\n\n- **`workflow-iterate`** — the author-side counterpart of this skill. Read it if you\'re editing the workflow that produced this task, or want to understand why this particular schema is shaped the way it is (which gates downstream depend on it, etc.).\n';
11636
11739
 
11637
11740
  // templates/skills/wts-expert/config.json
11638
- var config_default50 = `{
11741
+ var config_default51 = `{
11639
11742
  "category": "skills",
11640
11743
  "description": "Git worktree management expert for @desplega.ai/wts. Use when the user asks about git worktrees, wts commands, worktree workflows, or wants help managing multiple branches simultaneously.",
11641
11744
  "displayName": "WTS Expert",
@@ -11656,7 +11759,7 @@ var config_default50 = `{
11656
11759
  `;
11657
11760
 
11658
11761
  // templates/skills/wts-expert/content.md
11659
- var content_default50 = `# WTS Expert
11762
+ var content_default51 = `# WTS Expert
11660
11763
 
11661
11764
  You are an expert on \`@desplega.ai/wts\`, a CLI tool for managing Git worktrees with tmux integration, Claude Code launcher support, and GitHub PR creation.
11662
11765
 
@@ -11969,6 +12072,201 @@ last_updated_by: [Author name]
11969
12072
  ## Next Steps
11970
12073
 
11971
12074
  - [Handoff decision: research, plan, or parked]
12075
+ `
12076
+ }
12077
+ ],
12078
+ comms: [
12079
+ {
12080
+ path: "references/ste-rules.md",
12081
+ content: `# Precise mode — ASD-STE100 rules
12082
+
12083
+ Condensed from [asd-ste100-skill](https://github.com/desplega-ai/asd-ste100-skill) (MIT), which encodes the rule categories of ASD-STE100 Issue 9 (Jan 2025).
12084
+
12085
+ This encodes the standard's rule *categories*, not ASD's ~900-word approved dictionary (free to obtain, not free to redistribute). Structural rules are checkable from the description alone — apply them with confidence. Lexical rules depend on the dictionary — apply them as a direction of travel, and never imply dictionary compliance.
12086
+
12087
+ ## Structural rules — apply these
12088
+
12089
+ | Rule | Do | Don't |
12090
+ |---|---|---|
12091
+ | Active voice | "The agent deletes the file." | "The file is deleted (by the agent)." — unless the actor is genuinely unknown or irrelevant |
12092
+ | No phrasal verbs | "Remove the panel." / "Start the job." | "Take off the panel." / "Spin up the job." |
12093
+ | One instruction per sentence | "Open the file. Read line 3." | "Open the file and read line 3, then check if it matches." |
12094
+ | Sentence length | ≤20 words for instructions, ≤25 for descriptions | Long compound/subordinate-clause sentences |
12095
+ | No semicolons | Split into separate sentences | Any semicolon at all |
12096
+ | Noun clusters | ≤3 words stacked as a noun phrase | 4+ word noun stacks ("high pressure fuel pump inlet valve assembly") |
12097
+ | No ellipsis | Keep subject, verb, and article explicit | Drop words to save space ("Files not backed up will be lost" → ambiguous which files) |
12098
+ | Keep modality | "The request **may have** failed." stays "may have" | Promote a hedge to a fact, or invent a certainty the source did not state |
12099
+ | Paragraph limits | One topic per paragraph, ≤6 sentences | Multi-topic paragraphs |
12100
+ | Lists for sequences | Numbered/bulleted list for 3+ steps or conditions | A sequence buried in one prose sentence |
12101
+
12102
+ ## Lexical rules — direction of travel only
12103
+
12104
+ | Rule | Do | Don't |
12105
+ |---|---|---|
12106
+ | One word, one meaning | Pick one verb for one action and reuse it every time | Rotate synonyms ("check"/"verify"/"confirm") for the same action |
12107
+ | One part of speech per word | "Apply oil to the valve" (oil = noun) | "Oil the valve" (oil = verb) |
12108
+ | Verb, not noun | "Analyze the log." | "Perform an analysis of the log." |
12109
+ | Domain terms | Keep needed technical terms; define each once if not common English | Jargon never defined |
12110
+
12111
+ ## Simple tenses — one exception
12112
+
12113
+ STE permits infinitive, imperative, simple present, simple past, simple future, and past participle as adjective. It excludes present perfect: "we received the report", not "we have received the report". Exception: where the compound form carries information the simple form cannot — current relevance ("the job has completed" = output available now), or a hedge like "may have failed" — keep it and flag the departure.
12114
+
12115
+ ## Scan checklist
12116
+
12117
+ Scan for all six before rewriting. Each is mechanical — you can point at the exact word that breaks it.
12118
+
12119
+ 1. **Synonym rotation** — the same thing has several names ("the user", "the customer", "the client"). Fix: one name, every time.
12120
+ 2. **Hedge stacking** — qualifiers pile up until nothing is asserted ("it is important to note that this may potentially help to improve"). Fix: state the claim or delete it.
12121
+ 3. **Nominalization** — an action frozen into a noun ("perform an analysis of"). Fix: use the verb.
12122
+ 4. **Marketing adjectives** — seamless, robust, powerful, blazing-fast. Fix: delete, or replace with the measurement that earns the claim.
12123
+ 5. **Run-on sentences** — ideas joined by semicolons or em dashes. Fix: one idea per sentence.
12124
+ 6. **Soft phrasal verbs** — spin up, reach out, dive into, kick off. Fix: the single plain verb (start, contact, read, begin).
12125
+
12126
+ ## Process
12127
+
12128
+ 1. Pick the sub-mode (Strict or STE-flavored). Keep the choice internal unless asked.
12129
+ 2. Read the input once for meaning before rewriting anything.
12130
+ 3. Walk it sentence by sentence; flag every violation. In STE-flavored, flag lexical rules but do not enforce them.
12131
+ 4. Rewrite each flagged sentence, preserving the original meaning exactly. If a rewrite would drop necessary precision (a safety condition, scope qualifier, number), keep the longer phrasing and flag it. Check modality before committing — a shorter sentence that upgrades a hedge to a fact is a different claim. Never add a fact the source did not state.
12132
+ 5. Output the rewritten text alone. If the input already complies, say so — do not force changes.
12133
+
12134
+ ## Diff table format (on request)
12135
+
12136
+ When asked to "show the diff" / "which rules did it break" / "before/after":
12137
+
12138
+ \`\`\`markdown
12139
+ | Rule violated | Original | Simplified |
12140
+ |---|---|---|
12141
+ | Present perfect tense | "We have received your request." | "We received your request." |
12142
+ | Noun cluster (4+ words) | "the agent task queue priority handler" | "the handler that sets task-queue priority" |
12143
+
12144
+ Mode: Strict. 7 violations found.
12145
+ \`\`\`
12146
+
12147
+ Follow with one line naming anything deliberately not simplified, and why.
12148
+
12149
+ ## Boundaries
12150
+
12151
+ - Not a certified STE authoring tool — a clarity tool inspired by the standard. For aerospace-grade compliance, check word-by-word against the official dictionary from [asd-ste100.org](https://www.asd-ste100.org/STE_downloads.html).
12152
+ - Fixes form, not substance: a hollow paragraph rewritten under these rules is a clean hollow paragraph. Say so instead of polishing it.
12153
+ - Stop when the sentence is unambiguous, not when it is shortest.
12154
+ `
12155
+ },
12156
+ {
12157
+ path: "references/visual-shapes.md",
12158
+ content: `# Visual mode — example shapes
12159
+
12160
+ Concrete examples for each view the Visual mode can produce. Source: the show-me skill (bundled into this skill).
12161
+
12162
+ Logic or an algorithm as pseudocode:
12163
+
12164
+ \`\`\`text
12165
+ on(save)
12166
+ if content is unchanged
12167
+ return cached result
12168
+ write new content
12169
+ return fresh result
12170
+ \`\`\`
12171
+
12172
+ Runtime control flow as a call tree:
12173
+
12174
+ \`\`\`text
12175
+ submitForm
12176
+ createSession
12177
+ persistPrompt
12178
+ launchAgent
12179
+ navigateToSession
12180
+ \`\`\`
12181
+
12182
+ UI structure as a component tree, including state and module boundaries that matter:
12183
+
12184
+ \`\`\`tsx
12185
+ <SessionPage> (apps/example/src/routes/session.tsx)
12186
+ useSessionEvents()
12187
+ <SessionToolbar>
12188
+ <RunSkillButton> (packages/ui)
12189
+ \`\`\`
12190
+
12191
+ File responsibility or a broad refactor as a shallow file tree:
12192
+
12193
+ \`\`\`text
12194
+ src/
12195
+ ├── commands/ # parses user actions
12196
+ ├── sessions/ # owns session state
12197
+ └── transport/ # sends API requests
12198
+ \`\`\`
12199
+
12200
+ Component interaction, control flow, or data flow with Mermaid:
12201
+
12202
+ \`\`\`mermaid
12203
+ sequenceDiagram
12204
+ participant User
12205
+ participant UI
12206
+ participant Daemon
12207
+ User->>UI: choose command
12208
+ UI->>Daemon: send expanded prompt
12209
+ Daemon-->>UI: stream result
12210
+ \`\`\`
12211
+
12212
+ \`diff\` shapes — match the diff to the topic.
12213
+
12214
+ Component change:
12215
+
12216
+ \`\`\`diff
12217
+ <SessionPage>
12218
+ useSessionEvents()
12219
+ <SessionToolbar>
12220
+ + <RunSkillButton />
12221
+ <SessionTimeline>
12222
+ + <SkillResultCard />
12223
+ \`\`\`
12224
+
12225
+ File-layout change:
12226
+
12227
+ \`\`\`diff
12228
+ src/
12229
+ ├── commands/
12230
+ +│ └── show-me.ts # expands the slash command
12231
+ ├── sessions/
12232
+ -└── transport.ts
12233
+ +└── transport/
12234
+ + ├── client.ts
12235
+ + └── stream.ts
12236
+ \`\`\`
12237
+
12238
+ Call-tree change:
12239
+
12240
+ \`\`\`diff
12241
+ submitForm
12242
+ createSession
12243
+ persistPrompt
12244
+ + expandSkillMention
12245
+ launchAgent
12246
+ - navigateToSession
12247
+ + navigateToSession
12248
+ + subscribeToEvents
12249
+ \`\`\`
12250
+
12251
+ State or control-flow change:
12252
+
12253
+ \`\`\`diff
12254
+ on(save)
12255
+ - write content
12256
+ + if content is unchanged
12257
+ + return cached result
12258
+ + write new content
12259
+ + invalidate cache
12260
+ \`\`\`
12261
+
12262
+ Whole block when most of it is new or a copyable target shape is needed:
12263
+
12264
+ \`\`\`ts
12265
+ function expandSkill(command: string): string {
12266
+ const skillName = command.slice(1)
12267
+ return \`use the \${skillName} skill\`
12268
+ }
12269
+ \`\`\`
11972
12270
  `
11973
12271
  }
11974
12272
  ],
@@ -14276,7 +14574,8 @@ var BUILT_IN_SKILL_SOURCES = [
14276
14574
  { config: config_default47, body: content_default47 },
14277
14575
  { config: config_default48, body: content_default48 },
14278
14576
  { config: config_default49, body: content_default49 },
14279
- { config: config_default50, body: content_default50 }
14577
+ { config: config_default50, body: content_default50 },
14578
+ { config: config_default51, body: content_default51 }
14280
14579
  ];
14281
14580
  function canonicalFiles(files) {
14282
14581
  return [...files].sort((a, b) => a.path.localeCompare(b.path)).map((file) => `${file.path}
@@ -14494,7 +14793,7 @@ async function runSeeders(seeders, opts) {
14494
14793
  var import_cron_parser = __toESM(require_dist(), 1);
14495
14794
 
14496
14795
  // templates/schedules/daily-blocker-digest/config.json
14497
- var config_default51 = `{
14796
+ var config_default52 = `{
14498
14797
  "kind": "schedule",
14499
14798
  "name": "daily-blocker-digest",
14500
14799
  "displayName": "Daily Blocker Digest",
@@ -14511,7 +14810,7 @@ var config_default51 = `{
14511
14810
  `;
14512
14811
 
14513
14812
  // templates/schedules/daily-blocker-digest/content.md
14514
- var content_default51 = `# Daily Blocker Digest
14813
+ var content_default52 = `# Daily Blocker Digest
14515
14814
 
14516
14815
  Delivery uses configured admin channels with an in-app fallback.
14517
14816
 
@@ -14681,7 +14980,7 @@ Call \`store-progress\` with status \`completed\` and an output paragraph coveri
14681
14980
  `;
14682
14981
 
14683
14982
  // templates/schedules/daily-compounding-reflection/config.json
14684
- var config_default52 = `{
14983
+ var config_default53 = `{
14685
14984
  "kind": "schedule",
14686
14985
  "name": "daily-compounding-reflection",
14687
14986
  "displayName": "Daily Evolution",
@@ -14703,7 +15002,7 @@ var config_default52 = `{
14703
15002
  `;
14704
15003
 
14705
15004
  // templates/schedules/daily-compounding-reflection/content.md
14706
- var content_default52 = `# Daily Compounding Reflection
15005
+ var content_default53 = `# Daily Compounding Reflection
14707
15006
 
14708
15007
  Delivery uses configured admin channels with an in-app fallback.
14709
15008
 
@@ -14928,7 +15227,7 @@ If you have zero changes across all three folds and zero deferred items, somethi
14928
15227
  `;
14929
15228
 
14930
15229
  // templates/schedules/daily-status-report/config.json
14931
- var config_default53 = `{
15230
+ var config_default54 = `{
14932
15231
  "kind": "schedule",
14933
15232
  "name": "daily-status-report",
14934
15233
  "displayName": "Daily Status Report",
@@ -14945,7 +15244,7 @@ var config_default53 = `{
14945
15244
  `;
14946
15245
 
14947
15246
  // templates/schedules/daily-status-report/content.md
14948
- var content_default53 = `# Daily Status Report
15247
+ var content_default54 = `# Daily Status Report
14949
15248
 
14950
15249
  Give the operator one daily read on whether the swarm is healthy: what's running, what's failed, what's waiting on them.
14951
15250
 
@@ -15028,7 +15327,7 @@ Integration setup: [missing credentials from /status], or all verified.
15028
15327
  `;
15029
15328
 
15030
15329
  // templates/schedules/daily-workflow-health-audit/config.json
15031
- var config_default54 = `{
15330
+ var config_default55 = `{
15032
15331
  "kind": "schedule",
15033
15332
  "name": "daily-workflow-health-audit",
15034
15333
  "displayName": "Daily Workflow Health Audit",
@@ -15045,7 +15344,7 @@ var config_default54 = `{
15045
15344
  `;
15046
15345
 
15047
15346
  // templates/schedules/daily-workflow-health-audit/content.md
15048
- var content_default54 = `# Daily Workflow Health Audit
15347
+ var content_default55 = `# Daily Workflow Health Audit
15049
15348
 
15050
15349
  Delivery uses configured admin channels with an in-app fallback.
15051
15350
 
@@ -15239,7 +15538,7 @@ Omit any section whose count is 0. Cap message at 4000 chars (Slack limit) — i
15239
15538
  `;
15240
15539
 
15241
15540
  // templates/schedules/gtm-weekly-review/config.json
15242
- var config_default55 = `{
15541
+ var config_default56 = `{
15243
15542
  "kind": "schedule",
15244
15543
  "name": "gtm-weekly-review",
15245
15544
  "displayName": "Weekly GTM Metrics Review",
@@ -15256,7 +15555,7 @@ var config_default55 = `{
15256
15555
  `;
15257
15556
 
15258
15557
  // templates/schedules/gtm-weekly-review/content.md
15259
- var content_default55 = `Template parameters: {{REPO_URL}}, {{GSC_PROPERTY}}
15558
+ var content_default56 = `Template parameters: {{REPO_URL}}, {{GSC_PROPERTY}}
15260
15559
 
15261
15560
  # Weekly GTM Metrics Review
15262
15561
 
@@ -15337,7 +15636,7 @@ This is part of your team's GTM goal; update the goal statement before enabling
15337
15636
  `;
15338
15637
 
15339
15638
  // templates/schedules/weekly-code-health-reports/config.json
15340
- var config_default56 = `{
15639
+ var config_default57 = `{
15341
15640
  "kind": "schedule",
15342
15641
  "name": "weekly-code-health-reports",
15343
15642
  "displayName": "Weekly Code Health Reports",
@@ -15354,7 +15653,7 @@ var config_default56 = `{
15354
15653
  `;
15355
15654
 
15356
15655
  // templates/schedules/weekly-code-health-reports/content.md
15357
- var content_default56 = `# Weekly Code Health Reports
15656
+ var content_default57 = `# Weekly Code Health Reports
15358
15657
 
15359
15658
  Template parameters: {{REPO_URL}}, {{BRANCH}}, {{SCOPE_PATH}}, {{REPORT_NAME}}, {{PAGE_ID}}
15360
15659
 
@@ -15419,7 +15718,7 @@ Call \`store-progress\` with status \`completed\` and an output summary that inc
15419
15718
  `;
15420
15719
 
15421
15720
  // templates/schedules/weekly-dependabot-triage/config.json
15422
- var config_default57 = `{
15721
+ var config_default58 = `{
15423
15722
  "kind": "schedule",
15424
15723
  "name": "weekly-dependabot-triage",
15425
15724
  "displayName": "Weekly Dependency Triage",
@@ -15436,7 +15735,7 @@ var config_default57 = `{
15436
15735
  `;
15437
15736
 
15438
15737
  // templates/schedules/weekly-dependabot-triage/content.md
15439
- var content_default57 = `# Weekly Dependency Triage
15738
+ var content_default58 = `# Weekly Dependency Triage
15440
15739
 
15441
15740
  Template parameters: {{SLACK_CHANNEL_ID}}, {{REPO_URL}}, {{TIMEZONE}}
15442
15741
 
@@ -15490,7 +15789,7 @@ Call \`store-progress\` with status \`completed\` and an output summary listing
15490
15789
  `;
15491
15790
 
15492
15791
  // templates/schedules/weekly-dora-metrics/config.json
15493
- var config_default58 = `{
15792
+ var config_default59 = `{
15494
15793
  "kind": "schedule",
15495
15794
  "name": "weekly-dora-metrics",
15496
15795
  "displayName": "Weekly DORA Metrics",
@@ -15507,7 +15806,7 @@ var config_default58 = `{
15507
15806
  `;
15508
15807
 
15509
15808
  // templates/schedules/weekly-dora-metrics/content.md
15510
- var content_default58 = `# Weekly DORA Metrics
15809
+ var content_default59 = `# Weekly DORA Metrics
15511
15810
 
15512
15811
  Template parameters: {{REPO_URL}}, {{BRANCH}}, {{TAG_PATTERN}}, {{REPORT_NAME}}, {{PAGE_ID}}
15513
15812
 
@@ -15576,7 +15875,7 @@ Call \`store-progress\` with status \`completed\` and an output summary that inc
15576
15875
  init_db();
15577
15876
 
15578
15877
  // templates/workflows/alerts-triage/config.json
15579
- var config_default59 = `{
15878
+ var config_default60 = `{
15580
15879
  "kind": "workflow",
15581
15880
  "name": "alerts-triage",
15582
15881
  "displayName": "Alerts Triage",
@@ -15593,7 +15892,7 @@ var config_default59 = `{
15593
15892
  `;
15594
15893
 
15595
15894
  // templates/workflows/alerts-triage/content.md
15596
- var content_default59 = `# Alerts Triage
15895
+ var content_default60 = `# Alerts Triage
15597
15896
 
15598
15897
  The Slack handler emits \`slack.message\`; this workflow keeps the event-driven path and deduplicates work after the channel filter.
15599
15898
 
@@ -15613,7 +15912,7 @@ The Slack handler emits \`slack.message\`; this workflow keeps the event-driven
15613
15912
  `;
15614
15913
 
15615
15914
  // templates/workflows/autopilot/config.json
15616
- var config_default60 = `{
15915
+ var config_default61 = `{
15617
15916
  "kind": "workflow",
15618
15917
  "name": "autopilot",
15619
15918
  "displayName": "Autopilot Feature Pipeline",
@@ -15630,7 +15929,7 @@ var config_default60 = `{
15630
15929
  `;
15631
15930
 
15632
15931
  // templates/workflows/autopilot/content.md
15633
- var content_default60 = `# Autopilot Feature Pipeline
15932
+ var content_default61 = `# Autopilot Feature Pipeline
15634
15933
 
15635
15934
  Template parameter: {{REPO_URL}}
15636
15935
 
@@ -15642,7 +15941,7 @@ Use this workflow as a canonical feature delivery pipeline. Customize roles and
15642
15941
  `;
15643
15942
 
15644
15943
  // templates/workflows/competitor-radar/config.json
15645
- var config_default61 = `{
15944
+ var config_default62 = `{
15646
15945
  "kind": "workflow",
15647
15946
  "name": "competitor-radar",
15648
15947
  "displayName": "Competitor Radar",
@@ -15659,7 +15958,7 @@ var config_default61 = `{
15659
15958
  `;
15660
15959
 
15661
15960
  // templates/workflows/competitor-radar/content.md
15662
- var content_default61 = `# Competitor Radar
15961
+ var content_default62 = `# Competitor Radar
15663
15962
 
15664
15963
  This self-hosted port retains the scheduled, fixture, extraction, gap-analysis, litmus, cooldown, and bounded-report behavior. Its pinned GSC helper is embedded in the workflow, so it does not fetch executable code from Desplega infrastructure.
15665
15964
 
@@ -15669,7 +15968,7 @@ This self-hosted port retains the scheduled, fixture, extraction, gap-analysis,
15669
15968
  `;
15670
15969
 
15671
15970
  // templates/workflows/docs-site-releases/config.json
15672
- var config_default62 = `{
15971
+ var config_default63 = `{
15673
15972
  "kind": "workflow",
15674
15973
  "name": "docs-site-releases",
15675
15974
  "displayName": "Documentation Release Notes",
@@ -15686,7 +15985,7 @@ var config_default62 = `{
15686
15985
  `;
15687
15986
 
15688
15987
  // templates/workflows/docs-site-releases/content.md
15689
- var content_default62 = `# Documentation Release Notes
15988
+ var content_default63 = `# Documentation Release Notes
15690
15989
 
15691
15990
  This topology-preserving self-hosted port removes installation-specific identities, endpoints, and credentials while retaining the live workflow's nodes, edges, input mappings, guards, retries, cooldown, and triggers. Configure the declared template parameters and integrations before enabling it.
15692
15991
 
@@ -15701,7 +16000,7 @@ This topology-preserving self-hosted port removes installation-specific identiti
15701
16000
  `;
15702
16001
 
15703
16002
  // templates/workflows/linear-drain-loop/config.json
15704
- var config_default63 = `{
16003
+ var config_default64 = `{
15705
16004
  "kind": "workflow",
15706
16005
  "name": "linear-drain-loop",
15707
16006
  "displayName": "Linear Drain Loop",
@@ -15723,7 +16022,7 @@ var config_default63 = `{
15723
16022
  `;
15724
16023
 
15725
16024
  // templates/workflows/linear-drain-loop/content.md
15726
- var content_default63 = `# Linear Drain Loop
16025
+ var content_default64 = `# Linear Drain Loop
15727
16026
 
15728
16027
  Template parameter: {{LINEAR_PROJECT_ID}}
15729
16028
 
@@ -15768,7 +16067,7 @@ Blocked and ambiguous items are explicitly left alone — the dispatch node surf
15768
16067
  `;
15769
16068
 
15770
16069
  // templates/workflows/llm-safe-release-context/config.json
15771
- var config_default64 = `{
16070
+ var config_default65 = `{
15772
16071
  "kind": "workflow",
15773
16072
  "name": "llm-safe-release-context",
15774
16073
  "displayName": "LLM-Safe Release Context",
@@ -15785,7 +16084,7 @@ var config_default64 = `{
15785
16084
  `;
15786
16085
 
15787
16086
  // templates/workflows/llm-safe-release-context/content.md
15788
- var content_default64 = `# LLM-Safe Release Context
16087
+ var content_default65 = `# LLM-Safe Release Context
15789
16088
 
15790
16089
  Template parameters: {{ORG_ID}}, {{REPO_URL}}
15791
16090
 
@@ -15859,7 +16158,7 @@ This avoids the common failure mode where a large \`context.json\` fills the mod
15859
16158
  `;
15860
16159
 
15861
16160
  // templates/workflows/pr-review-status-sweep/config.json
15862
- var config_default65 = `{
16161
+ var config_default66 = `{
15863
16162
  "kind": "workflow",
15864
16163
  "name": "pr-review-status-sweep",
15865
16164
  "displayName": "PR Review Status Sweep",
@@ -15876,7 +16175,7 @@ var config_default65 = `{
15876
16175
  `;
15877
16176
 
15878
16177
  // templates/workflows/pr-review-status-sweep/content.md
15879
- var content_default65 = `# PR Review Status Sweep
16178
+ var content_default66 = `# PR Review Status Sweep
15880
16179
 
15881
16180
  This topology-preserving self-hosted port removes installation-specific identities, endpoints, and credentials while retaining the live workflow's nodes, edges, input mappings, guards, retries, cooldown, and triggers. Configure the declared template parameters and integrations before enabling it.
15882
16181
 
@@ -15889,7 +16188,7 @@ This topology-preserving self-hosted port removes installation-specific identiti
15889
16188
  `;
15890
16189
 
15891
16190
  // templates/workflows/ralph-loop/config.json
15892
- var config_default66 = `{
16191
+ var config_default67 = `{
15893
16192
  "kind": "workflow",
15894
16193
  "name": "ralph-loop",
15895
16194
  "displayName": "Iterative Review Loop",
@@ -15906,7 +16205,7 @@ var config_default66 = `{
15906
16205
  `;
15907
16206
 
15908
16207
  // templates/workflows/ralph-loop/content.md
15909
- var content_default66 = `# Iterative Review Loop
16208
+ var content_default67 = `# Iterative Review Loop
15910
16209
 
15911
16210
  Template parameter: {{REPO_URL}}
15912
16211
 
@@ -15957,14 +16256,14 @@ The \`maxIterations\` parameter is declarative: the reviewer signals PASS when d
15957
16256
  init_db();
15958
16257
  var asText2 = (value) => value;
15959
16258
  var BUILT_IN_WORKFLOW_SOURCES = [
15960
- { config: asText2(config_default59), content: asText2(content_default59) },
15961
16259
  { config: asText2(config_default60), content: asText2(content_default60) },
15962
16260
  { config: asText2(config_default61), content: asText2(content_default61) },
15963
16261
  { config: asText2(config_default62), content: asText2(content_default62) },
15964
16262
  { config: asText2(config_default63), content: asText2(content_default63) },
15965
16263
  { config: asText2(config_default64), content: asText2(content_default64) },
15966
16264
  { config: asText2(config_default65), content: asText2(content_default65) },
15967
- { config: asText2(config_default66), content: asText2(content_default66) }
16265
+ { config: asText2(config_default66), content: asText2(content_default66) },
16266
+ { config: asText2(config_default67), content: asText2(content_default67) }
15968
16267
  ];
15969
16268
  function sortJson(value) {
15970
16269
  if (Array.isArray(value))
@@ -16073,26 +16372,26 @@ var workflowsSeeder = createWorkflowsSeeder();
16073
16372
  // src/be/seed/schedules-seeder.ts
16074
16373
  var asText3 = (value) => value;
16075
16374
  var BUILT_IN_SCHEDULE_SOURCES = [
16076
- { config: asText3(config_default51), content: asText3(content_default51) },
16077
- {
16078
- config: asText3(config_default52),
16079
- content: asText3(content_default52)
16080
- },
16081
- { config: asText3(config_default53), content: asText3(content_default53) },
16375
+ { config: asText3(config_default52), content: asText3(content_default52) },
16082
16376
  {
16083
- config: asText3(config_default54),
16084
- content: asText3(content_default54)
16377
+ config: asText3(config_default53),
16378
+ content: asText3(content_default53)
16085
16379
  },
16086
- { config: asText3(config_default55), content: asText3(content_default55) },
16380
+ { config: asText3(config_default54), content: asText3(content_default54) },
16087
16381
  {
16088
- config: asText3(config_default56),
16089
- content: asText3(content_default56)
16382
+ config: asText3(config_default55),
16383
+ content: asText3(content_default55)
16090
16384
  },
16385
+ { config: asText3(config_default56), content: asText3(content_default56) },
16091
16386
  {
16092
16387
  config: asText3(config_default57),
16093
16388
  content: asText3(content_default57)
16094
16389
  },
16095
- { config: asText3(config_default58), content: asText3(content_default58) }
16390
+ {
16391
+ config: asText3(config_default58),
16392
+ content: asText3(content_default58)
16393
+ },
16394
+ { config: asText3(config_default59), content: asText3(content_default59) }
16096
16395
  ];
16097
16396
  function parseScheduleSource(source) {
16098
16397
  const config = JSON.parse(source.config);