From abb3d76ffa482a84d53fc93feaf8521ee9237965 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sat, 2 May 2026 02:18:03 +0200 Subject: [PATCH] =?UTF-8?q?chore(sf):=20minor=20sweep=20=E2=80=94=20gate-r?= =?UTF-8?q?egistry=20dedup,=20token-counter,=20worktree-health?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- src/headless.ts | 6 +++--- src/resources/extensions/sf/auto-post-unit.ts | 2 +- src/resources/extensions/sf/gate-registry.ts | 9 ++++++++- src/resources/extensions/sf/preferences-migrations.ts | 3 +++ src/resources/extensions/sf/scaffold-drift.ts | 4 +++- src/resources/extensions/sf/token-counter.ts | 3 +++ src/resources/extensions/sf/workflow-templates.ts | 4 ++++ src/resources/extensions/sf/worktree-health.ts | 2 +- 8 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/headless.ts b/src/headless.ts index 0e6ecb282..49322a912 100644 --- a/src/headless.ts +++ b/src/headless.ts @@ -1681,9 +1681,9 @@ async function runHeadlessOnce( : exitCode === EXIT_CANCELLED ? "cancelled" : exitCode === EXIT_ERROR - ? totalEvents === 0 - ? "error" - : "timeout" + ? timedOut + ? "timeout" + : "error" : "complete"; process.stderr.write(`[headless] Status: ${status}\n`); diff --git a/src/resources/extensions/sf/auto-post-unit.ts b/src/resources/extensions/sf/auto-post-unit.ts index 4754d252a..902a9c412 100644 --- a/src/resources/extensions/sf/auto-post-unit.ts +++ b/src/resources/extensions/sf/auto-post-unit.ts @@ -70,7 +70,7 @@ import { recordSelfFeedback } from "./self-feedback.js"; // crossReferenceEvidence available for future use when verification_evidence is stored in DB // import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js"; import { validateContent } from "./safety/content-validator.js"; -import { getEvidence } from "./safety/evidence-collector.js"; +import { clearEvidenceFromDisk, getEvidence } from "./safety/evidence-collector.js"; import { validateFileChanges } from "./safety/file-change-validator.js"; import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js"; import { consumeSignal } from "./session-status-io.js"; diff --git a/src/resources/extensions/sf/gate-registry.ts b/src/resources/extensions/sf/gate-registry.ts index 3cfb8068b..a2f4e852a 100644 --- a/src/resources/extensions/sf/gate-registry.ts +++ b/src/resources/extensions/sf/gate-registry.ts @@ -183,7 +183,14 @@ export const GATE_REGISTRY = { /** Type of the GATE_REGISTRY constant. */ export type GateRegistry = typeof GATE_REGISTRY; -/** Stable ordered lists per owner turn — iteration order matches declaration. */ +/** + * Stable ordered lists per owner turn — iteration order matches declaration. + * + * NOTE: Object.values() returns properties in insertion-order per the ES2020 + * specification (§9.1.12). The gate execution order is therefore determined + * by the key-declaration order in GATE_REGISTRY above. Add new gates at the + * correct position in that object literal — do NOT rely on alphabetical sort. + */ const ORDERED_GATES: readonly GateDefinition[] = Object.values( GATE_REGISTRY, ) as readonly GateDefinition[]; diff --git a/src/resources/extensions/sf/preferences-migrations.ts b/src/resources/extensions/sf/preferences-migrations.ts index fbddf8afe..2d0d155eb 100644 --- a/src/resources/extensions/sf/preferences-migrations.ts +++ b/src/resources/extensions/sf/preferences-migrations.ts @@ -27,6 +27,9 @@ import type { SFPreferences } from "./preferences-types.js"; */ export const CURRENT_PREFERENCES_SCHEMA_VERSION = 1; +/** + * A schema migration that transforms preferences from one version to the next. + */ export interface Migration { /** Schema version this migration upgrades from. */ from: number; diff --git a/src/resources/extensions/sf/scaffold-drift.ts b/src/resources/extensions/sf/scaffold-drift.ts index 6e2b292ad..b666138ac 100644 --- a/src/resources/extensions/sf/scaffold-drift.ts +++ b/src/resources/extensions/sf/scaffold-drift.ts @@ -219,7 +219,9 @@ export function detectScaffoldDrift(basePath: string): ScaffoldDriftReport { } else { // Stamped version equals (or is somehow ahead of) shipped version // and content matches — nothing to do. Bucket as `customized` per - // the spec ("already current"). + // the spec ("already current"). NOTE: this bucket includes both + // unedited pending files (hash matches) and user-edited files; + // use hashDrifted flag to distinguish (false = no user edits). items.push({ path: file.path, template: file.path, diff --git a/src/resources/extensions/sf/token-counter.ts b/src/resources/extensions/sf/token-counter.ts index f52be58f1..fa6a672c2 100644 --- a/src/resources/extensions/sf/token-counter.ts +++ b/src/resources/extensions/sf/token-counter.ts @@ -161,6 +161,9 @@ async function buildGoogleGeminiCliServer(apiKeyRaw: string) { ); } +/** + * Type guard for Google Gemini token counting payload. + */ export function isGoogleGeminiCountablePayload( payload: unknown, ): payload is CountTokensParameters { diff --git a/src/resources/extensions/sf/workflow-templates.ts b/src/resources/extensions/sf/workflow-templates.ts index 4456d72db..d9850d018 100644 --- a/src/resources/extensions/sf/workflow-templates.ts +++ b/src/resources/extensions/sf/workflow-templates.ts @@ -68,6 +68,10 @@ export interface TemplateMatch { matchedTrigger?: string; } +/** + * Scaffold data for a milestone slice generated from a template. + * Contains slice ID, title, risk, and planning details. + */ export interface MilestoneTemplateSliceScaffold { sliceId: string; title: string; diff --git a/src/resources/extensions/sf/worktree-health.ts b/src/resources/extensions/sf/worktree-health.ts index 8338d0516..f5f2681e6 100644 --- a/src/resources/extensions/sf/worktree-health.ts +++ b/src/resources/extensions/sf/worktree-health.ts @@ -7,7 +7,7 @@ * Only inspects worktrees under .sf/worktrees/ — SF owns what SF creates. */ -import { existsSync } from "node:fs"; +import { existsSync, lstatSync } from "node:fs"; import { nativeDetectMainBranch, nativeHasChanges,