@hassangameryt/freeflow 0.6.0 → 0.7.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +5 -6
- package/.cursor-plugin/plugin.json +25 -0
- package/README.md +66 -56
- package/capabilities/cognitive-routing/SKILL.md +288 -130
- package/com.github.copilot/hooks/hooks.json +11 -0
- package/command-surface.json +0 -24
- package/gemini-extension.json +5 -0
- package/hooks/adapters/claude-session-start.mjs +16 -0
- package/hooks/adapters/codex-session-start.mjs +16 -0
- package/hooks/adapters/copilot-session-start.mjs +13 -0
- package/hooks/adapters/cursor-session-start.mjs +13 -0
- package/hooks/adapters/gemini-session-start.mjs +15 -0
- package/hooks/claude/hooks.json +18 -0
- package/hooks/codex/hooks.json +18 -0
- package/hooks/cursor/hooks.json +9 -0
- package/hooks/freeflow-runtime-context.mjs +3 -650
- package/hooks/hooks.json +4 -30
- package/hooks/shared/runtime-context.mjs +210 -0
- package/hooks/tests/check-host-adapters.test.mjs +82 -0
- package/hooks/tests/check-runtime-context-hook.sh +140 -320
- package/package.json +20 -4
- package/pi-extension/dist/cognitive-routing/commands.js +3 -3
- package/pi-extension/dist/cognitive-routing/config.js +16 -20
- package/pi-extension/dist/cognitive-routing/controller.js +478 -48
- package/pi-extension/dist/cognitive-routing/history.js +12 -0
- package/pi-extension/dist/cognitive-routing/host.js +74 -12
- package/pi-extension/dist/cognitive-routing/pi-routing-session.js +414 -0
- package/pi-extension/dist/cognitive-routing/pi-session-control.js +320 -0
- package/pi-extension/dist/cognitive-routing/tool.js +1 -0
- package/pi-extension/dist/cognitive-routing/types.js +1 -1
- package/pi-extension/dist/index.js +236 -219
- package/pi-extension/dist/runtime/runtime-context.js +126 -286
- package/pi-extension/dist/settings/settings-ui.js +52 -336
- package/pi-extension/src/cognitive-routing/commands.ts +15 -5
- package/pi-extension/src/cognitive-routing/config.ts +16 -20
- package/pi-extension/src/cognitive-routing/controller.ts +561 -51
- package/pi-extension/src/cognitive-routing/history.ts +12 -0
- package/pi-extension/src/cognitive-routing/host.ts +110 -16
- package/pi-extension/src/cognitive-routing/pi-routing-session.ts +538 -0
- package/pi-extension/src/cognitive-routing/pi-session-control.ts +444 -0
- package/pi-extension/src/cognitive-routing/tool.ts +1 -0
- package/pi-extension/src/cognitive-routing/types.ts +1 -1
- package/pi-extension/src/index.ts +249 -239
- package/pi-extension/src/runtime/runtime-context.ts +129 -305
- package/pi-extension/src/settings/settings-ui.ts +53 -371
- package/pi-extension/tests/cognitive-routing/commands.test.js +1 -1
- package/pi-extension/tests/cognitive-routing/controller.test.js +69 -40
- package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +128 -57
- package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +434 -0
- package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +174 -0
- package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +91 -0
- package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +47 -4
- package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
- package/pi-extension/tests/integration/pi-extension.test.js +430 -2478
- package/pi-extension/tests/integration/prompt-architecture.test.js +124 -79
- package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
- package/plugin.json +33 -0
- package/runtime/prompts/cognitive-routing.md +5 -4
- package/runtime/prompts/conversation-history.md +1 -1
- package/runtime/prompts/core.md +77 -6
- package/runtime/prompts/interaction-contract.md +6 -2
- package/skills/action-selection/SKILL.md +93 -44
- package/skills/action-selection/references/trajectory-stalls.md +71 -0
- package/skills/bypass/SKILL.md +109 -39
- package/skills/commit-work/SKILL.md +94 -55
- package/skills/commit-work/references/git-state-edges.md +94 -0
- package/skills/commit-work/references/simple-push.md +92 -0
- package/skills/commit-work/references/staging-decisions.md +79 -46
- package/skills/decision-gate/SKILL.md +80 -22
- package/skills/design-for-depth/SKILL.md +208 -43
- package/skills/design-for-depth/references/design-pressure-signals.md +108 -240
- package/skills/design-for-depth/references/interface-design-loop.md +77 -97
- package/skills/design-for-depth/references/module-and-dependency-design.md +147 -0
- package/skills/design-for-depth/references/software-design-philosophy.md +127 -173
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
- package/skills/diagnose-failure/SKILL.md +198 -52
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +19 -5
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +13 -5
- package/skills/discuss/SKILL.md +118 -76
- package/skills/discuss/references/discussion-continuity.md +84 -32
- package/skills/evaluate-skill/SKILL.md +166 -52
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +2 -2
- package/skills/evaluate-skill/references/evaluation-design.md +56 -30
- package/skills/evaluate-skill/references/execution-and-evidence.md +1 -1
- package/skills/evaluate-skill/references/review-and-revision.md +62 -21
- package/skills/execute-work/SKILL.md +98 -59
- package/skills/execute-work/references/code-practices.md +4 -4
- package/skills/execute-work/references/execute-work-edges.md +42 -22
- package/skills/review-artifact/SKILL.md +132 -71
- package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +52 -41
- package/skills/review-work/SKILL.md +115 -72
- package/skills/review-work/references/adjudicate-work-review.md +97 -0
- package/skills/review-work/references/independent-work-reviewer-contract.md +40 -35
- package/skills/review-work/references/security-risk-lens.md +17 -15
- package/skills/setup-freeflow/SKILL.md +14 -17
- package/skills/setup-freeflow/references/activation-contract.md +24 -30
- package/skills/setup-freeflow/references/host-setup.md +6 -7
- package/skills/simplify-code/SKILL.md +97 -39
- package/skills/simplify-code/references/simplification-patterns.md +1 -1
- package/skills/tdd/SKILL.md +108 -41
- package/skills/tdd/references/test-design.md +1 -1
- package/skills/track-work/SKILL.md +133 -300
- package/skills/track-work/references/working-record-format.md +515 -0
- package/skills/track-work/scripts/lib/document.mjs +713 -0
- package/skills/track-work/scripts/lib/format.mjs +166 -0
- package/skills/track-work/scripts/lib/store.mjs +233 -0
- package/skills/track-work/scripts/lib/transitions.mjs +790 -0
- package/skills/track-work/scripts/lib/views.mjs +27 -430
- package/skills/track-work/scripts/working-record.mjs +292 -98
- package/skills/verify-work/SKILL.md +46 -20
- package/skills/verify-work/references/browser-runtime-evidence.md +1 -1
- package/skills/verify-work/references/integration-evidence.md +1 -7
- package/skills/verify-work/references/performance-evidence.md +1 -1
- package/skills/workflow/SKILL.md +110 -80
- package/skills/workflow/references/domain-skill-composition.md +24 -18
- package/skills/write-skill/SKILL.md +218 -62
- package/skills/write-skill/references/activation-boundaries.md +63 -21
- package/skills/write-skill/references/agent-first-instructions.md +61 -27
- package/skills/write-skill/references/progressive-disclosure.md +91 -41
- package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
- package/runtime/prompts/skills.md +0 -65
- package/skills/mode-contract/SKILL.md +0 -104
- package/skills/track-work/scripts/lib/codec.mjs +0 -570
- package/skills/track-work/scripts/lib/commands.mjs +0 -568
- package/skills/track-work/scripts/lib/contract.mjs +0 -303
- package/skills/track-work/scripts/lib/model.mjs +0 -506
- package/skills/track-work/scripts/lib/operations.mjs +0 -965
- package/skills/track-work/scripts/lib/record-store.mjs +0 -264
- package/skills/track-work/scripts/lib/result.mjs +0 -37
- package/skills/track-work/scripts/lib/rewrites.mjs +0 -740
- package/skills/track-work/scripts/lib/schema.mjs +0 -277
- package/skills/track-work/scripts/lib/source-inventory.mjs +0 -162
- package/skills/track-work/scripts/lib/workspace.mjs +0 -134
|
@@ -89,7 +89,7 @@ test("releases manual ownership through auto without a model transition", async
|
|
|
89
89
|
|
|
90
90
|
assert.equal(await handleCognitiveRoutingProfileCommand("profile auto", context, controller), true);
|
|
91
91
|
assert.equal(calls, 1);
|
|
92
|
-
assert.match(context.notifications[0].message, /automatic control is active/);
|
|
92
|
+
assert.match(context.notifications[0].message, /automatic Reasoning control is active/);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test("rejects manual profile changes while Pi is running", async () => {
|
|
@@ -103,21 +103,21 @@ test("prepares activation before acquiring and applying the host pair", async ()
|
|
|
103
103
|
});
|
|
104
104
|
assert.deepEqual(host.calls[0][2].target, {
|
|
105
105
|
provider: "faux",
|
|
106
|
-
modelId: "
|
|
107
|
-
thinkingLevel: "
|
|
106
|
+
modelId: "reasoning",
|
|
107
|
+
thinkingLevel: "max",
|
|
108
108
|
});
|
|
109
|
-
assert.equal(controller.state().activeProfile, "
|
|
109
|
+
assert.equal(controller.state().activeProfile, "reasoning");
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
test("activates each configured session-start control and profile combination", async () => {
|
|
113
113
|
const combinations = [
|
|
114
|
-
["automatic", "standard", "automatic"],
|
|
115
|
-
["automatic", "reasoning", "automatic"],
|
|
116
|
-
["manual", "standard", "manual-standard"],
|
|
117
|
-
["manual", "reasoning", "manual-reasoning"],
|
|
114
|
+
["automatic", "standard", "automatic", "reasoning"],
|
|
115
|
+
["automatic", "reasoning", "automatic", "reasoning"],
|
|
116
|
+
["manual", "standard", "manual-standard", "standard"],
|
|
117
|
+
["manual", "reasoning", "manual-reasoning", "reasoning"],
|
|
118
118
|
];
|
|
119
119
|
|
|
120
|
-
for (const [control, profile, expectedControlMode] of combinations) {
|
|
120
|
+
for (const [control, profile, expectedControlMode, expectedProfile] of combinations) {
|
|
121
121
|
const host = createHost({ onAcquire: appliedLease });
|
|
122
122
|
const controller = new CognitiveRoutingController({
|
|
123
123
|
capabilityState: {
|
|
@@ -136,9 +136,9 @@ test("activates each configured session-start control and profile combination",
|
|
|
136
136
|
const result = await controller.activate();
|
|
137
137
|
|
|
138
138
|
assert.equal(result.status, "active");
|
|
139
|
-
assert.equal(controller.state().activeProfile,
|
|
139
|
+
assert.equal(controller.state().activeProfile, expectedProfile);
|
|
140
140
|
assert.equal(controller.state().controlMode, expectedControlMode);
|
|
141
|
-
assert.equal(host.calls[2][1].modelId,
|
|
141
|
+
assert.equal(host.calls[2][1].modelId, expectedProfile);
|
|
142
142
|
}
|
|
143
143
|
});
|
|
144
144
|
|
|
@@ -201,14 +201,14 @@ test("does not persist or reapply an automatic request for the active profile",
|
|
|
201
201
|
await controller.activate();
|
|
202
202
|
const callsBefore = host.calls.length;
|
|
203
203
|
|
|
204
|
-
const result = await controller.switchAutomaticProfile("
|
|
204
|
+
const result = await controller.switchAutomaticProfile("reasoning", "Keep the current profile.");
|
|
205
205
|
|
|
206
206
|
assert.deepEqual(result, {
|
|
207
207
|
status: "active",
|
|
208
208
|
changed: false,
|
|
209
|
-
from: "
|
|
210
|
-
to: "
|
|
211
|
-
profile: "
|
|
209
|
+
from: "reasoning",
|
|
210
|
+
to: "reasoning",
|
|
211
|
+
profile: "reasoning",
|
|
212
212
|
});
|
|
213
213
|
assert.equal(host.calls.length, callsBefore);
|
|
214
214
|
});
|
|
@@ -226,19 +226,19 @@ test("switches profiles through the automatic owner with bounded agent evidence"
|
|
|
226
226
|
});
|
|
227
227
|
await controller.activate();
|
|
228
228
|
|
|
229
|
-
const result = await controller.switchAutomaticProfile("
|
|
229
|
+
const result = await controller.switchAutomaticProfile("standard", "Need a lighter execution pass.");
|
|
230
230
|
|
|
231
231
|
assert.deepEqual(result, {
|
|
232
232
|
status: "active",
|
|
233
233
|
changed: true,
|
|
234
|
-
from: "
|
|
235
|
-
to: "
|
|
236
|
-
profile: "
|
|
234
|
+
from: "reasoning",
|
|
235
|
+
to: "standard",
|
|
236
|
+
profile: "standard",
|
|
237
237
|
});
|
|
238
238
|
assert.equal(controller.state().controlMode, "automatic");
|
|
239
239
|
assert.equal(host.calls.at(-1)[0], "setState");
|
|
240
240
|
assert.equal(host.calls[3][2].source, "agent");
|
|
241
|
-
assert.equal(host.calls[3][2].reason, "Need a
|
|
241
|
+
assert.equal(host.calls[3][2].reason, "Need a lighter execution pass.");
|
|
242
242
|
});
|
|
243
243
|
|
|
244
244
|
test("blocks an automatic switch while a manual hold owns the controller", async () => {
|
|
@@ -285,6 +285,21 @@ test("releases manual control as a durable control-only entry without switching
|
|
|
285
285
|
);
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
+
test("releases a manual Standard hold by switching to automatic Reasoning", async () => {
|
|
289
|
+
const host = createHost({ onAcquire: appliedLease });
|
|
290
|
+
const controller = new CognitiveRoutingController({ capabilityState, pi: host.pi, ctx: host.ctx });
|
|
291
|
+
await controller.activate();
|
|
292
|
+
await controller.setManualProfile("standard");
|
|
293
|
+
|
|
294
|
+
const result = await controller.setAutomaticControl("profile-command");
|
|
295
|
+
|
|
296
|
+
assert.deepEqual(result, { status: "automatic" });
|
|
297
|
+
assert.equal(controller.state().activeProfile, "reasoning");
|
|
298
|
+
assert.equal(controller.state().controlMode, "automatic");
|
|
299
|
+
assert.equal(host.calls.at(-1)[0], "setState");
|
|
300
|
+
assert.equal(host.calls.at(-1)[1].modelId, "reasoning");
|
|
301
|
+
});
|
|
302
|
+
|
|
288
303
|
test("does not acquire or switch when durable activation preparation fails", async () => {
|
|
289
304
|
let acquireCalls = 0;
|
|
290
305
|
const host = createHost({
|
|
@@ -422,7 +437,7 @@ test("serializes deactivation behind an in-flight activation", async () => {
|
|
|
422
437
|
lease: {
|
|
423
438
|
async setState(request) {
|
|
424
439
|
calls.push(["setState", request]);
|
|
425
|
-
if (request.modelId === "
|
|
440
|
+
if (request.modelId === "reasoning") {
|
|
426
441
|
resolveTransition();
|
|
427
442
|
await new Promise((resolve) => {
|
|
428
443
|
releaseTransition = resolve;
|
|
@@ -1003,14 +1018,14 @@ test("writes v2 mechanism, causal, and baseline metadata before transitions", as
|
|
|
1003
1018
|
pi: host.pi,
|
|
1004
1019
|
ctx: host.ctx,
|
|
1005
1020
|
idFactory: (() => {
|
|
1006
|
-
const ids = ["epoch-1", "activation-correlation", "
|
|
1021
|
+
const ids = ["epoch-1", "activation-correlation", "standard-correlation", "automatic-reasoning-correlation"];
|
|
1007
1022
|
return () => ids.shift();
|
|
1008
1023
|
})(),
|
|
1009
1024
|
});
|
|
1010
1025
|
|
|
1011
1026
|
await controller.activate();
|
|
1012
|
-
await controller.switchAutomaticProfile("
|
|
1013
|
-
await controller.setAutomaticControl();
|
|
1027
|
+
await controller.switchAutomaticProfile("standard", "Need a lighter execution pass.");
|
|
1028
|
+
await controller.setAutomaticControl("profile-command");
|
|
1014
1029
|
|
|
1015
1030
|
const intents = host.sessionEntries.filter(
|
|
1016
1031
|
(entry) => entry.type === "custom" && entry.customType === COGNITIVE_ROUTING_INTENT_ENTRY,
|
|
@@ -1025,10 +1040,10 @@ test("writes v2 mechanism, causal, and baseline metadata before transitions", as
|
|
|
1025
1040
|
branchId: null,
|
|
1026
1041
|
epoch: "epoch-1",
|
|
1027
1042
|
correlationId: "activation-correlation",
|
|
1028
|
-
target: { provider: "faux", modelId: "
|
|
1043
|
+
target: { provider: "faux", modelId: "reasoning", thinkingLevel: "max" },
|
|
1029
1044
|
returnTarget: { provider: "faux", modelId: "return", thinkingLevel: "medium" },
|
|
1030
1045
|
fromPair: { provider: "faux", modelId: "return", thinkingLevel: "medium" },
|
|
1031
|
-
profile: "
|
|
1046
|
+
profile: "reasoning",
|
|
1032
1047
|
});
|
|
1033
1048
|
assert.deepEqual(intents[1].data, {
|
|
1034
1049
|
version: 2,
|
|
@@ -1037,30 +1052,44 @@ test("writes v2 mechanism, causal, and baseline metadata before transitions", as
|
|
|
1037
1052
|
control: "automatic",
|
|
1038
1053
|
source: "agent",
|
|
1039
1054
|
mechanism: "agent-tool",
|
|
1040
|
-
decisionCorrelationId: "
|
|
1055
|
+
decisionCorrelationId: "standard-correlation",
|
|
1056
|
+
fromControl: "automatic",
|
|
1041
1057
|
branchId: null,
|
|
1042
1058
|
epoch: "epoch-1",
|
|
1043
|
-
correlationId: "
|
|
1044
|
-
profile: "
|
|
1045
|
-
target: { provider: "faux", modelId: "
|
|
1059
|
+
correlationId: "standard-correlation",
|
|
1060
|
+
profile: "standard",
|
|
1061
|
+
target: { provider: "faux", modelId: "standard", thinkingLevel: "high" },
|
|
1046
1062
|
returnTarget: { provider: "faux", modelId: "return", thinkingLevel: "medium" },
|
|
1047
|
-
fromPair: { provider: "faux", modelId: "
|
|
1048
|
-
fromProfile: "
|
|
1049
|
-
reason: "Need a
|
|
1063
|
+
fromPair: { provider: "faux", modelId: "reasoning", thinkingLevel: "max" },
|
|
1064
|
+
fromProfile: "reasoning",
|
|
1065
|
+
reason: "Need a lighter execution pass.",
|
|
1050
1066
|
});
|
|
1051
|
-
|
|
1052
|
-
const control = host.sessionEntries.find(
|
|
1053
|
-
(entry) => entry.type === "custom" && entry.customType === COGNITIVE_ROUTING_CONTROL_ENTRY,
|
|
1054
|
-
);
|
|
1055
|
-
assert.deepEqual(control.data, {
|
|
1067
|
+
assert.deepEqual(intents[2].data, {
|
|
1056
1068
|
version: 2,
|
|
1069
|
+
phase: "prepared",
|
|
1070
|
+
kind: "profile",
|
|
1057
1071
|
control: "automatic",
|
|
1058
1072
|
source: "user",
|
|
1059
1073
|
mechanism: "profile-command",
|
|
1060
|
-
|
|
1074
|
+
decisionCorrelationId: "automatic-reasoning-correlation",
|
|
1075
|
+
fromControl: "automatic",
|
|
1061
1076
|
branchId: null,
|
|
1062
1077
|
epoch: "epoch-1",
|
|
1078
|
+
correlationId: "automatic-reasoning-correlation",
|
|
1079
|
+
profile: "reasoning",
|
|
1080
|
+
target: { provider: "faux", modelId: "reasoning", thinkingLevel: "max" },
|
|
1081
|
+
returnTarget: { provider: "faux", modelId: "return", thinkingLevel: "medium" },
|
|
1082
|
+
fromPair: { provider: "faux", modelId: "standard", thinkingLevel: "high" },
|
|
1083
|
+
fromProfile: "standard",
|
|
1084
|
+
reason: "automatic control selects the Reasoning profile",
|
|
1063
1085
|
});
|
|
1086
|
+
|
|
1087
|
+
assert.equal(
|
|
1088
|
+
host.sessionEntries.some(
|
|
1089
|
+
(entry) => entry.type === "custom" && entry.customType === COGNITIVE_ROUTING_CONTROL_ENTRY,
|
|
1090
|
+
),
|
|
1091
|
+
false,
|
|
1092
|
+
);
|
|
1064
1093
|
});
|
|
1065
1094
|
|
|
1066
1095
|
test("fails closed before a profile transition when no current baseline is observable", async () => {
|
|
@@ -1072,7 +1101,7 @@ test("fails closed before a profile transition when no current baseline is obser
|
|
|
1072
1101
|
host.ctx.model = undefined;
|
|
1073
1102
|
host.ctx.thinkingLevel = undefined;
|
|
1074
1103
|
|
|
1075
|
-
const result = await controller.switchAutomaticProfile("
|
|
1104
|
+
const result = await controller.switchAutomaticProfile("standard", "Need a deeper analysis.");
|
|
1076
1105
|
|
|
1077
1106
|
assert.deepEqual(result, { status: "inactive", reason: "current_state_unavailable" });
|
|
1078
1107
|
assert.equal(host.calls.length, callsBefore);
|
|
@@ -1094,6 +1123,6 @@ test("restores the return target without guessing a missing closing baseline", a
|
|
|
1094
1123
|
(entry) => entry.type === "custom" && entry.customType === COGNITIVE_ROUTING_INTENT_ENTRY,
|
|
1095
1124
|
);
|
|
1096
1125
|
assert.equal(closingIntent.data.fromPair, undefined);
|
|
1097
|
-
assert.equal(closingIntent.data.fromProfile, "
|
|
1126
|
+
assert.equal(closingIntent.data.fromProfile, "reasoning");
|
|
1098
1127
|
assert.equal(host.sessionEntries.at(-1).type, "model_state_change");
|
|
1099
1128
|
});
|
|
@@ -137,7 +137,7 @@ function createContext(cwd, host) {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
test("registered shortcuts cycle manual holds and automatic
|
|
140
|
+
test("registered shortcuts cycle manual holds and establish automatic Reasoning", async () => {
|
|
141
141
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-shortcuts-"));
|
|
142
142
|
await mkdir(join(cwd, ".freeflow"));
|
|
143
143
|
await writeFile(
|
|
@@ -157,38 +157,29 @@ test("registered shortcuts cycle manual holds and automatic profiles", async ()
|
|
|
157
157
|
ctx.isIdle = () => true;
|
|
158
158
|
try {
|
|
159
159
|
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
160
|
+
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
160
161
|
const cycle = host.shortcuts.find(({ shortcut }) => shortcut === "ctrl+shift+r");
|
|
161
162
|
const automatic = host.shortcuts.find(({ shortcut }) => shortcut === "ctrl+shift+a");
|
|
162
163
|
assert.ok(cycle);
|
|
163
164
|
assert.ok(automatic);
|
|
164
165
|
|
|
165
166
|
await cycle.definition.handler(ctx);
|
|
166
|
-
assert.equal(host.entries.at(-1).modelId, "
|
|
167
|
+
assert.equal(host.entries.filter((entry) => entry.modelId).at(-1).modelId, "standard");
|
|
168
|
+
|
|
167
169
|
await automatic.definition.handler(ctx);
|
|
168
|
-
assert.equal(host.entries.at(-1).customType, "freeflow-cognitive-routing-control");
|
|
169
170
|
assert.equal(host.entries.filter((entry) => entry.modelId).at(-1).modelId, "reasoning");
|
|
171
|
+
const modelEntriesAfterAutomatic = host.entries.filter((entry) => entry.modelId).length;
|
|
172
|
+
|
|
170
173
|
await automatic.definition.handler(ctx);
|
|
171
|
-
assert.equal(host.entries.at(-1).modelId, "
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
assert.equal(host.entries.filter((entry) => entry.modelId).at(-1).modelId, "reasoning");
|
|
175
|
+
assert.equal(host.entries.filter((entry) => entry.modelId).length, modelEntriesAfterAutomatic);
|
|
176
|
+
|
|
174
177
|
const automaticIntent = host.entries
|
|
175
178
|
.filter((entry) => entry.customType === "freeflow-cognitive-routing-intent")
|
|
176
179
|
.at(-1);
|
|
177
180
|
assert.equal(automaticIntent.data.source, "user");
|
|
178
181
|
assert.equal(automaticIntent.data.mechanism, "profile-shortcut");
|
|
179
|
-
assert.equal(automaticIntent.data.reason, "
|
|
180
|
-
assert.deepEqual(host.operations, [
|
|
181
|
-
"prepare",
|
|
182
|
-
"acquire",
|
|
183
|
-
"setState",
|
|
184
|
-
"prepare",
|
|
185
|
-
"setState",
|
|
186
|
-
"prepare",
|
|
187
|
-
"prepare",
|
|
188
|
-
"setState",
|
|
189
|
-
"prepare",
|
|
190
|
-
"setState",
|
|
191
|
-
]);
|
|
182
|
+
assert.equal(automaticIntent.data.reason, "automatic control selects the Reasoning profile");
|
|
192
183
|
} finally {
|
|
193
184
|
await rm(cwd, { recursive: true, force: true });
|
|
194
185
|
}
|
|
@@ -295,7 +286,7 @@ test("Cognitive Routing retries activation after a transient failure", async ()
|
|
|
295
286
|
const providerContext = await host.handlers.get("context")({ messages: [] }, ctx);
|
|
296
287
|
assert.match(providerContext.messages.at(-1).content, /Cognitive Routing: active/);
|
|
297
288
|
assert.match(providerContext.messages.at(-1).content, /Control: `automatic`/);
|
|
298
|
-
assert.match(providerContext.messages.at(-1).content, /Profile: `
|
|
289
|
+
assert.match(providerContext.messages.at(-1).content, /Profile: `reasoning`/);
|
|
299
290
|
assert.ok(host.operations.includes("setState"));
|
|
300
291
|
} finally {
|
|
301
292
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
@@ -385,13 +376,13 @@ test("new empty sessions do not persist Cognitive Routing state until the first
|
|
|
385
376
|
|
|
386
377
|
test("new sessions honor each configured Cognitive Routing startup combination", async () => {
|
|
387
378
|
const combinations = [
|
|
388
|
-
["automatic", "standard"],
|
|
389
|
-
["automatic", "reasoning"],
|
|
390
|
-
["manual", "standard"],
|
|
391
|
-
["manual", "reasoning"],
|
|
379
|
+
["automatic", "standard", "reasoning"],
|
|
380
|
+
["automatic", "reasoning", "reasoning"],
|
|
381
|
+
["manual", "standard", "standard"],
|
|
382
|
+
["manual", "reasoning", "reasoning"],
|
|
392
383
|
];
|
|
393
384
|
|
|
394
|
-
for (const [control, profile] of combinations) {
|
|
385
|
+
for (const [control, profile, expectedProfile] of combinations) {
|
|
395
386
|
const cwd = await mkdtemp(join(tmpdir(), `freeflow-cognitive-routing-start-${control}-${profile}-`));
|
|
396
387
|
await mkdir(join(cwd, ".freeflow"));
|
|
397
388
|
await writeFile(
|
|
@@ -414,11 +405,11 @@ test("new sessions honor each configured Cognitive Routing startup combination",
|
|
|
414
405
|
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
415
406
|
await host.handlers.get("before_agent_start")({ prompt: "hello", systemPrompt: "base prompt" }, ctx);
|
|
416
407
|
|
|
417
|
-
assert.equal(host.entries.filter((entry) => entry.modelId).at(-1).modelId,
|
|
408
|
+
assert.equal(host.entries.filter((entry) => entry.modelId).at(-1).modelId, expectedProfile);
|
|
418
409
|
const activation = host.entries.find(
|
|
419
410
|
(entry) => entry.customType === "freeflow-cognitive-routing-intent" && entry.data.kind === "activation",
|
|
420
411
|
);
|
|
421
|
-
assert.equal(activation.data.profile,
|
|
412
|
+
assert.equal(activation.data.profile, expectedProfile);
|
|
422
413
|
assert.equal(activation.data.control, control);
|
|
423
414
|
} finally {
|
|
424
415
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
@@ -461,7 +452,7 @@ test("editing session-start settings does not activate the current empty session
|
|
|
461
452
|
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
462
453
|
result = value;
|
|
463
454
|
});
|
|
464
|
-
|
|
455
|
+
component.handleInput("\u001b[B");
|
|
465
456
|
component.handleInput("\r");
|
|
466
457
|
for (let index = 0; index < 3; index += 1) component.handleInput("\u001b[B");
|
|
467
458
|
component.handleInput("\r");
|
|
@@ -513,11 +504,11 @@ test("child extension activation does not deactivate the parent routing controll
|
|
|
513
504
|
try {
|
|
514
505
|
await parent.handlers.get("session_start")({ type: "session_start", reason: "startup" }, parentContext);
|
|
515
506
|
await parent.handlers.get("before_agent_start")({ prompt: "hello", systemPrompt: "base prompt" }, parentContext);
|
|
516
|
-
assert.deepEqual(parent.state, { model: { provider: "faux", id: "
|
|
507
|
+
assert.deepEqual(parent.state, { model: { provider: "faux", id: "reasoning" }, thinkingLevel: "max" });
|
|
517
508
|
|
|
518
509
|
await child.handlers.get("session_start")({ type: "session_start", reason: "startup" }, childContext);
|
|
519
510
|
|
|
520
|
-
assert.deepEqual(parent.state, { model: { provider: "faux", id: "
|
|
511
|
+
assert.deepEqual(parent.state, { model: { provider: "faux", id: "reasoning" }, thinkingLevel: "max" });
|
|
521
512
|
assert.equal(
|
|
522
513
|
parent.entries.some((entry) => entry.kind === "closing"),
|
|
523
514
|
false,
|
|
@@ -548,6 +539,7 @@ test("registered profile commands create manual holds and release them without a
|
|
|
548
539
|
const ctx = createContext(cwd, host);
|
|
549
540
|
try {
|
|
550
541
|
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
542
|
+
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
551
543
|
const command = host.commands.find(({ name }) => name === "freeflow");
|
|
552
544
|
assert.ok(command);
|
|
553
545
|
assert.deepEqual(
|
|
@@ -665,6 +657,7 @@ test("reload preserves a manual reasoning hold after lease rotation", async () =
|
|
|
665
657
|
ctx.isIdle = () => true;
|
|
666
658
|
try {
|
|
667
659
|
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
660
|
+
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
668
661
|
await host.commands.find(({ name }) => name === "freeflow").definition.handler("profile reasoning", ctx);
|
|
669
662
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "reload" }, ctx);
|
|
670
663
|
|
|
@@ -705,6 +698,7 @@ test("tree navigation retains the current profile without a supported branch cho
|
|
|
705
698
|
const ctx = createContext(cwd, host);
|
|
706
699
|
try {
|
|
707
700
|
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
701
|
+
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
708
702
|
const standardBranch = [...host.entries];
|
|
709
703
|
const command = host.commands.find(({ name }) => name === "freeflow");
|
|
710
704
|
await command.definition.handler("profile reasoning", ctx);
|
|
@@ -748,7 +742,7 @@ test("compaction reconciles without changing an active routing pair", async () =
|
|
|
748
742
|
await host.handlers.get("session_compact")({ type: "session_compact" }, ctx);
|
|
749
743
|
|
|
750
744
|
assert.deepEqual(host.operations, operationsBeforeCompaction);
|
|
751
|
-
assert.deepEqual(host.state, { model: { provider: "faux", id: "
|
|
745
|
+
assert.deepEqual(host.state, { model: { provider: "faux", id: "reasoning" }, thinkingLevel: "max" });
|
|
752
746
|
assert.ok(host.activeToolNames().includes("freeflow_switch_profile"));
|
|
753
747
|
} finally {
|
|
754
748
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
@@ -865,7 +859,7 @@ test("reload recovery stays inactive after an unmatched closing intent", async (
|
|
|
865
859
|
}
|
|
866
860
|
});
|
|
867
861
|
|
|
868
|
-
test("Pi delivers
|
|
862
|
+
test("Pi delivers stable Cognitive Routing cues and refreshes runtime state only when needed", async () => {
|
|
869
863
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-compact-delivery-"));
|
|
870
864
|
await mkdir(join(cwd, ".freeflow"));
|
|
871
865
|
await writeFile(
|
|
@@ -889,14 +883,17 @@ test("Pi delivers a compact Cognitive Routing cue and volatile state per turn",
|
|
|
889
883
|
|
|
890
884
|
assert.equal(first.message, undefined);
|
|
891
885
|
assert.match(first.systemPrompt, /## Cognitive Routing Cue/);
|
|
892
|
-
assert.match(
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
);
|
|
896
|
-
assert.match(
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
);
|
|
886
|
+
assert.match(first.systemPrompt, /each user interaction begins in Reasoning/);
|
|
887
|
+
assert.match(first.systemPrompt, /If the full Cognitive Routing skill is not visible/);
|
|
888
|
+
assert.match(first.systemPrompt, /Make that read the only environment call/);
|
|
889
|
+
assert.match(first.systemPrompt, /it is not a route transition/);
|
|
890
|
+
assert.match(first.systemPrompt, /YIELD/);
|
|
891
|
+
assert.match(first.systemPrompt, /Delegate/);
|
|
892
|
+
assert.match(first.systemPrompt, /ACT_BOUNDED/);
|
|
893
|
+
assert.match(first.systemPrompt, /Automatic Standard only executes active Yield or Delegate contracts/);
|
|
894
|
+
assert.match(first.systemPrompt, /writes `YIELD HANDOFF` or `RETURN` and switches to Reasoning/);
|
|
895
|
+
assert.match(first.systemPrompt, /Standard never handles substantive user-facing interaction/);
|
|
896
|
+
assert.doesNotMatch(first.systemPrompt, /TASK ACT|OBSERVE/);
|
|
900
897
|
assert.ok(
|
|
901
898
|
first.systemPrompt.indexOf("## Action Selection Cue") < first.systemPrompt.indexOf("## Cognitive Routing Cue"),
|
|
902
899
|
);
|
|
@@ -909,7 +906,22 @@ test("Pi delivers a compact Cognitive Routing cue and volatile state per turn",
|
|
|
909
906
|
assert.equal(firstContext.messages[0].customType, "freeflow-runtime-state");
|
|
910
907
|
assert.match(firstContext.messages[0].content, /Cognitive Routing: active/);
|
|
911
908
|
assert.match(firstContext.messages[0].content, /Control: `automatic`/);
|
|
912
|
-
assert.match(firstContext.messages[0].content, /Profile: `
|
|
909
|
+
assert.match(firstContext.messages[0].content, /Profile: `reasoning`/);
|
|
910
|
+
|
|
911
|
+
const unchangedContext = await contextHandler({ messages: firstContext.messages }, ctx);
|
|
912
|
+
assert.equal(unchangedContext, undefined);
|
|
913
|
+
|
|
914
|
+
await host.handlers.get("session_tree")({ type: "session_tree", reason: "branch" }, ctx);
|
|
915
|
+
const branchContext = await contextHandler({ messages: firstContext.messages }, ctx);
|
|
916
|
+
assert.ok(branchContext);
|
|
917
|
+
assert.equal(branchContext.messages.length, 1);
|
|
918
|
+
assert.match(branchContext.messages[0].content, /Profile: `reasoning`/);
|
|
919
|
+
|
|
920
|
+
await host.handlers.get("session_compact")({ type: "session_compact", reason: "compaction" }, ctx);
|
|
921
|
+
const compactContext = await contextHandler({ messages: branchContext.messages }, ctx);
|
|
922
|
+
assert.ok(compactContext);
|
|
923
|
+
assert.equal(compactContext.messages.length, 1);
|
|
924
|
+
assert.match(compactContext.messages[0].content, /Profile: `reasoning`/);
|
|
913
925
|
|
|
914
926
|
const second = await beforeAgentStart({ systemPrompt: "base prompt" }, ctx);
|
|
915
927
|
assert.equal(second.message, undefined);
|
|
@@ -920,6 +932,65 @@ test("Pi delivers a compact Cognitive Routing cue and volatile state per turn",
|
|
|
920
932
|
}
|
|
921
933
|
});
|
|
922
934
|
|
|
935
|
+
test("Pi preserves runtime state after a no-op profile switch", async () => {
|
|
936
|
+
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-no-op-state-"));
|
|
937
|
+
await mkdir(join(cwd, ".freeflow"));
|
|
938
|
+
await writeFile(
|
|
939
|
+
join(cwd, ".freeflow", "config.json"),
|
|
940
|
+
JSON.stringify({
|
|
941
|
+
cognitiveRouting: {
|
|
942
|
+
enabled: true,
|
|
943
|
+
profiles: {
|
|
944
|
+
standard: { provider: "faux", model: "standard", thinkingLevel: "high" },
|
|
945
|
+
reasoning: { provider: "faux", model: "reasoning", thinkingLevel: "max" },
|
|
946
|
+
},
|
|
947
|
+
},
|
|
948
|
+
}),
|
|
949
|
+
);
|
|
950
|
+
const host = createExtensionHost();
|
|
951
|
+
const ctx = createContext(cwd, host);
|
|
952
|
+
try {
|
|
953
|
+
await host.handlers.get("session_start")({ type: "session_start", reason: "startup" }, ctx);
|
|
954
|
+
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
955
|
+
|
|
956
|
+
const contextHandler = host.handlers.get("context");
|
|
957
|
+
const reasoningContext = await contextHandler({ messages: [] }, ctx);
|
|
958
|
+
const runtimeStateMessages = reasoningContext.messages.filter(
|
|
959
|
+
(message) =>
|
|
960
|
+
message.customType === "freeflow-runtime-state" ||
|
|
961
|
+
message.customType === "freeflow-cognitive-routing-runtime-state",
|
|
962
|
+
);
|
|
963
|
+
assert.equal(runtimeStateMessages.length, 1);
|
|
964
|
+
assert.equal(runtimeStateMessages[0].customType, "freeflow-runtime-state");
|
|
965
|
+
|
|
966
|
+
const switchTool = host.tools.find((tool) => tool.name === "freeflow_switch_profile");
|
|
967
|
+
const result = await switchTool.execute(
|
|
968
|
+
"call-no-op-volatile-state",
|
|
969
|
+
{ target: "reasoning", reason: "Remain on Reasoning for this check." },
|
|
970
|
+
undefined,
|
|
971
|
+
undefined,
|
|
972
|
+
ctx,
|
|
973
|
+
);
|
|
974
|
+
assert.equal(result.details.result.status, "active");
|
|
975
|
+
assert.equal(result.details.result.changed, false);
|
|
976
|
+
|
|
977
|
+
await host.handlers.get("tool_result")({ type: "tool_result", toolName: "freeflow_switch_profile" }, ctx);
|
|
978
|
+
const unchangedContext = await contextHandler({ messages: reasoningContext.messages }, ctx);
|
|
979
|
+
assert.equal(unchangedContext, undefined);
|
|
980
|
+
assert.equal(
|
|
981
|
+
reasoningContext.messages.filter(
|
|
982
|
+
(message) =>
|
|
983
|
+
message.customType === "freeflow-runtime-state" ||
|
|
984
|
+
message.customType === "freeflow-cognitive-routing-runtime-state",
|
|
985
|
+
).length,
|
|
986
|
+
1,
|
|
987
|
+
);
|
|
988
|
+
} finally {
|
|
989
|
+
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
990
|
+
await rm(cwd, { recursive: true, force: true });
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
|
|
923
994
|
test("Pi refreshes volatile Cognitive Routing state after a profile switch", async () => {
|
|
924
995
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-volatile-state-"));
|
|
925
996
|
await mkdir(join(cwd, ".freeflow"));
|
|
@@ -942,31 +1013,31 @@ test("Pi refreshes volatile Cognitive Routing state after a profile switch", asy
|
|
|
942
1013
|
await host.handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
943
1014
|
|
|
944
1015
|
const contextHandler = host.handlers.get("context");
|
|
945
|
-
const
|
|
946
|
-
assert.match(
|
|
1016
|
+
const reasoningContext = await contextHandler({ messages: [] }, ctx);
|
|
1017
|
+
assert.match(reasoningContext.messages[0].content, /Profile: `reasoning`/);
|
|
947
1018
|
|
|
948
1019
|
const switchTool = host.tools.find((tool) => tool.name === "freeflow_switch_profile");
|
|
949
1020
|
const result = await switchTool.execute(
|
|
950
1021
|
"call-volatile-state",
|
|
951
|
-
{ target: "
|
|
1022
|
+
{ target: "standard", reason: "Use Standard for bounded execution." },
|
|
952
1023
|
undefined,
|
|
953
1024
|
undefined,
|
|
954
1025
|
ctx,
|
|
955
1026
|
);
|
|
956
|
-
assert.equal(result.details.result.to, "
|
|
1027
|
+
assert.equal(result.details.result.to, "standard");
|
|
957
1028
|
|
|
958
|
-
const
|
|
959
|
-
assert.equal(
|
|
960
|
-
assert.match(
|
|
961
|
-
assert.match(
|
|
962
|
-
assert.doesNotMatch(
|
|
1029
|
+
const standardContext = await contextHandler({ messages: reasoningContext.messages }, ctx);
|
|
1030
|
+
assert.equal(standardContext.messages.length, 1);
|
|
1031
|
+
assert.match(standardContext.messages[0].content, /Control: `automatic`/);
|
|
1032
|
+
assert.match(standardContext.messages[0].content, /Profile: `standard`/);
|
|
1033
|
+
assert.doesNotMatch(standardContext.messages[0].content, /Profile: `reasoning`/);
|
|
963
1034
|
} finally {
|
|
964
1035
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
965
1036
|
await rm(cwd, { recursive: true, force: true });
|
|
966
1037
|
}
|
|
967
1038
|
});
|
|
968
1039
|
|
|
969
|
-
test("Pi
|
|
1040
|
+
test("Pi rejects the removed Skills configuration instead of gating Cognitive Routing", async () => {
|
|
970
1041
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-skills-gate-"));
|
|
971
1042
|
await mkdir(join(cwd, ".freeflow"));
|
|
972
1043
|
await writeFile(
|
|
@@ -992,8 +1063,8 @@ test("Pi keeps Cognitive Routing behind the Skills parent gate", async () => {
|
|
|
992
1063
|
assert.doesNotMatch(result.systemPrompt, /^# Cognitive Routing$/m);
|
|
993
1064
|
assert.ok(!host.activeToolNames().includes("freeflow_switch_profile"));
|
|
994
1065
|
const providerContext = await host.handlers.get("context")({ messages: [] }, ctx);
|
|
995
|
-
assert.match(providerContext.messages[0].content, /
|
|
996
|
-
assert.
|
|
1066
|
+
assert.match(providerContext.messages[0].content, /Freeflow: config error/);
|
|
1067
|
+
assert.doesNotMatch(providerContext.messages[0].content, /Skills:/);
|
|
997
1068
|
} finally {
|
|
998
1069
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
999
1070
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -1026,7 +1097,7 @@ test("Pi lifecycle prepares, activates, restores, and releases Cognitive Routing
|
|
|
1026
1097
|
ctx,
|
|
1027
1098
|
);
|
|
1028
1099
|
assert.deepEqual(host.operations.slice(0, 3), ["prepare", "acquire", "setState"]);
|
|
1029
|
-
assert.deepEqual(host.state, { model: { provider: "faux", id: "
|
|
1100
|
+
assert.deepEqual(host.state, { model: { provider: "faux", id: "reasoning" }, thinkingLevel: "max" });
|
|
1030
1101
|
assert.equal(host.entries[0].customType, "freeflow-cognitive-routing-intent");
|
|
1031
1102
|
assert.ok(host.activeToolNames().includes("freeflow_switch_profile"));
|
|
1032
1103
|
assert.match(beforeAgentStart.systemPrompt, /## Cognitive Routing Cue/);
|
|
@@ -1037,12 +1108,12 @@ test("Pi lifecycle prepares, activates, restores, and releases Cognitive Routing
|
|
|
1037
1108
|
const switchTool = host.tools.find((tool) => tool.name === "freeflow_switch_profile");
|
|
1038
1109
|
await switchTool.execute(
|
|
1039
1110
|
"call-1",
|
|
1040
|
-
{ target: "
|
|
1111
|
+
{ target: "standard", reason: "Use Standard for the bounded execution pass." },
|
|
1041
1112
|
undefined,
|
|
1042
1113
|
undefined,
|
|
1043
1114
|
ctx,
|
|
1044
1115
|
);
|
|
1045
|
-
assert.deepEqual(host.state, { model: { provider: "faux", id: "
|
|
1116
|
+
assert.deepEqual(host.state, { model: { provider: "faux", id: "standard" }, thinkingLevel: "high" });
|
|
1046
1117
|
|
|
1047
1118
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "reload" }, ctx);
|
|
1048
1119
|
|
|
@@ -1062,7 +1133,7 @@ test("Pi lifecycle prepares, activates, restores, and releases Cognitive Routing
|
|
|
1062
1133
|
|
|
1063
1134
|
await host.handlers.get("session_start")({ type: "session_start", reason: "reload" }, ctx);
|
|
1064
1135
|
assert.deepEqual(host.operations.slice(-3), ["prepare", "acquire", "setState"]);
|
|
1065
|
-
assert.deepEqual(host.state, { model: { provider: "faux", id: "
|
|
1136
|
+
assert.deepEqual(host.state, { model: { provider: "faux", id: "standard" }, thinkingLevel: "high" });
|
|
1066
1137
|
assert.ok(host.activeToolNames().includes("freeflow_switch_profile"));
|
|
1067
1138
|
await host.handlers.get("session_shutdown")({ type: "session_shutdown", reason: "test-cleanup" }, ctx);
|
|
1068
1139
|
} finally {
|