pi-reason-harness 1.0.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.
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/extensions/pi-reason-harness/index.ts +171 -0
- package/extensions/pi-reason-harness/src/dashboard/index.ts +47 -0
- package/extensions/pi-reason-harness/src/lifecycle/index.ts +47 -0
- package/extensions/pi-reason-harness/src/state/index.ts +49 -0
- package/extensions/pi-reason-harness/src/tools/index.ts +88 -0
- package/extensions/pi-reason-harness/src/types/index.ts +23 -0
- package/extensions/pi-reason-harness/src/ui/index.ts +76 -0
- package/harness/cli.ts +472 -0
- package/harness/server.test.ts +2095 -0
- package/harness/server.ts +5900 -0
- package/package.json +50 -0
- package/skills/reason-harness/SKILL.md +178 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🤯 pi-reason-harness
|
|
4
|
+
|
|
5
|
+
**Recursive self-improving reasoning harness for [pi](https://github.com/earendil-works/pi-coding-agent)**
|
|
6
|
+
|
|
7
|
+
_20-layer meta-system that discovers, adapts, evolves, transfers, and validates strategies autonomously._
|
|
8
|
+
|
|
9
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
10
|
+
[](./LICENSE)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
Builds task-specific reasoning strategies on top of any LLM by running iterative solve-verify-feedback loops with multi-expert ensembling, voting, and a **20-layer meta-system** that discovers, adapts, evolves, transfers, and validates strategies autonomously.
|
|
17
|
+
|
|
18
|
+
**JS-exclusive** — LLM calls go through pi's native LLM infrastructure (`@earendil-works/pi-ai`). Code sandbox uses Node's `vm` module. Zero Python dependency.
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
The core insight (from first-principles analysis of SOTA reasoning systems): **LLMs are knowledge stores that require intelligent probing strategies to extract reliable answers.** The harness layer (open-source) iteratively generates, verifies, and refines. The meta-system layer (proprietary, rebuilt here) discovers and evolves the strategies themselves.
|
|
23
|
+
|
|
24
|
+
### The 20-Layer Meta-System
|
|
25
|
+
|
|
26
|
+
| Layer | Name | What it does |
|
|
27
|
+
|-------|------|-------------|
|
|
28
|
+
| 0 | **Problem Critic** | Inspects problems, proposes *targeted deltas* to proven templates (not writing from scratch) |
|
|
29
|
+
| 1 | **Strategy Library** | Persistent store of proven strategies with ROI + quality metrics |
|
|
30
|
+
| 2 | **Meta-Rule Engine** | Extracts cross-strategy principles that compound over time |
|
|
31
|
+
| 3 | **Model Router** | Thompson sampling for intelligent model selection per category |
|
|
32
|
+
| 4 | **Budget Bandit** | Early stopping, budget reallocation, re-exploration when stuck |
|
|
33
|
+
| 5 | **Auto-Trigger** | Self-improvement runs automatically (on success rate drops, new categories, periodic) |
|
|
34
|
+
| 6 | **Recursive Harness Generation** | Generates entire solve approach configurations (the "solver of solvers") |
|
|
35
|
+
| 7 | **Ensemble Diversification** | Each expert uses a fundamentally different approach strategy |
|
|
36
|
+
| 8 | **Sub-problem Decomposition** | Break hard problems into sub-problems, solve independently, combine |
|
|
37
|
+
| 9 | **Budget Optimization** | Marginal ROI estimation, reallocate iterations to high-ROI experts |
|
|
38
|
+
| 10 | **Cross-Domain Transfer** | Transfer proven strategies across analogous categories automatically |
|
|
39
|
+
| 11 | **Confidence-Weighted Voting** | Weight votes by self-assessed quality, not just output match |
|
|
40
|
+
| 12 | **Progressive Difficulty** | Train on easiest examples first, build up to harder ones |
|
|
41
|
+
| 13 | **Auto-Transfer** | Automatically transfer strategies when new categories are encountered |
|
|
42
|
+
| 14 | **Per-Problem Prompt Synthesis** | Generate + validate specialized prompts for novel problem types |
|
|
43
|
+
| 15 | **Meta-Meta Level** | Harness-of-harnesses — generate new approach types from performance data |
|
|
44
|
+
| 16 | **Gradient-Based Budget Optimization** | Trajectory-based improvement estimation with finite-difference gradients |
|
|
45
|
+
| 17 | **Recursive Meta-Meta Nesting** | Meta-harnesses feed back into solve; recursive evolution of underperformers |
|
|
46
|
+
| 18 | **Multi-Model Decomposition** | Route sub-questions to different models in parallel based on strengths |
|
|
47
|
+
| 19 | **Per-Iteration Prompt Adaptation** | Evolve the solver prompt mid-solve based on failure patterns |
|
|
48
|
+
| 20 | **ARC-AGI Benchmark Integration** | Validate against real ARC-AGI-2 challenges with scoring |
|
|
49
|
+
|
|
50
|
+
### Layer 6: Recursive Harness Generation — the "solver of solvers"
|
|
51
|
+
|
|
52
|
+
The biggest gap with Poetiq: their open-source code shows ONE harness configuration with fixed prompts. Their blog results prove they generate MULTIPLE different configurations per problem type.
|
|
53
|
+
|
|
54
|
+
A **HarnessSpec** defines a complete solve approach:
|
|
55
|
+
- **Approach type**: code-sandbox, decomposition, chain-of-questions, analogy, counter-factual, exhaustive-search, code-direct
|
|
56
|
+
- **Solver/feedback prompts**: Full templates with `$$problem$$` placeholders
|
|
57
|
+
- **Config overrides**: Temperature, iterations, reasoning level
|
|
58
|
+
- **Decomposition config**: Max sub-problems, depth, combine strategy
|
|
59
|
+
- **Validation data**: Score on held-out data, production stats
|
|
60
|
+
|
|
61
|
+
The system generates multiple specs per problem, validates them, and evolves them over time.
|
|
62
|
+
|
|
63
|
+
### Layer 7: Ensemble Diversification
|
|
64
|
+
|
|
65
|
+
Instead of N experts with the same prompt (just different seeds/models), each expert uses a **fundamentally different approach**:
|
|
66
|
+
|
|
67
|
+
| Expert | Approach | When to use |
|
|
68
|
+
|--------|----------|-------------|
|
|
69
|
+
| 1 | code-sandbox | Grid/array problems — generate code, execute, verify |
|
|
70
|
+
| 2 | decomposition | Complex problems — break into sub-problems |
|
|
71
|
+
| 3 | analogy | Hard problems — solve simpler version first |
|
|
72
|
+
| 4 | chain-of-questions | Knowledge tasks — hierarchical probing |
|
|
73
|
+
| 5 | counter-factual | Stubborn problems — generate wrong solutions, invert |
|
|
74
|
+
| 6 | exhaustive-search | Small search spaces — enumerate, filter |
|
|
75
|
+
|
|
76
|
+
Each approach has its own specialized prompt template.
|
|
77
|
+
|
|
78
|
+
### Layer 8: Sub-problem Decomposition
|
|
79
|
+
|
|
80
|
+
For hard problems that resist direct solving, the decomposer breaks them into independent sub-problems:
|
|
81
|
+
1. LLM analyzes the problem and proposes 2-4 sub-problems
|
|
82
|
+
2. Each sub-problem is solved independently
|
|
83
|
+
3. Sub-solutions are combined (sequentially, in parallel, or hierarchically)
|
|
84
|
+
|
|
85
|
+
Example: "Rotate 90° clockwise" → Sub-problem 1: "Transpose the grid" → Sub-problem 2: "Reverse each row"
|
|
86
|
+
|
|
87
|
+
### Layer 9: Budget Optimization via Marginal ROI
|
|
88
|
+
|
|
89
|
+
Not just "stop when stuck" but **"spend where ROI is highest"**:
|
|
90
|
+
- Estimate marginal ROI per expert based on recent improvement rate
|
|
91
|
+
- Reallocate remaining iterations to experts with highest expected improvement
|
|
92
|
+
- Phase-based execution: run all experts for half-iterations, then reallocate
|
|
93
|
+
|
|
94
|
+
### Layer 10-13: Cross-Domain Transfer + Auto-Transfer
|
|
95
|
+
|
|
96
|
+
When a strategy works in one domain, the system **automatically transfers** it to analogous domains:
|
|
97
|
+
- Category similarity map: grid-transformation ↔ pattern-completion ↔ spatial-reasoning
|
|
98
|
+
- Transfer adapts domain-specific parts while keeping universal insights
|
|
99
|
+
- Auto-triggered when a new category is encountered with no existing strategies
|
|
100
|
+
- Creates both a strategy entry and a harness spec for the new category
|
|
101
|
+
|
|
102
|
+
### Layer 11: Confidence-Weighted Voting
|
|
103
|
+
|
|
104
|
+
Voting is weighted by **self-assessed quality**:
|
|
105
|
+
- Solutions that pass in fewer iterations count more (efficiency bonus)
|
|
106
|
+
- Solutions with high soft scores count more (partial accuracy bonus)
|
|
107
|
+
- Failed solutions grouped by output similarity, ranked by total confidence
|
|
108
|
+
|
|
109
|
+
### Layer 12: Progressive Difficulty
|
|
110
|
+
|
|
111
|
+
Training examples are ordered from **easiest to hardest**:
|
|
112
|
+
- Difficulty proxy: grid size + unique value count + input/output asymmetry
|
|
113
|
+
- The solver sees simpler patterns first, building up to complex ones
|
|
114
|
+
- Mirrors Poetiq's per-iteration shuffle but with intelligence
|
|
115
|
+
|
|
116
|
+
### Layer 14: Per-Problem Prompt Synthesis
|
|
117
|
+
|
|
118
|
+
For truly novel problems where no proven strategy exists, the system **synthesizes specialized prompts**:
|
|
119
|
+
- Computes a problem fingerprint based on structural features (grid size, unique values, operation type)
|
|
120
|
+
- If a validated synthesized prompt matches the fingerprint, uses it instead of the generic template
|
|
121
|
+
- If no match, generates a new specialized prompt via LLM and validates it on training data
|
|
122
|
+
- Prompts with validation score > 0.5 are persisted for future use
|
|
123
|
+
- Fingerprint-based matching allows cross-problem generalization
|
|
124
|
+
|
|
125
|
+
### Layer 15: Meta-Meta Level — Harness-of-Harnesses
|
|
126
|
+
|
|
127
|
+
The biggest architectural gap with Poetiq: their system doesn't just generate strategies, it generates **new types of harness approaches**. Our meta-meta level:
|
|
128
|
+
- Analyzes performance data across all harness specs and meta-harnesses
|
|
129
|
+
- Uses LLM to propose NEW approach types that combine strengths of successful ones
|
|
130
|
+
- Each meta-harness has a name, description, solver prompt, config overrides, and rationale
|
|
131
|
+
- Meta-harnesses can evolve (generation counter, parent lineage) like strategies
|
|
132
|
+
- Example: "Decomposed-Sandbox-Synthesis" — combines decomposition's cognitive offloading with code-sandbox's deterministic verification
|
|
133
|
+
|
|
134
|
+
### Layer 16: Gradient-Based Budget Optimization
|
|
135
|
+
|
|
136
|
+
Replaces simple proportional reallocation with **finite-difference gradient estimation**:
|
|
137
|
+
- Estimates dScore/dIteration (improvement rate) using a 5-point window
|
|
138
|
+
- Estimates d²Score/dIteration² (acceleration/deceleration)
|
|
139
|
+
- Predicts expected next score: current + gradient + 0.5 × acceleration
|
|
140
|
+
- Allocates iterations proportional to (expected improvement × confidence)
|
|
141
|
+
- Detects when an expert should switch approaches: stuck (gradient ≈ 0) + decelerating (acceleration < 0)
|
|
142
|
+
|
|
143
|
+
### Layer 17: Recursive Meta-Meta Nesting
|
|
144
|
+
|
|
145
|
+
Meta-harnesses don't just get generated — they **feed back into solve**:
|
|
146
|
+
- `selectMetaHarnessExpertConfig()` assigns the best meta-harness to one expert in the ensemble
|
|
147
|
+
- Meta-harness performance is tracked (useCount, avgScore, successCount)
|
|
148
|
+
- Underperforming meta-harnesses (useCount ≥ 2, avgScore < 0.5, generation < 3) are **recursively evolved** via `recursiveMetaEvolve()`
|
|
149
|
+
- This creates a true recursive loop: solve → generate meta-harness → use in solve → evolve if underperforming → repeat
|
|
150
|
+
|
|
151
|
+
### Layer 18: Multi-Model Decomposition
|
|
152
|
+
|
|
153
|
+
When multiple models are available, the system **routes sub-questions to the best-suited model**:
|
|
154
|
+
- `decomposeAndRoute()`: LLM analyzes the problem and assigns sub-problems to models based on heuristic strengths
|
|
155
|
+
- Model strength heuristics: Anthropic (complex reasoning, code), OpenAI (math, creative), Google (multimodal), Groq (fast), Wafer (reasoning), DeepSeek (code, math)
|
|
156
|
+
- Dependency tracking: sub-problems can depend on previous results
|
|
157
|
+
- `solveRoutedDecomposition()`: solves each sub-problem with its assigned model, combines results
|
|
158
|
+
- Triggered automatically in solve when `models.length > 1` and `useMeta=true`
|
|
159
|
+
|
|
160
|
+
### Layer 19: Per-Iteration Prompt Adaptation
|
|
161
|
+
|
|
162
|
+
The solver prompt **adapts mid-solve** based on failure patterns:
|
|
163
|
+
- After 3 consecutive failed iterations (score < 0.5), `adaptPromptMidSolve()` is called
|
|
164
|
+
- LLM analyzes the failure trajectory and suggests a prompt modification
|
|
165
|
+
- Three adaptation types: `pre-insert` (add before problem), `anti-pattern` (warn after problem), `section-replace` (replace a named section)
|
|
166
|
+
- `applyIterationAdaptation()` modifies the prompt for subsequent iterations
|
|
167
|
+
- The adaptation persists within the expert's solve loop
|
|
168
|
+
|
|
169
|
+
### Layer 20: ARC-AGI Benchmark Integration
|
|
170
|
+
|
|
171
|
+
The system can **validate against real ARC-AGI-2 challenges**:
|
|
172
|
+
- `loadArcChallenges()`: loads challenges from ARC-AGI JSON files
|
|
173
|
+
- `runArcBenchmark()`: runs the harness on a batch of challenges with budget limits
|
|
174
|
+
- Re-verifies test outputs against ground truth (when available)
|
|
175
|
+
- Computes: solved, partial solved, avg best score, total cost, total time
|
|
176
|
+
- CLI: `pi-reason-harness arc-benchmark --data-path ... --max-challenges 5`
|
|
177
|
+
- **Benchmark results with wafer/GLM-5.1**: 5/7 unique challenges solved (71%), 1 near-miss (0.97), cost ~$0.04/challenge
|
|
178
|
+
|
|
179
|
+
### Layers 0-5: Core Meta-System
|
|
180
|
+
|
|
181
|
+
These were implemented in the previous iteration and remain the foundation:
|
|
182
|
+
|
|
183
|
+
- **Layer 0: Critique, Don't Create** — The critic receives proven templates and proposes targeted deltas (insertions, anti-patterns, examples). This is code review, not writing from zero.
|
|
184
|
+
- **Layer 2: Meta-Rules Compound** — When a child strategy outperforms its parent, generalizable principles are extracted and applied to other categories.
|
|
185
|
+
- **Layer 3: Thompson Sampling** — Beta(α,β) sampling with Laplace smoothing picks the best model per category.
|
|
186
|
+
- **Layer 4: Budget Bandit** — Early stopping, re-exploration when all experts fail.
|
|
187
|
+
- **Layer 5: Auto-Trigger** — Runs automatically on success rate drops, new categories, and every 5th problem.
|
|
188
|
+
|
|
189
|
+
### The Harness Layer
|
|
190
|
+
|
|
191
|
+
Below the meta-system, the harness implements the iterative solve loop with Poetiq-parity features:
|
|
192
|
+
|
|
193
|
+
1. **Iterative solve-verify-feedback loops** — Generate code, sandbox-execute, build detailed feedback
|
|
194
|
+
2. **Multi-expert ensembling** — Parallel experts with diverse approaches
|
|
195
|
+
3. **Confidence-weighted voting** — Group by output, rank by confidence
|
|
196
|
+
4. **Poetiq-parity feedback** — Element-by-element diff grids, shape mismatch detection
|
|
197
|
+
5. **Poetiq-parity formatting** — `<Diagram>` text with Fisher-Yates shuffle
|
|
198
|
+
6. **Self-audit verification** — LLM checks its own answers
|
|
199
|
+
7. **Budget tracking** — Per-problem cost/time limits
|
|
200
|
+
|
|
201
|
+
### Task Types
|
|
202
|
+
|
|
203
|
+
| Type | Strategy | Verification |
|
|
204
|
+
|------|----------|--------------|
|
|
205
|
+
| `code-reasoning` | Generate JavaScript code → sandbox execute → verify against examples → feedback loop | Sandbox (default) or external |
|
|
206
|
+
| `knowledge-extraction` | Chain-of-questions probing → self-audit → confidence bucketing | Self-audit (recommended) |
|
|
207
|
+
| `hybrid` | Decide per-problem: code or direct answer → verify → feedback | Any method |
|
|
208
|
+
|
|
209
|
+
### Approach Types (for ensemble diversification)
|
|
210
|
+
|
|
211
|
+
| Approach | Description | Best for |
|
|
212
|
+
|----------|-------------|----------|
|
|
213
|
+
| `code-sandbox` | Generate JS code, execute in sandbox, verify output | Grid/array transformations |
|
|
214
|
+
| `code-direct` | Generate code, extract answer without execution | Computation-heavy |
|
|
215
|
+
| `decomposition` | Break into sub-problems, solve each, combine | Multi-step problems |
|
|
216
|
+
| `chain-of-questions` | Hierarchical probing from broad to specific | Knowledge questions |
|
|
217
|
+
| `analogy` | Solve simpler version first, then scale up | Hard spatial problems |
|
|
218
|
+
| `counter-factual` | Generate wrong solutions, analyze failures, invert | Stubborn problems |
|
|
219
|
+
| `exhaustive-search` | Enumerate possibilities, filter by constraints | Small search spaces |
|
|
220
|
+
|
|
221
|
+
### Persistent Data
|
|
222
|
+
|
|
223
|
+
The meta-system persists across server restarts at `~/.pi-reason-harness/`:
|
|
224
|
+
|
|
225
|
+
| File | Contents |
|
|
226
|
+
|------|----------|
|
|
227
|
+
| `strategies.json` | Strategy library with ROI, quality metrics, lineage |
|
|
228
|
+
| `meta-rules.json` | Cross-strategy principles with validation stats |
|
|
229
|
+
| `model-routes.json` | Per model×category routing stats |
|
|
230
|
+
| `harness-specs.json` | Complete harness specifications per category×approach |
|
|
231
|
+
| `synthesized-prompts.json` | Per-problem-type specialized prompts with validation |
|
|
232
|
+
| `meta-harnesses.json` | Generated approach types with evolution lineage |
|
|
233
|
+
|
|
234
|
+
## Quick Start
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Initialize a reasoning session
|
|
238
|
+
pi-reason-harness init --name "ARC solver" --type code-reasoning \
|
|
239
|
+
--models '["anthropic/claude-sonnet-4-5","openai/gpt-4o"]' --num-experts 3
|
|
240
|
+
|
|
241
|
+
# Solve with the full 13-layer meta-system pipeline
|
|
242
|
+
pi-reason-harness solve --meta --problem "Transform the grid..." \
|
|
243
|
+
--train-inputs '[[1,2],[3,4]]' \
|
|
244
|
+
--train-outputs '[[4,3],[2,1]]' \
|
|
245
|
+
--test-inputs '[[5,6]]'
|
|
246
|
+
|
|
247
|
+
# Analyze a problem without solving
|
|
248
|
+
pi-reason-harness meta-analyze --problem "Rotate a 2x2 grid 90 degrees clockwise"
|
|
249
|
+
|
|
250
|
+
# Decompose a hard problem into sub-problems
|
|
251
|
+
pi-reason-harness decompose --problem "Rotate a 3x3 grid 90 degrees clockwise. Input: [[1,2,3],[4,5,6],[7,8,9]]"
|
|
252
|
+
|
|
253
|
+
# Check harness specs
|
|
254
|
+
pi-reason-harness harness-specs
|
|
255
|
+
|
|
256
|
+
# Evolve the worst-performing spec
|
|
257
|
+
pi-reason-harness evolve-harness
|
|
258
|
+
|
|
259
|
+
# Check the strategy library
|
|
260
|
+
pi-reason-harness strategies
|
|
261
|
+
|
|
262
|
+
# Transfer a strategy from grid-transformation to pattern-completion
|
|
263
|
+
pi-reason-harness transfer --source-category grid-transformation --target-category pattern-completion
|
|
264
|
+
|
|
265
|
+
# Check meta-rules
|
|
266
|
+
pi-reason-harness meta-rules
|
|
267
|
+
|
|
268
|
+
# Check model routing stats
|
|
269
|
+
pi-reason-harness model-routes
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Architecture
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
┌───────────────────────────────────────────────────────────┐
|
|
276
|
+
│ META-SYSTEM V3 (16 layers — the proprietary layer) │
|
|
277
|
+
│ │
|
|
278
|
+
│ Layer 0: Problem Critic (critique-don't-create) │
|
|
279
|
+
│ Layer 1: Strategy Library (ROI + quality metrics) │
|
|
280
|
+
│ Layer 2: Meta-Rule Engine (cross-strategy principles) │
|
|
281
|
+
│ Layer 3: Model Router (Thompson sampling) │
|
|
282
|
+
│ Layer 4: Budget Bandit (early stopping + re-explore) │
|
|
283
|
+
│ Layer 5: Auto-Trigger (self-improving loop) │
|
|
284
|
+
│ Layer 6: Recursive Harness Generation (solver-of-solvers)│
|
|
285
|
+
│ Layer 7: Ensemble Diversification (different approaches) │
|
|
286
|
+
│ Layer 8: Sub-problem Decomposition (break & combine) │
|
|
287
|
+
│ Layer 9: Budget Optimization (marginal ROI realloc) │
|
|
288
|
+
│ Layer 10: Cross-Domain Transfer (analogous categories) │
|
|
289
|
+
│ Layer 11: Confidence-Weighted Voting (quality-ranked) │
|
|
290
|
+
│ Layer 12: Progressive Difficulty (easiest-first) │
|
|
291
|
+
│ Layer 13: Auto-Transfer (new category handling) │
|
|
292
|
+
│ Layer 14: Per-Problem Prompt Synthesis (novel types) │
|
|
293
|
+
│ Layer 15: Meta-Meta Level (harness-of-harnesses) │
|
|
294
|
+
│ Layer 16: Gradient-Based Budget Optimization │
|
|
295
|
+
│ Layer 17: Recursive Meta-Meta Nesting (harness↔solve) │
|
|
296
|
+
│ Layer 18: Multi-Model Decomposition (model routing) │
|
|
297
|
+
│ Layer 19: Per-Iteration Prompt Adaptation (mid-solve) │
|
|
298
|
+
│ Layer 20: ARC-AGI Benchmark Integration (validation) │
|
|
299
|
+
└───────────────────────┬───────────────────────────────────┘
|
|
300
|
+
│ generates (with deltas + rules + specs)
|
|
301
|
+
▼
|
|
302
|
+
┌─────────────────────────────────────────────────────────┐
|
|
303
|
+
│ HARNESS (iterative solve-verify-feedback) │
|
|
304
|
+
│ │
|
|
305
|
+
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │
|
|
306
|
+
│ │ Expert 1 │ │ Expert 2 │ │ Expert N │ │
|
|
307
|
+
│ │ code-sandbox│ │ decomposition│ │ analogy │ │
|
|
308
|
+
│ │ (pi-ai │ │ (pi-ai │ │ (pi-ai │ │
|
|
309
|
+
│ │ LLM call │ │ LLM call │ │ LLM call │ │
|
|
310
|
+
│ │ + sandbox │ │ + sub- │ │ + analogy │ │
|
|
311
|
+
│ │ + verify │ │ solve │ │ + verify │ │
|
|
312
|
+
│ │ + feedback │ │ + combine │ │ + feedback │ │
|
|
313
|
+
│ └────┬────────┘ └─┬────────────┘ └──┬──────────┘ │
|
|
314
|
+
│ └─────────────┼──────────────────┘ │
|
|
315
|
+
│ ▼ │
|
|
316
|
+
│ CONFIDENCE-WEIGHTED VOTING │
|
|
317
|
+
│ (group by output, rank by confidence) │
|
|
318
|
+
│ │ │
|
|
319
|
+
│ ▼ │
|
|
320
|
+
│ LEARN + ADAPT + EVOLVE + TRANSFER │
|
|
321
|
+
│ (update strategies, extract rules, evolve specs, │
|
|
322
|
+
│ transfer to new categories, auto-improve) │
|
|
323
|
+
└─────────────────────────────────────────────────────────┘
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## CLI Reference
|
|
327
|
+
|
|
328
|
+
| Command | Description |
|
|
329
|
+
|---------|-------------|
|
|
330
|
+
| `init` | Initialize session with task config, models, verification |
|
|
331
|
+
| `solve` | Run iterative solve-verify-feedback loop |
|
|
332
|
+
| `status` | Show session state, budget, learned adaptations |
|
|
333
|
+
| `results` | Show iteration results |
|
|
334
|
+
| `learn` | Inspect strategy adaptations |
|
|
335
|
+
| `reset-learn` | Clear learned strategies |
|
|
336
|
+
| `clear` | Clear session |
|
|
337
|
+
| `meta-analyze` | Analyze a problem with the critic (no solving) |
|
|
338
|
+
| `meta-improve` | Manually trigger strategy evolution + rule extraction |
|
|
339
|
+
| `strategies` | List strategy library with ROI + quality metrics |
|
|
340
|
+
| `meta-rules` | List meta-rules with validation stats |
|
|
341
|
+
| `model-routes` | List model routing stats per model×category |
|
|
342
|
+
| `harness-specs` | List harness specifications with validation + production stats |
|
|
343
|
+
| `evolve-harness` | Evolve the worst-performing harness spec |
|
|
344
|
+
| `transfer` | Transfer strategy from one category to another |
|
|
345
|
+
| `decompose` | Decompose a problem into sub-problems |
|
|
346
|
+
| `synth-prompts` | List synthesized prompts with validation stats |
|
|
347
|
+
| `meta-harnesses` | List meta-harnesses (generated approach types) |
|
|
348
|
+
| `generate-meta-harness` | Generate a new approach type from performance data |
|
|
349
|
+
| `arc-benchmark` | Run ARC-AGI benchmark validation against real challenges |
|
|
350
|
+
| `route-decompose` | Decompose a problem across multiple models |
|
|
351
|
+
|
|
352
|
+
### init flags
|
|
353
|
+
|
|
354
|
+
`--name`, `--type`, `--models`, `--num-experts`, `--verification`, `--verify-command`, `--max-cost`, `--max-time`
|
|
355
|
+
|
|
356
|
+
### solve flags
|
|
357
|
+
|
|
358
|
+
`--problem`, `--train-inputs`, `--train-outputs`, `--test-inputs`, `--meta` / `-m`
|
|
359
|
+
|
|
360
|
+
### transfer flags
|
|
361
|
+
|
|
362
|
+
`--source-category`, `--target-category`
|
|
363
|
+
|
|
364
|
+
### decompose flags
|
|
365
|
+
|
|
366
|
+
`--problem`
|
|
367
|
+
|
|
368
|
+
## LLM Integration
|
|
369
|
+
|
|
370
|
+
The harness uses `@earendil-works/pi-ai` for all LLM calls. Models are specified in `provider/model` format (e.g., `anthropic/claude-sonnet-4-5`, `openai/gpt-4o`). API keys are resolved from the same environment variables pi uses:
|
|
371
|
+
|
|
372
|
+
- `ANTHROPIC_API_KEY` — Anthropic models
|
|
373
|
+
- `OPENAI_API_KEY` — OpenAI models
|
|
374
|
+
- `GEMINI_API_KEY` — Google models
|
|
375
|
+
- `GROQ_API_KEY` — Groq models
|
|
376
|
+
- `WAFER_API_KEY` — Wafer Pass models (GLM-5.1, Qwen3.5-397B-A17B)
|
|
377
|
+
- etc.
|
|
378
|
+
|
|
379
|
+
### Custom Providers
|
|
380
|
+
|
|
381
|
+
The harness also supports custom providers (like Wafer Pass) that aren't in pi-ai's built-in model registry. Custom providers use direct OpenAI-compatible API calls. Currently supported:
|
|
382
|
+
|
|
383
|
+
| Provider | Base URL | Models | Notes |
|
|
384
|
+
|----------|----------|--------|-------|
|
|
385
|
+
| `wafer` | `https://pass.wafer.ai/v1` | `GLM-5.1`, `Qwen3.5-397B-A17B` | Reasoning models with `reasoning_content` field |
|
|
386
|
+
|
|
387
|
+
To add a new custom provider, add it to the `CUSTOM_PROVIDERS` map in `server.ts`.
|
|
388
|
+
|
|
389
|
+
No additional setup required — if pi can call the model, so can the harness.
|
|
390
|
+
|
|
391
|
+
## Tests
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
npm test
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
104 tests covering: vm sandbox, formatProblem, arrayDiff, buildDetailedFeedback, PromptDelta application, budget bandit, Thompson sampling, meta-rule engine, prompt quality metrics, harness specs, ensemble diversification, budget optimization, cross-domain transfer, confidence-weighted voting, progressive difficulty, decomposition, problem fingerprinting, synthesized prompts, meta-harnesses, gradient estimation, approach switching, recursive meta-meta nesting, multi-model decomposition routing, per-iteration prompt adaptation, ARC-AGI benchmark.
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-reason-harness — Pi Extension
|
|
3
|
+
*
|
|
4
|
+
* Thin lifecycle shell for the reason harness server.
|
|
5
|
+
* All reasoning interactions happen through the `pi-reason-harness` CLI,
|
|
6
|
+
* which dispatches to a long-lived harness server holding session state.
|
|
7
|
+
*
|
|
8
|
+
* This extension:
|
|
9
|
+
* - Installs the CLI shell alias on session start
|
|
10
|
+
* - Starts/stops the harness server
|
|
11
|
+
* - Manages the status widget
|
|
12
|
+
* - Provides the /reason command
|
|
13
|
+
* - Registers tools for LLM-driven reasoning
|
|
14
|
+
* - Writes session ID to disk for the harness server
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
import { spawn as spawnChild, type ChildProcess } from 'node:child_process';
|
|
20
|
+
import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
21
|
+
import { createRuntimeStore } from './src/state/index.js';
|
|
22
|
+
import { createWidgetUpdater, clearSessionUi } from './src/ui/index.js';
|
|
23
|
+
import { installShellAlias, writeSessionId, getDirs } from './src/lifecycle/index.js';
|
|
24
|
+
import { registerTools } from './src/tools/index.js';
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// CLI path resolution
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
31
|
+
|
|
32
|
+
function getProjectRoot(): string {
|
|
33
|
+
return join(__dirname, '..', '..');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getCliPath(): string {
|
|
37
|
+
return join(getProjectRoot(), 'harness', 'cli.ts');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Harness server lifecycle
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
interface HarnessServerController {
|
|
45
|
+
start(): void;
|
|
46
|
+
stop(): void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createHarnessServer(): HarnessServerController {
|
|
50
|
+
let harnessProcess: ChildProcess | null = null;
|
|
51
|
+
|
|
52
|
+
function start(): void {
|
|
53
|
+
if (harnessProcess) return;
|
|
54
|
+
if (process.env.PI_SWARM_SPAWNED === '1') return;
|
|
55
|
+
|
|
56
|
+
const cliPath = getCliPath();
|
|
57
|
+
const projectRoot = getProjectRoot();
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
harnessProcess = spawnChild('npx', ['tsx', cliPath, '--start'], {
|
|
61
|
+
cwd: projectRoot,
|
|
62
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
63
|
+
detached: true,
|
|
64
|
+
});
|
|
65
|
+
harnessProcess.unref();
|
|
66
|
+
} catch {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function stop(): void {
|
|
70
|
+
if (!harnessProcess) return;
|
|
71
|
+
try {
|
|
72
|
+
harnessProcess.kill('SIGTERM');
|
|
73
|
+
} catch {}
|
|
74
|
+
harnessProcess = null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return { start, stop };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Extension
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
export default function reasonHarnessExtension(pi: ExtensionAPI) {
|
|
85
|
+
const runtimeStore = createRuntimeStore();
|
|
86
|
+
const getSessionKey = (ctx: ExtensionContext) => ctx.sessionManager.getSessionId();
|
|
87
|
+
const getRuntime = (ctx: ExtensionContext) => runtimeStore.ensure(getSessionKey(ctx));
|
|
88
|
+
|
|
89
|
+
const updateWidget = createWidgetUpdater(getRuntime);
|
|
90
|
+
const harnessServer = createHarnessServer();
|
|
91
|
+
|
|
92
|
+
registerTools(pi);
|
|
93
|
+
|
|
94
|
+
pi.registerCommand('reason', {
|
|
95
|
+
description: 'Manage reasoning harness (init, solve, status, learn, clear)',
|
|
96
|
+
handler: async (args, extCtx) => {
|
|
97
|
+
const runtime = getRuntime(extCtx);
|
|
98
|
+
const trimmedArgs = (args ?? '').trim();
|
|
99
|
+
const command = trimmedArgs.toLowerCase();
|
|
100
|
+
|
|
101
|
+
if (!trimmedArgs) {
|
|
102
|
+
extCtx.ui.notify('Usage: /reason [off|clear|status|learn|<config>]', 'info');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (command === 'off') {
|
|
107
|
+
runtime.sessionName = null;
|
|
108
|
+
runtime.status = 'idle';
|
|
109
|
+
updateWidget(extCtx);
|
|
110
|
+
extCtx.ui.notify('Reason harness OFF', 'info');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (command === 'clear') {
|
|
115
|
+
runtime.sessionName = null;
|
|
116
|
+
runtime.taskType = null;
|
|
117
|
+
runtime.status = 'idle';
|
|
118
|
+
runtime.iterationCount = 0;
|
|
119
|
+
runtime.bestScore = 0;
|
|
120
|
+
runtime.solved = false;
|
|
121
|
+
runtime.totalTokens = 0;
|
|
122
|
+
runtime.totalCost = 0;
|
|
123
|
+
runtime.adaptations = 0;
|
|
124
|
+
runtime.budget = { costUsed: 0, timeUsed: 0, problemsSolved: 0, problemsAttempted: 0 };
|
|
125
|
+
updateWidget(extCtx);
|
|
126
|
+
extCtx.ui.notify('Reason harness cleared', 'info');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (command === 'status') {
|
|
131
|
+
pi.sendUserMessage('Run `pi-reason-harness status` to see session details.');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (command === 'learn') {
|
|
136
|
+
pi.sendUserMessage('Run `pi-reason-harness learn` to see strategy adaptations.');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Treat as init configuration
|
|
141
|
+
pi.sendUserMessage(
|
|
142
|
+
`Initializing reason harness: ${trimmedArgs}. Use pi-reason-harness CLI to configure and solve.`
|
|
143
|
+
);
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
pi.registerShortcut('ctrl+shift+r', {
|
|
148
|
+
description: 'Toggle reason harness widget',
|
|
149
|
+
handler: async (ctx) => {
|
|
150
|
+
const runtime = getRuntime(ctx);
|
|
151
|
+
if (!runtime.sessionName) {
|
|
152
|
+
ctx.ui.notify('No reason harness session active', 'info');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
updateWidget(ctx);
|
|
156
|
+
ctx.ui.notify('Reason harness widget updated', 'info');
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
pi.on('session_start', async (_event, ctx) => {
|
|
161
|
+
installShellAlias(getCliPath(), getProjectRoot());
|
|
162
|
+
writeSessionId(ctx);
|
|
163
|
+
harnessServer.start();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
pi.on('session_shutdown', async (_e, ctx) => {
|
|
167
|
+
runtimeStore.clear(getSessionKey(ctx));
|
|
168
|
+
clearSessionUi(ctx);
|
|
169
|
+
harnessServer.stop();
|
|
170
|
+
});
|
|
171
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-reason-harness — Dashboard rendering
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ReasonHarnessRuntime } from '../types/index.js';
|
|
6
|
+
|
|
7
|
+
export function renderDashboardLines(
|
|
8
|
+
runtime: ReasonHarnessRuntime,
|
|
9
|
+
width: number,
|
|
10
|
+
theme: { fg: (color: string, text: string) => string },
|
|
11
|
+
maxLines: number = 6
|
|
12
|
+
): string[] {
|
|
13
|
+
const lines: string[] = [];
|
|
14
|
+
|
|
15
|
+
lines.push(
|
|
16
|
+
` Type: ${runtime.taskType} │ Status: ${runtime.status} │ Experts: ${runtime.expertCount}`
|
|
17
|
+
);
|
|
18
|
+
lines.push(
|
|
19
|
+
` ★ Best score: ${runtime.bestScore.toFixed(2)} │ ${runtime.solved ? '✅ Solved' : '❌ Not solved'} │ ${runtime.iterationCount} iterations`
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
if (runtime.totalTokens > 0 || runtime.totalCost > 0) {
|
|
23
|
+
lines.push(
|
|
24
|
+
` Tokens: ${runtime.totalTokens} │ Cost: $${runtime.totalCost.toFixed(4)}`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (runtime.budget.problemsAttempted > 0) {
|
|
29
|
+
lines.push(
|
|
30
|
+
` Budget: ${runtime.budget.problemsSolved}/${runtime.budget.problemsAttempted} solved │ $${runtime.budget.costUsed.toFixed(4)} spent │ ${runtime.budget.timeUsed.toFixed(1)}s`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (runtime.adaptations > 0) {
|
|
35
|
+
lines.push(
|
|
36
|
+
` 🧠 ${runtime.adaptations} strategy adaptation(s) active`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (runtime.models.length > 0) {
|
|
41
|
+
lines.push(
|
|
42
|
+
` Models: ${runtime.models.join(', ')}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return lines.slice(0, maxLines);
|
|
47
|
+
}
|