@lifeaitools/rdc-skills 0.13.5 → 0.13.7
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.
- package/.claude-plugin/plugin.json +9 -3
- package/package.json +1 -1
- package/skills/deploy/SKILL.md +100 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdc",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight unattended builds with work-item tracking and TDD enforcement.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "LIFEAI",
|
|
@@ -297,7 +297,7 @@
|
|
|
297
297
|
"name": "deploy",
|
|
298
298
|
"slash": "rdc:deploy",
|
|
299
299
|
"category": "deploy",
|
|
300
|
-
"usage": "rdc:deploy <slug> [new|diagnose|audit] [--fix]",
|
|
300
|
+
"usage": "rdc:deploy <slug> [new|diagnose|audit|promote] [--fix|--hotfix <sha>]",
|
|
301
301
|
"args": {
|
|
302
302
|
"positional": [
|
|
303
303
|
{
|
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
"name": "action",
|
|
311
311
|
"required": false,
|
|
312
312
|
"description": "Operation kind",
|
|
313
|
-
"accepts": "new | diagnose | audit | (omit for default deploy)"
|
|
313
|
+
"accepts": "new | diagnose | audit | promote | (omit for default deploy)"
|
|
314
314
|
}
|
|
315
315
|
],
|
|
316
316
|
"flags": [
|
|
@@ -319,6 +319,12 @@
|
|
|
319
319
|
"type": "bool",
|
|
320
320
|
"default": false,
|
|
321
321
|
"description": "Apply remediation during diagnose/audit"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"name": "--hotfix",
|
|
325
|
+
"type": "string",
|
|
326
|
+
"default": null,
|
|
327
|
+
"description": "With promote: cherry-pick this specific commit sha to main instead of the app-path develop delta"
|
|
322
328
|
}
|
|
323
329
|
]
|
|
324
330
|
},
|
package/package.json
CHANGED
package/skills/deploy/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rdc:deploy
|
|
3
|
-
description: "Usage `rdc:deploy <slug> [new|diagnose|audit] [--fix]` — Deploy an app to Coolify (production) or PM2 (staging), add a new Coolify app, diagnose a failed deploy, or audit watch paths. Handles DNS, health checks, and post-deploy verification."
|
|
3
|
+
description: "Usage `rdc:deploy <slug> [new|diagnose|audit|promote] [--fix|--hotfix <sha>]` — Deploy an app to Coolify (production) or PM2 (staging), promote a verified dev change to production (one-command cherry-pick → PR → admin-merge → explicit Coolify trigger → verify), add a new Coolify app, diagnose a failed deploy, or audit watch paths. Handles DNS, branch protection, health checks, and post-deploy verification."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
> **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
|
|
@@ -15,10 +15,11 @@ No raw MCP dumps. No UUIDs unless asked.
|
|
|
15
15
|
|
|
16
16
|
> **Sandbox contract:** This skill honors `RDC_TEST=1` per `guides/agent-bootstrap.md` § RDC_TEST Sandbox Contract. Destructive external calls short-circuit under the flag.
|
|
17
17
|
>
|
|
18
|
-
> *Under `$RDC_TEST=1`:* Modes 1 (deploy)
|
|
18
|
+
> *Under `$RDC_TEST=1`:* Modes 1 (deploy), 2 (new), and 5 (promote) are **entirely skipped** — echo `[RDC_TEST] skipping Coolify deploy/create/promote` and mark every `[ ]` line in those checklists as `[~]`. Modes 3 (diagnose) and 4 (audit without `--fix`) are **read-only and run normally**. Mode 4 with `--fix` skips all remediation — echo `[RDC_TEST] skipping audit --fix remediation` and report findings only. Registry SELECTs, Coolify status reads, HTTP gate probes, TLS checks, and DNS lookups are NOT destructive and run normally. Anything that writes (create app, set watch_paths, deploy trigger, **PR/admin-merge to main**, env var write, DNS write, CF cache purge, registry UPDATE/INSERT) is gated.
|
|
19
19
|
|
|
20
20
|
## When to Use
|
|
21
21
|
- Project lead says "deploy", "ship it", "push to production", "update the server"
|
|
22
|
+
- Project lead says "promote", "patch prod", "hotfix production", "push this fix live" — use `rdc:deploy <slug> promote`
|
|
22
23
|
- A new app needs to be registered and deployed for the first time (`rdc:deploy new`)
|
|
23
24
|
- A deployed app is behaving unexpectedly and needs diagnosis (`rdc:deploy diagnose`)
|
|
24
25
|
- Running a compliance/health audit of all deployed apps (`rdc:deploy audit`)
|
|
@@ -27,6 +28,8 @@ No raw MCP dumps. No UUIDs unless asked.
|
|
|
27
28
|
|
|
28
29
|
- `rdc:deploy <slug>` — deploy existing app (latest commit on its watched branch)
|
|
29
30
|
- `rdc:deploy <slug> <build-id>` — deploy specific commit/tag
|
|
31
|
+
- `rdc:deploy <slug> promote` — promote the verified `develop` change for this app to production (Mode 5)
|
|
32
|
+
- `rdc:deploy <slug> promote --hotfix <sha>` — promote a specific commit (cherry-pick just that sha to `main`)
|
|
30
33
|
- `rdc:deploy new <slug>` — create a new Coolify app from registry
|
|
31
34
|
- `rdc:deploy diagnose <slug>` — debug why an app is broken
|
|
32
35
|
- `rdc:deploy audit` — fleet-wide scan for missed failures
|
|
@@ -53,6 +56,7 @@ rdc:deploy: <slug> → <domain>
|
|
|
53
56
|
[ ] Gate: TLS valid (no SSL cipher mismatch)
|
|
54
57
|
[ ] Gate: cache headers correct on HTML
|
|
55
58
|
[ ] Gate: container running on declared port
|
|
59
|
+
[ ] Gate: metadata audit (see § Metadata Audit below) — warn on gaps, do not block deploy
|
|
56
60
|
[ ] Cloudflare cache purged (if proxied)
|
|
57
61
|
[ ] artifact_registry INSERT per PUBLISH.md surface (if PUBLISH.md present)
|
|
58
62
|
[ ] deployment_registry updated (last_deploy_at, status)
|
|
@@ -138,6 +142,96 @@ Severity rules:
|
|
|
138
142
|
|
|
139
143
|
`--fix` auto-remediates only: missing watch_paths, registry row updates, CF cache purges. Never touches env vars, DNS, or container config without explicit confirmation.
|
|
140
144
|
|
|
145
|
+
### Mode 5 — promote <slug> [--hotfix <sha>]
|
|
146
|
+
|
|
147
|
+
Promote a **verified `develop` change** for one app to production. This is the sanctioned production-patch fast path — one command instead of fighting branch protection, the main-push hook, and a flaky Coolify webhook by hand.
|
|
148
|
+
|
|
149
|
+
**Authorization:** production promote requires explicit user go-ahead ("promote", "patch prod", "push live", "go"). A dev deploy does NOT. If the user has not given it for THIS promote, stop and ask first.
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
rdc:deploy promote: <slug> → <prod-domain>
|
|
153
|
+
[ ] Registry lookup: PROD row (uuid, prod branch=main, watch_paths, url)
|
|
154
|
+
[ ] PUBLISH.md status gate: status=active AND prod in environments (block if not)
|
|
155
|
+
[ ] Scope resolved: --hotfix <sha> → that commit; else the app-path commits on develop not on main
|
|
156
|
+
[ ] Scope guard: promote ONLY this app's paths. NEVER merge develop→main wholesale (drags unrelated WIP to prod)
|
|
157
|
+
[ ] Clean worktree off origin/main (never switch the dirty working tree)
|
|
158
|
+
[ ] Apply change: cherry-pick <sha> (or `git checkout <develop-sha> -- <app-paths>`); confirm diff = expected files only
|
|
159
|
+
[ ] Mandatory pre-promote code-review (pr-review-toolkit:code-reviewer on the promote diff). Block on critical/high.
|
|
160
|
+
[ ] Commit on promote branch; push branch (NOT main directly — the main-push hook blocks raw main pushes)
|
|
161
|
+
[ ] Open PR base=main; merge with admin override (`gh pr merge --squash --admin --delete-branch`) — branch protection needs --admin
|
|
162
|
+
[ ] EXPLICITLY trigger Coolify deploy — NEVER rely on the GitHub→Coolify webhook (it silently no-ops on some merges even with auto-deploy ON)
|
|
163
|
+
[ ] Deployment reached "finished" state (poll coolify_events / deployment status)
|
|
164
|
+
[ ] Gate: HTTP 200 on prod domain
|
|
165
|
+
[ ] Gate: content-level check — assert the actual changed string is live (200 alone is NOT proof; origin may serve stale)
|
|
166
|
+
[ ] Gate: TLS valid
|
|
167
|
+
[ ] Gate: metadata audit (see § Metadata Audit below) — BLOCK promote on any missing required item
|
|
168
|
+
[ ] Cloudflare cache purged (if proxied)
|
|
169
|
+
[ ] deployment_registry updated (last_deploy_at, last_deploy_commit, status)
|
|
170
|
+
✅ rdc:deploy promote: <slug> live in prod — <changed-string> verified
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**The explicit Coolify trigger (the whole point — do not skip):**
|
|
174
|
+
```bash
|
|
175
|
+
_COOLIFY=$(curl -s http://127.0.0.1:52437/v/coolify-api)
|
|
176
|
+
# Correct endpoint is GET /api/v1/deploy?uuid= — NOT POST /applications/<uuid>/deploy (that 404s)
|
|
177
|
+
curl -s -H "Authorization: Bearer $_COOLIFY" \
|
|
178
|
+
"$DEPLOY_API_BASE/api/v1/deploy?uuid=<PROD_UUID>&force=true"
|
|
179
|
+
# → {"deployments":[{"deployment_uuid":"...","message":"...deployment queued."}]}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Why each guard exists (lessons from 2026-06-05 EF Hooper promote):**
|
|
183
|
+
- `main` branch protection rejects PR merge without `--admin`; a raw `git push …:main` is blocked by the main-push hook → must go branch → PR → admin-merge.
|
|
184
|
+
- Coolify auto-deploy was **ON** for the app yet the merge did **not** auto-deploy — a webhook-delivery flake. A promote must ALWAYS trigger the deploy explicitly and verify; never hope the webhook fired.
|
|
185
|
+
- `develop` was 87 commits ahead of `main` (unrelated apps' WIP). Promoting must be surgical (this app's paths / one sha), never a develop→main merge.
|
|
186
|
+
- HTTP 200 was returned by the stale origin the whole time — only a content-level assertion (`curl … | grep '<new string>'`) proves the promote landed.
|
|
187
|
+
|
|
188
|
+
## Metadata Audit
|
|
189
|
+
|
|
190
|
+
After a successful deploy or promote, audit the live site's `<head>` metadata. Run this against the deployed URL (not a local file).
|
|
191
|
+
|
|
192
|
+
**Check list** (curl the deployed URL, parse the HTML `<head>`):
|
|
193
|
+
|
|
194
|
+
| # | Item | How to check | Required | Severity |
|
|
195
|
+
|---|------|-------------|----------|----------|
|
|
196
|
+
| 1 | `<title>` | grep `<title>` — non-empty, not default/placeholder | yes | block |
|
|
197
|
+
| 2 | `<meta name="description">` | content attr ≥ 50 chars, ≤ 160 chars | yes | block on promote; warn on deploy |
|
|
198
|
+
| 3 | `<link rel="canonical">` | href present, starts with `https://`, matches the deployed domain | yes | block on promote; warn on deploy |
|
|
199
|
+
| 4 | `og:title` | `<meta property="og:title">` present | yes | block on promote; warn on deploy |
|
|
200
|
+
| 5 | `og:description` | `<meta property="og:description">` present, ≥ 50 chars | yes | block on promote; warn on deploy |
|
|
201
|
+
| 6 | `og:image` | `<meta property="og:image">` present, URL returns HTTP 200 | yes | block on promote; warn on deploy |
|
|
202
|
+
| 7 | `og:url` | present, matches canonical | recommended | warn |
|
|
203
|
+
| 8 | `twitter:card` | `summary_large_image` or `summary` | recommended | warn |
|
|
204
|
+
| 9 | `twitter:image` | present, URL returns HTTP 200 | recommended | warn |
|
|
205
|
+
| 10 | Favicon | `<link rel="icon">` present, href returns HTTP 200 | yes | block on promote; warn on deploy |
|
|
206
|
+
| 11 | `sitemap.xml` | `<domain>/sitemap.xml` returns HTTP 200 | recommended | warn |
|
|
207
|
+
| 12 | `robots.txt` | `<domain>/robots.txt` returns HTTP 200 | recommended | warn |
|
|
208
|
+
| 13 | Version | `<meta name="version">` or visible version string in page | yes (project rule) | warn |
|
|
209
|
+
|
|
210
|
+
**Behavior by mode:**
|
|
211
|
+
- **Mode 1 (deploy):** run the audit after HTTP/TLS gates. Print a table of results. **Warn** on gaps but do NOT block the deploy — dev deploys are iterative.
|
|
212
|
+
- **Mode 5 (promote):** run the audit after content-level check. **Block the promote** if any item marked "block on promote" is missing. Print the table and require the metadata to be fixed before re-attempting.
|
|
213
|
+
- **Mode 4 (audit):** include the metadata sweep in the fleet scan (one row per app per missing item in the findings table).
|
|
214
|
+
|
|
215
|
+
**Implementation — one-liner per check:**
|
|
216
|
+
```bash
|
|
217
|
+
URL="https://<domain>"
|
|
218
|
+
HEAD=$(curl -s "$URL" | sed -n '/<head/,/<\/head>/p')
|
|
219
|
+
echo "$HEAD" | grep -ioE '<title>[^<]+</title>'
|
|
220
|
+
echo "$HEAD" | grep -ioE 'name="description"[^>]*content="[^"]*"'
|
|
221
|
+
echo "$HEAD" | grep -ioE 'rel="canonical"[^>]*href="[^"]*"'
|
|
222
|
+
echo "$HEAD" | grep -ioE 'property="og:title"[^>]*content="[^"]*"'
|
|
223
|
+
echo "$HEAD" | grep -ioE 'property="og:image"[^>]*content="[^"]*"'
|
|
224
|
+
echo "$HEAD" | grep -ioE 'name="twitter:card"[^>]*content="[^"]*"'
|
|
225
|
+
echo "$HEAD" | grep -ioE 'rel="icon"[^>]*href="[^"]*"'
|
|
226
|
+
echo "$HEAD" | grep -ioE 'name="version"[^>]*content="[^"]*"'
|
|
227
|
+
curl -s -o /dev/null -w "%{http_code}" "$URL/sitemap.xml"
|
|
228
|
+
curl -s -o /dev/null -w "%{http_code}" "$URL/robots.txt"
|
|
229
|
+
OG_IMG=$(echo "$HEAD" | grep -ioE 'property="og:image"[^>]*content="([^"]*)"' | grep -ioE 'https://[^"]*')
|
|
230
|
+
[ -n "$OG_IMG" ] && curl -s -o /dev/null -w "%{http_code}" "$OG_IMG"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Why this exists (2026-06-05):** life.ai deployed to production with zero social/SEO metadata — no description, no OG, no favicon, no sitemap. HTTP 200 + TLS + content passed; metadata was invisible to the existing gates. This audit catches that class of defect.
|
|
234
|
+
|
|
141
235
|
## PUBLISH.md Integration
|
|
142
236
|
|
|
143
237
|
Every deploy reads `PUBLISH.md` from the app's source root to derive `watch_paths` and to register surfaces in Studio `artifact_registry`.
|
|
@@ -225,9 +319,10 @@ curl -s -H "Authorization: Bearer $_COOLIFY" \
|
|
|
225
319
|
curl -s -H "Authorization: Bearer $_COOLIFY" \
|
|
226
320
|
"$DEPLOY_API_BASE/api/v1/applications/<uuid>"
|
|
227
321
|
|
|
228
|
-
# Deploy (trigger)
|
|
229
|
-
|
|
230
|
-
|
|
322
|
+
# Deploy (trigger) — correct endpoint is GET /api/v1/deploy?uuid=
|
|
323
|
+
# (POST /applications/<uuid>/deploy returns {"message":"Not found."})
|
|
324
|
+
curl -s -H "Authorization: Bearer $_COOLIFY" \
|
|
325
|
+
"$DEPLOY_API_BASE/api/v1/deploy?uuid=<uuid>&force=true"
|
|
231
326
|
|
|
232
327
|
# Get deployment logs
|
|
233
328
|
curl -s -H "Authorization: Bearer $_COOLIFY" \
|