chore(sf): minor self-feedback + workflow-template tweaks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
51d0a06bbc
commit
9e8361da23
8 changed files with 18 additions and 16 deletions
|
|
@ -723,6 +723,9 @@ async function runHeadlessOnce(
|
|||
let exitCode = 0;
|
||||
let milestoneReady = false; // tracks "Milestone X ready." for auto-chaining
|
||||
let timedOut = false; // true only when the overall timeout timer fires
|
||||
// Rolling buffer for milestone-ready detection across split streaming deltas.
|
||||
// Capped at 200 chars — long enough to bridge any realistic delta boundary.
|
||||
let milestoneDetectionBuffer = "";
|
||||
let providerAutoResumePending = false;
|
||||
const recentEvents: TrackedEvent[] = [];
|
||||
const interactiveToolCallIds = new Set<string>();
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ export function atomicWriteSyncWithOps(
|
|||
const tmpPath = ops.createTempPath?.(filePath) ?? defaultTempPath(filePath);
|
||||
ops.writeFile(tmpPath, content, encoding);
|
||||
|
||||
let lastError: unknown = null;
|
||||
const errors: unknown[] = [];
|
||||
let attempts = 0;
|
||||
|
||||
for (attempts = 1; attempts <= MAX_RENAME_ATTEMPTS; attempts++) {
|
||||
|
|
@ -169,7 +169,7 @@ export function atomicWriteSyncWithOps(
|
|||
ops.rename(tmpPath, filePath);
|
||||
return;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
errors.push(error);
|
||||
if (!isTransientLockError(error) || attempts === MAX_RENAME_ATTEMPTS) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -178,7 +178,7 @@ export function atomicWriteSyncWithOps(
|
|||
}
|
||||
|
||||
cleanupTempFileSync(tmpPath, ops);
|
||||
throw buildAtomicWriteError(filePath, attempts, lastError);
|
||||
throw buildAtomicWriteError(filePath, attempts, errors);
|
||||
}
|
||||
|
||||
const DEFAULT_ASYNC_OPS: AtomicWriteAsyncOps = {
|
||||
|
|
|
|||
|
|
@ -345,16 +345,8 @@ export async function checkRuntimeHealth(
|
|||
);
|
||||
|
||||
// Check for critical runtime patterns that must be present.
|
||||
// NOTE: SF_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth.
|
||||
// This is a minimal subset for the doctor check.
|
||||
const criticalPatterns = [
|
||||
".sf/activity/",
|
||||
".sf/runtime/",
|
||||
".sf/auto.lock",
|
||||
".sf/sf.db*",
|
||||
".sf/completed-units*.json",
|
||||
".sf/event-log.jsonl",
|
||||
];
|
||||
// Use the canonical SF_RUNTIME_PATTERNS list for consistency.
|
||||
const criticalPatterns = Array.from(SF_RUNTIME_PATTERNS);
|
||||
|
||||
// If blanket .sf/ or .sf is present, all patterns are covered
|
||||
const hasBlanketIgnore =
|
||||
|
|
|
|||
|
|
@ -637,6 +637,7 @@ export async function runSFDoctor(
|
|||
const requirementsContent = await loadFile(requirementsPath);
|
||||
issues.push(...auditRequirements(requirementsContent));
|
||||
|
||||
const t0state = Date.now();
|
||||
const state = await deriveState(basePath);
|
||||
|
||||
// Provider / auth health checks — only relevant when there is active work to dispatch.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const MAX_JSONL_BYTES = 10 * 1024 * 1024; // 10 MB
|
|||
|
||||
/**
|
||||
* Parse a raw JSONL string into an array of parsed objects.
|
||||
*
|
||||
* If the input exceeds MAX_JSONL_BYTES, only the tail is parsed (most recent entries).
|
||||
*/
|
||||
export function parseJSONL(raw: string): unknown[] {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ function escapeCell(text: string): string {
|
|||
|
||||
function readActiveUnit(basePath: string): SelfFeedbackOccurredIn | undefined {
|
||||
try {
|
||||
const lockPath = join(basePath, ".sf", "auto.lock");
|
||||
const lockPath = join(sfRuntimeRoot(basePath), "auto.lock");
|
||||
if (!existsSync(lockPath)) return undefined;
|
||||
const lock = JSON.parse(readFileSync(lockPath, "utf-8"));
|
||||
const id: string | undefined = lock?.unitId;
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ export function loadRegistry(): TemplateRegistry {
|
|||
*
|
||||
* Consumer: `/sf` command completion catalogs and `/sf start` usage rendering.
|
||||
*/
|
||||
/**
|
||||
* Get registry-backed command definitions for /sf start completion and help.
|
||||
*/
|
||||
export function workflowTemplateCommandDefinitions(): WorkflowTemplateCommandDefinition[] {
|
||||
const registry = loadRegistry();
|
||||
return Object.entries(registry.templates).map(([id, entry]) => ({
|
||||
|
|
|
|||
|
|
@ -620,11 +620,13 @@ export class WorktreeResolver {
|
|||
);
|
||||
|
||||
// Clean up stale merge state left by failed squash-merge (#1389)
|
||||
// Use resolveGitDir to handle worktrees where .git is a file (gitdir pointer)
|
||||
// Use resolveGitDir to handle worktrees where .git is a file (gitdir pointer).
|
||||
// Use resolve() rather than join() to normalise any backslash separators on
|
||||
// Windows and avoid mixed-separator paths in downstream comparisons.
|
||||
try {
|
||||
const gitDir = resolveGitDir(originalBase || this.s.basePath);
|
||||
for (const f of ["SQUASH_MSG", "MERGE_HEAD", "MERGE_MSG"]) {
|
||||
const p = join(gitDir, f);
|
||||
const p = resolve(gitDir, f);
|
||||
if (existsSync(p)) unlinkSync(p);
|
||||
}
|
||||
} catch {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue