@firatcand/roster 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -0
  3. package/agents/critic.md +74 -0
  4. package/agents/enricher.md +56 -0
  5. package/agents/lesson-drafter.md +64 -0
  6. package/agents/pattern-detector.md +62 -0
  7. package/agents/promotion-arbiter.md +71 -0
  8. package/agents/prospector.md +51 -0
  9. package/agents/writer.md +58 -0
  10. package/bin/roster.js +2093 -0
  11. package/lib/.gitkeep +0 -0
  12. package/package.json +68 -0
  13. package/skills/chief-of-staff/SKILL.md +218 -0
  14. package/skills/dreamer/SKILL.md +112 -0
  15. package/skills/roster-orchestrator/SKILL.md +122 -0
  16. package/skills/sdr/SKILL.md +147 -0
  17. package/templates/CLAUDE.project.template.md +45 -0
  18. package/templates/CONTEXT.template.md +51 -0
  19. package/templates/env.example +25 -0
  20. package/templates/gitignore-defaults.txt +28 -0
  21. package/templates/scaffold/.config/functions.yaml +22 -0
  22. package/templates/scaffold/chief-of-staff/README.md +86 -0
  23. package/templates/scaffold/chief-of-staff/agent.md +122 -0
  24. package/templates/scaffold/chief-of-staff/logs/.gitkeep +0 -0
  25. package/templates/scaffold/chief-of-staff/plans/add-agent-to-project.yaml +45 -0
  26. package/templates/scaffold/chief-of-staff/plans/archive-project.yaml +51 -0
  27. package/templates/scaffold/chief-of-staff/plans/audit-agent.yaml +32 -0
  28. package/templates/scaffold/chief-of-staff/plans/audit-project.yaml +34 -0
  29. package/templates/scaffold/chief-of-staff/plans/audit-repo.yaml +26 -0
  30. package/templates/scaffold/chief-of-staff/plans/create-agent.yaml +123 -0
  31. package/templates/scaffold/chief-of-staff/plans/create-function.yaml +48 -0
  32. package/templates/scaffold/chief-of-staff/plans/create-project.yaml +65 -0
  33. package/templates/scaffold/chief-of-staff/plans/remove-agent-from-project.yaml +50 -0
  34. package/templates/scaffold/chief-of-staff/plans/rename-project.yaml +62 -0
  35. package/templates/scaffold/chief-of-staff/plans/unarchive-project.yaml +41 -0
  36. package/templates/scaffold/chief-of-staff/playbook/.gitkeep +0 -0
  37. package/templates/scaffold/conventions.md +608 -0
  38. package/templates/scaffold/design/.gitkeep +0 -0
  39. package/templates/scaffold/design/EXPERT.md +68 -0
  40. package/templates/scaffold/dreamer/README.md +32 -0
  41. package/templates/scaffold/dreamer/agent.md +101 -0
  42. package/templates/scaffold/dreamer/logs/.gitkeep +0 -0
  43. package/templates/scaffold/dreamer/pending/.gitkeep +0 -0
  44. package/templates/scaffold/dreamer/plans/nightly-reflection.yaml +113 -0
  45. package/templates/scaffold/dreamer/playbook/.gitkeep +0 -0
  46. package/templates/scaffold/dreamer/state.md +13 -0
  47. package/templates/scaffold/dreamer/subagents/lesson-drafter.md +56 -0
  48. package/templates/scaffold/dreamer/subagents/pattern-detector.md +55 -0
  49. package/templates/scaffold/dreamer/subagents/promotion-arbiter.md +64 -0
  50. package/templates/scaffold/gtm/EXPERT.md +83 -0
  51. package/templates/scaffold/gtm/sdr/.claude/settings.json +3 -0
  52. package/templates/scaffold/gtm/sdr/.mcp.json +21 -0
  53. package/templates/scaffold/gtm/sdr/README.md +46 -0
  54. package/templates/scaffold/gtm/sdr/agent.md +136 -0
  55. package/templates/scaffold/gtm/sdr/plans/cold-outreach.yaml +92 -0
  56. package/templates/scaffold/gtm/sdr/playbook/.gitkeep +0 -0
  57. package/templates/scaffold/gtm/sdr/projects/_demo/asset-references.md +7 -0
  58. package/templates/scaffold/gtm/sdr/projects/_demo/config/default.yaml +69 -0
  59. package/templates/scaffold/gtm/sdr/projects/_demo/log/feedback/.gitkeep +0 -0
  60. package/templates/scaffold/gtm/sdr/projects/_demo/log/runs/.gitkeep +0 -0
  61. package/templates/scaffold/gtm/sdr/projects/_demo/playbook/.gitkeep +0 -0
  62. package/templates/scaffold/gtm/sdr/subagents/critic.md +67 -0
  63. package/templates/scaffold/gtm/sdr/subagents/enricher.md +49 -0
  64. package/templates/scaffold/gtm/sdr/subagents/prospector.md +44 -0
  65. package/templates/scaffold/gtm/sdr/subagents/writer.md +51 -0
  66. package/templates/scaffold/logs/cron/.gitkeep +0 -0
  67. package/templates/scaffold/ops/.gitkeep +0 -0
  68. package/templates/scaffold/ops/EXPERT.md +84 -0
  69. package/templates/scaffold/product/.gitkeep +0 -0
  70. package/templates/scaffold/product/EXPERT.md +87 -0
  71. package/templates/scaffold/projects/_demo/CLAUDE.md +35 -0
  72. package/templates/scaffold/projects/_demo/README.md +16 -0
  73. package/templates/scaffold/projects/_demo/assets/.gitkeep +0 -0
  74. package/templates/scaffold/projects/_demo/config/default.yaml +28 -0
  75. package/templates/scaffold/projects/_demo/guidelines/asset-links.md +15 -0
  76. package/templates/scaffold/projects/_demo/guidelines/brand-book.md +25 -0
  77. package/templates/scaffold/projects/_demo/guidelines/icps/_persona-template.md +44 -0
  78. package/templates/scaffold/projects/_demo/guidelines/messaging.md +20 -0
  79. package/templates/scaffold/projects/_demo/guidelines/voice.md +29 -0
  80. package/templates/scaffold/projects/_demo/state.md +11 -0
  81. package/templates/scaffold/scripts/lib/README.md +13 -0
  82. package/templates/scaffold/scripts/lib/functions.sh +89 -0
  83. package/templates/scaffold/scripts/new-project.sh +125 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Firat Dogan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,272 @@
1
+ ![banner](https://raw.githubusercontent.com/firatcand/roster/7095215fd4224709f47d69270f35201b1c3206ce/roster-banner%402x.png)
2
+
3
+
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ # Roster
7
+
8
+ > A CLI that installs and scaffolds an opinionated multi-agent workspace for Claude Code today, with Codex CLI and Gemini support landing in v0.2 — role-based agents for GTM, product, design, and ops, with a reinforcement loop that compounds learning.
9
+
10
+ ## What is this?
11
+
12
+ `@firatcand/roster` is an npm CLI. You run it once and it does two things:
13
+
14
+ 1. **`roster install`** — copies a curated set of skills and agent definitions into your AI coding tool's config dir. Detects and installs to `~/.claude/`, `~/.codex/`, and `~/.gemini/`.
15
+ 2. **`roster init`** — scaffolds a structured agent-team workspace in any directory. v0.1 produces the minimal scaffold (`CLAUDE.md` + `projects/_demo/`); v0.2 adds the full tree (function dirs, role-based agents, maintenance agent, reinforcement agent).
16
+
17
+ The workspace it scaffolds separates **substrate** (strategic context: brand voice, ICPs, messaging) from **artifacts** (daily output: emails, posts, components), and runs work through named YAML **plans** that are deterministic, auditable, and schedule-friendly.
18
+
19
+ If you're a solo founder or ≤5-person team using Claude Code (or Codex / Gemini) and you need outbound, content, design, and ops work done without losing context between sessions — this might fit.
20
+
21
+ ## Getting started
22
+
23
+ First-time install and first run — under 10 minutes on a Mac with Node ≥ 22.
24
+
25
+ ```bash
26
+ # 1. Install skills + agents into your AI tool's config dir
27
+ npx @firatcand/roster install
28
+
29
+ # 2. Scaffold a workspace in a fresh directory
30
+ mkdir my-team && cd my-team
31
+ npx @firatcand/roster init
32
+
33
+ # 3. Open Claude Code in that directory
34
+ claude
35
+
36
+ # 4. Run the demo SDR plan
37
+ /sdr run cold-outreach for _demo
38
+
39
+ # 5. Read the run log and provide feedback — lessons surface
40
+ # in dreamer/pending/ on the next nightly reinforcement pass.
41
+ ```
42
+
43
+ > Until v0.1 is published to npm, install locally with `npm pack && npm install -g firatcand-roster-*.tgz` from a clone. See [docs/roadmap.md](docs/roadmap.md) for publish status.
44
+
45
+ [docs/HOWTO.md](docs/HOWTO.md) has the long-form step-by-step.
46
+
47
+ ### What `roster install` looks like
48
+
49
+ ```
50
+ $ npx --yes @firatcand/roster install --all
51
+
52
+ roster v0.1.0
53
+ Multi-agent workspace scaffolder for Claude Code, Codex CLI, and Gemini.
54
+
55
+ ✓ Claude Code — 3 skills → ~/.claude/skills, 7 agents → ~/.claude/agents
56
+ ✓ Codex CLI — 4 skills → ~/.codex/skills, 7 agents → ~/.codex/agents
57
+ ✓ Gemini CLI — 3 skills → ~/.gemini/extensions, 7 agents → ~/.gemini/agents
58
+
59
+ Next: roster init to scaffold a workspace.
60
+ ```
61
+
62
+ Without `--all`, you'll get an interactive checkbox to pick which tools to receive the skills + agents. Exit codes: 0 success, 1 error, 2 cancelled, 3 no tools detected.
63
+
64
+ ## Subcommands
65
+
66
+ | Command | What it does |
67
+ |---|---|
68
+ | `roster install` | Detect installed AI tools, prompt for selection, copy skills + agents into each tool's config dir. Idempotent. |
69
+ | `roster install --all` | Install to every detected tool, non-interactive (good for CI / scripted migration). |
70
+ | `roster install --tool <name>` | Install to a single named tool (`claude`, `codex`, or `gemini`), non-interactive. |
71
+ | `roster init [name]` | Scaffold the agent-team workspace into CWD. Substitutes `{{PROJECT_NAME}}`. |
72
+ | `roster doctor` | Audit installed skills/agents per AI tool; exits non-zero on drift. Includes a Scheduling section that runs `schedule validate` against the current workspace. |
73
+ | `roster schedule validate` | Validate every `roster/<function>/schedules.yaml` file in the workspace. `--json` / `--silent` / `--cwd <dir>`. Exits non-zero on schema or cron errors. |
74
+ | `roster --help` / `--version` | Usage + version from `package.json`. |
75
+
76
+ ## Tool support
77
+
78
+ | Tool | Status | Skills installed to | Agents installed to |
79
+ |---|---|---|---|
80
+ | Claude Code | Supported | `~/.claude/skills/<skill>/` (directory per skill) | `~/.claude/agents/<agent>.md` |
81
+ | Codex CLI | Supported | `~/.codex/skills/<skill>/` (directory per skill) | `~/.codex/agents/<agent>.md` |
82
+ | Gemini CLI | Supported | `~/.gemini/extensions/<skill>/` (directory per skill) | `~/.gemini/agents/<agent>.md` |
83
+ | Cursor | **Out of scope** — see [docs/roadmap.md](docs/roadmap.md) | — | — |
84
+
85
+ Detection is presence-only: roster considers a tool installed if its config root exists. Override via `ROSTER_CLAUDE_HOME` / `ROSTER_CODEX_HOME` / `ROSTER_GEMINI_HOME` (used by the test suite).
86
+
87
+ ## What roster installs
88
+
89
+ `roster install` copies three skills and seven agents into each detected tool's config dir. Skills are the entry points (one per agent function); agents are the building blocks the skills call.
90
+
91
+ **Skills**
92
+
93
+ | Skill | Purpose |
94
+ |---|---|
95
+ | `chief-of-staff` | Repo maintenance for roster workspaces — create, archive, rename, and audit projects, agents, and functions. Wraps `scripts/` with confirmation gates for destructive operations. |
96
+ | `dreamer` | Off-hours reflection. Reads recent runs + feedback, detects recurring patterns, drafts lesson candidates, and writes approved lessons to the right playbook scope. The only agent that writes to playbook files. |
97
+ | `sdr` | Cold outreach for a project — find prospects matching an ICP, enrich, draft personalized first-touch messages in the project's voice, and route through HITL approval. |
98
+
99
+ **Agents** (called by skills, not invoked directly)
100
+
101
+ | Agent | Owner skill | Purpose |
102
+ |---|---|---|
103
+ | `critic` | `sdr` | Reviews drafts for tone, brand fit, risk, compliance. Returns pass/fail with specific feedback. Does not rewrite. |
104
+ | `enricher` | `sdr` | Fills missing fields on prospects (recent posts, company news) via Apollo, HeyReach, web search. Does not score or contact. |
105
+ | `prospector` | `sdr` | Finds prospects matching ICP criteria. Read-only — no enrichment beyond search, no contact, no CRM writes. |
106
+ | `writer` | `sdr` | Drafts a single first-touch message for a single prospect using enrichment context and lessons. Does not send. |
107
+ | `lesson-drafter` | `dreamer` | Takes a candidate pattern and drafts a lesson file in the schema defined by `conventions.md`. One lesson per invocation. |
108
+ | `pattern-detector` | `dreamer` | Reads runs + matched feedback, returns raw candidate patterns with cited evidence. Returns everything that recurs. |
109
+ | `promotion-arbiter` | `dreamer` | Decides whether a project-validated lesson should be promoted to global, kept project-specific, or marked as conflicting. Decisions only. |
110
+
111
+ Every skill and agent ships with version `0.1.0` (frontmatter pin). `roster doctor` will surface drift between installed and shipped versions in v0.2.
112
+
113
+ ## What `init` scaffolds
114
+
115
+ `roster init` is non-destructive — re-running merges new files in without overwriting your edits. The full scaffold:
116
+
117
+ ```
118
+ my-team/ ← full layout
119
+ ├── CLAUDE.md, conventions.md ← workspace-level context
120
+ ├── gtm/, product/, design/, ops/ ← functions (top-level domains)
121
+ │ ├── EXPERT.md ← function-level expert (substrate-shaping)
122
+ │ └── <agent-role>/ ← role-based agents (sdr, ux-designer, ...)
123
+ │ ├── agent.md ← contract: purpose, inputs, plans, outputs
124
+ │ ├── plans/*.yaml ← named workflows the agent can run
125
+ │ ├── subagents/*.md ← reusable building blocks
126
+ │ └── projects/<project>/ ← per-project instance with config + logs
127
+ ├── projects/<project>/ ← project-level shared substrate
128
+ │ └── CLAUDE.md, guidelines/ ← voice, ICPs, messaging, brand-book
129
+ ├── chief-of-staff/ ← cross-cutting maintenance agent
130
+ ├── dreamer/ ← cross-cutting reinforcement agent
131
+ ├── scripts/ ← backing scripts (create/archive/audit/rename)
132
+ └── .claude/commands/ ← workspace-level slash commands
133
+ ```
134
+
135
+ The two big ideas behind the layout:
136
+
137
+ 1. **Substrate vs artifacts**: experts shape substrate (project guidelines), agents produce artifacts (specific outputs). Don't conflate them.
138
+ 2. **Plans**: each agent has named plans (YAML workflow recipes). Cron-friendly. Auditable. Reusable.
139
+
140
+ ## Migrating from agent-team
141
+
142
+ If you've been running the original `~/repos/agent-team` layout, here's the verbatim migration. Project substrate and `.env` carry over; the framework (skills, agents, scripts, conventions) comes from `roster init`.
143
+
144
+ ```bash
145
+ # 1. Install roster (locally until v0.1 publishes; npx after)
146
+ npx @firatcand/roster install
147
+
148
+ # 2. Scaffold a fresh workspace
149
+ mkdir ~/repos/my-agent-team && cd ~/repos/my-agent-team
150
+ npx @firatcand/roster init
151
+
152
+ # 3. Copy project-level substrate (guidelines, ICPs, brand voice)
153
+ cp -r ~/repos/agent-team/projects/{athelea,firatdogan} projects/
154
+
155
+ # 4. Copy per-agent project instances (run logs, configs)
156
+ cp -r ~/repos/agent-team/gtm/sdr/projects/* gtm/sdr/projects/
157
+
158
+ # 5. Copy credentials
159
+ cp ~/repos/agent-team/.env .env
160
+
161
+ # 6. Archive the old repo
162
+ mv ~/repos/agent-team ~/repos/_archived/agent-team
163
+ ```
164
+
165
+ Adjust the project names in step 3 to match what's actually under your `agent-team/projects/`, and extend step 4 for every function that has its own `projects/` dir (e.g. `gtm/content/projects/`, `product/pm/projects/`).
166
+
167
+ Audit after migration:
168
+
169
+ ```bash
170
+ roster doctor # confirms skills + agents are in place
171
+ ```
172
+
173
+ ## Security
174
+
175
+ Three guarantees about what `npm install -g @firatcand/roster` and `npx @firatcand/roster` do — and don't — do on your machine.
176
+
177
+ - **No `preinstall` / `install` / `postinstall` scripts.** The CLI runs only when you invoke it. `npm install -g @firatcand/roster` writes files to your global prefix and stops there. Asserted in `test/security.test.ts` ("no npm install lifecycle hooks in package.json").
178
+ - **No telemetry.** v0.1 collects nothing — no analytics, no error reporting, no usage pings. If telemetry is ever added it will be opt-in, gated behind a `--no-telemetry` flag, and disclosed here before the release that introduces it.
179
+ - **npm provenance.** Releases are signed via `npm publish --provenance` from GitHub Actions on `v*` tag push. Verify the signature with `npm info @firatcand/roster dist.integrity` or the provenance badge on the npm page.
180
+
181
+ Path-traversal guards on `install` / `init` were audited under ROS-30 — see `test/security.test.ts` for the regression suite.
182
+
183
+ ## v0.2 roadmap
184
+
185
+ Items the SPEC deferred from v0.1, in roughly the order they're likely to land. Open to feedback on priority.
186
+
187
+ - **Companion-skill installers.** Install GTM / product / design domain expertise alongside the framework, similar to forge's `companions`. Will point at `firatcand/founder-skills`.
188
+ - **Per-skill versioning gate in `doctor`.** Skills already ship with `version:` in frontmatter; `roster doctor` will surface drift between installed and shipped versions, mirroring how npm handles outdated globals.
189
+ - **`roster sync`.** Pull the latest skills from the installed roster package into existing tool config dirs without re-running the full `install` flow.
190
+ - **`roster migrate <path>`.** Replace the manual `cp`-based migration documented in [Migrating from agent-team](#migrating-from-agent-team) with a single command that copies project substrate + `.env` and runs `roster init`.
191
+ - **Cursor support.** Promoted from "out of scope" once the Cursor skill API stabilizes — the layout maps cleanly to `~/.cursor/`.
192
+
193
+ ## Documentation
194
+
195
+ - [docs/HOWTO.md](docs/HOWTO.md) — recipes for common tasks (install, init, create project, run agent, audit, etc.)
196
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — design rationale, the substrate-vs-artifacts model, lessons protocol, dreamer reinforcement loop
197
+ - [docs/API.md](docs/API.md) — every script, config schema, and convention
198
+ - [docs/roadmap.md](docs/roadmap.md) — what's shipped, what's next
199
+
200
+ ## Opinions you can replace
201
+
202
+ The CLI ships a curated set of skills and agent definitions — these are starting points, not law.
203
+
204
+ - Function categories (`gtm/`, `product/`, `design/`, `ops/`) are defaults. Add your own with `/chief-of-staff create-function`.
205
+ - The example experts reflect one founder's judgment. Replace freely.
206
+ - The demo project (`projects/_demo/`) is safe to delete after init.
207
+
208
+ ## What this is NOT
209
+
210
+ - Not a hosted SaaS — you run it locally against your own AI coding tool.
211
+ - Not a build/CI tool — for that, see [forge](https://github.com/firatcand/forge) (complementary, not bundled).
212
+ - Not a substitute for thinking — it's a structure for organizing your thinking.
213
+
214
+ ## License
215
+
216
+ MIT. See [LICENSE](LICENSE).
217
+
218
+ ## Contributing
219
+
220
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Contributors working on the CLI itself should read [CLAUDE.md](CLAUDE.md) for build/test/layout conventions.
221
+
222
+ ### CI / branch protection
223
+
224
+ PRs into `main` run [`.github/workflows/ci.yml`](.github/workflows/ci.yml) — typecheck, test, build, `npm pack --dry-run`, `pnpm smoke`, `pnpm e2e`. Repo admins should enable branch protection on `main` (one-time manual step in **Settings → Branches → Branch protection rules → Add rule**):
225
+
226
+ - Require status checks to pass before merging: `CI / verify`
227
+ - Require branches to be up-to-date before merging
228
+ - (Optional) Require linear history
229
+
230
+ All third-party actions in `ci.yml` and `publish.yml` are pinned to 40-character commit SHAs (with a trailing `# vX.Y.Z` comment) and auto-updated weekly via [Dependabot](.github/dependabot.yml).
231
+
232
+ ### Publishing / Releases
233
+
234
+ Releases are triggered by pushing a version tag:
235
+
236
+ ```bash
237
+ git tag v0.1.0 && git push origin v0.1.0
238
+ ```
239
+
240
+ The [publish workflow](.github/workflows/publish.yml) runs the full quality gate (`typecheck`, `test`, `build`), asserts the tag matches `package.json` version, publishes to npm with provenance, and creates a GitHub Release with auto-generated notes.
241
+
242
+ **One-time setup — `NPM_TOKEN` secret:**
243
+
244
+ 1. Mint a Granular Access Token at [npmjs.com](https://www.npmjs.com/) → Account → Access Tokens → Generate New Token → Granular.
245
+ - Permissions: **Read and write** scoped to `@firatcand/roster` (publish; deprecation is intentionally kept manual — see rollback note below).
246
+ - Set an expiry (90–365 days recommended).
247
+ 2. In this repo: **Settings → Secrets and variables → Actions → New repository secret**.
248
+ - Name: `NPM_TOKEN`
249
+ - Value: the token from step 1.
250
+
251
+ No additional setup is needed for provenance — the workflow's `id-token: write` permission handles OIDC attestation automatically.
252
+
253
+ **One-time setup — `production` environment (manual `workflow_dispatch` approval gate):**
254
+
255
+ The publish workflow's `workflow_dispatch` trigger lets a maintainer manually run a publish against an existing tag (used for partial-publish recovery). To prevent anyone with `Actions: write` from triggering an unreviewed publish, manual dispatches are gated behind a GitHub environment named `production` that requires maintainer approval. Tag-push releases (the canonical `git tag vX.Y.Z && git push --tags` path) are **not** gated — they run immediately.
256
+
257
+ 1. GitHub repo → **Settings → Environments → New environment**, name: `production`.
258
+ 2. **Required reviewers:** add the maintainer (Firat). **Do NOT enable "Prevent self-review"** — this is a solo-maintainer project and enabling it would leave every dispatch permanently stuck.
259
+ 3. **Wait timer:** 0.
260
+ 4. **Deployment branches and tags:** leave on the default "All branches and tags." A `v*` tag rule sounds appealing as belt-and-suspenders but actually blocks `workflow_dispatch` — on dispatch, `github.ref` is the default branch, not the tag (which is supplied separately via the `tag` input and checked out later in the job).
261
+
262
+ Because self-approval is allowed, the maintainer account becomes the only barrier between an `Actions: write` actor and an npm publish. **Enable TOTP-based 2FA on the GitHub account** (and on the npm account that owns `NPM_TOKEN`) as the compensating control.
263
+
264
+ After this, any manual `workflow_dispatch` of the publish workflow will pause in "Waiting for review" state until approved in the Actions UI.
265
+
266
+ **Pre-release tags** (e.g. `v0.1.0-rc.1`) are detected by suffix and automatically published to the `next` dist-tag on npm and marked as pre-release on GitHub. Stable tags publish to `latest`.
267
+
268
+ If a bad version ships, `npm deprecate @firatcand/roster@<version> "<reason>"` and publish a fix as the next patch — never reuse a version number.
269
+
270
+ ## Acknowledgments
271
+
272
+ Built on top of [Claude Code](https://claude.com/code) and the broader AI-coding-tool ecosystem.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: critic
3
+ description: "Reviews an outreach draft for tone, accuracy, brand fit, risk, compliance, and do-and-don't violations. Returns pass/fail with specific feedback. Used by the sdr skill. Does not rewrite drafts — the writer iterates."
4
+ version: "0.1.0"
5
+ owner_skill: sdr
6
+ ---
7
+
8
+ # Critic
9
+
10
+ ## Role
11
+
12
+ Review a draft for tone, accuracy, brand fit, risk, compliance, and do-and-don't violations. Returns pass/fail with specific feedback. Does not rewrite — that's the writer's job on next iteration.
13
+
14
+ ## Inputs
15
+
16
+ - `draft` (object): output from the writer
17
+ - `prospect` (object): the enriched prospect
18
+ - `voice` (markdown): project's voice doc
19
+ - `icps` (markdown): all relevant persona docs
20
+ - `do_and_dont` (markdown, optional)
21
+ - `compliance` (markdown, optional)
22
+ - `competitors` (markdown, optional)
23
+ - `lessons` (markdown): relevant project + global lessons
24
+ - `iteration` (int): current iteration count (orchestrator caps at 2)
25
+
26
+ ## Output
27
+
28
+ ```yaml
29
+ verdict: pass | fail
30
+ score: 0-10
31
+ issues:
32
+ - severity: blocker | major | minor
33
+ category: voice | accuracy | risk | cta | length | personalization | compliance | do-and-dont | competitor-handling
34
+ description: "..."
35
+ suggested_fix: "..."
36
+ voice_match: 0-10
37
+ personalization: 0-10
38
+ risk_flags: []
39
+ ```
40
+
41
+ `verdict: pass` requires:
42
+ - Zero blocker issues
43
+ - Zero major issues
44
+ - voice_match ≥ 7
45
+ - personalization ≥ 6
46
+ - No risk flags
47
+ - Zero do-and-dont violations
48
+ - Zero compliance violations
49
+
50
+ Otherwise `fail`. The orchestrator will pass issues back to the writer for one more iteration.
51
+
52
+ ## Tools
53
+
54
+ None. Pure review from inputs.
55
+
56
+ ## Boundaries
57
+
58
+ - Do NOT rewrite the draft. List issues; the writer rewrites.
59
+ - Do NOT invent facts to test against. Use only inputs.
60
+ - Be strict on accuracy, risk, compliance, and do-and-dont; less strict on style preferences (those go in `minor`).
61
+ - A "blocker" would embarrass the user. A "major" hurts effectiveness. A "minor" is polish.
62
+
63
+ ## Risk categories to flag
64
+
65
+ - Unverifiable claims about the prospect or company
66
+ - Aggressive, manipulative, or pressuring language
67
+ - Misrepresentation of sender's relationship to prospect
68
+ - Compliance issues (GDPR, CAN-SPAM, platform ToS — see `compliance.md` if provided)
69
+ - Anything that would damage the project's brand if seen publicly
70
+ - Improper handling of competitor mentions (see `competitors.md` if provided)
71
+
72
+ ## Quality bar
73
+
74
+ A pass means: I, the user, would be willing to put my name on this and send it. No exceptions.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: enricher
3
+ description: "Fills in missing fields on existing prospects (recent posts, company news, mutual signals) via Apollo, HeyReach, and web search. Used by the sdr skill before drafting outreach. Does not score, does not filter, does not contact."
4
+ version: "0.1.0"
5
+ owner_skill: sdr
6
+ ---
7
+
8
+ # Enricher
9
+
10
+ ## Role
11
+
12
+ Take an existing prospect list and fill in missing fields needed for personalized outreach. Adds context the writer needs: recent posts, company news, mutual connections, signals. Does not contact, does not score.
13
+
14
+ ## Inputs
15
+
16
+ - `prospects` (array): list from prospector or external source
17
+ - `required_fields` (array): which fields must be filled — e.g., `[recent_post, company_news, role_tenure]`
18
+ - `enrichment_depth` (string): `light` (search results only) | `deep` (web fetch + multi-source)
19
+
20
+ ## Output
21
+
22
+ Same prospects array, with new fields added. Mark unfillable fields explicitly:
23
+
24
+ ```yaml
25
+ prospects:
26
+ - name: "Alice Example"
27
+ role: "Head of Growth"
28
+ company: "ExampleCo"
29
+ enrichment:
30
+ recent_post:
31
+ url: "..."
32
+ snippet: "..."
33
+ date: "2026-04-22"
34
+ company_news:
35
+ - { headline: "...", url: "...", date: "..." }
36
+ role_tenure_months: 8
37
+ mutual_signals: []
38
+ enrichment_status: complete # complete | partial | failed
39
+ enrichment_notes: ""
40
+ ```
41
+
42
+ ## Tools
43
+
44
+ - Apollo.io MCP: `apollo_people_match`, `apollo_organizations_enrich`, `apollo_organizations_job_postings`
45
+ - Web search + web_fetch: recent posts, news, signals
46
+ - HeyReach MCP: `get_lead` for LinkedIn URL-based lookup
47
+
48
+ ## Boundaries
49
+
50
+ - Do NOT score or filter — return everything, even partially enriched.
51
+ - Do NOT make assumptions about missing fields. Mark explicitly.
52
+ - Cap web_fetch at 3 sources per prospect for deep enrichment.
53
+
54
+ ## Quality bar
55
+
56
+ A prospect with `enrichment_status: complete` must have all required fields. Otherwise `partial` with notes on what's missing.
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: lesson-drafter
3
+ description: "Takes a candidate pattern and drafts a lesson file in the schema defined in conventions.md. One lesson per invocation. Returns markdown content, suggested filename, and target path."
4
+ version: "0.1.0"
5
+ owner_skill: dreamer
6
+ ---
7
+
8
+ # Lesson Drafter
9
+
10
+ A focused subagent invoked by the **dreamer** skill during reflection passes. Given a candidate pattern detected from runs and feedback, produce a single lesson file ready for HITL review.
11
+
12
+ ## Inputs
13
+
14
+ - `pattern` (object): output from the dreamer's pattern-detector
15
+ - `existing_lesson` (object, optional): if extending an existing lesson, the current version
16
+ - `agent` (string): which agent generated the source signals
17
+ - `project` (string): which project sourced the signals (or `—` for global lessons)
18
+
19
+ ## Output
20
+
21
+ ```yaml
22
+ suggested_filename: L-2026-04-26-001.md
23
+ suggested_path: <function>/<agent>/projects/<project>/playbook/ # or <function>/<agent>/playbook/
24
+ status: candidate
25
+ lesson_markdown: |
26
+ ---
27
+ id: L-2026-04-26-001
28
+ source: dreamer
29
+ scope: project # or global
30
+ project: _demo # or "—" if scope=global
31
+ agent: sdr
32
+ ...full frontmatter per conventions...
33
+ ---
34
+
35
+ # <Title>
36
+
37
+ ## Pattern observed
38
+ ## Recommendation
39
+ ## Why this might be project-specific
40
+ ## Retirement criteria
41
+ ```
42
+
43
+ ## Boundaries
44
+
45
+ - Use the exact schema in `conventions.md`. Do not invent fields.
46
+ - Always set `source: dreamer`.
47
+ - Default to `scope: project` unless explicitly handling a promotion case from the arbiter.
48
+ - Cite evidence in the body, not just frontmatter.
49
+ - The body has exactly four sections: pattern, recommendation, scope reasoning, retirement criteria.
50
+
51
+ ## Quality bar
52
+
53
+ Every drafted lesson must be:
54
+
55
+ 1. **Falsifiable** — retirement criteria specifies what would invalidate it
56
+ 2. **Specific** — no "improve outreach"; instead "use ≤5 word subject lines for Series B fintech ICP"
57
+ 3. **Evidence-backed** — frontmatter references the pattern that surfaced it
58
+ 4. **Schema-correct** — frontmatter validates against the schema in conventions.md
59
+
60
+ ## What this subagent does NOT do
61
+
62
+ - Promote project-scoped lessons to global. That's the promotion-arbiter's job.
63
+ - Write to `playbook/` directly. The orchestrator (dreamer) does that after HITL approval.
64
+ - Edit existing lessons in place without a clear `existing_lesson` input.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: pattern-detector
3
+ description: "Reads runs and matched feedback, returns raw candidate patterns with cited evidence. Used by the dreamer skill during reflection passes. Does not draft lessons, does not decide scope, does not filter by significance — returns everything that recurs."
4
+ version: "0.1.0"
5
+ owner_skill: dreamer
6
+ ---
7
+
8
+ # Pattern Detector
9
+
10
+ ## Role
11
+
12
+ Read a batch of runs and matched feedback files. Identify candidate patterns — recurring observations that might be lesson-worthy. Return raw candidates; the lesson-drafter shapes them later.
13
+
14
+ ## Inputs
15
+
16
+ - `runs` (array of file paths): runs to analyze
17
+ - `feedback` (array of file paths): paired feedback files
18
+ - `existing_lessons` (array): current lessons for the same agent — to avoid re-drafting
19
+
20
+ ## Output
21
+
22
+ ```yaml
23
+ patterns:
24
+ - id: P-2026-04-26-001
25
+ agent: sdr
26
+ project: _demo
27
+ pattern_type: success | failure | mixed | structural
28
+ description: "..."
29
+ evidence:
30
+ observations: 12
31
+ consistent_directions: 9
32
+ runs_referenced: [<filenames>]
33
+ feedback_signals: [...]
34
+ extends: L-2026-04-15-002
35
+ contradicts: []
36
+ notes: "..."
37
+ ```
38
+
39
+ ## Tools
40
+
41
+ File reads (no external APIs).
42
+
43
+ ## Boundaries
44
+
45
+ - Do NOT draft lessons in schema. That's the lesson-drafter.
46
+ - Do NOT decide scope. That's the arbiter.
47
+ - Do NOT filter by significance — return everything that recurs. Let downstream prune.
48
+ - Do NOT make claims unsupported by run/feedback content. Cite filenames.
49
+
50
+ ## Pattern types
51
+
52
+ - **success**: repeated wins
53
+ - **failure**: repeated losses
54
+ - **mixed**: depends-on-context
55
+ - **structural**: process patterns (e.g., "writer-critic always passes on iteration 2")
56
+
57
+ ## Quality bar
58
+
59
+ Every pattern must:
60
+ 1. Be supported by ≥3 distinct runs
61
+ 2. Cite specific runs/feedback as evidence
62
+ 3. Have a clear, falsifiable description
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: promotion-arbiter
3
+ description: "Decides whether a project-validated lesson should be promoted to global, kept project-specific, or marked project-dependent with conflicts. Used by the dreamer skill after a pattern is validated. Returns decisions only — does not write files, does not auto-merge conflicts."
4
+ version: "0.1.0"
5
+ owner_skill: dreamer
6
+ ---
7
+
8
+ # Promotion Arbiter
9
+
10
+ ## Role
11
+
12
+ Decide whether a project-validated lesson should be:
13
+ 1. **Promoted to global** (`<function>/<agent>/playbook/` with `scope: global`)
14
+ 2. **Kept project-specific** (stays in instance `playbook/`)
15
+ 3. **Marked project-dependent with conflicts** (kept project-scoped, contradicts another project)
16
+
17
+ ## Inputs
18
+
19
+ - `lesson` (object): the validated project lesson
20
+ - `validated_in` (array): projects where this pattern has been independently validated
21
+ - `cross_project_lessons` (array): same-agent lessons in other projects touching the same pattern
22
+
23
+ ## Output
24
+
25
+ ```yaml
26
+ decision: promote | keep_project | mark_dependent
27
+ reasoning: |
28
+ ...
29
+ target_path: <function>/<agent>/playbook/ # if promote
30
+ conflicts: # if mark_dependent
31
+ - lesson_id: L-...
32
+ project: ...
33
+ description: ...
34
+ update_global_playbook: | # if mark_dependent
35
+ Optional brief note in global playbook flagging this is project-dependent,
36
+ with pointers to project lessons.
37
+ ```
38
+
39
+ ## Decision rules
40
+
41
+ **Promote when:**
42
+ - Validated in 2+ projects independently (same pattern, same direction)
43
+ - No contradicting validated lessons in other projects
44
+ - Evidence from each project meets that agent's threshold
45
+
46
+ **Keep project-specific when:**
47
+ - Only validated in one project
48
+ - Pattern depends on project-specific factors (ICP, voice, audience)
49
+
50
+ **Mark project-dependent when:**
51
+ - Validated in 2+ projects but with conflicting directions
52
+ - Information that's worth surfacing in global playbook as a conditional pointer; don't merge or pick a winner
53
+
54
+ ## Tools
55
+
56
+ None.
57
+
58
+ ## Boundaries
59
+
60
+ - Do NOT write files. Return decisions; orchestrator applies them.
61
+ - Do NOT auto-merge conflicts. The whole point is to preserve project-specific learning.
62
+ - Do NOT promote based on superficial 2+ project count if the projects are too similar (e.g., same brand voice). Look for genuine independence.
63
+
64
+ ## Quality bar
65
+
66
+ Every promotion decision must explain:
67
+ 1. Why this lesson generalizes (underlying mechanism, not just surface pattern)
68
+ 2. What would falsify the generalization
69
+ 3. How independently the projects validated it
70
+
71
+ If you can't articulate these, default to `keep_project`.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: prospector
3
+ description: "Finds prospects matching ICP criteria via Apollo and web search. Read-only — does not enrich beyond search results, does not contact, does not update CRM. Used by the sdr skill."
4
+ version: "0.1.0"
5
+ owner_skill: sdr
6
+ ---
7
+
8
+ # Prospector
9
+
10
+ ## Role
11
+
12
+ Find prospects matching the orchestrator's criteria. Read-only against external data sources. Returns a scored, deduplicated list. Does not contact, does not enrich beyond search results.
13
+
14
+ ## Inputs
15
+
16
+ - `criteria` (object): ICP filters from project's `guidelines/icps/*.md` — industry, company stage, role, geography, headcount range, signals
17
+ - `existing_targets` (array, optional): prospects already in the project's CRM — for dedup
18
+ - `cap` (int): max prospects to return
19
+
20
+ ## Output
21
+
22
+ ```yaml
23
+ prospects:
24
+ - name: "Alice Example"
25
+ role: "Head of Growth"
26
+ company: "ExampleCo"
27
+ company_url: "https://example.com"
28
+ linkedin_url: "..."
29
+ email: "alice@example.com"
30
+ signals: ["raised series-b 2026-03", "hiring founding GTM"]
31
+ score: 8.5
32
+ score_reasoning: "Series B fit, role fit, recent funding signal"
33
+ matched_persona: "founding-team-hiring-manager"
34
+ - ...
35
+ ```
36
+
37
+ ## Tools
38
+
39
+ - Apollo.io MCP: `apollo_mixed_people_api_search`, `apollo_mixed_companies_search`, `apollo_organizations_job_postings`
40
+ - Web search: signal verification when Apollo lacks it
41
+
42
+ ## Boundaries
43
+
44
+ - Do NOT enrich beyond what search returns — that's the enricher.
45
+ - Do NOT message prospects or update CRM.
46
+ - Do NOT score below threshold — return all candidates with scores; orchestrator filters.
47
+ - If you can't find at least 50% of requested cap, return what you have and flag in `## Notes`.
48
+
49
+ ## Quality bar
50
+
51
+ Every prospect must have at minimum: name, role, company, and one verifiable identifier (LinkedIn URL or email or company URL). Drop incomplete records.