greprag 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/inbox-watch.d.ts +6 -0
- package/dist/commands/inbox-watch.js +12 -1
- package/dist/commands/inbox-watch.js.map +1 -1
- package/dist/commands/init.js +51 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/hook.js +37 -10
- package/dist/hook.js.map +1 -1
- package/dist/index.js +90 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/content-advisor/SKILL.md +65 -0
- package/skill/content-advisor/docs/data-sources.md +51 -0
- package/skill/content-advisor/docs/decision-rules.md +114 -0
- package/skill/content-advisor/docs/episodic-memory-queries.md +116 -0
- package/skill/content-advisor/docs/handoff-contract.md +91 -0
- package/skill/content-advisor/docs/output-format.md +89 -0
- package/skill/content-advisor/docs/setup.md +125 -0
- package/skill/content-advisor/docs/writing-activity.md +89 -0
- package/skill/{SKILL.md → greprag/SKILL.md} +242 -15
- package/skill/templates/agent-coordination.md +253 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Handoff Contract
|
|
2
|
+
|
|
3
|
+
The content-advisor's output ends at a brief. The writer master takes it from there. Source of truth: `C:/openwriter/skills/WRITER-CONVENTION.md` — read it before changing anything in this doc.
|
|
4
|
+
|
|
5
|
+
## v1 mode: list-only
|
|
6
|
+
|
|
7
|
+
Advisor produces the opportunity list with the exact slash-command in each item's `Handoff` field. User reads, picks, runs the command manually.
|
|
8
|
+
|
|
9
|
+
**Why list-only:** auto-invocation creates two problems early: (1) the user can't review the angle before the writer commits to it, and (2) if the writer needs clarifying input, the advisor isn't in the call to provide it. List-only keeps the human in the loop where judgment matters most — angle selection.
|
|
10
|
+
|
|
11
|
+
Future v2: when the user picks an opportunity by number ("do #3"), advisor invokes the chosen writer with the brief.
|
|
12
|
+
|
|
13
|
+
## Brief shape (per WRITER-CONVENTION.md §4)
|
|
14
|
+
|
|
15
|
+
The slash-command serializes a brief object:
|
|
16
|
+
|
|
17
|
+
| Field | Required | Where it comes from in advisor |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `source_material` | yes | `--source memory:<uuid>` for ship-event / daily / weekly OR `--source doc:<id>` for OpenWriter draft OR `--source inline:"topic phrase"` as last resort |
|
|
20
|
+
| `angle` | no but advisor always provides | `--angle "<phrase>"` derived from source content's first informative clause |
|
|
21
|
+
| `sub_form` | yes | Positional arg per writer (`/x-writer thread`, `/blog-writer long`, `/newsletter-writer issue`) |
|
|
22
|
+
| `venture` | yes when relevant | `--venture <slug>` matches the venture in `docs/ventures.md` |
|
|
23
|
+
| `voice` | no | Defaults to venture's authors-voice profile; advisor doesn't override |
|
|
24
|
+
|
|
25
|
+
## Per-writer command shape
|
|
26
|
+
|
|
27
|
+
### `/x-writer`
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
/x-writer <sub_form> --source <ref> --venture <slug> --angle "<phrase>"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Sub-forms: `thread` | `single` | `article` | `comic` | `reply` | `quote`.
|
|
34
|
+
|
|
35
|
+
Advisor picks sub-form by:
|
|
36
|
+
- Source is a fresh ship-event with rich content → `thread` or `article`
|
|
37
|
+
- Source is a pattern across 3+ dailies → `thread`
|
|
38
|
+
- Source is a single sharp observation → `single`
|
|
39
|
+
- Visual narrative or comparative → `comic`
|
|
40
|
+
- `reply` / `quote` are out of scope for the advisor (those belong to `/x-strategy`)
|
|
41
|
+
|
|
42
|
+
### `/blog-writer`
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
/blog-writer <sub_form> --source <ref> --venture <slug> --angle "<phrase>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Sub-forms: `long` | `short` | `tutorial` | `announcement`.
|
|
49
|
+
|
|
50
|
+
Advisor picks:
|
|
51
|
+
- Source is a ship-event with code-level detail → `announcement` or `tutorial`
|
|
52
|
+
- Source is a weekly through-line → `long`
|
|
53
|
+
- Source is one focused topic → `short`
|
|
54
|
+
|
|
55
|
+
### `/newsletter-writer`
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
/newsletter-writer <sub_form> --source <ref> --venture <slug> --angle "<phrase>"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Sub-forms: `issue` | `supplemental` | `archive`.
|
|
62
|
+
|
|
63
|
+
Default for cadence-floor opportunities: `issue`. Use `supplemental` only when an issue already shipped this week but a hot ship-event landed after.
|
|
64
|
+
|
|
65
|
+
## Return contract (what the writer reports back)
|
|
66
|
+
|
|
67
|
+
Per WRITER-CONVENTION.md §5:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"status": "draft-ready" | "needs-input" | "blocked",
|
|
72
|
+
"artifact": { "doc_id": "...", "workspace_id": "..." },
|
|
73
|
+
"next_steps": ["/polish", "/schedule", "/announce"],
|
|
74
|
+
"notes": "..."
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
In v1 the advisor doesn't observe this directly (user invokes the writer themselves). When v2 lands, the advisor will pass `notes` back to the user verbatim and the suggested `next_steps` become the next round of advisor proposals.
|
|
79
|
+
|
|
80
|
+
## What the advisor does NOT do
|
|
81
|
+
|
|
82
|
+
- **Generate the slash-command on behalf of the user and run it.** v1 prints; user runs.
|
|
83
|
+
- **Pick voice profile.** Default is venture's profile per `/authors-voice`.
|
|
84
|
+
- **Schedule or polish.** Those are downstream skills (`/schedule`, `/polish`); writer's `next_steps` surfaces them; user chains.
|
|
85
|
+
- **Fall back to inline-topic.** Always prefer `memory:<uuid>` or `doc:<id>`. Only use `inline:` for cadence-floor opportunities where no specific memory row drives the pitch.
|
|
86
|
+
|
|
87
|
+
## Anti-patterns
|
|
88
|
+
|
|
89
|
+
- Calling a writer for a venture not in `channels_per_venture` for that channel. Setup config guards this; if a venture has only `["x"]`, do not propose blog or newsletter opportunities for it.
|
|
90
|
+
- Stuffing multiple ships into one brief. One brief = one source. If three ships cluster on a theme, that's a weekly-pattern opportunity, not a multi-source brief.
|
|
91
|
+
- Inventing a sub-form not in the writer's enum. Per WRITER-CONVENTION.md §4: if a needed sub-form doesn't exist, that's a signal to propose adding it to the writer — don't improvise on the advisor side.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Output Format
|
|
2
|
+
|
|
3
|
+
What the user sees when `/content-advisor` finishes. Plain English. Top-line first, then ranked list, then optional "consider later" tier.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
# Content Advisor — <YYYY-MM-DD>
|
|
9
|
+
|
|
10
|
+
**Top of the queue:** <one-sentence pitch for #1 with the venture and channel>
|
|
11
|
+
|
|
12
|
+
## Act now (final_rank ≥ 6)
|
|
13
|
+
|
|
14
|
+
### 1. <Channel> — <Venture> — <short angle>
|
|
15
|
+
- **Why now:** <one sentence>
|
|
16
|
+
- **Source:** <memory_id excerpt | doc_id title | "recombine: <topic>">
|
|
17
|
+
- **Handoff:** `/<channel>-writer <sub_form> --source <source_ref> --venture <venture> --angle "<angle>"`
|
|
18
|
+
|
|
19
|
+
### 2. ...
|
|
20
|
+
|
|
21
|
+
## Consider later (final_rank 3–5)
|
|
22
|
+
|
|
23
|
+
### N. ...
|
|
24
|
+
|
|
25
|
+
## Notes
|
|
26
|
+
|
|
27
|
+
- <warnings: missing focus.md, X data unavailable, fallback turns used for venture Y, etc.>
|
|
28
|
+
- <ventures excluded as backburner>
|
|
29
|
+
- <ships that triggered an opportunity already in flight as an OpenWriter draft — listed here so the user knows the system noticed>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Per-entry fields (rendered, not raw JSON in v1)
|
|
33
|
+
|
|
34
|
+
| Field | Source | Example |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| Channel | candidate.channel | `x: thread`, `blog: long`, `newsletter: issue` |
|
|
37
|
+
| Venture | candidate.venture | `paybot`, `tournament-male`, `personal` |
|
|
38
|
+
| Angle | derived from source content (first informative phrase) | "Upgrade-flow rebuild lessons" |
|
|
39
|
+
| Why now | rule_triggered + tier | "Shipped 9d ago, no content yet · Tier 1 venture" |
|
|
40
|
+
| Source | memory_id (preferred) / doc_id / "cadence-recombine" | `memory:7f3a...` |
|
|
41
|
+
| Handoff | slash-command per WRITER-CONVENTION.md | `/x-writer thread --source memory:7f3a-... --venture paybot --angle "..."` |
|
|
42
|
+
|
|
43
|
+
## Ranking display
|
|
44
|
+
|
|
45
|
+
Items are numbered globally (1-N), not per-tier. The "Act now" / "Consider later" split is a cut on `final_rank ≥ 6`. Cap total at 10 items in v1.
|
|
46
|
+
|
|
47
|
+
## When the list is empty
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
# Content Advisor — <date>
|
|
51
|
+
|
|
52
|
+
No opportunities surfaced.
|
|
53
|
+
|
|
54
|
+
This usually means one of:
|
|
55
|
+
- All recent ships are already covered (good — you're caught up)
|
|
56
|
+
- All channels are within their cadence floor (good — you're current)
|
|
57
|
+
- GrepRAG has no recent activity (write something, ship something)
|
|
58
|
+
|
|
59
|
+
Specific signal:
|
|
60
|
+
- Ventures scanned: <N>
|
|
61
|
+
- Ships in window: <N>
|
|
62
|
+
- Open in-flight drafts: <N>
|
|
63
|
+
- Channels within cadence: <list>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Empty is a valid state — surface why explicitly so the user knows the advisor ran cleanly.
|
|
67
|
+
|
|
68
|
+
## When data is degraded
|
|
69
|
+
|
|
70
|
+
Lead with a Notes block at the top before the queue, naming exactly what's missing:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
**Degraded run** — operating with partial data:
|
|
74
|
+
- focus.md missing → tier prioritization disabled
|
|
75
|
+
- X recent posts unavailable → X cadence-floor rule skipped
|
|
76
|
+
- Project `xyz` returned 5xx → excluded this pass
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then the list as normal. The user makes a judgment call on whether to act on a degraded ranking.
|
|
80
|
+
|
|
81
|
+
## What we deliberately don't include in v1
|
|
82
|
+
|
|
83
|
+
- Engagement predictions ("this will get N views")
|
|
84
|
+
- Auto-scheduling slot picks
|
|
85
|
+
- Image suggestions
|
|
86
|
+
- Polishing scores
|
|
87
|
+
- Multi-step plans ("first do A, then B, then C")
|
|
88
|
+
|
|
89
|
+
The advisor proposes the next thing. The writer ships it. The user decides which one.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Setup — First-Run Gateway
|
|
2
|
+
|
|
3
|
+
The advisor's first invocation enters bootstrap. Setup runs once, written to a config file, then subsequent invocations skip directly to the standard protocol.
|
|
4
|
+
|
|
5
|
+
## Portfolio root resolution
|
|
6
|
+
|
|
7
|
+
Resolution order:
|
|
8
|
+
|
|
9
|
+
1. Env var `CONTENT_ADVISOR_ROOT`
|
|
10
|
+
2. Config file `~/.claude/content-advisor.json` with `{ "portfolio_root": "/abs/path" }`
|
|
11
|
+
3. Marker file scan up the cwd tree — looks for `docs/ventures.md` and `docs/strategy/focus.md`
|
|
12
|
+
4. Fallback default: `C:/orchestrator`
|
|
13
|
+
5. None applicable → ask user, save to config
|
|
14
|
+
|
|
15
|
+
The advisor never operates against an unresolved portfolio root.
|
|
16
|
+
|
|
17
|
+
## Setup flow
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
/content-advisor (no config detected)
|
|
21
|
+
↓
|
|
22
|
+
[Step 1] Locate portfolio root
|
|
23
|
+
→ default C:/orchestrator; confirm or override
|
|
24
|
+
→ save to ~/.claude/content-advisor.json
|
|
25
|
+
↓
|
|
26
|
+
[Step 2] Check GrepRAG
|
|
27
|
+
→ command -v greprag → exits 0?
|
|
28
|
+
→ test -n "$GREPRAG_API_KEY"? (source ~/.env if missing)
|
|
29
|
+
→ greprag discover --json → returns ≥1 project?
|
|
30
|
+
→ any failure → walk user through /greprag setup
|
|
31
|
+
↓
|
|
32
|
+
[Step 3] Verify writer skills present
|
|
33
|
+
→ ~/.claude/skills/x-writer/SKILL.md exists?
|
|
34
|
+
→ ~/.claude/skills/blog-writer/SKILL.md exists?
|
|
35
|
+
→ ~/.claude/skills/newsletter-writer/SKILL.md exists?
|
|
36
|
+
→ any missing → "Run /skill-publish from C:/openwriter to install the writer masters."
|
|
37
|
+
↓
|
|
38
|
+
[Step 4] Read WRITER-CONVENTION.md
|
|
39
|
+
→ C:/openwriter/skills/WRITER-CONVENTION.md (source of truth for handoff brief shape)
|
|
40
|
+
→ if absent, advisor still works but warns the contract is unverified
|
|
41
|
+
↓
|
|
42
|
+
[Step 4.5] Per-venture ICP (Ideal Customer Profile) derivation
|
|
43
|
+
→ For each venture in `project_to_venture`:
|
|
44
|
+
a) Search for an existing avatar / audience doc:
|
|
45
|
+
- OpenWriter workspaces with titles like "Audience", "Audience & Reader Journey", "Avatar", "ICP"
|
|
46
|
+
- The venture's marketing-site repo for `content/audience.md` or similar
|
|
47
|
+
- If found → store pointer in config under `icp_per_venture[venture]` as
|
|
48
|
+
`"openwriter:<docId>"` or `"file:<absolute-path>"`
|
|
49
|
+
b) If no doc exists, conduct a short interview (5-7 questions max):
|
|
50
|
+
- Who is the buyer? (one sentence)
|
|
51
|
+
- What's their current state? (the pain that brings them in)
|
|
52
|
+
- What do they pick up your content hoping for?
|
|
53
|
+
- What's the recognition shock they want? (their life mirrored back)
|
|
54
|
+
- What do they walk away with that's actionable this week?
|
|
55
|
+
- What's the failure mode of content that doesn't land?
|
|
56
|
+
- Optional: who do they trust today that you're competing with?
|
|
57
|
+
c) Write the interview output to `docs/icp/<venture>.md` in the portfolio
|
|
58
|
+
root and store the pointer in config.
|
|
59
|
+
→ Per-venture ICP is the demand-side spec the advisor reads at rank time
|
|
60
|
+
(see Rule 5 in `decision-rules.md`).
|
|
61
|
+
↓
|
|
62
|
+
[Step 5] Verify portfolio docs
|
|
63
|
+
→ docs/ventures.md, docs/strategy/focus.md present?
|
|
64
|
+
→ each missing → "Run /business-advisor to scaffold portfolio docs."
|
|
65
|
+
↓
|
|
66
|
+
[Step 6] Project ↔ venture mapping
|
|
67
|
+
→ greprag discover --json lists project names
|
|
68
|
+
→ match each to a venture umbrella (often 1:1; some ventures span multiple repos)
|
|
69
|
+
→ save to ~/.claude/content-advisor.json under `project_to_venture`
|
|
70
|
+
↓
|
|
71
|
+
[Step 7] Optional: per-venture cadence overrides
|
|
72
|
+
→ defaults in docs/decision-rules.md (X daily, newsletter weekly, blog 2×/mo)
|
|
73
|
+
→ user can override per venture in config under `cadence_overrides`
|
|
74
|
+
↓
|
|
75
|
+
[Step 8] Lock in
|
|
76
|
+
→ run one full pass, present opportunity list as the first output
|
|
77
|
+
→ confirm config persisted
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Config file format
|
|
81
|
+
|
|
82
|
+
`~/.claude/content-advisor.json`:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"portfolio_root": "C:/orchestrator",
|
|
87
|
+
"greprag_api_url": "https://api.greprag.com",
|
|
88
|
+
"project_to_venture": {
|
|
89
|
+
"openwriter": "openwriter",
|
|
90
|
+
"openwriter-site": "openwriter",
|
|
91
|
+
"openwriter-publish": "openwriter",
|
|
92
|
+
"paybot": "paybot",
|
|
93
|
+
"paybot-portal": "paybot",
|
|
94
|
+
"tournamentmale": "tournament-male",
|
|
95
|
+
"tm-book": "tournament-male",
|
|
96
|
+
"orchestrator": "personal"
|
|
97
|
+
},
|
|
98
|
+
"cadence_overrides": {
|
|
99
|
+
"openwriter": { "blog": "weekly" }
|
|
100
|
+
},
|
|
101
|
+
"icp_per_venture": {
|
|
102
|
+
"your-venture-here": "openwriter:doc_abc123",
|
|
103
|
+
"another-venture": "file:C:/path/to/portfolio/docs/icp/another-venture.md"
|
|
104
|
+
},
|
|
105
|
+
"channels_per_venture": {
|
|
106
|
+
"tournament-male": ["x", "newsletter", "blog"],
|
|
107
|
+
"paybot": ["x", "blog"],
|
|
108
|
+
"openwriter": ["x", "blog"],
|
|
109
|
+
"personal": ["x", "newsletter"]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`channels_per_venture` is the gate that prevents the advisor from proposing a blog post for a venture that has no blog. Default behavior when a venture is missing from this map: assume all three channels eligible.
|
|
115
|
+
|
|
116
|
+
## Re-running setup
|
|
117
|
+
|
|
118
|
+
Delete `~/.claude/content-advisor.json` and re-invoke. Or invoke with "redo setup step N" to re-enter one sub-flow.
|
|
119
|
+
|
|
120
|
+
## Failure modes
|
|
121
|
+
|
|
122
|
+
- **GrepRAG unreachable** → advisor cannot run. Setup blocks. Source-farmer rule needs ship-events; nothing else compensates.
|
|
123
|
+
- **Writer skills missing** → advisor still produces the list but flags handoff commands as unverified.
|
|
124
|
+
- **Portfolio docs missing** → tier prioritization disabled (all opportunities treated equal). Surface a warning.
|
|
125
|
+
- **No projects in greprag discover** → no source material. Advisor exits with "no episodic memory yet — write code, ship something, then check back."
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Writing Activity
|
|
2
|
+
|
|
3
|
+
The "what have we already written" stream. Pairs with episodic memory to drive the anti-duplication and cadence-floor rules.
|
|
4
|
+
|
|
5
|
+
## What we want to know per channel per venture
|
|
6
|
+
|
|
7
|
+
| Channel | The question | Source |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| X | When was the last post? What topics in last 7d? | x-strategy cache, or fxtwitter recent timeline |
|
|
10
|
+
| Blog | When was the last post? What topics in last 30d? | git log on the venture's marketing-site repo + frontmatter scan |
|
|
11
|
+
| Newsletter | When was the last issue sent? What was its through-line? | `mcp__openwriter__list_newsletter_issues` |
|
|
12
|
+
| OpenWriter drafts | What's in flight right now (un-shipped drafts touched in last 14d)? | `mcp__openwriter__list_documents` filtered by recency |
|
|
13
|
+
|
|
14
|
+
## Per-source procedure
|
|
15
|
+
|
|
16
|
+
### OpenWriter drafts (in-flight)
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
list_workspaces → for each workspace:
|
|
20
|
+
list_documents → filter where updatedAt > now-14d AND not in trash
|
|
21
|
+
→ for each doc: extract { id, title, workspace_name, updatedAt, tags }
|
|
22
|
+
→ infer channel from workspace name conventions (blog/newsletter/x/scratch)
|
|
23
|
+
OR from tags if present
|
|
24
|
+
→ infer venture from workspace name OR explicit metadata
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
These are CRUCIAL — an in-flight draft on topic X means "don't propose another piece on X." Surface them as "in progress" markers, not opportunities.
|
|
28
|
+
|
|
29
|
+
### Newsletter sends
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
list_newsletter_issues → sort desc by sentAt → take top 4
|
|
33
|
+
→ for each: { id, subject, sentAt, doc_id }
|
|
34
|
+
→ most recent sentAt → "newsletter last sent N days ago"
|
|
35
|
+
→ if N > cadence floor (default 7d): cadence-floor opportunity for newsletter
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Blog history
|
|
39
|
+
|
|
40
|
+
For each venture with a marketing-site repo (path resolved via `project_to_venture` config + scanning `ventures.md` for repo paths):
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
git -C <repo> log --since="30 days ago" --name-only --pretty=format:'%h|%ci|%s'
|
|
44
|
+
→ filter file changes to blog content paths (src/content/blog/**, content/posts/**, etc.)
|
|
45
|
+
→ group commits by post file → { post_file, first_commit_date, latest_commit_date }
|
|
46
|
+
→ most recent → "blog last shipped N days ago"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The blog-content path convention varies per site; try common patterns:
|
|
50
|
+
- `src/content/blog/**` (Astro)
|
|
51
|
+
- `content/posts/**` (Hugo)
|
|
52
|
+
- `_posts/**` (Jekyll)
|
|
53
|
+
- `app/blog/**/page.mdx` (Next.js)
|
|
54
|
+
|
|
55
|
+
If no match, fall back to scanning frontmatter (`---\npubDate:`) in any `.md`/`.mdx` file modified in window.
|
|
56
|
+
|
|
57
|
+
### X activity
|
|
58
|
+
|
|
59
|
+
Three options, in preference order:
|
|
60
|
+
|
|
61
|
+
1. **`/x-strategy` cache** — if present at a known path, parse the latest cached export.
|
|
62
|
+
2. **`mcp__x__*` tools** — if the X MCP is connected, query recent tweets for @Meta_Trav.
|
|
63
|
+
3. **fxtwitter timeline** — public, free; parse the user's recent posts.
|
|
64
|
+
|
|
65
|
+
What we want: list of `{ posted_at, text, type: thread|single|article|comic, topic_inferred }`. Topic inference is best-effort — a 30-word excerpt is enough to dedupe against memory rows.
|
|
66
|
+
|
|
67
|
+
## Output of this stream
|
|
68
|
+
|
|
69
|
+
A per-venture-per-channel activity map:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"tournament-male": {
|
|
74
|
+
"x": { "last_at": "2026-05-24T...", "topics_7d": ["six-week challenge", "kettlebell program"] },
|
|
75
|
+
"newsletter": { "last_at": "2026-05-19T...", "subject": "Week of May 19" },
|
|
76
|
+
"blog": { "last_at": "2026-04-30T...", "recent_topics": ["bible study cohort"] }
|
|
77
|
+
},
|
|
78
|
+
"paybot": {
|
|
79
|
+
"x": { "last_at": "2026-05-23T...", "topics_7d": ["upgrade flow ship"] },
|
|
80
|
+
"blog": { "last_at": "2026-05-10T...", "recent_topics": ["new pricing"] }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Plus a separate "in-flight drafts" list across all ventures (the OpenWriter list_documents output, filtered by recency).
|
|
86
|
+
|
|
87
|
+
## Failure tolerance
|
|
88
|
+
|
|
89
|
+
Any one of these sources can be down without breaking the advisor — they're enrichment. The minimum viable run is: greprag memory + ventures.md + focus.md. Everything else just sharpens ranking.
|