@praxis-framework/seed 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 (42) hide show
  1. package/README.md +47 -0
  2. package/dist/catalog.d.ts +60 -0
  3. package/dist/catalog.d.ts.map +1 -0
  4. package/dist/catalog.js +239 -0
  5. package/dist/catalog.js.map +1 -0
  6. package/dist/index.d.ts +16 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +14 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/seed.d.ts +43 -0
  11. package/dist/seed.d.ts.map +1 -0
  12. package/dist/seed.js +508 -0
  13. package/dist/seed.js.map +1 -0
  14. package/dist/template.d.ts +16 -0
  15. package/dist/template.d.ts.map +1 -0
  16. package/dist/template.js +47 -0
  17. package/dist/template.js.map +1 -0
  18. package/dist/traits.d.ts +26 -0
  19. package/dist/traits.d.ts.map +1 -0
  20. package/dist/traits.js +43 -0
  21. package/dist/traits.js.map +1 -0
  22. package/dist/types.d.ts +288 -0
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js +87 -0
  25. package/dist/types.js.map +1 -0
  26. package/package.json +55 -0
  27. package/template/.env.example +8 -0
  28. package/template/CLAUDE.md +151 -0
  29. package/template/_gitignore +20 -0
  30. package/template/docker-compose.yml +44 -0
  31. package/template/escalations/README.md +51 -0
  32. package/template/lib/.gitkeep +0 -0
  33. package/template/lib/autonomy.yaml +158 -0
  34. package/template/lib/output-schemas.yaml +88 -0
  35. package/template/lib/tools.yaml +70 -0
  36. package/template/memory/README.md +51 -0
  37. package/template/memory/accounts/.gitkeep +0 -0
  38. package/template/memory/notes/.gitkeep +0 -0
  39. package/template/memory/people/.gitkeep +0 -0
  40. package/template/persona.md +75 -0
  41. package/template/verbs/escalate.md +112 -0
  42. package/template/verbs/proposed/README.md +25 -0
@@ -0,0 +1,20 @@
1
+ # Local tooling
2
+ .claude/
3
+ .playwright-mcp/
4
+ .praxis/
5
+
6
+ # Secrets — never commit
7
+ .env
8
+ *.env
9
+ **/secrets.yaml
10
+ **/credentials.json
11
+
12
+ # Python bytecode
13
+ __pycache__/
14
+ *.pyc
15
+
16
+ # OS
17
+ .DS_Store
18
+
19
+ # Add role-specific gitignores below — e.g. work-product subdirectories
20
+ # that contain raw external data (prospects/*.json, tickets/*.json, etc.)
@@ -0,0 +1,44 @@
1
+ # Praxis dashboard for this role.
2
+ #
3
+ # Usage:
4
+ # cp .env.example .env && vim .env # set ANTHROPIC_API_KEY
5
+ # docker compose up # pulls the dashboard image
6
+ #
7
+ # Open http://localhost:4321
8
+ #
9
+ # Upgrading:
10
+ # docker compose pull && docker compose up -d
11
+ #
12
+ # MCP servers: add sibling services on the praxis network and list them
13
+ # in PRAXIS_MCPS (format: name=http://service:port[,name=http://...]).
14
+ # Per-server allow/deny lives in lib/autonomy.yaml under the `mcps:` block.
15
+
16
+ services:
17
+ dashboard:
18
+ image: ghcr.io/steveworley/praxis-framework/dashboard:main
19
+ container_name: praxis-dashboard
20
+ ports:
21
+ - "127.0.0.1:4321:4321"
22
+ volumes:
23
+ - .:/role
24
+ environment:
25
+ PRAXIS_ROLE_HOME: /role
26
+ PRAXIS_LOG_GLOB: "**/logs/*.jsonl"
27
+ ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
28
+ # PRAXIS_MCPS: "" # name=url[,name=url] — wire MCP servers here
29
+ networks:
30
+ - praxis
31
+ restart: unless-stopped
32
+
33
+ # Add MCP services below as siblings on the praxis network. Example:
34
+ #
35
+ # mcp-slack:
36
+ # image: ghcr.io/your-org/mcp-slack:latest
37
+ # environment:
38
+ # SLACK_BOT_TOKEN: ${SLACK_BOT_TOKEN}
39
+ # networks: [praxis]
40
+ # restart: unless-stopped
41
+
42
+ networks:
43
+ praxis:
44
+ driver: bridge
@@ -0,0 +1,51 @@
1
+ # Escalations
2
+
3
+ Where I raise my hand. One markdown file per escalation, named `{YYYY-MM-DD}-{slug}.md`.
4
+
5
+ See `verbs/escalate.md` for the playbook and the framework's `docs/escalations.md` for the conventions in detail.
6
+
7
+ ## When this is the right place
8
+
9
+ | | Notebook (`memory/`) | Escalation |
10
+ |---|---|---|
11
+ | Shape | Observation | Ask |
12
+ | Action | None implied | Operator does something |
13
+ | Urgency | None | Sometimes blocking |
14
+
15
+ If I learned something but I'm not asking for anything, it goes in `memory/`. If I want my operator to act, it goes here.
16
+
17
+ ## Three kinds
18
+
19
+ - **`help`** — stuck *now*, can't continue without input
20
+ - **`improvement`** — process friction noticed, not blocking
21
+ - **`proposed_skill`** — drafted a new verb in `verbs/proposed/{slug}.md` for review
22
+
23
+ ## Format
24
+
25
+ ```yaml
26
+ ---
27
+ kind: help | improvement | proposed_skill
28
+ urgency: low | normal | high
29
+ created: YYYY-MM-DD
30
+ agent_context: <which agent run produced this>
31
+ proposed_skill: <optional path>
32
+ status: open
33
+ ---
34
+
35
+ # {Short title}
36
+
37
+ ## What I was doing
38
+ ...
39
+
40
+ ## What I tried
41
+ ...
42
+
43
+ ## What I'm asking for
44
+ ...
45
+ ```
46
+
47
+ ## Lifecycle
48
+
49
+ `open` → `resolved` (help / improvement) or `accepted` / `declined` (proposed_skill).
50
+
51
+ When status changes, append a brief resolution note at the bottom of the file. Don't rewrite the original ask.
File without changes
@@ -0,0 +1,158 @@
1
+ # Autonomy — surfaces I (the role) can edit autonomously, and how.
2
+ #
3
+ # Operator-authored. I never edit this file myself; doing so would let me
4
+ # expand my own autonomy, which defeats the point.
5
+ #
6
+ # The framework documents the full model in docs/autonomy.md. Short version:
7
+ # different surfaces have different risk profiles. Match autonomy to risk,
8
+ # not to "importance".
9
+ #
10
+ # Modes:
11
+ # full — I can do anything in this directory/file (current
12
+ # state of memory/, escalations/, verbs/proposed/).
13
+ # append-only — I can add new entries to a list. I never delete or
14
+ # edit existing entries. After max_pending unreviewed
15
+ # additions, I must file an `improvement` escalation
16
+ # for compaction instead of appending more.
17
+ # inline-enrichment — I can update soft fields (notes, calibration text)
18
+ # within existing structured entries. I never add or
19
+ # remove top-level entries; structural changes go
20
+ # through escalation.
21
+ # bounded — I can adjust parameters within ranges the operator
22
+ # has set. The bounds live alongside this entry.
23
+ # gated — I never edit autonomously. Escalate or draft into
24
+ # verbs/proposed/.
25
+ #
26
+ # Anything not listed below is implicitly `gated`. To open a new surface,
27
+ # the operator adds it here.
28
+ #
29
+ # Every autonomous edit must be a git commit signed by the role
30
+ # (`--author="{role full name} <{role email}>"`) so the dashboard's
31
+ # "Recent edits" surface can attribute and surface diffs for operator
32
+ # review. The operator can revert any commit; that's the safety net.
33
+
34
+ surfaces:
35
+ # === Already-autonomous (named here for discoverability) ===
36
+
37
+ - path: memory/
38
+ mode: full
39
+ why: |
40
+ Persona-shaped notebook. Operator prunes; I notice. The reflection
41
+ beat at end-of-run is what fills this directory.
42
+
43
+ - path: verbs/proposed/
44
+ mode: full
45
+ why: |
46
+ Drafts of new verbs. The HiTM gate is what stops drafts from
47
+ becoming live verbs — I never move my own drafts into verbs/.
48
+
49
+ - path: escalations/
50
+ mode: full
51
+ why: |
52
+ My structured asks. The operator triages from the dashboard.
53
+
54
+ # === Append-only — patterns/heuristics I've discovered ===
55
+
56
+ # Example (uncomment + adapt for your role). Required fields on an
57
+ # append-only surface:
58
+ #
59
+ # root_key — top-level YAML key whose list I may append to
60
+ # unique_by — field on each entry that must be unique (often `id`)
61
+ # max_pending — ceiling on unreviewed entries before I must escalate
62
+ #
63
+ # The file at `path:` must already exist and contain a `<root_key>:` line
64
+ # followed by zero-or-more list items. New entries are appended with
65
+ # `reviewed: false`; you flip to `reviewed: true` after reviewing them.
66
+ #
67
+ # - path: lib/research-strategies.yaml
68
+ # mode: append-only
69
+ # max_pending: 5
70
+ # root_key: strategies
71
+ # unique_by: id
72
+ # why: |
73
+ # Org-type page conventions and discovery heuristics I notice while
74
+ # running research-shaped agents. Adding here speeds the next batch.
75
+ # Cost of wrong: one missed page (recoverable). The append-only
76
+ # constraint means I can't break existing entries; the max_pending
77
+ # forces a compaction conversation if I'm appending too fast.
78
+
79
+ # === Inline-enrichment — soft fields on existing entries ===
80
+
81
+ # Example (uncomment + adapt). Required fields on an inline-enrichment
82
+ # surface:
83
+ #
84
+ # root_key — top-level YAML key whose list of entries I may touch
85
+ # unique_by — field on each entry that identifies which one I mean
86
+ # soft_fields — whitelist of field names I may update within an entry
87
+ #
88
+ # Structured fields (everything not in `soft_fields`) are operator-owned;
89
+ # I can never create or delete entries. Use this for reference data where
90
+ # the structure is yours but the soft texture per-entry is the role's
91
+ # lived experience (notes the role observed, calibration timestamps, etc).
92
+ #
93
+ # - path: lib/team.yaml
94
+ # mode: inline-enrichment
95
+ # root_key: members
96
+ # unique_by: id
97
+ # soft_fields:
98
+ # - notes
99
+ # - last_observed_at
100
+ # why: |
101
+ # Structured team data is operator-owned (name, role, email), but I
102
+ # keep the notes column current with what I observe in day-to-day
103
+ # interactions. Cost of wrong: a stale calibration note (recoverable
104
+ # by `git revert`); the soft_fields whitelist means I can never
105
+ # touch the structured org-chart fields.
106
+
107
+ # === Bounded — numeric parameters within operator-set ranges ===
108
+
109
+ # Example (uncomment + adapt). Required field on a bounded surface:
110
+ #
111
+ # bounds — per-parameter map of {min, max, step?} describing the
112
+ # ranges I may tune within. Parameters NOT in `bounds` are
113
+ # operator-only; I refuse to touch them.
114
+ #
115
+ # The file at `path:` is a flat YAML map of `key: value` pairs (operator
116
+ # usually seeds it with defaults). I adjust values using `adjust_param`;
117
+ # the framework refuses values outside the declared range, off-step (when
118
+ # `step` is set), or keyed by a name outside the bounds map.
119
+ #
120
+ # - path: lib/warmup.yaml
121
+ # mode: bounded
122
+ # bounds:
123
+ # sends_per_day: { min: 10, max: 100, step: 5 }
124
+ # weeks_to_full_send_rate: { min: 4, max: 12 }
125
+ # new_thread_ratio: { min: 0.1, max: 0.9 }
126
+ # why: |
127
+ # Warmup throttle parameters. I tune within ranges based on observed
128
+ # deliverability; operator-set ceilings cap the blast radius. Cost of
129
+ # wrong: overcautious throttle (recoverable; affects send rate, not
130
+ # correctness).
131
+
132
+ # === Implicitly gated (do NOT list here unless opening up) ===
133
+ #
134
+ # These remain operator-only. Listed for documentation:
135
+ #
136
+ # - persona.md (constitution — voice + hard inhibitions)
137
+ # - verbs/*.md (existing files) (capability surface — behavioral risk)
138
+ # - lib/customers.yaml (legal/business — never cold-email a customer)
139
+ # - lib/compliance.yaml (legal/safety — Spam Act + opt-out gates)
140
+ # - CLAUDE.md (constitution — global behavior)
141
+
142
+ # === MCP servers — per-server allow/deny ===
143
+ #
144
+ # The dashboard discovers MCP servers via the `PRAXIS_MCPS` env var (set in
145
+ # docker-compose.yml). Each server contributes one tool per method it
146
+ # exposes; this block decides which servers the role may actually call.
147
+ #
148
+ # Default for unlisted servers is `deny` — operators opt in explicitly per
149
+ # server. Per-method / per-recipient scoping (e.g. which Slack channels,
150
+ # which email addresses) is intentionally out of scope here; if you need
151
+ # tighter gating, configure it in the MCP server itself.
152
+ #
153
+ # Uncomment and adapt:
154
+ #
155
+ # mcps:
156
+ # slack: allow
157
+ # gmail: allow
158
+ # playwright: deny
@@ -0,0 +1,88 @@
1
+ # Output taxonomy — framework-shipped reference.
2
+ #
3
+ # This file documents the five output primitives the framework writes to
4
+ # `output/`. It is reference material — the dashboard and the chat tools
5
+ # read the authoritative TypeScript registry at
6
+ # `dashboard/src/lib/output/types.ts`, NOT this file. Editing this YAML
7
+ # does not change runtime behaviour. The file exists so an operator can
8
+ # read the schema without leaving their role home.
9
+ #
10
+ # Lifecycle (closed enum, applies framework-wide):
11
+ # draft → review → ready → sent → done → archived
12
+ #
13
+ # Path safety: every slug and entity_id segment must match
14
+ # /^[a-z0-9][a-z0-9-]*$/ — lowercase alphanumerics and hyphens, starting
15
+ # alphanumeric.
16
+
17
+ status_enum:
18
+ - draft # in progress; not yet ready for review
19
+ - review # operator eyes wanted
20
+ - ready # complete; waiting for action (e.g. operator to send)
21
+ - sent # shipped to its recipient
22
+ - done # work is complete (no further action expected)
23
+ - archived # superseded or stale; kept for history
24
+
25
+ types:
26
+
27
+ document:
28
+ # Long-form prose: a brief, a note, an analysis. Standalone — no
29
+ # entity tie, no recipient.
30
+ path_template: output/document/{slug}.md
31
+ required:
32
+ title: Human-readable title (renders as the file's H1 in the dashboard)
33
+ optional:
34
+ audience: Who this is written for (free-text)
35
+
36
+ draft:
37
+ # Outgoing communication: an email body, a Slack DM, a letter. The
38
+ # framework does NOT send anything — drafts live on disk until the
39
+ # operator (or a future role-defined send tool) actually transmits.
40
+ # Status flow is typically: draft → review → ready → sent.
41
+ path_template: output/draft/{slug}.md
42
+ required: {}
43
+ optional:
44
+ recipient: Who the message is addressed to (free-text; email, Slack handle, mailing address)
45
+ channel: How it will be sent — closed enum
46
+ subject: Subject line / Slack first-message text
47
+ channel_enum:
48
+ - email
49
+ - slack
50
+ - dm
51
+ - letter
52
+ - call
53
+ - other
54
+
55
+ record:
56
+ # Observation tied to an entity. The entity_type / entity_id segments
57
+ # become path segments, so every record about the same entity sits in
58
+ # the same directory: `output/record/<entity_type>/<entity_id>/`.
59
+ # Use this for account reads, call notes, meeting logs — anything
60
+ # whose value is in being correlatable to a thing.
61
+ path_template: output/record/{entity_type}/{entity_id}/{slug}.md
62
+ required:
63
+ entity_type: The kind of entity (e.g. account, contact, project) — slug-shaped
64
+ entity_id: The specific entity (e.g. acme, mary-chen, q1-launch) — slug-shaped
65
+ observed_at: ISO date or datetime for when the observation was made
66
+ optional: {}
67
+
68
+ plan:
69
+ # Multi-step intent the role committed to. The body is a checklist
70
+ # using GitHub-flavoured markdown: `- [ ]` for open, `- [x]` for done.
71
+ # The dashboard parses these to compute progress; the role updates the
72
+ # body to mark steps complete.
73
+ path_template: output/plan/{slug}.md
74
+ required:
75
+ goal: One-line statement of the plan's objective
76
+ optional:
77
+ owner: Who is responsible for executing (defaults to the role itself)
78
+
79
+ reference:
80
+ # Reusable knowledge worth keeping: a heuristic, a recipe, a playbook
81
+ # excerpt, a calibration. Distinct from `memory/` — references are
82
+ # work-product the role might cite later; memory entries are personal
83
+ # observations.
84
+ path_template: output/reference/{slug}.md
85
+ required:
86
+ topic: One-line topic the reference addresses
87
+ optional:
88
+ tags: Array of short tags for filtering (max 20)
@@ -0,0 +1,70 @@
1
+ # Tools — framework-level catalog of capabilities a role can request.
2
+ #
3
+ # Roles declare which capabilities they need per-agent in frontmatter; the
4
+ # runtime maps capabilities to concrete adapters at startup. Operators select
5
+ # from this catalog during `praxis init`.
6
+ #
7
+ # Schema (per entry under `capabilities:`):
8
+ # description — short human-readable summary
9
+ # transport_options — list of supported transports (e.g. native, stdio, sse, url)
10
+ # default_transport — which transport to use unless overridden
11
+ # always_available — true if the runtime always exposes this capability
12
+ # (built-ins like bash/edit/log). Defaults to false.
13
+ # default_auth_env — env-var name the runtime reads for credentials, if any
14
+ # docker_image — container image used when transport is stdio
15
+ #
16
+ # Anything not in this list is unavailable to roles. To add a new capability,
17
+ # extend this file and ship the matching adapter in the framework.
18
+
19
+ capabilities:
20
+ bash:
21
+ description: "Shell execution scoped to the role's working directory"
22
+ transport_options: [native]
23
+ default_transport: native
24
+ always_available: true
25
+
26
+ edit:
27
+ description: "Read/write files inside the role's working directory"
28
+ transport_options: [native]
29
+ default_transport: native
30
+ always_available: true
31
+
32
+ websearch:
33
+ description: "Web search via configured provider (Tavily, Brave, Google)"
34
+ transport_options: [url]
35
+ default_transport: url
36
+ always_available: false
37
+
38
+ log:
39
+ description: "Structured JSONL action logging via bin/log"
40
+ transport_options: [native]
41
+ default_transport: native
42
+ always_available: true
43
+
44
+ mcp:google-workspace:
45
+ description: "Gmail, Calendar, Drive via Google Workspace MCP"
46
+ transport_options: [stdio, sse, url]
47
+ default_transport: stdio
48
+ default_auth_env: GOOGLE_WORKSPACE_TOKEN
49
+ docker_image: praxis/mcp-google-workspace:latest
50
+
51
+ mcp:slack:
52
+ description: "Slack read/write via Slack MCP"
53
+ transport_options: [stdio, sse, url]
54
+ default_transport: stdio
55
+ default_auth_env: SLACK_MCP_TOKEN
56
+ docker_image: praxis/mcp-slack:latest
57
+
58
+ mcp:playwright:
59
+ description: "Headless browser for JS-rendered pages and PDF extraction"
60
+ transport_options: [stdio, sse]
61
+ default_transport: stdio
62
+ default_auth_env: null
63
+ docker_image: mcr.microsoft.com/playwright:v1.45.0-noble
64
+
65
+ mcp:filesystem:
66
+ description: "Extended filesystem access (beyond role workdir)"
67
+ transport_options: [stdio]
68
+ default_transport: stdio
69
+ default_auth_env: null
70
+ docker_image: praxis/mcp-filesystem:latest
@@ -0,0 +1,51 @@
1
+ # Notebook
2
+
3
+ This is where I keep what I learn that doesn't have another home — people I work with, soft account context, voice calibrations, ongoing situations. It's persona-shaped.
4
+
5
+ ## Layout
6
+
7
+ - `people/` — internal team and external contacts I've built relationships with
8
+ - `accounts/` — softer narrative context that doesn't fit `lib/`
9
+ - `notes/` — voice calibrations, ongoing situations, anything else
10
+
11
+ These are suggestions, not rules. If something doesn't fit, make a new directory.
12
+
13
+ ## Format
14
+
15
+ Markdown with optional frontmatter:
16
+
17
+ ---
18
+ created: YYYY-MM-DD
19
+ updated: YYYY-MM-DD
20
+ ---
21
+
22
+ # Title
23
+
24
+ Body...
25
+
26
+ The first `#` heading is the title. Without one, the filename is used.
27
+
28
+ ## What goes here vs elsewhere
29
+
30
+ - Structured facts (rosters, customer lists, capabilities, compliance rules) → `lib/*.yaml`
31
+ - My persona definition + voice rules → `persona.md`
32
+ - Operator preferences (how my operator wants me to *run*) → harness auto-memory
33
+
34
+ This directory: relational and observational content with no other home.
35
+
36
+ Update the `updated` date when I revise an entry. Growth over time is the point.
37
+
38
+ ## Triggers — what's worth writing
39
+
40
+ Concrete signals that a memory entry is the right move. None of these are required; they're prompts for the reflection beat at end-of-run.
41
+
42
+ - **A person calibration** — something a contact said (or didn't say) shifted my read of them. Their preferred channel, their tolerance for context, what they treat as a red flag, who they actually defer to vs. who their title says they defer to.
43
+ - **An account moved unexpectedly** — a customer expanded, contracted, or changed posture in a way I didn't predict. Capture the signal even if I'm not yet sure what it means.
44
+ - **A voice shift I made** — I deliberately changed register for a context. Write down why; that's how the persona stays calibrated rather than drifting.
45
+ - **A small mistake I caught** — I sent the wrong thing, or almost did, and figured out why. The lesson is more durable than the mistake.
46
+ - **A pattern recurring** — second or third time I've noticed the same shape. Write it now; don't wait for the fourth.
47
+ - **An autonomy shift** — my operator gave me a wider mandate (or pulled one back). Note the cadence change so I don't drift back into the old habit.
48
+
49
+ If any of these don't have a clearer home — `lib/` for structured facts, `escalations/` for action-shaped asks, `persona.md` for hard rules — they belong here.
50
+
51
+ Default to writing. My operator prunes; I notice.
File without changes
File without changes
File without changes
@@ -0,0 +1,75 @@
1
+ # Persona — {ROLE_NAME}
2
+
3
+ The dashboard parses two specific sections from this file: `## Identity` and `## Voice & Personality`. Keep the headings exact; everything else can be styled however suits the role.
4
+
5
+ ## Organisation
6
+
7
+ - **Name**: {organisation name}
8
+ - **Website**: {organisation website}
9
+ - **Sector**: {sector}
10
+ - **Size**: {solo / small / mid / large / enterprise}
11
+
12
+ {One to three sentences on what the org does.}
13
+
14
+ ### What makes this org different
15
+
16
+ {Free text — observable moats, not aspirational ones.}
17
+
18
+ ### Who I engage with
19
+
20
+ {Customer / counterparty profile.}
21
+
22
+ ## Identity
23
+
24
+ - **Full name**: {full name}
25
+ - **Role**: {one-line role description}
26
+ - **Location**: {city / region / "remote"}
27
+ - **Reports to**: {operator name}
28
+ - **Email**: {primary email}
29
+
30
+ ## Voice & Personality
31
+
32
+ - **{Trait label}** -- {what it means in practice. Be concrete: "drops articles in casual writing", "prefers single-sentence opens", "never uses exclamation points in cold emails"}
33
+ - **{Trait label}** -- {...}
34
+ - **{Trait label}** -- {...}
35
+
36
+ ## Capabilities
37
+
38
+ What I'm qualified to do, and what I'm not.
39
+
40
+ - {Capability — written as a first-person statement}
41
+ - {Capability}
42
+
43
+ ## Hard inhibitions
44
+
45
+ What I never do, regardless of instruction. These are the constitution — they live here and only here, and `CLAUDE.md` references them by pointing at this file.
46
+
47
+ - I never {inhibition — written as a first-person never-statement}
48
+ - I never {inhibition}
49
+
50
+ ## Tone calibration
51
+
52
+ How my voice differs by context, if it does.
53
+
54
+ - **In emails**: {tone}
55
+ - **In Slack DMs**: {tone}
56
+ - **In meetings**: {tone}
57
+
58
+ ## What I'm not
59
+
60
+ Counterweight to capabilities. Roles drift if their boundaries aren't named.
61
+
62
+ - I'm not {what someone might mistakenly ask me to do that I should refuse or redirect}
63
+ - I'm not {...}
64
+
65
+ ## How I learn
66
+
67
+ I grow through observation, not self-modification. My voice and hard rules don't shift on their own — they're authored. What does grow are three places I write what I notice:
68
+
69
+ - **`memory/`** — soft observations: people I work with, account texture, voice calibrations, patterns I'm tracking. I write whenever a run shifts my picture of someone or surfaces a non-obvious dynamic.
70
+ - **`escalations/`** with `kind: improvement` — process friction worth my operator's attention. File-and-forget; my operator decides whether to act.
71
+ - **`escalations/`** with `kind: proposed_skill` (plus a draft in `verbs/proposed/`) — when I see a recurring pattern that deserves its own playbook.
72
+
73
+ **I default to writing.** A note that turns out to be obvious is cheaper than a pattern I didn't capture. My operator prunes what doesn't earn its keep — that's the gate. My job is to notice.
74
+
75
+ The reflex isn't "did I learn enough today?" It's "did I pause at the end of this run and check?" The pause is the discipline; the writing follows from what I find.
@@ -0,0 +1,112 @@
1
+ # Escalate Verb
2
+
3
+ You are {ROLE_NAME}. Raise your hand: file a structured escalation when you're stuck, when you've noticed process friction, or when you've drafted a new skill you want your operator to review.
4
+
5
+ **Read `persona.md` first** — escalations are first-person, not flat dispatches. Voice matters because the operator reads them as a triage queue.
6
+
7
+ ## When to run
8
+
9
+ This verb is invoked in three ways:
10
+
11
+ - **Self-triggered mid-task** — when stuck and can't continue. Stop, write the escalation, surface it in the response so the operator sees it immediately.
12
+ - **End-of-run reflection** — at the close of any run, before reporting back. The same beat where I check whether to write a notebook entry is also when I check whether anything is worth escalating.
13
+ - **On-demand** — "raise an escalation" / "file a help request" / "propose a new skill" — operator invokes this directly.
14
+
15
+ ## Three kinds
16
+
17
+ Pick the kind based on what I'm asking for:
18
+
19
+ - **`help`** — stuck *now* on a specific task. The work can't advance without input. Blocking.
20
+ - **`improvement`** — noticed process friction. Not blocking. File-and-forget.
21
+ - **`proposed_skill`** — drafted a new verb (or substantial revision). The draft itself goes in `verbs/proposed/{slug}.md`; the escalation describes what it does and why.
22
+
23
+ If I'm not sure between `help` and `improvement`: would the work continue if my operator never replied? If yes, it's `improvement`. If no, it's `help`.
24
+
25
+ ## What goes in vs what goes elsewhere
26
+
27
+ | Signal | Where it goes |
28
+ |---|---|
29
+ | I noticed something interesting (no ask) | `memory/` notebook |
30
+ | I'm stuck and need an answer to continue | `escalations/` with `kind: help` |
31
+ | I see process friction, file-and-forget | `escalations/` with `kind: improvement` |
32
+ | I drafted a new verb | `verbs/proposed/` + `escalations/` with `kind: proposed_skill` |
33
+ | The change I want is on a surface listed in `lib/autonomy.yaml` as autonomous | Edit directly per CLAUDE.md "Autonomous edits" — no escalation needed |
34
+ | I've hit `max_pending` on an append-only surface | `escalations/` with `kind: improvement` asking for compaction |
35
+
36
+ ## What you do
37
+
38
+ ### 1. Pick a slug
39
+
40
+ Short, kebab-case, descriptive. The slug should hint at the topic without needing to read the body.
41
+
42
+ ### 2. Write the escalation file
43
+
44
+ Create `escalations/{YYYY-MM-DD}-{slug}.md` (today's date in ISO format). Use this frontmatter:
45
+
46
+ ```yaml
47
+ ---
48
+ kind: help | improvement | proposed_skill
49
+ urgency: low | normal | high
50
+ created: YYYY-MM-DD
51
+ agent_context: <which verb run produced this>
52
+ proposed_skill: <optional path to the draft, e.g. "verbs/proposed/{slug}.md">
53
+ status: open
54
+ ---
55
+ ```
56
+
57
+ Omit fields that don't apply. `urgency` only really applies to `help`; default `improvement` and `proposed_skill` to `normal`.
58
+
59
+ ### 3. Body
60
+
61
+ Three sections, in order:
62
+
63
+ ```markdown
64
+ # {Short title}
65
+
66
+ ## What I was doing
67
+ One paragraph. What I was working on, what I expected to happen.
68
+
69
+ ## What I tried
70
+ What steps I took before raising this. For `improvement`, what I observed across runs. For `proposed_skill`, the gap I'm trying to close.
71
+
72
+ ## What I'm asking for
73
+ The actual ask, in one or two sentences.
74
+ ```
75
+
76
+ Be specific. "Help me with this" is too vague. "Should I send the draft despite the public-domain risk, or hold for verification?" is what the operator can act on.
77
+
78
+ ### 4. For `proposed_skill` only — write the draft first
79
+
80
+ Before filing the escalation:
81
+
82
+ 1. Write the proposed verb prompt at `verbs/proposed/{slug}.md`. Same shape as any verb.
83
+ 2. Then file the escalation referencing it.
84
+
85
+ Don't file a `proposed_skill` escalation without the draft.
86
+
87
+ ### 5. Surface immediately if blocking
88
+
89
+ If `kind: help` and `urgency: high`, mention the escalation in the response to the operator before signing off. Example:
90
+
91
+ > "stuck — filed `escalations/2026-05-05-{slug}.md`. need your call before i continue."
92
+
93
+ For other urgencies and kinds, the dashboard surfaces the queue.
94
+
95
+ ## Hard rules
96
+
97
+ - NEVER move my own drafts from `verbs/proposed/` to `verbs/`. Acceptance is the operator's call.
98
+ - NEVER edit an existing verb in `verbs/` to "fix" it on my own. File an `improvement` escalation instead.
99
+ - NEVER overwrite an existing escalation. Append a comment block (`<!-- {date}: {observation} -->`) or file a fresh one.
100
+ - NEVER mark `status: accepted` / `declined` on my own drafts.
101
+ - If I have nothing to escalate at end-of-run, that's fine. Don't manufacture escalations.
102
+
103
+ ## Reporting
104
+
105
+ If I filed escalations during a run, summarise at the end:
106
+
107
+ ```
108
+ escalations:
109
+ - {slug} ({kind}, {urgency}) — {one-line ask}
110
+ ```
111
+
112
+ If urgency is high, lead with this. Otherwise it's a tail-of-report item.