@agentproto/corpus-presets 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/dist/marketing/index.d.ts +31 -0
- package/dist/marketing/index.mjs +684 -0
- package/dist/marketing/index.mjs.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agentproto contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# @agentproto/corpus-presets
|
|
2
|
+
|
|
3
|
+
Catalog of starter workspaces for the AIP-10 corpus runtime. Subpath exports per vertical — pure TS data, no filesystem dependency. Host iterates `files` and writes via FsPort.
|
|
4
|
+
|
|
5
|
+
## Discovery
|
|
6
|
+
|
|
7
|
+
The `corpus` CLI discovers presets via the `agentproto/corpus-preset/v1` manifest declared in this package's `package.json#agentproto-corpus-preset`. Third-party packages following the same convention can be added to the discovery set via `corpusPresetPackages[]` in `~/.agentproto/config.json`.
|
|
8
|
+
|
|
9
|
+
## Direct usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { MarketingCorpusPreset } from "@agentproto/corpus-presets/marketing"
|
|
13
|
+
|
|
14
|
+
for (const [rel, content] of Object.entries(MarketingCorpusPreset.files)) {
|
|
15
|
+
await fs.writeFile(path.join(workspaceRoot, rel), content)
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or via the CLI, which uses the manifest to resolve the slug:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
corpus init marketing ./my-corpus
|
|
23
|
+
corpus init --list # show every discoverable preset
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Source of truth
|
|
27
|
+
|
|
28
|
+
The fixture dir at `@agentproto/corpus/test/fixtures/<slug>/` is the single source of truth. The TS file `src/<slug>/files.ts` is a build artifact — gitignored, regenerated by this package's `prebuild` / `precheck-types` / `pretest` / `predev` hooks. The conformance test enforces those `.md` files validate against the actual AgentProto JSON Schemas, so what ships here is always AIP-conformant by construction.
|
|
29
|
+
|
|
30
|
+
To edit a preset:
|
|
31
|
+
|
|
32
|
+
1. Edit `packages/corpus/test/fixtures/<vertical>/...`
|
|
33
|
+
2. Run `pnpm --filter @agentproto/corpus test` to confirm conformance still holds
|
|
34
|
+
3. Build (or check-types, or test) the preset — the regen runs automatically: `pnpm --filter @agentproto/corpus-presets build`
|
|
35
|
+
|
|
36
|
+
The standalone `pnpm gen:marketing` script still exists for explicit regen but isn't needed in the normal flow.
|
|
37
|
+
|
|
38
|
+
## Adding a new vertical to this package
|
|
39
|
+
|
|
40
|
+
1. Add fixtures: `packages/corpus/test/fixtures/<slug>/`
|
|
41
|
+
2. Extend `packages/corpus/src/__tests__/conformance.test.ts` to cover them
|
|
42
|
+
3. Copy `scripts/gen-marketing.mjs` → `scripts/gen-<slug>.mjs`
|
|
43
|
+
4. Add `gen-<slug>` to each pre-hook in `package.json` (or fold it into a single bootstrap script that runs all generators)
|
|
44
|
+
5. Add `src/<slug>/index.ts` exporting `<Slug>CorpusPreset: CorpusPreset`
|
|
45
|
+
6. Add `./<slug>` subpath to `package.json#exports`
|
|
46
|
+
7. Add `"<slug>/index"` entry to `tsup.config.ts`
|
|
47
|
+
8. Append an entry to `package.json#agentproto-corpus-preset.presets[]` with the slug + entry + export
|
|
48
|
+
9. Add the generated file to the root `.gitignore`
|
|
49
|
+
|
|
50
|
+
## Shipping a preset from a third-party package
|
|
51
|
+
|
|
52
|
+
Create your own npm package (`@vendor/corpus-presets`, `<name>-corpus-presets`, …) and add the same manifest block to its `package.json`:
|
|
53
|
+
|
|
54
|
+
```jsonc
|
|
55
|
+
{
|
|
56
|
+
"agentproto-corpus-preset": {
|
|
57
|
+
"schema": "agentproto/corpus-preset/v1",
|
|
58
|
+
"presets": [
|
|
59
|
+
{ "slug": "<your-slug>", "entry": "./dist/index.mjs", "export": "<YourPreset>" }
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then point the CLI at it:
|
|
66
|
+
|
|
67
|
+
```jsonc
|
|
68
|
+
// ~/.agentproto/config.json
|
|
69
|
+
{
|
|
70
|
+
"corpusPresetPackages": [
|
|
71
|
+
"@agentproto/corpus-presets",
|
|
72
|
+
"@vendor/corpus-presets"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`corpus init --list` will show every discovered preset.
|
package/dist/index.d.ts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CorpusPreset } from '@agentproto/corpus';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AUTO-GENERATED build artifact — DO NOT COMMIT, DO NOT EDIT.
|
|
5
|
+
*
|
|
6
|
+
* Regenerated from @agentproto/corpus/test/fixtures/marketing/
|
|
7
|
+
* by the prebuild / precheck-types / pretest / predev hooks on
|
|
8
|
+
* this package. To change the preset content, edit the fixtures.
|
|
9
|
+
*/
|
|
10
|
+
declare const MARKETING_PRESET_FILES: Readonly<Record<string, string>>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Marketing corpus preset.
|
|
14
|
+
*
|
|
15
|
+
* Pure TS data — `files` is inlined from the M0 fixture workspace at
|
|
16
|
+
* build time via `scripts/gen-marketing.mjs`. The M0 conformance test
|
|
17
|
+
* proves every file validates against the actual AgentProto JSON
|
|
18
|
+
* Schemas, so a host that writes these to disk gets a known-good
|
|
19
|
+
* starter workspace.
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
*
|
|
23
|
+
* import { MarketingCorpusPreset } from "@agentproto/corpus-presets/marketing"
|
|
24
|
+
* for (const [rel, content] of Object.entries(MarketingCorpusPreset.files)) {
|
|
25
|
+
* await fs.writeFile(path.join(workspaceRoot, rel), content)
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
declare const MarketingCorpusPreset: CorpusPreset;
|
|
30
|
+
|
|
31
|
+
export { MARKETING_PRESET_FILES, MarketingCorpusPreset };
|
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agentproto/corpus-presets v0.1.0-alpha
|
|
3
|
+
* Pure-TS starter workspaces for the AIP-10 corpus runtime.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// src/marketing/files.ts
|
|
7
|
+
var MARKETING_PRESET_FILES = Object.freeze({
|
|
8
|
+
"collections/corpus-candidate/COLLECTION.md": '---\nschema: collection.schema/v1\nname: corpus-candidate\ntitle: Corpus Candidate\ndescription: |\n Candidate corpus item awaiting analysis and promotion to an AIP-10 entry.\n Discovered candidates live in `_candidates.yaml` sidecar; materialized\n ITEM.md files appear only after transition out of `discovered`.\nversion: 1.0.0\ninitialStatus: discovered\nstatuses:\n - { id: discovered, label: Discovered, transitionsTo: [analyzed, rejected] }\n - { id: analyzed, label: Analyzed, transitionsTo: [approved, rejected, needs-work] }\n - { id: needs-work, label: Needs Work, transitionsTo: [analyzed, rejected] }\n - { id: approved, label: Approved, terminal: true }\n - { id: rejected, label: Rejected, terminal: true }\nidentity:\n slugSource: id\n filingPath: "collections/corpus-candidate/{slug}/ITEM.md"\nfields:\n - { name: sourcePath, type: string, required: true }\n - { name: sourceUrl, type: url }\n - { name: targetEntryPath, type: string }\n - { name: corpusKind, type: enum, enum: [principle, example, pattern, critique, summary, timeline, playbook], required: true }\n - { name: qualityScore, type: number }\n - { name: riskScore, type: number }\n - { name: promotionMode, type: enum, enum: [auto, human] }\n - { name: contentHash, type: string }\n - { name: reviewerNotes, type: text }\nlints:\n - { id: required-field-source-path, kind: required-field, appliesTo: "*", severity: error, params: { fields: [sourcePath] } }\n - { id: required-field-corpus-kind, kind: required-field, appliesTo: "*", severity: error, params: { fields: [corpusKind] } }\nmetadata:\n corpus:\n description: Used by source-scout (writes), marketing-analyst (writes), quality-reviewer (scores), corpus-curator (promotes).\n---\n\n# Corpus Candidate collection\n\nHolds candidates discovered by the scout, analyzed by the analyst, scored by the reviewer, and promoted by the curator. State machine enforced by `statuses[].transitionsTo`.\n',
|
|
9
|
+
"collections/corpus-candidate/tiktok-hook-2026-05/ITEM.md": '---\nschema: collection.item/v1\ncollection: corpus-candidate\nid: tiktok-hook-2026-05\ntitle: TikTok contrarian hook pattern\nstatus: analyzed\nsourcePath: sources/fresh/tiktok-hook-2026-05.md\nsourceUrl: https://example.com/tiktok/123\ntargetEntryPath: entries/patterns/2026/contrarian-short-form-hooks.md\ncorpusKind: pattern\ncontentHash: sha256:abc1234567890def1234567890abcdef1234567890abcdef1234567890abcdef\ntags: [short-form, hooks]\ncreatedAt: "2026-05-22T14:30:00Z"\nupdatedAt: "2026-05-22T15:00:00Z"\nmetadata:\n corpus:\n qualityScore: 4.3\n riskScore: 1.1\n promotionMode: auto\n---\n\n# Candidate: TikTok contrarian hook\n\nCandidate extracted from fresh social examples. The pattern (contrarian belief-flip in <5s hooks) generalizes across short-form channels. Analyst recommends auto-promotion.\n\n## Analysis\n- Pattern present in 6 of 10 top-performing TikToks reviewed\n- Transferable to Reels, Shorts, cold-email subject lines\n- No risk of legal / brand misuse identified\n\n## Decision\n- promotionMode: auto\n- gates pass: qualityScore 4.3 \u2265 4.2, riskScore 1.1 \u2264 1.5, archive hash present, all required fields populated\n',
|
|
10
|
+
"entries/critiques/2026/weak-positioning-saas.md": `---
|
|
11
|
+
schema: knowledge.entry/v1
|
|
12
|
+
slug: weak-positioning-saas
|
|
13
|
+
kind: critique
|
|
14
|
+
title: Weak positioning \u2014 "powerful platform for X"
|
|
15
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
16
|
+
sources:
|
|
17
|
+
- tiktok-hook-2026-05
|
|
18
|
+
confidence: 0.85
|
|
19
|
+
tags: [positioning, anti-pattern, saas]
|
|
20
|
+
metadata:
|
|
21
|
+
corpus:
|
|
22
|
+
status: active
|
|
23
|
+
qualityScore: 4.1
|
|
24
|
+
riskScore: 1.2
|
|
25
|
+
domain: marketing
|
|
26
|
+
funnelStage: consideration
|
|
27
|
+
temporal:
|
|
28
|
+
firstSeen: "2024-08-01T00:00:00Z"
|
|
29
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
30
|
+
mentions:
|
|
31
|
+
- { at: "2024-08-01T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 0.7 }
|
|
32
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
33
|
+
promotionMode: human
|
|
34
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
35
|
+
promotedBy: corpus-curator
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What's wrong
|
|
39
|
+
"Powerful platform for [audience]" makes zero claims. It's substitutable for any competitor's homepage.
|
|
40
|
+
|
|
41
|
+
## Why it fails
|
|
42
|
+
- No specific outcome promised
|
|
43
|
+
- No specific cost / friction acknowledged
|
|
44
|
+
- No specific audience excluded
|
|
45
|
+
- Reader can't tell if it's for them
|
|
46
|
+
|
|
47
|
+
## How to fix
|
|
48
|
+
Replace with: "[outcome] for [specific audience] without [specific pain]". E.g. "Ship marketing copy in 10 minutes, not 10 days \u2014 without hiring a copywriter".
|
|
49
|
+
|
|
50
|
+
## Use this critique when
|
|
51
|
+
- Reviewing landing-page hero copy
|
|
52
|
+
- Reviewing PRD positioning sections
|
|
53
|
+
- Onboarding a new marketing-analyst operator
|
|
54
|
+
`,
|
|
55
|
+
"entries/examples/2026/apple-2007-iphone-keynote.md": `---
|
|
56
|
+
schema: knowledge.entry/v1
|
|
57
|
+
slug: apple-2007-iphone-keynote
|
|
58
|
+
kind: example
|
|
59
|
+
title: Apple 2007 iPhone keynote \u2014 three-products framing
|
|
60
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
61
|
+
sources:
|
|
62
|
+
- tiktok-hook-2026-05
|
|
63
|
+
confidence: 0.92
|
|
64
|
+
tags: [keynote, framing, apple, launch]
|
|
65
|
+
metadata:
|
|
66
|
+
corpus:
|
|
67
|
+
status: active
|
|
68
|
+
qualityScore: 4.7
|
|
69
|
+
riskScore: 0.3
|
|
70
|
+
domain: marketing
|
|
71
|
+
channel: keynote
|
|
72
|
+
funnelStage: awareness
|
|
73
|
+
temporal:
|
|
74
|
+
firstSeen: "2024-01-09T00:00:00Z"
|
|
75
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
76
|
+
mentions:
|
|
77
|
+
- { at: "2024-01-09T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
78
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
79
|
+
promotionMode: human
|
|
80
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
81
|
+
promotedBy: corpus-curator
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Summary
|
|
85
|
+
Jobs opened the 2007 keynote by saying Apple was launching three products: a widescreen iPod with touch controls, a revolutionary mobile phone, and a breakthrough internet communicator. After repeating the trio twice, he revealed: "These are not three separate devices. This is one device. And we are calling it iPhone." The pattern earned a standing ovation before any feature was shown.
|
|
86
|
+
|
|
87
|
+
## What's specific
|
|
88
|
+
- Three concrete categories the audience already understood (iPod, phone, internet).
|
|
89
|
+
- Deliberate repetition built rhythm; the reveal collapsed all three into one.
|
|
90
|
+
- The reveal happened on word 47 of the keynote \u2014 pre-product, pre-spec.
|
|
91
|
+
|
|
92
|
+
## Transferable lesson
|
|
93
|
+
For a category-creating product, don't announce the new category. Announce three known things, then collapse them.
|
|
94
|
+
|
|
95
|
+
## Use this example when
|
|
96
|
+
- Pitching anything that's "X + Y + Z combined".
|
|
97
|
+
- Launching to an audience that doesn't have a mental slot for the new thing yet.
|
|
98
|
+
|
|
99
|
+
## Avoid this pattern when
|
|
100
|
+
- The product genuinely is one thing \u2014 manufacturing a trio is fake.
|
|
101
|
+
- The audience already knows the category (then specs, not framing, win).
|
|
102
|
+
`,
|
|
103
|
+
"entries/patterns/2026/contrarian-short-form-hooks.md": `---
|
|
104
|
+
schema: knowledge.entry/v1
|
|
105
|
+
slug: contrarian-short-form-hooks
|
|
106
|
+
kind: pattern
|
|
107
|
+
title: Contrarian short-form hooks
|
|
108
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
109
|
+
sources:
|
|
110
|
+
- tiktok-hook-2026-05
|
|
111
|
+
confidence: 0.88
|
|
112
|
+
links:
|
|
113
|
+
- specificity-beats-superlatives
|
|
114
|
+
tags: [hooks, short-form, tiktok, contrarian]
|
|
115
|
+
metadata:
|
|
116
|
+
corpus:
|
|
117
|
+
status: active
|
|
118
|
+
qualityScore: 4.5
|
|
119
|
+
riskScore: 1.0
|
|
120
|
+
domain: marketing
|
|
121
|
+
channel: tiktok
|
|
122
|
+
funnelStage: awareness
|
|
123
|
+
temporal:
|
|
124
|
+
firstSeen: "2023-04-12T00:00:00Z"
|
|
125
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
126
|
+
halfLifeDays: 180
|
|
127
|
+
mentions:
|
|
128
|
+
- { at: "2023-04-12T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
129
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
130
|
+
promotionMode: auto
|
|
131
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
132
|
+
promotedBy: corpus-curator
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Summary
|
|
136
|
+
Open with a popularly-held belief, then contradict it with a specific counter-claim. Forces a "wait, what?" pattern interrupt that buys 3-5 more seconds of attention.
|
|
137
|
+
|
|
138
|
+
## Why it works
|
|
139
|
+
Pattern-interrupt + curiosity gap. The viewer's brain treats the contradiction as a problem to resolve.
|
|
140
|
+
|
|
141
|
+
## Transferable pattern
|
|
142
|
+
1. State a widely-held belief in 5 words
|
|
143
|
+
2. Counter with one specific contradiction
|
|
144
|
+
3. Promise the why in the next 30 seconds
|
|
145
|
+
|
|
146
|
+
## Use when
|
|
147
|
+
- Short-form video (TikTok, Reels, Shorts)
|
|
148
|
+
- Cold-outbound email subject lines
|
|
149
|
+
- Ad creative for low-awareness audiences
|
|
150
|
+
|
|
151
|
+
## Avoid when
|
|
152
|
+
- Branded content (feels manipulative)
|
|
153
|
+
- Audience already aligned with your stance
|
|
154
|
+
- Long-form (the hook doesn't sustain)
|
|
155
|
+
|
|
156
|
+
## Examples
|
|
157
|
+
- "Most marketers write listicles. Here's why every viral piece I've made started with a contradiction."
|
|
158
|
+
- "Cold email is dead \u2014 for the 99% who do it wrong. Here's the 1%."
|
|
159
|
+
`,
|
|
160
|
+
"entries/patterns/2026/story-then-payoff.md": `---
|
|
161
|
+
schema: knowledge.entry/v1
|
|
162
|
+
slug: story-then-payoff
|
|
163
|
+
kind: pattern
|
|
164
|
+
title: Story-then-payoff structure
|
|
165
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
166
|
+
sources:
|
|
167
|
+
- tiktok-hook-2026-05
|
|
168
|
+
confidence: 0.85
|
|
169
|
+
links:
|
|
170
|
+
- contrarian-short-form-hooks
|
|
171
|
+
- clarity-beats-cleverness
|
|
172
|
+
tags: [storytelling, structure, copy]
|
|
173
|
+
metadata:
|
|
174
|
+
corpus:
|
|
175
|
+
status: active
|
|
176
|
+
qualityScore: 4.3
|
|
177
|
+
riskScore: 0.8
|
|
178
|
+
domain: marketing
|
|
179
|
+
funnelStage: awareness
|
|
180
|
+
temporal:
|
|
181
|
+
firstSeen: "2023-09-15T00:00:00Z"
|
|
182
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
183
|
+
mentions:
|
|
184
|
+
- { at: "2023-09-15T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
185
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
186
|
+
promotionMode: auto
|
|
187
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
188
|
+
promotedBy: corpus-curator
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Summary
|
|
192
|
+
Open with a 1-2 sentence story (specific, sensory), then deliver the payoff (principle, product, CTA). The story buys attention; the payoff cashes it in.
|
|
193
|
+
|
|
194
|
+
## Why it works
|
|
195
|
+
Brains are pattern-completion engines. A half-told story creates open loop tension. Closing the loop with the payoff delivers a small dopamine hit + transfers credibility from the story to the claim.
|
|
196
|
+
|
|
197
|
+
## Transferable pattern
|
|
198
|
+
- Story: \u22642 sentences, one concrete moment.
|
|
199
|
+
- Payoff: \u22641 sentence, names the principle / product / CTA.
|
|
200
|
+
- Optional: 1 sentence connecting the two.
|
|
201
|
+
|
|
202
|
+
## Use when
|
|
203
|
+
- Cold email openers, ad creative, landing-page heros.
|
|
204
|
+
- Audiences that don't know the product yet.
|
|
205
|
+
|
|
206
|
+
## Avoid when
|
|
207
|
+
- Internal comms (waste of words).
|
|
208
|
+
- Audiences past consideration stage \u2014 they want specs, not stories.
|
|
209
|
+
`,
|
|
210
|
+
"entries/principles/2026/clarity-beats-cleverness.md": `---
|
|
211
|
+
schema: knowledge.entry/v1
|
|
212
|
+
slug: clarity-beats-cleverness
|
|
213
|
+
kind: principle
|
|
214
|
+
title: Clarity beats cleverness
|
|
215
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
216
|
+
sources:
|
|
217
|
+
- tiktok-hook-2026-05
|
|
218
|
+
confidence: 0.95
|
|
219
|
+
tags: [copy, clarity, conversion]
|
|
220
|
+
metadata:
|
|
221
|
+
corpus:
|
|
222
|
+
status: active
|
|
223
|
+
qualityScore: 4.8
|
|
224
|
+
riskScore: 0.5
|
|
225
|
+
domain: marketing
|
|
226
|
+
funnelStage: awareness
|
|
227
|
+
temporal:
|
|
228
|
+
firstSeen: "2022-01-01T00:00:00Z"
|
|
229
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
230
|
+
mentions:
|
|
231
|
+
- { at: "2022-01-01T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
232
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
233
|
+
promotionMode: human
|
|
234
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
235
|
+
promotedBy: corpus-curator
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Summary
|
|
239
|
+
If the reader has to re-read a sentence, the joke is on the writer. Wordplay that's clever-but-confusing loses 100% of distracted readers.
|
|
240
|
+
|
|
241
|
+
## Why it works
|
|
242
|
+
Reading is involuntary effort. Clever copy taxes that effort; clear copy doesn't. The cheapest conversion is the one where the reader didn't have to work.
|
|
243
|
+
|
|
244
|
+
## Transferable pattern
|
|
245
|
+
- Write at a 6th-grade reading level (Hemingway score).
|
|
246
|
+
- Replace every metaphor that doesn't add new information.
|
|
247
|
+
- One idea per sentence.
|
|
248
|
+
|
|
249
|
+
## Use when
|
|
250
|
+
- Landing-page headlines, CTAs, ad creative.
|
|
251
|
+
- Any audience that hasn't already paid attention.
|
|
252
|
+
|
|
253
|
+
## Avoid when
|
|
254
|
+
- Brand-content where the voice IS the product (Liquid Death, Cards Against Humanity).
|
|
255
|
+
- Inside-baseball content for an already-converted audience.
|
|
256
|
+
`,
|
|
257
|
+
"entries/principles/2026/specificity-beats-superlatives.md": `---
|
|
258
|
+
schema: knowledge.entry/v1
|
|
259
|
+
slug: specificity-beats-superlatives
|
|
260
|
+
kind: principle
|
|
261
|
+
title: Specificity beats superlatives
|
|
262
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
263
|
+
sources:
|
|
264
|
+
- tiktok-hook-2026-05
|
|
265
|
+
confidence: 0.92
|
|
266
|
+
tags: [copy, specificity, conversion]
|
|
267
|
+
metadata:
|
|
268
|
+
corpus:
|
|
269
|
+
status: active
|
|
270
|
+
qualityScore: 4.7
|
|
271
|
+
riskScore: 0.8
|
|
272
|
+
domain: marketing
|
|
273
|
+
funnelStage: consideration
|
|
274
|
+
temporal:
|
|
275
|
+
firstSeen: "2023-04-12T00:00:00Z"
|
|
276
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
277
|
+
mentions:
|
|
278
|
+
- { at: "2023-04-12T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
279
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
280
|
+
promotionMode: human
|
|
281
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
282
|
+
promotedBy: corpus-curator
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Summary
|
|
286
|
+
Concrete claims with numbers outperform superlative adjectives. "3x conversion" beats "amazing results"; "287 customers in 90 days" beats "many happy customers".
|
|
287
|
+
|
|
288
|
+
## Why it works
|
|
289
|
+
Readers parse numbers as evidence; adjectives as marketing noise. Specificity transfers credibility because it implies the author can be checked.
|
|
290
|
+
|
|
291
|
+
## Transferable pattern
|
|
292
|
+
- Replace every superlative with a specific number, date, or named entity
|
|
293
|
+
- If you can't substitute, the claim is probably untrue
|
|
294
|
+
|
|
295
|
+
## Use when
|
|
296
|
+
- Writing landing-page copy
|
|
297
|
+
- Drafting ad creative
|
|
298
|
+
- Replying to objections
|
|
299
|
+
|
|
300
|
+
## Avoid when
|
|
301
|
+
- Numbers are unverifiable (then say nothing)
|
|
302
|
+
- Aspirational brand voice required
|
|
303
|
+
`,
|
|
304
|
+
"entries/summaries/2026/short-form-hook-meta.md": `---
|
|
305
|
+
schema: knowledge.entry/v1
|
|
306
|
+
slug: short-form-hook-meta
|
|
307
|
+
kind: summary
|
|
308
|
+
title: Short-form hook meta \u2014 what's working in 2026
|
|
309
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
310
|
+
sources:
|
|
311
|
+
- tiktok-hook-2026-05
|
|
312
|
+
confidence: 0.7
|
|
313
|
+
links:
|
|
314
|
+
- contrarian-short-form-hooks
|
|
315
|
+
- story-then-payoff
|
|
316
|
+
- clarity-beats-cleverness
|
|
317
|
+
tags: [meta, short-form, hooks, trends]
|
|
318
|
+
metadata:
|
|
319
|
+
corpus:
|
|
320
|
+
status: active
|
|
321
|
+
qualityScore: 4.0
|
|
322
|
+
riskScore: 1.0
|
|
323
|
+
domain: marketing
|
|
324
|
+
channel: tiktok
|
|
325
|
+
funnelStage: awareness
|
|
326
|
+
temporal:
|
|
327
|
+
firstSeen: "2026-04-01T00:00:00Z"
|
|
328
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
329
|
+
halfLifeDays: 60
|
|
330
|
+
mentions:
|
|
331
|
+
- { at: "2026-04-01T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
332
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
333
|
+
promotionMode: human
|
|
334
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
335
|
+
promotedBy: corpus-curator
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Summary
|
|
339
|
+
As of mid-2026, the dominant short-form hook patterns on TikTok / Reels / Shorts share three traits: (1) contradiction in the first 2 seconds, (2) specific number or named entity by the 5-second mark, (3) the payoff arrives before 30 seconds.
|
|
340
|
+
|
|
341
|
+
## What's NOT working anymore
|
|
342
|
+
- Generic "POV:" openers \u2014 algo deprioritized them after the Q1 update.
|
|
343
|
+
- Long establishing shots \u2014 90% drop-off before the 3-second mark.
|
|
344
|
+
- "Watch till the end" framing \u2014 overuse killed effectiveness.
|
|
345
|
+
|
|
346
|
+
## Patterns that scale across channels
|
|
347
|
+
- [[contrarian-short-form-hooks]] \u2014 universal, lowest production cost.
|
|
348
|
+
- [[story-then-payoff]] \u2014 needs a sharp specific story; expensive to source.
|
|
349
|
+
|
|
350
|
+
## Half-life
|
|
351
|
+
60 days. Re-mention via scout when a new platform algorithm update lands.
|
|
352
|
+
`,
|
|
353
|
+
"entries/timelines/2026/saas-positioning-shifts-2020-2026.md": `---
|
|
354
|
+
schema: knowledge.entry/v1
|
|
355
|
+
slug: saas-positioning-shifts-2020-2026
|
|
356
|
+
kind: timeline
|
|
357
|
+
title: SaaS positioning shifts \u2014 2020 to 2026
|
|
358
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
359
|
+
sources:
|
|
360
|
+
- tiktok-hook-2026-05
|
|
361
|
+
confidence: 0.78
|
|
362
|
+
links:
|
|
363
|
+
- weak-positioning-saas
|
|
364
|
+
tags: [positioning, saas, timeline, trend]
|
|
365
|
+
metadata:
|
|
366
|
+
corpus:
|
|
367
|
+
status: active
|
|
368
|
+
qualityScore: 4.1
|
|
369
|
+
riskScore: 1.2
|
|
370
|
+
domain: marketing
|
|
371
|
+
funnelStage: consideration
|
|
372
|
+
temporal:
|
|
373
|
+
firstSeen: "2024-06-01T00:00:00Z"
|
|
374
|
+
lastSeen: "2026-05-22T14:30:00Z"
|
|
375
|
+
halfLifeDays: 180
|
|
376
|
+
mentions:
|
|
377
|
+
- { at: "2024-06-01T00:00:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
378
|
+
- { at: "2026-05-22T14:30:00Z", sourceId: tiktok-hook-2026-05, weight: 1.0 }
|
|
379
|
+
promotionMode: human
|
|
380
|
+
promotedAt: "2026-05-22T14:30:00Z"
|
|
381
|
+
promotedBy: corpus-curator
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Summary
|
|
385
|
+
B2B SaaS positioning evolved through five distinct phases between 2020 and 2026, each driven by a buyer environment shift.
|
|
386
|
+
|
|
387
|
+
## 2020 \u2014 "All-in-one platform"
|
|
388
|
+
Buyers consolidating tools post-COVID; positioning prized breadth.
|
|
389
|
+
Result: feature-list arms race, undifferentiated category copy.
|
|
390
|
+
|
|
391
|
+
## 2022 \u2014 "Best-in-class for X"
|
|
392
|
+
Stack-fatigue reversed; buyers wanted focused tools.
|
|
393
|
+
Result: "the [adjective] [category] for [vertical]" replaced "all-in-one".
|
|
394
|
+
|
|
395
|
+
## 2023 \u2014 "AI-native"
|
|
396
|
+
GPT-3.5 wave; everything claimed AI even when it was a wrapper.
|
|
397
|
+
Result: skepticism by mid-2024; AI claims now require demonstrated trade-offs.
|
|
398
|
+
|
|
399
|
+
## 2024 \u2014 "Replace your [old tool]"
|
|
400
|
+
Direct displacement framing. Worked for late-comers in mature categories.
|
|
401
|
+
|
|
402
|
+
## 2026 \u2014 "We don't ship a [thing]"
|
|
403
|
+
Reactive positioning \u2014 define yourself by what you refused to build.
|
|
404
|
+
Most credible when accompanied by a concrete reason (compliance, philosophy).
|
|
405
|
+
|
|
406
|
+
## Pattern
|
|
407
|
+
Positioning rotates roughly every 18-24 months. The current peak narrative is the most-imitated; the next winner is usually the inverse of the saturated one.
|
|
408
|
+
`,
|
|
409
|
+
"KNOWLEDGE.md": '---\nschema: knowledge.workspace/v1\nname: marketing-corpus\ntitle: Marketing Expert Corpus\ndescription: |\n Expert marketing knowledge for autonomous agents. Composes AIP-10 (knowledge),\n AIP-12 (playbooks), AIP-18 (curation collections), AIP-9 (operators),\n AIP-15 (workflows), and AIP-41 (routines) into an autonomous improvement loop.\nversion: 1.0.0\nentityTypes:\n - { name: Principle, description: "Durable expert rule" }\n - { name: Example, description: "Concrete source-derived example" }\n - { name: Pattern, description: "Reusable transferable mechanic" }\n - { name: Critique, description: "Negative example or failure mode" }\n - { name: Summary, description: "Compressed source synthesis" }\n - { name: Timeline, description: "Time-sensitive trend evolution" }\n - { name: PlaybookCase, description: "Documented case study of a great playbook" }\nsources:\n retention: forever\n signing: optional\n hashAlgo: sha256\n authorityDefault: secondary\nlints:\n - { id: require-source-on-examples, kind: require-source, appliesTo: Example, severity: error }\n - { id: min-confidence-principles, kind: min-confidence, appliesTo: Principle, severity: warn, params: { min: 0.6 } }\n - { id: max-age-timelines, kind: max-age, appliesTo: Timeline, severity: warn, params: { days: 730 } }\n - { id: max-age-summaries, kind: max-age, appliesTo: Summary, severity: warn, params: { days: 180 } }\n - { id: broken-ref-all, kind: broken-ref, appliesTo: "*", severity: error }\n - { id: orphan-all, kind: orphan, appliesTo: "*", severity: info }\ncuration:\n tone: "neutral, expert, source-backed"\n depth: medium\n autoLink: byName\n conflictResolution: authority\nqueryHints:\n preferRecent: true\n preferAuthoritative: true\nmetadata:\n corpus:\n version: 1\n domain: marketing\n autoPromote:\n enabled: true\n requires:\n qualityScore: { min: 4.2 }\n riskScore: { max: 1.5 }\n hasArchiveHash: true\n requiredFields: [why_it_works, transferable_pattern, use_when, avoid_when]\n notRestricted: true\n temporal:\n defaultHalfLifeDays: 180\n scoreFormula: max-mention-decay\n retrievalBoosts:\n qualityScore: { weight: 0.30 }\n temporalScore: { weight: 0.20 }\n mentionCount: { weight: 0.10 }\n confidence: { weight: 0.15 }\n retrievalDefaults:\n status: active\n minQualityScore: 3.5\n minTemporalScore: 0.1\n accessModes:\n read: { allowedRoles: ["*"] }\n cite: { allowedRoles: ["*"] }\n flag-learning: { allowedRoles: ["*"], rateLimit: { perOperator: 20, window: "24h" } }\n curate: { allowedRoles: [corpus-curator, admin] }\n promote: { allowedRoles: [corpus-curator, admin] }\n activate-playbook: { allowedRoles: [corpus-curator, admin], requireApproval: true }\n admin-reindex: { allowedRoles: [admin] }\n bypass-default-filters: { allowedRoles: [corpus-curator, admin], audit: true }\n---\n\n# Marketing Corpus\n\nSource-of-truth for autonomous marketing agents. Composes AgentProto AIPs into a closed-loop knowledge-improvement system.\n\n## Three loops\n- **Knowledge curation** \u2014 gap-finder \u2192 curator \u2192 entries\n- **Playbook evolution** \u2014 gap \u2192 AIP-12 shadow playbook \u2192 evaluator \u2192 active|archived\n- **Retrieval-quality feedback** \u2014 every query logged; `utility` + `lift` written back to entries\n\nAll corpus-specific policy lives under `metadata.corpus.*`. AIP amendments (A1-A8) may hoist specific fields to first-class later \u2014 strictly additive, no rip-and-replace.\n',
|
|
410
|
+
"operators/corpus-curator/OPERATOR.md": '---\nname: Corpus Curator\nid: corpus-curator\npersona_summary: Promotes approved candidates to AIP-10 entries, maintains _index.md, handles deprecation + supersession. The corpus\'s editor-in-chief.\nversion: "1.0.0"\nprofile:\n role: |\n Promote candidates that pass the auto-promote gate. Review the\n human-review queue, decide approve/reject/needs-work. Keep the\n corpus tidy: dedupe, deprecate stale entries, resolve\n contradictions.\n voice: |\n Direct, decisive, opinionated about quality bar. First-person\n plural for company voice. Cites specific entry slugs when\n discussing deprecation or supersession.\n boundaries:\n - Never promote an entry that fails the auto-promote gate without explicit bypass.\n - Never deprecate without a written reason in metadata.corpus.archiveReason.\n - Always preserve the audit chain \u2014 _log.md events are append-only.\ngovernance:\n audit_log: "audit:corpus/marketing/_log.md"\n autonomy: autonomous\n policies:\n - "policy:corpus/marketing/curation"\nskills:\n - source-analysis\n - taxonomy\n - editorial-judgment\ntools:\n - corpus-promote-candidate\n - corpus-activate-playbook\n - corpus-archive-playbook\n - corpus-log-event\n - knowledge-query\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, curator, corpus]\nmetadata:\n corpus:\n domain: marketing\n overlays:\n policy: open\n maxActiveCount: 10\n---\n\n# Corpus Curator\n\nRuns after the reviewer scores a candidate. Promotes auto-approved entries; queues human-review-required candidates for the team. Also drives playbook lifecycle (`activate` / `archive`).\n',
|
|
411
|
+
"operators/gap-finder/OPERATOR.md": '---\nname: Gap Finder\nid: gap-finder\npersona_summary: Mines low-scoring eval-cases for systematic weaknesses in the corpus. Opens corpus-gap items so the scout knows what to look for next.\nversion: "1.0.0"\nprofile:\n role: |\n Read recent eval-case results, identify recurring failure modes,\n classify them (generic-output, weak-strategy, stale-reference,\n poor-style, missing-domain-context), and open corpus-gap items\n with priority based on frequency.\n voice: |\n Diagnostic, pattern-oriented, prescriptive. Says "we have N\n failures of kind X" not "the agent sometimes struggles".\n Recommends a concrete next scouting target.\n boundaries:\n - Never open a gap on a single low-score case \u2014 require \u22653 occurrences.\n - Never blame the operator \u2014 gaps describe missing knowledge, not bad reasoning.\n - Always link the eval-case refs that motivated the gap.\ngovernance:\n audit_log: "audit:corpus/marketing/_log.md"\n autonomy: autonomous\nskills:\n - source-analysis\n - pattern-recognition\ntools:\n - corpus-log-event\n - knowledge-query\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, gap-finder, corpus]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Gap Finder\n\nRuns monthly (via `monthly-eval-gap-finder` routine). Scans the last 30 days of `eval-case` results, finds clusters of failure, opens `corpus-gap/*/ITEM.md` items with `weaknessType` + `priority`. The scout reads these to prioritize the next harvest.\n',
|
|
412
|
+
"operators/marketing-analyst/OPERATOR.md": '---\nname: Marketing Analyst\nid: marketing-analyst\npersona_summary: Senior marketing analyst who converts raw social/web sources into expert principles, patterns, and critiques for the marketing corpus.\nversion: "1.0.0"\nprofile:\n role: |\n Convert candidate sources discovered by the scout into corpus-grade\n expert analysis: principles, patterns, critiques. Score quality and\n risk to inform promotion gates.\n voice: |\n Concrete, source-backed, never superlative. Cite specific numbers and\n named entities. First-person plural ("we") for company voice.\n boundaries:\n - Never invent quantitative claims; cite a source or mark as opinion.\n - Never promote without quality-reviewer signoff (unless auto-promote gates pass).\n - Never edit raw sources \u2014 only entries.\ngovernance:\n audit_log: "audit:corpus/marketing/_log.md"\n autonomy: supervised\n policies:\n - "policy:corpus/marketing/curation"\nskills:\n - source-analysis\n - copywriting\ntools:\n - corpus-flag-learning\n - knowledge-query\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, analyst, corpus]\nmetadata:\n corpus:\n domain: marketing\n knowledgeViews:\n - corpus: marketing\n filter:\n domain: [marketing]\n minQualityScore: 3.5\n defaultBoosts:\n qualityScore: { weight: 0.40 }\n temporalScore: { weight: 0.30 }\n overlays:\n policy: gated\n maxActiveCount: 5\n requireApprovalFrom: corpus-curator\n allowedKinds: [overlay, block-replacement]\n---\n\n# Marketing Analyst\n\nReads candidate sources from the scout, writes expert analysis as AIP-10 entries. Scores quality and risk. Signals the curator on auto-promote gate pass.\n',
|
|
413
|
+
"operators/playbook-evaluator/OPERATOR.md": "---\nname: Playbook Evaluator\nid: playbook-evaluator\npersona_summary: Runs shadow vs baseline eval batches on AIP-12 playbooks. Records winRateVsBaseline, decides promote / archive based on the playbook's auto_promote gate.\nversion: \"1.0.0\"\nprofile:\n role: |\n For every shadow playbook, run eval-cases through both arms\n (overlay applied vs operator default). Score outputs via the\n rubric the playbook's evidence[].eval-case references. Record\n metrics in metadata.corpus.shadowMetrics. Trigger curator action\n when the auto_promote.threshold is met.\n voice: |\n Quantitative, dispassionate, hypothesis-driven. States the null\n hypothesis explicitly (n, threshold, observed) before\n recommending an action.\n boundaries:\n - Never activate a playbook \u2014 that's the curator's call (audit chain).\n - Never report a winRate on n < playbook.metadata.corpus.autoPromote.minSampleSize.\n - Always run identical eval-cases on both arms (same prompts, same rubric).\ngovernance:\n audit_log: \"audit:corpus/marketing/_log.md\"\n autonomy: autonomous\nskills:\n - statistics\n - source-analysis\ntools:\n - corpus-list-playbooks\n - corpus-log-event\n - knowledge-query\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, evaluator, corpus, aip-12]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Playbook Evaluator\n\nDrives the playbook side of closed loop #2 (procedure). Runs nightly (via per-playbook eval-batch routines, configured per playbook). Writes back `shadowMetrics.{sampleSize, winRateVsBaseline, lastEvaluatedAt}` to PLAYBOOK.md. When gates pass, posts a `playbook.ready-for-activation` event the curator subscribes to.\n",
|
|
414
|
+
"operators/quality-reviewer/OPERATOR.md": '---\nname: Quality Reviewer\nid: quality-reviewer\npersona_summary: Scores analyzed candidates against the corpus\'s quality + risk rubric. Decides promotionMode (auto vs human). Flags concerns the analyst missed.\nversion: "1.0.0"\nprofile:\n role: |\n Independent second pair of eyes on every analyzed candidate.\n Adversarial-by-design \u2014 assumes the analyst was too generous\n and looks for reasons NOT to promote.\n voice: |\n Critical, concrete, fair. Cites specific clauses of the\n candidate body, not vibes. Always proposes a concrete score\n (qualityScore 0-5, riskScore 0-5).\n boundaries:\n - Never promote on the analyst\'s authority \u2014 score and route.\n - Never auto-promote a candidate flagged as restricted / personal / legal.\n - Always justify a sub-2.0 quality score in reviewerNotes.\ngovernance:\n audit_log: "audit:corpus/marketing/_log.md"\n autonomy: supervised\n policies:\n - "policy:corpus/marketing/review-policy"\nskills:\n - source-analysis\n - critical-reading\ntools:\n - corpus-flag-learning\n - knowledge-query\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, reviewer, corpus]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Quality Reviewer\n\nRuns after `marketing-analyst` produces an analyzed ITEM.md. Scores against:\n\n- **qualityScore** \u2014 accuracy, transferability, evidence\n- **riskScore** \u2014 legal/brand/compliance hazards\n- **promotionMode** \u2014 auto (gates pass) vs human (needs curator)\n',
|
|
415
|
+
"operators/source-scout/OPERATOR.md": '---\nname: Source Scout\nid: source-scout\npersona_summary: Curates external feeds for fresh marketing source material \u2014 TikToks, blog posts, ad creative, internal performance data \u2014 and archives the worth-keeping ones into sources/.\nversion: "1.0.0"\nprofile:\n role: |\n Discover new candidate sources for the marketing corpus. Filter\n noise vs signal at the scout stage so the analyst only sees\n promising material.\n voice: |\n Efficient, terse, evidence-first. Names URLs + numbers, not\n adjectives. Reports findings as `{source: <id>, why: <reason>}`\n triples.\n boundaries:\n - Never re-archive an already-archived source (check content_hash).\n - Never archive content with PII unless explicitly sanitized.\n - Never archive paywalled / DMCA-restricted material.\ngovernance:\n audit_log: "audit:corpus/marketing/_log.md"\n autonomy: autonomous\n policies:\n - "policy:corpus/marketing/source-policy"\nskills:\n - web-research\n - source-analysis\ntools:\n - corpus-create-candidate\n - knowledge-query\n - web-search\nparticipation:\n mode: proactive\nmemory:\n kind: operator-context\nruntime:\n kind: in-process\ntags: [marketing, scout, corpus]\nmetadata:\n corpus:\n domain: marketing\n knowledgeViews:\n - corpus: marketing\n filter:\n domain: [marketing]\n---\n\n# Source Scout\n\nRuns daily (via `daily-source-scout` routine). Fetches configured feeds, hashes content, dedups against existing sources, and writes new candidates to `_candidates.yaml`. The analyst takes over from there.\n',
|
|
416
|
+
"playbooks/ad-angle-generation/PLAYBOOK.md": '---\nschema: playbooks/v1\nslug: ad-angle-generation\ntitle: Ad angle generation \u2014 JTBD-grounded variants\ntargets:\n - { kind: operator, ref: marketing-analyst }\nbinds_operator: marketing-analyst\nkind: overlay\nstatus: shadow\npriority: 90\nlock_check:\n - factual-grounded\nevidence:\n - kind: run\n ref: collections/eval-case/ad-angle-suite/runs/initial\n note: First eval batch, n=20 planned\n - kind: reflection\n ref: collections/corpus-gap/generic-ad-copy/ITEM.md\n note: Gap that motivated this playbook\nttl: "P90D"\nsupersedes: []\ncreated_at: "2026-05-22T14:30:00Z"\nupdated_at: "2026-05-22T14:30:00Z"\ntags: [ads, angles, jtbd]\nmetadata:\n corpus:\n authoredBy: corpus-curator\n shadowTrafficPct: 0.10\n autoPromote:\n enabled: true\n metric: winRateVsBaseline\n threshold: { gte: 0.55 }\n minSampleSize: 30\n cooldown: "7d"\n execution: sandboxed\n---\n\n## Overlay\nWhen generating ad creative, generate 3 distinct angles before refining any single one.\n\n## Procedure\n1. Identify the JTBD (job-to-be-done) the audience hires the product for.\n2. Generate one angle per axis: outcome, pain, identity.\n3. For each angle, write a hook + body in <50 words.\n4. Score each angle on specificity + audience fit; promote the highest.\n\n## Promotion gate\nPromote shadow \u2192 active when winRateVsBaseline \u2265 0.55 over n \u2265 30 evals.\n',
|
|
417
|
+
"playbooks/cold-email-outbound/PLAYBOOK.md": `---
|
|
418
|
+
schema: playbooks/v1
|
|
419
|
+
slug: cold-email-outbound
|
|
420
|
+
title: Cold email outbound \u2014 earned-attention opener
|
|
421
|
+
targets:
|
|
422
|
+
- { kind: operator, ref: marketing-analyst }
|
|
423
|
+
binds_operator: marketing-analyst
|
|
424
|
+
kind: overlay
|
|
425
|
+
status: shadow
|
|
426
|
+
priority: 70
|
|
427
|
+
lock_check: []
|
|
428
|
+
evidence:
|
|
429
|
+
- kind: run
|
|
430
|
+
ref: collections/eval-case/cold-email-suite/runs/initial
|
|
431
|
+
note: First eval batch planned
|
|
432
|
+
ttl: "P90D"
|
|
433
|
+
supersedes: []
|
|
434
|
+
created_at: "2026-05-22T14:30:00Z"
|
|
435
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
436
|
+
tags: [cold-email, outbound, sales]
|
|
437
|
+
metadata:
|
|
438
|
+
corpus:
|
|
439
|
+
authoredBy: corpus-curator
|
|
440
|
+
shadowTrafficPct: 0.10
|
|
441
|
+
autoPromote:
|
|
442
|
+
enabled: true
|
|
443
|
+
metric: winRateVsBaseline
|
|
444
|
+
threshold: { gte: 0.55 }
|
|
445
|
+
minSampleSize: 30
|
|
446
|
+
cooldown: "7d"
|
|
447
|
+
execution: sandboxed
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Overlay
|
|
451
|
+
Cold-email opener MUST earn the reader's next 5 seconds by stating something they didn't know, not by claiming a benefit.
|
|
452
|
+
|
|
453
|
+
## Procedure
|
|
454
|
+
1. Research one specific thing about the prospect (their hire, their post, their company's recent move).
|
|
455
|
+
2. State that thing in <12 words as the opener.
|
|
456
|
+
3. Connect it to the offer in the next sentence \u2014 NO "I noticed you\u2026" bridge.
|
|
457
|
+
4. End with one specific yes/no question.
|
|
458
|
+
|
|
459
|
+
## Promotion gate
|
|
460
|
+
Promote shadow \u2192 active when winRateVsBaseline \u2265 0.55 over n \u2265 30 evals.
|
|
461
|
+
`,
|
|
462
|
+
"playbooks/competitor-positioning/PLAYBOOK.md": `---
|
|
463
|
+
schema: playbooks/v1
|
|
464
|
+
slug: competitor-positioning
|
|
465
|
+
title: Competitor positioning \u2014 pick your axis, name the trade
|
|
466
|
+
targets:
|
|
467
|
+
- { kind: operator, ref: marketing-analyst }
|
|
468
|
+
binds_operator: marketing-analyst
|
|
469
|
+
kind: overlay
|
|
470
|
+
status: shadow
|
|
471
|
+
priority: 80
|
|
472
|
+
lock_check:
|
|
473
|
+
- factual-grounded
|
|
474
|
+
- brand-voice
|
|
475
|
+
evidence:
|
|
476
|
+
- kind: run
|
|
477
|
+
ref: collections/eval-case/positioning-suite/runs/initial
|
|
478
|
+
note: First eval batch planned
|
|
479
|
+
ttl: "P90D"
|
|
480
|
+
supersedes: []
|
|
481
|
+
created_at: "2026-05-22T14:30:00Z"
|
|
482
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
483
|
+
tags: [positioning, competitive, differentiation]
|
|
484
|
+
metadata:
|
|
485
|
+
corpus:
|
|
486
|
+
authoredBy: corpus-curator
|
|
487
|
+
shadowTrafficPct: 0.10
|
|
488
|
+
autoPromote:
|
|
489
|
+
enabled: true
|
|
490
|
+
metric: winRateVsBaseline
|
|
491
|
+
threshold: { gte: 0.55 }
|
|
492
|
+
minSampleSize: 30
|
|
493
|
+
cooldown: "7d"
|
|
494
|
+
execution: sandboxed
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## Overlay
|
|
498
|
+
Positioning copy MUST name the specific competitor weakness it's trading off against. "We're faster" is noise; "We don't ship a CLI" is positioning.
|
|
499
|
+
|
|
500
|
+
## Procedure
|
|
501
|
+
1. List the top 3 competitors by ICP overlap.
|
|
502
|
+
2. For each, identify one specific decision they made that we explicitly DIDN'T.
|
|
503
|
+
3. Write the positioning line as: \`For [ICP], who [problem], [product] is the [category] that [specific trade-off vs competitor]\`.
|
|
504
|
+
4. Lint output against the [[weak-positioning-saas]] critique.
|
|
505
|
+
|
|
506
|
+
## Promotion gate
|
|
507
|
+
Promote shadow \u2192 active when winRateVsBaseline \u2265 0.55 over n \u2265 30 evals.
|
|
508
|
+
`,
|
|
509
|
+
"playbooks/landing-page-copy/PLAYBOOK.md": `---
|
|
510
|
+
schema: playbooks/v1
|
|
511
|
+
slug: landing-page-copy
|
|
512
|
+
title: Landing-page copy \u2014 high-conversion structure
|
|
513
|
+
targets:
|
|
514
|
+
- { kind: operator, ref: marketing-analyst }
|
|
515
|
+
binds_operator: marketing-analyst
|
|
516
|
+
kind: overlay
|
|
517
|
+
status: shadow
|
|
518
|
+
priority: 100
|
|
519
|
+
lock_check:
|
|
520
|
+
- brand-voice
|
|
521
|
+
- factual-grounded
|
|
522
|
+
evidence:
|
|
523
|
+
- kind: run
|
|
524
|
+
ref: collections/eval-case/landing-page-copy-conversion-suite/runs/2026-05-22-batch-1
|
|
525
|
+
note: First shadow batch, n=30 evals, winRateVsBaseline TBD
|
|
526
|
+
- kind: reflection
|
|
527
|
+
ref: collections/corpus-gap/weak-positioning-saas/ITEM.md
|
|
528
|
+
note: Gap that motivated this playbook
|
|
529
|
+
ttl: "P90D"
|
|
530
|
+
supersedes: []
|
|
531
|
+
created_at: "2026-05-22T14:30:00Z"
|
|
532
|
+
updated_at: "2026-05-22T14:30:00Z"
|
|
533
|
+
tags: [landing-page, copy, conversion]
|
|
534
|
+
metadata:
|
|
535
|
+
corpus:
|
|
536
|
+
authoredBy: corpus-curator
|
|
537
|
+
derivedFromGap: collections/corpus-gap/weak-positioning-saas/ITEM.md
|
|
538
|
+
shadowTrafficPct: 0.10
|
|
539
|
+
autoPromote:
|
|
540
|
+
enabled: true
|
|
541
|
+
metric: winRateVsBaseline
|
|
542
|
+
threshold: { gte: 0.55 }
|
|
543
|
+
minSampleSize: 30
|
|
544
|
+
cooldown: "7d"
|
|
545
|
+
shadowMetrics:
|
|
546
|
+
sampleSize: 0
|
|
547
|
+
winRateVsBaseline: null
|
|
548
|
+
lastEvaluatedAt: null
|
|
549
|
+
archiveReason: null
|
|
550
|
+
execution: sandboxed
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## Overlay
|
|
554
|
+
[Markdown that gets merged into marketing-analyst's prompt at runtime when this playbook is active. The block-replacement / overlay merge logic is the runtime's concern, not this fixture's.]
|
|
555
|
+
|
|
556
|
+
## Procedure
|
|
557
|
+
1. Read brief: ICP, offer, current page.
|
|
558
|
+
2. Apply principle [[specificity-beats-superlatives]] \u2014 every superlative gets a number, date, or named entity.
|
|
559
|
+
3. Generate 3 hook variants using pattern [[contrarian-short-form-hooks]].
|
|
560
|
+
4. Lint output against critique [[weak-positioning-saas]].
|
|
561
|
+
5. Output: H1, sub-H1, 3 CTA variants, 1 social-proof block.
|
|
562
|
+
|
|
563
|
+
## Promotion gate
|
|
564
|
+
Promote shadow \u2192 active when winRateVsBaseline \u2265 0.55 over n \u2265 30 evals (see metadata.corpus.autoPromote).
|
|
565
|
+
`,
|
|
566
|
+
"playbooks/social-hook-design/PLAYBOOK.md": '---\nschema: playbooks/v1\nslug: social-hook-design\ntitle: Social hook design \u2014 pattern interrupt in 5 seconds\ntargets:\n - { kind: operator, ref: marketing-analyst }\nbinds_operator: marketing-analyst\nkind: overlay\nstatus: shadow\npriority: 95\nlock_check: []\nevidence:\n - kind: run\n ref: collections/eval-case/social-hook-suite/runs/initial\n note: First eval batch planned\n - kind: reflection\n ref: entries/patterns/2026/contrarian-short-form-hooks.md\n note: Pattern this playbook operationalizes\nttl: "P90D"\nsupersedes: []\ncreated_at: "2026-05-22T14:30:00Z"\nupdated_at: "2026-05-22T14:30:00Z"\ntags: [social, hook, short-form]\nmetadata:\n corpus:\n authoredBy: corpus-curator\n shadowTrafficPct: 0.10\n autoPromote:\n enabled: true\n metric: winRateVsBaseline\n threshold: { gte: 0.55 }\n minSampleSize: 30\n cooldown: "7d"\n execution: sandboxed\n---\n\n## Overlay\nEvery short-form hook MUST earn the next 5 seconds. State a contradiction OR a specific number OR a named entity in the first sentence.\n\n## Procedure\n1. Generate 3 hooks per outline: contradiction, number, name.\n2. Score each by surprise (1-5) + relevance (1-5).\n3. Promote the highest combined score; archive the rest as alts.\n4. Output: hook + first 3 sentences + CTA.\n\n## Promotion gate\nPromote shadow \u2192 active when winRateVsBaseline \u2265 0.55 over n \u2265 30 evals.\n',
|
|
567
|
+
"routines/daily-source-scout/ROUTINE.md": '---\nschema: routine/v1\nid: daily-source-scout\ndescription: |\n Daily routine that runs the source-scout operator to discover new\n candidate sources across configured external feeds. Discovered sources\n are archived under sources/ and rows appended to _candidates.yaml.\nversion: "1.0.0"\nschedule:\n kind: cron\n cron: "0 9 * * *"\n timezone: "UTC"\n catchup: skip\ntarget:\n workflow: ingest-source\n inputs:\n feeds: [tiktok-curated, hubspot-blog, reddit-marketing]\n maxItemsPerRun: 50\nretry:\n max_attempts: 3\n backoff: exponential\non_failure:\n create_work_item: true\n fire_event: corpus.scout.failed\nfires_events:\n - corpus.scout.completed\n - corpus.candidate.discovered\nenabled: true\ntags: [corpus, scout, daily]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Daily Source Scout\n\nRuns every morning at 09:00 UTC. Scouts external feeds for new candidate sources, archives them, and appends to `_candidates.yaml`. The candidate event downstream triggers `analyze-candidate` workflow.\n',
|
|
568
|
+
"routines/monthly-eval-gap-finder/ROUTINE.md": '---\nschema: routine/v1\nid: monthly-eval-gap-finder\ndescription: |\n Monthly gap-finder run \u2014 reads the last 30 days of eval-case\n failures, clusters them, opens corpus-gap items for the scout.\n Closes loop #3 by turning observed weaknesses into next-harvest\n priorities.\nversion: "1.0.0"\nschedule:\n kind: cron\n cron: "0 8 1 * *"\n timezone: "UTC"\n catchup: skip\ntarget:\n workflow: detect-corpus-gaps\n inputs:\n windowDays: 30\n minOccurrences: 3\nretry:\n max_attempts: 2\n backoff: exponential\non_failure:\n create_work_item: true\n fire_event: corpus.gap-finder.failed\nfires_events:\n - corpus.gap-finder.completed\n - corpus.gap.opened\nenabled: true\ntags: [corpus, gaps, monthly]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Monthly Eval Gap Finder\n\nFirst day of each month, 08:00 UTC. Reads aggregated eval-case results, clusters failure modes, opens `corpus-gap/*/ITEM.md` items.\n',
|
|
569
|
+
"routines/quarterly-archive-cleanup/ROUTINE.md": '---\nschema: routine/v1\nid: quarterly-archive-cleanup\ndescription: |\n Quarterly storage hygiene \u2014 migrate sources older than 6 months\n to sources/cold/, hard-delete archived entries past their\n retention window, prune orphaned _candidates.yaml rows.\nversion: "1.0.0"\nschedule:\n kind: cron\n cron: "0 6 1 1,4,7,10 *"\n timezone: "UTC"\n catchup: skip\ntarget:\n workflow: corpus-archive-cleanup\nretry:\n max_attempts: 1\n backoff: fixed\non_failure:\n create_work_item: true\n fire_event: corpus.archive-cleanup.failed\nfires_events:\n - corpus.archive-cleanup.completed\nenabled: true\ntags: [corpus, archive, quarterly, maintenance]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Quarterly Archive Cleanup\n\nFirst day of every quarter at 06:00 UTC. Migrates aging sources to cold storage (still under `sources/cold/` for AIP-10 path resolvability), and prunes terminal-status candidates beyond retention.\n',
|
|
570
|
+
"routines/weekly-corpus-curation/ROUTINE.md": '---\nschema: routine/v1\nid: weekly-corpus-curation\ndescription: |\n Weekly curator pass \u2014 review the human-review queue, promote\n what\'s ready, deprecate what\'s stale, archive playbooks whose\n shadow eval has converged.\nversion: "1.0.0"\nschedule:\n kind: cron\n cron: "0 10 * * 1"\n timezone: "UTC"\n catchup: skip\ntarget:\n workflow: review-candidate\n inputs:\n mode: batch\n maxItems: 50\nretry:\n max_attempts: 2\n backoff: exponential\non_failure:\n create_work_item: true\n fire_event: corpus.curation.weekly-failed\nfires_events:\n - corpus.curation.weekly-completed\nenabled: true\ntags: [corpus, curation, weekly]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Weekly Corpus Curation\n\nMonday 10:00 UTC. The curator runs through the corpus-review queue, promotes approved candidates, deprecates stale entries. Pairs with `daily-source-scout` (which fills the pipeline).\n',
|
|
571
|
+
"sources/fresh/tiktok-hook-2026-05.md": `---
|
|
572
|
+
schema: knowledge.source/v1
|
|
573
|
+
id: tiktok-hook-2026-05
|
|
574
|
+
path: sources/fresh/tiktok-hook-2026-05.md
|
|
575
|
+
title: TikTok contrarian hook example \u2014 May 2026
|
|
576
|
+
captured_at: "2026-05-22T14:30:00Z"
|
|
577
|
+
captured_by: source-scout
|
|
578
|
+
content_hash: sha256:abc1234567890def1234567890abcdef1234567890abcdef1234567890abcdef
|
|
579
|
+
authority: secondary
|
|
580
|
+
language: en
|
|
581
|
+
tags: [tiktok, hook, short-form, contrarian]
|
|
582
|
+
metadata:
|
|
583
|
+
corpus:
|
|
584
|
+
originalUrl: https://example.com/tiktok/123
|
|
585
|
+
archiveTier: hot
|
|
586
|
+
archivedBy: source-scout
|
|
587
|
+
snapshotPath: sources/fresh/tiktok-hook-2026-05.snapshot.mhtml
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
# TikTok hook \u2014 "Most marketers are doing X. Here's why they're wrong."
|
|
591
|
+
|
|
592
|
+
Captured from a top-performing TikTok in May 2026. The hook contradicts a widely-held belief, generates 8x average engagement on the channel, and converts at 3x baseline for the SaaS product mentioned.
|
|
593
|
+
|
|
594
|
+
## Transcript
|
|
595
|
+
> Everyone says you should write listicles. But the truth is \u2014 and this took me three years to figure out \u2014 every viral piece I've ever written started with one specific contradiction\u2026
|
|
596
|
+
|
|
597
|
+
## Performance
|
|
598
|
+
- Views: 1.2M
|
|
599
|
+
- Engagement rate: 18.4% (channel avg: 2.3%)
|
|
600
|
+
- CTR to product: 4.1% (channel avg: 0.8%)
|
|
601
|
+
`,
|
|
602
|
+
"workflows/analyze-candidate/WORKFLOW.md": '---\nname: Analyze Corpus Candidate\nid: analyze-candidate\ndescription: |\n Convert a discovered corpus candidate into an analyzed ITEM.md with\n expert analysis, quality score, and risk score. Triggered by the\n source-scout when it appends a row to _candidates.yaml.\nversion: "1.0.0"\ninputs:\n type: object\n required: [candidateId, sourcePath]\n properties:\n candidateId: { type: string, pattern: "^[a-z0-9][a-z0-9-]*$" }\n sourcePath: { type: string }\noutputs:\n type: object\n required: [itemPath, status]\n properties:\n itemPath: { type: string }\n status: { type: string, enum: [analyzed, rejected, needs-work] }\n qualityScore: { type: number }\n riskScore: { type: number }\nsteps:\n - id: load-source\n kind: tool\n tool: knowledge.read_source\n name: Load source bytes from sources/\n inputs: { type: object, properties: { sourceId: { type: string } } }\n next: analyze\n - id: analyze\n kind: tool\n tool: marketing-analyst.analyze\n name: Run marketing-analyst operator over the source\n next: score\n - id: score\n kind: tool\n tool: quality-reviewer.score\n name: Compute quality + risk scores\n next: gate\n - id: gate\n kind: branch\n name: Decide promotionMode (auto vs human)\n description: Check auto-promote gate against KNOWLEDGE.md.metadata.corpus.autoPromote\n branches:\n - { when: "output.qualityScore >= 4.2 && output.riskScore <= 1.5", next: "auto-promote" }\n - { when: "true", next: "human-review" }\n - id: auto-promote\n kind: tool\n tool: corpus-curator-promote\n name: Promote to AIP-10 entry\n - id: human-review\n kind: approval\n name: Queue for human curator\n prompt: Review and approve or reject this candidate.\n approvers:\n - { role: corpus-curator }\ntags: [corpus, workflow, analysis]\nmetadata:\n corpus:\n domain: marketing\n triggeredBy: source-scout\n---\n\n# Analyze Candidate workflow\n\nConverts a discovered candidate into an analyzed ITEM.md. The marketing-analyst operator runs the actual analysis; this workflow orchestrates the pipeline (load \u2192 analyze \u2192 score \u2192 gate).\n',
|
|
603
|
+
"workflows/detect-corpus-gaps/WORKFLOW.md": '---\nname: Detect corpus gaps\nid: detect-corpus-gaps\ndescription: |\n Scan the last 30 days of eval-case failures, cluster by\n weakness type, open corpus-gap items with priority. Drives the\n scout\'s next harvest.\nversion: "1.0.0"\ninputs:\n type: object\n properties:\n windowDays: { type: integer, minimum: 1, maximum: 365, default: 30 }\n minOccurrences: { type: integer, minimum: 1, default: 3 }\noutputs:\n type: object\n required: [gapsOpened]\n properties:\n gapsOpened: { type: integer }\n clusters: { type: array }\nsteps:\n - id: load-failures\n kind: tool\n tool: corpus-load-eval-failures\n name: Load last-N-days eval failures\n - id: cluster\n kind: tool\n tool: gap-finder-cluster\n name: Cluster failures by weakness type + recurrence\n - id: open-gaps\n kind: map\n over: "steps.cluster.output.clusters"\n steps:\n - { id: open, kind: tool, tool: corpus-open-gap }\ntags: [corpus, gaps]\nmetadata:\n corpus:\n domain: marketing\n triggeredBy: gap-finder\n---\n\n# Detect corpus gaps workflow\n\nRuns monthly. Reads eval-case results, clusters failures, opens `corpus-gap/*/ITEM.md` items for the scout to read.\n',
|
|
604
|
+
"workflows/evaluate-agent-output/WORKFLOW.md": `---
|
|
605
|
+
name: Evaluate agent output
|
|
606
|
+
id: evaluate-agent-output
|
|
607
|
+
description: |
|
|
608
|
+
Score an agent output against a rubric via the pluggable
|
|
609
|
+
IEvaluator (M9). Wins seed flagCorpusLearning candidates;
|
|
610
|
+
losses feed detect-corpus-gaps.
|
|
611
|
+
version: "1.0.0"
|
|
612
|
+
inputs:
|
|
613
|
+
type: object
|
|
614
|
+
required: [prompt, response, rubricSlug]
|
|
615
|
+
properties:
|
|
616
|
+
prompt: { type: string }
|
|
617
|
+
response: { type: string }
|
|
618
|
+
rubricSlug: { type: string }
|
|
619
|
+
operatorRef: { type: string }
|
|
620
|
+
conversationId: { type: string }
|
|
621
|
+
retrievedHits:
|
|
622
|
+
type: array
|
|
623
|
+
items: { type: object }
|
|
624
|
+
outputs:
|
|
625
|
+
type: object
|
|
626
|
+
required: [score]
|
|
627
|
+
properties:
|
|
628
|
+
score: { type: number }
|
|
629
|
+
dimensions: { type: object }
|
|
630
|
+
rationale: { type: string }
|
|
631
|
+
routedAs: { type: string, enum: [win, loss, neutral] }
|
|
632
|
+
steps:
|
|
633
|
+
- id: evaluate
|
|
634
|
+
kind: tool
|
|
635
|
+
tool: evaluator-evaluate
|
|
636
|
+
name: Run IEvaluator against the rubric
|
|
637
|
+
- id: classify
|
|
638
|
+
kind: branch
|
|
639
|
+
name: Route win / loss / neutral
|
|
640
|
+
branches:
|
|
641
|
+
- { when: "output.score >= 0.7", next: "as-win" }
|
|
642
|
+
- { when: "output.score < 0.4", next: "as-loss" }
|
|
643
|
+
- { when: "true", next: "as-neutral" }
|
|
644
|
+
- id: as-win
|
|
645
|
+
kind: tool
|
|
646
|
+
tool: flagCorpusLearning
|
|
647
|
+
name: Seed a candidate from the winning trace
|
|
648
|
+
- id: as-loss
|
|
649
|
+
kind: tool
|
|
650
|
+
tool: corpus-record-eval-failure
|
|
651
|
+
name: Add to the eval-failure log for gap-finder
|
|
652
|
+
- id: as-neutral
|
|
653
|
+
kind: tool
|
|
654
|
+
tool: corpus-log-event
|
|
655
|
+
name: Log neutral outcome (no candidate spawn)
|
|
656
|
+
tags: [corpus, eval, telemetry]
|
|
657
|
+
metadata:
|
|
658
|
+
corpus:
|
|
659
|
+
domain: marketing
|
|
660
|
+
requires:
|
|
661
|
+
pluggable: [evaluator]
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
# Evaluate agent output workflow
|
|
665
|
+
|
|
666
|
+
Closes loop #3 (retrieval quality). Every agent output that's worth evaluating runs through this. Win / loss / neutral routing feeds the curation queue + the gap finder.
|
|
667
|
+
`,
|
|
668
|
+
"workflows/ingest-source/WORKFLOW.md": '---\nname: Ingest source\nid: ingest-source\ndescription: |\n Fetch + hash + dedup + archive a single source. Output: a new\n candidate row in _candidates.yaml (or no-op if duplicate).\nversion: "1.0.0"\ninputs:\n type: object\n required: [sourceUrl]\n properties:\n sourceUrl: { type: string }\n category: { type: string, enum: [fresh, classic, competitors, internal, performance] }\noutputs:\n type: object\n required: [outcome]\n properties:\n outcome: { type: string, enum: [archived, duplicate, rejected] }\n sourceId: { type: string }\n candidateId: { type: string }\nsteps:\n - id: fetch\n kind: tool\n tool: web-fetch\n name: Fetch source content\n - id: hash\n kind: tool\n tool: hash-content\n name: Compute sha256 content_hash\n - id: dedup\n kind: branch\n name: Dedup against existing sources\n branches:\n - { when: "output.duplicate === true", next: "done-dup" }\n - { when: "true", next: "archive" }\n - id: archive\n kind: tool\n tool: corpus-archive-source\n name: Write source frontmatter + body to sources/<category>/<slug>.md\n - id: create-candidate\n kind: tool\n tool: createCorpusCandidate\n name: Append discovered row to _candidates.yaml\n - id: done-dup\n kind: tool\n tool: corpus-log-event\n name: Log dedup hit (no-op outcome)\ntags: [corpus, ingest, scout]\nmetadata:\n corpus:\n domain: marketing\n triggeredBy: source-scout\n---\n\n# Ingest source workflow\n\nStep 1 of the corpus loop. Single-source entry point. Called by `daily-source-scout` once per discovered URL.\n',
|
|
669
|
+
"workflows/promote-corpus-item/WORKFLOW.md": '---\nname: Promote corpus item\nid: promote-corpus-item\ndescription: |\n Lift an approved candidate into a published AIP-10 entry. Writes\n the entry file, regenerates _index.md, ships chunks to the\n backing engine, appends a promotion event. Wraps the kit\'s\n CorpusPromoter.promote().\nversion: "1.0.0"\ninputs:\n type: object\n required: [candidateId, entrySlug, entryKind, entryPath, frontmatter, body]\n properties:\n candidateId: { type: string }\n entrySlug: { type: string }\n entryKind: { type: string, enum: [principle, example, pattern, critique, summary, timeline, playbook] }\n entryPath: { type: string }\n frontmatter: { type: object }\n body: { type: string }\n bypassGate: { type: boolean }\noutputs:\n type: object\n required: [entryPath, gatePassed]\n properties:\n entryPath: { type: string }\n versionToken: { type: string }\n chunkCount: { type: integer }\n gatePassed: { type: boolean }\n bypassed: { type: boolean }\nsteps:\n - id: promote\n kind: tool\n tool: promoteCorpusCandidate\n name: Atomic promote (lock + write + index + chunks + event)\ntags: [corpus, promote]\nmetadata:\n corpus:\n domain: marketing\n triggeredBy: corpus-curator\n---\n\n# Promote corpus item workflow\n\nStep 4 of the corpus loop. Single-step wrapper for callers that want the workflow shape; the underlying `CorpusPromoter` does the multi-file transaction.\n',
|
|
670
|
+
"workflows/review-candidate/WORKFLOW.md": '---\nname: Review analyzed candidate\nid: review-candidate\ndescription: |\n Score an analyzed candidate (quality + risk), set promotionMode,\n route to auto-promote or human-review queue.\nversion: "1.0.0"\ninputs:\n type: object\n required: [candidateId]\n properties:\n candidateId: { type: string }\noutputs:\n type: object\n required: [decision]\n properties:\n decision: { type: string, enum: [auto-promote, queue-review, reject] }\n qualityScore: { type: number }\n riskScore: { type: number }\nsteps:\n - id: load\n kind: tool\n tool: corpus-load-candidate\n name: Load candidate ITEM.md\n - id: score\n kind: tool\n tool: quality-reviewer-score\n name: Compute qualityScore + riskScore via reviewer operator\n - id: gate\n kind: branch\n name: Auto-promote gate\n branches:\n - { when: "output.qualityScore >= 4.2 && output.riskScore <= 1.5", next: "auto-promote" }\n - { when: "output.qualityScore < 2.0 || output.riskScore > 3.0", next: "reject" }\n - { when: "true", next: "queue-review" }\n - id: auto-promote\n kind: tool\n tool: promoteCorpusCandidate\n name: Promote without human gate\n - id: queue-review\n kind: tool\n tool: corpus-route-to-review\n name: Move ITEM.md to corpus-review collection\n - id: reject\n kind: tool\n tool: corpus-log-event\n name: Log corpus.candidate.rejected with reason\ntags: [corpus, review]\nmetadata:\n corpus:\n domain: marketing\n triggeredBy: marketing-analyst\n---\n\n# Review candidate workflow\n\nStep 3 of the corpus loop (after `analyze-candidate`). Reviewer scores and routes.\n',
|
|
671
|
+
"workflows/update-corpus-index/WORKFLOW.md": '---\nname: Update corpus index\nid: update-corpus-index\ndescription: |\n Regenerate _index.md (faceted catalog) from the current set of\n active entries. Triggered on promotion, deprecation, or\n status changes; can also run on demand.\nversion: "1.0.0"\ninputs:\n type: object\n properties:\n reason: { type: string, enum: [promoted, deprecated, archived, manual] }\noutputs:\n type: object\n required: [entryCount]\n properties:\n entryCount: { type: integer }\n indexBytes: { type: integer }\nsteps:\n - id: snapshot\n kind: tool\n tool: corpus-read-snapshot\n name: Read current workspace snapshot\n - id: regen\n kind: tool\n tool: corpus-regen-index\n name: Write _index.md from active entries (kind facets)\n - id: log\n kind: tool\n tool: corpus-log-event\n name: Log corpus.entry.indexed event\ntags: [corpus, index]\nmetadata:\n corpus:\n domain: marketing\n---\n\n# Update corpus index workflow\n\nMaintenance workflow \u2014 keeps `_index.md` in sync with the entries directory. The promote workflow inlines this; standalone version is for drift recovery.\n'
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// src/marketing/index.ts
|
|
675
|
+
var MarketingCorpusPreset = Object.freeze({
|
|
676
|
+
slug: "marketing",
|
|
677
|
+
title: "Marketing Expert Corpus",
|
|
678
|
+
description: "Autonomous marketing knowledge \u2014 principles, patterns, critiques, playbooks. Composes AIP-10/12/18/9/15/41 into a closed-loop improvement system.",
|
|
679
|
+
files: MARKETING_PRESET_FILES
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
export { MARKETING_PRESET_FILES, MarketingCorpusPreset };
|
|
683
|
+
//# sourceMappingURL=index.mjs.map
|
|
684
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/marketing/files.ts","../../src/marketing/index.ts"],"names":[],"mappings":";;;;;;AAQO,IAAM,sBAAA,GAA2D,OAAO,MAAA,CAAO;AAAA,EACpF,4CAAA,EAA8C,q6DAAA;AAAA,EAC9C,0DAAA,EAA4D,+oCAAA;AAAA,EAC5D,iDAAA,EAAmD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EACnD,oDAAA,EAAsD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EACtD,sDAAA,EAAwD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EACxD,4CAAA,EAA8C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAC9C,qDAAA,EAAuD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EACvD,2DAAA,EAA6D,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAC7D,gDAAA,EAAkD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAAA,EAClD,6DAAA,EAA+D,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAAA,EAC/D,cAAA,EAAgB,uhHAAA;AAAA,EAChB,sCAAA,EAAwC,grDAAA;AAAA,EACxC,kCAAA,EAAoC,kiDAAA;AAAA,EACpC,yCAAA,EAA2C,mxDAAA;AAAA,EAC3C,0CAAA,EAA4C,wuDAAA;AAAA,EAC5C,wCAAA,EAA0C,yiDAAA;AAAA,EAC1C,oCAAA,EAAsC,wjDAAA;AAAA,EACtC,2CAAA,EAA6C,24CAAA;AAAA,EAC7C,2CAAA,EAA6C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAAA,EAC7C,8CAAA,EAAgD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAAA,EAChD,yCAAA,EAA2C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAAA,EAC3C,0CAAA,EAA4C,05CAAA;AAAA,EAC5C,wCAAA,EAA0C,6gCAAA;AAAA,EAC1C,6CAAA,EAA+C,i7BAAA;AAAA,EAC/C,+CAAA,EAAiD,i7BAAA;AAAA,EACjD,4CAAA,EAA8C,65BAAA;AAAA,EAC9C,sCAAA,EAAwC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EACxC,yCAAA,EAA2C,koEAAA;AAAA,EAC3C,0CAAA,EAA4C,8qCAAA;AAAA,EAC5C,6CAAA,EAA+C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA,CAAA;AAAA,EAC/C,qCAAA,EAAuC,ukDAAA;AAAA,EACvC,2CAAA,EAA6C,w5CAAA;AAAA,EAC7C,wCAAA,EAA0C,4mDAAA;AAAA,EAC1C,2CAAA,EAA6C;AAC/C,CAAC;;;ACvBM,IAAM,qBAAA,GAAsC,OAAO,MAAA,CAAO;AAAA,EAC/D,IAAA,EAAM,WAAA;AAAA,EACN,KAAA,EAAO,yBAAA;AAAA,EACP,WAAA,EACE,wJAAA;AAAA,EACF,KAAA,EAAO;AACT,CAAC","file":"index.mjs","sourcesContent":["/**\n * AUTO-GENERATED build artifact — DO NOT COMMIT, DO NOT EDIT.\n *\n * Regenerated from @agentproto/corpus/test/fixtures/marketing/\n * by the prebuild / precheck-types / pretest / predev hooks on\n * this package. To change the preset content, edit the fixtures.\n */\n\nexport const MARKETING_PRESET_FILES: Readonly<Record<string, string>> = Object.freeze({\n \"collections/corpus-candidate/COLLECTION.md\": \"---\\nschema: collection.schema/v1\\nname: corpus-candidate\\ntitle: Corpus Candidate\\ndescription: |\\n Candidate corpus item awaiting analysis and promotion to an AIP-10 entry.\\n Discovered candidates live in `_candidates.yaml` sidecar; materialized\\n ITEM.md files appear only after transition out of `discovered`.\\nversion: 1.0.0\\ninitialStatus: discovered\\nstatuses:\\n - { id: discovered, label: Discovered, transitionsTo: [analyzed, rejected] }\\n - { id: analyzed, label: Analyzed, transitionsTo: [approved, rejected, needs-work] }\\n - { id: needs-work, label: Needs Work, transitionsTo: [analyzed, rejected] }\\n - { id: approved, label: Approved, terminal: true }\\n - { id: rejected, label: Rejected, terminal: true }\\nidentity:\\n slugSource: id\\n filingPath: \\\"collections/corpus-candidate/{slug}/ITEM.md\\\"\\nfields:\\n - { name: sourcePath, type: string, required: true }\\n - { name: sourceUrl, type: url }\\n - { name: targetEntryPath, type: string }\\n - { name: corpusKind, type: enum, enum: [principle, example, pattern, critique, summary, timeline, playbook], required: true }\\n - { name: qualityScore, type: number }\\n - { name: riskScore, type: number }\\n - { name: promotionMode, type: enum, enum: [auto, human] }\\n - { name: contentHash, type: string }\\n - { name: reviewerNotes, type: text }\\nlints:\\n - { id: required-field-source-path, kind: required-field, appliesTo: \\\"*\\\", severity: error, params: { fields: [sourcePath] } }\\n - { id: required-field-corpus-kind, kind: required-field, appliesTo: \\\"*\\\", severity: error, params: { fields: [corpusKind] } }\\nmetadata:\\n corpus:\\n description: Used by source-scout (writes), marketing-analyst (writes), quality-reviewer (scores), corpus-curator (promotes).\\n---\\n\\n# Corpus Candidate collection\\n\\nHolds candidates discovered by the scout, analyzed by the analyst, scored by the reviewer, and promoted by the curator. State machine enforced by `statuses[].transitionsTo`.\\n\",\n \"collections/corpus-candidate/tiktok-hook-2026-05/ITEM.md\": \"---\\nschema: collection.item/v1\\ncollection: corpus-candidate\\nid: tiktok-hook-2026-05\\ntitle: TikTok contrarian hook pattern\\nstatus: analyzed\\nsourcePath: sources/fresh/tiktok-hook-2026-05.md\\nsourceUrl: https://example.com/tiktok/123\\ntargetEntryPath: entries/patterns/2026/contrarian-short-form-hooks.md\\ncorpusKind: pattern\\ncontentHash: sha256:abc1234567890def1234567890abcdef1234567890abcdef1234567890abcdef\\ntags: [short-form, hooks]\\ncreatedAt: \\\"2026-05-22T14:30:00Z\\\"\\nupdatedAt: \\\"2026-05-22T15:00:00Z\\\"\\nmetadata:\\n corpus:\\n qualityScore: 4.3\\n riskScore: 1.1\\n promotionMode: auto\\n---\\n\\n# Candidate: TikTok contrarian hook\\n\\nCandidate extracted from fresh social examples. The pattern (contrarian belief-flip in <5s hooks) generalizes across short-form channels. Analyst recommends auto-promotion.\\n\\n## Analysis\\n- Pattern present in 6 of 10 top-performing TikToks reviewed\\n- Transferable to Reels, Shorts, cold-email subject lines\\n- No risk of legal / brand misuse identified\\n\\n## Decision\\n- promotionMode: auto\\n- gates pass: qualityScore 4.3 ≥ 4.2, riskScore 1.1 ≤ 1.5, archive hash present, all required fields populated\\n\",\n \"entries/critiques/2026/weak-positioning-saas.md\": \"---\\nschema: knowledge.entry/v1\\nslug: weak-positioning-saas\\nkind: critique\\ntitle: Weak positioning — \\\"powerful platform for X\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.85\\ntags: [positioning, anti-pattern, saas]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.1\\n riskScore: 1.2\\n domain: marketing\\n funnelStage: consideration\\n temporal:\\n firstSeen: \\\"2024-08-01T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n mentions:\\n - { at: \\\"2024-08-01T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 0.7 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## What's wrong\\n\\\"Powerful platform for [audience]\\\" makes zero claims. It's substitutable for any competitor's homepage.\\n\\n## Why it fails\\n- No specific outcome promised\\n- No specific cost / friction acknowledged\\n- No specific audience excluded\\n- Reader can't tell if it's for them\\n\\n## How to fix\\nReplace with: \\\"[outcome] for [specific audience] without [specific pain]\\\". E.g. \\\"Ship marketing copy in 10 minutes, not 10 days — without hiring a copywriter\\\".\\n\\n## Use this critique when\\n- Reviewing landing-page hero copy\\n- Reviewing PRD positioning sections\\n- Onboarding a new marketing-analyst operator\\n\",\n \"entries/examples/2026/apple-2007-iphone-keynote.md\": \"---\\nschema: knowledge.entry/v1\\nslug: apple-2007-iphone-keynote\\nkind: example\\ntitle: Apple 2007 iPhone keynote — three-products framing\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.92\\ntags: [keynote, framing, apple, launch]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.7\\n riskScore: 0.3\\n domain: marketing\\n channel: keynote\\n funnelStage: awareness\\n temporal:\\n firstSeen: \\\"2024-01-09T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n mentions:\\n - { at: \\\"2024-01-09T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nJobs opened the 2007 keynote by saying Apple was launching three products: a widescreen iPod with touch controls, a revolutionary mobile phone, and a breakthrough internet communicator. After repeating the trio twice, he revealed: \\\"These are not three separate devices. This is one device. And we are calling it iPhone.\\\" The pattern earned a standing ovation before any feature was shown.\\n\\n## What's specific\\n- Three concrete categories the audience already understood (iPod, phone, internet).\\n- Deliberate repetition built rhythm; the reveal collapsed all three into one.\\n- The reveal happened on word 47 of the keynote — pre-product, pre-spec.\\n\\n## Transferable lesson\\nFor a category-creating product, don't announce the new category. Announce three known things, then collapse them.\\n\\n## Use this example when\\n- Pitching anything that's \\\"X + Y + Z combined\\\".\\n- Launching to an audience that doesn't have a mental slot for the new thing yet.\\n\\n## Avoid this pattern when\\n- The product genuinely is one thing — manufacturing a trio is fake.\\n- The audience already knows the category (then specs, not framing, win).\\n\",\n \"entries/patterns/2026/contrarian-short-form-hooks.md\": \"---\\nschema: knowledge.entry/v1\\nslug: contrarian-short-form-hooks\\nkind: pattern\\ntitle: Contrarian short-form hooks\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.88\\nlinks:\\n - specificity-beats-superlatives\\ntags: [hooks, short-form, tiktok, contrarian]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.5\\n riskScore: 1.0\\n domain: marketing\\n channel: tiktok\\n funnelStage: awareness\\n temporal:\\n firstSeen: \\\"2023-04-12T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n halfLifeDays: 180\\n mentions:\\n - { at: \\\"2023-04-12T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: auto\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nOpen with a popularly-held belief, then contradict it with a specific counter-claim. Forces a \\\"wait, what?\\\" pattern interrupt that buys 3-5 more seconds of attention.\\n\\n## Why it works\\nPattern-interrupt + curiosity gap. The viewer's brain treats the contradiction as a problem to resolve.\\n\\n## Transferable pattern\\n1. State a widely-held belief in 5 words\\n2. Counter with one specific contradiction\\n3. Promise the why in the next 30 seconds\\n\\n## Use when\\n- Short-form video (TikTok, Reels, Shorts)\\n- Cold-outbound email subject lines\\n- Ad creative for low-awareness audiences\\n\\n## Avoid when\\n- Branded content (feels manipulative)\\n- Audience already aligned with your stance\\n- Long-form (the hook doesn't sustain)\\n\\n## Examples\\n- \\\"Most marketers write listicles. Here's why every viral piece I've made started with a contradiction.\\\"\\n- \\\"Cold email is dead — for the 99% who do it wrong. Here's the 1%.\\\"\\n\",\n \"entries/patterns/2026/story-then-payoff.md\": \"---\\nschema: knowledge.entry/v1\\nslug: story-then-payoff\\nkind: pattern\\ntitle: Story-then-payoff structure\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.85\\nlinks:\\n - contrarian-short-form-hooks\\n - clarity-beats-cleverness\\ntags: [storytelling, structure, copy]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.3\\n riskScore: 0.8\\n domain: marketing\\n funnelStage: awareness\\n temporal:\\n firstSeen: \\\"2023-09-15T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n mentions:\\n - { at: \\\"2023-09-15T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: auto\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nOpen with a 1-2 sentence story (specific, sensory), then deliver the payoff (principle, product, CTA). The story buys attention; the payoff cashes it in.\\n\\n## Why it works\\nBrains are pattern-completion engines. A half-told story creates open loop tension. Closing the loop with the payoff delivers a small dopamine hit + transfers credibility from the story to the claim.\\n\\n## Transferable pattern\\n- Story: ≤2 sentences, one concrete moment.\\n- Payoff: ≤1 sentence, names the principle / product / CTA.\\n- Optional: 1 sentence connecting the two.\\n\\n## Use when\\n- Cold email openers, ad creative, landing-page heros.\\n- Audiences that don't know the product yet.\\n\\n## Avoid when\\n- Internal comms (waste of words).\\n- Audiences past consideration stage — they want specs, not stories.\\n\",\n \"entries/principles/2026/clarity-beats-cleverness.md\": \"---\\nschema: knowledge.entry/v1\\nslug: clarity-beats-cleverness\\nkind: principle\\ntitle: Clarity beats cleverness\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.95\\ntags: [copy, clarity, conversion]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.8\\n riskScore: 0.5\\n domain: marketing\\n funnelStage: awareness\\n temporal:\\n firstSeen: \\\"2022-01-01T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n mentions:\\n - { at: \\\"2022-01-01T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nIf the reader has to re-read a sentence, the joke is on the writer. Wordplay that's clever-but-confusing loses 100% of distracted readers.\\n\\n## Why it works\\nReading is involuntary effort. Clever copy taxes that effort; clear copy doesn't. The cheapest conversion is the one where the reader didn't have to work.\\n\\n## Transferable pattern\\n- Write at a 6th-grade reading level (Hemingway score).\\n- Replace every metaphor that doesn't add new information.\\n- One idea per sentence.\\n\\n## Use when\\n- Landing-page headlines, CTAs, ad creative.\\n- Any audience that hasn't already paid attention.\\n\\n## Avoid when\\n- Brand-content where the voice IS the product (Liquid Death, Cards Against Humanity).\\n- Inside-baseball content for an already-converted audience.\\n\",\n \"entries/principles/2026/specificity-beats-superlatives.md\": \"---\\nschema: knowledge.entry/v1\\nslug: specificity-beats-superlatives\\nkind: principle\\ntitle: Specificity beats superlatives\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.92\\ntags: [copy, specificity, conversion]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.7\\n riskScore: 0.8\\n domain: marketing\\n funnelStage: consideration\\n temporal:\\n firstSeen: \\\"2023-04-12T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n mentions:\\n - { at: \\\"2023-04-12T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nConcrete claims with numbers outperform superlative adjectives. \\\"3x conversion\\\" beats \\\"amazing results\\\"; \\\"287 customers in 90 days\\\" beats \\\"many happy customers\\\".\\n\\n## Why it works\\nReaders parse numbers as evidence; adjectives as marketing noise. Specificity transfers credibility because it implies the author can be checked.\\n\\n## Transferable pattern\\n- Replace every superlative with a specific number, date, or named entity\\n- If you can't substitute, the claim is probably untrue\\n\\n## Use when\\n- Writing landing-page copy\\n- Drafting ad creative\\n- Replying to objections\\n\\n## Avoid when\\n- Numbers are unverifiable (then say nothing)\\n- Aspirational brand voice required\\n\",\n \"entries/summaries/2026/short-form-hook-meta.md\": \"---\\nschema: knowledge.entry/v1\\nslug: short-form-hook-meta\\nkind: summary\\ntitle: Short-form hook meta — what's working in 2026\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.7\\nlinks:\\n - contrarian-short-form-hooks\\n - story-then-payoff\\n - clarity-beats-cleverness\\ntags: [meta, short-form, hooks, trends]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.0\\n riskScore: 1.0\\n domain: marketing\\n channel: tiktok\\n funnelStage: awareness\\n temporal:\\n firstSeen: \\\"2026-04-01T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n halfLifeDays: 60\\n mentions:\\n - { at: \\\"2026-04-01T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nAs of mid-2026, the dominant short-form hook patterns on TikTok / Reels / Shorts share three traits: (1) contradiction in the first 2 seconds, (2) specific number or named entity by the 5-second mark, (3) the payoff arrives before 30 seconds.\\n\\n## What's NOT working anymore\\n- Generic \\\"POV:\\\" openers — algo deprioritized them after the Q1 update.\\n- Long establishing shots — 90% drop-off before the 3-second mark.\\n- \\\"Watch till the end\\\" framing — overuse killed effectiveness.\\n\\n## Patterns that scale across channels\\n- [[contrarian-short-form-hooks]] — universal, lowest production cost.\\n- [[story-then-payoff]] — needs a sharp specific story; expensive to source.\\n\\n## Half-life\\n60 days. Re-mention via scout when a new platform algorithm update lands.\\n\",\n \"entries/timelines/2026/saas-positioning-shifts-2020-2026.md\": \"---\\nschema: knowledge.entry/v1\\nslug: saas-positioning-shifts-2020-2026\\nkind: timeline\\ntitle: SaaS positioning shifts — 2020 to 2026\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\nsources:\\n - tiktok-hook-2026-05\\nconfidence: 0.78\\nlinks:\\n - weak-positioning-saas\\ntags: [positioning, saas, timeline, trend]\\nmetadata:\\n corpus:\\n status: active\\n qualityScore: 4.1\\n riskScore: 1.2\\n domain: marketing\\n funnelStage: consideration\\n temporal:\\n firstSeen: \\\"2024-06-01T00:00:00Z\\\"\\n lastSeen: \\\"2026-05-22T14:30:00Z\\\"\\n halfLifeDays: 180\\n mentions:\\n - { at: \\\"2024-06-01T00:00:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n - { at: \\\"2026-05-22T14:30:00Z\\\", sourceId: tiktok-hook-2026-05, weight: 1.0 }\\n promotionMode: human\\n promotedAt: \\\"2026-05-22T14:30:00Z\\\"\\n promotedBy: corpus-curator\\n---\\n\\n## Summary\\nB2B SaaS positioning evolved through five distinct phases between 2020 and 2026, each driven by a buyer environment shift.\\n\\n## 2020 — \\\"All-in-one platform\\\"\\nBuyers consolidating tools post-COVID; positioning prized breadth.\\nResult: feature-list arms race, undifferentiated category copy.\\n\\n## 2022 — \\\"Best-in-class for X\\\"\\nStack-fatigue reversed; buyers wanted focused tools.\\nResult: \\\"the [adjective] [category] for [vertical]\\\" replaced \\\"all-in-one\\\".\\n\\n## 2023 — \\\"AI-native\\\"\\nGPT-3.5 wave; everything claimed AI even when it was a wrapper.\\nResult: skepticism by mid-2024; AI claims now require demonstrated trade-offs.\\n\\n## 2024 — \\\"Replace your [old tool]\\\"\\nDirect displacement framing. Worked for late-comers in mature categories.\\n\\n## 2026 — \\\"We don't ship a [thing]\\\"\\nReactive positioning — define yourself by what you refused to build.\\nMost credible when accompanied by a concrete reason (compliance, philosophy).\\n\\n## Pattern\\nPositioning rotates roughly every 18-24 months. The current peak narrative is the most-imitated; the next winner is usually the inverse of the saturated one.\\n\",\n \"KNOWLEDGE.md\": \"---\\nschema: knowledge.workspace/v1\\nname: marketing-corpus\\ntitle: Marketing Expert Corpus\\ndescription: |\\n Expert marketing knowledge for autonomous agents. Composes AIP-10 (knowledge),\\n AIP-12 (playbooks), AIP-18 (curation collections), AIP-9 (operators),\\n AIP-15 (workflows), and AIP-41 (routines) into an autonomous improvement loop.\\nversion: 1.0.0\\nentityTypes:\\n - { name: Principle, description: \\\"Durable expert rule\\\" }\\n - { name: Example, description: \\\"Concrete source-derived example\\\" }\\n - { name: Pattern, description: \\\"Reusable transferable mechanic\\\" }\\n - { name: Critique, description: \\\"Negative example or failure mode\\\" }\\n - { name: Summary, description: \\\"Compressed source synthesis\\\" }\\n - { name: Timeline, description: \\\"Time-sensitive trend evolution\\\" }\\n - { name: PlaybookCase, description: \\\"Documented case study of a great playbook\\\" }\\nsources:\\n retention: forever\\n signing: optional\\n hashAlgo: sha256\\n authorityDefault: secondary\\nlints:\\n - { id: require-source-on-examples, kind: require-source, appliesTo: Example, severity: error }\\n - { id: min-confidence-principles, kind: min-confidence, appliesTo: Principle, severity: warn, params: { min: 0.6 } }\\n - { id: max-age-timelines, kind: max-age, appliesTo: Timeline, severity: warn, params: { days: 730 } }\\n - { id: max-age-summaries, kind: max-age, appliesTo: Summary, severity: warn, params: { days: 180 } }\\n - { id: broken-ref-all, kind: broken-ref, appliesTo: \\\"*\\\", severity: error }\\n - { id: orphan-all, kind: orphan, appliesTo: \\\"*\\\", severity: info }\\ncuration:\\n tone: \\\"neutral, expert, source-backed\\\"\\n depth: medium\\n autoLink: byName\\n conflictResolution: authority\\nqueryHints:\\n preferRecent: true\\n preferAuthoritative: true\\nmetadata:\\n corpus:\\n version: 1\\n domain: marketing\\n autoPromote:\\n enabled: true\\n requires:\\n qualityScore: { min: 4.2 }\\n riskScore: { max: 1.5 }\\n hasArchiveHash: true\\n requiredFields: [why_it_works, transferable_pattern, use_when, avoid_when]\\n notRestricted: true\\n temporal:\\n defaultHalfLifeDays: 180\\n scoreFormula: max-mention-decay\\n retrievalBoosts:\\n qualityScore: { weight: 0.30 }\\n temporalScore: { weight: 0.20 }\\n mentionCount: { weight: 0.10 }\\n confidence: { weight: 0.15 }\\n retrievalDefaults:\\n status: active\\n minQualityScore: 3.5\\n minTemporalScore: 0.1\\n accessModes:\\n read: { allowedRoles: [\\\"*\\\"] }\\n cite: { allowedRoles: [\\\"*\\\"] }\\n flag-learning: { allowedRoles: [\\\"*\\\"], rateLimit: { perOperator: 20, window: \\\"24h\\\" } }\\n curate: { allowedRoles: [corpus-curator, admin] }\\n promote: { allowedRoles: [corpus-curator, admin] }\\n activate-playbook: { allowedRoles: [corpus-curator, admin], requireApproval: true }\\n admin-reindex: { allowedRoles: [admin] }\\n bypass-default-filters: { allowedRoles: [corpus-curator, admin], audit: true }\\n---\\n\\n# Marketing Corpus\\n\\nSource-of-truth for autonomous marketing agents. Composes AgentProto AIPs into a closed-loop knowledge-improvement system.\\n\\n## Three loops\\n- **Knowledge curation** — gap-finder → curator → entries\\n- **Playbook evolution** — gap → AIP-12 shadow playbook → evaluator → active|archived\\n- **Retrieval-quality feedback** — every query logged; `utility` + `lift` written back to entries\\n\\nAll corpus-specific policy lives under `metadata.corpus.*`. AIP amendments (A1-A8) may hoist specific fields to first-class later — strictly additive, no rip-and-replace.\\n\",\n \"operators/corpus-curator/OPERATOR.md\": \"---\\nname: Corpus Curator\\nid: corpus-curator\\npersona_summary: Promotes approved candidates to AIP-10 entries, maintains _index.md, handles deprecation + supersession. The corpus's editor-in-chief.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n Promote candidates that pass the auto-promote gate. Review the\\n human-review queue, decide approve/reject/needs-work. Keep the\\n corpus tidy: dedupe, deprecate stale entries, resolve\\n contradictions.\\n voice: |\\n Direct, decisive, opinionated about quality bar. First-person\\n plural for company voice. Cites specific entry slugs when\\n discussing deprecation or supersession.\\n boundaries:\\n - Never promote an entry that fails the auto-promote gate without explicit bypass.\\n - Never deprecate without a written reason in metadata.corpus.archiveReason.\\n - Always preserve the audit chain — _log.md events are append-only.\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: autonomous\\n policies:\\n - \\\"policy:corpus/marketing/curation\\\"\\nskills:\\n - source-analysis\\n - taxonomy\\n - editorial-judgment\\ntools:\\n - corpus-promote-candidate\\n - corpus-activate-playbook\\n - corpus-archive-playbook\\n - corpus-log-event\\n - knowledge-query\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, curator, corpus]\\nmetadata:\\n corpus:\\n domain: marketing\\n overlays:\\n policy: open\\n maxActiveCount: 10\\n---\\n\\n# Corpus Curator\\n\\nRuns after the reviewer scores a candidate. Promotes auto-approved entries; queues human-review-required candidates for the team. Also drives playbook lifecycle (`activate` / `archive`).\\n\",\n \"operators/gap-finder/OPERATOR.md\": \"---\\nname: Gap Finder\\nid: gap-finder\\npersona_summary: Mines low-scoring eval-cases for systematic weaknesses in the corpus. Opens corpus-gap items so the scout knows what to look for next.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n Read recent eval-case results, identify recurring failure modes,\\n classify them (generic-output, weak-strategy, stale-reference,\\n poor-style, missing-domain-context), and open corpus-gap items\\n with priority based on frequency.\\n voice: |\\n Diagnostic, pattern-oriented, prescriptive. Says \\\"we have N\\n failures of kind X\\\" not \\\"the agent sometimes struggles\\\".\\n Recommends a concrete next scouting target.\\n boundaries:\\n - Never open a gap on a single low-score case — require ≥3 occurrences.\\n - Never blame the operator — gaps describe missing knowledge, not bad reasoning.\\n - Always link the eval-case refs that motivated the gap.\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: autonomous\\nskills:\\n - source-analysis\\n - pattern-recognition\\ntools:\\n - corpus-log-event\\n - knowledge-query\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, gap-finder, corpus]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Gap Finder\\n\\nRuns monthly (via `monthly-eval-gap-finder` routine). Scans the last 30 days of `eval-case` results, finds clusters of failure, opens `corpus-gap/*/ITEM.md` items with `weaknessType` + `priority`. The scout reads these to prioritize the next harvest.\\n\",\n \"operators/marketing-analyst/OPERATOR.md\": \"---\\nname: Marketing Analyst\\nid: marketing-analyst\\npersona_summary: Senior marketing analyst who converts raw social/web sources into expert principles, patterns, and critiques for the marketing corpus.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n Convert candidate sources discovered by the scout into corpus-grade\\n expert analysis: principles, patterns, critiques. Score quality and\\n risk to inform promotion gates.\\n voice: |\\n Concrete, source-backed, never superlative. Cite specific numbers and\\n named entities. First-person plural (\\\"we\\\") for company voice.\\n boundaries:\\n - Never invent quantitative claims; cite a source or mark as opinion.\\n - Never promote without quality-reviewer signoff (unless auto-promote gates pass).\\n - Never edit raw sources — only entries.\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: supervised\\n policies:\\n - \\\"policy:corpus/marketing/curation\\\"\\nskills:\\n - source-analysis\\n - copywriting\\ntools:\\n - corpus-flag-learning\\n - knowledge-query\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, analyst, corpus]\\nmetadata:\\n corpus:\\n domain: marketing\\n knowledgeViews:\\n - corpus: marketing\\n filter:\\n domain: [marketing]\\n minQualityScore: 3.5\\n defaultBoosts:\\n qualityScore: { weight: 0.40 }\\n temporalScore: { weight: 0.30 }\\n overlays:\\n policy: gated\\n maxActiveCount: 5\\n requireApprovalFrom: corpus-curator\\n allowedKinds: [overlay, block-replacement]\\n---\\n\\n# Marketing Analyst\\n\\nReads candidate sources from the scout, writes expert analysis as AIP-10 entries. Scores quality and risk. Signals the curator on auto-promote gate pass.\\n\",\n \"operators/playbook-evaluator/OPERATOR.md\": \"---\\nname: Playbook Evaluator\\nid: playbook-evaluator\\npersona_summary: Runs shadow vs baseline eval batches on AIP-12 playbooks. Records winRateVsBaseline, decides promote / archive based on the playbook's auto_promote gate.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n For every shadow playbook, run eval-cases through both arms\\n (overlay applied vs operator default). Score outputs via the\\n rubric the playbook's evidence[].eval-case references. Record\\n metrics in metadata.corpus.shadowMetrics. Trigger curator action\\n when the auto_promote.threshold is met.\\n voice: |\\n Quantitative, dispassionate, hypothesis-driven. States the null\\n hypothesis explicitly (n, threshold, observed) before\\n recommending an action.\\n boundaries:\\n - Never activate a playbook — that's the curator's call (audit chain).\\n - Never report a winRate on n < playbook.metadata.corpus.autoPromote.minSampleSize.\\n - Always run identical eval-cases on both arms (same prompts, same rubric).\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: autonomous\\nskills:\\n - statistics\\n - source-analysis\\ntools:\\n - corpus-list-playbooks\\n - corpus-log-event\\n - knowledge-query\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, evaluator, corpus, aip-12]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Playbook Evaluator\\n\\nDrives the playbook side of closed loop #2 (procedure). Runs nightly (via per-playbook eval-batch routines, configured per playbook). Writes back `shadowMetrics.{sampleSize, winRateVsBaseline, lastEvaluatedAt}` to PLAYBOOK.md. When gates pass, posts a `playbook.ready-for-activation` event the curator subscribes to.\\n\",\n \"operators/quality-reviewer/OPERATOR.md\": \"---\\nname: Quality Reviewer\\nid: quality-reviewer\\npersona_summary: Scores analyzed candidates against the corpus's quality + risk rubric. Decides promotionMode (auto vs human). Flags concerns the analyst missed.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n Independent second pair of eyes on every analyzed candidate.\\n Adversarial-by-design — assumes the analyst was too generous\\n and looks for reasons NOT to promote.\\n voice: |\\n Critical, concrete, fair. Cites specific clauses of the\\n candidate body, not vibes. Always proposes a concrete score\\n (qualityScore 0-5, riskScore 0-5).\\n boundaries:\\n - Never promote on the analyst's authority — score and route.\\n - Never auto-promote a candidate flagged as restricted / personal / legal.\\n - Always justify a sub-2.0 quality score in reviewerNotes.\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: supervised\\n policies:\\n - \\\"policy:corpus/marketing/review-policy\\\"\\nskills:\\n - source-analysis\\n - critical-reading\\ntools:\\n - corpus-flag-learning\\n - knowledge-query\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, reviewer, corpus]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Quality Reviewer\\n\\nRuns after `marketing-analyst` produces an analyzed ITEM.md. Scores against:\\n\\n- **qualityScore** — accuracy, transferability, evidence\\n- **riskScore** — legal/brand/compliance hazards\\n- **promotionMode** — auto (gates pass) vs human (needs curator)\\n\",\n \"operators/source-scout/OPERATOR.md\": \"---\\nname: Source Scout\\nid: source-scout\\npersona_summary: Curates external feeds for fresh marketing source material — TikToks, blog posts, ad creative, internal performance data — and archives the worth-keeping ones into sources/.\\nversion: \\\"1.0.0\\\"\\nprofile:\\n role: |\\n Discover new candidate sources for the marketing corpus. Filter\\n noise vs signal at the scout stage so the analyst only sees\\n promising material.\\n voice: |\\n Efficient, terse, evidence-first. Names URLs + numbers, not\\n adjectives. Reports findings as `{source: <id>, why: <reason>}`\\n triples.\\n boundaries:\\n - Never re-archive an already-archived source (check content_hash).\\n - Never archive content with PII unless explicitly sanitized.\\n - Never archive paywalled / DMCA-restricted material.\\ngovernance:\\n audit_log: \\\"audit:corpus/marketing/_log.md\\\"\\n autonomy: autonomous\\n policies:\\n - \\\"policy:corpus/marketing/source-policy\\\"\\nskills:\\n - web-research\\n - source-analysis\\ntools:\\n - corpus-create-candidate\\n - knowledge-query\\n - web-search\\nparticipation:\\n mode: proactive\\nmemory:\\n kind: operator-context\\nruntime:\\n kind: in-process\\ntags: [marketing, scout, corpus]\\nmetadata:\\n corpus:\\n domain: marketing\\n knowledgeViews:\\n - corpus: marketing\\n filter:\\n domain: [marketing]\\n---\\n\\n# Source Scout\\n\\nRuns daily (via `daily-source-scout` routine). Fetches configured feeds, hashes content, dedups against existing sources, and writes new candidates to `_candidates.yaml`. The analyst takes over from there.\\n\",\n \"playbooks/ad-angle-generation/PLAYBOOK.md\": \"---\\nschema: playbooks/v1\\nslug: ad-angle-generation\\ntitle: Ad angle generation — JTBD-grounded variants\\ntargets:\\n - { kind: operator, ref: marketing-analyst }\\nbinds_operator: marketing-analyst\\nkind: overlay\\nstatus: shadow\\npriority: 90\\nlock_check:\\n - factual-grounded\\nevidence:\\n - kind: run\\n ref: collections/eval-case/ad-angle-suite/runs/initial\\n note: First eval batch, n=20 planned\\n - kind: reflection\\n ref: collections/corpus-gap/generic-ad-copy/ITEM.md\\n note: Gap that motivated this playbook\\nttl: \\\"P90D\\\"\\nsupersedes: []\\ncreated_at: \\\"2026-05-22T14:30:00Z\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\ntags: [ads, angles, jtbd]\\nmetadata:\\n corpus:\\n authoredBy: corpus-curator\\n shadowTrafficPct: 0.10\\n autoPromote:\\n enabled: true\\n metric: winRateVsBaseline\\n threshold: { gte: 0.55 }\\n minSampleSize: 30\\n cooldown: \\\"7d\\\"\\n execution: sandboxed\\n---\\n\\n## Overlay\\nWhen generating ad creative, generate 3 distinct angles before refining any single one.\\n\\n## Procedure\\n1. Identify the JTBD (job-to-be-done) the audience hires the product for.\\n2. Generate one angle per axis: outcome, pain, identity.\\n3. For each angle, write a hook + body in <50 words.\\n4. Score each angle on specificity + audience fit; promote the highest.\\n\\n## Promotion gate\\nPromote shadow → active when winRateVsBaseline ≥ 0.55 over n ≥ 30 evals.\\n\",\n \"playbooks/cold-email-outbound/PLAYBOOK.md\": \"---\\nschema: playbooks/v1\\nslug: cold-email-outbound\\ntitle: Cold email outbound — earned-attention opener\\ntargets:\\n - { kind: operator, ref: marketing-analyst }\\nbinds_operator: marketing-analyst\\nkind: overlay\\nstatus: shadow\\npriority: 70\\nlock_check: []\\nevidence:\\n - kind: run\\n ref: collections/eval-case/cold-email-suite/runs/initial\\n note: First eval batch planned\\nttl: \\\"P90D\\\"\\nsupersedes: []\\ncreated_at: \\\"2026-05-22T14:30:00Z\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\ntags: [cold-email, outbound, sales]\\nmetadata:\\n corpus:\\n authoredBy: corpus-curator\\n shadowTrafficPct: 0.10\\n autoPromote:\\n enabled: true\\n metric: winRateVsBaseline\\n threshold: { gte: 0.55 }\\n minSampleSize: 30\\n cooldown: \\\"7d\\\"\\n execution: sandboxed\\n---\\n\\n## Overlay\\nCold-email opener MUST earn the reader's next 5 seconds by stating something they didn't know, not by claiming a benefit.\\n\\n## Procedure\\n1. Research one specific thing about the prospect (their hire, their post, their company's recent move).\\n2. State that thing in <12 words as the opener.\\n3. Connect it to the offer in the next sentence — NO \\\"I noticed you…\\\" bridge.\\n4. End with one specific yes/no question.\\n\\n## Promotion gate\\nPromote shadow → active when winRateVsBaseline ≥ 0.55 over n ≥ 30 evals.\\n\",\n \"playbooks/competitor-positioning/PLAYBOOK.md\": \"---\\nschema: playbooks/v1\\nslug: competitor-positioning\\ntitle: Competitor positioning — pick your axis, name the trade\\ntargets:\\n - { kind: operator, ref: marketing-analyst }\\nbinds_operator: marketing-analyst\\nkind: overlay\\nstatus: shadow\\npriority: 80\\nlock_check:\\n - factual-grounded\\n - brand-voice\\nevidence:\\n - kind: run\\n ref: collections/eval-case/positioning-suite/runs/initial\\n note: First eval batch planned\\nttl: \\\"P90D\\\"\\nsupersedes: []\\ncreated_at: \\\"2026-05-22T14:30:00Z\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\ntags: [positioning, competitive, differentiation]\\nmetadata:\\n corpus:\\n authoredBy: corpus-curator\\n shadowTrafficPct: 0.10\\n autoPromote:\\n enabled: true\\n metric: winRateVsBaseline\\n threshold: { gte: 0.55 }\\n minSampleSize: 30\\n cooldown: \\\"7d\\\"\\n execution: sandboxed\\n---\\n\\n## Overlay\\nPositioning copy MUST name the specific competitor weakness it's trading off against. \\\"We're faster\\\" is noise; \\\"We don't ship a CLI\\\" is positioning.\\n\\n## Procedure\\n1. List the top 3 competitors by ICP overlap.\\n2. For each, identify one specific decision they made that we explicitly DIDN'T.\\n3. Write the positioning line as: `For [ICP], who [problem], [product] is the [category] that [specific trade-off vs competitor]`.\\n4. Lint output against the [[weak-positioning-saas]] critique.\\n\\n## Promotion gate\\nPromote shadow → active when winRateVsBaseline ≥ 0.55 over n ≥ 30 evals.\\n\",\n \"playbooks/landing-page-copy/PLAYBOOK.md\": \"---\\nschema: playbooks/v1\\nslug: landing-page-copy\\ntitle: Landing-page copy — high-conversion structure\\ntargets:\\n - { kind: operator, ref: marketing-analyst }\\nbinds_operator: marketing-analyst\\nkind: overlay\\nstatus: shadow\\npriority: 100\\nlock_check:\\n - brand-voice\\n - factual-grounded\\nevidence:\\n - kind: run\\n ref: collections/eval-case/landing-page-copy-conversion-suite/runs/2026-05-22-batch-1\\n note: First shadow batch, n=30 evals, winRateVsBaseline TBD\\n - kind: reflection\\n ref: collections/corpus-gap/weak-positioning-saas/ITEM.md\\n note: Gap that motivated this playbook\\nttl: \\\"P90D\\\"\\nsupersedes: []\\ncreated_at: \\\"2026-05-22T14:30:00Z\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\ntags: [landing-page, copy, conversion]\\nmetadata:\\n corpus:\\n authoredBy: corpus-curator\\n derivedFromGap: collections/corpus-gap/weak-positioning-saas/ITEM.md\\n shadowTrafficPct: 0.10\\n autoPromote:\\n enabled: true\\n metric: winRateVsBaseline\\n threshold: { gte: 0.55 }\\n minSampleSize: 30\\n cooldown: \\\"7d\\\"\\n shadowMetrics:\\n sampleSize: 0\\n winRateVsBaseline: null\\n lastEvaluatedAt: null\\n archiveReason: null\\n execution: sandboxed\\n---\\n\\n## Overlay\\n[Markdown that gets merged into marketing-analyst's prompt at runtime when this playbook is active. The block-replacement / overlay merge logic is the runtime's concern, not this fixture's.]\\n\\n## Procedure\\n1. Read brief: ICP, offer, current page.\\n2. Apply principle [[specificity-beats-superlatives]] — every superlative gets a number, date, or named entity.\\n3. Generate 3 hook variants using pattern [[contrarian-short-form-hooks]].\\n4. Lint output against critique [[weak-positioning-saas]].\\n5. Output: H1, sub-H1, 3 CTA variants, 1 social-proof block.\\n\\n## Promotion gate\\nPromote shadow → active when winRateVsBaseline ≥ 0.55 over n ≥ 30 evals (see metadata.corpus.autoPromote).\\n\",\n \"playbooks/social-hook-design/PLAYBOOK.md\": \"---\\nschema: playbooks/v1\\nslug: social-hook-design\\ntitle: Social hook design — pattern interrupt in 5 seconds\\ntargets:\\n - { kind: operator, ref: marketing-analyst }\\nbinds_operator: marketing-analyst\\nkind: overlay\\nstatus: shadow\\npriority: 95\\nlock_check: []\\nevidence:\\n - kind: run\\n ref: collections/eval-case/social-hook-suite/runs/initial\\n note: First eval batch planned\\n - kind: reflection\\n ref: entries/patterns/2026/contrarian-short-form-hooks.md\\n note: Pattern this playbook operationalizes\\nttl: \\\"P90D\\\"\\nsupersedes: []\\ncreated_at: \\\"2026-05-22T14:30:00Z\\\"\\nupdated_at: \\\"2026-05-22T14:30:00Z\\\"\\ntags: [social, hook, short-form]\\nmetadata:\\n corpus:\\n authoredBy: corpus-curator\\n shadowTrafficPct: 0.10\\n autoPromote:\\n enabled: true\\n metric: winRateVsBaseline\\n threshold: { gte: 0.55 }\\n minSampleSize: 30\\n cooldown: \\\"7d\\\"\\n execution: sandboxed\\n---\\n\\n## Overlay\\nEvery short-form hook MUST earn the next 5 seconds. State a contradiction OR a specific number OR a named entity in the first sentence.\\n\\n## Procedure\\n1. Generate 3 hooks per outline: contradiction, number, name.\\n2. Score each by surprise (1-5) + relevance (1-5).\\n3. Promote the highest combined score; archive the rest as alts.\\n4. Output: hook + first 3 sentences + CTA.\\n\\n## Promotion gate\\nPromote shadow → active when winRateVsBaseline ≥ 0.55 over n ≥ 30 evals.\\n\",\n \"routines/daily-source-scout/ROUTINE.md\": \"---\\nschema: routine/v1\\nid: daily-source-scout\\ndescription: |\\n Daily routine that runs the source-scout operator to discover new\\n candidate sources across configured external feeds. Discovered sources\\n are archived under sources/ and rows appended to _candidates.yaml.\\nversion: \\\"1.0.0\\\"\\nschedule:\\n kind: cron\\n cron: \\\"0 9 * * *\\\"\\n timezone: \\\"UTC\\\"\\n catchup: skip\\ntarget:\\n workflow: ingest-source\\n inputs:\\n feeds: [tiktok-curated, hubspot-blog, reddit-marketing]\\n maxItemsPerRun: 50\\nretry:\\n max_attempts: 3\\n backoff: exponential\\non_failure:\\n create_work_item: true\\n fire_event: corpus.scout.failed\\nfires_events:\\n - corpus.scout.completed\\n - corpus.candidate.discovered\\nenabled: true\\ntags: [corpus, scout, daily]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Daily Source Scout\\n\\nRuns every morning at 09:00 UTC. Scouts external feeds for new candidate sources, archives them, and appends to `_candidates.yaml`. The candidate event downstream triggers `analyze-candidate` workflow.\\n\",\n \"routines/monthly-eval-gap-finder/ROUTINE.md\": \"---\\nschema: routine/v1\\nid: monthly-eval-gap-finder\\ndescription: |\\n Monthly gap-finder run — reads the last 30 days of eval-case\\n failures, clusters them, opens corpus-gap items for the scout.\\n Closes loop #3 by turning observed weaknesses into next-harvest\\n priorities.\\nversion: \\\"1.0.0\\\"\\nschedule:\\n kind: cron\\n cron: \\\"0 8 1 * *\\\"\\n timezone: \\\"UTC\\\"\\n catchup: skip\\ntarget:\\n workflow: detect-corpus-gaps\\n inputs:\\n windowDays: 30\\n minOccurrences: 3\\nretry:\\n max_attempts: 2\\n backoff: exponential\\non_failure:\\n create_work_item: true\\n fire_event: corpus.gap-finder.failed\\nfires_events:\\n - corpus.gap-finder.completed\\n - corpus.gap.opened\\nenabled: true\\ntags: [corpus, gaps, monthly]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Monthly Eval Gap Finder\\n\\nFirst day of each month, 08:00 UTC. Reads aggregated eval-case results, clusters failure modes, opens `corpus-gap/*/ITEM.md` items.\\n\",\n \"routines/quarterly-archive-cleanup/ROUTINE.md\": \"---\\nschema: routine/v1\\nid: quarterly-archive-cleanup\\ndescription: |\\n Quarterly storage hygiene — migrate sources older than 6 months\\n to sources/cold/, hard-delete archived entries past their\\n retention window, prune orphaned _candidates.yaml rows.\\nversion: \\\"1.0.0\\\"\\nschedule:\\n kind: cron\\n cron: \\\"0 6 1 1,4,7,10 *\\\"\\n timezone: \\\"UTC\\\"\\n catchup: skip\\ntarget:\\n workflow: corpus-archive-cleanup\\nretry:\\n max_attempts: 1\\n backoff: fixed\\non_failure:\\n create_work_item: true\\n fire_event: corpus.archive-cleanup.failed\\nfires_events:\\n - corpus.archive-cleanup.completed\\nenabled: true\\ntags: [corpus, archive, quarterly, maintenance]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Quarterly Archive Cleanup\\n\\nFirst day of every quarter at 06:00 UTC. Migrates aging sources to cold storage (still under `sources/cold/` for AIP-10 path resolvability), and prunes terminal-status candidates beyond retention.\\n\",\n \"routines/weekly-corpus-curation/ROUTINE.md\": \"---\\nschema: routine/v1\\nid: weekly-corpus-curation\\ndescription: |\\n Weekly curator pass — review the human-review queue, promote\\n what's ready, deprecate what's stale, archive playbooks whose\\n shadow eval has converged.\\nversion: \\\"1.0.0\\\"\\nschedule:\\n kind: cron\\n cron: \\\"0 10 * * 1\\\"\\n timezone: \\\"UTC\\\"\\n catchup: skip\\ntarget:\\n workflow: review-candidate\\n inputs:\\n mode: batch\\n maxItems: 50\\nretry:\\n max_attempts: 2\\n backoff: exponential\\non_failure:\\n create_work_item: true\\n fire_event: corpus.curation.weekly-failed\\nfires_events:\\n - corpus.curation.weekly-completed\\nenabled: true\\ntags: [corpus, curation, weekly]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Weekly Corpus Curation\\n\\nMonday 10:00 UTC. The curator runs through the corpus-review queue, promotes approved candidates, deprecates stale entries. Pairs with `daily-source-scout` (which fills the pipeline).\\n\",\n \"sources/fresh/tiktok-hook-2026-05.md\": \"---\\nschema: knowledge.source/v1\\nid: tiktok-hook-2026-05\\npath: sources/fresh/tiktok-hook-2026-05.md\\ntitle: TikTok contrarian hook example — May 2026\\ncaptured_at: \\\"2026-05-22T14:30:00Z\\\"\\ncaptured_by: source-scout\\ncontent_hash: sha256:abc1234567890def1234567890abcdef1234567890abcdef1234567890abcdef\\nauthority: secondary\\nlanguage: en\\ntags: [tiktok, hook, short-form, contrarian]\\nmetadata:\\n corpus:\\n originalUrl: https://example.com/tiktok/123\\n archiveTier: hot\\n archivedBy: source-scout\\n snapshotPath: sources/fresh/tiktok-hook-2026-05.snapshot.mhtml\\n---\\n\\n# TikTok hook — \\\"Most marketers are doing X. Here's why they're wrong.\\\"\\n\\nCaptured from a top-performing TikTok in May 2026. The hook contradicts a widely-held belief, generates 8x average engagement on the channel, and converts at 3x baseline for the SaaS product mentioned.\\n\\n## Transcript\\n> Everyone says you should write listicles. But the truth is — and this took me three years to figure out — every viral piece I've ever written started with one specific contradiction…\\n\\n## Performance\\n- Views: 1.2M\\n- Engagement rate: 18.4% (channel avg: 2.3%)\\n- CTR to product: 4.1% (channel avg: 0.8%)\\n\",\n \"workflows/analyze-candidate/WORKFLOW.md\": \"---\\nname: Analyze Corpus Candidate\\nid: analyze-candidate\\ndescription: |\\n Convert a discovered corpus candidate into an analyzed ITEM.md with\\n expert analysis, quality score, and risk score. Triggered by the\\n source-scout when it appends a row to _candidates.yaml.\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n required: [candidateId, sourcePath]\\n properties:\\n candidateId: { type: string, pattern: \\\"^[a-z0-9][a-z0-9-]*$\\\" }\\n sourcePath: { type: string }\\noutputs:\\n type: object\\n required: [itemPath, status]\\n properties:\\n itemPath: { type: string }\\n status: { type: string, enum: [analyzed, rejected, needs-work] }\\n qualityScore: { type: number }\\n riskScore: { type: number }\\nsteps:\\n - id: load-source\\n kind: tool\\n tool: knowledge.read_source\\n name: Load source bytes from sources/\\n inputs: { type: object, properties: { sourceId: { type: string } } }\\n next: analyze\\n - id: analyze\\n kind: tool\\n tool: marketing-analyst.analyze\\n name: Run marketing-analyst operator over the source\\n next: score\\n - id: score\\n kind: tool\\n tool: quality-reviewer.score\\n name: Compute quality + risk scores\\n next: gate\\n - id: gate\\n kind: branch\\n name: Decide promotionMode (auto vs human)\\n description: Check auto-promote gate against KNOWLEDGE.md.metadata.corpus.autoPromote\\n branches:\\n - { when: \\\"output.qualityScore >= 4.2 && output.riskScore <= 1.5\\\", next: \\\"auto-promote\\\" }\\n - { when: \\\"true\\\", next: \\\"human-review\\\" }\\n - id: auto-promote\\n kind: tool\\n tool: corpus-curator-promote\\n name: Promote to AIP-10 entry\\n - id: human-review\\n kind: approval\\n name: Queue for human curator\\n prompt: Review and approve or reject this candidate.\\n approvers:\\n - { role: corpus-curator }\\ntags: [corpus, workflow, analysis]\\nmetadata:\\n corpus:\\n domain: marketing\\n triggeredBy: source-scout\\n---\\n\\n# Analyze Candidate workflow\\n\\nConverts a discovered candidate into an analyzed ITEM.md. The marketing-analyst operator runs the actual analysis; this workflow orchestrates the pipeline (load → analyze → score → gate).\\n\",\n \"workflows/detect-corpus-gaps/WORKFLOW.md\": \"---\\nname: Detect corpus gaps\\nid: detect-corpus-gaps\\ndescription: |\\n Scan the last 30 days of eval-case failures, cluster by\\n weakness type, open corpus-gap items with priority. Drives the\\n scout's next harvest.\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n properties:\\n windowDays: { type: integer, minimum: 1, maximum: 365, default: 30 }\\n minOccurrences: { type: integer, minimum: 1, default: 3 }\\noutputs:\\n type: object\\n required: [gapsOpened]\\n properties:\\n gapsOpened: { type: integer }\\n clusters: { type: array }\\nsteps:\\n - id: load-failures\\n kind: tool\\n tool: corpus-load-eval-failures\\n name: Load last-N-days eval failures\\n - id: cluster\\n kind: tool\\n tool: gap-finder-cluster\\n name: Cluster failures by weakness type + recurrence\\n - id: open-gaps\\n kind: map\\n over: \\\"steps.cluster.output.clusters\\\"\\n steps:\\n - { id: open, kind: tool, tool: corpus-open-gap }\\ntags: [corpus, gaps]\\nmetadata:\\n corpus:\\n domain: marketing\\n triggeredBy: gap-finder\\n---\\n\\n# Detect corpus gaps workflow\\n\\nRuns monthly. Reads eval-case results, clusters failures, opens `corpus-gap/*/ITEM.md` items for the scout to read.\\n\",\n \"workflows/evaluate-agent-output/WORKFLOW.md\": \"---\\nname: Evaluate agent output\\nid: evaluate-agent-output\\ndescription: |\\n Score an agent output against a rubric via the pluggable\\n IEvaluator (M9). Wins seed flagCorpusLearning candidates;\\n losses feed detect-corpus-gaps.\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n required: [prompt, response, rubricSlug]\\n properties:\\n prompt: { type: string }\\n response: { type: string }\\n rubricSlug: { type: string }\\n operatorRef: { type: string }\\n conversationId: { type: string }\\n retrievedHits:\\n type: array\\n items: { type: object }\\noutputs:\\n type: object\\n required: [score]\\n properties:\\n score: { type: number }\\n dimensions: { type: object }\\n rationale: { type: string }\\n routedAs: { type: string, enum: [win, loss, neutral] }\\nsteps:\\n - id: evaluate\\n kind: tool\\n tool: evaluator-evaluate\\n name: Run IEvaluator against the rubric\\n - id: classify\\n kind: branch\\n name: Route win / loss / neutral\\n branches:\\n - { when: \\\"output.score >= 0.7\\\", next: \\\"as-win\\\" }\\n - { when: \\\"output.score < 0.4\\\", next: \\\"as-loss\\\" }\\n - { when: \\\"true\\\", next: \\\"as-neutral\\\" }\\n - id: as-win\\n kind: tool\\n tool: flagCorpusLearning\\n name: Seed a candidate from the winning trace\\n - id: as-loss\\n kind: tool\\n tool: corpus-record-eval-failure\\n name: Add to the eval-failure log for gap-finder\\n - id: as-neutral\\n kind: tool\\n tool: corpus-log-event\\n name: Log neutral outcome (no candidate spawn)\\ntags: [corpus, eval, telemetry]\\nmetadata:\\n corpus:\\n domain: marketing\\n requires:\\n pluggable: [evaluator]\\n---\\n\\n# Evaluate agent output workflow\\n\\nCloses loop #3 (retrieval quality). Every agent output that's worth evaluating runs through this. Win / loss / neutral routing feeds the curation queue + the gap finder.\\n\",\n \"workflows/ingest-source/WORKFLOW.md\": \"---\\nname: Ingest source\\nid: ingest-source\\ndescription: |\\n Fetch + hash + dedup + archive a single source. Output: a new\\n candidate row in _candidates.yaml (or no-op if duplicate).\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n required: [sourceUrl]\\n properties:\\n sourceUrl: { type: string }\\n category: { type: string, enum: [fresh, classic, competitors, internal, performance] }\\noutputs:\\n type: object\\n required: [outcome]\\n properties:\\n outcome: { type: string, enum: [archived, duplicate, rejected] }\\n sourceId: { type: string }\\n candidateId: { type: string }\\nsteps:\\n - id: fetch\\n kind: tool\\n tool: web-fetch\\n name: Fetch source content\\n - id: hash\\n kind: tool\\n tool: hash-content\\n name: Compute sha256 content_hash\\n - id: dedup\\n kind: branch\\n name: Dedup against existing sources\\n branches:\\n - { when: \\\"output.duplicate === true\\\", next: \\\"done-dup\\\" }\\n - { when: \\\"true\\\", next: \\\"archive\\\" }\\n - id: archive\\n kind: tool\\n tool: corpus-archive-source\\n name: Write source frontmatter + body to sources/<category>/<slug>.md\\n - id: create-candidate\\n kind: tool\\n tool: createCorpusCandidate\\n name: Append discovered row to _candidates.yaml\\n - id: done-dup\\n kind: tool\\n tool: corpus-log-event\\n name: Log dedup hit (no-op outcome)\\ntags: [corpus, ingest, scout]\\nmetadata:\\n corpus:\\n domain: marketing\\n triggeredBy: source-scout\\n---\\n\\n# Ingest source workflow\\n\\nStep 1 of the corpus loop. Single-source entry point. Called by `daily-source-scout` once per discovered URL.\\n\",\n \"workflows/promote-corpus-item/WORKFLOW.md\": \"---\\nname: Promote corpus item\\nid: promote-corpus-item\\ndescription: |\\n Lift an approved candidate into a published AIP-10 entry. Writes\\n the entry file, regenerates _index.md, ships chunks to the\\n backing engine, appends a promotion event. Wraps the kit's\\n CorpusPromoter.promote().\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n required: [candidateId, entrySlug, entryKind, entryPath, frontmatter, body]\\n properties:\\n candidateId: { type: string }\\n entrySlug: { type: string }\\n entryKind: { type: string, enum: [principle, example, pattern, critique, summary, timeline, playbook] }\\n entryPath: { type: string }\\n frontmatter: { type: object }\\n body: { type: string }\\n bypassGate: { type: boolean }\\noutputs:\\n type: object\\n required: [entryPath, gatePassed]\\n properties:\\n entryPath: { type: string }\\n versionToken: { type: string }\\n chunkCount: { type: integer }\\n gatePassed: { type: boolean }\\n bypassed: { type: boolean }\\nsteps:\\n - id: promote\\n kind: tool\\n tool: promoteCorpusCandidate\\n name: Atomic promote (lock + write + index + chunks + event)\\ntags: [corpus, promote]\\nmetadata:\\n corpus:\\n domain: marketing\\n triggeredBy: corpus-curator\\n---\\n\\n# Promote corpus item workflow\\n\\nStep 4 of the corpus loop. Single-step wrapper for callers that want the workflow shape; the underlying `CorpusPromoter` does the multi-file transaction.\\n\",\n \"workflows/review-candidate/WORKFLOW.md\": \"---\\nname: Review analyzed candidate\\nid: review-candidate\\ndescription: |\\n Score an analyzed candidate (quality + risk), set promotionMode,\\n route to auto-promote or human-review queue.\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n required: [candidateId]\\n properties:\\n candidateId: { type: string }\\noutputs:\\n type: object\\n required: [decision]\\n properties:\\n decision: { type: string, enum: [auto-promote, queue-review, reject] }\\n qualityScore: { type: number }\\n riskScore: { type: number }\\nsteps:\\n - id: load\\n kind: tool\\n tool: corpus-load-candidate\\n name: Load candidate ITEM.md\\n - id: score\\n kind: tool\\n tool: quality-reviewer-score\\n name: Compute qualityScore + riskScore via reviewer operator\\n - id: gate\\n kind: branch\\n name: Auto-promote gate\\n branches:\\n - { when: \\\"output.qualityScore >= 4.2 && output.riskScore <= 1.5\\\", next: \\\"auto-promote\\\" }\\n - { when: \\\"output.qualityScore < 2.0 || output.riskScore > 3.0\\\", next: \\\"reject\\\" }\\n - { when: \\\"true\\\", next: \\\"queue-review\\\" }\\n - id: auto-promote\\n kind: tool\\n tool: promoteCorpusCandidate\\n name: Promote without human gate\\n - id: queue-review\\n kind: tool\\n tool: corpus-route-to-review\\n name: Move ITEM.md to corpus-review collection\\n - id: reject\\n kind: tool\\n tool: corpus-log-event\\n name: Log corpus.candidate.rejected with reason\\ntags: [corpus, review]\\nmetadata:\\n corpus:\\n domain: marketing\\n triggeredBy: marketing-analyst\\n---\\n\\n# Review candidate workflow\\n\\nStep 3 of the corpus loop (after `analyze-candidate`). Reviewer scores and routes.\\n\",\n \"workflows/update-corpus-index/WORKFLOW.md\": \"---\\nname: Update corpus index\\nid: update-corpus-index\\ndescription: |\\n Regenerate _index.md (faceted catalog) from the current set of\\n active entries. Triggered on promotion, deprecation, or\\n status changes; can also run on demand.\\nversion: \\\"1.0.0\\\"\\ninputs:\\n type: object\\n properties:\\n reason: { type: string, enum: [promoted, deprecated, archived, manual] }\\noutputs:\\n type: object\\n required: [entryCount]\\n properties:\\n entryCount: { type: integer }\\n indexBytes: { type: integer }\\nsteps:\\n - id: snapshot\\n kind: tool\\n tool: corpus-read-snapshot\\n name: Read current workspace snapshot\\n - id: regen\\n kind: tool\\n tool: corpus-regen-index\\n name: Write _index.md from active entries (kind facets)\\n - id: log\\n kind: tool\\n tool: corpus-log-event\\n name: Log corpus.entry.indexed event\\ntags: [corpus, index]\\nmetadata:\\n corpus:\\n domain: marketing\\n---\\n\\n# Update corpus index workflow\\n\\nMaintenance workflow — keeps `_index.md` in sync with the entries directory. The promote workflow inlines this; standalone version is for drift recovery.\\n\",\n})\n","/**\n * Marketing corpus preset.\n *\n * Pure TS data — `files` is inlined from the M0 fixture workspace at\n * build time via `scripts/gen-marketing.mjs`. The M0 conformance test\n * proves every file validates against the actual AgentProto JSON\n * Schemas, so a host that writes these to disk gets a known-good\n * starter workspace.\n *\n * Usage:\n *\n * import { MarketingCorpusPreset } from \"@agentproto/corpus-presets/marketing\"\n * for (const [rel, content] of Object.entries(MarketingCorpusPreset.files)) {\n * await fs.writeFile(path.join(workspaceRoot, rel), content)\n * }\n */\n\nimport type { CorpusPreset } from \"@agentproto/corpus\"\nimport { MARKETING_PRESET_FILES } from \"./files.js\"\n\nexport const MarketingCorpusPreset: CorpusPreset = Object.freeze({\n slug: \"marketing\",\n title: \"Marketing Expert Corpus\",\n description:\n \"Autonomous marketing knowledge — principles, patterns, critiques, playbooks. Composes AIP-10/12/18/9/15/41 into a closed-loop improvement system.\",\n files: MARKETING_PRESET_FILES,\n})\n\n// Re-export the raw file map for callers that want it directly.\nexport { MARKETING_PRESET_FILES }\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentproto/corpus-presets",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "@agentproto/corpus-presets — catalog of starter workspaces for the AIP-10 corpus runtime. Subpath exports per vertical (marketing, sales, …). Each preset is pure TS data — host iterates `files` and writes via FsPort. Mirrors @agentproto/role-catalog.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentproto",
|
|
7
|
+
"corpus",
|
|
8
|
+
"presets",
|
|
9
|
+
"starter",
|
|
10
|
+
"aip-10"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://agentproto.sh/docs/corpus",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/agentproto/ts",
|
|
16
|
+
"directory": "packages/corpus-presets"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/agentproto/ts/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "dist/index.mjs",
|
|
24
|
+
"module": "dist/index.mjs",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.mjs",
|
|
30
|
+
"default": "./dist/index.mjs"
|
|
31
|
+
},
|
|
32
|
+
"./marketing": {
|
|
33
|
+
"types": "./dist/marketing/index.d.ts",
|
|
34
|
+
"import": "./dist/marketing/index.mjs",
|
|
35
|
+
"default": "./dist/marketing/index.mjs"
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"agentproto-corpus-preset": {
|
|
40
|
+
"schema": "agentproto/corpus-preset/v1",
|
|
41
|
+
"presets": [
|
|
42
|
+
{
|
|
43
|
+
"slug": "marketing",
|
|
44
|
+
"entry": "./dist/marketing/index.mjs",
|
|
45
|
+
"export": "MarketingCorpusPreset",
|
|
46
|
+
"description": "Marketing knowledge corpus — principles, patterns, critiques, playbooks. Composes AIP-10/12/18/9/15/41 into a closed-loop improvement system."
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE"
|
|
54
|
+
],
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"sideEffects": false,
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@agentproto/corpus": "0.1.0-alpha.1"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^25.6.2",
|
|
64
|
+
"tsup": "^8.5.1",
|
|
65
|
+
"typescript": "^5.9.3",
|
|
66
|
+
"vitest": "^3.2.4",
|
|
67
|
+
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"predev": "node scripts/gen-marketing.mjs",
|
|
71
|
+
"dev": "tsup --watch",
|
|
72
|
+
"prebuild": "node scripts/gen-marketing.mjs",
|
|
73
|
+
"build": "tsup",
|
|
74
|
+
"clean": "rm -rf dist src/marketing/files.ts",
|
|
75
|
+
"precheck-types": "node scripts/gen-marketing.mjs",
|
|
76
|
+
"check-types": "tsc --noEmit",
|
|
77
|
+
"pretest": "node scripts/gen-marketing.mjs",
|
|
78
|
+
"test": "vitest run --passWithNoTests",
|
|
79
|
+
"gen:marketing": "node scripts/gen-marketing.mjs"
|
|
80
|
+
}
|
|
81
|
+
}
|