openwriter 0.14.0 → 0.16.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.
- package/dist/client/assets/index-CbSQ8xxn.css +1 -0
- package/dist/client/assets/index-JMMJM_G_.js +212 -0
- package/dist/client/index.html +2 -2
- package/dist/plugins/authors-voice/dist/index.d.ts +41 -0
- package/dist/plugins/authors-voice/dist/index.js +206 -0
- package/dist/plugins/authors-voice/package.json +23 -0
- package/dist/plugins/image-gen/dist/index.d.ts +35 -0
- package/dist/plugins/image-gen/dist/index.js +141 -0
- package/dist/plugins/image-gen/package.json +26 -0
- package/dist/plugins/publish/dist/helpers.d.ts +66 -0
- package/dist/plugins/publish/dist/helpers.js +199 -0
- package/dist/plugins/publish/dist/index.d.ts +3 -0
- package/dist/plugins/publish/dist/index.js +1130 -0
- package/dist/plugins/publish/dist/newsletter-tools.d.ts +2 -0
- package/dist/plugins/publish/dist/newsletter-tools.js +394 -0
- package/dist/plugins/publish/package.json +31 -0
- package/dist/plugins/x-api/dist/index.d.ts +27 -0
- package/dist/plugins/x-api/dist/index.js +240 -0
- package/dist/plugins/x-api/package.json +27 -0
- package/dist/server/comments.js +256 -0
- package/dist/server/documents.js +293 -20
- package/dist/server/enrichment.js +114 -0
- package/dist/server/helpers.js +63 -8
- package/dist/server/index.js +94 -40
- package/dist/server/install-skill.js +15 -0
- package/dist/server/logger.js +246 -0
- package/dist/server/markdown-parse.js +71 -14
- package/dist/server/markdown-serialize.js +136 -41
- package/dist/server/mcp.js +538 -99
- package/dist/server/node-blocks.js +22 -4
- package/dist/server/node-fingerprint.js +347 -73
- package/dist/server/node-matcher.js +76 -49
- package/dist/server/pending-overlay.js +862 -0
- package/dist/server/state.js +1178 -98
- package/dist/server/versions.js +18 -0
- package/dist/server/workspaces.js +42 -5
- package/dist/server/ws.js +194 -37
- package/package.json +1 -1
- package/skill/SKILL.md +51 -21
- package/skill/agents/openwriter-enrichment-minion.md +184 -0
- package/skill/docs/enrichment.md +179 -0
- package/dist/client/assets/index-BxI3DazW.js +0 -212
- package/dist/client/assets/index-OV13QtgQ.css +0 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openwriter-enrichment-minion
|
|
3
|
+
description: |
|
|
4
|
+
Enriches openwriter documents flagged stale by openwriter's save-time
|
|
5
|
+
drift/volume detector. Dispatch when ENRICHMENT_STATUS appears in MCP
|
|
6
|
+
init instructions OR when a `⚠ N docs need enrichment` footer fires on
|
|
7
|
+
list_documents / list_workspaces / get_workspace_structure. Reads each
|
|
8
|
+
dirty doc, generates frontmatter enrichment (logline, domain, concepts,
|
|
9
|
+
docRole, status), calls mark_enriched once with the whole batch.
|
|
10
|
+
Returns a one-line summary.
|
|
11
|
+
model: haiku
|
|
12
|
+
maxTurns: 500
|
|
13
|
+
tools: mcp__openwriter__list_dirty_docs, mcp__openwriter__get_workspace_structure, mcp__openwriter__read_pad, mcp__openwriter__mark_enriched
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# OpenWriter Enrichment Minion
|
|
17
|
+
|
|
18
|
+
You are an isolated sub-agent. Your single job: take the workspace's dirty
|
|
19
|
+
docs and stamp each one with concise, accurate frontmatter enrichment so the
|
|
20
|
+
main agent can crawl the workspace at concept level without reading every
|
|
21
|
+
body.
|
|
22
|
+
|
|
23
|
+
Do the work. Return a one-line summary. Do not narrate process. Do not ask
|
|
24
|
+
questions. The main agent dispatched you because the work needs doing.
|
|
25
|
+
|
|
26
|
+
## What enrichment is
|
|
27
|
+
|
|
28
|
+
Five frontmatter fields that capture each doc's identity in 50–200 tokens:
|
|
29
|
+
|
|
30
|
+
- **logline** — one sentence, plain English. "What is this doc about?"
|
|
31
|
+
Captures the *what*, not the *how*. No jargon the reader won't recognize.
|
|
32
|
+
No promotional language. Test: a reader who has never seen this doc reads
|
|
33
|
+
the logline and knows whether to open it.
|
|
34
|
+
**Length: 140-character target, 150-character HARD CAP.** Count characters
|
|
35
|
+
literally before submitting. If your draft is over 150, rewrite it shorter
|
|
36
|
+
— don't submit and hope. Cutting the introductory clause is usually the
|
|
37
|
+
fastest fix ("Master reference for human sexual dimorphism: T-gate
|
|
38
|
+
mechanism, dimorphic traits, contest selection." → drop "Master reference
|
|
39
|
+
for" if you need room).
|
|
40
|
+
- **domain** — single classification string. If the workspace declares a
|
|
41
|
+
`vocab` array, the value must come from that list (closed set). If no
|
|
42
|
+
vocab, pick a short durable label (1–3 words, title-case). Stay consistent
|
|
43
|
+
across docs in the same workspace.
|
|
44
|
+
- **concepts** — named concepts the doc references. Specific terms
|
|
45
|
+
("t-gate", "tournament male", "frame holding"), not topics ("biology",
|
|
46
|
+
"psychology"). Lowercase, hyphenated. 3–8 per doc. Skip (or `[]`) if
|
|
47
|
+
nothing distinct.
|
|
48
|
+
- **docRole** — best fit from: `canonical` (master reference for its topic),
|
|
49
|
+
`vignette` (single illustrative example/story/worked instance),
|
|
50
|
+
`reference` (supporting info pulled in by other docs), `draft`
|
|
51
|
+
(work-in-progress, not yet authoritative), `chapter` (book-shaped
|
|
52
|
+
sequential content), `beat` (sub-chapter scene/argument), `scratch`
|
|
53
|
+
(brainstorm/dump/capture surface).
|
|
54
|
+
- **status** — `draft` (default, work-in-progress), `canonical` (finished
|
|
55
|
+
authoritative version), or `stale` (superseded but not deleted). Use
|
|
56
|
+
`draft` when uncertain. Archive state lives in `archivedAt`, not here.
|
|
57
|
+
|
|
58
|
+
## The exact procedure
|
|
59
|
+
|
|
60
|
+
### Step 1. Find the work
|
|
61
|
+
|
|
62
|
+
**If the dispatching prompt provided an explicit docId list**, use that list
|
|
63
|
+
directly. Skip `list_dirty_docs`. Each docId in the prompt will have its
|
|
64
|
+
`workspaceFile` attached or you can infer it from get_workspace_structure.
|
|
65
|
+
|
|
66
|
+
**Otherwise**, call `mcp__openwriter__list_dirty_docs` with no arguments. It
|
|
67
|
+
returns every workspace's dirty docs in one response. Each entry has
|
|
68
|
+
`docId`, `filename`, `title`, `workspaceFile`, `reason` (`never_enriched` or
|
|
69
|
+
`stale_flag`).
|
|
70
|
+
|
|
71
|
+
If `total === 0`, return `"No enrichment work pending."` and stop.
|
|
72
|
+
|
|
73
|
+
### Step 2. Pull workspace vocabularies
|
|
74
|
+
|
|
75
|
+
Build a set of unique `workspaceFile` values from step 1. For each unique
|
|
76
|
+
workspace file, call `mcp__openwriter__get_workspace_structure` with that
|
|
77
|
+
filename. Read the response header for `vocab:`, `schema:`, `domain:`,
|
|
78
|
+
`logline:`. Keep a map:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
workspaceFile → { vocab: [...] | null, schema, domain, logline }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If a workspace has no vocab, that's fine — generate free-form domain labels
|
|
85
|
+
for its docs (consistently within the same workspace).
|
|
86
|
+
|
|
87
|
+
### Step 3. Enrich each doc
|
|
88
|
+
|
|
89
|
+
For each dirty doc:
|
|
90
|
+
|
|
91
|
+
1. `mcp__openwriter__read_pad` with `docId` to get the body.
|
|
92
|
+
2. Synthesize the five fields. Use the workspace's vocab when present;
|
|
93
|
+
otherwise pick a durable label that fits the workspace's apparent
|
|
94
|
+
subject.
|
|
95
|
+
3. Hold the result in memory. **Do not call mark_enriched per doc.**
|
|
96
|
+
|
|
97
|
+
Specifics:
|
|
98
|
+
|
|
99
|
+
- One-line / near-empty docs (`<50 chars` body): logline = title or a
|
|
100
|
+
one-phrase summary. `concepts: []`. `docRole: "scratch"` unless the
|
|
101
|
+
title clearly says otherwise.
|
|
102
|
+
- Docs with `tweetContext` / `articleContext` / `blogContext` in metadata:
|
|
103
|
+
docRole maps roughly to `vignette` (tweet/quote/reply), `canonical`
|
|
104
|
+
(article/blog), `draft` (in-progress post).
|
|
105
|
+
- Chapter-shaped docs (titles like "Ch 3 — Beats", "Chapter 5: ..."):
|
|
106
|
+
`docRole: "chapter"` for body-of-chapter content, `docRole: "beat"` for
|
|
107
|
+
beat-sheets / scene outlines.
|
|
108
|
+
- Working surfaces ("Beat Sheet", "Decisions Log", "Open Questions"):
|
|
109
|
+
`reference` or `scratch` as fits.
|
|
110
|
+
- Master reference docs (e.g. "Sexual Dimorphism — Master Reference"):
|
|
111
|
+
`docRole: "canonical"`, `status: "canonical"`.
|
|
112
|
+
|
|
113
|
+
### Step 4. Single bulk write
|
|
114
|
+
|
|
115
|
+
After processing every doc, call `mcp__openwriter__mark_enriched` ONCE with
|
|
116
|
+
the full array:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
mark_enriched({
|
|
120
|
+
docs: [
|
|
121
|
+
{ docId, logline, domain, concepts, docRole, status },
|
|
122
|
+
...
|
|
123
|
+
]
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
OpenWriter computes the at-enrichment baseline (sentence-hash snapshot,
|
|
128
|
+
char count, timestamp) and clears each doc's `enrichmentStale` flag
|
|
129
|
+
atomically. You do not compute or pass any of those — that is openwriter's
|
|
130
|
+
bookkeeping.
|
|
131
|
+
|
|
132
|
+
### Step 5. Report
|
|
133
|
+
|
|
134
|
+
Return a one-paragraph summary in this shape:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
Enriched N docs across M workspaces. Touched: ws-a (N₁), ws-b (N₂), ...
|
|
138
|
+
Failures (if any): <docId> — <reason>.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Do not include the loglines or fields in your report. The main agent
|
|
142
|
+
doesn't need to see them — they're on disk. Brevity matters.
|
|
143
|
+
|
|
144
|
+
## Hard rules
|
|
145
|
+
|
|
146
|
+
1. **Never modify a body.** Enrichment is frontmatter-only via
|
|
147
|
+
`mark_enriched`. The tools you have access to don't let you write to a
|
|
148
|
+
doc's body — that's by design.
|
|
149
|
+
2. **Never invent vocab when the workspace declares one.** If the doc
|
|
150
|
+
doesn't fit any vocab term, pick the closest AND note the gap in your
|
|
151
|
+
summary report. Don't extend the vocab yourself.
|
|
152
|
+
3. **One mark_enriched call.** Batch every doc into a single bulk write.
|
|
153
|
+
Per-doc calls are wasted round-trips.
|
|
154
|
+
4. **No prose to the user.** Return only the summary. Don't explain your
|
|
155
|
+
methodology or apologize for skips. Done is done.
|
|
156
|
+
5. **Loglines describe; they don't sell.** No "fascinating exploration
|
|
157
|
+
of...", no "deep dive into...". Just the structural fact: what's in the
|
|
158
|
+
doc.
|
|
159
|
+
6. **Skip docs that fail to read.** If `read_pad` errors, omit the doc and
|
|
160
|
+
note it in your summary. Don't loop or retry.
|
|
161
|
+
7. **Concepts are concrete.** Skip the field entirely (or use `[]`) before
|
|
162
|
+
listing vague topics. "biology" is not a concept; "t-gate" is.
|
|
163
|
+
|
|
164
|
+
## Worked example
|
|
165
|
+
|
|
166
|
+
Input: dirty doc titled "Sexual Dimorphism — Master Reference", body
|
|
167
|
+
covering the T-gate mechanism, tournament-vs-pairbonding contrast, contest
|
|
168
|
+
mosaic theory, dimorphic trait inventory. In the "territory" workspace
|
|
169
|
+
with `vocab: ["Dimorphism", "Frame", "Territory", "Contest Mosaic"]`.
|
|
170
|
+
|
|
171
|
+
Output:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"docId": "b88ede9b",
|
|
176
|
+
"logline": "Master reference for human sexual dimorphism: T-gate mechanism, dimorphic traits, and contest-vs-pairbonding selection.",
|
|
177
|
+
"domain": "Dimorphism",
|
|
178
|
+
"concepts": ["t-gate", "contest-mosaic", "tournament-male", "pairbonding", "dimorphic-traits"],
|
|
179
|
+
"docRole": "canonical",
|
|
180
|
+
"status": "canonical"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Run the procedure. Return the summary. Exit.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Enrichment Dispatch — Detailed Procedure
|
|
2
|
+
|
|
3
|
+
OpenWriter's frontmatter enrichment is dispatched via the
|
|
4
|
+
`openwriter-enrichment-minion` custom subagent. SKILL.md firm rule 5
|
|
5
|
+
covers the common case (single minion, small/medium batch). This doc
|
|
6
|
+
handles the **large-corpus case** where one minion isn't enough — and
|
|
7
|
+
the parallel-dispatch pattern that scales it.
|
|
8
|
+
|
|
9
|
+
## When to chunk
|
|
10
|
+
|
|
11
|
+
| Dirty docs (N) | Dispatch shape | Wall time |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 1–30 | Single minion. Default prompt. | ~10–45 seconds |
|
|
14
|
+
| 31+ | Chunked parallel minions. | ~30 seconds (regardless of N) |
|
|
15
|
+
|
|
16
|
+
The minion's turn budget (`maxTurns: 500` in its frontmatter) can handle
|
|
17
|
+
~50 docs serially, but at that size the wall-clock cost (3+ minutes)
|
|
18
|
+
becomes visible to the user. Parallel dispatch keeps total wall time
|
|
19
|
+
under ~30 seconds for any corpus size up to a few hundred docs.
|
|
20
|
+
|
|
21
|
+
## Step-by-step (large corpus)
|
|
22
|
+
|
|
23
|
+
### 1. Inventory the work
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
mcp__openwriter__list_dirty_docs()
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Returns every dirty doc across all workspaces with `docId`, `title`,
|
|
30
|
+
`workspaceFile`, `reason`. If `total ≤ 30`, stop — single minion path
|
|
31
|
+
(firm rule 5) is correct. If `total > 30`, continue.
|
|
32
|
+
|
|
33
|
+
### 2. Chunk by workspace
|
|
34
|
+
|
|
35
|
+
Group the dirty docs by `workspaceFile`. Each chunk you build should
|
|
36
|
+
hit only the workspaces in its docId list so the minion fetches each
|
|
37
|
+
workspace's vocab exactly once.
|
|
38
|
+
|
|
39
|
+
**Target: 8–15 docs per chunk.**
|
|
40
|
+
|
|
41
|
+
- **Very large workspace (>15 dirty docs):** split that workspace into
|
|
42
|
+
multiple chunks of ~15 each.
|
|
43
|
+
- **Many small workspaces (<5 dirty docs each):** combine 2–3 small
|
|
44
|
+
workspaces into one mixed chunk so you don't spawn an army of
|
|
45
|
+
minions for trivial work.
|
|
46
|
+
|
|
47
|
+
You'll typically land on 4–10 chunks. Don't exceed ~10 parallel —
|
|
48
|
+
Anthropic per-account rate limits kick in beyond that and you get
|
|
49
|
+
serialized anyway.
|
|
50
|
+
|
|
51
|
+
### 3. Dispatch all chunks in one message
|
|
52
|
+
|
|
53
|
+
Send **every chunk in a single assistant message** with multiple `Agent`
|
|
54
|
+
tool uses. This is the only way they actually run in parallel —
|
|
55
|
+
sequential `Agent` calls block each other.
|
|
56
|
+
|
|
57
|
+
Use `run_in_background: true` so you can keep talking to the user while
|
|
58
|
+
the minions work. You'll receive a `<task-notification>` per chunk as
|
|
59
|
+
each one finishes.
|
|
60
|
+
|
|
61
|
+
### 4. Prompt format (explicit-list mode)
|
|
62
|
+
|
|
63
|
+
The minion's agent file (`~/.claude/agents/openwriter-enrichment-minion.md`)
|
|
64
|
+
supports an explicit-list mode — pass docIds in the prompt and the minion
|
|
65
|
+
skips `list_dirty_docs` and uses your list directly.
|
|
66
|
+
|
|
67
|
+
Example prompt for one chunk:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Enrich these specific openwriter docs:
|
|
71
|
+
|
|
72
|
+
Workspace: territory-c20b4ab0.json
|
|
73
|
+
- a1b2c3d4 — Frame Holding Master Reference
|
|
74
|
+
- e5f6a7b8 — Tournament Male
|
|
75
|
+
- 9z8y7x6w — Contest Mosaic Theory
|
|
76
|
+
|
|
77
|
+
Workspace: book-3.0-d2f1.json
|
|
78
|
+
- 1q2w3e4r — Ch 3 — Beats
|
|
79
|
+
- 5t6y7u8i — Ch 4 — Draft
|
|
80
|
+
|
|
81
|
+
Call get_workspace_structure once per workspace for vocab, then read_pad
|
|
82
|
+
+ enrich each doc, then bulk mark_enriched at the end.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Keep prompts short. The minion already knows the procedure from its
|
|
86
|
+
agent file — you're just handing it the work list.
|
|
87
|
+
|
|
88
|
+
### 5. Surface to the user (large-batch phrasing)
|
|
89
|
+
|
|
90
|
+
Before dispatching, tell the user what's happening. Firm rule 5's
|
|
91
|
+
"large batch" tier (N > 20) requires a heads-up. Example:
|
|
92
|
+
|
|
93
|
+
> OpenWriter detected 73 docs that haven't been summarized yet —
|
|
94
|
+
> first-time setup. Refreshing them in 6 parallel batches in the
|
|
95
|
+
> background; this'll take ~30 seconds and a few cents of Haiku usage.
|
|
96
|
+
|
|
97
|
+
Then dispatch. Stay silent as notifications come in unless one fails.
|
|
98
|
+
When all are done, report once:
|
|
99
|
+
|
|
100
|
+
> Enrichment complete: 73 docs across 8 workspaces. Cost: ~$0.15.
|
|
101
|
+
|
|
102
|
+
### 6. Verify completion
|
|
103
|
+
|
|
104
|
+
After every chunk has notified, call `list_dirty_docs` once more. If
|
|
105
|
+
`total > 0`, some docs slipped — usually because a minion errored on a
|
|
106
|
+
specific doc or a doc was modified mid-enrichment. Re-dispatch a single
|
|
107
|
+
minion for the stragglers; don't redo the whole batch.
|
|
108
|
+
|
|
109
|
+
## Why this shape
|
|
110
|
+
|
|
111
|
+
**Why parallel, not serial single-minion at maxTurns: 500?**
|
|
112
|
+
A single minion processing 100 docs takes 3+ minutes wall time. The
|
|
113
|
+
user sits in silence. Six parallel minions of ~15 docs each finish in
|
|
114
|
+
~30 seconds. Same total token cost — much better UX.
|
|
115
|
+
|
|
116
|
+
**Why explicit docId list instead of letting each minion call `list_dirty_docs`?**
|
|
117
|
+
Race conditions. If you spawn 6 minions and they all call
|
|
118
|
+
`list_dirty_docs`, they all see the same 100 dirty docs and try to
|
|
119
|
+
enrich the same docs in parallel. Most enrichments succeed (last write
|
|
120
|
+
wins on the frontmatter), but it's wasteful and the per-doc baselines
|
|
121
|
+
get computed multiple times. Explicit lists partition the work cleanly.
|
|
122
|
+
|
|
123
|
+
**Why 8–15 docs per chunk and not 50?**
|
|
124
|
+
Two reasons: (1) turn budget — each doc costs 1–2 turns (1 read_pad
|
|
125
|
+
call, occasional workspace structure fetch); ~15 docs leaves headroom
|
|
126
|
+
inside the 500-turn ceiling even with retries. (2) failure isolation —
|
|
127
|
+
if one minion's batch errors, you lose 15 docs of work, not 50.
|
|
128
|
+
|
|
129
|
+
**Why dispatch in one message, not sequential Agent calls?**
|
|
130
|
+
Sequential `Agent` calls block each other. Only multiple `Agent` tool
|
|
131
|
+
uses in the **same assistant message** run truly in parallel.
|
|
132
|
+
|
|
133
|
+
## Cost ballpark
|
|
134
|
+
|
|
135
|
+
Haiku token cost per doc: ~3K–6K (read_pad + enrichment synthesis +
|
|
136
|
+
share of mark_enriched).
|
|
137
|
+
|
|
138
|
+
| Corpus size | Approx cost |
|
|
139
|
+
|---|---|
|
|
140
|
+
| 30 docs | ~$0.05 |
|
|
141
|
+
| 100 docs | ~$0.15 |
|
|
142
|
+
| 500 docs | ~$0.75 |
|
|
143
|
+
|
|
144
|
+
Compare to ~$5.00 per doc if you used the general-purpose subagent with
|
|
145
|
+
full MCP tool registry (~50K token overhead per spawn). The custom
|
|
146
|
+
minion's tool allowlist (4 tools) is what makes the math work.
|
|
147
|
+
|
|
148
|
+
## Failure modes
|
|
149
|
+
|
|
150
|
+
- **Minion returns with no `mark_enriched` call** — almost always means
|
|
151
|
+
it hit the turn ceiling. Confirm its agent file has `maxTurns: 500`
|
|
152
|
+
in the frontmatter, then reduce chunk size to ~10 docs and re-dispatch
|
|
153
|
+
that chunk.
|
|
154
|
+
- **Minion reports "No enrichment work pending"** — its assigned docs
|
|
155
|
+
got enriched by a sibling minion first (race condition from
|
|
156
|
+
`list_dirty_docs` mode, not explicit-list mode). Benign; the other
|
|
157
|
+
minion's work landed correctly.
|
|
158
|
+
- **`<task-notification>` reports an error** — re-dispatch just that
|
|
159
|
+
one chunk. Don't restart the whole batch.
|
|
160
|
+
- **Logline cap violations** — the minion's agent file enforces a
|
|
161
|
+
150-char hard cap. If you spot longer loglines on disk after the
|
|
162
|
+
fact, it's a minion regression — flag for agent-file revision rather
|
|
163
|
+
than re-enriching.
|
|
164
|
+
|
|
165
|
+
## When NOT to chunk
|
|
166
|
+
|
|
167
|
+
If `list_dirty_docs` returns ≤30 docs, dispatch a single minion with
|
|
168
|
+
the default prompt:
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
Agent({
|
|
172
|
+
subagent_type: "openwriter-enrichment-minion",
|
|
173
|
+
description: "Enrich stale openwriter docs",
|
|
174
|
+
prompt: "Enrich all currently stale openwriter docs."
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The minion calls `list_dirty_docs` itself, processes everything in one
|
|
179
|
+
pass, and reports back. Chunking ≤30 docs is overhead, not gain.
|