devrel-origin 0.2.14__py3-none-any.whl

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.
Files changed (98) hide show
  1. devrel_origin/__init__.py +15 -0
  2. devrel_origin/cli/__init__.py +92 -0
  3. devrel_origin/cli/_common.py +243 -0
  4. devrel_origin/cli/analytics.py +28 -0
  5. devrel_origin/cli/argus.py +497 -0
  6. devrel_origin/cli/auth.py +227 -0
  7. devrel_origin/cli/config.py +108 -0
  8. devrel_origin/cli/content.py +259 -0
  9. devrel_origin/cli/cost.py +108 -0
  10. devrel_origin/cli/cro.py +298 -0
  11. devrel_origin/cli/deliverables.py +65 -0
  12. devrel_origin/cli/docs.py +91 -0
  13. devrel_origin/cli/doctor.py +178 -0
  14. devrel_origin/cli/experiment.py +29 -0
  15. devrel_origin/cli/growth.py +97 -0
  16. devrel_origin/cli/init.py +472 -0
  17. devrel_origin/cli/intel.py +27 -0
  18. devrel_origin/cli/kb.py +96 -0
  19. devrel_origin/cli/listen.py +31 -0
  20. devrel_origin/cli/marketing.py +66 -0
  21. devrel_origin/cli/migrate.py +45 -0
  22. devrel_origin/cli/run.py +46 -0
  23. devrel_origin/cli/sales.py +57 -0
  24. devrel_origin/cli/schedule.py +62 -0
  25. devrel_origin/cli/synthesize.py +28 -0
  26. devrel_origin/cli/triage.py +29 -0
  27. devrel_origin/cli/video.py +35 -0
  28. devrel_origin/core/__init__.py +58 -0
  29. devrel_origin/core/agent_config.py +75 -0
  30. devrel_origin/core/argus.py +964 -0
  31. devrel_origin/core/atlas.py +1450 -0
  32. devrel_origin/core/base.py +372 -0
  33. devrel_origin/core/cyra.py +563 -0
  34. devrel_origin/core/dex.py +708 -0
  35. devrel_origin/core/echo.py +614 -0
  36. devrel_origin/core/growth/__init__.py +27 -0
  37. devrel_origin/core/growth/recommendations.py +219 -0
  38. devrel_origin/core/growth/target_kinds.py +51 -0
  39. devrel_origin/core/iris.py +513 -0
  40. devrel_origin/core/kai.py +1367 -0
  41. devrel_origin/core/llm.py +542 -0
  42. devrel_origin/core/llm_backends.py +274 -0
  43. devrel_origin/core/mox.py +514 -0
  44. devrel_origin/core/nova.py +349 -0
  45. devrel_origin/core/pax.py +1205 -0
  46. devrel_origin/core/rex.py +532 -0
  47. devrel_origin/core/sage.py +486 -0
  48. devrel_origin/core/sentinel.py +385 -0
  49. devrel_origin/core/types.py +98 -0
  50. devrel_origin/core/video/__init__.py +22 -0
  51. devrel_origin/core/video/assembler.py +131 -0
  52. devrel_origin/core/video/browser_recorder.py +118 -0
  53. devrel_origin/core/video/desktop_recorder.py +254 -0
  54. devrel_origin/core/video/overlay_renderer.py +143 -0
  55. devrel_origin/core/video/script_parser.py +147 -0
  56. devrel_origin/core/video/tts_engine.py +82 -0
  57. devrel_origin/core/vox.py +268 -0
  58. devrel_origin/core/watchdog.py +321 -0
  59. devrel_origin/project/__init__.py +1 -0
  60. devrel_origin/project/config.py +75 -0
  61. devrel_origin/project/cost_sink.py +61 -0
  62. devrel_origin/project/init.py +104 -0
  63. devrel_origin/project/paths.py +75 -0
  64. devrel_origin/project/state.py +241 -0
  65. devrel_origin/project/templates/__init__.py +4 -0
  66. devrel_origin/project/templates/config.toml +24 -0
  67. devrel_origin/project/templates/devrel.gitignore +10 -0
  68. devrel_origin/project/templates/slop-blocklist.md +45 -0
  69. devrel_origin/project/templates/style.md +24 -0
  70. devrel_origin/project/templates/voice.md +29 -0
  71. devrel_origin/quality/__init__.py +66 -0
  72. devrel_origin/quality/editorial.py +357 -0
  73. devrel_origin/quality/persona.py +84 -0
  74. devrel_origin/quality/readability.py +148 -0
  75. devrel_origin/quality/slop.py +167 -0
  76. devrel_origin/quality/style.py +110 -0
  77. devrel_origin/quality/voice.py +15 -0
  78. devrel_origin/tools/__init__.py +9 -0
  79. devrel_origin/tools/analytics.py +304 -0
  80. devrel_origin/tools/api_client.py +393 -0
  81. devrel_origin/tools/apollo_client.py +305 -0
  82. devrel_origin/tools/code_validator.py +428 -0
  83. devrel_origin/tools/github_tools.py +297 -0
  84. devrel_origin/tools/instantly_client.py +412 -0
  85. devrel_origin/tools/kb_harvester.py +340 -0
  86. devrel_origin/tools/mcp_server.py +578 -0
  87. devrel_origin/tools/notifications.py +245 -0
  88. devrel_origin/tools/run_report.py +193 -0
  89. devrel_origin/tools/scheduler.py +231 -0
  90. devrel_origin/tools/search_tools.py +321 -0
  91. devrel_origin/tools/self_improve.py +168 -0
  92. devrel_origin/tools/sheets.py +236 -0
  93. devrel_origin-0.2.14.dist-info/METADATA +354 -0
  94. devrel_origin-0.2.14.dist-info/RECORD +98 -0
  95. devrel_origin-0.2.14.dist-info/WHEEL +5 -0
  96. devrel_origin-0.2.14.dist-info/entry_points.txt +2 -0
  97. devrel_origin-0.2.14.dist-info/licenses/LICENSE +21 -0
  98. devrel_origin-0.2.14.dist-info/top_level.txt +1 -0
@@ -0,0 +1,236 @@
1
+ """
2
+ Google Sheets — Content calendar integration.
3
+
4
+ Publishes agent outputs to a Google Sheets content calendar
5
+ for editorial review and scheduling. Uses Google Sheets API v4
6
+ via service account or OAuth credentials.
7
+ """
8
+
9
+ import logging
10
+ from dataclasses import dataclass
11
+ from typing import Any
12
+
13
+ import httpx
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ SHEETS_API = "https://sheets.googleapis.com/v4/spreadsheets"
18
+
19
+ # Content calendar column layout
20
+ CALENDAR_HEADERS = [
21
+ "Date",
22
+ "Day",
23
+ "Platform",
24
+ "Type",
25
+ "Pillar",
26
+ "Agent",
27
+ "Hook",
28
+ "Content",
29
+ "CTA",
30
+ "Status",
31
+ "Quality Score",
32
+ "Notes",
33
+ ]
34
+
35
+
36
+ @dataclass
37
+ class SheetsConfig:
38
+ """Google Sheets configuration."""
39
+
40
+ spreadsheet_id: str = ""
41
+ credentials_path: str = "" # Path to service account JSON
42
+ access_token: str = "" # Or direct OAuth access token
43
+
44
+
45
+ class ContentCalendar:
46
+ """Async Google Sheets content calendar manager.
47
+
48
+ Publishes agent outputs as rows in a content calendar spreadsheet.
49
+ Supports deduplication by (date, agent, hook) to prevent duplicates
50
+ on re-runs.
51
+
52
+ Usage::
53
+
54
+ cal = ContentCalendar(config)
55
+ await cal.publish_content(context)
56
+ await cal.update_status(row_id, "published")
57
+ """
58
+
59
+ SHEET_NAME = "Content"
60
+
61
+ def __init__(self, config: SheetsConfig):
62
+ self.config = config
63
+ self._client = httpx.AsyncClient(timeout=20.0)
64
+ self._headers: dict[str, str] = {}
65
+ if config.access_token:
66
+ self._headers["Authorization"] = f"Bearer {config.access_token}"
67
+
68
+ async def close(self) -> None:
69
+ await self._client.aclose()
70
+
71
+ async def _request(
72
+ self,
73
+ method: str,
74
+ url: str,
75
+ **kwargs: Any,
76
+ ) -> dict[str, Any]:
77
+ """Make an authenticated Sheets API request."""
78
+ resp = await self._client.request(
79
+ method,
80
+ url,
81
+ headers=self._headers,
82
+ **kwargs,
83
+ )
84
+ resp.raise_for_status()
85
+ return resp.json() if resp.content else {}
86
+
87
+ async def ensure_headers(self) -> None:
88
+ """Create the header row if the sheet is empty."""
89
+ if not self.config.spreadsheet_id:
90
+ return
91
+ url = f"{SHEETS_API}/{self.config.spreadsheet_id}/values/{self.SHEET_NAME}!A1:L1"
92
+ try:
93
+ data = await self._request("GET", url)
94
+ values = data.get("values", [])
95
+ if not values:
96
+ await self._append_rows([CALENDAR_HEADERS])
97
+ logger.info("Created content calendar headers")
98
+ except Exception as exc:
99
+ logger.warning(f"Failed to check/create headers: {exc}")
100
+
101
+ async def _append_rows(self, rows: list[list[str]]) -> None:
102
+ """Append rows to the content calendar sheet."""
103
+ url = f"{SHEETS_API}/{self.config.spreadsheet_id}/values/{self.SHEET_NAME}!A:L:append"
104
+ await self._request(
105
+ "POST",
106
+ url,
107
+ params={
108
+ "valueInputOption": "USER_ENTERED",
109
+ "insertDataOption": "INSERT_ROWS",
110
+ },
111
+ json={"values": rows},
112
+ )
113
+
114
+ async def publish_content(self, context: dict[str, Any]) -> dict[str, int]:
115
+ """Extract content from SharedContext and publish to the calendar.
116
+
117
+ Returns counts of rows added per agent.
118
+ """
119
+ if not self.config.spreadsheet_id:
120
+ logger.debug("No spreadsheet_id configured, skipping")
121
+ return {}
122
+
123
+ await self.ensure_headers()
124
+
125
+ rows: list[list[str]] = []
126
+ added: dict[str, int] = {}
127
+
128
+ from datetime import datetime
129
+
130
+ today = datetime.now().strftime("%Y-%m-%d")
131
+ day_name = datetime.now().strftime("%A")
132
+
133
+ # Kai content
134
+ kai = context.get("kai_content")
135
+ if isinstance(kai, dict) and kai.get("content"):
136
+ rev = kai.get("revision", {})
137
+ rows.append(
138
+ [
139
+ today,
140
+ day_name,
141
+ "Blog/Docs",
142
+ "Tutorial",
143
+ "DevRel",
144
+ "Kai",
145
+ kai.get("task", "")[:100],
146
+ kai.get("content", "")[:500],
147
+ "",
148
+ "draft",
149
+ str(rev.get("final_score", "")),
150
+ "",
151
+ ]
152
+ )
153
+ added["kai"] = 1
154
+
155
+ # Mox content
156
+ mox = context.get("mox_campaigns")
157
+ if isinstance(mox, dict) and mox.get("content"):
158
+ content_type = mox.get("content_type", "marketing")
159
+ platform = {
160
+ "blog": "Blog",
161
+ "social": "Social",
162
+ "landing_page": "Website",
163
+ "email_campaign": "Email",
164
+ }.get(content_type, "Marketing")
165
+ rows.append(
166
+ [
167
+ today,
168
+ day_name,
169
+ platform,
170
+ content_type,
171
+ "Growth",
172
+ "Mox",
173
+ mox.get("task", "")[:100],
174
+ mox.get("content", "")[:500],
175
+ "",
176
+ "draft",
177
+ str(mox.get("revision", {}).get("final_score", "")),
178
+ "",
179
+ ]
180
+ )
181
+ added["mox"] = 1
182
+
183
+ # Rex competitive intel
184
+ rex = context.get("rex_competitive")
185
+ if isinstance(rex, dict) and rex.get("competitors_discovered"):
186
+ comps = ", ".join(rex["competitors_discovered"][:5])
187
+ rows.append(
188
+ [
189
+ today,
190
+ day_name,
191
+ "Internal",
192
+ "Competitive Intel",
193
+ "Strategy",
194
+ "Rex",
195
+ f"Competitors: {comps}",
196
+ "",
197
+ "",
198
+ "complete",
199
+ "",
200
+ "",
201
+ ]
202
+ )
203
+ added["rex"] = 1
204
+
205
+ if rows:
206
+ try:
207
+ await self._append_rows(rows)
208
+ logger.info(f"Published {len(rows)} rows to content calendar")
209
+ except Exception as exc:
210
+ logger.warning(f"Failed to publish to sheets: {exc}")
211
+ return {}
212
+
213
+ return added
214
+
215
+ async def get_pending_content(self) -> list[dict[str, str]]:
216
+ """Fetch rows with status='draft' for editorial review."""
217
+ if not self.config.spreadsheet_id:
218
+ return []
219
+
220
+ url = f"{SHEETS_API}/{self.config.spreadsheet_id}/values/{self.SHEET_NAME}!A:L"
221
+ try:
222
+ data = await self._request("GET", url)
223
+ rows = data.get("values", [])
224
+ if len(rows) < 2:
225
+ return []
226
+ headers = rows[0]
227
+ pending = []
228
+ for row in rows[1:]:
229
+ padded = row + [""] * (len(headers) - len(row))
230
+ entry = dict(zip(headers, padded, strict=True))
231
+ if entry.get("Status", "").lower() == "draft":
232
+ pending.append(entry)
233
+ return pending
234
+ except Exception as exc:
235
+ logger.warning(f"Failed to fetch pending content: {exc}")
236
+ return []
@@ -0,0 +1,354 @@
1
+ Metadata-Version: 2.4
2
+ Name: devrel-origin
3
+ Version: 0.2.14
4
+ Summary: A 15-agent CLI that runs DevRel, sales, and marketing on your repo. BYO Anthropic or OpenRouter key.
5
+ Author-email: Daria Dovzhikova <dovzhikova@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/dovzhikova/devrel-origin
8
+ Project-URL: Repository, https://github.com/dovzhikova/devrel-origin
9
+ Project-URL: Issues, https://github.com/dovzhikova/devrel-origin/issues
10
+ Project-URL: Changelog, https://github.com/dovzhikova/devrel-origin/blob/main/CHANGELOG.md
11
+ Project-URL: Documentation, https://github.com/dovzhikova/devrel-origin/tree/main/docs
12
+ Keywords: devrel,developer-advocacy,ai-agents,anthropic,claude,marketing-automation,content-pipeline,competitive-intelligence,cli,pipx
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development
21
+ Classifier: Topic :: Software Development :: Documentation
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
23
+ Classifier: Topic :: Office/Business
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.12
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: httpx>=0.25.0
29
+ Requires-Dist: anthropic>=0.28.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Requires-Dist: scipy>=1.13.0
32
+ Requires-Dist: python-dotenv>=1.0.0
33
+ Requires-Dist: tenacity>=8.2.0
34
+ Requires-Dist: PyGithub>=2.1.1
35
+ Requires-Dist: typer>=0.12.0
36
+ Requires-Dist: rich>=13.7.0
37
+ Requires-Dist: tomli-w>=1.0.0
38
+ Requires-Dist: urllib3>=2.7.0
39
+ Provides-Extra: video
40
+ Requires-Dist: openai>=1.50.0; extra == "video"
41
+ Requires-Dist: playwright>=1.49.0; extra == "video"
42
+ Requires-Dist: pyautogui>=0.9.54; extra == "video"
43
+ Provides-Extra: seo
44
+ Requires-Dist: google-api-python-client>=2.150.0; extra == "seo"
45
+ Requires-Dist: google-auth-oauthlib>=1.2.0; extra == "seo"
46
+ Requires-Dist: google-auth-httplib2>=0.2.0; extra == "seo"
47
+ Requires-Dist: beautifulsoup4>=4.12.0; extra == "seo"
48
+ Provides-Extra: geo-google
49
+ Requires-Dist: google-search-results>=2.4.2; extra == "geo-google"
50
+ Provides-Extra: growth
51
+ Requires-Dist: devrel-origin[seo]; extra == "growth"
52
+ Provides-Extra: dev
53
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
54
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
55
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
56
+ Requires-Dist: respx>=0.20.2; extra == "dev"
57
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
58
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
59
+ Requires-Dist: build>=1.0.0; extra == "dev"
60
+ Requires-Dist: twine>=5.0.0; extra == "dev"
61
+ Requires-Dist: devrel-origin[growth,video]; extra == "dev"
62
+ Dynamic: license-file
63
+
64
+ # devrel-origin
65
+
66
+ **A developer-first CLI for AI-powered DevRel, sales, and marketing.**
67
+
68
+ `devrel-origin` is a `pipx`-installable command-line tool that runs a 15-agent system against any project — community triage, social listening, theme extraction, growth experiments, content production, video tutorials, documentation, competitive intel, sales outreach, brand-consistent campaigns, and post-publish content performance analysis. Operates on a project repo the way `git`, `npm`, and `cargo` do.
69
+
70
+ Every piece of content the system produces flows through an 8-stage editorial pipeline (developmental edit → line edit → copy edit → anti-slop → reader-persona test → readability check → brand audit) so output reads like senior-editor work, not generic AI prose.
71
+
72
+ > Every deliverable in this repository was produced by the agent system itself.
73
+
74
+ ---
75
+
76
+ ## Quick start
77
+
78
+ First content in five minutes. `devrel init` is now an interactive wizard
79
+ that walks you through scaffold → LLM key → health check → voice tuning →
80
+ first draft in one session.
81
+
82
+ ```bash
83
+ pipx install devrel-origin
84
+
85
+ cd /path/to/your/project
86
+ devrel init # interactive wizard, all the way to first draft
87
+ ```
88
+
89
+ The wizard:
90
+
91
+ 1. **Scaffolds `.devrel/`** with `config.toml`, `voice.md`, `style.md`,
92
+ `slop-blocklist.md`, `kb/`, `deliverables/`, `state.db`
93
+ 2. **Configures an LLM key** — pick Anthropic or OpenRouter (recommended:
94
+ free credits, no waitlist), validates with a one-token ping, writes to
95
+ `.devrel/.env` (chmod 600)
96
+ 3. **Runs a health check** — confirms env, scaffold, schema
97
+ 4. **Opens `voice.md` in `$EDITOR`** so you can drop in 3-5 sample passages
98
+ from your best published content
99
+ 5. **Generates your first content draft** — prompts for topic + type, calls
100
+ Kai through the full editorial pipeline, persists the draft +
101
+ grounding/code-validation trace
102
+
103
+ Skip flags for non-default flows:
104
+
105
+ ```bash
106
+ devrel init --skip-draft # wizard through voice edit, no LLM call
107
+ devrel init --skip-chain # scaffold only, you run auth/doctor/draft yourself
108
+ devrel init --non-interactive --name myproj --url ... --github-repo ...
109
+ # CI shape: scaffold only, no prompts
110
+ ```
111
+
112
+ After onboarding:
113
+
114
+ ```bash
115
+ devrel run # ad-hoc weekly pipeline (all 15 agents)
116
+ devrel schedule install # cron it (Mondays 09:00 UTC default)
117
+ ```
118
+
119
+ > **Why OpenRouter?** Lower onboarding barrier than Anthropic API access (no
120
+ > waitlist, free monthly credits) and supports per-agent model routing.
121
+ > The wizard recommends it.
122
+
123
+ Stuck? See [docs/troubleshooting.md](docs/troubleshooting.md) for the
124
+ common failures (OpenRouter 400, missing keys, ungrounded content,
125
+ quality-gate aborts) and their fixes.
126
+
127
+ After `devrel init`, your repo has a `.devrel/` directory with:
128
+
129
+ ```
130
+ .devrel/
131
+ config.toml # product identity, model selection, budget caps
132
+ voice.md # tone profile + sample passages (commit)
133
+ style.md # house style + per-content targets (commit)
134
+ slop-blocklist.md # banned phrases (commit)
135
+ kb/ # knowledge base, TF-IDF indexed
136
+ deliverables/ # generated outputs
137
+ state.db # SQLite: jobs, costs, checkpoints
138
+ ```
139
+
140
+ The four committed files (`config.toml`, `voice.md`, `style.md`, `slop-blocklist.md`) encode the editorial contract. Diff them like any other source.
141
+
142
+ ---
143
+
144
+ ## Commands
145
+
146
+ ```
147
+ # Bootstrap & health
148
+ devrel init bootstrap .devrel/ in cwd
149
+ devrel doctor [--json] check env, API keys, KB freshness
150
+ devrel cost [--month YYYY-MM] token + USD report from state.db
151
+
152
+ # Pipelines
153
+ devrel run full weekly cycle
154
+ devrel run --health health check only (Watchdog)
155
+ devrel run --agent NAME --task T run a single agent ad-hoc
156
+
157
+ # DevRel
158
+ devrel triage [--days N] GitHub issue triage (Sage)
159
+ devrel listen [--platforms ...] Reddit / HN / X (Echo)
160
+ devrel synthesize theme extraction (Iris)
161
+ devrel experiment HYPOTHESIS A/B + power analysis (Nova)
162
+
163
+ # Content
164
+ devrel content draft PROMPT revision-looped + 5-lever quality (Kai)
165
+ devrel content audit FILE run quality pipeline on existing draft
166
+ devrel content slop FILE run only the anti-slop pass
167
+ devrel docs build AST-based docs (Dex)
168
+ devrel video record SCRIPT screen-recorded tutorial (Vox)
169
+
170
+ # Sales
171
+ devrel intel COMPETITOR
172
+ devrel sales outreach COMPANY
173
+ devrel sales battlecard COMPETITOR
174
+ devrel sales sequence CAMPAIGN
175
+
176
+ # Marketing
177
+ devrel marketing blog TOPIC
178
+ devrel marketing landing TOPIC
179
+ devrel marketing social TOPIC
180
+ devrel marketing campaign BRIEF
181
+
182
+ # Knowledge base
183
+ devrel kb add URL [--category C]
184
+ devrel kb list
185
+ devrel kb refresh
186
+
187
+ # Config & schedule
188
+ devrel config get KEY
189
+ devrel config set KEY VALUE
190
+ devrel schedule install | list | remove
191
+
192
+ # Outputs
193
+ devrel deliverables list
194
+ devrel deliverables show NAME
195
+
196
+ # Analytics (Argus)
197
+ devrel analytics report [--since 7d] [--push] [--push-on-partial]
198
+ devrel analytics history CONTENT_ID
199
+ devrel analytics diff PERIOD_A PERIOD_B
200
+ devrel analytics calibration
201
+ devrel analytics summary [--root PATH]
202
+ ```
203
+
204
+ Global flags on most verbs: `--json` (machine-readable output) and `--quiet`.
205
+
206
+ ---
207
+
208
+ ## Editorial quality pipeline
209
+
210
+ Every content-producing run (`devrel content draft`, `devrel content audit`, plus internal calls from `marketing`, `sales`, `kb`-driven tutorials) flows through 8 stages:
211
+
212
+ ```
213
+ 1. Generate KB-grounded; voice.md + style.md in prompt
214
+ 2. Developmental critique+revise (structure, argument, hook)
215
+ 3. Line edit critique+revise (rhythm, voice fidelity)
216
+ 4. Copy edit critique+revise (grammar, code, consistency)
217
+ 5. Anti-slop regex blocklist + LLM lint; force-rewrite on hit;
218
+ second failure aborts loud with a phrase report
219
+ 6. Reader persona "skeptical senior backend dev" scores 1-10
220
+ 7. Readability Flesch + sentence variance + jargon density
221
+ checked against per-content-type targets
222
+ 8. Brand audit Sentinel (existing 6-dimension audit)
223
+
224
+ → deliverables/ + revision-trace.json (every stage's score + diff)
225
+ ```
226
+
227
+ Stages 5-7 use Haiku for cost; stages 2-4 use Sonnet. Total cost ≈ 2.5-4× a single revision loop, with prompt caching pulling toward the lower bound. BudgetGate guardrails (configurable in `.devrel/config.toml`) track spend; `devrel cost --month YYYY-MM` reports it.
228
+
229
+ ---
230
+
231
+ ## How it works internally
232
+
233
+ Hub-and-spoke with 15 agents. Atlas orchestrates; specialists execute across the pipelines.
234
+
235
+ ```
236
+ Atlas (Orchestrator)
237
+ ├── Health: Watchdog (pre-flight) + Sentinel (pre-publish brand audit) + Argus (post-publish performance analyst)
238
+ ├── DevRel: Sage, Echo, Iris, Nova, Kai, Vox, Dex
239
+ └── Sales: Rex, Pax, Mox
240
+ ```
241
+
242
+ The weekly cycle (driven by `devrel run`):
243
+
244
+ ```
245
+ Stage 0: Watchdog (health + budget check)
246
+ Stage 1: Sage + Echo + Dex parallel
247
+ Stage 2: Rex + Iris parallel
248
+ Stage 3: Nova + Kai parallel (Kai routes through quality pipeline)
249
+ Stage 4: Vox
250
+ Stage 5: Sentinel brand audit
251
+ Stage 5b: Argus post-publish content performance analysis
252
+ Stage 6: Instantly sync, OKR compilation, Sheets publish, digest
253
+ ```
254
+
255
+ Argus is config-gated by `[orchestration].analytics_in_run` (default `true`); set to `false` to skip the stage. Standalone use via `devrel analytics report` is unaffected.
256
+
257
+ The `Atlas.delegate()` API also dispatches single-agent tasks, which is what every non-`run` verb wraps. So `devrel triage` is `Atlas.delegate("sage", "Triage GitHub issues from the last 7 days")` — the agents never appear in the public CLI surface, only the verbs.
258
+
259
+ ---
260
+
261
+ ## Configuration
262
+
263
+ `.devrel/config.toml` example:
264
+
265
+ ```toml
266
+ [project]
267
+ name = "openclaw"
268
+ url = "https://openclaw.ai"
269
+ github_repo = "openclaw/openclaw"
270
+
271
+ [model]
272
+ default = "claude-sonnet-4-6"
273
+ cheap = "claude-haiku-4-5-20251001"
274
+ opus_opt_in = true
275
+
276
+ [budget]
277
+ monthly_usd = 100.0
278
+ warn_at_pct = 80
279
+ ```
280
+
281
+ Edit with `devrel config set <key> <value>` or directly in your editor.
282
+
283
+ ### Environment variables
284
+
285
+ | Variable | Required | Used by |
286
+ |----------|----------|---------|
287
+ | `ANTHROPIC_API_KEY` | yes | every LLM-using verb |
288
+ | `GITHUB_TOKEN` | for triage | Sage |
289
+ | `FIRECRAWL_API_KEY` | for KB harvest + intel | `kb add`, Echo, Rex |
290
+ | `BRAVE_API_KEY` | optional fallback | search |
291
+ | `INSTANTLY_API_KEY` | for cold-email sync | Pax, Mox |
292
+ | `APOLLO_API_KEY` | for lead enrichment | Rex, Pax |
293
+ | `TELEGRAM_BOT_TOKEN` | for digests | Atlas pipeline |
294
+ | `EMAIL_SENDER` / `EMAIL_PASSWORD` | for digests | Atlas pipeline |
295
+ | `OPENAI_API_KEY` | for video TTS | Vox |
296
+
297
+ `.env` files at the project root are loaded automatically. Cross-project shared keys can live at `~/.devrel/secrets.env`.
298
+
299
+ ---
300
+
301
+ ## Retargeting to another product
302
+
303
+ ```bash
304
+ cd /path/to/other-project
305
+ devrel init --name otherproduct --url https://otherproduct.dev --github-repo owner/otherproduct
306
+ devrel kb add https://otherproduct.dev/docs --category docs
307
+ # edit voice.md / style.md / slop-blocklist.md to match the other product's voice
308
+ devrel doctor
309
+ devrel run
310
+ ```
311
+
312
+ The agent system is product-agnostic. Per-project config + KB + voice files do all the targeting.
313
+
314
+ ---
315
+
316
+ ## Documentation
317
+
318
+ The user-facing docs live in [`docs/`](docs/):
319
+
320
+ - [`docs/quickstart.md`](docs/quickstart.md) — install, configure an LLM key, ship your first grounded draft in 5 minutes
321
+ - [`docs/troubleshooting.md`](docs/troubleshooting.md) — common failures and fixes (OpenRouter 400, missing keys, ungrounded content, quality-gate aborts)
322
+ - [`docs/agents/argus.md`](docs/agents/argus.md) — content performance analyst, the 13th agent
323
+ - [`docs/cli/analytics.md`](docs/cli/analytics.md) — full reference for the `devrel analytics` subgroup
324
+ - [`docs/cookbook.md`](docs/cookbook.md) — common recipes (calibration, weekly cron, multi-project rollups)
325
+
326
+ Internal docs (architecture specs, implementation plans) live in [`docs/superpowers/`](docs/superpowers/).
327
+
328
+ ---
329
+
330
+ ## Tech stack
331
+
332
+ | Component | Choice |
333
+ |---|---|
334
+ | Language | Python 3.12+ |
335
+ | CLI framework | Typer + Rich |
336
+ | Agent SDK | Claude Agent SDK |
337
+ | HTTP | httpx (async) |
338
+ | Default model | Claude Sonnet 4.6 (Haiku for cheap quality stages, Opus opt-in) |
339
+ | Stats | scipy (power analysis, Bayesian eval) |
340
+ | Video | Playwright + FFmpeg + OpenAI TTS |
341
+ | Storage | SQLite per project (.devrel/state.db) |
342
+ | Tests | pytest + pytest-asyncio + respx |
343
+
344
+ ---
345
+
346
+ ## Author
347
+
348
+ **Daria Dovzhikova** — DevTools Growth Strategist & AI Agent Builder
349
+ - 12+ years in DevTools (JetBrains, Huawei, Lightrun, Odigos)
350
+ - [dariadovzhikova.com](https://dariadovzhikova.com)
351
+
352
+ ---
353
+
354
+ MIT License
@@ -0,0 +1,98 @@
1
+ devrel_origin/__init__.py,sha256=XRNSIc1olNqGhFlCMKpssCvrze02SYNa6AX7PnZ1vXY,585
2
+ devrel_origin/cli/__init__.py,sha256=N7fVM2zuvUCa8f7UN4vu0se83xQ5pUFvZwBvOdf2bDg,3110
3
+ devrel_origin/cli/_common.py,sha256=R6HmwwoB5Ude549EPZ4r7I3elk7KtLucM4UQ8FcVBNI,9508
4
+ devrel_origin/cli/analytics.py,sha256=hF0diLs__4R9gbDCZScgy0DTs75LIhvLPPWX7KlFkKg,730
5
+ devrel_origin/cli/argus.py,sha256=ce6LMETAlI5KP4txbSQd6uKOV7X3Re1xhLDEsw0SPFY,18242
6
+ devrel_origin/cli/auth.py,sha256=AViGsxnFEXVrCdv8EIIrut2kHwx4Syaa09ccLosm4ys,7807
7
+ devrel_origin/cli/config.py,sha256=kYoVZt8mCfJ24W8q_o9Ysoac16jmyb7G3MiJv9YX5rM,3091
8
+ devrel_origin/cli/content.py,sha256=opO7DiGVQk0pgT-n1QcskKQPr6FoutOu_KhxffmQSFM,9786
9
+ devrel_origin/cli/cost.py,sha256=4fnbFxv4ZI2MjQRYmebyhDd6JyK0lP0i810n285QGpE,3467
10
+ devrel_origin/cli/cro.py,sha256=Kmr-tRPnCak4I52JL_L-9Oig7x_Iuyjhjo-OfuGMg84,10282
11
+ devrel_origin/cli/deliverables.py,sha256=XbwS0qqeluIWX31hUI2okp__Xuql2TyZ3v4tauPsl3g,2275
12
+ devrel_origin/cli/docs.py,sha256=MuMJJ-xNYD0kIf0xBFy8c2XkdIsdqwVEo3KUqaob_jQ,3234
13
+ devrel_origin/cli/doctor.py,sha256=UXicW5eNJDqV3C4HIYYlxFjN4meuwdK33gCK2MliB1s,5454
14
+ devrel_origin/cli/experiment.py,sha256=BzwLebzo4ncDOhVyqau-xNjbkXTYsrD7qLbaO-UBu4k,840
15
+ devrel_origin/cli/growth.py,sha256=1QYYCppcnqgQamGfBbb7QniH2pkdQNTEvf3siwG98Ak,3349
16
+ devrel_origin/cli/init.py,sha256=iJ_6j7QKqIbXWaPTm6_qRN3kKQBNDUwvIVszBEdHri4,17304
17
+ devrel_origin/cli/intel.py,sha256=hTlsElzimle-xELMpZVu5n9S2bl334XuXBrF21C_y5E,790
18
+ devrel_origin/cli/kb.py,sha256=cGc4HydPi2SOifODxMxWpn6KzJXZVDXji6Lk9UYTZQw,3025
19
+ devrel_origin/cli/listen.py,sha256=UCvJZt5egNdPpA5hiTyBZb3VWBFLvotm7KkHM61QSAY,871
20
+ devrel_origin/cli/marketing.py,sha256=_gPJzF_6aDwxim6prfcD17dccqgrU4mhlzjTfDYYvHQ,1873
21
+ devrel_origin/cli/migrate.py,sha256=0QYHHHwdIp4Q5e1v_8BmUXyhv3WV-bXNUQzvCr6ssYE,1521
22
+ devrel_origin/cli/run.py,sha256=QFTb23m3sT6hcq0JV-jyZi8sVn9i1xREMjmV5bgWVYg,1709
23
+ devrel_origin/cli/sales.py,sha256=3-ZgqT96SEqaX_HZElf0_g9uM97V3iSupRpHjl85WnU,1677
24
+ devrel_origin/cli/schedule.py,sha256=QcGPqMHCcuK_7Z_6eiy7CYMkT7dJvDKsCHy019axfy4,1903
25
+ devrel_origin/cli/synthesize.py,sha256=MuHNzCof3g5A6G_FxxMzzd24B2Sf80VTCf0IwEzb5-A,769
26
+ devrel_origin/cli/triage.py,sha256=WuQrMyPPxMg_ssVIxZ59DKX-j_7832i5YUhN36T6nig,820
27
+ devrel_origin/cli/video.py,sha256=qMtY64RVtgB00mUUR8nKVZA97bmVXbQdjXhjMYNGyAk,976
28
+ devrel_origin/core/__init__.py,sha256=RCjyqLBFsotZLCW4QvHQNryF1CLL-9mCawe6vD_xJCM,1263
29
+ devrel_origin/core/agent_config.py,sha256=VUdnNxSH2JnDMDX-b6NHub3Ov_4GjRN6daEdbZDzaSA,2871
30
+ devrel_origin/core/argus.py,sha256=eN1nFmO4pYXiPwLZqQVFgEsPoCE8Rk-IRUNx-WwYqNc,36781
31
+ devrel_origin/core/atlas.py,sha256=IOC5x3oPsqH8GMTu8L3-fBHAvNMSyMG8zLdBqx5r0cA,59514
32
+ devrel_origin/core/base.py,sha256=7u73eFdLff63iA_QNJ8fLMczIerAYJYUK4AUUqVkMG8,11099
33
+ devrel_origin/core/cyra.py,sha256=5k9NXxX5Uh8wGK0rTEJ9cJ6mi_PW5p64EPM8_pWA5Kw,20450
34
+ devrel_origin/core/dex.py,sha256=kBPeGOT49iNqv-OaJV_fIRNUiEj0K0gcAAsDzkeLzHk,26462
35
+ devrel_origin/core/echo.py,sha256=lq78Wf745eUUcSI2CXDx8Wz1PELdwxq0LqAy58JekFY,21100
36
+ devrel_origin/core/iris.py,sha256=iDbOe00P9pg8pxh9ifSV5rIc6Sw4mm5zxM-P6jjg7HA,20274
37
+ devrel_origin/core/kai.py,sha256=iT-7f7E2cetioy24cOxVw7sBXbWzKzqsoLw1_PEFCBI,59491
38
+ devrel_origin/core/llm.py,sha256=6o4fb5O2esTuDZsFY6YUgCcYSKQIgZJP_CC9xA_pOlc,20651
39
+ devrel_origin/core/llm_backends.py,sha256=_pjWgiNKwoQw6Lva6FBZlcRtJIXeGAOp3iveWV2Doc4,10198
40
+ devrel_origin/core/mox.py,sha256=hfA7GigqsfHy8ylxYvTd2wLF3SUnks6fZvoJy1S0Z_I,19163
41
+ devrel_origin/core/nova.py,sha256=v2K7KBKIWPjjYMs_e2eWghbI4DE6y0LUm1crb3XLj4Y,13676
42
+ devrel_origin/core/pax.py,sha256=u4hBDWwJq2iLvTGEklUUeGKYqcyYU9AvxZPyCYm2o3o,45965
43
+ devrel_origin/core/rex.py,sha256=sfv5uI_QBijbKcqbULBn_PxO6anEUozMwPoNzmTOk9Q,18883
44
+ devrel_origin/core/sage.py,sha256=fkkHh5GHv-WKBmEm86xk_VxEmeAL2EKorcKhe9uuQxM,17800
45
+ devrel_origin/core/sentinel.py,sha256=tDalxI66IU_85GQvC-SO78_emAY0i-XPKzUWIsC8V5k,12899
46
+ devrel_origin/core/types.py,sha256=rq3ump2gWzzPwEa4gs2PsKEyX-5Fe_abmBnA7nqCfoA,2087
47
+ devrel_origin/core/vox.py,sha256=s3B4fgPg6pQX8cXjPUCX3iBdNT9EHX2VtFFSpNKZXFM,9970
48
+ devrel_origin/core/watchdog.py,sha256=eTmhg3JsD0-auO-rnXB13UTRTDwaW2imhxbwJ6A-zIk,11286
49
+ devrel_origin/core/growth/__init__.py,sha256=ltfr5Br_TiYDvuwW3aEd737zxmP7AOiRvM7xs92xIxw,594
50
+ devrel_origin/core/growth/recommendations.py,sha256=NSweaItgSteQP3G2c5rgTPKKXPYqw2tYgrg15kNQfMA,7560
51
+ devrel_origin/core/growth/target_kinds.py,sha256=6ig977X50kT4xMb9XwcXmsKqwePXLs13Lcxk1hW_64M,1684
52
+ devrel_origin/core/video/__init__.py,sha256=E-xEzaZ3ISr9zwwcf3gAVAreKB4o-UkB3qN_XDh0lVQ,771
53
+ devrel_origin/core/video/assembler.py,sha256=r6TCikQcCmNOvuGFk4GSDr1Jzz6dXoKDEv7dtoxOidI,4697
54
+ devrel_origin/core/video/browser_recorder.py,sha256=uX-HATHh3v4RpYwkKu8lXwgdSxvZJbDWCUvPnLkR-oI,4439
55
+ devrel_origin/core/video/desktop_recorder.py,sha256=kVkbJWhq-7gxf_WBAXT6T7Cp151oagZuNTfKmFLkk30,9392
56
+ devrel_origin/core/video/overlay_renderer.py,sha256=F9LMDS2IQLn3oUMLy4ALZWtmPX2v0ovX5JKxFZob9_c,5059
57
+ devrel_origin/core/video/script_parser.py,sha256=nr6zT5utFryCKXZyqbrLBNhEZ5zv9BPKW7Xf8iqwBOI,4563
58
+ devrel_origin/core/video/tts_engine.py,sha256=c4WcyvWzWi_oyeHn-qIz6FumrB_GCdvReq_icsaltHA,2538
59
+ devrel_origin/project/__init__.py,sha256=_eVaeNQaC30P0IcCQhXB7BXn9bou4XmKnjoLn-jA8nQ,66
60
+ devrel_origin/project/config.py,sha256=u6tiM2OoRPkncv41DhTeOStB0-Idr6E9bSoKMIEj9SY,2506
61
+ devrel_origin/project/cost_sink.py,sha256=eGBGsn4_FCAI1tqbTeV51GTsyHl8K7m8XP7paULEucc,2241
62
+ devrel_origin/project/init.py,sha256=lRCxjifF4dbU2UK2Mq8IUbsJtBczMPTQ3V-rkcKwyAA,3522
63
+ devrel_origin/project/paths.py,sha256=iCjZGlmQtE-qyQgVrd59UIKSgrPKk-1wW9mSWI60XkI,2236
64
+ devrel_origin/project/state.py,sha256=Kw1aX4BSIX4pkTHTbYPhTWIwMxGGG5qO2l3M7iso79c,7785
65
+ devrel_origin/project/templates/__init__.py,sha256=B73blGm73tDzoyUL_Nzl6r9UBRgos61iiUqF41lXy4A,144
66
+ devrel_origin/project/templates/config.toml,sha256=DDkrySUAxnCewksEKIAe90tJj9qcV-vG79umxPBP8Vs,870
67
+ devrel_origin/project/templates/devrel.gitignore,sha256=pEJ_5o01w5LAComVzdmVmffDVRwCFbmvRjCNOfQYyDs,286
68
+ devrel_origin/project/templates/slop-blocklist.md,sha256=q7MkP9pbFgpcN2-zsxKCByKIew7rC8-EOq3tFt6sLSE,800
69
+ devrel_origin/project/templates/style.md,sha256=qi9tmKo-_XUNmlPOtLqI9WCCL_Mcc2SMYv9uRDojKDY,936
70
+ devrel_origin/project/templates/voice.md,sha256=3drXVMWE_Oyh6xgvDlkPGrzeWLArne-m6bL1FwIo3Qc,970
71
+ devrel_origin/quality/__init__.py,sha256=m-yJRZ-qUmD7DImL7Xjd6A5HNl1g-dFDqB_YXfFvu0w,2636
72
+ devrel_origin/quality/editorial.py,sha256=r35OqyFUZ22pBIt5lJzumPDA5ASh93uSrEq6LvPd83Q,11250
73
+ devrel_origin/quality/persona.py,sha256=JZ-7wmwuSErTWQyzcMia-FHhHqmWAb9G1h-jAus2y5Y,2783
74
+ devrel_origin/quality/readability.py,sha256=Hqf5KjozPPY94b0NSNL9P8UOWq5R_DNPxuZeTut_eEQ,5107
75
+ devrel_origin/quality/slop.py,sha256=tfcV3-7Qm-W-ffuCyepLr-NPp9ecrQDkkzm21Zhps-8,6063
76
+ devrel_origin/quality/style.py,sha256=hdRPP-6MSJkdDv7w_0Qpq8RqCUR2o9pG5KGeChnxPZo,3642
77
+ devrel_origin/quality/voice.py,sha256=4aN5pciJdQy02VwsYv-uIionVKFXf9Ef6ZJz12WAWX0,515
78
+ devrel_origin/tools/__init__.py,sha256=nK8FUFcVsn6MP8X_3z3lXpNwfwi4IQ6v_qUrcmuzYRc,328
79
+ devrel_origin/tools/analytics.py,sha256=ZZYSn2iQoKtXodZzrRguDfFxvFM8ATSbrVkHsJw5yBs,11102
80
+ devrel_origin/tools/api_client.py,sha256=0ORz7F3phcpQYSt4Vz_e8czPVkFth3vtrZa7ljLqW20,13629
81
+ devrel_origin/tools/apollo_client.py,sha256=DbXemkljMz6lmsmrdPsAqSjCJTsG_ug6C30sEf89lOI,10321
82
+ devrel_origin/tools/code_validator.py,sha256=xA2ogo4B4pyoSkfG9pMbHYbrpLjKMdHzpQs-MuCL_Bg,14433
83
+ devrel_origin/tools/github_tools.py,sha256=U4tP7eMuM-OMC-TNXdYbPNX3nz05xj4PoXlAFGlNFW0,9642
84
+ devrel_origin/tools/instantly_client.py,sha256=H37L_ACMUf1yDILgYS4MzsvUBn9MhKwEh1hn-fE6fas,13838
85
+ devrel_origin/tools/kb_harvester.py,sha256=IpMWayHZza40wk6FWlwyeg9DlxbwNWMx4K9QA1JOa9s,11615
86
+ devrel_origin/tools/mcp_server.py,sha256=wr4K2d_goKGmY-clNdSZPpU6z8DdSm5Vk-xFtwpUqb8,21382
87
+ devrel_origin/tools/notifications.py,sha256=CnDqMAcAwCMNrpN_1H2D-niV__mnmJ3eYvscibJ37ig,9984
88
+ devrel_origin/tools/run_report.py,sha256=4NSkKMPqVrfFMOgQngHLoUOlkCZ35AjTG9BNWQyONic,6521
89
+ devrel_origin/tools/scheduler.py,sha256=ke_5n_QI08_YtdIgopiyCaBCcVoNguzjDq-KMj7o0_c,7359
90
+ devrel_origin/tools/search_tools.py,sha256=6aYRLMtJltLVIWPv_M5mUOJJcCM0qdqjisa7AbTkY4Y,11532
91
+ devrel_origin/tools/self_improve.py,sha256=J-hLbltJ17IxDqyz1-dCfTtMz4KdWxCaHzMrnhEiG-I,5381
92
+ devrel_origin/tools/sheets.py,sha256=WUEsQz7TjA-dMKPEFVwIFxnn4C9PzcTw3GpM4YIPetM,7257
93
+ devrel_origin-0.2.14.dist-info/licenses/LICENSE,sha256=1nyNN0gSFeC1_agCa0to7zYB52KmMk0NpRQeFnVzTnA,1073
94
+ devrel_origin-0.2.14.dist-info/METADATA,sha256=icy-KzVZ2VRqT_Ueyl_OvKyFAvOlLe8i3mc4Vrx0WZ0,13503
95
+ devrel_origin-0.2.14.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
96
+ devrel_origin-0.2.14.dist-info/entry_points.txt,sha256=-YEl3yJw4Au3B9HYn_XJ0eOHAPJWKeWg2JoKSVPnFws,49
97
+ devrel_origin-0.2.14.dist-info/top_level.txt,sha256=Wi9qS2xsthK7-S28ybs-4PK1WgI6qRF15EZx-fdrtDA,14
98
+ devrel_origin-0.2.14.dist-info/RECORD,,