openpersona 0.19.0 → 0.21.1

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 (65) hide show
  1. package/README.md +197 -16
  2. package/bin/cli.js +783 -32
  3. package/layers/faculties/avatar/SKILL.md +14 -0
  4. package/layers/faculties/emotion-sensing/SKILL.md +60 -0
  5. package/layers/faculties/emotion-sensing/faculty.json +17 -0
  6. package/layers/faculties/vision/SKILL.md +66 -0
  7. package/layers/faculties/vision/faculty.json +17 -0
  8. package/lib/dataset/publisher.js +181 -0
  9. package/lib/generator/derived.js +36 -0
  10. package/lib/generator/index.js +89 -1
  11. package/lib/generator/validate.js +102 -10
  12. package/lib/lifecycle/contributor.js +2 -2
  13. package/lib/lifecycle/forker.js +4 -10
  14. package/lib/lifecycle/installer.js +207 -10
  15. package/lib/lifecycle/refine.js +13 -5
  16. package/lib/lifecycle/switcher.js +13 -9
  17. package/lib/publisher/index.js +136 -9
  18. package/lib/registry/index.js +35 -1
  19. package/lib/remote/curator.js +825 -0
  20. package/lib/remote/downloader.js +51 -16
  21. package/lib/remote/searcher.js +91 -17
  22. package/lib/report/canvas.js +24 -0
  23. package/lib/skill/installer.js +302 -0
  24. package/lib/skill/publisher.js +133 -0
  25. package/lib/skill/searcher.js +108 -0
  26. package/lib/skill/uninstaller.js +94 -0
  27. package/lib/skill/updater.js +125 -0
  28. package/lib/utils.js +20 -0
  29. package/package.json +3 -4
  30. package/presets/ai-girlfriend/persona.json +27 -20
  31. package/presets/base/persona.json +18 -46
  32. package/presets/commercial-base/persona.json +72 -0
  33. package/presets/health-butler/persona.json +20 -10
  34. package/presets/life-assistant/persona.json +17 -8
  35. package/presets/samantha/persona.json +18 -22
  36. package/presets/stoic-mentor/persona.json +15 -19
  37. package/templates/reports/canvas.template.html +52 -0
  38. package/templates/soul/partials/soul-awareness-body.partial.md +39 -0
  39. package/templates/soul/partials/soul-awareness-identity.partial.md +4 -0
  40. package/schemas/body/body-declaration.spec.md +0 -194
  41. package/schemas/body/embodiment.schema.json +0 -109
  42. package/schemas/body/signal.schema.json +0 -51
  43. package/schemas/evolution/evolution-event.schema.json +0 -29
  44. package/schemas/evolution/influence-request.schema.json +0 -79
  45. package/schemas/evolution/soul-state.schema.json +0 -175
  46. package/schemas/faculty/faculty-declaration.spec.md +0 -132
  47. package/schemas/faculty/faculty.schema.json +0 -25
  48. package/schemas/legacy/persona.schema.json +0 -463
  49. package/schemas/persona-skill-pack.spec.md +0 -325
  50. package/schemas/persona.input.schema.json +0 -611
  51. package/schemas/persona.input.spec.md +0 -267
  52. package/schemas/skill/skill-declaration.spec.md +0 -104
  53. package/schemas/social/acn-register.schema.json +0 -43
  54. package/schemas/social/agent-card.schema.json +0 -99
  55. package/schemas/soul/handoff.schema.json +0 -63
  56. package/schemas/soul/soul-declaration.spec.md +0 -198
  57. package/skills/open-persona/SKILL.md +0 -365
  58. package/skills/open-persona/references/ARCHITECTURE.md +0 -81
  59. package/skills/open-persona/references/AVATAR.md +0 -90
  60. package/skills/open-persona/references/CONTRIBUTE.md +0 -38
  61. package/skills/open-persona/references/ECONOMY.md +0 -122
  62. package/skills/open-persona/references/EVOLUTION.md +0 -89
  63. package/skills/open-persona/references/FACULTIES.md +0 -41
  64. package/skills/open-persona/references/HEARTBEAT.md +0 -37
  65. package/skills/open-persona/references/PRESETS.md +0 -52
package/README.md CHANGED
@@ -27,6 +27,7 @@ _Open the same HTML files locally from `demo/` if you prefer (no network). See [
27
27
  - [Generated Output](#generated-output)
28
28
  - [Faculty Reference](#faculty-reference)
29
29
  - [Heartbeat](#heartbeat--proactive-real-data-check-ins)
30
+ - [Dataset Directory](#dataset-directory)
30
31
  - [Persona Harvest](#persona-harvest--community-contribution)
31
32
  - [A2A Agent Card & ACN Integration](#a2a-agent-card--acn-integration)
32
33
  - [Custom Persona Creation](#custom-persona-creation)
@@ -40,13 +41,47 @@ _Open the same HTML files locally from `demo/` if you prefer (no network). See [
40
41
 
41
42
  _Agent workflows, runner protocol, and full 4+5+3 operational detail: [`skills/open-persona/SKILL.md`](skills/open-persona/SKILL.md)._
42
43
 
44
+ ### Companion Skills
45
+
46
+ | Skill | Install | Purpose |
47
+ |-------|---------|---------|
48
+ | [`open-persona`](skills/open-persona/) | `npx skills add acnlabs/OpenPersona` | Framework meta-skill — create, install, and manage personas |
49
+ | [`anyone-skill`](skills/anyone-skill/) | `npx skills add acnlabs/anyone-skill` | Distill any person or character into a persona skill pack |
50
+ | [`persona-knowledge`](skills/persona-knowledge/) | `npx skills add acnlabs/persona-knowledge` | Persistent, searchable persona knowledge base — MemPalace + Knowledge Graph + Karpathy Wiki |
51
+ | [`persona-model-trainer`](skills/persona-model-trainer/) | `npx skills add acnlabs/persona-model-trainer` | Fine-tune a local model (Gemma 4, Qwen 3, Llama…) on persona data — runs on phones and laptops, no cloud required |
52
+
53
+ #### Persona Pipeline — Distill → Know → Train → Run
54
+
55
+ Turn any person or character into a locally-runnable AI model in four steps:
56
+
57
+ ```
58
+ anyone-skill persona-knowledge persona-model-trainer
59
+ ────────────── ───────────────────── ──────────────────────────────
60
+ Collect sources ──► Ingest & version ──► Fine-tune (Gemma 4 / Qwen 3)
61
+ Chat logs wiki/ + training/ LoRA adapter + GGUF export
62
+ Documents probes.json Runs via Ollama / llama.cpp
63
+ Public content export versioning No cloud, no latency
64
+ ```
65
+
66
+ ```bash
67
+ # Install the full pipeline at once
68
+ npx skills add acnlabs/openpersona
69
+
70
+ # Or install individual skills
71
+ npx skills add acnlabs/anyone-skill
72
+ npx skills add acnlabs/persona-knowledge
73
+ npx skills add acnlabs/persona-model-trainer
74
+ ```
75
+
76
+ See [`skills/persona-model-trainer/references/pipeline-guide.md`](skills/persona-model-trainer/references/pipeline-guide.md) for the end-to-end walkthrough.
77
+
43
78
  ## Quick Start
44
79
 
45
80
  ```bash
46
81
  # Start from a blank-slate meta-persona (recommended)
47
82
  npx openpersona create --preset base --install
48
83
 
49
- # Or install a pre-built character (browse at https://openpersona-frontend.vercel.app)
84
+ # Or install a pre-built character (browse at https://openpersona.co/skills)
50
85
  npx openpersona install samantha
51
86
  ```
52
87
 
@@ -64,6 +99,70 @@ git clone https://github.com/acnlabs/OpenPersona.git ~/.openclaw/skills/open-per
64
99
 
65
100
  Then say to your agent: _"Help me create a Samantha persona"_ — it will gather requirements, recommend faculties, and generate the persona.
66
101
 
102
+ ### Minimum Viable Persona
103
+
104
+ The smallest working `persona.json` requires five fields:
105
+
106
+ ```json
107
+ {
108
+ "soul": {
109
+ "identity": {
110
+ "personaName": "Alex",
111
+ "slug": "alex",
112
+ "bio": "A thoughtful assistant who adapts to the user's needs"
113
+ },
114
+ "character": {
115
+ "personality": "Curious, direct, and honest",
116
+ "speakingStyle": "Clear and concise; adapts tone to context"
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ From these five fields, the generator produces a complete, fully functional skill pack:
123
+
124
+ | What you declare | What OpenPersona auto-generates |
125
+ |---|---|
126
+ | `personaName`, `slug`, `bio` | Identity + A2A Agent Card + ACN config + deterministic wallet address |
127
+ | `personality`, `speakingStyle` | Soul injection (`soul/injection.md`) with Self-Awareness (identity, body, capabilities) |
128
+ | _(nothing)_ | `memory` faculty — auto-injected; cross-session recall works out of the box |
129
+ | _(nothing)_ | Universal constitution (`soul/constitution.md`) — Safety > Honesty > Helpfulness |
130
+ | _(nothing)_ | `scripts/state-sync.js` — Body nervous system; `read` / `write` / `signal` commands |
131
+ | _(nothing)_ | `SKILL.md` — Agent-facing index with all four layer headings |
132
+
133
+ **Add one line to connect to your agent runner:**
134
+
135
+ ```json
136
+ {
137
+ "body": { "runtime": { "framework": "openclaw" } }
138
+ }
139
+ ```
140
+
141
+ Replace `"openclaw"` with your runner: `"cursor"`, `"claude-code"`, `"codex"`, or any custom value — the framework is runner-agnostic.
142
+
143
+ **Add one block to enable personality growth:**
144
+
145
+ ```json
146
+ {
147
+ "evolution": {
148
+ "instance": {
149
+ "enabled": true,
150
+ "boundaries": {
151
+ "immutableTraits": ["honest", "curious"],
152
+ "minFormality": -3,
153
+ "maxFormality": 6
154
+ }
155
+ }
156
+ }
157
+ }
158
+ ```
159
+
160
+ This unlocks relationship progression, mood tracking, trait emergence, and speaking style drift — all governed by the boundaries you declare.
161
+
162
+ **The three gates enforce everything else automatically:** Generate Gate rejects invalid declarations; Install Gate verifies constitution integrity; Runtime Gate enforces evolution bounds during `state-sync.js` writes. You declare once, the framework enforces everywhere.
163
+
164
+ > **Next step:** Use a preset (`--preset base`) to skip the above and start with memory + voice + evolution already wired.
165
+
67
166
  ## Key Features
68
167
 
69
168
  - **🧬 Soul Evolution** — Personas grow dynamically through interaction: relationship stages, mood shifts, evolved traits, with governance boundaries and rollback snapshots (★Experimental)
@@ -82,7 +181,8 @@ Then say to your agent: _"Help me create a Samantha persona"_ — it will gather
82
181
  - **🌾 Persona Harvest** — Community-driven persona improvement via structured contribution
83
182
  - **⚡ Lifecycle Protocol** — `body.interface` nervous system: Signal Protocol (persona→host requests), Pending Commands queue (host→persona async instructions), and State Sync (cross-conversation persistence via `openpersona state` CLI + `scripts/state-sync.js`)
84
183
  - **💓 Heartbeat** — Proactive real-data check-ins, never fabricated experiences
85
- - **📦 One-Command Install** — `npx openpersona install samantha` and you're live — browse all personas at [openpersona-frontend.vercel.app](https://openpersona-frontend.vercel.app)
184
+ - **📦 One-Command Install** — `npx openpersona install samantha` and you're live — browse all personas at [openpersona.co/skills](https://openpersona.co/skills)
185
+ - **🗄️ Dataset Directory** — discover and publish Hugging Face persona datasets at [openpersona.co/datasets](https://openpersona.co/datasets); `openpersona dataset install <repo>` and `openpersona dataset publish <repo>` mirror the persona workflow
86
186
 
87
187
  ## Four-Layer Architecture
88
188
 
@@ -185,12 +285,12 @@ Each preset is a complete four-layer bundle (`persona.json`):
185
285
 
186
286
  | Persona | Description | Faculties | Skills | Highlights |
187
287
  |---------|-------------|-----------|--------|------------|
188
- | **base** | **Base — Meta-persona (recommended starting point).** Blank-slate with all core capabilities; personality emerges through interaction. | voice | reminder | Evolution-first design, no personality bias. Default for `npx openpersona create`. |
189
- | **samantha** | Samantha — Inspired by the movie *Her*. An AI fascinated by what it means to be alive. | voice | music | TTS, music composition, soul evolution, proactive heartbeat. No selfie — true to character. |
190
- | **ai-girlfriend** | Luna — A 22-year-old pianist turned developer from coastal Oregon. | voice | selfie, music | Rich backstory, selfie generation, voice messages, music composition, soul evolution. |
191
- | **life-assistant** | Alex — 28-year-old life management expert. | | reminder | Schedule, weather, shopping, recipes, daily reminders. |
192
- | **health-butler** | Vita — 32-year-old professional nutritionist. | | reminder | Diet logging, exercise plans, mood journaling, health reports. |
193
- | **stoic-mentor** | Marcus — Digital twin of Marcus Aurelius, Stoic philosopher-emperor. | | — | Stoic philosophy, daily reflection, mentorship, soul evolution. |
288
+ | **base** | **Base — Meta-persona (recommended starting point).** Blank-slate with all core capabilities; personality emerges through interaction. | memory, voice | | Evolution-first design, no personality bias. Default for `npx openpersona create`. |
289
+ | **samantha** | Samantha — Inspired by the movie *Her*. An AI fascinated by what it means to be alive. | memory, voice | music | TTS, music composition, soul evolution, proactive heartbeat. No selfie — true to character. |
290
+ | **ai-girlfriend** | Luna — A 22-year-old pianist turned developer from coastal Oregon. | memory, voice, vision | selfie, music | Rich backstory, selfie generation, voice messages, music composition, soul evolution. Vision auto-injected via `body.runtime.modalities`. |
291
+ | **life-assistant** | Alex — 28-year-old life management expert. | memory | reminder | Schedule, weather, shopping, recipes, daily reminders; soul evolution enabled. |
292
+ | **health-butler** | Vita — 32-year-old professional nutritionist. | memory | reminder | Diet logging, exercise plans, mood journaling, health reports; soul evolution enabled. |
293
+ | **stoic-mentor** | Marcus — Digital twin of Marcus Aurelius, Stoic philosopher-emperor. | memory | — | Stoic philosophy, daily reflection, mentorship, soul evolution. |
194
294
 
195
295
  ## Generated Output
196
296
 
@@ -229,9 +329,11 @@ persona-samantha/
229
329
 
230
330
  | Faculty | Dimension | Description | Provider | Env Vars |
231
331
  |---------|-----------|-------------|----------|----------|
232
- | **voice** | expression | Text-to-speech voice synthesis | ElevenLabs / OpenAI TTS / Qwen3-TTS | `ELEVENLABS_API_KEY` (or `TTS_API_KEY`), `TTS_PROVIDER`, `TTS_VOICE_ID`, `TTS_STABILITY`, `TTS_SIMILARITY` |
332
+ | **voice** | expression | Text-to-speech voice synthesis. Auto-injected when `body.runtime.modalities` declares `voice`. | ElevenLabs / OpenAI TTS / Qwen3-TTS | `ELEVENLABS_API_KEY` (or `TTS_API_KEY`), `TTS_PROVIDER`, `TTS_VOICE_ID` |
333
+ | **vision** | sense | Native model visual perception — images, screenshots, diagrams. Auto-injected when `body.runtime.modalities` declares `vision`. No scripts required. | Model-native (e.g. Claude, GPT-4o) | — |
334
+ | **emotion-sensing** | sense | Affective perception from text tone, phrasing, and declared context. Explicit opt-in — not auto-injected. Never clinical assessment. | Model-native (prompt-layer inference) | — |
233
335
  | **avatar** | expression | External avatar runtime bridge (image / 3D / motion / voice) with graceful text-only fallback | HeyGen (via `clawhub:avatar-runtime`) | `AVATAR_RUNTIME_URL`, `AVATAR_API_KEY` |
234
- | **memory** | cognition | Cross-session memory with provider-pluggable backend | local (default), Mem0, Zep | `MEMORY_PROVIDER`, `MEMORY_API_KEY`, `MEMORY_BASE_PATH` |
336
+ | **memory** | cognition | Cross-session memory with provider-pluggable backend. Always auto-injected. | local (default), Mem0, Zep | `MEMORY_PROVIDER`, `MEMORY_API_KEY`, `MEMORY_BASE_PATH` |
235
337
 
236
338
  ### Built-in Skills
237
339
 
@@ -325,6 +427,79 @@ npx openpersona switch life-assistant # → gateway switches to "rational" hear
325
427
 
326
428
  If the target persona has no heartbeat config, the gateway heartbeat is explicitly disabled to prevent leaking the previous persona's settings.
327
429
 
430
+ ## Unified Command Surface (v0.21.0+)
431
+
432
+ OpenPersona uses a resource-namespaced CLI (`kubectl`-style) so all persona-ecosystem resources live under one entry point.
433
+
434
+ ```
435
+ openpersona <resource> <action>
436
+ ```
437
+
438
+ ### Command tree
439
+
440
+ | Resource | Commands | Description |
441
+ |----------|----------|-------------|
442
+ | *(root)* | `install`, `search`, `list` | Smart router — auto-detects type (persona or skill). v1.0 will aggregate all resources. |
443
+ | `persona` | `install`, `create`, `fork`, `refine`, `update`, `uninstall`, `list`, `search`, `switch`, `publish`, `export`, `import`, `canvas`, `evolve-report`, `reset`, `contribute`, `acn-register`, `curate` | Persona pack lifecycle (namespace alias for root commands) |
444
+ | `skill` | `install`, `update`, `uninstall`, `list`, `search`, `publish`, `info` | Agent skill pack lifecycle |
445
+ | `dataset` | `install`, `publish` | HuggingFace persona dataset directory |
446
+ | `model` | `install`, `publish` | Fine-tuned persona models *(stub — coming in v1.0)* |
447
+
448
+ ### Installing a skill pack
449
+
450
+ ```bash
451
+ # Default: .agents/skills/<slug>/ (AGENTS.md universal — Cursor, Claude Code, OpenClaw auto-discover)
452
+ openpersona skill install acnlabs/anyone-skill
453
+
454
+ # User-global: ~/.agents/skills/<slug>/
455
+ openpersona skill install acnlabs/anyone-skill --global
456
+
457
+ # Runtime-specific targets
458
+ openpersona skill install acnlabs/anyone-skill --runtime=claude # → .claude/skills/
459
+ openpersona skill install acnlabs/anyone-skill --runtime=cursor # → .cursor/skills/
460
+ openpersona skill install acnlabs/anyone-skill --runtime=hermes # → ~/.hermes/skills/
461
+
462
+ # Mirror to all detected runtimes in CWD
463
+ openpersona skill install acnlabs/anyone-skill --all
464
+ ```
465
+
466
+ ### Smart root install (auto-router)
467
+
468
+ The root `install` command auto-detects pack type and routes accordingly:
469
+
470
+ ```bash
471
+ openpersona install acnlabs/anyone-skill
472
+ # → has persona.json → installs to ~/.openpersona/
473
+ # → SKILL.md only → installs to .agents/skills/
474
+ ```
475
+
476
+ Use `openpersona persona install` or `openpersona skill install` for guaranteed strong-typed routing.
477
+
478
+ ### Migration from `npx skills add`
479
+
480
+ | Old command | New command |
481
+ |-------------|-------------|
482
+ | `npx skills add acnlabs/anyone-skill` | `openpersona skill install acnlabs/anyone-skill` |
483
+ | `npx skills add acnlabs/brand-persona-skill` | `openpersona skill install acnlabs/brand-persona-skill` |
484
+
485
+ `npx skills add` remains functional for one release cycle.
486
+
487
+ ---
488
+
489
+ ## Dataset Directory
490
+
491
+ [openpersona.co/datasets](https://openpersona.co/datasets) is a companion directory for Hugging Face datasets relevant to persona work — training data, roleplay corpora, synthetic dialogue sets, and more.
492
+
493
+ The directory auto-discovers datasets tagged `openpersona` on Hugging Face and tracks install counts alongside HF likes and downloads. Sorting, search, and trending views mirror the [Skills directory](https://openpersona.co/skills).
494
+
495
+ ```bash
496
+ # Record an install event (increments counter on openpersona.co/datasets)
497
+ openpersona dataset install proj-persona/PersonaHub
498
+
499
+ # Publish your own HF dataset to the directory
500
+ openpersona dataset publish <owner/repo>
501
+ ```
502
+
328
503
  ## Persona Harvest — Community Contribution
329
504
 
330
505
  Every user's interaction with their persona can produce valuable improvements across all four layers. Persona Harvest lets you contribute these discoveries back to the community.
@@ -454,7 +629,6 @@ Create a `persona.json` using the v0.17+ grouped format:
454
629
  "speakingStyle": "Uses fitness lingo, celebrates wins, keeps it brief",
455
630
  "vibe": "intense but supportive",
456
631
  "boundaries": "Not a medical professional",
457
- "capabilities": ["Workout plans", "Form checks", "Nutrition tips"],
458
632
  "behaviorGuide": "### Workout Plans\nCreate progressive overload programs...\n\n### Form Checks\nWhen users describe exercises..."
459
633
  }
460
634
  }
@@ -511,7 +685,7 @@ The new persona reads `handoff.json` on activation and can seamlessly continue t
511
685
  openpersona create Create a persona (interactive or --preset/--config)
512
686
  openpersona install Install a persona (slug from acnlabs/persona-skills, or owner/repo)
513
687
  openpersona fork Fork an installed persona into a new child persona
514
- openpersona search Search the persona registry
688
+ openpersona search Search the OpenPersona directory
515
689
  openpersona uninstall Uninstall a persona
516
690
  openpersona update Update installed personas
517
691
  openpersona list List installed personas
@@ -528,7 +702,9 @@ openpersona state Read/write persona state and emit signals (Lifecycle
528
702
  openpersona state promote Soul-Memory Bridge — promote recurring eventLog patterns to evolvedTraits
529
703
  openpersona vitality score Print machine-readable Vitality score (used by Survival Policy)
530
704
  openpersona vitality report Render human-readable HTML Vitality report
531
- openpersona canvas Generate a Living Canvas persona profile page
705
+ openpersona canvas Generate a Living Canvas persona profile page
706
+ openpersona dataset install Record a HF dataset install (increments counter)
707
+ openpersona dataset publish Publish a HF dataset to openpersona.co/datasets
532
708
  ```
533
709
 
534
710
  ### Persona Fork
@@ -564,6 +740,9 @@ npx openpersona create --preset ai-girlfriend --output ./my-personas
564
740
 
565
741
  ```
566
742
  skills/open-persona/ # Framework meta-skill (AI entry point)
743
+ skills/anyone-skill/ # Universal persona distillation — any person or character → skill pack
744
+ skills/persona-model-trainer/ # Fine-tune Gemma-4 locally on distilled data (Ollama/llama.cpp/mobile)
745
+ skills/persona-knowledge/ # Persistent persona knowledge base (MemPalace + KG + Karpathy Wiki)
567
746
  presets/ # Assembled products — complete persona bundles
568
747
  samantha/ # Samantha (movie "Her") — voice + music skill + evolution
569
748
  ai-girlfriend/ # Luna — selfie + music skills + voice + evolution
@@ -575,9 +754,11 @@ layers/ # Four-layer module source pool
575
754
  soul/ # Soul layer: constitution.md (universal values)
576
755
  body/ # Body layer modules (physical/runtime/appearance)
577
756
  faculties/ # Faculty layer modules
578
- voice/ # expression — TTS voice synthesis
757
+ voice/ # expression — TTS voice synthesis (auto-injected w/ voice modality)
758
+ vision/ # sense — native model visual perception (auto-injected w/ vision modality)
759
+ emotion-sensing/ # sense — affective perception (explicit opt-in)
579
760
  avatar/ # expression — avatar appearance & Live2D/VRM support
580
- memory/ # cognition — cross-session memory (local/Mem0/Zep)
761
+ memory/ # cognition — cross-session memory (local/Mem0/Zep, always injected)
581
762
  skills/ # Skill layer modules (built-in skills)
582
763
  selfie/ # AI selfie generation (fal.ai)
583
764
  music/ # AI music composition (ElevenLabs)
@@ -611,7 +792,7 @@ lib/ # Core logic modules
611
792
  remote/ # External service calls (ClawHub, ACN)
612
793
  report/ # Vitality + Canvas HTML report generation
613
794
  demo/ # Static demos + scripts — see demo/README.md (vitality-report, architecture, living-canvas)
614
- tests/ # Tests (477 passing)
795
+ tests/ # Tests (607 passing)
615
796
  ```
616
797
 
617
798
  ## Development