summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/config/loader.ts
AgeCommit message (Collapse)Author
2026-06-04chore: genesis — remove all files to rebuild from scratch (arch rewrite)Adam Malczewski
2026-06-03fix(config): emit local permission patterns after global ones in mergeAdam Malczewski
Gemini review caught a precedence-inversion bug in mergePermissions: when a nested permission group exists in BOTH global and local configs, the previous `{ ...existing, ...value }` spread updated an overridden pattern IN PLACE, leaving its original (global) insertion slot. Since configToRuleset flattens patterns in iteration order and evaluate() uses findLast (last match wins), a more-general global pattern declared lower (e.g. "*") would sit AFTER the local override and silently shadow it. Example: global bash { "npm test"=allow, "*"=ask } + local bash { "npm test"=deny } resolved "npm test" to "ask" instead of "deny". Fix: drop global patterns the local block also defines, keep remaining global patterns in order, then append ALL local patterns last — reproducing a clean "global rules then local rules" concatenation so local always wins. Adds a regression test asserting order and evaluation outcome.
2026-06-03feat(config): merge home-directory global dispatch.toml under project configAdam Malczewski
Load an optional global config at ~/.config/dispatch/dispatch.toml (override via DISPATCH_GLOBAL_CONFIG) and deep-merge it underneath every project/working-directory dispatch.toml, so machine-wide settings — most notably globally available LSP servers — work in any repo without per-repo config. Local always wins on conflicts. - loader: add getGlobalConfigPath(), loadGlobalConfig(), mergeConfigs(); loadConfig(dir) now loads+merges global. [lsp] and [[keys]] merge by id; [permissions] merge per-group with global patterns emitted first so local rules win at evaluation time (findLast). A malformed global config is downgraded to empty rather than breaking every repo. - watcher: watch BOTH global and local dispatch.toml so hot-reload re-merges on either change (dedupes when paths coincide). - export new loader fns from config/index and core index. - types/agent-manager: doc updates reflecting merged LSP resolution. - dispatch.toml: document global-default merge behavior; activate biome and typescript-language-server LSP entries. - tests: merge precedence, lsp/keys merge-by-id, permissions merge, filesystem integration, malformed-global resilience; isolate global path in existing loader tests.
2026-05-22feat: agent builder, CWD support, auto-save, UI polish, unavailable tool ↵Adam Malczewski
handling - Agent Builder: full CRUD with card grid, drag-and-drop model reorder, edit/delete - Auto-save on edit with 600ms debounce, AbortController for concurrency, fieldset disabled until name entered - Agent definitions stored as TOML with cwd field, loaded from global/project dirs - Working directory: per-tab CWD override in Chat Settings, agent default CWD, auto-create on first message - CWD validation: check-dir endpoint with ~ expansion, real-time validity indicator - Subagent CWD validated against parent's effective CWD using path.relative - Unavailable tool calls: caught gracefully, shown as tool call with error badge, model retries - UI: tab bar border radius, sidebar border removed, chat input ghost style, scroll-to-bottom rectangle - Skills dir collapse uses CSS rotation, Model Choice renamed to Chat Settings, System Prompt view removed - Reusable SkillsBrowser/ToolPermissions with external mode for Agent Builder - ModelSelector: Agent/Manual toggle, agent list, Agent Settings link - Page router, skills recursive scanning, bin/up gopass removed, docker volume mounts
2026-05-20feat: phase 3 — config, skills, model groups, task list, and sidebar UIAdam Malczewski
- Config system: TOML-based dispatch.toml with hot-reload via chokidar - Model/key resolution: tag-based model selection, key fallback chains - Skills system: directory loader with TOML frontmatter, agent mappings - Task list tool: add/update/list/get operations with WebSocket events - API routes: GET /config, /skills, /skills/:name, /models, /models/resolve - Frontend: sidebar with model status, task list, config viewer, skills browser, permission log - Sliding sidebar animation using CSS transitions (not Svelte transitions)
2026-05-19feat: Phase 2 — shell permissions, tree-sitter analysis, permission UIAdam Malczewski
Permission engine: - Rule-based engine: wildcard matching, last-match-wins, reject cascade - PermissionService with pending/approved state, PermissionChecker interface - dispatch.yaml config loader with per-permission pattern rules Shell tool: - run_shell tool with child_process spawn, timeout, streaming output - Tree-sitter static analysis (web-tree-sitter + tree-sitter-bash WASM) - BashArity command normalization for 'always allow' patterns - FILE_COMMANDS set: rm, cp, mv, mkdir, ls, find, grep, cat, etc. Agent loop refactored: - Removed maxSteps, manual step loop with tool execution - Permission checks on shell commands (external_directory only) - Permission checks on file tools outside workspace boundary - Symlink bypass fix (realpathSync), .. false positive fix - Shell output streaming via Promise.race + setImmediate polling API layer: - PermissionManager wraps PermissionService, broadcasts via WebSocket - WebSocket handles permission-reply messages from frontend - Config loaded from dispatch.yaml, converted to ruleset Frontend: - Permission prompt modal (native dialog, focus trap, ARIA) - Always-allow confirmation flow with pattern preview - Shell output display (live streaming + final parsed result) - Permission log panel (fixed bottom-right overlay) - Exit code badge (green 0, red non-zero) 134 tests, typecheck clean on all 3 packages