Commit graph

784 commits

Author SHA1 Message Date
Mikael Hugo
0b5fa75c0d fix(lint): fix all pre-existing lint failures
- check-sf-extension-inventory.mjs: expand parseDirectRegisteredCommands()
  scan to include 7 more files (guards/inturn.js, notifications/notify.js,
  permissions/index.js, ui/usage-bar.js, commands/legacy/audit.js,
  commands/legacy/create-extension.js, commands/legacy/create-slash-command.js)
  and filter results by BASE_RUNTIME_COMMAND_NAMES to exclude doc-string false
  positives ("name" in create-slash-command.js template text)

- extension-manifest.json: remove 'clear' (subcommand of logs/notifications,
  never a top-level pi.registerCommand)

- packages/pi-agent-core/src/db/sf-db.ts: fix 23 noVoidTypeReturn errors
  - openDatabase: void → boolean (caller uses return value at line 5625)
  - claimEscalationOverride: void → boolean (caller checks at escalation.js:243)
  - resolveSelfFeedbackEntry: void → boolean (caller checks at self-feedback.js:387)
  - copyWorktreeDb: void → boolean (caller checks at reconcileWorktreeDb)
  - compactUokMessages: void → {before,after} (caller returns value at message-bus.js:238)
  - insertSessionTurn: void → bigint|null (caller uses id at session-recorder.js:104)
  - expireStaleMemories: void → number (caller uses count at auto-start.js:1047)
  - deleteMemorySourceRow: void → boolean (caller returns value at memory-source-store.js:107)
  - deleteMemoryEmbedding: void → boolean (caller returns value at memory-embeddings.js:328)
  - updateBacklogItemStatus: remove dead return expression (callers discard value)
  - removeBacklogItem: remove dead return expression (callers discard value)
  - updateGateCircuitBreaker: remove dead return {total,avgMs,...} (wrong-type
    code accidentally merged from getGateLatencyStats, never reachable)
  - markUokMessageRead: remove dead return true/false (callers discard value)

- Auto-fix formatting and organizeImports in ~30 source files (biome --write)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 04:02:31 +02:00
Mikael Hugo
2dea73398d fix(learning): add save_knowledge to manifest, failure_mode to aggregator SELECT + index
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 23:18:02 +02:00
Mikael Hugo
e50321b62b feat(selection): thread unitType + failure_mode into fallback outcome records
- FallbackResolver.setUnitContext() stores {unitType,unitId} from autonomous dispatch
- run-unit.js calls pi.setFallbackUnitContext() before/after each unit
- _findAnyAvailableFallback uses real unitType/unitId from context, not sentinel
- Schema v59: failure_mode column in llm_task_outcomes
- insertLlmTaskOutcome accepts failure_mode (rate_limit, quota_exhausted, auth_error)
- register-hooks.js passes event.classification.reason as failure_mode
- register-hooks.js uses real event.unitId when available
- ExtensionRuntimeActions.setFallbackUnitContext added to pi API surface

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 23:14:22 +02:00
Mikael Hugo
009651e86f feat(selection): wire before_model_select into FallbackResolver for outcome-aware fallback
When a model fails and FallbackResolver picks a replacement, it now:
1. Fires the before_model_select hook with reason='fallback' and the
   failing model's ID — the learning system records the failure outcome
   and returns the best Bayesian-blended replacement from llm_task_outcomes
2. Falls back to the existing heuristic sort (reasoning + context window)
   if the hook is unavailable or returns no override

Changes:
- BeforeModelSelectEvent: add optional currentModelId and reason fields
- FallbackResolver: accept emitBeforeModelSelect in constructor; make
  _findAnyAvailableFallback async; fire hook before heuristic fallback
- agent-session.ts: inject lazy emitBeforeModelSelect closure into resolver
- register-hooks.js: record failure outcome when reason='fallback' before
  returning selectLearnedModel result

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 23:05:33 +02:00
Mikael Hugo
fb1bd3e5fa refactor(shared): deduplicate shared/ utilities against coding-agent package exports
- Add packages/coding-agent/src/utils/format.ts as the canonical source
  for formatDuration, formatTokenCount, truncateWithEllipsis, sparkline,
  formatDateShort, fileLink, stripAnsi, normalizeStringArray — all already
  exported from @singularity-forge/coding-agent via index.ts.

- Convert shared/format-utils.js to a compatibility shim that re-exports
  the 8 functions from @singularity-forge/coding-agent. All 13 importers
  continue to work with no import changes required.

- Convert shared/path-display.js to a compatibility shim that re-exports
  toPosixPath from @singularity-forge/coding-agent. Implementation in
  packages/coding-agent/src/utils/path-display.ts was already canonical.

- shared/frontmatter.js is intentionally NOT shimmed: splitFrontmatter/
  parseFrontmatterMap have a different API from the package's parseFrontmatter/
  stripFrontmatter (flat-map vs {frontmatter, body} object).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 22:41:03 +02:00
Mikael Hugo
7227912a29 perf(search): move web-search provider injection from extension hook to native middleware
- Create packages/coding-agent/src/core/providers/web-search-middleware.ts with
  WebSearchMiddleware class: injects web_search tool, enforces session budget (#1309),
  strips thinking blocks from history, and respects PREFERENCES.md search_provider.

- Wire webSearchMiddleware.applyToPayload into sdk.ts onPayload callback (before
  extension hook dispatch) so injection runs as compiled TypeScript with zero
  jiti-dispatch overhead.

- Export WebSearchMiddleware, webSearchMiddleware singleton, setPreferBraveResolver,
  CUSTOM_SEARCH_TOOL_NAMES, MAX_NATIVE_SEARCHES_PER_SESSION, and stripThinkingFromHistory
  from @singularity-forge/coding-agent so the extension can delegate to the same instance.

- Refactor search-the-web/native-search.js: remove self-contained injection logic;
  import and delegate before_provider_request to webSearchMiddleware singleton.
  Use tri-state isAnthropicProvider (null/false/true) to synthesize a provider hint
  when event.model is absent but model_select has already fired — prevents the
  model-name heuristic from wrongly injecting into Copilot claude-* requests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 22:37:42 +02:00
Mikael Hugo
3fba4bcb03 refactor(mcp): move MCP connection manager to packages/coding-agent/src/core/mcp/
- Create config.ts with McpServerConfig types and readMcpConfigs/getServerConfig
- Create auth.ts with buildHttpTransportOpts and createCliOAuthProvider
- Create connection-manager.ts with McpConnectionManager class
- Create index.ts re-exporting the public API
- Export McpConnectionManager and helpers from @singularity-forge/coding-agent
- Rewrite mcp-client extension as thin wrapper using McpConnectionManager
- Rewrite auth.js as re-export shim from @singularity-forge/coding-agent
- Update test to import buildHttpTransportOpts from @singularity-forge/coding-agent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 22:19:46 +02:00
Mikael Hugo
9e55528c95 revert(tui): remove Ink bridge, restore pure custom differential renderer
The Ink bridge added today was a misguided gradual-migration wrapper:
- Components still rendered via the old string-line protocol (no Ink layout)
- Key decodes were re-encoded to escape sequences → keys.ts decoded again (double round-trip bug)
- The _useInk / _inkHandle path blocked TTY start unconditionally via process.stdout.isTTY check

Removed: ink-bridge.tsx, ink-bridge.test.ts, useInk() method, _useInk/_inkHandle fields,
startInkRenderer import/export, Ink branch in start()/stop()/requestRender().

Removed ink and react from packages/tui dependencies and peerDependencies.
Reverted tsconfig.extensions.json jsx settings (only needed for the .tsx bridge file).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 21:38:54 +02:00
Mikael Hugo
a77e1551d2 refactor(memory): consolidate memory system, remove dead code
- Delete memory-backfill.js — not imported anywhere, dead code
- Rename memory-sleeper.js → tool-watchdog.js — misnamed; it is a
  tool-output watchdog with no relation to the memory store
- Collapse memory-embeddings-llm-gateway.js into memory-embeddings.js —
  removes the lazy-import split; loadGatewayConfigFromEnv,
  createGatewayEmbedFn, and rerankCandidates are now direct exports
- Remove buildEmbeddingFn() dead stub (always returned null)
- Enable packages/coding-agent memory extraction extension by default
  (memory.enabled ?? true) so session-level extraction is active
- Update all import sites and tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 18:17:49 +02:00
Mikael Hugo
3ffd882c8c sf snapshot: uncommitted changes after 56m inactivity 2026-05-10 17:16:30 +02:00
Mikael Hugo
924383b6f7 sf snapshot: uncommitted changes after 197m inactivity 2026-05-10 15:59:33 +02:00
Mikael Hugo
de77cf439f fix(tui): error boundary in doRender, extract autonomousStatus, clean parseCellSize
Some checks failed
CI / detect-changes (push) Has been cancelled
CI / docs-check (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled
CI / integration-tests (push) Has been cancelled
CI / windows-portability (push) Has been cancelled
CI / rtk-portability (linux, blacksmith-4vcpu-ubuntu-2404) (push) Has been cancelled
CI / rtk-portability (macos, macos-15) (push) Has been cancelled
CI / rtk-portability (windows, blacksmith-4vcpu-windows-2025) (push) Has been cancelled
- doRender() now catches render errors and emits a fallback line
- autonomousStatus ANSI formatting extracted to renderAutonomousStatus()
  with named color constants instead of raw escape strings
- parseCellSizeResponse extracted to pure function with proper validation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 12:41:47 +02:00
Mikael Hugo
b0a8f32a10 feat(tui): wire Ink bridge into TUI.start() and stop()
- TUI.useInk() opts into Ink-backed rendering (call before start())
- In start(): if _useInk || process.stdout.isTTY, mount Ink renderer via
  startInkRenderer() and skip the legacy differential render path entirely
- In stop(): unmount Ink handle and return early; legacy terminal cleanup
  (cursor repositioning, showCursor, terminal.stop) is skipped since Ink
  handles terminal restoration itself
- Passes this.render()/invalidate() via a plain Component wrapper to avoid
  the private handleInput TypeScript conflict
- Two new contract tests: useInk() flag and stop() Ink handle teardown
- 80/80 tests pass; legacy path unchanged for non-TTY (CI/tests)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 12:15:09 +02:00
Mikael Hugo
4e97058d7e feat(tui): add Ink bridge for gradual migration from custom renderer
Install ink@7.0.2 + react@19.2.6. Add JSX/react-jsx support to
packages/tui tsconfig. Create ink-bridge.tsx: LegacyComponentView wraps
existing Component objects as React nodes, startInkRenderer drives the
Ink render loop around any legacy Component tree.

Exports startInkRenderer from @singularity-forge/tui public API.
All 78 existing tui tests pass; 3 new ink-bridge tests added.

This is the infrastructure step for migrating components one-by-one from
the custom differential renderer to native Ink React components, without
breaking interactive mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 12:10:39 +02:00
Mikael Hugo
d447095bd7 build: switch full build pipeline to TypeScript 7 native (tsgo)
Replace tsc with tsgo in all build scripts — 5.6x faster emit.
tsgo has full emit parity for this codebase (NodeNext, ES2022, strict).

- build:core: tsc → tsgo (root tsconfig.json)
- copy-resources.cjs: typescript/bin/tsc → @typescript/native-preview/bin/tsgo.js
- All workspace packages (agent-core, ai, coding-agent, daemon,
  google-gemini-cli-provider, native, rpc-client, tui): tsc → tsgo

Benchmarks (root project):
  tsc --project tsconfig.json: 7.7s
  tsgo --project tsconfig.json: 1.4s  (5.6x faster)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:58:58 +02:00
Mikael Hugo
e09eb8f899 build: add TypeScript 7 (native preview) for fast type checking
- Remove vestigial experimentalDecorators/emitDecoratorMetadata from all
  package tsconfigs (no actual decorators in source — flags were from
  pi-mono vendor copy)
- Add @typescript/native-preview for 8-10x faster type checking (measured
  4.6x on this repo: tsc 6.5s vs tsgo 1.4s)
- Fix tsconfig.extensions.json: remove baseUrl (removed in tsgo/TS7) and
  use relative paths in paths mappings — compatible with both tsc and tsgo
- Add typecheck/typecheck:extensions scripts using tsgo

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:53:22 +02:00
Mikael Hugo
cab8b5decc refactor: strip internal pi branding (Phase 2A)
- CURSOR_MARKER: \x1b_pi:c\x07 → \x1b_sf:c\x07
- process.title: "pi" → "sf"
- PiManifest → SFManifest (with pi field backwards compat)
- readPiManifest → readSFManifest (loader.ts and package-manager.ts)
- readPiManifestFile → readSFManifestFile (package-manager.ts)
- .pi/skills → .sf/skills (keeps .pi/skills for backwards compat)
- User-facing path strings updated to .sf/ where appropriate
- ARCHITECTURE.md: "Pi coding-agent extension" → "coding-agent extension"
- Temp editor file: pi-editor-*.pi.md → sf-editor-*.sf.md
- Test fixtures: appName "pi" → "sf", pi manifest field → sf

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:50:55 +02:00
Mikael Hugo
02a4339a51 refactor: rename pi-* packages to forge-native names (Phase 1)
Rename all four packages/pi-* directories to forge-native names,
stripping the 'pi' identity and establishing forge's own:

- packages/pi-coding-agent → packages/coding-agent
- packages/pi-ai → packages/ai
- packages/pi-agent-core → packages/agent-core
- packages/pi-tui → packages/tui

Package names updated:
- @singularity-forge/pi-coding-agent → @singularity-forge/coding-agent
- @singularity-forge/pi-ai → @singularity-forge/ai
- @singularity-forge/pi-agent-core → @singularity-forge/agent-core
- @singularity-forge/pi-tui → @singularity-forge/tui

All import references, bare string references, path references,
internal variable names (_bundledPi*), and dist files updated.
@mariozechner/pi-* third-party compat aliases preserved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:28:01 +02:00
Mikael Hugo
6725a55591 feat(web): add error boundaries, expand test coverage, add README
- Add class-based ErrorBoundary component wrapping all 7 main views
  inside WorkspaceChrome; fallback shows view name, error, reload button
- Add 30 new unit tests (boot null-project path × 9, onboarding
  pure-function logic × 21); all 43 web/lib tests pass
- Add web/README.md: architecture, auth flow, 7 views, dev setup,
  API route pattern, test instructions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:24:40 +02:00
Mikael Hugo
7085ad850d refactor(tools): remove sf_ prefix from all remaining tool names
plan_milestone, plan_slice, plan_task, complete_task, complete_slice,
complete_milestone, skip_slice, replan_slice, reassess_roadmap,
validate_milestone, save_requirement, update_requirement, milestone_status

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 07:20:56 +02:00
Mikael Hugo
1322bc7d9a feat: implement Copilot coding agent lessons in SF
- fix(compaction): tokensBefore undefined crash on reload
  compaction-orchestrator now falls back to preparation.totalTokens when
  extension returns tokensBefore: undefined; compaction-summary-message
  guards with ?? 0 defensively

- feat(exec): inline truncation notice in sf_exec digest
  appends [stdout truncated — read full output: <path>] when
  stdout_truncated=true so agent knows to use sf_exec_search

- feat(exec): wire onUpdate progress for sf_exec
  calls onUpdate before execution starts with status/command so TUI
  shows live feedback during long-running commands

- feat(security): prompt injection defense for external content
  new sanitize-external-content.js utility: strips HTML comments,
  detects 15 injection patterns (instruction override, role reassignment,
  fake system messages, encoded payloads); wired into exec-tool digest

- feat(tools): sf_session_todo tool (persisted cross-compaction)
  add/check/list ops; persists to .sf/session_todo.json; pending todos
  injected into compaction summary block for context continuity

- feat(hooks): shell hooks surface (.sf/hooks/pre-tool/*.sh, post-tool/*.sh)
  pre-tool hooks block tool execution (exit≠0 = block with stdout reason)
  post-tool hooks fire-and-forget; JSON context piped to stdin; 5s timeout

- fix(db): WAL autocheckpoint disabled to prevent corruption
  PRAGMA wal_autocheckpoint=0 in initSchema(); explicit checkpointWal()
  after successful finalize verification — the only safe checkpoint point

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 07:01:28 +02:00
Mikael Hugo
20c0d74106 sf snapshot: pre-dispatch, uncommitted changes after 31m inactivity 2026-05-10 06:26:32 +02:00
Mikael Hugo
705f9e2ba1 fix: queue user prompt as followUp when system turn is streaming
When the agent is already streaming (system-triggered turn, e.g. autonomous
dispatch at startup) and the user sends a message without an explicit
streamingBehavior, default to followUp instead of steer.

Steer injects mid-stream into the current turn. FollowUp queues the
message as a clean new turn after the system work finishes — which is
what the user expects when they type their first message at startup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 22:17:09 +02:00
Mikael Hugo
c391abe08d fix: remove internal API names from user-facing busy-agent error messages
Replace 'Use steer() or followUp()' with plain language guidance.
Users see this when sending a message while the agent is still working.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 22:04:34 +02:00
Mikael Hugo
d895cf2a16 fix: silence OpenTelemetry diag and LogTape meta startup warnings
- Align google-gemini-cli-provider's @google/gemini-cli-core dep from
  0.40.1 → 0.41.2 to match root; npm deduplicates to a single module
  instance, so diag.setLogger is called only once (no 'overwritten' warn)
- Add logtape.meta logger config at 'warning' level to suppress LogTape's
  own 'loggers are configured' info message on every startup

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 21:54:26 +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
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
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
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
e4c951ff0c feat: improve sf runtime self-reload and safeguards 2026-05-08 23:52:35 +02:00
Mikael Hugo
19bfc3d3f6 feat(sf): align node sqlite uok runtime 2026-05-08 03:01:20 +02:00
Mikael Hugo
b5893d1c28 Make SF direct command surface baseline 2026-05-08 01:34:07 +02:00
Mikael Hugo
6fc054e7c3 sf snapshot: uncommitted changes after 49m inactivity 2026-05-08 01:07:24 +02:00
Mikael Hugo
b0fce94f9e feat: record retrieval evidence across context tools 2026-05-07 18:17:41 +02:00
Mikael Hugo
b1a7749763 fix: harden widget and provider auth handling 2026-05-07 17:20:52 +02:00
Mikael Hugo
426fea7334 fix: reload sf source runtime on extension changes 2026-05-07 10:31:34 +02:00
Mikael Hugo
932f17b93a refactor: rename workflow tool boundary 2026-05-07 03:45:41 +02:00
Mikael Hugo
4cefa6de2a feat: persist SF runtime signals 2026-05-07 03:07:51 +02:00
Mikael Hugo
a2a44f8d15 feat: implement Tier 1.1 Vault secret resolver
- Create vault-resolver.js: URI parser, auth chain (env → file → AppRole), in-memory caching
- Add resolveConfigValueAsync() to pi-coding-agent for lazy vault URI resolution
- Integrate vault credential resolution into auth-storage credential loading path
- Add doctor check (checkVaultHealth) for vault setup validation at startup
- Document vault setup, auth methods, examples, troubleshooting in preferences-reference.md
- Add comprehensive test suite (18 tests) for vault URI parsing, auth, caching, fallback

Auth Chain:
1. VAULT_TOKEN env var (simplest for local dev)
2. ~/.vault-token file (recommended for local dev)
3. VAULT_ROLE_ID + VAULT_SECRET_ID env vars (AppRole for CI/CD)

Fail-open behavior: If vault unavailable, falls back to plaintext URIs to allow continued operation.

URI Format: vault://secret/path/to/secret#fieldname
Example: ANTHROPIC_API_KEY=vault://secret/anthropic/prod#api_key

Tests: parseVaultUri, isVaultUri, resolveSecret, caching, edge cases all passing (18/18).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 02:39:51 +02:00
Mikael Hugo
30f8738585 test: harden uok self-evolution paths 2026-05-06 22:55:35 +02:00
Mikael Hugo
8f6dbb30ff refactor(pi-coding-agent): update widget host tests to reflect degraded-silent behavior
- Rename tests to match actual behavior: degrades_silently / degrades_to_no_op
- Remove incorrect status-bar routing assertions from setWidget tests
- Add federated-memory module with test
2026-05-06 08:23:27 +02:00
Mikael Hugo
2e67b15ff9 sf snapshot: uncommitted changes after 39m inactivity 2026-05-06 08:15:40 +02:00
Mikael Hugo
76b218762b fix: harden sf autonomous runtime 2026-05-06 06:02:46 +02:00
Mikael Hugo
fbb61026fc fix: stabilize uok ledger and steering 2026-05-06 01:47:21 +02:00
Mikael Hugo
fec9292104 fix: stabilize uok parity and startup widgets 2026-05-06 00:56:55 +02:00
Mikael Hugo
87d49abd87 fix: stabilize sf startup and state linting 2026-05-05 19:46:08 +02:00
Mikael Hugo
46db1e95ef refactor: remove legacy autonomous aliases 2026-05-05 18:47:50 +02:00
Mikael Hugo
861c4b6cf6 fix: stabilize interactive extension startup 2026-05-05 18:42:00 +02:00