@hassangameryt/freeflow 0.6.0 → 0.7.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -5
- package/README.md +39 -55
- package/capabilities/cognitive-routing/SKILL.md +288 -130
- package/command-surface.json +0 -24
- package/hooks/freeflow-runtime-context.mjs +42 -477
- package/hooks/hooks.json +1 -26
- package/hooks/tests/check-runtime-context-hook.sh +108 -319
- package/package.json +4 -2
- 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/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
|
@@ -4,15 +4,12 @@ import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
handleModeCommand,
|
|
8
7
|
readCapabilityState,
|
|
9
8
|
readFreeflowConfig,
|
|
10
9
|
readFreeflowConfigLayers,
|
|
11
10
|
readFreeflowLocalConfig,
|
|
12
|
-
readModeState,
|
|
13
11
|
resetSessionOverrides,
|
|
14
12
|
setSessionCoreOverride,
|
|
15
|
-
VALID_MODES,
|
|
16
13
|
} from "../runtime/runtime-context.js";
|
|
17
14
|
import {
|
|
18
15
|
PiSettingsComponent,
|
|
@@ -22,6 +19,7 @@ import {
|
|
|
22
19
|
type SettingsWizard,
|
|
23
20
|
type SettingsWizardStep,
|
|
24
21
|
} from "./settings-tui.js";
|
|
22
|
+
import { supportsPiSessionModelStateApi } from "../cognitive-routing/pi-session-control.js";
|
|
25
23
|
import { isPiFlowHost } from "../runtime/runtime-identity.js";
|
|
26
24
|
import type {
|
|
27
25
|
CognitiveRoutingCapabilityState,
|
|
@@ -31,22 +29,8 @@ import type {
|
|
|
31
29
|
} from "../cognitive-routing/types.js";
|
|
32
30
|
|
|
33
31
|
const DEFAULT_FREEFLOW_ENABLED = true;
|
|
34
|
-
const DEFAULT_INTERACTION_CONTRACT_ENABLED = true;
|
|
35
|
-
const DEFAULT_SKILLS_ENABLED = true;
|
|
36
32
|
const DEFAULT_CONTEXT_VIRTUALIZATION_ENABLED = false;
|
|
37
33
|
const DEFAULT_CONVERSATION_HISTORY_ENABLED = false;
|
|
38
|
-
const MODE_VALUES = ["conversation", "workflow", "strict-workflow"];
|
|
39
|
-
const MODE_LABELS = {
|
|
40
|
-
default: "Use configured default",
|
|
41
|
-
conversation: "conversation",
|
|
42
|
-
workflow: "workflow",
|
|
43
|
-
"strict-workflow": "strict-workflow",
|
|
44
|
-
};
|
|
45
|
-
const MODE_DESCRIPTIONS = {
|
|
46
|
-
conversation: "Discussion and read-only inspection",
|
|
47
|
-
workflow: "Adaptive workflow for consequential work",
|
|
48
|
-
"strict-workflow": "Stronger decision and evidence pressure for high-risk work",
|
|
49
|
-
};
|
|
50
34
|
const LOCAL_INHERIT = "inherit";
|
|
51
35
|
const execFileAsync = promisify(execFile);
|
|
52
36
|
|
|
@@ -307,114 +291,29 @@ function createScopedBooleanItem(options: ScopedBooleanItemOptions): SettingsIte
|
|
|
307
291
|
return item;
|
|
308
292
|
}
|
|
309
293
|
|
|
310
|
-
type ScopedDefaultModeItemOptions = {
|
|
311
|
-
scope: ConfigScope;
|
|
312
|
-
repositoryDefaultMode: string;
|
|
313
|
-
repositoryDefaultSource: ConfigSource;
|
|
314
|
-
localDefaultMode?: string;
|
|
315
|
-
effectiveValue: string;
|
|
316
|
-
effectiveSource: ConfigSource;
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
function createScopedDefaultModeItem(options: ScopedDefaultModeItemOptions): SettingsItem {
|
|
320
|
-
let item: SettingsItem;
|
|
321
|
-
if (options.scope === "local") {
|
|
322
|
-
item = {
|
|
323
|
-
id: "freeflow.defaultMode",
|
|
324
|
-
label: "Default mode",
|
|
325
|
-
description:
|
|
326
|
-
"Personal default mode for this checkout. Choose inherit to use the repository default; use /freeflow settings repo to edit shared defaults.",
|
|
327
|
-
path: ["defaultMode"],
|
|
328
|
-
kind: "enum",
|
|
329
|
-
value: options.localDefaultMode ?? LOCAL_INHERIT,
|
|
330
|
-
values: [LOCAL_INHERIT, ...MODE_VALUES],
|
|
331
|
-
valueLabels: {
|
|
332
|
-
inherit: "Inherit repository",
|
|
333
|
-
...MODE_LABELS,
|
|
334
|
-
},
|
|
335
|
-
valueDescriptions: {
|
|
336
|
-
inherit: `Use ${options.repositoryDefaultMode} from ${options.repositoryDefaultSource}.`,
|
|
337
|
-
...MODE_DESCRIPTIONS,
|
|
338
|
-
},
|
|
339
|
-
format: (value) => String(value),
|
|
340
|
-
configScope: "local",
|
|
341
|
-
configValues: { inherit: undefined },
|
|
342
|
-
effectiveValue: options.effectiveValue,
|
|
343
|
-
effectiveSource: options.effectiveSource,
|
|
344
|
-
inheritedValue: options.repositoryDefaultMode,
|
|
345
|
-
inheritedSource: options.repositoryDefaultSource,
|
|
346
|
-
};
|
|
347
|
-
} else {
|
|
348
|
-
item = {
|
|
349
|
-
id: "freeflow.defaultMode",
|
|
350
|
-
label: "Default mode",
|
|
351
|
-
description:
|
|
352
|
-
"Shared repository default Freeflow mode used when Skills are enabled. This edits .freeflow/config.json.",
|
|
353
|
-
path: ["defaultMode"],
|
|
354
|
-
kind: "enum",
|
|
355
|
-
value: options.repositoryDefaultMode,
|
|
356
|
-
values: MODE_VALUES,
|
|
357
|
-
valueLabels: MODE_LABELS,
|
|
358
|
-
valueDescriptions: MODE_DESCRIPTIONS,
|
|
359
|
-
configScope: "repository",
|
|
360
|
-
effectiveValue: options.effectiveValue,
|
|
361
|
-
effectiveSource: options.effectiveSource,
|
|
362
|
-
localOverrideValue: options.localDefaultMode,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
item.displaySuffix = coreDisplaySuffix(item);
|
|
366
|
-
return item;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function sessionModeDisplaySuffix(
|
|
370
|
-
sessionMode: string,
|
|
371
|
-
defaultMode: string,
|
|
372
|
-
defaultSource: ConfigSource,
|
|
373
|
-
inactive: boolean,
|
|
374
|
-
): string | undefined {
|
|
375
|
-
if (sessionMode !== "default") return undefined;
|
|
376
|
-
const inactiveSuffix = inactive ? " · inactive" : "";
|
|
377
|
-
return `(${defaultMode} · ${defaultSource}${inactiveSuffix})`;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function validModeOrUndefined(value: unknown): string | undefined {
|
|
381
|
-
return typeof value === "string" && VALID_MODES.has(value) ? value : undefined;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
294
|
function resolveSettingsCoreView(
|
|
385
295
|
rawConfig: Record<string, unknown>,
|
|
386
296
|
layers?: Awaited<ReturnType<typeof readFreeflowConfigLayers>>,
|
|
387
297
|
) {
|
|
388
298
|
const localConfig = layers?.local.valid && isRecord(layers.local.parsed) ? layers.local.parsed : {};
|
|
389
|
-
const repositorySkillsValue = getPath(rawConfig, ["skills"]);
|
|
390
|
-
const repositorySkills = isRecord(repositorySkillsValue) ? repositorySkillsValue : {};
|
|
391
299
|
const fallbackCore = {
|
|
392
300
|
enabled: getPath(rawConfig, ["enabled"]) !== false,
|
|
393
|
-
interactionContract: getPath(rawConfig, ["interactionContract"]) !== false,
|
|
394
301
|
contextVirtualization: getPath(rawConfig, ["contextVirtualization"]) === true,
|
|
395
302
|
conversationHistory: getPath(rawConfig, ["conversationHistory"]) === true,
|
|
396
|
-
skills: { enabled: getPath(repositorySkills, ["enabled"]) !== false },
|
|
397
|
-
defaultMode: validModeOrUndefined(rawConfig.defaultMode) ?? "workflow",
|
|
398
303
|
};
|
|
399
304
|
const fallbackSources = {
|
|
400
305
|
enabled: typeof getPath(rawConfig, ["enabled"]) === "boolean" ? "repository" : "builtin",
|
|
401
|
-
interactionContract: typeof getPath(rawConfig, ["interactionContract"]) === "boolean" ? "repository" : "builtin",
|
|
402
306
|
contextVirtualization:
|
|
403
307
|
typeof getPath(rawConfig, ["contextVirtualization"]) === "boolean" ? "repository" : "builtin",
|
|
404
308
|
conversationHistory: typeof getPath(rawConfig, ["conversationHistory"]) === "boolean" ? "repository" : "builtin",
|
|
405
|
-
skillsEnabled: typeof getPath(repositorySkills, ["enabled"]) === "boolean" ? "repository" : "builtin",
|
|
406
|
-
defaultMode: validModeOrUndefined(rawConfig.defaultMode) === undefined ? "builtin" : "repository",
|
|
407
309
|
} as const;
|
|
408
310
|
return {
|
|
409
311
|
localConfig,
|
|
410
312
|
core: layers?.coreConfig ?? fallbackCore,
|
|
411
313
|
sources: (layers?.sources ?? fallbackSources) as {
|
|
412
314
|
enabled: ConfigSource;
|
|
413
|
-
interactionContract: ConfigSource;
|
|
414
315
|
contextVirtualization: ConfigSource;
|
|
415
316
|
conversationHistory: ConfigSource;
|
|
416
|
-
skillsEnabled: ConfigSource;
|
|
417
|
-
defaultMode: ConfigSource;
|
|
418
317
|
},
|
|
419
318
|
};
|
|
420
319
|
}
|
|
@@ -423,7 +322,7 @@ function createSessionBooleanItem(options: {
|
|
|
423
322
|
id: string;
|
|
424
323
|
label: string;
|
|
425
324
|
description: string;
|
|
426
|
-
key: "enabled" | "
|
|
325
|
+
key: "enabled" | "contextVirtualization" | "conversationHistory";
|
|
427
326
|
inheritedValue: boolean;
|
|
428
327
|
inheritedSource: ConfigSource;
|
|
429
328
|
effectiveValue: boolean;
|
|
@@ -469,24 +368,19 @@ function createSessionBooleanItem(options: {
|
|
|
469
368
|
|
|
470
369
|
function sessionFreeflowItems(
|
|
471
370
|
state: Awaited<ReturnType<typeof readCapabilityState>>,
|
|
472
|
-
modeState: Awaited<ReturnType<typeof readModeState>>,
|
|
473
371
|
cognitiveRoutingController?: CognitiveRoutingSettingsController,
|
|
474
372
|
): SettingsItem[] {
|
|
475
373
|
const sessionOverrides = state.sessionOverrides as Record<string, boolean>;
|
|
476
374
|
const configured = state.configuredCoreConfig;
|
|
477
375
|
const configuredSources = state.configuredSources as {
|
|
478
376
|
enabled: ConfigSource;
|
|
479
|
-
interactionContract: ConfigSource;
|
|
480
377
|
contextVirtualization: ConfigSource;
|
|
481
378
|
conversationHistory: ConfigSource;
|
|
482
|
-
skillsEnabled: ConfigSource;
|
|
483
379
|
};
|
|
484
380
|
const effectiveSources = state.configSources as {
|
|
485
381
|
enabled: ConfigSource;
|
|
486
|
-
interactionContract: ConfigSource;
|
|
487
382
|
contextVirtualization: ConfigSource;
|
|
488
383
|
conversationHistory: ConfigSource;
|
|
489
|
-
skillsEnabled: ConfigSource;
|
|
490
384
|
};
|
|
491
385
|
|
|
492
386
|
const freeflowItem = createSessionBooleanItem({
|
|
@@ -500,28 +394,6 @@ function sessionFreeflowItems(
|
|
|
500
394
|
effectiveSource: effectiveSources.enabled,
|
|
501
395
|
sessionOverrides,
|
|
502
396
|
});
|
|
503
|
-
const interactionItem = createSessionBooleanItem({
|
|
504
|
-
id: "freeflow.interactionContract",
|
|
505
|
-
label: "Interaction Contract",
|
|
506
|
-
description: "Temporary Interaction Contract override for this Pi session.",
|
|
507
|
-
key: "interactionContract",
|
|
508
|
-
inheritedValue: configured.interactionContract,
|
|
509
|
-
inheritedSource: configuredSources.interactionContract,
|
|
510
|
-
effectiveValue: state.interactionContract.enabled,
|
|
511
|
-
effectiveSource: effectiveSources.interactionContract,
|
|
512
|
-
sessionOverrides,
|
|
513
|
-
});
|
|
514
|
-
const skillsItem = createSessionBooleanItem({
|
|
515
|
-
id: "freeflow.skills.enabled",
|
|
516
|
-
label: "Skills",
|
|
517
|
-
description: "Temporary Freeflow Skills override for this Pi session.",
|
|
518
|
-
key: "skillsEnabled",
|
|
519
|
-
inheritedValue: configured.skills.enabled,
|
|
520
|
-
inheritedSource: configuredSources.skillsEnabled,
|
|
521
|
-
effectiveValue: state.skills.enabled,
|
|
522
|
-
effectiveSource: effectiveSources.skillsEnabled,
|
|
523
|
-
sessionOverrides,
|
|
524
|
-
});
|
|
525
397
|
const contextVirtualizationItem = createSessionBooleanItem({
|
|
526
398
|
id: "freeflow.contextVirtualization",
|
|
527
399
|
label: "Context Virtualization",
|
|
@@ -546,38 +418,8 @@ function sessionFreeflowItems(
|
|
|
546
418
|
});
|
|
547
419
|
|
|
548
420
|
const freeflowInactive = !state.enabled;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
skillsItem.inactive = freeflowInactive;
|
|
552
|
-
contextVirtualizationItem.inactive = freeflowInactive || !skillsEnabled;
|
|
553
|
-
conversationHistoryItem.inactive = freeflowInactive || !skillsEnabled;
|
|
554
|
-
|
|
555
|
-
const sessionMode = modeState.currentMode ?? "default";
|
|
556
|
-
const sessionModeItem: SettingsItem = {
|
|
557
|
-
id: "freeflow.sessionMode",
|
|
558
|
-
label: "Mode",
|
|
559
|
-
description: "Temporary mode override for this Pi session.",
|
|
560
|
-
kind: "enum",
|
|
561
|
-
value: sessionMode,
|
|
562
|
-
values: ["default", ...MODE_VALUES],
|
|
563
|
-
valueLabels: {
|
|
564
|
-
...MODE_LABELS,
|
|
565
|
-
default: "Use configured default",
|
|
566
|
-
},
|
|
567
|
-
valueDescriptions: {
|
|
568
|
-
default: `${modeState.defaultMode} from ${modeState.defaultModeSource}`,
|
|
569
|
-
...MODE_DESCRIPTIONS,
|
|
570
|
-
},
|
|
571
|
-
inactive: freeflowInactive || !skillsEnabled,
|
|
572
|
-
displaySuffix: sessionModeDisplaySuffix(
|
|
573
|
-
sessionMode,
|
|
574
|
-
modeState.defaultMode,
|
|
575
|
-
modeState.defaultModeSource,
|
|
576
|
-
freeflowInactive || !skillsEnabled,
|
|
577
|
-
),
|
|
578
|
-
inheritedValue: modeState.defaultMode,
|
|
579
|
-
inheritedSource: modeState.defaultModeSource,
|
|
580
|
-
};
|
|
421
|
+
contextVirtualizationItem.inactive = freeflowInactive;
|
|
422
|
+
conversationHistoryItem.inactive = freeflowInactive;
|
|
581
423
|
|
|
582
424
|
const cognitiveRoutingState = cognitiveRoutingController?.state();
|
|
583
425
|
const cognitiveRoutingProfile =
|
|
@@ -604,7 +446,7 @@ function sessionFreeflowItems(
|
|
|
604
446
|
standard: "Hold the standard profile until /freeflow profile auto.",
|
|
605
447
|
reasoning: "Hold the reasoning profile until /freeflow profile auto.",
|
|
606
448
|
},
|
|
607
|
-
inactive: !state.cognitiveRouting.effective || cognitiveRoutingController === undefined,
|
|
449
|
+
inactive: freeflowInactive || !state.cognitiveRouting.effective || cognitiveRoutingController === undefined,
|
|
608
450
|
runtimeInactive: state.cognitiveRouting.blockingReason?.code === "runtime_disabled",
|
|
609
451
|
displaySuffix: cognitiveRoutingState?.effective ? cognitiveRoutingProfile : "unavailable",
|
|
610
452
|
}
|
|
@@ -612,15 +454,11 @@ function sessionFreeflowItems(
|
|
|
612
454
|
|
|
613
455
|
return [
|
|
614
456
|
freeflowItem,
|
|
615
|
-
interactionItem,
|
|
616
|
-
skillsItem,
|
|
617
|
-
sessionModeItem,
|
|
618
457
|
...(cognitiveRoutingItem ? [cognitiveRoutingItem] : []),
|
|
619
458
|
{
|
|
620
459
|
id: "freeflow.session.reset",
|
|
621
460
|
label: "Reset session overrides",
|
|
622
|
-
description:
|
|
623
|
-
"Clear Freeflow, Interaction Contract, Skills, Context Virtualization, Conversation History, and mode overrides for this Pi session.",
|
|
461
|
+
description: "Clear Freeflow, Context Virtualization, and Conversation History overrides for this Pi session.",
|
|
624
462
|
kind: "enum",
|
|
625
463
|
value: "available",
|
|
626
464
|
values: ["reset"],
|
|
@@ -899,18 +737,18 @@ function cognitiveRoutingSessionStartItem(options: {
|
|
|
899
737
|
capabilityState: CognitiveRoutingCapabilityState | undefined;
|
|
900
738
|
}): SettingsItem {
|
|
901
739
|
const path = ["cognitiveRouting", "sessionStart", options.setting];
|
|
902
|
-
const defaultValue = options.setting === "control" ? "automatic" : "
|
|
740
|
+
const defaultValue = options.setting === "control" ? "automatic" : "reasoning";
|
|
903
741
|
const values = options.setting === "control" ? ["automatic", "manual"] : ["standard", "reasoning"];
|
|
904
742
|
const labels = Object.fromEntries(values.map((value) => [value, value]));
|
|
905
743
|
const descriptions =
|
|
906
744
|
options.setting === "control"
|
|
907
745
|
? {
|
|
908
|
-
automatic: "
|
|
746
|
+
automatic: "Start the new session in Reasoning; automatic delegation may use Standard during execution.",
|
|
909
747
|
manual: "Hold the selected profile for the new session until the user changes it.",
|
|
910
748
|
}
|
|
911
749
|
: {
|
|
912
|
-
standard: "Start a new session with the configured Standard preset.",
|
|
913
|
-
reasoning: "Start a new session with the configured Reasoning preset.",
|
|
750
|
+
standard: "Start a new manual session with the configured Standard preset.",
|
|
751
|
+
reasoning: "Start a new manual session with the configured Reasoning preset.",
|
|
914
752
|
};
|
|
915
753
|
const repositoryValue = getPath(options.rawConfig, path);
|
|
916
754
|
const localValue = getPath(options.localConfig, path);
|
|
@@ -921,13 +759,21 @@ function cognitiveRoutingSessionStartItem(options: {
|
|
|
921
759
|
const inheritedSource: ConfigSource = repositorySetting ? "repository" : "builtin";
|
|
922
760
|
const configuredSource =
|
|
923
761
|
options.capabilityState?.sessionStartSources?.[options.setting] ?? (repositorySetting ? "repository" : undefined);
|
|
924
|
-
const
|
|
762
|
+
const effectiveSessionStartControl =
|
|
763
|
+
options.capabilityState?.sessionStart?.control ??
|
|
764
|
+
getPath(options.localConfig, ["cognitiveRouting", "sessionStart", "control"]) ??
|
|
765
|
+
getPath(options.rawConfig, ["cognitiveRouting", "sessionStart", "control"]) ??
|
|
766
|
+
"automatic";
|
|
767
|
+
const effectiveValue =
|
|
768
|
+
options.setting === "profile" && effectiveSessionStartControl === "automatic"
|
|
769
|
+
? "reasoning"
|
|
770
|
+
: (options.capabilityState?.sessionStart?.[options.setting] ?? inheritedValue);
|
|
925
771
|
const effectiveSource = cognitiveRoutingSettingsSource(configuredSource);
|
|
926
|
-
const label = options.setting === "control" ? "Session start control" : "
|
|
772
|
+
const label = options.setting === "control" ? "Session start control" : "Manual session-start profile";
|
|
927
773
|
const description =
|
|
928
774
|
options.setting === "control"
|
|
929
775
|
? "Choose automatic or manual control for new sessions only; changing this does not alter the active session."
|
|
930
|
-
: "Choose the
|
|
776
|
+
: "Choose the profile for manual session starts; automatic sessions always start in Reasoning.";
|
|
931
777
|
|
|
932
778
|
const item: SettingsItem =
|
|
933
779
|
options.scope === "local"
|
|
@@ -973,15 +819,18 @@ function cognitiveRoutingSessionStartItem(options: {
|
|
|
973
819
|
return item;
|
|
974
820
|
}
|
|
975
821
|
|
|
822
|
+
function isCognitiveRoutingRuntimeAvailable(pi: any): boolean {
|
|
823
|
+
return isPiFlowHost(pi?.host) || supportsPiSessionModelStateApi(pi);
|
|
824
|
+
}
|
|
825
|
+
|
|
976
826
|
function freeflowItems(
|
|
977
827
|
rawConfig: Record<string, unknown>,
|
|
978
|
-
modeState?: Awaited<ReturnType<typeof readModeState>>,
|
|
979
828
|
options: {
|
|
980
829
|
scope?: ConfigScope;
|
|
981
830
|
layers?: Awaited<ReturnType<typeof readFreeflowConfigLayers>>;
|
|
982
831
|
cognitiveRouting?: CognitiveRoutingCapabilityState;
|
|
983
832
|
ctx?: any;
|
|
984
|
-
|
|
833
|
+
runtimeAvailable?: boolean;
|
|
985
834
|
} = {},
|
|
986
835
|
): SettingsItem[] {
|
|
987
836
|
const scope = options.scope ?? "repository";
|
|
@@ -994,36 +843,12 @@ function freeflowItems(
|
|
|
994
843
|
localConfig,
|
|
995
844
|
id: "freeflow.enabled",
|
|
996
845
|
label: "Freeflow",
|
|
997
|
-
description: "Master switch for
|
|
846
|
+
description: "Master switch for Freeflow's core guidance, skills, and optional capabilities in this checkout.",
|
|
998
847
|
path: ["enabled"],
|
|
999
848
|
effectiveValue: core.enabled,
|
|
1000
849
|
effectiveSource: sources.enabled,
|
|
1001
850
|
defaultValue: DEFAULT_FREEFLOW_ENABLED,
|
|
1002
851
|
});
|
|
1003
|
-
const interactionItem = createScopedBooleanItem({
|
|
1004
|
-
scope,
|
|
1005
|
-
rawConfig,
|
|
1006
|
-
localConfig,
|
|
1007
|
-
id: "freeflow.interactionContract",
|
|
1008
|
-
label: "Interaction Contract",
|
|
1009
|
-
description: "Apply Freeflow's compact turn-interpretation and collaboration guidance.",
|
|
1010
|
-
path: ["interactionContract"],
|
|
1011
|
-
effectiveValue: core.interactionContract,
|
|
1012
|
-
effectiveSource: sources.interactionContract,
|
|
1013
|
-
defaultValue: DEFAULT_INTERACTION_CONTRACT_ENABLED,
|
|
1014
|
-
});
|
|
1015
|
-
const skillsItem = createScopedBooleanItem({
|
|
1016
|
-
scope,
|
|
1017
|
-
rawConfig,
|
|
1018
|
-
localConfig,
|
|
1019
|
-
id: "freeflow.skills.enabled",
|
|
1020
|
-
label: "Skills",
|
|
1021
|
-
description: "Expose Freeflow skills and discover Workflow before consequential or mutating work.",
|
|
1022
|
-
path: ["skills", "enabled"],
|
|
1023
|
-
effectiveValue: core.skills.enabled,
|
|
1024
|
-
effectiveSource: sources.skillsEnabled,
|
|
1025
|
-
defaultValue: DEFAULT_SKILLS_ENABLED,
|
|
1026
|
-
});
|
|
1027
852
|
const contextVirtualizationItem = createScopedBooleanItem({
|
|
1028
853
|
scope,
|
|
1029
854
|
rawConfig,
|
|
@@ -1049,55 +874,12 @@ function freeflowItems(
|
|
|
1049
874
|
defaultValue: DEFAULT_CONVERSATION_HISTORY_ENABLED,
|
|
1050
875
|
});
|
|
1051
876
|
|
|
1052
|
-
const repositoryModeValue = validModeOrUndefined(rawConfig.defaultMode);
|
|
1053
|
-
const repositoryDefaultMode = repositoryModeValue ?? "workflow";
|
|
1054
|
-
const repositoryDefaultSource: ConfigSource = repositoryModeValue ? "repository" : "builtin";
|
|
1055
|
-
const localDefaultMode = validModeOrUndefined(localConfig.defaultMode);
|
|
1056
|
-
const defaultModeItem = createScopedDefaultModeItem({
|
|
1057
|
-
scope,
|
|
1058
|
-
repositoryDefaultMode,
|
|
1059
|
-
repositoryDefaultSource,
|
|
1060
|
-
localDefaultMode,
|
|
1061
|
-
effectiveValue: core.defaultMode,
|
|
1062
|
-
effectiveSource: sources.defaultMode,
|
|
1063
|
-
});
|
|
1064
|
-
|
|
1065
877
|
const freeflowInactive = !core.enabled;
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
skillsItem.inactive = freeflowInactive;
|
|
1069
|
-
contextVirtualizationItem.inactive = freeflowInactive || !skillsEnabled;
|
|
1070
|
-
conversationHistoryItem.inactive = freeflowInactive || !skillsEnabled;
|
|
1071
|
-
defaultModeItem.inactive = freeflowInactive;
|
|
1072
|
-
defaultModeItem.displaySuffix = coreDisplaySuffix(defaultModeItem, freeflowInactive || !skillsEnabled);
|
|
1073
|
-
const sessionMode = modeState?.currentMode ?? "default";
|
|
1074
|
-
const sessionModeItem: SettingsItem = {
|
|
1075
|
-
id: "freeflow.sessionMode",
|
|
1076
|
-
label: "Session mode",
|
|
1077
|
-
description:
|
|
1078
|
-
"Temporary mode override for this Pi session. Use configured default clears the override without changing either config file.",
|
|
1079
|
-
kind: "enum",
|
|
1080
|
-
value: sessionMode,
|
|
1081
|
-
values: ["default", ...MODE_VALUES],
|
|
1082
|
-
valueLabels: {
|
|
1083
|
-
...MODE_LABELS,
|
|
1084
|
-
default: "Use configured default",
|
|
1085
|
-
},
|
|
1086
|
-
valueDescriptions: {
|
|
1087
|
-
default: `${core.defaultMode} from ${sources.defaultMode}`,
|
|
1088
|
-
...MODE_DESCRIPTIONS,
|
|
1089
|
-
},
|
|
1090
|
-
inactive: freeflowInactive || !skillsEnabled,
|
|
1091
|
-
displaySuffix: sessionModeDisplaySuffix(
|
|
1092
|
-
sessionMode,
|
|
1093
|
-
core.defaultMode,
|
|
1094
|
-
sources.defaultMode,
|
|
1095
|
-
freeflowInactive || !skillsEnabled,
|
|
1096
|
-
),
|
|
1097
|
-
};
|
|
878
|
+
contextVirtualizationItem.inactive = freeflowInactive;
|
|
879
|
+
conversationHistoryItem.inactive = freeflowInactive;
|
|
1098
880
|
|
|
1099
881
|
const cognitiveRoutingState = options.cognitiveRouting;
|
|
1100
|
-
const cognitiveRoutingRuntimeDisabled =
|
|
882
|
+
const cognitiveRoutingRuntimeDisabled = options.runtimeAvailable !== true;
|
|
1101
883
|
const cognitiveRoutingGroup = (() => {
|
|
1102
884
|
const cognitiveRoutingEnabledItem = createScopedBooleanItem({
|
|
1103
885
|
scope,
|
|
@@ -1106,14 +888,14 @@ function freeflowItems(
|
|
|
1106
888
|
id: "freeflow.cognitiveRouting.enabled",
|
|
1107
889
|
label: "Enabled",
|
|
1108
890
|
description: cognitiveRoutingRuntimeDisabled
|
|
1109
|
-
? "
|
|
891
|
+
? "Requires a host model-state control API; configuration is read-only on this host."
|
|
1110
892
|
: "Allow Cognitive Routing to own the session model lease and switch the configured profiles.",
|
|
1111
893
|
path: ["cognitiveRouting", "enabled"],
|
|
1112
894
|
effectiveValue: cognitiveRoutingState?.enabled ?? false,
|
|
1113
895
|
effectiveSource: cognitiveRoutingSettingsSource(cognitiveRoutingState?.enabledSource),
|
|
1114
896
|
defaultValue: false,
|
|
1115
897
|
});
|
|
1116
|
-
cognitiveRoutingEnabledItem.inactive = freeflowInactive ||
|
|
898
|
+
cognitiveRoutingEnabledItem.inactive = freeflowInactive || cognitiveRoutingRuntimeDisabled;
|
|
1117
899
|
cognitiveRoutingEnabledItem.runtimeInactive = cognitiveRoutingRuntimeDisabled;
|
|
1118
900
|
|
|
1119
901
|
const cognitiveRoutingProfiles = ["standard", "reasoning"].map((name) =>
|
|
@@ -1137,11 +919,11 @@ function freeflowItems(
|
|
|
1137
919
|
}),
|
|
1138
920
|
);
|
|
1139
921
|
for (const item of [...cognitiveRoutingProfiles, ...cognitiveRoutingSessionStart]) {
|
|
1140
|
-
item.inactive ||= freeflowInactive ||
|
|
922
|
+
item.inactive ||= freeflowInactive || cognitiveRoutingRuntimeDisabled;
|
|
1141
923
|
item.runtimeInactive = cognitiveRoutingRuntimeDisabled;
|
|
1142
924
|
}
|
|
1143
925
|
const cognitiveRoutingStatus = cognitiveRoutingRuntimeDisabled
|
|
1144
|
-
? "
|
|
926
|
+
? "unavailable · host unsupported"
|
|
1145
927
|
: cognitiveRoutingState
|
|
1146
928
|
? cognitiveRoutingState.effective
|
|
1147
929
|
? "active"
|
|
@@ -1153,11 +935,11 @@ function freeflowItems(
|
|
|
1153
935
|
id: "freeflow.cognitiveRouting",
|
|
1154
936
|
label: "Cognitive Routing",
|
|
1155
937
|
description: cognitiveRoutingRuntimeDisabled
|
|
1156
|
-
? "Cognitive Routing configuration is visible for inspection but
|
|
1157
|
-
: "Configure the
|
|
938
|
+
? "Cognitive Routing configuration is visible for inspection but requires a host model-state control API."
|
|
939
|
+
: "Configure the Standard and Reasoning profiles and choose whether Freeflow may manage model state for this repository.",
|
|
1158
940
|
kind: "group" as const,
|
|
1159
941
|
value: cognitiveRoutingRuntimeDisabled ? false : (cognitiveRoutingState?.enabled ?? false),
|
|
1160
|
-
inactive: freeflowInactive
|
|
942
|
+
inactive: freeflowInactive,
|
|
1161
943
|
displaySuffix: cognitiveRoutingStatus,
|
|
1162
944
|
children: [cognitiveRoutingEnabledItem, ...cognitiveRoutingProfiles, ...cognitiveRoutingSessionStart],
|
|
1163
945
|
} satisfies SettingsItem;
|
|
@@ -1165,10 +947,6 @@ function freeflowItems(
|
|
|
1165
947
|
|
|
1166
948
|
return [
|
|
1167
949
|
freeflowItem,
|
|
1168
|
-
interactionItem,
|
|
1169
|
-
skillsItem,
|
|
1170
|
-
sessionModeItem,
|
|
1171
|
-
defaultModeItem,
|
|
1172
950
|
...(cognitiveRoutingGroup ? [cognitiveRoutingGroup] : []),
|
|
1173
951
|
{
|
|
1174
952
|
id: "freeflow.context",
|
|
@@ -1185,8 +963,7 @@ function freeflowItems(
|
|
|
1185
963
|
function pruneKnownDefaults(config: Record<string, unknown>) {
|
|
1186
964
|
const defaultPaths: Array<{ path: string[]; value: unknown }> = [
|
|
1187
965
|
{ path: ["enabled"], value: DEFAULT_FREEFLOW_ENABLED },
|
|
1188
|
-
{ path: ["
|
|
1189
|
-
{ path: ["skills", "enabled"], value: DEFAULT_SKILLS_ENABLED },
|
|
966
|
+
{ path: ["contextVirtualization"], value: DEFAULT_CONTEXT_VIRTUALIZATION_ENABLED },
|
|
1190
967
|
{ path: ["conversationHistory"], value: DEFAULT_CONVERSATION_HISTORY_ENABLED },
|
|
1191
968
|
];
|
|
1192
969
|
|
|
@@ -1316,10 +1093,6 @@ function findSettingsItem(items: SettingsItem[], id: string): SettingsItem | und
|
|
|
1316
1093
|
function refreshSettingsDerivedState(items: SettingsItem[]) {
|
|
1317
1094
|
const freeflowItem = findSettingsItem(items, "freeflow.enabled");
|
|
1318
1095
|
const freeflowInactive = freeflowItem ? effectiveItemValue(freeflowItem) !== true : false;
|
|
1319
|
-
const skillsItem = findSettingsItem(items, "freeflow.skills.enabled");
|
|
1320
|
-
const skillsEnabled = skillsItem ? effectiveItemValue(skillsItem) === true : true;
|
|
1321
|
-
const sessionModeItem = findSettingsItem(items, "freeflow.sessionMode");
|
|
1322
|
-
const defaultModeItem = findSettingsItem(items, "freeflow.defaultMode");
|
|
1323
1096
|
const cognitiveRoutingGroup = findSettingsItem(items, "freeflow.cognitiveRouting");
|
|
1324
1097
|
const cognitiveRoutingEnabledItem = findSettingsItem(items, "freeflow.cognitiveRouting.enabled");
|
|
1325
1098
|
const cognitiveRoutingProfiles = [
|
|
@@ -1327,24 +1100,6 @@ function refreshSettingsDerivedState(items: SettingsItem[]) {
|
|
|
1327
1100
|
findSettingsItem(items, "freeflow.cognitiveRouting.reasoning"),
|
|
1328
1101
|
];
|
|
1329
1102
|
|
|
1330
|
-
if (sessionModeItem) {
|
|
1331
|
-
const defaultMode = String(
|
|
1332
|
-
defaultModeItem ? effectiveItemValue(defaultModeItem) : (sessionModeItem.inheritedValue ?? "workflow"),
|
|
1333
|
-
);
|
|
1334
|
-
const defaultSource = defaultModeItem?.effectiveSource ?? sessionModeItem.inheritedSource ?? "builtin";
|
|
1335
|
-
sessionModeItem.inactive = freeflowInactive || !skillsEnabled;
|
|
1336
|
-
sessionModeItem.displaySuffix = sessionModeDisplaySuffix(
|
|
1337
|
-
String(sessionModeItem.value),
|
|
1338
|
-
defaultMode,
|
|
1339
|
-
defaultSource,
|
|
1340
|
-
freeflowInactive || !skillsEnabled,
|
|
1341
|
-
);
|
|
1342
|
-
sessionModeItem.valueDescriptions = {
|
|
1343
|
-
default: `${defaultMode} from ${defaultSource}`,
|
|
1344
|
-
...MODE_DESCRIPTIONS,
|
|
1345
|
-
};
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
1103
|
if (cognitiveRoutingGroup && cognitiveRoutingEnabledItem) {
|
|
1349
1104
|
const enabled = effectiveItemValue(cognitiveRoutingEnabledItem) === true;
|
|
1350
1105
|
const profilesConfigured = cognitiveRoutingProfiles.every((item) =>
|
|
@@ -1358,7 +1113,7 @@ function refreshSettingsDerivedState(items: SettingsItem[]) {
|
|
|
1358
1113
|
: "configured"
|
|
1359
1114
|
: "not configured"
|
|
1360
1115
|
: "disabled";
|
|
1361
|
-
cognitiveRoutingGroup.inactive = freeflowInactive
|
|
1116
|
+
cognitiveRoutingGroup.inactive = freeflowInactive;
|
|
1362
1117
|
}
|
|
1363
1118
|
|
|
1364
1119
|
const contextGroup = findSettingsItem(items, "freeflow.context");
|
|
@@ -1373,31 +1128,11 @@ function refreshSettingsDerivedState(items: SettingsItem[]) {
|
|
|
1373
1128
|
candidate.inactive = false;
|
|
1374
1129
|
} else if (candidate.configScope) {
|
|
1375
1130
|
const inactive =
|
|
1376
|
-
candidate.id === "freeflow.enabled"
|
|
1377
|
-
? false
|
|
1378
|
-
: candidate.runtimeInactive === true ||
|
|
1379
|
-
freeflowInactive ||
|
|
1380
|
-
(!skillsEnabled &&
|
|
1381
|
-
[
|
|
1382
|
-
"freeflow.cognitiveRouting",
|
|
1383
|
-
"freeflow.cognitiveRouting.enabled",
|
|
1384
|
-
"freeflow.cognitiveRouting.standard",
|
|
1385
|
-
"freeflow.cognitiveRouting.reasoning",
|
|
1386
|
-
"freeflow.cognitiveRouting.sessionStart.control",
|
|
1387
|
-
"freeflow.cognitiveRouting.sessionStart.profile",
|
|
1388
|
-
"freeflow.contextVirtualization",
|
|
1389
|
-
"freeflow.conversationHistory",
|
|
1390
|
-
].includes(candidate.id));
|
|
1391
|
-
const displayInactive = candidate.id === "freeflow.defaultMode" ? freeflowInactive || !skillsEnabled : inactive;
|
|
1131
|
+
candidate.id === "freeflow.enabled" ? false : candidate.runtimeInactive === true || freeflowInactive;
|
|
1392
1132
|
candidate.inactive = inactive;
|
|
1393
|
-
candidate.displaySuffix = coreDisplaySuffix(candidate,
|
|
1394
|
-
} else if (candidate.id === "freeflow.sessionMode") {
|
|
1395
|
-
candidate.inactive = candidate.runtimeInactive === true || freeflowInactive || !skillsEnabled;
|
|
1133
|
+
candidate.displaySuffix = coreDisplaySuffix(candidate, inactive);
|
|
1396
1134
|
} else {
|
|
1397
|
-
candidate.inactive =
|
|
1398
|
-
candidate.runtimeInactive === true ||
|
|
1399
|
-
freeflowInactive ||
|
|
1400
|
-
(!skillsEnabled && candidate.id === "freeflow.cognitiveRouting");
|
|
1135
|
+
candidate.inactive = candidate.runtimeInactive === true || freeflowInactive;
|
|
1401
1136
|
}
|
|
1402
1137
|
});
|
|
1403
1138
|
}
|
|
@@ -1517,7 +1252,7 @@ function freeflowStatusText(
|
|
|
1517
1252
|
const cognitiveRouting = state.cognitiveRouting;
|
|
1518
1253
|
const cognitiveRoutingStatus = cognitiveRouting
|
|
1519
1254
|
? cognitiveRouting.blockingReason?.code === "runtime_disabled"
|
|
1520
|
-
? "
|
|
1255
|
+
? "unavailable (host unsupported)"
|
|
1521
1256
|
: cognitiveRouting.effective
|
|
1522
1257
|
? routingState?.effective
|
|
1523
1258
|
? `active (${routingState.activeProfile ?? "unknown"}, ${routingState.controlMode})`
|
|
@@ -1529,21 +1264,13 @@ function freeflowStatusText(
|
|
|
1529
1264
|
const contextEnabled = state.contextVirtualization?.effective || state.conversationHistory?.effective;
|
|
1530
1265
|
return [
|
|
1531
1266
|
`Freeflow: ${state.enabled ? "enabled" : "disabled"}${sessionSuffix(state.configSources.enabled as ConfigSource)}`,
|
|
1532
|
-
`interaction contract: ${state.interactionContract.effective ? "enabled" : "disabled"}${sessionSuffix(
|
|
1533
|
-
state.configSources.interactionContract as ConfigSource,
|
|
1534
|
-
)}`,
|
|
1535
|
-
`skills: ${state.skills.effective ? "enabled" : "disabled (workflow modes inactive)"}${sessionSuffix(
|
|
1536
|
-
state.configSources.skillsEnabled as ConfigSource,
|
|
1537
|
-
)}`,
|
|
1538
1267
|
`context: ${contextEnabled ? "enabled" : "disabled"} (virtualization ${state.contextVirtualization?.effective ? "enabled" : "disabled"}, history ${state.conversationHistory?.effective ? "enabled" : "disabled"})`,
|
|
1539
1268
|
...(cognitiveRoutingStatus ? [`cognitive routing: ${cognitiveRoutingStatus}`] : []),
|
|
1540
1269
|
].join("; ");
|
|
1541
1270
|
}
|
|
1542
1271
|
|
|
1543
1272
|
const NON_TUI_SETTINGS_GUIDANCE =
|
|
1544
|
-
"Freeflow settings require Pi TUI mode. Use /freeflow status to inspect current state; supported non-TUI changes are /freeflow enable
|
|
1545
|
-
const NON_TUI_MODE_GUIDANCE =
|
|
1546
|
-
"Freeflow mode selector requires Pi TUI mode. Use /freeflow mode conversation, /freeflow mode workflow, /freeflow mode strict-workflow, or /freeflow mode reset.";
|
|
1273
|
+
"Freeflow settings require Pi TUI mode. Use /freeflow status to inspect current state; supported non-TUI changes are /freeflow enable and /freeflow disable.";
|
|
1547
1274
|
|
|
1548
1275
|
function ensureSettingsIdle(ctx: any): boolean {
|
|
1549
1276
|
if (typeof ctx?.isIdle !== "function" || ctx.isIdle()) return true;
|
|
@@ -1611,9 +1338,6 @@ export async function handleFreeflowCommand(
|
|
|
1611
1338
|
const [action, ...rest] = input.split(/\s+/);
|
|
1612
1339
|
const actionValue = rest.join(" ");
|
|
1613
1340
|
const nonTui = ctx?.mode && ctx.mode !== "tui";
|
|
1614
|
-
if (nonTui && action === "mode" && !actionValue) {
|
|
1615
|
-
return nonTuiGuidance(ctx, NON_TUI_MODE_GUIDANCE);
|
|
1616
|
-
}
|
|
1617
1341
|
const settingsSelector =
|
|
1618
1342
|
action === "settings" &&
|
|
1619
1343
|
(!actionValue || ["session", "local", "personal", "repo", "repository", "shared"].includes(actionValue));
|
|
@@ -1621,10 +1345,9 @@ export async function handleFreeflowCommand(
|
|
|
1621
1345
|
return nonTuiGuidance(ctx, NON_TUI_SETTINGS_GUIDANCE);
|
|
1622
1346
|
}
|
|
1623
1347
|
|
|
1624
|
-
const [layers, state
|
|
1348
|
+
const [layers, state] = await Promise.all([
|
|
1625
1349
|
readFreeflowConfigLayers(ctx.cwd),
|
|
1626
1350
|
readCapabilityState(ctx.cwd, ctx, pi?.host),
|
|
1627
|
-
readModeState(ctx.cwd),
|
|
1628
1351
|
]);
|
|
1629
1352
|
const configState = layers.repository;
|
|
1630
1353
|
const raw = configState.valid ? configState.parsed : {};
|
|
@@ -1646,50 +1369,15 @@ export async function handleFreeflowCommand(
|
|
|
1646
1369
|
return { changed: false, reloaded: false, error: "invalid_local_config" };
|
|
1647
1370
|
}
|
|
1648
1371
|
|
|
1649
|
-
if (action === "mode") {
|
|
1650
|
-
if (!ensureSettingsIdle(ctx)) return { changed: false, reloaded: false, error: "busy" };
|
|
1651
|
-
if (actionValue) {
|
|
1652
|
-
const result = await handleModeCommand(actionValue, ctx, pi);
|
|
1653
|
-
return { changed: result.changed, reloaded: false, error: result.error };
|
|
1654
|
-
}
|
|
1655
|
-
if (!state.enabled || !state.skills.effective) {
|
|
1656
|
-
const result = await handleModeCommand(undefined, ctx, pi);
|
|
1657
|
-
return { changed: false, reloaded: false, error: result.error };
|
|
1658
|
-
}
|
|
1659
|
-
if (typeof ctx?.ui?.custom !== "function") {
|
|
1660
|
-
const result = await handleModeCommand(undefined, ctx, pi);
|
|
1661
|
-
return { changed: false, reloaded: false, error: result.error };
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
|
-
const item = freeflowItems(raw, modeState, {
|
|
1665
|
-
scope: "local",
|
|
1666
|
-
layers,
|
|
1667
|
-
cognitiveRouting: state.cognitiveRouting as CognitiveRoutingCapabilityState,
|
|
1668
|
-
ctx,
|
|
1669
|
-
hostInfo: pi?.host,
|
|
1670
|
-
}).find((candidate) => candidate.id === "freeflow.sessionMode")!;
|
|
1671
|
-
const session = await openSettings({
|
|
1672
|
-
title: "Freeflow Mode",
|
|
1673
|
-
items: [item],
|
|
1674
|
-
initialChoice: item,
|
|
1675
|
-
ctx,
|
|
1676
|
-
onChange: async (_item, value) => {
|
|
1677
|
-
const result = await handleModeCommand(String(value), ctx, pi);
|
|
1678
|
-
return { changed: result.changed, reloadRequired: false };
|
|
1679
|
-
},
|
|
1680
|
-
});
|
|
1681
|
-
return { changed: session.changed, reloaded: false, error: session.failed ? "write_failed" : undefined };
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
1372
|
if (["enable", "on", "true", "disable", "off", "false"].includes(action)) {
|
|
1685
1373
|
if (!ensureSettingsIdle(ctx)) return { changed: false, reloaded: false, error: "busy" };
|
|
1686
1374
|
const enabled = ["enable", "on", "true"].includes(action);
|
|
1687
|
-
const item = freeflowItems(raw,
|
|
1375
|
+
const item = freeflowItems(raw, {
|
|
1688
1376
|
scope: "repository",
|
|
1689
1377
|
layers,
|
|
1690
1378
|
cognitiveRouting: state.cognitiveRouting as CognitiveRoutingCapabilityState,
|
|
1691
1379
|
ctx,
|
|
1692
|
-
|
|
1380
|
+
runtimeAvailable: isCognitiveRoutingRuntimeAvailable(pi),
|
|
1693
1381
|
}).find((candidate) => candidate.id === "freeflow.enabled")!;
|
|
1694
1382
|
await updateConfig(ctx.cwd, item, enabled, "repository");
|
|
1695
1383
|
await afterChange(true);
|
|
@@ -1704,7 +1392,7 @@ export async function handleFreeflowCommand(
|
|
|
1704
1392
|
|
|
1705
1393
|
if (action && action !== "settings") {
|
|
1706
1394
|
ctx.ui.notify(
|
|
1707
|
-
"Usage: /freeflow, /freeflow settings [local|repo], /freeflow status, /freeflow
|
|
1395
|
+
"Usage: /freeflow, /freeflow settings [local|repo], /freeflow status, /freeflow enable, or /freeflow disable",
|
|
1708
1396
|
"warning",
|
|
1709
1397
|
);
|
|
1710
1398
|
return { changed: false, reloaded: false, error: "invalid_action" };
|
|
@@ -1728,13 +1416,13 @@ export async function handleFreeflowCommand(
|
|
|
1728
1416
|
let reconcileCognitiveRouting = settingsScope === "session";
|
|
1729
1417
|
const items =
|
|
1730
1418
|
settingsScope === "session"
|
|
1731
|
-
? sessionFreeflowItems(state,
|
|
1732
|
-
: freeflowItems(raw,
|
|
1419
|
+
? sessionFreeflowItems(state, cognitiveRoutingController)
|
|
1420
|
+
: freeflowItems(raw, {
|
|
1733
1421
|
scope: settingsScope,
|
|
1734
1422
|
layers,
|
|
1735
1423
|
cognitiveRouting: state.cognitiveRouting as CognitiveRoutingCapabilityState,
|
|
1736
1424
|
ctx,
|
|
1737
|
-
|
|
1425
|
+
runtimeAvailable: isCognitiveRoutingRuntimeAvailable(pi),
|
|
1738
1426
|
});
|
|
1739
1427
|
const session = await openSettings({
|
|
1740
1428
|
title:
|
|
@@ -1747,14 +1435,10 @@ export async function handleFreeflowCommand(
|
|
|
1747
1435
|
ctx,
|
|
1748
1436
|
onChange: async (item, value) => {
|
|
1749
1437
|
if (!ensureSettingsIdle(ctx)) return { changed: false, reloadRequired: false };
|
|
1750
|
-
if (!
|
|
1751
|
-
ctx.ui.notify("Cognitive Routing is
|
|
1438
|
+
if (!isCognitiveRoutingRuntimeAvailable(pi) && item.id.startsWith("freeflow.cognitiveRouting.")) {
|
|
1439
|
+
ctx.ui.notify("Cognitive Routing is unavailable because this host lacks model-state controls.", "warning");
|
|
1752
1440
|
return { changed: false, reloadRequired: false };
|
|
1753
1441
|
}
|
|
1754
|
-
if (item.id === "freeflow.sessionMode") {
|
|
1755
|
-
const result = await handleModeCommand(String(value), ctx, pi);
|
|
1756
|
-
return { changed: result.changed, reloadRequired: false };
|
|
1757
|
-
}
|
|
1758
1442
|
if (item.id === "freeflow.cognitiveRouting.profile") {
|
|
1759
1443
|
if (!cognitiveRoutingController) {
|
|
1760
1444
|
ctx.ui.notify("Cognitive Routing is unavailable for this session.", "warning");
|
|
@@ -1781,8 +1465,6 @@ export async function handleFreeflowCommand(
|
|
|
1781
1465
|
if (item.configScope === "session") {
|
|
1782
1466
|
const keyById = {
|
|
1783
1467
|
"freeflow.enabled": "enabled",
|
|
1784
|
-
"freeflow.interactionContract": "interactionContract",
|
|
1785
|
-
"freeflow.skills.enabled": "skillsEnabled",
|
|
1786
1468
|
"freeflow.contextVirtualization": "contextVirtualization",
|
|
1787
1469
|
"freeflow.conversationHistory": "conversationHistory",
|
|
1788
1470
|
} as const;
|