Commit graph

3765 commits

Author SHA1 Message Date
Mikael Hugo
effada2bb4 chore(sf): judgment-log + auto-post-unit + milestone-framing-check cleanup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:43:28 +02:00
Mikael Hugo
070c0eb802 fix(sf): drive typecheck to 0 errors
Pre-existing errors fixed:
- tools/complete-slice.ts:421 widened error-return-type (field?/reason?)
- workflow-manifest.ts:158-159 parseObjectArray for key_risks/proof_strategy
- workflow-logger.ts LogComponent union additions (memory-embeddings et al.)
- project-research-policy.ts lambda param types (ParsedRequirement element)

Typecheck: 0 errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:43:06 +02:00
Mikael Hugo
4238c033fb chore(sf): final minor cleanup — auto-post-unit + milestone-framing-check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:42:26 +02:00
Mikael Hugo
d1be5d9b74 feat(sf): seed .sf/PRINCIPLES.md, TASTE.md, ANTI-GOALS.md (PDD-anchored)
Tacit knowledge files captured in tracked .sf/ artifacts (per ADR-001):
- PRINCIPLES.md: durable design philosophy, with PDD as the canonical
  change method (purpose / consumer / contract / failure boundary /
  evidence / non-goals / invariants — all 7 fields required)
- TASTE.md: what good code looks like in SF — verbose names, domain >
  layer, behavior-is-the-spec, minimum change, idempotent dispatch,
  fail-non-fatal, structured blocker format, PDD discipline
- ANTI-GOALS.md: 25 rule-coded anti-patterns (SF001-SF025) covering bare
  errors, type lies, magic strings, partial migrations, Ralph-loop retry,
  central federation, MCP between first-party services, implementation-
  mirror tests, coding-before-PDD-fields, happy-path-only, etc.

Translated from ACE-coder's STYLEGUIDE.md as the model. Anchored on
purpose-driven-development as the canonical change method. These three
files plus KNOWLEDGE.md plus DECISIONS.md are the tacit-knowledge layer
auto-injected into every agent context (via system-context.ts mtime cache).

Closes the "smart human gap" identified in this session: the difference
between SF behaving like a competent engineer in this codebase vs. a
generic LLM is the accumulated tacit knowledge available to the agent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:41:51 +02:00
Mikael Hugo
8a1f131557 feat(sf): cross-tier escalation policy + ask-gate
Adds explicit Tier 1 / Tier 2 / Tier 3 escalation guidance to every system
prompt. Tier 1 = code lookup (sift, source, .sf/DECISIONS.md). Tier 2 =
external lookup (WebSearch, WebFetch, Context7, MCP servers). Tier 3 = ask
user (in auto/step) or exit-with-structured-blocker (in autonomous).

- bootstrap/system-context.ts: buildEscalationPolicyBlock injected at top
  of SF system-context section, mode-aware via isCanAskUser()
- bootstrap/ask-gate.ts: gateAskUserQuestions() runtime safety net,
  blocks ask_user_questions in autonomous mode at the tool layer with a
  structured rejection that escalates back to Tier 1/2
- tests: 18 escalation-policy + 16 ask-gate, all pass

Implements the user's "solve it like a smart human, not Ralph Wiggum"
philosophy: in autonomous mode the agent must do the research a competent
human would do, and only stop with a blocker when even a human couldn't
proceed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:36:14 +02:00
Mikael Hugo
ec07eca5bd fix(sf): wire schemas/parsers into project-research-policy, trim deep-project-setup stubs
- project-research-policy.ts: replace throw stubs with real imports from
  schemas/parsers.ts — parseProject and parseRequirements now live
- deep-project-setup-policy.ts: remove redundant inline stubs now that
  schemas/validate.ts is ported
- tests/runtime-root-redirect.test.ts: new test for root redirect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:34:08 +02:00
Mikael Hugo
0efc9cd656 docs(sf): final cluster JSDoc — mcp/preferences/native bridges/sf-db/onboarding 2026-05-02 02:32:15 +02:00
Mikael Hugo
f761d31d1c feat(sf): port schemas/parsers+validate, fix project-research-policy stubs + sweeps
- schemas/parsers.ts: new — Markdown→structured object parsers (ParsedProject,
  ParsedRequirements, ParsedRequirement, ParsedRoadmap, parseProject,
  parseRequirements, parseRoadmap, parseRoadmapMilestone)
- schemas/validate.ts: new — artifact validation against parsed schemas
  (validateProject, validateRequirements, validateArtifact)
- project-research-policy.ts: remove throw stubs, wire real parseProject/
  parseRequirements from schemas/parsers — classifyProjectResearchScope now live
- verification-gate.ts: escalation-policy backoff improvements
- workflow-events.ts + workflow-logger.ts: minor type/log additions
- worktree-health.ts: health check timing
- doctor-runtime-checks.ts: expand checks
- tests/escalation-policy.test.ts: new test for gate escalation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:30:57 +02:00
Mikael Hugo
98da1980fb refactor + docs: SF_RUNTIME_PATTERNS canonical + bootstrap/workflow JSDoc
Dead-code removal:
- state.ts: getDeriveTelemetry, resetDeriveTelemetry (zero refs)
- context-budget.ts: reduceToFit (zero refs)
- auto.ts: getActiveRunDir (zero refs)

SF_RUNTIME_PATTERNS canonical extraction (per TODO audit):
- gitignore.ts: exported SF_RUNTIME_PATTERNS
- git-service.ts: RUNTIME_EXCLUSION_PATHS = SF_RUNTIME_PATTERNS (was 27-line mirror)
- worktree-manager.ts: SKIP_PATHS/SKIP_EXACT/SKIP_PREFIXES derived at module load
- doctor-runtime-checks.ts: criticalPatterns = SF_RUNTIME_PATTERNS
- Cross-file sync obligation now compile-time enforced

Bootstrap + workflow JSDoc sweep: 189 blocks across 17 files.

Typecheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:29:46 +02:00
Mikael Hugo
b8bcd6fdd1 feat(sf): port deep-project-setup-policy + UOK audit event types + sweeps
- deep-project-setup-policy.ts: new — DeepProjectSetupState, getDeepProjectSetupState,
  getNextDeepProjectSetupStage, researchDecisionPath, writeDefaultResearchSkipDecision
- uok/audit.ts: add missing audit event types to match gsd2 (model-policy-block,
  gate-timeout, gate-input-fail, dispatch-blocked)
- hook-emitter.ts: proper emitExtensionEvent wiring with SF's ExtensionAPI
- bootstrap/system-context.ts: deep-project-setup context block injection
- doctor-types.ts + doctor-runtime-checks.ts: expand runtime check types
- milestone-id-reservation.ts: align ghost-milestone reuse logic
- tests/detection.test.ts: fix stale import path
- worktree-resolver.ts: path normalization edge case

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:29:16 +02:00
Mikael Hugo
360208cbaf feat(sf): port commands-memory, component-loader, workflow-oneshot prompt + sweeps
- commands-memory.ts: /sf memory command handlers (add/list/search/delete)
- component-loader.ts: component lifecycle management and validation
- prompts/workflow-oneshot.md: oneshot workflow execution prompt template
- session-forensics.ts, definition-io.ts, sf-db.ts, commands-scaffold-sync,
  worktree-resolver: secondary sweep improvements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:27:42 +02:00
Mikael Hugo
3a3ea29c51 chore(sf): test backfill, parse helpers, parallel session pickups 2026-05-02 02:26:01 +02:00
Mikael Hugo
192fd3e180 feat(sf): port python-resolver, state-transition-matrix
- python-resolver.ts: new — resolves python/python3 executable path
- state-transition-matrix.ts: new — valid auto-mode state machine transitions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:22:47 +02:00
Mikael Hugo
dda9793cd6 feat(sf): port sf-home, memory-embeddings, component-types, workflow-install + sweep
- sf-home.ts: new — resolves ~/.sf/ path and SF home dir helpers (port of gsd-home.ts)
- memory-embeddings.ts: new — embedding helpers for memory similarity search
- component-types.ts: new — Component, ComponentManifest, ComponentHook type defs
- workflow-install.ts: new — workflow installation from local/remote sources
- auto-post-unit.ts: clearEvidenceFromDisk after successful verification
- routing-history.ts: add cost-per-token tracking to routing decisions
- workflow-{manifest,templates}.ts: hardening sweep

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:22:13 +02:00
Mikael Hugo
9e8361da23 chore(sf): minor self-feedback + workflow-template tweaks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:21:13 +02:00
Mikael Hugo
51d0a06bbc docs(sf): model + routing + provider cluster docstrings
49 JSDoc blocks across 10 files (model-router, model-cost-table,
auto-model-selection, benchmark-selector, blocked-models,
preferences-models, session-model-override, provider-error-pause,
error-classifier, token-counter).

ADR references preserved (ADR-004 capability-aware routing,
ADR-005 multi-model provider tools, ADR-007 model catalog split).

Typecheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:20:33 +02:00
Mikael Hugo
df8fca8cc7 feat(sf): workflow-plugins port, sf-db expansions, worktree-manager hardening
- workflow-plugins.ts: new — unified plugin discovery, 4 execution modes
  (oneshot, yaml-step, markdown-phase, auto-milestone), hot-reload support
- sf-db.ts: add milestone ghosting/reservation, hook_runs table, memory
  embedding schema, subscription token usage tracking
- worktree-manager.ts: active-worktree tracking, health check cascade,
  dangling-ref pruning, sync-on-switch
- atomic-write.ts: add writeJsonAtomic convenience wrapper
- workflow-logger.ts: add "plugins" LogComponent variant
- workflow-templates.ts: template hot-reload + validation sweep
- scaffold-versioning.ts: versioned drift detection improvements
- preferences-migrations.ts: v3→v4 subscription cost fields migration
- self-feedback.ts: feedback loop dedup window
- headless.ts: EXIT_RELOAD + notification dedup boundary (final)
- tests/auto-vs-autonomous.test.ts: expand coverage for both code paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:20:14 +02:00
Mikael Hugo
b719169ed5 perf + docs: KNOWLEDGE/ARCHITECTURE mtime cache + notification cluster JSDoc
Performance fix from audit:
- bootstrap/system-context.ts: cachedReadFile() with mtime-keyed in-process
  cache for KNOWLEDGE.md (global + project) and ARCHITECTURE.md. Eliminates
  3-4 sync readFileSync calls per agent turn on the common case where these
  files haven't changed. Live edits still picked up via mtime invalidation.

Docstring sweep on the notification + detection cluster:
- headless-events.ts: 17 JSDoc blocks (exit codes + every classification fn)
- notification-store.ts, notification-overlay.ts, notification-widget.ts,
  notifications.ts: ~17 blocks
- detection.ts, codebase-generator.ts: ~5 blocks

Typecheck clean. 3/3 perf tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:18:40 +02:00
Mikael Hugo
abb3d76ffa chore(sf): minor sweep — gate-registry dedup, token-counter, worktree-health
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:18:03 +02:00
Mikael Hugo
86026c9e4f feat(sf): final UOK parity pass + secondary agent sweep
Evidence-collector (matches gsd2 exactly):
- recordToolCall now takes toolCallId as first arg (parallel-call fix)
- recordToolResult matches by toolCallId, not last-unresolved heuristic
- saveEvidenceToDisk now atomic tmp-rename JSON (not appendFileSync JSONL)
- clearEvidenceFromDisk added; resetEvidence takes no args
- stricter isEvidenceArray validator

auto/loop.ts:
- PID guard in loadStuckState prevents cross-test state pollution
- pid field added to saveStuckState payload
- saveCustomVerifyRetryCounts uses atomicWriteSync (crash-safe)

auto/run-unit.ts:
- chdir failure marked isTransient:true (dir may exist on retry)

auto/session.ts:
- canAskUser field added with reset() support

auto/phases.ts:
- currentUnit = null in closeoutAndStop (no stale refs after stop)

bootstrap/provider-error-resume.ts:
- resetTransientRetryState injectable via ProviderErrorResumeDeps

Secondary sweep (worktree, workflow, token-counter, verification-gate,
activity-log, doctor-environment, json-persistence, scaffold-keeper tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:17:21 +02:00
Mikael Hugo
9db94ed77e chore(sf): residual session work — final consolidation
Last batch from the parallel swarm session: docstring tweaks,
verification-gate doc additions, workflow-reconcile and worktree-command
follow-ups, doctor-environment cleanup. Typecheck clean.

Most of the session work landed in earlier commits (8be8f4774, 3045538cb,
038938f2a, ed85252fc, 4f4b584e5, etc.); this commit is the residual
working-tree state after all swarms reported.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:17:03 +02:00
Mikael Hugo
f1cef7c476 feat(sf): multi-agent sweep — paths, verification, auto closeout, bootstrap, worktree
- paths.ts: add resolveSliceSummaryPath, resolveCheckpointPath, task-summary helpers
- bootstrap/system-context.ts: worktree active context + codebase-map inject
- auto.ts: plumb autonomousMode flag, startAuto options expansion
- auto/loop.ts: Math.max(0,...) clock-skew guard in enforceMinRequestInterval
- auto/session.ts: add lastUnitAgentEndMessages and PreExecFailure tracking
- auto-post-unit.ts: clearEvidenceFromDisk after verification, isDeterministicPolicyError
- auto-unit-closeout.ts: populate lastPreExecFailure on gate failures
- cache.ts: fix TTL helper arg counts
- codebase-generator.ts: add incremental refresh helpers
- commands/handlers/auto.ts: wire autonomousMode and plan-v2 flags
- context-budget.ts: remove stale context-budget trimming (was dead code)
- dispatch-guard.ts: trim unused guards
- doctor-{environment,runtime-checks}.ts: expand health checks
- execution-instruction-guard.ts: add approval-boundary guard
- gate-registry.ts: de-dup gate registration on reload
- gitignore.ts: add .sf/worktrees to default gitignore
- notification-store.ts: add dedup window + category grouping
- pre-execution-checks.ts: add provider-readiness pre-check
- preferences.ts: subscription cost helpers + allow_flat_rate_providers
- production-mutation-approval.ts: approval-required flag on mutation tools
- state.ts: remove redundant fallback (now handled in deriveState)
- token-counter.ts: subscription token usage tracking
- verification-gate.ts: gate retry on bounded failure class
- workflow-{projections,reconcile,template-compiler,templates}: hardening
- worktree-{command,manager}: path normalization + active-worktree tracking
- tests/verification-evidence.test.ts: new — evidence load/save/clear coverage
- tests/provider-errors.test.ts: add missing provider-delay tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:16:13 +02:00
Mikael Hugo
d828f9861f chore(sf): residual edits from parallel autonomous + bug-hunt sweep
Touches auto.ts, auto/loop.ts, preferences.ts, safety/git-checkpoint.ts,
token-counter.ts, tools/complete-slice.ts, verification-gate.ts,
workflow-logger.ts, workflow-migration.ts, plus new
tests/record-promoter.test.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:09:11 +02:00
Mikael Hugo
3045538cbe feat(sf): bug-hunt fixes, UOK phase hardening, model policy, record-promoter
- auto/loop.ts: runLegacyAutoLoop / runUokKernelLoop contract routing fixes
- auto/phases.ts: plan-gate in runDispatch, verification gate in runFinalize,
  consecutiveSessionTimeouts exponential backoff, structuredQuestionsAvailable
  passed to resolveDispatch (GAP-13)
- auto/run-unit.ts: _setSessionSwitchInFlight cleared on timeout (GAP-11)
- safety/git-checkpoint.ts: remove stash-before-rollback (user: never stash)
- bootstrap/system-context.ts: fix "system-context" → "bootstrap" LogComponent
- preferences-models.ts: fill missing unit-type routing buckets
- post-execution-checks.ts + tests: type-safe post-exec check expansion
- session-model-override.ts: add override-clear helper
- tests/provider-errors.test.ts: add resetTransientRetryState to all mocks
- memory-relations.ts: add cross-entity relation helpers
- memory-store.ts: fix ranked memory pagination
- onboarding-state.ts: add step-completion persistence
- cache.ts: add TTL-aware get helpers
- definition-io.ts: stricter parse with field validation
- blocked-models.ts: add provider-level block support
- worktree-{manager,resolver}: path normalization edge cases
- commands/catalog.ts: register skill-health and record-promoter commands
- workflow-mcp.ts: MCP tool registration improvements
- agentic-docs-scaffold.ts: clarify scaffold header comment
- headless-events.ts: EXIT_RELOAD + notification dedup boundary
- record-promoter.ts: new — promotes draft records to canonical location
- docs/records/2026-05-02-bug-hunt-findings.md: bug-hunt audit findings log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 02:03:55 +02:00
Mikael Hugo
8be8f4774b feat(sf): autonomous agent sweep — docstrings, robustness, preferences, workflow reconcile
- headless-events: add EXIT_RELOAD handling and dedup boundary types
- atomic-write: improve tmp-file cleanup and error reporting
- auto-model-selection: add flat-rate provider filtering and cost-aware routing stubs
- auto-worktree: strengthen worktree validation paths
- auto/phases.ts: emit artifact-verification-retry journal event on bounded retry
- auto/run-unit.ts: anchor cwd before session init, add AbortController for timeout
- benchmark-selector, captures, definition-loader: docstring/robustness sweep
- bootstrap/{notify-interceptor,provider-error-resume,write-gate}: error path hardening
- branch-patterns, git-constants, git-self-heal: comment/constant clarifications
- commands-{logs,maintenance}: expose additional log and maintenance commands
- custom-verification, post-execution-checks, pre-execution-checks: defensive fixes
- doctor: expand check coverage and structured output
- gate-registry: improve gate deduplication and ordering
- json-persistence: add atomic-write path and versioned schema helpers
- notifications: add dedup window and notification grouping
- preferences-types: add subscription_monthly_cost_usd + subscription_monthly_tokens
- production-mutation-approval, skill-health, skill-manifest: hardening sweep
- structured-data-formatter: improve table rendering edge cases
- workflow-events, workflow-manifest, workflow-reconcile: reconcile robustness
- worktree-{manager,resolver}: path normalization fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 01:57:24 +02:00
Mikael Hugo
c6a7c7772d chore(sf): autonomous docstring sweep — additional SF extension files
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:52:37 +02:00
Mikael Hugo
038938f2ac fix: headless EXIT_RELOAD case + notification dedup boundary
- src/headless-events.ts: add case "reload" → EXIT_RELOAD (12).
  EXIT_RELOAD sentinel was defined but unused — "reload" status fell
  through to EXIT_ERROR (1).
- src/resources/extensions/sf/notification-store.ts:109: use <= for
  dedup window so a second identical notification at exactly
  DEDUP_WINDOW_MS still gets suppressed (was off-by-one at boundary).
- src/resources/extensions/sf/definition-loader.ts: pending docstring
  tweaks from autonomous sweep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:52:29 +02:00
Mikael Hugo
7824cb527c docs(sf): expand rebuildState docstring for clarity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 01:51:26 +02:00
Mikael Hugo
e7347fe499 chore(sf): docstring sweep across remaining SF extensions
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:50:11 +02:00
Mikael Hugo
93b1841735 chore(sf): docstring tweaks in notification-overlay + self-feedback
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:49:10 +02:00
Mikael Hugo
229ade7e45 chore(sf): more docstring tweaks in auto/phases + bootstrap/write-gate
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:49:03 +02:00
Mikael Hugo
3dfc60e04b chore(sf): follow-up docstring tweaks in doctor.ts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:48:57 +02:00
Mikael Hugo
4f4b584e53 feat(sf): worktree hardening, skip-slice handler, cwd anchoring + docstrings
- new worktree-root.ts / worktree-session-state.ts: track and restore
  original project root after /worktree merge or /worktree return
- new tools/skip-slice.ts: cascade skip to tasks in the slice so milestone
  completion isn't blocked by pending tasks (#4375)
- auto/run-unit.ts: anchor cwd to basePath before newSession() captures it
  (GAP-10) — prevents tool runtime / system prompt from rooting on drifted
  cwd from async_bash, background jobs, or prior unit cleanup
- safety/git-checkpoint.ts: harden HEAD-rev-parse against execFileSync
  errors, surface stderr properly
- broad JSDoc / docstring pass across the rest of the SF extension surface

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:48:37 +02:00
Mikael Hugo
ed47951960 feat(pi-ai): delegate google-gemini-cli auth + project to cli-core
Replace ~700 LOC of hand-rolled OAuth and onboarding with cli-core's own
getOauthClient + setupUser. The provider now reads ~/.gemini/oauth_creds.json
itself (via cli-core), refreshes tokens, and discovers the Code Assist
project + tier server-side — exactly like the real gemini CLI does.

- provider/google-gemini-cli.ts: drop apiKey={token,projectId} JSON
  plumbing; getCodeAssistServer() uses cli-core for everything
- delete utils/oauth/google-gemini-cli.ts (457 LOC: hand-rolled login,
  PKCE, callback server, discoverProject, onboardUser, tier handling)
- delete utils/oauth/google-oauth-utils.ts (201 LOC: only consumed by
  the deleted gemini-cli helper)
- oauth/index.ts: remove gemini-cli from BUILT_IN_OAUTH_PROVIDERS
  registry; google-gemini-cli is no longer SF-managed
- auth-storage.ts: update 3 error messages to direct users to the real
  gemini CLI for authentication instead of the removed /login command

Login UX: users authenticate with the real gemini CLI; we just consume
~/.gemini/oauth_creds.json. Whole-provider disable goes through manual
settings.json edit (per-model toggle still works in interactive UI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:47:48 +02:00
Mikael Hugo
ed85252fc5 feat: plumb /sf autonomous full + add docstrings on the auto-command path
`/sf autonomous full` (or `--full`) plumbs through to AutoSession.fullAutonomy,
to be consumed at milestone-complete to skip the human-review pause and
auto-merge + chain to the next milestone. Git revert is the safety net
(see ADR-019/021 conversation on autonomy and reversibility).

Plumbing path:
- commands/handlers/auto.ts: parses `full` / `--full` modifier, threads
  fullAutonomy through launchAuto options
- commands/catalog.ts: completion entries for `full` and `--full`
- auto.ts: startAuto and startAutoDetached accept fullAutonomy in options;
  startAuto pins it on the session up-front so resume paths preserve it
- auto/session.ts: AutoSession.fullAutonomy field with full docstring

Behavior change is staged: the milestone-complete consumer that auto-merges
and chains is intentionally not in this commit (parallel session is active
in auto-post-unit.ts and auto/loop.ts; will land in a follow-up).

Also adds JSDoc to the functions on the touched path:
- handleAutoCommand (full command-family doc)
- launchAuto (headless vs detached routing)
- startAutoDetached (fire-and-forget rationale, why it diverges from startAuto)
- AutoSession.fullAutonomy (full inline doc)

Typecheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 01:36:29 +02:00
Mikael Hugo
356d1d1f99 feat(uok): port gsd2 resilience patterns — rate-limit, evidence reload, provider recovery
loop.ts:
- saveStuckState on main dev path (was only on custom-engine path — P1 fix)
- Add pid to stuck-state JSON to prevent test pollution across process runs
- Use atomicWriteSync in saveCustomVerifyRetryCounts for crash-safety
- Add enforceMinRequestInterval + call before both runUnitPhaseViaContract sites
- Update s.lastRequestTimestamp from requestDispatchedAt on each unit

session.ts:
- Add lastRequestTimestamp and lastUnitAgentEndMessages fields

phases.ts:
- Add consecutiveSessionTimeouts + exponential-backoff auto-resume (up to 3x)
  for session-creation timeouts before pausing for manual review
- Add loadEvidenceFromDisk after resetEvidence to rehydrate evidence on restart
- Add USER_DRIVEN_DEEP_UNITS + isAwaitingUserInput guard to skip artifact
  verification when a deep-planning unit is paused awaiting user input
- Store s.lastUnitAgentEndMessages after each unit run
- Add requestDispatchedAt to runUnitPhase return type

evidence-collector.ts: add loadEvidenceFromDisk export
auto-post-unit.ts: add USER_DRIVEN_DEEP_UNITS set + re-export isAwaitingUserInput
user-input-boundary.ts: port from gsd2 (isAwaitingUserInput + approval helpers)
run-unit.ts: capture requestDispatchedAt at API dispatch time
kernel.ts: remove redundant !legacyFallback guard (enabled already encodes it)
tests/uok-kernel-path.test.ts: add SF_UOK_AUDIT_ENVELOPE env var assertions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 01:27:37 +02:00
Mikael Hugo
dda1bc1206 test: make uok-gitops-wiring assertion whitespace-tolerant
The test was checking for a literal single-line ternary in auto-post-unit.ts,
but the formatter naturally renders the same ternary multi-line. The semantic
content is identical; the test was failing on whitespace alone.

Normalize runs of whitespace before substring-matching so the assertion
survives prettier/biome formatting changes.

After this fix: 39/39 uok tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 01:21:36 +02:00
Mikael Hugo
9c20ebd76b feat(uok): wire ExecutionGraphScheduler into kernel loop path
- loop.ts: add DispatchContract type, AutoLoopOptions, resolveDispatchNodeKind,
  runUnitPhaseViaContract — kernel path routes unit execution through
  ExecutionGraphScheduler; legacy path passes through directly
- loop.ts: export runUokKernelLoop (contract=uok-scheduler) and
  runLegacyAutoLoop (contract=legacy-direct)
- auto-loop.ts: re-export both new loop functions
- auto.ts: use runUokKernelLoop/runLegacyAutoLoop at both call sites
- phases.ts: use uokFlags.planningFlow for plan gate (was bypassing
  legacyFallback via raw pref read)
- auto-dispatch.ts: use hasFinalizedMilestoneContext for execution-entry
  context check (picks up SF_PROJECT_ROOT artifact fallback)
- tests: port uok-writer, uok-parity-report, uok-loop-adapter-writer,
  uok-kernel-path test files from gsd2 — all 8 tests pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:54:15 +02:00
Mikael Hugo
ca5d2880ec polish: tighten scaffold-keeper signature + dedupe Pending report row
Follow-up to commit 39e2dc70c. Two small improvements that surfaced when
the parallel Phase D subagent finished and inspected the worktree:

- commands-scaffold-sync.ts:
  - Tighten ScaffoldKeeperFn to match Phase D's actual dispatcher signature
    (basePath, ctx) => Promise<number>. Define a local minimal
    ScaffoldKeeperCtxShape for the lazy loader so we don't form a hard
    import dependency on scaffold-keeper.ts.
  - Remove duplicated "Upgradable" line from the report table — keep only
    "Pending" since ADR-021 §10 names that the user-facing label.
- tests/scaffold-keeper.test.ts: better-typed notify stub; covers Phase E
  arg-parser helpers (parseScaffoldSyncArgs, matchesOnly, applyOnlyFilter).

Typecheck clean. 49/49 scaffold tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:49:43 +02:00
Mikael Hugo
39e2dc70c9 feat: ADR-021 Phase D + E — scaffold-keeper agent + /sf scaffold sync command
Phase D: scaffold-keeper background agent
- scaffold-keeper.ts: dispatchScaffoldKeeperIfNeeded fires async after milestone
  completion and on stopAuto cleanup. Detects editing-drift items, writes
  <file>.proposed artifacts (template-only stub for now; later wires the
  records-keeper skill subagent for code-as-fact merging), emits a structured
  approval_request notification with stable dedupe_key so repeated runs don't
  spam the user.
- Wired into auto-post-unit.ts and auto.ts:stopAuto via fire-and-forget so
  the auto loop is never blocked by scaffold work.
- Failure modes non-fatal: try/catch around the dispatch, errors logged via
  logWarning("scaffold").

Phase E: /sf scaffold sync command (escape hatch)
- commands-scaffold-sync.ts: parseScaffoldSyncArgs + handleScaffoldSync.
- Flags:
    --dry-run         report what would change, no writes
    --include-editing run scaffold-keeper synchronously for editing-drift items
    --only=<glob>     scope to a path glob (suffix/prefix match)
- Wired into the SF command system via commands-bootstrap.ts, commands/catalog.ts,
  and commands/handlers/ops.ts following the existing /sf <verb> pattern.
- Reuses ensureAgenticDocsScaffold from Phase C — doesn't reimplement sync logic.

Doctor finding (checkScaffoldFreshness) refined to reference the new command.

Tests: 8 new cases in scaffold-keeper.test.ts. All 49 scaffold tests green.

Together with Phases A-C, this completes ADR-021. Documents are now versioned,
upgrades are automatic for the safe cases, and editing-drift surfaces through
.proposed artifacts and structured notifications. The scaffold-keeper agent
body is currently a template-only stub; replacing it with a real records-keeper
subagent dispatch is a follow-up that the architecture now enables.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:45:54 +02:00
Mikael Hugo
14b5c2b12c test: add Phase C coverage for drift-aware ensureAgenticDocsScaffold
Phase C (automatic silent sync) had no dedicated tests when committed.
Added 8 cases covering:
- ensureAgenticDocsScaffold on empty dir creates files with markers
- old-version pending marker silently re-renders to current
- editing-drift file left untouched
- legacy unmarked file matched against archive promoted to pending
- migrateLegacyScaffold idempotency

Total scaffold test count: 41 (was 33).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:43:19 +02:00
Mikael Hugo
d01b2f0b7f feat(uok): complete pipeline integration and close all parity gaps vs gsd2
- flags: gitopsTurnAction default → "commit" (ensures git history per turn)
- kernel: add runKernelLoop routing, parity label → "uok-kernel"
- auto: pass runKernelLoop at both call sites
- loop-adapter: already had writer token acquire/release (confirmed at parity)
- gate-runner: already had try/catch, dynamic ceiling, maxAttempts (confirmed)
- audit: isStaleWrite guard already present (confirmed at parity)
- plan-v2: add emptyGraph/sliceCount fields, isEmptyPlanV2GraphResult export,
  allow validating/completing-milestone with zero task nodes + slices present
- phases: add empty-graph recovery (invalidate-caches + re-derive) in runPreDispatch
- execution-graph: add ExecutionGraphSnapshot interface + buildExecutionGraphSnapshot
- auto-dispatch: wire buildDispatchEnvelope at all 3 dispatch exit points,
  emit dispatch-envelope audit event when gates or auditEnvelope enabled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:42:41 +02:00
Mikael Hugo
2cb3f5f75a feat: ADR-021 Phase C — automatic silent scaffold sync
The user-visible "automatic" upgrade behavior. After this lands, projects
pointed at SF silently catch up to the current scaffold without any user
action — for the simple cases.

Drift-aware ensureAgenticDocsScaffold:
- Step 1: migrateLegacyScaffold runs first to promote unmarked-but-recognised
  files via SCAFFOLD_VERSION_ARCHIVE hash matching
- Step 2: per-template walk:
  - Missing → create + stamp + manifest entry (existing behavior)
  - Present, marker, state=pending, version drifted, hash matches stamp
    → silent re-render with current template + restamp (NEW)
  - Editing/completed/customized → leave alone (Phase D handles editing-drift)
- Silent contract: no stdout/stderr, only logWarning("scaffold") for I/O
  failures. All failure modes non-fatal.

SCAFFOLD_VERSION_ARCHIVE bootstrap:
- Lazily seeded with current SF version's body hashes from SCAFFOLD_FILES
- Future SF releases append entries when templates change so legacy projects
  can match against any prior version

checkScaffoldFreshness doctor finding (ADR-021 §8):
- Surfaces missing/upgradable/editing-drift counts as "scaffold_drift" warning
- Auto-fix runs ensureAgenticDocsScaffold to handle missing+pending
- Non-fatal warning, never blocks dispatch
- Editing-drift left for Phase D (scaffold-keeper background agent)

Tests pass: 33/33 across scaffold-versioning + scaffold-drift suites.
Typecheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:39:44 +02:00
Mikael Hugo
deab93bed6 test: split scaffold tests into per-module files; fix require() in ESM test
Subagent split scaffold tests into scaffold-versioning.test.ts (Phase A)
and scaffold-drift.test.ts (Phase B). Fixed an ESM-incompatible
require("node:fs") in one drift test that was breaking with
--experimental-strip-types. All 33 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:35:12 +02:00
Mikael Hugo
6f9a99da0a feat: ADR-021 Phase A+B — scaffold versioning + drift detection
Foundation for automatic scaffold upgrades. Data plane only — Phase C
wires drift detection into the existing scaffold pipeline.

New modules:
- scaffold-versioning.ts: HTML-comment markers on Markdown scaffold
  files (sf-doc: version=X template=Y state=pending hash=sha256:Z),
  body-hash helpers, manifest read/write/dedup, stamp helpers.
  Manifest at .sf/scaffold-manifest.json.
- scaffold-drift.ts: detectScaffoldDrift returns five buckets
  (missing/upgradable/editing-drift/untracked/customized) per ADR-021.
  migrateLegacyScaffold stub for Phase C archive support.

Wired in:
- agentic-docs-scaffold.ts: new files get markers + manifest entries.
  NO_MARKER_PATHS list excludes .siftignore (per ADR-021 §2 — dotfile
  config tooling fights inline markers).
- gitignore.ts: PREFERENCES.md template gains sf_template_state and
  sf_template_hash frontmatter fields, extending the existing
  last_synced_with_sf pattern.
- preferences-types.ts: SFPreferences interface adds the two new
  optional fields; KNOWN_PREFERENCE_KEYS updated.

Tests (23 cases, all pass):
- parseMarker / formatMarker round-trip
- bodyHash determinism
- stampScaffoldFile new + replace-existing-marker
- manifest read/write/dedup
- detectScaffoldDrift bucket assignment

Behavior unchanged: existing files in existing projects are left alone.
Phase C uses these primitives to make automatic sync transparent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:32:15 +02:00
Mikael Hugo
851bd7fca3 feat(uok): enforce gates, port gsd2 modules, flip flags to on-by-default
- Wire plan-gate in runDispatch() and verification gate in runFinalize()
- Add planningFlow gate persistence in guided-flow.ts
- Add execution-graph gate event in auto-dispatch.ts
- Flip all UOK feature flags from opt-in (=== true) to on-by-default (?? true)
- Port dispatch-envelope.ts, parity-report.ts, writer.ts from gsd2
- Add DispatchReasonCode, UokDispatchEnvelope, WriterToken, WriteRecord,
  WriteSequence, DispatchExplanation to contracts.ts
- Add "refine" to UokNodeKind
- Extend auto-worktree.ts with workspace.after_create hook support
- Add workspace.after_create to preferences-types and preferences-validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:26:10 +02:00
Mikael Hugo
0399bb9c8c detection: fix 6 bugs surfaced by ace-coder validation
Phase 4-D fixes from the Phase 3 validation report. ace-coder is a
uv-managed Python repo with Rust crates in subdirectories; SF was
mis-detecting it in ways that would have failed every autonomous
verification.

1. detectPackageManager: return undefined when no root package.json
   (previously hallucinated "npm" as default, leaking into reports)
2. detectVerificationCommands: only synthesize npm runner when
   package.json actually present at root
3. ROOT_ONLY_PROJECT_FILES: expanded with Cargo.toml, go.mod,
   pyproject.toml, setup.py, pom.xml, pubspec.yaml, Package.swift,
   mix.exs — these are root-only signals; nested instances are
   handled explicitly by emitter logic
4. Cargo block: distinguishes workspace-root vs single-crate-root vs
   nested-only-crates layouts; emits per-crate bash loop for the last
   case (mirrors the Go multi-module branch pattern)
5. pyprojectHasTool: matches both [tool.X] and [tool.X.subkey] so
   ace-coder's [tool.ruff.lint] / [tool.ruff.format] are detected
6. Makefile branch: skip `make test` when (a) test command already
   emitted by another block, or (b) the test target depends on
   _verify_nix or similar nix-shell gates (ace-coder's case)

After these fixes, detectProjectSignals on ace-coder yields the
expected output: no spurious "npm", per-crate cargo loops, ruff/pyright
detected, no nix-gated `make test`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:19:49 +02:00
Mikael Hugo
eb56173fe5 ADR-021: versioned documents + automatic upgrade via records-keeper
Generalizes the preferences-template-upgrade pattern to all scaffold-managed
documents with three states (pending/editing/completed), HTML-comment markers
on Markdown files, frontmatter on PREFERENCES.md, and a content-hash archive
for migrating legacy projects.

Operation is automatic-first, not command-driven:
- Synchronous on every SF startup (cheap path: missing + upgradable + legacy)
- Asynchronous after milestone completion: scaffold-keeper subagent runs the
  existing records-keeper skill, treating code as the source of truth and
  re-deriving doc content from source when drift is detected
- Surfaces results via the structured-notification model (kind:approval_request)
  only when human review is warranted; silent runs produce no notification
- Manual /sf scaffold sync exists as an escape hatch for dry-run + forced
  refresh, not as the primary interface

Five implementation phases (A-E), each independently shippable. Phase A
unlocks the architectural property; Phase D is what makes records-keeper
autonomous for code-derived docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:18:16 +02:00
Mikael Hugo
064dff2f0f feat: SF strengthening + ADR-020 wire architecture (Phases 1-2)
Phase 1 — close SF-side polish gaps:

- codebase-generator: distinguish uv/poetry/pdm in Python stack-signals;
  surface configured tooling (ruff/mypy/pyright) when config files exist
- doctor-environment: new checkPythonEnvironment — detects uv/poetry/pdm
  via lockfile, verifies binary on PATH, warns with install hint when missing
- doctor-environment: new checkSiftAvailable — recommends sift install for
  repos > 5000 source files when not on PATH
- tech-debt-tracker: documented future memory-as-sub-extension extraction
  (defer until real backend-swap requirement)

Phase 2 — internal wire architecture:

- ADR-020: singularity-grpc as shared schema repo; gRPC + typed clients
  for first-party services; MCP façade only at external-tool boundary
- ADR-019: trimmed MCP scope section to a 3-line summary linking to ADR-020
  to avoid the wire-format table living in two places
- design-docs/index.md: ADR-020 added to ADR table

These changes make SF stronger for autonomous work on Python repos
(particularly ace-coder) and capture the internal wire architecture
decision as a durable ADR before any singularity-grpc code lands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 00:03:34 +02:00
Mikael Hugo
3d8e8c5d57 detection: skip Python tool caches during project scans
Adds __pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .tox, .eggs,
and htmlcov to RECURSIVE_SCAN_IGNORED_DIRS so SF doesn't walk into them
when scanning project files. These directories can contain thousands of
files in mature Python projects and were slowing down detection / scan
operations on Python codebases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 23:49:46 +02:00