newsjack 0.1.5
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/.mcp.json +9 -0
- package/.newsjack-npm +1 -0
- package/COMMIT +1 -0
- package/LICENSE +21 -0
- package/README.md +133 -0
- package/VERSION +1 -0
- package/bin/newsjack +74 -0
- package/package.json +37 -0
- package/skills/.gitkeep +0 -0
- package/skills/ETHICS.md +265 -0
- package/skills/WHY-NOT-SPAM.md +257 -0
- package/skills/angle-generator/SKILL.md +224 -0
- package/skills/angle-generator/examples.md +517 -0
- package/skills/angle-generator/rubric.md +219 -0
- package/skills/coverage-tracker/SKILL.md +124 -0
- package/skills/coverage-tracker-setup/SKILL.md +84 -0
- package/skills/crisis-holding/SKILL.md +336 -0
- package/skills/crisis-holding/examples.md +302 -0
- package/skills/crisis-holding/rubric.md +218 -0
- package/skills/fact-check/SKILL.md +212 -0
- package/skills/fact-check/examples.md +195 -0
- package/skills/fact-check/rubric.md +228 -0
- package/skills/journalist-fit-check/SKILL.md +199 -0
- package/skills/journalist-fit-check/examples.md +271 -0
- package/skills/journalist-fit-check/rubric.md +251 -0
- package/skills/meanest-editor/SKILL.md +112 -0
- package/skills/meanest-editor/examples.md +331 -0
- package/skills/meanest-editor/rubric.md +275 -0
- package/skills/media-list-manager/SKILL.md +204 -0
- package/skills/media-list-manager/examples.md +88 -0
- package/skills/media-list-manager/rubric.md +67 -0
- package/skills/news-search/SKILL.md +56 -0
- package/skills/newsjack-detector/SKILL.md +286 -0
- package/skills/newsjack-detector/examples.md +118 -0
- package/skills/newsjack-detector/references/engine-cli.md +29 -0
- package/skills/newsjack-detector/references/harness-routing.md +38 -0
- package/skills/newsjack-detector/references/rss-feeds.json +106 -0
- package/skills/newsjack-detector/rubric.md +160 -0
- package/skills/newsjack-monitor-setup/SKILL.md +202 -0
- package/skills/newsjack-monitor-setup/examples.md +106 -0
- package/skills/newsjack-triage/SKILL.md +98 -0
- package/skills/newsworthiness-check/SKILL.md +179 -0
- package/skills/newsworthiness-check/examples.md +232 -0
- package/skills/newsworthiness-check/rubric.md +218 -0
- package/skills/pr-strategist/SKILL.md +304 -0
- package/skills/reactive-comment/SKILL.md +297 -0
- package/skills/reactive-comment/examples.md +284 -0
- package/skills/reactive-comment/rubric.md +280 -0
- package/skills/relevance-coarse-filter/SKILL.md +61 -0
- package/skills/story-origin-check/SKILL.md +160 -0
- package/skills/voice-extractor/SKILL.md +330 -0
- package/skills/voice-extractor/examples.md +227 -0
- package/skills/voice-extractor/rubric.md +251 -0
- package/skills-manifest.json +254 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Newsjack Detector Rubric
|
|
2
|
+
|
|
3
|
+
Use this rubric after the engine returns queued evidence. The engine exposes mechanical scores and `routing.queue_priority`; neither is a PR judgment.
|
|
4
|
+
|
|
5
|
+
The engine has two discovery lanes:
|
|
6
|
+
|
|
7
|
+
- `profile_relevance` - profile/topic/competitor queries. These catch highly relevant but sometimes minor stories.
|
|
8
|
+
- `major_news` - curated RSS/Atom feed items. These catch broader major news first, then require a stricter client-relevance judgment.
|
|
9
|
+
|
|
10
|
+
Do not treat a `major_news` item as pitchable because it is big. The client still needs standing and a journalist shape.
|
|
11
|
+
|
|
12
|
+
## Story Size
|
|
13
|
+
|
|
14
|
+
Use `story_size` to calibrate effort, not to approve a pitch. It is a deterministic media-attention proxy based on news-search publication metadata:
|
|
15
|
+
|
|
16
|
+
- log-scaled estimated monthly traffic
|
|
17
|
+
- domain authority
|
|
18
|
+
- coverage spread across independently surfaced domains
|
|
19
|
+
|
|
20
|
+
`major` or `high` story size means the opportunity may justify faster review. It does not compensate for stale timing, weak standing, or a bad journalist shape.
|
|
21
|
+
|
|
22
|
+
## Freshness Gate
|
|
23
|
+
|
|
24
|
+
For recurring scheduled output, the LLM `story-origin-check` recovers the first-public timestamp and canonical coverage, then the Go CLI `origin-apply` computes the freshness gate. News-search `published_at` values are reliable evidence for article timestamps and should be used to find candidate originals, but they are not alone a same-story or first-publication judgment.
|
|
25
|
+
|
|
26
|
+
Before assigning `pitch_now`, `develop_angle`, or `monitor`, inspect `freshness_gate.computed_status`:
|
|
27
|
+
|
|
28
|
+
- `fresh` - eligible for normal judgment.
|
|
29
|
+
- `fresh_new_development` - eligible, but the angle must be about the new development, not the older background story.
|
|
30
|
+
- `stale` - reject as stale.
|
|
31
|
+
- `unverified_no_corroboration`, `unverified_boundary`, `unverified_no_timestamp`, or missing - reject for recurring scheduled output. Track the reason: `unverified_no_corroboration` is a worker/pipeline miss (the clock may be fine, just under-sourced — re-runnable), while `unverified_boundary`/`unverified_no_timestamp` reflect genuinely thin evidence.
|
|
32
|
+
|
|
33
|
+
Do not reset the clock because an aggregator, syndication partner, or secondary outlet republished an older article.
|
|
34
|
+
|
|
35
|
+
When citing the story, prefer `story_origin.canonical_coverage_url` when present. It should be the major or most authoritative same-story coverage, such as a primary source, wire, major publisher, or recognized trade, instead of the small pickup that triggered retrieval.
|
|
36
|
+
|
|
37
|
+
## Verdict Ladder
|
|
38
|
+
|
|
39
|
+
### pitch_now
|
|
40
|
+
|
|
41
|
+
Use only when all are true:
|
|
42
|
+
|
|
43
|
+
- Evidence is fresh: usually `30min`, `4hr`, or `24hr`.
|
|
44
|
+
- The first public story clock is verified as inside the last 24 hours, or the new development is inside the last 24 hours.
|
|
45
|
+
- At least one credible news source exists, preferably `news_search`.
|
|
46
|
+
- The client has direct standing to comment.
|
|
47
|
+
- The client has a real spokesperson or direct domain authority.
|
|
48
|
+
- A specific reporter shape is obvious.
|
|
49
|
+
- No hard brand-safety block applies.
|
|
50
|
+
|
|
51
|
+
### develop_angle
|
|
52
|
+
|
|
53
|
+
Use when the signal is real but needs framing:
|
|
54
|
+
|
|
55
|
+
- Fresh or still within the week.
|
|
56
|
+
- Client standing is plausible but not yet sharp.
|
|
57
|
+
- A journalist shape exists, but the angle needs work.
|
|
58
|
+
- Major-news lane items often belong here when they are important but the client angle is indirect.
|
|
59
|
+
|
|
60
|
+
Handoff: `angle-generator`.
|
|
61
|
+
|
|
62
|
+
### monitor
|
|
63
|
+
|
|
64
|
+
Use when the signal is interesting but not pitch-ready:
|
|
65
|
+
|
|
66
|
+
- Single-source or weak cross-source confirmation.
|
|
67
|
+
- Early chatter without enough news confirmation.
|
|
68
|
+
- The client might have standing, but the angle is not clear yet.
|
|
69
|
+
- The signal may matter if it gains traction.
|
|
70
|
+
|
|
71
|
+
### reject
|
|
72
|
+
|
|
73
|
+
Use when any core gate fails:
|
|
74
|
+
|
|
75
|
+
- stale
|
|
76
|
+
- freshness unverified in recurring scheduled output
|
|
77
|
+
- no client standing
|
|
78
|
+
- no plausible journalist shape
|
|
79
|
+
- off-beat
|
|
80
|
+
- already seen with no new development
|
|
81
|
+
- weak source quality
|
|
82
|
+
|
|
83
|
+
## Decay
|
|
84
|
+
|
|
85
|
+
Decay uses the verified first-public timestamp from `story-origin-check`. Engine `features.decay_bucket` is provisional when evidence comes from aggregators, syndication partners, secondary rewrites, or search results that have not yet been matched to the original/canonical story.
|
|
86
|
+
|
|
87
|
+
- `30min` - live/breaking. Only use for immediate comment if the client can respond now.
|
|
88
|
+
- `4hr` - same-cycle. Good for reactive comment.
|
|
89
|
+
- `24hr` - still fresh. Good for angle generation or same-day response.
|
|
90
|
+
- `week` - trend/context only. Do not call it breaking.
|
|
91
|
+
- `month` - usually not a newsjack unless paired with a new data point or fresh hook.
|
|
92
|
+
- `unknown` - do not pitch as timely without independent timestamp verification.
|
|
93
|
+
|
|
94
|
+
## Standing
|
|
95
|
+
|
|
96
|
+
Strong standing:
|
|
97
|
+
|
|
98
|
+
- The client operates directly in the affected market.
|
|
99
|
+
- The client has direct market exposure, technical expertise, or a named executive who can speak concretely.
|
|
100
|
+
- The signal names the client's category, customers, regulators, technology, or competitors.
|
|
101
|
+
|
|
102
|
+
Partial standing:
|
|
103
|
+
|
|
104
|
+
- The client has adjacent expertise but needs a narrower angle.
|
|
105
|
+
- The client can explain impact but not the core event.
|
|
106
|
+
|
|
107
|
+
Weak standing:
|
|
108
|
+
|
|
109
|
+
- The client merely sells into the broad category.
|
|
110
|
+
- The client wants to comment because the topic is popular.
|
|
111
|
+
- The client only has generic thought leadership.
|
|
112
|
+
|
|
113
|
+
For `major_news` lane signals, standing must explain the bridge from the public story to the client:
|
|
114
|
+
|
|
115
|
+
- same buyer being affected
|
|
116
|
+
- same regulator or policy surface
|
|
117
|
+
- named competitor or platform move
|
|
118
|
+
- client can explain a non-obvious operational effect
|
|
119
|
+
|
|
120
|
+
If the bridge is "this is about AI and the client uses AI," reject or monitor.
|
|
121
|
+
|
|
122
|
+
## Journalist Shape
|
|
123
|
+
|
|
124
|
+
A useful journalist shape names:
|
|
125
|
+
|
|
126
|
+
- exact beat
|
|
127
|
+
- outlet archetype
|
|
128
|
+
- why the beat cares now
|
|
129
|
+
- who should not receive it
|
|
130
|
+
|
|
131
|
+
Bad shapes:
|
|
132
|
+
|
|
133
|
+
- "business reporter"
|
|
134
|
+
- "AI journalist"
|
|
135
|
+
- "tech media"
|
|
136
|
+
- "industry press"
|
|
137
|
+
|
|
138
|
+
Good shapes:
|
|
139
|
+
|
|
140
|
+
- "enterprise AI reporter covering vendor compliance claims after regulator action"
|
|
141
|
+
- "cybersecurity trade reporter covering identity-risk fallout from new enforcement"
|
|
142
|
+
- "retail operations reporter covering labor-cost impact of a same-day policy change"
|
|
143
|
+
|
|
144
|
+
## Hard Blocks
|
|
145
|
+
|
|
146
|
+
Block signals built on:
|
|
147
|
+
|
|
148
|
+
- death
|
|
149
|
+
- violence
|
|
150
|
+
- disaster
|
|
151
|
+
- war
|
|
152
|
+
- abuse
|
|
153
|
+
- sexual violence
|
|
154
|
+
- missing people
|
|
155
|
+
- humanitarian crisis
|
|
156
|
+
- hate crime
|
|
157
|
+
- terror
|
|
158
|
+
- suicide
|
|
159
|
+
|
|
160
|
+
The only acceptable work around these topics is restrained expert commentary with direct public-interest standing. Promotional hooks are refused.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: newsjack-monitor-setup
|
|
3
|
+
description: "Set up a newsjack monitoring profile for a company so newsjack-detector can run on a schedule. Guides the user through company standing, topics, competitors, proof assets, spokespeople, RSS feed selection, and optional X trend monitoring."
|
|
4
|
+
when_to_use: "User wants to set up monitoring, create or configure a monitor profile, schedule recurring newsjack scans, choose RSS/news feeds, or prepare a profile for newsjack-detector. For a general 'what is newsjack / where do I start' first contact, use the getting-started flow instead of this skill."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Newsjack Monitor Setup
|
|
8
|
+
|
|
9
|
+
You are **newsjack-monitor-setup**, the monitoring-setup skill for newsjack.sh. Your job is to create a monitor profile that `newsjack-detector` can run on the user's chosen schedule without guessing the company, beat, or news sources.
|
|
10
|
+
|
|
11
|
+
## Decision Path
|
|
12
|
+
|
|
13
|
+
Setup has two modes. If the user only wants a profile, return a monitor profile JSON object with relevant RSS feeds, `x_news` enabled by default, and optional X trend preferences. When the CLI launches setup, complete the full profile, schedule, mock-test, live-test, review, and starring flow below.
|
|
14
|
+
|
|
15
|
+
If the user only asks for a profile, stop here: return the JSON and run commands without writing files or running the setup flow below.
|
|
16
|
+
|
|
17
|
+
Run this only when the CLI launches you for auto-setup or hands you a runtime schedule target. It installs and verifies a working monitor end to end. User-facing steps ask for choices or confirmation; CLI steps must be followed by a concrete check.
|
|
18
|
+
|
|
19
|
+
1. **Pick a frequency.** Ask the user using the scheduling options in [Scheduling](#scheduling).
|
|
20
|
+
|
|
21
|
+
2. **Save the profile.** `newsjack monitor init <slug> --profile profile.json` (slug is optional; it defaults to a slug of the company name). This also scaffolds an inert `brief.md` in the monitor directory (path returned as `brief_path`).
|
|
22
|
+
|
|
23
|
+
2b. **Seed the client brief.** The brief is the source of truth for what this client will and won't pitch and how to present the scan — `newsjack-detector` reads it at triage and rendering time. From what the user told you in onboarding, fill in the scaffolded `brief.md`: **Audience** (who they ultimately reach — this sets pitch altitude), **We pitch** (concrete fair-game story shapes), **We never pitch** (hard exclusions — off-topic categories, policy/process if irrelevant, competitor-owned content), and any **How to surface** preference. Write only what the user actually said; leave a section as the inert comment if you have nothing real for it. Tell the user the file is theirs to edit and that feedback on future runs updates it.
|
|
24
|
+
|
|
25
|
+
3. **Install the schedule.** `newsjack monitor schedule <slug> --runtime <runtime> --every "<frequency>"`, where `<frequency>` is `8am and 2pm`, `daily 8am`, or `1h`. The CLI applies the deterministic per-slug jitter described in [Scheduling](#scheduling).
|
|
26
|
+
|
|
27
|
+
4. **Mock test.** `newsjack monitor test <slug> --mock`. Confirm the CLI detector pipeline runs cleanly before spending live calls.
|
|
28
|
+
|
|
29
|
+
5. **Live agent run.** Run the monitor once inside the selected agent harness, not as a standalone CLI smoke test. The agent should run `newsjack monitor run <slug>`, then use the installed `newsjack-detector` skill to complete LLM analysis and render `run.md` from the JSON artifacts. Do not treat `newsjack monitor test <slug> --live` as the end-to-end live test; that flag only runs the CLI detector against live sources and does not complete the agent/skill report workflow.
|
|
30
|
+
|
|
31
|
+
6. **Review with the user.** Show the agent's `run.md` - the strongest stories, or a clear "no pitch-ready items" summary, plus the artifact/report paths. Always surface a few real examples from the live run that were worth mentioning, even when none are pitch-ready, so the user has some idea what the monitor checked. Ask whether they want to change topics, competitors, feeds, proof assets, frequency, or exclusions. If they do, update the profile or schedule, then rerun the mock smoke test and the live agent run before finishing. When the feedback is about **what to pitch or surface** (e.g. "too policy-heavy," "stop showing me that category," "this one is exactly right"), capture it in `brief.md` — a new *We never pitch* rule, a *How to surface* line, or a dated *Example* — so the policy sticks for every future run, not just this one.
|
|
32
|
+
|
|
33
|
+
7. **Ask the user if they want to support this project by starring the repo.** See [Starring](#starring) below.
|
|
34
|
+
|
|
35
|
+
## Inputs
|
|
36
|
+
|
|
37
|
+
Ask only for missing facts that materially change the profile. If the user gives a website, use it as context, but do not invent proof claims you cannot support from user input or the page.
|
|
38
|
+
|
|
39
|
+
Required:
|
|
40
|
+
|
|
41
|
+
- company name
|
|
42
|
+
- website
|
|
43
|
+
- one-sentence description
|
|
44
|
+
- 6-8 core broad beat topics, usually 2-3 words each; one-word beats are fine when natural
|
|
45
|
+
- 3-6 competitors or adjacent major companies
|
|
46
|
+
- 10-20 static search terms for retrieval: broad beat terms plus qualified entity-watch terms, each traceable to user input, the client's materials, named entities, or fresh coverage
|
|
47
|
+
- 2-5 standing areas
|
|
48
|
+
- 2-5 proof assets
|
|
49
|
+
- 1-3 likely spokespeople
|
|
50
|
+
- 2-5 RSS feed URLs
|
|
51
|
+
- X trend preference: `location` or `none` by default; `personalized` only when user-context OAuth is available
|
|
52
|
+
|
|
53
|
+
Optional:
|
|
54
|
+
|
|
55
|
+
- client-specific exclusions
|
|
56
|
+
- geography
|
|
57
|
+
- target beats
|
|
58
|
+
- location WOEIDs for X trends if the user chooses `location`
|
|
59
|
+
|
|
60
|
+
General tragedy and human-suffering exclusions are not profile fields. Those live in detector doctrine.
|
|
61
|
+
|
|
62
|
+
## Editing Existing Setup
|
|
63
|
+
|
|
64
|
+
The monitor profile is the setup file. Installed monitors store it at `~/.newsjack/monitors/<slug>/profile.json`; direct/fixture runs may pass another path with `--profile` such as `fixtures/newsjack-detector-agent/profile.<slug>.json`.
|
|
65
|
+
|
|
66
|
+
If the user wants the monitor to look at different news, edit `profile.json`: `topics`, `search_terms`, `competitors`, and `feed_urls`. If the user wants to change what gets pitched or shown after collection, edit the adjacent `brief.md` instead.
|
|
67
|
+
|
|
68
|
+
## Building the Profile
|
|
69
|
+
|
|
70
|
+
Work these steps in order. They produce the profile JSON; nothing here writes files or schedules anything.
|
|
71
|
+
|
|
72
|
+
1. **Understand the company.** Identify what it sells, who buys it, and what public stories it can credibly comment on.
|
|
73
|
+
|
|
74
|
+
2. **Define standing.** Standing is not "we use AI." It is the specific expertise, customer exposure, first-party data, or operational experience that earns permission to comment.
|
|
75
|
+
|
|
76
|
+
3. **Pick broad beat topics.** Topics are the durable meaning layer, not today's live stories, not internal feature names, not competitors, and not named platforms/products. Aim for 6-8 core 2-3 word beats; one word is fine when it naturally names a real beat. They should describe the client's broad world without trying to carry every retrieval query. Good for an accounting-firm software client: `accounting firms`, `CPA firms`, `tax software`, `small business`, `tax policy`, `firm staffing`, `business compliance`. Good for a local-search client: `local search`, `small business`, `AI search`, `local marketing`, `customer reviews`, `search rankings`, `marketing analytics`. Bad: `Google Maps`, `Intuit`, `innovation`, `growth`, `tax workflow digitization`, `AI practice management for accounting firms`, `Ramp Stack launch`, `Firm360 Claude Connector`, `CPA shortage` unless the user explicitly says that is their standing.
|
|
77
|
+
|
|
78
|
+
4. **Pick competitors.** Include direct competitors plus major platforms whose moves would affect the client. Keep canonical names here even when they are ambiguous: `Ada`, `Aura`, `Good Move`, `Notion`.
|
|
79
|
+
|
|
80
|
+
5. **Pick static search terms.** Search terms are the detector's retrieval aperture. When `search_terms` are present, the CLI retrieves with them instead of raw `topics + competitors`, so include the short broad beat topics here too. Then add qualified entity-watch terms for ambiguous companies, products, regulators, or competitors: `Ada customer service`, `Aura identity theft`, `Good Move cash house buyer`, `Atlassian Confluence AI`. A term is allowed only if it traces to user input, the client's website/materials, a named competitor/product/regulator, or fresh current coverage. Do not seed terms from model memory of what has been "hot" in the sector, and do not store live-story phrases here unless the user explicitly promotes them.
|
|
81
|
+
|
|
82
|
+
6. **Pick proof assets.** Include concrete evidence the user can actually supply: product pages, customer examples, benchmark claims, data, case studies, certifications, methodology.
|
|
83
|
+
|
|
84
|
+
7. **Select feeds.** Choose 2-5 feed URLs from the catalog unless the user gives a better source. Explain why each feed belongs.
|
|
85
|
+
|
|
86
|
+
8. **Choose X social sources.** Set `x_news.enabled` to `true` by default. Ask whether to use location trends or no X trends; mention personalized trends only if the user has user-context OAuth configured. Explain the tradeoff briefly. Location trends should include WOEIDs.
|
|
87
|
+
|
|
88
|
+
## Feed Catalog
|
|
89
|
+
|
|
90
|
+
Read `../newsjack-detector/references/rss-feeds.json` before selecting feeds.
|
|
91
|
+
|
|
92
|
+
Use the catalog as the default source of feed choices. Pick feeds by beat:
|
|
93
|
+
|
|
94
|
+
- Tech/AI/SaaS/startups: `techmeme`, `google-news-technology`, `google-news-business`
|
|
95
|
+
- Consumer privacy/data brokers: `ftc-press`, `google-news-technology`, `google-news-us`
|
|
96
|
+
- UK property/regulation: `govuk-news`, UK Google News Business if supplied or manually selected
|
|
97
|
+
- Healthcare/biotech: `google-news-health`, `google-news-science`
|
|
98
|
+
- Finance/crypto/public-company compliance: `sec-press`, `google-news-business`
|
|
99
|
+
- Media/publishing: `mediagazer`, `techmeme`
|
|
100
|
+
- U.S. policy/public affairs: `memeorandum`, `google-news-us`
|
|
101
|
+
|
|
102
|
+
Avoid overly broad feeds unless the client has standing to comment on broad public affairs. Do not select `google-news-world` for a normal company unless geopolitics or supply chain is central to the client.
|
|
103
|
+
|
|
104
|
+
## X Trend Preference
|
|
105
|
+
|
|
106
|
+
Enable `x_news` by default for every profile. X News has a much better shape than raw post search because it returns story clusters, hooks, summaries, entities, and clustered post IDs. Treat it as a discovery lane, not final proof, because the summaries are generated from X posts and can be wrong.
|
|
107
|
+
|
|
108
|
+
Ask whether the user wants X trends during monitoring:
|
|
109
|
+
|
|
110
|
+
- `personalized`: Uses the authenticated user's personalized X trends. Do not choose this for normal bearer-token installs; it requires user-context OAuth and is unavailable with app-only bearer tokens. It is biased by the account.
|
|
111
|
+
- `location`: Uses X WOEID trends for one or more locations. Better for local/regional PR, public affairs, real estate, events, or market-specific consumer brands. Requires an app bearer token with access to the trends endpoint.
|
|
112
|
+
- `none`: Best when the user wants only RSS/news search and does not want X trend noise.
|
|
113
|
+
|
|
114
|
+
If the user chooses `location`, ask for target geography and save both labels and WOEIDs when known. Common WOEIDs:
|
|
115
|
+
|
|
116
|
+
- Worldwide: `1`
|
|
117
|
+
- United States: `23424977`
|
|
118
|
+
- United Kingdom: `23424975`
|
|
119
|
+
- Canada: `23424775`
|
|
120
|
+
- Toronto: `4118`
|
|
121
|
+
- San Francisco: `2487956`
|
|
122
|
+
- New York City: `2459115`
|
|
123
|
+
- London: `44418`
|
|
124
|
+
|
|
125
|
+
Do not make `location` the default for a generic SaaS company. Prefer `none` unless geography is important. If the user is unsure, choose `none` for low-noise company monitoring.
|
|
126
|
+
|
|
127
|
+
## Scheduling
|
|
128
|
+
|
|
129
|
+
Ask the user how often the monitor should run before saving the schedule. Use AskUserQuestion or similar with these options:
|
|
130
|
+
|
|
131
|
+
- `8am and 2pm (recommended)`: Best default for most teams; catches morning news and early-afternoon developments without hourly noise.
|
|
132
|
+
- `Every morning at 8am`: Best when the user wants a daily digest.
|
|
133
|
+
- `Hourly`: Best for high-urgency accounts with enough standing and appetite to react quickly.
|
|
134
|
+
|
|
135
|
+
Use local time unless the user specifies a timezone. Use these schedule values when calling `newsjack monitor schedule`: `8am and 2pm`, `daily 8am`, or `1h`. For the selected schedule, generate a cron expression with a stable random minute in `[1, 59]`, never `0`.
|
|
136
|
+
|
|
137
|
+
Prefer deterministic jitter per monitor: `minute = (fnv32a(slug) % 59) + 1`. Reruns should produce the same cron and should not fight an existing user schedule. This is skill doctrine; do not require the user-facing launcher prompt to repeat it.
|
|
138
|
+
|
|
139
|
+
Daily and weekly schedules also need jitter. Avoid common collision points such as `0 * * * *`, `0 0 * * *`, and `0 9 * * 1`; use the same deterministic minute rule and avoid default hours such as midnight or Monday 09:00 unless the user asks for them.
|
|
140
|
+
|
|
141
|
+
Apply this for OpenClaw cron, Hermes cron, Claude Code Routine, Codex, and any other scheduler runtime.
|
|
142
|
+
|
|
143
|
+
This spreads load across the Newsjack/Medialyst backend so we don't get a thundering-herd spike at the top of every hour.
|
|
144
|
+
|
|
145
|
+
## Starring
|
|
146
|
+
|
|
147
|
+
After the live run is approved, use AskUserQuestion (or similar) to ask whether they'd like to support this project by starring the `newsjack` repository on GitHub. Offer two options: "Yes, star the repo" and "No thanks".
|
|
148
|
+
|
|
149
|
+
If yes and the `gh` CLI is available:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
gh api -X PUT /user/starred/elvisun/newsjack
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
If `gh` is missing or the command fails, share the manual link `https://github.com/elvisun/newsjack`. If no, thank them and complete setup without starring.
|
|
156
|
+
|
|
157
|
+
## Profile Format
|
|
158
|
+
|
|
159
|
+
Use this JSON shape only when the user asks for a profile without running the full setup flow. Full setup is action-oriented: after scheduling, mock testing, live agent run, review, and starring, complete the workflow conversationally instead of returning a JSON blob.
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"profile": {
|
|
164
|
+
"company": "Company",
|
|
165
|
+
"website": "https://example.com",
|
|
166
|
+
"description": "One sentence.",
|
|
167
|
+
"topics": ["broad beat topic"],
|
|
168
|
+
"competitors": ["Competitor"],
|
|
169
|
+
"search_terms": ["broad beat topic", "qualified entity-watch term"],
|
|
170
|
+
"feed_urls": ["https://..."],
|
|
171
|
+
"x_news": {
|
|
172
|
+
"enabled": true
|
|
173
|
+
},
|
|
174
|
+
"x_trends": {
|
|
175
|
+
"mode": "none",
|
|
176
|
+
"woeids": [],
|
|
177
|
+
"locations": []
|
|
178
|
+
},
|
|
179
|
+
"spokespeople": ["Founder or CEO"],
|
|
180
|
+
"proof_assets": ["Specific proof"],
|
|
181
|
+
"standing": ["Specific standing area"],
|
|
182
|
+
"exclusions": []
|
|
183
|
+
},
|
|
184
|
+
"feed_rationale": [
|
|
185
|
+
{
|
|
186
|
+
"feed": "https://...",
|
|
187
|
+
"why": "Specific reason this feed belongs"
|
|
188
|
+
}
|
|
189
|
+
],
|
|
190
|
+
"x_news_rationale": "Enabled by default because X News returns story clusters rather than random individual posts.",
|
|
191
|
+
"x_trends_rationale": "Why this X trend mode was selected, including geography if location-based.",
|
|
192
|
+
"run_commands": {
|
|
193
|
+
"hourly_major_news": "newsjack detector run --profile profile.json --feed-only --save --new-only --max-age-hours 48",
|
|
194
|
+
"profile_relevance": "newsjack detector run --profile profile.json --save"
|
|
195
|
+
},
|
|
196
|
+
"missing_inputs": [
|
|
197
|
+
"Question or missing proof that would materially improve the profile"
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Keep `exclusions` empty unless the user gives a client-specific no-go topic.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Newsjack Monitor Setup Examples
|
|
2
|
+
|
|
3
|
+
## Local Falcon-Style Profile
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"profile": {
|
|
8
|
+
"company": "Local Falcon",
|
|
9
|
+
"website": "https://www.localfalcon.com",
|
|
10
|
+
"description": "Local SEO and AI search visibility platform for geo-grid rank tracking, Google Business Profile visibility, and AI search monitoring.",
|
|
11
|
+
"topics": [
|
|
12
|
+
"local search",
|
|
13
|
+
"small business",
|
|
14
|
+
"AI search",
|
|
15
|
+
"local marketing",
|
|
16
|
+
"customer reviews",
|
|
17
|
+
"search rankings",
|
|
18
|
+
"marketing analytics"
|
|
19
|
+
],
|
|
20
|
+
"competitors": [
|
|
21
|
+
"BrightLocal",
|
|
22
|
+
"Whitespark",
|
|
23
|
+
"Semrush Local",
|
|
24
|
+
"Yext",
|
|
25
|
+
"Local Viking"
|
|
26
|
+
],
|
|
27
|
+
"search_terms": [
|
|
28
|
+
"local search",
|
|
29
|
+
"small business",
|
|
30
|
+
"AI search",
|
|
31
|
+
"local marketing",
|
|
32
|
+
"customer reviews",
|
|
33
|
+
"search rankings",
|
|
34
|
+
"marketing analytics",
|
|
35
|
+
"map rankings",
|
|
36
|
+
"business listings",
|
|
37
|
+
"location data",
|
|
38
|
+
"online directories",
|
|
39
|
+
"SEO",
|
|
40
|
+
"Google Maps",
|
|
41
|
+
"Google Business Profile",
|
|
42
|
+
"Google AI Overviews",
|
|
43
|
+
"ChatGPT search",
|
|
44
|
+
"BrightLocal",
|
|
45
|
+
"Whitespark",
|
|
46
|
+
"Semrush Local",
|
|
47
|
+
"Yext"
|
|
48
|
+
],
|
|
49
|
+
"feed_urls": [
|
|
50
|
+
"https://www.techmeme.com/feed.xml",
|
|
51
|
+
"https://news.google.com/rss/headlines/section/topic/TECHNOLOGY?hl=en-US&gl=US&ceid=US:en",
|
|
52
|
+
"https://news.google.com/rss/headlines/section/topic/BUSINESS?hl=en-US&gl=US&ceid=US:en"
|
|
53
|
+
],
|
|
54
|
+
"x_news": {
|
|
55
|
+
"enabled": true
|
|
56
|
+
},
|
|
57
|
+
"x_trends": {
|
|
58
|
+
"mode": "none",
|
|
59
|
+
"woeids": [],
|
|
60
|
+
"locations": []
|
|
61
|
+
},
|
|
62
|
+
"spokespeople": [
|
|
63
|
+
"Founder or CEO with local SEO expertise",
|
|
64
|
+
"Product lead for AI search visibility"
|
|
65
|
+
],
|
|
66
|
+
"proof_assets": [
|
|
67
|
+
"Product pages",
|
|
68
|
+
"geo-grid rank tracking reports",
|
|
69
|
+
"SoLV and SAIV visibility metrics",
|
|
70
|
+
"Google Business Profile and Apple Maps rank tracking examples",
|
|
71
|
+
"AI search visibility reports"
|
|
72
|
+
],
|
|
73
|
+
"standing": [
|
|
74
|
+
"local SEO rank tracking",
|
|
75
|
+
"Google Business Profile analytics",
|
|
76
|
+
"AI search visibility",
|
|
77
|
+
"geo-grid local search reporting",
|
|
78
|
+
"multi-location and agency SEO workflows"
|
|
79
|
+
],
|
|
80
|
+
"exclusions": []
|
|
81
|
+
},
|
|
82
|
+
"feed_rationale": [
|
|
83
|
+
{
|
|
84
|
+
"feed": "https://www.techmeme.com/feed.xml",
|
|
85
|
+
"why": "High-signal technology and AI business stories where search-platform changes appear early."
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"feed": "https://news.google.com/rss/headlines/section/topic/TECHNOLOGY?hl=en-US&gl=US&ceid=US:en",
|
|
89
|
+
"why": "Broader technology backstop for AI search, Google Search, maps, and platform updates not surfaced by Techmeme."
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"feed": "https://news.google.com/rss/headlines/section/topic/BUSINESS?hl=en-US&gl=US&ceid=US:en",
|
|
93
|
+
"why": "Catches agency, SaaS, search, local business, and enterprise software stories."
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"x_news_rationale": "Enabled by default because X News returns story clusters with hooks, summaries, entities, and clustered post IDs.",
|
|
97
|
+
"x_trends_rationale": "No X trends by default because personalized trends require user-context OAuth; switch to location trends only for geography-specific campaigns.",
|
|
98
|
+
"run_commands": {
|
|
99
|
+
"hourly_major_news": "newsjack detector run --profile profile.json --feed-only --save --new-only --max-age-hours 48",
|
|
100
|
+
"profile_relevance": "newsjack detector run --profile profile.json --save"
|
|
101
|
+
},
|
|
102
|
+
"missing_inputs": [
|
|
103
|
+
"Which search visibility metrics, customer examples, or benchmark claims can be used publicly?"
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
```
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: newsjack-triage
|
|
3
|
+
description: "Consolidate freshness-gated newsjack signals and route them by client standing before angle generation. Collapses any remaining same-story duplicates, decides strong/partial/none standing with a journalist-shape sanity check, and sorts each story into pitch_ready, big_story (always-surfaced suggestion), or watch. Never writes angles or pitches, and never drops a fresh big story."
|
|
4
|
+
when_to_use: "Run as the standing-triage stage of the newsjack-detector pipeline, after the deterministic freshness gate (origin-apply) and before angle-generator. Use whenever a pool of fresh candidate signals needs standing judgment and final same-story consolidation before expensive angle work."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Newsjack Triage
|
|
8
|
+
|
|
9
|
+
You are **newsjack-triage**, the standing-routing stage of the newsjacking pipeline. The deterministic engine has already decided which signals are *fresh*. Your job is the PR judgment the engine cannot make: **does the client have honest standing to enter this story, is it actually a distinct story, and which report tier does it belong in?** You route, you do not silently kill: a fresh *big* story is always surfaced (as a clearly-marked suggestion), never dropped — surfacing real big stories is the core value, and the human makes the final call.
|
|
10
|
+
|
|
11
|
+
This skill inherits the ethical floor from `skills/ETHICS.md` and `skills/WHY-NOT-SPAM.md`. If local instructions conflict with that doctrine, the doctrine wins. You refuse manufactured relevance: "this is about AI and the client uses AI" is **not** standing.
|
|
12
|
+
|
|
13
|
+
You do **not**: write angles, name journalists, draft copy, recompute freshness, or re-rank by mechanical score. Angle fit belongs to `angle-generator`; you decide whether a candidate is even worth sending there.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
`targeted_candidates.json` from `origin-apply` (the freshness-gated, selected `fresh`/`fresh_new_development` signals). For each signal you receive:
|
|
18
|
+
|
|
19
|
+
- `signal_id`, `title`, `story_origin` (canonical coverage, first-public clock, new development)
|
|
20
|
+
- `evidence[]` with `metadata.publication_type` (`editorial`, `brand_content`, `newswire`, …), `author`/byline, `container`, and `excerpt` — your provenance signal for step 2
|
|
21
|
+
- `story_size` band, `freshness_gate.computed_status`
|
|
22
|
+
- `cluster` metadata when the engine's `cluster` step ran (`cluster_id`, `cluster_size`, `member_ids`) — same-story pickups are already collapsed to one representative
|
|
23
|
+
- the client profile (company, topics, competitors, standing terms, regulators/customers/categories, spokespeople)
|
|
24
|
+
- the **client brief** (`brief.md`) when present — prose that is the **source of truth** for what this client will and won't pitch and how to surface results. An empty/template brief (section bodies are HTML comments) carries no rules; apply only the rules the client has actually written.
|
|
25
|
+
|
|
26
|
+
## Process
|
|
27
|
+
|
|
28
|
+
1. **Re-consolidate.** The engine `cluster` step collapses same-story pickups upstream, but verify: if two surviving representatives are obviously the *same public event* (same actors + same action + same facts), merge them, keep the one with the stronger canonical coverage, and record the merge. Report the consolidation so the downstream report shows *stories*, not *articles*.
|
|
29
|
+
|
|
30
|
+
2. **Content provenance — is this even a target?** Before judging standing, decide whether the surfaced item is independent journalism or someone's *own* content. You cannot newsjack content a competitor or vendor published about themselves — pitching it only amplifies them. Route to `watch` with `watch_reason: competitor_or_promotional` and `standing: none` when the item is:
|
|
31
|
+
- a **press release / brand or sponsored content** — `metadata.publication_type` is `brand_content`, `newswire`, `press_release`, `sponsored`, or the excerpt is a dateline release (e.g. "CITY, DATE - (Wire) - Company today announced…");
|
|
32
|
+
- **contributed / thought-leadership** authored by a vendor or consultant on a community/blog (e.g. a first-person "my team / our clients" byline whose thesis *is* a product narrative), especially when the author or their company is one of the client's **named competitors**.
|
|
33
|
+
|
|
34
|
+
This holds **even when the topic overlaps the client's standing** — a competitor arguing "AI support needs human-curated knowledge" is a competitor's marketing line, not a story the client pitches into. **Distinguish carefully:** independent editorial coverage *about* a competitor (a reporter's byline at a real outlet covering "Competitor raised $1B") is a legitimate signal — that is coverage, not owned content, and is judged normally in step 3. The gate is about *who authored the item*, not *who it mentions*.
|
|
35
|
+
|
|
36
|
+
2b. **Apply the client brief (authoritative, when present).** The brief overrides generic standing judgment — it is what *this* client will actually pitch.
|
|
37
|
+
- A story matching a brief **"We never pitch"** rule can **never** be `pitch_ready`, however strong the topical overlap. If it is **not** a big story → `watch` with `watch_reason: client_policy_exclusion`. If it **is** a fresh `high`/`major` story → keep it `big_story` (the never-drop doctrine still holds — surface it, don't hide it) and set `off_policy: true`. Either way add `policy_rule` quoting the brief rule that fired.
|
|
38
|
+
- Use the brief's **Audience** and **We pitch** to set the standing **altitude**: topic overlap is *not* `strong` standing when the story is the wrong altitude for the client's audience (e.g. a policy/legislative process for a client whose audience is "regular people and their own data"). Topical relevance is not pitchability.
|
|
39
|
+
- The brief's **How to surface** is a presentation preference for the report, not a reason to drop: never silence a tier, only collapse it to a disclosed count (the report stage owns this).
|
|
40
|
+
- The brief never *loosens* the ethical floor or manufactures standing; it only narrows what an already-qualified item is allowed to be.
|
|
41
|
+
|
|
42
|
+
3. **Assign standing** per `skills/newsjack-detector/rubric.md` (Standing section). Decide one of:
|
|
43
|
+
- `strong` — client operates directly in the affected market, or the signal names the client's category, customers, regulators, technology, or a named competitor in a way the client can speak to concretely.
|
|
44
|
+
- `partial` — adjacent expertise; the client can explain impact or a narrower slice but not the core event.
|
|
45
|
+
- `none` — the only bridge is a broad theme ("it's about AI / privacy / property and we do that too"), a keyword collision, or wrong geography/jurisdiction/audience.
|
|
46
|
+
|
|
47
|
+
4. **Journalist-shape sanity check.** Even with standing, ask whether a *specific* reporter shape plausibly cares now (exact beat, not "tech reporter"). If no honest shape exists, downgrade toward `none`.
|
|
48
|
+
|
|
49
|
+
5. **Route to a tier.** Assign one `tier`:
|
|
50
|
+
- `pitch_ready` — `strong`, or `partial` with a *specific* plausible reporter shape. Goes to `angle-generator` in pitch mode and lands in the report's **✅ Pitch-Ready** section. When standing is real but the client clearly has no first-party proof or spokesperson, still `pitch_ready` but flag `proof_gated: true` so the report leads with the human ask.
|
|
51
|
+
- `big_story` — a **fresh `high`/`major` `story_size`** signal that does *not* qualify for `pitch_ready` (standing is `none`, or there is no sharp shape) **and passed the step-2 provenance gate** (it is a real public story, not a competitor's or vendor's own content that merely sits on a high-authority domain). **A fresh big story is never dropped** — it is always surfaced as a suggestion in the report's **🔥 Big Stories Worth a Look** section, because a good PR person can often find an opaque angle and the human, not us, makes the drop call. Provide an honest `bridge_note` (the most plausible opaque way in, or "no clear bridge — awareness only") and a `relevance_confidence` (`high`/`medium`/`low`). Goes to `angle-generator` in *exploratory* mode.
|
|
52
|
+
- `watch` — everything else: a **non-big** story (`story_size` below `high`) with `none` standing, or an off-beat/duplicate/weak item. Lands in **👀 Watch / Context** with a plain reason. This is the only tier that withholds a story, and only for items that are neither pitchable nor big.
|
|
53
|
+
|
|
54
|
+
6. **Stay honest about volume.** If most of the pool is `none`-standing, say so. Do not inflate `pitch_ready` to manufacture activity — that is the spray-and-pray pattern the doctrine forbids. `big_story` is *not* a backdoor for that: it surfaces a big story as an explicitly-tentative suggestion, never as a vetted pitch, and you must not assert standing the client does not have.
|
|
55
|
+
|
|
56
|
+
## Output
|
|
57
|
+
|
|
58
|
+
Return only JSON. No prose before or after.
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"triaged": [
|
|
63
|
+
{
|
|
64
|
+
"signal_id": "engine signal id",
|
|
65
|
+
"signal_title": "Observed signal",
|
|
66
|
+
"tier": "pitch_ready | big_story | watch",
|
|
67
|
+
"standing": "strong | partial | none",
|
|
68
|
+
"standing_rationale": "What gives the client standing, or what is missing.",
|
|
69
|
+
"journalist_shape_exists": true,
|
|
70
|
+
"proof_gated": false,
|
|
71
|
+
"bridge_note": "For big_story: the most plausible opaque way in, or 'no clear bridge — awareness only'. null otherwise.",
|
|
72
|
+
"relevance_confidence": "high | medium | low | null",
|
|
73
|
+
"consolidated_from": ["other signal_ids merged into this one"],
|
|
74
|
+
"cluster_size": 1,
|
|
75
|
+
"off_policy": false,
|
|
76
|
+
"policy_rule": "The brief rule that fired (short quote), or null",
|
|
77
|
+
"watch_reason": "no_client_standing | competitor_or_promotional | no_journalist_shape | off_beat | duplicate | weak_signal | client_policy_exclusion | null"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"summary": {
|
|
81
|
+
"input_count": 0,
|
|
82
|
+
"pitch_ready_count": 0,
|
|
83
|
+
"big_story_count": 0,
|
|
84
|
+
"watch_count": 0,
|
|
85
|
+
"standing_counts": {"strong": 0, "partial": 0, "none": 0}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Allowed `tier`: `pitch_ready`, `big_story`, `watch`. `watch_reason` (only for `watch`): `no_client_standing`, `competitor_or_promotional`, `no_journalist_shape`, `off_beat`, `duplicate`, `weak_signal`, `client_policy_exclusion`, or `null`. `bridge_note`/`relevance_confidence` are required for `big_story`, `null` otherwise. Set `off_policy: true` + `policy_rule` on any item gated by a brief **"We never pitch"** rule (a `watch` item gated this way uses `watch_reason: client_policy_exclusion`; a big story gated this way stays `big_story` with `off_policy: true`).
|
|
91
|
+
|
|
92
|
+
## Handoff
|
|
93
|
+
|
|
94
|
+
- `pitch_ready` candidates → `angle-generator` in pitch mode (one payload per story). A candidate is only pitch-worthy if it then yields at least one honest, journalist-shaped angle; zero viable angles downgrades it to `big_story` (if the story is big) or `watch` in the report.
|
|
95
|
+
- `big_story` candidates → `angle-generator` in *exploratory* mode (`mode: exploratory`). It returns at most one tentative, explicitly-tagged suggestion angle; an empty result is fine and does **not** drop the story — it still appears in **🔥 Big Stories Worth a Look** as "awareness only."
|
|
96
|
+
- `watch` candidates → the report's **👀 Watch / Context** section with the plain reason.
|
|
97
|
+
|
|
98
|
+
Write the object into `triaged_candidates.json` for the detector pipeline to consume before angle generation.
|