@hassangameryt/freeflow 0.5.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 +141 -163
- package/capabilities/cognitive-routing/SKILL.md +387 -0
- package/capabilities/context-virtualization/SKILL.md +103 -0
- package/capabilities/conversation-history/SKILL.md +53 -0
- package/command-surface.json +6 -37
- package/hooks/freeflow-runtime-context.mjs +50 -541
- package/hooks/hooks.json +1 -26
- package/hooks/tests/check-runtime-context-hook.sh +114 -308
- package/package.json +27 -17
- package/pi-extension/dist/cognitive-routing/commands.js +96 -0
- package/pi-extension/dist/cognitive-routing/config.js +232 -0
- package/pi-extension/dist/cognitive-routing/controller.js +1292 -0
- package/pi-extension/dist/cognitive-routing/history.js +451 -0
- package/pi-extension/dist/cognitive-routing/host.js +188 -0
- 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/runtime.js +43 -0
- package/pi-extension/dist/cognitive-routing/tool.js +212 -0
- package/pi-extension/dist/cognitive-routing/types.js +6 -0
- package/pi-extension/dist/context-virtualization/commands.js +89 -0
- package/pi-extension/dist/context-virtualization/projector.js +42 -0
- package/pi-extension/dist/context-virtualization/runtime.js +356 -0
- package/pi-extension/dist/context-virtualization/state.js +57 -0
- package/pi-extension/dist/context-virtualization/types.js +10 -0
- package/pi-extension/dist/conversation-history/passages.js +66 -0
- package/pi-extension/dist/conversation-history/ranking.js +105 -0
- package/pi-extension/dist/conversation-history/runtime.js +226 -0
- package/pi-extension/dist/conversation-history/search.js +56 -0
- package/pi-extension/dist/conversation-history/types.js +1 -0
- package/pi-extension/dist/freeflow-context/resolver.js +120 -0
- package/pi-extension/dist/freeflow-context/runtime.js +80 -0
- package/pi-extension/dist/freeflow-context/source-projector.js +95 -0
- package/pi-extension/dist/freeflow-context/tool.js +308 -0
- package/pi-extension/dist/freeflow-context/types.js +12 -0
- package/pi-extension/dist/freeflow-context/visibility.js +28 -0
- package/pi-extension/dist/index.js +564 -129
- package/pi-extension/dist/runtime/runtime-context.js +357 -470
- package/pi-extension/dist/runtime/runtime-identity.js +5 -0
- package/pi-extension/dist/settings/settings-tui.js +78 -0
- package/pi-extension/dist/settings/settings-ui.js +572 -826
- package/pi-extension/dist/ui/text-component.js +57 -0
- package/pi-extension/src/cognitive-routing/commands.ts +129 -0
- package/pi-extension/src/cognitive-routing/config.ts +303 -0
- package/pi-extension/src/cognitive-routing/controller.ts +1628 -0
- package/pi-extension/src/cognitive-routing/history.ts +650 -0
- package/pi-extension/src/cognitive-routing/host.ts +266 -0
- 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/runtime.ts +57 -0
- package/pi-extension/src/cognitive-routing/tool.ts +273 -0
- package/pi-extension/src/cognitive-routing/types.ts +89 -0
- package/pi-extension/src/context-virtualization/commands.ts +111 -0
- package/pi-extension/src/context-virtualization/projector.ts +62 -0
- package/pi-extension/src/context-virtualization/runtime.ts +406 -0
- package/pi-extension/src/context-virtualization/state.ts +79 -0
- package/pi-extension/src/context-virtualization/types.ts +92 -0
- package/pi-extension/src/conversation-history/passages.ts +81 -0
- package/pi-extension/src/conversation-history/ranking.ts +155 -0
- package/pi-extension/src/conversation-history/runtime.ts +250 -0
- package/pi-extension/src/conversation-history/search.ts +79 -0
- package/pi-extension/src/conversation-history/types.ts +31 -0
- package/pi-extension/src/freeflow-context/resolver.ts +139 -0
- package/pi-extension/src/freeflow-context/runtime.ts +100 -0
- package/pi-extension/src/freeflow-context/source-projector.ts +106 -0
- package/pi-extension/src/freeflow-context/tool.ts +360 -0
- package/pi-extension/src/freeflow-context/types.ts +70 -0
- package/pi-extension/src/freeflow-context/visibility.ts +53 -0
- package/pi-extension/src/index.ts +597 -135
- package/pi-extension/src/runtime/runtime-context.ts +373 -491
- package/pi-extension/src/runtime/runtime-identity.ts +8 -0
- package/pi-extension/src/settings/settings-tui.ts +93 -0
- package/pi-extension/src/settings/settings-ui.ts +679 -910
- package/pi-extension/src/ui/text-component.ts +66 -0
- package/pi-extension/tests/cognitive-routing/commands.test.js +134 -0
- package/pi-extension/tests/cognitive-routing/controller.test.js +1128 -0
- package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +1142 -0
- package/pi-extension/tests/cognitive-routing/history.test.js +274 -0
- package/pi-extension/tests/cognitive-routing/host-fixture.js +4 -0
- package/pi-extension/tests/cognitive-routing/host-identity.test.js +63 -0
- 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 +279 -0
- package/pi-extension/tests/cognitive-routing/tool.test.js +230 -0
- package/pi-extension/tests/context-virtualization/extension.test.js +749 -0
- package/pi-extension/tests/context-virtualization/projector.test.js +110 -0
- package/pi-extension/tests/context-virtualization/runtime.test.js +216 -0
- package/pi-extension/tests/conversation-history/runtime.test.js +98 -0
- package/pi-extension/tests/conversation-history/search.test.js +97 -0
- package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
- package/pi-extension/tests/integration/pi-extension.test.js +532 -3701
- package/pi-extension/tests/integration/prompt-architecture.test.js +350 -0
- package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
- package/runtime/prompts/cognitive-routing.md +10 -0
- package/runtime/prompts/context-virtualization.md +3 -0
- package/runtime/prompts/conversation-history.md +3 -0
- package/runtime/prompts/core.md +84 -0
- package/runtime/prompts/interaction-contract.md +11 -0
- package/skills/action-selection/SKILL.md +140 -0
- package/skills/action-selection/references/trajectory-stalls.md +71 -0
- package/skills/bypass/SKILL.md +109 -38
- 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 +206 -60
- 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 +128 -174
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
- package/skills/diagnose-failure/SKILL.md +200 -48
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +18 -6
- package/skills/diagnose-failure/references/{flaky-and-performance.md → flaky-and-performance-diagnosis.md} +13 -5
- package/skills/discuss/SKILL.md +119 -65
- package/skills/discuss/references/discussion-continuity.md +123 -0
- package/skills/evaluate-skill/SKILL.md +166 -52
- package/skills/evaluate-skill/references/{definition-schema.md → evaluation-definition-schema.md} +43 -3
- package/skills/evaluate-skill/references/evaluation-design.md +56 -30
- package/skills/evaluate-skill/references/execution-and-evidence.md +8 -3
- package/skills/evaluate-skill/references/review-and-revision.md +62 -21
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +114 -3
- package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +156 -1
- package/skills/evaluate-skill/scripts/lib/grade.mjs +9 -1
- package/skills/evaluate-skill/scripts/lib/pi.mjs +147 -32
- package/skills/evaluate-skill/scripts/lib/rpc.mjs +4 -4
- package/skills/evaluate-skill/scripts/lib/runner.mjs +36 -14
- package/skills/evaluate-skill/scripts/lib/sandbox.mjs +92 -0
- package/skills/evaluate-skill/scripts/pi-guard.mjs +1 -1
- package/skills/evaluate-skill/scripts/pi-observer.mjs +66 -0
- package/skills/evaluate-skill/scripts/skill-eval.mjs +6 -5
- package/skills/execute-work/SKILL.md +99 -57
- package/skills/execute-work/references/code-practices.md +4 -4
- package/skills/execute-work/references/execute-work-edges.md +62 -0
- package/skills/finish-branch/SKILL.md +2 -2
- package/skills/finish-branch/references/integration-options.md +1 -1
- package/skills/handoff/SKILL.md +3 -3
- package/skills/launch-work/SKILL.md +1 -1
- package/skills/launch-work/references/launch-readiness.md +2 -2
- package/skills/migration-work/SKILL.md +2 -2
- package/skills/migration-work/references/migration-lifecycle.md +1 -1
- package/skills/release-work/SKILL.md +1 -1
- package/skills/release-work/references/release-evidence.md +1 -1
- package/skills/review-artifact/SKILL.md +129 -66
- package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +159 -0
- package/skills/review-work/SKILL.md +113 -68
- package/skills/review-work/references/adjudicate-work-review.md +97 -0
- package/skills/review-work/references/independent-work-reviewer-contract.md +139 -0
- package/skills/review-work/references/security-risk-lens.md +18 -16
- package/skills/setup-freeflow/SKILL.md +16 -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 +100 -53
- package/skills/tdd/references/test-design.md +3 -3
- package/skills/track-work/SKILL.md +195 -58
- 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 +40 -0
- package/skills/track-work/scripts/working-record.mjs +316 -0
- package/skills/verify-work/SKILL.md +57 -19
- package/skills/verify-work/references/browser-runtime-evidence.md +2 -2
- package/skills/verify-work/references/integration-evidence.md +1 -7
- package/skills/verify-work/references/performance-evidence.md +2 -2
- package/skills/workflow/SKILL.md +137 -55
- package/skills/workflow/references/domain-skill-composition.md +26 -40
- package/skills/write-plan/SKILL.md +1 -1
- package/skills/write-skill/SKILL.md +218 -61
- 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 +97 -33
- package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
- package/capabilities/output-router/SKILL.md +0 -206
- package/capabilities/output-router/references/safety-policy.md +0 -40
- package/capabilities/output-router/references/setup.md +0 -110
- package/pi-extension/dist/output-router/host-producer-identification.js +0 -232
- package/pi-extension/dist/output-router/native-safety-net.js +0 -216
- package/pi-extension/dist/output-router/observed-tool-routing.js +0 -122
- package/pi-extension/dist/output-router/renderers.js +0 -1023
- package/pi-extension/dist/output-router/router-tools.js +0 -554
- package/pi-extension/dist/output-router/schemas.js +0 -383
- package/pi-extension/dist/output-router/status.js +0 -744
- package/pi-extension/dist/output-router/utils.js +0 -502
- package/pi-extension/src/output-router/host-producer-identification.ts +0 -256
- package/pi-extension/src/output-router/native-safety-net.ts +0 -248
- package/pi-extension/src/output-router/observed-tool-routing.ts +0 -134
- package/pi-extension/src/output-router/renderers.ts +0 -1108
- package/pi-extension/src/output-router/router-tools.ts +0 -579
- package/pi-extension/src/output-router/schemas.ts +0 -387
- package/pi-extension/src/output-router/status.ts +0 -791
- package/pi-extension/src/output-router/utils.ts +0 -554
- package/pi-extension/tests/output-router/observed-producers.test.js +0 -132
- package/pi-extension/tests/output-router/search.test.js +0 -722
- package/router/dist/benchmarks/benchmark-harness.d.ts +0 -35
- package/router/dist/benchmarks/benchmark-harness.js +0 -92
- package/router/dist/benchmarks/benchmarks.d.ts +0 -109
- package/router/dist/benchmarks/benchmarks.js +0 -979
- package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +0 -95
- package/router/dist/benchmarks/codex-qa-benchmarks.js +0 -500
- package/router/dist/benchmarks/command-benchmarks.d.ts +0 -143
- package/router/dist/benchmarks/command-benchmarks.js +0 -698
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +0 -82
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +0 -773
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +0 -132
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +0 -1380
- package/router/dist/benchmarks/context-saving-baseline.d.ts +0 -60
- package/router/dist/benchmarks/context-saving-baseline.js +0 -470
- package/router/dist/benchmarks/index-benchmarks.d.ts +0 -103
- package/router/dist/benchmarks/index-benchmarks.js +0 -862
- package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +0 -101
- package/router/dist/benchmarks/storage-policy-benchmarks.js +0 -618
- package/router/dist/benchmarks/vault-index-benchmarks.d.ts +0 -56
- package/router/dist/benchmarks/vault-index-benchmarks.js +0 -322
- package/router/dist/config/config.d.ts +0 -103
- package/router/dist/config/config.js +0 -632
- package/router/dist/config/router-contract.d.ts +0 -10
- package/router/dist/config/router-contract.js +0 -54
- package/router/dist/config/schema.d.ts +0 -27
- package/router/dist/config/schema.js +0 -648
- package/router/dist/config/types.d.ts +0 -573
- package/router/dist/config/types.js +0 -41
- package/router/dist/evidence/bounded-evidence.d.ts +0 -40
- package/router/dist/evidence/bounded-evidence.js +0 -323
- package/router/dist/evidence/evidence-range-selector.d.ts +0 -24
- package/router/dist/evidence/evidence-range-selector.js +0 -232
- package/router/dist/evidence/evidence-search.d.ts +0 -27
- package/router/dist/evidence/evidence-search.js +0 -490
- package/router/dist/evidence/evidence.d.ts +0 -38
- package/router/dist/evidence/evidence.js +0 -200
- package/router/dist/evidence/failure-contracts.d.ts +0 -37
- package/router/dist/evidence/failure-contracts.js +0 -166
- package/router/dist/evidence/line-ranges.d.ts +0 -24
- package/router/dist/evidence/line-ranges.js +0 -22
- package/router/dist/experiments/local-index.d.ts +0 -64
- package/router/dist/experiments/local-index.js +0 -581
- package/router/dist/index.d.ts +0 -30
- package/router/dist/index.js +0 -32
- package/router/dist/local/local-traversal.d.ts +0 -18
- package/router/dist/local/local-traversal.js +0 -334
- package/router/dist/processing/engine.d.ts +0 -132
- package/router/dist/processing/engine.js +0 -533
- package/router/dist/processing/reducers.d.ts +0 -280
- package/router/dist/processing/reducers.js +0 -1673
- package/router/dist/processing/renderers.d.ts +0 -31
- package/router/dist/processing/renderers.js +0 -195
- package/router/dist/processing/scripts.d.ts +0 -91
- package/router/dist/processing/scripts.js +0 -386
- package/router/dist/repo/repo-traversal.d.ts +0 -18
- package/router/dist/repo/repo-traversal.js +0 -245
- package/router/dist/routing/observed-reducers.d.ts +0 -41
- package/router/dist/routing/observed-reducers.js +0 -661
- package/router/dist/routing/observed-routing.d.ts +0 -26
- package/router/dist/routing/observed-routing.js +0 -378
- package/router/dist/routing/parsers.d.ts +0 -16
- package/router/dist/routing/parsers.js +0 -521
- package/router/dist/routing/run-filters.d.ts +0 -60
- package/router/dist/routing/run-filters.js +0 -238
- package/router/dist/routing/run-reducers.d.ts +0 -49
- package/router/dist/routing/run-reducers.js +0 -122
- package/router/dist/sandbox/adapter-roots.d.ts +0 -46
- package/router/dist/sandbox/adapter-roots.js +0 -66
- package/router/dist/sandbox/eryx-python-adapter.d.ts +0 -13
- package/router/dist/sandbox/eryx-python-adapter.js +0 -868
- package/router/dist/sandbox/jq-wasm-adapter.d.ts +0 -9
- package/router/dist/sandbox/jq-wasm-adapter.js +0 -429
- package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +0 -13
- package/router/dist/sandbox/quickjs-wasi-adapter.js +0 -384
- package/router/dist/sandbox/script-sandbox.d.ts +0 -134
- package/router/dist/sandbox/script-sandbox.js +0 -337
- package/router/dist/setup/script-transform-adapters.d.ts +0 -32
- package/router/dist/setup/script-transform-adapters.js +0 -278
- package/router/dist/tools/batch.d.ts +0 -33
- package/router/dist/tools/batch.js +0 -586
- package/router/dist/tools/run.d.ts +0 -62
- package/router/dist/tools/run.js +0 -1304
- package/router/dist/tools/search.d.ts +0 -66
- package/router/dist/tools/search.js +0 -1364
- package/router/dist/transform/engine.d.ts +0 -168
- package/router/dist/transform/engine.js +0 -2072
- package/router/dist/vault/vault-index.d.ts +0 -125
- package/router/dist/vault/vault-index.js +0 -416
- package/router/dist/vault/vault.d.ts +0 -138
- package/router/dist/vault/vault.js +0 -630
- package/runtime/interaction-contract.md +0 -16
- package/skills/discuss/references/checkpoints.md +0 -66
- package/skills/execute-work/references/execution-loop.md +0 -77
- package/skills/mode-contract/SKILL.md +0 -104
- package/skills/review-artifact/references/reviewer-prompt.md +0 -148
- package/skills/review-work/references/reviewer-prompt.md +0 -134
- package/skills/track-work/references/working-record-schema.md +0 -378
- package/skills/workflow/references/workflow-loop.md +0 -92
- /package/skills/handoff/references/{templates.md → handoff-templates.md} +0 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
|
|
9
|
+
import freeflowExtension from "../../dist/index.js";
|
|
10
|
+
import { resetSessionOverrides, setSessionCoreOverride } from "../../dist/runtime/runtime-context.js";
|
|
11
|
+
import { PIFLOW_HOST } from "../cognitive-routing/host-fixture.js";
|
|
12
|
+
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
|
|
15
|
+
const theme = {
|
|
16
|
+
fg(_color, text) {
|
|
17
|
+
return text;
|
|
18
|
+
},
|
|
19
|
+
bold(text) {
|
|
20
|
+
return text;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function context(cwd, options = {}) {
|
|
25
|
+
const notifications = [];
|
|
26
|
+
const reloads = [];
|
|
27
|
+
const statuses = [];
|
|
28
|
+
return {
|
|
29
|
+
cwd,
|
|
30
|
+
notifications,
|
|
31
|
+
reloads,
|
|
32
|
+
statuses,
|
|
33
|
+
mode: options.mode,
|
|
34
|
+
hasUI: options.hasUI,
|
|
35
|
+
isIdle: options.isIdle,
|
|
36
|
+
async reload() {
|
|
37
|
+
reloads.push(true);
|
|
38
|
+
},
|
|
39
|
+
sessionManager: {
|
|
40
|
+
getBranch: () => options.entries ?? [],
|
|
41
|
+
getEntries: () => options.entries ?? [],
|
|
42
|
+
},
|
|
43
|
+
ui: {
|
|
44
|
+
setStatus(name, value) {
|
|
45
|
+
statuses.push({ name, value });
|
|
46
|
+
},
|
|
47
|
+
notify(message, level) {
|
|
48
|
+
notifications.push({ message, level });
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function loadExtension() {
|
|
55
|
+
const handlers = new Map();
|
|
56
|
+
const commands = [];
|
|
57
|
+
const tools = [];
|
|
58
|
+
const pi = {
|
|
59
|
+
host: PIFLOW_HOST,
|
|
60
|
+
registerTool(tool) {
|
|
61
|
+
tools.push(tool);
|
|
62
|
+
},
|
|
63
|
+
registerCommand(name, definition) {
|
|
64
|
+
commands.push({ name, definition });
|
|
65
|
+
},
|
|
66
|
+
registerShortcut() {},
|
|
67
|
+
on(name, handler) {
|
|
68
|
+
handlers.set(name, handler);
|
|
69
|
+
},
|
|
70
|
+
appendEntry() {},
|
|
71
|
+
sendUserMessage() {},
|
|
72
|
+
getAllTools() {
|
|
73
|
+
return tools.map((tool) => ({ name: tool.name }));
|
|
74
|
+
},
|
|
75
|
+
getActiveTools() {
|
|
76
|
+
return tools.map((tool) => tool.name);
|
|
77
|
+
},
|
|
78
|
+
setActiveTools() {},
|
|
79
|
+
};
|
|
80
|
+
freeflowExtension(pi);
|
|
81
|
+
return { handlers, commands, pi };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function configuredRepo(config = {}) {
|
|
85
|
+
const cwd = await mkdtemp(join(tmpdir(), "freeflow-unaffected-regressions-"));
|
|
86
|
+
await mkdir(join(cwd, ".freeflow"));
|
|
87
|
+
await writeFile(join(cwd, ".freeflow/config.json"), JSON.stringify(config, null, 2), "utf8");
|
|
88
|
+
return cwd;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function freeflowCommand(commands) {
|
|
92
|
+
const command = commands.find((candidate) => candidate.name === "freeflow");
|
|
93
|
+
assert.ok(command);
|
|
94
|
+
return command;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
test("non-TUI settings selectors provide guidance without mutation", async () => {
|
|
98
|
+
const cwd = await configuredRepo();
|
|
99
|
+
const configPath = join(cwd, ".freeflow/config.json");
|
|
100
|
+
const original = await readFile(configPath, "utf8");
|
|
101
|
+
try {
|
|
102
|
+
const { commands } = loadExtension();
|
|
103
|
+
const command = freeflowCommand(commands);
|
|
104
|
+
const rpc = context(cwd, { mode: "rpc" });
|
|
105
|
+
rpc.ui.custom = async () => assert.fail("RPC settings must not open the TUI");
|
|
106
|
+
await command.definition.handler("settings", rpc);
|
|
107
|
+
assert.match(rpc.notifications.at(-1).message, /require Pi TUI/);
|
|
108
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
109
|
+
|
|
110
|
+
const print = context(cwd, { mode: "json", hasUI: false });
|
|
111
|
+
await assert.rejects(() => command.definition.handler("settings", print), /require Pi TUI/);
|
|
112
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
113
|
+
} finally {
|
|
114
|
+
await rm(cwd, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("settings refuse a mid-run mutation before opening the TUI", async () => {
|
|
119
|
+
const cwd = await configuredRepo();
|
|
120
|
+
const configPath = join(cwd, ".freeflow/config.json");
|
|
121
|
+
const original = await readFile(configPath, "utf8");
|
|
122
|
+
try {
|
|
123
|
+
const { commands } = loadExtension();
|
|
124
|
+
const command = freeflowCommand(commands);
|
|
125
|
+
const settings = context(cwd, { isIdle: () => false });
|
|
126
|
+
settings.ui.custom = async () => assert.fail("settings UI must not open while Pi is running");
|
|
127
|
+
await command.definition.handler("settings repo", settings);
|
|
128
|
+
assert.match(settings.notifications.at(-1).message, /only while Pi is idle/);
|
|
129
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
130
|
+
} finally {
|
|
131
|
+
await rm(cwd, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("settings recheck idle state before committing a master-switch selection", async () => {
|
|
136
|
+
const cwd = await configuredRepo({ enabled: false });
|
|
137
|
+
const configPath = join(cwd, ".freeflow/config.json");
|
|
138
|
+
const original = await readFile(configPath, "utf8");
|
|
139
|
+
let idle = true;
|
|
140
|
+
try {
|
|
141
|
+
const { commands } = loadExtension();
|
|
142
|
+
const command = freeflowCommand(commands);
|
|
143
|
+
const settings = context(cwd, { isIdle: () => idle });
|
|
144
|
+
settings.ui.custom = async (factory) => {
|
|
145
|
+
let result;
|
|
146
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
147
|
+
result = value;
|
|
148
|
+
});
|
|
149
|
+
idle = false;
|
|
150
|
+
component.handleInput("\r");
|
|
151
|
+
component.handleInput("\u001b[A");
|
|
152
|
+
component.handleInput("\r");
|
|
153
|
+
await component.waitForWrites();
|
|
154
|
+
component.handleInput("\u001b");
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
await command.definition.handler("settings repo", settings);
|
|
158
|
+
assert.match(settings.notifications.at(-1).message, /only while Pi is idle/);
|
|
159
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
160
|
+
} finally {
|
|
161
|
+
await rm(cwd, { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("personal settings keep repository state unchanged while editing context", async () => {
|
|
166
|
+
const cwd = await configuredRepo();
|
|
167
|
+
const configPath = join(cwd, ".freeflow/config.json");
|
|
168
|
+
const original = await readFile(configPath, "utf8");
|
|
169
|
+
try {
|
|
170
|
+
const { commands } = loadExtension();
|
|
171
|
+
const command = freeflowCommand(commands);
|
|
172
|
+
const settings = context(cwd);
|
|
173
|
+
settings.ui.custom = async (factory) => {
|
|
174
|
+
let result;
|
|
175
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
176
|
+
result = value;
|
|
177
|
+
});
|
|
178
|
+
component.handleInput("\u001b[B");
|
|
179
|
+
component.handleInput("\u001b[B");
|
|
180
|
+
component.handleInput("\r");
|
|
181
|
+
component.handleInput("\r");
|
|
182
|
+
component.handleInput("\u001b[B");
|
|
183
|
+
component.handleInput("\r");
|
|
184
|
+
await component.waitForWrites();
|
|
185
|
+
component.handleInput("\u001b");
|
|
186
|
+
component.handleInput("\u001b");
|
|
187
|
+
return result;
|
|
188
|
+
};
|
|
189
|
+
await command.definition.handler("settings", settings);
|
|
190
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
191
|
+
assert.equal(JSON.parse(await readFile(join(cwd, ".freeflow/local.json"), "utf8")).contextVirtualization, true);
|
|
192
|
+
} finally {
|
|
193
|
+
await rm(cwd, { recursive: true, force: true });
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("context settings refresh their parent summary after a child changes", async () => {
|
|
198
|
+
const cwd = await configuredRepo({ contextVirtualization: true });
|
|
199
|
+
try {
|
|
200
|
+
const { commands } = loadExtension();
|
|
201
|
+
const command = freeflowCommand(commands);
|
|
202
|
+
const settings = context(cwd);
|
|
203
|
+
settings.ui.custom = async (factory) => {
|
|
204
|
+
let result;
|
|
205
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
206
|
+
result = value;
|
|
207
|
+
});
|
|
208
|
+
assert.match(component.render(120).join("\n"), /Freeflow Context\s+enabled \(2\) 1\/2 enabled/);
|
|
209
|
+
component.handleInput("\u001b[B");
|
|
210
|
+
component.handleInput("\u001b[B");
|
|
211
|
+
component.handleInput("\r");
|
|
212
|
+
component.handleInput("\r");
|
|
213
|
+
component.handleInput("\u001b[B");
|
|
214
|
+
component.handleInput("\u001b[B");
|
|
215
|
+
component.handleInput("\r");
|
|
216
|
+
await component.waitForWrites();
|
|
217
|
+
component.handleInput("\u001b");
|
|
218
|
+
assert.match(component.render(120).join("\n"), /Freeflow Context\s+disabled \(2\) 0\/2 enabled/);
|
|
219
|
+
component.handleInput("\u001b");
|
|
220
|
+
return result;
|
|
221
|
+
};
|
|
222
|
+
await command.definition.handler("settings", settings);
|
|
223
|
+
const local = JSON.parse(await readFile(join(cwd, ".freeflow/local.json"), "utf8"));
|
|
224
|
+
assert.equal(local.contextVirtualization, false);
|
|
225
|
+
assert.equal(settings.reloads.length, 1);
|
|
226
|
+
} finally {
|
|
227
|
+
await rm(cwd, { recursive: true, force: true });
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("repository settings show personal effective sources without changing shared state", async () => {
|
|
232
|
+
const cwd = await configuredRepo({ contextVirtualization: false });
|
|
233
|
+
const repositoryPath = join(cwd, ".freeflow/config.json");
|
|
234
|
+
const localPath = join(cwd, ".freeflow/local.json");
|
|
235
|
+
try {
|
|
236
|
+
await writeFile(localPath, JSON.stringify({ contextVirtualization: true }, null, 2), "utf8");
|
|
237
|
+
const { commands } = loadExtension();
|
|
238
|
+
const command = freeflowCommand(commands);
|
|
239
|
+
const settings = context(cwd, { isIdle: () => true });
|
|
240
|
+
settings.ui.custom = async (factory) => {
|
|
241
|
+
let result;
|
|
242
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
243
|
+
result = value;
|
|
244
|
+
});
|
|
245
|
+
component.handleInput("\u001b[B");
|
|
246
|
+
component.handleInput("\u001b[B");
|
|
247
|
+
component.handleInput("\r");
|
|
248
|
+
assert.match(component.render(120).join("\n"), /Context Virtualization\s+disabled \(effective enabled · local\)/);
|
|
249
|
+
component.handleInput("\u001b");
|
|
250
|
+
return result;
|
|
251
|
+
};
|
|
252
|
+
await command.definition.handler("settings repo", settings);
|
|
253
|
+
assert.deepEqual(JSON.parse(await readFile(repositoryPath, "utf8")), { contextVirtualization: false });
|
|
254
|
+
assert.deepEqual(JSON.parse(await readFile(localPath, "utf8")), { contextVirtualization: true });
|
|
255
|
+
assert.equal(settings.reloads.length, 0);
|
|
256
|
+
} finally {
|
|
257
|
+
await rm(cwd, { recursive: true, force: true });
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("Cognitive Routing preset cancellation preserves the previous repository value", async () => {
|
|
262
|
+
const cwd = await configuredRepo({
|
|
263
|
+
cognitiveRouting: {
|
|
264
|
+
enabled: true,
|
|
265
|
+
profiles: {
|
|
266
|
+
standard: { provider: "test", model: "model-a", thinkingLevel: "low" },
|
|
267
|
+
reasoning: { provider: "test", model: "model-b", thinkingLevel: "high" },
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
const original = await readFile(join(cwd, ".freeflow/config.json"), "utf8");
|
|
272
|
+
try {
|
|
273
|
+
const { commands } = loadExtension();
|
|
274
|
+
const command = freeflowCommand(commands);
|
|
275
|
+
const settings = context(cwd, { isIdle: () => true });
|
|
276
|
+
settings.modelRegistry = cognitiveRoutingModelRegistry();
|
|
277
|
+
settings.ui.custom = async (factory) => {
|
|
278
|
+
let result;
|
|
279
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
280
|
+
result = value;
|
|
281
|
+
});
|
|
282
|
+
component.handleInput("\u001b[B");
|
|
283
|
+
component.handleInput("\r");
|
|
284
|
+
component.handleInput("\u001b[B");
|
|
285
|
+
component.handleInput("\r");
|
|
286
|
+
component.handleInput("\u001b");
|
|
287
|
+
component.handleInput("\u001b");
|
|
288
|
+
return result;
|
|
289
|
+
};
|
|
290
|
+
await command.definition.handler("settings repo", settings);
|
|
291
|
+
assert.equal(await readFile(join(cwd, ".freeflow/config.json"), "utf8"), original);
|
|
292
|
+
assert.equal(settings.reloads.length, 0);
|
|
293
|
+
} finally {
|
|
294
|
+
await rm(cwd, { recursive: true, force: true });
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("Cognitive Routing settings refresh after enabling the capability", async () => {
|
|
299
|
+
const cwd = await configuredRepo({
|
|
300
|
+
cognitiveRouting: {
|
|
301
|
+
enabled: false,
|
|
302
|
+
profiles: {
|
|
303
|
+
standard: { provider: "test", model: "model-a", thinkingLevel: "low" },
|
|
304
|
+
reasoning: { provider: "test", model: "model-b", thinkingLevel: "high" },
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
try {
|
|
309
|
+
const { commands } = loadExtension();
|
|
310
|
+
const command = freeflowCommand(commands);
|
|
311
|
+
const settings = context(cwd, { isIdle: () => true });
|
|
312
|
+
settings.modelRegistry = cognitiveRoutingModelRegistry();
|
|
313
|
+
settings.ui.custom = async (factory) => {
|
|
314
|
+
let result;
|
|
315
|
+
const component = factory({ requestRender() {} }, theme, {}, (value) => {
|
|
316
|
+
result = value;
|
|
317
|
+
});
|
|
318
|
+
component.handleInput("\u001b[B");
|
|
319
|
+
component.handleInput("\r");
|
|
320
|
+
component.handleInput("\r");
|
|
321
|
+
component.handleInput("\u001b[A");
|
|
322
|
+
component.handleInput("\r");
|
|
323
|
+
await component.waitForWrites();
|
|
324
|
+
component.handleInput("\u001b");
|
|
325
|
+
assert.match(component.render(120).join("\n"), /Cognitive Routing\s+enabled \(5\) configured/);
|
|
326
|
+
component.handleInput("\u001b");
|
|
327
|
+
return result;
|
|
328
|
+
};
|
|
329
|
+
await command.definition.handler("settings repo", settings);
|
|
330
|
+
const saved = JSON.parse(await readFile(join(cwd, ".freeflow/config.json"), "utf8"));
|
|
331
|
+
assert.equal(saved.cognitiveRouting.enabled, true);
|
|
332
|
+
assert.equal(settings.reloads.length, 1);
|
|
333
|
+
} finally {
|
|
334
|
+
await rm(cwd, { recursive: true, force: true });
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("session settings preserve mandatory prompts through compaction and resume", async () => {
|
|
339
|
+
const cwd = await configuredRepo();
|
|
340
|
+
try {
|
|
341
|
+
const { handlers } = loadExtension();
|
|
342
|
+
const ctx = context(cwd);
|
|
343
|
+
const before = await handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
344
|
+
assert.match(before.systemPrompt, /# Freeflow Interaction Contract/);
|
|
345
|
+
await handlers.get("session_compact")({ reason: "manual" }, ctx);
|
|
346
|
+
const afterCompact = await handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
347
|
+
assert.match(afterCompact.systemPrompt, /# Freeflow Interaction Contract/);
|
|
348
|
+
await handlers.get("session_start")({ reason: "resume" }, ctx);
|
|
349
|
+
const afterResume = await handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
350
|
+
assert.match(afterResume.systemPrompt, /# Freeflow Interaction Contract/);
|
|
351
|
+
} finally {
|
|
352
|
+
await rm(cwd, { recursive: true, force: true });
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("retired router-shaped configuration remains inert while core activation works", async () => {
|
|
357
|
+
const cwd = await configuredRepo({ outputRouter: { postToolRouting: "always" } });
|
|
358
|
+
try {
|
|
359
|
+
const { handlers } = loadExtension();
|
|
360
|
+
const ctx = context(cwd);
|
|
361
|
+
const before = await handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
362
|
+
assert.match(before.systemPrompt, /# Freeflow Interaction Contract/);
|
|
363
|
+
assert.doesNotMatch(before.systemPrompt, /Output Router|freeflow_(search|run|batch)/i);
|
|
364
|
+
} finally {
|
|
365
|
+
await rm(cwd, { recursive: true, force: true });
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
test("remaining session overrides apply without changing repository configuration", async () => {
|
|
370
|
+
const cwd = await configuredRepo();
|
|
371
|
+
try {
|
|
372
|
+
const configPath = join(cwd, ".freeflow/config.json");
|
|
373
|
+
const original = await readFile(configPath, "utf8");
|
|
374
|
+
const { pi } = loadExtension();
|
|
375
|
+
const ctx = context(cwd);
|
|
376
|
+
await setSessionCoreOverride("contextVirtualization", true, ctx, pi);
|
|
377
|
+
const state = await import("../../dist/runtime/runtime-context.js").then(({ readCapabilityState }) =>
|
|
378
|
+
readCapabilityState(cwd, undefined, PIFLOW_HOST),
|
|
379
|
+
);
|
|
380
|
+
assert.equal(state.contextVirtualization.effective, true);
|
|
381
|
+
assert.equal(await readFile(configPath, "utf8"), original);
|
|
382
|
+
await resetSessionOverrides(ctx, pi);
|
|
383
|
+
} finally {
|
|
384
|
+
await rm(cwd, { recursive: true, force: true });
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
function cognitiveRoutingModelRegistry() {
|
|
389
|
+
const models = [
|
|
390
|
+
{ provider: "test", id: "model-a", name: "Model A", reasoning: true },
|
|
391
|
+
{ provider: "test", id: "model-b", name: "Model B", reasoning: true },
|
|
392
|
+
];
|
|
393
|
+
const supported = new Map([
|
|
394
|
+
["model-a", new Set(["off", "low", "medium", "high"])],
|
|
395
|
+
["model-b", new Set(["off", "low", "medium", "high", "max"])],
|
|
396
|
+
]);
|
|
397
|
+
return {
|
|
398
|
+
getAvailable() {
|
|
399
|
+
return models;
|
|
400
|
+
},
|
|
401
|
+
find(provider, id) {
|
|
402
|
+
return models.find((model) => model.provider === provider && model.id === id);
|
|
403
|
+
},
|
|
404
|
+
async getApiKeyAndHeaders() {
|
|
405
|
+
return { ok: true };
|
|
406
|
+
},
|
|
407
|
+
clampThinkingLevel(model, level) {
|
|
408
|
+
return supported.get(model.id)?.has(level) ? level : "off";
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## Cognitive Routing Cue
|
|
2
|
+
|
|
3
|
+
Cognitive Routing changes compute only; it never changes Workflow ownership or authority. `Control` and `Profile` in the latest Runtime State report current compute state, not Yield, Delegate, `ACT_BOUNDED`, or boundary state. A Runtime State refresh is host context, not a user interruption, and does not end an active route or `ACT_BOUNDED` scope unless contradicted. Recover routing state from visible records; never infer `Boundary state: NONE`.
|
|
4
|
+
|
|
5
|
+
- **Manual:** the held profile runs the ordinary unsplit Workflow; do not request switching.
|
|
6
|
+
- **Automatic:** each user interaction begins in Reasoning, which owns conversational and user-facing analysis, discussion, decisions, questions, assessment, and reporting. This work needs no route marker.
|
|
7
|
+
|
|
8
|
+
If the full Cognitive Routing skill is not visible, read it before interpreting or acting on the request. Make that read the only environment call; it is not a route transition. If the read fails or is unavailable, stop and report missing context.
|
|
9
|
+
|
|
10
|
+
Once visible, follow the skill's boundary-first execution model. Automatic Standard only executes active Yield or Delegate contracts; at every return condition it writes `YIELD HANDOFF` or `RETURN` and switches to Reasoning. Standard never handles substantive user-facing interaction.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
## Context Virtualization Cue
|
|
2
|
+
|
|
3
|
+
After broad or noisy tool evidence has been safely narrowed, exhausted, or crossed a meaningful activity boundary, use Context Virtualization to keep necessary evidence active and archive residue. Do not archive governing context or exact evidence still needed by current work.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Freeflow Stable Guidance
|
|
2
|
+
|
|
3
|
+
Freeflow is a workflow layer for one active coding agent. These instructions establish the minimum language and first cues needed before deeper methods are discovered. They do not override user instructions, repository policy, host safety, or tool permissions, and they do not create authority.
|
|
4
|
+
|
|
5
|
+
Use the latest Freeflow Runtime State supplied by the host. It refreshes at session start, after context loss, or when displayed state changes; otherwise the existing snapshot may remain visible without re-emission. Treat earlier state as history and use only the Freeflow guidance, skills, and tools exposed for this request.
|
|
6
|
+
|
|
7
|
+
Freeflow's core guidance and the separate Interaction Contract are always delivered together whenever Freeflow is enabled. The Interaction Contract remains a separately editable prompt fragment; it is not an optional capability.
|
|
8
|
+
|
|
9
|
+
## Shared Terms
|
|
10
|
+
|
|
11
|
+
- **Authority envelope:** the requested outcome, permitted effects, covered active evidence generation, and stop condition established by a direct request or still-valid approval.
|
|
12
|
+
- **Passive observation:** inspecting existing evidence or sources without exercising target behavior or intentionally changing task state.
|
|
13
|
+
- **Active evidence generation:** exercising target behavior to produce new evidence, including tests, reproductions, benchmarks, prototypes, instrumentation, and runtime probes.
|
|
14
|
+
- **Mutation or delivery:** changing the repository, durable task or session, or external state.
|
|
15
|
+
- **Bounded activity:** one coherent unit of discussion, preservation, execution, evidence, or judgment that ends in one assessable result.
|
|
16
|
+
- **Current owner:** the one Freeflow activity responsible for carrying the current bounded activity to an assessable result. Methods, lenses, references, domain guidance, tools, and reviewers may support it without taking ownership automatically.
|
|
17
|
+
- **Slice:** one coherent outcome that may span several bounded activities and methods. Track Work gives it durable identity when task memory is needed.
|
|
18
|
+
- **Evidence boundary:** the strongest claim current direct evidence can support. It is established by the observing mechanism, not by intent, authority, or confidence.
|
|
19
|
+
- **Self-review:** after fresh evidence initially supports a bounded result, the producing agent silently checks that supported state once for alignment, correctness, suitability, and unnecessary complexity before accepting or reusing it. A corrected state receives only the affected recheck. Self-review is not independent review.
|
|
20
|
+
- **Independent review:** separately selected judgment from a context that did not produce the reviewed state. It reports without editing and does not authorize correction.
|
|
21
|
+
- **Checkpoint:** a deliberately selected boundary that dependent work must not cross unresolved. It may require a decision, review, preservation action, or delivery result. An activity ending or work pausing does not create one automatically.
|
|
22
|
+
- **Re-entry:** return only to the narrowest current owner whose responsibility changed, preserving valid work, decisions, and evidence.
|
|
23
|
+
- **Supported Exit:** the justified end of the current Interaction Lifecycle: an evidence-supported answer, wait, pause, handoff, deferment, controlled boundary, stop, or completion, with material limits and unresolved state made explicit.
|
|
24
|
+
|
|
25
|
+
One Interaction Lifecycle may contain several bounded activities. A Slice may span several bounded activities and methods. Each bounded activity has one current owner and may contain several environment interactions.
|
|
26
|
+
|
|
27
|
+
## Recover After Context Loss
|
|
28
|
+
|
|
29
|
+
After compaction, summarization, clear, resume, session navigation, handoff, or uncertain continuity, pause task-directed work. Until recovery is complete, use the environment only for bounded reads needed to recover current state.
|
|
30
|
+
|
|
31
|
+
Treat summaries, records, prior skill reads, transition results, and historical messages as memory. They may preserve still-valid context and authority, but they do not create or widen authority, prove live state, keep a method active, or settle current ownership. Current user direction, live source truth, and the latest Freeflow Runtime State take precedence when they conflict.
|
|
32
|
+
|
|
33
|
+
Before continuing:
|
|
34
|
+
|
|
35
|
+
- Require the latest Freeflow Runtime State. If it is absent, stale, conflicting, or inconsistent with the exposed skills and tools, do not infer it.
|
|
36
|
+
- Read each relevant active capability skill before relying on or changing that capability.
|
|
37
|
+
- When ongoing work has or may have a Working Record, read Track Work and recover its `resume` view before task work.
|
|
38
|
+
- Identify the current owner. Read Workflow when authority, ownership, route, or continuity is unclear, then read the owner’s skill when its exact method is absent.
|
|
39
|
+
- Recover the current Slice, route or execution boundary, blockers, checkpoints, evidence boundary, partial effects, and stop condition without inventing missing state.
|
|
40
|
+
|
|
41
|
+
Resume only when authority, ownership, current work, route, evidence requirements, and the stop condition are coherent. Otherwise inspect the missing source, ask, defer, or stop.
|
|
42
|
+
|
|
43
|
+
## Three Nested Loops
|
|
44
|
+
|
|
45
|
+
One user-facing **Interaction Lifecycle** runs from Entry to a Feedback Loop when needed to a Supported Exit. A later user turn or new evidence begins another lifecycle.
|
|
46
|
+
|
|
47
|
+
For each bounded activity, the **Feedback Loop** is:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
Orient
|
|
51
|
+
-> choose one current owner
|
|
52
|
+
-> use the current owner
|
|
53
|
+
-> gather or produce evidence
|
|
54
|
+
-> determine what the result proves
|
|
55
|
+
-> self-review the supported result
|
|
56
|
+
-> continue, correct, re-enter, ask, defer, stop, or exit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
When the current owner must touch the environment, the **Environment Interaction Loop** is:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Need evidence or a covered effect
|
|
63
|
+
-> select and bound one environment action
|
|
64
|
+
-> choose the tool
|
|
65
|
+
-> execute once
|
|
66
|
+
-> observe
|
|
67
|
+
-> identify what changed
|
|
68
|
+
-> reconcile observation residency when available
|
|
69
|
+
-> return to the current owner
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The Environment Interaction Loop may run zero or more times inside one Feedback Loop. It never changes the current owner or authority by itself.
|
|
73
|
+
|
|
74
|
+
## Workflow Cue
|
|
75
|
+
|
|
76
|
+
Workflow owns authority interpretation and enforcement, one current owner for the current bounded activity, evidence-driven re-entry, and Supported Exit. A direct request covers only its bounded outcome and entailed tools, checks, and reversible local choices. Before uncovered active evidence generation, mutation, delivery, or another separately controlled action, state the purpose, action, expected result, and stop condition; ask once and wait. Freeflow guidance, memory, reviews, and new evidence do not grant authority.
|
|
77
|
+
|
|
78
|
+
## Action Selection Cue
|
|
79
|
+
|
|
80
|
+
Before an uncertain, broad, or repeated environment interaction, use Action Selection to choose and bound one useful action. Return its observation and state change to the current owner. An obvious mechanical and directly verifiable action takes the fast path without manufactured alternatives.
|
|
81
|
+
|
|
82
|
+
## Supported Exit
|
|
83
|
+
|
|
84
|
+
Reach a Supported Exit when current evidence and authority support the reported answer, wait, pause, deferment, controlled boundary, stop, or completion; required self-review and selected checkpoints are resolved where applicable; task memory and required artifacts are accurate; and no material contradiction, source conflict, or user-owned decision remains hidden. Report the outcome, evidence, limits, and current route.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Freeflow Interaction Contract
|
|
2
|
+
|
|
3
|
+
Work as a collaborative senior engineer. Read the whole user turn before responding. Treat the user’s goals and choices as theirs, and judge factual and technical claims from evidence: agree when supported, disagree when warranted, state uncertainty plainly, and revise when evidence changes.
|
|
4
|
+
|
|
5
|
+
Questions, criticism, examples, hypotheses, and tentative ideas do not authorize action by themselves.
|
|
6
|
+
|
|
7
|
+
When a turn combines a direct question with a requested action, answer the question first. If the answer leaves the action clear, supported, and explicitly authorized, proceed in the same response. If the answer could change the user’s choice, expose a source conflict, or leave the action conditional, answer and wait.
|
|
8
|
+
|
|
9
|
+
With a clear action request, recommend brief discussion only when user input could materially change the outcome, scope, tradeoffs, approach, or acceptance. Otherwise stay within the request and current authority envelope, choose reversible local details, and proceed. Ask before going beyond the request.
|
|
10
|
+
|
|
11
|
+
Use Freeflow terminology in user-facing responses only when it materially improves clarity. Otherwise speak in ordinary engineering language.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "action-selection"
|
|
3
|
+
description: "Use when the current owner needs to choose, bound, or learn from an environment interaction, especially when several actions are plausible, expected output may be broad or noisy, or recent interactions have not materially changed the current decision."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Action Selection
|
|
7
|
+
|
|
8
|
+
Choose one covered environment interaction likely to advance the current question or accepted outcome, learn from its actual result, and return the changed evidence to the current owner.
|
|
9
|
+
|
|
10
|
+
An **environment interaction** is one bounded tool-mediated observation or effect and the result it returns. A bounded activity may contain several environment interactions.
|
|
11
|
+
|
|
12
|
+
Action Selection does not choose the current owner, execution method, accepted behavior, authority, Slice, checkpoint, or Workflow route. It does not replace implementation, diagnosis, verification, review, or domain guidance.
|
|
13
|
+
|
|
14
|
+
## Run One Interaction Loop
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
Need evidence or a covered effect
|
|
18
|
+
-> name what this interaction must resolve or produce
|
|
19
|
+
-> check whether current evidence supports one obvious action
|
|
20
|
+
-> yes: fast path
|
|
21
|
+
-> no: branch mentally
|
|
22
|
+
-> choose and bound one environment action
|
|
23
|
+
-> execute once
|
|
24
|
+
-> observe the actual result
|
|
25
|
+
-> identify what changed
|
|
26
|
+
-> return the observation and state change to the current owner
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Action Selection improves one local interaction. It does not plan the whole task or simulate a long future trajectory.
|
|
30
|
+
|
|
31
|
+
## Take The Fast Path When The Action Is Obvious
|
|
32
|
+
|
|
33
|
+
Use the direct tool when current evidence supports one known, mechanical, covered, and directly verifiable interaction.
|
|
34
|
+
|
|
35
|
+
The fast path is not the first plausible action. Use it only when choosing the target, hypothesis, observer, effect, and scope requires no unresolved material judgment.
|
|
36
|
+
|
|
37
|
+
Typical fast-path interactions include:
|
|
38
|
+
|
|
39
|
+
- reading a known file, symbol, range, or artifact;
|
|
40
|
+
- applying an already selected exact edit;
|
|
41
|
+
- running the exact focused check required by the current method;
|
|
42
|
+
- formatting an accepted changed file;
|
|
43
|
+
- inspecting a known diff or generated result.
|
|
44
|
+
|
|
45
|
+
Do not generate alternatives for an obvious continuation.
|
|
46
|
+
|
|
47
|
+
An action is not obvious merely because it is easy to execute. Choosing where to search, which hypothesis to test, what boundary to observe, or what effect to apply normally requires the branch path when several materially different choices remain.
|
|
48
|
+
|
|
49
|
+
## Branch Mentally, Execute Once
|
|
50
|
+
|
|
51
|
+
Use the branch path when:
|
|
52
|
+
|
|
53
|
+
- several actions are plausible;
|
|
54
|
+
- the relevant target, hypothesis, observer, or scope is unsettled;
|
|
55
|
+
- the likely interaction is broad, noisy, destructive, expensive, or difficult to recover;
|
|
56
|
+
- recent interactions have not materially changed the current question or accepted outcome.
|
|
57
|
+
|
|
58
|
+
Before touching the environment:
|
|
59
|
+
|
|
60
|
+
1. name the question or concrete effect the next interaction must resolve or produce;
|
|
61
|
+
2. check whether active evidence already answers it;
|
|
62
|
+
3. consider only a few materially different actions—not synonyms of the same search or observer;
|
|
63
|
+
4. reject actions that repeat unchanged evidence, revisit an eliminated path, or gather information without a current question;
|
|
64
|
+
5. prefer the action most directly connected to the question;
|
|
65
|
+
6. among similarly direct actions, prefer one that distinguishes the leading alternatives;
|
|
66
|
+
7. among similarly discriminating actions, prefer the narrowest interaction with proportionate output, side effects, context residue, and recovery cost;
|
|
67
|
+
8. execute only the selected interaction and decide again from reality.
|
|
68
|
+
|
|
69
|
+
Keep this comparison internal unless it exposes a user-owned decision. Do not produce candidate tables, assign numeric scores, simulate several environment results, or plan multiple interactions before the first observation.
|
|
70
|
+
|
|
71
|
+
## Prefer Decision-Bearing Actions
|
|
72
|
+
|
|
73
|
+
A **decision-bearing action** produces a result that changes what the current owner should believe or do whether it supports or contradicts the leading hypothesis.
|
|
74
|
+
|
|
75
|
+
Among actions already covered by the current route, authority, and any active execution contract, prefer one that:
|
|
76
|
+
|
|
77
|
+
- bears directly on the current question or accepted outcome;
|
|
78
|
+
- distinguishes meaningful alternatives;
|
|
79
|
+
- uses the narrowest sufficient observer or effect;
|
|
80
|
+
- avoids unchanged evidence, eliminated paths, and equivalent prior interactions;
|
|
81
|
+
- produces a clear next branch under both favorable and unfavorable results;
|
|
82
|
+
- keeps expected observation volume, context residue, side effects, reversibility, and recovery cost proportionate.
|
|
83
|
+
|
|
84
|
+
Do not calculate a numeric value. Use these properties to reject low-value branches and select one useful interaction.
|
|
85
|
+
|
|
86
|
+
The objective is not maximal information. It is the smallest observation or effect capable of changing the decision.
|
|
87
|
+
|
|
88
|
+
## Shape The Environment Action
|
|
89
|
+
|
|
90
|
+
Match the action and tool to the required relationship:
|
|
91
|
+
|
|
92
|
+
- when the entity, artifact, location, or range is known, use a focused operation;
|
|
93
|
+
- when ownership, callers, dependencies, or structure are the question, use the most structured relationship query available;
|
|
94
|
+
- when the target is literal, generated, or dynamically referenced, use bounded text or content search;
|
|
95
|
+
- when behavior is the question, use the smallest direct test, runtime observer, or reproduction that exercises the required boundary;
|
|
96
|
+
- when an exact covered effect has already been selected, use the narrowest direct mutation operation;
|
|
97
|
+
- when the relevant entity is genuinely unknown, use one bounded broad discovery action, then narrow from its result instead of restarting breadth.
|
|
98
|
+
|
|
99
|
+
These rules apply across repositories, filesystems, local processes, browsers, databases, APIs, and other environments. Use environment-specific guidance when available.
|
|
100
|
+
|
|
101
|
+
Bound the directory, entity, pattern, range, test target, time window, result count, requested fields, affected state, or recovery scope when the tool supports it.
|
|
102
|
+
|
|
103
|
+
Tool sophistication is not evidence quality. Choose the simplest available operation that can establish the required boundary.
|
|
104
|
+
|
|
105
|
+
## Update From Reality
|
|
106
|
+
|
|
107
|
+
After execution, identify:
|
|
108
|
+
|
|
109
|
+
- what fact, hypothesis, path, effect, or task state changed;
|
|
110
|
+
- what became stronger, weaker, eliminated, contradicted, or still unresolved;
|
|
111
|
+
- whether the interaction answered the current question or produced the intended effect;
|
|
112
|
+
- what next branch, if any, is now supported.
|
|
113
|
+
|
|
114
|
+
New information is not automatically decision-relevant information.
|
|
115
|
+
|
|
116
|
+
If the observation did not change the decision or distinguish alternatives, do not repeat it through synonyms, nearby files, a wider version of the same search, or another tool returning equivalent evidence. Reframe the question, choose a different observer class, or stop with the missing evidence.
|
|
117
|
+
|
|
118
|
+
When two or more recent interactions have not materially changed the current question, advanced the covered effect, or supported a new branch, read [Trajectory Stalls](references/trajectory-stalls.md) before another interaction.
|
|
119
|
+
|
|
120
|
+
Repeat the loop only while the same current owner, question, authority, and execution contract remain valid and each interaction either changes the decision surface or advances the exact covered effect.
|
|
121
|
+
|
|
122
|
+
## Return To The Current Owner
|
|
123
|
+
|
|
124
|
+
Return the observation and its material state change to the activity that requested it. Action Selection does not interpret another method’s final claim or return directly to a compute profile.
|
|
125
|
+
|
|
126
|
+
When an active execution contract exists, stop when its return condition is met. Do not reinterpret or expand the contract to keep interacting.
|
|
127
|
+
|
|
128
|
+
Return to [Workflow](../workflow/SKILL.md) when the result changes authority, accepted scope, current ownership, accepted direction, the required observing boundary, or stop conditions.
|
|
129
|
+
|
|
130
|
+
Use [Diagnose Failure](../diagnose-failure/SKILL.md) when repeated failure remains unexplained rather than selecting another speculative interaction.
|
|
131
|
+
|
|
132
|
+
Stop when:
|
|
133
|
+
|
|
134
|
+
- one next action is sufficiently supported;
|
|
135
|
+
- the requested effect was produced;
|
|
136
|
+
- no covered interaction can reduce the important uncertainty;
|
|
137
|
+
- the active execution contract requires return;
|
|
138
|
+
- another activity now owns the problem.
|
|
139
|
+
|
|
140
|
+
The objective is not fewer tool calls at any cost. It is fewer low-value interactions while preserving supported outcomes.
|