@desplega.ai/agent-swarm 1.91.0 → 1.92.1

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 (114) hide show
  1. package/README.md +3 -2
  2. package/openapi.json +1005 -152
  3. package/package.json +6 -6
  4. package/plugin/skills/pages/SKILL.md +5 -2
  5. package/src/be/db.ts +662 -19
  6. package/src/be/memory/constants.ts +2 -1
  7. package/src/be/memory/providers/openai-embedding.ts +2 -5
  8. package/src/be/memory/providers/sqlite-store.ts +293 -76
  9. package/src/be/memory/types.ts +35 -0
  10. package/src/be/migrations/083_script_workflows.sql +51 -0
  11. package/src/be/migrations/084_script_run_journal_duration.sql +5 -0
  12. package/src/be/migrations/085_script_runs_kind.sql +9 -0
  13. package/src/be/migrations/086_pages_default_authed.sql +64 -0
  14. package/src/be/migrations/087_skill_files.sql +19 -0
  15. package/src/be/modelsdev-cache.json +42310 -38617
  16. package/src/be/scripts/typecheck.ts +49 -0
  17. package/src/be/seed-scripts/catalog/boot-triage.ts +221 -0
  18. package/src/be/seed-scripts/catalog/catalog-report.ts +457 -0
  19. package/src/be/seed-scripts/catalog/compound-insights.ts +310 -6
  20. package/src/be/seed-scripts/catalog/gh-pr-snapshot.ts +1 -1
  21. package/src/be/seed-scripts/catalog/memory-eval.ts +1059 -0
  22. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +506 -0
  23. package/src/be/seed-scripts/catalog/schedule-health.ts +78 -2
  24. package/src/be/seed-scripts/catalog/task-context-gathering.ts +92 -0
  25. package/src/be/seed-scripts/catalog/task-failure-audit.ts +48 -1
  26. package/src/be/seed-scripts/catalog/tool-usage.ts +6 -3
  27. package/src/be/seed-scripts/index.ts +51 -5
  28. package/src/be/seed-skills/index.ts +3 -3
  29. package/src/be/skill-sync.ts +91 -7
  30. package/src/be/swarm-config-guard.ts +17 -0
  31. package/src/commands/runner.ts +49 -4
  32. package/src/heartbeat/templates.ts +20 -16
  33. package/src/http/db-query.ts +20 -5
  34. package/src/http/index.ts +51 -7
  35. package/src/http/mcp-user.ts +23 -0
  36. package/src/http/mcp.ts +58 -0
  37. package/src/http/memory.ts +58 -0
  38. package/src/http/pages.ts +1 -1
  39. package/src/http/script-runs.ts +557 -0
  40. package/src/http/scripts.ts +39 -2
  41. package/src/http/skills.ts +225 -0
  42. package/src/prompts/session-templates.ts +24 -4
  43. package/src/providers/claude-adapter.ts +107 -28
  44. package/src/script-workflows/executor.ts +110 -0
  45. package/src/script-workflows/harness.ts +73 -0
  46. package/src/script-workflows/label-lint.ts +51 -0
  47. package/src/script-workflows/limits.ts +22 -0
  48. package/src/script-workflows/supervisor.ts +139 -0
  49. package/src/script-workflows/workflow-ctx.ts +209 -0
  50. package/src/scripts-runtime/sdk-allowlist.ts +4 -0
  51. package/src/scripts-runtime/swarm-sdk.ts +13 -0
  52. package/src/scripts-runtime/types/stdlib.d.ts +61 -0
  53. package/src/scripts-runtime/types/swarm-sdk.d.ts +61 -0
  54. package/src/server.ts +4 -0
  55. package/src/slack/handlers.ts +11 -4
  56. package/src/slack/message-text.ts +98 -0
  57. package/src/slack/thread-buffer.ts +5 -3
  58. package/src/tests/claude-adapter-binary.test.ts +271 -74
  59. package/src/tests/create-page-tool.test.ts +19 -2
  60. package/src/tests/db-query.test.ts +28 -0
  61. package/src/tests/error-tracker.test.ts +121 -0
  62. package/src/tests/harness-provider-resolution.test.ts +33 -0
  63. package/src/tests/heartbeat-checklist.test.ts +36 -0
  64. package/src/tests/mcp-tools.test.ts +6 -0
  65. package/src/tests/mcp-transport-gc.test.ts +58 -0
  66. package/src/tests/memory-health-endpoint.test.ts +78 -0
  67. package/src/tests/memory-store.test.ts +221 -1
  68. package/src/tests/pages-http.test.ts +20 -2
  69. package/src/tests/pages-storage.test.ts +26 -0
  70. package/src/tests/prompt-template-session.test.ts +34 -5
  71. package/src/tests/script-runs-http.test.ts +278 -0
  72. package/src/tests/script-workflows-label-lint.test.ts +43 -0
  73. package/src/tests/script-workflows-runtime-e2e.test.ts +170 -0
  74. package/src/tests/scripts-mcp-e2e.test.ts +102 -2
  75. package/src/tests/seed-scripts.test.ts +468 -3
  76. package/src/tests/skill-files-http.test.ts +171 -0
  77. package/src/tests/skill-files.test.ts +162 -0
  78. package/src/tests/skill-get-file-tool.test.ts +110 -0
  79. package/src/tests/skill-sync.test.ts +125 -6
  80. package/src/tests/slack-message-text.test.ts +250 -0
  81. package/src/tests/system-default-skills.test.ts +40 -0
  82. package/src/tools/create-page.ts +2 -2
  83. package/src/tools/db-query.ts +16 -6
  84. package/src/tools/script-runs.ts +123 -0
  85. package/src/tools/skills/index.ts +1 -0
  86. package/src/tools/skills/skill-get-file.ts +80 -0
  87. package/src/tools/slack-read.ts +12 -3
  88. package/src/tools/tool-config.ts +6 -2
  89. package/src/types.ts +72 -0
  90. package/src/utils/error-tracker.ts +40 -1
  91. package/src/utils/internal-ai/complete-structured.ts +10 -4
  92. package/src/workflows/executors/raw-llm.ts +76 -59
  93. package/templates/schedules/daily-blocker-digest/content.md +68 -54
  94. package/templates/schedules/daily-compounding-reflection/content.md +4 -4
  95. package/templates/schedules/daily-hn-briefing/content.md +5 -5
  96. package/templates/schedules/daily-workflow-health-audit/content.md +6 -6
  97. package/templates/schedules/gtm-weekly-review/content.md +9 -9
  98. package/templates/schedules/weekly-dependabot-triage/content.md +24 -20
  99. package/templates/skills/agentmail-sending/content.md +6 -7
  100. package/templates/skills/desloppify/content.md +8 -9
  101. package/templates/skills/jira-interaction/content.md +25 -33
  102. package/templates/skills/kapso-whatsapp/content.md +29 -30
  103. package/templates/skills/linear-interaction/content.md +8 -9
  104. package/templates/skills/pages/content.md +205 -55
  105. package/templates/skills/profile-corruption-escalation/content.md +44 -85
  106. package/templates/skills/script-workflows/config.json +14 -0
  107. package/templates/skills/script-workflows/content.md +68 -0
  108. package/templates/skills/sprite-cli/content.md +4 -5
  109. package/templates/skills/swarm-scripts/content.md +2 -3
  110. package/templates/skills/turso-interaction/content.md +14 -17
  111. package/templates/skills/workflow-iterate/content.md +38 -391
  112. package/templates/skills/x-api-interactions/content.md +4 -6
  113. package/templates/skills/scheduled-task-resilience/config.json +0 -14
  114. package/templates/skills/scheduled-task-resilience/content.md +0 -95
@@ -1,85 +1,235 @@
1
1
  # Pages
2
2
 
3
- Pages are persistent, shareable HTML documents created via the swarm's `create_page` MCP tool. Use them when the output benefits from layout, tables, headers, and persistent sharing unlike Slack messages, pages don't expire and can be bookmarked.
3
+ Pages are persistent, shareable HTML documents created via the swarm's page tooling. Use them when the output benefits from layout, tables, headers, and persistent sharing. A page should be a clean human-facing report, not a raw dump with a URL.
4
+
5
+ This skill covers both how to publish and how to design the page. It distills the current external design guidance from Anthropic's `frontend-design`, Vercel's `composition-patterns`, and Vercel's `web-design-guidelines`: start from content hierarchy, use a small spacing system, keep typography readable, prefer restraint over decoration, and make responsive behavior intentional.
4
6
 
5
7
  ## When to Create a Page
6
8
 
7
9
  - A report, dashboard, or summary that benefits from structured layout
8
10
  - Analysis that should be linkable and bookmarkable
9
- - Results that need to be reviewed asynchronously (not in a Slack thread)
10
- - Content that's too long or rich for a `store-progress.output` string
11
+ - Results that need to be reviewed asynchronously
12
+ - Content that is too long or rich for a `store-progress.output` string
11
13
 
12
14
  Do NOT use pages for:
13
- - In-flight progress notes (use `store-progress.progress`)
14
- - Sensitive data (credentials, private customer data)
15
- - Large binary files (use agent-fs for PNG/MP4)
15
+
16
+ - In-flight progress notes; use `store-progress.progress`
17
+ - Secrets, private credentials, or unapproved personal data
18
+ - Large binary files; use agent-fs for PNG/MP4
19
+ - Raw verbose logs; summarize them and link to artifacts
20
+
21
+ ## Page Design Defaults
22
+
23
+ Every page should be useful at a glance.
24
+
25
+ - Put the page's point in the first viewport: title, one-sentence summary, and 3-6 key numbers or statuses.
26
+ - Use a single-column reading spine with `max-width: 1120px`; keep prose measure around 65-75 characters.
27
+ - Use system fonts unless there is a clear reason not to: `Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`.
28
+ - Use a restrained palette: neutral background, high-contrast text, white panels, one accent color, and semantic colors for statuses only.
29
+ - Use a consistent spacing scale: `8, 12, 16, 24, 32, 48, 72`.
30
+ - Use clear type hierarchy: page title 36-48px desktop / 30-36px mobile, section titles 22-28px, body 15-16px, supporting text 13-14px.
31
+ - Keep tables readable: sticky/scannable headers where useful, padded cells, zebra-free or very subtle row borders, `tabular-nums` for numbers, horizontal scroll on narrow screens.
32
+ - Prefer cards only for repeated records or metrics. Do not nest cards inside cards.
33
+ - Hide raw JSON behind a collapsed `<details>` block at the bottom.
34
+ - Make mobile explicit with media queries: single-column grids, reduced padding, no overflow except intentional table scroll.
35
+
36
+ ## Content Structure
37
+
38
+ Use this order unless the task gives a better domain-specific structure:
39
+
40
+ 1. Hero: title, short summary, timestamp/source context
41
+ 2. Key metrics: 3-6 tiles that answer "how big / how bad / what changed?"
42
+ 3. Findings or sections grouped by theme, owner, severity, or stage
43
+ 4. Evidence tables or samples under each finding
44
+ 5. Next actions or recommendations
45
+ 6. Raw evidence links / collapsed JSON appendix
46
+
47
+ Write section headings as labels, not slogans. Favor "Critical Routing Gaps" over "Things We Found".
16
48
 
17
49
  ## Creating a Page
18
50
 
51
+ Use the page tool with an HTML body. Prefer `contentType: "text/html"` and an explicit `authMode` for internal reports.
52
+
19
53
  ```javascript
20
- // Via MCP tool
21
- create_page({
22
- title: "Q2 SEO Performance Report",
23
- content: `<h1>Q2 SEO Performance</h1>
24
- <p>Analysis period: 2026-04-01 to 2026-06-30</p>
25
- <h2>Summary</h2>
26
- <table>
27
- <tr><th>Metric</th><th>Q1</th><th>Q2</th><th>Change</th></tr>
28
- <tr><td>Organic clicks</td><td>12,400</td><td>18,600</td><td>+50%</td></tr>
29
- </table>
30
- <h2>Next Actions</h2>
31
- <ul>
32
- <li>Publish 3 new pillar pages targeting high-intent queries</li>
33
- <li>Fix 23 pages with missing meta descriptions</li>
34
- </ul>`
35
- })
54
+ const html = `<!doctype html>
55
+ <html lang="en">
56
+ <head>
57
+ <meta charset="utf-8">
58
+ <meta name="viewport" content="width=device-width, initial-scale=1">
59
+ <title>Q2 SEO Performance</title>
60
+ <style>
61
+ :root {
62
+ color-scheme: light;
63
+ --bg: #f6f4f0;
64
+ --panel: #ffffff;
65
+ --ink: #18181b;
66
+ --muted: #62646a;
67
+ --line: #dedbd2;
68
+ --accent: #2563eb;
69
+ --danger: #b42318;
70
+ --warn: #b54708;
71
+ --ok: #067647;
72
+ --radius: 8px;
73
+ --shadow: 0 1px 2px rgba(24, 24, 27, 0.06), 0 12px 32px rgba(24, 24, 27, 0.07);
74
+ }
75
+ * { box-sizing: border-box; }
76
+ body {
77
+ margin: 0;
78
+ background: var(--bg);
79
+ color: var(--ink);
80
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
81
+ font-size: 16px;
82
+ line-height: 1.55;
83
+ }
84
+ main {
85
+ width: min(1120px, calc(100% - 32px));
86
+ margin: 0 auto;
87
+ padding: 48px 0 72px;
88
+ }
89
+ header { margin-bottom: 32px; }
90
+ .eyebrow {
91
+ margin: 0 0 8px;
92
+ color: var(--muted);
93
+ font-size: 13px;
94
+ font-weight: 700;
95
+ letter-spacing: 0.08em;
96
+ text-transform: uppercase;
97
+ }
98
+ h1 {
99
+ margin: 0;
100
+ max-width: 780px;
101
+ font-size: clamp(2rem, 4vw, 3rem);
102
+ line-height: 1.05;
103
+ letter-spacing: 0;
104
+ }
105
+ .lede {
106
+ max-width: 760px;
107
+ margin: 16px 0 0;
108
+ color: var(--muted);
109
+ font-size: 18px;
110
+ }
111
+ .metrics {
112
+ display: grid;
113
+ grid-template-columns: repeat(4, minmax(0, 1fr));
114
+ gap: 12px;
115
+ margin: 32px 0;
116
+ }
117
+ .metric, .section {
118
+ background: var(--panel);
119
+ border: 1px solid var(--line);
120
+ border-radius: var(--radius);
121
+ box-shadow: var(--shadow);
122
+ }
123
+ .metric { padding: 18px; }
124
+ .metric strong {
125
+ display: block;
126
+ font-size: 32px;
127
+ line-height: 1;
128
+ font-variant-numeric: tabular-nums;
129
+ }
130
+ .metric span {
131
+ display: block;
132
+ margin-top: 8px;
133
+ color: var(--muted);
134
+ font-size: 13px;
135
+ font-weight: 650;
136
+ }
137
+ .section {
138
+ margin-top: 18px;
139
+ padding: 24px;
140
+ }
141
+ h2 { margin: 0 0 12px; font-size: 24px; line-height: 1.2; }
142
+ h3 { margin: 0 0 8px; font-size: 17px; line-height: 1.3; }
143
+ p { margin: 0 0 12px; }
144
+ .table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }
145
+ table { width: 100%; border-collapse: collapse; min-width: 640px; }
146
+ th, td { padding: 10px 12px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
147
+ th { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; }
148
+ td { font-size: 14px; }
149
+ code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
150
+ details { margin-top: 24px; }
151
+ summary { cursor: pointer; font-weight: 700; }
152
+ pre { overflow: auto; padding: 16px; background: #111827; color: #f9fafb; border-radius: var(--radius); }
153
+ @media (max-width: 760px) {
154
+ main { width: min(100% - 24px, 1120px); padding-top: 32px; }
155
+ .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
156
+ .section { padding: 18px; }
157
+ }
158
+ @media (max-width: 520px) {
159
+ .metrics { grid-template-columns: 1fr; }
160
+ .lede { font-size: 16px; }
161
+ }
162
+ </style>
163
+ </head>
164
+ <body>
165
+ <main>
166
+ <header>
167
+ <p class="eyebrow">Generated 2026-06-04</p>
168
+ <h1>Q2 SEO Performance</h1>
169
+ <p class="lede">Organic traffic grew sharply, but the next gains depend on fixing thin page metadata and publishing three high-intent pillar pages.</p>
170
+ </header>
171
+
172
+ <section class="metrics" aria-label="Key metrics">
173
+ <div class="metric"><strong>18.6k</strong><span>Organic clicks</span></div>
174
+ <div class="metric"><strong>+50%</strong><span>Quarter over quarter</span></div>
175
+ <div class="metric"><strong>23</strong><span>Metadata fixes</span></div>
176
+ <div class="metric"><strong>3</strong><span>Priority pages</span></div>
177
+ </section>
178
+
179
+ <section class="section">
180
+ <h2>Summary</h2>
181
+ <p>Start with the conclusion. Add tables only after the reader understands what changed and what to do next.</p>
182
+ <div class="table-wrap">
183
+ <table>
184
+ <thead><tr><th>Metric</th><th>Q1</th><th>Q2</th><th>Change</th></tr></thead>
185
+ <tbody><tr><td>Organic clicks</td><td>12,400</td><td>18,600</td><td>+50%</td></tr></tbody>
186
+ </table>
187
+ </div>
188
+ </section>
189
+ </main>
190
+ </body>
191
+ </html>`;
192
+
193
+ await create_page({
194
+ title: "Q2 SEO Performance",
195
+ slug: "q2-seo-performance",
196
+ description: "Human-readable SEO performance report with summary metrics and next actions.",
197
+ contentType: "text/html",
198
+ authMode: "authed",
199
+ body: html,
200
+ });
36
201
  ```
37
202
 
38
- Returns a page ID. Build the share URL:
39
- ```
203
+ Returns a page ID. Build share URLs from environment:
204
+
205
+ ```text
40
206
  ${APP_URL}/pages/<pageId> # opens in SPA with chrome
41
207
  ${APP_URL}/pages/<pageId>?mode=full # slim header, full viewport
42
- ${MCP_BASE_URL}/p/<pageId> # direct HTML (no SPA)
208
+ ${MCP_BASE_URL}/p/<pageId> # direct HTML
43
209
  ```
44
210
 
45
- Read `APP_URL` and `MCP_BASE_URL` from environment never hardcode.
211
+ Read `APP_URL` and `MCP_BASE_URL` from environment. Never hardcode localhost or example hosts in shared output.
46
212
 
47
- ## Content Guidelines
213
+ ## Design Checklist
48
214
 
49
- **Keep raw evidence in artifacts and link to it.** The page should contain:
50
- 1. **Short summary** (1 paragraph) — what this covers and the key finding
51
- 2. **Source links** — links to the data, agent-fs artifacts, or upstream systems
52
- 3. **Structured content** — tables, headers, numbered lists
53
- 4. **Next actions** — what should happen next, who owns it
215
+ Before publishing:
54
216
 
55
- Do NOT embed:
56
- - Secrets or private credentials
57
- - Personal data of individuals without approval
58
- - Raw verbose logs (summarize them)
217
+ - The first viewport states what the page is, why it matters, and the key numbers.
218
+ - The page has a clear hierarchy: `h1`, short lede, metrics, sections, evidence.
219
+ - Body text is readable on mobile and desktop.
220
+ - Tables scroll horizontally on mobile instead of crushing columns.
221
+ - Status colors are semantic and not the whole visual identity.
222
+ - Raw JSON/logs are collapsed or linked, not the primary experience.
223
+ - No nested cards, decorative gradients, oversized hero art, or cramped default browser styles.
224
+ - No text overlaps, clipped buttons, or unreadable low-contrast text.
59
225
 
60
- ## Page vs. Agent-fs
226
+ ## Page vs Agent-fs
61
227
 
62
228
  | Use pages for | Use agent-fs for |
63
229
  |---|---|
64
230
  | Reports, dashboards, human-readable summaries | Markdown research notes, code files, recordings |
65
231
  | Content that benefits from HTML layout | Searchable knowledge base entries |
66
- | Quick share links to non-technical stakeholders | Binary artifacts (PNG, MP4) |
232
+ | Quick share links to non-technical stakeholders | Binary artifacts such as PNG or MP4 |
67
233
  | Time-bounded deliverables | Long-lived reference documentation |
68
234
 
69
- ## Sharing Pages
70
-
71
- Always use the platform share URL (from `APP_URL` env var) rather than hardcoded local hosts. Append `?mode=full` for a standalone view (hides sidebar/header — good for screenshots or embedding in Slack previews).
72
-
73
- ```bash
74
- # Get the share URL
75
- PAGE_URL="${APP_URL}/pages/${pageId}?mode=full"
76
-
77
- # Post to Slack
78
- slack-reply --taskId <id> --message "Report ready: ${PAGE_URL}"
79
- ```
80
-
81
- ## Trade-offs
82
-
83
- **Pages vs Slack messages:** Slack messages are ephemeral and scroll out of view. Pages are persistent and bookmarkable. Use pages for anything you'd want to reference in 3 months; use Slack for in-the-moment communication.
84
-
85
- **Pages vs agent-fs:** Pages are rendered HTML with a share URL — great for non-technical stakeholders. Agent-fs files are raw content — great for other agents and developers who need the source data. For a research memo, write the source to agent-fs and create a page for the human-facing summary.
235
+ For a research memo, write the source to agent-fs and create a page for the human-facing summary.
@@ -1,105 +1,64 @@
1
1
  # Profile Corruption Escalation
2
2
 
3
- ## STATUS: Root cause for the Picateclas corruption family was found and fixed in PR #374 (merged 2026-04-24)
3
+ Use this skill when an agent's persisted profile (`SOUL.md`, `IDENTITY.md`, or equivalent DB fields) appears to be overwritten with placeholder, fixture, truncated, or otherwise invalid content.
4
4
 
5
- The 13-recurrence Picateclas corruption was traced to `src/tools/update-profile.ts:231` unconditionally writing `/workspace/SOUL.md` whenever `isUpdatingSelf=true`, plus the `update-profile-auth.test.ts` fixture setting a fake `WORKER_ID=bbbb0000-...` that satisfied the gate. The Stop hook then synced the corrupted file to DB. PR #374 fixed both:
6
- - `src/tools/update-profile.ts:231` — gated the file write on `requestInfo.agentId === process.env.AGENT_ID`
7
- - `src/hooks/hook.ts:359` — raised `IDENTITY_FILE_MIN_LENGTH` from 100 → 500 (defense in depth)
5
+ ## When to Use
8
6
 
9
- **14th restore** completed post-merge with a 1,930/2,065-char payload. If a **15th corruption** of Picateclas (or any agent) appears with the same sentinels post-2026-04-24, treat it as a **DIFFERENT code path**, not the same bug. Escalate immediately — do NOT just restore.
7
+ - An agent profile contains sentinel text such as "Test Worker", "Updated by Myself", repeated padding, or another canned payload.
8
+ - The profile is much shorter than the expected baseline.
9
+ - A recently restored profile was overwritten again.
10
+ - A hook, seeder, migration, test fixture, or profile-update tool may be writing to the wrong agent.
10
11
 
11
- See memories: `picateclas-14th-restore-post-pr374`, `reviewer-corruption-hunt-pattern`.
12
+ ## Triage Loop
12
13
 
13
- ## When to use
14
+ 1. Capture the corrupted payload, agent ID, and `lastUpdatedAt` timestamp before changing anything.
15
+ 2. Search memory and recent task history for the same sentinel string or same agent.
16
+ 3. Grep the source repo for exact sentinel strings. Stable placeholder text usually points to a fixture, seed path, or test helper faster than manual restoration does.
17
+ 4. Inspect code paths that can write profile files or profile DB fields: profile-update tools, startup hooks, stop/session hooks, seeders, migrations, and tests that set agent identity env vars.
18
+ 5. If you find the writer, fix or escalate the code path before restoring the profile.
19
+ 6. Restore only after evidence is captured, and only if restoration will not destroy useful debugging evidence.
14
20
 
15
- You inspect `get-swarm` and find an agent's `soulMd` or `identityMd` field corrupted — short placeholder content, unusual sentinels ("Test Worker", "Updated by Myself", "xxx" padding to bypass 200-char minLength), or any canned payload that you've seen before.
21
+ ## Escalation Threshold
16
22
 
17
- ## Step 0 Sentinel-grep BEFORE counting recurrences
23
+ Escalate instead of repeatedly restoring when any of these are true:
18
24
 
19
- Before applying the N-recurrence ceiling, **grep the agent-swarm repo for the literal sentinel strings**. The 13-recurrence Picateclas mystery was solved in 4m25s by grepping `"Test Worker"` — it should have happened at recurrence 2 or 3, not 13.
25
+ - The same profile is corrupted more than once in a short period.
26
+ - The sentinel text appears to come from code that knows schema limits or exact file paths.
27
+ - You cannot identify the writer quickly.
28
+ - A previous fix should already have eliminated this corruption family.
20
29
 
21
- Heuristic: if the corrupted payload contains stable sentinel content with padding sized to clear a known schema floor (e.g. exactly 200 chars to bypass `minLength=200`), the writer is **server-side code that knows the schema** — almost always a test fixture or seed script. Grep wins fast.
30
+ ## Escalation Package
22
31
 
23
- ```
24
- grep -rn '"Test Worker"' /workspace/repos/agent-swarm/src
25
- grep -rn '"Updated by Myself"' /workspace/repos/agent-swarm/src
26
- ```
27
-
28
- If you find the writer in <5 minutes, fix it (or open a PR) instead of restoring. That's the 1000× higher-value outcome.
32
+ Post a concise report to the operator channel or issue tracker with:
29
33
 
30
- See memory `reviewer-corruption-hunt-pattern` for the full pattern.
34
+ - Agent name and ID.
35
+ - Fresh write timestamp.
36
+ - Exact sentinel strings to search for.
37
+ - Whether you already grepped the repo and what matched.
38
+ - Suspected writer classes: hook, seeder, migration, test fixture, startup script, or profile-update tool.
39
+ - Whether you restored the profile or left it corrupted as evidence.
40
+ - Link to the task, log, or memory entry containing the captured payload.
31
41
 
32
- ## The N-recurrence ceiling rule
42
+ ## Report Template
33
43
 
34
- Apply this only AFTER step 0 fails (sentinel grep returns nothing in the repo).
44
+ ```text
45
+ Profile corruption detected
35
46
 
36
- Count prior corruptions of the same agent with the same sentinel. Consult memory first:
47
+ Agent: <agent-name> (<agent-id>)
48
+ Fresh write at: <timestamp>
49
+ Sentinel strings:
50
+ - "<literal-1>"
51
+ - "<literal-2>"
37
52
 
38
- ```
39
- memory-search "picateclas profile corruption" # or whichever agent name
40
- ```
41
-
42
- - **1st–12th occurrence**: Restore the profile (surgical update-profile with the agent's best-known-good SOUL/IDENTITY from your memory). Write a new `{agent}-{N}th-profile-corruption-{YYYY-MM-DD}` memory recording the state + escalation status.
43
- - **13th+ occurrence**: **STOP RESTORING.** Rebuild fatigue has proven the restore doesn't stick — the bug lives in code you don't control. Escalate instead.
44
-
45
- If you can't determine N from memory, treat anything ≥ 2 prior corruptions in < 7 days as "escalate now."
46
-
47
- **Post PR #374 (Apr 2026):** any new sentinel-payload corruption of any agent should be treated as recurrence 1 of a NEW bug — investigate fresh code paths, do not assume it's the same `update-profile.ts:231` issue.
48
-
49
- ## Escalation package (what to post)
50
-
51
- Use `slack-post` to the ops channel. Include ALL of:
52
-
53
- 1. **Sentinel payload strings as grep targets** — exact literals to search for in the source repo. Example: `"Test Worker"`, `"Updated by Myself"`, `xxxxx...` patterns. **State whether you already grepped (and what the result was).**
54
- 2. **Proof of fresh write** — `lastUpdatedAt` timestamp from `get-swarm`, newer than the previous restore. Without this it could be stale state, not new corruption.
55
- 3. **Corruption tally** — "N occurrences in ~M weeks, half-life now <24h."
56
- 4. **Investigation leads** — where to look:
57
- - Grep the `desplega-ai/agent-swarm` repo for the sentinel strings.
58
- - Check for scheduled tasks named `validate profile`, `test update-profile`, etc.
59
- - Check seed/migration scripts that run on container restart.
60
- - Audit `PostToolUse` hook content-validation (flagged in prior memories as "not shipped").
61
- - **Post PR #374:** Audit any other code path that writes `/workspace/SOUL.md` or `/workspace/IDENTITY.md` — the original bug was at `src/tools/update-profile.ts:231`; look for siblings.
62
- 5. **What you did NOT do** — explicit "I did not perform the Nth restore. Profile is left corrupted in DB as evidence."
63
-
64
- ## Template
65
-
66
- ```
67
- :rotating_light: Profile Corruption — {N}th recurrence — escalation trigger fired
68
-
69
- Agent: {name} ({id})
70
- Fresh write at: {lastUpdatedAt}
71
- Tally: {N} corruptions in ~{M} weeks, half-life {<hours>}h.
72
-
73
- Sentinel grep targets (expect to find in source):
74
- - "Test Worker"
75
- - "Updated by Myself"
76
- - Long "xxxxx…" padding literals
77
-
78
- I already grepped: {summary of grep result, e.g. "no hits in src/ post-#374 — this is a NEW code path"}.
79
-
80
- Investigation leads:
81
- 1. Grep agent-swarm for the sentinels above.
82
- 2. Check for scheduled "validate profile" / "test update-profile" tasks.
83
- 3. Audit seed/migration scripts on container restart.
84
- 4. Audit any code path that writes /workspace/SOUL.md or /workspace/IDENTITY.md (original bug was update-profile.ts:231).
85
-
86
- I did NOT perform the {N}th restore. Profile is corrupted in DB as evidence. Waiting for engineering fix before next restore.
87
-
88
- See memory: {agent}-{N}th-profile-corruption-{date}
53
+ Repo grep result: <matches or no matches>
54
+ Suspected writer: <hook/seeder/migration/test/tool/unknown>
55
+ Action taken: <restored profile | left as evidence | opened fix PR>
56
+ Evidence: <task/log/memory link>
89
57
  ```
90
58
 
91
59
  ## Gotchas
92
60
 
93
- - **Work quality profile validity.** Even a corrupted profile worker ships working code because the persona/working-style lives more in CLAUDE.md + memory than in the short SOUL.md. Don't let "but the agent still works" push you to keep restoring — that masks the bug.
94
- - **Don't rewrite CLAUDE.md during restoration.** In this corruption family, CLAUDE.md has been stable through 12 cycles. Only SOUL/IDENTITY get touched. Restoring CLAUDE.md too is wasted work and risks overwriting real learnings.
95
- - **Rotate escalation target.** If you've already escalated to one person and no fix in a week, try a different channel (DM vs public, a different engineer, a Linear ticket). Slack-only escalation can get missed.
96
- - **Don't auto-retry.** After escalating, do not put the restore back on a schedule. The next restore waits for explicit human ack ("OK to restore now, code fix merged").
97
- - **Sentinel-grep first, escalate second.** If a 2nd recurrence happens and you haven't grepped the sentinel literal yet, you're escalating prematurely. Grep is cheap (<5 min) and usually wins.
98
-
99
- ## Related
100
-
101
- - Memory family: `{agent}-Nth-profile-corruption-YYYY-MM-DD`
102
- - Memory: `reviewer-corruption-hunt-pattern` — the heuristic that solved the 13-recurrence mystery
103
- - Memory: `picateclas-14th-restore-post-pr374` — restore payload + the fix details
104
- - Lead rule #9 in CLAUDE.md: "Sentinel-grep before escalating recurring bugs"
105
-
61
+ - Do not rely on repeated manual restores as the fix. They can hide the writer and destroy evidence.
62
+ - Search exact sentinel strings before broad refactors; fixture text is usually distinctive.
63
+ - Do not overwrite unrelated profile files during restoration.
64
+ - Treat a recurrence after a code fix as a new investigation unless you can prove the same writer is still active.
@@ -0,0 +1,14 @@
1
+ {
2
+ "kind": "skill",
3
+ "name": "script-workflows",
4
+ "displayName": "Script Workflows",
5
+ "slug": "script-workflows",
6
+ "title": "Script Workflows",
7
+ "description": "Launch and inspect durable one-off script workflow runs with journaled swarm-script, raw-llm, and agent-task steps.",
8
+ "version": "1.0.0",
9
+ "category": "skills",
10
+ "placeholders": [],
11
+ "runAllSeedersCandidate": true,
12
+ "systemDefault": true,
13
+ "tags": ["scripts", "workflows", "automation"]
14
+ }
@@ -0,0 +1,68 @@
1
+ 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.
2
+
3
+ ## Tool Flow
4
+
5
+ Load the script workflow tools with ToolSearch when they are not already visible:
6
+
7
+ ```text
8
+ launch-script-run
9
+ get-script-run
10
+ list-script-runs
11
+ ```
12
+
13
+ Use `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.
14
+
15
+ Use `get-script-run` to read terminal status and journal entries. Poll it when needed, but keep polling bounded and report progress for long runs.
16
+
17
+ Use `list-script-runs` to find recent runs or filter by `status` / `agentId`.
18
+
19
+ Do 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.
20
+
21
+ ## Source Shape
22
+
23
+ Author TypeScript workflow source as a default export. The runtime provides `args` and `ctx`.
24
+
25
+ ```ts
26
+ export default async function main(args, ctx) {
27
+ const lookup = await ctx.step.swarmScript("lookup-data", {
28
+ scriptName: "fetch-readable",
29
+ args: { url: args.url },
30
+ });
31
+
32
+ const summary = await ctx.step.rawLlm("summarize", {
33
+ prompt: `Summarize this for an operator:\n${JSON.stringify(lookup)}`,
34
+ });
35
+
36
+ const task = await ctx.step.agentTask("operator-review", {
37
+ task: `Review this summary and flag risks:\n${JSON.stringify(summary)}`,
38
+ tags: ["script-run"],
39
+ priority: 50,
40
+ });
41
+
42
+ return { lookup, summary, task };
43
+ }
44
+ ```
45
+
46
+ ## Label Rules
47
+
48
+ Step 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`.
49
+
50
+ For looped work, include an item identifier in the label:
51
+
52
+ ```ts
53
+ for (const item of args.items) {
54
+ await ctx.step.agentTask(`review-${item.id}`, { task: item.prompt });
55
+ }
56
+ ```
57
+
58
+ ## Statuses
59
+
60
+ Terminal statuses to surface clearly:
61
+
62
+ - `completed` — run finished and `output` may be present.
63
+ - `failed` — run ended with `error`.
64
+ - `cancelled` — run was cancelled before completion.
65
+ - `aborted_limit` — runtime guardrail stopped the run, usually step count, agent-task count, or wall-clock cap.
66
+ - `label_lint_violation` — launch-time rejection, not a persisted run status.
67
+
68
+ When a run is not terminal, report the current status, journal count, and latest heartbeat if present.
@@ -29,7 +29,7 @@ The org token is stored in swarm config as `SPRITES_API_KEY` (global, secret). S
29
29
  sprite auth setup --token "$SPRITES_API_KEY"
30
30
  ```
31
31
 
32
- Token format is `<org>/<account_id>/<token_id>/<secret>`. The first segment is the org (`desplega`).
32
+ Token format is `<org>/<account_id>/<token_id>/<secret>`. The first segment is your organization slug.
33
33
 
34
34
  ## Core commands
35
35
 
@@ -45,9 +45,9 @@ Token format is `<org>/<account_id>/<token_id>/<secret>`. The first segment is t
45
45
 
46
46
  Flags: every command takes `-s <sprite>` (or sets a default via `sprite use`). `-o <org>` overrides the org if you have multiple.
47
47
 
48
- ## Sandbox baseline (as of 2026-05-07)
48
+ ## Sandbox baseline
49
49
 
50
- - Ubuntu 25.10 (Questing Quokka), kernel 6.12.x-fly (firecracker microVM)
50
+ - Ubuntu-based microVM image (exact version may change over time)
51
51
  - Non-root `sprite` user (uid 1001), passwordless `sudo`
52
52
  - No docker, no `/var/run/docker.sock`, no container runtime preinstalled
53
53
  - No systemd / init — `service` and `systemctl` won't work; start daemons manually with `sudo <daemon> &` or `nohup`
@@ -105,7 +105,7 @@ trap "sprite destroy test-$$ --force" EXIT INT TERM
105
105
  # … work …
106
106
  ```
107
107
 
108
- If a script crashes, `sprite list` shows what's still up. Sweep with `sprite list -o desplega` and destroy anything you don't recognize.
108
+ If a script crashes, `sprite list` shows what's still up. Sweep with `sprite list -o <org>` and destroy anything you don't recognize.
109
109
 
110
110
  ## Setup script snippet
111
111
 
@@ -130,4 +130,3 @@ grep -q '/.local/bin' "$HOME/.bashrc" 2>/dev/null || echo 'export PATH="$HOME/.l
130
130
  - **Daemon survival:** `sprite exec` runs in a fresh subshell. A daemon backgrounded with `&` survives the exec call (sprites use a shared init), but if you want to be safe use `nohup`. To stop it, `sprite exec -s … -- sudo pkill <daemon>`.
131
131
  - **Port forwarding:** ports inside the sprite are not exposed to your swarm container. Curl from *inside* the sprite (`sprite exec -s … -- curl localhost:5432`) — not from your container.
132
132
  - **Don't leak secrets:** treat the sprite as an untrusted host. Don't put production tokens in there.
133
-
@@ -66,14 +66,13 @@ Good named scripts:
66
66
 
67
67
  For scripts that aggregate over tasks, sessions, or memory, `ctx.swarm.db_query` with direct SQL is far more efficient than fetching lists client-side.
68
68
 
69
- **The parameter is `sql`, not `query`:**
69
+ **The parameter is `sql`:**
70
70
 
71
71
  ```typescript
72
72
  // CORRECT
73
73
  const res = await ctx.swarm.db_query({ sql: "SELECT status, count(*) as cnt FROM agent_tasks GROUP BY status" });
74
74
 
75
- // WRONG silently returns no data
76
- const res = await ctx.swarm.db_query({ query: "SELECT ..." });
75
+ // Legacy scripts may still run with `query`, but new code should not use it.
77
76
  ```
78
77
 
79
78
  **`db_query` returns positional rows, not objects.** The response shape is `{ rows: unknown[][], columns: string[] }`. Zip them into objects: