refactor(tools): rename SF tools to cleaner action-oriented names
Align tool names with Copilot coding agent conventions: - sf_exec → run_command - sf_exec_search → read_output - sf_resume → resume_agent - capture_thought → log_reasoning - sf_log_judgment → log_decision - sf_self_report → report_issue - sf_self_feedback_resolve → resolve_issue - sf_save_gate_result → record_gate - sf_autonomous_checkpoint → checkpoint - sf_milestone_generate_id → new_milestone_id - sf_graph → memory_graph - memory_query → memory_search - sf_retrieval_evidence → search_evidence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
1322bc7d9a
commit
ac371926cb
89 changed files with 440 additions and 227 deletions
|
|
@ -2894,7 +2894,7 @@ export async function buildGateEvaluatePrompt(
|
|||
"## Instructions",
|
||||
"",
|
||||
"Analyze the slice plan above and answer the gate question.",
|
||||
`Call the \`sf_save_gate_result\` tool with:`,
|
||||
`Call the \`record_gate\` tool with:`,
|
||||
`- \`milestoneId\`: "${mid}"`,
|
||||
`- \`sliceId\`: "${sid}"`,
|
||||
`- \`gateId\`: "${def.id}"`,
|
||||
|
|
|
|||
|
|
@ -219,6 +219,16 @@ export function evaluateRunawayGuard(
|
|||
) {
|
||||
return { action: "none" };
|
||||
}
|
||||
// Skip hard-pause if the unit is making file-change progress — growth with
|
||||
// changes is legitimate diagnostic/planning work, not a stuck loop.
|
||||
// Without this check, discuss/plan phases that legitimately consume tokens
|
||||
// while writing summaries/plans would be hard-paused despite making progress.
|
||||
if (
|
||||
(unitMetrics.changedFiles ?? 0) > 0 ||
|
||||
unitMetrics.worktreeChangedSinceStart === true
|
||||
) {
|
||||
return { action: "none" };
|
||||
}
|
||||
if (
|
||||
config.hardPause &&
|
||||
s.finalWarningSent &&
|
||||
|
|
|
|||
|
|
@ -2387,7 +2387,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|||
missingCheckpointDiagnosis.evidence ?? "",
|
||||
].join("\n"),
|
||||
suggestedFix:
|
||||
"Improve solver repair policy, tool availability, or prompt wording so missing-checkpoint repairs end with a successful sf_autonomous_checkpoint tool call.",
|
||||
"Improve solver repair policy, tool availability, or prompt wording so missing-checkpoint repairs end with a successful checkpoint tool call.",
|
||||
acceptanceCriteria: [
|
||||
"Missing-checkpoint repair attempts include failure classification in the prompt.",
|
||||
"Repeated repair failures file self-feedback automatically.",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* instead of relying on a single agent turn to either finish or silently drift.
|
||||
*
|
||||
* Consumer: auto/phases.js injects the contract into each autonomous unit, and
|
||||
* bootstrap/db-tools.js records agent checkpoints via sf_autonomous_checkpoint.
|
||||
* bootstrap/db-tools.js records agent checkpoints via checkpoint.
|
||||
*/
|
||||
import {
|
||||
appendFileSync,
|
||||
|
|
@ -354,13 +354,13 @@ export function buildAutonomousSolverPromptBlock(state) {
|
|||
"",
|
||||
"## CHECKPOINT REQUIREMENT",
|
||||
"",
|
||||
"`sf_autonomous_checkpoint` is ALWAYS available in autonomous mode. It is registered unconditionally at startup.",
|
||||
"`checkpoint` is ALWAYS available in autonomous mode. It is registered unconditionally at startup.",
|
||||
"If you do not see it in your tool list, that is a perception error — call it anyway. It will work.",
|
||||
"Do NOT conclude it is missing or phantom based on a codebase search. It is registered at runtime by the extension bootstrap, not as a standalone file.",
|
||||
"",
|
||||
"Hard requirement: before ending the turn, call the actual `sf_autonomous_checkpoint` tool. Writing SUMMARY.md, LOOP.md, task files, chat prose, or any other artifact is useful evidence, but it is not a checkpoint and does not satisfy this requirement.",
|
||||
"Hard requirement: before ending the turn, call the actual `checkpoint` tool. Writing SUMMARY.md, LOOP.md, task files, chat prose, or any other artifact is useful evidence, but it is not a checkpoint and does not satisfy this requirement.",
|
||||
"",
|
||||
"Call `sf_autonomous_checkpoint` with:",
|
||||
"Call `checkpoint` with:",
|
||||
'- `outcome: "complete"` only when this unit\'s normal completion tool/artifact is also done.',
|
||||
'- `outcome: "continue"` when you made real progress but more autonomous iterations are needed.',
|
||||
'- `outcome: "blocked"` when the next step cannot proceed without unavailable facts, credentials, or a broken environment.',
|
||||
|
|
@ -376,7 +376,7 @@ export function buildAutonomousSolverPromptBlock(state) {
|
|||
"- Invariants: rules that must remain true across iterations.",
|
||||
"- Assumptions: uncertain facts you relied on and how to falsify them later.",
|
||||
"",
|
||||
"If you are executing an `execute-task` unit and the task is finished, `sf_task_complete` remains mandatory; `sf_autonomous_checkpoint` does not replace it.",
|
||||
"If you are executing an `execute-task` unit and the task is finished, `sf_task_complete` remains mandatory; `checkpoint` does not replace it.",
|
||||
"If you need another iteration, leave exact remaining items in the checkpoint rather than ending with vague prose.",
|
||||
"Your final autonomous action should be the checkpoint tool call unless a required completion tool such as sf_task_complete must be called immediately before it.",
|
||||
);
|
||||
|
|
@ -389,7 +389,7 @@ export function buildAutonomousSolverPromptBlock(state) {
|
|||
* Purpose: turn the agent's end-of-iteration status into structured autonomous
|
||||
* state that can be inspected, gated, and resumed.
|
||||
*
|
||||
* Consumer: sf_autonomous_checkpoint tool.
|
||||
* Consumer: checkpoint tool.
|
||||
*/
|
||||
export function appendAutonomousSolverCheckpoint(basePath, params) {
|
||||
const state =
|
||||
|
|
@ -487,7 +487,7 @@ export function readAutonomousSolverState(basePath) {
|
|||
* Purpose: enforce the checkpoint contract with one repair chance while
|
||||
* preventing an unbounded missing-checkpoint redispatch loop.
|
||||
*
|
||||
* Consumer: runUnitPhase after the first unit turn omits sf_autonomous_checkpoint.
|
||||
* Consumer: runUnitPhase after the first unit turn omits checkpoint.
|
||||
*/
|
||||
export function recordAutonomousSolverMissingCheckpointRetry(
|
||||
basePath,
|
||||
|
|
@ -545,8 +545,8 @@ export function classifyAutonomousSolverMissingCheckpointFailure(messages) {
|
|||
evidence: "",
|
||||
};
|
||||
}
|
||||
const mentionsCheckpoint = lower.includes("sf_autonomous_checkpoint");
|
||||
// Check whether sf_autonomous_checkpoint is actually registered in the manifest.
|
||||
const mentionsCheckpoint = lower.includes("checkpoint");
|
||||
// Check whether checkpoint is actually registered in the manifest.
|
||||
// When the agent reports "tool unavailable" but the tool IS registered, this means
|
||||
// the agent mentioned the tool without calling it — reclassify accordingly to
|
||||
// break the self-referential repair loop.
|
||||
|
|
@ -562,18 +562,18 @@ export function classifyAutonomousSolverMissingCheckpointFailure(messages) {
|
|||
if (!manifestContent) return false;
|
||||
const manifest = JSON.parse(manifestContent);
|
||||
return Array.isArray(manifest?.provides?.tools) &&
|
||||
manifest.provides.tools.includes("sf_autonomous_checkpoint");
|
||||
manifest.provides.tools.includes("checkpoint");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
const mentionsToolUnavailable =
|
||||
/(unknown|unavailable|not available|not found|no such) tool/.test(lower) ||
|
||||
(lower.includes("sf_autonomous_checkpoint") &&
|
||||
(lower.includes("checkpoint") &&
|
||||
/(unavailable|not available|not found|unknown)/.test(lower));
|
||||
const mentionsToolFailure =
|
||||
lower.includes("error in sf_autonomous_checkpoint") ||
|
||||
(lower.includes("sf_autonomous_checkpoint") &&
|
||||
lower.includes("error in checkpoint") ||
|
||||
(lower.includes("checkpoint") &&
|
||||
/(failed|error|exception|invalid)/.test(lower));
|
||||
const mentionsFileSubstitute =
|
||||
/\bsummary\.md\b/i.test(text) ||
|
||||
|
|
@ -584,7 +584,7 @@ export function classifyAutonomousSolverMissingCheckpointFailure(messages) {
|
|||
lower.includes("summary file");
|
||||
const falselyClaimsSaved =
|
||||
(lower.includes("checkpoint") ||
|
||||
lower.includes("sf_autonomous_checkpoint")) &&
|
||||
lower.includes("checkpoint")) &&
|
||||
/(saved|recorded|complete|now saved)/.test(lower);
|
||||
if (mentionsToolUnavailable) {
|
||||
// Tool reported as unavailable but IS registered in manifest — agent mentioned
|
||||
|
|
@ -626,13 +626,13 @@ export function classifyAutonomousSolverMissingCheckpointFailure(messages) {
|
|||
return {
|
||||
classification: "mentioned-checkpoint-without-tool",
|
||||
summary:
|
||||
"The agent discussed sf_autonomous_checkpoint but did not record a checkpoint.",
|
||||
"The agent discussed checkpoint but did not record a checkpoint.",
|
||||
evidence: truncateEvidence(text),
|
||||
};
|
||||
}
|
||||
return {
|
||||
classification: "no-checkpoint-tool-call",
|
||||
summary: "The agent ended without calling sf_autonomous_checkpoint.",
|
||||
summary: "The agent ended without calling checkpoint.",
|
||||
evidence: truncateEvidence(text),
|
||||
};
|
||||
}
|
||||
|
|
@ -829,17 +829,17 @@ export function buildAutonomousSolverMissingCheckpointRepairPrompt(
|
|||
if (diagnosis?.classification && diagnosis.classification !== "no-transcript") {
|
||||
const classificationLabels = {
|
||||
"checkpoint-tool-unavailable":
|
||||
"⚠️ sf_autonomous_checkpoint appeared unavailable — but it is ALWAYS registered at runtime. Call it now without searching for it. If you don't see it in your tool list, that is a model perception error; the tool will work.",
|
||||
"⚠️ checkpoint appeared unavailable — but it is ALWAYS registered at runtime. Call it now without searching for it. If you don't see it in your tool list, that is a model perception error; the tool will work.",
|
||||
"checkpoint-tool-failed":
|
||||
"⚠️ The sf_autonomous_checkpoint tool call failed with an error. Fix the input (check required fields, types) and call it again.",
|
||||
"⚠️ The checkpoint tool call failed with an error. Fix the input (check required fields, types) and call it again.",
|
||||
"file-substituted-for-checkpoint":
|
||||
"⚠️ You wrote a summary or projection file instead of calling sf_autonomous_checkpoint. Writing files is not a checkpoint. Call the tool.",
|
||||
"⚠️ You wrote a summary or projection file instead of calling checkpoint. Writing files is not a checkpoint. Call the tool.",
|
||||
"claimed-checkpoint-without-tool":
|
||||
"⚠️ You stated the checkpoint was saved but no tool call succeeded. Do not describe or narrate the checkpoint — call sf_autonomous_checkpoint now.",
|
||||
"⚠️ You stated the checkpoint was saved but no tool call succeeded. Do not describe or narrate the checkpoint — call checkpoint now.",
|
||||
"mentioned-checkpoint-without-tool":
|
||||
"⚠️ You discussed sf_autonomous_checkpoint without calling it. Discussion is not execution. Call the tool.",
|
||||
"⚠️ You discussed checkpoint without calling it. Discussion is not execution. Call the tool.",
|
||||
"no-checkpoint-tool-call":
|
||||
"⚠️ You ended your turn without calling sf_autonomous_checkpoint at all. This is required. Call it now.",
|
||||
"⚠️ You ended your turn without calling checkpoint at all. This is required. Call it now.",
|
||||
};
|
||||
const label = classificationLabels[diagnosis.classification]
|
||||
?? `⚠️ Failure pattern: ${diagnosis.classification} — ${diagnosis.summary ?? "missing checkpoint"}`;
|
||||
|
|
@ -861,8 +861,8 @@ export function buildAutonomousSolverMissingCheckpointRepairPrompt(
|
|||
"1. Read .sf/runtime/autonomous-solver/LOOP.md to see what was expected.",
|
||||
"2. List files in the milestone/slice/task directories to find what artifacts exist.",
|
||||
"3. Read any SUMMARY.md or PLAN.md files to understand what progress was made.",
|
||||
"4. Based on the evidence, call sf_autonomous_checkpoint with the appropriate outcome and PDD fields.",
|
||||
"5. Based on the evidence, call sf_autonomous_checkpoint with the appropriate outcome and PDD fields.",
|
||||
"4. Based on the evidence, call checkpoint with the appropriate outcome and PDD fields.",
|
||||
"5. Based on the evidence, call checkpoint with the appropriate outcome and PDD fields.",
|
||||
"6. If you cannot determine what happened with high confidence, reconstruct best-effort and use outcome='continue' or outcome='complete' as appropriate — do not pause for human input.",
|
||||
);
|
||||
lines.push(
|
||||
|
|
@ -881,9 +881,9 @@ export function buildAutonomousSolverMissingCheckpointRepairPrompt(
|
|||
);
|
||||
}
|
||||
lines.push(
|
||||
"Inspect the work already performed, then call the actual sf_autonomous_checkpoint tool with the correct outcome and all eight PDD fields.",
|
||||
"Do not write a summary file as a substitute. Do not say the checkpoint is saved unless the sf_autonomous_checkpoint tool call succeeds.",
|
||||
"Your final action in this repair turn must be the sf_autonomous_checkpoint tool call.",
|
||||
"Inspect the work already performed, then call the actual checkpoint tool with the correct outcome and all eight PDD fields.",
|
||||
"Do not write a summary file as a substitute. Do not say the checkpoint is saved unless the checkpoint tool call succeeds.",
|
||||
"Your final action in this repair turn must be the checkpoint tool call.",
|
||||
);
|
||||
if (repairAttempt >= 2) {
|
||||
lines.push(
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ export function registerDbTools(pi) {
|
|||
},
|
||||
};
|
||||
pi.registerTool(summarySaveTool);
|
||||
// ─── sf_milestone_generate_id ────────────────────────────────────────
|
||||
// ─── new_milestone_id ────────────────────────────────────────
|
||||
const milestoneGenerateIdExecute = async (
|
||||
_toolCallId,
|
||||
_params,
|
||||
|
|
@ -468,7 +468,7 @@ export function registerDbTools(pi) {
|
|||
return {
|
||||
content: [{ type: "text", text: reserved }],
|
||||
details: {
|
||||
operation: "sf_milestone_generate_id",
|
||||
operation: "new_milestone_id",
|
||||
id: reserved,
|
||||
source: "reserved",
|
||||
},
|
||||
|
|
@ -486,7 +486,7 @@ export function registerDbTools(pi) {
|
|||
return {
|
||||
content: [{ type: "text", text: newId }],
|
||||
details: {
|
||||
operation: "sf_milestone_generate_id",
|
||||
operation: "new_milestone_id",
|
||||
id: newId,
|
||||
existingCount: existingIds.length,
|
||||
uniqueEnabled,
|
||||
|
|
@ -501,7 +501,7 @@ export function registerDbTools(pi) {
|
|||
text: `Error generating milestone ID: ${msg}`,
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_milestone_generate_id", error: msg },
|
||||
details: { operation: "new_milestone_id", error: msg },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -525,7 +525,7 @@ export function registerDbTools(pi) {
|
|||
}
|
||||
}
|
||||
const milestoneGenerateIdTool = {
|
||||
name: "sf_milestone_generate_id",
|
||||
name: "new_milestone_id",
|
||||
label: "Generate Milestone ID",
|
||||
description:
|
||||
"Generate the next milestone ID for a new SF milestone. " +
|
||||
|
|
@ -534,7 +534,7 @@ export function registerDbTools(pi) {
|
|||
promptSnippet:
|
||||
"Generate a valid milestone ID (respects unique_milestone_ids preference)",
|
||||
promptGuidelines: [
|
||||
"ALWAYS call sf_milestone_generate_id before creating a new milestone directory or writing milestone files.",
|
||||
"ALWAYS call new_milestone_id before creating a new milestone directory or writing milestone files.",
|
||||
"Never invent or hardcode milestone IDs like M001, M002 — always use this tool.",
|
||||
"Call it once per milestone you need to create. For multi-milestone projects, call it once for each milestone in sequence.",
|
||||
"The tool returns the correct format based on project preferences (e.g. M001 or M001-r5jzab).",
|
||||
|
|
@ -543,7 +543,7 @@ export function registerDbTools(pi) {
|
|||
execute: milestoneGenerateIdExecute,
|
||||
renderCall(_args, theme) {
|
||||
return new Text(
|
||||
theme.fg("toolTitle", theme.bold("sf_milestone_generate_id")),
|
||||
theme.fg("toolTitle", theme.bold("new_milestone_id")),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
|
@ -563,7 +563,7 @@ export function registerDbTools(pi) {
|
|||
},
|
||||
};
|
||||
pi.registerTool(milestoneGenerateIdTool);
|
||||
// ─── sf_self_report ─────────────────────────────────────────────────
|
||||
// ─── report_issue ─────────────────────────────────────────────────
|
||||
// Agent-callable bug-report channel. Records anomalies the agent observes
|
||||
// in sf's own behavior so they accumulate in self-feedback (forge's own
|
||||
// .sf/SELF-FEEDBACK.md when running on forge itself, ~/.sf/agent/upstream-feedback.jsonl
|
||||
|
|
@ -625,18 +625,18 @@ export function registerDbTools(pi) {
|
|||
};
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
logError("tool", `sf_self_report tool failed: ${msg}`, {
|
||||
tool: "sf_self_report",
|
||||
logError("tool", `report_issue tool failed: ${msg}`, {
|
||||
tool: "report_issue",
|
||||
error: String(err),
|
||||
});
|
||||
return {
|
||||
content: [{ type: "text", text: `Error in sf_self_report: ${msg}` }],
|
||||
content: [{ type: "text", text: `Error in report_issue: ${msg}` }],
|
||||
details: { operation: "self_report", error: msg },
|
||||
};
|
||||
}
|
||||
};
|
||||
const selfReportTool = {
|
||||
name: "sf_self_report",
|
||||
name: "report_issue",
|
||||
label: "Self Report",
|
||||
description:
|
||||
"Record any thought about sf itself — bugs, missing features, prompt-quality issues, ideas, " +
|
||||
|
|
@ -651,9 +651,9 @@ export function registerDbTools(pi) {
|
|||
promptSnippet:
|
||||
"Report any sf-internal observation: bug, missing feature, prompt issue, idea, friction",
|
||||
promptGuidelines: [
|
||||
"Use sf_self_report for ANY sf-internal observation — not just bugs. Acceptable kinds include: 'prompt-quality-issue' (you found a prompt ambiguous, contradictory, or missing context), 'improvement-idea' (a non-bug enhancement that would help), 'agent-friction' (workflow friction you worked around), 'design-thought' (broader speculation), 'missing-feature' (capability you wished sf had), as well as classic bug kinds like 'brittle-predicate' or 'git-empty-pathspec'.",
|
||||
"Use report_issue for ANY sf-internal observation — not just bugs. Acceptable kinds include: 'prompt-quality-issue' (you found a prompt ambiguous, contradictory, or missing context), 'improvement-idea' (a non-bug enhancement that would help), 'agent-friction' (workflow friction you worked around), 'design-thought' (broader speculation), 'missing-feature' (capability you wished sf had), as well as classic bug kinds like 'brittle-predicate' or 'git-empty-pathspec'.",
|
||||
"Do NOT use this for bugs in the user's project, for your own task work, or to track your task's todo list. ONLY for observations about sf-the-tool itself.",
|
||||
"This tool FILES new entries; it does not resolve existing ones. High/critical forge self-feedback may be queued autonomously at startup or an idle turn boundary as repair work. Use sf_self_feedback_resolve after fixing an entry; do not hand-edit the JSONL.",
|
||||
"This tool FILES new entries; it does not resolve existing ones. High/critical forge self-feedback may be queued autonomously at startup or an idle turn boundary as repair work. Use resolve_issue after fixing an entry; do not hand-edit the JSONL.",
|
||||
"Over-reporting is preferred to under-reporting at this stage. If you noticed it about sf, file it. Dedup and threshold-to-roadmap promotion are tracked as their own self-feedback items and will eventually clean noise.",
|
||||
"Severity guide: low = cosmetic / nice-to-have / improvement idea. medium = noisy or imperfect or recurring friction. high = blocked the unit (sf-the-tool prevented you from completing the task). critical = needs immediate fix (currently treated as high until inline-fix dispatch lands).",
|
||||
"high/critical entries mark the originating unit as blocked: it will not seal as success, and will be re-queued only after sf is bumped past the recorded version.",
|
||||
|
|
@ -716,7 +716,7 @@ export function registerDbTools(pi) {
|
|||
}),
|
||||
execute: selfReportExecute,
|
||||
renderCall(args, theme) {
|
||||
let text = theme.fg("toolTitle", theme.bold("sf_self_report "));
|
||||
let text = theme.fg("toolTitle", theme.bold("report_issue "));
|
||||
if (args.severity)
|
||||
text += theme.fg(
|
||||
args.severity === "critical" || args.severity === "high"
|
||||
|
|
@ -744,7 +744,7 @@ export function registerDbTools(pi) {
|
|||
},
|
||||
};
|
||||
pi.registerTool(selfReportTool);
|
||||
// ─── sf_self_feedback_resolve ────────────────────────────────────────
|
||||
// ─── resolve_issue ────────────────────────────────────────
|
||||
// Agent-callable resolver for inline self-feedback repair turns. The
|
||||
// inline-fix prompt must not rely on hand-editing JSONL: the tool updates
|
||||
// the structured source of truth and regenerates the markdown view.
|
||||
|
|
@ -800,15 +800,15 @@ export function registerDbTools(pi) {
|
|||
};
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
logError("tool", `sf_self_feedback_resolve tool failed: ${msg}`, {
|
||||
tool: "sf_self_feedback_resolve",
|
||||
logError("tool", `resolve_issue tool failed: ${msg}`, {
|
||||
tool: "resolve_issue",
|
||||
error: String(err),
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error in sf_self_feedback_resolve: ${msg}`,
|
||||
text: `Error in resolve_issue: ${msg}`,
|
||||
},
|
||||
],
|
||||
details: {
|
||||
|
|
@ -820,7 +820,7 @@ export function registerDbTools(pi) {
|
|||
}
|
||||
};
|
||||
pi.registerTool({
|
||||
name: "sf_self_feedback_resolve",
|
||||
name: "resolve_issue",
|
||||
label: "Resolve Self Feedback",
|
||||
description:
|
||||
"Mark a repaired SF self-feedback entry resolved with structured agent-fix evidence. " +
|
||||
|
|
@ -828,7 +828,7 @@ export function registerDbTools(pi) {
|
|||
promptSnippet:
|
||||
"Resolve a repaired SF self-feedback entry with commit/test evidence",
|
||||
promptGuidelines: [
|
||||
"Use sf_self_feedback_resolve during self-feedback inline-fix repair turns after the fix is implemented and verified.",
|
||||
"Use resolve_issue during self-feedback inline-fix repair turns after the fix is implemented and verified.",
|
||||
"Do not hand-edit `.sf/self-feedback.jsonl` or `.sf/SELF-FEEDBACK.md`; this tool updates the durable self-feedback store and regenerates the markdown projection.",
|
||||
"If the entry has acceptance criteria, pass criteria_met with the criteria that were satisfied.",
|
||||
"Pass commit_sha when a commit exists. If an entry was already fixed, cite the existing commit or include summary_narrative and test_path.",
|
||||
|
|
@ -861,7 +861,7 @@ export function registerDbTools(pi) {
|
|||
}),
|
||||
execute: selfFeedbackResolveExecute,
|
||||
renderCall(args, theme) {
|
||||
let text = theme.fg("toolTitle", theme.bold("sf_self_feedback_resolve "));
|
||||
let text = theme.fg("toolTitle", theme.bold("resolve_issue "));
|
||||
if (args.id) text += theme.fg("muted", args.id);
|
||||
return new Text(text, 0, 0);
|
||||
},
|
||||
|
|
@ -881,7 +881,7 @@ export function registerDbTools(pi) {
|
|||
);
|
||||
},
|
||||
});
|
||||
// ─── sf_autonomous_checkpoint ───────────────────────────────────────
|
||||
// ─── checkpoint ───────────────────────────────────────
|
||||
const autonomousCheckpointExecute = async (
|
||||
_toolCallId,
|
||||
params,
|
||||
|
|
@ -911,15 +911,15 @@ export function registerDbTools(pi) {
|
|||
};
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
logError("tool", `sf_autonomous_checkpoint tool failed: ${msg}`, {
|
||||
tool: "sf_autonomous_checkpoint",
|
||||
logError("tool", `checkpoint tool failed: ${msg}`, {
|
||||
tool: "checkpoint",
|
||||
error: String(err),
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error in sf_autonomous_checkpoint: ${msg}`,
|
||||
text: `Error in checkpoint: ${msg}`,
|
||||
},
|
||||
],
|
||||
details: { operation: "autonomous_checkpoint", error: msg },
|
||||
|
|
@ -927,7 +927,7 @@ export function registerDbTools(pi) {
|
|||
}
|
||||
};
|
||||
pi.registerTool({
|
||||
name: "sf_autonomous_checkpoint",
|
||||
name: "checkpoint",
|
||||
label: "Autonomous Checkpoint",
|
||||
description:
|
||||
"Record a PDD-shaped autonomous solver checkpoint for the current unit. " +
|
||||
|
|
@ -935,7 +935,7 @@ export function registerDbTools(pi) {
|
|||
promptSnippet:
|
||||
"Checkpoint autonomous solver progress with PDD fields and semantic outcome",
|
||||
promptGuidelines: [
|
||||
"Call sf_autonomous_checkpoint before ending an autonomous unit turn.",
|
||||
"Call checkpoint before ending an autonomous unit turn.",
|
||||
"Do not write SUMMARY.md, LOOP.md, task files, or chat prose as a substitute for this tool call.",
|
||||
"The checkpoint is recorded only when this actual tool returns success.",
|
||||
"Use outcome=complete only when the normal unit completion artifact/tool is also complete.",
|
||||
|
|
@ -1008,7 +1008,7 @@ export function registerDbTools(pi) {
|
|||
}),
|
||||
execute: autonomousCheckpointExecute,
|
||||
renderCall(args, theme) {
|
||||
let text = theme.fg("toolTitle", theme.bold("sf_autonomous_checkpoint "));
|
||||
let text = theme.fg("toolTitle", theme.bold("checkpoint "));
|
||||
if (args.outcome) text += theme.fg("accent", `[${args.outcome}] `);
|
||||
if (args.unitType || args.unitId) {
|
||||
text += theme.fg(
|
||||
|
|
@ -2526,7 +2526,7 @@ export function registerDbTools(pi) {
|
|||
execute: reassessRoadmapExecute,
|
||||
};
|
||||
pi.registerTool(reassessRoadmapTool);
|
||||
// ─── sf_save_gate_result ──────────────────────────────────────────────
|
||||
// ─── record_gate ──────────────────────────────────────────────
|
||||
const saveGateResultExecute = async (
|
||||
_toolCallId,
|
||||
params,
|
||||
|
|
@ -2537,7 +2537,7 @@ export function registerDbTools(pi) {
|
|||
return executeSaveGateResult(params, process.cwd());
|
||||
};
|
||||
const saveGateResultTool = {
|
||||
name: "sf_save_gate_result",
|
||||
name: "record_gate",
|
||||
label: "Save Gate Result",
|
||||
description:
|
||||
"Save the result of a quality gate evaluation (Q3-Q8 or MV01-MV04) to the SF database. " +
|
||||
|
|
@ -2545,7 +2545,7 @@ export function registerDbTools(pi) {
|
|||
promptSnippet:
|
||||
"Save quality gate evaluation result (verdict, rationale, findings)",
|
||||
promptGuidelines: [
|
||||
"Use sf_save_gate_result after evaluating a quality gate question.",
|
||||
"Use record_gate after evaluating a quality gate question.",
|
||||
"gateId must be one of: Q3, Q4, Q5, Q6, Q7, Q8, MV01, MV02, MV03, MV04.",
|
||||
"verdict must be: pass (no concerns), flag (concerns found), or omitted (not applicable).",
|
||||
"rationale should be a one-sentence justification for the verdict.",
|
||||
|
|
@ -2571,7 +2571,7 @@ export function registerDbTools(pi) {
|
|||
}),
|
||||
execute: saveGateResultExecute,
|
||||
renderCall(args, theme) {
|
||||
let text = theme.fg("toolTitle", theme.bold("sf_save_gate_result "));
|
||||
let text = theme.fg("toolTitle", theme.bold("record_gate "));
|
||||
text += theme.fg("accent", args.gateId ?? "");
|
||||
text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
|
||||
return new Text(text, 0, 0);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// SF — Exec (context-mode) tool registration.
|
||||
//
|
||||
// Registers the `sf_exec`, `sf_exec_search`, `sf_resume`, and `kill_agent`
|
||||
// Registers the `run_command`, `read_output`, `resume_agent`, and `kill_agent`
|
||||
// tools as native SF agent tools.
|
||||
// Opt-in: sf_exec is disabled unless `context_mode.enabled: true` is set
|
||||
// Opt-in: run_command is disabled unless `context_mode.enabled: true` is set
|
||||
// (or left unset — enabled by default).
|
||||
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
|
@ -19,7 +19,7 @@ import { executeResume } from "../tools/resume-tool.js";
|
|||
import { logWarning } from "../workflow-logger.js";
|
||||
export function registerExecTools(pi) {
|
||||
pi.registerTool({
|
||||
name: "sf_exec",
|
||||
name: "run_command",
|
||||
label: "Exec (Sandboxed)",
|
||||
description:
|
||||
"Run a short script (bash/node/python) in a subprocess. Full stdout/stderr persist to " +
|
||||
|
|
@ -30,7 +30,7 @@ export function registerExecTools(pi) {
|
|||
promptSnippet:
|
||||
"Run a bash/node/python script in a sandbox; full output is saved to disk and only a digest returns",
|
||||
promptGuidelines: [
|
||||
"Prefer sf_exec for analyses that would otherwise read >3 files or produce large tool output.",
|
||||
"Prefer run_command for analyses that would otherwise read >3 files or produce large tool output.",
|
||||
"Write scripts that log the finding (counts, matches, summaries) rather than raw dumps.",
|
||||
"The digest is the last ~300 chars of stdout — size your log output accordingly.",
|
||||
"Need the full output? Read the stdout_path returned in details (file on local disk).",
|
||||
|
|
@ -70,17 +70,17 @@ export function registerExecTools(pi) {
|
|||
} catch (err) {
|
||||
logWarning(
|
||||
"tool",
|
||||
`sf_exec could not load preferences: ${err instanceof Error ? err.message : String(err)}`,
|
||||
`run_command could not load preferences: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
onUpdate?.({
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `⏳ sf_exec: running ${params.runtime} script…`,
|
||||
text: `⏳ run_command: running ${params.runtime} script…`,
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_exec", status: "running" },
|
||||
details: { operation: "run_command", status: "running" },
|
||||
});
|
||||
return executeSfExec(params, {
|
||||
baseDir: process.cwd(),
|
||||
|
|
@ -89,13 +89,13 @@ export function registerExecTools(pi) {
|
|||
},
|
||||
});
|
||||
pi.registerTool({
|
||||
name: "sf_exec_search",
|
||||
label: "Search sf_exec History",
|
||||
name: "read_output",
|
||||
label: "Search run_command History",
|
||||
description:
|
||||
"List prior sf_exec runs (most recent first) from .sf/exec/*.meta.json. Useful for " +
|
||||
"List prior run_command runs (most recent first) from .sf/exec/*.meta.json. Useful for " +
|
||||
"rediscovering the stdout_path of an earlier run without re-executing it. Read-only.",
|
||||
promptSnippet:
|
||||
"Search prior sf_exec runs by substring, runtime, or failing-only filter",
|
||||
"Search prior run_command runs by substring, runtime, or failing-only filter",
|
||||
promptGuidelines: [
|
||||
"Use this before re-running an expensive analysis — the prior run's stdout file may still answer.",
|
||||
"The preview shows the trailing ~300 chars of stdout; read stdout_path for the full transcript.",
|
||||
|
|
@ -138,17 +138,17 @@ export function registerExecTools(pi) {
|
|||
},
|
||||
});
|
||||
pi.registerTool({
|
||||
name: "sf_resume",
|
||||
name: "resume_agent",
|
||||
label: "Resume (Read Snapshot)",
|
||||
description:
|
||||
"Return the contents of .sf/last-snapshot.md — a ≤2 KB digest of top memories, recent " +
|
||||
"sf_exec runs, and active context, written automatically on session_before_compact. Use " +
|
||||
"run_command runs, and active context, written automatically on session_before_compact. Use " +
|
||||
"this after compaction or session resume to re-orient quickly.",
|
||||
promptSnippet:
|
||||
"Read the pre-compaction snapshot to re-orient after context loss",
|
||||
promptGuidelines: [
|
||||
"Call this right after a session resumes if you feel you've lost durable context.",
|
||||
"The snapshot is a summary — use memory_query or sf_exec_search for detail.",
|
||||
"The snapshot is a summary — use memory_search or read_output for detail.",
|
||||
],
|
||||
parameters: Type.Object({}),
|
||||
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Judgment tools — expose sf_log_judgment to the agent in autonomous mode.
|
||||
* Judgment tools — expose log_decision to the agent in autonomous mode.
|
||||
*
|
||||
* The agent is instructed (via the system prompt) to call this tool when
|
||||
* making non-trivial calls so the user can review reasoning at milestone close.
|
||||
|
|
@ -8,7 +8,7 @@ import { Type } from "@sinclair/typebox";
|
|||
import { appendJudgment } from "../judgment-log.js";
|
||||
export function registerJudgmentTools(pi) {
|
||||
pi.registerTool({
|
||||
name: "sf_log_judgment",
|
||||
name: "log_decision",
|
||||
label: "Log Judgment",
|
||||
description:
|
||||
"Record an agent judgment call for user review at milestone close. " +
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SF — Memory tool registration
|
||||
//
|
||||
// Exposes the memory-layer tools (capture_thought, memory_query, sf_graph)
|
||||
// Exposes the memory-layer tools (log_reasoning, memory_search, memory_graph)
|
||||
// as native SF tools. All three degrade gracefully when the SF database is
|
||||
// unavailable.
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
|
@ -11,9 +11,9 @@ import {
|
|||
} from "../tools/memory-tools.js";
|
||||
import { ensureDbOpen } from "./dynamic-tools.js";
|
||||
export function registerMemoryTools(pi) {
|
||||
// ─── capture_thought ────────────────────────────────────────────────────
|
||||
// ─── log_reasoning ────────────────────────────────────────────────────
|
||||
pi.registerTool({
|
||||
name: "capture_thought",
|
||||
name: "log_reasoning",
|
||||
label: "Capture Thought",
|
||||
description:
|
||||
"Record a durable piece of project knowledge (decision, convention, gotcha, pattern, " +
|
||||
|
|
@ -22,7 +22,7 @@ export function registerMemoryTools(pi) {
|
|||
promptSnippet:
|
||||
"Capture a durable project insight into the SF memory store (categories: architecture, convention, gotcha, pattern, preference, environment)",
|
||||
promptGuidelines: [
|
||||
"Use capture_thought for insights that will remain useful across future sessions.",
|
||||
"Use log_reasoning for insights that will remain useful across future sessions.",
|
||||
"Do NOT capture one-off bug fixes, temporary state, secrets, or task-specific details.",
|
||||
"Keep content to 1–3 sentences.",
|
||||
"Set confidence: 0.6 tentative, 0.8 solid, 0.95 well-confirmed (default 0.8).",
|
||||
|
|
@ -67,9 +67,9 @@ export function registerMemoryTools(pi) {
|
|||
return executeMemoryCapture(params);
|
||||
},
|
||||
});
|
||||
// ─── memory_query ───────────────────────────────────────────────────────
|
||||
// ─── memory_search ───────────────────────────────────────────────────────
|
||||
pi.registerTool({
|
||||
name: "memory_query",
|
||||
name: "memory_search",
|
||||
label: "Query Memory",
|
||||
description:
|
||||
"Search the SF memory store for relevant memories. Uses keyword matching ranked " +
|
||||
|
|
@ -77,7 +77,7 @@ export function registerMemoryTools(pi) {
|
|||
promptSnippet:
|
||||
"Search the SF memory store by keyword; returns ranked memories with id, category, and content",
|
||||
promptGuidelines: [
|
||||
"Use memory_query when you need durable project context that may not be in the current prompt.",
|
||||
"Use memory_search when you need durable project context that may not be in the current prompt.",
|
||||
"Provide a short keyword-style query — not a full question.",
|
||||
"Use category to narrow results to gotchas, conventions, architecture notes, etc.",
|
||||
],
|
||||
|
|
@ -120,16 +120,16 @@ export function registerMemoryTools(pi) {
|
|||
text: "Error: SF database is not available. Cannot query memory.",
|
||||
},
|
||||
],
|
||||
details: { operation: "memory_query", error: "db_unavailable" },
|
||||
details: { operation: "memory_search", error: "db_unavailable" },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
return executeMemoryQuery(params);
|
||||
},
|
||||
});
|
||||
// ─── sf_graph ──────────────────────────────────────────────────────────
|
||||
// ─── memory_graph ──────────────────────────────────────────────────────────
|
||||
pi.registerTool({
|
||||
name: "sf_graph",
|
||||
name: "memory_graph",
|
||||
label: "SF Knowledge Graph",
|
||||
description:
|
||||
"Inspect the relationship graph between memories. mode=query walks supersedes edges from a " +
|
||||
|
|
@ -177,7 +177,7 @@ export function registerMemoryTools(pi) {
|
|||
text: "Error: SF database is not available.",
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_graph", error: "db_unavailable" },
|
||||
details: { operation: "memory_graph", error: "db_unavailable" },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function registerQueryTools(pi) {
|
|||
},
|
||||
});
|
||||
pi.registerTool({
|
||||
name: "sf_retrieval_evidence",
|
||||
name: "search_evidence",
|
||||
label: "Retrieval Evidence",
|
||||
description:
|
||||
"Read recent retrieval provenance from the SF database. Returns source backend, query, scope, freshness, status, and result metadata. " +
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ export function registerHooks(pi, ecosystemHandlers = []) {
|
|||
"sf_plan_milestone",
|
||||
"sf_plan_slice",
|
||||
"sf_plan_task",
|
||||
"sf_milestone_generate_id",
|
||||
"new_milestone_id",
|
||||
"sf_replan_slice",
|
||||
"sf_reassess_roadmap",
|
||||
]);
|
||||
|
|
@ -828,7 +828,7 @@ export function registerHooks(pi, ecosystemHandlers = []) {
|
|||
`unknowns (API behavior, version compatibility, library defaults).\n` +
|
||||
`4. Self-assess: rate your confidence 0–1. If ≥ 0.98 → proceed. ` +
|
||||
`If still < 0.98 → there is a real, concrete blocker.\n` +
|
||||
`5. Concrete blocker only: call sf_autonomous_checkpoint with outcome="blocked" ` +
|
||||
`5. Concrete blocker only: call checkpoint with outcome="blocked" ` +
|
||||
`and a precise blockerReason naming the specific unresolvable gap ` +
|
||||
`(missing credentials, impossible contract, safety violation, legal scope).\n\n` +
|
||||
`Do NOT call ask_user_questions again. Do NOT pause for user input. ` +
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export function registerSessionTodoTool(pi) {
|
|||
"Add, check off, or list session-scoped tasks that survive compaction",
|
||||
promptGuidelines: [
|
||||
"Add todos at the start of complex multi-step work so you don't lose track after compaction.",
|
||||
"Check items off as you complete them — the list is visible in sf_resume after compaction.",
|
||||
"Check items off as you complete them — the list is visible in resume_agent after compaction.",
|
||||
"Use list before starting a new sub-task to see what remains.",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
|
|
|
|||
|
|
@ -307,9 +307,9 @@ export async function buildBeforeAgentStartResult(event, ctx) {
|
|||
// stronger language that forbids ask_user_questions entirely.
|
||||
const escalationPolicyBlock = buildEscalationPolicyBlock(isCanAskUser());
|
||||
// Judgment-log instruction for autonomous mode: agent is prompted to call
|
||||
// sf_log_judgment when making non-trivial calls between alternatives.
|
||||
// log_decision when making non-trivial calls between alternatives.
|
||||
const judgmentLogBlock = !isCanAskUser()
|
||||
? `\n\n[JUDGMENT LOG — autonomous mode]\nWhen you make a judgment call between alternatives at an ambiguous point, call sf_log_judgment with: decision, alternatives, reasoning, confidence. This lets the user review your reasoning at milestone close. It does NOT delay or block the work.`
|
||||
? `\n\n[JUDGMENT LOG — autonomous mode]\nWhen you make a judgment call between alternatives at an ambiguous point, call log_decision with: decision, alternatives, reasoning, confidence. This lets the user review your reasoning at milestone close. It does NOT delay or block the work.`
|
||||
: "";
|
||||
const selfFeedbackBlock = loadSelfFeedbackBlock(process.cwd());
|
||||
const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — SF]\n\n${escalationPolicyBlock}${systemContent}${preferenceBlock}${knowledgeBlock}${architectureBlock}${tacitKnowledgeBlock}${codebaseBlock}${codeIntelligenceBlock}${memoryBlock}${newSkillsBlock}${selfFeedbackBlock}${worktreeBlock}${repositoryVcsBlock}${modelIdentityBlock}${subagentModelBlock}${judgmentLogBlock}`;
|
||||
|
|
@ -444,7 +444,7 @@ function loadSelfFeedbackBlock(cwd) {
|
|||
}
|
||||
// Add note about where to find full evidence
|
||||
if (entries.length > kept.length) {
|
||||
block += `\n\n*(${entries.length - kept.length} more entries hidden to prevent context bloat. Use sf_self_feedback_resolve/read tools or .sf/SELF-FEEDBACK.md entry IDs to inspect full evidence.)*`;
|
||||
block += `\n\n*(${entries.length - kept.length} more entries hidden to prevent context bloat. Use resolve_issue/read tools or .sf/SELF-FEEDBACK.md entry IDs to inspect full evidence.)*`;
|
||||
}
|
||||
return `\n\n[SELF-FEEDBACK — Recent sf-internal anomalies]\n\n${block}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const QUEUE_SAFE_TOOLS = new Set([
|
|||
"glob",
|
||||
// Discussion & planning tools
|
||||
"ask_user_questions",
|
||||
"sf_milestone_generate_id",
|
||||
"new_milestone_id",
|
||||
"sf_summary_save",
|
||||
// Web research tools used during queue discussion
|
||||
"search-the-web",
|
||||
|
|
|
|||
|
|
@ -116,21 +116,21 @@ Items without a \`Source:\` line are invalid.
|
|||
|
||||
## Optional: Capture Individual Learnings
|
||||
|
||||
If the \`capture_thought\` tool is available, call it once for each extracted item with:
|
||||
If the \`log_reasoning\` tool is available, call it once for each extracted item with:
|
||||
- category: "decision" | "lesson" | "pattern" | "surprise"
|
||||
- phase: "${ctx.milestoneId}"
|
||||
- content: {the learning text}
|
||||
- source: {artifact filename}
|
||||
|
||||
If \`capture_thought\` is not available, skip this step silently — do not report an error.
|
||||
If \`log_reasoning\` is not available, skip this step silently — do not report an error.
|
||||
|
||||
---
|
||||
|
||||
## Rebuild Knowledge Graph
|
||||
|
||||
After writing LEARNINGS.md, call the \`sf_graph\` tool with \`{ "mode": "build" }\` to rebuild the knowledge graph so the new learnings are immediately queryable by future milestone prompts.
|
||||
After writing LEARNINGS.md, call the \`memory_graph\` tool with \`{ "mode": "build" }\` to rebuild the knowledge graph so the new learnings are immediately queryable by future milestone prompts.
|
||||
|
||||
If the \`sf_graph\` tool is not available, skip this step silently.
|
||||
If the \`memory_graph\` tool is not available, skip this step silently.
|
||||
`;
|
||||
}
|
||||
export function buildFrontmatter(ctx) {
|
||||
|
|
@ -273,27 +273,27 @@ feed from its content.
|
|||
### Step 3 — Optionally pre-query the memory store for semantic duplicates
|
||||
|
||||
Before persisting any extracted item in Steps 4–6, you may call
|
||||
\`memory_query\` with 2–3 keywords from the item to check whether the
|
||||
\`memory_search\` with 2–3 keywords from the item to check whether the
|
||||
memory store already holds a semantically equivalent entry at high
|
||||
confidence. Skip those items in their respective steps.
|
||||
|
||||
### Step 4 — Persist Patterns via \`capture_thought\`
|
||||
### Step 4 — Persist Patterns via \`log_reasoning\`
|
||||
|
||||
For each extracted Pattern, call \`capture_thought\` exactly once with:
|
||||
For each extracted Pattern, call \`log_reasoning\` exactly once with:
|
||||
- \`category: "pattern"\`
|
||||
- \`content\`: a 1–2 sentence restatement combining the Pattern, Where, and any non-obvious notes
|
||||
- \`scope: "${ctx.milestoneId}"\`
|
||||
|
||||
### Step 5 — Persist Lessons via \`capture_thought\`
|
||||
### Step 5 — Persist Lessons via \`log_reasoning\`
|
||||
|
||||
For each extracted Lesson, call \`capture_thought\` exactly once with:
|
||||
For each extracted Lesson, call \`log_reasoning\` exactly once with:
|
||||
- \`category: "gotcha"\` when the Lesson describes a pitfall, surprise root cause, or recurring failure mode; \`category: "convention"\` when it describes a project-wide rule or normative practice
|
||||
- \`content\`: a 1–3 sentence restatement of What Happened + Root Cause + Fix
|
||||
- \`scope: "${ctx.milestoneId}"\`
|
||||
|
||||
### Step 6 — Persist Decisions via \`capture_thought\`
|
||||
### Step 6 — Persist Decisions via \`log_reasoning\`
|
||||
|
||||
For each extracted Decision, call \`capture_thought\` exactly once with:
|
||||
For each extracted Decision, call \`log_reasoning\` exactly once with:
|
||||
- \`category: "architecture"\`
|
||||
- \`content\`: a 1–3 sentence restatement combining decision + choice + rationale
|
||||
- \`scope: "${ctx.milestoneId}"\`
|
||||
|
|
@ -301,12 +301,12 @@ For each extracted Decision, call \`capture_thought\` exactly once with:
|
|||
|
||||
### Step 7 — Deduplication rule (applies to Steps 4, 5, 6)
|
||||
|
||||
Before each \`capture_thought\` call, optionally call \`memory_query\` with 2–3
|
||||
Before each \`log_reasoning\` call, optionally call \`memory_search\` with 2–3
|
||||
keywords from the entry. If a semantically equivalent memory is returned at
|
||||
high confidence, skip the capture entirely.
|
||||
|
||||
### Step 8 — Surprises stay only in LEARNINGS.md
|
||||
|
||||
Surprises are milestone-local context and are NOT cross-session-reusable. Do
|
||||
not persist them via \`capture_thought\` or any other native memory tool.`;
|
||||
not persist them via \`log_reasoning\` or any other native memory tool.`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ function buildExtractPrompt(source) {
|
|||
return [
|
||||
header,
|
||||
"",
|
||||
"Read the content below and call the `capture_thought` tool once per durable insight",
|
||||
"Read the content below and call the `log_reasoning` tool once per durable insight",
|
||||
"(architecture, convention, gotcha, preference, environment, pattern). Skip one-off details,",
|
||||
"temporary state, and anything secret. Keep each memory to 1–3 sentences.",
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SF Compaction Snapshot — writes a ≤2 KB markdown digest of durable
|
||||
// project state before the session context is compacted. On resume, an
|
||||
// agent can `sf_resume` (or Read .sf/last-snapshot.md) to re-orient
|
||||
// agent can `resume_agent` (or Read .sf/last-snapshot.md) to re-orient
|
||||
// without re-deriving the same memories.
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
|
|
@ -38,7 +38,7 @@ export function buildSnapshot(sources, opts = {}) {
|
|||
}
|
||||
const exec = sources.execHistory.slice(0, maxExec);
|
||||
if (exec.length > 0) {
|
||||
lines.push("## Recent sf_exec runs");
|
||||
lines.push("## Recent run_command runs");
|
||||
for (const entry of exec) {
|
||||
const status = entry.timed_out
|
||||
? "timeout"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const CACHE_MAX = 50;
|
|||
* - sf_summary_save: writes CONTEXT.md artifacts (all discuss prompts)
|
||||
* - sf_decision_save: records decisions (discuss.md output phase)
|
||||
* - sf_plan_milestone: writes roadmap (discuss.md single/multi milestone)
|
||||
* - sf_milestone_generate_id: generates milestone IDs (discuss.md multi-milestone)
|
||||
* - new_milestone_id: generates milestone IDs (discuss.md multi-milestone)
|
||||
* - sf_requirement_update: updates requirements during discuss
|
||||
*/
|
||||
export const DISCUSS_TOOLS_ALLOWLIST = [
|
||||
|
|
@ -41,7 +41,7 @@ export const DISCUSS_TOOLS_ALLOWLIST = [
|
|||
// Milestone planning (needed for discuss.md output phase)
|
||||
"sf_plan_milestone",
|
||||
// Milestone ID generation (multi-milestone flow)
|
||||
"sf_milestone_generate_id",
|
||||
"new_milestone_id",
|
||||
// Requirement updates
|
||||
"sf_requirement_update",
|
||||
];
|
||||
|
|
@ -57,7 +57,7 @@ export const DISCUSS_TOOLS_ALLOWLIST = [
|
|||
* Consumer: guided-flow.ts and auto/run-unit.ts when narrowing SF tools for
|
||||
* research-milestone and research-slice turns.
|
||||
*/
|
||||
export const RESEARCH_TOOLS_ALLOWLIST = ["sf_summary_save", "sf_self_report"];
|
||||
export const RESEARCH_TOOLS_ALLOWLIST = ["sf_summary_save", "report_issue"];
|
||||
/**
|
||||
* Return the SF tool allowlist for a workflow unit, or null when the full SF
|
||||
* tool set is appropriate.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SF Exec History — read-side helpers for the exec sandbox.
|
||||
//
|
||||
// Pure I/O: scans `.sf/exec/*.meta.json` under a base directory and
|
||||
// returns lightweight records. Used by the sf_exec_search tool and
|
||||
// returns lightweight records. Used by the read_output tool and
|
||||
// any future compaction-snapshot enrichment.
|
||||
import {
|
||||
closeSync,
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export function extractExecutionPolicyInput(toolName, input) {
|
|||
if (toolName === "write" || toolName === "edit") {
|
||||
return String(input.path ?? "");
|
||||
}
|
||||
if (toolName === "sf_exec") return String(input.script ?? "");
|
||||
if (toolName === "run_command") return String(input.script ?? "");
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ export async function showQueueAdd(_ctx, pi, basePath, state) {
|
|||
state,
|
||||
);
|
||||
// ── Determine next milestone ID ─────────────────────────────────────
|
||||
// Note: the LLM will use the sf_milestone_generate_id tool to get IDs
|
||||
// Note: the LLM will use the new_milestone_id tool to get IDs
|
||||
// at creation time, but we still mention the next ID in the preamble
|
||||
// for context about where the sequence is.
|
||||
const uniqueEnabled =
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ export function injectTodoContext(basePath, preamble) {
|
|||
// ─── ID Generation with Reservation ─────────────────────────────────────────
|
||||
/**
|
||||
* Generate the next milestone ID, accounting for reserved IDs, and reserve it.
|
||||
* Ensures any preview ID shown in the UI matches what `sf_milestone_generate_id`
|
||||
* Ensures any preview ID shown in the UI matches what `new_milestone_id`
|
||||
* will later return.
|
||||
*/
|
||||
function nextMilestoneIdReserved(existingIds, uniqueEnabled) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* JudgmentEntries accumulate in the SQLite judgments table (schema v40+).
|
||||
* Storage: sf.db judgments table — DB-first, no file fallback.
|
||||
*
|
||||
* The tool `sf_log_judgment` (registered in dynamic-tools.ts or equivalent)
|
||||
* The tool `log_decision` (registered in dynamic-tools.ts or equivalent)
|
||||
* calls appendJudgment(). readJudgmentLog() is used by the compounding step.
|
||||
*/
|
||||
import { mkdirSync } from "node:fs";
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// Read consumers:
|
||||
// (1) `getRelevantMemoriesRanked` walks edges of cosine top-N memories
|
||||
// and applies a one-pass intra-pool score boost (damping 0.4).
|
||||
// (2) `sf_graph` exposes BFS traversal for explicit agent queries.
|
||||
// (2) `memory_graph` exposes BFS traversal for explicit agent queries.
|
||||
// All writes go through the single-writer gate in `sf-db.ts`.
|
||||
import { _getAdapter, isDbAvailable } from "./sf-db.js";
|
||||
export const VALID_RELATIONS = [
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export function nextMilestoneId(milestoneIds, uniqueEnabled) {
|
|||
/**
|
||||
* Module-level set of milestone IDs that have been previewed/promised to the
|
||||
* user but not yet materialised on disk. Both guided-flow (preview) and
|
||||
* sf_milestone_generate_id (tool) share this set so the ID shown in the UI
|
||||
* new_milestone_id (tool) share this set so the ID shown in the UI
|
||||
* matches the one the tool returns.
|
||||
*/
|
||||
const reservedMilestoneIds = new Set();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* in filesystem or loading logic.
|
||||
*/
|
||||
/**
|
||||
* Resolve whether context-mode features (sf_exec sandbox + compaction snapshot)
|
||||
* Resolve whether context-mode features (run_command sandbox + compaction snapshot)
|
||||
* should be active. Default is ON: missing config or missing `enabled` is true.
|
||||
*/
|
||||
export function isContextModeEnabled(prefs) {
|
||||
|
|
|
|||
|
|
@ -35,4 +35,4 @@ You are generating tests for recently completed SF work.
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ Call `sf_summary_save` with `milestone_id: {{milestoneId}}`, `artifact_type: "CH
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If you observe sf-the-tool friction during this unit, file via `sf_self_report`.
|
||||
If you observe sf-the-tool friction during this unit, file via `report_issue`.
|
||||
|
||||
When done, say: "Challenge {{milestoneId}} complete — verdict: <verdict>."
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ If work falls into the second bucket, do not fail the milestone just because it
|
|||
- `deviations` (string) — Deviations from the original plan
|
||||
12. Update `.sf/PROJECT.md`: use the `write` tool with `path: ".sf/PROJECT.md"` and `content` containing the full updated document reflecting milestone completion and current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
|
||||
13. Review all slice summaries for cross-cutting lessons, patterns, or gotchas that emerged during this milestone. Append any non-obvious, reusable insights to `.sf/KNOWLEDGE.md`.
|
||||
13b. Review `.sf/SELF-FEEDBACK.md` (if present — it lives only when sf is dogfooded on forge) and the global `~/.sf/agent/upstream-feedback.jsonl`. For any sf-internal anomaly that recurred across multiple slices in this milestone but is not yet captured in either log, file it now via `sf_self_report`. The milestone-close agent is the last line of defense for systemic sf bugs that single-task agents missed.
|
||||
13b. Review `.sf/SELF-FEEDBACK.md` (if present — it lives only when sf is dogfooded on forge) and the global `~/.sf/agent/upstream-feedback.jsonl`. For any sf-internal anomaly that recurred across multiple slices in this milestone but is not yet captured in either log, file it now via `report_issue`. The milestone-close agent is the last line of defense for systemic sf bugs that single-task agents missed.
|
||||
14. Do not commit manually — the system auto-commits your changes after this unit completes.
|
||||
- Say: "Milestone {{milestoneId}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Then:
|
|||
8. Draft the UAT content you will pass as `uatContent` — a concrete UAT script with real test cases derived from the slice plan and task summaries. Include preconditions, numbered steps with expected outcomes, and edge cases. This must NOT be a placeholder or generic template — tailor every test case to what this slice actually built.
|
||||
9. Review task summaries for `key_decisions`. Append any significant decisions to `.sf/DECISIONS.md` if missing.
|
||||
10. Review task summaries for patterns, gotchas, or non-obvious lessons learned. If any would save future agents from repeating investigation or hitting the same issues, append them to `.sf/KNOWLEDGE.md`. Only add entries that are genuinely useful — don't pad with obvious observations.
|
||||
10b. Scan task summaries and the slice's activity log for sf-internal anomalies that the per-task agents may not have reported individually — repeated `Git stage failed`, `Verification failed … advisory`, `Safety: N unexpected file change(s)`, brittle gate predicates, etc. For any genuine sf-the-tool defect that surfaced during this slice but was NOT already filed via `sf_self_report`, file it now via `sf_self_report` with appropriate severity. This is the slice-level sweep — task-level agents file individual reports during execution; the slice-close agent catches systemic issues only visible across multiple tasks.
|
||||
10b. Scan task summaries and the slice's activity log for sf-internal anomalies that the per-task agents may not have reported individually — repeated `Git stage failed`, `Verification failed … advisory`, `Safety: N unexpected file change(s)`, brittle gate predicates, etc. For any genuine sf-the-tool defect that surfaced during this slice but was NOT already filed via `report_issue`, file it now via `report_issue` with appropriate severity. This is the slice-level sweep — task-level agents file individual reports during execution; the slice-close agent catches systemic issues only visible across multiple tasks.
|
||||
11. Call `sf_slice_complete` with the camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`, plus any optional enrichment fields you have. Do NOT manually mark the roadmap checkbox — the tool writes to the DB, renders `{{sliceSummaryPath}}` and `{{sliceUatPath}}`, and updates the ROADMAP.md projection automatically.
|
||||
12. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds.
|
||||
13. Update `.sf/PROJECT.md` if it exists — refresh current state if needed: use the `write` tool with `path: ".sf/PROJECT.md"` and `content` containing the full updated document reflecting current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ Goal semantics:
|
|||
## Instructions
|
||||
|
||||
1. Read `.sf/debug/sessions/{{slug}}.json` for any prior session context.
|
||||
1a. Call `memory_query` with keywords from the issue (error text, subsystem, file paths). A prior session may have captured this exact gotcha — finding it now saves the investigation.
|
||||
1a. Call `memory_search` with keywords from the issue (error text, subsystem, file paths). A prior session may have captured this exact gotcha — finding it now saves the investigation.
|
||||
2. Investigate the reported issue in `{{workingDirectory}}`.
|
||||
3. Follow the goal constraint above strictly.
|
||||
4. When complete, surface a clear summary: what failed, why, and what was done (or what a fix would require for root-cause-only mode).
|
||||
5. Once root cause is identified, call `capture_thought` with `category: "gotcha"` so future debug sessions can find it via `memory_query`. Keep the content to 1–3 sentences — the symptom, the root cause, and the fix or guard.
|
||||
5. Once root cause is identified, call `log_reasoning` with `category: "gotcha"` so future debug sessions can find it via `memory_search`. Keep the content to 1–3 sentences — the symptom, the root cause, and the fix or guard.
|
||||
|
||||
{{skillActivation}}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ If the deploy failed:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If you observe sf-the-tool friction during this unit, file via `sf_self_report`.
|
||||
If you observe sf-the-tool friction during this unit, file via `report_issue`.
|
||||
|
||||
When done, say: "Deploy {{milestoneId}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ After writing final context and roadmap, say exactly: "Milestone {{milestoneId}}
|
|||
|
||||
#### Phase 1: Shared artifacts
|
||||
|
||||
1. For each milestone, call `sf_milestone_generate_id` to get its ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices` for each.
|
||||
1. For each milestone, call `new_milestone_id` to get its ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices` for each.
|
||||
2. Write `.sf/PROJECT.md` — use the **Project** output template below.
|
||||
3. Write `.sf/REQUIREMENTS.md` — use the **Requirements** output template below. Capture Active, Deferred, Out of Scope, and any already Validated requirements. Later milestones may have provisional ownership where slice plans do not exist yet.
|
||||
4. For any architectural or pattern decisions, call `sf_decision_save` — the tool auto-assigns IDs and regenerates `.sf/DECISIONS.md` automatically.
|
||||
|
|
@ -313,11 +313,11 @@ After writing final context and roadmap, say exactly: "Milestone {{milestoneId}}
|
|||
- **Investigate thoroughly** — scout codebase, check library docs, web search. Same rigor as interactive mode.
|
||||
- **Build project knowledge first** — use Sift/grep/lsp evidence to identify stack signals, critical paths, verification commands, skill needs, file descriptions, and unresolved gaps before writing context. Update `.sf/CODEBASE.md` only when you need a refreshed durable fallback snapshot.
|
||||
- **Do focused research** — identify table stakes, domain standards, omissions, scope traps. Same rigor as interactive mode.
|
||||
- **Use proper tools** — `sf_plan_milestone` for roadmaps, `sf_decision_save` for decisions, `sf_milestone_generate_id` for IDs
|
||||
- **Use proper tools** — `sf_plan_milestone` for roadmaps, `sf_decision_save` for decisions, `new_milestone_id` for IDs
|
||||
- **Print artifacts in chat** — requirements table, roadmap preview, depth summary. The TUI scrollback is the user's audit trail.
|
||||
- **Use depends_on frontmatter** for multi-milestone sequences
|
||||
- **Anti-reduction rule** — if the spec describes a big vision, plan the big vision. Phase complexity — don't cut it.
|
||||
- **Naming convention** — always use `sf_milestone_generate_id` for IDs. Directories use bare IDs, files use ID-SUFFIX format.
|
||||
- **Naming convention** — always use `new_milestone_id` for IDs. Directories use bare IDs, files use ID-SUFFIX format.
|
||||
- **End with "Milestone {{milestoneId}} ready." only after final context and roadmap exist.** Draft output must end with "Milestone {{milestoneId}} drafted for discussion." so autonomous mode does not start from shallow knowledge.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ Once the user confirms the milestone split:
|
|||
|
||||
#### Phase 1: Shared artifacts
|
||||
|
||||
1. For each milestone, call `sf_milestone_generate_id` to get its ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices`.
|
||||
1. For each milestone, call `new_milestone_id` to get its ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices`.
|
||||
2. Write `.sf/PROJECT.md` — use the **Project** output template below.
|
||||
3. Write `.sf/REQUIREMENTS.md` — use the **Requirements** output template below. Capture Active, Deferred, Out of Scope, and any already Validated requirements. Later milestones may have provisional ownership where slice plans do not exist yet.
|
||||
4. For any architectural or pattern decisions made during discussion, call `sf_decision_save` — the tool auto-assigns IDs and regenerates `.sf/DECISIONS.md` automatically.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ Then:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
- End with: "SF doctor heal complete."
|
||||
|
|
@ -83,8 +83,8 @@ Then:
|
|||
- For compile/typecheck failures that mention an unknown method, function, type, import, or package member, verify the exact local API before editing. Use the language's own tooling or installed source (`go doc`, `go list`, module cache/source grep, `tsc` types, generated declarations, or equivalent). Do not invent adjacent method names.
|
||||
- After a compile-repair edit, rerun the narrow failing command immediately before more feature work. If two repair attempts leave the same unknown-symbol class, stop broad edits and write a precise handoff/blocker summary.
|
||||
17. **Blocker discovery:** If execution reveals that the remaining slice plan is fundamentally invalid — not just a bug or minor deviation, but a plan-invalidating finding like a wrong API, missing capability, or architectural mismatch — set `blocker_discovered: true` in the task summary frontmatter and describe the blocker clearly in the summary narrative. Do NOT set `blocker_discovered: true` for ordinary debugging, minor deviations, or issues that can be fixed within the current task or the remaining plan. This flag triggers an automatic replan of the slice.
|
||||
17b. **sf-internal anomalies and observations:** If during execution you observe sf-the-tool misbehaving (empty `git add --` pathspecs, brittle gate predicates, advisory-downgrade hiding real failures, false safety floods), find a prompt ambiguous or contradictory, hit workflow friction, or have an idea that would make sf better — call `sf_self_report`. Use `prompt-quality-issue`, `improvement-idea`, `agent-friction`, or `design-thought` kinds for non-bug observations alongside the classic bug kinds. Severity guide: `low`/`medium` for cosmetic / noisy / nice-to-have (sf continues); `high`/`critical` only when the sf issue actually prevents the task from sealing correctly (this blocks the unit). For high/critical, include `acceptance_criteria` so a future resolver has a falsifiable bar. This is distinct from `blocker_discovered` (which is about the user's plan, not about sf). Over-reporting is preferred to under-reporting at this stage.
|
||||
17c. **Self-feedback is a TRIAGE inbox, not a work queue.** Do NOT autonomously pick up entries from `.sf/SELF-FEEDBACK.md` or `~/.sf/agent/upstream-feedback.jsonl` and try to fix them — those are open observations awaiting human/triage-agent review to decide which become scheduled work, duplicates, or wontfix. Your scope is the task plan you were dispatched with. The only interaction your task should have with self-feedback is FILING new entries (via `sf_self_report`) when you observe sf-internal anomalies. The exception: if a self-feedback entry id is *explicitly named* in your task plan as the work to be done, treat it as you would any other planned item — read its `acceptanceCriteria`, satisfy each, and cite the entry id + criteria met in your task summary's `narrative` so the resolution is traceable.
|
||||
17b. **sf-internal anomalies and observations:** If during execution you observe sf-the-tool misbehaving (empty `git add --` pathspecs, brittle gate predicates, advisory-downgrade hiding real failures, false safety floods), find a prompt ambiguous or contradictory, hit workflow friction, or have an idea that would make sf better — call `report_issue`. Use `prompt-quality-issue`, `improvement-idea`, `agent-friction`, or `design-thought` kinds for non-bug observations alongside the classic bug kinds. Severity guide: `low`/`medium` for cosmetic / noisy / nice-to-have (sf continues); `high`/`critical` only when the sf issue actually prevents the task from sealing correctly (this blocks the unit). For high/critical, include `acceptance_criteria` so a future resolver has a falsifiable bar. This is distinct from `blocker_discovered` (which is about the user's plan, not about sf). Over-reporting is preferred to under-reporting at this stage.
|
||||
17c. **Self-feedback is a TRIAGE inbox, not a work queue.** Do NOT autonomously pick up entries from `.sf/SELF-FEEDBACK.md` or `~/.sf/agent/upstream-feedback.jsonl` and try to fix them — those are open observations awaiting human/triage-agent review to decide which become scheduled work, duplicates, or wontfix. Your scope is the task plan you were dispatched with. The only interaction your task should have with self-feedback is FILING new entries (via `report_issue`) when you observe sf-internal anomalies. The exception: if a self-feedback entry id is *explicitly named* in your task plan as the work to be done, treat it as you would any other planned item — read its `acceptanceCriteria`, satisfy each, and cite the entry id + criteria met in your task summary's `narrative` so the resolution is traceable.
|
||||
18. If you made an architectural, pattern, library, or observability decision during this task that downstream work should know about, append it to `.sf/DECISIONS.md` (read the template at `~/.sf/agent/extensions/sf/templates/decisions.md` if the file doesn't exist yet). Not every task produces decisions — only append when a meaningful choice was made.
|
||||
19. If you discover a non-obvious rule, recurring gotcha, or useful pattern during execution, append it to `.sf/KNOWLEDGE.md`. Only add entries that would save future agents from repeating your investigation. Don't add obvious things.
|
||||
20. Read the template at `~/.sf/agent/extensions/sf/templates/task-summary.md`
|
||||
|
|
|
|||
|
|
@ -199,4 +199,4 @@ Remind the user that the full forensic report was saved locally (the path will b
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ The following gate implementations may be present in this project. Each has dist
|
|||
|
||||
1. **Dispatch all gates** using `subagent` in parallel mode. Each subagent prompt is provided below.
|
||||
2. **Wait for all subagents** to complete.
|
||||
3. **Verify each gate wrote its result** by checking that `sf_save_gate_result` was called for each gate ID.
|
||||
3. **Verify each gate wrote its result** by checking that `record_gate` was called for each gate ID.
|
||||
4. **Report the batch outcome** — which gates passed, which flagged concerns, and which were omitted as not applicable.
|
||||
|
||||
## Verdict Discipline
|
||||
|
|
@ -60,4 +60,4 @@ When the batch returns, scan for `omitted` verdicts without a reason. Treat any
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ Complete slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Your
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ Execute the next task: {{taskId}} ("{{taskTitle}}") in slice {{sliceId}} of mile
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,6 @@ After writing the roadmap, analyze the slices and their boundary maps for extern
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ Plan slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.s
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.sf/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.sf/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. {{skillActivation}} Use native `lsp` first for symbol lookup, references, and cross-file navigation. For direct text inspection use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. If the repository is checked out locally, GitHub code search is a scarce remote-only fallback: do not use GitHub `/search/code` for that local repo; use `git grep` for tracked-file global search, `rg` for broader worktree text search, plus `lsp`, `sift_search`, or `codebase_search` instead. GitHub's `code_search` bucket is small and separate from normal REST/GraphQL quotas, so use it only for repositories that are not on disk, dedupe repeated queries, and treat `403` rate-limit responses as a signal to wait for reset or continue with local evidence. If there are 2-3 independent unknowns, use a research swarm with parallel `scout`/`researcher` subagents and synthesize their findings here; do not swarm narrow sequence-dependent research. Check libraries DeepWiki-first: `ask_question` / `read_wiki_structure` / `read_wiki_contents` for any GitHub-hosted library; fall back to `resolve_library` / `get_library_docs` (Context7, capped at 1000 req/month free) for npm/pypi/crates packages DeepWiki doesn't have. Skip both for libraries already used in this codebase. Use the **Research** output template below. Call `sf_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "RESEARCH"`, and the research content — the tool writes the file to disk and persists to DB. After `sf_summary_save` succeeds, stop immediately; do **not** call `sf_milestone_generate_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool.
|
||||
Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.sf/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.sf/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. {{skillActivation}} Use native `lsp` first for symbol lookup, references, and cross-file navigation. For direct text inspection use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. If the repository is checked out locally, GitHub code search is a scarce remote-only fallback: do not use GitHub `/search/code` for that local repo; use `git grep` for tracked-file global search, `rg` for broader worktree text search, plus `lsp`, `sift_search`, or `codebase_search` instead. GitHub's `code_search` bucket is small and separate from normal REST/GraphQL quotas, so use it only for repositories that are not on disk, dedupe repeated queries, and treat `403` rate-limit responses as a signal to wait for reset or continue with local evidence. If there are 2-3 independent unknowns, use a research swarm with parallel `scout`/`researcher` subagents and synthesize their findings here; do not swarm narrow sequence-dependent research. Check libraries DeepWiki-first: `ask_question` / `read_wiki_structure` / `read_wiki_contents` for any GitHub-hosted library; fall back to `resolve_library` / `get_library_docs` (Context7, capped at 1000 req/month free) for npm/pypi/crates packages DeepWiki doesn't have. Skip both for libraries already used in this codebase. Use the **Research** output template below. Call `sf_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "RESEARCH"`, and the research content — the tool writes the file to disk and persists to DB. After `sf_summary_save` succeeds, stop immediately; do **not** call `new_milestone_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool.
|
||||
|
||||
**You are the scout.** A planner agent reads your output in a fresh context to decompose this slice into tasks. Write for the planner — surface key files, where the work divides naturally, what to build first, and how to verify. If the research doc is vague, the planner re-explores code you already read. If it's precise, the planner decomposes immediately.
|
||||
|
||||
|
|
@ -14,6 +14,6 @@ Research should drive planning decisions, not just collect facts. Explicitly add
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ Resume interrupted work. Find the continue file (`{{sliceId}}-CONTINUE.md` or `c
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ Then write a brief summary of the finding to {{healArtifact}}.
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -34,4 +34,4 @@ The same task payloads are expanded below for readability.
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ If this milestone does not require any external API keys or secrets, skip this s
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction - ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas - file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries - your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction - ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas - file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries - your scope is your unit.
|
||||
|
||||
When done, say: "Milestone {{milestoneId}} planned."
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ The slice directory and tasks/ subdirectory already exist. Do NOT mkdir. All wor
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "Slice {{sliceId}} planned."
|
||||
|
||||
|
|
|
|||
|
|
@ -74,4 +74,4 @@ After the tool call, respond with:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ The user confirms or corrects before you write. One depth verification per miles
|
|||
|
||||
Once the user is satisfied, in a single pass for **each** new milestone:
|
||||
|
||||
1. Call `sf_milestone_generate_id` to get the milestone ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices`.
|
||||
1. Call `new_milestone_id` to get the milestone ID — never invent milestone IDs manually. Then `mkdir -p .sf/milestones/<ID>/slices`.
|
||||
2. Call `sf_summary_save` with `milestone_id: <ID>`, `artifact_type: "CONTEXT"`, and the full context markdown as `content` — the tool computes the file path and persists to both DB and disk. Capture intent, scope, risks, constraints, integration points, and relevant requirements in the content. Mark the status as "Queued — pending autonomous mode execution." **If this milestone depends on other milestones, include YAML frontmatter with `depends_on` in the content:**
|
||||
```yaml
|
||||
---
|
||||
|
|
@ -134,6 +134,6 @@ After writing the files and committing, say exactly: "Queued N milestone(s). Aut
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ You are executing a SF quick task — a lightweight, focused unit of work outsid
|
|||
- <what was tested/verified>
|
||||
```
|
||||
|
||||
If you observe sf-the-tool friction during this quick task, file it via `sf_self_report` before sealing.
|
||||
If you observe sf-the-tool friction during this quick task, file it via `report_issue` before sealing.
|
||||
|
||||
When done, say: "Quick task {{taskNum}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,6 @@ If any subagent fails:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
{{inlinedTemplates}}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ If `.sf/REQUIREMENTS.md` exists and requirement ownership or status changed, upd
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "Roadmap reassessed."
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ If publish fails (network error, auth error), set `published = 0` in release_rec
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If you observe sf-the-tool friction during this unit, file via `sf_self_report`.
|
||||
If you observe sf-the-tool friction during this unit, file via `report_issue`.
|
||||
|
||||
When done, say: "Release {{newVersion}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ Consider these captures when rewriting the remaining tasks — they represent th
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "Slice {{sliceId}} replanned."
|
||||
|
||||
|
|
|
|||
|
|
@ -60,11 +60,11 @@ Research the codebase and relevant technologies. Narrate key findings and surpri
|
|||
**Research is advisory, not auto-binding.** Surface candidate requirements clearly instead of silently expanding scope.
|
||||
|
||||
**You MUST call `sf_summary_save` with the research content before finishing.**
|
||||
After `sf_summary_save` succeeds, do **not** call `sf_milestone_generate_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool. The orchestrator dispatches planner units after research.
|
||||
After `sf_summary_save` succeeds, do **not** call `new_milestone_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool. The orchestrator dispatches planner units after research.
|
||||
|
||||
When done, say only: "Milestone {{milestoneId}} researched."
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say only: "Milestone {{milestoneId}} researched."
|
||||
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ Research what this slice needs. Narrate key findings and surprises as you go —
|
|||
The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir.
|
||||
|
||||
**You MUST call `sf_summary_save` with the research content before finishing.**
|
||||
After `sf_summary_save` succeeds, stop immediately. Do **not** call `sf_milestone_generate_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool. The orchestrator dispatches planner units after research.
|
||||
After `sf_summary_save` succeeds, stop immediately. Do **not** call `new_milestone_id`, `sf_plan_milestone`, `sf_plan_slice`, `sf_plan_task`, or any planning/creation tool. The orchestrator dispatches planner units after research.
|
||||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say only: "Slice {{sliceId}} researched."
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ queue order.
|
|||
**CRITICAL — Non-bypassable gate:** Discarding is irreversible. You MUST confirm with the user before discarding. Warn explicitly if the milestone has completed work. If the user does not respond or gives an ambiguous answer, you MUST re-ask — never rationalize past the block. A missing confirmation is a "do not discard."
|
||||
|
||||
### Add a new milestone
|
||||
Use the `sf_milestone_generate_id` tool to get the next ID, then call `sf_summary_save` with `milestone_id: {ID}`, `artifact_type: "CONTEXT"`, and the scope/goals/success criteria as `content` — the tool writes the context file to disk and persists to DB. Update the DB-backed queue order to place it at the desired position.
|
||||
Use the `new_milestone_id` tool to get the next ID, then call `sf_summary_save` with `milestone_id: {ID}`, `artifact_type: "CONTEXT"`, and the scope/goals/success criteria as `content` — the tool writes the context file to disk and persists to DB. Update the DB-backed queue order to place it at the desired position.
|
||||
|
||||
### Update dependencies
|
||||
Edit `depends_on` in the YAML frontmatter of a milestone's `{ID}-CONTEXT.md` file. For example:
|
||||
|
|
@ -97,4 +97,4 @@ If a proposed order would violate constraints, explain the issue and suggest alt
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -67,4 +67,4 @@ If the overall result is FAIL, explain what needs manual attention. If PASS WITH
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ An override was issued by the user that changes a fundamental decision or approa
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "Override applied across all documents."
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ Output `<turn_status>blocked</turn_status>` — the milestone requires a repair
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If you observe sf-the-tool friction during this unit, file via `sf_self_report`.
|
||||
If you observe sf-the-tool friction during this unit, file via `report_issue`.
|
||||
|
||||
When done, say: "Rollback {{milestoneId}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ date: <ISO 8601 timestamp>
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "UAT {{sliceId}} complete."
|
||||
|
||||
|
|
|
|||
|
|
@ -79,4 +79,4 @@ For this scan, only these documents are relevant: **{{documents}}**. Refer only
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ If any critical check fails:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If you observe sf-the-tool friction during this unit, file via `sf_self_report`.
|
||||
If you observe sf-the-tool friction during this unit, file via `report_issue`.
|
||||
|
||||
When done, say: "Smoke {{milestoneId}} complete — verdict: {{verdict}}."
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ Work through the self-feedback entries above. For each cluster of related entrie
|
|||
- Prefer `merge-into-existing-requirement` over creating a new requirement when the
|
||||
existing requirement's description already covers the failure mode.
|
||||
- Do not schedule work that is already covered by an in-flight slice.
|
||||
- Use `sf_self_report` only if you observe something NEW during this triage session
|
||||
- Use `report_issue` only if you observe something NEW during this triage session
|
||||
(e.g. a systematic gap in the self-feedback structure itself). Do not re-report
|
||||
entries already in self-feedback.
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ If verdict is `needs-remediation`:
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
||||
When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>."
|
||||
|
||||
|
|
|
|||
|
|
@ -27,4 +27,4 @@ and no resume mechanism. Just execute the instructions below and return.
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -29,4 +29,4 @@ Follow the workflow defined below. Execute each phase in order, completing one b
|
|||
|
||||
### Report sf-internal observations
|
||||
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `sf_self_report` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
// - Role-boundary overrides: "You are now DAN", "[SYSTEM]:", "<system>"
|
||||
// - Instruction override phrases: "ignore all previous instructions"
|
||||
// - Encoded payloads: long base64 strings embedded in content
|
||||
// Sources considered untrusted: sf_exec stdout (scripts fetching external
|
||||
// Sources considered untrusted: run_command stdout (scripts fetching external
|
||||
// data), web fetch / search result text, GitHub issue/PR body text, and
|
||||
// user-provided spec files from outside the repo.
|
||||
|
||||
|
|
|
|||
|
|
@ -153,8 +153,8 @@ function buildInlineFixPrompt(entries) {
|
|||
"2. Fix the smallest coherent set of code/docs/tests needed to satisfy the acceptance criteria.",
|
||||
"3. Run focused verification and typecheck for touched areas.",
|
||||
"4. Commit the fix with a conventional commit message.",
|
||||
"5. Call `sf_self_feedback_resolve` for each repaired entry with agent-fix evidence and the commit SHA.",
|
||||
"6. If an entry is already fixed, verify it and call `sf_self_feedback_resolve` with the verification evidence.",
|
||||
"5. Call `resolve_issue` for each repaired entry with agent-fix evidence and the commit SHA.",
|
||||
"6. If an entry is already fixed, verify it and call `resolve_issue` with the verification evidence.",
|
||||
"7. Do not hand-edit `.sf/self-feedback.jsonl` or `.sf/SELF-FEEDBACK.md`; use the resolver tool so the durable self-feedback store, markdown projection, and reload detection stay consistent.",
|
||||
"",
|
||||
"When done, say: Self-feedback inline fix complete.",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* Self-Feedback channel — sf records its own anomalies (caught by runtime
|
||||
* detectors or reported via the sf_self_report tool) so they can be addressed
|
||||
* detectors or reported via the report_issue tool) so they can be addressed
|
||||
* by future units.
|
||||
*
|
||||
* Routing:
|
||||
|
|
@ -50,7 +50,7 @@ const SF_HOME = process.env.SF_HOME || join(homedir(), ".sf");
|
|||
const SELF_FEEDBACK_HEADER =
|
||||
"# SF Self-Feedback\n\n" +
|
||||
"Anomalies caught during auto runs (by runtime detectors or via the\n" +
|
||||
"`sf_self_report` tool). Each row is a candidate work item for sf to\n" +
|
||||
"`report_issue` tool). Each row is a candidate work item for sf to\n" +
|
||||
"address in itself. This markdown file is a compact working view; the\n" +
|
||||
"durable source of truth is `.sf/sf.db`.\n\n" +
|
||||
"Blocking entries (severity high+) remain active until an sf fix explicitly\n" +
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Cover: purpose, consumer, contract, implementation sketch, test strategy, eviden
|
|||
When approved, persist to memory so the next session can find it:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="design-decision",
|
||||
content="design: <what> for <consumer> — approach: <key decision> — refused: <scope defence>",
|
||||
confidence=0.9
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ For the memory store, use SF's DB-backed memory/query tools rather than direct `
|
|||
/memory search "pattern"
|
||||
```
|
||||
|
||||
Inside an agent session, prefer the registered `memory_query` tool for targeted lookups.
|
||||
Inside an agent session, prefer the registered `memory_search` tool for targeted lookups.
|
||||
|
||||
Look for:
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ After a parallel or debate batch returns, the parent agent **must** synthesise.
|
|||
Persist non-trivial syntheses to memory:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="design-synthesis",
|
||||
content="<one-line synthesis of the swarm result> — slice <id>",
|
||||
confidence=<0.0-1.0>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ Keep scope tight: fix the validated review issue, not every adjacent redesign th
|
|||
After resolving significant review comments:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="review-learning",
|
||||
content="review caught: <what> in <component> — prevent by <design principle or test gap>",
|
||||
confidence=0.9
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ Stop when:
|
|||
Persist the delivery context so future units can trace what was built and why:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="delivery",
|
||||
content="delivered: <what changed> — slice: <id> — consumer: <caller> — insight: <what was learned>",
|
||||
confidence=0.9
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ LLM confidence is poorly calibrated in absolute terms — the relative signal ma
|
|||
- For non-trivial slices, persist the contract to sf memory:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="contract",
|
||||
content="<symbol> — <what the test proved> — slice <sliceId>",
|
||||
confidence=0.9
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ A check without a `Command run` block is a skip. "I re-ran the repro and it work
|
|||
Persist the pattern to memory so future units don't re-hit it:
|
||||
|
||||
```
|
||||
capture_thought(
|
||||
log_reasoning(
|
||||
category="anti-pattern",
|
||||
content="<symptom> in <component> — root cause: <one line> — fix: <approach> — test: <name>",
|
||||
confidence=0.9
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ import { logWarning } from "./workflow-logger.js";
|
|||
export function isGhostMilestone(basePath, mid) {
|
||||
// If the milestone has a DB row, it's usually a known milestone — not a ghost.
|
||||
// Exception: a "queued" row with no disk artifacts is a phantom from
|
||||
// sf_milestone_generate_id that was never planned (#3645).
|
||||
// new_milestone_id that was never planned (#3645).
|
||||
if (isDbAvailable()) {
|
||||
const dbRow = getMilestone(mid);
|
||||
if (dbRow) {
|
||||
|
|
|
|||
203
src/resources/extensions/sf/tests/auto-runaway-guard.test.mjs
Normal file
203
src/resources/extensions/sf/tests/auto-runaway-guard.test.mjs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* Tests for auto-runaway-guard.ts — progress-check behavior.
|
||||
*
|
||||
* Purpose: verify the runaway guard does not hard-pause units that are
|
||||
* making file-change progress, even when token growth would otherwise
|
||||
* trigger a hard pause.
|
||||
*
|
||||
* Consumer: autonomous loop — evaluateRunawayGuard() controls whether a
|
||||
* unit is warned, hard-paused, or allowed to continue.
|
||||
*/
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "vitest";
|
||||
import {
|
||||
clearRunawayGuardState,
|
||||
evaluateRunawayGuard,
|
||||
resetRunawayGuardState,
|
||||
} from "../auto-runaway-guard.js";
|
||||
|
||||
function makeConfig(overrides = {}) {
|
||||
return {
|
||||
enabled: true,
|
||||
toolCallWarning: 60,
|
||||
tokenWarning: 1_000_000,
|
||||
elapsedMs: 20 * 60 * 1000,
|
||||
changedFilesWarning: 75,
|
||||
diagnosticTurns: 2,
|
||||
hardPause: true,
|
||||
minIntervalMs: 120_000,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function makeMetrics(overrides = {}) {
|
||||
return {
|
||||
toolCalls: 67,
|
||||
sessionTokens: 2_940_000,
|
||||
elapsedMs: 20 * 60 * 1000,
|
||||
changedFiles: undefined,
|
||||
worktreeFingerprint: null,
|
||||
worktreeChangedSinceStart: undefined,
|
||||
topTools: {},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function makeBaseline() {
|
||||
return { sessionTokens: 0, changedFiles: 0, worktreeFingerprint: null };
|
||||
}
|
||||
|
||||
// ── Progress-check tests ───────────────────────────────────────────────────────
|
||||
|
||||
test("progress check returns none regardless of hard-pause conditions", () => {
|
||||
// Verify the progress check (changedFiles > 0) fires before the hard-pause
|
||||
// block even when all other hard-pause conditions are met.
|
||||
// This directly tests the fix: the progress guard short-circuits hard-pause.
|
||||
resetRunawayGuardState("discuss-milestone", "M001", makeBaseline());
|
||||
const config = makeConfig({ hardPause: true });
|
||||
const now = Date.now();
|
||||
|
||||
// First call: finalWarningSent becomes true
|
||||
evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
{ toolCalls: 67, sessionTokens: 1_500_000, elapsedMs: 22 * 60 * 1000, changedFiles: 0, worktreeFingerprint: null, worktreeChangedSinceStart: false, topTools: {} },
|
||||
config,
|
||||
now,
|
||||
);
|
||||
|
||||
// Second call: all hard-pause conditions are met (finalWarningSent=true, growth=true)
|
||||
// BUT changedFiles > 0 → progress check fires first → returns 'none'
|
||||
const r = evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
{ toolCalls: 67, sessionTokens: 2_000_000, elapsedMs: 25 * 60 * 1000, changedFiles: 1, worktreeFingerprint: null, worktreeChangedSinceStart: false, topTools: {} },
|
||||
config,
|
||||
now + 180_000,
|
||||
);
|
||||
// The progress check fires BEFORE the hard-pause block, returning 'none'
|
||||
assert.equal(r.action, "none", "progress check should return none even when hardPause conditions are met");
|
||||
});
|
||||
|
||||
test("returns none when changedFiles > 0 despite token growth and 2 warnings", () => {
|
||||
// The core fix: units making file-change progress should not be hard-paused.
|
||||
resetRunawayGuardState("discuss-milestone", "M001", makeBaseline());
|
||||
const config = makeConfig();
|
||||
const now = Date.now();
|
||||
|
||||
// First diagnostic turn
|
||||
evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
makeMetrics({ sessionTokens: 1_500_000 }),
|
||||
config,
|
||||
now,
|
||||
);
|
||||
|
||||
// Second call: tokens grew, but changedFiles > 0 → progress, not stuck
|
||||
const r = evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
makeMetrics({ sessionTokens: 2_940_000, changedFiles: 1 }),
|
||||
config,
|
||||
now + 180_000,
|
||||
);
|
||||
assert.equal(r.action, "none", "should not pause when changedFiles > 0");
|
||||
});
|
||||
|
||||
test("returns none when worktreeChangedSinceStart === true despite token growth", () => {
|
||||
// The worktree fingerprint changed — dirty file content was modified.
|
||||
// This is progress even with 0 new changed files.
|
||||
resetRunawayGuardState("execute-task", "T01", makeBaseline());
|
||||
const config = makeConfig();
|
||||
const now = Date.now();
|
||||
|
||||
// First diagnostic turn
|
||||
evaluateRunawayGuard(
|
||||
"execute-task",
|
||||
"T01",
|
||||
makeMetrics({ sessionTokens: 1_500_000, changedFiles: 0 }),
|
||||
config,
|
||||
now,
|
||||
);
|
||||
|
||||
// Second: tokens grew, worktree changed (dirty content), no new files
|
||||
const r = evaluateRunawayGuard(
|
||||
"execute-task",
|
||||
"T01",
|
||||
makeMetrics({
|
||||
sessionTokens: 2_940_000,
|
||||
changedFiles: 0,
|
||||
worktreeChangedSinceStart: true,
|
||||
}),
|
||||
config,
|
||||
now + 180_000,
|
||||
);
|
||||
assert.equal(r.action, "none", "should not pause when worktreeChangedSinceStart === true");
|
||||
});
|
||||
|
||||
test("returns none when changedFiles is explicitly 0 but worktreeChangedSinceStart is false", () => {
|
||||
// No progress at all — this should NOT be caught by the progress check.
|
||||
// It should proceed to the hard-pause logic.
|
||||
resetRunawayGuardState("discuss-milestone", "M001", makeBaseline());
|
||||
const config = makeConfig();
|
||||
const now = Date.now();
|
||||
|
||||
evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
makeMetrics({ sessionTokens: 1_500_000, changedFiles: 0 }),
|
||||
config,
|
||||
now,
|
||||
);
|
||||
|
||||
const r = evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001",
|
||||
makeMetrics({ sessionTokens: 2_940_000, changedFiles: 0, worktreeChangedSinceStart: false }),
|
||||
config,
|
||||
now + 180_000,
|
||||
);
|
||||
// No progress check match, but hardPause conditions may or may not fire
|
||||
// depending on hasMeaningfulGrowth — this test just ensures the progress
|
||||
// check doesn't erroneously match when changedFiles IS 0
|
||||
assert.ok(
|
||||
r.action === "pause" || r.action === "warn" || r.action === "none",
|
||||
`expected pause/warn/none, got ${r.action}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("discuss-milestone with file changes does not get hard-paused", () => {
|
||||
// Regression test for the exact SELF-FEEDBACK.md scenario:
|
||||
// discuss-milestone was hard-paused with 2.94M tokens and 67 tool calls
|
||||
// despite 1 new changed file and dirty file content modified.
|
||||
resetRunawayGuardState("discuss-milestone", "M001-6377a4", makeBaseline());
|
||||
const config = makeConfig();
|
||||
const now = Date.now();
|
||||
|
||||
// First diagnostic turn (token growth begins)
|
||||
evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001-6377a4",
|
||||
makeMetrics({ sessionTokens: 1_500_000 }),
|
||||
config,
|
||||
now,
|
||||
);
|
||||
|
||||
// Second call: exactly the scenario from SELF-FEEDBACK.md
|
||||
// 2.94M tokens, 67 tool calls, 20min elapsed, 1 changed file
|
||||
const r = evaluateRunawayGuard(
|
||||
"discuss-milestone",
|
||||
"M001-6377a4",
|
||||
makeMetrics({
|
||||
sessionTokens: 2_940_000,
|
||||
toolCalls: 67,
|
||||
elapsedMs: 20 * 60 * 1000,
|
||||
changedFiles: 1,
|
||||
worktreeChangedSinceStart: true, // dirty content changed
|
||||
}),
|
||||
config,
|
||||
now + 180_000,
|
||||
);
|
||||
assert.equal(r.action, "none", "discuss-milestone with file changes should not be paused");
|
||||
});
|
||||
|
|
@ -125,7 +125,7 @@ describe("autonomous solver", () => {
|
|||
});
|
||||
|
||||
expect(prompt).toContain("/autonomous iteration 3 of 12");
|
||||
expect(prompt).toContain("sf_autonomous_checkpoint");
|
||||
expect(prompt).toContain("checkpoint");
|
||||
expect(prompt).toContain("Writing SUMMARY.md");
|
||||
expect(prompt).toContain("is not a checkpoint");
|
||||
expect(prompt).toContain("final autonomous action");
|
||||
|
|
@ -143,7 +143,7 @@ describe("autonomous solver", () => {
|
|||
"M012/parallel-research",
|
||||
);
|
||||
|
||||
expect(prompt).toContain("actual sf_autonomous_checkpoint tool");
|
||||
expect(prompt).toContain("actual checkpoint tool");
|
||||
expect(prompt).toContain("Do not write a summary file as a substitute");
|
||||
expect(prompt).toContain("tool call succeeds");
|
||||
expect(prompt).toContain("final action");
|
||||
|
|
@ -209,14 +209,14 @@ describe("autonomous solver", () => {
|
|||
});
|
||||
|
||||
test("classifyAutonomousSolverMissingCheckpointFailure_reclassifies_tool_unavailable_when_registered", () => {
|
||||
// When the agent reports "tool unavailable" but sf_autonomous_checkpoint IS in the
|
||||
// When the agent reports "tool unavailable" but checkpoint IS in the
|
||||
// manifest, classify as "mentioned-checkpoint-without-tool" instead of
|
||||
// "checkpoint-tool-unavailable" to break the self-referential repair loop.
|
||||
const diagnosis = classifyAutonomousSolverMissingCheckpointFailure([
|
||||
{
|
||||
role: "assistant",
|
||||
content:
|
||||
"The sf_autonomous_checkpoint tool does not exist in my available toolset. I am unable to call it.",
|
||||
"The checkpoint tool does not exist in my available toolset. I am unable to call it.",
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ test("sift_search_when_successful_records_retrieval_evidence", async () => {
|
|||
},
|
||||
]);
|
||||
|
||||
const queryTool = captureQueryTool("sf_retrieval_evidence");
|
||||
const queryTool = captureQueryTool("search_evidence");
|
||||
const queryResult = await queryTool.execute("call-2", { limit: 1 });
|
||||
assert.match(queryResult.content[0].text, /Retrieval evidence: 1 row/);
|
||||
assert.equal(queryResult.details.rows[0].backend, "sift");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SF Exec Search Tool — lists and filters prior sf_exec runs.
|
||||
// SF Exec Search Tool — lists and filters prior run_command runs.
|
||||
//
|
||||
// Scans .sf/exec/*.meta.json and returns a ranked summary so agents can
|
||||
// re-discover past runs without re-executing. Read-only; no DB writes.
|
||||
|
|
@ -14,9 +14,9 @@ export function executeExecSearch(params, opts) {
|
|||
if (hits.length === 0) {
|
||||
return {
|
||||
content: [
|
||||
{ type: "text", text: "No prior sf_exec runs match those filters." },
|
||||
{ type: "text", text: "No prior run_command runs match those filters." },
|
||||
],
|
||||
details: { operation: "sf_exec_search", matches: 0 },
|
||||
details: { operation: "read_output", matches: 0 },
|
||||
};
|
||||
}
|
||||
const lines = [`Found ${hits.length} exec run(s), most recent first:`];
|
||||
|
|
@ -37,7 +37,7 @@ export function executeExecSearch(params, opts) {
|
|||
return {
|
||||
content: [{ type: "text", text: lines.join("\n") }],
|
||||
details: {
|
||||
operation: "sf_exec_search",
|
||||
operation: "read_output",
|
||||
matches: hits.length,
|
||||
results: hits.map((hit) => ({
|
||||
id: hit.entry.id,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SF Exec Tool — executor for the native sf_exec agent tool.
|
||||
// SF Exec Tool — executor for the native run_command agent tool.
|
||||
//
|
||||
// Thin wrapper around exec-sandbox.ts that reads effective options from
|
||||
// the project preferences (context_mode block) and formats the result
|
||||
|
|
@ -51,18 +51,18 @@ function disabledResult() {
|
|||
{
|
||||
type: "text",
|
||||
text:
|
||||
"sf_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
|
||||
"run_command is disabled by `context_mode.enabled: false` in preferences. Remove that " +
|
||||
"override (or set it to true) to re-enable sandboxed tool-output execution.",
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_exec", error: "context_mode_disabled" },
|
||||
details: { operation: "run_command", error: "context_mode_disabled" },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
function paramError(message) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: ${message}` }],
|
||||
details: { operation: "sf_exec", error: "invalid_params", detail: message },
|
||||
details: { operation: "run_command", error: "invalid_params", detail: message },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -109,15 +109,15 @@ export async function executeSfExec(params, deps) {
|
|||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: sf_exec failed — ${message}` }],
|
||||
details: { operation: "sf_exec", error: message },
|
||||
content: [{ type: "text", text: `Error: run_command failed — ${message}` }],
|
||||
details: { operation: "run_command", error: message },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
function formatResult(result) {
|
||||
const headerLines = [
|
||||
`sf_exec[${result.id}] runtime=${result.runtime} exit=${formatExit(result)} duration=${result.duration_ms}ms`,
|
||||
`run_command[${result.id}] runtime=${result.runtime} exit=${formatExit(result)} duration=${result.duration_ms}ms`,
|
||||
` stdout: ${result.stdout_bytes}B${result.stdout_truncated ? " (truncated)" : ""} → ${result.stdout_path}`,
|
||||
` stderr: ${result.stderr_bytes}B${result.stderr_truncated ? " (truncated)" : ""} → ${result.stderr_path}`,
|
||||
];
|
||||
|
|
@ -125,13 +125,13 @@ function formatResult(result) {
|
|||
? `\n[stdout truncated — read full output: ${result.stdout_path}]`
|
||||
: "";
|
||||
const rawDigest = `${result.digest}${truncationNote}`;
|
||||
const { text: safeDigest } = sanitizeExternalContent(rawDigest, `sf_exec[${result.id}]`);
|
||||
const { text: safeDigest } = sanitizeExternalContent(rawDigest, `run_command[${result.id}]`);
|
||||
const summary =
|
||||
`${headerLines.join("\n")}\n--- digest ---\n${safeDigest}`.trimEnd();
|
||||
return {
|
||||
content: [{ type: "text", text: summary }],
|
||||
details: {
|
||||
operation: "sf_exec",
|
||||
operation: "run_command",
|
||||
id: result.id,
|
||||
runtime: result.runtime,
|
||||
exit_code: result.exit_code,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SF Memory Tools — Phase 1 executors for capture_thought, memory_query, sf_graph
|
||||
// SF Memory Tools — Phase 1 executors for log_reasoning, memory_search, memory_graph
|
||||
//
|
||||
// These executors back the three memory-layer tools the LLM can call at any
|
||||
// point in a session. They build on the existing `memory-store.ts` layer
|
||||
|
|
@ -79,7 +79,7 @@ function clampConfidence(value) {
|
|||
return value;
|
||||
}
|
||||
export function executeMemoryQuery(params) {
|
||||
if (!isDbAvailable()) return dbUnavailable("memory_query");
|
||||
if (!isDbAvailable()) return dbUnavailable("memory_search");
|
||||
const query = (params.query ?? "").trim().toLowerCase();
|
||||
const k = clampTopK(params.k, 10);
|
||||
const category = params.category?.trim().toLowerCase() || undefined;
|
||||
|
|
@ -119,7 +119,7 @@ export function executeMemoryQuery(params) {
|
|||
return {
|
||||
content: [{ type: "text", text: summary }],
|
||||
details: {
|
||||
operation: "memory_query",
|
||||
operation: "memory_search",
|
||||
query,
|
||||
k,
|
||||
returned: hits.length,
|
||||
|
|
@ -134,7 +134,7 @@ export function executeMemoryQuery(params) {
|
|||
text: `Error: memory query failed: ${err.message}`,
|
||||
},
|
||||
],
|
||||
details: { operation: "memory_query", error: err.message },
|
||||
details: { operation: "memory_search", error: err.message },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -146,19 +146,19 @@ function clampTopK(value, fallback) {
|
|||
return Math.floor(value);
|
||||
}
|
||||
export function executeSfGraph(params) {
|
||||
if (!isDbAvailable()) return dbUnavailable("sf_graph");
|
||||
if (!isDbAvailable()) return dbUnavailable("memory_graph");
|
||||
if (params.mode === "build") {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text:
|
||||
"sf_graph build acknowledged. Graph edges are populated incrementally by memory " +
|
||||
"memory_graph build acknowledged. Graph edges are populated incrementally by memory " +
|
||||
"extraction (including LINK actions). Use `/memory extract <SRC-...>` to trigger " +
|
||||
"extraction against a specific ingested source.",
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_graph", mode: "build", built: 0 },
|
||||
details: { operation: "memory_graph", mode: "build", built: 0 },
|
||||
};
|
||||
}
|
||||
if (params.mode !== "query") {
|
||||
|
|
@ -169,7 +169,7 @@ export function executeSfGraph(params) {
|
|||
text: `Error: unknown mode "${params.mode}". Must be "build" or "query".`,
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_graph", error: "invalid_mode" },
|
||||
details: { operation: "memory_graph", error: "invalid_mode" },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ export function executeSfGraph(params) {
|
|||
content: [
|
||||
{ type: "text", text: "Error: memoryId is required for mode=query." },
|
||||
],
|
||||
details: { operation: "sf_graph", error: "missing_memory_id" },
|
||||
details: { operation: "memory_graph", error: "missing_memory_id" },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ export function executeSfGraph(params) {
|
|||
{ type: "text", text: `No memory found with id ${memoryId}.` },
|
||||
],
|
||||
details: {
|
||||
operation: "sf_graph",
|
||||
operation: "memory_graph",
|
||||
mode: "query",
|
||||
memoryId,
|
||||
nodes: [],
|
||||
|
|
@ -215,7 +215,7 @@ export function executeSfGraph(params) {
|
|||
return {
|
||||
content: [{ type: "text", text: summary }],
|
||||
details: {
|
||||
operation: "sf_graph",
|
||||
operation: "memory_graph",
|
||||
mode: "query",
|
||||
memoryId,
|
||||
nodes: nodes.map((n) => ({
|
||||
|
|
@ -234,7 +234,7 @@ export function executeSfGraph(params) {
|
|||
text: `Error: graph query failed: ${err.message}`,
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_graph", error: err.message },
|
||||
details: { operation: "memory_graph", error: err.message },
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ export function executeResume(_params, opts) {
|
|||
"on session_before_compact (enabled by default; set context_mode.enabled=false to opt out).",
|
||||
},
|
||||
],
|
||||
details: { operation: "sf_resume", found: false },
|
||||
details: { operation: "resume_agent", found: false },
|
||||
};
|
||||
}
|
||||
return {
|
||||
content: [{ type: "text", text: snapshot }],
|
||||
details: {
|
||||
operation: "sf_resume",
|
||||
operation: "resume_agent",
|
||||
found: true,
|
||||
bytes: Buffer.byteLength(snapshot, "utf-8"),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export function executeSessionTodoCheck(params, baseDir) {
|
|||
* List all session todo items.
|
||||
*
|
||||
* Purpose: show the current checklist state so the agent knows what remains.
|
||||
* Consumer: agent at start of each turn or after compaction via sf_resume.
|
||||
* Consumer: agent at start of each turn or after compaction via resume_agent.
|
||||
*/
|
||||
export function executeSessionTodoList(baseDir) {
|
||||
const todos = loadTodos(baseDir);
|
||||
|
|
|
|||
|
|
@ -637,8 +637,8 @@ export async function executeSaveGateResult(params, basePath = process.cwd()) {
|
|||
};
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
logError("tool", `sf_save_gate_result failed: ${msg}`, {
|
||||
tool: "sf_save_gate_result",
|
||||
logError("tool", `record_gate failed: ${msg}`, {
|
||||
tool: "record_gate",
|
||||
error: String(err),
|
||||
});
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ entry. Patterns earn one.
|
|||
|
||||
For each pattern:
|
||||
|
||||
- One call to `sf_self_report` with `kind` (slug, hyphenated), `severity`
|
||||
- One call to `report_issue` with `kind` (slug, hyphenated), `severity`
|
||||
(`low`/`medium`/`high`/`critical` — almost always `medium`), `summary`
|
||||
(one sentence naming the pattern), `evidence` (concrete file paths +
|
||||
line numbers + counts), `suggestedFix` (one or two specific edits — not
|
||||
|
|
@ -94,7 +94,7 @@ A short report:
|
|||
|
||||
- snapshot numbers (entries scanned, days covered)
|
||||
- patterns considered + which ones met the 3-occurrence bar
|
||||
- entry IDs filed (with `sf_self_report`'s returned id), or "none filed"
|
||||
- entry IDs filed (with `report_issue`'s returned id), or "none filed"
|
||||
when the system is healthy
|
||||
- one sentence on what trend you'd watch next run
|
||||
</output>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export function getRequiredWorkflowToolsForAutoUnit(unitType) {
|
|||
case "reassess-roadmap":
|
||||
return ["sf_milestone_status", "sf_reassess_roadmap"];
|
||||
case "gate-evaluate":
|
||||
return ["sf_save_gate_result"];
|
||||
return ["record_gate"];
|
||||
case "validate-milestone":
|
||||
return ["sf_milestone_status", "sf_validate_milestone"];
|
||||
case "complete-milestone":
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue