@hobin/developer 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,10 +48,10 @@ Unify the duplicate schedule types and conversion logic without changing existin
48
48
  | Command | Effect |
49
49
  | --- | --- |
50
50
  | `/develop` | Open the interactive Developer control menu |
51
- | `/develop on` | Enable adaptive routing without restricting Pi's existing tools |
52
- | `/develop strict` | Enable routing and withhold Pi's built-in mutation tools until a direct route is active |
51
+ | `/develop on` | Enable adaptive routing; tools stay active unless a `before-direct` question gate is open |
52
+ | `/develop strict` | Gate shell execution behind an active route and structured artifact mutation behind a direct route |
53
53
  | `/develop status` | Inspect current branch state in a read-only panel |
54
- | `/develop questions` | Choose an unresolved question and prepare an editable revisit prompt |
54
+ | `/develop questions` | Choose an unresolved question, answer it or request investigation, and submit it to Pi |
55
55
  | `/develop off` | Disable the protocol and clear current protocol state |
56
56
 
57
57
  Explicit command arguments participate in Pi's completion UI. In interactive
@@ -71,14 +71,18 @@ pi --develop-mode strict
71
71
 
72
72
  | Mode | Routing | Built-in mutation tools | Best fit |
73
73
  | --- | --- | --- | --- |
74
- | `on` | Adaptive | Unchanged | Normal product development |
75
- | `strict` | Adaptive | Pi built-in `edit`, `write`, and `bash` require an active `direct` route | High-risk changes and workflow-discipline experiments |
74
+ | `on` | Adaptive | Unchanged except while a `before-direct` question gate is open | Normal product development |
75
+ | `strict` | Adaptive | `bash` is available during skill/direct routes; Pi built-in `edit` and `write` require an active `direct` route and no `before-direct` gate | High-risk changes and workflow-discipline experiments |
76
76
  | `off` | Disabled | Developer makes no changes to the active set | Normal Pi behavior without the protocol |
77
77
 
78
- Strict mode is a workflow-integrity gate, not a security sandbox. It recognizes
79
- Pi built-ins from their provenance and does not claim to classify or block
80
- mutation-capable tools registered by other extensions. It also preserves
81
- unrelated active tools and does not force-enable read tools the user disabled.
78
+ Strict mode and question gates are workflow-integrity controls, not a security
79
+ sandbox. A skill route receives the shell execution lane needed for repository
80
+ inspection and verifier execution, while structured `edit`/`write` mutation
81
+ remains direct-only. Shell commands are not parsed as a security language; skill
82
+ contracts prohibit artifact mutation, and adversarial evaluation checks the
83
+ workspace boundary. Developer recognizes Pi built-ins from their provenance,
84
+ preserves unrelated active tools, and does not force-enable tools the user
85
+ disabled.
82
86
 
83
87
  ## How a request runs
84
88
 
@@ -93,6 +97,10 @@ Developer adds two model-facing protocol tools:
93
97
  4. `developer_record_judgment` closes the route with a status, result, evidence,
94
98
  artifacts, and any newly opened questions. Developer then routes again from
95
99
  the stable landing before another movement.
100
+ 5. Consecutive direct routes remain valid. To prevent routing by momentum, a
101
+ direct route that follows a direct judgment must cite the previous landing
102
+ evidence and record the plausible skill routes reconsidered plus why they add
103
+ no useful judgment at that point.
96
104
 
97
105
  The conditional default topology is:
98
106
 
@@ -122,11 +130,19 @@ Developer uses different Pi surfaces for different information:
122
130
  - The footer contains only global mode, protocol state, and current route target.
123
131
  - A compact widget appears only while a route or unresolved question exists.
124
132
  - `/develop` uses a `SelectList` action menu.
125
- - `/develop status` opens a branch-grounded, read-only status panel.
126
- - `/develop questions` uses stable question IDs and only prepares editor text;
127
- selection alone never mutates protocol state.
128
- - Protocol tool rows show compact status by default and evidence details when
129
- expanded with the user's configured Pi keybinding.
133
+ - `/develop status` opens a branch-grounded, read-only status panel with recent
134
+ route/judgment history and the alternatives recorded for consecutive direct work.
135
+ - `/develop questions` uses stable internal question IDs. Selecting one opens an
136
+ answer/evidence editor and submits the resulting resolution request to Pi;
137
+ cancelling the editor leaves protocol state unchanged.
138
+ - Selection and status overlays use most of the terminal, keep a stable rendered
139
+ height while navigating or scrolling, and remain bounded on small terminals.
140
+ They support mouse-wheel/trackpad scrolling, arrow keys, Page Up/Down, and
141
+ Home/End. Terminal mouse reporting is enabled only while the overlay is open
142
+ and is released when it closes.
143
+ - Protocol tool rows show compact status by default and higher-contrast evidence
144
+ details when expanded with the user's configured Pi keybinding. They render
145
+ without Pi's default full tool-row background.
130
146
 
131
147
  RPC, JSON, and print modes keep the same protocol semantics without depending on
132
148
  terminal components.
@@ -137,8 +153,11 @@ terminal components.
137
153
  | --- | --- |
138
154
  | `idle` | No active route and no unresolved Developer question |
139
155
  | `needs-judgment` | One route is active and must be closed with a judgment |
140
- | `needs-evidence` | At least one question remains open for evidence |
141
- | `blocked` | At least one pending question carries a recorded blocker |
156
+ | `needs-evidence` | At least one agent- or environment-owned evidence question remains open |
157
+ | `needs-answer` | At least one user-owned answer or decision remains open |
158
+ | `needs-routing` | A direct stable landing must be re-observed and routed again |
159
+ | `needs-verification` | Changed artifacts still need a resolved verify judgment |
160
+ | `blocked` | A question is unavailable or explicitly gates direct work |
142
161
 
143
162
  These are routing states, not product-completion claims. In particular:
144
163
 
@@ -146,12 +165,34 @@ These are routing states, not product-completion claims. In particular:
146
165
  - A resolved `specify` judgment is not user acceptance.
147
166
  - A resolved `verify` judgment is not timeless proof after later changes.
148
167
 
149
- Pending questions receive stable internal IDs, but users do not type them.
150
- Selecting `/develop questions` focuses the question in branch state; the next
151
- route automatically associates that focus. A sole pending question or an exact
152
- question match is also associated automatically. Resolved and not-applicable
153
- judgments remove the associated question immediately; needs-evidence and blocked
154
- judgments retain the same identity.
168
+ Pending questions receive stable internal IDs, but users do not type them. Each
169
+ question records:
170
+
171
+ - `resolutionOwner`: `agent`, `user`, or `environment`;
172
+ - `gate`: `none`, `before-direct`, or `before-completion`;
173
+ - `resolutionCriteria`: the observable evidence or answer that closes it.
174
+
175
+ Selecting `/develop questions` opens an owner-specific editor: user questions
176
+ ask for the required decision, agent questions ask Pi to investigate, and
177
+ environment questions request access or an external observation. Submitting the
178
+ editor focuses the question in branch state; an explicit ID, focus, or exact
179
+ question match associates the next route. Selection alone never closes it.
180
+
181
+ Every judgment rechecks all pending questions. `question_updates` can resolve an
182
+ unfocused question when implementation, tests, inspection, user input, or an
183
+ environment observation naturally supplies its criteria. A focused question
184
+ must receive an explicit update: resolve or dismiss it with concrete basis,
185
+ retain it as open or blocked, or close the broad parent while opening narrower
186
+ children. Resolved and not-applicable updates remove the question with recorded
187
+ basis; open or blocked updates preserve its identity. A `before-direct` question blocks both direct
188
+ routes and Pi built-in mutation tools even in adaptive mode. A
189
+ `before-completion` question allows investigation and implementation but keeps
190
+ the protocol non-idle and prevents verification debt from being cleared as a
191
+ completion claim.
192
+
193
+ When a judgment replaces a broad unresolved question with more specific evidence
194
+ questions, only the actionable children remain. Equivalent question wording is
195
+ deduplicated while preserving the existing identity.
155
196
 
156
197
  ## Skills
157
198
 
@@ -162,7 +203,7 @@ or the user may invoke one directly with `/skill:<name>`.
162
203
  | --- | --- |
163
204
  | `specify` | Product meaning, scope, invariants, risks, and blocking unknowns |
164
205
  | `model` | Condition spaces, contracts, replacement, transitions, guarantees, and verification targets |
165
- | `sketch` | Data-driven skeletons, abstraction and composition boundaries, state, responsibility, and variation |
206
+ | `sketch` | Inspectable code/pseudocode skeletons, case and interface tables, boundary/flow maps, state, responsibility, and variation |
166
207
  | `signal` | Evidence-backed structural movement and model-code mismatch |
167
208
  | `naming-judgment` | Domain sense, honest effects, and change-preserving names |
168
209
  | `abstraction-review` | Whether a candidate should be kept, revised, split, rejected, or deferred |
@@ -171,6 +212,19 @@ or the user may invoke one directly with `/skill:<name>`.
171
212
  | `visualize` | The smallest visual surface that lowers judgment cost |
172
213
  | `adversarial-eval` | Finite, escalating attempts to falsify a skill or implementation claim |
173
214
 
215
+ Each leaf chooses a surface that matches its inspection problem instead of
216
+ returning undifferentiated prose: contract and scope tables for `specify`, case
217
+ or transition models for `model`, code/interface/check surfaces for `sketch`,
218
+ artifact comparisons for `signal`, rename maps for `naming-judgment`, review
219
+ cards and boundaries for `abstraction-review`, timing matrices for `schedule`,
220
+ evidence matrices for `verify`, escalation matrices for `adversarial-eval`, and
221
+ a completed visual artifact for `visualize` when a visual is warranted. Simple
222
+ judgments may remain compact when prose is genuinely clearer.
223
+
224
+ Skill judgment results preserve those surfaces as Markdown. Expanded protocol
225
+ rows render tables and code blocks through Pi's Markdown component rather than
226
+ flattening them into dim text.
227
+
174
228
  Pi's loaded resource metadata is authoritative. If package configuration filters
175
229
  or disables a skill, Developer cannot route to it even if its file exists in the
176
230
  npm package.
@@ -200,19 +254,46 @@ disabled, or replaced through resource configuration.
200
254
  ## State, branches, and compaction
201
255
 
202
256
  Mode changes are stored as Pi custom session entries. Routes and judgments are
203
- stored in tool-result details. Developer reconstructs state from the current
204
- session branch on startup and tree navigation, so a fork inherits only the
205
- events on its branch.
257
+ stored in tool-result details. Developer replays the current branch through an
258
+ XState v5 machine on startup and tree navigation, so a fork inherits only the
259
+ events on its branch. Parallel machine regions keep mode, route, question gates,
260
+ framing debt, and verification debt explicit; transition guards reject a direct
261
+ route while a `before-direct` question remains.
206
262
 
207
- The current event contract is `developer/v3`. Legacy `developer/v1` and
208
- `developer/v2` routing history can be replayed, but new framing and verification
209
- obligations are not retroactively inferred.
263
+ ```text
264
+ developerMachine (parallel)
265
+ ├── mode: off | on | strict
266
+ ├── route: idle | judgment | direct
267
+ ├── questions: clear | open
268
+ ├── directGate: clear | blocked
269
+ ├── completionGate: clear | blocked
270
+ ├── checkpoint: ready | required
271
+ ├── framing: clear | required
272
+ └── verification: current | required
273
+ ```
210
274
 
211
- Developer uses Pi's normal compaction. Each new agent turn receives current
212
- protocol state, and route results place identity and recovery metadata before
213
- potentially long skill instructions. Tool output is checked against Pi's standard size
214
- limits before state changes are committed. At most twenty pending questions may
215
- remain in current state.
275
+ Judgment routes carry the `execute` tag, direct routes carry `execute` and
276
+ `mutate`, and question/debt regions expose blocking tags. Every direct judgment
277
+ moves the checkpoint to `required`; the next accepted route returns it to
278
+ `ready`. Tool availability, runtime call guards, status, and direct-transition
279
+ eligibility are derived from the same machine snapshot.
280
+
281
+ The current event contract is `developer/v4`. Legacy `developer/v1` through
282
+ `developer/v3` routing history can be replayed. Legacy questions receive
283
+ conservative owner, gate, and resolution-criteria defaults rather than guessed
284
+ product decisions.
285
+
286
+ Developer deliberately leaves compaction ownership to Pi. It does not trigger,
287
+ cancel, or replace threshold/overflow compaction, so it cannot override the
288
+ user's Pi settings or race another extension. Configure earlier compaction with
289
+ Pi's `compaction.reserveTokens` and `compaction.keepRecentTokens` settings when
290
+ a large-context model reaches its limit too abruptly.
291
+
292
+ Each new agent turn receives current protocol state, and route results place
293
+ identity and recovery metadata before potentially long skill instructions. That
294
+ makes the active route recoverable after Pi compacts normally. Tool output is
295
+ checked against Pi's standard size limits before state changes are committed.
296
+ At most twenty pending questions may remain in current state.
216
297
 
217
298
  ## Update, configure, and remove
218
299
 
@@ -240,10 +321,11 @@ pinning, and security behavior.
240
321
  ```text
241
322
  extensions/
242
323
  ├── developer.ts # command, protocol tools, events, and Pi integration
324
+ ├── machine.ts # XState v5 parallel regions, guards, transitions, and tags
243
325
  ├── references/ # direct execution profiles loaded through tool results
244
- ├── state.ts # replayable developer/v2 branch state
326
+ ├── state.ts # developer/v4 event normalization and branch replay
245
327
  ├── skills.ts # loaded-skill filtering and instruction rendering
246
- ├── tool-policy.ts # strict-mode active-tool reconciliation
328
+ ├── tool-policy.ts # machine-derived execution and mutation access policy
247
329
  └── tui.ts # selectors, widget, status panel, and prompt preparation
248
330
  skills/ # ten independently loadable Pi skills
249
331
  SOURCES.md # source-to-capability maintenance trace
@@ -267,10 +349,50 @@ Load the workspace package into Pi without installing it:
267
349
  pi -e ./packages/developer
268
350
  ```
269
351
 
352
+ Launch the isolated modal fixture in a new Ghostty window for visual QA:
353
+
354
+ ```sh
355
+ ./packages/developer/scripts/ghostty-tui-qa.sh
356
+ ```
357
+
358
+ Choose **Inspect status** or **Revisit an open question**, then resize the window
359
+ while the modal is open. The fixture disables discovered extensions, skills,
360
+ tools, sessions, and network startup so it cannot mutate Developer state or call
361
+ a model.
362
+
270
363
  `check` validates package structure and deterministic behavior. `eval` launches
271
364
  the real Pi RPC surface without a model and covers package resources, commands,
272
- mode state, and strict tool gating. Maintainers can use `eval:json` and the live
273
- fixtures for model-dependent scenarios.
365
+ mode state, and strict tool gating. These are release-gating checks.
366
+
367
+ Model-dependent runs are probabilistic evaluations rather than binary tests:
368
+
369
+ ```sh
370
+ PI_CODING_AGENT_DIR=~/.pi/agent \
371
+ DEVELOPER_EVAL_FIXTURE=agent-before-direct-evidence-gate \
372
+ DEVELOPER_EVAL_TRIALS=5 \
373
+ pnpm --filter @hobin/developer eval:live
374
+ ```
375
+
376
+ Use `eval:live:json` for the JSON transport. Each report separates the hard
377
+ admissibility envelope from routing quality: structurally valid runs must use an
378
+ admissible route, preserve mutation/question/completion invariants, satisfy
379
+ hidden artifact checks, include required semantic terms, and end in a declared
380
+ outcome. Among accepted runs, `preferredFirstOwners` measures better versus
381
+ merely admissible routing. Reports include acceptance and preference rates,
382
+ 95% Wilson intervals, inadmissible results, rejected protocol attempts, budget
383
+ exhaustion, and environment failures. Any accepted inadmissible result makes the
384
+ evaluation command fail; ordinary admissible preference variation remains a
385
+ rate. A single model sample is not release evidence.
386
+
387
+ Live fixtures classify terminal outcomes as `settled-unchanged`, `pending`,
388
+ `changed-paused`, or `changed-verified`. An eval-only observer compares
389
+ product-file snapshots around bash/edit/write calls and rejects artifact changes
390
+ outside a direct route. Dedicated fixtures sample a deliberately paused direct
391
+ landing and an agent-owned before-direct question resolved through a non-direct
392
+ bash evidence route; their structural guarantees also have deterministic machine,
393
+ extension, trace, filesystem, and outcome tests. RPC and JSON runners share
394
+ route, tool-call, tool-error, wall-clock, and no-progress budgets and preserve a
395
+ trace for diagnosis.
274
396
 
275
397
  ## License
276
398