@acedatacloud/skills 2026.712.2 → 2026.713.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.
package/AGENTS.md CHANGED
@@ -24,6 +24,7 @@ Skills are located in the `skills/` directory (also mirrored to `.agents/skills/
24
24
  - **hailuo-video** — Generate videos with Hailuo / MiniMax
25
25
  - **seedance-video** — Generate dance/motion videos with ByteDance Seedance
26
26
  - **wan-video** — Generate videos with Alibaba Wan
27
+ - **maestro-video** — Produce complete videos from a brief with scripting, media, voiceover, editing, captions, and multilingual variants
27
28
 
28
29
  ### AI Chat & Tools
29
30
  - **ai-chat** — Unified LLM gateway — GPT, Claude, Gemini, Kimi, Grok (50+ models)
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  Compatible with **30+ AI coding agents** via the [agentskills.io](https://agentskills.io/) open standard: Claude Code, GitHub Copilot, Gemini CLI, OpenAI Codex, Cursor, Roo Code, Goose, and more.
14
14
 
15
- ## Available Skills (30)
15
+ ## Available Skills
16
16
 
17
17
  ### AI Music & Audio
18
18
 
@@ -40,6 +40,7 @@ Compatible with **30+ AI coding agents** via the [agentskills.io](https://agents
40
40
  | [kling-video](skills/kling-video/) | Generate videos with Kuaishou Kling (motion control) |
41
41
  | [hailuo-video](skills/hailuo-video/) | Generate videos with Hailuo / MiniMax |
42
42
  | [seedance-video](skills/seedance-video/) | Generate dance/motion videos with ByteDance Seedance |
43
+ | [maestro-video](skills/maestro-video/) | Produce complete videos from a brief with script, media, voiceover, captions, and editing |
43
44
 
44
45
  ### AI Chat & Tools
45
46
 
@@ -208,6 +209,7 @@ Skills provide **knowledge** (when to use, parameters, gotchas). MCP servers pro
208
209
  | veo-video | [mcp-veo](https://pypi.org/project/mcp-veo/) | `pip install mcp-veo` | `https://veo.mcp.acedata.cloud/mcp` |
209
210
  | seedream-image | [mcp-seedream](https://pypi.org/project/mcp-seedream/) | `pip install mcp-seedream` | `https://seedream.mcp.acedata.cloud/mcp` |
210
211
  | seedance-video | [mcp-seedance](https://pypi.org/project/mcp-seedance/) | `pip install mcp-seedance` | `https://seedance.mcp.acedata.cloud/mcp` |
212
+ | maestro-video | [mcp-maestro](https://pypi.org/project/mcp-maestro/) | `pip install mcp-maestro` | `https://maestro.mcp.acedata.cloud/mcp` |
211
213
  | nano-banana-image | [mcp-nano-banana](https://pypi.org/project/mcp-nano-banana/) | `pip install mcp-nano-banana` | `https://nano-banana.mcp.acedata.cloud/mcp` |
212
214
  | short-url | [mcp-shorturl](https://pypi.org/project/mcp-shorturl/) | `pip install mcp-shorturl` | `https://short-url.mcp.acedata.cloud/mcp` |
213
215
  | wan-video | [mcp-wan](https://pypi.org/project/mcp-wan/) | `pip install mcp-wan` | `https://wan.mcp.acedata.cloud/mcp` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acedatacloud/skills",
3
- "version": "2026.712.2",
3
+ "version": "2026.713.1",
4
4
  "description": "Agent Skills for AceDataCloud AI services — music, image, video generation, LLM chat, web search. Compatible with Claude Code, GitHub Copilot, Gemini CLI, OpenAI Codex, and 30+ AI coding agents.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -15,6 +15,7 @@ Each AceDataCloud service has a corresponding MCP server that provides tool-use
15
15
  | veo-video | `pip install mcp-veo` | `https://veo.mcp.acedata.cloud/mcp` |
16
16
  | seedream-image | `pip install mcp-seedream` | `https://seedream.mcp.acedata.cloud/mcp` |
17
17
  | seedance-video | `pip install mcp-seedance` | `https://seedance.mcp.acedata.cloud/mcp` |
18
+ | maestro-video | `pip install mcp-maestro` | `https://maestro.mcp.acedata.cloud/mcp` |
18
19
  | nano-banana-image | `pip install mcp-nano-banana` | `https://nano-banana.mcp.acedata.cloud/mcp` |
19
20
  | short-url | `pip install mcp-shorturl` | `https://short-url.mcp.acedata.cloud/mcp` |
20
21
  | wan-video | `pip install mcp-wan` | `https://wan.mcp.acedata.cloud/mcp` |
@@ -0,0 +1,271 @@
1
+ ---
2
+ name: maestro-video
3
+ description: "Produce complete AI videos with Maestro via AceDataCloud API. Use when: Maestro, article-to-video, prompt-to-video, turn a brief or reference media into a finished captioned video, generate scripts/visuals/voiceover/music/editing in one workflow, create multilingual video variants, or remix/edit/extend a previous Maestro video. Covers task creation, progress polling, history, and final output retrieval."
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: acedatacloud
7
+ version: "1.0"
8
+ compatibility: Requires ACEDATACLOUD_API_TOKEN in .env file (see _shared/authentication.md). Optionally pair with mcp-maestro for tool-use.
9
+ ---
10
+
11
+ # Maestro End-to-End Video Production
12
+
13
+ Use Maestro when the user wants a **finished video**, not only a generated clip. A headless AI director turns one natural-language brief into a script, visual assets, voiceover, music, edit, captions, quality checks, and rendered video variants.
14
+
15
+ > **Setup:** See [authentication](../_shared/authentication.md) for token setup.
16
+
17
+ ## Choose Maestro When
18
+
19
+ - The user wants an article, idea, product brief, or campaign turned into a complete video.
20
+ - The workflow needs scripting, visuals, narration, captions, and editing handled together.
21
+ - The user supplies product images, a logo, portrait, source footage, or reference audio.
22
+ - One visual production must be rendered in multiple languages.
23
+ - A completed Maestro video needs to be remixed, edited, or extended.
24
+
25
+ Use a model-specific video API such as Seedance, Kling, or Veo when the user only needs a short generated shot and wants direct model controls. Maestro may use multiple media services internally and is optimized for the finished production.
26
+
27
+ ## Quick Start
28
+
29
+ ```bash
30
+ curl -X POST https://api.acedata.cloud/maestro/videos \
31
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" \
32
+ -H "Content-Type: application/json" \
33
+ -d '{
34
+ "prompt": "Create a 30-second beginner-friendly video explaining vector databases. End with one memorable takeaway.",
35
+ "aspect": "16:9",
36
+ "duration": 30,
37
+ "quality": "standard",
38
+ "scenario": "narrated",
39
+ "langs": ["en"]
40
+ }'
41
+ ```
42
+
43
+ The response contains a `task_id`. Maestro is asynchronous, so query the task until it reaches `succeeded` or `failed`:
44
+
45
+ ```bash
46
+ curl -X POST https://api.acedata.cloud/maestro/tasks \
47
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" \
48
+ -H "Content-Type: application/json" \
49
+ -d '{"id": "<task_id>", "action": "retrieve"}'
50
+ ```
51
+
52
+ Do not invent output URLs or report completion while the task is still running.
53
+
54
+ ## Core Workflow
55
+
56
+ 1. Translate the user's goal into a concrete production brief.
57
+ 2. Call `POST /maestro/videos` and preserve the returned `task_id` and `trace_id`.
58
+ 3. Poll `POST /maestro/tasks` at a reasonable interval.
59
+ 4. Continue through nonterminal states; stop only at `succeeded` or `failed`.
60
+ 5. On success, return every item in `response.data.variants`, including its language and `output_url`.
61
+ 6. If requested, iterate by creating a new task with `action`, `ref_task_id`, and a change-focused prompt.
62
+
63
+ Polling and history queries are free; the video task is settled after production based on delivered output. Avoid submitting duplicate creation requests while an existing task is still running.
64
+
65
+ ## Creation Parameters
66
+
67
+ | Parameter | Type | Default | Description |
68
+ |---|---|---|---|
69
+ | `prompt` | string | required | Natural-language production brief: topic, audience, content, tone, and desired result |
70
+ | `action` | string | `generate` | `generate`, `remix`, `edit`, or `extend` |
71
+ | `ref_task_id` | string | - | Required for `remix`, `edit`, and `extend` |
72
+ | `file_urls` | string[] | - | Public image, video, or audio references, up to the limits enforced by the API |
73
+ | `langs` | string[] | `["zh-cn"]` | Output language codes; each creates a localized rendered variant |
74
+ | `aspect` | string | `9:16` | `9:16`, `16:9`, or `1:1` |
75
+ | `duration` | integer | `30` | Target duration from 1 to 600 seconds |
76
+ | `quality` | string | `standard` | `draft`, `standard`, or `premium` |
77
+ | `scenario` | string | `auto` | `auto`, `narrated`, `drama`, `avatar`, `motion`, or `slideshow` |
78
+ | `style` | string | `auto` | Preset or freeform visual direction |
79
+ | `voice` | string | `auto` | Cross-lingual voice preset or a 32-hex-character Fish reference ID |
80
+ | `callback_url` | string | - | Optional webhook called on success or failure |
81
+
82
+ ### Quality
83
+
84
+ - `draft`: fast rough cut for validating direction.
85
+ - `standard`: balanced default for normal production.
86
+ - `premium`: richer, more polished production with a higher cost and longer turnaround.
87
+
88
+ ### Scenarios
89
+
90
+ - `auto`: let the director choose from the brief.
91
+ - `narrated`: multi-scene explainer, documentary, brand, history, or product video with voiceover.
92
+ - `drama`: acted short drama with characters and dialogue.
93
+ - `avatar`: talking-head or digital-human video; normally provide a portrait in `file_urls`.
94
+ - `motion`: kinetic typography, data, logo, or abstract motion graphics.
95
+ - `slideshow`: presentation deck, pitch, or slide-led video.
96
+
97
+ ### Styles
98
+
99
+ Named presets include `cinematic`, `glass`, `luxury`, `swiss`, `modern`, `editorial`, `warm`, `vibrant`, `neon`, `mono`, `pastel`, `bold`, `industrial`, `futuristic`, and `retro`. The API also accepts a freeform style hint.
100
+
101
+ ### Voices
102
+
103
+ Available presets include:
104
+
105
+ - Female: `warm-female`, `bright-female`, `anchor-female`, `clean-female`
106
+ - Male: `calm-male`, `deep-male`, `documentary-male`, `energetic-male`, `storyteller-male`
107
+ - Automatic: `auto`
108
+
109
+ Voice controls timbre rather than language. The same preset speaks the language selected in `langs`.
110
+
111
+ ## Reference Media
112
+
113
+ Pass public URLs in `file_urls`:
114
+
115
+ ```json
116
+ {
117
+ "prompt": "Create a product launch video that clearly shows the camera body and logo. Use the supplied audio as the tone reference.",
118
+ "file_urls": [
119
+ "https://example.com/product.jpg",
120
+ "https://example.com/logo.png",
121
+ "https://example.com/reference.mp3"
122
+ ],
123
+ "scenario": "narrated",
124
+ "style": "editorial",
125
+ "aspect": "16:9"
126
+ }
127
+ ```
128
+
129
+ Reference URLs must be reachable by the service. Do not pass local file paths. Upload local assets first, then use their public URLs.
130
+
131
+ ## Multilingual Variants
132
+
133
+ Use one request to reuse the production across languages:
134
+
135
+ ```json
136
+ {
137
+ "prompt": "A concise product walkthrough for first-time customers",
138
+ "langs": ["en", "de", "ja"],
139
+ "voice": "warm-female",
140
+ "duration": 45
141
+ }
142
+ ```
143
+
144
+ The first language is primary. A successful task normally returns one item per delivered language in `response.data.variants`. Do not assume every requested language succeeded; inspect the actual variants.
145
+
146
+ ## Iterate on a Previous Video
147
+
148
+ All iteration actions require `ref_task_id`.
149
+
150
+ ### Remix
151
+
152
+ Use `remix` for a new creative interpretation that keeps the previous task as context:
153
+
154
+ ```json
155
+ {
156
+ "action": "remix",
157
+ "ref_task_id": "previous-task-id",
158
+ "prompt": "Rework this as a faster social cut with a stronger opening hook and neon styling.",
159
+ "aspect": "9:16"
160
+ }
161
+ ```
162
+
163
+ ### Edit
164
+
165
+ Use `edit` for targeted revisions:
166
+
167
+ ```json
168
+ {
169
+ "action": "edit",
170
+ "ref_task_id": "previous-task-id",
171
+ "prompt": "Keep the structure and visuals. Replace the final call to action and use a calmer narrator."
172
+ }
173
+ ```
174
+
175
+ ### Extend
176
+
177
+ Use `extend` to continue or lengthen the production:
178
+
179
+ ```json
180
+ {
181
+ "action": "extend",
182
+ "ref_task_id": "previous-task-id",
183
+ "prompt": "Add a 15-second customer example before the conclusion.",
184
+ "duration": 60
185
+ }
186
+ ```
187
+
188
+ Iteration creates a new task. Continue polling the new `task_id`; do not overwrite or confuse it with the source task.
189
+
190
+ ## Task Response
191
+
192
+ A task response exposes top-level progress for user feedback:
193
+
194
+ ```json
195
+ {
196
+ "id": "task-id",
197
+ "status": "producing",
198
+ "progress": {
199
+ "percent": 52,
200
+ "stage": "visuals",
201
+ "message": "Generating scene assets",
202
+ "activity": "Creating scene 4"
203
+ },
204
+ "response": null
205
+ }
206
+ ```
207
+
208
+ On success, inspect the delivered variants:
209
+
210
+ ```json
211
+ {
212
+ "status": "succeeded",
213
+ "response": {
214
+ "success": true,
215
+ "data": {
216
+ "variants": [
217
+ {
218
+ "lang": "en",
219
+ "output_url": "https://cdn.example/video.mp4",
220
+ "captions_url": "https://cdn.example/captions.vtt",
221
+ "cover_url": "https://cdn.example/cover.jpg",
222
+ "duration": 31.2,
223
+ "qc_score": 0.96
224
+ }
225
+ ]
226
+ }
227
+ }
228
+ }
229
+ ```
230
+
231
+ Treat the fields above as a shape guide. Return fields that are actually present; never fabricate missing captions, covers, durations, or QC scores.
232
+
233
+ ## List Recent Tasks
234
+
235
+ The live task endpoint also supports account history:
236
+
237
+ ```bash
238
+ curl -X POST https://api.acedata.cloud/maestro/tasks \
239
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" \
240
+ -H "Content-Type: application/json" \
241
+ -d '{"action": "retrieve_batch", "limit": 20}'
242
+ ```
243
+
244
+ Optional Unix timestamp filters are `created_at_min` and `created_at_max`. The authenticated identity determines which tasks are returned; do not supply or trust a body-level user ID.
245
+
246
+ ## Prompting Guidance
247
+
248
+ A useful brief answers:
249
+
250
+ - What is the subject and desired outcome?
251
+ - Who is the audience?
252
+ - What facts, products, people, or scenes must appear?
253
+ - What should the viewer feel or do afterward?
254
+ - Which platform determines aspect ratio and pacing?
255
+ - Are there exact brand, compliance, or wording constraints?
256
+
257
+ Prefer a concrete production brief over a list of low-level model instructions. Maestro is responsible for choosing and orchestrating media tools.
258
+
259
+ ## Gotchas
260
+
261
+ - This API is asynchronous. Always preserve and poll the returned `task_id`.
262
+ - Terminal states are `succeeded` and `failed`; other status names may evolve as the production pipeline changes.
263
+ - `remix`, `edit`, and `extend` fail without `ref_task_id`.
264
+ - `file_urls` must be public URLs, not local paths.
265
+ - `avatar` usually needs a usable portrait reference.
266
+ - Requested duration is a target; report the actual delivered duration from the result.
267
+ - Multilingual requests may return fewer variants than requested if one output fails.
268
+ - Do not resubmit the same brief merely because a long-running poll has not finished.
269
+ - Do not expose the API token in logs, output, source files, or examples.
270
+
271
+ > **MCP:** `pip install mcp-maestro` | Hosted: `https://maestro.mcp.acedata.cloud/mcp` | See [all MCP servers](../_shared/mcp-servers.md)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: reddit
3
- description: Submit posts (link or text) to subreddits and read your Reddit identity / content via the Reddit API. Use when the user mentions Reddit, posting to a subreddit, submitting a link or self-post, or checking their Reddit profile / submissions.
3
+ description: Submit posts (link or text) to subreddits and read your Reddit identity / submissions using either official OAuth or your own Reddit login cookies. Use when the user mentions Reddit, posting to a subreddit, submitting a link or self-post, or checking their Reddit profile / submissions.
4
4
  when_to_use: |
5
5
  Trigger when the user wants to submit a post to a subreddit (link or
6
6
  self/text post), or read their own Reddit identity and submissions.
@@ -8,75 +8,88 @@ when_to_use: |
8
8
  / karma requirements — confirm the target subreddit, title and body
9
9
  before submitting.
10
10
  connections: [reddit]
11
- allowed_tools: [Bash]
11
+ allowed_tools: [Bash, publish_artifact]
12
12
  license: Apache-2.0
13
13
  metadata:
14
14
  author: acedatacloud
15
- version: "1.0"
15
+ version: "2.0"
16
16
  ---
17
17
 
18
- Call the **Reddit API** (OAuth endpoints) with `curl + jq`. The user's bearer
19
- token is in `$REDDIT_TOKEN`. **Every call MUST send a `User-Agent` header** or
20
- Reddit returns `429`. Use the OAuth host `https://oauth.reddit.com`.
18
+ # Reddit OAuth or login-cookie access
21
19
 
22
- ```bash
23
- UA="web:cloud.acedata.connectors:v1.0 (by /u/acedatacloud)"
24
- ```
20
+ The connector injects exactly one of these credentials:
25
21
 
26
- Errors are JSON; a submit returns `{"json":{"errors":[...], "data":{...}}}`
27
- if `errors` is non-empty, show them verbatim. `401` token expired, re-connect.
22
+ - `REDDIT_COOKIES`: JSON cookie array captured by the ACE browser extension.
23
+ It includes `reddit_session` and grants full account access. **Secret never
24
+ echo, print, log or return it.**
25
+ - `REDDIT_TOKEN`: official OAuth bearer token (`identity read submit`).
28
26
 
29
- **Always start by confirming identity:**
27
+ The helper automatically prefers Cookie when present and otherwise uses OAuth.
28
+ It sends Reddit's required descriptive User-Agent and never forwards cookies
29
+ outside `reddit.com`.
30
30
 
31
- ```bash
32
- curl -sS -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
33
- "https://oauth.reddit.com/api/v1/me" | jq '{name, total_karma, link_karma}'
34
- ```
31
+ ## Script resolution
35
32
 
36
- ## Submit a post
37
-
38
- **Confirm the subreddit + title + body with the user first.** `sr` is the
39
- subreddit name WITHOUT the `r/` prefix.
40
-
41
- ```bash
42
- # Self (text) post: kind=self + text. Link post: kind=link + url.
43
- curl -sS -X POST "https://oauth.reddit.com/api/submit" \
44
- -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
45
- --data-urlencode "sr=test" \
46
- --data-urlencode "kind=self" \
47
- --data-urlencode "title=My title" \
48
- --data-urlencode "text=My self-post body in markdown" \
49
- --data-urlencode "api_type=json" \
50
- | jq '.json | {errors, url: .data.url, id: .data.id}'
33
+ Bash calls do not share shell variables. Resolve the helper inside **every**
34
+ fenced Bash invocation before using it:
35
+
36
+ ```sh
37
+ R="${SKILL_DIR:-}/scripts/reddit.py"; [ -f "$R" ] || R=$(find /tmp -maxdepth 8 -path '*/skills/*/reddit/scripts/reddit.py' -print -quit 2>/dev/null)
38
+ [ -f "$R" ] || { echo "reddit script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
39
+ python3 "$R" whoami
51
40
  ```
52
41
 
53
- For a link post:
42
+ If authentication fails, ask the user to reconnect at
43
+ <https://auth.acedata.cloud/user/connections>. Do not loop-retry a blocked or
44
+ expired session.
45
+
46
+ ## Read
54
47
 
55
- ```bash
56
- curl -sS -X POST "https://oauth.reddit.com/api/submit" \
57
- -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
58
- --data-urlencode "sr=test" --data-urlencode "kind=link" \
59
- --data-urlencode "title=My title" --data-urlencode "url=https://example.com" \
60
- --data-urlencode "api_type=json" | jq '.json'
48
+ ```sh
49
+ R="${SKILL_DIR:-}/scripts/reddit.py"; [ -f "$R" ] || R=$(find /tmp -maxdepth 8 -path '*/skills/*/reddit/scripts/reddit.py' -print -quit 2>/dev/null)
50
+ [ -f "$R" ] || { echo "reddit script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
51
+ python3 "$R" whoami
52
+ python3 "$R" submissions --limit 10
61
53
  ```
62
54
 
63
- ## Read my submissions
55
+ ## Submit a post — GATED
64
56
 
65
- ```bash
66
- curl -sS -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
67
- "https://oauth.reddit.com/user/USERNAME/submitted?limit=10" \
68
- | jq '.data.children[] | .data | {title, subreddit, ups, num_comments, permalink}'
69
- ```
57
+ Posting is public. **Always show the subreddit, final title and final body/URL,
58
+ then obtain explicit confirmation.** Without a trailing `--confirm`, both write
59
+ commands are dry-runs and make no network request.
60
+
61
+ ```sh
62
+ R="${SKILL_DIR:-}/scripts/reddit.py"; [ -f "$R" ] || R=$(find /tmp -maxdepth 8 -path '*/skills/*/reddit/scripts/reddit.py' -print -quit 2>/dev/null)
63
+ [ -f "$R" ] || { echo "reddit script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
70
64
 
71
- ## Gotchas
65
+ # Text post: use a file for long Markdown.
66
+ python3 "$R" submit-text --subreddit test --title "My title" --text-file post.md
67
+ python3 "$R" submit-text --subreddit test --title "My title" --text-file post.md --confirm
68
+
69
+ # Link post.
70
+ python3 "$R" submit-link --subreddit test --title "My title" --url "https://example.com"
71
+ python3 "$R" submit-link --subreddit test --title "My title" --url "https://example.com" --confirm
72
+ ```
72
73
 
73
- - **User-Agent is mandatory** on every request omitting it → `429`.
74
- - Many subreddits gate posting on **account age / karma / flair**; a submit can
75
- return `errors` like `[["SUBREDDIT_NOTALLOWED", ...]]` — surface it and try
76
- `r/test` to validate the flow.
77
- - Respect rate limits: read the `X-Ratelimit-Remaining` response header; space
78
- out bulk submits.
79
- - Use `r/test` as a safe target when validating that the connection works.
74
+ `--confirm` is honored only when it is the final argument. A title or body that
75
+ contains the text `--confirm` can never trigger a write.
76
+
77
+ ## Safety and failure handling
78
+
79
+ - Never print `REDDIT_COOKIES`, `REDDIT_TOKEN`, `reddit_session` or the modhash.
80
+ - Do not vote, send private messages, evade bans, automate engagement, or
81
+ cross-post identical content. This skill intentionally exposes none of those
82
+ operations.
83
+ - Follow each subreddit's rules. Account age, karma and flair requirements can
84
+ reject a post; report the rejection without exposing Reddit's raw authenticated
85
+ response, which may contain reflected credential material.
86
+ - Do not retry a write automatically. A timeout may occur after Reddit accepted
87
+ it, and replaying could create a duplicate.
88
+ - Respect rate limits and never bulk-submit. Use `r/test` only for a deliberate
89
+ end-to-end validation.
90
+ - Cookie mode drives Reddit's first-party web JSON endpoints and may drift when
91
+ Reddit changes its site. Report unexpected HTML or route errors as upstream
92
+ drift instead of guessing another private endpoint.
80
93
 
81
94
 
82
95
  ## Record the output