@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,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghostwriter:delete
|
|
3
|
+
tier: 2
|
|
4
|
+
cluster: ghostwriter
|
|
5
|
+
sub: delete
|
|
6
|
+
description: Hard-delete a ghostwriter profile at agents/ghostwriter/<slug>.md after a two-step confirmation. No backup, no soft delete — the file is gone after acceptance.
|
|
7
|
+
disable-model-invocation: true
|
|
8
|
+
suggestion:
|
|
9
|
+
eligible: true
|
|
10
|
+
trigger_description: "delete ghostwriter profile, remove public-figure voice, drop ghostwriter, retire captured profile"
|
|
11
|
+
trigger_context: "user wants to permanently remove a captured ghostwriter profile from agents/ghostwriter/"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ghostwriter:delete
|
|
15
|
+
|
|
16
|
+
Hard-delete a single `agents/ghostwriter/<slug>.md` profile after a
|
|
17
|
+
**two-step confirmation**. The file is gone after acceptance — no
|
|
18
|
+
backup, no soft delete, no trash directory. Mirrors the destructive
|
|
19
|
+
posture of `/agents:user:delete`.
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
### 1. Resolve target
|
|
24
|
+
|
|
25
|
+
Argument shapes:
|
|
26
|
+
|
|
27
|
+
- `/ghostwriter:delete <slug>` → positional slug.
|
|
28
|
+
- `/ghostwriter:delete` → interactive: print the same numbered table
|
|
29
|
+
as [`/ghostwriter:list`](list.md) and ask the user to pick one by
|
|
30
|
+
number or slug. One question per turn.
|
|
31
|
+
|
|
32
|
+
| State | Action |
|
|
33
|
+
|---|---|
|
|
34
|
+
| File missing | Abort. Print: *"No profile at `agents/ghostwriter/<slug>.md`. Run `/ghostwriter:list` to see what exists."* |
|
|
35
|
+
| File present, `fictional: true` | Abort. Print: *"`<slug>.md` is a package-side fixture. Delete it via the source tree, not this command."* |
|
|
36
|
+
| File present, real | Proceed to Step 2 |
|
|
37
|
+
|
|
38
|
+
### 2. Print a minimal summary
|
|
39
|
+
|
|
40
|
+
Show the user **exactly** what is about to disappear, sourced from
|
|
41
|
+
the file's frontmatter (do not render the full profile body):
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
About to delete agents/ghostwriter/<slug>.md
|
|
45
|
+
identity.name: <name>
|
|
46
|
+
role: <role_or_title>
|
|
47
|
+
category: <public_figure_category>
|
|
48
|
+
confidence: <low|med|high>
|
|
49
|
+
source count: <source_provenance.count>
|
|
50
|
+
last_fetched_at: <ISO date>
|
|
51
|
+
verification: <fetched|user-asserted>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This is the only summary surface — the full profile is one
|
|
55
|
+
`/ghostwriter:show <slug>` away if the user wants to re-inspect
|
|
56
|
+
before answering.
|
|
57
|
+
|
|
58
|
+
### 3. First confirmation (intent)
|
|
59
|
+
|
|
60
|
+
Ask, verbatim, one question per turn:
|
|
61
|
+
|
|
62
|
+
> *"Delete this ghostwriter profile? `<slug>.md` will be hard-deleted
|
|
63
|
+
> with no backup. Type `delete` to continue, anything else to cancel."*
|
|
64
|
+
|
|
65
|
+
Anything other than the literal token `delete` (case-insensitive,
|
|
66
|
+
trimmed) → abort with: *"Cancelled. No file was deleted."*
|
|
67
|
+
|
|
68
|
+
### 4. Second confirmation (irreversibility)
|
|
69
|
+
|
|
70
|
+
Ask, verbatim:
|
|
71
|
+
|
|
72
|
+
> *"Last chance. This is hard-delete — no `.bak`, no trash, no undo
|
|
73
|
+
> from this command. Type the slug `<slug>` exactly to confirm."*
|
|
74
|
+
|
|
75
|
+
User must type the slug literally (case-sensitive, trimmed). Any
|
|
76
|
+
other input → abort with the same cancel line as Step 3.
|
|
77
|
+
|
|
78
|
+
### 5. Delete + print confirmation
|
|
79
|
+
|
|
80
|
+
Remove the file. Then print:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
✅ agents/ghostwriter/<slug>.md deleted.
|
|
84
|
+
/ghostwriter:list now shows N profiles.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`N` reflects the post-delete count under `agents/ghostwriter/`
|
|
88
|
+
(excluding `README.md`).
|
|
89
|
+
|
|
90
|
+
### 6. Stale-warning surface (optional)
|
|
91
|
+
|
|
92
|
+
After the delete, if any remaining profile is stale (>90 days), print
|
|
93
|
+
the standard stale-warning lines (one per stale slug). Mirrors the
|
|
94
|
+
post-write surface in `/ghostwriter:fetch` Step 7. Non-blocking.
|
|
95
|
+
|
|
96
|
+
## Rules
|
|
97
|
+
|
|
98
|
+
- **Hard-delete only.** No `.bak`, no soft delete, no trash directory.
|
|
99
|
+
Mirrors `/agents:user:delete`.
|
|
100
|
+
- **Two-step confirmation is mandatory.** Skipping either step is a
|
|
101
|
+
contract violation. The two prompts must be distinct turns; do not
|
|
102
|
+
batch them into one numbered-options block.
|
|
103
|
+
- **Do NOT commit, push, or open a PR.** The user owns the git surface;
|
|
104
|
+
consumer ghostwriter files are gitignored by default.
|
|
105
|
+
- **Do NOT delete package-side fixtures.** `fictional: true` files
|
|
106
|
+
belong to the source tree and are out of scope for this command.
|
|
107
|
+
- **Do NOT delete `agents/ghostwriter/README.md`.** The directory
|
|
108
|
+
anchor is not a profile.
|
|
109
|
+
- **Do NOT bulk-delete.** One slug per invocation, even when the user
|
|
110
|
+
passes a glob.
|
|
111
|
+
|
|
112
|
+
## See also
|
|
113
|
+
|
|
114
|
+
- [`/ghostwriter`](../ghostwriter.md) — parent cluster.
|
|
115
|
+
- [`/ghostwriter:list`](list.md) — pick a slug to delete.
|
|
116
|
+
- [`/ghostwriter:show`](show.md) — re-inspect before deleting.
|
|
117
|
+
- [`/ghostwriter:fetch`](fetch.md) — re-create a profile from scratch (no recovery from this command).
|
|
118
|
+
- [`/agents:user:delete`](../agents/user/delete.md) — sibling destructive command this one mirrors.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghostwriter:fetch
|
|
3
|
+
tier: 2
|
|
4
|
+
cluster: ghostwriter
|
|
5
|
+
sub: fetch
|
|
6
|
+
description: Build or refresh a public-figure voice profile at agents/ghostwriter/<slug>.md from a URL or bare name; runs the public-figure attestation gate; delegates web-fetch / web-search to the host agent.
|
|
7
|
+
disable-model-invocation: true
|
|
8
|
+
suggestion:
|
|
9
|
+
eligible: true
|
|
10
|
+
trigger_description: "fetch public figure writing voice, capture LinkedIn / blog / Substack style, build ghostwriter profile from name, refresh stale profile"
|
|
11
|
+
trigger_context: "user wants to capture a documented public figure's writing voice from a URL or by name into agents/ghostwriter/<slug>.md"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ghostwriter:fetch
|
|
15
|
+
|
|
16
|
+
Build (or refresh) a ghostwriter profile at
|
|
17
|
+
`agents/ghostwriter/<slug>.md` from one of two inputs:
|
|
18
|
+
|
|
19
|
+
| Input | Mode | Host-agent capability used |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| URL (LinkedIn / blog / Substack / personal site) | **URL mode** | web-fetch |
|
|
22
|
+
| Bare name (`"Alice Walker"`) | **Name-only mode** | web-search |
|
|
23
|
+
|
|
24
|
+
Zero network code in the package — the host agent performs the fetch /
|
|
25
|
+
search; this command is procedural only. Schema:
|
|
26
|
+
[`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md).
|
|
27
|
+
|
|
28
|
+
## Steps
|
|
29
|
+
|
|
30
|
+
### 1. Parse input + resolve slug
|
|
31
|
+
|
|
32
|
+
Argument shape: `/ghostwriter:fetch <input> [--force-refresh]`.
|
|
33
|
+
|
|
34
|
+
- Looks like a URL (`https?://`) → URL mode. Derive slug from the
|
|
35
|
+
page's primary author / persona name (kebab-case).
|
|
36
|
+
- Otherwise → name-only mode. Slug = full name kebab-case
|
|
37
|
+
(`alice-walker`). If a slug already exists with a different role,
|
|
38
|
+
ask the user for a discriminator suffix (`alice-walker-novelist`).
|
|
39
|
+
|
|
40
|
+
Existing `agents/ghostwriter/<slug>.md`?
|
|
41
|
+
|
|
42
|
+
| State | Action |
|
|
43
|
+
|---|---|
|
|
44
|
+
| Missing | Proceed to fresh-fetch flow |
|
|
45
|
+
| Exists, no `--force-refresh` | Diff-and-accept flow (Step 6) |
|
|
46
|
+
| Exists, `--force-refresh` | Back up to `<slug>.md.bak`, rebuild from scratch |
|
|
47
|
+
|
|
48
|
+
### 2. Public-figure attestation gate (BLOCKING)
|
|
49
|
+
|
|
50
|
+
Print verbatim, one question per turn, **all four** required before any
|
|
51
|
+
write. Mirrors the deterministic gate in
|
|
52
|
+
[`ghostwriter-schema § public-figure gate`](../../../docs/contracts/ghostwriter-schema.md).
|
|
53
|
+
|
|
54
|
+
1. *"Is the target a documented public figure with a public-facing role
|
|
55
|
+
(author / executive / academic / politician / journalist /
|
|
56
|
+
public-speaker / public-artist / deceased-historical)? Which category?"*
|
|
57
|
+
2. *"Are all sources you intend to use public — not paywalled,
|
|
58
|
+
login-walled, leaked, or retracted?"*
|
|
59
|
+
3. *"Do you accept the right-of-publicity and defamation surface? The
|
|
60
|
+
package documents the gate but the legal call is yours."*
|
|
61
|
+
4. *"Do you understand the disclosure footer on every `/ghostwriter:write`
|
|
62
|
+
output is non-removable?"*
|
|
63
|
+
|
|
64
|
+
Any "no" / silence / decline → abort. Do not write the file.
|
|
65
|
+
Record the UTC ISO timestamp of the fourth "yes" into
|
|
66
|
+
`identity.attestation_recorded_at`.
|
|
67
|
+
|
|
68
|
+
### 3a. URL mode — host-agent fetch
|
|
69
|
+
|
|
70
|
+
Instruct the host agent: *"Fetch the URL `<input>` and any linked
|
|
71
|
+
author archive / post index. Return public posts (target: last 100;
|
|
72
|
+
floor: 3 distinct items). Exclude paywalled / login-walled / private
|
|
73
|
+
content."*
|
|
74
|
+
|
|
75
|
+
| Result | Action |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Host has web-fetch + ≥ 3 distinct items returned | `source_provenance.verification: fetched`; proceed to Step 4 |
|
|
78
|
+
| Host has web-fetch but < 3 items | Abort; report the floor; suggest name-only mode for broader sources |
|
|
79
|
+
| Host cannot fetch | Emit paste-prompt (Step 3c) |
|
|
80
|
+
|
|
81
|
+
### 3b. Name-only mode — host-agent search
|
|
82
|
+
|
|
83
|
+
Instruct the host agent: *"Search authoritative public sources for
|
|
84
|
+
`<name>`: Wikipedia, official site, verified social, archived
|
|
85
|
+
interviews, published books (for deceased figures). Return ≥ 3
|
|
86
|
+
distinct authoritative items."*
|
|
87
|
+
|
|
88
|
+
| Result | Action |
|
|
89
|
+
|---|---|
|
|
90
|
+
| ≥ 3 distinct authoritative items | `verification: fetched`; proceed to Step 4 |
|
|
91
|
+
| < 3 items | Abort; report the floor; ask the user to supply URLs |
|
|
92
|
+
| Host cannot search | Emit paste-prompt (Step 3c) |
|
|
93
|
+
|
|
94
|
+
### 3c. Paste-prompt fallback
|
|
95
|
+
|
|
96
|
+
Print: *"Host agent cannot fetch / search. Paste ≥ 3 public-source
|
|
97
|
+
excerpts with their URLs; one excerpt per code block, max ~200 words
|
|
98
|
+
each. Type `done` when finished."*
|
|
99
|
+
|
|
100
|
+
Collected material → `source_provenance.verification: user-asserted`.
|
|
101
|
+
`/ghostwriter:show` will surface a `⚠️ user-asserted` warning on this
|
|
102
|
+
profile.
|
|
103
|
+
|
|
104
|
+
### 4. Derive frontmatter
|
|
105
|
+
|
|
106
|
+
From the gathered material, populate the locked frontmatter per
|
|
107
|
+
[`ghostwriter-schema § locked frontmatter (v1)`](../../../docs/contracts/ghostwriter-schema.md):
|
|
108
|
+
|
|
109
|
+
- `identity.*` — name, role, category (from Step 2), source URLs,
|
|
110
|
+
`fetched_at` (today, ISO date), `attestation_recorded_at` (Step 2).
|
|
111
|
+
- `style.fingerprint.*` — derive `sentence_length_avg`, `vocab_register`,
|
|
112
|
+
opener / closer patterns, hashtag / emoji rules, paragraph cadence
|
|
113
|
+
from the gathered excerpts.
|
|
114
|
+
- `style.free_form_notes` — short prose summary.
|
|
115
|
+
- `voice_samples` — pick up to 3 public excerpts, ≤ 200 words each,
|
|
116
|
+
source-attributed.
|
|
117
|
+
- `taboos` — what the figure demonstrably never does in public writing.
|
|
118
|
+
- `source_provenance.{count, last_fetched_at, types, verification}`.
|
|
119
|
+
- `confidence` — derived deterministically:
|
|
120
|
+
|
|
121
|
+
| Sources × types | Confidence |
|
|
122
|
+
|---|---|
|
|
123
|
+
| 3 sources, same platform | `low` |
|
|
124
|
+
| 3+ sources, 2+ platforms | `med` |
|
|
125
|
+
| 5+ sources, 3+ platforms, ≥ 1 canonical | `high` |
|
|
126
|
+
|
|
127
|
+
- `fictional: false` (always, for consumer-side files).
|
|
128
|
+
- `last_updated` — today, ISO date.
|
|
129
|
+
|
|
130
|
+
Body: a single `# Notes` section, empty for fresh fetches.
|
|
131
|
+
**Hard cap: 200 lines total.**
|
|
132
|
+
|
|
133
|
+
### 5. Propose + confirm (fresh-fetch path)
|
|
134
|
+
|
|
135
|
+
Print the proposed file content as a fenced markdown block. Ask:
|
|
136
|
+
|
|
137
|
+
> 1. write — save to `agents/ghostwriter/<slug>.md`
|
|
138
|
+
> 2. edit — open in IDE first (per `file-editor` skill), save after
|
|
139
|
+
> 3. cancel — discard
|
|
140
|
+
|
|
141
|
+
Only on choice 1 or 2 (after save) write the file. Print the
|
|
142
|
+
post-write summary:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
✅ agents/ghostwriter/<slug>.md written.
|
|
146
|
+
confidence: <low|med|high> · sources: <n> · verification: <fetched|user-asserted>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 6. Diff-and-accept (re-fetch path, no `--force-refresh`)
|
|
150
|
+
|
|
151
|
+
Re-run Steps 2–4 against the existing file. Show a **field-by-field
|
|
152
|
+
diff** (frontmatter keys + voice samples). Ask the user to accept
|
|
153
|
+
per-field changes (numbered options). Bump `last_updated` and
|
|
154
|
+
`source_provenance.last_fetched_at` on accept. Mirrors
|
|
155
|
+
[`/agents:user:accept`](../agents/user/accept.md).
|
|
156
|
+
|
|
157
|
+
### 7. Stale-warning surface (always)
|
|
158
|
+
|
|
159
|
+
After any write (or no-op accept), if any other profile under
|
|
160
|
+
`agents/ghostwriter/*.md` has `source_provenance.last_fetched_at` >
|
|
161
|
+
90 days old, print one line per stale profile:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
⚠️ ghostwriter/<other-slug>.md last fetched YYYY-MM-DD (>90 days). Run /ghostwriter:fetch <other-slug> --force-refresh.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Non-blocking.
|
|
168
|
+
|
|
169
|
+
## Rules
|
|
170
|
+
|
|
171
|
+
- **Do NOT commit, push, or open a PR.** The user owns the git surface.
|
|
172
|
+
- **Do NOT write the file before the attestation gate completes** with
|
|
173
|
+
four explicit "yes" answers.
|
|
174
|
+
- **Do NOT bypass the < 3 distinct sources floor** under any flag.
|
|
175
|
+
- **Do NOT introduce network code in the package** — the host agent
|
|
176
|
+
performs every fetch / search; this command only orchestrates.
|
|
177
|
+
- **Do NOT accept private / paywalled / leaked / retracted material**
|
|
178
|
+
even when the user pastes it (Step 3c).
|
|
179
|
+
|
|
180
|
+
## See also
|
|
181
|
+
|
|
182
|
+
- [`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md) — locked v1 frontmatter, verification levels, confidence derivation.
|
|
183
|
+
- [`/ghostwriter`](../ghostwriter.md) — parent cluster.
|
|
184
|
+
- [`/ghostwriter:write`](write.md) — consume side; appends the mandatory disclosure footer.
|
|
185
|
+
- [`/agents:user:accept`](../agents/user/accept.md) — the diff-and-accept flow this command mirrors on re-fetch.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghostwriter:list
|
|
3
|
+
tier: 2
|
|
4
|
+
cluster: ghostwriter
|
|
5
|
+
sub: list
|
|
6
|
+
description: List captured ghostwriter profiles under agents/ghostwriter/ as a numbered table with confidence, last-fetched, and stale-warning flags. Read-only.
|
|
7
|
+
disable-model-invocation: true
|
|
8
|
+
suggestion:
|
|
9
|
+
eligible: true
|
|
10
|
+
trigger_description: "list ghostwriter profiles, show available public-figure voices, which ghostwriters do I have, ghostwriter inventory"
|
|
11
|
+
trigger_context: "user wants to see which ghostwriter profiles exist locally and which are stale"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ghostwriter:list
|
|
15
|
+
|
|
16
|
+
Read-only listing of every consumer-side ghostwriter profile under
|
|
17
|
+
`agents/ghostwriter/`. Numbered, with the fields needed to pick one
|
|
18
|
+
for `/ghostwriter:write` or to spot stale profiles that need a
|
|
19
|
+
re-fetch.
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
### 1. Scan
|
|
24
|
+
|
|
25
|
+
Enumerate `agents/ghostwriter/*.md`, excluding:
|
|
26
|
+
|
|
27
|
+
- `README.md` (directory anchor, not a profile).
|
|
28
|
+
- Any file whose frontmatter carries `fictional: true` (package-side
|
|
29
|
+
fixtures are not consumer profiles; they should never appear in
|
|
30
|
+
`agents/ghostwriter/` — surface a warning if one is found).
|
|
31
|
+
|
|
32
|
+
For each remaining file, read the frontmatter and extract:
|
|
33
|
+
|
|
34
|
+
| Field | Source |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Slug | filename without `.md` |
|
|
37
|
+
| Name | `identity.name` |
|
|
38
|
+
| Role | `identity.role_or_title` |
|
|
39
|
+
| Category | `identity.public_figure_category` |
|
|
40
|
+
| Confidence | `identity.confidence` (`low` / `med` / `high`) |
|
|
41
|
+
| Verification | `source_provenance.verification` (`fetched` / `user-asserted`) |
|
|
42
|
+
| Last fetched | `source_provenance.last_fetched_at` (ISO date) |
|
|
43
|
+
| Stale | `last_fetched_at` older than 90 days → `⚠️` |
|
|
44
|
+
| User-asserted | `verification == user-asserted` → `⚠️` |
|
|
45
|
+
|
|
46
|
+
### 2. Render
|
|
47
|
+
|
|
48
|
+
Empty result → print and exit:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
No ghostwriter profiles found under agents/ghostwriter/.
|
|
52
|
+
Run /ghostwriter:fetch <url-or-name> to capture one.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Otherwise, print a numbered table sorted by slug:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
# Ghostwriters (N profiles)
|
|
59
|
+
|
|
60
|
+
# Slug Name Confidence Last fetched Flags
|
|
61
|
+
1 alice-walker Alice Walker high 2026-04-12
|
|
62
|
+
2 jane-doe-author Jane Doe med 2025-11-03 ⚠️ stale
|
|
63
|
+
3 bob-smith Bob Smith low 2026-05-01 ⚠️ user-asserted
|
|
64
|
+
|
|
65
|
+
Next: /ghostwriter:show <slug> · /ghostwriter:write --as=<slug>
|
|
66
|
+
/ghostwriter:fetch <slug> --force-refresh # for stale profiles
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Column widths are illustrative — pick the widest entry per column.
|
|
70
|
+
|
|
71
|
+
### 3. Fixture leak warning (defensive)
|
|
72
|
+
|
|
73
|
+
If Step 1 encountered a `fictional: true` file under
|
|
74
|
+
`agents/ghostwriter/`, print **after** the table:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
⚠️ agents/ghostwriter/<file>.md carries `fictional: true` — fixtures
|
|
78
|
+
belong in the package source, not in consumer ghostwriter/. Move
|
|
79
|
+
or delete this file.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This should not normally happen — `scripts/lint_ghostwriter_source.py`
|
|
83
|
+
guards the package side (run via the package's CI), and consumer-side
|
|
84
|
+
`fetch` always writes `fictional: false`.
|
|
85
|
+
|
|
86
|
+
## Rules
|
|
87
|
+
|
|
88
|
+
- **Read-only.** Do not modify or move any file.
|
|
89
|
+
- **Do NOT commit, push, or open a PR.** No git ops.
|
|
90
|
+
- **Do NOT inline voice samples.** Use `/ghostwriter:show <slug>` for
|
|
91
|
+
the full profile body — this command is an index, not a renderer.
|
|
92
|
+
- **Do NOT include `fictional: true` profiles in the main table** —
|
|
93
|
+
they are package-side schema examples, not consumable styles. Surface
|
|
94
|
+
any leak as a separate warning (Step 3).
|
|
95
|
+
|
|
96
|
+
## See also
|
|
97
|
+
|
|
98
|
+
- [`/ghostwriter`](../ghostwriter.md) — parent cluster.
|
|
99
|
+
- [`/ghostwriter:show`](show.md) — render a single profile in full.
|
|
100
|
+
- [`/ghostwriter:fetch`](fetch.md) — refresh stale profiles with `--force-refresh`.
|
|
101
|
+
- [`/ghostwriter:write`](write.md) — consume side; reuses the slugs listed here via `--as=<slug>`.
|
|
102
|
+
- [`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md) — field definitions used in the table.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghostwriter:show
|
|
3
|
+
tier: 2
|
|
4
|
+
cluster: ghostwriter
|
|
5
|
+
sub: show
|
|
6
|
+
description: Render a single ghostwriter profile in full — identity, style fingerprint, voice samples, taboos, source URLs. Read-only.
|
|
7
|
+
disable-model-invocation: true
|
|
8
|
+
suggestion:
|
|
9
|
+
eligible: true
|
|
10
|
+
trigger_description: "show ghostwriter profile, inspect public-figure voice, view ghostwriter details, what does this profile contain"
|
|
11
|
+
trigger_context: "user wants to inspect a single captured ghostwriter profile before writing with it or deciding to refresh / delete it"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ghostwriter:show
|
|
15
|
+
|
|
16
|
+
Read-only render of a single `agents/ghostwriter/<slug>.md` profile.
|
|
17
|
+
Surfaces every field needed to decide whether to consume the voice
|
|
18
|
+
(`/ghostwriter:write`), refresh it (`/ghostwriter:fetch <slug>
|
|
19
|
+
--force-refresh`), or delete it (`/ghostwriter:delete`).
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
### 1. Resolve target
|
|
24
|
+
|
|
25
|
+
Argument shapes:
|
|
26
|
+
|
|
27
|
+
- `/ghostwriter:show <slug>` → positional slug.
|
|
28
|
+
- `/ghostwriter:show <n>` → numeric index from the most recent
|
|
29
|
+
`/ghostwriter:list` ordering (re-derive by listing slugs sorted
|
|
30
|
+
ascending; index is 1-based).
|
|
31
|
+
- `/ghostwriter:show` → interactive — print the same numbered table
|
|
32
|
+
as [`/ghostwriter:list`](list.md) and ask the user to pick one
|
|
33
|
+
by number or slug, one question per turn.
|
|
34
|
+
|
|
35
|
+
Resolution table:
|
|
36
|
+
|
|
37
|
+
| State | Action |
|
|
38
|
+
|---|---|
|
|
39
|
+
| File missing | Abort. Print: *"No profile at `agents/ghostwriter/<slug>.md`. Run `/ghostwriter:list` to see what exists."* |
|
|
40
|
+
| File present, `fictional: true` | Print a one-line warning before rendering: *"⚠️ This is a package-side fixture, not a real-person profile."* Then render normally. |
|
|
41
|
+
| File present, real | Render (Step 2) |
|
|
42
|
+
|
|
43
|
+
### 2. Render
|
|
44
|
+
|
|
45
|
+
Print the profile as fenced sections in the user's language. Sections,
|
|
46
|
+
in order:
|
|
47
|
+
|
|
48
|
+
1. **Header** — name, slug, public-figure category.
|
|
49
|
+
2. **Identity** — `role_or_title`, `era`, source URLs as a bullet list,
|
|
50
|
+
`fetched_at`, `attestation_recorded_at`, `confidence`.
|
|
51
|
+
3. **Source provenance** — `count`, `last_fetched_at`, `types` (bullet
|
|
52
|
+
list), `verification`. If `verification: user-asserted`, prefix the
|
|
53
|
+
section header with `⚠️`.
|
|
54
|
+
4. **Style fingerprint** — `sentence_length_avg`, `vocab_register`,
|
|
55
|
+
`opener_patterns`, `closer_patterns`, `hashtag_rules`, `emoji_rules`,
|
|
56
|
+
`paragraph_cadence`.
|
|
57
|
+
5. **Free-form notes** — `style.free_form_notes` verbatim.
|
|
58
|
+
6. **Voice samples** — each sample as a fenced quote block with the
|
|
59
|
+
source URL underneath. Truncate samples > 200 words with `[…]` and
|
|
60
|
+
note the cap.
|
|
61
|
+
7. **Taboos** — bullet list.
|
|
62
|
+
8. **Body — `# Notes`** — the in-file Notes section, verbatim (may be
|
|
63
|
+
empty for fresh fetches).
|
|
64
|
+
|
|
65
|
+
### 3. Footer hints
|
|
66
|
+
|
|
67
|
+
After the rendered profile, print the available next actions:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Next:
|
|
71
|
+
/ghostwriter:write --as=<slug> # draft in this voice
|
|
72
|
+
/ghostwriter:fetch <slug> --force-refresh # rebuild from scratch
|
|
73
|
+
/ghostwriter:delete <slug> # hard-delete the file
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Stale + user-asserted surface
|
|
77
|
+
|
|
78
|
+
If `last_fetched_at` is > 90 days old, append a one-line warning:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
⚠️ Last fetched YYYY-MM-DD (>90 days). Consider /ghostwriter:fetch <slug> --force-refresh.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If `verification: user-asserted`, append:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
⚠️ Profile is user-asserted (no host-fetched verification). Style fidelity may be lower.
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Non-blocking.
|
|
91
|
+
|
|
92
|
+
## Rules
|
|
93
|
+
|
|
94
|
+
- **Read-only.** Do not modify, move, or write the file.
|
|
95
|
+
- **Do NOT commit, push, or open a PR.** No git ops.
|
|
96
|
+
- **Do NOT redact voice samples by topic.** The whole sample (capped at
|
|
97
|
+
200 words per `ghostwriter-schema`) is part of the schema contract;
|
|
98
|
+
partial rendering would mislead the consumer about the captured
|
|
99
|
+
style.
|
|
100
|
+
- **Do NOT auto-trigger a re-fetch on stale profiles.** Surface the
|
|
101
|
+
warning and let the user run `/ghostwriter:fetch <slug>
|
|
102
|
+
--force-refresh` explicitly.
|
|
103
|
+
- **Do NOT consume `personas/*.md` or `.agent-user.md`.** Wrong
|
|
104
|
+
primitive — those are not ghostwriters.
|
|
105
|
+
|
|
106
|
+
## See also
|
|
107
|
+
|
|
108
|
+
- [`/ghostwriter`](../ghostwriter.md) — parent cluster.
|
|
109
|
+
- [`/ghostwriter:list`](list.md) — index of profiles (use first to pick a slug).
|
|
110
|
+
- [`/ghostwriter:fetch`](fetch.md) — refresh path; `--force-refresh` rebuilds from scratch.
|
|
111
|
+
- [`/ghostwriter:delete`](delete.md) — hard-delete the profile.
|
|
112
|
+
- [`/ghostwriter:write`](write.md) — consume the rendered voice.
|
|
113
|
+
- [`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md) — field definitions used here.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghostwriter:write
|
|
3
|
+
tier: 2
|
|
4
|
+
cluster: ghostwriter
|
|
5
|
+
sub: write
|
|
6
|
+
description: Draft a markdown post in the voice of a captured public-figure ghostwriter profile; appends the mandatory non-removable disclosure footer.
|
|
7
|
+
disable-model-invocation: true
|
|
8
|
+
suggestion:
|
|
9
|
+
eligible: true
|
|
10
|
+
trigger_description: "draft post in style of public figure, write in someone's voice, ghostwriter draft, LinkedIn post in style of X"
|
|
11
|
+
trigger_context: "user wants to generate a copyable draft in a previously captured public-figure voice with the mandatory disclosure footer"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ghostwriter:write
|
|
15
|
+
|
|
16
|
+
Generate a copyable markdown draft in the voice of a captured
|
|
17
|
+
ghostwriter profile under `agents/ghostwriter/<slug>.md`. Implements
|
|
18
|
+
the [`write-engine`](../../../docs/contracts/write-engine.md) contract
|
|
19
|
+
with **mandatory disclosure footer** appended by this command's output
|
|
20
|
+
template (not by the model, no opt-out).
|
|
21
|
+
|
|
22
|
+
> Writing in your **own** voice? Use [`/post-as:me`](../post-as/me.md)
|
|
23
|
+
> — reads `.agent-user.md`, no disclosure footer.
|
|
24
|
+
|
|
25
|
+
## Steps
|
|
26
|
+
|
|
27
|
+
### 1. Select the ghostwriter (style source)
|
|
28
|
+
|
|
29
|
+
Argument shapes:
|
|
30
|
+
|
|
31
|
+
- `/ghostwriter:write` → interactive numbered menu (see below).
|
|
32
|
+
- `/ghostwriter:write --as=<value> [...modifiers]` → non-interactive.
|
|
33
|
+
- `/ghostwriter:write <value> [...modifiers]` → positional shorthand.
|
|
34
|
+
|
|
35
|
+
`<value>` resolves against **slugs** and (when
|
|
36
|
+
`ghostwriter.aliases: true` in `.agent-project-settings.yml` — default
|
|
37
|
+
on) the `aliases:` list of every consumer profile. See
|
|
38
|
+
[`ghostwriter-schema § Aliases`](../../../docs/contracts/ghostwriter-schema.md#aliases).
|
|
39
|
+
|
|
40
|
+
Scan `agents/ghostwriter/*.md`, excluding `README.md` and any file
|
|
41
|
+
with `fictional: true` (fixtures are not consumable from this
|
|
42
|
+
command — they live in the package source as schema examples).
|
|
43
|
+
|
|
44
|
+
Resolution order for `--as=<value>` / positional `<value>`:
|
|
45
|
+
|
|
46
|
+
1. **Slug match** — case-insensitive equality against filename stem.
|
|
47
|
+
2. **Alias match** (skip when `ghostwriter.aliases: false`) —
|
|
48
|
+
case-insensitive equality against every profile's `aliases:` entry.
|
|
49
|
+
Conflicts are impossible at runtime — the consumer-side lint
|
|
50
|
+
rejects cross-profile alias collisions at commit time, so an alias
|
|
51
|
+
resolves to exactly one profile or zero.
|
|
52
|
+
3. **No match** → abort with: *"No profile matches `<value>` (tried
|
|
53
|
+
slug + aliases). Run `/ghostwriter:list` to see available profiles."*
|
|
54
|
+
|
|
55
|
+
| State | Action |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Zero non-fixture profiles | **Abort.** Print: *"No ghostwriter profiles exist. Run `/ghostwriter:fetch <url-or-name>` first."* |
|
|
58
|
+
| One or more profiles, interactive | Numbered menu: `1. <slug> — <identity.name> · <confidence> · <last_updated>` |
|
|
59
|
+
| `--as=<value>` / positional | Resolve via the order above; abort on no match |
|
|
60
|
+
|
|
61
|
+
User picks by number or value. No default — explicit choice required.
|
|
62
|
+
|
|
63
|
+
### 2. Load the style source
|
|
64
|
+
|
|
65
|
+
Read the selected file's frontmatter. Required keys (per
|
|
66
|
+
[`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md)):
|
|
67
|
+
`identity.name`, `style.fingerprint.*`, `style.free_form_notes`,
|
|
68
|
+
`voice_samples`, `taboos`, `source_provenance.verification`.
|
|
69
|
+
|
|
70
|
+
`verification: user-asserted` → print a one-line warning before
|
|
71
|
+
proceeding: *"⚠️ Profile is user-asserted (not host-fetched).
|
|
72
|
+
Style fidelity may be lower."* Non-blocking.
|
|
73
|
+
|
|
74
|
+
### 3. Collect topic + modifiers
|
|
75
|
+
|
|
76
|
+
Per [`write-engine § 2`](../../../docs/contracts/write-engine.md).
|
|
77
|
+
Flag form: `--tone=<formal|casual|neutral>`,
|
|
78
|
+
`--length=<words>`, `--channel=<linkedin-post|tweet|blog|freeform>`,
|
|
79
|
+
`--audience=<text>`. Missing flags → interactive prompt, **one
|
|
80
|
+
question per turn**, in the order Topic → Tone → Length → Channel →
|
|
81
|
+
Audience. Tone / length defaults derive from the per-channel table
|
|
82
|
+
and the vocab-register → tone mapping in the engine contract.
|
|
83
|
+
|
|
84
|
+
### 4. Negative-constraint pass
|
|
85
|
+
|
|
86
|
+
Apply the loaded `taboos` list as exclusions before drafting (per
|
|
87
|
+
[`write-engine § 3`](../../../docs/contracts/write-engine.md)). Print
|
|
88
|
+
a one-line acknowledgement: *"Excluding N taboos from this profile."*
|
|
89
|
+
|
|
90
|
+
### 5. Draft
|
|
91
|
+
|
|
92
|
+
Generate the body as a single fenced markdown block per
|
|
93
|
+
[`write-engine § 4`](../../../docs/contracts/write-engine.md). Honour
|
|
94
|
+
fingerprint constraints: sentence-length ±25 %, opener / closer
|
|
95
|
+
patterns, hashtag / emoji rules, ±15 % length tolerance.
|
|
96
|
+
|
|
97
|
+
### 6. Append the disclosure footer (literal, deterministic)
|
|
98
|
+
|
|
99
|
+
After the body, emit a blank line, then the literal string (rendered
|
|
100
|
+
in the user's language; English template below):
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
*Written in the style of <identity.name>, not by them.*
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
This footer is appended **by this command's output template** as a
|
|
107
|
+
fixed string. It is not produced by the model. No `--no-disclosure`
|
|
108
|
+
flag, no `--internal` flag, no opt-out. The absence of any such flag
|
|
109
|
+
is the acceptance criterion (locked in
|
|
110
|
+
[`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md)
|
|
111
|
+
§ Mandatory disclosure footer).
|
|
112
|
+
|
|
113
|
+
**The footer always uses `identity.name`, never the alias that
|
|
114
|
+
triggered the command.** Invoking `--as=Hawking` against a profile
|
|
115
|
+
with `identity.name: "Stephen Hawking"` produces *"Written in the
|
|
116
|
+
style of Stephen Hawking, not by them."* — never *"…of Hawking…"*.
|
|
117
|
+
Aliases are UX-only; identity attribution stays deterministic.
|
|
118
|
+
|
|
119
|
+
### 7. Print
|
|
120
|
+
|
|
121
|
+
Print the complete block (body + blank line + footer) inside one
|
|
122
|
+
fenced markdown region. No file writes, no commit, no save. The user
|
|
123
|
+
copies the output manually.
|
|
124
|
+
|
|
125
|
+
### 8. Stale-warning surface
|
|
126
|
+
|
|
127
|
+
If the selected profile's `source_provenance.last_fetched_at` is
|
|
128
|
+
> 90 days old, print one line **after** the fenced block:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
⚠️ agents/ghostwriter/<slug>.md last fetched YYYY-MM-DD (>90 days). Run /ghostwriter:fetch <slug> --force-refresh.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Non-blocking.
|
|
135
|
+
|
|
136
|
+
## Rules
|
|
137
|
+
|
|
138
|
+
- **Do NOT commit, push, or open a PR.** The user owns the git surface.
|
|
139
|
+
- **Do NOT omit the disclosure footer.** It is mandatory on every
|
|
140
|
+
invocation. Any flag that would suppress it is forbidden by design
|
|
141
|
+
and rejected by the package skill linter (`scripts/lint_skills.py`).
|
|
142
|
+
- **Do NOT write the draft to disk.** This command prints only.
|
|
143
|
+
- **Do NOT blend multiple ghostwriter voices.** One style source per
|
|
144
|
+
invocation in v1.
|
|
145
|
+
- **Do NOT consume `personas/*.md` or `.agent-user.md`** — those are
|
|
146
|
+
separate primitives. Personas are review lenses; `.agent-user.md`
|
|
147
|
+
is `/post-as:me`.
|
|
148
|
+
- **Do NOT proceed without an explicit `--as=<slug>` or interactive
|
|
149
|
+
selection.** No default ghostwriter.
|
|
150
|
+
- **Do NOT bypass the negative-constraint pass** even when the user
|
|
151
|
+
asks for off-profile content. Surface the taboo and abort.
|
|
152
|
+
|
|
153
|
+
## See also
|
|
154
|
+
|
|
155
|
+
- [`write-engine`](../../../docs/contracts/write-engine.md) — shared procedural contract.
|
|
156
|
+
- [`ghostwriter-schema`](../../../docs/contracts/ghostwriter-schema.md) — locked v1 frontmatter.
|
|
157
|
+
- [`/ghostwriter`](../ghostwriter.md) — parent cluster.
|
|
158
|
+
- [`/ghostwriter:fetch`](fetch.md) — the producer side.
|
|
159
|
+
- [`/post-as:ghostwriter`](../post-as/ghostwriter.md) — thin alias for this command.
|
|
160
|
+
- [`/post-as:me`](../post-as/me.md) — sibling consumer, user-self voice, no footer.
|