Commit graph

2560 commits

Author SHA1 Message Date
Mikael Hugo
2bc8d0cdd3 fix: route vision debate subagents correctly 2026-04-30 22:02:41 +02:00
Mikael Hugo
78be73fcb8 fix: stabilize sf auto and subagent routing 2026-04-30 21:55:17 +02:00
Mikael Hugo
da324da27e test: Add idempotency, schema validation, and --ci behavior tests to co…
SF-Task: S04/T02
2026-04-30 21:43:49 +02:00
Mikael Hugo
a7b96cd004 sf snapshot: pre-dispatch, uncommitted changes after 46m inactivity 2026-04-30 21:07:36 +02:00
Mikael Hugo
b43bf6991e sf snapshot: pre-dispatch, uncommitted changes after 47m inactivity 2026-04-30 20:21:12 +02:00
Mikael Hugo
69be7aeeaa feat: Added renderSkillProposal() to detect recurring patterns in triag…
- src/resources/extensions/sf/commands-todo.ts
- src/resources/extensions/sf/tests/commands-todo.test.ts

SF-Task: S03/T01
2026-04-30 19:31:40 +02:00
Mikael Hugo
30586f36f8 feat: Add backlog JSONL writer to appendBacklogItems() with BacklogEntr…
- src/resources/extensions/sf/commands-todo.ts

SF-Task: S02/T01
2026-04-30 19:13:34 +02:00
Mikael Hugo
2111da8e60 sf snapshot: pre-dispatch, uncommitted changes after 53m inactivity 2026-04-30 19:10:38 +02:00
Mikael Hugo
40e0835d5e test: Add unit tests for triage routing and edge cases in commands-todo…
- src/resources/extensions/sf/tests/commands-todo.test.ts

SF-Task: S01/T02
2026-04-30 18:16:43 +02:00
Mikael Hugo
e90298f2e0 sf snapshot: pre-dispatch, uncommitted changes after 120m inactivity 2026-04-30 17:44:03 +02:00
Mikael Hugo
d8a9d63c87 feat: Replaced bare error writes in cli.ts, headless.ts, and startup-mo…
- src/cli.ts
- src/headless.ts
- src/startup-model-validation.ts

SF-Task: S04/T03
2026-04-30 15:43:29 +02:00
Mikael Hugo
8677e73046 sf snapshot: pre-dispatch, uncommitted changes after 97m inactivity 2026-04-30 15:11:45 +02:00
Mikael Hugo
b26dca40ec fix: Stop milestone completion git archaeology 2026-04-30 13:34:24 +02:00
Mikael Hugo
0f27ffe865 fix: Let safe smoke tasks use LLM approval 2026-04-30 13:11:26 +02:00
Mikael Hugo
6a33357df5 fix: Add production mutation approval gate 2026-04-30 12:17:35 +02:00
Mikael Hugo
08ea92b072 fix: Harden auto recovery and production guards 2026-04-30 11:35:16 +02:00
Mikael Hugo
62d430ab23 Add provider smoke benchmark and headless updates 2026-04-30 10:19:18 +02:00
Mikael Hugo
1dbd30c713 Fix Kimi Code K2.6 routing and pricing 2026-04-30 10:03:06 +02:00
Mikael Hugo
6ccce42c62 Add headless bootstrap and TODO triage tests 2026-04-30 09:21:24 +02:00
Mikael Hugo
e62b3854cb Prevent auto-commit after cancelled units 2026-04-30 09:07:44 +02:00
Mikael Hugo
8487507d1b Add TODO triage and validation recheck flow 2026-04-30 08:41:49 +02:00
Mikael Hugo
ed19fa1864 Complete SF safe ID remediation sweep 2026-04-30 08:08:10 +02:00
Mikael Hugo
f76504a038 Add runaway recovery handoff artifacts 2026-04-30 08:07:44 +02:00
Mikael Hugo
6aa631c17a Apply shared safe ID validation 2026-04-30 07:56:13 +02:00
Mikael Hugo
1a0c458ac4 Harden SF safe path validation 2026-04-30 07:55:07 +02:00
Mikael Hugo
cd69e85608 Harden SF model routing and harness contracts 2026-04-30 07:41:24 +02:00
Mikael Hugo
37c5db3dd3 test: Add verification gate integration tests for failure catching, cle…
- src/resources/extensions/sf/tests/verification-gate.test.ts

SF-Task: S03/T02
2026-04-30 06:40:54 +02:00
Mikael Hugo
a45f873124 chore: snapshot WIP before resuming M004/S03 auto
84 files spanning provider capabilities, model routing, headless
runtime, sf auto subsystems, gitbook docs, and test coverage. Snapshotted
so headless auto can resume M004 (Production Readiness) S03
(Verification Gate Validation) on a clean tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 06:31:19 +02:00
Mikael Hugo
3d3a8e26e3 fix(sf): tighten mimo and openrouter model policy 2026-04-29 21:49:49 +02:00
Mikael Hugo
9c4bf9b3e6 fix(sf): use live ollama k2.6 routes 2026-04-29 21:38:51 +02:00
Mikael Hugo
f78c3fb2b8 fix(sf): keep kimi versions exact 2026-04-29 21:17:00 +02:00
Mikael Hugo
ab57548f2b fix: keep skipped tasks out of slice verification 2026-04-29 20:37:56 +02:00
Mikael Hugo
d6fc1211b7 fix: auto-skip stale instruction-conflict tasks 2026-04-29 20:33:06 +02:00
Mikael Hugo
46174c1183 fix: block stale staging task dispatch 2026-04-29 20:25:39 +02:00
Mikael Hugo
120d7deda8 fix: keep headless alive for provider auto-resume 2026-04-29 20:16:23 +02:00
Mikael Hugo
db41f92812 fix: stage declared untracked task files 2026-04-29 20:15:35 +02:00
Mikael Hugo
9398c7000d fix: route bare model families canonically 2026-04-29 20:15:28 +02:00
Mikael Hugo
aa70e1db56 fix: make auto recovery evidence-driven 2026-04-29 19:45:43 +02:00
Mikael Hugo
2ed1638153 fix: add headless heartbeat output 2026-04-29 19:29:43 +02:00
Mikael Hugo
0d6eca9cdd fix: preserve subagent debate mode details 2026-04-29 17:50:26 +02:00
Mikael Hugo
d78c5ac198 feat: add SF skills and subagent debate mode 2026-04-29 17:44:30 +02:00
Mikael Hugo
d02d33aa70 feat: add repo harness profiler 2026-04-29 17:39:52 +02:00
Mikael Hugo
fb4885b757 prompt(execute-task): add parallel-tool-call rule
Adds step 0a: when independent reads/greps are needed, batch them in a
single assistant turn instead of one-at-a-time. The existing step 0
already pushed for terse narration, but didn't address the bigger waste
— sequential tool calls when parallel would work. Common case: reading
handler + test + schema to triangulate a bug — three reads in one turn,
not three turns.

Also nudges away from "talking-then-doing": if the next action is
unambiguous, just take it. Describing intent before every call is the
dead weight that adds up to 30-50% extra round-trips.

Behavior fix only (prompt-level). Model can still narrate inside its
thinking channel since that's a model property; this targets the
chat/tool-use channel where the user pays per turn.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 15:42:22 +02:00
Mikael Hugo
c5df4b46a6 fix(headless): await auto loop in headless mode 2026-04-29 15:37:17 +02:00
Mikael Hugo
df614a3e47 fix(headless): split idle-timeout role from deadlock-backstop role
The single IDLE_TIMEOUT_MS constant was conflating two different jobs:
"are we done?" vs "is the agent stuck?". For multi-turn commands (auto,
next, discuss, plan), the first question is wrong — those signal
completion explicitly via "auto-mode stopped" terminal notifications,
and child-process exit catches crashes. The 120s I'd just bumped
multi-turn to was still in idle-detection mindset; that's not what we
need from this timer.

New semantics:
- IDLE_TIMEOUT_MS = 15s — quick commands (status, queue, …); idle
  really does mean done.
- NEW_MILESTONE_IDLE_TIMEOUT_MS = 120s — bounded creative task with
  pauses for thinking between bootstrap steps.
- MULTI_TURN_DEADLOCK_BACKSTOP_MS = 30 minutes — auto/next/discuss/plan.
  Not a "done" detector; a deadlock recovery bound. Long enough to
  never bother slow LLM reasoning or chained tool calls; short enough
  to recover from a true hang within a reasonable window. Real
  completion comes from terminal notifications + child-process exit,
  both already wired.

Code reads cleaner too: effectiveIdleTimeout selection now mirrors the
three-way conceptual split.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 15:18:58 +02:00
Mikael Hugo
c239ad6c9d fix(headless): use long idle timeout for auto/next/discuss/plan
The 15s IDLE_TIMEOUT_MS was killing auto-mode prematurely. Symptom: sf
headless auto would dispatch a task, the LLM would make 1-2 tool calls,
pause to reason about the next step, exceed 15s of "no events", and
headless would declare "Status: complete" — exiting at ~35s with the task
barely started (123 events but only 2 tool calls).

The 120s NEW_MILESTONE_IDLE_TIMEOUT_MS already exists for the same reason
("LLM may pause between tool calls e.g. after mkdir, before writing
files"). The same applies to auto/next/discuss/plan — all multi-turn
commands where the LLM thinks longer between actions, especially on
non-trivial tasks. isMultiTurnCommand was already defined for related
logic; this just wires it into the idle-timeout decision.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 15:13:43 +02:00
Mikael Hugo
2afe2ac6f1 feat(prefs): self-aligning template upgrades — sf keeps its own files synced
Companion to the earlier schema-versioning framework. Where that handles
data-shape evolution via forward migrations, this handles file-template
evolution via silent self-rewrite. The user shouldn't have to know:

- ensurePreferences() now stamps `last_synced_with_sf: <semver>` in the
  frontmatter when seeding a new project's PREFERENCES.md, recording the
  sf version that wrote the template.
- New module preferences-template-upgrade.ts:
  - detectTemplateDrift(prefs) — pure check, returns
    { fromVersion, toVersion, needsUpgrade }.
  - upgradePreferencesFileIfDrifted(path, prefs) — silently re-renders
    the file's frontmatter when fromVersion ≠ toVersion. Body (anything
    after the closing `---`) is preserved verbatim, so user notes stay.
- Wired into loadPreferencesFile() — every read self-aligns. No human
  warnings, no opt-in flow; sf keeps its own house in order.
- last_synced_with_sf added to SFPreferences + KNOWN_PREFERENCE_KEYS so
  it round-trips through validatePreferences without "unknown key"
  warnings.

Failure modes are non-fatal: missing file, malformed frontmatter, or
read-only filesystem all leave the file alone and return the in-memory
prefs unchanged. SF_VERSION env var (set by loader.ts) is the source of
truth for "current sf"; "0.0.0" sentinel skips upgrade so atypical entry
points don't stamp incorrect values.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 15:05:37 +02:00
Mikael Hugo
a2b709f669 fix(gitignore): write sf runtime patterns to .git/info/exclude, not .gitignore
ensureGitignore was re-adding `.sf`, `.sf-id`, `.bg-shell/` to the project's
.gitignore on every sf run, causing two issues:

1. Working-tree churn — every invocation dirtied .gitignore, forcing a
   commit just to silence "uncommitted changes" warnings. Pattern flagged
   by user: "is this the right way with its own every run".

2. False-positive duplicate-add — the literal-string check
   (`existingLines.has(".sf")`) didn't recognize user-equivalent patterns
   like `/.sf` (root-only) or `.sf/` (with trailing slash), so an explicit
   user entry got duplicated by the auto-add on next run.

Fix: move sf-specific runtime patterns to `.git/info/exclude` via new
`ensureGitInfoExclude()`. That file is per-clone (not committed), so
re-writing is invisible to git status. The project's `.gitignore` stays
human-curated and sf doesn't opinionate on it.

`ensureGitignore()` now calls `ensureGitInfoExclude()` first so callers
don't need to update — backwards compatible. Generic OS/IDE/lang patterns
(.DS_Store, node_modules/, target/, etc.) stay in BASELINE_PATTERNS for
.gitignore since those genuinely belong in version control.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 14:58:14 +02:00
Mikael Hugo
9b718f8e36 fix(headless): repair missing sf project symlink 2026-04-29 14:43:30 +02:00
Mikael Hugo
3b6cbcd79f feat(prefs): schema versioning with forward-migration registry
Adds the framework for evolving the prefs schema without silently breaking
projects pinned to older versions. Each PREFERENCES.md declares `version: N`;
sf declares CURRENT_PREFERENCES_SCHEMA_VERSION in code. On load:

- prefs.version === current → no-op
- prefs.version < current → run registered migrations in chain (forward only,
  pure functions). Missing migration in the chain throws — bumping the
  schema version requires a matching Migration entry, by construction.
- prefs.version > current → warn "prefs from a newer sf, fields may be
  ignored", preserve the value so a later upgrade reads correctly.
- prefs.version undefined → assume v1 (legacy file pre-versioning) and
  warn so the user adds an explicit pin.

Migration registry is empty for now (current schema version stays at 1) —
the framework is in place so the first real schema bump is a one-line
addition, not a refactor. Drift detection (`checkPreferencesDrift`) is also
the natural surface for future deprecated-key / missing-required-field
checks when CLAUDE.md / template comparisons are added.

Wired into validatePreferences() so every load path gets the new behavior
automatically — no caller changes needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 14:38:43 +02:00