diff --git a/.agents/LEARNINGS.md b/.agents/LEARNINGS.md index af4a3bf..8f0b9ab 100644 --- a/.agents/LEARNINGS.md +++ b/.agents/LEARNINGS.md @@ -2,7 +2,7 @@ ## User Preferences -- Keep Wildcard lightweight with minimal permissions; avoid heavy, screenpipe-style capture by default. +- Keep Wildcard lightweight with minimal permissions; avoid heavy capture by default. - Deprioritize context-switching tips; AI-agent workflows can require frequent intentional switching. - After wildcard code updates, do not rely on `pm2 restart` (cache/stale behavior). Use: `pm2 delete wildcard` then `pm2 start ~/.pm2/ecosystem.config.js --only wildcard`. @@ -26,6 +26,7 @@ - For macOS app-title capture reliability and cleaner TCC attribution, running wildcard via launchd (`install-launchd`, `com.wildcard.wildcard`) works better than PM2. - In `AppUsageTracker.tick`, always catch/log sample flush errors to prevent unhandled interval-loop failures; also refresh `window_title` while app identity remains unchanged. - In `src/wildcard.ts`, `commander` command definitions plus typed option objects are easier to maintain than mutable `argv` helpers (`pop_flag`/`has_flag`) while preserving CLI behavior. +- For hidden Commander compatibility aliases, use `.command(name, { hidden: true })`; `.hideHelp()` exists for `Option`, not `Command`. - For local CLI iteration, symlink `src/wildcard.ts` directly (`ln -sf "$(pwd)/src/wildcard.ts" ~/.bun/bin/wildcard`) so daily commands do not depend on a repo-root launcher wrapper. - Keeping `src/wildcard.ts` as thin commander wiring and moving handlers into `src/commands/*` makes future command changes safer and easier to review. - For long-running CLI command handlers, splitting orchestration (`watch.ts`) from runtime loop (`watch_runtime.ts`) and diagnostics (`status.ts`) keeps behavior stable while reducing file complexity. @@ -36,16 +37,34 @@ - In sync flows, extracting tiny helpers for cursor and error persistence reduces duplicate `setState`/`flush` blocks without changing runtime behavior. - For sync shutdown verification, use a delayed `/bulk-upload/v1` server and assert all three: upload started, shutdown latency stayed low, and `sync.*.cursor_rowid` did not advance. - In shutdown-abort sync tests, `watch` may still create extra `app_usage` rows while running; assert cursor/pending-event invariants rather than an exact `pending_app_usage` count. -- When refreshing docs/tutorials, treat `src/wildcard.ts` and `ARCHITECTURE.md` as source of truth first; old `apps/*`, `packages/*`, and Screenpipe references can linger after architecture consolidation. +- When refreshing docs/tutorials, treat `src/wildcard.ts` and `ARCHITECTURE.md` as source of truth first; old `apps/*` and `packages/*` references can linger after architecture consolidation. +- For `docs/`, keep `docs/ARCHITECTURE.md` as the canonical system spec and treat the HTML pages as topic-specific visual explainers; trim duplication instead of letting each HTML page become a parallel architecture doc. - During snake_case -> kebab-case migrations, sweep architecture/docs tables and diagrams for stale underscore filenames to keep docs executable. - For report-style commands with human output on `stdout`, send progress/status lines to `stderr` to keep markdown/JSON pipe-safe. - For table-like CLI output with variable project/branch labels, compute the label column width from the current rows instead of hard-coding `padEnd(...)`; fixed widths break quickly on long branch names. - AI provider env var fallbacks should be provider-specific: only use `OPENAI_API_KEY` when provider is `openai`, not `ollama`. -- For architecture-probe workflows, prefer creating `scratch/` scripts that favor read-only real module imports and print resolved module/config boundaries before performing any writes. +- When reorganizing repo docs into `docs/`, keep a small root `SECURITY.md` pointer because GitHub expects that filename at the repository root for security-policy discovery. +- For architecture-probe workflows, prefer creating hidden `.scratch/` scripts that favor read-only real module imports and keep all temp DB/files inside `.scratch/`. +- For updated scratch refreshes, mirror the numbered-probe layout: `01-*` through `0N-*`, `99-compose.ts`, and `.scratch/Tutorial.md`. +- `TimelineDb` does not expose a generic `queryAppUsage()` façade; use `queryAppUsageEndingBefore(...)` or `getAppUsageSummary(...)` for public app-usage reads. - `ConfigStore` + `wildcard` CLI outputs show that command behavior is mostly orchestrator-based and storage-driven; this helps in architecture mapping. - `SyncEngine.syncOnce()` behavior is visible with a temp local `/bulk-upload/v1` server, but empty app_usage streams can leave corresponding cursor keys unset until data arrives. - For time-bucketing utilities, anchor bucket boundaries to the requested range start instead of epoch multiples so local day/week labels do not drift in non-UTC timezones. - For prompt readability in summary/report flows, keep stable system instructions in feature-local markdown files (`src/summary/prompts/*.md`) and keep dynamic session/project payload assembly in code. +- For server config precedence where `config` must beat env, keep server env resolution out of `ConfigStore.load()` and use `ConfigStore.loadSources()` plus a server-specific resolver instead of inferring from merged defaults. +- For Bun package hygiene, `files: ["src"]` still ships `*.test.ts`; use explicit `src/**/*.ts` + `src/**/*.md` entries with a `!src/**/*.test.ts` negation to keep the published tarball runtime-only. +- For managed `wildcard server` lifecycle, never trust the PID file alone; verify the live process command still matches `server start --child` before `stop` or `doctor`, or a reused PID can target an unrelated process. +- When moving server entrypoints to the CLI namespace, update `ecosystem.config.cjs` in the same change so PM2 keeps using `src/wildcard.ts server start` and the `WILDCARD_SERVER_*` env names/default `timeline.db`. +- For `server start --daemon`, the detached child must ignore `config.yaml` server fields and boot from the parent-resolved `WILDCARD_SERVER_*` env, or CLI flags can diverge from the actual bind host/port/db path. +- PM2 should launch Bun directly with `interpreter: 'none'` and `script: ~/.bun/bin/bun`; PM2's Bun interpreter mode against `src/wildcard.ts` is unreliable here. +- For ingest body limits, do not trust `Content-Length` alone; enforce `max_body_size_bytes` while streaming/chunking the request body so chunked uploads cannot bypass the cap. +- For first-run UX and docs, avoid hard-coding one developer's workspace layout (like `~/Projects`); prefer portable examples such as `~/code` and let setup infer from common directories plus the current working directory. +- When invoking `codex exec` in a fresh temp directory as a trust boundary, include `--skip-git-repo-check` or the subprocess will fail before doing any work. +- In interactive setup flows, disabling an optional config block should explicitly delete it from the assembled config object; starting from `...existing` makes toggles sticky otherwise. +- If `defaultConfig()` defines an optional config block, deleting that block from `config.yaml` does not disable it after `deepMerge`; add an explicit `enabled` flag or a load-time opt-out when true disablement matters. +- When moving repo docs under `docs/`, keep lightweight root pointers for GitHub-discovered files such as `SECURITY.md` and `CONTRIBUTING.md`; otherwise repo metadata links regress even if the docs still exist. +- When renaming CLI commands, update `README.md`, `SKILL.md`, `docs/`, relevant `tutorials/`, and any command-shape tests in the same change; hidden compatibility aliases do not keep docs/tests correct on their own. +- In `cmdReport`, only auto-run enrichment when the report has an AI provider and enrichment is explicitly configured; otherwise heuristic/disabled-AI reports do unnecessary Codex work without affecting output. ## Patterns That Don't Work @@ -59,12 +78,13 @@ are not installed; use `pnpm dlx` or `bunx` launchers instead. - `@clack/prompts` `log.*` and `spinner()` write to `stdout`, so they pollute pipeable report output if used for progress. - With Commander, `--no-` sets `` to `false` (e.g. `opts.ai === false`), not `opts.no`. +- In this Commander version, `Command.hideHelp()` does not exist; trying to chain it on subcommands breaks startup and typecheck. ## Domain Notes +- 2026-03-21: `AGENTS.md` still references the older `apps/*` + `packages/*` monorepo layout, but the active Wildcard runtime is consolidated under `src/`; for architecture and implementation questions, inspect `src/` and `docs/ARCHITECTURE.md` first. - Session thresholds tuned for file-edit tracking: `idle_threshold_s: 300`, `activity_window_s: 120`. -- Screenpipe events arrive frequently (every few seconds), so session thresholds matter less when screenpipe is active. - Watcher can hold a DB lock: `report` may fail with `database is locked` while watcher is running; `show` uses read-only queries and is typically safe. - Frontmost-app metadata on file events is sparse; dedicated polled `app_usage` segments provide better app-time aggregation. - `frontmost_app` uses AppleScript AXTitle via `System Events`; permissions apply to the runtime context. @@ -78,5 +98,5 @@ - 2026-02-23: Ignore pattern updates should be mirrored in both `src/config/config-store.ts` (default config ignores) and `src/capture/ignore-patterns.ts` (defensive fallback) to keep watch filtering consistent when config is unavailable. - 2026-02-24: In `SKILL.md` report guidance, require a two-pass "timeline + project enrichment" workflow: run `show/report`, then inspect top projects' README/manifests and changed high-signal files to produce impact-oriented summaries with confidence and explicit unknowns. -- 2026-03-03: For `scratch/` architecture probes, combine source parsing with real `wildcard --help`/`status --json` execution; parser-only command-dispatch checks can miss multiline `.action(...)` wiring. +- 2026-03-03: For `.scratch/` architecture probes, combine source parsing with real `wildcard --help`/`status --json` execution; parser-only command-dispatch checks can miss multiline `.action(...)` wiring. - 2026-03-20: When refreshing Wildcard docs, verify `README.md`, `docs/ARCHITECTURE.md`, and `SKILL.md` against `src/wildcard.ts`, `src/config/config-store.ts`, and `src/server/bulk-upload-server.ts`; command flags, config defaults, and ingest routes drift independently. diff --git a/.gitignore b/.gitignore index 70cff5b..de1ab50 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids +.scratch/ *.pid *.seed *.pid.lock diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..cadf1c4 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +**/*.test.ts diff --git a/.specify/init-options.json b/.specify/init-options.json index 041f293..3044e9e 100644 --- a/.specify/init-options.json +++ b/.specify/init-options.json @@ -6,4 +6,4 @@ "preset": null, "script": "sh", "speckit_version": "0.3.1" -} \ No newline at end of file +} diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index c2ba454..e779403 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -3,18 +3,23 @@ ## Core Principles ### I. Local-First, Minimal Permissions + Wildcard must stay local-first. Core capture, search, sessionization, and reporting flows must work without network dependencies, and new features must preserve the project's lightweight, minimal-permission posture by default. ### II. CLI-First, Pipe-Safe Interfaces + Every user-facing workflow must be operable from the CLI. Human-readable output goes to `stdout`, progress and diagnostics go to `stderr`, and machine-readable modes must remain stable enough for automation. ### III. Small, Typed Changes + Changes should follow the existing Bun + TypeScript patterns: strict typing, focused modules, 2-space indentation, single quotes, and small helpers over sprawling abstractions. Prefer extending current command/session/storage flows before introducing new layers. ### IV. Validation Before Commit + Behavior changes must be backed by the smallest validation that proves them safe: focused tests for new logic, full `bun test` and `bun run check` before marking cross-cutting work complete, and CLI smoke checks for user-facing commands. ### V. Honest Specs and Docs + Specs, task lists, README/tutorial content, and architecture docs must reflect the code that actually ships. Tasks may only be marked done after the corresponding implementation and validation have really happened. ## Additional Constraints diff --git a/.specify/templates/checklist-template.md b/.specify/templates/checklist-template.md index 806657d..0caeacf 100644 --- a/.specify/templates/checklist-template.md +++ b/.specify/templates/checklist-template.md @@ -6,16 +6,16 @@ **Note**: This checklist is generated by the `/speckit.checklist` command based on feature context and requirements. - diff --git a/.specify/templates/constitution-template.md b/.specify/templates/constitution-template.md index a4670ff..4e9354e 100644 --- a/.specify/templates/constitution-template.md +++ b/.specify/templates/constitution-template.md @@ -1,50 +1,73 @@ # [PROJECT_NAME] Constitution + ## Core Principles ### [PRINCIPLE_1_NAME] + + [PRINCIPLE_1_DESCRIPTION] + ### [PRINCIPLE_2_NAME] + + [PRINCIPLE_2_DESCRIPTION] + ### [PRINCIPLE_3_NAME] + + [PRINCIPLE_3_DESCRIPTION] + ### [PRINCIPLE_4_NAME] + + [PRINCIPLE_4_DESCRIPTION] + ### [PRINCIPLE_5_NAME] + + [PRINCIPLE_5_DESCRIPTION] + ## [SECTION_2_NAME] + [SECTION_2_CONTENT] + ## [SECTION_3_NAME] + [SECTION_3_CONTENT] + ## Governance + [GOVERNANCE_RULES] + **Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE] + diff --git a/.specify/templates/plan-template.md b/.specify/templates/plan-template.md index 5a2fafe..480c526 100644 --- a/.specify/templates/plan-template.md +++ b/.specify/templates/plan-template.md @@ -29,7 +29,7 @@ ## Constitution Check -*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* +_GATE: Must pass before Phase 0 research. Re-check after Phase 1 design._ [Gates determined based on constitution file] @@ -48,6 +48,7 @@ specs/[###-feature]/ ``` ### Source Code (repository root) + @@ -83,8 +82,8 @@ Examples of foundational tasks (adjust based on your project): > **NOTE: Write these tests FIRST, ensure they FAIL before implementation** -- [ ] T010 [P] [US1] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T011 [P] [US1] Integration test for [user journey] in tests/integration/test_[name].py +- [ ] T010 [P] [US1] Contract test for [endpoint] in tests/contract/test\_[name].py +- [ ] T011 [P] [US1] Integration test for [user journey] in tests/integration/test\_[name].py ### Implementation for User Story 1 @@ -107,8 +106,8 @@ Examples of foundational tasks (adjust based on your project): ### Tests for User Story 2 (OPTIONAL - only if tests requested) ⚠️ -- [ ] T018 [P] [US2] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T019 [P] [US2] Integration test for [user journey] in tests/integration/test_[name].py +- [ ] T018 [P] [US2] Contract test for [endpoint] in tests/contract/test\_[name].py +- [ ] T019 [P] [US2] Integration test for [user journey] in tests/integration/test\_[name].py ### Implementation for User Story 2 @@ -129,8 +128,8 @@ Examples of foundational tasks (adjust based on your project): ### Tests for User Story 3 (OPTIONAL - only if tests requested) ⚠️ -- [ ] T024 [P] [US3] Contract test for [endpoint] in tests/contract/test_[name].py -- [ ] T025 [P] [US3] Integration test for [user journey] in tests/integration/test_[name].py +- [ ] T024 [P] [US3] Contract test for [endpoint] in tests/contract/test\_[name].py +- [ ] T025 [P] [US3] Integration test for [user journey] in tests/integration/test\_[name].py ### Implementation for User Story 3 diff --git a/AGENTS.md b/AGENTS.md index 5276f90..3613791 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,12 +2,12 @@ ## Project Structure & Module Organization -This is a Bun + TypeScript monorepo with workspaces in `apps/*` and `packages/*`. +This is a Bun + TypeScript CLI project centered on `src/`. -- `apps/cli` holds the main CLI (entry at `apps/cli/src/wildcard.ts`). -- `apps/shell` contains shell-facing tooling. -- `packages/*` contains the core modules (e.g., `ai`, `capture`, `config`, `context`, `screenpipe`, `session`, `storage`, `summary`). -- `tutorials/` and `skills/` contain docs, examples, and internal workflow notes. +- `src/wildcard.ts` is the CLI entrypoint. +- `src/commands/` contains command handlers. +- `src/ai`, `src/capture`, `src/config`, `src/context`, `src/runtime`, `src/server`, `src/session`, `src/storage`, and `src/summary` contain the core runtime modules. +- `docs/`, `tutorials/`, and `SKILL.md` contain architecture notes, examples, and operator guidance. ## Build, Test, and Development Commands @@ -23,13 +23,13 @@ CLI commands run via the `wildcard` bin (link for dev: `ln -sf "$(pwd)/src/wildc ## Coding Style & Naming Conventions - TypeScript (ESM) with `strict` enabled in `tsconfig.json`. -- Use 2-space indentation and single quotes, matching existing files in `apps/cli/src`. +- Use 2-space indentation and single quotes, matching existing files in `src/`. - Naming patterns observed: `snake_case` for functions (e.g., `store_paths`, `fmt_time`) and lower-case file names. - Prefer workspace path aliases from `tsconfig.json` (e.g., `@wildcard/config`). ## Testing Guidelines -No test framework or test files are currently present. If adding tests, colocate them near the module (e.g., `packages//test`) and document the command in `package.json`. +Bun test is available via `bun test`. Colocate tests near the module under `src/` (for example `src/summary/*.test.ts`) and keep any new verification commands documented in `package.json` when needed. ## Commit & Pull Request Guidelines @@ -42,4 +42,4 @@ For PRs, include: ## Configuration Notes -TypeScript path aliases are centralized in `tsconfig.json`. Update both the alias and the referenced `packages//src/index.ts` if you add new modules. +TypeScript path aliases are centralized in `tsconfig.json`. Update both the alias and the corresponding `src/` export surface if you add new modules. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 344855c..18f0f2c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,55 +1,6 @@ # Contributing to Wildcard -Thanks for your interest in contributing! This project is a Bun + TypeScript -monorepo with workspaces in `apps/*` and `packages/*`. +The canonical contribution guide lives in [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md). -## Code of Conduct - -By participating, you agree to abide by the Code of Conduct in -`CODE_OF_CONDUCT.md`. - -## Getting Started - -- Install Bun (https://bun.sh) -- Clone the repo -- Install dependencies: - -```bash -bun install -``` - -## Development - -Run the CLI locally: - -```bash -bun run wildcard --help -``` - -Common scripts: - -```bash -bun run watch -bun run show -bun run report -bun run search -bun run status -``` - -## Linting and Type Checking - -```bash -bun run check -``` - -## Pull Requests - -- Keep changes focused and include context in the description. -- Update docs and examples when behavior changes. -- If you add new configuration, document it in the README. -- Ensure `bun run check` passes before opening a PR. - -## Releasing - -Releases are handled by maintainers. If your change requires a release, call -that out in the PR description. +GitHub recognizes `CONTRIBUTING.md` at the repository root, so this file stays +here as a pointer while the detailed guide lives under `docs/`. diff --git a/README.md b/README.md index fc481e8..828f9cf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # Wildcard -Wildcard is a Bun-first CLI that captures file activity into a local timeline you can search and summarize. It is local-first, offline by default, and designed for personal workflows. +Between your own coding sessions, AI agents running tasks, and work spread across multiple machines, there's a lot happening in a day. Too much to keep in your head. Wildcard captures all of it — file edits, app focus, agent activity — into a local timeline that your AI can use to help you prioritize, write daily briefs, and keep track of what actually got done. -The built-in `watch` pipeline captures file changes as `edit` events. The event model also supports `ocr`, `audio`, and `ui` event types, which are expected from external producers via ingest APIs. +Tools like [ActivityWatch](https://activitywatch.net/) and [screenpipe](https://github.com/mediar-ai/screenpipe) are impressive projects, but this data is deeply personal. I wanted something with no telemetry, a low memory footprint, and a codebase simple enough to fork and own completely. Wildcard is MIT-licensed and will always be free of any tracking. As local models get better, the goal is to drop third-party AI providers entirely. -Status: early alpha. Expect breaking changes while the data model and UX settle. +### How it works + +Wildcard runs as a background daemon that watches your project directories. File changes become timestamped events in a local SQLite database. Those events get grouped into sessions, then summarized into project-level reports — optionally enriched by a coding agent that reads your git history and explains what changed in plain language. + +The real payoff is multi-device: run wildcard on your laptop, your dev server, wherever your agents operate. Each device syncs to a central archive, giving you (or your AI agent — [openclaw](https://github.com/openclaw/openclaw), Claude, ChatGPT, whatever you use) a single feed of everything that happened. + +**Status:** early alpha. Expect breaking changes while the data model and UX settle. For implementation details, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). For the operator-focused reporting workflow used by AI agents, see [SKILL.md](SKILL.md). @@ -14,7 +20,7 @@ For implementation details, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). Fo - macOS or Linux (Windows is not supported; use WSL2 if needed) - Optional: Ollama, OpenAI, or Gemini for AI summaries -## Install / Run From Source +## Install ```bash git clone git@github.com:abpai/wildcard.git @@ -30,10 +36,10 @@ Commands are intended to run via the `wildcard` bin. ```bash # Start watching (foreground) -wildcard watch --roots ~/Projects +wildcard watch --roots ~/code # Start watching as a daemon -wildcard watch --roots ~/Projects --daemon +wildcard watch --roots ~/code --daemon # Show today's sessions wildcard show today @@ -45,9 +51,26 @@ wildcard log week # Generate a weekly report wildcard report week +# Enrich projects with AI-powered change analysis (requires Codex CLI) +wildcard enrich +wildcard enrich --period week +wildcard enrich --dry-run + # Push pending local data to a central ingest server wildcard sync push +# Start the central archive ingest endpoint +wildcard server start + +# Start the archive server as a managed daemon +wildcard server start --daemon + +# Inspect, stop, restart, or validate the managed archive server +wildcard server status +wildcard server stop +wildcard server restart +wildcard server doctor + # Search the timeline wildcard search "config" --from 2025-01-01 --to 2025-01-31 --types edit,ocr @@ -56,23 +79,39 @@ wildcard status wildcard status --json # macOS: install/uninstall launchd service -wildcard install-launchd --roots ~/Projects -wildcard uninstall-launchd -wildcard restart +wildcard launchd install --roots ~/code +wildcard launchd uninstall +wildcard launchd restart # Prune old local data wildcard prune --older-than 30 ``` +For one release, `bun run server` remains as a compatibility alias to `wildcard server start`. + +## Archive Host Workflow + +Use `wildcard server start` on the central archive host and point it at `timeline.db` so the regular CLI and the ingest endpoint read and write the same archive directly. + +```bash +wildcard server start --db-path ~/.wildcard/timeline.db +wildcard server status --db-path ~/.wildcard/timeline.db +``` + +Remote devices should set: + +- `sync.server_url` to the archive host URL +- `identity.device_id` to a unique per-device value + ### Update launchd service (macOS) - Reload the running service after code/config updates: - `wildcard restart` + `wildcard launchd restart` - Rebuild service definition (for changed roots or plist args): - `wildcard install-launchd --roots ~/Projects` + `wildcard launchd install --roots ~/code` - Full clean reinstall if launchd gets into a bad state: - `wildcard uninstall-launchd` - `wildcard install-launchd --roots ~/Projects` + `wildcard launchd uninstall` + `wildcard launchd install --roots ~/code` Event types: @@ -84,6 +123,7 @@ Useful flags: - `show`, `log`, `report`, `search`: `--device ` to filter multi-device data - `report`: `--force-refresh` to bypass summary cache - `report`: `--no-ai` to force heuristic summaries +- `report`: `--no-enrich` to skip automatic code enrichment - `report`: `--no-progress` to keep stdout clean for piping or file capture - `log`: `--json` for machine-readable output - `status`: `--json` for machine-readable output @@ -98,7 +138,7 @@ store_dir: ~/.wildcard watch: roots: - - ~/Projects + - ~/code ignore: - .git/** - node_modules/** @@ -118,7 +158,7 @@ session: ai: enabled: false provider: ollama - model: llama3.2 + model: qwen3.5:latest base_url: http://localhost:11434 identity: @@ -132,6 +172,15 @@ sync: interval_s: 300 max_retries: 8 batch_delay_ms: 0 + +server: + host: 0.0.0.0 + port: 3000 + db_path: ~/.wildcard/timeline.db + api_key: + allowed_devices: [] + max_body_size_bytes: 10485760 + pid_file: ~/.wildcard/wildcard-server.pid ``` Environment variables: @@ -153,8 +202,23 @@ Environment variables: - `WILDCARD_SYNC_INTERVAL_S` - `WILDCARD_SYNC_MAX_RETRIES` - `WILDCARD_SYNC_BATCH_DELAY_MS` +- `WILDCARD_SERVER_HOST` +- `WILDCARD_SERVER_PORT` +- `WILDCARD_SERVER_DB_PATH` +- `WILDCARD_SERVER_API_KEY` +- `WILDCARD_SERVER_ALLOWED_DEVICES` +- `WILDCARD_SERVER_MAX_BODY_SIZE_BYTES` +- `WILDCARD_SERVER_PID_FILE` - `WILDCARD_DEBUG_OSASCRIPT` (`1` to log frontmost-app AppleScript stderr/debug details) +Legacy server env fallbacks kept for one release: + +- `PORT` +- `MAX_BODY_SIZE` +- `WILDCARD_API_KEY` +- `WILDCARD_ALLOWED_DEVICES` +- `WILDCARD_DB_PATH` + AI summary prompt templates live in `src/summary/prompts/*.md`. The markdown files hold the stable system instructions, while runtime session/project data is still assembled in code. ## Data Locations @@ -163,12 +227,16 @@ AI summary prompt templates live in `src/summary/prompts/*.md`. The markdown fil - includes `events`, `events_fts`, summary cache tables, and `app_usage` focus segments - `~/.wildcard/blobs/` (content-addressable blobs) - `~/.wildcard/wildcard.pid` (daemon PID) +- `~/.wildcard/wildcard-server.pid` (archive server daemon PID) - `~/Library/LaunchAgents/com.wildcard.wildcard.plist` (macOS launchd) - `~/.wildcard/launchd.out.log` and `~/.wildcard/launchd.err.log` (macOS logs) ## Development ```bash +git clone git@github.com:abpai/wildcard.git +cd wildcard +bun install ln -sf "$(pwd)/src/wildcard.ts" ~/.bun/bin/wildcard bun run check wildcard --help diff --git a/SECURITY.md b/SECURITY.md index 636140d..a4bebf6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,15 +1,6 @@ # Security Policy -## Reporting a Vulnerability +The canonical security policy lives in [docs/SECURITY.md](docs/SECURITY.md). -Please report security issues via GitHub Security Advisories (preferred). -If that is not possible, open a private issue and mark it as a security -concern so maintainers can follow up. - -We aim to acknowledge reports within 7 days and provide a remediation plan -or timeline as soon as possible. - -## Supported Versions - -This project is in early development (0.x). Security fixes are applied to the -`main` branch and released in the next patch/minor version. +GitHub recognizes `SECURITY.md` at the repository root, so this file stays here +as a pointer while the actual policy lives under `docs/`. diff --git a/SKILL.md b/SKILL.md index 9881f13..ad05565 100644 --- a/SKILL.md +++ b/SKILL.md @@ -24,6 +24,7 @@ Use this skill when the user wants to: - **Configure** wildcard (config.yaml, env vars) - **Push local data upstream** (`sync push`) - **Manage the macOS daemon** (install/uninstall launchd, restart) +- **Enrich reports** with AI-powered git change analysis (`enrich`) - **Maintain data** (prune old data, archive to another DB) - **Troubleshoot** issues (daemon not running, stale PID, AI not working) - **Set up** wildcard for the first time (`setup`) @@ -43,7 +44,7 @@ ln -sf "$(pwd)/src/wildcard.ts" ~/.bun/bin/wildcard wildcard --help # Start watching (foreground) -wildcard watch --roots ~/Projects +wildcard watch --roots ~/code # View today's sessions wildcard show today @@ -57,10 +58,10 @@ Start the file watcher in foreground or as a background daemon. ```bash # Foreground (Ctrl+C to stop) -wildcard watch --roots ~/Projects +wildcard watch --roots ~/code # Background daemon -wildcard watch --roots ~/Projects --daemon +wildcard watch --roots ~/code --daemon # With memory logging and guards wildcard watch --daemon --memlog --mem-warn-mb 512 --mem-limit-mb 1024 @@ -137,6 +138,7 @@ wildcard report yesterday --no-progress | Flag | Description | | ----------------- | --------------------------------------- | | `--no-ai` | Force heuristic summaries | +| `--no-enrich` | Skip automatic code enrichment | | `--force-refresh` | Bypass summary cache and regenerate | | `--device ` | Filter by device ID(s), comma-separated | | `--no-progress` | Disable progress output on stderr | @@ -145,15 +147,28 @@ wildcard report yesterday --no-progress For summary/report requests: -1. Run `wildcard show ` and `wildcard report --no-progress`. -2. If `wildcard report ... --no-progress` stalls for ~60 seconds, rerun with `--no-ai --no-progress`. -3. Rank projects by active time. -4. Enrich the top 3 projects, plus any project with at least 20 minutes active time. -5. For each enriched project: +1. If enrichment data is available, run `wildcard enrich` first to analyze git changes. This pre-gathers redacted git diffs and sends them to Codex CLI for structured summaries that feed into the report. +2. Run `wildcard show ` and `wildcard report --no-progress`. +3. If `wildcard report ... --no-progress` stalls for ~60 seconds, rerun with `--no-ai --no-progress`. +4. Rank projects by active time. +5. Enrich the top 3 projects, plus any project with at least 20 minutes active time. +6. For each enriched project: - Detect repo path from project name, window titles, and key file paths. - Read local project metadata (`README*`, `package.json`, `pyproject.toml`, `go.mod`, or `Cargo.toml` as available). - Use changed-file evidence from wildcard output to identify meaningful edits. -6. Produce per-project impact analysis with explicit confidence and unknowns. +7. Produce per-project impact analysis with explicit confidence and unknowns. + +### Automated Enrichment via `wildcard enrich` + +The `enrich` command automates git change analysis for qualifying projects: + +```bash +wildcard enrich # Enrich today's projects +wildcard enrich --period week # Enrich this week's projects +wildcard enrich --dry-run # Preview what would be enriched +``` + +Enrichment pre-gathers redacted git context (commits, diffs, working tree status) and sends it to Codex CLI for synthesis. Results are stored in the database and automatically injected into `wildcard report` summaries. Projects below activity thresholds (< 5 edits, < 2 source files, < 1 min duration) are skipped. Requires the Codex CLI to be installed (`npm install -g @openai/codex`). ## Project Enrichment Heuristics @@ -274,7 +289,7 @@ Use this when `sync.server_url` is configured and you want to push local `events Creates a launchd plist for automatic startup on login. ```bash -wildcard install-launchd --roots ~/Projects +wildcard launchd install --roots ~/code ``` ### Uninstall LaunchAgent @@ -282,7 +297,7 @@ wildcard install-launchd --roots ~/Projects Removes the plist and stops the service. ```bash -wildcard uninstall-launchd +wildcard launchd uninstall ``` ### Restart @@ -290,14 +305,14 @@ wildcard uninstall-launchd Reload the running service after code or config changes. ```bash -wildcard restart +wildcard launchd restart ``` ### Update workflow -- **Config/code changed:** `wildcard restart` -- **Watch roots changed:** `wildcard install-launchd --roots ~/Projects` (rebuilds the plist) -- **Launchd in a bad state:** `wildcard uninstall-launchd && wildcard install-launchd --roots ~/Projects` +- **Config/code changed:** `wildcard launchd restart` +- **Watch roots changed:** `wildcard launchd install --roots ~/code` (rebuilds the plist) +- **Launchd in a bad state:** `wildcard launchd uninstall && wildcard launchd install --roots ~/code` ### View logs @@ -315,7 +330,7 @@ store_dir: ~/.wildcard watch: roots: - - ~/Projects + - ~/code ignore: - .git/** - node_modules/** @@ -335,7 +350,7 @@ session: ai: enabled: false provider: ollama - model: llama3.2 + model: qwen3.5:latest base_url: http://localhost:11434 identity: @@ -414,10 +429,10 @@ Wildcard supports heuristic summaries by default. For AI-powered summaries, enab ai: enabled: true provider: ollama - model: llama3.2 + model: qwen3.5:latest ``` -Requires Ollama running locally: `ollama pull llama3.2` +Requires Ollama running locally: `ollama pull qwen3.5:latest` ### OpenAI @@ -487,31 +502,35 @@ Only run one instance of `wildcard watch`. ### LaunchAgent in a bad state ```bash -wildcard uninstall-launchd -wildcard install-launchd --roots ~/Projects +wildcard launchd uninstall +wildcard launchd install --roots ~/code ``` ## Quick Reference -| Command | Description | -| -------------------------------------------------- | ------------------------------------ | -| `wildcard watch --roots ` | Start file watcher (foreground) | -| `wildcard watch --daemon` | Start as background daemon | -| `wildcard status` | Show daemon status | -| `wildcard status --json` | Show machine-readable status | -| `wildcard show today\|yesterday\|week` | List sessions for a period | -| `wildcard log today\|yesterday\|week` | Show chronological activity log | -| `wildcard report today\|yesterday\|week` | Generate summary report | -| `wildcard report --no-ai` | Report with heuristic summaries only | -| `wildcard report --force-refresh` | Regenerate summaries (bypass cache) | -| `wildcard report --no-progress` | Suppress progress output on stderr | -| `wildcard search "query"` | Full-text search | -| `wildcard search "q" --from --to ` | Search with time range | -| `wildcard search "q" --types edit,ocr` | Search by event type | -| `wildcard setup` | Interactive first-time setup | -| `wildcard sync push` | Push pending local data upstream | -| `wildcard install-launchd --roots ` | Install macOS LaunchAgent | -| `wildcard uninstall-launchd` | Remove macOS LaunchAgent | -| `wildcard restart` | Restart LaunchAgent service | -| `wildcard prune --older-than ` | Delete old data | -| `wildcard archive --older-than --to ` | Copy old data to archive | +| Command | Description | +| -------------------------------------------------- | ---------------------------------------- | +| `wildcard watch --roots ` | Start file watcher (foreground) | +| `wildcard watch --daemon` | Start as background daemon | +| `wildcard status` | Show daemon status | +| `wildcard status --json` | Show machine-readable status | +| `wildcard show today\|yesterday\|week` | List sessions for a period | +| `wildcard log today\|yesterday\|week` | Show chronological activity log | +| `wildcard report today\|yesterday\|week` | Generate summary report | +| `wildcard report --no-ai` | Report with heuristic summaries only | +| `wildcard report --no-enrich` | Skip automatic code enrichment | +| `wildcard report --force-refresh` | Regenerate summaries (bypass cache) | +| `wildcard report --no-progress` | Suppress progress output on stderr | +| `wildcard search "query"` | Full-text search | +| `wildcard search "q" --from --to ` | Search with time range | +| `wildcard search "q" --types edit,ocr` | Search by event type | +| `wildcard enrich` | Enrich projects with git change analysis | +| `wildcard enrich --period week` | Enrich this week's projects | +| `wildcard enrich --dry-run` | Preview what would be enriched | +| `wildcard setup` | Interactive first-time setup | +| `wildcard sync push` | Push pending local data upstream | +| `wildcard launchd install --roots ` | Install macOS LaunchAgent | +| `wildcard launchd uninstall` | Remove macOS LaunchAgent | +| `wildcard launchd restart` | Restart LaunchAgent service | +| `wildcard prune --older-than ` | Delete old data | +| `wildcard archive --older-than --to ` | Copy old data to archive | diff --git a/bun.lock b/bun.lock index 23ccc49..e796a32 100644 --- a/bun.lock +++ b/bun.lock @@ -7,7 +7,7 @@ "dependencies": { "@ai-sdk/google": "^3.0.52", "@ai-sdk/openai": "^3.0.47", - "@clack/prompts": "^0.7.0", + "@clack/prompts": "^1.1.0", "ai": "^6.0.134", "ai-sdk-ollama": "^3.8.1", "commander": "^14.0.3", @@ -15,13 +15,10 @@ "yaml": "^2.8.1", }, "devDependencies": { - "@eslint/js": "^9.17.0", "@types/bun": "^1.1.0", "@types/picomatch": "^2.3.4", - "eslint": "^9.17.0", "prettier": "^3.4.2", "typescript": "^5.8.3", - "typescript-eslint": "^8.19.0", }, "optionalDependencies": { "fsevents": "^2.3.3", @@ -39,35 +36,9 @@ "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], - "@clack/core": ["@clack/core@0.3.5", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ=="], + "@clack/core": ["@clack/core@1.1.0", "", { "dependencies": { "sisteransi": "^1.0.5" } }, "sha512-SVcm4Dqm2ukn64/8Gub2wnlA5nS2iWJyCkdNHcvNHPIeBTGojpdJ+9cZKwLfmqy7irD4N5qLteSilJlE0WLAtA=="], - "@clack/prompts": ["@clack/prompts@0.7.0", "", { "dependencies": { "@clack/core": "^0.3.3", "is-unicode-supported": "*", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA=="], - - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - - "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], - - "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], - - "@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="], - - "@eslint/js": ["@eslint/js@9.39.2", "", {}, "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA=="], - - "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], - - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], - - "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], - - "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@clack/prompts": ["@clack/prompts@1.1.0", "", { "dependencies": { "@clack/core": "1.1.0", "sisteransi": "^1.0.5" } }, "sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g=="], "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], @@ -75,228 +46,44 @@ "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], "@types/picomatch": ["@types/picomatch@2.3.4", "", {}, "sha512-0so8lU8O5zatZS/2Fi4zrwks+vZv7e0dygrgEZXljODXBig97l4cPQD+9LabXfGJOWwoRkTVz6Q4edZvD12UOA=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.53.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/type-utils": "8.53.1", "@typescript-eslint/utils": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.53.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.53.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg=="], - - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.53.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.53.1", "@typescript-eslint/types": "^8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1" } }, "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ=="], - - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.53.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@8.53.1", "", {}, "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.53.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.53.1", "@typescript-eslint/tsconfig-utils": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.53.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg=="], - "@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - "ai": ["ai@6.0.134", "", { "dependencies": { "@ai-sdk/gateway": "3.0.77", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-YalNEaavld/kE444gOcsMKXdVVRGEe0SK77fAFcWYcqLg+a7xKnEet8bdfrEAJTfnMjj01rhgrIL10903w1a5Q=="], "ai-sdk-ollama": ["ai-sdk-ollama@3.8.1", "", { "dependencies": { "@ai-sdk/provider": "^3.0.8", "@ai-sdk/provider-utils": "^4.0.19", "jsonrepair": "^3.13.3", "ollama": "^0.6.3" }, "peerDependencies": { "ai": "^6.0.116" } }, "sha512-DeNG88t3Knsu0AFNU8qe20tp82W+9yczgjduSltIEFWvo2mKuR3MeUNjg5/iGz2IBOkYKnni8pDoI19OxOCN/Q=="], - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "eslint": ["eslint@9.39.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw=="], - - "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], - - "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], - - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], - - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - - "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - "jsonrepair": ["jsonrepair@3.13.3", "", { "bin": { "jsonrepair": "bin/cli.js" } }, "sha512-BTznj0owIt2CBAH/LTo7+1I5pMvl1e1033LRl/HUowlZmJOIhzC0zbX5bxMngLkfT4WnzPP26QnW5wMr2g9tsQ=="], - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "ollama": ["ollama@0.6.3", "", { "dependencies": { "whatwg-fetch": "^3.6.20" } }, "sha512-KEWEhIqE5wtfzEIZbDCLH51VFZ6Z3ZSa6sIOg/E/tBV8S51flyqBOXi+bRxlOYKDf8i327zG9eSTb8IJxvm3Zg=="], - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - - "ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], - - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "typescript-eslint": ["typescript-eslint@8.53.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.53.1", "@typescript-eslint/parser": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="], - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], - - "@clack/prompts/is-unicode-supported": ["is-unicode-supported@2.1.0", "", { "bundled": true }, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], - - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], } } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 58c3ecb..99b6eed 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,10 +1,20 @@ # Wildcard Architecture -This document explains the current runtime layout in `src/`. For installation and day-to-day usage, see [README.md](../README.md). For the reporting workflow used by AI agents, see [SKILL.md](../SKILL.md). +This is the canonical architecture reference for Wildcard's current runtime layout in `src/`. + +For installation and day-to-day usage, see [README.md](../README.md). For the reporting workflow used by AI agents, see [SKILL.md](../SKILL.md). + +## Related Visual Docs + +The HTML docs in this directory are topic-specific visual explainers, not parallel architecture specs: + +- [`wildcard-event-pipeline.html`](./wildcard-event-pipeline.html) focuses on the watch, storage, query, and report path. +- [`wildcard-ai-usage.html`](./wildcard-ai-usage.html) focuses on report-time AI summarization and fallback behavior. +- [`wildcard-multi-device-sync.html`](./wildcard-multi-device-sync.html) focuses on sync push, server ingest, and device-scoped reads. ## Overview -Wildcard is a local-first CLI that captures file activity into a unified SQLite timeline. The built-in watch capture path emits `edit` file events; non-filesystem events (`ocr`, `audio`, `ui`) can be ingested via the bulk upload server. +Wildcard is a local-first CLI that captures file activity into a unified SQLite timeline. The built-in watch capture path emits `edit` file events; non-filesystem events (`ocr`, `audio`, `ui`) can be ingested via the archive server exposed as `wildcard server ...`. It groups events into sessions, generates cached heuristic/AI summaries, supports device-aware queries, and can push pending local data to a central ingest server. @@ -20,18 +30,24 @@ It groups events into sessions, generates cached heuristic/AI summaries, support WatchRuntime orchestrates the full pipeline lifecycle [External Ingest Path (server)] - External producer -> bulk-upload-server (POST /bulk-upload/v1) -> TimelineDb + External producer -> wildcard server start (POST /bulk-upload/v1) -> TimelineDb [Optional Sync Push Path] TimelineDb -> BatchExtractor -> SyncClient -> POST /bulk-upload/v1 [Local Storage] - TimelineDb facade -> EventRepository, FileStateRepository, AppUsageRepository, SummaryRepository, StateRepository + TimelineDb facade -> EventRepository, FileStateRepository, AppUsageRepository, SummaryRepository, EnrichmentRepository, StateRepository TimelineDb -> events_fts ChangeTracker -> BlobStore +[Enrichment Path (wildcard enrich)] + TimelineDb -> QueryService -> SessionManager -> groupSessionsByProject -> ThresholdFilter + -> gather_git_context (git log --all, status, diff) -> redact_git_output -> run_codex (in /tmp) + -> EnrichmentRepository (upsert) + [Read / Report Path] TimelineDb -> QueryService -> SessionManager -> groupSessionsByProject -> SummaryBuilder -> wildcard CLI output + SummaryBuilder optionally injects enrichment data into project summary AI prompts TimelineDb -> QueryService -> SessionManager -> bucketSessionsByTime -> groupFragmentsByProject -> wildcard log output SummaryBuilder <-> SummaryCache TimelineDb -> wildcard CLI output (direct app usage queries) @@ -47,29 +63,31 @@ It groups events into sessions, generates cached heuristic/AI summaries, support 6. Cached summaries (heuristic by default, optional AI provider) 7. Frontmost-app usage capture into `app_usage` time segments 8. Data maintenance via `prune` and copy-only `archive` -9. Optional HTTP bulk ingest (`src/server/bulk-upload-server.ts`) +9. Optional HTTP bulk ingest via `wildcard server start` 10. Optional one-shot sync push via `wildcard sync push` 11. macOS launchd install/uninstall/restart helpers 12. Chronological activity log via `wildcard log` with hourly/daily time-slot bucketing +13. Agent-powered enrichment via `wildcard enrich` (Codex CLI analyzes redacted git diffs for richer report summaries) ## Module Layout (src/) -| Module | Responsibility | Key Exports | -| ----------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| `src/wildcard.ts` | CLI entrypoint (commander-based) | Registers all commands via `src/commands/` | -| `src/commands/` | Command handlers and CLI helpers | `cmdWatch`, `cmdShow`, `cmdLog`, `cmdReport`, `cmdSearch`, `cmdStatus`, `cmdSetup`, `cmdArchive`, `cmdPrune`, `cmdSyncPush` | -| `src/config/` | Config loading, defaults, env overrides | `ConfigStore`, `WildcardConfig`, `defaultConfig` | -| `src/capture/` | Raw watcher events and normalization | `FileWatcher`, `Debouncer`, `FileNormalizer`, `IgnorePatterns` | -| `src/capture/platform/` | Platform-specific watcher implementations | `DarwinWatcher`, `PollingWatcher`, `createPlatformWatcher` | -| `src/context/` | Context resolution, frontmost app, primary context | `ContextResolver`, `FrontmostAppCache`, `PrimaryContext` | -| `src/runtime/` | Watch pipeline orchestration and lifecycle | `runWatchRuntime`, `WatchPipeline`, `WatchRuntimeOptions` | -| `src/session/` | Change tracking, app usage tracking, session/query logic | `ChangeTracker`, `AppUsageTracker`, `SessionManager`, `QueryService`, `bucketSessionsByTime`, `groupFragmentsByProject` | -| `src/storage/` | SQLite repositories, FTS, state, blob integration | `TimelineDb`, `EventRepository`, `FileStateRepository`, `AppUsageRepository`, etc. | -| `src/summary/` | Project grouping and summary generation/cache | `SummaryBuilder`, `SummaryCache`, `groupSessionsByProject` | -| `src/ai/` | AI provider abstraction (AI SDK v6) | `createAiProvider`, `AiSdkProvider` | -| `src/sync/` | Batch extraction and remote upload | `SyncEngine`, `BatchExtractor`, `SyncClient` | -| `src/server/` | External bulk ingestion HTTP server | `bulk-upload-server.ts` | -| `src/utils/` | Time, formatting, store paths, process, AI factory | `fmtTime`, `dayRange`, `storePaths`, `process.ts`, `ai-factory.ts` | +| Module | Responsibility | Key Exports | +| ----------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/wildcard.ts` | CLI entrypoint (commander-based) | Registers all commands via `src/commands/` | +| `src/commands/` | Command handlers and CLI helpers | `cmdWatch`, `cmdShow`, `cmdLog`, `cmdReport`, `cmdSearch`, `cmdStatus`, `cmdSetup`, `cmdEnrich`, `cmdArchive`, `cmdPrune`, `cmdSyncPush`, `cmdServerStart` | +| `src/config/` | Config loading, defaults, env overrides | `ConfigStore`, `WildcardConfig`, `defaultConfig` | +| `src/capture/` | Raw watcher events and normalization | `FileWatcher`, `Debouncer`, `FileNormalizer`, `IgnorePatterns` | +| `src/capture/platform/` | Platform-specific watcher implementations | `DarwinWatcher`, `PollingWatcher`, `createPlatformWatcher` | +| `src/context/` | Context resolution, frontmost app, primary context | `ContextResolver`, `FrontmostAppCache`, `PrimaryContext` | +| `src/runtime/` | Watch pipeline orchestration and lifecycle | `runWatchRuntime`, `WatchPipeline`, `WatchRuntimeOptions` | +| `src/session/` | Change tracking, app usage tracking, session/query logic | `ChangeTracker`, `AppUsageTracker`, `SessionManager`, `QueryService`, `bucketSessionsByTime`, `groupFragmentsByProject` | +| `src/storage/` | SQLite repositories, FTS, state, blob integration | `TimelineDb`, `EventRepository`, `FileStateRepository`, `AppUsageRepository`, etc. | +| `src/summary/` | Project grouping and summary generation/cache | `SummaryBuilder`, `SummaryCache`, `groupSessionsByProject` | +| `src/enrichment/` | Agent-powered change analysis for richer reports | `EnrichmentService`, `gather_git_context`, `redact_diff_content`, `run_codex`, `is_worth_enriching` | +| `src/ai/` | AI provider abstraction (AI SDK v6) | `createAiProvider`, `AiSdkProvider` | +| `src/sync/` | Batch extraction and remote upload | `SyncEngine`, `BatchExtractor`, `SyncClient` | +| `src/server/` | External bulk ingestion runtime and config resolution | `bulk-upload-server.ts`, `config.ts` | +| `src/utils/` | Time, formatting, store paths, process, AI factory | `fmtTime`, `dayRange`, `storePaths`, `process.ts`, `ai-factory.ts` | ### `src/commands/` breakdown @@ -84,8 +102,6 @@ The former `shared.ts` has been split into focused modules: | `launchd-helpers.ts` | macOS launchd plist helpers | | `activity-log.ts` | `log` command: time-slot rendering and JSON output | -Note: legacy references to Screenpipe still exist in older notes, but the active runtime architecture lives under `src/`. - ## Data Model ### UnifiedEvent @@ -181,11 +197,12 @@ WatchRuntime (src/runtime/) -> WatchPipeline: ### External Bulk Ingest Pipeline ```text -External Producer -> bulk-upload-server(/bulk-upload/v1) -> TimelineDb +External Producer -> wildcard server(/bulk-upload/v1) -> TimelineDb ``` -- `src/server/bulk-upload-server.ts` accepts a JSON object with `device_id`, `events`, `app_usage`, and optional `client_checkpoint`. -- Default server DB path is `~/.wildcard/archive.db` unless `WILDCARD_DB_PATH` is set. +- `wildcard server start` uses `src/server/bulk-upload-server.ts` as the reusable runtime and accepts a JSON object with `device_id`, `events`, `app_usage`, and optional `client_checkpoint`. +- Default server DB path is `~/.wildcard/timeline.db` unless `server.db_path` or `WILDCARD_SERVER_DB_PATH` is set. +- `wildcard server status|stop|restart|doctor` manage the optional PID-file daemon path for archive-host setups. - This path can insert `ocr` / `audio` / `ui` events and frontmost-app usage segments, even though local file watching emits `edit` events. ### Sync Push Pipeline @@ -309,6 +326,7 @@ CREATE TABLE app_usage (...); - AI summaries are used only when `ai.enabled` is true and a provider is configured. - `SummaryBuilder` can summarize per session and per report window. - `SummaryCache` stores both session summaries and daily report markdown. +- The visual deep-dive for this subsystem lives in [`wildcard-ai-usage.html`](./wildcard-ai-usage.html). ## Configuration @@ -334,7 +352,17 @@ CLI/runtime environment variable overrides: - `WILDCARD_SYNC_MAX_RETRIES` - `WILDCARD_SYNC_BATCH_DELAY_MS` -Bulk upload server environment variables: +Archive server environment variables: + +- `WILDCARD_SERVER_HOST` +- `WILDCARD_SERVER_PORT` +- `WILDCARD_SERVER_DB_PATH` +- `WILDCARD_SERVER_API_KEY` +- `WILDCARD_SERVER_ALLOWED_DEVICES` +- `WILDCARD_SERVER_MAX_BODY_SIZE_BYTES` +- `WILDCARD_SERVER_PID_FILE` + +Legacy fallbacks for one release: - `PORT` - `MAX_BODY_SIZE` @@ -352,3 +380,5 @@ Notes: - macOS uses FSEvents for realtime file watching and `osascript` for frontmost-app detection. Accessibility permissions may be required. - Linux uses a polling watcher based on `find` plus marker files. - Windows is not supported (use WSL2 if needed). + +For focused visual walkthroughs, see [`wildcard-event-pipeline.html`](./wildcard-event-pipeline.html) and [`wildcard-multi-device-sync.html`](./wildcard-multi-device-sync.html). diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..f75f3c9 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# Contributing to Wildcard + +Thanks for your interest in contributing! This project is a Bun + TypeScript +CLI centered on `src/`. + +## Code of Conduct + +By participating, please follow the collaboration guidelines in +`AGENTS.md` and keep contributions respectful and focused. + +## Getting Started + +- Install Bun (https://bun.sh) +- Clone the repo +- Install dependencies: + +```bash +bun install +``` + +## Development + +Run the CLI locally: + +```bash +bun run wildcard --help +``` + +Common scripts: + +```bash +bun run watch +bun run show +bun run report +bun run enrich +bun run search +bun run status +``` + +## Formatting and Type Checking + +```bash +bun run check +``` + +## Pull Requests + +- Keep changes focused and include context in the description. +- Update docs and examples when behavior changes. +- If you add new configuration, document it in the README. +- Ensure `bun run check` passes before opening a PR. + +## Releasing + +Releases are handled by maintainers. If your change requires a release, call +that out in the PR description. diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..636140d --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,15 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report security issues via GitHub Security Advisories (preferred). +If that is not possible, open a private issue and mark it as a security +concern so maintainers can follow up. + +We aim to acknowledge reports within 7 days and provide a remediation plan +or timeline as soon as possible. + +## Supported Versions + +This project is in early development (0.x). Security fixes are applied to the +`main` branch and released in the next patch/minor version. diff --git a/TODO.md b/docs/TODO.md similarity index 100% rename from TODO.md rename to docs/TODO.md diff --git a/WORKFLOW.md b/docs/WORKFLOW.md similarity index 73% rename from WORKFLOW.md rename to docs/WORKFLOW.md index 0f511b3..ef85f7b 100644 --- a/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -11,30 +11,29 @@ Create `~/.wildcard/config.yaml`: ```yaml watch: roots: - - ~/Projects - - ~/work + - ~/code ``` Or set via environment: ```bash -export WILDCARD_WATCH_ROOTS=~/Projects,~/work +export WILDCARD_WATCH_ROOTS=~/code ``` ### 2. Start Watching ```bash # Foreground (for testing) -bun run wildcard watch +wildcard watch # Background daemon (recommended) -bun run wildcard watch --daemon +wildcard watch --daemon ``` ### 3. View Activity ```bash -bun run wildcard show today +wildcard show today ``` --- @@ -47,10 +46,10 @@ See what you worked on yesterday: ```bash # Quick session list -bun run wildcard show yesterday +wildcard show yesterday # AI-powered summary (requires AI enabled) -bun run wildcard report yesterday +wildcard report yesterday ``` Output example: @@ -70,10 +69,10 @@ Start the daemon and check status: ```bash # Start daemon -bun run wildcard watch --daemon +wildcard watch --daemon # Check if running -bun run wildcard status +wildcard status ``` Status output: @@ -90,23 +89,23 @@ Generate a summary of today's work: ```bash # Session overview -bun run wildcard show today +wildcard show today # Full report with AI summary -bun run wildcard report today +wildcard report today # Report without AI (heuristic summary) -bun run wildcard report today --no-ai +wildcard report today --no-ai ``` ### Weekly Review ```bash # All sessions this week -bun run wildcard show week +wildcard show week # Weekly summary report -bun run wildcard report week +wildcard report week ``` --- @@ -118,33 +117,33 @@ bun run wildcard report week Search across all captured content: ```bash -bun run wildcard search "authentication" +wildcard search "authentication" ``` ### Time-Filtered Search ```bash # ISO timestamp (start time) -bun run wildcard search "bug fix" --from "2024-01-15T09:00:00Z" +wildcard search "bug fix" --from "2024-01-15T09:00:00Z" # Specific date range -bun run wildcard search "refactor" --from 2024-01-10 --to 2024-01-15 +wildcard search "refactor" --from 2024-01-10 --to 2024-01-15 # ISO timestamps work too -bun run wildcard search "api" --from 2024-01-15T09:00:00 +wildcard search "api" --from 2024-01-15T09:00:00 ``` ### Event Type Filtering ```bash # Only file edits -bun run wildcard search "config" --types edit +wildcard search "config" --types edit -# Only OCR captures (requires Screenpipe) -bun run wildcard search "password" --types ocr +# Only OCR captures +wildcard search "password" --types ocr # Multiple types -bun run wildcard search "meeting" --types audio,ocr +wildcard search "meeting" --types audio,ocr ``` ### Search Output @@ -163,10 +162,10 @@ Jan 15, 2024 02:22 PM · my-project · ocr · Authentication required... ```bash # Start daemon -bun run wildcard watch --daemon +wildcard watch --daemon # Check status -bun run wildcard status +wildcard status # Stop daemon (find and kill PID) kill $(cat ~/.wildcard/wildcard.pid) @@ -177,7 +176,7 @@ kill $(cat ~/.wildcard/wildcard.pid) Install a LaunchAgent for automatic startup: ```bash -bun run wildcard install-launchd --roots ~/Projects,~/work +wildcard launchd install --roots ~/code ``` This creates `~/Library/LaunchAgents/com.wildcard.wildcard.plist`. @@ -197,7 +196,7 @@ launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.wildcard.wildcard.plis Remove the LaunchAgent and clean up: ```bash -bun run wildcard uninstall-launchd +wildcard launchd uninstall ``` ### View Logs (LaunchAgent) @@ -228,21 +227,21 @@ mkdir -p ~/.wildcard cat > ~/.wildcard/config.yaml << 'EOF' watch: roots: - - ~/Projects + - ~/code EOF ``` 3. Test in foreground: ```bash -bun run wildcard watch +wildcard watch # Make some edits, then Ctrl+C ``` 4. Verify captures: ```bash -bun run wildcard show today +wildcard show today ``` ### Enable AI Summaries @@ -253,7 +252,7 @@ bun run wildcard show today 2. Pull a model: ```bash -ollama pull qwen3:8b +ollama pull qwen3.5:latest ``` 3. Update config: @@ -262,7 +261,7 @@ ollama pull qwen3:8b ai: enabled: true provider: ollama - model: qwen3:8b + model: qwen3.5:latest ``` #### Option B: OpenAI @@ -283,28 +282,6 @@ export WILDCARD_AI_PROVIDER=openai export OPENAI_API_KEY=sk-your-key-here ``` -### Enable Screenpipe Integration - -[Screenpipe](https://github.com/mediar-ai/screenpipe) captures OCR, audio, and UI snippets. Wildcard imports the results; OCR/transcription happens inside your Screenpipe setup. - -1. Install and run Screenpipe -2. Update config: - -```yaml -screenpipe: - enabled: true - base_url: http://localhost:3030 - poll_interval_ms: 60000 -``` - -3. Start with Screenpipe: - -```bash -bun run wildcard watch --screenpipe -``` - -If `screenpipe.enabled` is true in config, the flag is optional. - ### Customize Ignore Patterns ```yaml @@ -344,30 +321,33 @@ session: ## Command Reference -| Command | Description | -| ------------------------------------ | ----------------------------------- | -| `wildcard watch` | Start file watcher (foreground) | -| `wildcard watch --daemon` | Start as background daemon | -| `wildcard watch --screenpipe` | Enable Screenpipe integration | -| `wildcard watch --roots ` | Override watch roots | -| `wildcard status` | Show daemon status and last event | -| `wildcard show today` | List today's sessions | -| `wildcard show yesterday` | List yesterday's sessions | -| `wildcard show week` | List this week's sessions | -| `wildcard show --force-refresh` | Regenerate summaries (ignore cache) | -| `wildcard report today` | Generate today's summary | -| `wildcard report yesterday` | Generate yesterday's summary | -| `wildcard report week` | Generate weekly summary | -| `wildcard report --no-ai` | Report without AI summary | -| `wildcard report --force-refresh` | Regenerate summaries (ignore cache) | -| `wildcard search "query"` | Search all content | -| `wildcard search "q" --from