pi-continual-harness 0.21.0 → 0.22.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 +26 -1
- package/README.md +8 -4
- package/dist/auto-refine.js +1 -1
- package/dist/classify.d.ts +24 -2
- package/dist/classify.js +33 -4
- package/dist/config.d.ts +9 -3
- package/dist/config.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -2
- package/dist/inject.d.ts +8 -0
- package/dist/inject.js +8 -0
- package/dist/refine.js +1 -1
- package/dist/remind.js +2 -2
- package/dist/setup.js +1 -1
- package/dist/status.js +7 -3
- package/harness.schema.json +6 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -8,7 +8,32 @@ Releases are tag-driven (`vX.Y.Z`) and published by GitHub Actions via npm
|
|
|
8
8
|
Trusted Publishing. This file begins at 0.7.0; earlier releases are recorded in
|
|
9
9
|
the git tags (`git tag -l`) and the [GitHub release history](https://github.com/pungggi/pi-continual-harness/releases).
|
|
10
10
|
|
|
11
|
-
## [
|
|
11
|
+
## [0.22.0] — 2026-11-11
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Classifier auto-discovery** (pi ≥ 1.5.1 interplay): when `classifier.model`
|
|
16
|
+
is unset, the classifier seam now falls back to a single known-good hosted
|
|
17
|
+
classifier — `github-copilot/microsoft-decision-1`, shipped by pi 1.5.1+
|
|
18
|
+
with GitHub Copilot auth — so classifier-confirmed dedupe and the auto-refine
|
|
19
|
+
gate work with zero setup for Copilot users. Discovery deliberately never
|
|
20
|
+
picks a local llama.cpp entry (the catalog can list one while no server
|
|
21
|
+
runs). An explicit `classifier.model` always wins; `"classifier": { "auto":
|
|
22
|
+
false }` restores explicit-only. `/harness status` and the setup/reminder
|
|
23
|
+
copy now treat the gate as the only required key when discovery is on.
|
|
24
|
+
- **Determinism contract for the injected block** (pinned by a test): for an
|
|
25
|
+
unchanged store + config, `renderHarnessBlock` is byte-identical. This is
|
|
26
|
+
what lets pi 1.5.1+'s Anthropic message threads `continue` a conversation —
|
|
27
|
+
the thread-prefix hash covers the system prompt, so unchanged harness state
|
|
28
|
+
rides the server-side thread and the warmed prompt cache, while any harness
|
|
29
|
+
change mismatches the hash and pi correctly falls back to a full resend.
|
|
30
|
+
Idle prompt-cache warming (pi 1.5.1) similarly keeps the injected system
|
|
31
|
+
prefix warm between runs — no package change needed, both verified against
|
|
32
|
+
the pi-ai 1.5.2 source.
|
|
33
|
+
- Dev dependencies bumped to `@earendil-works/pi-*` `^1.5.2` (runtime peers
|
|
34
|
+
stay `>=1.2.0`; nothing 1.5-only is imported at runtime).
|
|
35
|
+
|
|
36
|
+
## [0.21.0] — 2026-11-07
|
|
12
37
|
|
|
13
38
|
### Added
|
|
14
39
|
|
package/README.md
CHANGED
|
@@ -195,7 +195,7 @@ Optional config at `~/.pi/agent/harness.json` (missing → defaults; malformed
|
|
|
195
195
|
"remindRefine": { "enabled": true, "everyTurns": 25, "detailEvery": 4 },
|
|
196
196
|
"autoRefine": { "enabled": false, "everyTurns": 100, "commit": false, "gate": false, "refineNoOpSkip": 3 },
|
|
197
197
|
"outcomeImportance": { "enabled": false, "bump": 0.03 },
|
|
198
|
-
"classifier": { "model": "
|
|
198
|
+
"classifier": { "model": "github-copilot/microsoft-decision-1", "auto": true },
|
|
199
199
|
"virtualBinding": "virtual"
|
|
200
200
|
}
|
|
201
201
|
```
|
|
@@ -218,7 +218,7 @@ schemas (the same pattern pi ≥ 1.2 ships for its own `settings.json` /
|
|
|
218
218
|
| `remindRefine` | on, every 25 turns | The notify-only `/refine` activation nudge; every 4th one is a detailed educational guide. |
|
|
219
219
|
| `autoRefine` | off, every 100 turns | Opt-in autonomous `/refine` on a cadence; `gate` adds the classifier question, `refineNoOpSkip` the free history gate. |
|
|
220
220
|
| `outcomeImportance` | off, bump 0.03 | Opt-in promotion of items you cite by `[h_xxxx]` tag. Promotion only — never deletes. |
|
|
221
|
-
| `classifier` | unset | Classifier
|
|
221
|
+
| `classifier` | `model` unset, `auto: true` | Classifier enabling classifier-confirmed dedupe + the auto-refine gate. With `auto` (default), an unset `model` auto-resolves the hosted `github-copilot/microsoft-decision-1` on pi ≥ 1.5.1 with Copilot auth; set `model` to pin any classifier, or `auto: false` to require it. |
|
|
222
222
|
| `virtualBinding` | `"virtual"` | Per-model isolation key for router (virtual) models; `"physical"` keys by the routed model. |
|
|
223
223
|
|
|
224
224
|
The package's autonomous paths (`autoImport`, `autoRefine`, `outcomeImportance`)
|
|
@@ -542,8 +542,12 @@ migration; developed and tested against pi 1.5). Implemented:
|
|
|
542
542
|
config key; the store is never changed by selection. Rendered on **every
|
|
543
543
|
provider request** (`context_with_system`), so a mid-run `harness_mutate`
|
|
544
544
|
shows up on the very next request.
|
|
545
|
-
- **Classifier features (pi ≥ 0.99, opt-in)**:
|
|
546
|
-
|
|
545
|
+
- **Classifier features (pi ≥ 0.99, opt-in)**: a classifier resolves via
|
|
546
|
+
`"classifier": { "model": … }`, or — when `model` is unset — via
|
|
547
|
+
auto-discovery (default on, `"classifier": { "auto": false }` opts out)
|
|
548
|
+
of the hosted `github-copilot/microsoft-decision-1` that pi ≥ 1.5.1 ships
|
|
549
|
+
with GitHub Copilot auth. A resolved classifier enables (1)
|
|
550
|
+
classifier-confirmed dedupe — candidate merge pairs confirmed by
|
|
547
551
|
one batched yes/no call (errors fall back to the rule-based plan) — and (2)
|
|
548
552
|
the auto-refine gate `"autoRefine": { "gate": true }`, which skips a cadenced
|
|
549
553
|
refine when the trajectory holds no durable correction.
|
package/dist/auto-refine.js
CHANGED
|
@@ -131,7 +131,7 @@ export async function handleAutoRefineTurnEnd(pi, event, ctx) {
|
|
|
131
131
|
}
|
|
132
132
|
// Opt-in classifier gate: cheap yes/no before spending the refine.
|
|
133
133
|
if (config.autoRefine?.gate) {
|
|
134
|
-
const classify = buildClassify(ctx, config.classifier
|
|
134
|
+
const classify = buildClassify(ctx, config.classifier);
|
|
135
135
|
if (classify) {
|
|
136
136
|
const evidence = gatherEvidence(ctx, DEFAULT_LOOKBACK_TURNS);
|
|
137
137
|
const res = await classify(buildGateRequest(evidence));
|
package/dist/classify.d.ts
CHANGED
|
@@ -65,14 +65,36 @@ interface ClassifierModelLike {
|
|
|
65
65
|
* it then degrades to its no-classifier behavior.
|
|
66
66
|
*/
|
|
67
67
|
export declare function resolveClassifierModel(registry: RegistryLike | undefined, configured?: string): ClassifierModelLike | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The auto-discovered default classifier: a hosted bool/score classifier that
|
|
70
|
+
* pi ≥ 1.5.1 ships with GitHub Copilot authentication (billed to the user's
|
|
71
|
+
* Copilot plan; no local server, no extra API key). Keeping this a single
|
|
72
|
+
* known-good id — not "first classifier in the catalog" — makes discovery
|
|
73
|
+
* deterministic and reviewable; widen it only deliberately.
|
|
74
|
+
*/
|
|
75
|
+
export declare const DEFAULT_CLASSIFIER = "github-copilot/microsoft-decision-1";
|
|
76
|
+
/**
|
|
77
|
+
* Auto-discovery fallback for buildClassify: the hosted default above when the
|
|
78
|
+
* registry lists it, otherwise undefined (degrade to no-classifier behavior).
|
|
79
|
+
*/
|
|
80
|
+
export declare function discoverClassifierModel(registry: RegistryLike | undefined): ClassifierModelLike | undefined;
|
|
68
81
|
/** Build the ClassifyFn adapter over a resolved classifier model. */
|
|
69
82
|
export declare function makeClassifyFn(registry: RegistryLike, model: ClassifierModelLike, signal?: AbortSignal): ClassifyFn;
|
|
83
|
+
/** Structural slice of the normalized `classifier` config (config.ts). */
|
|
84
|
+
export interface ClassifierConfigSlice {
|
|
85
|
+
model?: string | undefined;
|
|
86
|
+
/** Default true (opt-out): when `model` is unset, fall back to the hosted
|
|
87
|
+
* default classifier when the registry lists one. */
|
|
88
|
+
auto?: boolean;
|
|
89
|
+
}
|
|
70
90
|
/**
|
|
71
91
|
* Resolve the ClassifyFn for a session from config + ctx, or undefined.
|
|
72
92
|
* The single construction point shared by refine (ProposeInput.classify) and
|
|
73
|
-
* the auto-refine gate.
|
|
93
|
+
* the auto-refine gate. An explicit `classifier.model` always wins; with
|
|
94
|
+
* `auto` (default) an unset model falls back to discovery (see
|
|
95
|
+
* discoverClassifierModel).
|
|
74
96
|
*/
|
|
75
|
-
export declare function buildClassify(ctx: ExtensionContext,
|
|
97
|
+
export declare function buildClassify(ctx: ExtensionContext, classifier?: ClassifierConfigSlice): ClassifyFn | undefined;
|
|
76
98
|
/**
|
|
77
99
|
* The auto-refine gate question: did the recent trajectory contain a durable,
|
|
78
100
|
* reusable correction worth a /refine pass? Pure builder — unit-testable.
|
package/dist/classify.js
CHANGED
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
// 2. dedupe confirmation (proposer.ts): a precision filter on candidate merge
|
|
11
11
|
// pairs — see classifyConfirmPairs().
|
|
12
12
|
//
|
|
13
|
+
// Model resolution has two tiers (buildClassify): an explicitly configured
|
|
14
|
+
// `classifier.model` always wins; when it is unset, auto-discovery (default on,
|
|
15
|
+
// `classifier.auto: false` opts out) falls back to ONE known hosted classifier —
|
|
16
|
+
// github-copilot/microsoft-decision-1, shipped by pi ≥ 1.5.1 with GitHub
|
|
17
|
+
// Copilot auth — so the gated paths work with zero setup for Copilot users.
|
|
18
|
+
// Discovery deliberately never picks a local llama.cpp entry: the catalog can
|
|
19
|
+
// list one while no server is running, and an unreachable classifier is worse
|
|
20
|
+
// than none (the gates would soft-fail every time).
|
|
21
|
+
//
|
|
13
22
|
// The pi-ai classifier shapes (ClassifierContext/ClassifierQuestion/…) are kept
|
|
14
23
|
// OUT of the public proposer interface: ClassifyFn below is a minimal structural
|
|
15
24
|
// contract so proposers stay testable without pi runtime types.
|
|
@@ -35,6 +44,21 @@ export function resolveClassifierModel(registry, configured) {
|
|
|
35
44
|
return cm.id === configured || `${cm.provider}/${cm.id}` === configured;
|
|
36
45
|
}) ?? undefined);
|
|
37
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* The auto-discovered default classifier: a hosted bool/score classifier that
|
|
49
|
+
* pi ≥ 1.5.1 ships with GitHub Copilot authentication (billed to the user's
|
|
50
|
+
* Copilot plan; no local server, no extra API key). Keeping this a single
|
|
51
|
+
* known-good id — not "first classifier in the catalog" — makes discovery
|
|
52
|
+
* deterministic and reviewable; widen it only deliberately.
|
|
53
|
+
*/
|
|
54
|
+
export const DEFAULT_CLASSIFIER = "github-copilot/microsoft-decision-1";
|
|
55
|
+
/**
|
|
56
|
+
* Auto-discovery fallback for buildClassify: the hosted default above when the
|
|
57
|
+
* registry lists it, otherwise undefined (degrade to no-classifier behavior).
|
|
58
|
+
*/
|
|
59
|
+
export function discoverClassifierModel(registry) {
|
|
60
|
+
return resolveClassifierModel(registry, DEFAULT_CLASSIFIER);
|
|
61
|
+
}
|
|
38
62
|
/** Build the ClassifyFn adapter over a resolved classifier model. */
|
|
39
63
|
export function makeClassifyFn(registry, model, signal) {
|
|
40
64
|
const label = `${model.provider}/${model.id}`;
|
|
@@ -102,12 +126,17 @@ export function makeClassifyFn(registry, model, signal) {
|
|
|
102
126
|
/**
|
|
103
127
|
* Resolve the ClassifyFn for a session from config + ctx, or undefined.
|
|
104
128
|
* The single construction point shared by refine (ProposeInput.classify) and
|
|
105
|
-
* the auto-refine gate.
|
|
129
|
+
* the auto-refine gate. An explicit `classifier.model` always wins; with
|
|
130
|
+
* `auto` (default) an unset model falls back to discovery (see
|
|
131
|
+
* discoverClassifierModel).
|
|
106
132
|
*/
|
|
107
|
-
export function buildClassify(ctx,
|
|
133
|
+
export function buildClassify(ctx, classifier) {
|
|
108
134
|
const registry = ctx.modelRegistry;
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
if (!registry)
|
|
136
|
+
return undefined;
|
|
137
|
+
const model = resolveClassifierModel(registry, classifier?.model) ??
|
|
138
|
+
(classifier?.auto !== false ? discoverClassifierModel(registry) : undefined);
|
|
139
|
+
if (!model)
|
|
111
140
|
return undefined;
|
|
112
141
|
return makeClassifyFn(registry, model, ctx.signal);
|
|
113
142
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -72,12 +72,18 @@ export interface HarnessConfig {
|
|
|
72
72
|
* DEFAULT_REFINE_NOOP_SKIP (3); 0 disables the history gate. */
|
|
73
73
|
refineNoOpSkip?: number;
|
|
74
74
|
};
|
|
75
|
-
/** Classifier
|
|
75
|
+
/** Classifier for the cheap gated paths (pi ≥ 0.99): "provider/id" or
|
|
76
76
|
* a bare id of a classifier catalog entry (e.g. "typesafe/jev-latest" or a
|
|
77
|
-
* local llama.cpp classifier). When unset or unresolvable,
|
|
78
|
-
*
|
|
77
|
+
* local llama.cpp classifier). When `model` is unset or unresolvable,
|
|
78
|
+
* `auto` (default true) falls back to a hosted zero-setup classifier when
|
|
79
|
+
* the registry lists one — pi ≥ 1.5.1 ships
|
|
80
|
+
* "github-copilot/microsoft-decision-1" with GitHub Copilot auth. When
|
|
81
|
+
* nothing resolves, every classifier feature degrades to its no-classifier
|
|
82
|
+
* behavior. */
|
|
79
83
|
classifier?: {
|
|
80
84
|
model?: string | undefined;
|
|
85
|
+
/** Default true (opt-out). Set false to require an explicit `model`. */
|
|
86
|
+
auto?: boolean;
|
|
81
87
|
};
|
|
82
88
|
/** Virtual-model binding policy (pi ≥ 0.99). Default "virtual". */
|
|
83
89
|
virtualBinding?: VirtualBinding;
|
package/dist/config.js
CHANGED
|
@@ -50,7 +50,7 @@ export const DEFAULT_CONFIG = {
|
|
|
50
50
|
omitStaleDrafts: true,
|
|
51
51
|
refineNoOpSkip: DEFAULT_REFINE_NOOP_SKIP,
|
|
52
52
|
},
|
|
53
|
-
classifier: { model: undefined },
|
|
53
|
+
classifier: { model: undefined, auto: true },
|
|
54
54
|
virtualBinding: "virtual",
|
|
55
55
|
proposer: "steering",
|
|
56
56
|
outcomeImportance: { enabled: false, bump: DEFAULT_REF_BUMP },
|
|
@@ -113,6 +113,7 @@ function mergeConfig(over) {
|
|
|
113
113
|
model: typeof over.classifier?.model === "string" && over.classifier.model
|
|
114
114
|
? over.classifier.model
|
|
115
115
|
: undefined,
|
|
116
|
+
auto: over.classifier?.auto !== false,
|
|
116
117
|
},
|
|
117
118
|
virtualBinding: over.virtualBinding === "physical" ? "physical" : "virtual",
|
|
118
119
|
proposer: over.proposer ?? "steering",
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { preview, renderListReport, selectListItems, type ListOptions, type List
|
|
|
13
13
|
export { DEFAULT_INJECTION, estimateTokens, normalizeInjection, selectForInjection, type InjectionConfig, type NormalizedInjection, type SelectionResult, } from "./select.js";
|
|
14
14
|
export { branchEntries, isVirtualModel, physicalKeyFromBranch, resolveBindingKey, VIRTUAL_MODEL_API, } from "./vmodel.js";
|
|
15
15
|
export { buildDetailGuide, buildNudge, reminderState, type ReminderState, } from "./remind.js";
|
|
16
|
-
export { buildGateRequest, gateDecision, type ClassifyBoolAnswer, type ClassifyBoolQuestion, type ClassifyBoolResult, type ClassifyFn, } from "./classify.js";
|
|
16
|
+
export { DEFAULT_CLASSIFIER, buildGateRequest, discoverClassifierModel, gateDecision, type ClassifyBoolAnswer, type ClassifyBoolQuestion, type ClassifyBoolResult, type ClassifyFn, type ClassifierConfigSlice, } from "./classify.js";
|
|
17
17
|
export { AUTO_REFINE_ENTRY, buildOmissionDrafts, buildRefineDraft, turnEndedBadly, type OmissionDraft, type ProjectedLike, } from "./auto-refine.js";
|
|
18
18
|
export { messageText } from "./refine.js";
|
|
19
19
|
export { deepMergeConfig, readConfigRaw, saveConfig, type SaveConfigResult, } from "./config.js";
|
package/dist/index.js
CHANGED
|
@@ -51,8 +51,9 @@ export { branchEntries, isVirtualModel, physicalKeyFromBranch, resolveBindingKey
|
|
|
51
51
|
// richer /harness status) share the same copy source.
|
|
52
52
|
export { buildDetailGuide, buildNudge, reminderState, } from "./remind.js";
|
|
53
53
|
// Classifier seam (pi ≥ 0.99, 0.12.0): the minimal structural ClassifyFn
|
|
54
|
-
// contract proposers see, plus the gate builders (pure, testable)
|
|
55
|
-
|
|
54
|
+
// contract proposers see, plus the gate builders (pure, testable) and the
|
|
55
|
+
// auto-discovery default (0.22.0: hosted fallback for unset classifier.model).
|
|
56
|
+
export { DEFAULT_CLASSIFIER, buildGateRequest, discoverClassifierModel, gateDecision, } from "./classify.js";
|
|
56
57
|
// Auto-refine boundary helpers (pi ≥ 0.87, 0.12.0–0.13.0): the steering draft,
|
|
57
58
|
// the stale-draft context-edit omissions, and the shared aborted/error-turn
|
|
58
59
|
// predicate (pi BoundaryState.outcome). Re-exported for tests and companion
|
package/dist/inject.d.ts
CHANGED
|
@@ -30,6 +30,14 @@ export declare function resetInjectionStats(): void;
|
|
|
30
30
|
* defining the marker when any such item is surfaced; `priority` is honored
|
|
31
31
|
* inside the selection (trusted items win budget contention).
|
|
32
32
|
*
|
|
33
|
+
* DETERMINISM CONTRACT: for an unchanged store + config the returned block is
|
|
34
|
+
* byte-identical (stable item ids, no timestamps, no random ordering — pinned
|
|
35
|
+
* by test/model-binding.test.ts). This is what lets pi ≥ 1.5.1 Anthropic message
|
|
36
|
+
* threads `continue` a conversation: the thread-prefix hash covers the system
|
|
37
|
+
* message, so an unchanged harness rides the server-side thread (and the
|
|
38
|
+
* warmed prompt cache) while any harness change mismatches the hash and pi
|
|
39
|
+
* correctly falls back to a full resend. Never add volatile content here.
|
|
40
|
+
*
|
|
33
41
|
* Note: every non-empty render folds into the session injection stats
|
|
34
42
|
* (InjectionStats above; /harness status surfaces them). Tests that render
|
|
35
43
|
* directly reset with resetInjectionStats().
|
package/dist/inject.js
CHANGED
|
@@ -51,6 +51,14 @@ export function resetInjectionStats() {
|
|
|
51
51
|
* defining the marker when any such item is surfaced; `priority` is honored
|
|
52
52
|
* inside the selection (trusted items win budget contention).
|
|
53
53
|
*
|
|
54
|
+
* DETERMINISM CONTRACT: for an unchanged store + config the returned block is
|
|
55
|
+
* byte-identical (stable item ids, no timestamps, no random ordering — pinned
|
|
56
|
+
* by test/model-binding.test.ts). This is what lets pi ≥ 1.5.1 Anthropic message
|
|
57
|
+
* threads `continue` a conversation: the thread-prefix hash covers the system
|
|
58
|
+
* message, so an unchanged harness rides the server-side thread (and the
|
|
59
|
+
* warmed prompt cache) while any harness change mismatches the hash and pi
|
|
60
|
+
* correctly falls back to a full resend. Never add volatile content here.
|
|
61
|
+
*
|
|
54
62
|
* Note: every non-empty render folds into the session injection stats
|
|
55
63
|
* (InjectionStats above; /harness status surfaces them). Tests that render
|
|
56
64
|
* directly reset with resetInjectionStats().
|
package/dist/refine.js
CHANGED
|
@@ -103,7 +103,7 @@ async function buildProposeInput(ctx, evidence, lookback, options) {
|
|
|
103
103
|
complete: buildComplete(ctx),
|
|
104
104
|
// Inject the classifier adapter when `classifier.model` is configured and
|
|
105
105
|
// resolvable (pi ≥ 0.99) — the dedupe proposer uses it to confirm merges.
|
|
106
|
-
classify: buildClassify(ctx, config.classifier
|
|
106
|
+
classify: buildClassify(ctx, config.classifier),
|
|
107
107
|
ownerKey,
|
|
108
108
|
lessons,
|
|
109
109
|
evidence,
|
package/dist/remind.js
CHANGED
|
@@ -151,9 +151,9 @@ export const DETAIL_GUIDES = [
|
|
|
151
151
|
' "remindRefine": { "enabled": true, "everyTurns": 25, "detailEvery": 4 },',
|
|
152
152
|
' "autoRefine": { "enabled": true, "everyTurns": 100, "gate": true, "commit": false },',
|
|
153
153
|
' "outcomeImportance": { "enabled": true, "bump": 0.03 },',
|
|
154
|
-
' "classifier": { "
|
|
154
|
+
' "classifier": { "auto": true }',
|
|
155
155
|
"}",
|
|
156
|
-
`Guidance: gate
|
|
156
|
+
`Guidance: gate spends one cheap yes/no question before each auto-refine, so cadence becomes signal. With classifier.auto (default true) and no explicit classifier.model, the hosted github-copilot/microsoft-decision-1 resolves automatically on pi >= 1.5.1 with Copilot auth; otherwise set classifier.model to any classifier catalog entry (e.g. a local llama.cpp classifier). Durable writes are autonomous in this config: with autoImport on, the layers re-export on every store change (that is what makes /refine output survive into new sessions); commit only adds a flush at each auto-run and matters when autoImport is off. Prefer autoImport off + manual /harness export until you trust the refinements, then opt in. This nudge fires every ${state.everyTurns} completed turns and shows a guide every ${state.detailEvery}th reminder (about every ${state.everyTurns * state.detailEvery} completed turns).`,
|
|
157
157
|
].join("\n"),
|
|
158
158
|
];
|
|
159
159
|
/** Rotation slot for the ordinal-th detailed reminder (1-based, pure). */
|
package/dist/setup.js
CHANGED
|
@@ -99,7 +99,7 @@ export const PRESETS = {
|
|
|
99
99
|
title: "durable sync + awareness reminders",
|
|
100
100
|
description: "autoImport on (refinements survive into new sessions) paired with the importRemind awareness reminders.",
|
|
101
101
|
notes: [
|
|
102
|
-
"Gate-ready: to make refinement signal-driven later, set
|
|
102
|
+
"Gate-ready: to make refinement signal-driven later, set autoRefine.gate (pi >= 0.99; a classifier resolves automatically on pi >= 1.5.1 with Copilot, else set classifier.model). This preset leaves the gate off.",
|
|
103
103
|
],
|
|
104
104
|
deltas: recommendedDeltas(),
|
|
105
105
|
},
|
package/dist/status.js
CHANGED
|
@@ -125,11 +125,15 @@ function applicableHints(state, config, impact) {
|
|
|
125
125
|
// Classifier/gate not fully configured → the cheapest activation lever is
|
|
126
126
|
// invisible to the user. `classifier.model` ALONE changes nothing gating-wise
|
|
127
127
|
// (the gate needs `autoRefine.gate: true` too — review #27), so the hint
|
|
128
|
-
// stays until
|
|
129
|
-
|
|
128
|
+
// stays until the gate is on and the copy names the keys. Since auto-
|
|
129
|
+
// discovery (0.22.0) a classifier may resolve with `classifier.model` unset
|
|
130
|
+
// (hosted default on pi ≥ 1.5.1 + Copilot auth), so the copy treats the
|
|
131
|
+
// model as optional.
|
|
132
|
+
if (config.autoRefine?.gate !== true ||
|
|
133
|
+
(!config.classifier?.model && config.classifier?.auto === false)) {
|
|
130
134
|
hints.push({
|
|
131
135
|
id: "classifier-gate",
|
|
132
|
-
text: 'the auto-refine gate is available: set `
|
|
136
|
+
text: 'the auto-refine gate is available: set `autoRefine: { "gate": true }` in harness.json so cadenced refines skip when nothing durable happened (a classifier resolves automatically on pi ≥ 1.5.1 with GitHub Copilot; otherwise also set `classifier.model`)',
|
|
133
137
|
});
|
|
134
138
|
}
|
|
135
139
|
// Zero citations ever and the loop is off → the outcome half of the fitness
|
package/harness.schema.json
CHANGED
|
@@ -71,12 +71,17 @@
|
|
|
71
71
|
},
|
|
72
72
|
"classifier": {
|
|
73
73
|
"type": "object",
|
|
74
|
-
"description": "Classifier
|
|
74
|
+
"description": "Classifier for the cheap gated paths.",
|
|
75
75
|
"additionalProperties": true,
|
|
76
76
|
"properties": {
|
|
77
77
|
"model": {
|
|
78
78
|
"type": "string",
|
|
79
79
|
"description": "\"provider/id\" or a bare id of a classifier catalog entry (e.g. \"typesafe/jev-latest\" or a local llama.cpp classifier). Unset/unresolvable → every classifier feature degrades to its no-classifier behavior."
|
|
80
|
+
},
|
|
81
|
+
"auto": {
|
|
82
|
+
"type": "boolean",
|
|
83
|
+
"default": true,
|
|
84
|
+
"description": "When model is unset (default), fall back to a hosted zero-setup classifier when the registry lists one — pi ≥ 1.5.1 ships github-copilot/microsoft-decision-1 with GitHub Copilot auth. Set false to require an explicit model."
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-continual-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Online self-improvement layer for pi. A unified, in-trajectory harness-state store (prompt notes, memory, skill descriptions, sub-agent specs) with a manual /refine that proposes evidence-backed structured CRUD deltas. Composes with pi-reflect (offline) and pi-mem (storage); owns only the online optimizer layer. Inspired by Continual Harness (arXiv 2605.09998) and ACE (arXiv 2510.04618).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@biomejs/biome": "^2.6.4",
|
|
47
|
-
"@earendil-works/pi-ai": "^1.5.
|
|
48
|
-
"@earendil-works/pi-coding-agent": "^1.5.
|
|
49
|
-
"@earendil-works/pi-schema": "^1.5.
|
|
47
|
+
"@earendil-works/pi-ai": "^1.5.2",
|
|
48
|
+
"@earendil-works/pi-coding-agent": "^1.5.2",
|
|
49
|
+
"@earendil-works/pi-schema": "^1.5.2",
|
|
50
50
|
"@types/node": "^22.0.0",
|
|
51
51
|
"@vitest/coverage-v8": "^3.2.7",
|
|
52
52
|
"typebox": ">=1.0.0",
|