@quantod/qq 0.3.6 → 1.0.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.
@@ -0,0 +1,491 @@
1
+ # QQ — Complete Reference
2
+
3
+ QQ is a persistent, crash-safe pipeline for multi-stage agentic workflows. It is a **state machine with concurrency guarantees**: stages are states, items move through them, and `claim → release` is an atomic transition only one agent can hold at a time. State survives session restarts and crashes.
4
+
5
+ Use QQ when work fans out: web crawling, bulk API enrichment, research pipelines (find → filter → enrich), batch transforms, any task where multiple items move through multiple stages, possibly with concurrent agents working in parallel.
6
+
7
+ ---
8
+
9
+ ## Mental Model
10
+
11
+ A **pipeline** holds **items**. Each item lives in exactly one **stage** at a time. Items are pushed once and never deleted — they move between stages, accumulating payload as they go.
12
+
13
+ Stages are just labels. The pipeline has no built-in notion of "first" or "last" — you define the topology in your PIPELINES.md.
14
+
15
+ Items have:
16
+ - `id` — the deduplication key. Pushing an item with an existing id fails.
17
+ - `stage` — the current state
18
+ - `payload` — item data; append-only string by default; YAML by convention.
19
+ - `seq` — the claim token, returned by `claim`, required to `release`
20
+ - `priority` — float, higher = claimed first (default 0.0)
21
+
22
+ ---
23
+
24
+ ## The Core Loop
25
+
26
+ ```
27
+ make_pipeline → create a pipeline, get its name, once per setup
28
+ push (N times) → load items into a stage
29
+ claim → atomically lock one item (returns seq + payload)
30
+ ... do work ...
31
+ release → unlock item, move to next stage, append payload
32
+ status → monitor progress
33
+ unstick → recover stuck/lost items
34
+ ```
35
+
36
+ **Orchestrator** creates the pipeline, pushes items, spawns subagents, monitors with `status`, calls `batch_read` to collect results, calls `unstick` after.
37
+
38
+ **Subagent** claims one item, does its work, releases to the next stage, repeats until "no items to claim" — then stops and reports back.
39
+
40
+ ---
41
+
42
+ ## Orchestrator / Subagent Pattern
43
+
44
+ Orchestrator example:
45
+ ```
46
+ make_pipeline → "0529_a3f9c2" (store this as Q)
47
+ push Q/pending "url-1" payload: "url: https://a.com"
48
+ push Q/pending "url-2" payload: "url: https://b.com"
49
+ push Q/pending "url-3" payload: "url: https://c.com"
50
+ ```
51
+
52
+ Spawn subagents with instructions like:
53
+ > Claim an item from pipeline `0529_a3f9c2` stage `pending`. Open the URL. Extract name, price, availability. Release to `done` appending the fields. If the page fails, release to `failed` appending `error: <reason>`. Repeat until "No items to claim". Report back.
54
+
55
+ Monitor with `status` — done when `pending: [0, 0]` and nothing claimed.
56
+
57
+ ---
58
+
59
+ ## MCP Tools — Full Reference
60
+
61
+ ### make_pipeline
62
+
63
+ Creates a pipeline. Returns its name.
64
+
65
+ Parameters:
66
+ - `name` (string, optional) — custom name. Auto-generated (`MMDD_xxxxxx`) if omitted. Fails if name already taken.
67
+ - `description` (string, optional) — plain-text description of the pipeline's purpose.
68
+
69
+ Returns:
70
+ ```yaml
71
+ pipeline: 0529_a3f9c2
72
+ ```
73
+
74
+ ---
75
+
76
+ ### push
77
+
78
+ Pushes an item into a pipeline stage. Fails if an item with the same `id` already exists in the pipeline (deduplication).
79
+
80
+ Parameters:
81
+ - `pipeline` (string) — pipeline name
82
+ - `stage` (string, optional) — destination stage. Supports sub-paths: `enriched/shortlisted`. Defaults to empty string if omitted.
83
+ - `id` (string, optional) — stable unique identifier. Omit to use auto-generated seq number.
84
+ - `payload` (string, optional) — payload string
85
+ - `payloadFormat` (`yaml` | `json` | `text`, optional, default `yaml`) — `yaml`: validate as YAML. `json`: validate as JSON and minify to one line (appended payloads form valid JSONL). `text`: no validation.
86
+ - `priority` (number, optional) — float, default 0.0. Higher = claimed first. Only set when meaningful.
87
+
88
+ Returns:
89
+ ```yaml
90
+ id: url-1
91
+ ```
92
+
93
+ **ID strategy**: use the item's natural stable identity from its origin system — URL, database row id, API object id. Omit id only when items have no upstream identity.
94
+
95
+ ---
96
+
97
+ ### claim
98
+
99
+ Atomically claims the highest-priority lowest-seq unclaimed item from a stage. Returns the item with its full payload.
100
+
101
+ Parameters:
102
+ - `pipeline` (string)
103
+ - `stage` (string) — supports glob wildcards: `enriched/*`, `*`. Omit to claim from any stage.
104
+ - `id` (string, optional) — claim a specific item by id. Fails if not found or already claimed.
105
+ - `random` (boolean, optional) — claim a random unclaimed item instead of priority+seq order
106
+
107
+ Returns:
108
+ ```yaml
109
+ id: url-1
110
+ stage: pending
111
+ seq: 3
112
+ priority: 0
113
+ claimed: true
114
+ created: 1748476800000
115
+ last_modified: 1748476800000
116
+ payload: |
117
+ url: https://example.com/product/42
118
+ ```
119
+
120
+ Returns `error: no items to claim` when nothing is available. **Stop and report back when this happens** — do not retry.
121
+
122
+ Errors (MCP YAML / SDK JSON):
123
+ - `error: no items to claim` — stage is empty or all items are already claimed. Stop and report back.
124
+ - `error: item <id> not found` — only when claiming by specific `id`
125
+ - `error: item <id> already claimed` — only when claiming by specific `id`
126
+
127
+ **Save the `seq` value** — it is your claim token, required to call `release`.
128
+
129
+ ---
130
+
131
+ ### release
132
+
133
+ Releases a claimed item. Optionally moves it to a new stage and appends/replaces payload.
134
+
135
+ Parameters:
136
+ - `pipeline` (string)
137
+ - `seq` (number) — the claim token from `claim`
138
+ - `target` (string, optional) — destination stage. **Always specify when moving the item.** Omit to release back to the same stage.
139
+ - `payload` (string, optional) — payload string to append (or replace)
140
+ - `payloadFormat` (`yaml` | `json` | `text`, optional, default `yaml`) — same as `push`
141
+ - `replace` (boolean, optional) — replace payload entirely instead of appending. Use when treating payload as a structured object.
142
+ - `priority` (number, optional) — update the item's priority
143
+
144
+ Returns:
145
+ ```yaml
146
+ ok: true
147
+ ```
148
+
149
+ Fails if the claim expired (item was unstuck while you worked) or item is not claimed.
150
+
151
+ **Payload is append-only history by default.** Each stage appends its output — resulting duplicate YAML fields are intentional. Use `replace: true` only when treating payload as a structured object you own.
152
+
153
+ ---
154
+
155
+ ### status
156
+
157
+ Returns the pipeline description and item counts per stage.
158
+
159
+ Parameters:
160
+ - `pipeline` (string) — pipeline name
161
+
162
+ Returns:
163
+ ```yaml
164
+ description: Scrape product pages and extract pricing
165
+ stats:
166
+ '*': [23, 3]
167
+ done: [7, 0]
168
+ failed: [6, 0]
169
+ pending: [10, 3]
170
+ ```
171
+
172
+ Each value is `[total, claimed]` — total item count and how many are currently claimed (being processed). `*` is the pipeline-level aggregate across all stages. For nested stages (`enriched/shortlisted`), intermediate paths are included as aggregates of their children. `description` is `null` if none was set.
173
+
174
+ ---
175
+
176
+ ### batch_read
177
+
178
+ Reads items without claiming them. For inspection, data collection, and monitoring.
179
+
180
+ Parameters:
181
+ - `pipeline` (string)
182
+ - `stage` (string, optional) — supports globs. Defaults to `*`
183
+ - `includePayload` (boolean, optional) — include payload in results
184
+ - `claimed` (boolean, optional) — filter by claimed status. Default: unclaimed
185
+ - `ids` (string[], optional)
186
+ - `createdAfter`, `createdBefore`, `modifiedAfter` (number, epoch ms)
187
+ - `limit`, `offset` (number)
188
+
189
+ Returns a YAML list of items. `payload` is omitted unless `includePayload: true`. Returns `[]` when nothing matches.
190
+
191
+ ```yaml
192
+ - id: url-1
193
+ stage: done
194
+ claimed: false
195
+ seq: 5
196
+ priority: 0
197
+ created: 1748476800000
198
+ last_modified: 1748476801000
199
+ - id: url-2
200
+ stage: done
201
+ claimed: false
202
+ seq: 7
203
+ priority: 0
204
+ created: 1748476800001
205
+ last_modified: 1748476802000
206
+ ```
207
+
208
+ ---
209
+
210
+ ### unstick
211
+
212
+ Releases all stuck claimed items back to their stage. Use when agents have crashed and left items locked.
213
+
214
+ Parameters:
215
+ - `pipeline` (string)
216
+ - `stage` (string, optional) — limit to a specific stage. Defaults to `*`
217
+ - `ids`, `createdAfter`, `createdBefore`, `modifiedAfter` — optional filters
218
+
219
+ Returns:
220
+ ```yaml
221
+ unstuck: 3
222
+ ```
223
+
224
+ ---
225
+
226
+ ### delete_pipeline
227
+
228
+ Deletes a pipeline and all its items. Irreversible. Only call if explicitly asked.
229
+
230
+ Parameters:
231
+ - `pipeline` (string)
232
+
233
+ Returns:
234
+ ```yaml
235
+ ok: true
236
+ ```
237
+
238
+ ---
239
+
240
+ ### get_sdk
241
+
242
+ Returns a self-contained SDK snippet (JavaScript or Python) that scripts can use to interact with QQ's HTTP bridge from anywhere — including the Cowork VM or a browser's HTTP-origin tab.
243
+
244
+ Parameters:
245
+ - `language` ("javascript" | "python")
246
+
247
+ Returns a code snippet to inline at the top of your script. The snippet uses only stdlib — no installs. It has the host IP, port, and token baked in for this MCP process's lifetime.
248
+
249
+ **Call once per task.** Re-call only if a script throws `BridgeError: Connection failed` — that means this MCP server restarted and credentials changed.
250
+
251
+ **JavaScript signatures:**
252
+ ```
253
+ QQ.push(pipeline, stage, id?, payload?, opts?) → Promise<{ id: string } | { error: string }>
254
+ QQ.claim(pipeline, stage, opts?) → Promise<Item | { error: string }>
255
+ QQ.release(pipeline, seq, opts?) → Promise<{ ok: true } | { error: string }>
256
+ QQ.batch_read(pipeline, stage, opts?) → Promise<Item[] | { error: string }>
257
+ QQ.status(pipeline) → Promise<{ description: string|null, stats: Record<string, [number,number]> } | { error: string }>
258
+ ```
259
+
260
+ - `push` opts: `priority` (number), `payloadFormat` (`"yaml"` | `"json"` | `"text"`)
261
+ - `claim` opts: `id` (string — claim a specific item), `random` (boolean)
262
+ - `release` opts: `target` (string), `payload` (string), `replace` (boolean), `priority` (number), `payloadFormat`
263
+ - `batch_read` opts: `includePayload` (boolean), `claimed` (boolean), `ids` (string, comma-separated), `createdAfter`, `createdBefore`, `modifiedAfter` (epoch ms), `limit`, `offset` (number)
264
+
265
+ All functions return `{ error: string }` on failure — never throw (except `BridgeError` for network connection failures). Check `result.error` before using the result.
266
+
267
+ `claim` returns `{ error: "no items to claim" }` when nothing is available.
268
+
269
+ Item shape (returned by `claim` and `batch_read`):
270
+ ```
271
+ { id: string, stage: string, seq: number, priority: number, claimed: boolean,
272
+ created: number, last_modified: number, payload?: string | null }
273
+ ```
274
+
275
+ `claim` always includes `payload`. `batch_read` omits `payload` unless `includePayload: true`.
276
+
277
+ **Python signatures:**
278
+ ```
279
+ qq_push(pipeline, stage, id=None, payload=None, **opts) → { 'id': str } | { 'error': str }
280
+ qq_claim(pipeline, stage, **opts) → dict | { 'error': str }
281
+ qq_release(pipeline, seq, **opts) → { 'ok': True } | { 'error': str }
282
+ qq_batch_read(pipeline, stage, **opts) → list[dict] | { 'error': str }
283
+ qq_status(pipeline) → { 'description': str|None, 'stats': dict } | { 'error': str }
284
+ ```
285
+
286
+ All Python functions return `{ 'error': str }` on failure — never raise (except `BridgeError` for connection failures).
287
+
288
+ ---
289
+
290
+ ### load_file
291
+
292
+ Loads multiple items from a file on the host filesystem into a pipeline. Each record in the file becomes one pipeline item.
293
+
294
+ **Supported formats:** JSONL (`.jsonl`, `.ndjson`), JSON array (`.json`), YAML array (`.yaml`, `.yml`), CSV (`.csv`). Format is detected from the file extension.
295
+
296
+ **`path`** supports `$VAR` environment variable expansion — e.g. `$HOME/Downloads/data.jsonl`.
297
+
298
+ Parameters:
299
+ - `path` (string) — path to the file. Supports `$VAR` expansion.
300
+ - `pipeline` (string) — pipeline to push records into
301
+ - `stage` (string, optional) — default stage for records that do not specify their own. Defaults to empty string.
302
+ - `deleteAfter` (boolean, optional) — delete the file after loading. Default: false.
303
+
304
+ **Record format** (all fields optional):
305
+ ```yaml
306
+ id: item-1
307
+ stage: pending
308
+ payload: "any string"
309
+ priority: 0.0
310
+ ```
311
+ - `id` — omit for auto-generated id
312
+ - `stage` — overrides the `stage` parameter for this record
313
+ - `payload` — treated as an opaque string; non-string values are YAML-serialized
314
+ - `priority` — float, default 0.0
315
+
316
+ **Returns** one line per record:
317
+ ```
318
+ item-1: ok
319
+ item-2: duplicate
320
+ item-3: error: <message>
321
+ ```
322
+
323
+ File-level parse errors (bad JSON, malformed CSV, etc.) abort the entire operation. Per-record push failures are reported individually without aborting remaining records.
324
+
325
+ ---
326
+
327
+ ## SDK Usage
328
+
329
+ Use the SDK when you need to run code that processes pipeline items programmatically — loops, transforms, bulk operations. It is faster and more efficient than calling MCP tools one at a time for batch work.
330
+
331
+ ### When to use SDK vs MCP tools
332
+
333
+ - **MCP tools**: orchestration decisions, one-off operations, monitoring, anything requiring Claude's judgment
334
+ - **SDK (via script)**: processing many items in a loop, transforming data, bulk pushes, anything that is pure computation
335
+
336
+ ### Typical workflow
337
+
338
+ ```javascript
339
+ // 1. Call get_sdk once to get the snippet
340
+ // 2. Write a script, inline the snippet at the top
341
+ // 3. Run with: node script.js or python script.py
342
+
343
+ // --- JavaScript example ---
344
+ // [paste get_sdk output here]
345
+
346
+ const pipeline = '0529_a3f9c2';
347
+
348
+ // Bulk push — payload is a YAML string
349
+ for (const url of urls) {
350
+ await QQ.push(pipeline, 'pending', url, `url: ${url}`);
351
+ }
352
+
353
+ // Claim loop — check result.error, not null
354
+ while (true) {
355
+ const item = await QQ.claim(pipeline, 'pending');
356
+ if (item.error) break; // "no items to claim" or other error
357
+ const result = await processItem(item.payload);
358
+ await QQ.release(pipeline, item.seq, { target: 'done', payload: result });
359
+ }
360
+
361
+ // Collect results with payloads
362
+ const done = await QQ.batch_read(pipeline, 'done', { includePayload: true });
363
+ for (const item of done) {
364
+ console.log(item.id, item.payload);
365
+ }
366
+
367
+ // Monitor progress
368
+ const s = await QQ.status(pipeline);
369
+ console.log(`total=${s.stats['*'][0]} pending=${s.stats.pending?.[0] ?? 0}`);
370
+ ```
371
+
372
+ ### Error routing
373
+
374
+ Release to `failed` on error, `done` on success — never leave items claimed when your work throws:
375
+
376
+ ```javascript
377
+ while (true) {
378
+ const item = await QQ.claim(pipeline, 'pending');
379
+ if (item.error) break;
380
+ try {
381
+ const result = await processItem(item.payload);
382
+ await QQ.release(pipeline, item.seq, { target: 'done', payload: `result: ${result}` });
383
+ } catch (e) {
384
+ await QQ.release(pipeline, item.seq, { target: 'failed', payload: `error: ${e.message}` });
385
+ }
386
+ }
387
+ ```
388
+
389
+ ### Structured JSON payloads
390
+
391
+ Use `payloadFormat: "json"` when payload is a JSON object. Appended payloads form valid JSONL; `replace: true` treats it as a single mutable object:
392
+
393
+ ```javascript
394
+ // Push with JSON payload
395
+ await QQ.push(pipeline, 'pending', 'item-1', JSON.stringify({ url: 'https://a.com', score: 0 }),
396
+ { payloadFormat: 'json' });
397
+
398
+ // Update a structured payload: parse → modify → replace
399
+ const item = await QQ.claim(pipeline, 'pending');
400
+ if (!item.error) {
401
+ const data = JSON.parse(item.payload);
402
+ data.score = await scoreItem(data.url);
403
+ await QQ.release(pipeline, item.seq, {
404
+ target: 'done',
405
+ payload: JSON.stringify(data),
406
+ payloadFormat: 'json',
407
+ replace: true,
408
+ });
409
+ }
410
+ ```
411
+
412
+ ### Python example
413
+
414
+ ```python
415
+ # [paste get_sdk output here]
416
+
417
+ pipeline = "0529_a3f9c2"
418
+
419
+ # Bulk push
420
+ for url in urls:
421
+ qq_push(pipeline, "pending", url, f"url: {url}")
422
+
423
+ # Claim loop
424
+ while True:
425
+ item = qq_claim(pipeline, "pending")
426
+ if "error" in item: # "no items to claim" or other error
427
+ break
428
+ result = process_item(item["payload"])
429
+ qq_release(pipeline, item["seq"], target="done", payload=result)
430
+
431
+ items = qq_batch_read(pipeline, "done", includePayload=True)
432
+ for item in items:
433
+ print(item["id"], item["payload"])
434
+
435
+ # Monitor
436
+ s = qq_status(pipeline)
437
+ print(f"total={s['stats']['*'][0]}")
438
+ ```
439
+
440
+ ### BridgeError reconnect
441
+
442
+ If a script throws `BridgeError: Connection failed`:
443
+ 1. Call `get_sdk` again to get fresh credentials
444
+ 2. Update the snippet in your script
445
+ 3. Re-run the script
446
+
447
+ This happens when the QQ MCP server restarted (e.g. Claude Desktop was restarted).
448
+
449
+ ---
450
+
451
+ ## YAML Payload Conventions
452
+
453
+ Payload is a YAML string appended to existing content by default. The result is a YAML document where fields may appear multiple times — this is intentional. Each stage's output appears in sequence, creating a trace of the item's journey.
454
+
455
+ ```yaml
456
+ # After push:
457
+ url: https://example.com/product/42
458
+
459
+ # After first subagent appends:
460
+ url: https://example.com/product/42
461
+ name: Widget Pro
462
+ price: 29.99
463
+ available: true
464
+
465
+ # After second subagent appends (review):
466
+ url: https://example.com/product/42
467
+ name: Widget Pro
468
+ price: 29.99
469
+ available: true
470
+ review_reason: price seems anomalous
471
+ ```
472
+
473
+ Use `replace: true` only when you own the payload as a structured object (e.g., accumulating messages in a chat pipeline). To update a structured payload: claim, parse with yaml.load, modify, release with replace.
474
+
475
+ ---
476
+
477
+ ## Globs, Filters, Priority
478
+
479
+ **Stage globs**: `*` matches any single segment, `enriched/*` matches sub-stages. Use in `claim` and `batch_read` to work across multiple stages.
480
+
481
+ **Priority**: float, default 0.0. Higher value = claimed first within the same stage. Use only when meaningful (e.g., score, confidence). Most pipelines don't need priority.
482
+
483
+ **Filters in batch_read / unstick**: `claimed`, `ids`, `createdAfter`, `createdBefore`, `modifiedAfter`, `limit`, `offset`.
484
+
485
+ ---
486
+
487
+ ## Pipeline Design
488
+
489
+ Before creating a new pipeline, read the `pipeline_design` resource. It walks through the design process, the PIPELINES.md template, a filled example, and a pre-implementation checklist.
490
+
491
+ Document every pipeline in `PIPELINES.md` before pushing a single item.
@@ -0,0 +1,192 @@
1
+ # Pipeline Design Guide
2
+
3
+ ## The Iron Law
4
+
5
+ ```
6
+ NO PIPELINE IMPLEMENTATION WITHOUT A PIPELINES.md ENTRY FIRST
7
+ ```
8
+
9
+ Design the pipeline on paper before pushing a single item. Undocumented pipelines drift — stages accumulate, payload grows inconsistently, and future agents guess wrong about what each stage means.
10
+
11
+ **Violating the letter of this process is violating the spirit of it.**
12
+
13
+ ---
14
+
15
+ ## When to Use This Guide
16
+
17
+ Follow this guide whenever you are:
18
+ - Creating a new pipeline
19
+ - Adding stages to an existing pipeline
20
+ - Changing what payload a stage produces
21
+
22
+ **When working with an existing pipeline:** read `PIPELINES.md` first. It should contain everything you need. If it's missing or incomplete, update it before proceeding.
23
+
24
+ ---
25
+
26
+ ## Clarifying with the User
27
+
28
+ Pipeline design usually happens with a human partner. Before filling in the template, ask the user to clarify what you don't know. **One question per message.** Prefer multiple-choice when the options are known.
29
+
30
+ The five Phase 1 questions are your agenda — work through them in dialogue, not in isolation.
31
+
32
+ **Good questions to ask:**
33
+ - "What are the sources of items — where do they come from, and what identifies each one uniquely?"
34
+ - "What should happen when an item fails — retry, discard, or route to a review stage?"
35
+ - "Is there a natural stable id for each item (URL, database id), or should the pipeline assign one?"
36
+ - "Are any stages optional, or does every item pass through all of them?"
37
+ - "Who runs the orchestrator and when — on demand, scheduled, or triggered by an event?"
38
+
39
+ **When to skip asking:**
40
+ - The user has already provided enough detail to answer all five Phase 1 questions
41
+ - You are working from a spec or design doc that covers the pipeline completely
42
+ - The pipeline is a trivial two-stage transform with no ambiguous transitions
43
+
44
+ If you skip asking, state why — don't silently proceed.
45
+
46
+ ---
47
+
48
+ ## Phase 1 — Design
49
+
50
+ Answer all five questions before writing anything.
51
+
52
+ ### 1. What does this pipeline do?
53
+
54
+ One sentence. If you need more than one sentence, the scope is unclear — break it down or narrow it.
55
+
56
+ ### 2. What are the stages?
57
+
58
+ List every stage by name. For each: what does it mean for an item to be in this stage?
59
+
60
+ Stages are not steps in a script — they are **states** an item can be in. Name them as nouns or past participles, not verbs.
61
+
62
+ | Good stage names | Bad stage names |
63
+ |-----------------|-----------------|
64
+ | `pending`, `fetched`, `done` | `fetch`, `process`, `handle` |
65
+ | `review/approved`, `review/rejected` | `reviewing`, `to_review` |
66
+
67
+ Sub-stages (`review/approved`, `enriched/shortlisted`) are valid — use them when a stage has distinct sub-states that agents need to distinguish.
68
+
69
+ ### 3. What are the valid transitions?
70
+
71
+ For each transition: which stage does it come from, which stage does it go to, and what did the agent do to earn the move?
72
+
73
+ **Terminal stages** are stages with no outbound transitions — `done`, `failed`, `discarded`. Be explicit about which stages are terminal.
74
+
75
+ **Loops** (releasing back to the same stage) are valid: use them for retry logic or chat-style accumulation. Document them explicitly.
76
+
77
+ ### 4. What is the item ID — and why?
78
+
79
+ The `id` is the deduplication primitive. An item can only be pushed once per pipeline per id. Choose it carefully.
80
+
81
+ | Situation | Use |
82
+ |-----------|-----|
83
+ | Items come from an external system | The external system's stable identifier (URL, database row id, API object id) |
84
+ | Items have no upstream identifier | Omit `id` — the pipeline assigns a sequence number |
85
+ | Items must be globally unique across runs | A hash or composite key (e.g., `sha256(url + date)`) |
86
+
87
+ Never use a generated UUID as the id unless items genuinely have no stable identity.
88
+
89
+ ### 5. What does the payload accumulate?
90
+
91
+ Payload is append-only history by default. Each stage appends its output.
92
+
93
+ For each field that will appear in the payload:
94
+ - Which stage introduces it?
95
+ - What type/shape is it?
96
+ - Is it ever replaced (use `replace: true`) rather than appended?
97
+
98
+ ---
99
+
100
+ ## Red Flags — Stop and Re-Design
101
+
102
+ | Thought | Problem |
103
+ |---------|---------|
104
+ | "I'll figure out the stages as I go" | Undefined stages produce inconsistent item states |
105
+ | "Payload structure is flexible" | Future agents can't reliably parse a payload with no schema |
106
+ | "I'll use auto-generated IDs for now" | If items have a natural identity, you'll get duplicates across runs |
107
+ | "I'll document after it works" | You won't, and future agents will guess wrong |
108
+ | "The pipeline is simple, it doesn't need docs" | Undocumented simple pipelines become undocumented complex ones |
109
+ | "I'll add the review stage later if we need it" | Retrofit stages invalidate existing items' stage semantics |
110
+ | "Error handling is just releasing to `failed`" | What happens to items in `failed`? Document it. |
111
+
112
+ ---
113
+
114
+ ## Phase 2 — Document
115
+
116
+ Write the PIPELINES.md entry using the template below. Every field is required.
117
+
118
+ PIPELINES.md lives in the project root. One file documents all pipelines in the project.
119
+
120
+ ### PIPELINES.md Template
121
+
122
+ ```markdown
123
+ ## [Pipeline Name]
124
+
125
+ **Description:** One sentence.
126
+
127
+ **Purpose:** 2-3 sentences. Why does this pipeline exist? What triggers it?
128
+
129
+ **Pipeline ID:** `[name or auto-generated pattern]`
130
+
131
+ ---
132
+
133
+ ### ID Strategy
134
+ [What value is used as the item id and why.]
135
+
136
+ ---
137
+
138
+ ### Payload Schema
139
+
140
+ | Field | Type | Added by stage | Description |
141
+ |-------|------|----------------|-------------|
142
+
143
+ ---
144
+
145
+ ### Stages
146
+
147
+ | Stage | Meaning | Terminal? |
148
+ |-------|---------|-----------|
149
+
150
+ ---
151
+
152
+ ### Transitions
153
+
154
+ | From | To | Agent action | Payload appended | Notes |
155
+ |------|----|-------------|-----------------|-------|
156
+
157
+ ---
158
+
159
+ ### State Diagram
160
+
161
+ ```mermaid
162
+ stateDiagram-v2
163
+ [*] --> pending
164
+ pending --> done : processed
165
+ done --> [*]
166
+ ```
167
+
168
+ ---
169
+
170
+ ### Process Notes
171
+
172
+ **Orchestrator responsibilities:**
173
+ **Subagent responsibilities:**
174
+ **Retry logic:**
175
+ **Error handling:**
176
+ **Known edge cases:**
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Phase 3 — Verify
182
+
183
+ - [ ] Every stage has a defined meaning in the Stages table
184
+ - [ ] Every valid transition appears in both the Transitions table and the Mermaid diagram
185
+ - [ ] Terminal stages are identified
186
+ - [ ] ID strategy is explicit and justified
187
+ - [ ] Payload schema shows which stage introduces each field
188
+ - [ ] Retry logic is documented
189
+ - [ ] Orchestrator and subagent responsibilities are separated and complete
190
+ - [ ] Process notes cover what happens to `failed` items
191
+
192
+ If any item is unchecked: complete it before implementing.
@@ -0,0 +1,2 @@
1
+ export declare function renderJavaScriptSdk(host: string, port: number, token: string): string;
2
+ //# sourceMappingURL=javascript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../src/sdk-templates/javascript.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAmBrF"}