@event4u/agent-config 2.16.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-src/commands/ghostwriter/delete.md +118 -0
- package/.agent-src/commands/ghostwriter/fetch.md +185 -0
- package/.agent-src/commands/ghostwriter/list.md +102 -0
- package/.agent-src/commands/ghostwriter/show.md +113 -0
- package/.agent-src/commands/ghostwriter/write.md +160 -0
- package/.agent-src/commands/ghostwriter.md +96 -0
- package/.agent-src/commands/post-as/ghostwriter.md +66 -0
- package/.agent-src/commands/post-as/me.md +124 -0
- package/.agent-src/commands/post-as.md +58 -0
- package/.agent-src/ghostwriter/README.md +61 -0
- package/.agent-src/ghostwriter/fictional-fixture-v1.md +94 -0
- package/.agent-src/personas/README.md +8 -0
- package/.agent-src/rules/domain-safety-disclaimer-consulting.md +52 -0
- package/.agent-src/rules/domain-safety-disclaimer-financial.md +54 -0
- package/.agent-src/rules/domain-safety-disclaimer-legal.md +49 -0
- package/.agent-src/rules/domain-safety-disclaimer-medical.md +56 -0
- package/.agent-src/rules/domain-safety-export-redact.md +65 -0
- package/.agent-src/rules/domain-safety-logging-pii-floor.md +55 -0
- package/.agent-src/rules/domain-safety-pii-finance.md +57 -0
- package/.agent-src/rules/domain-safety-pii-marketing.md +60 -0
- package/.agent-src/rules/domain-safety-pii-recruiting.md +56 -0
- package/.agent-src/rules/domain-safety-pii-support.md +57 -0
- package/.agent-src/rules/domain-safety-retention-finance.md +48 -0
- package/.agent-src/rules/domain-safety-retention-support.md +55 -0
- package/.agent-src/skills/api-design/SKILL.md +3 -0
- package/.agent-src/skills/authz-review/SKILL.md +3 -0
- package/.agent-src/skills/competitive-moat-analysis/SKILL.md +3 -0
- package/.agent-src/skills/competitive-positioning/SKILL.md +3 -0
- package/.agent-src/skills/content-funnel-design/SKILL.md +3 -0
- package/.agent-src/skills/contracts-cognition/SKILL.md +3 -0
- package/.agent-src/skills/dashboard-design/SKILL.md +3 -0
- package/.agent-src/skills/data-handling-judgment/SKILL.md +3 -0
- package/.agent-src/skills/dcf-modeling/SKILL.md +3 -0
- package/.agent-src/skills/deal-qualification-meddic/SKILL.md +3 -0
- package/.agent-src/skills/discovery-interview/SKILL.md +3 -0
- package/.agent-src/skills/editorial-calendar/SKILL.md +3 -0
- package/.agent-src/skills/forecast-accuracy/SKILL.md +3 -0
- package/.agent-src/skills/forecasting/SKILL.md +3 -0
- package/.agent-src/skills/fundraising-narrative/SKILL.md +3 -0
- package/.agent-src/skills/gtm-launch/SKILL.md +3 -0
- package/.agent-src/skills/incident-commander/SKILL.md +3 -0
- package/.agent-src/skills/launch-readiness/SKILL.md +3 -0
- package/.agent-src/skills/messaging-architecture/SKILL.md +3 -0
- package/.agent-src/skills/okr-tree-modeling/SKILL.md +3 -0
- package/.agent-src/skills/pipeline-strategy/SKILL.md +3 -0
- package/.agent-src/skills/playwright-architect/SKILL.md +3 -0
- package/.agent-src/skills/privacy-review/SKILL.md +4 -1
- package/.agent-src/skills/quality-tools/SKILL.md +3 -0
- package/.agent-src/skills/release-comms/SKILL.md +3 -0
- package/.agent-src/skills/runway-cognition/SKILL.md +3 -0
- package/.agent-src/skills/scenario-modeling/SKILL.md +3 -0
- package/.agent-src/skills/secrets-management/SKILL.md +3 -0
- package/.agent-src/skills/tech-debt-tracker/SKILL.md +3 -0
- package/.agent-src/skills/unit-economics-modeling/SKILL.md +3 -0
- package/.agent-src/skills/voc-extract/SKILL.md +3 -0
- package/.agent-src/skills/voice-and-tone-design/SKILL.md +3 -0
- package/.agent-src/templates/agents/agent-project-settings.example.yml +16 -1
- package/.claude-plugin/marketplace.json +10 -1
- package/CHANGELOG.md +69 -0
- package/README.md +44 -23
- package/config/gitignore-block.txt +8 -0
- package/docs/announcements/2026-05-non-dev-launch.md +79 -0
- package/docs/architecture.md +2 -2
- package/docs/case-studies/_template.md +60 -0
- package/docs/catalog.md +24 -3
- package/docs/contracts/agent-user-schema.md +1 -0
- package/docs/contracts/command-clusters.md +2 -0
- package/docs/contracts/file-ownership-matrix.json +490 -0
- package/docs/contracts/ghostwriter-schema.md +337 -0
- package/docs/contracts/init-telemetry.md +133 -0
- package/docs/contracts/router-blending.md +71 -0
- package/docs/contracts/universal-skills.md +92 -0
- package/docs/contracts/write-engine.md +142 -0
- package/docs/getting-started-by-role.md +89 -0
- package/docs/getting-started-laravel.md +72 -0
- package/docs/getting-started.md +2 -2
- package/docs/safety.md +30 -0
- package/package.json +1 -1
- package/scripts/bench_runner.py +158 -0
- package/scripts/check_role_doc_links.py +110 -0
- package/scripts/compress.py +11 -0
- package/scripts/ghostwriter_fixture_allowlist.txt +16 -0
- package/scripts/install.py +133 -1
- package/scripts/lint_ghostwriter_source.py +240 -0
- package/scripts/measure_skill_reduction.py +102 -0
- package/scripts/schemas/rule.schema.json +5 -0
- package/scripts/schemas/skill.schema.json +6 -0
- package/scripts/update-github-metadata.sh +84 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-13
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `ghostwriter/<slug>.md` schema (v1)
|
|
7
|
+
|
|
8
|
+
> **Status:** beta — locked for the `/ghostwriter` cluster roadmap.
|
|
9
|
+
> Re-evaluate fields after the cluster has shipped + been in use
|
|
10
|
+
> for ≥ 1 week.
|
|
11
|
+
|
|
12
|
+
A **ghostwriter profile** is a single Markdown file that captures the
|
|
13
|
+
public writing voice of a documented public figure so the `/ghostwriter:write`
|
|
14
|
+
and `/post-as:ghostwriter` commands can emit copyable drafts in that
|
|
15
|
+
voice. Ghostwriter is the third voice primitive in the package, peer
|
|
16
|
+
to `personas/*.md` (review-lens, internal) and `.agent-user.md` (the
|
|
17
|
+
maintainer themselves).
|
|
18
|
+
|
|
19
|
+
The file is owned by the user. The agent never edits it without an
|
|
20
|
+
explicit `accept` step on `/ghostwriter:fetch` re-runs.
|
|
21
|
+
|
|
22
|
+
## Storage model (dual)
|
|
23
|
+
|
|
24
|
+
- **Consumer projects** — `agents/ghostwriter/<slug>.md`. Real-person
|
|
25
|
+
profiles live here. **Gitignored by default** via the package-managed
|
|
26
|
+
`.gitignore` block. A `--shared` opt-in to commit profiles is
|
|
27
|
+
deferred to v2; only the doc note lands in v1.
|
|
28
|
+
- **Package source** — `.agent-src.uncompressed/ghostwriter/` ships
|
|
29
|
+
the README, this schema doc, and `fictional: true` fixtures only.
|
|
30
|
+
**Zero real-person profiles ever ship with the OSS package.** A CI
|
|
31
|
+
lint (`task lint-ghostwriter-source`) enforces this rule by failing
|
|
32
|
+
on any non-allowlisted file or any file lacking the `fictional: true`
|
|
33
|
+
frontmatter key.
|
|
34
|
+
|
|
35
|
+
Slug = full-name kebab-case (`alice-walker`). Optional `-<discriminator>`
|
|
36
|
+
suffix for disambiguation (`alice-walker-novelist` vs `alice-walker-cyclist`).
|
|
37
|
+
Namespace conflict resolution is consumer-owned — the package does not
|
|
38
|
+
deduplicate across consumers.
|
|
39
|
+
|
|
40
|
+
## Locked frontmatter (v1)
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
---
|
|
44
|
+
version: 1
|
|
45
|
+
fictional: false # required — true for package-side fixtures, false for real-person consumer profiles
|
|
46
|
+
identity:
|
|
47
|
+
name: "Alice Walker" # required — public name
|
|
48
|
+
role_or_title: "novelist" # required — short role label
|
|
49
|
+
era: "1944–" # optional — birth–death range; "1944–" if living
|
|
50
|
+
public_figure_category: "public_artist" # required — enum below
|
|
51
|
+
source_urls: # required — public sources only, ≥ 3 distinct items
|
|
52
|
+
- "https://example.org/walker/interview-1"
|
|
53
|
+
- "https://example.org/walker/essay-collection"
|
|
54
|
+
- "https://example.org/walker/lecture-2018"
|
|
55
|
+
fetched_at: "2026-05-15" # required — ISO date of last fetch
|
|
56
|
+
confidence: "med" # required — low | med | high (see § Confidence)
|
|
57
|
+
attestation_recorded_at: "2026-05-15T10:00:00Z" # required — when the user attested (NOT consent, see § Ethics floor)
|
|
58
|
+
aliases: # optional, consumer-only — alternative names that resolve to this slug
|
|
59
|
+
- "Hawking" # case-insensitive match, case-preserving storage
|
|
60
|
+
- "Prof. Hawking" # min 2 chars, no homoglyphs (see § Aliases)
|
|
61
|
+
style:
|
|
62
|
+
fingerprint:
|
|
63
|
+
sentence_length_avg: 18 # avg words per sentence across samples
|
|
64
|
+
vocab_register: "literary" # casual | conversational | professional | literary | academic
|
|
65
|
+
opener_patterns: ["personal anecdote", "rhetorical question"]
|
|
66
|
+
closer_patterns: ["call to reflection", "quoted aphorism"]
|
|
67
|
+
hashtag_rules: "never" # always | sometimes | never
|
|
68
|
+
emoji_rules: "never" # always | sometimes | never
|
|
69
|
+
paragraph_cadence: "long-form, 4–6 sentence paragraphs"
|
|
70
|
+
free_form_notes: |
|
|
71
|
+
Tends to weave personal narrative with broader social observation.
|
|
72
|
+
Rarely uses imperatives; prefers invitations.
|
|
73
|
+
voice_samples: # required — max 3 items, each ≤ 200 words, source-attributed
|
|
74
|
+
- source_url: "https://example.org/walker/interview-1"
|
|
75
|
+
length_words: 142
|
|
76
|
+
text: |
|
|
77
|
+
[actual public excerpt, max 200 words]
|
|
78
|
+
taboos: # required — what the target never does in public writing
|
|
79
|
+
- "political endorsements"
|
|
80
|
+
- "profanity"
|
|
81
|
+
- "hashtag-driven posts"
|
|
82
|
+
source_provenance: # required
|
|
83
|
+
count: 3 # number of distinct source URLs
|
|
84
|
+
last_fetched_at: "2026-05-15"
|
|
85
|
+
types: ["interview", "essay", "lecture"] # platforms/formats represented
|
|
86
|
+
verification: "fetched" # required — fetched | user-asserted (see § Verification)
|
|
87
|
+
last_updated: "2026-05-15" # YYYY-MM-DD — bumped on every accepted change
|
|
88
|
+
---
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
After the frontmatter, the body is a single freeform **`# Notes`**
|
|
92
|
+
section for the user's own observations on the profile. Hard cap:
|
|
93
|
+
**200 lines** total file size (frontmatter + body + Notes).
|
|
94
|
+
|
|
95
|
+
## Field reference
|
|
96
|
+
|
|
97
|
+
| Field | Required | Purpose |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `version` | yes | Schema version. v1 is the only valid value today. |
|
|
100
|
+
| `fictional` | yes | `true` for package fixtures, `false` for real-person consumer profiles. Drives `task lint-ghostwriter-source`. |
|
|
101
|
+
| `identity.name` | yes | Public name of the figure. |
|
|
102
|
+
| `identity.role_or_title` | yes | Short role label (novelist, executive, …). |
|
|
103
|
+
| `identity.era` | no | Birth–death range. Trailing `–` for living figures. |
|
|
104
|
+
| `identity.public_figure_category` | yes | Enum: `author` \| `executive` \| `academic` \| `politician` \| `journalist` \| `public_speaker` \| `public_artist` \| `deceased_historical`. |
|
|
105
|
+
| `identity.source_urls` | yes | ≥ 3 public source URLs. Drives `confidence`. |
|
|
106
|
+
| `identity.fetched_at` | yes | ISO date of the most recent fetch. |
|
|
107
|
+
| `identity.confidence` | yes | `low` \| `med` \| `high` — derived from source count/diversity. |
|
|
108
|
+
| `identity.attestation_recorded_at` | yes | ISO timestamp the user attested the public-figure gate. |
|
|
109
|
+
| `aliases` | no | Consumer-only list of alternative names that resolve to this profile's slug. See [§ Aliases](#aliases). Banned on `fictional: true` fixtures. |
|
|
110
|
+
| `style.fingerprint.*` | yes | Structured shape of the voice. All sub-fields required. |
|
|
111
|
+
| `style.free_form_notes` | yes | Free-form supplement to the structured fingerprint. |
|
|
112
|
+
| `voice_samples` | yes | Max 3 items; each `≤ 200 words`; each source-attributed. |
|
|
113
|
+
| `taboos` | yes | What the target never does — feeds the write engine's negative-constraint pass. |
|
|
114
|
+
| `source_provenance.count` | yes | Distinct source URLs. |
|
|
115
|
+
| `source_provenance.last_fetched_at` | yes | ISO date — drives the 90-day stale warning. |
|
|
116
|
+
| `source_provenance.types` | yes | Platforms/formats (interview, essay, post, book, …). |
|
|
117
|
+
| `source_provenance.verification` | yes | `fetched` (host agent retrieved) \| `user-asserted` (user pasted; not verifiable). |
|
|
118
|
+
| `last_updated` | yes | ISO date, bumped on every accept. |
|
|
119
|
+
|
|
120
|
+
## Confidence
|
|
121
|
+
|
|
122
|
+
Derived deterministically from `source_provenance.count` and `types`:
|
|
123
|
+
|
|
124
|
+
| Sources × types | Confidence |
|
|
125
|
+
|---|---|
|
|
126
|
+
| 3 sources, same platform | `low` |
|
|
127
|
+
| 3+ sources, 2+ platforms | `med` |
|
|
128
|
+
| 5+ sources, 3+ platforms, ≥ 1 canonical (Wikipedia / official site / published book) | `high` |
|
|
129
|
+
|
|
130
|
+
`/ghostwriter:fetch` refuses to write a profile with fewer than 3 distinct
|
|
131
|
+
authoritative sources.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
## Aliases
|
|
135
|
+
|
|
136
|
+
`aliases` is an **optional, consumer-only** field listing alternative
|
|
137
|
+
names that resolve to this profile's slug. It is a portability win
|
|
138
|
+
over per-user shell aliases — team-shared profiles become immediately
|
|
139
|
+
usable without per-developer config.
|
|
140
|
+
|
|
141
|
+
The list is read by `/ghostwriter:write --as=<value>` (and the
|
|
142
|
+
`/post-as:ghostwriter` thin alias) when resolving the style source:
|
|
143
|
+
|
|
144
|
+
1. Exact slug match (case-insensitive on filename stem).
|
|
145
|
+
2. **If no slug match**, scan every consumer profile's `aliases` list
|
|
146
|
+
for a case-insensitive equality match against `<value>`.
|
|
147
|
+
3. If neither matches, fall through to the interactive numbered menu.
|
|
148
|
+
|
|
149
|
+
### Storage rules
|
|
150
|
+
|
|
151
|
+
- **Case-insensitive match, case-preserving storage** — the resolver
|
|
152
|
+
treats `--as=hawking` and `--as=Hawking` as identical, but the YAML
|
|
153
|
+
preserves the author's chosen casing.
|
|
154
|
+
- **Minimum length: 2 characters** — single-character aliases are
|
|
155
|
+
collision magnets and are rejected by the consumer-side lint.
|
|
156
|
+
- **No homoglyphs** — aliases must use Latin script (ASCII letters,
|
|
157
|
+
digits, common punctuation, common Latin diacritics). Cyrillic,
|
|
158
|
+
Greek, or other confusable scripts are rejected. Prevents spoofing
|
|
159
|
+
like `Stephеn` (Cyrillic `е`) shadowing `Stephen`.
|
|
160
|
+
- **Case-insensitive uniqueness within a profile** — a single profile
|
|
161
|
+
cannot list both `"Hawking"` and `"hawking"`.
|
|
162
|
+
- **Case-insensitive uniqueness across consumer profiles** — two
|
|
163
|
+
different profiles in the same consumer tree cannot share an alias
|
|
164
|
+
(including alias-vs-slug collisions). Conflicts fail the consumer-side
|
|
165
|
+
lint (Option B — lint-time rejection, never a runtime disambiguation
|
|
166
|
+
menu). Determinism contract trumps UX convenience.
|
|
167
|
+
|
|
168
|
+
### Footer integrity (canonical name only)
|
|
169
|
+
|
|
170
|
+
The mandatory [disclosure footer](#mandatory-disclosure-footer-deterministic)
|
|
171
|
+
**always** uses `identity.name`, never the alias that triggered the
|
|
172
|
+
command. A user invoking `/ghostwriter:write --as=Hawking` against a
|
|
173
|
+
profile with `identity.name: "Stephen Hawking"` produces a footer
|
|
174
|
+
reading *"Written in the style of Stephen Hawking, not by them."* —
|
|
175
|
+
not *"…of Hawking, not by them."* This makes aliases UX-only; identity
|
|
176
|
+
attribution stays deterministic.
|
|
177
|
+
|
|
178
|
+
### Package-source ban
|
|
179
|
+
|
|
180
|
+
`aliases:` is **forbidden** on any file with `fictional: true`. Package
|
|
181
|
+
fixtures are schema examples for a single canonical name; aliases are a
|
|
182
|
+
consumer-only deployment feature. The package-source lint
|
|
183
|
+
(`task lint-ghostwriter-source`) fails on `aliases:` in
|
|
184
|
+
`.agent-src.uncompressed/ghostwriter/`.
|
|
185
|
+
|
|
186
|
+
### Settings toggle (consumer-only)
|
|
187
|
+
|
|
188
|
+
The consumer enables alias resolution via `.agent-project-settings.yml`:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
ghostwriter:
|
|
192
|
+
aliases: true # default: true — set to false to disable resolver
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Toggling `aliases: false` makes `/ghostwriter:write --as=<value>` resolve
|
|
196
|
+
against slug names only; any `aliases:` entries in profiles are ignored
|
|
197
|
+
at resolve time (but the lint still validates them on commit).
|
|
198
|
+
|
|
199
|
+
## Verification
|
|
200
|
+
|
|
201
|
+
`source_provenance.verification` distinguishes two acquisition paths:
|
|
202
|
+
|
|
203
|
+
- `fetched` — the host agent retrieved the source URLs via its built-in
|
|
204
|
+
web-fetch / web-search capability. Default for `/ghostwriter:fetch`.
|
|
205
|
+
- `user-asserted` — the host agent could not fetch and the user pasted
|
|
206
|
+
the material manually. The package cannot independently verify these
|
|
207
|
+
sources. `/ghostwriter:show` surfaces user-asserted profiles with a
|
|
208
|
+
visible `⚠️ user-asserted sources — not independently verified` line.
|
|
209
|
+
|
|
210
|
+
This split exists because the package contains zero network code (see
|
|
211
|
+
[§ Determinism floor](#determinism-floor)); the agent cannot otherwise
|
|
212
|
+
distinguish first-party fetch from paste-and-trust.
|
|
213
|
+
|
|
214
|
+
## Ethics floor
|
|
215
|
+
|
|
216
|
+
### Public-figure-only gate (advisory)
|
|
217
|
+
|
|
218
|
+
Before `/ghostwriter:fetch` writes any file, the user must explicitly
|
|
219
|
+
attest that:
|
|
220
|
+
|
|
221
|
+
1. The target is a documented public figure with a public-facing role
|
|
222
|
+
matching `public_figure_category`.
|
|
223
|
+
2. The source URLs are public, not paywalled, not login-walled, not
|
|
224
|
+
leaked, not retracted.
|
|
225
|
+
3. The user accepts the right-of-publicity and defamation surface — the
|
|
226
|
+
user owns the legal call, not the package.
|
|
227
|
+
4. The user understands the disclosure footer on every `/ghostwriter:write`
|
|
228
|
+
output is non-removable.
|
|
229
|
+
|
|
230
|
+
The attestation timestamp is recorded in `identity.attestation_recorded_at`.
|
|
231
|
+
|
|
232
|
+
**The gate is advisory by design.** The package has no network code and
|
|
233
|
+
cannot verify the target's public-figure status against Wikidata or any
|
|
234
|
+
external source. The user's attestation is a documented user-asserted
|
|
235
|
+
checkpoint, not legal consent on the figure's behalf — for living
|
|
236
|
+
figures, no consent path exists short of direct opt-in (deferred to v2).
|
|
237
|
+
|
|
238
|
+
### Mandatory disclosure footer (deterministic)
|
|
239
|
+
|
|
240
|
+
Every `/ghostwriter:write` and `/post-as:ghostwriter` output ends with
|
|
241
|
+
this literal footer:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Written in the style of <identity.name>, not by them.
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The footer is appended by the command's procedural output template as
|
|
248
|
+
a literal string — **not** generated by the model. There is no
|
|
249
|
+
`--no-disclosure` flag. The acceptance criteria grep-verify the absence
|
|
250
|
+
of any opt-out flag in the command source.
|
|
251
|
+
|
|
252
|
+
### Banned content (always)
|
|
253
|
+
|
|
254
|
+
Even for documented public figures, `/ghostwriter:fetch` refuses:
|
|
255
|
+
|
|
256
|
+
- Leaked drafts or material marked private / draft / internal.
|
|
257
|
+
- Paywalled or login-walled content.
|
|
258
|
+
- Private DMs, private email leaks, retracted posts.
|
|
259
|
+
- Medical, financial, or legal data attributed to the figure.
|
|
260
|
+
- Opinions the figure has not publicly stated.
|
|
261
|
+
|
|
262
|
+
### Excluded targets
|
|
263
|
+
|
|
264
|
+
Private individuals (a random LinkedIn user who is not a public figure)
|
|
265
|
+
remain out of scope. This carve-out only widens the persona-roadmap's
|
|
266
|
+
"no third-party PII" floor for documented public figures, never for
|
|
267
|
+
anyone else.
|
|
268
|
+
|
|
269
|
+
## Determinism floor (inherited)
|
|
270
|
+
|
|
271
|
+
The `agent-config` package contains **zero network code**. `/ghostwriter:fetch`
|
|
272
|
+
is a procedural document that delegates the fetch or search to the host
|
|
273
|
+
agent's built-in capability. The package only reads the returned data
|
|
274
|
+
and proposes a diff for user acceptance.
|
|
275
|
+
|
|
276
|
+
## Staleness
|
|
277
|
+
|
|
278
|
+
When `source_provenance.last_fetched_at` is older than 90 days, any
|
|
279
|
+
`/ghostwriter:*` command surfaces a one-line warning (non-blocking):
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
⚠️ ghostwriter/<slug>.md was last fetched YYYY-MM-DD (>90 days ago). Run /ghostwriter:fetch <slug> --force-refresh.
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Re-fetch flow
|
|
286
|
+
|
|
287
|
+
`/ghostwriter:fetch` on an existing slug routes through a diff-and-accept
|
|
288
|
+
flow mirroring `/agents user accept` — the user reviews the proposed
|
|
289
|
+
diff before any write. `--force-refresh` rebuilds the profile from scratch
|
|
290
|
+
instead of merging.
|
|
291
|
+
|
|
292
|
+
## Lint enforcement (`task lint-ghostwriter-source`)
|
|
293
|
+
|
|
294
|
+
The lint runs in `task ci` and fails on:
|
|
295
|
+
|
|
296
|
+
1. Any file under `.agent-src.uncompressed/ghostwriter/` whose stem is
|
|
297
|
+
**not** on the fixture allowlist (`scripts/ghostwriter_fixture_allowlist.txt`).
|
|
298
|
+
2. Any allowlisted file missing `fictional: true` in frontmatter.
|
|
299
|
+
3. Any package-source file (`fictional: true`) carrying an `aliases:`
|
|
300
|
+
field (aliases are a consumer-only feature; see [§ Aliases](#aliases)).
|
|
301
|
+
4. Any consumer-side file under `agents/ghostwriter/` with `fictional: true`
|
|
302
|
+
(fictional profiles belong in the package source, not consumer trees).
|
|
303
|
+
5. Any consumer-side `aliases:` entry that violates the storage rules:
|
|
304
|
+
shorter than 2 characters, non-Latin scripts (homoglyph protection),
|
|
305
|
+
duplicate within a profile (case-insensitive), or colliding across
|
|
306
|
+
profiles (case-insensitive — alias-vs-alias or alias-vs-slug).
|
|
307
|
+
|
|
308
|
+
New package-side fixtures require updating the allowlist + reviewer
|
|
309
|
+
sign-off.
|
|
310
|
+
|
|
311
|
+
## Commands
|
|
312
|
+
|
|
313
|
+
| Command | Role |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `/ghostwriter:fetch` | Creates or refreshes a profile from URL or name input. Runs the public-figure gate. |
|
|
316
|
+
| `/ghostwriter:write` | Generates a draft in the chosen voice. Appends the mandatory disclosure footer. |
|
|
317
|
+
| `/ghostwriter:list` | Numbered listing of available profiles. |
|
|
318
|
+
| `/ghostwriter:show` | Read-only render of one profile. |
|
|
319
|
+
| `/ghostwriter:delete` | Two-step confirmation, hard-deletes the file. |
|
|
320
|
+
| `/post-as:me` | Separate top-level command. Reads `.agent-user.md`; shares the write engine. |
|
|
321
|
+
| `/post-as:ghostwriter` | Thin alias to `/ghostwriter:write`. |
|
|
322
|
+
|
|
323
|
+
See [`command-clusters.md`](command-clusters.md) for the locked
|
|
324
|
+
cluster registration.
|
|
325
|
+
|
|
326
|
+
## Gitignore
|
|
327
|
+
|
|
328
|
+
`agents/ghostwriter/*.md` (except `README.md`) is added to the
|
|
329
|
+
package-managed `.gitignore` block ([`config/gitignore-block.txt`](../../config/gitignore-block.txt))
|
|
330
|
+
and ignored by default. A `--shared` opt-in to commit profiles is
|
|
331
|
+
deferred to v2.
|
|
332
|
+
|
|
333
|
+
## See also
|
|
334
|
+
|
|
335
|
+
- [`agent-user-schema`](agent-user-schema.md) — the maintainer-self primitive that `/post-as:me` consumes.
|
|
336
|
+
- [`persona-schema`](persona-schema.md) — the review-lens primitive, distinct from ghostwriter.
|
|
337
|
+
- [`command-clusters`](command-clusters.md) — the canonical cluster registry.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-15
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Init Telemetry v1
|
|
7
|
+
|
|
8
|
+
> **Status:** beta · **Owner:** step-12 Phase 7 (`agents/roadmaps/step-12-universal-os-reframe.md`) · **Depends on:** [`step-9-user-types-axis`](../../agents/roadmaps/step-99-north-star-restructure.md) telemetry wire-up · **Stability:** additive only
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
Define the wire-shape, redaction floor, opt-in semantics, and producer/consumer split for anonymous telemetry emitted by `agent-config init --interactive`. Used to validate the **Universal-OS reframe hypothesis**: that real `init` runs distribute across non-developer `user_type` values, not only `developer`.
|
|
13
|
+
|
|
14
|
+
This contract ships **ahead of execution**. The producer (`scripts/install.py`) and consumer (aggregation endpoint) are gated on `step-9` user-type filtering — until that ships, this document is the binding shape for the deferred implementation.
|
|
15
|
+
|
|
16
|
+
## Scope
|
|
17
|
+
|
|
18
|
+
Defines:
|
|
19
|
+
|
|
20
|
+
- The single event emitted (`init.user_type.selected`).
|
|
21
|
+
- Field allowlist (no PII, no free-form text, no host fingerprints).
|
|
22
|
+
- Opt-out default (no event without explicit `--telemetry=on` or `.agent-config.local.json` opt-in).
|
|
23
|
+
- Endpoint contract (HTTPS POST, JSON, retention).
|
|
24
|
+
|
|
25
|
+
Does **not** define:
|
|
26
|
+
|
|
27
|
+
- Aggregation queries or dashboards (consumer concern).
|
|
28
|
+
- Other agent-config events — this contract is `init`-scoped.
|
|
29
|
+
|
|
30
|
+
## Iron Law — opt-out by default
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
NO TELEMETRY UNLESS THE USER OPTED IN THIS RUN OR IN .agent-config.local.json.
|
|
34
|
+
NO IP, NO HOSTNAME, NO PATH, NO USERNAME, NO FREE-FORM TEXT.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `--interactive` flag MUST surface the telemetry choice on first run with a clear default (`off`). The choice is persisted to `.agent-config.local.json` under `telemetry.init: true|false`. Re-runs read the persisted value; `--telemetry=on|off` overrides for that run only.
|
|
38
|
+
|
|
39
|
+
## Event shape
|
|
40
|
+
|
|
41
|
+
One JSON object per emitted event. UTF-8, no trailing newline:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"event": "init.user_type.selected",
|
|
46
|
+
"schema_version": 1,
|
|
47
|
+
"ts": "2026-05-15T00:00:00Z",
|
|
48
|
+
"user_type": "creator",
|
|
49
|
+
"stack": "none",
|
|
50
|
+
"verbosity": "normal",
|
|
51
|
+
"interactive": true,
|
|
52
|
+
"agent_config_version": "1.4.2",
|
|
53
|
+
"install_id": "anon-7f3a2b1c"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Field rules:**
|
|
58
|
+
|
|
59
|
+
| Field | Type | Required | Allowed values |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `event` | string | yes | `init.user_type.selected` (only event in v1) |
|
|
62
|
+
| `schema_version` | int | yes | `1` |
|
|
63
|
+
| `ts` | string | yes | ISO-8601 UTC, second precision |
|
|
64
|
+
| `user_type` | string | yes | `creator` · `founder` · `consultant` · `gtm` · `finance` · `ops` · `developer` |
|
|
65
|
+
| `stack` | string | yes | `none` · `laravel` · `nextjs` · `python` · `symfony` · `generic` |
|
|
66
|
+
| `verbosity` | string | yes | `quiet` · `normal` · `verbose` |
|
|
67
|
+
| `interactive` | bool | yes | `true` if `--interactive`, `false` if env-var path |
|
|
68
|
+
| `agent_config_version` | string | yes | semver from `package.json` |
|
|
69
|
+
| `install_id` | string | yes | random 8-char hex, generated on first opt-in, persisted to `.agent-config.local.json` under `telemetry.install_id` |
|
|
70
|
+
|
|
71
|
+
**Forbidden fields:** IP, hostname, OS user, working-directory path, project name, git remote, env vars beyond the version stamp, any free-form text.
|
|
72
|
+
|
|
73
|
+
## Install-id semantics
|
|
74
|
+
|
|
75
|
+
- Generated **only** when the user opts in.
|
|
76
|
+
- Random 8 hex chars (`secrets.token_hex(4)`) — collision space is sufficient for "is this the same install retrying?" without identifying the install.
|
|
77
|
+
- Persisted to `.agent-config.local.json` under `telemetry.install_id`.
|
|
78
|
+
- Deleting the file regenerates the id on next opt-in — by design.
|
|
79
|
+
- Never sent if opt-out is active.
|
|
80
|
+
|
|
81
|
+
## Endpoint contract
|
|
82
|
+
|
|
83
|
+
- **URL:** `https://telemetry.event4u.app/v1/agent-config/init` (placeholder; final URL pinned when consumer ships).
|
|
84
|
+
- **Method:** POST, `Content-Type: application/json`, body is one event object.
|
|
85
|
+
- **Auth:** none — anonymous by design.
|
|
86
|
+
- **Timeout:** 2 s connect, 3 s total. Failure is silent — `init` MUST NOT block or error on telemetry failure.
|
|
87
|
+
- **Retention:** events aggregated to user-type counts per day; raw events purged after 30 d. Aggregate retention 24 months.
|
|
88
|
+
- **Region:** EU-hosted (GDPR Art. 3 footprint; no Standard Contractual Clauses needed for EU installs).
|
|
89
|
+
|
|
90
|
+
## Opt-out mechanics
|
|
91
|
+
|
|
92
|
+
`.agent-config.local.json`:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"telemetry": {
|
|
97
|
+
"init": false
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
When `telemetry.init: false`, the producer:
|
|
103
|
+
|
|
104
|
+
1. Skips event construction entirely.
|
|
105
|
+
2. Does NOT generate or persist `install_id`.
|
|
106
|
+
3. Logs nothing to stderr.
|
|
107
|
+
4. `--telemetry=on` for the run overrides only that invocation (does not persist).
|
|
108
|
+
|
|
109
|
+
## GDPR fit
|
|
110
|
+
|
|
111
|
+
- **Lawful basis:** consent (Art. 6(1)(a)). The `--interactive` prompt is the consent surface.
|
|
112
|
+
- **Data minimization:** Art. 5(1)(c) — only the seven fields above; the field allowlist is the redaction floor.
|
|
113
|
+
- **Storage limitation:** Art. 5(1)(e) — 30 d raw, 24 mo aggregate.
|
|
114
|
+
- **Right to withdraw:** Art. 7(3) — `telemetry.init: false` revokes consent; no further events emitted. Already-collected events remain in the aggregate counts (anonymous, no link to person).
|
|
115
|
+
- **Right of access / erasure:** Arts. 15 / 17 — `install_id` is the only handle; the user can rotate it by deleting `.agent-config.local.json`, breaking the link from current to future events.
|
|
116
|
+
|
|
117
|
+
## Producer / consumer split
|
|
118
|
+
|
|
119
|
+
| Side | Responsibility | Where |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| **Producer** | Construct + POST the event when opt-in is active. Silent failure. | `scripts/install.py::_emit_init_telemetry()` (deferred to `step-9` wire-up). |
|
|
122
|
+
| **Consumer** | Receive + validate against this schema; aggregate per UTC day; purge raw after 30 d. | Telemetry endpoint (not in this repo; pinned URL ships with `step-9`). |
|
|
123
|
+
|
|
124
|
+
## Cross-references
|
|
125
|
+
|
|
126
|
+
- [`step-12-universal-os-reframe.md`](../../agents/roadmaps/step-12-universal-os-reframe.md) Phase 7 L127 — the box this contract pre-authors.
|
|
127
|
+
- [`universal-skills.md`](universal-skills.md) — sibling contract for the allowlist this telemetry validates against.
|
|
128
|
+
- [`router-blending.md`](router-blending.md) — the user-type → skill blend that telemetry confirms is being used.
|
|
129
|
+
- [`STABILITY.md`](STABILITY.md) — schema_version bump rules.
|
|
130
|
+
|
|
131
|
+
## Versioning
|
|
132
|
+
|
|
133
|
+
`schema_version=1` is additive-only. Field additions require an `init-telemetry.md` patch and producer support. Field removals or type changes require a new `schema_version` and a producer that emits both shapes for ≥ 1 minor release.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-13
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Router Blending — Cross-Domain Skill Mix Contract
|
|
8
|
+
|
|
9
|
+
> **Status:** beta · **Owner:** router governance · **Depends on:** [`universal-skills.md`](universal-skills.md), the user-types axis (axis seeds — schema field defined under [`skill.schema.json`](../../scripts/schemas/skill.schema.json) → `recommended_for_user_types`).
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
A founder doing technical due diligence needs both `runway-cognition` and `data-flow-mapper`. A consultant pitching ghost-written thought leadership needs both `ghostwriter` and `competitive-positioning`. Pure prefix-filtering — "load consulting/* for consultants" — silos these workflows and forces the operator to re-enable skills manually.
|
|
14
|
+
|
|
15
|
+
Router blending defines the mix-ratio per user-type so the resolved skill set covers the **dominant** domain plus the **bridge** skills that real workflows demand.
|
|
16
|
+
|
|
17
|
+
## The blend formula
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
loaded_skills(user_type) =
|
|
21
|
+
universal_allowlist (always — see universal-skills.md)
|
|
22
|
+
∪ dominant_pool(user_type) (primary domain, ≈70%)
|
|
23
|
+
∪ bridge_pool(user_type) (cross-domain, ≈20%)
|
|
24
|
+
∪ context_pool(user_type) (content / writing / safety, ≈10%)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Percentages are **soft caps** measured against the post-filter skill count, not hard quotas. Drift > ±10% on any pool triggers a re-tag pass and a finding in `agents/eval-findings/`.
|
|
28
|
+
|
|
29
|
+
## Per user-type blends
|
|
30
|
+
|
|
31
|
+
| user_type | Dominant (~70%) | Bridge (~20%) | Context (~10%) |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| **creator** | `voice-and-tone-design`, `editorial-calendar`, `content-funnel-design`, `messaging-architecture`, `release-comms` | `customer-research`, `competitive-positioning`, `voc-extract` | `privacy-review`, `accessibility-auditor` |
|
|
34
|
+
| **founder** | `runway-cognition`, `unit-economics-modeling`, `fundraising-narrative`, `scenario-modeling`, `okr-tree-modeling` | `data-flow-mapper`, `threat-modeling`, `api-design` | `voice-and-tone-design`, `release-comms` |
|
|
35
|
+
| **consultant** | `discovery-interview`, `competitive-moat-analysis`, `competitive-positioning`, `stakeholder-tradeoff`, `customer-research` | `messaging-architecture`, `voice-and-tone-design`, `release-comms` | `privacy-review`, `data-handling-judgment` |
|
|
36
|
+
| **gtm** | `pipeline-strategy`, `forecast-accuracy`, `deal-qualification-meddic`, `gtm-launch`, `release-comms` | `voice-and-tone-design`, `messaging-architecture`, `voc-extract` | `privacy-review`, `unit-economics-modeling` |
|
|
37
|
+
| **finance** | `runway-cognition`, `unit-economics-modeling`, `scenario-modeling`, `forecasting`, `dcf-modeling` | `data-handling-judgment`, `privacy-review`, `contracts-cognition` | `voice-and-tone-design`, `stakeholder-tradeoff` |
|
|
38
|
+
| **ops** | `incident-commander`, `data-handling-judgment`, `privacy-review`, `dashboard-design`, `launch-readiness` | `threat-modeling`, `secrets-management`, `api-design` | `voice-and-tone-design`, `release-comms` |
|
|
39
|
+
| **developer** | language-/framework-keyed pool (laravel · nextjs-patterns · php-coder · …) | `api-design`, `authz-review`, `playwright-architect`, `threat-modeling` | `voice-and-tone-design`, `release-comms` |
|
|
40
|
+
|
|
41
|
+
Each pool entry is a `recommended_for_user_types:` frontmatter tag on the skill. A skill with no tag is **universal** (see [`universal-skills.md`](universal-skills.md)).
|
|
42
|
+
|
|
43
|
+
## How the loader resolves a profile
|
|
44
|
+
|
|
45
|
+
1. **Read** `.agent-config.local.json` → `user_type`.
|
|
46
|
+
2. **Filter** all 210 skills: keep the skill iff `user_type ∈ recommended_for_user_types` **or** `recommended_for_user_types` is absent (universal).
|
|
47
|
+
3. **Stack overlay.** If `stack` is set (laravel / nextjs / python / …), also keep skills whose body cites that stack — language-keyed bridge. Implementation: pattern match on the skill `description:` frontmatter; details land with the schema-rigor contract once the schema bridge for stack-keyed bridge tagging is finalised.
|
|
48
|
+
4. **Cap.** No filter is applied if the result drops below 50 skills (safety floor — under-filtering is recoverable, over-filtering hides essentials).
|
|
49
|
+
5. **Surface** `loaded_skills_count` + per-pool counts in the agent debug output.
|
|
50
|
+
|
|
51
|
+
## Drift detection
|
|
52
|
+
|
|
53
|
+
`scripts/check_router_blend.py` (to ship with Phase 5) walks each user-type and reports:
|
|
54
|
+
|
|
55
|
+
- Dominant-pool fraction (must be ≥ 0.55).
|
|
56
|
+
- Bridge-pool fraction (≥ 0.15).
|
|
57
|
+
- Empty-pool sentinel: any user-type with zero bridge tags fails the check.
|
|
58
|
+
|
|
59
|
+
Wired into `task ci` as a non-blocking warning until the user-types axis stabilizes; promoted to blocking once `step-9` ships its three seed user-types.
|
|
60
|
+
|
|
61
|
+
## Open questions (tracked for Phase 5 → Phase 6 transition)
|
|
62
|
+
|
|
63
|
+
- Stack overlay precedence: framework tag vs. user-type tag — currently union, may want intersection for the `developer + laravel` combo. Empirical question, tested by corpus.
|
|
64
|
+
- Cross-domain explicit opt-in: `agent-config skills enable <name>` to override the filter on demand. Not in scope for Phase 5 — opens once the filter ships.
|
|
65
|
+
- Persona ↔ user-type mapping: a `consultant` user_type may default to `discovery-lead` persona, but personas are role-axis, not user-axis. Final mapping resolved with [`docs/contracts/persona-schema.md`](persona-schema.md).
|
|
66
|
+
|
|
67
|
+
## Related
|
|
68
|
+
|
|
69
|
+
- [`universal-skills.md`](universal-skills.md) — the always-loaded floor under the blend.
|
|
70
|
+
- [`skill.schema.json`](../../scripts/schemas/skill.schema.json) — `recommended_for_user_types` field that carries the tags.
|
|
71
|
+
- [`tests/eval/corpus-non-dev.yaml`](../../tests/eval/corpus-non-dev.yaml) — empirical validation of the blends.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-13
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Universal Skills — Allowlist Contract
|
|
8
|
+
|
|
9
|
+
> **Status:** beta · **Owner:** step-12 Phase 3 · **Stability:** additive only (no removals without a migration note in `STABILITY.md`)
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
When `agent-config init --interactive` writes a `.agent-config.local.json` with a `user_type` (e.g., `creator`, `founder`, `consultant`), the host agent filters its loaded skill set to that user-type's recommended skills + this allowlist. **Skills on this allowlist are loaded for every user-type regardless of profile.**
|
|
14
|
+
|
|
15
|
+
The allowlist solves the over-siloing risk identified by the AI Council 2026-05-15 review: a `consultant` user still needs `decision-record` and `risk-officer`; a `creator` still needs `refine-prompt` and `verify-completion-evidence`. These are not domain skills — they are agent-OS primitives.
|
|
16
|
+
|
|
17
|
+
## The 15
|
|
18
|
+
|
|
19
|
+
| Skill | Why universal |
|
|
20
|
+
|---|---|
|
|
21
|
+
| [`refine-prompt`](../../.agent-src/skills/refine-prompt/SKILL.md) | Every free-form request needs AC + assumption + confidence band before the engine runs. |
|
|
22
|
+
| [`refine-ticket`](../../.agent-src/skills/refine-ticket/SKILL.md) | Every ticket (Jira / Linear / GH issue) needs scoped AC before plan. |
|
|
23
|
+
| [`estimate-ticket`](../../.agent-src/skills/estimate-ticket/SKILL.md) | Sizing + split + risk — applies to any work item, technical or not. |
|
|
24
|
+
| [`verify-completion-evidence`](../../.agent-src/skills/verify-completion-evidence/SKILL.md) | Iron-Law gate: fresh evidence before any "done" claim. Survives every mode. |
|
|
25
|
+
| [`threat-modeling`](../../.agent-src/skills/threat-modeling/SKILL.md) | Pre-implementation abuse-case enumeration — same lens applies to a marketing form and a payment endpoint. |
|
|
26
|
+
| [`systematic-debugging`](../../.agent-src/skills/systematic-debugging/SKILL.md) | Reproduce → isolate → hypothesize → verify — works on broken pipelines, broken docs, broken funnels. |
|
|
27
|
+
| [`doc-coauthoring`](../../.agent-src/skills/doc-coauthoring/SKILL.md) | 3-stage write loop (context → section → reader-test) for any long-form doc. |
|
|
28
|
+
| [`deep-reading-analyst`](../../.agent-src/skills/deep-reading-analyst/SKILL.md) | Article / long-form analysis via SCQA + mental models — used by every role that reads. |
|
|
29
|
+
| [`decision-record`](../../.agent-src/skills/decision-record/SKILL.md) | Trade-off framing before any commit. ADR-shape works for tech, hiring, and pricing. |
|
|
30
|
+
| [`adr-create`](../../.agent-src/skills/adr-create/SKILL.md) | Naming + numbering + index regen — the file mechanics of `decision-record`. |
|
|
31
|
+
| [`risk-officer`](../../.agent-src/skills/risk-officer/SKILL.md) | Blast-radius framing + residual-risk verdict before any commit. |
|
|
32
|
+
| [`adversarial-review`](../../.agent-src/skills/adversarial-review/SKILL.md) | Devil's advocate stress-test — opt-in but always available. |
|
|
33
|
+
| [`customer-research`](../../.agent-src/skills/customer-research/SKILL.md) | Discovery-slice shaping (JTBD, switch-event) — used by founder, GTM, consultant, creator. |
|
|
34
|
+
| [`stakeholder-tradeoff`](../../.agent-src/skills/stakeholder-tradeoff/SKILL.md) | Per-lens framing when stakeholders disagree — applies in every org. |
|
|
35
|
+
| [`md-language-check`](../../.agent-src/skills/md-language-check/SKILL.md) | Hard gate: `.md` files stay English; the agent translates at runtime. |
|
|
36
|
+
|
|
37
|
+
## Inclusion criteria
|
|
38
|
+
|
|
39
|
+
A skill earns the universal label when **all three** hold:
|
|
40
|
+
|
|
41
|
+
1. **Cross-role payback.** ≥ 4 of the 6 seeded user-types (creator / founder / consultant / GTM / finance-ops / developer) reach for it in week-one workflows. The non-dev eval corpus ([`tests/eval/corpus-non-dev.yaml`](../../tests/eval/corpus-non-dev.yaml)) is the empirical test.
|
|
42
|
+
2. **No stack assumption.** The skill body does not rely on a specific language, framework, or repo shape. `laravel`, `nextjs-patterns`, `pest-testing` are domain skills, not universal.
|
|
43
|
+
3. **Agent-OS primitive.** The skill encodes a meta-pattern of agent behavior (refine, verify, decide, debug, document, threat-model) rather than a domain deliverable (write a launch email, draft an ADR for the auth module).
|
|
44
|
+
|
|
45
|
+
## Exclusion criteria
|
|
46
|
+
|
|
47
|
+
- **Domain anchor.** `voice-and-tone-design` (creator), `runway-cognition` (founder), `quality-tools` (developer), `pipeline-strategy` (GTM) — strong-fit for one user-type, weak for the other five. These tag via the `recommended_for_user_types:` frontmatter field defined in [`skill.schema.json`](../../scripts/schemas/skill.schema.json).
|
|
48
|
+
- **Tool-specific.** `laravel-horizon`, `nextjs-patterns`, `mcp-builder`, `terraform` — load only when the matching stack flag is set.
|
|
49
|
+
- **Council / role review.** `judge-bug-hunter`, `judge-security-auditor`, `architecture-review-lens` — load via subagent orchestration, not via universal allowlist.
|
|
50
|
+
|
|
51
|
+
## How loading works (forward-compatible)
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
// .agent-config.local.json — written by `agent-config init --interactive`
|
|
55
|
+
{
|
|
56
|
+
"user_type": "consultant",
|
|
57
|
+
"stack": "none",
|
|
58
|
+
"verbosity": "normal",
|
|
59
|
+
"enabled_skill_prefixes": ["consulting/*", "writing/*"],
|
|
60
|
+
"default_persona": "discovery-lead"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The host agent's skill loader is expected to:
|
|
65
|
+
|
|
66
|
+
1. Resolve `enabled_skill_prefixes` against the per-user-type recommendation list (Phase 5 `recommended_for_user_types:` tags).
|
|
67
|
+
2. Union with this universal allowlist (always, no opt-out).
|
|
68
|
+
3. Surface a `loaded_skills_count` in the agent's debug / status output so the operator can verify filtering ran.
|
|
69
|
+
|
|
70
|
+
**Runtime filter status:** the prefix-filter pass is gated on the user-types axis shipping the `user-types/` directory and `--user-type` flag. Until then, every skill loads (current v2.x behavior); this contract is the forward declaration of the eventual filter, not its implementation.
|
|
71
|
+
|
|
72
|
+
## Change procedure
|
|
73
|
+
|
|
74
|
+
Adding a skill to this allowlist:
|
|
75
|
+
|
|
76
|
+
1. Open a PR that edits this file + the relevant skill's `recommended_for_user_types:` (omitted = universal).
|
|
77
|
+
2. Cite ≥ 4 user-type prompts from `tests/eval/corpus-non-dev.yaml` that select the skill.
|
|
78
|
+
3. Require approval from one Tier-1 reviewer (architecture-review-lens or skill-writing).
|
|
79
|
+
4. Document the inclusion in `agents/eval-findings/` with the supporting eval prompts.
|
|
80
|
+
|
|
81
|
+
Removing a skill is breaking. It must be announced in `STABILITY.md` with a deprecation window ≥ one minor release.
|
|
82
|
+
|
|
83
|
+
## Versioning
|
|
84
|
+
|
|
85
|
+
- This contract is **beta**. Once non-dev selection-accuracy ≥ 0.60 sustains across two consecutive `task bench --corpus non-dev` runs, status promotes to **stable** and entries become semver-protected.
|
|
86
|
+
|
|
87
|
+
## Related
|
|
88
|
+
|
|
89
|
+
- [`STABILITY.md`](STABILITY.md) — public-identifier stability surface.
|
|
90
|
+
- [`agent-memory-contract.md`](agent-memory-contract.md) — companion contract for the cross-cutting memory layer.
|
|
91
|
+
- [`docs/getting-started-by-role.md`](../getting-started-by-role.md) — consumer-facing role docs that reference these skills.
|
|
92
|
+
- [`tests/eval/corpus-non-dev.yaml`](../../tests/eval/corpus-non-dev.yaml) — empirical test corpus.
|