@hassangameryt/freeflow 0.7.1 → 0.7.2
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 +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +28 -23
- package/capabilities/cognitive-routing/SKILL.md +94 -311
- package/command-surface.json +7 -1
- package/gemini-extension.json +1 -1
- package/package.json +4 -4
- package/pi-extension/dist/cognitive-routing-v2/budget.js +42 -0
- package/pi-extension/dist/cognitive-routing-v2/config.js +120 -0
- package/pi-extension/dist/cognitive-routing-v2/projection.js +321 -0
- package/pi-extension/dist/cognitive-routing-v2/render.js +231 -0
- package/pi-extension/dist/cognitive-routing-v2/runtime.js +1585 -0
- package/pi-extension/dist/cognitive-routing-v2/schemas.js +107 -0
- package/pi-extension/dist/cognitive-routing-v2/state.js +612 -0
- package/pi-extension/dist/cognitive-routing-v2/tools.js +91 -0
- package/pi-extension/dist/cognitive-routing-v2/types.js +44 -0
- package/pi-extension/dist/freeflow-context/tool.js +5 -0
- package/pi-extension/dist/index.js +279 -624
- package/pi-extension/dist/runtime/runtime-context.js +63 -13
- package/pi-extension/dist/session-sources/events.js +195 -0
- package/pi-extension/dist/session-sources/read-only-session.js +148 -0
- package/pi-extension/dist/session-sources/sources.js +233 -0
- package/pi-extension/dist/settings/settings-ui.js +44 -117
- package/pi-extension/src/cognitive-routing-v2/budget.ts +42 -0
- package/pi-extension/src/cognitive-routing-v2/config.ts +143 -0
- package/pi-extension/src/cognitive-routing-v2/projection.ts +365 -0
- package/pi-extension/src/cognitive-routing-v2/render.ts +256 -0
- package/pi-extension/src/cognitive-routing-v2/runtime.ts +1634 -0
- package/pi-extension/src/cognitive-routing-v2/schemas.ts +109 -0
- package/pi-extension/src/cognitive-routing-v2/state.ts +622 -0
- package/pi-extension/src/cognitive-routing-v2/tools.ts +93 -0
- package/pi-extension/src/cognitive-routing-v2/types.ts +222 -0
- package/pi-extension/src/freeflow-context/tool.ts +5 -0
- package/pi-extension/src/index.ts +285 -674
- package/pi-extension/src/runtime/runtime-context.ts +75 -14
- package/pi-extension/src/session-sources/events.ts +208 -0
- package/pi-extension/src/session-sources/read-only-session.ts +170 -0
- package/pi-extension/src/session-sources/sources.ts +263 -0
- package/pi-extension/src/settings/settings-ui.ts +54 -131
- package/pi-extension/tests/cognitive-routing-v2/communication.test.js +484 -0
- package/pi-extension/tests/cognitive-routing-v2/compaction-input.test.js +183 -0
- package/pi-extension/tests/cognitive-routing-v2/native.test.js +441 -0
- package/pi-extension/tests/cognitive-routing-v2/performance.test.js +87 -0
- package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +245 -0
- package/pi-extension/tests/cognitive-routing-v2/projection.test.js +241 -0
- package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +236 -0
- package/pi-extension/tests/cognitive-routing-v2/render.test.js +230 -0
- package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +153 -0
- package/pi-extension/tests/cognitive-routing-v2/stabilization.test.js +521 -0
- package/pi-extension/tests/cognitive-routing-v2/state.test.js +275 -0
- package/pi-extension/tests/context-virtualization/extension.test.js +16 -0
- package/pi-extension/tests/fixtures/routing-native.js +188 -0
- package/pi-extension/tests/integration/mode-free-core.test.js +3 -2
- package/pi-extension/tests/integration/pi-extension.test.js +154 -37
- package/pi-extension/tests/integration/prompt-architecture.test.js +87 -6
- package/pi-extension/tests/integration/unaffected-regressions.test.js +77 -10
- package/plugin.json +1 -1
- package/runtime/prompts/cognitive-routing.md +4 -5
- package/runtime/prompts/core.md +51 -45
- package/runtime/prompts/interaction-contract.md +5 -5
- package/skills/action-selection/SKILL.md +57 -97
- package/skills/design-for-depth/SKILL.md +58 -193
- package/skills/design-for-depth/references/implementation-decisions.md +76 -0
- package/skills/diagnose-failure/SKILL.md +64 -196
- package/skills/discuss/SKILL.md +64 -123
- package/skills/discuss/references/discussion-continuity.md +7 -3
- package/skills/execute-work/SKILL.md +69 -88
- package/skills/execute-work/references/execute-work-edges.md +9 -3
- package/skills/handoff/SKILL.md +44 -54
- package/skills/handoff/references/handoff-templates.md +15 -6
- package/skills/review-artifact/SKILL.md +80 -127
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +1 -1
- package/skills/review-work/SKILL.md +65 -115
- package/skills/review-work/references/independent-work-reviewer-contract.md +1 -1
- package/skills/simplify-code/SKILL.md +47 -100
- package/skills/track-work/SKILL.md +128 -119
- package/skills/track-work/references/working-record-format.md +14 -2
- package/skills/verify-work/SKILL.md +58 -62
- package/skills/verify-work/references/integration-evidence.md +4 -2
- package/skills/verify-work/references/test-design.md +89 -0
- package/skills/workflow/SKILL.md +73 -119
- package/skills/write-plan/SKILL.md +46 -77
- package/skills/write-plan/references/plan-shapes.md +5 -5
- package/skills/write-spec/SKILL.md +51 -63
- package/skills/write-spec/references/artifact-standards.md +2 -2
- package/skills/write-spec/references/decision-records.md +3 -2
- package/skills/write-spec/references/spec-shapes.md +15 -0
- package/pi-extension/dist/cognitive-routing/commands.js +0 -96
- package/pi-extension/dist/cognitive-routing/config.js +0 -232
- package/pi-extension/dist/cognitive-routing/controller.js +0 -1292
- package/pi-extension/dist/cognitive-routing/history.js +0 -451
- package/pi-extension/dist/cognitive-routing/host.js +0 -188
- package/pi-extension/dist/cognitive-routing/pi-routing-session.js +0 -414
- package/pi-extension/dist/cognitive-routing/pi-session-control.js +0 -320
- package/pi-extension/dist/cognitive-routing/runtime.js +0 -43
- package/pi-extension/dist/cognitive-routing/tool.js +0 -212
- package/pi-extension/dist/cognitive-routing/types.js +0 -6
- package/pi-extension/src/cognitive-routing/commands.ts +0 -129
- package/pi-extension/src/cognitive-routing/config.ts +0 -303
- package/pi-extension/src/cognitive-routing/controller.ts +0 -1628
- package/pi-extension/src/cognitive-routing/history.ts +0 -650
- package/pi-extension/src/cognitive-routing/host.ts +0 -266
- package/pi-extension/src/cognitive-routing/pi-routing-session.ts +0 -538
- package/pi-extension/src/cognitive-routing/pi-session-control.ts +0 -444
- package/pi-extension/src/cognitive-routing/runtime.ts +0 -57
- package/pi-extension/src/cognitive-routing/tool.ts +0 -273
- package/pi-extension/src/cognitive-routing/types.ts +0 -89
- package/pi-extension/tests/cognitive-routing/commands.test.js +0 -134
- package/pi-extension/tests/cognitive-routing/controller.test.js +0 -1128
- package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +0 -1142
- package/pi-extension/tests/cognitive-routing/history.test.js +0 -274
- package/pi-extension/tests/cognitive-routing/host-identity.test.js +0 -63
- package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +0 -434
- package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +0 -174
- package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +0 -91
- package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +0 -279
- package/pi-extension/tests/cognitive-routing/tool.test.js +0 -230
- package/skills/tdd/SKILL.md +0 -143
- package/skills/tdd/references/test-design.md +0 -96
- /package/pi-extension/tests/{cognitive-routing/host-fixture.js → fixtures/pi-host.js} +0 -0
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import { resolveCognitiveRoutingConfig } from "../../dist/cognitive-routing/config.js";
|
|
7
|
-
import { resolveCognitiveRoutingState } from "../../dist/cognitive-routing/runtime.js";
|
|
8
|
-
import { readCapabilityState } from "../../dist/runtime/runtime-context.js";
|
|
9
|
-
import { PIFLOW_HOST } from "./host-fixture.js";
|
|
10
|
-
|
|
11
|
-
const standard = {
|
|
12
|
-
provider: "openai-codex",
|
|
13
|
-
model: "gpt-5.6-luna",
|
|
14
|
-
thinkingLevel: "high",
|
|
15
|
-
};
|
|
16
|
-
const reasoning = {
|
|
17
|
-
provider: "openai-codex",
|
|
18
|
-
model: "gpt-5.6-sol",
|
|
19
|
-
thinkingLevel: "max",
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
function configuredRepository(overrides = {}) {
|
|
23
|
-
return {
|
|
24
|
-
cognitiveRouting: {
|
|
25
|
-
enabled: true,
|
|
26
|
-
profiles: { standard, reasoning },
|
|
27
|
-
...overrides,
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function createHost({ models = [], unauthenticated = [], clamps = {} } = {}) {
|
|
33
|
-
const modelMap = new Map(models.map((model) => [`${model.provider}/${model.id}`, model]));
|
|
34
|
-
const unauthenticatedSet = new Set(unauthenticated);
|
|
35
|
-
return {
|
|
36
|
-
modelRegistry: {
|
|
37
|
-
find(provider, modelId) {
|
|
38
|
-
return modelMap.get(`${provider}/${modelId}`);
|
|
39
|
-
},
|
|
40
|
-
async getApiKeyAndHeaders(model) {
|
|
41
|
-
return unauthenticatedSet.has(model.provider) ? { ok: false, error: "missing credentials" } : { ok: true };
|
|
42
|
-
},
|
|
43
|
-
clampThinkingLevel(model, level) {
|
|
44
|
-
return clamps[`${model.provider}/${model.id}`]?.[level] ?? level;
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const standardModel = { provider: standard.provider, id: standard.model };
|
|
51
|
-
const reasoningModel = { provider: reasoning.provider, id: reasoning.model };
|
|
52
|
-
|
|
53
|
-
test("resolves two complete repository profiles", () => {
|
|
54
|
-
const result = resolveCognitiveRoutingConfig(configuredRepository(), {});
|
|
55
|
-
|
|
56
|
-
assert.equal(result.valid, true);
|
|
57
|
-
assert.equal(result.enabled, true);
|
|
58
|
-
assert.equal(result.enabledSource, "repository");
|
|
59
|
-
assert.deepEqual(result.profiles, { standard, reasoning });
|
|
60
|
-
assert.deepEqual(result.profileSources, { standard: "repository", reasoning: "repository" });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("defaults new-session Cognitive Routing to automatic Reasoning control", () => {
|
|
64
|
-
const result = resolveCognitiveRoutingConfig(configuredRepository(), {});
|
|
65
|
-
|
|
66
|
-
assert.deepEqual(result.sessionStart, { control: "automatic", profile: "reasoning" });
|
|
67
|
-
assert.deepEqual(result.sessionStartSources, { control: "default", profile: "default" });
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("canonicalizes automatic session starts to Reasoning", () => {
|
|
71
|
-
const result = resolveCognitiveRoutingConfig(
|
|
72
|
-
configuredRepository({ sessionStart: { control: "automatic", profile: "standard" } }),
|
|
73
|
-
{},
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
assert.deepEqual(result.sessionStart, { control: "automatic", profile: "reasoning" });
|
|
77
|
-
assert.deepEqual(result.sessionStartSources, { control: "repository", profile: "default" });
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("layers session-start control and profile independently", () => {
|
|
81
|
-
const result = resolveCognitiveRoutingConfig(
|
|
82
|
-
configuredRepository({ sessionStart: { control: "automatic", profile: "standard" } }),
|
|
83
|
-
{ cognitiveRouting: { sessionStart: { control: "manual", profile: "reasoning" } } },
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
assert.deepEqual(result.sessionStart, { control: "manual", profile: "reasoning" });
|
|
87
|
-
assert.deepEqual(result.sessionStartSources, { control: "personal", profile: "personal" });
|
|
88
|
-
|
|
89
|
-
const inheritedProfile = resolveCognitiveRoutingConfig(
|
|
90
|
-
configuredRepository({ sessionStart: { control: "manual" } }),
|
|
91
|
-
{ cognitiveRouting: { sessionStart: { profile: "reasoning" } } },
|
|
92
|
-
);
|
|
93
|
-
assert.deepEqual(inheritedProfile.sessionStart, { control: "manual", profile: "reasoning" });
|
|
94
|
-
assert.deepEqual(inheritedProfile.sessionStartSources, { control: "repository", profile: "personal" });
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test("replaces a profile atomically from the personal layer", () => {
|
|
98
|
-
const personalStandard = {
|
|
99
|
-
provider: "openai-codex",
|
|
100
|
-
model: "gpt-5.6-luna-personal",
|
|
101
|
-
thinkingLevel: "medium",
|
|
102
|
-
};
|
|
103
|
-
const result = resolveCognitiveRoutingConfig(configuredRepository(), {
|
|
104
|
-
cognitiveRouting: { profiles: { standard: personalStandard } },
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
assert.equal(result.valid, true);
|
|
108
|
-
assert.deepEqual(result.profiles.standard, personalStandard);
|
|
109
|
-
assert.deepEqual(result.profiles.reasoning, reasoning);
|
|
110
|
-
assert.deepEqual(result.profileSources, { standard: "personal", reasoning: "repository" });
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("rejects a partial personal profile instead of merging fields", () => {
|
|
114
|
-
const result = resolveCognitiveRoutingConfig(configuredRepository(), {
|
|
115
|
-
cognitiveRouting: { profiles: { standard: { model: "personal-only" } } },
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
assert.equal(result.valid, false);
|
|
119
|
-
assert.equal(result.error.code, "invalid_profile");
|
|
120
|
-
assert.equal(result.error.profile, "standard");
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test("keeps Cognitive Routing disabled by default without a config block", async () => {
|
|
124
|
-
const result = await resolveCognitiveRoutingState({}, {}, createHost({ models: [standardModel, reasoningModel] }));
|
|
125
|
-
|
|
126
|
-
assert.equal(result.configured, false);
|
|
127
|
-
assert.equal(result.enabled, false);
|
|
128
|
-
assert.equal(result.effective, false);
|
|
129
|
-
assert.equal(result.blockingReason.code, "disabled");
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test("fails only Cognitive Routing closed when its config is invalid", async () => {
|
|
133
|
-
const result = await resolveCognitiveRoutingState(
|
|
134
|
-
{ cognitiveRouting: { enabled: true, profiles: { standard: { provider: "only-provider" } } } },
|
|
135
|
-
{},
|
|
136
|
-
createHost({ models: [standardModel, reasoningModel] }),
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
assert.equal(result.configured, true);
|
|
140
|
-
assert.equal(result.configValid, false);
|
|
141
|
-
assert.equal(result.effective, false);
|
|
142
|
-
assert.equal(result.blockingReason.code, "config_invalid");
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("reports an unsupported host without weakening core capability state", async () => {
|
|
146
|
-
const result = await resolveCognitiveRoutingState(configuredRepository(), {}, undefined);
|
|
147
|
-
|
|
148
|
-
assert.equal(result.enabled, true);
|
|
149
|
-
assert.equal(result.effective, false);
|
|
150
|
-
assert.equal(result.blockingReason.code, "host_unsupported");
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("preflights exact identities, authentication, and effective thinking levels", async () => {
|
|
154
|
-
const host = createHost({
|
|
155
|
-
models: [standardModel, reasoningModel],
|
|
156
|
-
clamps: { "openai-codex/gpt-5.6-luna": { high: "high" }, "openai-codex/gpt-5.6-sol": { max: "max" } },
|
|
157
|
-
});
|
|
158
|
-
const result = await resolveCognitiveRoutingState(configuredRepository(), {}, host);
|
|
159
|
-
|
|
160
|
-
assert.equal(result.effective, true);
|
|
161
|
-
assert.deepEqual(result.resolvedProfiles.standard, {
|
|
162
|
-
...standard,
|
|
163
|
-
effectiveThinkingLevel: "high",
|
|
164
|
-
});
|
|
165
|
-
assert.deepEqual(result.resolvedProfiles.reasoning, {
|
|
166
|
-
...reasoning,
|
|
167
|
-
effectiveThinkingLevel: "max",
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test("normal Pi preflight resolves thinking levels from model metadata without a registry clamp", async () => {
|
|
172
|
-
const models = [
|
|
173
|
-
{
|
|
174
|
-
provider: standard.provider,
|
|
175
|
-
id: standard.model,
|
|
176
|
-
reasoning: true,
|
|
177
|
-
thinkingLevelMap: { xhigh: "xhigh", max: "max" },
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
provider: reasoning.provider,
|
|
181
|
-
id: reasoning.model,
|
|
182
|
-
reasoning: true,
|
|
183
|
-
thinkingLevelMap: { xhigh: "xhigh", max: "max" },
|
|
184
|
-
},
|
|
185
|
-
];
|
|
186
|
-
const modelMap = new Map(models.map((model) => [`${model.provider}/${model.id}`, model]));
|
|
187
|
-
const host = {
|
|
188
|
-
modelRegistry: {
|
|
189
|
-
find(provider, modelId) {
|
|
190
|
-
return modelMap.get(`${provider}/${modelId}`);
|
|
191
|
-
},
|
|
192
|
-
async getApiKeyAndHeaders() {
|
|
193
|
-
return { ok: true };
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
const result = await resolveCognitiveRoutingState(configuredRepository(), {}, host);
|
|
199
|
-
|
|
200
|
-
assert.equal(result.effective, true);
|
|
201
|
-
assert.equal(result.resolvedProfiles.standard.effectiveThinkingLevel, "high");
|
|
202
|
-
assert.equal(result.resolvedProfiles.reasoning.effectiveThinkingLevel, "max");
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test("runtime context isolates invalid Cognitive Routing from core Freeflow state", async () => {
|
|
206
|
-
const cwd = await mkdtemp(join(tmpdir(), "freeflow-cognitive-routing-"));
|
|
207
|
-
await mkdir(join(cwd, ".freeflow"));
|
|
208
|
-
const host = createHost({ models: [standardModel, reasoningModel] });
|
|
209
|
-
try {
|
|
210
|
-
await writeFile(
|
|
211
|
-
join(cwd, ".freeflow", "config.json"),
|
|
212
|
-
JSON.stringify({ cognitiveRouting: configuredRepository().cognitiveRouting }),
|
|
213
|
-
);
|
|
214
|
-
let state = await readCapabilityState(cwd, host, PIFLOW_HOST);
|
|
215
|
-
assert.equal(state.configured, true);
|
|
216
|
-
assert.equal(state.enabled, true);
|
|
217
|
-
assert.equal(state.cognitiveRouting.effective, true);
|
|
218
|
-
|
|
219
|
-
await writeFile(
|
|
220
|
-
join(cwd, ".freeflow", "config.json"),
|
|
221
|
-
JSON.stringify({ enabled: false, cognitiveRouting: configuredRepository().cognitiveRouting }),
|
|
222
|
-
);
|
|
223
|
-
state = await readCapabilityState(cwd, host, PIFLOW_HOST);
|
|
224
|
-
assert.equal(state.enabled, false);
|
|
225
|
-
assert.equal(state.cognitiveRouting.enabled, false);
|
|
226
|
-
assert.equal(state.cognitiveRouting.effective, false);
|
|
227
|
-
assert.equal(state.cognitiveRouting.blockingReason.code, "disabled");
|
|
228
|
-
|
|
229
|
-
await writeFile(
|
|
230
|
-
join(cwd, ".freeflow", "config.json"),
|
|
231
|
-
JSON.stringify({
|
|
232
|
-
cognitiveRouting: { enabled: true, profiles: { standard: { provider: "only-provider" } } },
|
|
233
|
-
}),
|
|
234
|
-
);
|
|
235
|
-
state = await readCapabilityState(cwd, host, PIFLOW_HOST);
|
|
236
|
-
assert.equal(state.configured, true);
|
|
237
|
-
assert.equal(state.enabled, true);
|
|
238
|
-
assert.equal(state.cognitiveRouting.configValid, false);
|
|
239
|
-
assert.equal(state.cognitiveRouting.effective, false);
|
|
240
|
-
} finally {
|
|
241
|
-
await rm(cwd, { recursive: true, force: true });
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test("rejects unavailable, unauthenticated, weakened, and identical profile pairs", async () => {
|
|
246
|
-
const unavailable = await resolveCognitiveRoutingState(
|
|
247
|
-
configuredRepository(),
|
|
248
|
-
{},
|
|
249
|
-
createHost({ models: [standardModel] }),
|
|
250
|
-
);
|
|
251
|
-
assert.equal(unavailable.blockingReason.code, "profile_unavailable");
|
|
252
|
-
assert.equal(unavailable.blockingReason.profile, "reasoning");
|
|
253
|
-
|
|
254
|
-
const unauthenticated = await resolveCognitiveRoutingState(
|
|
255
|
-
configuredRepository(),
|
|
256
|
-
{},
|
|
257
|
-
createHost({ models: [standardModel, reasoningModel], unauthenticated: ["openai-codex"] }),
|
|
258
|
-
);
|
|
259
|
-
assert.equal(unauthenticated.blockingReason.code, "profile_unauthenticated");
|
|
260
|
-
assert.equal(unauthenticated.blockingReason.profile, "standard");
|
|
261
|
-
|
|
262
|
-
const weakened = await resolveCognitiveRoutingState(
|
|
263
|
-
configuredRepository(),
|
|
264
|
-
{},
|
|
265
|
-
createHost({
|
|
266
|
-
models: [standardModel, reasoningModel],
|
|
267
|
-
clamps: { "openai-codex/gpt-5.6-luna": { high: "medium" } },
|
|
268
|
-
}),
|
|
269
|
-
);
|
|
270
|
-
assert.equal(weakened.blockingReason.code, "profile_clamped");
|
|
271
|
-
assert.equal(weakened.blockingReason.profile, "standard");
|
|
272
|
-
|
|
273
|
-
const identical = await resolveCognitiveRoutingState(
|
|
274
|
-
configuredRepository({ profiles: { standard, reasoning: { ...standard } } }),
|
|
275
|
-
{},
|
|
276
|
-
createHost({ models: [standardModel] }),
|
|
277
|
-
);
|
|
278
|
-
assert.equal(identical.blockingReason.code, "profiles_identical");
|
|
279
|
-
});
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import {
|
|
4
|
-
COGNITIVE_ROUTING_HISTORY_TOOL_NAME,
|
|
5
|
-
COGNITIVE_ROUTING_SWITCH_TOOL_NAME,
|
|
6
|
-
registerCognitiveRoutingHistoryTool,
|
|
7
|
-
registerCognitiveRoutingTool,
|
|
8
|
-
} from "../../dist/cognitive-routing/tool.js";
|
|
9
|
-
|
|
10
|
-
function register(getController) {
|
|
11
|
-
let tool;
|
|
12
|
-
registerCognitiveRoutingTool(
|
|
13
|
-
{
|
|
14
|
-
registerTool(candidate) {
|
|
15
|
-
tool = candidate;
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
getController,
|
|
19
|
-
);
|
|
20
|
-
return tool;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function registerHistory(getHistory) {
|
|
24
|
-
let tool;
|
|
25
|
-
registerCognitiveRoutingHistoryTool(
|
|
26
|
-
{
|
|
27
|
-
registerTool(candidate) {
|
|
28
|
-
tool = candidate;
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
getHistory,
|
|
32
|
-
);
|
|
33
|
-
return tool;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
test("exposes exactly the bounded profile switch schema", () => {
|
|
37
|
-
const tool = register(() => undefined);
|
|
38
|
-
|
|
39
|
-
assert.equal(tool.name, COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
|
|
40
|
-
assert.deepEqual(tool.parameters.required, ["target", "reason"]);
|
|
41
|
-
assert.deepEqual(tool.parameters.properties.target.enum, ["standard", "reasoning"]);
|
|
42
|
-
assert.equal(tool.parameters.properties.reason.maxLength, 160);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("validates reason before any controller call", async () => {
|
|
46
|
-
const tool = register(() => undefined);
|
|
47
|
-
|
|
48
|
-
const result = await tool.execute(
|
|
49
|
-
"call-1",
|
|
50
|
-
{ target: "reasoning", reason: "line one\nline two" },
|
|
51
|
-
undefined,
|
|
52
|
-
undefined,
|
|
53
|
-
{},
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
assert.deepEqual(result.details.result, { status: "blocked", reason: "reason_must_be_single_line" });
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("blocks stale or manually held execution without host mutation", async () => {
|
|
60
|
-
let calls = 0;
|
|
61
|
-
const controller = {
|
|
62
|
-
state() {
|
|
63
|
-
return { effective: true, controlMode: "manual-reasoning" };
|
|
64
|
-
},
|
|
65
|
-
async switchAutomaticProfile() {
|
|
66
|
-
calls += 1;
|
|
67
|
-
return { status: "active", profile: "standard" };
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
const tool = register(() => controller);
|
|
71
|
-
|
|
72
|
-
const result = await tool.execute(
|
|
73
|
-
"call-2",
|
|
74
|
-
{ target: "standard", reason: "Need a simpler pass." },
|
|
75
|
-
undefined,
|
|
76
|
-
undefined,
|
|
77
|
-
{},
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
assert.deepEqual(result.details.result, { status: "blocked", reason: "manual_hold" });
|
|
81
|
-
assert.equal(calls, 0);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test("renders no-op results as already active", () => {
|
|
85
|
-
const tool = register(() => undefined);
|
|
86
|
-
const theme = {
|
|
87
|
-
fg(_color, text) {
|
|
88
|
-
return text;
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
assert.equal(
|
|
93
|
-
tool
|
|
94
|
-
.renderResult(
|
|
95
|
-
{
|
|
96
|
-
details: {
|
|
97
|
-
result: {
|
|
98
|
-
status: "active",
|
|
99
|
-
changed: false,
|
|
100
|
-
from: "reasoning",
|
|
101
|
-
to: "reasoning",
|
|
102
|
-
profile: "reasoning",
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
{},
|
|
107
|
-
theme,
|
|
108
|
-
)
|
|
109
|
-
.render(120)
|
|
110
|
-
.join("\n"),
|
|
111
|
-
"Cognitive Routing: reasoning (already active)",
|
|
112
|
-
);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("recovers a structured result from model-visible tool text", () => {
|
|
116
|
-
const tool = register(() => undefined);
|
|
117
|
-
const theme = {
|
|
118
|
-
fg(_color, text) {
|
|
119
|
-
return text;
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
assert.equal(
|
|
124
|
-
tool
|
|
125
|
-
.renderResult(
|
|
126
|
-
{ content: [{ type: "text", text: "freeflow_switch_profile|active\\nprofile|reasoning" }], isError: false },
|
|
127
|
-
{},
|
|
128
|
-
theme,
|
|
129
|
-
)
|
|
130
|
-
.render(120)
|
|
131
|
-
.join("\n"),
|
|
132
|
-
"Cognitive Routing: active · reasoning",
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test("hides the duplicate pending line without reading mutable controller state", () => {
|
|
137
|
-
const tool = register(() => {
|
|
138
|
-
throw new Error("renderCall must not read live profile state");
|
|
139
|
-
});
|
|
140
|
-
const theme = {
|
|
141
|
-
fg(_color, text) {
|
|
142
|
-
return text;
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
assert.deepEqual(tool.renderCall({ target: "reasoning" }, theme).render(120), []);
|
|
147
|
-
assert.equal(
|
|
148
|
-
tool
|
|
149
|
-
.renderResult(
|
|
150
|
-
{
|
|
151
|
-
details: {
|
|
152
|
-
result: {
|
|
153
|
-
status: "active",
|
|
154
|
-
changed: true,
|
|
155
|
-
from: "standard",
|
|
156
|
-
to: "reasoning",
|
|
157
|
-
profile: "reasoning",
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
{},
|
|
162
|
-
theme,
|
|
163
|
-
)
|
|
164
|
-
.render(120)
|
|
165
|
-
.join("\n"),
|
|
166
|
-
"Cognitive Routing: standard → reasoning",
|
|
167
|
-
);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
test("exposes the read-only Cognitive Routing history tool contract", async () => {
|
|
171
|
-
const calls = [];
|
|
172
|
-
const resultValue = {
|
|
173
|
-
current: { control: "automatic", profile: "reasoning" },
|
|
174
|
-
summary: { latestSemanticEventId: "intent-1", unresolvedCount: 0, anomalyCount: 0 },
|
|
175
|
-
events: [],
|
|
176
|
-
};
|
|
177
|
-
const tool = registerHistory((options) => {
|
|
178
|
-
calls.push(options);
|
|
179
|
-
return resultValue;
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
assert.equal(tool.name, COGNITIVE_ROUTING_HISTORY_TOOL_NAME);
|
|
183
|
-
assert.deepEqual(tool.parameters.required, []);
|
|
184
|
-
assert.deepEqual(tool.parameters.properties.scope.enum, ["session", "active-branch"]);
|
|
185
|
-
assert.equal(tool.parameters.properties.limit.minimum, 1);
|
|
186
|
-
|
|
187
|
-
const result = await tool.execute(
|
|
188
|
-
"history-1",
|
|
189
|
-
{ scope: "active-branch", anomaliesOnly: true, limit: 7 },
|
|
190
|
-
undefined,
|
|
191
|
-
undefined,
|
|
192
|
-
{},
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
assert.deepEqual(calls, [{ scope: "active-branch", anomaliesOnly: true, limit: 7 }]);
|
|
196
|
-
assert.deepEqual(result.details.result, resultValue);
|
|
197
|
-
assert.match(result.content[0].text, /Cognitive Routing history/);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test("routes a valid automatic request through the controller", async () => {
|
|
201
|
-
const calls = [];
|
|
202
|
-
const controller = {
|
|
203
|
-
state() {
|
|
204
|
-
return { effective: true, controlMode: "automatic" };
|
|
205
|
-
},
|
|
206
|
-
async switchAutomaticProfile(target, reason) {
|
|
207
|
-
calls.push([target, reason]);
|
|
208
|
-
return { status: "active", changed: true, from: "standard", to: target, profile: target };
|
|
209
|
-
},
|
|
210
|
-
};
|
|
211
|
-
const tool = register(() => controller);
|
|
212
|
-
|
|
213
|
-
const result = await tool.execute(
|
|
214
|
-
"call-3",
|
|
215
|
-
{ target: "reasoning", reason: "Need a deeper analysis. " },
|
|
216
|
-
undefined,
|
|
217
|
-
undefined,
|
|
218
|
-
{},
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
assert.deepEqual(calls, [["reasoning", "Need a deeper analysis."]]);
|
|
222
|
-
assert.deepEqual(result.details.result, {
|
|
223
|
-
status: "active",
|
|
224
|
-
changed: true,
|
|
225
|
-
from: "standard",
|
|
226
|
-
to: "reasoning",
|
|
227
|
-
profile: "reasoning",
|
|
228
|
-
});
|
|
229
|
-
assert.match(result.content[0].text, /profile\|reasoning/);
|
|
230
|
-
});
|
package/skills/tdd/SKILL.md
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: tdd
|
|
3
|
-
description: Use when implementing or changing settled behavior test-first, reproducing a bug through regression evidence, or protecting existing behavior before a refactor.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Test-Driven Development
|
|
7
|
-
|
|
8
|
-
Use one observed failing behavior check to guide the smallest complete implementation for one settled behavior.
|
|
9
|
-
|
|
10
|
-
TDD provides test-first behavior discipline. It does not define intended behavior, authorize test or production effects, select or close a Slice, or prove claims beyond its observing boundary.
|
|
11
|
-
|
|
12
|
-
One behavior loop is one coherent method result. It may contain several reads, edits, commands, and focused checks. Finish and return one behavior before starting another.
|
|
13
|
-
|
|
14
|
-
## Enter With Settled Behavior
|
|
15
|
-
|
|
16
|
-
Before RED, establish:
|
|
17
|
-
|
|
18
|
-
- the accepted behavior and caller-visible result;
|
|
19
|
-
- relevant success and failure semantics;
|
|
20
|
-
- the boundary where the behavior must hold;
|
|
21
|
-
- authority covering both the check and production effects;
|
|
22
|
-
- the expected reason RED should fail.
|
|
23
|
-
|
|
24
|
-
Return unsettled behavior, source conflicts, or user-owned choices to [Workflow](../workflow/SKILL.md). Do not encode a guess as a test.
|
|
25
|
-
|
|
26
|
-
Use TDD for:
|
|
27
|
-
|
|
28
|
-
- accepted behavior changes;
|
|
29
|
-
- bug corrections with a supported cause or reliable regression loop;
|
|
30
|
-
- consequential logic whose contract benefits from executable evidence;
|
|
31
|
-
- characterization needed before a protected refactor.
|
|
32
|
-
|
|
33
|
-
Do not force TDD onto documentation, static content, formatting, generated output, or a disposable prototype that is not selected production behavior.
|
|
34
|
-
|
|
35
|
-
When a bug lacks a supported cause or reliable reproduction, use [Diagnose Failure](../diagnose-failure/SKILL.md) before selecting a production correction.
|
|
36
|
-
|
|
37
|
-
## Design The Behavior Check
|
|
38
|
-
|
|
39
|
-
Before designing or materially changing the check, read [Test Design](references/test-design.md).
|
|
40
|
-
|
|
41
|
-
Name:
|
|
42
|
-
|
|
43
|
-
- the behavior concept;
|
|
44
|
-
- the stable caller-visible seam;
|
|
45
|
-
- an oracle independent from the implementation;
|
|
46
|
-
- the expected missing behavior RED should expose;
|
|
47
|
-
- the focused and affected boundaries that must be rerun after GREEN.
|
|
48
|
-
|
|
49
|
-
Use the smallest test environment that still exercises the real behavior and relevant failure path. Do not choose a smaller boundary that mocks away the claim or a larger one that adds noise without proving more.
|
|
50
|
-
|
|
51
|
-
Keep one behavior concept per loop. Several assertions are appropriate when they jointly describe one outcome.
|
|
52
|
-
|
|
53
|
-
## Follow The Behavior Loop
|
|
54
|
-
|
|
55
|
-
```text
|
|
56
|
-
[Settled accepted behavior]
|
|
57
|
-
-> [Choose stable seam and independent oracle]
|
|
58
|
-
-> [RED: write and run the smallest behavior check]
|
|
59
|
-
-> fails for the intended missing behavior -> GREEN
|
|
60
|
-
-> passes immediately -> inspect test, boundary, and existing behavior
|
|
61
|
-
-> errors or fails elsewhere -> correct the harness or diagnose
|
|
62
|
-
-> [GREEN: implement the smallest complete behavior]
|
|
63
|
-
-> [Run the focused behavior check]
|
|
64
|
-
-> [REFACTOR locally when useful]
|
|
65
|
-
-> [Rerun the original path and affected boundary]
|
|
66
|
-
-> [Return the method result and evidence]
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Do not write all tests first and implementation later. Finish one behavior loop before another.
|
|
70
|
-
|
|
71
|
-
## Observe Valid RED
|
|
72
|
-
|
|
73
|
-
Run RED before changing production behavior.
|
|
74
|
-
|
|
75
|
-
RED is valid only when:
|
|
76
|
-
|
|
77
|
-
- the check executes through the intended seam;
|
|
78
|
-
- its assertion represents accepted behavior;
|
|
79
|
-
- it fails because the behavior is missing or incorrect;
|
|
80
|
-
- unrelated syntax, setup, environment, or fixture failures do not explain it.
|
|
81
|
-
|
|
82
|
-
If the check passes immediately, inspect whether:
|
|
83
|
-
|
|
84
|
-
- the behavior already exists;
|
|
85
|
-
- the assertion is ineffective;
|
|
86
|
-
- the observing boundary is wrong;
|
|
87
|
-
- the test is reproducing a nearby path rather than the reported behavior.
|
|
88
|
-
|
|
89
|
-
Do not proceed automatically to GREEN.
|
|
90
|
-
|
|
91
|
-
Correct a clear local harness defect. When the failure remains unexplained or repeated harness changes do not establish valid RED, return to Diagnose Failure.
|
|
92
|
-
|
|
93
|
-
## Implement Complete GREEN
|
|
94
|
-
|
|
95
|
-
Before changing production code, read [Code Practices](../execute-work/references/code-practices.md).
|
|
96
|
-
|
|
97
|
-
Implement the smallest complete behavior that satisfies the accepted contract—not merely the visible assertion.
|
|
98
|
-
|
|
99
|
-
Do not:
|
|
100
|
-
|
|
101
|
-
- weaken or rewrite a valid test to obtain GREEN;
|
|
102
|
-
- calculate expected values through production logic;
|
|
103
|
-
- add public hooks, states, flags, or branches used only by tests;
|
|
104
|
-
- silently invent fallback, retry, recovery, or edge-case behavior;
|
|
105
|
-
- broaden implementation into another accepted behavior.
|
|
106
|
-
|
|
107
|
-
If GREEN requires an unsettled behavior, public contract, subsystem, or material scope expansion, return the evidence to Workflow.
|
|
108
|
-
|
|
109
|
-
## Refactor Locally
|
|
110
|
-
|
|
111
|
-
Refactor only when it improves the behavior just implemented while its focused check remains green.
|
|
112
|
-
|
|
113
|
-
TDD refactoring is immediate local cleanup within the behavior loop. It may improve names, remove nearby duplication, simplify control flow, or clarify ownership without changing the accepted result.
|
|
114
|
-
|
|
115
|
-
Do not turn REFACTOR into a general cleanup stream. When reducing existing complexity is itself an accepted result, return the completed behavior loop and use [Simplify Code](../simplify-code/SKILL.md) as a separate execution route.
|
|
116
|
-
|
|
117
|
-
When test pressure exposes caller coordination, public states, test-only seams, or ownership problems, preserve that evidence. Use [Design for Depth](../design-for-depth/SKILL.md) only when structural pressure is supported.
|
|
118
|
-
|
|
119
|
-
## Fix Bugs Through The Reported Boundary
|
|
120
|
-
|
|
121
|
-
First reproduce the reported symptom through the correct seam. A nearby failing path is diagnostic evidence, not the bug.
|
|
122
|
-
|
|
123
|
-
After GREEN, rerun:
|
|
124
|
-
|
|
125
|
-
1. the minimized regression check;
|
|
126
|
-
2. the original unminimized symptom or strongest available observer;
|
|
127
|
-
3. the smallest affected boundary capable of exposing regression.
|
|
128
|
-
|
|
129
|
-
Do not report a fix when only the minimized check passes and the reported boundary remains unavailable.
|
|
130
|
-
|
|
131
|
-
## Return The Method Result
|
|
132
|
-
|
|
133
|
-
Return to the current owner with:
|
|
134
|
-
|
|
135
|
-
- accepted behavior and observing seam;
|
|
136
|
-
- observed RED result and why it was valid;
|
|
137
|
-
- GREEN implementation result;
|
|
138
|
-
- local refactor, when performed;
|
|
139
|
-
- focused, original-path, and affected-boundary evidence;
|
|
140
|
-
- what the evidence supports and does not support;
|
|
141
|
-
- unresolved or unverified behavior.
|
|
142
|
-
|
|
143
|
-
Do not select another behavior, close the Slice, trigger review, commit, or continue merely because GREEN was reached.
|