@hobin/developer
Adaptive product-development reasoning and evidence for Pi.
Package details
Install @hobin/developer from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@hobin/developer- Package
@hobin/developer- Version
0.1.8- Published
- Jul 24, 2026
- Downloads
- 932/mo · 932/wk
- Author
- hobin_jang
- License
- MIT
- Types
- extension, skill
- Size
- 360.8 KB
- Dependencies
- 1 dependency · 4 peers
Pi manifest JSON
{
"extensions": [
"./extensions/developer.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@hobin/developer
Adaptive product-development judgment for Pi.
Developer combines a small, branch-aware coordination extension with ten independent skills. It routes one concrete question or green-to-green movement at a time, records the resulting evidence, and preserves unresolved questions. Its default topology gives feature work a useful backbone without turning every task into a fixed lifecycle.
Install
Requires Node.js 22.19 or newer. Tested with Pi 0.80.3 and 0.80.10.
pi install npm:@hobin/developer
Try it for one run without installing:
pi -e npm:@hobin/developer
Quick start
Start Pi, turn Developer on, and describe the product task normally:
/develop on
The selected payment method disappears after navigating back to checkout. Find the cause and fix it.
Developer decides whether the next concrete question would benefit from a focused skill or is already justified as implementation action. You do not need to call its internal protocol tools yourself. While Developer is on, Pi's built-in shell and artifact tools follow the active route.
Commands
| Command | Effect |
|---|---|
/develop |
Open the non-overlay Developer settings surface |
/develop on |
Enable adaptive routing and route-bound access to Pi built-in bash, edit, and write |
/develop status |
Inspect current branch state in a read-only panel |
/develop questions |
Choose an unresolved question, answer it or request investigation, and submit it to Pi |
/develop off |
Disable the protocol and clear current protocol state |
Explicit command arguments participate in Pi's completion UI. In interactive use, turning Developer off while a route or unresolved question exists requires confirmation. The historical session entries remain; only current protocol state is cleared.
Start a non-interactive or preconfigured session with Developer enabled:
pi --develop
Activation and tool policy
Developer has one boolean setting: on or off. When on, adaptive routing and the
route-bound tool policy always apply. Pi built-in bash is available during
skill and implementation routes; built-in edit and write require an active
implementation route and no before-implementation gate. When off, Developer
clears current protocol state and restores only tools that it withheld.
The tool policy and question gates are workflow-integrity controls, not a security
sandbox. A skill route receives the shell execution lane needed for repository
inspection and verifier execution, while structured edit/write mutation
remains implementation-only. Shell commands are not parsed as a security language; skill
contracts prohibit artifact mutation, and adversarial evaluation checks the
workspace boundary. Developer recognizes Pi built-ins from their provenance,
preserves unrelated active tools, and does not force-enable tools the user
disabled.
Before Pi tears down a session runtime, Developer releases its route-bound tool
delta so a reload, session replacement, or later extension instance does not
inherit orphaned restrictions. After that release, the package records a
reload-safe lifecycle marker. If an in-process reload finds older Developer
history without a later release marker, Developer stays off and requires a full
Pi process restart. Neither /reload nor /develop off → on can safely infer
which built-ins the user originally enabled.
How a request runs
Developer adds two model-facing protocol tools:
developer_route_questionopens one route for one concrete question.- The route target is
implementationor one currently available Developer skill. - A skill route returns the exact Pi-discovered
SKILL.mdinstructions and canonical path; an implementation route declares one movement, its stable landing, and its narrow verification. A behavior-preserving structural route also loads the focused execution profile based on flocking-style movement and small tidyings. developer_record_judgmentcloses the route with a status, result, evidence, artifacts, and any newly opened questions. Developer then routes again from the stable landing before another movement.- Consecutive implementation routes remain valid. To prevent routing by momentum, a implementation route that follows an implementation judgment must cite the previous landing evidence and record the plausible skill routes reconsidered plus why they add no useful judgment at that point.
The conditional default topology is:
clarify when needed → model consequential cases
→ sketch the first feature implementation surface OR signal existing-code movement
→ one implementation green-to-green movement → re-route from evidence
→ verify before completion
This is not a mandatory phase sequence. A stage may be not applicable and new
evidence may route backward or sideways. One guard is deliberate: a resolved
model cannot flow straight into mutation. New feature work receives an initial
sketch; existing-code structural work receives a signal first.
Product code is still read, edited, executed, and tested with Pi's normal tools. Developer's tools only route and record judgment; they do not implement product changes themselves.
There is never a required order such as specify → model → sketch → verify.
Each new route is chosen from the current question and evidence.
What the TUI shows
Developer uses different Pi surfaces for different information:
- The footer contains only activation, protocol state, and current route target.
- A compact widget appears only while a route or unresolved question exists.
/developuses Pi'sSettingsListsemantics: theDeveloperrow shows and toggles the current On/Off value,Statusopens branch details,History · Nopens complete route/judgment records when present, andOpen questions · Nappears only when unresolved questions exist./develop statusopens a non-overlay, branch-grounded, read-only status panel with recent route/judgment history and the alternatives recorded for consecutive implementation work./develop questionsuses stable internal question IDs. A sole question opens directly; multiple questions use one selector. Every open question, regardless of owner or gate, first shows a complete non-overlay decision brief: context is rendered as Markdown, then blocked work, gate, resolution criteria, and every structured field/option appear before Continue or Leave open controls. Cancelling the first field or editor returns to that brief; leaving the brief returns to the parent without changing protocol state.- A newly opened, answerable user question that gates implementation work is pushed
to the same explanation-first brief before the judgment tool returns. The user
may continue only after reviewing the explanation or leave it open. Structured
responses then collect each option/detail and provide review/edit before submission.
The answer still requires a focused judgment and explicit
question_updates. - Developer custom surfaces leave mouse ownership with the terminal: wheel/trackpad scrolls normal-buffer content, drag selects text, and Cmd+C copies it. Wheel input never changes the selected control; arrow keys do. Potentially long surfaces render complete content rather than hiding it behind an application-owned viewport.
- Protocol tool rows show compact status by default and higher-contrast evidence details when expanded with the user's configured Pi keybinding. They render without Pi's default full tool-row background.
RPC, JSON, and print modes keep the same protocol semantics without depending on terminal components.
Protocol states
| State | Meaning |
|---|---|
idle |
No active route and no unresolved Developer question |
needs-judgment |
One route is active and must be closed with a judgment |
needs-evidence |
At least one agent- or environment-owned evidence question remains open |
needs-answer |
At least one user-owned answer or decision remains open |
needs-routing |
An implementation stable landing must be re-observed and routed again |
needs-verification |
Changed artifacts still need a resolved verify judgment |
blocked |
A question is unavailable or explicitly gates implementation work |
These are routing states, not product-completion claims. In particular:
idledoes not mean the user's task is finished.- A resolved
specifyjudgment is not user acceptance. - A resolved
verifyjudgment is not timeless proof after later changes.
Pending questions receive stable internal IDs, but users do not type them. Each question records:
resolutionOwner:agent,user, orenvironment;gate:none,before-implementation, orbefore-completion;resolutionCriteria: the observable evidence or answer that closes it;context: Markdown explanation rendered before answer controls for every open question; required for user-ownedbefore-implementationandbefore-completionquestions, optional for other and legacy questions;- optional user-owned
responseSpec: a boundedchoice-formwith required single-choice fields and optional per-option detail prompts.
A producer should use response_spec when a user must answer finite decisions
such as A, B1–B4, C, and so on. Each decision becomes one field; the TUI does not
infer controls by parsing Markdown. Options such as A3 or G3 that need additional
input declare detail_prompt. Missing or malformed replay data falls back to the
freeform editor without dropping the pending question.
Selecting /develop questions always opens the explanation brief before any
structured control or owner-specific editor. User questions then ask for the
required decision, agent questions ask Pi to investigate, and environment
questions request access or an external observation. Submitting
focuses the question in branch state; an explicit ID, focus, or exact question
match associates the next route. Selection alone never closes it.
Every judgment rechecks all pending questions. question_updates can resolve an
unfocused question when implementation, tests, inspection, user input, or an
environment observation naturally supplies its criteria. A focused question
must receive an explicit update: resolve or dismiss it with concrete basis,
retain it as open or blocked, or close the broad parent while opening narrower
children. Resolved and not-applicable updates remove the question with recorded
basis; open or blocked updates preserve its identity. A before-implementation question blocks both implementation
routes and Pi built-in artifact tools while Developer is on. A
before-completion question allows investigation and implementation but keeps
the protocol non-idle and prevents verification debt from being cleared as a
completion claim.
A resolved or not-applicable judgment may preserve a distinct follow-up question: finishing the routed judgment does not imply that no later work was discovered. It may not reopen its own normalized question under a resolved status; that route must remain needs-evidence/blocked or explicitly refine a focused parent instead.
When a judgment replaces a broad unresolved question with more specific evidence questions, only the actionable children remain. Equivalent question wording is deduplicated while preserving the existing identity.
Skills
Pi may match these skills automatically, Developer may route a question to one,
or the user may invoke one directly with /skill:<name>.
| Skill | Helps decide |
|---|---|
specify |
Product meaning, scope, invariants, risks, and blocking unknowns |
model |
Condition spaces, contracts, replacement, transitions, guarantees, and verification targets |
sketch |
Inspectable code/pseudocode skeletons, case and interface tables, boundary/flow maps, state, responsibility, and variation |
signal |
Evidence-backed structural movement and model-code mismatch |
naming-judgment |
Domain sense, honest effects, and change-preserving names |
abstraction-review |
Whether a candidate should be kept, revised, split, rejected, or deferred |
schedule |
Behavior/structure timing: now, after, or never |
verify |
Verifier selection, evidence relevance, and pass-but-wrong risk |
visualize |
The smallest visual surface that lowers judgment cost |
adversarial-eval |
Finite, escalating attempts to falsify a skill or implementation claim |
Each leaf chooses a surface that matches its inspection problem instead of
returning undifferentiated prose: contract and scope tables for specify, case
or transition models for model, code/interface/check surfaces for sketch,
artifact comparisons for signal, rename maps for naming-judgment, review
cards and boundaries for abstraction-review, timing matrices for schedule,
evidence matrices for verify, escalation matrices for adversarial-eval, and
a completed visual artifact for visualize when a visual is warranted. Simple
judgments may remain compact when prose is genuinely clearer.
Skill judgment results preserve those surfaces as Markdown. Expanded protocol rows render tables and code blocks through Pi's Markdown component rather than flattening them into dim text.
Pi's loaded resource metadata is authoritative. If package configuration filters or disables a skill, Developer cannot route to it even if its file exists in the npm package.
Several skills link to detailed capability documents under their own
references/ directory. Pi loads the SKILL.md instructions on demand; the
instructions say when each reference is worth reading and resolve it relative to
the skill directory. A reference may synthesize several sources because the
leaf's question, not a book title, owns the capability. Each source-derived
reference includes a source trace, and SOURCES.md maps the full
book coverage across leaves and the implementation path. Small, settled judgments do not
need the extra context.
Primary references retain the capability's core insight and one complete case.
When a question has materially different derivation rules, the skill routes a
more focused supporting reference—for example, data-shape templates separately
from generative recursion, or representation barriers separately from state and
time. This follows Pi's documented progressive-disclosure structure: supporting
files stay relative to their skill and load only when the unresolved question
needs them. SOURCES.md also records the reference-quality contract used to
prevent source summaries from replacing executable judgment recipes.
Developer treats Pi's loaded systemPromptOptions.skills metadata as the skill
SSOT. It does not rescan the package and cannot route a skill Pi filtered,
disabled, or replaced through resource configuration.
State, branches, and compaction
Activation changes are stored as Pi custom session entries. Routes and judgments
are stored in tool-result details. Developer replays the current branch through
an XState v5 machine on startup and tree navigation, so a fork inherits only the
events on its branch. Parallel machine regions keep activation, route, question gates,
framing debt, and verification debt explicit; transition guards reject an implementation
route while a before-implementation question remains.
developerMachine (parallel)
├── activation: disabled | enabled
├── route: idle | judgment | implementation
├── questions: clear | open
├── implementationGate: clear | blocked
├── completionGate: clear | blocked
├── checkpoint: ready | required
├── framing: clear | required
└── verification: current | required
Judgment routes carry the execute tag, implementation routes carry execute and
mutate, and question/debt regions expose blocking tags. Every implementation judgment
moves the checkpoint to required; the next accepted route returns it to
ready. Tool availability, runtime call guards, status, and implementation-transition
eligibility are derived from the same machine snapshot.
The current event contract is developer/v5. Earlier protocol entries are not
replayed; this breaking contract uses target, implementation, and
before-implementation consistently across tools, events, and machine state.
A process started on the current package may open a branch containing those
entries, but hot-reloading directly from a pre-handoff runtime is rejected with
a restart instruction so its in-memory tool ownership cannot be mistaken for
user configuration.
Developer deliberately leaves compaction ownership to Pi. It does not trigger,
cancel, or replace threshold/overflow compaction, so it cannot override the
user's Pi settings or race another extension. Configure earlier compaction with
Pi's compaction.reserveTokens and compaction.keepRecentTokens settings when
a large-context model reaches its limit too abruptly.
Each new agent turn receives current protocol state, and route results place identity and recovery metadata before potentially long skill instructions. That makes the active route recoverable after Pi compacts normally. Tool output is checked against Pi's standard size limits before state changes are committed. At most twenty pending questions may remain in current state.
Update, configure, and remove
pi list
pi config
pi update npm:@hobin/developer
pi remove npm:@hobin/developer
Use a project-local install when a repository should declare the package in
.pi/settings.json:
pi install -l npm:@hobin/developer
Pi packages execute with Pi's system access. Review the extension and skills before installation. See the Pi package documentation for package scope, filtering, pinning, and security behavior.
Package contents
extensions/
├── developer.ts # command, protocol tools, events, and Pi integration
├── machine.ts # XState v5 parallel regions, guards, transitions, and tags
├── references/ # implementation profiles loaded through tool results
├── state.ts # developer/v5 event normalization and branch replay
├── skills.ts # loaded-skill filtering and instruction rendering
├── tool-policy.ts # machine-derived execution and mutation access policy
└── tui.ts # selectors, widget, status panel, and prompt preparation
skills/ # ten independently loadable Pi skills
SOURCES.md # source-to-capability maintenance trace
evals/ # model-dependent scenarios and workspace assertions
tests/ # deterministic state, policy, extension, and TUI tests
Development
From the monorepo root:
pnpm install
pnpm --filter @hobin/developer check
pnpm --filter @hobin/developer eval
Load the workspace package into Pi without installing it:
pi -e ./packages/developer
Launch the isolated surface fixture in a new Ghostty window for visual QA:
./packages/developer/scripts/ghostty-tui-qa.sh
Choose each independent scenario from the QA menu:
- Activation + confirm/cancel — toggle Off/On on the same Settings surface; cancel destructive Off and verify the row stays On, then confirm it and verify the route/questions clear before toggling On again.
- Settings / Status / History / Questions — open a History judgment, drag-select detail text and paste it elsewhere, then verify one-level Escape from detail → History → Settings → scenario menu with parent focus restored.
- Custom answer + Korean IME — choose Write another answer…, then check composition, validation, review/edit, and preset/custom provenance.
- Resize / scroll / mouse cleanup — repeatedly resize long Status and History detail surfaces between wide and narrow layouts; check native mouse wheel scrolling, border alignment, drag selection, Cmd+C, and paste elsewhere.
- Unicode + compact overlay footprint — inspect
◆,→,↑↓,·,…, and Korean glyph alignment, untouched background, and content-bounded overlays.
Across Developer surfaces, Ghostty owns the mouse: the wheel scrolls terminal
scrollback, ordinary drag selects text, and Cmd+C copies it. Wheel movement
never changes the selected list target; use ↑/↓ for selection. Potentially
long lists render every row as non-overlay surfaces, while complete two-choice
interruptions remain compact overlays.
Each scenario creates a fresh in-memory model. Activation events use the same
applyDeveloperEvent reducer and DeveloperSettingsBinding contract as the
production surface; no state is shared between scenario runs. The fixture does
not append entries, submit answers, register tools, mutate active tools, restore
sessions, start network work, or send model messages. Prepared answers are shown
only as a character count.
check validates package structure and deterministic behavior, including
reload migration detection and shutdown restoration of Developer-owned tool
deltas. eval launches the real Pi RPC surface without a model and covers
package resources, commands, activation state, and route-bound tool gating.
These are release-gating checks.
Model-dependent runs are probabilistic evaluations rather than binary tests:
PI_CODING_AGENT_DIR=~/.pi/agent \
DEVELOPER_EVAL_FIXTURE=agent-before-implementation-evidence-gate \
DEVELOPER_EVAL_TRIALS=5 \
pnpm --filter @hobin/developer eval:live
Use eval:live:json for the JSON transport. Each report separates the hard
admissibility envelope from routing quality: structurally valid runs must use an
admissible route, preserve mutation/question/completion invariants, satisfy
hidden artifact checks, include required semantic terms, and end in a declared
outcome. Among accepted runs, preferredFirstTargets measures better versus
merely admissible routing. Reports include acceptance and preference rates,
95% Wilson intervals, inadmissible results, rejected protocol attempts, budget
exhaustion, and environment failures. Any accepted inadmissible result makes the
evaluation command fail; ordinary admissible preference variation remains a
rate. A single model sample is not release evidence.
Live fixtures classify terminal outcomes as settled-unchanged, pending,
changed-paused, or changed-verified. An eval-only observer compares
product-file snapshots around bash/edit/write calls and rejects artifact changes
outside an implementation route. Dedicated fixtures sample a deliberately paused implementation
landing and an agent-owned before-implementation question resolved through a non-implementation
bash evidence route; their structural guarantees also have deterministic machine,
extension, trace, filesystem, and outcome tests. RPC and JSON runners share
route, tool-call, tool-error, wall-clock, and no-progress budgets and preserve a
trace for diagnosis.