@hassangameryt/freeflow 0.8.0 → 0.9.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/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +96 -149
- package/capabilities/cognitive-routing/SKILL.md +21 -129
- package/capabilities/cognitive-routing/references/coordinator.md +163 -0
- package/capabilities/cognitive-routing/references/worker.md +38 -0
- package/capabilities/compaction/SKILL.md +3 -3
- package/capabilities/compaction/references/summary-format.md +26 -15
- package/capabilities/messaging/SKILL.md +49 -0
- package/capabilities/task-memory/SKILL.md +87 -0
- package/command-surface.json +6 -54
- package/gemini-extension.json +1 -1
- package/hooks/claude/hooks.json +13 -3
- package/hooks/codex/hooks.json +2 -1
- package/hooks/shared/runtime-context.mjs +69 -77
- package/package.json +25 -8
- package/pi-extension/dist/ask-user/ask.js +108 -0
- package/pi-extension/dist/ask-user/form.js +250 -0
- package/pi-extension/dist/ask-user/questions.js +66 -0
- package/pi-extension/dist/ask-user/tool.js +124 -0
- package/pi-extension/dist/cognitive-routing/assembler.js +35 -11
- package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
- package/pi-extension/dist/cognitive-routing/config.js +3 -4
- package/pi-extension/dist/cognitive-routing/event-store.js +4 -1
- package/pi-extension/dist/cognitive-routing/gate.js +20 -5
- package/pi-extension/dist/cognitive-routing/handlers.js +15 -13
- package/pi-extension/dist/cognitive-routing/model-control.js +17 -8
- package/pi-extension/dist/cognitive-routing/projection.js +23 -6
- package/pi-extension/dist/cognitive-routing/provenance.js +3 -1
- package/pi-extension/dist/cognitive-routing/render.js +15 -15
- package/pi-extension/dist/cognitive-routing/runtime.js +4 -2
- package/pi-extension/dist/cognitive-routing/schemas.js +4 -4
- package/pi-extension/dist/cognitive-routing/session.js +3 -1
- package/pi-extension/dist/cognitive-routing/sources.js +29 -4
- package/pi-extension/dist/cognitive-routing/state.js +18 -8
- package/pi-extension/dist/cognitive-routing/status.js +4 -3
- package/pi-extension/dist/cognitive-routing/tools.js +29 -15
- package/pi-extension/dist/cognitive-routing/types.js +10 -1
- package/pi-extension/dist/compaction/carry.js +36 -22
- package/pi-extension/dist/compaction/config.js +4 -2
- package/pi-extension/dist/compaction/controller.js +52 -29
- package/pi-extension/dist/compaction/harness.js +19 -3
- package/pi-extension/dist/compaction/results.js +14 -13
- package/pi-extension/dist/compaction/tool.js +6 -6
- package/pi-extension/dist/host/catalog.js +20 -35
- package/pi-extension/dist/host/config-validation.js +233 -0
- package/pi-extension/dist/host/config.js +78 -91
- package/pi-extension/dist/host/inbound.js +142 -0
- package/pi-extension/dist/host/projection-tags.js +1 -1
- package/pi-extension/dist/host/prompts.js +24 -13
- package/pi-extension/dist/host/read-only-session.js +6 -1
- package/pi-extension/dist/host/request-history.js +7 -3
- package/pi-extension/dist/host/rows.js +25 -0
- package/pi-extension/dist/host/runtime-state.js +17 -2
- package/pi-extension/dist/host/section-keeper.js +85 -0
- package/pi-extension/dist/host/settings/freeflow-command.js +846 -93
- package/pi-extension/dist/host/settings/settings-view.js +27 -8
- package/pi-extension/dist/host/status.js +19 -5
- package/pi-extension/dist/index.js +638 -72
- package/pi-extension/dist/messaging/config.js +27 -0
- package/pi-extension/dist/messaging/messaging.js +398 -0
- package/pi-extension/dist/messaging/registry.js +57 -0
- package/pi-extension/dist/messaging/render.js +90 -0
- package/pi-extension/dist/messaging/tools.js +109 -0
- package/pi-extension/dist/messaging/transport.js +101 -0
- package/pi-extension/dist/provider-support/cache/keepalive.js +16 -4
- package/pi-extension/dist/task-memory/config.js +49 -0
- package/pi-extension/dist/task-memory/registry.js +119 -0
- package/pi-extension/dist/task-memory/render.js +107 -0
- package/pi-extension/dist/task-memory/runtime.js +994 -0
- package/pi-extension/dist/task-memory/tool.js +233 -0
- package/pi-extension/dist/tool-execution/apply-patch/tool.js +1 -1
- package/pi-extension/dist/tool-execution/background.js +220 -28
- package/pi-extension/dist/tool-execution/config.js +14 -3
- package/pi-extension/dist/tool-execution/file-tracking.js +24 -4
- package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
- package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
- package/pi-extension/dist/tool-execution/tools.js +2 -2
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/runtime/prompts/core.md +24 -14
- package/runtime/prompts/interaction-contract.md +7 -4
- package/runtime/prompts/tool-execution.md +3 -16
- package/runtime/prompts/working-method.md +16 -99
- package/skills/deliver-work/SKILL.md +76 -0
- package/skills/deliver-work/references/branch-closeout.md +134 -0
- package/skills/deliver-work/references/commit.md +83 -0
- package/skills/deliver-work/references/launch.md +94 -0
- package/skills/deliver-work/references/release.md +85 -0
- package/skills/deliver-work/scripts/commit-state.mjs +139 -0
- package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
- package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
- package/skills/deliver-work/scripts/push-route.mjs +122 -0
- package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
- package/skills/discuss-work/SKILL.md +148 -0
- package/skills/{discuss → discuss-work}/references/discussion-continuity.md +10 -27
- package/skills/discuss-work/references/learning-action.md +36 -0
- package/skills/discuss-work/scripts/choices.mjs +101 -0
- package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
- package/skills/evaluate-behavior/SKILL.md +107 -0
- package/skills/evaluate-behavior/references/authoring.md +381 -0
- package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
- package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
- package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
- package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
- package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
- package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
- package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
- package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
- package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
- package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
- package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
- package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
- package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
- package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
- package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
- package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
- package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
- package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
- package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
- package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
- package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
- package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
- package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
- package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
- package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
- package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
- package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
- package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
- package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +119 -14
- package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
- package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
- package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
- package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
- package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
- package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
- package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +235 -265
- package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
- package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
- package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
- package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +159 -18
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-command-tool.mjs +21 -6
- package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
- package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
- package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
- package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
- package/skills/execute-work/SKILL.md +96 -104
- package/skills/execute-work/references/code-practices.md +27 -51
- package/skills/execute-work/references/design.md +271 -0
- package/skills/execute-work/references/diagnose.md +117 -0
- package/skills/execute-work/references/migration.md +108 -0
- package/skills/execute-work/references/simplify.md +65 -0
- package/skills/execute-work/scripts/self-review.mjs +422 -0
- package/skills/execute-work/scripts/touch-map.mjs +290 -0
- package/skills/review-work/SKILL.md +89 -65
- package/skills/review-work/references/adjudication.md +94 -0
- package/skills/review-work/references/artifact.md +198 -0
- package/skills/review-work/references/evals-and-judges.md +66 -0
- package/skills/review-work/references/work.md +177 -0
- package/skills/review-work/scripts/check-brief.mjs +128 -0
- package/skills/review-work/scripts/review-packet.mjs +233 -0
- package/skills/setup-freeflow/SKILL.md +68 -17
- package/skills/track-work/SKILL.md +52 -20
- package/skills/track-work/references/handoff.md +190 -0
- package/skills/track-work/references/projects.md +51 -0
- package/skills/track-work/references/working-record-format.md +36 -18
- package/skills/track-work/scripts/lib/document.mjs +17 -13
- package/skills/track-work/scripts/lib/format.mjs +2 -0
- package/skills/track-work/scripts/lib/recover.mjs +254 -0
- package/skills/track-work/scripts/lib/registry.mjs +656 -0
- package/skills/track-work/scripts/lib/search.mjs +40 -0
- package/skills/track-work/scripts/lib/store.mjs +46 -15
- package/skills/track-work/scripts/lib/views.mjs +50 -1
- package/skills/track-work/scripts/working-record.mjs +232 -13
- package/skills/verify-work/SKILL.md +45 -37
- package/skills/verify-work/references/feature-map.md +120 -0
- package/skills/verify-work/references/runtime-evidence.md +203 -0
- package/skills/verify-work/references/test-design.md +25 -6
- package/skills/verify-work/scripts/test-changes.mjs +246 -0
- package/skills/write-docs/SKILL.md +113 -25
- package/skills/write-docs/references/documentation-shapes.md +68 -3
- package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
- package/skills/write-docs/scripts/artifact-check.mjs +148 -0
- package/skills/write-docs/scripts/docs-check.mjs +96 -6
- package/skills/write-docs/scripts/plan-lint.mjs +123 -0
- package/skills/write-skill/SKILL.md +92 -52
- package/skills/write-skill/references/activation-and-wording.md +143 -0
- package/skills/write-skill/references/placement-and-dependencies.md +154 -0
- package/skills/write-skill/scripts/lib/compare.mjs +701 -0
- package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
- package/skills/write-skill/scripts/skill-author.mjs +51 -8
- package/capabilities/cognitive-routing/references/both-mode.md +0 -36
- package/capabilities/cognitive-routing/references/executor-mode.md +0 -48
- package/capabilities/cognitive-routing/references/helper-mode.md +0 -47
- package/plugin.json +0 -33
- package/skills/action-selection/SKILL.md +0 -92
- package/skills/action-selection/references/trajectory-stalls.md +0 -73
- package/skills/bypass/SKILL.md +0 -153
- package/skills/commit-work/SKILL.md +0 -93
- package/skills/commit-work/references/git-state-edges.md +0 -94
- package/skills/commit-work/references/simple-push.md +0 -94
- package/skills/commit-work/references/staging-decisions.md +0 -106
- package/skills/decision-gate/SKILL.md +0 -87
- package/skills/design-for-depth/SKILL.md +0 -108
- package/skills/design-for-depth/references/design-pressure-signals.md +0 -84
- package/skills/design-for-depth/references/implementation-decisions.md +0 -76
- package/skills/design-for-depth/references/interface-design-loop.md +0 -105
- package/skills/design-for-depth/references/module-and-dependency-design.md +0 -117
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -125
- package/skills/diagnose-failure/SKILL.md +0 -140
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -50
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
- package/skills/discuss/SKILL.md +0 -140
- package/skills/evaluate-skill/SKILL.md +0 -188
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -415
- package/skills/evaluate-skill/references/evaluation-design.md +0 -112
- package/skills/evaluate-skill/references/execution-and-evidence.md +0 -111
- package/skills/evaluate-skill/references/review-and-revision.md +0 -94
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -448
- package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
- package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
- package/skills/evaluate-skill/scripts/lib/review.mjs +0 -196
- package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -405
- package/skills/evaluate-skill/scripts/lib/trials.mjs +0 -103
- package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -181
- package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -182
- package/skills/execute-work/references/execute-work-edges.md +0 -78
- package/skills/finish-branch/SKILL.md +0 -117
- package/skills/finish-branch/references/integration-options.md +0 -80
- package/skills/handoff/SKILL.md +0 -82
- package/skills/handoff/references/handoff-templates.md +0 -150
- package/skills/launch-work/SKILL.md +0 -116
- package/skills/launch-work/references/launch-readiness.md +0 -85
- package/skills/migration-work/SKILL.md +0 -115
- package/skills/migration-work/references/migration-lifecycle.md +0 -82
- package/skills/release-work/SKILL.md +0 -118
- package/skills/release-work/references/release-evidence.md +0 -78
- package/skills/review-artifact/SKILL.md +0 -143
- package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
- package/skills/review-work/references/adjudicate-work-review.md +0 -97
- package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
- package/skills/review-work/references/security-risk-lens.md +0 -67
- package/skills/setup-freeflow/references/activation-contract.md +0 -103
- package/skills/setup-freeflow/references/host-setup.md +0 -67
- package/skills/simplify-code/SKILL.md +0 -85
- package/skills/simplify-code/references/simplification-patterns.md +0 -70
- package/skills/verify-work/references/browser-runtime-evidence.md +0 -51
- package/skills/verify-work/references/integration-evidence.md +0 -49
- package/skills/verify-work/references/performance-evidence.md +0 -59
- package/skills/workflow/SKILL.md +0 -171
- package/skills/workflow/references/domain-skill-composition.md +0 -45
- package/skills/write-plan/SKILL.md +0 -92
- package/skills/write-plan/references/plan-shapes.md +0 -156
- package/skills/write-skill/references/activation-boundaries.md +0 -106
- package/skills/write-skill/references/agent-first-instructions.md +0 -133
- package/skills/write-skill/references/progressive-disclosure.md +0 -129
- package/skills/write-skill/references/skill-dependency-graphs.md +0 -192
- package/skills/write-spec/SKILL.md +0 -85
- package/skills/write-spec/references/artifact-standards.md +0 -86
- package/skills/write-spec/references/decision-records.md +0 -80
- package/skills/write-spec/references/spec-shapes.md +0 -143
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
rewriteEditError,
|
|
12
12
|
writeRefusal,
|
|
13
13
|
} from "./edit-messages.js";
|
|
14
|
+
import { SkillReads } from "./skill-reads.js";
|
|
14
15
|
import { cachedBranch } from "../host/branch.js";
|
|
15
16
|
function existingFile(path, cwd) {
|
|
16
17
|
try {
|
|
@@ -33,7 +34,8 @@ function shown(path, cwd) {
|
|
|
33
34
|
}
|
|
34
35
|
return path;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
/** A tool result's content with lines appended to its text (before delivery: nothing already sent changes). */
|
|
38
|
+
export function withLines(content, lines) {
|
|
37
39
|
const text = content.map((part) => (part?.type === "text" ? part.text : "")).join("");
|
|
38
40
|
return [
|
|
39
41
|
{ type: "text", text: [text, ...lines].filter(Boolean).join("\n") },
|
|
@@ -42,21 +44,29 @@ function withLines(content, lines) {
|
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
44
46
|
* Claude Code's file awareness around Pi's read, edit and write: refuse a whole-file write over a file never read,
|
|
45
|
-
* say when an edited file changed since it was read,
|
|
46
|
-
* (codemode) are handled like
|
|
47
|
+
* say when an edited file changed since it was read, turn edit errors into one next action, and answer a repeat
|
|
48
|
+
* read of a Freeflow instruction file the model already holds with one line. Nested calls (codemode) are handled like
|
|
49
|
+
* direct ones, except that a nested read is never answered for the model: the script consumes its text.
|
|
47
50
|
*/
|
|
48
51
|
export class FileTracking {
|
|
49
52
|
state = new FileState();
|
|
50
53
|
changed = new Map();
|
|
54
|
+
skillReads = new SkillReads();
|
|
51
55
|
built = false;
|
|
52
56
|
reset() {
|
|
53
57
|
this.state.reset();
|
|
54
58
|
this.changed.clear();
|
|
59
|
+
this.skillReads.reset();
|
|
55
60
|
this.built = false;
|
|
56
61
|
}
|
|
57
62
|
/** Forget the branch's files; they are rebuilt from the new branch before the next tool call. */
|
|
58
63
|
invalidate() {
|
|
59
64
|
this.built = false;
|
|
65
|
+
this.skillReads.invalidate();
|
|
66
|
+
}
|
|
67
|
+
/** After Pi's own compaction the files are unchanged, but the instruction files read before it are out of view. */
|
|
68
|
+
piCompacted() {
|
|
69
|
+
this.skillReads.clear();
|
|
60
70
|
}
|
|
61
71
|
clearPending() {
|
|
62
72
|
this.changed.clear();
|
|
@@ -67,6 +77,12 @@ export class FileTracking {
|
|
|
67
77
|
this.changed.clear();
|
|
68
78
|
for (const path of carried) await this.state.observe(path, ctx.cwd, "read");
|
|
69
79
|
this.built = true;
|
|
80
|
+
this.skillReads.clear();
|
|
81
|
+
}
|
|
82
|
+
/** Freeflow skills the model holds in this context, by name; reads are rebuilt from the branch when needed. */
|
|
83
|
+
loadedSkills(ctx) {
|
|
84
|
+
if (!this.skillReads.built) this.skillReads.rebuild(cachedBranch(ctx.sessionManager) ?? [], ctx.cwd);
|
|
85
|
+
return this.skillReads.skills();
|
|
70
86
|
}
|
|
71
87
|
/** The branch's file state for apply_patch, built when needed. */
|
|
72
88
|
async forPatch(ctx) {
|
|
@@ -79,6 +95,7 @@ export class FileTracking {
|
|
|
79
95
|
for (const path of paths) await this.state.observe(path, ctx.cwd, "apply_patch");
|
|
80
96
|
}
|
|
81
97
|
async ensureBuilt(ctx) {
|
|
98
|
+
if (!this.skillReads.built) this.skillReads.rebuild(cachedBranch(ctx.sessionManager) ?? [], ctx.cwd);
|
|
82
99
|
if (this.built) return;
|
|
83
100
|
await this.state.rebuild(cachedBranch(ctx.sessionManager) ?? [], ctx.cwd);
|
|
84
101
|
this.built = true;
|
|
@@ -131,7 +148,10 @@ export class FileTracking {
|
|
|
131
148
|
return rewritten === undefined ? undefined : { content: [{ type: "text", text: rewritten }] };
|
|
132
149
|
}
|
|
133
150
|
await this.state.observe(path, ctx.cwd, name);
|
|
134
|
-
if (name === "read")
|
|
151
|
+
if (name === "read") {
|
|
152
|
+
this.skillReads.observe(event, ctx.cwd);
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
135
155
|
const lines =
|
|
136
156
|
name === "edit"
|
|
137
157
|
? [...(changed ? [changedAfterEdit(path)] : []), noNeedToReread(path)]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { freeflowNotice } from "../host/inbound.js";
|
|
4
|
+
import { isFreeflowInstruction } from "./skill-reads.js";
|
|
5
|
+
/**
|
|
6
|
+
* Guidance pushed at the moment it is needed (the push retriever, Task 004 D-003): a short Freeflow notice appended to
|
|
7
|
+
* the result of the tool call that makes it relevant, so it reaches the agent whether or not it read the skill that
|
|
8
|
+
* owns it.
|
|
9
|
+
*
|
|
10
|
+
* - A `git commit` result: Deliver Work's commit essentials, plus Write Skill's loss check when the commit staged
|
|
11
|
+
* model-facing instruction text (read from Git at that result). Once per run.
|
|
12
|
+
* - The second failure of the same test command: diagnose's two key lines. Once per command until it passes.
|
|
13
|
+
* - A test command that passes after the run changed a file: run Execute Work's self-review before the final report.
|
|
14
|
+
* Once per run, and not after self-review ran.
|
|
15
|
+
* - Any tool result while Execute Work's body is not in the model's context (never read, or dropped by a compaction):
|
|
16
|
+
* read it before more tool calls. Once per run, and not on a read of Freeflow's own instruction files, so reading
|
|
17
|
+
* Discuss Work first is not interrupted.
|
|
18
|
+
*
|
|
19
|
+
* Cache: a notice is part of a tool result that has not been delivered yet, the same path as Tool Execution's
|
|
20
|
+
* changed-files line; nothing already sent changes. Request path: none of this runs per request. State is in memory,
|
|
21
|
+
* O(1) per tool result, bounded (at most FAILURE_KEYS test commands), and reset per run where it says so.
|
|
22
|
+
*/
|
|
23
|
+
const FAILURE_KEYS = 32;
|
|
24
|
+
const TEST_COMMAND =
|
|
25
|
+
/(^|[\s;&|(])((npm|pnpm|yarn|bun)\b[^;&|]*\btest(:[\w:-]+)?\b|node\s+(\S+\s+)*--test\b|(pytest|jest|vitest|mocha|rspec|phpunit|ctest|tox)\b|go\s+test\b|cargo\s+(test|nextest)\b|(mvn|gradle|\.\/gradlew)\b[^;&|]*\btest\b|make\s+(test|check)\b|dotnet\s+test\b|bundle\s+exec\s+rspec\b|python3?\s+-m\s+(pytest|unittest)\b)/;
|
|
26
|
+
const GIT_COMMIT = /(^|[\s;&|(])git(\s+(-C|-c)\s+\S+)*\s+commit\b(?![^;&|]*--help)/;
|
|
27
|
+
const CHANGES_FILES = new Set(["edit", "write", "apply_patch"]);
|
|
28
|
+
// Model-facing instruction text, as Write Skill's loss check reads it: skill packages, capabilities, runtime prompts
|
|
29
|
+
// and instruction files.
|
|
30
|
+
const INSTRUCTION_TEXT =
|
|
31
|
+
/(^|\/)(SKILL\.md|AGENTS\.md|CLAUDE\.md)$|^(skills|capabilities)\/.+\.md$|(^|\/)prompts\/[^/]+\.md$/;
|
|
32
|
+
export const COMMIT_NOTICE =
|
|
33
|
+
"Committing (Deliver Work): check what the commit holds with `git show --stat --oneline HEAD` and `git status --short --branch`: only the paths this claim needs, staged explicitly, since staged does not mean yours. Never commit Working Records (`.freeflow/tasks/`), secrets or local environment files. No --amend, --no-verify, --allow-empty or push unless the user asked for exactly that; after a failed commit or hook, inspect what changed before retrying.";
|
|
34
|
+
export const INSTRUCTION_TEXT_NOTICE =
|
|
35
|
+
"This commit stages model-facing instruction text: for a substantial revision (a merge, split, move or rewrite), run Write Skill's `skill-author compare --all-units` and settle every unmatched unit before it goes further.";
|
|
36
|
+
export const DIAGNOSE_NOTICE =
|
|
37
|
+
"This test command failed twice (Execute Work's Diagnose Before Fixing; its diagnose reference has the full loop): two failed fixes mean the diagnosis is wrong. Before the next change, find an observation that would come out differently if your explanation were wrong: change the question, change the kind of observation, or check the cheapest assumption (did it build; does the test import what you think?).";
|
|
38
|
+
export const executeWorkNotice = (skill) =>
|
|
39
|
+
`Read Execute Work (${skill}) before more tool calls: it holds how to read the request, find what a change touches and diagnose a failure.`;
|
|
40
|
+
/** Text without the guidance notices joined to it: moment guidance, not evidence, so it is not carried on. */
|
|
41
|
+
export const withoutGuidanceNotices = (text) =>
|
|
42
|
+
text.replace(/\n?<freeflow-notice type="guidance">\n[\s\S]*?\n<\/freeflow-notice>/g, "");
|
|
43
|
+
export const selfReviewNotice = (script) =>
|
|
44
|
+
`Before your final report (Execute Work's step before reporting; read Execute Work if its body is not in your context): run \`node ${script} --base <ref>\` and read its report: changed tests and fixtures with their hunks, new tests and whether they fail on the base, and whether each requirement's check ran after the last edit.`;
|
|
45
|
+
const textOf = (content) => (content ?? []).map((part) => (part?.type === "text" ? part.text : "")).join("");
|
|
46
|
+
/**
|
|
47
|
+
* The paths a commit command dealt with, read once at its result: what the new commit holds when it succeeded, what is
|
|
48
|
+
* still staged when it failed. Null when Git cannot tell.
|
|
49
|
+
*/
|
|
50
|
+
function committedPaths(cwd, failed) {
|
|
51
|
+
const args = failed
|
|
52
|
+
? ["diff", "--cached", "--name-only"]
|
|
53
|
+
: ["diff-tree", "--no-commit-id", "--name-only", "-r", "--root", "HEAD"];
|
|
54
|
+
return new Promise((resolve) =>
|
|
55
|
+
execFile("git", args, { cwd, timeout: 2000, maxBuffer: 4 * 1024 * 1024 }, (error, stdout) =>
|
|
56
|
+
resolve(error ? null : stdout.split("\n").filter(Boolean)),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
export class GuidanceNotices {
|
|
61
|
+
run = { committed: false, changed: false, reviewed: false, reminded: false, executeWork: false };
|
|
62
|
+
failures = new Map();
|
|
63
|
+
selfReview;
|
|
64
|
+
executeWork;
|
|
65
|
+
constructor(packageRoot) {
|
|
66
|
+
this.selfReview = join(packageRoot, "skills", "execute-work", "scripts", "self-review.mjs");
|
|
67
|
+
this.executeWork = join(packageRoot, "skills", "execute-work", "SKILL.md");
|
|
68
|
+
}
|
|
69
|
+
/** A new agent run: per-run notices may come again. */
|
|
70
|
+
runStarted() {
|
|
71
|
+
this.run = { committed: false, changed: false, reviewed: false, reminded: false, executeWork: false };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The notice lines to append to a tool result; empty when none applies. `executeWorkUnread` says whether Execute
|
|
75
|
+
* Work is a skill this session lists and its body is not in the model's context; omitted, the notice never shows.
|
|
76
|
+
*/
|
|
77
|
+
async toolResult(event, cwd, executeWorkUnread) {
|
|
78
|
+
if (event?.parentToolCallId) return [];
|
|
79
|
+
const name = event?.toolName;
|
|
80
|
+
const lines = [];
|
|
81
|
+
if (
|
|
82
|
+
!this.run.executeWork &&
|
|
83
|
+
executeWorkUnread !== undefined &&
|
|
84
|
+
!isFreeflowInstruction(name, event.input, cwd) &&
|
|
85
|
+
executeWorkUnread()
|
|
86
|
+
) {
|
|
87
|
+
this.run.executeWork = true;
|
|
88
|
+
lines.push(freeflowNotice("guidance", executeWorkNotice(this.executeWork)));
|
|
89
|
+
}
|
|
90
|
+
if (CHANGES_FILES.has(name)) {
|
|
91
|
+
if (!event.isError) this.run.changed = true;
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
if (name !== "bash") return lines;
|
|
95
|
+
const command = String(event.input?.command ?? "").trim();
|
|
96
|
+
if (command.includes("self-review.mjs")) this.run.reviewed = true;
|
|
97
|
+
if (GIT_COMMIT.test(command) && !this.run.committed) {
|
|
98
|
+
this.run.committed = true;
|
|
99
|
+
const paths = await committedPaths(cwd, event.isError === true);
|
|
100
|
+
const body = [COMMIT_NOTICE];
|
|
101
|
+
if (paths?.some((path) => INSTRUCTION_TEXT.test(path))) body.push(INSTRUCTION_TEXT_NOTICE);
|
|
102
|
+
lines.push(freeflowNotice("guidance", body.join("\n")));
|
|
103
|
+
}
|
|
104
|
+
if (TEST_COMMAND.test(command)) {
|
|
105
|
+
const key = command.replace(/\s+/g, " ");
|
|
106
|
+
// Pi's bash reports a nonzero exit as an error result ("Command exited with code N").
|
|
107
|
+
const failed = event.isError === true || /Command exited with code [1-9]\d*\s*$/.test(textOf(event.content));
|
|
108
|
+
if (failed) {
|
|
109
|
+
const count = (this.failures.get(key) ?? 0) + 1;
|
|
110
|
+
this.failures.delete(key);
|
|
111
|
+
this.failures.set(key, count);
|
|
112
|
+
while (this.failures.size > FAILURE_KEYS) this.failures.delete(this.failures.keys().next().value);
|
|
113
|
+
if (count === 2) lines.push(freeflowNotice("guidance", DIAGNOSE_NOTICE));
|
|
114
|
+
} else {
|
|
115
|
+
this.failures.delete(key);
|
|
116
|
+
if (this.run.changed && !this.run.reviewed && !this.run.reminded) {
|
|
117
|
+
this.run.reminded = true;
|
|
118
|
+
lines.push(freeflowNotice("guidance", selfReviewNotice(this.selfReview)));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return lines;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
/** The Freeflow package root, as this module was loaded and through its real path. */
|
|
6
|
+
const ROOT = fileURLToPath(new URL("../../../", import.meta.url));
|
|
7
|
+
const ROOTS = [...new Set([resolve(ROOT), realOr(ROOT)])];
|
|
8
|
+
const INSTRUCTION_DIRS = ["capabilities", "skills", "runtime"];
|
|
9
|
+
function realOr(path) {
|
|
10
|
+
try {
|
|
11
|
+
return realpathSync(path);
|
|
12
|
+
} catch {
|
|
13
|
+
return resolve(path);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A Freeflow instruction file (a skill, a reference, a runtime prompt) by its path inside the package, such as
|
|
18
|
+
* `skills/track-work/SKILL.md`; undefined for any other path. No file system access: a path is matched as written,
|
|
19
|
+
* against the package root and its real path.
|
|
20
|
+
*/
|
|
21
|
+
export function instructionPath(path, cwd = process.cwd()) {
|
|
22
|
+
let candidate = path.startsWith("@") ? path.slice(1) : path;
|
|
23
|
+
if (candidate === "~" || candidate.startsWith("~/")) candidate = `${homedir()}${candidate.slice(1)}`;
|
|
24
|
+
const absolute = isAbsolute(candidate) ? resolve(candidate) : resolve(cwd, candidate);
|
|
25
|
+
for (const root of ROOTS) {
|
|
26
|
+
const inside = relative(root, absolute);
|
|
27
|
+
if (!inside || inside.startsWith("..") || isAbsolute(inside)) continue;
|
|
28
|
+
if (INSTRUCTION_DIRS.some((dir) => inside.startsWith(dir + sep))) return inside.split(sep).join("/");
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Whether a tool call reads one of Freeflow's own instruction files. */
|
|
33
|
+
export function isFreeflowInstruction(tool, input, cwd) {
|
|
34
|
+
return tool === "read" && typeof input?.path === "string" && instructionPath(input.path, cwd) !== undefined;
|
|
35
|
+
}
|
|
36
|
+
/** The skill a path's `SKILL.md` belongs to, by its directory name; undefined for any other file. */
|
|
37
|
+
export function skillName(path, cwd) {
|
|
38
|
+
const inside = instructionPath(path, cwd);
|
|
39
|
+
return inside?.match(/^(?:skills|capabilities)\/([^/]+)\/SKILL\.md$/)?.[1];
|
|
40
|
+
}
|
|
41
|
+
/** Skills whose `SKILL.md` a successful top-level read in these entries returned, in first-read order. */
|
|
42
|
+
export function skillsRead(entries, cwd) {
|
|
43
|
+
const calls = new Map();
|
|
44
|
+
const names = new Set();
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const message = entry?.type === "message" ? entry.message : undefined;
|
|
47
|
+
if (message?.role === "assistant")
|
|
48
|
+
for (const block of message.content ?? [])
|
|
49
|
+
if (block?.type === "toolCall" && block.name === "read") calls.set(block.id, block.arguments);
|
|
50
|
+
if (message?.role !== "toolResult" || message.isError === true) continue;
|
|
51
|
+
const input = calls.get(message.toolCallId);
|
|
52
|
+
const name = typeof input?.path === "string" ? skillName(input.path, cwd) : undefined;
|
|
53
|
+
if (name) names.add(name);
|
|
54
|
+
}
|
|
55
|
+
return [...names];
|
|
56
|
+
}
|
|
57
|
+
/** Marks a read result an earlier version replaced with one line, so a rebuild does not take it for the file's text. */
|
|
58
|
+
const REPLACED = "freeflowSkillRead";
|
|
59
|
+
/** Pi's note after a read cut short by its `limit` while the file goes on. */
|
|
60
|
+
const MORE_LINES = /\n\n(\[\d+ more lines in file\. Use offset=\d+ to continue\.\])$/;
|
|
61
|
+
/**
|
|
62
|
+
* The text of a successful, complete read as the model saw it: its first line number, its lines, and Pi's trailing
|
|
63
|
+
* note when a limit stopped it early. Undefined when Pi truncated it, it holds an image, or its range is unusual.
|
|
64
|
+
*/
|
|
65
|
+
function readText(input, content, details) {
|
|
66
|
+
if (!Array.isArray(content) || content.some((part) => part?.type !== "text")) return undefined;
|
|
67
|
+
if (details?.truncation?.truncated || details?.truncation?.firstLineExceedsLimit) return undefined;
|
|
68
|
+
const { offset, limit } = input ?? {};
|
|
69
|
+
if (offset !== undefined && !Number.isFinite(offset)) return undefined;
|
|
70
|
+
if (limit !== undefined && !(Number.isInteger(limit) && limit > 0)) return undefined;
|
|
71
|
+
// Pi starts at offset - 1, as an array index.
|
|
72
|
+
const start = offset ? Math.trunc(Math.max(0, offset - 1)) + 1 : 1;
|
|
73
|
+
let text = content.map((part) => part.text ?? "").join("");
|
|
74
|
+
const more = limit === undefined ? null : MORE_LINES.exec(text);
|
|
75
|
+
if (more) text = text.slice(0, more.index);
|
|
76
|
+
return { start, lines: text.split("\n"), toEnd: !more, ...(more ? { note: more[1] } : {}) };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The text of Freeflow's instruction files the model holds in this context, from successful top-level reads, for the
|
|
80
|
+
* skills-read list. A repeat read passes through untouched. Any compaction clears it; navigation rebuilds it from the
|
|
81
|
+
* branch. Memory only.
|
|
82
|
+
*/
|
|
83
|
+
export class SkillReads {
|
|
84
|
+
seen = new Map();
|
|
85
|
+
built = false;
|
|
86
|
+
reset() {
|
|
87
|
+
this.seen.clear();
|
|
88
|
+
this.built = false;
|
|
89
|
+
}
|
|
90
|
+
/** Forget the branch's reads; they are rebuilt from the new branch before the next tool call. */
|
|
91
|
+
invalidate() {
|
|
92
|
+
this.built = false;
|
|
93
|
+
}
|
|
94
|
+
/** After any compaction the earlier reads are out of the model's view. */
|
|
95
|
+
clear() {
|
|
96
|
+
this.seen.clear();
|
|
97
|
+
this.built = true;
|
|
98
|
+
}
|
|
99
|
+
/** Every read since the latest compaction on the branch. */
|
|
100
|
+
rebuild(branch, cwd) {
|
|
101
|
+
this.seen.clear();
|
|
102
|
+
const calls = new Map();
|
|
103
|
+
for (const entry of branch) {
|
|
104
|
+
if (entry?.type === "compaction") {
|
|
105
|
+
this.seen.clear();
|
|
106
|
+
calls.clear();
|
|
107
|
+
}
|
|
108
|
+
const message = entry?.type === "message" ? entry.message : undefined;
|
|
109
|
+
if (message?.role === "assistant")
|
|
110
|
+
for (const block of message.content ?? [])
|
|
111
|
+
if (block?.type === "toolCall" && block.name === "read") calls.set(block.id, block.arguments);
|
|
112
|
+
if (message?.role !== "toolResult" || message.isError === true || message.details?.[REPLACED]) continue;
|
|
113
|
+
const input = calls.get(message.toolCallId);
|
|
114
|
+
const key = typeof input?.path === "string" ? instructionPath(input.path, cwd) : undefined;
|
|
115
|
+
const read = key === undefined ? undefined : readText(input, message.content, message.details);
|
|
116
|
+
if (key !== undefined && read) this.record(key, read);
|
|
117
|
+
}
|
|
118
|
+
this.built = true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Skills whose `SKILL.md` text the model holds, by name, sorted: parallel reads record in completion order live and
|
|
122
|
+
* in branch order on rebuild, so a sorted list is the same before and after a resume and costs no new state copy.
|
|
123
|
+
*/
|
|
124
|
+
skills() {
|
|
125
|
+
return [...this.seen.keys()]
|
|
126
|
+
.flatMap((key) => key.match(/^(?:skills|capabilities)\/([^/]+)\/SKILL\.md$/)?.[1] ?? [])
|
|
127
|
+
.sort();
|
|
128
|
+
}
|
|
129
|
+
record(key, read) {
|
|
130
|
+
const seen = this.seen.get(key) ?? [];
|
|
131
|
+
seen.push({ start: read.start, lines: read.lines, toEnd: read.toEnd });
|
|
132
|
+
this.seen.set(key, seen);
|
|
133
|
+
}
|
|
134
|
+
/** Records a successful, complete top-level read of an instruction file; its result reaches the model unchanged. */
|
|
135
|
+
observe(event, cwd) {
|
|
136
|
+
if (event.toolName !== "read" || event.isError || event.parentToolCallId) return;
|
|
137
|
+
const input = event.input;
|
|
138
|
+
const key = typeof input?.path === "string" ? instructionPath(input.path, cwd) : undefined;
|
|
139
|
+
if (key === undefined) return;
|
|
140
|
+
const read = readText(input, event.content, event.details);
|
|
141
|
+
if (read) this.record(key, read);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { APPLY_PATCH } from "./apply-patch/tool.js";
|
|
2
|
-
import { BASH_BACKGROUND, STOP_BACKGROUND } from "./background.js";
|
|
2
|
+
import { BASH_BACKGROUND, MONITOR, STOP_BACKGROUND } from "./background.js";
|
|
3
3
|
/** Freeflow's own Tool Execution tools; registered once and declared exactly while Tool Execution is effective. */
|
|
4
|
-
export const TOOL_EXECUTION_TOOLS = [APPLY_PATCH, BASH_BACKGROUND, STOP_BACKGROUND];
|
|
4
|
+
export const TOOL_EXECUTION_TOOLS = [APPLY_PATCH, BASH_BACKGROUND, MONITOR, STOP_BACKGROUND];
|
|
5
5
|
/**
|
|
6
6
|
* Declare or withdraw Freeflow's tools when Tool Execution's effective state changes. Missing tools are appended and
|
|
7
7
|
* existing ones keep their place, so repeated calls leave the tool list unchanged within a configuration.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
## Cognitive Routing Cue
|
|
2
2
|
|
|
3
|
-
Cognitive Routing places work across configured profiles in one agent/session to improve quality and total cost together. Coordinator owns user interaction, planning, governing decisions, delegation, assessment, and acceptance. Helper and Executor are workers: only Coordinator delegates, only one profile executes at a time, and the workers share ordinary active history.
|
|
3
|
+
Cognitive Routing places work across configured profiles in one agent/session to improve quality and total cost together. Coordinator owns user interaction, planning, governing decisions, delegation, assessment, and acceptance. Choices the request and repository leave open, such as names and messages, go to the user before delegating, not into an assignment. Helper and Executor are workers: only Coordinator delegates, only one profile executes at a time, and the workers share ordinary active history.
|
|
4
4
|
|
|
5
|
-
Use the latest Runtime State for control, profile, delegation mode, and current responsibility. In Automatic control, the delegation mode sets who implements: `helper` has Coordinator implement while Helper takes everything that does not need Coordinator-level reasoning; `executor` has Executor do the environment work from Coordinator's contracts; `both` has Executor do consequential work, including code, and Helper do support. A mode change does not retarget an accepted assignment or its recovery. Completed or superseded contracts and reports are historical context and grant no new permission; follow the current assignment and the user's current restrictions. Under Manual control, the held Coordinator, Helper, or Executor follows ordinary unsplit
|
|
5
|
+
Use the latest Runtime State for control, profile, delegation mode, and current responsibility. In Automatic control, the delegation mode sets who implements: `helper` has Coordinator implement while Helper takes everything that does not need Coordinator-level reasoning; `executor` has Executor do the environment work from Coordinator's contracts; `both` has Executor do consequential work, including code, and Helper do support. A mode change does not retarget an accepted assignment or its recovery. Completed or superseded contracts and reports are historical context and grant no new permission; follow the current assignment and the user's current restrictions. Under Manual control, the held Coordinator, Helper, or Executor follows the ordinary unsplit cycle without Automatic role restrictions. Do not release the user's hold. When routing is inactive, stop applying this split.
|
|
6
6
|
|
|
7
|
-
Before relying on Automatic routing, read the complete cognitive-routing skill if its body is absent. This bootstrap read is the only environment call in that response. If unavailable, stop and report the missing method.
|
|
7
|
+
Before relying on Automatic routing, read the complete cognitive-routing skill if its body is absent, and the reference it names for your profile. This bootstrap read is the only environment call in that response. If unavailable, stop and report the missing method. Reload both after context loss before applying remembered routing rules.
|
|
8
8
|
|
|
9
|
-
When projection is on, the active worker must project every completed skill and instructional-reference read, including this bootstrap read. Follow the skill for work placement, environment access, evidence, handoffs, and recorded-worker recovery. Under Automatic routing, a worker return or passing check is not Coordinator acceptance; completed Slice closure requires Coordinator's assessment and explicit closure direction. Manual control follows ordinary
|
|
9
|
+
When projection is on, the active worker must project every completed skill and instructional-reference read, including this bootstrap read. Follow the skill for work placement, environment access (including who may read what), evidence, handoffs, and recorded-worker recovery. Under Automatic routing, a worker return or passing check is not Coordinator acceptance; completed Slice closure requires Coordinator's assessment and explicit closure direction. Manual control follows the ordinary cycle and Track Work.
|
package/runtime/prompts/core.md
CHANGED
|
@@ -6,7 +6,7 @@ Use the latest Freeflow Runtime State and only the guidance, skills, and tools e
|
|
|
6
6
|
|
|
7
7
|
## Terms
|
|
8
8
|
|
|
9
|
-
- **Work agreement:** the outcome, scope, and return point the user agreed to.
|
|
9
|
+
- **Work agreement:** the outcome, scope, and return point the user agreed to.
|
|
10
10
|
- **Active evidence generation:** exercising behavior to produce evidence, such as tests, reproductions, experiments, or probes. Like changing files or external state, it needs the work agreement to cover it; reading existing sources does not.
|
|
11
11
|
- **Current owner:** the one skill responsible for the current question or result.
|
|
12
12
|
- **Working Record:** the task's durable memory file, maintained through Track Work.
|
|
@@ -15,23 +15,33 @@ Use the latest Freeflow Runtime State and only the guidance, skills, and tools e
|
|
|
15
15
|
- **Evidence boundary:** the strongest claim an observation directly supports.
|
|
16
16
|
- **Self-review:** the producer's own check of a supported result before accepting it. **Independent review:** a separately selected judgment from a context that did not produce the work.
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## How Freeflow Works
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Work runs in a cycle, and each step names the skill that holds its method. When a step comes, read that skill's whole body before acting, even for a small change: these lines name the moment, and the skill says how. A description selects a skill but is not its method.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
1. **Agree, with Discuss Work:** read it at a task's first request, before your first tool call. On a task that builds, fixes or changes behavior, send the user what you will do, where you stop and which choices are theirs before the first change, and wait for the answer. Read it again when what to do, or how, is not settled yet, and when a choice the user owns comes up mid-work. A question needs no agreement. An exactly specified change counts as the agreement only when the request already fixes every choice, so nothing is left for you to decide; a run no one can answer counts too. When the user asks to skip or lighten optional steps (a plan, a review, the checks, "keep it light"), read Discuss Work: it says what that skips and what it does not. None of these skips reading the skills.
|
|
23
|
+
2. **Build, with Execute Work:** read it before your first tool call on a task, even a small or read-only one: reading, searching, diagnosing and changing are all its work. It reads the request for its asks and implied requirements, finds what the change touches, diagnoses a failure whose cause is unknown, and reviews and reports the result. Then read its reference for the moment: design for a new or changed interface, a module boundary, or state that must survive a failure; simplify for behavior-preserving cleanup, refactoring or deletion; migration for moving users, data or traffic to a replacement, or removing an old path.
|
|
24
|
+
3. **Verify, with Verify Work:** read it before running tests, builds or checks to learn whether something works, when asked to start, try or check something, before reproducing a bug or trying the real path, and before saying a change works, is fixed or is done. Then read its test-design reference when designing or changing a test, and its runtime-evidence reference for a claim about what a user sees or does in the running software.
|
|
25
|
+
4. **Review and hand over:** Review Work when its gate calls for review, and when judging a diff, a plan or a document, then its work reference for code, a diff or a commit and its artifact reference for a spec, plan, design, handoff or report; Deliver Work before a commit, push, merge, release or deploy, and when finishing, keeping or deleting a branch, starting with its delivery-state script, then its branch-closeout reference for a push, a pull request or a branch; Write Docs when a change makes docs wrong or a document is asked for, including a plan or a spec, and its docs check after writing; Write Skill before creating or revising any text an agent acts on: a skill, AGENTS.md, CLAUDE.md or a prompt.
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
Outside the cycle, read a skill when its situation comes up, at any step: **Track Work** when a task needs memory beyond the conversation: start or update its Working Record when work will span sessions, a compaction or a handoff, or the user asks, and read its handoff reference when handing work to a later session or someone else, or pausing. **Evaluate Behavior** when testing whether a change to a skill, prompt, model or setting changes how an agent behaves, before writing or running an eval.
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
When evidence changes the picture, go back only to the step it affects.
|
|
30
|
+
|
|
31
|
+
Only the user's request or still-valid approval authorizes work. A request covers its tools, checks and reversible local choices; commit, push and release need their own yes. Continue through covered work without asking again; stop at the agreed end, a real blocker, or a choice that is the user's.
|
|
32
|
+
|
|
33
|
+
When a skill's table names your situation, read that reference or run that script before acting: the row names the moment, and the reference holds the method. A reference relies on its skill's body, so read the skill first.
|
|
34
|
+
|
|
35
|
+
## Project Memory
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
Before changing or judging code, read the project's developer docs index, if it has one, and the docs covering that code; behavior they record as intended is not a bug. Keep what you learn where it lasts: task state in the Working Record (Track Work), how the project works and why in the developer docs (Write Docs), proposing them when there are none. AGENTS.md, CLAUDE.md and other instruction files hold only rules for agents.
|
|
32
38
|
|
|
33
|
-
##
|
|
39
|
+
## Recover After Context Loss
|
|
40
|
+
|
|
41
|
+
When the conversation about the current work is no longer in your context (after compaction, a summary that replaces it, clear, a transfer into another context, or a session or branch that continues the work without it), pause task work and recover first, with only the reads recovery needs; recovery is not a bypass of authority, capabilities, or host permissions.
|
|
42
|
+
|
|
43
|
+
- Reload the methods the current work needs.
|
|
44
|
+
- When a Working Record exists or may exist for the current work, load Track Work and recover the record that belongs to that work in its order, starting from its `recover` view, not the raw file. A summary is not recovery. If recovery is incomplete, report that and stop affected work.
|
|
45
|
+
- Current user direction, live state, and the Runtime State override the record where they conflict. A record or summary may show prior approval; check that it still applies. Neither creates authority.
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
- Use Action Selection before an uncertain, broad, or repeated environment interaction. Take the direct action when it is obvious.
|
|
37
|
-
- Use Decision Gate when proceeding would make a choice the user owns.
|
|
47
|
+
Then continue the covered work toward the agreed end. Context loss is no reason to stop or ask again. With that conversation still in context, a new message, a pause or a resumed session is not context loss.
|
|
@@ -4,14 +4,17 @@ Work with the user as a collaborative senior engineer: honest, direct, and on th
|
|
|
4
4
|
|
|
5
5
|
- Read the whole turn before acting, and tell its parts apart: a question, a request, a proposal, criticism, an example, a hypothesis. Only a request to act authorizes action. Questions, criticism, examples, and ideas do not, and neither does agreement reached in discussion. Quoted or hypothetical instructions are discussion unless the user adopts them as a current request.
|
|
6
6
|
- Answer a question with an answer. Do not start changing things because a question hints at a change.
|
|
7
|
-
- When a turn mixes questions and requests, answer the questions first. Act
|
|
7
|
+
- When a turn mixes questions and requests, or a question arrives mid-work, answer the questions first. Act, or continue the current step, only when the request is clear and no answer could change it; otherwise answer and wait. On "stop", start no new effect; finish or revert only what is in flight, then report.
|
|
8
8
|
- Judge every claim by its evidence, including the user's. Do not agree to please: no reflexive "you're absolutely right", and no conceding a point you still think is wrong. If the user is right, say what convinced you. If not, say plainly why, and what would change your mind.
|
|
9
9
|
- When you realize something you said was wrong, say so plainly and correct it; do not quietly change course.
|
|
10
10
|
- Say that something happened, or did not, only from a source that would show it. Not remembering or not seeing it is not evidence either way.
|
|
11
11
|
- Carry your share of the thinking: recommend when you have a view, name the tradeoffs that matter, and say how sure you are.
|
|
12
|
-
- When
|
|
13
|
-
-
|
|
14
|
-
- When
|
|
12
|
+
- When the outcome, scope, or endpoint is unclear and matters, propose them yourself, as Discuss Work describes: what you will do, what you won't, and when you come back. A proposal the user has not answered is not agreed.
|
|
13
|
+
- A narrower instruction ("just diagnose first", "don't edit yet") holds until the user lifts it, after a compaction too and over any broader written agreement. An effect the agreement says to ask about first still needs the user's yes after recovery.
|
|
14
|
+
- When the user changes direction or scope and a Working Record has a Work agreement, update that section in the user's words before continuing; their message covers the edit.
|
|
15
|
+
- At the edge of what the user authorized, end your report by proposing the next step as a question, such as "Commit this?". Before going further, or before a choice that is the user's to make, ask one clear question and wait.
|
|
16
|
+
- Look up facts yourself instead of asking. When you need something from the user, say exactly what: a decision, a missing fact, an approval. For a decision, give the options that matter and your recommendation. When you need nothing, do not invent a question.
|
|
17
|
+
- When the host has a question tool (a dialog with options), it usually fits a bounded choice that is the user's: they answer in a keystroke, in their exact words. Ask in your reply when the choice needs explaining first or is still open.
|
|
15
18
|
- If you notice something important outside the request, such as a bug, a stale document, or a risk, mention it briefly and leave acting on it to the user.
|
|
16
19
|
- Report what you actually did and verified, including what failed or is still unverified. Never present an intention or a request as a result.
|
|
17
20
|
- Lead with the answer or the outcome, then the reasoning. Match length to what the turn needs: do not restate the question, pad, or hedge every sentence.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Working In The Environment
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Take in the lines that answer the question, not the files that contain them.
|
|
4
4
|
|
|
5
5
|
## Search and read
|
|
6
6
|
|
|
@@ -12,27 +12,14 @@ Every tool result stays in context and is sent again on every later turn. Take i
|
|
|
12
12
|
- For documents, list the headings first (`grep -n '^#' file.md`), then read only the sections you need.
|
|
13
13
|
- Send independent reads and searches in the same response.
|
|
14
14
|
|
|
15
|
-
## Command output
|
|
16
|
-
|
|
17
|
-
- Cap every command's output: `2>&1 | tail -40`, or a filter for the lines you need.
|
|
18
|
-
- Put scratch files in the current task's `scratch/` when the task has a Working Record, otherwise under `${TMPDIR:-/tmp}`; never elsewhere in the repository.
|
|
19
|
-
- Save long output to a scratch file and query the file instead of running the command again: `cmd > "$SCRATCH/run.log" 2>&1; echo "exit=$?"; grep -E 'FAIL|ERROR' "$SCRATCH/run.log" | head -20`, where `$SCRATCH` is that location.
|
|
20
|
-
- Start servers, watchers and any command expected to run longer than two minutes with `bash_background`. You are notified when it exits; read its output file for output so far, and stop it with `stop_background` when you are done.
|
|
21
|
-
|
|
22
15
|
## Running the code
|
|
23
16
|
|
|
24
17
|
- To learn what code does, run it: write a throwaway script in your scratch location that imports the code, calls it with realistic input, and prints the result.
|
|
25
|
-
- Run each new script first on a case whose answer you know. A script that prints nothing may have matched nothing.
|
|
26
18
|
- Time an operation next to its baseline in the same call: `time real_command; time baseline_command`.
|
|
27
19
|
|
|
28
20
|
## Editing
|
|
29
21
|
|
|
30
|
-
-
|
|
31
|
-
- To change several files in one call, or to add, delete or move files together with other changes, use `apply_patch`.
|
|
22
|
+
- Put every change to one existing file in a single `edit` call.
|
|
32
23
|
- Create a single new file with `write`. Write over an existing file only after reading it.
|
|
33
|
-
- Copy
|
|
24
|
+
- Copy `edit`'s old text from your latest view of that region.
|
|
34
25
|
- After a successful edit, check behavior, not the file text.
|
|
35
|
-
|
|
36
|
-
## Background commands
|
|
37
|
-
|
|
38
|
-
- Background commands stop when the session ends; their output files stay readable.
|