infinity-harness 2.3.1 → 2.5.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,100 @@ All notable changes to this project are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.5.0] — 2026-08-25
8
+
9
+ ### Added
10
+
11
+ - **Wizard picks models and thinking per tier + consulting master.** `/infinity:init` now asks which
12
+ models and thinking levels to use for easy/moderate/difficult tiers and for the consulting master
13
+ (with `off/minimal/low/medium/high/xhigh/max` plus `inherit`). Persisted in
14
+ `harness/model-router.json` via `thinkingByDifficulty`/`thinkingMaster`/`thinkingDefault`; exposed
15
+ via `/infinity:config` → Models.
16
+
17
+ - **Customizable handoff granularity.** `goal → phase → sprint → feature → task → subtask`.
18
+ Wizard and `/infinity:config` both offer `goal` (single-session alias for `off`), `phase`
19
+ (old default), `sprint`, `feature`, **default `task`**, `subtask`, and `off`. A finer choice
20
+ implies coarser boundaries (picking `task` also hands off on feature/sprint/phase). Fixed:
21
+ `task`-scoped handoff previously never fired because only `phase` was compared.
22
+
23
+ - **Dashboard blinks the active branch.** Phase dot `pulse`, current feature/sprint/goal cards and the
24
+ active task row now pulse while being developed; `prefers-reduced-motion` disables them.
25
+
26
+ ### Fixed
27
+
28
+ - **Research autopilot stalled after pass.** `infinity_validate` now auto-advances on PASS when
29
+ the phase's mode is `autopilot` (mirrors `decideNext`), so `research → define` no longer requires
30
+ manually typing `continue`.
31
+ - **`alt+j/k/o` never fired.** Editor shortcut only runs when the editor has focus; the TUI
32
+ selector/overlay swallows input. Added `KeyId` shortcuts plus a raw `onTerminalInput`
33
+ fallback (`\x1bj/k/o`) installed on `session_start`.
34
+ - **Handoff threshold `0.7 → 0.6`.** Long BUILD phases now hand off earlier, under the context
35
+ window before compaction.
36
+
37
+ ## [2.4.0] — 2026-08-24
38
+
39
+ Two settings that were one switch each, and one switch turned out to be the wrong shape for both
40
+ questions.
41
+
42
+ ### Added
43
+
44
+ - **A mode per phase, not a mode per run.** "copilot" and "autopilot" could not say "let it define
45
+ and plan on its own but show me the review", and that is a thing people want. Every phase now
46
+ carries its own mode: `autopilot` advances when the gate passes, `copilot` stops and waits for
47
+ your signature. The two familiar words survive as two named points in that space rather than the
48
+ only two points in it, and every phase except INIT can be a checkpoint — the three that decide
49
+ *what gets built* are the ones that usually pay for themselves, but that is a default rather than
50
+ a limit.
51
+
52
+ - **Five workflows ship, and you can build your own.** `copilot`, `autopilot`, `spec and ship`
53
+ (you sign the scope going in and the release coming out), `research first`, and `every gate`.
54
+ Building one is its own short flow: pick the phases, then say for each whether it stops for you.
55
+ Name it and it is kept — in `~/.pi/agent/infinity-harness/`, with *you* rather than with the
56
+ project, because a workflow you designed is worth as much on the next one. It is then the first
57
+ thing offered there.
58
+
59
+ Built-ins are read-only, and their names cannot be taken. "copilot" has to mean the same thing in
60
+ every conversation about this tool; someone who wants a different copilot makes their own and
61
+ gives it their own name.
62
+
63
+ - **`/infinity:workflow`** — choose one, build one, switch by name (`/infinity:workflow
64
+ spec-and-ship`), or `list` what is available and what you are on. `/infinity:config` →
65
+ **Workflow** edits one phase at a time. All of it changes at any time and takes effect at the next
66
+ gate: three phases into a run is exactly when someone realises they do want to see the review.
67
+
68
+ - **Display templates.** Shipping all five plan levels to everyone was the wrong answer for the same
69
+ reason shipping two was: one person works in sprints and never opens a subtask, the next has no
70
+ sprints and lives in the subtask list. Four ship — `focus`, `everything`, `overview` (the shape,
71
+ no tasks), `worklist` (tasks only, no rail) — and anything else is chosen level by level: the
72
+ five plan levels, the `done/total` counts, the `← #3` dependency labels, the acceptance criteria,
73
+ the phase rail, the progress meter, the alert strip, and how many rows the terminal shows before
74
+ it scrolls. Name what you end up with and it is saved with you like a workflow.
75
+
76
+ - **`/infinity:display`** — pick a template, choose level by level, switch by name, or `list`.
77
+ `/infinity:config` → **Display** edits the same things one at a time.
78
+
79
+ - **The widget and the dashboard read the same setting.** Configure how you like to read a plan
80
+ once, not twice.
81
+
82
+ ### Changed
83
+
84
+ - `harness/config.json` gains `phaseModes`, `workflow` and `display`. A 2.3 config is migrated on
85
+ read: its three-phase `approvals` becomes the equivalent modes and is labelled with the workflow
86
+ it amounts to, so a project mid-run keeps exactly the approvals it was configured with and nobody
87
+ has to edit JSON to upgrade. The legacy field is kept in step on write.
88
+ - Hiding a plan level hides the row, never the work beneath it: turn off sprints on a plan organised
89
+ into sprints and the features move up one indent rather than vanishing, and task numbers do not
90
+ shift, so `← #3` still points at the same task. A task nobody can see is a task that gets stuck
91
+ forever.
92
+
93
+ ### Fixed
94
+
95
+ - **`initHarness` ignored a caller that passed the old `approvals` shape** once `phaseModes`
96
+ existed, silently producing an autopilot run. It falls back to `approvals` when no modes are
97
+ given — the same rule `loadConfig` applies to an older file.
98
+
99
+ ---
100
+
7
101
  ## [2.3.1] — 2026-08-24
8
102
 
9
103
  *(2.3.0 was staged at the registry and never completed; 2.3.1 is that release plus the last two
package/README.md CHANGED
@@ -100,11 +100,10 @@ It detects your stack and its lint/test/build commands, then asks you five quest
100
100
 
101
101
  | | |
102
102
  |---|---|
103
- | **How involved do you want to be?** | copilot you approve the definition and the plan · autopilot you choose what to approve, if anything |
104
- | **What are you building?** | One or two sentences. Asked in *both* modes, because a run with no goal has no business inventing one. |
105
- | **Research it first?** | Adds an optional RESEARCH phase before DEFINE: prior art, constraints, options with costs, a recommendation, and the questions only you can answer. |
106
- | **Which phases do you sign?** *(autopilot only)* | RESEARCH, DEFINE, PLAN — tick any, all or none. None is the walk-away setting. |
103
+ | **Which workflow?** | A built-in, one you saved, or *build one* pick the phases, then say for each whether it stops for you |
104
+ | **What are you building?** | One or two sentences. Asked whatever the workflow, because a run with no goal has no business inventing one. |
107
105
  | **When should it start a fresh session?** | Every phase (default) · every task · never |
106
+ | **How much of the plan on screen?** | A display template — `focus`, `everything`, `overview`, `worklist`, or level by level |
108
107
 
109
108
  Then it writes `harness/` — the config, an empty plan, the phase and role docs, and starters
110
109
  for the documents the review gate will demand — and hands the model its first brief. It never
@@ -134,14 +133,45 @@ the craft skills that match the work, and what to do next. Do the work, then:
134
133
 
135
134
  ## Who decides what
136
135
 
137
- The two words are about **who signs off**, not about how autonomous the agent is. Both modes
138
- run the same pipeline, the same gates and the same loop.
136
+ "copilot" and "autopilot" used to be one switch, and one switch is the wrong shape for the
137
+ question. What people actually want is per-phase: let the model define and plan on its own but
138
+ show me the review; or grill me on the definition and then leave me alone until it ships. Two
139
+ words cannot say that.
139
140
 
140
- | | copilot | autopilot |
141
- |---|---|---|
142
- | RESEARCH, DEFINE, PLAN | you approve each one | you pick which, if any |
143
- | Everything after PLAN | the gate decides | the gate decides |
144
- | When it is right | you care what gets built | you have said what you want and you are leaving |
141
+ So the setting is a **mode per phase**, and the two familiar words are two named points in that
142
+ space rather than the only two points in it.
143
+
144
+ | Mode | When a phase's gate passes |
145
+ |---|---|
146
+ | `autopilot` | it advances |
147
+ | `copilot` | it stops and waits for your signature |
148
+
149
+ Five workflows ship with the package, and none of them can be edited — `copilot` has to mean the
150
+ same thing in every conversation about this tool:
151
+
152
+ | Workflow | Stops at |
153
+ |---|---|
154
+ | **copilot** | DEFINE, PLAN |
155
+ | **autopilot** | nothing |
156
+ | **spec and ship** | DEFINE, SHIP — you sign the scope going in and the release coming out |
157
+ | **research first** | adds a RESEARCH phase, and stops on all three thinking phases |
158
+ | **every gate** | every phase. Slowest, and the one you want on something that matters |
159
+
160
+ Anything else you build yourself: pick the phases, then say for each whether it stops for you. Give
161
+ it a name and it is saved with *you*, not with the project, so it is the first thing offered on your
162
+ next one.
163
+
164
+ ```
165
+ /infinity:workflow choose one, or build one
166
+ /infinity:workflow spec-and-ship switch to a named one, no menu
167
+ /infinity:workflow list what is available, and what you are on now
168
+ ```
169
+
170
+ Any of it changes at any time and takes effect at the next gate — three phases into a run is
171
+ exactly when someone realises they do want to see the review after all. `/infinity:config` →
172
+ **Workflow** edits one phase at a time.
173
+
174
+ ### Signing a phase
145
175
 
146
176
  When a phase you signed up for passes its gate, the run **stops and asks you** rather than
147
177
  advancing. Approving continues it; answering with a sentence sends the phase back carrying your
@@ -152,9 +182,9 @@ words, so it is redone against your objection rather than redone identically:
152
182
  /infinity:approve the criteria say nothing about refunds
153
183
  ```
154
184
 
155
- A rejection is pinned to the state of the project when you made it, so the run will not ask you
156
- the same question again until the agent has actually changed something in response. If it never
157
- does, the run stops and says so instead of nagging forever.
185
+ A rejection is pinned to the state of the project when you made it, so the run will not ask you the
186
+ same question again until the agent has actually changed something in response. If it never does,
187
+ the run stops and says so instead of nagging forever.
158
188
 
159
189
  ## One run, many sessions
160
190
 
@@ -224,7 +254,8 @@ valid; the menu is the same data with prompts and bounds checking attached.
224
254
  |---|---|
225
255
  | **Models** | Which model runs each difficulty tier, the master model, consultation budget |
226
256
  | **Pipeline** | Which phases run, copilot vs autopilot, role strictness, pause |
227
- | **Your approvals** | Which of RESEARCH / DEFINE / PLAN stop and wait for your signature |
257
+ | **Workflow** | The mode for each phase which of them stop and wait for your signature |
258
+ | **Display** | Which plan levels and which chrome the widget and the dashboard draw |
228
259
  | **Sessions** | Fresh session per phase or per task, the context threshold, the carry note |
229
260
  | **Project commands** | lint / test / coverage / build — what the gate actually runs |
230
261
  | **Gates** | Enable, coverage threshold, placeholder rejection |
@@ -349,7 +380,7 @@ The agent edits it by submitting the **complete** task list through the `infinit
349
380
 
350
381
  ## Watching it work
351
382
 
352
- **In the terminal** — the widget above updates on every turn, showing all five levels of the plan:
383
+ **In the terminal** — the widget updates on every turn, showing the plan as deep as you asked for:
353
384
  goal, sprint, feature, task, subtask. It is a *window*, not a truncation — the rows above and
354
385
  below are counted, and one keypress away:
355
386
 
@@ -362,14 +393,43 @@ below are counted, and one keypress away:
362
393
  It is responsive down to ~58 columns, degrades to ASCII when the locale isn't UTF-8, and drops
363
394
  colour under `NO_COLOR`.
364
395
 
365
- **In a browser** — `/infinity:dashboard` serves a live page on loopback: phase rail, stacked progress
366
- meters that show stuck work as colour rather than absence, the whole plan as a collapsible
367
- goal → sprint → feature → task → subtask tree with counts at every level, and the last gate
368
- verdict. It refreshes itself every 5 seconds and reconnects with backoff if the run ends.
396
+ **In a browser** — `/infinity:dashboard` serves a live page on loopback: phase rail, stacked
397
+ progress meters that show stuck work as colour rather than absence, the plan as a collapsible tree
398
+ with counts at every level, and the last gate verdict. It refreshes itself every 5 seconds and
399
+ reconnects with backoff if the run ends.
369
400
 
370
401
  The dashboard is strictly read-only and binds to `127.0.0.1`. It never writes, and never bumps
371
402
  `baseRevision` — opening it can't perturb the run you're watching.
372
403
 
404
+ ### What they show is yours to choose
405
+
406
+ Two people watching the same run want different things on screen. One works in sprints and never
407
+ opens a subtask; the next has no sprints and lives in the subtask list. So it is a setting, and
408
+ **the widget and the dashboard read the same one** — configure how you like to read a plan once,
409
+ not twice.
410
+
411
+ | Template | |
412
+ |---|---|
413
+ | **focus** *(default)* | every level, with subtasks on the task being worked |
414
+ | **everything** | all five levels, every subtask on every task, a taller window |
415
+ | **overview** | goals, sprints and features with their counts. No tasks — the shape, not the work |
416
+ | **worklist** | tasks only. No grouping rows, no rail — for when you already know the plan |
417
+
418
+ ```
419
+ /infinity:display pick a template, or choose level by level
420
+ /infinity:display overview switch straight to one
421
+ /infinity:display list what is available, and what you are on now
422
+ ```
423
+
424
+ Choosing level by level also lets you turn off the phase rail, the progress meter, the alert strip,
425
+ the `done/total` counts, the `← #3` dependency labels and the acceptance criteria, and set how many
426
+ rows the terminal shows before it scrolls. Name what you end up with and it is saved with you,
427
+ offered on your next project. `/infinity:config` → **Display** edits the same things one at a time.
428
+
429
+ Hiding a level never hides what is under it: turn off sprints on a plan organised into sprints and
430
+ the features move up one indent, they do not vanish. A task nobody can see is a task that gets
431
+ stuck forever.
432
+
373
433
  ## Craft skills
374
434
 
375
435
  28 short documents on how to do the work well — how to write a test worth
@@ -447,10 +507,12 @@ infinity-harness/
447
507
  │ │ · featureList (the SSOT) · lock · exec
448
508
  │ │ · skills (match) · skillsAudit (guard)
449
509
  │ ├── ui/ theme · planTree (the five levels, once)
510
+ │ │ · display (what to draw, and the templates)
450
511
  │ │ · widget (terminal) · dashboard (web) · wizard · config
451
512
  │ ├── loop.ts the continuous-run driver and its stop conditions
452
513
  │ ├── runState.ts is a run armed, and which run is it — on disk, across sessions
453
514
  │ ├── handoff.ts when to continue in a fresh session, and what to tell it
515
+ │ ├── workflow.ts a mode per phase, the built-ins, and the ones you save
454
516
  │ ├── approval.ts · intake.ts human sign-off · what the start-up wizard's answers mean
455
517
  │ ├── escalate.ts the ladder's actuator: chooses a rung and takes it
456
518
  │ ├── goal.ts the outer loop: is the thing asked for actually done?
@@ -467,7 +529,10 @@ infinity-harness/
467
529
  │ ├── model-router.json optional routing
468
530
  │ ├── docs/ architecture · decisions · phase and role docs
469
531
  │ └── skills/ 28 craft skills the brief points at
470
- ├── tests/ 31 files, plain node:assert
532
+
533
+ │ ~/.pi/agent/infinity-harness/ the workflows and display templates you saved —
534
+ │ they belong to you, not to a project
535
+ ├── tests/ 33 files, plain node:assert
471
536
  └── scripts/
472
537
  ├── run-tests.mjs
473
538
  ├── e2e.mjs 16 scenarios, including one against a real pi process
@@ -482,7 +547,7 @@ there is one implementation, and the adapter calls it.
482
547
  ```bash
483
548
  npm install
484
549
  npm run check # tsc --noEmit, strict
485
- npm test # 31 test files
550
+ npm test # 33 test files
486
551
  npm run e2e # 16 end-to-end scenarios
487
552
  npm run e2e -- --only realpi # just the ones that drive a real pi process
488
553
  npm run e2e -- --list # what the scenarios are