Skip to content

Releases: VelimirMueller/code-context-mcp

v3.0.1

Choose a tag to compare

@VelimirMueller VelimirMueller released this 22 Oct 19:31
Immutable release. Only release title and notes can be modified.
v3.0.1
253c5f1

Fixed

  • --version and --help are flags of code-context and code-context-sprint, not a database path. --version (-v) prints the package version and --help (-h) prints the usage; both exit 0. Any other argument that starts with - is refused with exit 64. Before, code-context --version created and indexed a SQLite file named --version in the current directory. (#284)

v3.0.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 20 Oct 23:54
Immutable release. Only release title and notes can be modified.
v3.0.0
37e3d90

Breaking

  • The lean code profile is the default. A server with no setting lists 6 tools (find_symbol, get_file_context, who_imports, exports_in, search_files, query): about 850 tokens of tool definitions per model call instead of about 12,300. Every positive benchmark run used this profile. The old default, 97 tools (toolsets code, code-admin, scrum), is now the full profile. (#178)
  • The sprint process is opt-in. CODE_CONTEXT_PROFILE picks the profile: code (default), full or all (103 tools, adds fun and stream). CODE_CONTEXT_TOOLSETS still adds single toolsets (code-admin, scrum, fun, stream, all); it only adds and never removes a toolset of the profile. Without full, the 2.x meaning of CODE_CONTEXT_TOOLSETS=fun,stream (the default plus fun and stream) becomes code plus fun and stream.
  • Flair follows the sprint tools. The flair header and footer are on when the scrum toolset is on (full, all) and off otherwise, so they are off by default now. OVERDRIVE_FLAIR=0/1 still forces it.
  • Two entry points in one package: the code index and the sprint process. code-context (dist/server/index.js) is the index: its tool contract is frozen, with no setting it lists the 6 code tools. code-context-sprint (dist/server/sprint.js) loads the same server with CODE_CONTEXT_PROFILE=full as its default (97 tools); the scrum, bridge and dump/restore tools and the dashboard ride with it. A known CODE_CONTEXT_PROFILE still wins on both entries. (#179)
  • The browser logs in to the dashboard with an HttpOnly cookie from a one-time launch URL. The page no longer carries the token: window.__DASHBOARD_TOKEN__ is gone, and GET / without a session answers 401 with a short page that says how to log in. The dashboard prints a launch URL at startup (http://localhost:<port>/auth/launch?code=<random>); a bearer holder mints a fresh one with POST /api/auth/launch, and node scripts/dashboard-launch-url.mjs <db> does that after the /health nonce check from #246. A code works once and expires after 5 minutes. Opening it starts a session with a random 32-byte id, held in dashboard memory only, and sets cc_dashboard_session_<port> (HttpOnly; SameSite=Strict; Path=/; Max-Age=43200), then redirects to /. A session ends after 12 h, on POST /api/auth/logout, or when the dashboard restarts. The cookie never holds the token: cookies reach every localhost port, so another local service that sees it gets one session for at most 12 h, not the token. /api/events takes the cookie or the Authorization header; ?token= is refused with 401. Because a cookie reaches every localhost port, a cookie-authenticated write must send the exact dashboard Origin, and a request the browser marks Sec-Fetch-Site: same-site or cross-site is refused. The bearer header keeps working for the MCP server, the hooks and scripts (TM-01, TM-02). (#243)
  • The index entry no longer creates, migrates or seeds the scrum tables. Under the code profile it opens context.db with the code-index tables only and never loads src/scrum, src/dashboard or src/bridge. A sprint toolset (full, all, or CODE_CONTEXT_TOOLSETS with scrum, fun or stream) loads them through src/server/sprint-toolsets.ts. test/boundary.test.ts fails on any other import from src/server into the sprint side. (#179)
  • The custom bridge action is gone. POST /api/bridge/actions answers 400 for custom, and each forwarded action needs a payload that matches its schema; see Security. (#244)

Added

  • health reports profile and toolsets, and ignored_settings for a value the server did not understand. The server logs the profile at start and a WARN line for an ignored value.
  • setup writes the profile into .mcp.json. It sets CODE_CONTEXT_PROFILE=full in the code-context entry env, because setup installs the sprint process. --profile code|full|all picks another one. An existing CODE_CONTEXT_PROFILE is kept, a 2.x CODE_CONTEXT_TOOLSETS=code stays lean, and other keys of the entry (env, type, …) are no longer dropped. --name and --profile values are no longer taken as the target path.
  • /kickoff checks the profile first. Step 0a calls health and stops with the exact setting when the scrum or code-admin toolset is off. It names the code-context-sprint entry as the fix.
  • New bins code-context, code-context-sprint and vlm-code-context-mcp. vlm-code-context-mcp is an alias of code-context, so npx -y vlm-code-context-mcp ./context.db starts the index. code-context-mcp stays the setup command. (#179)
  • setup installs the entry that matches the profile. full and all write dist/server/sprint.js into .mcp.json, code writes dist/server/index.js. Setup still writes CODE_CONTEXT_PROFILE: the setting is explicit, health shows it, and the entry still works when pointed at index.js. (#179)
  • CI runs on pull requests to release branches (release/**), not only on main. (#179)
  • The public contract is written down and CI enforces it. docs/CONTRACT.md freezes the 3.x surface: the bins and their flags, the profiles and env settings, the names, input schemas and default output of the 6 code tools, the names and input schemas of the sprint tools (their output is best effort), the server instructions and the context.db rules (who owns which table; a minor release may add tables and columns, never drop or rename). Snapshots in test/contract/snapshots/ pin it; npm run contract:update rewrites them. The new CI job contract fails when a PR changes a snapshot without a major version bump in package.json or the label contract-change-approved (scripts/check-contract-change.mjs). A change to a tool description only is not a contract change. (#180)

Migration

  • An install that uses the sprint tools sets CODE_CONTEXT_PROFILE=full in the server env (.mcp.json → mcpServers["code-context"].env, or --mcp-config, or the shell). npx code-context-mcp setup . does it for a project: in update mode it writes full when the entry has no profile setting yet.
  • CODE_CONTEXT_TOOLSETS=code keeps working and changes nothing now; remove it when you like.
  • /kickoff in an existing project keeps its old copy (setup never overwrites a command file). Delete .claude/commands/kickoff.md and run setup again to get Step 0a.
  • Pick an entry (#179). code-context-sprint is canonical for the sprint process, code-context for the index:
    • You use the sprint process: change the command to code-context-sprint (or the args to …/dist/server/sprint.js <db>). npx code-context-mcp setup . does it in update mode.
    • You only read code: keep dist/server/index.js (now code-context) and remove CODE_CONTEXT_PROFILE. You get the lean profile.
    • An existing .mcp.json with dist/server/index.js and CODE_CONTEXT_PROFILE=full keeps working in 3.x: the index entry loads the sprint toolsets when the profile asks for them.
  • Open the dashboard through a launch URL (#243). Plain http://localhost:3333 no longer logs a browser in. Run /ccui, or open the launch URL the dashboard prints at startup; mint a new one with node node_modules/vlm-code-context-mcp/scripts/dashboard-launch-url.mjs <db>. A script that used /api/events?token= sends Authorization: Bearer <token> instead. A session lasts 12 h; after that, or after a dashboard restart, run /ccui again.
  • One shared context.db. Both entries open the same file. The index entry owns the code-index tables (files, exports, dependencies, directories, changes, indexed_repos); the sprint entry owns the scrum tables and the schema_versions stamp. A database the index entry created gets its scrum tables, stamped at the latest version, on the first start of the sprint entry. Both entries refuse a database stamped by a newer version.

Fixed

  • The live bench scores only the final answer block. The task checkers read the answer from the last fenced code block (or the text after an Answer:/Result:/Final answer: line), so a name a session mentions in explanation prose no longer counts as a wrong answer; --score-prose restores the old behaviour for comparison. The tool counter is the server's code profile (now including who_imports and exports_in) instead of a hand-kept list, and npm run bench:rescore prints the old and new success rate per arm. (#261)
  • The VitePress docs build passes again. The three dead links that failed npm run build in docs/ — ../README in docs/ARCHITECTURE.md and docs/REFERENCE.md, ../BENCHMARK-GUIDE in docs/user-guide.md — point at the GitHub files now, and CI builds the docs on pull requests that touch docs/, so a dead link cannot land unnoticed again. (#264)
  • The MCP server and the dashboard share one auth token again. Both read or create .code-context/dashboard.token in the directory of the context.db they open (dashboardTokenRoot in src/dashboard/auth.ts); earlier each used its own cwd, so the two processes held different tokens and every MCP notify call got 401 and the dashboard did not refresh live. The MCP server passes its db path to the notify code at start (setDashboardDbPath); the cwd is used only when no db path is known. CODE_CONTEXT_DASHBOARD_TOKEN still wins when set. Migration: an old .code-context/dashboard.token beside a launcher cwd stays in place and is now ignored; delete it, or set CODE_CONTEXT_DASHBOARD_TOKEN for both processes. (#235)
  • Restore and import never replace an existing row. restore_database, import_from_file and POST /api/restore share one restore (src/scrum/restore.ts) that inserts with ON CONFLICT DO NOTHING instead of INSERT OR REPLACE. Earlier a dump row with a clashing id, or since v27 a clashing ticket ref, sil...
Read more

v2.13.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 12 Oct 12:47
Immutable release. Only release title and notes can be modified.
v2.13.0
598b581
  • 2.12.0 was not published to npm; 2.13.0 contains its changes too.

Added

  • Rule-based verdict in ASD-STE100 on the dashboard and the site. Each agent run gets headline.verdict: BENEFICIAL, NO CLEAR EFFECT or SUBOPTIMAL per arm vs vanilla, from success change, uncached saved % and its spread, cost saved % and wall time change. SUBOPTIMAL: success drops by more than 5 pp, tokens increase in every repeat, or more than 25 % slower. Fewer than 3 repeats mark the verdict "indicative". Fixed templates make short sentences, e.g. "With guidance, code-context decreases the token use by 28 %." The dashboard shows a chip on the latest cards and a Verdict section in the run detail; the site shows a verdict card, the label in the history and per group on private-suite cards. Older runs and summaries get the verdict computed from the same fields, so no published file changes. Private summaries carry verdict per run and group; the shape check accepts only the text the rule makes from the block's numbers. Rule and constants: scripts/bench/lib/verdict.mts, documented in BENCHMARK-GUIDE.md "Verdict rule". (#156)
  • Private suite runs in the local dashboard. CODE_CONTEXT_BENCH_PRIVATE_DIRS (path list of suite dirs or their data/ dirs) merges private runs into the Benchmark page with a private chip and the suite alias, plus an All / Public / Private filter. /api/bench/run/:id?suite=pN serves them under the same id, index and realpath rules, per dir. The files are read from disk only and sent nowhere. (#154)
  • bench:publish --private-summary <suite-dir> [--runs id,id] publishes a redacted summary. Schema ccc-bench-private-summary/1 holds only the suite alias, scope counts, and per run and per group: success, uncached tokens per session and per PASS, cost, wall time, uncached saved % with min–max spread and cost saved %. A guard refuses the summary on any suite name, path, commit, task id, prompt token, answer item, hash, absolute path or secret, and names only the JSON path. Only data/private/<alias-slug>.json and data/private/index.json are written, through the usual temp worktree; --dry-run prints the summary. Full private runs stay refused. New optional suite fields: alias, groups, tasks[].group, groupByPrefix, publicTaskIds. The site shows each summary as a "Real-world private suite" card with the caption that task texts and code are private. (#154)
  • bench:live --suite <dir> runs private suites from outside the repository. A suite (suite.json, schema ccc-bench-suite/1, plus answers.json) pins local git clones by commit; each session workspace comes from git archive, so the clone's working tree is never read. New checkers path-set and symbol-set compare the answer with the suite's answer key. Results go to <dir>/data/. A private suite refuses a --data-dir inside the repository, its run JSON carries suite.private: true, and bench:publish refuses such runs. With redact (default for private suites), the run JSON stores tasks by id and sha256 only. npm run bench:suite-check -- <dir> validates a suite and builds and indexes one workspace without a model. (#149)
  • PHP in the code index. .php files get exports with one-line signatures and lines (class incl. abstract/final/readonly, interface, trait, enum, top-level function and const; short name in exports.name, namespace-qualified name in exports.description), use lines in import_lines, and dependency edges from use (grouped, aliased, use function, use const), extends, implements, trait use and class names in code. Names resolve through the nearest composer.json PSR-4 maps (autoload and autoload-dev, also in a subdirectory), then through the indexed declarations; same-namespace classes resolve without use. Vendor namespaces are external packages, not edges. Comments, strings, heredoc/nowdoc and inline HTML (Blade) never create exports or edges. find_symbol and who_imports also take a qualified name (App\Models\User). A synthetic 1,501-file PHP tree indexes in about 0.8 s. (#148)

Fixed

  • tsconfig/jsconfig path aliases make import-graph edges. import … from "@/lib/x" (and baseUrl imports such as components/Button) now resolve through the nearest tsconfig.json/jsconfig.json, its extends chain (relative and node_modules package configs) and, for Vite-style solution configs, the references entry whose include covers the file. paths follow TypeScript's rules (exact key, then longest * prefix, targets in order, relative to baseUrl or the defining config); files probe like relative imports, incl. .d.ts and .js → .ts. who_imports, exports_in, get_file_context and search_files see the new edges, and resolved aliases leave External packages. Configs are parsed with comments and trailing commas by a linear scanner, capped at 1 MB, and cached per index run. On a 475-file Vite React SPA: 952 of 952 alias imports resolve, edges 179 → 1,094. A 6,000-file synthetic tree indexes in ~3.1 s instead of ~2.5 s (27,119 edges instead of 8,872). Vite resolve.alias is not read. Re-index to get the edges. (#151)
  • bench:live timeouts end a session at the limit. The deadline runs on the wall clock, and SIGTERM then SIGKILL reach the agent's whole process tree; the runner no longer waits on output pipes a leftover process holds. A timed-out session keeps its partial usage. Root cause of the ~900 s sessions: the Mac idle-slept on battery, and the old monotonic timer stopped in sleep. The runner now holds caffeinate -i on macOS. (#146)

Changed

  • The benchmark page opens with one simple table for the latest run. The dashboard and the site show one row per model (GLM, Opus, DeepSeek) with the verdict chip, success, tokens, cost, speed and repeats in plain words ("25 % less", "23 % faster"), a caption and one result sentence per model. All other views move into one collapsed "Show details" block. (#160)
  • The lowest benchmark verdict is SUBOPTIMAL, and few repeats can show it. The verdict code and label change from HARMFUL to SUBOPTIMAL; the text says "Result: code-context is suboptimal for these tasks." With fewer than 3 repeats, a token increase of 10 % or more gives SUBOPTIMAL (indicative), e.g. "The token use increases by 12 % in 1 repeat." The dashboard, the site, the index builder and the private-summary check read a stored HARMFUL verdict as SUBOPTIMAL. (#158)
  • bench:live retries a failed session once. A provider error, 0 model calls or a machine sleep during the session gets one retry with a fresh workspace and HOME; the run notes list every retry. The run is void only when the retry fails too. A timeout with model calls stays a model FAIL. (#146)

v2.11.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 11 Oct 03:50
Immutable release. Only release title and notes can be modified.
v2.11.0
3fcf2ec

Added

  • Dashboard Benchmark page shows real ccc-bench runs: the latest run per kind with its date and age, the run list, and per-task detail. New /api/bench/index and /api/bench/run/:id read from CODE_CONTEXT_BENCH_DIR, then <db dir>/bench/, then origin/bench-results in the package's own git checkout; otherwise an explicit empty state. The June simulated data stays as a "Simulated (2026-06)" tab. (#114)
  • CODE_CONTEXT_TOOLSETS=code: a profile that lists only the 11 code-index tools (index_directory, find_symbol, get_file_context, search_files, get_changes, query, execute, health, set_description, set_directory_description, set_change_reason). Tool definitions drop from about 12,300 to about 1,300 tokens per model call. For sessions that read code but never run the sprint process. all still wins. The default does not change. (#109)
  • Fair benchmark arms: task prompts name no tools, a third cc-guided arm adds the "use code-context first" rule to the system prompt, both code-context arms run CODE_CONTEXT_TOOLSETS=code, and sessions record the cost the CLI reports. (#111)

Changed

  • bench:publish copies the merged data/ to CODE_CONTEXT_BENCH_DIR when set (never in Actions), so the dashboard gets new runs without a manual copy. (#114)
  • README token claim quotes the fair agent runs; the 46.3 % figure is labelled as simulated in the stats and bench panels. The site notes that agent runs before 2026-10-11 used grep-steering prompts. (#113)

Fixed

  • Repo-relative paths work. get_file_context and set_description accept src/server/schema.ts as well as absolute paths: relative to the server's working directory first, then a unique suffix match in the index. With several repos in one database, the match under the working directory wins, otherwise the tool lists the candidates. Before, a relative path answered "not in index", and agents fell back to grep. (#109)
  • A provider error or a session with 0 model calls voids a live benchmark run: no run file, the artefacts stay for diagnosis. (#112)
  • The dashboard build clears old hashed chunks in dist/dashboard/assets; the 2.10.0 pack held three copies of each. (#110)

v2.10.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 11 Oct 00:13
Immutable release. Only release title and notes can be modified.
v2.10.0
05fc890

Added

  • Benchmark task ladder S → XL on the sample project and on this repo's src/; prompts state exactly what counts, and the checker uses the same whole-word rule. (#105)
  • Fresh agent sessions and an Opus provider for agent benchmarks; cache reads count as tokens; a run fails when the model changes mid-run, and the agent prompt is recorded. (#102)
  • docs/CLAUDE-PROJECT.md: steps and paste-ready instructions for a Claude project about this repo. Not part of the docs site or the npm package. (#104)

Changed

  • Dashboard in the D-41 look: Inter and Space Mono bundled with the app (Geist from a CDN removed), Space Mono logo, headings and upper-case nav labels, a 32 px grid, white pill for primary actions, card radius 24, and the literal palette mapped to the token values. (#107)
  • Benchmark site serves Inter and Space Mono from site/assets/fonts; still no third-party request. (#107)
  • Agent benchmarks run locally; Actions skips them when secrets are missing. (#101)

Fixed

  • Claude token totals come from the result event. (#106)
  • Local bench:publish starts the Pages build. (#103)
  • Every regex metacharacter is escaped in wordRe (CodeQL). (#105)

v2.9.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 10 Oct 20:57
Immutable release. Only release title and notes can be modified.
v2.9.0
4c9d963

Added

  • On-demand benchmarks. npm run bench (simulated, no model), npm run bench:live (an OpenCode agent with and without code-context) and npm run bench:publish. A new Benchmark workflow (workflow_dispatch, inputs kind and provider) pushes runs to bench-results, which rebuilds Pages. A guard test fails when a workflow gets a schedule: trigger. (#94)
  • Benchmark site in the flagship look: indigo tokens, dark and light theme, latest run first, full history, a brand hero and section dividers. (#94, #95)

Changed

  • Dashboard accent is indigo (--accent: #818cf8, new --accent-fill: #6366f1). Green (--green) now means status only: done, passed, verified, on track, saved, live. The legacy dashboard.html keeps its own tokens. (#96)
  • README benchmark numbers come from the clean run sim-20261010-203937. (#98)
  • CI: tests take OS-assigned ports; artifact actions run on Node 24. (#99)

Fixed

  • The benchmark records the git state before the simulated tests run, so a run is no longer marked dirty by its own files. (#97)

Security

  • The live benchmark agent runs in a sandbox: one preparation path for every arm, no shell, no web, no access outside its workspace. A run_id must match ^[a-z0-9][a-z0-9-]{0,80}$. (#94)

v2.8.0

Choose a tag to compare

@VelimirMueller VelimirMueller released this 09 Oct 14:31
Immutable release. Only release title and notes can be modified.
v2.8.0
dc6dd23

Fixed

  • Skill sync follows the claude_development_skills 0.7.0 layout. Upstream moved the commit and PR skills from skills/workflow/ to skills/core/. The runtime sync skipped a missing set without a word, so after the upstream v0.7.0 tag the wf: rows would have frozen at 0.6.0. The workflow set now reads skills/core/ (names stay wf:write-commit-messages etc.; the set also brings wf:set-up-stack-profile, wf:extend-skillset, wf:audit-toolchain, wf:audit-security).
  • scripts/sync-skills.mjs vendors only the catalogues skill-set-registry.json names (upstream now ships eight).
  • The commit contract reads the first sentence of the subject paragraph, so re-wrapped markdown no longer cuts the rule. The body line stays "exactly three labeled bullet groups": the QA commit gate (COMMIT_BODY_LABELS) enforces all three. The workflow playbook heading is "Core Skills".

Added

  • Python symbols and import edges in the indexer (src/server/indexer.ts, regex-based like the JS/TS parsers, no new dependencies). .py/.pyi files now get rows in exports and edges in dependencies, so find_symbol and the dependency graph work for Python repos.
    • Exports: module-level def/async def (function), class (class) and UPPER_CASE = constants (const), with the first line of the symbol's docstring as description. _-prefixed names are skipped unless listed in __all__. __all__ = [...]/(...) filters the list and adds unknown listed names as re-export. Symbols inside module-level triple-quoted strings are ignored.
    • Imports: import a.b.c, import a.b as x, comma lists, from .mod import x, y as z, parenthesised multi-line from imports and from . import mod (relative sources keep their leading dots), at module level and inside functions.
    • Resolution: relative sources go up one directory per extra dot; absolute ones are tried from the repo root and root/src; candidates are <path>.py then <path>/__init__.py, always contained in the indexed root (isPathInside). Unresolved absolute imports (stdlib, third-party) land in external_imports as their top-level package. JS/TS behaviour is unchanged.
    • search_files summaries and auto-generated file descriptions now include Python exports/imports.

npm: vlm-code-context-mcp@2.8.0. No schema change (v24).

v2.5.1 — Session log hardening

Choose a tag to compare

@VelimirMueller VelimirMueller released this 09 Oct 00:08
Immutable release. Only release title and notes can be modified.
v2.5.1
0a5ee90

Security

  • Session log refuses anything but a regular file (overdrive contract rule 2). src/sessionlog.ts now opens the log with O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW|O_NONBLOCK (mode 0600) and checks the open handle with fstat before its one write. A symlink planted at the log path no longer redirects the append into its target; a directory or fifo at the log path gets nothing written and never blocks. Errors stay swallowed. On a platform without O_NOFOLLOW the helper writes nothing.

v2.5.0 — Session log

Choose a tag to compare

@VelimirMueller VelimirMueller released this 08 Oct 23:23
Immutable release. Only release title and notes can be modified.
v2.5.0
ee663cd

Added

  • Overdrive session log — the MCP server and the dashboard append one-line breadcrumbs to the shared per-session log ${OVERDRIVE_SESSION_LOG_DIR:-~/.claude/.local_ai_setup_logs/sessions}/<CLAUDE_CODE_SESSION_ID>.log (_nosession-YYYY-MM-DD.log without a session id), in the overdrive contract format <ts>\t<LEVEL>\tcode-context@<version>\tpid=<pid>\t<message>. New helper src/sessionlog.ts (node stdlib only): one O_APPEND write per line, dir 0700 / file 0600, every error swallowed, never prints (stdout is the MCP transport), OVERDRIVE_SESSION_LOG=0 turns it off.
    • INFO — server and dashboard start (version, port, db basename), sprint phase transitions, ticket status changes, discovery/sprint archive counts, index_directory runs (file count, duration).
    • WARN — advisory gate warnings from advance_sprint / update_sprint (counts), gate-blocked ticket edits (ticket id + rule), planning-gate blocks (counts), rejected dashboard requests (401/403/421, never the token or query string; at most one line per status+path per minute, with a suppressed=<n> count), dashboard routes that throw a 4xx error (status + error class), schema migrations applied.
    • CRITICAL — exceptions escaping any MCP tool handler, dashboard routes failing with a 5xx (error class only), DB open/migration failure.
    • Only ids, counts, phases and durations are logged — never titles, descriptions, retro text, file contents, the dashboard token or SQL values. Read paths stay silent.
  • The test suite runs with OVERDRIVE_SESSION_LOG=0 so it never writes into a real session log.

Release v2.4.2

Choose a tag to compare

@VelimirMueller VelimirMueller released this 07 Oct 15:20
Immutable release. Only release title and notes can be modified.
v2.4.2
d74c18e

What's changed

  • fix(watch): skip CocoaPods Pods/ directories when watching/indexing (#73)
  • chore(skills): sync vendored skills from upstream main (#74)

Full Changelog: v2.4.1...v2.4.2