Documentation
    Preparing search index...

    Changelog

    All notable changes to this project will be documented in this file.

    • (core) Config schema for payload indexes, API key and sources
    • (core) Request/response schemas for public API endpoints
    • (service) Record processing failures as typed issues
    • (service) Shared embedding rate limiter with Retry-After
    • (service) API bearer auth, configured payload indexes, integration harness
    • (service) Source callback client
    • (service) Notification queue for source documents
    • (service) POST /documents, POST /documents/delete, source references on render/metadata/reindex
    • (service) Reindex scopes cover source documents
    • (sdk) @karmaniverous/jeeves-watcher-sdk 0.1.0
    • CLI and OpenClaw plugin send the API bearer key
    • Machine-readable error codes on API error responses
    • Harden delete filters, issue records and config schemas
    • (service) Bound embedding retries, payload index flags and callback size
    • (service) Harden source processing, reindex routing and shutdown
    • (cli) Report unreadable or malformed config patches cleanly
    • (service) Client-input errors are 4xx; reindex prepares once
    • One source-point predicate, redacted config apply, never-throwing reindex callback, separator-aware path scopes
    • (service) A failed Qdrant read is an error, never "not indexed"
    • (service) Issues reindex tolerates a failed stored-rule lookup
    • (service) Gemini requests the configured dimensions; init template uses 3072
    • (service) GET /config/schema derives from the core config schema
    • (service) Reindex plans group files by each watch root's static glob prefix
    • (service) Enrich --json accepts only a JSON object
    • (service) An over-limit Retry-After fails every caller fast until it has fully passed
    • (release) GitHub release notes and changelog use the new version tag
    • [256] fix(service): resolve file-based schemas against config dir in /config/validate

    validateInferenceRuleSchemas now receives deps.configDir and passes it to mergeSchemas, so relative global schema paths resolve against the config file's directory instead of process.cwd(). Adds regression tests for the resolved and missing-file cases.

    Closes #256. Part of #273 (S1). (#274)

    • Updated core
    • (service) Resolver layer for file and source documents; prune guard
    • (service) Split executeReindex by scope
    • One HTTP client contract in core; error status comes from the code
    • Shared reindex deps, defaults and work policy; admin route schemas; route handlers wrapped
    • Core owns defaults, limits and index-type guards; uniform route registrars
    • (service) One metadata write path, shared rule options, core defaults, one failure recorder
    • (service) Per-kind document behaviour, one hash, options object for embed-and-upsert
    • (service) Retried Qdrant writes, queue idle signals, one source-operations path for the notify queue
    • (service) Split app wiring below 300 lines; config warnings emitted once by loadConfig
    • (service) Source rules without file access, one render result, test-support wiring from production
    • (service) One render-result builder, no file reader for source rules, shared test Qdrant helpers
    • (service) One WatcherProcessor type, adapter for file-only processors, no source guards in the API
    • Source documents, notify API, auth, payload indexes, SDK
    • Typedoc covers core, sdk and service; fix docs warnings
    • Document review fixes, error bodies and status shape
    • (service) Verification citations for the review-2 test changes
    • (service) Configuration reference matches the config schema and runtime
    • (service) API reference matches the handlers
    • (service) Architecture and deployment guides match the code
    • (service) Inference rules, getting started and CLI reference match the code
    • (service) Source documents and version control guides match the code
    • Root README, CONTRIBUTING and package READMEs match the code
    • (core) StateDir description names values.v8
    • (service) VERIFICATION shutdown order and stray punctuation
    • Neutral example paths and names in guides, skill and tests
    • (service) Prettier formatting in api-reference
    • Harden integration harness collection hygiene
    • Integration lifecycle for source documents
    • Neutral example names; remove client wording from tests and docs
    • Provision a throwaway Qdrant for local test runs
    • Build the PDF extractor fixture with correct xref offsets
    • Route-wide auth, shared limiter, reload and deletion proofs
    • Harden throwaway Qdrant provisioning and harness guards
    • Split oversized suites and add module docs
    • VERIFICATION.md covers Decision 18 and the review fixes
    • Prove ingest embedding exhaustion, rate-limit defaults, notify concurrency and CLI key source
    • Rule handlers, plugin config tools, CLI helpers and edges
    • Reindex guards, prune retries, callback errors, source scopes, config-apply trigger, vcs edges
    • (service) Cover enrichment merge, prepare, rule errors, render stage, maps, failed deletes, file render fallbacks
    • (service) Cover limiter back-off cap, attempt override and config wiring, payload deletes, shutdown timeouts, queue stop
    • (service) Cover test Qdrant provisioning: global setup, binary download, binary and Docker start failures, sweep and URL guard
    • (service) Strengthen processor, source client, embedding, vector store and config tests
    • (service) Pin startup warnings to the console, reload reindex deps, stop order, PDF warning and load-time warning suppression
    • (service) Count embeddings, assert issues and AJV details, isolate integration cases, synchronous notify burst
    • (service) Keep documents-integration within 300 lines
    • (service) Split the rules engine suite into matching, set and JsonMap suites
    • Ship LICENSE in every package; core README and license metadata
    • Service resolves the SDK from the workspace, not as a dependency
    • Tsdoc config for core; real-git reconciliation tests get the suite's 30 s budget
    • [249] fix(vcs): resilient commit pipeline and squash guard (#249)

    • Detect "nothing staged" with git diff --cached --quiet instead of parsing git's "nothing to commit" text; empty batches are no-ops.

    • Partition each batch: add existing files, stage removal of tracked-but-missing files (git rm --cached --ignore-unmatch), drop missing untracked files. A missing path never fails the batch.

    • Reconcile tracked deletions in the watch scope at the end of the initial scan so the baseline commit records them.

    • Retry only index.lock contention (shouldRetry on util/retry).

    • Circuit breaker retains pending files and recovers on a time-based half-open attempt (vcs.circuitBreakerCooldownMs, default 5 min); state exposed per root in GET /vcs/status.

    • Pass -c core.longpaths=true on every VCS git invocation.

    • Squash refuses on in-progress sequencer/rebase/merge state or dirty tracked files, aborts a failed cherry-pick during cleanup, and stale state is reported at startup.

    • [249] refactor(vcs): address #251 review, SOLID/DRY pass and test hardening

    Review fixes:

    • Treat only ENOENT/ENOTDIR as "missing" when partitioning a batch; other stat errors propagate so the batch is retained and retried.
    • Re-queue a failed batch in full (no cap); flush commits the backlog in maxBatchSize chunks, so no chunk exceeds the batch size.
    • breaker.pendingCount includes files taken for an in-flight commit.
    • isIndexLockError requires "index.lock"; a bare EEXIST is not retried.
    • Narrow unknown rejection values via getErrorCode before reading code.

    Structure:

    • Extract CommitCircuitBreaker (pure, injectable clock), batchStaging (classify + stage), gitIndex (index ops), gitRepoState (stale ops, dirty tree, index.lock), watchScope (glob + ignored scope), cronMatch, and runGit (single pinned-argv git runner used by VcsManager, SquashManager, vcsBootstrap, CommitMessageBuilder and VCS handlers).
    • Fix /vcs/status lastCommit when the subject contains "|".

    Tests:

    • Split resilience tests into VcsManager.staging / VcsManager.breaker, squash guards into SquashManager.guards, coordinator reconciliation into its own file; shared fixtures in test/vcsRepo and test/squashRepo.
    • Replace the mocked cherry-pick failure (and its type cast) with a real merge-commit failure; drop the trivial 52s re-queue-cap test.
    • New unit tests: CommitCircuitBreaker, batchStaging, gitIndex, gitRepoState, retry, watchScope, cronMatch, SquashManager scheduler, vcsStatus.
    • [249] test(vcs): split oversized VcsManager, SquashManager and VCS handler test files

    Pure moves along existing describe boundaries; all 80 test names preserved.

    • VcsManager.test.ts (1275) -> VcsManager.{commitBasics, lifecycle, lockHandling, circuitBreaker, messages, aiMessages, remotePush}.test.ts
    • SquashManager.test.ts (460) -> SquashManager.{retention, mechanism, pushAndPause}.test.ts
    • api/handlers/vcs/vcs.test.ts (793) -> vcs{Status, History, Show, Diff, CheckExclusion, Revert, Exclude}.handler.test.ts
    • Shared fixtures: test/vcsHandlers.ts (mock reply, repo + coordinator setup); test/vcsRepo.ts gains makeFastVcsConfig.
    • Drop a gitIndex timeout test that raced a 1 ms timer against git and flaked under parallel load.
    • [249] test(vcs): make pathKey test independent of host OS

    resolve() follows the host platform, so a Windows drive path is relative on Linux. Test lowercasing with a path absolute on both; run the backslash case on Windows only.

    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.19.1
    • [234] updated jeeves
    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.19.0
    • [234] chore(deps): pin @karmaniverous/jeeves 0.6.0-9
    • [234] updated core
    • [234] chore: release @karmaniverous/jeeves-watcher v0.19.0-3
    • [234] [244] fix(service): make git network calls non-interactive

    Route push and squash force push through execGitNetwork: -c credential.helper= plus GIT_TERMINAL_PROMPT=0, GCM_INTERACTIVE=never, GIT_ASKPASS/SSH_ASKPASS=echo, so system/global credential helpers (Git Credential Manager) can never block. Tests use loopback 127.0.0.1:9 instead of github.com / invalid.example.com.

    • [234] [244] fix(service): clear credential helpers only for injected tokens; drop-at-once test remote

    Adopt findings from the parked w243 attempt: always -c core.askPass= with empty GIT_ASKPASS/SSH_ASKPASS, GIT_TERMINAL_PROMPT=0, GCM_INTERACTIVE=never; reset credential.helper only when a token is injected so stored credentials still work. gitPushNonInteractive centralises push URL + policy (SquashManager 471 -> 468 lines). Tests use a local TCP server that drops connections (~ms) instead of 127.0.0.1:9 (~2 s on Windows).

    • [234] [245] fix(service): keep the access token off the git command line and out of errors

    Send the token to git as a URL-scoped http..extraHeader (Basic x-access-token) via GIT_CONFIG_COUNT/KEY/VALUE env for that push only, instead of embedding it in the push URL (which Node echoes in exec error messages/cmd, reaching logs and pushErrors / GET /vcs/status). Credential helpers are still cleared when a token is used (#244). Defence in depth: sanitizeGitError redacts raw, URL-encoded and base64 forms from message, stack, cmd, stderr and stdout. Remove buildAuthenticatedPushUrl.

    Closes #245

    • [234] chore(deps): pin @karmaniverous/jeeves 0.6.0-8
    • [234] updated core
    • [234] test(vcs): make git tests hermetic (ignore system credential helpers)
    • [234] Merge branch 'feature/234-core-060-lazy-config-root' of https://github.com/karmaniverous/jeeves-watcher into feature/234-core-060-lazy-config-root
    • [234] chore: release @karmaniverous/jeeves-watcher v0.19.0-2
    • [234] fix: tests and typecheck read watcher-core from source, not dist

    Service and openclaw vitest configs alias @karmaniverous/jeeves-watcher-core to packages/core/src, and their tsconfigs map it via paths, so typecheck and tests pass on a clean checkout with no dist/. Rollup builds override paths ({}) so bundling and typing still use the built core package with no TS warnings. Root npm test now also runs the openclaw package tests.

    Closes #242

    • [234] chore: update root package-lock in release-it after:bump hooks
    • [234] fix(deps): require watcher-core ^0.2.6-0 (no fallback to 0.2.5)
    • [234] [243] test(service): warm Fastify cold start in hooks, close apps

    The first onRulesChanged test paid Fastify's lazy require of ~250 CJS modules (ajv-compiler/ajv/fast-json-stringify), light-my-request's lazy load on first inject(), and the first ajv rule compile inside its 5s test budget, which timed out on a slower Windows machine during release:pre.

    Warm the full register path in beforeAll, close every app in afterEach, and drop the unneeded 50ms settle sleeps (executeReindex is invoked synchronously by the handler). Apply the same warm-up and server close to integration.test.ts.

    Closes #243

    • [234] chore: release @karmaniverous/jeeves-watcher v0.19.0-1
    • [234] chore(deps): ncu --peer across all packages (keep @karmaniverous/jeeves pinned)

    • [234] chore(deps): audit fix, transitive overrides, hold extra-typings@14, drop @types/js-yaml

    • npm audit fix, then overrides for type-only transitive chain of mdast-util-from-adf (linkify-it ^5.0.2, uuid ^14.0.2); lockfile regenerated so overrides apply

    • @commander-js/extra-typings held at ^14: peer-coupled to commander 14 used by @karmaniverous/jeeves 0.5.x (held via --reject)

    • @types/js-yaml removed: js-yaml 5 ships its own types

    • [234] fix: migrate vector search to Qdrant query API; drop meaningless void operators

    • @qdrant/js-client-rest 1.19 removed QdrantClient.search; use client.query (same params, results in .points)

    • typescript-eslint 8.70 no-meaningless-void-operator: remove unused params instead of voiding them

    • [234] chore: knip and prettier clean-up

    • knip 6.38: remove unused barrel re-exports and a stale backward-compat re-export (no public API change)

    • prettier 3.9 formatting; add .prettierignore for generated CHANGELOGs, config.schema.json and .stan state

    • [234] feat!: move core and service to @karmaniverous/jeeves 0.6.0-4

    Drop the v0.x workspace-writer descriptor fields (sectionId, refreshIntervalSeconds, generateToolsContent) removed in core 0.6.

    • [234] chore(service): update @commander-js/extra-typings to 15

    Unblocked by core 0.6.0-4 (commander 15).

    • [234] chore(build): zero build and typedoc warnings

    • service: drop tsconfig incremental (made the rollup configPlugin warn about outputToFilesystem); mark node: builtins external in the d.ts build.

    • openclaw: drop only bundled-zod INVALID_ANNOTATION / node_modules-only CIRCULAR_DEPENDENCY rollup warnings.

    • service: export SquashManagerOptions (typedoc referenced it).

    • [234] chore(deps): pin @karmaniverous/jeeves 0.6.0-6

    • [234] fix(release): use --github.preRelease for release-it 21

    • [234] refactor(service): migrate EnrichmentStore to node:sqlite

    Replace better-sqlite3 with the built-in node:sqlite DatabaseSync. Behaviour and EnrichmentStoreInterface are unchanged (WAL, busy_timeout 5000, startup wal_checkpoint(TRUNCATE) busy warning, schema, path normalisation, merge-on-set, atomic move). Adds a fixture written by the better-sqlite3 13.0.3 build and a test proving it opens, reads and updates correctly. Externalise node: built-ins in the service rollup library/CLI builds (matches jeeves-runner) so node:sqlite does not warn as unresolved. Refs #237.

    • [234] chore(deps): remove better-sqlite3

    Drop better-sqlite3 and @types/better-sqlite3 from packages/service and the better-sqlite3 entry from root allowScripts. Docs: note node:sqlite (no native build) and align stale Node 20+ prerequisites with engines >=22. Closes #237.

    • [234] fix: post-e2e fixes for core 0.6 (#238, #239, #240, #241)

    • deps: openclaw/service depend on watcher-core ^0.2.5 || ^0.2.6-0 so the core-0.6 prerelease resolves (#238)

    • service: pin @qdrant/js-client-rest ^1.19.0; real-QdrantClient regression test for POST /search (#239)

    • service: /config/apply merges into the running config file and deep-merges patches (#240)

    • engines.node >=22.13 everywhere; docs say 22.13+ (#241)

    • [234] chore(deps): pin @karmaniverous/jeeves 0.6.0-7

    • [234] chore: release @karmaniverous/jeeves-watcher v0.19.0-0

    • Use named imports for js-yaml (closes #232)
    • Release @karmaniverous/jeeves-watcher v0.18.12
    • [224] fix: append /** to bare directory watch paths (fixes #224)

    • [230] fix: squashmanager compound defect (#230)

    • Bug 1: Use configured branch name instead of dynamic git branch detection

    • Bug 2: Restart throttle timer after commit failure so re-queued files retry

    • Bug 3: Pause/resume coordination between SquashManager and VcsManager

    • Bug 4: Add timeouts to all git operations (30s standard, 120s cherry-pick, 60s push)

    • Bug 5: Exclude "nothing to commit" from circuit breaker failure count

    • Bug 6: Startup orphan branch detection and recovery

    Adds branch field to VcsConfig schema (default: "master"). SquashManager now pauses VcsManager commit pipeline during squash. All execFileAsync and gitAddViaStdin calls have explicit timeouts.

    Fixes #230

    • [230] refactor: SOLID/DRY pass on VCS subsystem (#230)

    • Extract GIT_TIMEOUT_STANDARD/CHERRY_PICK/PUSH constants from magic numbers

    • Extract buildAuthenticatedPushUrl() โ€” eliminates duplicate token-URL construction in vcsPush.ts and SquashManager.forcePushIfConfigured()

    • Extract getExecErrorFields() โ€” shared error field extraction replaces duplicate unsafe casts in isIndexLockError() and isNothingToCommitError()

    • Convert SquashManager constructor from 8 positional params to (rootPath, retention, logger, options?) pattern

    • [230] test: close coverage gaps for #230 utilities and error paths

    • Unit tests for getExecErrorFields() (ExecFileException fields, plain Error, non-Error values, non-string properties)

    • Unit tests for buildAuthenticatedPushUrl() (no token, undefined token, HTTPS injection, special chars, SSH URLs, file:// URLs)

    • VcsManager.start() error resilience: orphan recovery throws โ†’ logs error โ†’ manager continues and commits normally

    • [230] docs: sync guides and README with #230 code changes

    • Add branch field to VCS config tables and JSON examples in configuration.md, version-control.md, and service README

    • Document pause/resume coordination in squash mechanism

    • Document startup orphan branch detection and recovery

    • Document "nothing to commit" handling and retry timer after failure

    • Document git operation timeouts (30s/120s/60s)

    • Add troubleshooting entries: wrong branch after crash, git timeouts

    • [230] fix: call resumeCommits when pauseCommits throws (#230)

    If pauseCommits() threw after partially executing (e.g., flush succeeded but the flag wasn't set), runSquash() returned early without reaching the finally block that calls resumeCommits(). This could leave the commit pipeline permanently paused.

    Add resumeCommits() call in the pause-failure catch block. Resume is safe to call even if the pipeline isn't actually paused.

    Addresses Copilot review comment on PR #231.

    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.18.11
    • Add shared endpoint catalog in core package (#196)
    • Replace VCS commit debounce with throttle (#221)
    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.18.10
    • (vcs) Add stale lock detection, circuit breaker, and re-queue cap (#219)
    • (app) Thread VCS callbacks through config reload (#218)
    • (vcs) Apply retention defaults when retention config is omitted (#216)
    • (api) Prune incomplete-result safety and retry improvements (#182)
    • Address PR #220 review โ€” error handling, circuit breaker, case sensitivity, and test determinism
    • Address Copilot review โ€” error handling, circuit breaker reset, Windows case sensitivity, test determinism
    • Updated core
    • Lint fix
    • Update VCS and prune documentation for new features
    • (api) Rewrite computePrunePlan with filter-first approach (#187)
    • Release @karmaniverous/jeeves-watcher v0.18.9
    • (vcs) Eliminate redundant baseline enumeration (#214)
    • (vcs) Address review โ€” flush race, JSDoc, LOC decomposition
    • Release @karmaniverous/jeeves-watcher v0.18.8
    • Release @karmaniverous/jeeves-watcher v0.18.7
    • Use stdin-based git add to avoid ENAMETOOLONG (#211)
    • (vcs) Handle EPIPE on gitAddViaStdin stdin writes
    • Release @karmaniverous/jeeves-watcher v0.18.6
    • Declarative VCS git identity config (#209)
    • Address Copilot review comments on PR #210
    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.18.5
    • Case-insensitive VCS path matching on Windows + baseline commit for pre-existing files
    • Address Copilot review - baseline skips AI, isBaseline persists across batches, null-byte ls-files, injectable platform
    • Release @karmaniverous/jeeves-watcher v0.18.4
    • (vcs) Extract static roots from glob watch paths instead of skipping
    • Release @karmaniverous/jeeves-watcher v0.18.3
    • Installed deps
    • Release @karmaniverous/jeeves-watcher v0.18.2
    • Increase VCS test timeouts from 15s to 30s
    • Increase timeout for VCS tests that create real git repos
    • Release @karmaniverous/jeeves-watcher v0.18.1
    • (vcs) Phase 1 โ€” foundation (config schema, watch.paths, startup checks)
    • (vcs) Phase 2 โ€” commit pipeline (debounce, batch, git commit)
    • (vcs) Phase 3 โ€” read API (status, history, show, diff, check-exclusion)
    • (vcs) Phase 4 โ€” write API (revert, exclude)
    • (vcs) Phase 5 โ€” AI-generated commit messages
    • (vcs) Phase 6 โ€” remote push after commit
    • (vcs) Phase 7 โ€” squash retention on schedule
    • (vcs) Gateway credential fallback for AI commit messages (D6)
    • Export VCS types + fix typedoc anchor
    • Address Copilot review comments
    • Updated core
    • (vcs) SOLID/DRY pass โ€” extract shared utilities, separate bootstrap from runtime
    • (vcs) Phase 9 โ€” skill, README, code comments, TOOLS.md
    • (service) VCS guide + cross-references in all service guides
    • (vcs) Dedicated unit tests for gitExec, vcsBootstrap; cron edge case
    • Release @karmaniverous/jeeves-watcher v0.18.0
    • [0-18] chore: update dependencies

    Pin ajv to ~8.18.0 to avoid type mismatch with @fastify/ajv-compiler. Remove unused hast dependency. Fix knip config and stan integration.

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: case-insensitive path matching on Windows (#199)

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: pass offset through hybrid search path (#200)

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: eliminate double collection scroll on live prune (#182)

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: batch embedding calls to respect Gemini 100-doc limit (#186)

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] style: add missing JSDoc offset param + fix stale test module doc
    • [0-18] test: add offset-zero edge case for hybridSearch (#200)
    • [0-18] docs: fix stale prune response and collection bootstrap claims in guides
    • [0-18] chore: update dependencies

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: consume substituteEnvVars from jeeves core (#202)

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [0-18] fix: sort imports and revert ajv bump for fastify compat

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • Updated core
    • Release @karmaniverous/jeeves-watcher v0.17.11
    • Pin jeeves-watcher-core dependency to ^0.1.1
    • Release @karmaniverous/jeeves-watcher v0.17.10
    • Extract core package with shared schemas, types, defaults, and constants
    • Add npm publish safety net (.npmignore + gitignore *.local)
    • Move changelog generation to after:bump hook
    • Update all deps, switch core to rollup build, fix lint errors
    • Release @karmaniverous/jeeves-watcher v0.17.9
    • Updated jeeves core
    • Release @karmaniverous/jeeves-watcher v0.17.8
    • Updated jeeves core
    • Release @karmaniverous/jeeves-watcher v0.17.7
    • Updated jeeves-core
    • Release @karmaniverous/jeeves-watcher v0.17.6
    • Release @karmaniverous/jeeves-watcher v0.17.5
    • Unhoisted jeeves
    • Release @karmaniverous/jeeves-watcher v0.17.4
    • Hoisted jeeves
    • Hoisted knip
    • Release @karmaniverous/jeeves-watcher v0.17.3
    • Housekeeping batch (#184, #179, #176, #180, #178)
    • Release @karmaniverous/jeeves-watcher v0.17.2
    • Update deps for @karmaniverous/jeeves-core v0.5.3
    • Release @karmaniverous/jeeves-watcher v0.17.1
    • Bump core to ^0.5.1, engine floor >=22, adopt getPackageVersion
    • Add fetchSiblings built-in JsonMap helper for contextual embedding
    • Remove unused JSON_TEXT_FIELDS export (knip)
    • Break circular dependencies, clean knip config
    • Adopt core createConfigApplyHandler for /config/apply
    • Adopt core DEFAULT_PORTS for port constants
    • SOLID/DRY pass across codebase
    • Update skill, READMEs, and diagrams for v0.17.0
    • Sync all documentation and diagrams with implementation
    • Release @karmaniverous/jeeves-watcher v0.17.0
    • [CORE-046] feat: integrate core 0.4.6 โ€” init() called before descriptor.run()

    Bumps @karmaniverous/jeeves to 0.4.6 which fixes karmaniverous/jeeves#53: createServiceCli now calls init() before descriptor.run() in the start command, so getBindAddress() and other core functions that require initialization work correctly.

    This unblocks upgrading prod from 0.15.2 to the current release.

    • Release @karmaniverous/jeeves-watcher v0.16.3
    • [CORE-045] feat: integrate core 0.4.5 - add run callback to descriptor
    • Release @karmaniverous/jeeves-watcher v0.16.2
    • [PHASE-2] fix: resolve package root for bundled CLI entry point

    The descriptor used import.meta.url-relative paths for package.json and startCommand, which broke after Rollup bundled descriptor.ts into dist/cli/jeeves-watcher/index.js (3 levels deep instead of 1).

    Fix: walk up from current file to find the package root by name, then resolve all paths from there.

    • [PHASE-2] fix: use package-directory for robust package root resolution

    Replace hand-rolled directory walk with packageDirectorySync from package-directory (already a core dependency). Fixes bundled CLI crashing with Cannot find module errors when import.meta.url-relative paths resolve incorrectly after Rollup bundling.

    Added package-directory as direct dependency of service package.

    • Release @karmaniverous/jeeves-watcher v0.16.1
    • [PHASE-0] [#161] fix: catch async rejection in onRulesChanged instead of swallowing it

    The buildTemplateEngineAndCustomMapLib promise was fire-and-forget with void, silently discarding rejections. Replace with explicit .catch() that logs the error so failures are visible and diagnosable.

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [PHASE-0] [#159] fix: add try/catch to facets handler for config and schema errors

    getConfig() and buildFacetSchema() can throw on malformed inference rule configs. Wrap both in try/catch to return graceful error responses instead of crashing the endpoint.

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [PHASE-0] [#162] fix: batch embedAndUpsert to prevent OOM on large files

    embedAndUpsert previously sent all chunk points in a single upsert call, causing OOM on large files. Add configurable batch size (default 50) and loop upserts in batches. Includes tests for batching behavior.

    Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

    • [PHASE-0] fix: improve Phase 0 fixes - add tests, graceful facets degradation, waitForIdleWorkers

    • [PHASE-0] fix: guard upsertBatchSize against zero/negative (Gemini review)

    • [PHASE-1] feat: config path migration to jeeves-watcher/config.json (#149)

    • [PHASE-1] fix: address Gemini review - log migration errors, remove unused resolveConfigDir

    • [PHASE-2] feat: core 0.4.4 + Zod 4, dep updates, descriptor definition

    • Bump @karmaniverous/jeeves to ^0.4.4 (Zod 4)

    • Update all deps not blocked by peer constraints (eslint 10, knip 6, vitest 4.1.2, etc)

    • Fix ESLint 10 new rules: no-useless-assignment, preserve-caught-error

    • Rewrite watcherComponent.ts to return clean JeevesComponentDescriptor

    • Add descriptor.ts + descriptor.test.ts (Phase 2 D2)

    • Remove unused PROBE_TIMEOUT_MS export

    • Update writerIntegration test for core managed-content position change

    • [PHASE-2] [PHASE-3] feat: replace hand-rolled CLI with createServiceCli factory (S1)

    • Replace CLI entrypoint with createServiceCli(watcherDescriptor)

    • Consolidate 7 custom commands into customCommands.ts

    • Wire customCliCommands on the descriptor

    • Delete 17 dead CLI files (commands, helpers, wrappers)

    • Rewrite CLI tests for new structure

    • Resolve all knip findings:

      • Remove unused isQdrantAvailable export
      • Remove unused migrateConfigPath/MigrateConfigResult re-exports
      • Make BinaryFileStoreOptions interface non-exported
    • [PHASE-2] [PHASE-3] feat: adopt core status handler + getBindAddress (S2/S3)

    • Replace /status handler with core createStatusHandler factory

      • Watcher-specific health data (collection, reindex, initialScan) moved to getHealth callback
      • Response shape now follows core StatusResponse convention
    • Adopt getBindAddress('watcher') for service bind address (S3)

    • Keep watcher-specific /config/apply handler (core factory assumes config-init semantics that don't fit the live-config/reindex model)

    • [PHASE-2] refactor: SOLID/DRY review โ€” extract shared patterns, consolidate constants

    DRY fixes in customCommands.ts:

    • Extract withApiOptions helper (eliminates 7x repeated --port/--host options)
    • Extract handleErrors wrapper (eliminates 7x identical try/catch blocks)
    • Extract parseMetadataArgs (enrich command validation logic)
    • Extract baseUrl helper accepting ApiOpts interface

    DRY fixes in plugin constants:

    • Extract COMPONENT_NAME, SERVICE_PACKAGE, PLUGIN_PACKAGE, DEFAULT_PORT
    • watcherComponent.ts now references constants instead of hardcoded strings
    • DEFAULT_API_URL derived from DEFAULT_PORT

    Cleanup:

    • Remove stale Phase 3/4 placeholder comments from descriptor.ts
    • Add descriptive comments explaining why onConfigApply and generateToolsContent are wired at different layers
    • Remove accidentally committed commit-msg.txt, add to .gitignore
    • [PHASE-2] test: improve coverage for touched code, remove trivial and dead tests

    descriptor.test.ts:

    • Add tests for customMerge (verifies name-based rule merging)
    • Add test for customCliCommands (verifies all 7 commands registered)
    • Add test for initTemplate (returns config skeleton)
    • Add test for startCommand (produces valid node invocation)
    • Remove trivial "returns empty plugin tool list in Phase 2" test

    customCommands.test.ts:

    • Add helpers command tests (format output, no-helpers message)
    • Add enrich --key flag parsing test
    • Add enrich invalid JSON rejection test
    • Add custom --host/--port test
    • Add scan body verification (filter, limit, countOnly, fields splitting)
    • Add reindex multi-path array test
    • Strengthen rebuild-metadata and issues tests to verify response output
    • Parse and assert request bodies instead of using loose string contains

    Dead code removal:

    • Delete handlers/status.ts (replaced by core createStatusHandler in api/index.ts)
    • Delete handlers/status.test.ts (tested dead code)
    • [PHASE-2] docs: sync all documentation with current implementation

    CLI reference (guides/cli-reference.md) โ€” full rewrite:

    • Remove stale commands: query, config-reindex, config-apply, validate (standalone)
    • Document current CLI structure: core standard commands + domain-specific commands
    • Add service start/stop/restart/status subcommands
    • Document config/config validate/config apply subcommand structure

    SKILL.md:

    • Update /status response description for core StatusResponse shape (health.collection.pointCount instead of collection.pointCount)
    • Fix vectorStore config example: collection โ†’ collectionName
    • Update watcher_status tool description

    Delete dead status handler:

    • handlers/status.ts replaced by core createStatusHandler in api/index.ts

    • handlers/status.test.ts tested dead code

    • [PHASE-2] docs: align guide index structure with jeeves-server pattern

    • Add CHANGELOG to children front matter in both index files

    • Add descriptive list body to service and plugin guide indexes

    • Individual guides already have title front matter

    • Release @karmaniverous/jeeves-watcher v0.16.0
    • Linux CI compatibility โ€” cross-platform path test and skip integration tests without Qdrant
    • [153] fix: use getter for fileSystemWatcher in API handlers (#153)
    • [153] test: simplify walk rebuild getter test
    • [152] fix: EnrichmentStore SQLite recovery on startup (#152)
    • [152] fix: address PR review feedback on #152
    • [151] perf: ValuesManager binary serialization and debounced flush (#151)
    • [151] refactor: address PR review feedback on #151
    • [150] fix: QdrantClient write path leaks undici Agents (#150)
    • [150] refactor: address PR review feedback on #150
    • [120] fix: pause event queue during prune to prevent ECONNRESET under load
    • [120] fix: ensure queue resumes on all error paths (Gemini review)
    • [120] fix: drain in-flight queue work before prune scroll
    • Release @karmaniverous/jeeves-watcher v0.15.2
    • Release @karmaniverous/jeeves-watcher v0.15.1
    • Add full hot-reload with watcher rebuild on config change (#113)
    • Close EnrichmentStore on shutdown (#145), fix schema path resolution in metadata validation (#116)
    • Replace captured config with getter pattern in API handlers (#144, #146)
    • Convert remaining captured config refs to getters in status, render, walk, search handlers (SOLID/DRY)
    • Cache compiled rules in configMatch handler, invalidate on config change
    • Un-export unused types flagged by knip
    • Release @karmaniverous/jeeves-watcher v0.15.0
    • Extend interfaces for move detection and enrichment store
    • Add EnrichmentStore and composable merge utility
    • Add ContentHashCache for move detection
    • Add MoveCorrelator and wire into FileSystemWatcher
    • Implement DocumentProcessor.moveFile for zero-embedding moves
    • Wire EnrichmentStore into processor, remove sidecar metadata system
    • Remove trivial tests, add move pipeline integration tests
    • Release @karmaniverous/jeeves-watcher v0.14.0
    • Upgrade @karmaniverous/jeeves to ^0.3.0
    • Release @karmaniverous/jeeves-watcher v0.13.0
    • Adopt @karmaniverous/jeeves core v0.2.0 SDK (#138) (#138)
    • Release @karmaniverous/jeeves-watcher v0.12.0
    • Release @karmaniverous/jeeves-watcher v0.11.1
    • Add tagPrefix to auto-changelog config for monorepo tags
    • Sync documentation with implementation, replace Mermaid/ASCII with PlantUML diagrams
    • Release @karmaniverous/jeeves-watcher v0.11.0
    • [FIX-122] fix: use chokidar getWatched() for /walk endpoint instead of filesystem traversal

    Closes #122

    • Use path.join() for getWatchedFiles path construction
    • Release @karmaniverous/jeeves-watcher v0.10.1
    • (watcher) Add initial scan statistics logging
    • Use package-directory for version resolution in /status
    • [V0_10_0] feat: add scope validation, rules and path reindex scopes (Fixes 1, 2, 13)

    • Validate reindex scope against VALID_REINDEX_SCOPES; reject unknown scopes with 400

    • Add 'rules' scope: re-applies inference rules via processRulesUpdate without re-embedding

    • Add 'path' scope: reindex a specific file or directory with watch scope and gitignore validation

    • Update configWatchConfigSchema to accept 'rules'

    • Update watcher_reindex plugin tool with new scopes and optional path parameter

    • Broaden triggerReindex type to ReindexScope across configApply and API index

    • [V0_10_0] fix: wire gitignore filter into reindex path, support standalone .gitignore (Fixes 3, 4)

    • Thread GitignoreFilter through ExecuteReindexDeps to processAllFiles/listFilesFromGlobs

    • listFilesFromGlobs now accepts optional isGitignored callback

    • GitignoreFilter.scan() falls back to standalone .gitignore at watch root when no .git dir

    • createWatcher now returns { watcher, gitignoreFilter } for API server threading

    • All executeReindex call sites pass gitignoreFilter

    • [V0_10_0] fix: return actionable error details from wrapHandler, fix withCache payload capture (Fixes 7, 9)

    • wrapHandler now returns { error: className, message: actualMessage } instead of generic 'Internal server error'

    • withCache intercepts reply.send() to capture response payload for caching

    • On cache hit, withCache sends the captured payload via reply.send()

    • Fix 8 (watcher_enrich 500) deferred to runtime diagnosis with improved error messages

    • [V0_10_0] feat: version in /status, live scoreThresholds, virtual rule template rebuild, remove dead config keys (Fixes 6, 10, 12)

    • Add version field to /status response (read from package.json at startup)

    • Plugin reads search.scoreThresholds from config via /config/query, falls back to defaults

    • Score interpretation includes actionable guidance (strong/relevant/noise)

    • onRulesChanged rebuilds template engine with merged rules (config + virtual)

    • Remove slots and extractors from root config schema (dead keys)

    • Remove slots from merged virtual document

    • Fix 11 (port fallback) already resolved in prior version โ€” no 3456 reference found

    • [V0_10_0] test: fix mock dependencies and test assertions for reindex and cache handlers

    • [V0_10_0] chore: fix lint errors in promptInjection, clean up knip config, regenerate schema

    • [V0_10_0] fix: replace brittle glob parsing in path reindex with full file list + directory filter

    Address Gemini code review: directory-scoped path reindex now lists all watched files via listFilesFromGlobs then filters to the target directory, instead of attempting to parse and reconstruct glob patterns with a regex.

    • [FIX-14] feat: prune reindex scope, blast area plan, dryRun (Fix 14)

    • Add 'prune' reindex scope: scrolls Qdrant points, checks file_path against watch scope + gitignore, batch-deletes orphaned points

    • Add blast area 'plan' object to all reindex responses (counts by root)

    • Add dryRun parameter: returns plan without executing

    • Thread vectorStore into ExecuteReindexDeps for prune access

    • Refactor processAllFiles to accept pre-computed file list

    • Guard configWatch auto-trigger against prune scope

    • Add CONFIG_WATCH_VALID_SCOPES constant

    • Update plugin tool: prune in scope enum, dryRun parameter

    • Tests: dryRun per scope (issues/full/rules/prune), prune execution

    Closes Phase 6 of spec dev plan.

    • [FIX-14] docs: update all guides for reindex scopes, dryRun, plan, and version

    • api-reference.md: /config-reindex now documents all 5 scopes, dryRun, plan response shape; /status includes version field; error response includes error+message fields

    • cli-reference.md: config-reindex documents all scopes, --path, --dry-run

    • configuration.md: configWatch.reindex includes rules scope, notes path/prune exclusion

    • inference-rules.md: config watch reindex table adds rules scope, notes path/prune exclusion

    • README.md: updated API and CLI tables for all scopes

    • openclaw README.md: updated watcher_reindex description

    • SKILL.md: already updated in previous commit (#118)

    • [FIX-15] feat: initial scan visibility + prune scroll resilience (Fixes 15+16)

    Fix 15 - Initial Scan Visibility:

    • Add InitialScanTracker with start/setMatched/incrementProcessed/complete
    • Thread tracker through app init -> FileSystemWatcher -> status handler
    • /status now includes initialScan: { active, filesMatched, filesProcessed, startedAt, completedAt, durationMs }

    Fix 16 - Prune Scroll Resilience:

    • Add scrollPageWithRetry: per-page retry with exponential backoff (3 attempts, 1s base) and cursor-based resume on connection failure
    • Reduce prune scroll page size from 1000 to 500
    • Add incomplete flag to ReindexPlan for partial results on exhausted retries
    • Refactor computePrunePlan to use page-by-page scroll instead of async generator (enables retry/resume per page)
    • [FIX-15] fix: rename initialScan.filesProcessed to filesEnqueued for clarity

    The field tracks files enqueued to the processing queue during scan, not files that completed processing. Rename avoids misleading operators.

    • [FIX-15] docs: add initialScan to api-reference and SKILL.md

    • api-reference.md: initialScan fields in /status response + table

    • SKILL.md: watcher_status documents initialScan field, diagnostics updated

    • [FIX-17][FIX-18][FIX-19] feat: API Consolidation (Phase 8)

    • Convert POST /config/query to GET /config with unified inference rules

    • Rename watcher_query to watcher_config tool

    • Rename POST /config-reindex to POST /reindex with array path support

    • Update CLI, plugin, and tests to match

    • [FIX-17] [FIX-20][FIX-21] Phase 9: POST /walk endpoint, watcher_walk tool, auto rules-reindex on rule registration

    Fix 20:

    • New POST /walk handler: accepts { globs: string[] }, walks watch roots with glob intersection, returns { paths, matchedCount, scannedRoots }
    • Route registered in api/index.ts
    • New watcher_walk OpenClaw tool in watcherTools.ts
    • Tests: walk handler (4 tests), plugin tool registration + execution

    Fix 21:

    • onRulesChanged now extracts match globs from virtual rules (match.properties.file.properties.path.glob) and fires executeReindex with scope 'rules' and extracted globs array (fire-and-forget)
    • Skips reindex when no rules have match globs
    • Tests: 3 integration tests via Fastify inject

    Docs:

    • SKILL.md: added watcher_walk docs, updated API reference table (POST /walk, renamed endpoints from Phase 8), renamed watcher_query references to watcher_config, noted auto-reindex on rule registration

    Quality gates: 492 service tests, 28 plugin tests, zero lint/typecheck/knip errors.

    • [FIX-17] [FIX-19] fix: rename CLI config-reindex to reindex, fix stale doc refs, clean watch.ignored
    • [FIX-17] [FIX-19] fix: consolidate CLI reindex commands, fix scope validation, update dev plan
    • [FIX-17] [REFACTOR] DRY/SOLID pass: extract helpers, consolidate walk functions, separate onRulesChanged
    • [FIX-17] [TEST] Add missing test coverage: fileScan walk functions, extractMatchGlobs, rules+path reindex, createIsGitignored
    • [FIX-17] [DOCS] Resolve all docs warnings and root-level knip issues
    • [FIX-17] chore: gitignore generated docs directories
    • [FIX-17] chore: remove changelogs (generated at build time)
    • Release @karmaniverous/jeeves-watcher v0.10.0
    • [114] fix: add nocase to fileScan picomatch calls (#114)
    • Release @karmaniverous/jeeves-watcher v0.9.8
    • Release @karmaniverous/jeeves-watcher v0.9.9
    • [107] fix: remove HTML escaping from renderDoc markdown output

    renderValueAsMarkdown was passing string values through hbs.Utils.escapeExpression(), which HTML-encodes backticks, angle brackets, quotes, and ampersands. Since renderDoc produces markdown (not HTML), this corrupted fenced code blocks, PlantUML diagrams, and any content containing special characters.

    The fix returns string values as-is and defers HTML escaping to the downstream markdown-to-HTML renderer (jeeves-server's marked pipeline).

    Fixes #107

    • Release @karmaniverous/jeeves-watcher v0.9.7
    • Support glob/negation patterns in render.frontmatter
    • Release @karmaniverous/jeeves-watcher v0.9.6
    • Add concurrent file processing for reindex using radash parallel
    • Release @karmaniverous/jeeves-watcher v0.9.5
    • (service) Use node:https with keep-alive agent for Gemini API
    • Release @karmaniverous/jeeves-watcher v0.9.4
    • (service) Replace LangChain Gemini wrapper with direct API calls
    • Release @karmaniverous/jeeves-watcher v0.9.3
    • (service) Skip live value aggregation for non-enumerated facet uiHint types
    • Release @karmaniverous/jeeves-watcher v0.9.2
    • Release @karmaniverous/jeeves-watcher v0.9.0
    • (service) Add POST /scan handler with cursor-based pagination
    • (service) Clean up scan handler and test lint issues
    • (service) Extract scrollPage/count helpers, eliminate DRY violations
    • (service) Add TypeDoc for scrollPage return type fields
    • Add POST /scan and POST /rules/reapply to all documentation
    • Format scrollPage return type
    • Release @karmaniverous/jeeves-watcher v0.9.0-0
    • (values) Decompose array metadata into individual trackable elements
    • (facets) Reject object-type properties as facets, validate uiHint types
    • (test) Properly type mock deps in configReindex.test.ts
    • (app) Pass valuesManager to processor during initialization
    • Re-encode .gitignore as UTF-8 (was UTF-16 BOM from PowerShell)
    • Release @karmaniverous/jeeves-watcher v0.8.5
    • Update values index before hash check in processFile
    • Lintfix
    • Release @karmaniverous/jeeves-watcher v0.8.4
    • Pass valuesManager and issuesManager to config-reindex handler
    • Lintfix
    • Release @karmaniverous/jeeves-watcher v0.8.2
    • Update values index during rules reindex (processRulesUpdate)
    • Release @karmaniverous/jeeves-watcher v0.8.1
    • Add renderAs field to inference rule schema
    • Add renderAs to applyRules and buildMergedMetadata return types
    • Add POST /render endpoint with isPathWatched and renderFile
    • Add GET /search/facets endpoint with schema-derived facet definitions
    • Add Cache-Control no-cache support to withCache, wrap /render endpoint
    • Updated diagrams
    • Comprehensive documentation audit fixes
    • Add v0.8.0 documentation for renderAs, POST /render, GET /search/facets
    • Add render handler tests and buildMetadata last-match-wins test
    • Release @karmaniverous/jeeves-watcher v0.8.0
    • Inject ignored paths and expose watch config in merged document
    • Restore strict typings in withCache and fix lint errors
    • Release @karmaniverous/jeeves-watcher v0.7.1
    • Add renderDoc helper and render block for structured document rendering
    • Add api caching and agent bootstrap prompt injection
    • Use consistent default port 1936 in server.listen() and schema description
    • Resolve helper file paths relative to configDir in /config/validate
    • Resolve Gemini PR feedback (XSS escaping, js-yaml dump, radash get)
    • Review pass โ€” remove dead code, DRY context, harden tests, use radash title
    • SOLID/DRY pass โ€” extract buildSyntheticAttributes, shared sleep, deduplicate handlers
    • SOLID/DRY pass โ€” deduplicate attributes, handlers, sleep; fix extractor registry
    • Fix tsdoc warnings (add tsdoc.json, escape > chars in yamlEscape)
    • Copy tsdoc.json into package directories
    • Release @karmaniverous/jeeves-watcher v0.7.0
    • Fix all eslint errors (210 โ†’ 0) (#76) (#76)
    • Change default port from 3456 to 1936 (#75) (#75)
    • Release @karmaniverous/jeeves-watcher v0.6.9
    • Read CLI version from package.json instead of hardcoding (#72)
    • Release @karmaniverous/jeeves-watcher v0.6.8
    • Release @karmaniverous/jeeves-watcher v0.6.7
    • Use fresh QdrantClient for write ops to avoid stale keep-alive connections
    • Release @karmaniverous/jeeves-watcher v0.6.6
    • POST /rules/reapply endpoint + plugin auto-reapply after registration (#65) (#65)
    • Disable AJV strict mode to suppress schema type warnings (#55) (#55)
    • Release @karmaniverous/jeeves-watcher v0.6.5
    • Add nocase and dot options to AJV glob keyword
    • Release @karmaniverous/jeeves-watcher v0.6.4
    • Revert unconditional ensureTextIndex from initialization.ts
    • Release @karmaniverous/jeeves-watcher v0.6.3
    • Ensure text index on startup + re-register virtual rules after watcher restart (#60) (#60)
    • Release @karmaniverous/jeeves-watcher v0.6.2
    • Bump @karmaniverous/jsonmap to 2.1.1
    • Release @karmaniverous/jeeves-watcher v0.6.1
    • Convert to monorepo with service and openclaw plugin packages
    • (service) Add filesystem date metadata and line offsets (#46) (#46)
    • (service) Handlebars set expressions + date normalization (#47) (#47)
    • (service) Add hybrid search with BM25 text index and RRF fusion (#48) (#48)
    • Support external rule file references in inferenceRules config (#50) (#50)
    • Memory slot takeover with virtual rules API (#49) (#49)
    • Resolve eslint unbound-method and prettier errors
    • Removed docs from release script
    • Service SOLID/DRY fixes + 54 new tests (#51) (#51)
    • DRY fixes and comprehensive test coverage for openclaw package (#52) (#52)
    • Extract modules to fix 300 LOC violations (#53) (#53)
    • Add guides index pages for foldable typedoc sections
    • Fix template syntax, stale references, and add missing API/tool docs
    • Convert repo to npm workspaces monorepo
    • Fix knip after monorepo split
    • Fix docs, READMEs, and rollup config for monorepo
    • Make service package ESM-only, remove CJS and IIFE outputs
    • Align release-it config for monorepo
    • Release @karmaniverous/jeeves-watcher v0.5.1
    • Fix monorepo release-it tags, plugin id, and version sync
    • Release @karmaniverous/jeeves-watcher v0.6.0