Commit graph

4278 commits

Author SHA1 Message Date
Mikael Hugo
0712577f85 refactor(modes): collapse to Ask/Build; YOLO is a flag not a mode
- Remove 'plan' preset — ask covers discussion + planning, build covers execution
- Shift+Tab now cycles Ask ↔ Build (two stops, no awkward middle)
- YOLO (Ctrl+Y) forces Build mode if in Ask, then slams autonomous+deep+unrestricted
- Notify message shows 'switched to Build' when YOLO triggers a mode change
- YOLO off restores the pre-YOLO mode as before

Flow: Ask (user drives) → Build (SF drives) → Ctrl+Y (full send, no stops)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 19:53:22 +02:00
Mikael Hugo
fc60de80f5 fix(modes): presets own permissionProfile; build=unrestricted; default=normal
- Each preset now declares its own permissionProfile:
    ask  → normal   (conversational, can read/run safe commands)
    plan → normal   (structuring, not executing)
    build → unrestricted  (go do it, no permission prompts)

- setMode() calls for Shift+Tab and /mode now include permissionProfile
  so switching preset atomically sets all four axes.

- inferPresetName() includes permissionProfile in the match so status
  display shows 'build mode' only when permissions are also unrestricted.

- AutoSession default permissionProfile: 'restricted' → 'normal'
  (restricted was too conservative even for ask/chat use).

Flow: Ask (discuss) → Plan (structure) → Build (autonomous+unrestricted)
YOLO (Ctrl+Y) = build + autonomous + deep + unrestricted (turbo on top).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 19:46:57 +02:00
Mikael Hugo
8432b626c2 sf snapshot: uncommitted changes after 34m inactivity 2026-05-09 19:40:31 +02:00
Mikael Hugo
b93409cfa4 feat(headless): add -y / --yolo CLI flag to sf headless
- HeadlessOptions.yolo added
- parseHeadlessArgs handles --yolo and -y (short form)
- SF_YOLO=1 is injected into the RPC child env when flag is set
- AutoSession._loadPersistedModeState() checks SF_YOLO=1 and
  auto-activates YOLO mode (build+autonomous+deep+unrestricted)
  on session startup

Usage:
  sf headless -y autonomous       # YOLO + autonomous mode
  sf headless --yolo next         # YOLO + run next unit

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 19:05:32 +02:00
Mikael Hugo
995a57335b fix(surfaces): stamp correct surface in AutoSession + /mode yolo headless command
Surface stamp:
- AutoSession._loadPersistedModeState() now calls detectSurface() to stamp
  the correct surface (headless/web/tui) from env vars on every startup.
  Persisted surface value was the previous launch's surface — wrong when
  switching between TUI and headless on the same project.
  SF_HEADLESS=1 → 'headless', SF_WEB_BRIDGE_TUI=1 → 'web', else 'tui'.

/mode yolo:
- handleModeCommand now recognises 'yolo' as a toggleable special case.
  Headless callers can now run: sf headless --command '/mode yolo'
  Same behaviour as Ctrl+Y: full-autonomy slam + settingsManager bypass.
  /mode catalog description updated to list 'yolo' as an option.

Documentation:
- headless.ts /query and /doctor short-circuits annotated as intentional
  architecture trade-offs with a note to keep them in sync with the extension.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 17:03:33 +02:00
Mikael Hugo
38a654d5e4 fix(ux): exit YOLO before Shift+Tab or /mode preset switch
Ghost state bug: pressing Shift+Tab or /mode while YOLO was active left
session.yolo=true and settingsManager bypass ON even though mode changed.

- Shift+Tab handler calls s.toggleYolo() + settingsManager.toggleYOLO()
  before cycling to the next preset when YOLO is active
- handleModeCommand does the same before applying a named preset

This keeps yolo flag, status display ('SF — 🚀 YOLO'), and safe-git bypass
in sync with the actual running mode at all times.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:56:14 +02:00
Mikael Hugo
f7381781fa feat(ux): Ask/Plan/Build mode presets + YOLO full-autonomy
- Add SF_MODE_PRESETS (ask/plan/build) to operating-model.js
  ask  = chat  | manual     | fast
  plan = plan  | assisted   | smart
  build = build | autonomous | smart

- Shift+Tab cycles Ask → Plan → Build presets instead of raw workModes
- /mode ask|plan|build sets all three axes atomically
- formatModeState shows preset name when current mode matches a preset

YOLO (Ctrl+Y):
- session.toggleYolo() slams all axes to build+autonomous+deep+unrestricted
  and saves pre-YOLO mode for restore on toggle-off
- Terminal title shows 🚀 badge when YOLO is active
- Status line shows 'SF — 🚀 YOLO' when active
- Also calls settingsManager.toggleYOLO() for safe-git prompt bypass

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:47:14 +02:00
Mikael Hugo
6fb411df90 refactor(commands): eliminate dead handlers and catalog duplicates
Dead code removed:
- ops.js: second 'rate' handler block (lines 248-256) — unreachable because
  the top-level import block at line 187 fires first and returns true
- autonomous.js: 'stop' handler (trimmed === 'stop') — /stop is in
  BASE_RUNTIME_COMMANDS, platform intercepts it before SF extension sees it
- core.js: 'session-rename' handler block — /rename is the canonical command;
  alias added zero value and created confusion

Catalog duplicates fixed:
- 'plan' appeared twice (line 85 + 248) with contradictory descriptions;
  merged into single entry describing both phase-trigger and artifact-promotion
- 'steer' appeared twice (line 72 + 167); removed the TUI-panel shortcut
  entry (Shift+Tab is a keyboard binding, not a slash command)

Discoverability fix:
- 'recover' was handled in ops.js but absent from catalog and manifest;
  added to both with accurate description (reconstruct DB hierarchy from
  markdown on disk)
- 'session-rename' removed from catalog and manifest; users use /rename

Check script improvements:
- HIDDEN_OR_ALIAS_SUBCOMMANDS now filters both directions of the catalog
  ↔ handler consistency check (was only filtering 'handled but missing from
  catalog', not 'catalog but no SF handler')
- Added 'stop' to HIDDEN_OR_ALIAS_SUBCOMMANDS with comment explaining it is
  platform-intercepted; removed 'recover' (now properly in catalog)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:36:04 +02:00
Mikael Hugo
aca13d1d9b fix(build): fix build:core — native tsconfig types, inventory sync, compat alias catalog
- packages/native/tsconfig.json: add types:["node"] so Buffer/process/
  __dirname resolve correctly (root tsconfig has no lib/types for node)
- scripts/check-sf-extension-inventory.mjs: add footer-config, undo-turn,
  review-code to HIDDEN_OR_ALIAS_SUBCOMMANDS (they are aliases for statusline,
  rewind, rubber-duck)
- src/resources/extensions/sf/commands/catalog.js: add session-rename entry
  (real command handled in core.js, was missing from TOP_LEVEL_SUBCOMMANDS)
- src/resources/extensions/sf/extension-manifest.json: add 19 commands that
  exist in catalog but were absent from provides.commands
- src/resources/extensions/sf/guided-flow.js: remove showSmartEntry compat alias
  (no live imports — only a comment reference in headless-context.ts)
- src/resources/extensions/sf/graph.js: remove graphFromDefinition compat alias

build:core now passes end-to-end.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:18:11 +02:00
Mikael Hugo
29d2750687 feat(db): metrics ledger → DB-first unit_metrics table (schema v54)
- Add unit_metrics and project_metrics_meta tables in schema v54
- Export upsertUnitMetrics, getAllUnitMetrics, pruneUnitMetrics,
  getProjectStartedAt, setProjectStartedAt from sf-db.js
- Rewrite metrics.js disk I/O: remove json-persistence/paths imports,
  replace saveJsonFile/loadJsonFile with DB calls
- Public API surface unchanged: loadLedgerFromDisk, getLedger,
  pruneMetricsLedger all return same shapes
- Update schema version assertion in sf-db-migration.test.mjs to 54

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:05:06 +02:00
Mikael Hugo
830a259630 chore: delete superseded esbuild test-compile scripts
compile-tests.mjs and dist-test-resolve.mjs were for an older esbuild+node
--test approach. The project now uses Vitest end-to-end. Dead code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:04:41 +02:00
Mikael Hugo
9df46d2d88 feat(db): routing-history → DB-first (schema v53)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 16:02:47 +02:00
Mikael Hugo
bd0c612993 refactor(retire): drop JSONL fallback from judgment-log + delete one-shot migration scripts
- judgment-log.js: DB is always available; strip appendFileSync/readFileSync
  JSONL fallback paths and resolveJudgmentLogPath export. Non-fatal on DB
  failure is preserved — agent loop must never be disrupted.
- Delete scripts/migrate-to-vitest{,-all}.mjs and fix-vitest-api.mjs —
  one-shot migration tools that have already run; no longer needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 15:55:10 +02:00
Mikael Hugo
a70004cf2a refactor(db-first): migrate triage outputs and runtime counters to sf.db
- sf-db.js v52: triage_runs/evals/items/skills, runtime_counters,
  validation_attention_markers tables + CRUD functions
- commands-todo.js: write triage evals/items/skills to DB instead of JSONL;
  keep markdown report as human artifact
- auto-dispatch.js: rewrite-count + uat-count use runtime_counters table
  with file fallback; validation attention markers use DB with file fallback
- migration test: bump expected schema version 51 → 52
- jsonl-schema-versioning.test.mjs: update triage test to assert DB rows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 15:47:38 +02:00
Mikael Hugo
3b249c4144 feat(deploy): vision-to-production pipeline — deploy/smoke/release/rollback/challenge
- sf-db.js: ensureDeployTables() adds deploy_runs, smoke_results, release_records,
  rollback_runs (schema v51); migration block follows sleeptime v50
- preferences.js: deploy block merged (target, command, url, auto_release,
  release_type, publish_channel, adversarial_review)
- auto-prompts.js: buildDeployPrompt, buildSmokeProductionPrompt,
  buildReleasePrompt, buildRollbackPrompt, buildChallengePrompt
- auto-dispatch.js: 5 new rules — completing-milestone→challenge,
  completing-milestone→release, release-done→deploy,
  deploy-done→smoke-production, smoke-failed→rollback
- prompts/: deploy.md, smoke-production.md, release.md, rollback.md, challenge.md
- sf-db-migration test: bump expected schema version 49→51

The autonomous loop can now carry a milestone from complete-milestone all the
way to a live, smoke-verified, tagged release. Each stage is gated by prefs
(auto_release, deploy.target, deploy.url) so projects opt in per stage.
Challenge (adversarial review) runs before release when adversarial_review is set.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 15:25:47 +02:00
Mikael Hugo
d09c8282d0 chore: remove accidental root files (=, 0, test_output.log)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 15:15:43 +02:00
Mikael Hugo
00dc1ece89 feat(uok): 8-role swarm topology + DB-first sleeptime consolidation queue
- VALID_ROLES: coordinator/worker/scout/reviewer/planner/verifier/scribe/adversary (dropped architect)
- swarm-roles.js: PlannerAgent, VerifierAgent, ScribeAgent, AdversaryAgent + createDefaultSwarm wires all 8
- agent-swarm.js: route() maps plan/verify/document/challenge to new roles; _deriveWorkMode() covers all unitType patterns; getTopology() exposes all 8 role buckets; sleeptime case is now non-blocking (INSERT to DB queue instead of blocking memoryAgent.receive())
- sf-db.js: sleeptime_consolidation_queue table (schema v50) — id, conversation_agent, memory_agent, content, status, created_at, processed_at, result
- auto/loop.js: drainSleeptimeQueue() runs between every autonomous unit; reads pending queue rows, runs consolidation via PersistentAgent, marks done/error in DB
- core.js: workModes list includes verify/document/challenge
- skills/loader.js: isSkillRelevant() handles verify→review and document→docs trigger aliases
- swarm.test.mjs: updated topology assertions for 9-agent swarm

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 15:11:19 +02:00
Mikael Hugo
5dbd318a76 refactor(uok): rename scheduler-v2 and plan-v2 to drop v2 suffix
v1 no longer exists — the suffix is just noise. Update all import sites
and rename the test file to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 14:45:02 +02:00
Mikael Hugo
9450b4a11d feat(sf): Tier 4 — ASK_USER_ELICITATION, CONFIGURE_COPILOT_AGENT, BACKGROUND_SESSIONS, MULTI_TURN_AGENTS, marketplace Enter install
- ask_user_elicitation tool: structured select/input form when flag is on
- spawn_agent tool: persistent named sub-agent via file-backed .sf/agents/<name>/history.jsonl
- /configure-agent command: list/add/remove MCP servers in .mcp.json (CONFIGURE_COPILOT_AGENT flag)
- Ctrl+Alt+B: opens bg session switcher overlay from .sf/sessions-queue.json (BACKGROUND_SESSIONS flag)
- openBgSessionSwitcher(): TUI ctx.ui.select picker for session switching
- marketplace.js: Enter key triggers installExtensionNpm (EXTENSIONS flag); footer hint updated
- Fix require() → ESM-safe imports in sf-tui/index.js (spawn, execSync, platform from static imports)
- catalog.js: /configure-agent entry added

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 07:30:33 +02:00
Mikael Hugo
3017663a69 fix(sf): inline extractBodyAfterFrontmatter — it is not exported from commands-prefs-wizard
extractBodyAfterFrontmatter is a private function in commands-prefs-wizard.js.
Inline a local copy in experimental.js and handleThemeCommand (core.js) rather
than importing a non-existent export.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 05:37:26 +02:00
Mikael Hugo
b34f5997eb feat(sf): Tier 3 — /rubber-duck, /delegate, /share, /ask, /resume, /sidekicks
handlers/core.js:
- /ask <question> — ephemeral side question via ctx.fork (graceful
  fallback if fork unavailable)
- /resume [id] — session listing via ctx.listSessions; falls back to
  ~/.sf/sessions/ file listing with upgrade hint for BACKGROUND_SESSIONS

handlers/ops.js:
- /rubber-duck [topic] — constructive review subagent gated on
  RUBBER_DUCK experimental flag; routes via ctx.sendMessage
- /delegate [title] — GitHub PR creation via gh pr create --web;
  shows recent commits for context
- /share [md] — export session transcript to ~/sf-session-<ts>.md;
  copies path to clipboard (pbcopy / xclip / xsel)

catalog.js:
- Add /rubber-duck, /delegate, /share, /ask, /resume to TOP_LEVEL_SUBCOMMANDS

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 05:35:54 +02:00
Mikael Hugo
c1c3195f75 feat(sf): Tier 2 — SHOW_FILE tool, STATUS_LINE runner, /keep-alive, /sidekicks, Ctrl+G/T/X keybindings
sf-tui/index.js:
- Import getExperimentalFlag / setExperimentalFlag from experimental.js
- Ctrl+G — open project root in $EDITOR
- Ctrl+T — toggle show_reasoning experimental flag
- Ctrl+Alt+B — open /tasks background surface
- Ctrl+Alt+O — open last URL from agent output in browser
- STATUS_LINE runner: setInterval 5s, execFile user script, pipe stdout to ctx.ui.setStatus
- SHOW_FILE tool: pi.registerTool({name:'show_file',...}) gated on show_file flag; reads file slice, renders as fenced code block

handlers/ops.js:
- /keep-alive [off] — spawns caffeinate (macOS) or systemd-inhibit (Linux) as detached process; /keep-alive off kills it

handlers/core.js:
- /sidekicks — reads .sf/parallel/ subdirs, shows STATUS per worker

catalog.js:
- Add /sidekicks and /keep-alive to TOP_LEVEL_SUBCOMMANDS

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 05:33:24 +02:00
Mikael Hugo
eaf7165893 feat(sf): Copilot CLI feature parity — /experimental, /diff, /theme, /rename, /streamer-mode, /statusline, /search, /chronicle, /rewind, /instructions
Add experimental feature flag system and 10 new slash commands matching
Copilot CLI's experimental surface.

experimental.js:
- EXPERIMENTAL_FLAGS map (status_line, show_file, ask_elicitation,
  multi_turn_agents, extensions, configure_agent, background_sessions,
  rubber_duck, prompt_frame, streamer_mode)
- getExperimentalFlag / setExperimentalFlag / setAllExperimentalFlags
- Reads/writes project .sf/PREFERENCES.md via prefs frontmatter helpers

handlers/core.js:
- /experimental show|on|off|on <flag>|off <flag>
- /diff [--staged] — git diff HEAD or staged changes
- /theme [dark|light|dim|auto] — get/set UI theme in prefs
- /rename <name> — session name + OSC 2 terminal title
- /streamer-mode [on|off] — mask model names for screen sharing
- /statusline script <path>|off — configure footer status line script
- /search /find <query> — search session timeline entries
- /chronicle — git log + session events overview
- /rewind — revert last turn (ctx.rewind() with graceful fallback)
- /instructions — list all instruction files and their load status

catalog.js: add all 12 new commands to TOP_LEVEL_SUBCOMMANDS for autocomplete

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 05:30:25 +02:00
Mikael Hugo
c6d031fe01 docs: resolve all open questions in copilot-thoughts.md Appendix C
- Paused badge: P! prefix + dim (implemented)
- Mode per-session confirmed
- Tmux: user-opt-in only (SF does not inject tmux config)
- No sound/notification
- repair auto-transition: no ask gate
- Skill evals: on-demand with SF_SKILL_EVALS=1
- /tasks: inline output until pi-tui overlay support exists
- modelMode: supplement tiers via bridge (confirmed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 04:41:31 +02:00
Mikael Hugo
9441022909 feat(tui): mode badge in normal footer + paused state indicator
- renderFooter: add mode badge (compact at <80 cols, full at ≥80 cols)
  to right side so active mode is always visible, not only during auto
- renderAutoFooter: refactor to use shared renderModeBadge instead of
  duplicating badge logic inline
- renderModeBadge: handle paused state — all badge parts dim, 'P!' prefix
  shown in compact form, 'paused ·' prefix shown in full form
- getMode(): surface session.paused as a field on the returned mode object
  so badge renderers can reflect paused state without inspecting session directly
- Export renderModeBadge from header.js; footer imports it via FOOTER_THEME adapter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 04:41:00 +02:00
Mikael Hugo
848ac0dd99 feat(swarm): UOK-based swarm with PersistentAgent, AgentSwarm, and SwarmDispatchLayer
- PersistentAgent: stable identity across restarts, 3-tier memory (core
  blocks / recall / archival), durable SQLite inbox, sendAndWait request-
  reply, broadcast — all backed by UokCoordinationStore + MessageBus
- AgentSwarm: Letta-style group topology with ManagerType enum
  (round_robin, supervisor, dynamic, sleeptime), tag-based routing,
  shared agent_directory block, persist/load round-trip
- Role agents: CoordinatorAgent, WorkerAgent, ScoutAgent, ReviewerAgent
  extending PersistentAgent with preset tags + createDefaultSwarm factory
  (1 coordinator, 2 workers, 1 scout, 1 reviewer)
- SwarmDispatchLayer: routes UOK DispatchEnvelopes by workMode/unitType
  to the correct role agent, module-level cache, swarmDispatch() convenience fn
- 15 tests passing (identity persistence, messaging, registry, topology,
  dispatch routing) using real SQLite in tmp dirs
- Fix: tsconfig.resources.json — add types:[node] for TypeScript 6 compat

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 04:04:42 +02:00
Mikael Hugo
efa3ce4492 chore: major dependency bumps — genai v2, marked v18, diff v9, undici v8, proxy-agent v8, express v5, typescript v6
All bumps typecheck clean and pass 129 test files (1118 tests).

- @google/genai 1.45→2.0: backward-compatible for SF's API usage
- marked 15→18: no API changes affecting pi-tui markdown component
- diff 8→9: clean typecheck
- undici 7.25→8.2: clean typecheck
- proxy-agent 6→8: clean typecheck
- express 4→5 (pi-coding-agent only): clean typecheck
- typescript 5.9→6.0: added ignoreDeprecations for baseUrl+paths
- daemon typescript ^5.4→^6.0.3 aligned with root

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-09 03:58:26 +02:00
Mikael Hugo
412a7fec5f chore: bump dependencies — patch, minor, and zod v3→v4 in daemon
Patch: zod 4.4.1→4.4.3, @anthropic-ai/claude-agent-sdk 0.2.128→0.2.137,
yaml 2.8.2→2.8.4, minimatch 10.2.3→10.2.5, @types/picomatch 4.0.2→4.0.3,
discord.js 14.25→14.26.4, zod-to-json-schema 3.24→3.25.2,
esbuild 0.27.4→0.27.7

Minor: @anthropic-ai/sdk 0.93→0.95.1, openai 6.26→6.37, jiti 2.6→2.7,
@clack/prompts 1.1→1.3, koffi 2.9→2.16.2, get-east-asian-width 1.3→1.6,
undici 7.24→7.25, playwright 1.58→1.59, @google/gemini-cli-core 0.40→0.41

Align: daemon zod ^3.24.0 → ^4.4.3 (was already resolving hoisted v4)

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-09 03:39:52 +02:00
Mikael Hugo
1c9b69b57e feat(skills): locked enforcement + workflow skill injection into agent context
Phase 1 — Skill Integrity:
- buildSkillRecord now maps locked: true frontmatter → record.locked
- discoverAllSkills builds locked name set (workflow always locked, bundled if
  frontmatter declares locked: true) and silently drops project/user skills
  that collide with a locked skill name (shadow protection)
- loader.js enforces locked=true unconditionally for workflow source skills
- getUserInvocableSkills now hides locked + workflow skills from /skills catalog
- loadSkills defaults includeWorkflow: true for production context

Phase 2 — Workflow Skill Wiring:
- buildWorkflowConstraintsBlock: loads workflow skills, filters by permission
  profile + work mode triggers, caps at 5, formats as ## Active Workflow
  Constraints block (behavioral guidelines, not invocable tools)
- buildSkillActivationBlock now appends workflow constraints block after the
  user skill_activation block — injected into every agent dispatch prompt
- getAutoSession provides workMode + permissionProfile; fallback to build/normal

Tests: 18 skills tests + 1 auto-prompts test pass (was 15)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 03:28:24 +02:00
Mikael Hugo
c7c72fa12b docs: remove stale genai-proxy inventory entry 2026-05-09 02:58:06 +02:00
Mikael Hugo
03e1f808bc feat: two-tier skill architecture with 8 workflow-internal skills
- Add src/resources/workflow-skills/ directory with 8 internal skills
  enforcing the 20 cross-cutting agent patterns from the styleguide:
  P0: observe-first, vertical-slice, context-lean
  P1: irreversible-ops, error-routing, assumption-log
  P2: handoff-readability, state-discipline
- Update skills/directory.js: WORKFLOW_SKILL_DIR constant, workflow
  source in discoverAllSkills, exported all constants inline
- Update skills/loader.js: workflow source forces userInvocable: false;
  loadSkills() defaults to includeWorkflow: true for production use;
  getUserInvocableSkills excludes workflow source
- Update skills/index.js barrel to export WORKFLOW_SKILL_DIR
- Update install-pi-global.js / uninstall-pi-global.js for workflow-skills
- Fix skills.test.mjs: pass includeWorkflow: false in 4 project-scope
  tests to isolate them from the 8 bundled workflow skills
- Remove genai-proxy extension (unused, replaced by direct provider integration)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 02:55:16 +02:00
Mikael Hugo
9875812c1b sf snapshot: uncommitted changes after 131m inactivity 2026-05-09 02:53:47 +02:00
Mikael Hugo
5188b93ddc feat: Shift+Tab cycles work modes, Ctrl+T cycles thinking level
- Shift+Tab: cycles work mode (chat→plan→build→review→repair→research)
  when idle; opens steerable panel during autonomous execution
- Ctrl+T: cycles thinking level (replaces shift+tab binding)
- Removed toggleThinking from default Ctrl+T (superseded by cycleThinkingLevel)
- Drop hint for toggleThinking from interactive mode help text

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 00:42:41 +02:00
Mikael Hugo
22cbd83675 fix: update test snapshots for queryInstruction and complete /sf prefix Phase 2 deprecation
- Fix memory-embeddings-llm-gateway tests: add queryInstruction field to
  expected config objects after loadGatewayConfigFromEnv was updated to
  return it
- Add STYLEGUIDE.md: SF code standards adapted from ace-coder patterns
  (purpose doctrine, principles, anti-patterns STY001-012, thresholds,
  naming, patterns, documentation sections)
- Phase 2 /sf prefix removal: update all web components, browser dispatch,
  and tests to use direct commands (/autonomous, /stop, /next, /discuss,
  /init, /new-milestone) instead of /sf-prefixed forms
  - workflow-actions.ts: all command strings updated
  - chat-mode.tsx: SF_ACTIONS array updated
  - project-welcome.tsx: primaryCommand values updated
  - command-surface.tsx: fallback display updated
  - remaining-command-panels.tsx: usage examples updated
  - browser-slash-command-dispatch.ts: add stop/new-milestone/init to
    SF_PASSTHROUGH_COMMANDS so they route correctly to the extension
  - recovery-diagnostics-service.ts: suggestion commands updated
  - welcome-screen.ts: hint text updated
  - All affected tests updated to match new command strings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 00:17:47 +02:00
Mikael Hugo
e4c951ff0c feat: improve sf runtime self-reload and safeguards 2026-05-08 23:52:35 +02:00
Mikael Hugo
c5e9e4f9c8 fix: guard completeValidationRun and drop dead superseded_by column
- completeValidationRun now checks status='running' in WHERE clause and
  throws if no row was updated (catches double-complete and invalid runId)
- Remove unused superseded_by column from v46 CREATE TABLE DDL
- Add migration v47 to DROP COLUMN superseded_by from existing DBs
- Bump SCHEMA_VERSION to 47

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 21:45:58 +02:00
Mikael Hugo
6e6363da0d feat: migrate src/ core TS files to LogTape structured logging
Migrate 5 non-test TS files in src/ from console.* to LogTape:
- src/env.ts → getLogger('sf.core.env')
- src/resource-loader.ts → getLogger('sf.core.resource-loader')
- src/web/undo-service.ts → getLogger('sf.web.undo-service')
- src/web/cleanup-service.ts → getLogger('sf.web.cleanup-service')
- src/web/auto-dashboard-service.ts → getLogger('sf.web.auto-dashboard-service')

console.error(err) → log.error(msg, {error: err})
console.warn(msg) → log.warn(msg)

All CLI-facing output preserved. typecheck, lint pass.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 21:01:08 +02:00
Mikael Hugo
a46cbcbe40 Add more untracked runtime extension files 2026-05-08 20:51:18 +02:00
Mikael Hugo
fd06629f06 feat: add centralized LogTape logger module with dev/autonomous modes, PII redaction, and per-session file rotation
- Install @logtape/logtape, @logtape/pretty, @logtape/file, @logtape/redaction
- Create src/logger.ts with configureLogger() and getLogger() exports
- Dev mode: pretty console output with debug level
- Autonomous mode: JSON console + rotating file sink in .sf/logs/{sessionId}/
- PII redaction for API keys (sk-*, key-*, Bearer *) and home directory paths
- Category hierarchy: sf.core, sf.uok, sf.autonomous, sf.extension, sf.web
- Comprehensive tests in src/tests/logger.test.ts (10 tests)
- Wire configureLogger() into src/cli.ts startup path

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 19:58:11 +02:00
Mikael Hugo
8f02524fd7 Add untracked runtime extension files to git 2026-05-08 19:55:39 +02:00
Mikael Hugo
c3b202dd4c fix: use IS for NULL-safe equality in validation run queries
Consistent with latest_validation_state view. The verbose
(slice_id = :param OR (slice_id IS NULL AND :param IS NULL))
pattern is functionally equivalent to slice_id IS :param in SQLite.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 19:15:31 +02:00
Mikael Hugo
3b4dbfbcf0 Fix extension manifest and database schema for metrics-central
- Add missing commands: cost, implement, research, trajectory
- Fix validation runs schema: remove DEFAULT on created_at, make explicit in INSERT
- Simplify latest_validation_state view using MAX(rowid) approach
- Add run_id DESC to validation query ORDER BY clauses for consistent ordering
2026-05-08 19:13:44 +02:00
Mikael Hugo
533d1ce83c sf snapshot: uncommitted changes after 32m inactivity 2026-05-08 18:51:07 +02:00
Mikael Hugo
7318af029a sf snapshot: uncommitted changes after 33m inactivity 2026-05-08 18:18:47 +02:00
Mikael Hugo
d7c2663ca5 sf snapshot: uncommitted changes after 113m inactivity 2026-05-08 17:44:49 +02:00
Mikael Hugo
d3ff8efb22 build: add jscpd as direct dependency for duplicate code detection
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 15:51:38 +02:00
Mikael Hugo
7287490cfd fix: enhance missing-checkpoint repair with better low-confidence guidance
- Add explicit low-confidence reconstruction guidance for no-transcript cases
- Clarify when to use outcome='decide' when confidence < 0.98
- Fix typo in repair prompt ('what was was expected' -> 'what was expected')
- Strengthen final human-acceptance-gate guidance to prefer outcome='decide'
- Addresses solver-missing-checkpoint self-feedback entry acceptance criteria

Resolves: sf-mowykewh-3ehn5p
2026-05-08 15:47:00 +02:00
Mikael Hugo
e80e48d122 ci: enable jscpd duplicate detection and test timing artifact
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 15:22:06 +02:00
Mikael Hugo
4601a7d3fb fix(sf): implement features hinted by unused-import warnings
- ai-memory-tools.js: use options param for configurable limits in formatAllMemoriesForPrompt
- metrics-central.js: enforce MAX_HISTOGRAM_BUCKETS cap on histogram bucket count
- reasoning-assist.js: use REASONING_ASSIST_MAX_CHARS to cap prompt length with logWarning
- trajectory-recorder.js: add debugLog for failed step recordings

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-05-08 15:18:58 +02:00
Mikael Hugo
f440fbed9c autoresearch: checkpoint memory and runtime changes 2026-05-08 14:58:10 +02:00