pi-caduceus

Pi extension: persona-aware general-purpose lifecycle harness for the pi coding agent. Injects a deterministic, testable, byte-citable persona prompt segment before the first token of a pi session (mode, locale). Drives the full Spec-Driven Development li

Packages

Package details

extensionthemeprompt

Install pi-caduceus from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-caduceus
Package
pi-caduceus
Version
0.6.3
Published
Aug 27, 2026
Downloads
1,374/mo · 217/wk
Author
lyssom
License
MIT
Types
extension, theme, prompt
Size
590.9 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./extensions"
  ],
  "themes": [
    "./themes"
  ],
  "prompts": [
    "./prompts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-caduceus

npm version npm downloads License: MIT 0 deps Tests: 387 pi.dev

Persona-aware Spec-Driven Development lifecycle harness for pi. 10 built-in caduceus-original personas, a 5-MD-file SDD change lifecycle (explore → propose → apply → archive), a 6-state review machine with content-bound receipts, and 5 static-analysis lenses (risk/correctness/security/readability/spec-compliance) with P0–P3 severity. 0 runtime dependencies · 0 native binaries · 0 postinstall.

TL;DR

pi install npm:pi-caduceus

# In any pi session:
/caduceus:sdd:init my-feature            # create openspec/changes/my-feature/
/caduceus:sdd:explore <topic>          # requirements.md skeleton
/caduceus:sdd:propose my-feature        # render proposal.md
/caduceus:sdd:apply                     # mark completed tasks
/caduceus:review:start my-feature security   # persona-required lenses track
/caduceus:review:finalize my-feature    # writes content-bound receipt
/caduceus:sdd:archive                   # move to openspec/changes/archive/

Why pi-caduceus?

Feature pi-caduceus gentle-pi dracond
Persona layer ✅ 10 built-in, byte-stable, lint-tested ✅ 1 persona, brand-locked
SDD lifecycle ✅ 5-MD-file (proposal/design/tasks/requirements/constitution) ✅ 5-MD-file ✅ goal-queue
Review state machine ✅ 6-state + content-bound receipt ✅ Minisign-signed receipt ✅ detached auditor
Static-analysis lenses ✅ 5 lenses, P0–P3 severity
Subagent orchestration ⏳ Deferred (long-term) ❌ (delegated to pi-subagents)
Goal loop + budget ⏳ Under re-evaluation ✅ native ✅ mission-control
Runtime deps 0 0 0
Native binaries 0 yes (runtime/) 0
Postinstall 0 yes 0
Tarball ~116 kB ~7.6 MB ~545 kB
LOC ~7,300 ~56,000 ~28,000
License MIT MIT AGPL-3.0

Positioning: caduceus is the focused middle ground between feature-bloated (gentle-pi, dracond) and feature-thin (one-file loaders). It does the persona+SDD+review+lens core well in ~7 kLOC of pure TS, and bridges to nothing — every referenced pattern is re-implemented from scratch under MIT to preserve brand independence. Subagent orchestration and goal-loop layers are deferred long-term in favor of depth in the audit surface (see STATUS.md §7).

Install

pi install npm:pi-caduceus
# or
npm install -g pi-caduceus

That's it. No native binaries download, no postinstall script runs. pi loads the extension and registers 21 slash commands on session start (/caduceus:status, /caduceus:persona <name>, /caduceus:sdd:*, /caduceus:review:*).

What's in the box

10 built-in personas (prompts/)

default, plain, concise, reviewer, teacher, security, debugger, socratic, architect, pirate. Drop your own at ~/.pi/agent/caduceus/personas/<name>.md (global) or .caduceus/personas/<name>.md (project). /caduceus:lint enforces 8 structural checks (ID block, persona block, principles block, no-timestamp, ${mode} placeholder, conflicting-voice markers, …).

Spec-Driven Development (lib/sdd-templates.ts)

5-MD-file change artifact: proposal.md, design.md, tasks.md, requirements.md, constitution.md. The tasks.md template (v0.6.0+) includes an optional **Done when:** contract per task; the correctness lens fires on v0.6.0+-marker changes to enforce it. The constitution.md carries RFC 2119 levels (MUST/SHOULD/MAY) + CWE mappings; 5-check constitution-lint guards conformance.

Review state machine (lib/review-state-machine.ts)

6-state machine: idle → started → in-review → finalized → validated, plus terminal abandoned and synthetic corrupted. Receipt is content-bound SHA-256 over the 5 MD files (no crypto signing; design choice documented in docs/RESEARCH.md §2). v0.6.0+ receipts carry per-lens findings in lensRuns: LensRunDetail[].

5 static-analysis lenses (lib/lens/)

Lens Severity Detects
risk P1/P2/P3 BREAKING/DEPRECAT keyword (P1); ≥3 TODO/FIXME markers (P2); >10 files in change dir (P3)
correctness P1/P2 design.md references REQ-NNN not in requirements.md (P1); CON-NNN not in constitution.md (P2); **Done when:** missing on v0.6+ tasks (P2)
security P0/P1 MUST/SHALL-level CON-NNN lacking CWE field (P0); secret keywords password/api_key/token/secret (P1); curl|sh/wget|sh/sudo (P1)
readability P2/P3 MD file >200 lines (P2); proposal.md missing required sections (P2); depth-5+ headings (P3)
spec-compliance P1/P2 REQ-NNN declared but uncovered (P1); proposal.md §3 omits changeName (P2); CON-NNN declared but unreferenced (P2)

Findings are capped at 20 per lens with truncated: true. Persona-aware routing: security → [security, risk], reviewer → [readability, spec-compliance], architect → [spec-compliance, risk], debugger → [correctness].

Profile system

Save/load whole config sets as named profiles (mode + locale + systemPromptMode + persona). Storage: ~/.pi/agent/caduceus/profiles/<name>.json (global) and .caduceus/profiles/<name>.json (project, shadows global).

Brand independence

scripts/verify-package.mjs enforces 17 pre-publish invariants, including a grep for the v0.3.0 forbidden brand strings (gentle-pi content, retained as the legacy of caduceus's predecessor lineage) and an import-block on pi-review/pi-agents/dracond/ pi-muselinn-harness. caduceus references their patterns at the design level (in docs/RESEARCH.md §2 + STATUS.md §8) and re-implements in pure TS from scratch.

What's NOT in v0.6.2 (deliberately)

Feature Status Reason
Subagent orchestration Deferred (long-term) Was v0.7.0 plan; deferred 2026-08-18 — conflicts with caduceus's single-session review stance and DNA-3 ("light at core"). Re-evaluation gated on pi host API + ≥1 binding persona needing multi-agent. See STATUS.md §7.0.
Goal loop + budget Under re-evaluation Was v0.8.0 plan. pi-muselinn-harness's Swarm+Goal pattern is for long-horizon autonomy; caduceus is single-session. Re-evaluation gated on session-spanning pi API + user pain + lens calibration success. See STATUS.md §7.5.
Lens false-positive calibration Active P0 (v0.6.3 target) scripts/lens-calibration.mjs shows ~80% FP rate on archived changes (see STATUS.md §7.6). Must ship before any new lifecycle work.
LLM-based lens never Would break 0-deps invariant
Network calls in lens never Static analysis only
Detached auditor process Under re-evaluation Was v0.8.0+ evaluation; triggers on lens false-negative > 20%, AGPL-3.0 isolation required. Tied to v0.8.0 (above).

Architecture (DNA-3)

+---------------------+
|       pi (host)     |
+---------------------+
   |
   v
+---------------------+
|  extensions/caduceus.ts  |  <- SHELL (the only file that imports from pi)
+---------------------+
   |
   v
+---------------------+
|  lib/  (~24 pure-TS modules) |  <- MEAT (testable in plain node)
|  - persona-contract    |
|  - persona-lens-router |
|  - review-state-machine|
|  - review-receipt     |
|  - sdd-templates       |
|  - sdd-flow           |
|  - constitution-lint  |
|  - lens/{risk,correctness,security,readability,spec-compliance}  |
+---------------------+

The lib/ modules are pure functions over their inputs. The shell in extensions/caduceus.ts is a thin binding that wires the slash commands and before_agent_start hook. This separation means all 387 tests run with plain node --test, no jest, no vitest, no native test runner.

Testing & verification

npm test           # 387 tests, 0 failures
node scripts/verify-package.mjs   # 17 pre-publish checks

Both run on plain Node 22+ with --experimental-strip-types. No build step, no TypeScript compile, no native deps.

License

MIT. See LICENSE.

Acknowledgments

Patterns referenced (re-implemented in pure TS, never imported):

  • gentle-pi (Gentleman-Programming/gentle-ai) — persona layer, 5-MD-file SDD, review state machine (predecessor lineage; brand independence since v0.3.0)
  • dracond (DraconDev/pi-goal-list-loop-audit) — detached auditor worker process, regression shield, mission-control goal loop (design-level reference only; v0.8.0+ evaluation, AGPL-3.0 license isolation)
  • pi-muselinn-harness — triple-budget goal loop (design-level reference; v0.8.0+ evaluation)
  • pi-review — P0/P1/P2/P3 priority tier convention adopted in caduceus lens findings (v0.6.0)
  • pi-agents — multi-agent workflow pattern (reference only; caduceus does not ship subagents — see STATUS.md §7.0)

See docs/RESEARCH.md and STATUS.md §8 for full attribution. | /caduceus:status | Show the effective configuration. | | /caduceus:mode <default\|plain\|auto> | Switch persona mode (the label that runs through the persona). | | /caduceus:locale <auto\|es-AR\|es-ES\|en\|zh> | Set the locale preference. | | /caduceus:persona <name\|list> | Switch persona; list shows built-in + global + project. | | /caduceus:prompt <append\|replace> | How to inject the persona (append = default, replace = persona only). | | /caduceus:inspect | Print the rendered persona prompt. | | /caduceus:lint | Run static checks on the active persona. | | /caduceus:create <name> <description> | Generate a new persona file from a name and description. | | /caduceus:diff [a [b]] | Diff two personas (defaults: active vs default). | | /caduceus:profile <list\|save\|load\|delete\|show> <name> | Save/load/list/delete/show config profiles. | | /caduceus:sdd:init <name> | Initialize a change dir with 5 MD templates. | | /caduceus:sdd:explore <topic> | Show requirements.md skeleton for the active change. | | /caduceus:sdd:propose <name> | Generate proposal.md from requirements.md. | | /caduceus:sdd:apply | Mark completed task checkboxes for the active change. | | /caduceus:sdd:archive | Move the active change to openspec/changes/archive/. | | /caduceus:review:inspect <change> | Show current review state snapshot. | | /caduceus:review:start <change> [<persona>] | Start a review; persona defaults to active. | | /caduceus:review:advance <change> [advance\|abandon] | Advance the review state. | | /caduceus:review:finalize <change> | Finalize and write content-bound receipt. | | /caduceus:review:validate <change> | Re-validate receipt against current artifacts. | | /caduceus:review:reset <change> | Recover from corrupted state.json. |

Lifecycle Foundation (v0.5.0)

caduceus v0.5.0 ships a persona-aware general-purpose lifecycle harness for the pi coding agent. The 11 new slash commands (5 SDD + 6 review) drive a full OpenSpec-style change lifecycle with content-bound JSON receipts — no native binaries, no crypto signing.

SDD commands

/caduceus:sdd:init my-feature
# Creates openspec/changes/my-feature/ with 5 MD templates:
#   proposal.md, design.md, tasks.md, requirements.md, constitution.md

/caduceus:sdd:explore <topic>
# Returns the requirements.md skeleton for the active change

/caduceus:sdd:propose my-feature
# Renders proposal.md from the requirements context

/caduceus:sdd:apply
# Marks completed task checkboxes (idempotent)

/caduceus:sdd:archive
# Moves the change to openspec/changes/archive/<ISO-timestamp>-<name>/
# Requires a finalized receipt (finalVerificationPassed: true)

Review commands (6-state machine)

/caduceus:review:inspect my-feature
# Show current review state snapshot

/caduceus:review:start my-feature security
# Transition idle → started; capture persona

/caduceus:review:advance my-feature advance   # or 'abandon'
# Transition started → in-review (or any → abandoned)

/caduceus:review:finalize my-feature
# Transition in-review → finalized; write content-bound receipt

/caduceus:review:validate my-feature
# Re-validate receipt against current artifacts; reports receiptValid

/caduceus:review:reset my-feature
# Recover from corrupted state.json (per design.md §12 R3)

The receipt is a JSON document with the content hash of the 5 MD artifacts, the active persona snapshot, and a verification boolean. Reing Read it back with /caduceus:review:validate; modifying any of the 5 files invalidates the receipt.

Persona-aware lens framework

5 lens slots are wired (risk, correctness, security, readability, spec-compliance). 4 of the 10 built-in personas trigger lens requirements when they review:

Persona Required lenses
security security, risk
reviewer readability, spec-compliance
architect spec-compliance, risk
debugger correctness

See design.md §6.3 for the full routing table.

Constitutional constraints (RFC 2119)

constitution.md carries MUST/SHOULD/MAY-level principles. The built-in linter enforces:

  • CONSTITUTION_EXISTS — file is non-empty
  • CONSTITUTION_RFC2119Level is a valid RFC 2119 keyword
  • CONSTITUTION_CWE_MAPPING — MUST-level principles must have a CWE reference (or explicit CWE: N/A)
  • CONSTITUTION_COUNT — 0 principles → error; only MAY → warning
  • CONSTITUTION_NO_DUPLICATE_IDSCON-NNN IDs must be unique

Lens Framework (v0.6.0)

caduceus v0.6.0 populates the v0.5.0 lens framework with 5 real static-analysis implementations. When /caduceus:review:finalize is called, the persona-required lenses run against the change directory; findings are captured in the receipt's lensRuns field and surfaced in /caduceus:review:inspect output.

Lens Severity What it detects
risk P1/P2/P3 BREAKING/DEPRECAT keyword (P1); ≥3 TODO/FIXME markers (P2); >10 files in change dir (P3).
correctness P1/P2 design.md references REQ-NNN not in requirements.md (P1); CON-NNN not in constitution.md (P2); tasks.md missing **Done when:** (P2, gated by v0.6.0 marker); task with zero checkboxes (P2).
security P0/P1 MUST/SHALL-level CON-NNN lacking CWE field (P0); secret keywords in tasks/design (P1); risky shell patterns curl|sh / wget|sh / sudo (P1).
readability P2/P3 MD file >200 lines (P2); proposal.md missing required sections (P2); depth-5+ headings (P3).
spec-compliance P1/P2 REQ-NNN in requirements.md not covered by any task (P1); proposal.md §3 Scope omits changeName (P2); CON-NNN not referenced in proposal/design (P2).

Severity tiers

Tier Caduceus meaning
P0 Critical — must-fix. (caduceus reports only; does NOT auto-block in v0.6.0.)
P1 Warning — review and decide.
P2 Info — readability / consistency issue.
P3 Style / minor — consider fixing.

Persona → lens routing

Persona Required lenses
security security, risk
reviewer readability, spec-compliance
architect spec-compliance, risk
debugger correctness
(others) (none — non-binding)

The default and plain personas allocate no lenses; v0.5.0 receipts (with lensRuns: []) still validate via /caduceus:review:validate.

Built-in Personas

Persona Category Use case
default domain (default) Senior developer / architect voice. Direct, technical, names tradeoffs.
plain domain Minimal voice. Just answers the question.
concise style 1-3 sentence answers, no preamble.
reviewer style Code review with BLOCKER/SHOULD/NIT severity.
teacher style Patient teacher. Explains concepts step by step.
security domain Paranoid security engineer. Flags vulns by severity.
debugger domain Methodical debugger. Traces through code paths.
socratic style Socratic teacher. Answers questions with questions.
architect domain Systems architect. Names tradeoffs, prefers boring tech.
pirate style (easter egg) Speaks like a pirate, technically accurate underneath.

Add your own by dropping a markdown file at ~/.pi/agent/caduceus/personas/<name>.md (global) or .caduceus/personas/<name>.md (project), then run /caduceus:persona <name>. Or use the wizard:

/caduceus:create wizard Speaks like a wise wizard who never gives direct answers
# Lints the result, writes to ./.caduceus/personas/wizard.md
# Switch with: /caduceus:persona wizard

Profiles

Save and load whole config sets as named profiles. Profiles live in ~/.pi/agent/caduceus/profiles/<name>.json (global) or .caduceus/profiles/<name>.json (project).

/caduceus:profile save work
# Saves the current effective config as "work"

/caduceus:profile load learning
# Loads "learning" — updates mode, locale, systemPromptMode, persona
# atomically. v0.2.0 names in the loaded profile are auto-migrated
# to v0.3.x names.

/caduceus:profile list
# Shows all available profiles (project shadows global)

/caduceus:profile show work
# Displays the contents of the "work" profile

/caduceus:profile delete work
# Removes the "work" profile

Persona macros

Persona files can reference context-aware placeholders that are resolved at render time. Supported macros:

Macro Value
${userName} OS user ($USER or $USERNAME, falls back to "user")
${projectName} basename of current working directory
${cwd} full current working directory path
${date} today, ISO format (YYYY-MM-DD)
${os} process.platform (linux, darwin, etc.)
${mode} current persona mode (e.g., default, plain, auto)

The default persona uses ${projectName} to greet the user with the project name. The lint warns on unknown macros but does not fail.