From d4f1dd2f40b1f3776b239f7132df0c08e968a8a6 Mon Sep 17 00:00:00 2001 From: Suppaseth Charoenkarnka Date: Fri, 22 May 2026 16:29:46 +0700 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20plugin-only=20trim=20=E2=80=94=20s?= =?UTF-8?q?trip=20Bun=20CLI=20source=20=C2=B7=20CHANGELOG=20split=20=C2=B7?= =?UTF-8?q?=20README=20install=20update=20(v3.0.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This repo is now strictly the OneBrain plugin (skills, agents, hooks, INSTRUCTIONS, harness configs). The legacy v2.x TypeScript/Bun CLI source has been removed; the Rust CLI lives at `onebrain-ai/onebrain-cli` and ships from its own GH Releases. Repo file changes: - rm Bun toolchain: src/ (full tree, 17k lines), package.json, bun.lock, tsconfig.json, biome.json. AGPL on the legacy code stays preserved in git history. - rm legacy repo-root CHANGELOG.md (Bun-era CLI changelog, 38 KB) - mv PLUGIN-CHANGELOG.md → CHANGELOG.md (per [[onebrain-changelog-structure]] one-changelog-per-repo rule) plugin.json: - bump 3.0.1 → 3.0.2 (manifest change + scope reduction = version bump per repo convention) CHANGELOG.md (v3.0.2 entry, 6 bullets within 8-bullet cap): - chore: plugin-only trim summary - rm Bun toolchain from root - CHANGELOG split + heading rename - README update — install paths now point at the Rust CLI (Homebrew tap, npm wrapper, GH Release direct, onebrain update self-installer); license badge MIT → AGPL-3.0-only - GH Releases on this repo wiped (separate one-off; see follow-up) README.md: - Update version badge from npm to GH Release on onebrain-ai/onebrain-cli - License badge MIT → AGPL-3.0-only - Install section rewrite: brew tap + npm wrapper + GH Release direct + self- update path, with link to onebrain-ai/onebrain-cli - Drop "Optional bun" hint — v3 is a self-contained Rust binary - Auto Checkpoint footnote updated with both install paths Separately (NOT in this PR diff): all 39 GH Releases (v2.0.0 → v2.3.3) and matching v2.x tags will be deleted from onebrain-ai/onebrain after merge. Canonical Releases stream is onebrain-ai/onebrain-cli/releases going forward. --- .../onebrain/.claude-plugin/plugin.json | 2 +- CHANGELOG.md | 706 ++++++---- PLUGIN-CHANGELOG.md | 537 -------- README.md | 28 +- biome.json | 41 - bun.lock | 62 - package.json | 49 - src/commands/doctor.test.ts | 984 -------------- src/commands/doctor.ts | 584 -------- src/commands/init.integration.test.ts | 359 ----- src/commands/init.test.ts | 422 ------ src/commands/init.ts | 745 ----------- .../__snapshots__/checkpoint.test.ts.snap | 12 - .../__snapshots__/orphan-scan.test.ts.snap | 13 - .../__snapshots__/session-init.test.ts.snap | 15 - src/commands/internal/checkpoint.test.ts | 526 -------- src/commands/internal/checkpoint.ts | 355 ----- src/commands/internal/cli-banner.test.ts | 252 ---- src/commands/internal/cli-banner.ts | 617 --------- src/commands/internal/cli-ui.ts | 148 -- src/commands/internal/harness.test.ts | 136 -- src/commands/internal/harness.ts | 61 - src/commands/internal/migrate.test.ts | 336 ----- src/commands/internal/migrate.ts | 216 --- src/commands/internal/orphan-scan.test.ts | 699 ---------- src/commands/internal/orphan-scan.ts | 424 ------ src/commands/internal/qmd-reindex.test.ts | 136 -- src/commands/internal/qmd-reindex.ts | 56 - src/commands/internal/register-hooks.test.ts | 1191 ----------------- src/commands/internal/register-hooks.ts | 620 --------- src/commands/internal/session-init.test.ts | 678 ---------- src/commands/internal/session-init.ts | 469 ------- src/commands/internal/vault-sync.test.ts | 1017 -------------- src/commands/internal/vault-sync.ts | 968 -------------- src/commands/register-schedule.test.ts | 367 ----- src/commands/register-schedule.ts | 327 ----- src/commands/run-skill.test.ts | 286 ---- src/commands/run-skill.ts | 108 -- src/commands/update.integration.test.ts | 249 ---- src/commands/update.test.ts | 283 ---- src/commands/update.ts | 328 ----- src/index.ts | 238 ---- src/lib/fs-atomic.test.ts | 74 - src/lib/fs-atomic.ts | 21 - src/lib/fs-mkdir-safe.test.ts | 73 - src/lib/fs-mkdir-safe.ts | 50 - src/lib/index.test.ts | 640 --------- src/lib/index.ts | 27 - src/lib/parser.ts | 105 -- src/lib/patch-utf8.test.ts | 93 -- src/lib/patch-utf8.ts | 26 - src/lib/scheduler/cron-parse.test.ts | 88 -- src/lib/scheduler/cron-parse.ts | 79 -- src/lib/scheduler/entry.test.ts | 89 -- src/lib/scheduler/entry.ts | 59 - src/lib/scheduler/launchd.test.ts | 153 --- src/lib/scheduler/launchd.ts | 131 -- src/lib/scheduler/log-paths.test.ts | 14 - src/lib/scheduler/log-paths.ts | 13 - src/lib/scheduler/types.ts | 24 - src/lib/types.ts | 54 - src/lib/validator.ts | 760 ----------- src/scripts/postinstall.test.ts | 20 - src/scripts/postinstall.ts | 141 -- tsconfig.json | 21 - 65 files changed, 470 insertions(+), 17935 deletions(-) delete mode 100644 PLUGIN-CHANGELOG.md delete mode 100644 biome.json delete mode 100644 bun.lock delete mode 100644 package.json delete mode 100644 src/commands/doctor.test.ts delete mode 100644 src/commands/doctor.ts delete mode 100644 src/commands/init.integration.test.ts delete mode 100644 src/commands/init.test.ts delete mode 100644 src/commands/init.ts delete mode 100644 src/commands/internal/__snapshots__/checkpoint.test.ts.snap delete mode 100644 src/commands/internal/__snapshots__/orphan-scan.test.ts.snap delete mode 100644 src/commands/internal/__snapshots__/session-init.test.ts.snap delete mode 100644 src/commands/internal/checkpoint.test.ts delete mode 100644 src/commands/internal/checkpoint.ts delete mode 100644 src/commands/internal/cli-banner.test.ts delete mode 100644 src/commands/internal/cli-banner.ts delete mode 100644 src/commands/internal/cli-ui.ts delete mode 100644 src/commands/internal/harness.test.ts delete mode 100644 src/commands/internal/harness.ts delete mode 100644 src/commands/internal/migrate.test.ts delete mode 100644 src/commands/internal/migrate.ts delete mode 100644 src/commands/internal/orphan-scan.test.ts delete mode 100644 src/commands/internal/orphan-scan.ts delete mode 100644 src/commands/internal/qmd-reindex.test.ts delete mode 100644 src/commands/internal/qmd-reindex.ts delete mode 100644 src/commands/internal/register-hooks.test.ts delete mode 100644 src/commands/internal/register-hooks.ts delete mode 100644 src/commands/internal/session-init.test.ts delete mode 100644 src/commands/internal/session-init.ts delete mode 100644 src/commands/internal/vault-sync.test.ts delete mode 100644 src/commands/internal/vault-sync.ts delete mode 100644 src/commands/register-schedule.test.ts delete mode 100644 src/commands/register-schedule.ts delete mode 100644 src/commands/run-skill.test.ts delete mode 100644 src/commands/run-skill.ts delete mode 100644 src/commands/update.integration.test.ts delete mode 100644 src/commands/update.test.ts delete mode 100644 src/commands/update.ts delete mode 100644 src/index.ts delete mode 100644 src/lib/fs-atomic.test.ts delete mode 100644 src/lib/fs-atomic.ts delete mode 100644 src/lib/fs-mkdir-safe.test.ts delete mode 100644 src/lib/fs-mkdir-safe.ts delete mode 100644 src/lib/index.test.ts delete mode 100644 src/lib/index.ts delete mode 100644 src/lib/parser.ts delete mode 100644 src/lib/patch-utf8.test.ts delete mode 100644 src/lib/patch-utf8.ts delete mode 100644 src/lib/scheduler/cron-parse.test.ts delete mode 100644 src/lib/scheduler/cron-parse.ts delete mode 100644 src/lib/scheduler/entry.test.ts delete mode 100644 src/lib/scheduler/entry.ts delete mode 100644 src/lib/scheduler/launchd.test.ts delete mode 100644 src/lib/scheduler/launchd.ts delete mode 100644 src/lib/scheduler/log-paths.test.ts delete mode 100644 src/lib/scheduler/log-paths.ts delete mode 100644 src/lib/scheduler/types.ts delete mode 100644 src/lib/types.ts delete mode 100644 src/lib/validator.ts delete mode 100644 src/scripts/postinstall.test.ts delete mode 100644 src/scripts/postinstall.ts delete mode 100644 tsconfig.json diff --git a/.claude/plugins/onebrain/.claude-plugin/plugin.json b/.claude/plugins/onebrain/.claude-plugin/plugin.json index 0204f28c..8c5e39d2 100644 --- a/.claude/plugins/onebrain/.claude-plugin/plugin.json +++ b/.claude/plugins/onebrain/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "onebrain", - "version": "3.0.1", + "version": "3.0.2", "description": "OneBrain — Where human and AI thinking become one. A powerful thinking partner powered by AI synergy.", "author": { "name": "OneBrain Contributors" diff --git a/CHANGELOG.md b/CHANGELOG.md index f185b7e7..4e082a30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,356 +1,546 @@ --- -latest_version: 2.3.3 -released: 2026-05-13 +latest_version: 3.0.2 +released: 2026-05-22 --- -# CLI Changelog +# Changelog -All notable changes to the OneBrain CLI binary (`@onebrain-ai/cli`). +All notable changes to the OneBrain plugin — i.e., any vault-deployed content (Claude plugin under `.claude/plugins/onebrain/`, Gemini config under `.gemini/`, future harness configs). Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -> **Versioning:** CLI version is tracked in `package.json`. Bump only when TypeScript source changes. -> For plugin changes (skills, agents, hooks, INSTRUCTIONS), see [PLUGIN-CHANGELOG.md](PLUGIN-CHANGELOG.md). +> **Versioning:** Plugin version is tracked in `plugin.json`. Bump when ANY harness config changes — skills, agents, hooks, INSTRUCTIONS, Gemini settings, slash commands, etc. +> For CLI binary changes, see the [`onebrain-ai/onebrain-cli`](https://github.com/onebrain-ai/onebrain-cli/blob/main/CHANGELOG.md) repository. + +## v3.0.2 — 2026-05-22 + +- **chore: plugin-only trim** — this repo is now strictly the OneBrain plugin (skills, agents, hooks, INSTRUCTIONS, harness configs). The legacy v2.x TypeScript/Bun CLI source has been removed; the Rust CLI lives at [`onebrain-ai/onebrain-cli`](https://github.com/onebrain-ai/onebrain-cli) and ships from its own GitHub Releases. +- **rm Bun toolchain from repo root**: `src/`, `package.json`, `bun.lock`, `tsconfig.json`, `biome.json`. AGPL on the legacy code stays preserved in git history. +- **CHANGELOG split**: previous repo-root `CHANGELOG.md` was the legacy CLI changelog — removed. `PLUGIN-CHANGELOG.md` renamed to `CHANGELOG.md` (one changelog per repo per [`[[onebrain-changelog-structure]]`](../05-agent/memory/onebrain-changelog-structure.md)). All historical plugin entries preserved verbatim. +- **README update**: install instructions now point at the Rust CLI install paths (Homebrew tap, npm wrapper `@onebrain-ai/cli@3.0.0+`, GitHub Releases direct download, `onebrain update` self-installer). License badge MIT → AGPL-3.0-only (matches the [`v3.0.1` relicense](#v301--2026-05-22)). +- **GitHub Releases**: all 39 Bun-era releases (v2.0.0 → v2.3.3) and matching tags removed from this repo. The plugin repo no longer publishes Releases — the canonical Releases stream is [`onebrain-ai/onebrain-cli/releases`](https://github.com/onebrain-ai/onebrain-cli/releases). +- **No skill / hook / agent code changes** in this release — purely repo trim + manifest. + +## v3.0.1 — 2026-05-22 + +- **chore: relicense MIT → AGPL-3.0-only** to align with the OneBrain CLI (`onebrain-ai/onebrain-cli`), which has shipped under AGPL since v3.0.0-alpha.0. Same license now spans the binary and the plugin manifest / skills / hooks that consume it, so the network-use copyleft (AGPL §13) applies consistently across the whole OneBrain runtime. +- **LICENSE**: replaced 21-line MIT text with the canonical 661-line GNU Affero General Public License v3. +- **plugin.json**: added `"license": "AGPL-3.0-only"` field. Previously absent; existing copies of the plugin (v2.x and v3.0.0) inherited the repo-root LICENSE — explicit field documents intent at the manifest level. +- **plugin.json**: bump `3.0.0` → `3.0.1` for the license-field addition (manifest change ⇒ version bump per repo convention). +- **MIT compatibility**: prior releases (v2.x through v3.0.0) remain available under MIT for downstream users who pinned to those versions. AGPL applies from v3.0.1 forward. +- **No skill / hook / agent code changes** in this release — purely the license + manifest update. + +## v3.0.0 — 2026-05-22 + +- **feat(plugin.json): pin plugin to CLI v3.0+** — adds `requires.cli: ">=3.0.0"` field. Aligned with the OneBrain CLI v3.0.0 (Rust) GA shipped 2026-05-22. The pin in PR #180 was reverted in PR #181 because the CLI wasn't ready; this re-applies it now that v3.0.0 is live. +- **feat(hooks): SessionStart enforcement hook** — new `hooks/hooks.json` + `hooks/check-cli-version.sh` emits a `decision: block` JSON payload when the plugin boots alongside a CLI older than v3.0.0 (or no CLI on PATH); Claude Code refuses to start the session on that payload. Passes silently when v3.x is present. Pairs with the `requires.cli` field — the field is metadata for tooling, the hook is the runtime enforcement. Hook execution capped at 10 s via `timeout` in `hooks.json`. +- **chore(plugin.json): bump 2.4.14 → 3.0.0** — major-version break: this plugin release refuses to load against v2.x Bun-era CLIs. Existing v2.x users will see the SessionStart `decision: block` until they `onebrain update` (or reinstall via the new Homebrew tap / forthcoming npm wrapper). +- **Version comparison strategy**: hook extracts bare `MAJOR.MINOR.PATCH` via `grep -oE` (strips prerelease suffixes), then walks a pure-bash integer compare per field against the v3.0.0 floor. No dependency on GNU `sort -V` (absent from some older macOS BSD `sort` builds). Practical effect: any v3.0.0-alpha.x user passes (they're already on the Rust binary), only v2.x is blocked. +- **Distribution channels live at this release**: GitHub Releases (canonical, since v3.0.0 GA), Homebrew tap (`onebrain-ai/homebrew-onebrain` → `brew install onebrain-ai/onebrain/onebrain`), `onebrain update` self-installer. +- **What is NOT in this PR** (tracked for a follow-up plugin-trim PR per `[[onebrain-skill-design]]` single-responsibility): plugin repo README rewrite, trim to plugin-only (move CLI legacy `CHANGELOG.md` out of this repo), rename `PLUGIN-CHANGELOG.md` → `CHANGELOG.md`. Today's PR is scoped strictly to the pin + the runtime enforcement. + +## v2.4.14 — 2026-05-20 + +- chore: revert the "pin plugin to CLI v3.0 (Rust)" PR (#180). Keeping the plugin compatible with both the Bun v2.3.3 CLI and the in-flight v3.0.0-alpha.* line until the Rust port reaches GA. The `requires.cli` pin will be re-applied (likely to `>=3.0.0`) once the CLI GA tag ships. +- Plugin version stays at 2.4.x; the previous bump to `3.0.0-alpha.1` in PR #180 was a leading-edge signal that turned out to be premature. + +## v2.4.13 — 2026-05-19 + +- docs(update): add Known Gotcha about WebFetch returning summarized markdown — recommend `curl -fsSL` for raw-content fetches (`plugin.json`/`settings.json` JSON parsing, `PLUGIN-CHANGELOG.md` verbatim display, `SKILL.md` self-update bootstrap). Symptoms section helps diagnose silent corruption from summarized fetches. +- docs(update): add inline ⚠️ pointers at the four WebFetch call sites (version check, changelog display, SKILL.md bootstrap, settings.json merge) directing readers to the Known Gotcha when raw-content semantics matter — closes the "warning lives at the bottom but step prose says use WebFetch" coherence gap. + +## v2.4.12 — 2026-05-13 + +- docs(INSTRUCTIONS): rewrite "Headless invocation" section to describe the real contract — scheduler now goes through `onebrain run-skill` which spawns `claude -p "/skill args" --add-dir ` (the previous `claude --vault X --skill /name --headless` shape was never implemented on any binary; see CLI v2.3.3 for the fix) +- docs(INSTRUCTIONS): document `CLAUDE_BIN` env override for setups where `claude` is installed outside the probe list (`~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`) +- docs(INSTRUCTIONS): clarify that skill `args:` map values are appended as `key=value` tokens to the slash-command prompt and reach skills via Claude Code's standard ARGUMENTS slot + +## v2.4.11 — 2026-05-12 + +- docs(doctor): update SKILL.md hook-check description to match new validator behavior — effective command = `command` joined with `args[]`, so canonical exec-form `{command: "onebrain", args: ["checkpoint", "stop"]}` is recognized alongside legacy shell form + +## v2.4.10 — 2026-05-12 + +- feat(pause): new `/pause` skill saves snapshot of long-running work to `07-logs/pause/`; non-terminal — does not clear context +- feat(resume): new `/resume` skill loads active pause-thread state in fresh sessions; idempotent in same-session +- feat(wrapup): Step 0 detects active pause thread; "Yes" branch consolidates all pause files of slug + current checkpoints into one session log +- feat(wrapup, auto-summary): auto-finalize active pause thread before daily session log write (3 skip conditions prevent noise) +- feat(startup): banner shows `📂 active pause: {slug} ({N} snapshots)` when `_active.md` present +- feat(doctor): 3 new pause health checks (orphan pointer, missing pointer, idle > 14d) +- docs(instructions): wire `/pause` `/resume` into skills table, vault structure, file naming, routing, response profiles +- docs(session-formats): add Pause File Format + `synthesized_from_pause` session-log frontmatter case + +## 2.4.9 — 2026-05-12 + +- `/schedule-add` Step 0 first-run preset selector — Minimal / Essentials / Maintenance Plus / Custom (E15-B) +- `/onboarding` adds preset selection step after agent identity setup (default = Essentials) +- Canonical preset tier definitions at `_shared/schedule-presets.md` — single source of truth +- Tier 3 preset mixes skill-mode and command-mode entries (live example of E15-A schema) +- INSTRUCTIONS.md + README + CONTRIBUTING document preset bundles + +## 2.4.8 — 2026-05-12 + +- `/schedule-list` displays both skill-mode (`skill: /name (k=v)`) and command-mode (`cmd: binary arg1 arg2`) entries +- INSTRUCTIONS.md adds "Skill mode vs command mode" subsection with full YAML example +- README + CONTRIBUTING document command mode as alternative to thin wrapper skills +- Companion to CLI v2.3.1 which introduces the command-mode backend + +## 2.4.7 — 2026-05-12 + +- 4 new wizard skills: `/schedule-add` (recurring), `/schedule-once` (one-shot), `/schedule-list`, `/schedule-remove` (E9.1) +- 26 user-facing skills declare `schedulable:` / `schedulable_with_args:` frontmatter — gates which skills the CLI scheduler accepts (E9.4) +- `/doctor` extended with Scheduler Health section: scans `.err.md` files, detects drift between `vault.yml` and installed plists, flags 3+ consecutive failures + expired one-shots (E9.2) +- INSTRUCTIONS.md adds "Scheduling — which tool to use" + "Headless invocation" sections (E9.3) — disambiguates OneBrain scheduler vs Claude Code `/loop` and `/schedule` +- `/help` MAINTAIN tier lists the 4 new schedule commands + +## 2.4.6 — 2026-05-12 + +- Remove vault-author-specific references from plugin source for genericity +- /search: drop hardcoded `[projects_folder]/onebrain/plans/*.md` source; replace with generic `[projects_folder]/**/*.md` covering embedded specs/plans/design docs (keeps search coverage for projects with any folder layout) +- /search: replace hardcoded vault folder names with `[knowledge_folder]`/`[projects_folder]`/`[resources_folder]`/`[areas_folder]` placeholders; update progress line + frontmatter description to match +- /clone: replace personal example path with generic `/path/to/source/vault` in audit-log template +- /capture, /consolidate: replace concrete vault-author note paths in routing/moved examples with `[folder]/example/...` placeholders + +## 2.4.5 — 2026-05-12 + +- Hot-fix: enforced English-only across /search per `onebrain-repo-english-only` rule +- Removed non-English auto-invoke triggers; kept 3 English: `search vault`, `find in vault`, `why did` +- Removed non-English example phrases and regex tokens from SKILL.md body + references + INSTRUCTIONS routing description +- Removed premature `schedulable` / `schedulable_with_args` / `required_args` frontmatter (defer to E9 scheduler shipping in a later PR) +- Bilingual user input still routes via agent's intent matching on the English description; non-English literals were redundant + +## 2.4.4 — 2026-05-12 + +- New skill /search — general vault retrieval (E5) +- Answers both what + why questions across MEMORY/memory/sessions/plans/decisions logs/notes +- Uses qmd (lex+vec+hyde) with grep fallback +- Auto-invoke triggers: `search vault`, `find in vault`, `why did` (initial entry shipped with non-English triggers; hot-fixed in 2.4.5) +- Registered under 🔍 RECALL tier in /help + +## 2.4.3 — 2026-05-12 + +- Added `## Progress reporting` section to 6 long-running skills (E3) +- Skills updated: /research, /consolidate, /distill, /reorganize, /connect, /import +- Format: `→ [step N/M] ` emitted at each major step +- Trust improvement during multi-step skill runs + +## 2.4.2 — 2026-05-12 + +- /help reorganized into 4 Workflow tiers: 📥 INPUT · ⚙️ PROCESS · 🔍 RECALL · 🔧 MAINTAIN +- /onboarding moved from Maintain → Input (first run only) +- README skill list reordered to mirror tier structure +- Discoverability win for new users; existing users now see skills by phase ## [Unreleased] -## v2.3.3 — fix(scheduler): make scheduled skills actually run +## v2.4.1 — fix(qmd, /update): drop stale `--qmd` / `--remove-qmd` flags from docs + +CLI dropped both `--qmd` and `--remove-qmd` from `onebrain register-hooks` in v2.1.0 (auto-detects from `vault.yml`'s `qmd_collection` instead — present registers the hook, absent strips it). Three plugin docs still told users and `/update` to pass these flags. On Windows after upgrading to CLI v2.2.1+, both `/update` and `/qmd uninstall` surfaced this as `unknown option` errors from commander. + +- fix(skills/qmd/SKILL.md): Step 8 (`/qmd setup`) and Step 4b (`/qmd uninstall`) now run `onebrain register-hooks` (no flag); auto-detects from vault.yml. +- fix(skills/update/references/migration-steps.md): Step 6 merges the qmd-hook bullet into the unconditional `register-hooks` call — no separate `--qmd` invocation. + +## v2.4.0 — feat(07-logs): subfolder restructure + per-skill log entries + +Restructure `07-logs/` into 4 typed subfolders and add audit log entries for 12 skills. Companion CLI release v2.2.2 updates `orphan-scan` and the Stop hook's NN-counting helper to read from the new flat `checkpoint/` directory. + +- feat(07-logs): split into `session/YYYY/MM/`, `checkpoint/` (flat), `update/` (flat), `log/YYYY/MM/`. Mental model: session/checkpoint = NN per run, everything else = append per day. +- feat(/update Step 0): idempotent migration moves files to the new layout (preserve YYYY/MM for session; flatten checkpoint + update). Detect-by-residual-files re-runs cleanly on interrupt. +- feat(startup): legacy structure detection nudges /update with a one-line banner; orphan-scan fallback auto-detects pre- vs post-v2.4.0 layout (multi-vault user safety). +- feat(skills): /recap, /distill, /memory-review, /learn, /consolidate, /connect, /reorganize, /onboarding, /qmd, /clone, /doctor, /weekly each write an audit log to `log/YYYY/MM/`. Shared `_shared/audit-log-format.md` reference deduplicates frontmatter + append-per-day algorithm + run-section heading + failure-mode rules. +- feat(audit-log frontmatter): canonical 3-field schema (`tags: [audit-log, X]`, `skill: /X`, `date: YYYY-MM-DD`) across all skill audit logs; per-skill discriminators (topic, subcommand, mode, path, version). Tag taxonomy unified — `[doctor-log]`, `[update-log]`, `[weekly-review]` flipped to the `[audit-log, X]` umbrella so a single Obsidian `tag:#audit-log` query surfaces every skill run. +- feat(session log + checkpoint frontmatter): `session_token: ` added to all 5 Session Log Format cases and the Checkpoint Format. Token previously lived only in checkpoint filenames; cross-referencing a session log to its checkpoints required parsing filenames. Now `rg "session_token: abc12345" 07-logs/` surfaces every artifact for that session. +- feat(/wrapup): orphan recovery reads flat `checkpoint/`, writes to `session/YYYY/MM/`. Cross-midnight handling simplified to filename-date math. Progress signal for N>3 orphan groups. CRLF-safe marker check. +- feat(/doctor): 07-logs structure check (verifies the 4 subfolders); housekeeping warning at >1000 log files. /reorganize now aborts if pre-v2.4.0 structure is detected (run /update first). +- fix(checkpoint-hook.sh + checkpoint.ts): both write to and read from flat `checkpoint/`. Pre-fix, NN counting was reading from legacy `YYYY/MM/` path → every checkpoint after migration would have collided at NN=01. +- fix(/update backup): `[archive_folder]/[agent_folder]/...` instead of hardcoded `05-agent` so users who remapped `folders.agent` see backups land in the matching subfolder. +- fix(migrate.ts runBackfillRecapped): walks `[logs_folder]/session/YYYY/MM/` post-v2.4.0 (was walking `[logs_folder]/YYYY/MM/` and silently skipping all session logs). + +## v2.3.4 — docs(instructions): establish 11 iron-rule Working Principles + +Promote `## Working Principles` in `INSTRUCTIONS.md` from 4 unnumbered guidelines to 11 numbered iron rules with a precedence-stating intro. These are non-negotiable defaults that apply across every session, every skill, every workflow — and explicitly take precedence over skill-specific instructions when in conflict. Synthesised from a 60+ memory audit, an insights-report friction analysis, and 29 reviewer-passes across 15 distinct role perspectives (writer, designer, student, PM, lawyer, doctor, therapist, teacher, sales, fiction author, financial analyst, journalist, founder, translator, dev) so the language survives universally — neither dev-jargon nor watered-down for technical work. + +- docs(INSTRUCTIONS.md): convert `## Working Principles` to numbered list with intro stating these rules outrank skill-specific instructions when they conflict. +- docs(INSTRUCTIONS.md): new rules — *Speak in the user's vocabulary · Verify before asserting · Find the cause, not the symptom · Show a draft before extensive work · Update plan and task status in real time · Don't make the user wait · Update on evidence, not pressure · Carry changes through to related places.* +- docs(INSTRUCTIONS.md): rewrite original 4 rules per cross-role review — drop dev-only references (`AskUserQuestion`, slash-command exception list, "refactor"); merge "Surgical changes" into "Minimal footprint" with cleanup-after-yourself extension; add verifiable-criteria preference to "Define success". +- docs(INSTRUCTIONS.md): each rule body now includes register-matching, root-cause depth, draft-first for structural work, streaming-vs-background nuance, and explicit code-context coverage (callers, tests, types, migrations) — keeping rigor for dev users while staying accessible to writers, students, lawyers, clinicians, and operators. +- docs(INSTRUCTIONS.md): bullet 11 restructured per round-3 cross-role consensus — universal list (other notes, files that reference it, similar cases) leads, dev-specific examples fenced as `(in code: …)` so non-dev readers have a clear visual signal to skim past while dev users keep their precision. + +## v2.3.3 — feat(wrapup): PR #156 follow-ups (configurable threshold + recovered-log marker + fallback row) + +Three PR #156 follow-ups bundled. CLI track ships matching changes in v2.3.0 (see [CHANGELOG.md](CHANGELOG.md)). + +- feat(wrapup/SKILL.md): Step 1b resolves `threshold_minutes = max(60, 2 * checkpoint.minutes)` from vault.yml once before scanning groups (was: hard-coded 60). Users who raised `checkpoint.minutes` to 60/90 now get a proportionally larger guard. Missing/malformed vault.yml falls back to 60-min default — recovery is critical-path, never block on config issues. Cross-link to the symmetric CLI helper documents the contract. +- feat(session-formats.md, wrapup/SKILL.md): standardise the `` body marker for recovered session logs. The `already-recovered` short-circuit (Step 1b → step a) now matches via the marker instead of `case: recovered` frontmatter — version-independent, harness-independent, names the specific token+date pair so multi-group recovery logs short-circuit per group rather than as a whole. +- fix(wrapup/SKILL.md): the marker match is **anchored to start-of-line**, not bare substring. A session log that quotes the marker as documentation in mid-paragraph cannot trigger a false short-circuit (which would have destructively deleted checkpoints based on a documentation quote). Spec text in session-formats.md tightened in lockstep. +- fix(wrapup/SKILL.md): step (f) now re-reads the recovered session log and verifies the marker survived the write before falling through to step (g)'s checkpoint delete. If the marker is missing (LLM omission / partial write / encoding glitch), recovery aborts for that group: no delete, recovered-log path lands in `orphaned_recovered_logs`, and `skipped_active` records `marker_write_failed` for each file. This converts a silent destructive duplicate into an investigable skip. +- feat(wrapup/SKILL.md): new `marker_write_failed` enum value added to `skipped_active.reason` with its own row in the `{reason_summary}` rendering table. +- feat(wrapup/SKILL.md): `{reason_summary}` rendering table gets a catch-all fallback row for unmapped enum values. The surface signal stays generic so a missing explicit row is visible to the user and prompts contributors to add the proper mapping. Cross-linked to the enum definition at the top of Step 1b so future contributors who add a new `reason` value see both anchors. + +## v2.3.2 — refactor(update): delegate CLI bump to `onebrain update` + +`/update`'s "CLI Version Check" section was duplicating logic that the `onebrain update` CLI already owns: GitHub release lookup, package-manager detection, install, and binary validation. The skill now defers to the CLI as the single source of truth for the CLI bump. + +- refactor(update/SKILL.md): replace 30-line "CLI Version Check" block (raw `npm view` + AskUserQuestion + per-shell bun/npm detection + `npm install -g` / `bun install -g`) with a 3-step delegation: probe `onebrain --version`, run `onebrain update`, surface non-zero exits. +- refactor(update/SKILL.md): drop the npm/bun selection prompt — `onebrain update` already picks `bun` on macOS/Linux and `npm` on Windows; user already consented to `/update` upstream, so a second AskUserQuestion is noise. +- docs(update/SKILL.md): add Known Gotcha — raw `npm install -g` / `bun install -g` calls are reserved for first-time CLI bootstrap (README/install scripts), never `/update`. +- note: pure SKILL.md change, no CLI/binary change. CLI version unchanged at 2.2.0. + +## v2.3.1 — fix(wrapup): active-session guard prevents cross-harness checkpoint loss + +Wrapup's orphan recovery (Step 1b) auto-recovered any non-current-token checkpoint into a synthesised session log and deleted the originals — including in-flight checkpoints belonging to a *different live harness* in the same vault. Closes the cross-harness contamination path observed when running Claude + Gemini concurrently. + +- fix(wrapup/SKILL.md): add Active-Session Guard to Step 1b — for each orphan group, stat the newest checkpoint mtime; if `age_minutes < 60`, skip recovery (do not read, do not write a session log, do not delete) and surface in the Step 7 report as `skipped_active`. +- fix(wrapup/SKILL.md): explicit fail-safe — any stat error, unparseable mtime, or negative age forces skip-active. Destructive default on ambiguity is forbidden. +- fix(wrapup/SKILL.md): pre-delete re-stat in step 1b/f aborts the delete (and removes the just-written recovered log) if the owning session wrote a new checkpoint mid-recovery — closes the read→write→delete race. +- fix(wrapup/SKILL.md): exact `stat -f '%m'` (BSD) / `stat -c '%Y'` (GNU) commands spelled out so the LLM doesn't pick the wrong flag silently across platforms. +- fix(wrapup/SKILL.md): Step 7 `skipped_active` block is now MUST-emit (not soft-conditional) and renders `{path, age_minutes}` tuples — the user's only signal that a parallel harness owns checkpoints on disk. +- note: 60-minute threshold gives a buffer of two full auto-checkpoint windows (hook fires every 15 messages or 30 minutes). False-positives (idle but live sessions > 60 min) remain non-destructive — the owning user's next /wrapup consumes its own checkpoints. +- note: pure SKILL.md change, no CLI/binary change. CLI version unchanged at 2.2.0. + +## v2.3.0 — feat(gemini): project-level `.gemini/` config alongside `.claude/` + +Project-level `.gemini/` config ships alongside the Claude plugin so a single `onebrain init` (or `/update`) sets up both harnesses in the user's vault. Skills, agents, and INSTRUCTIONS stay single-source-of-truth in `.claude/plugins/onebrain/` — both harnesses reference them on demand, no duplication. + +- feat(.gemini/settings.json): declarative hooks — `AfterAgent` (matcher `*`) → `onebrain checkpoint stop` (= Claude `Stop` parity); `AfterTool` (matcher `write_file|replace`, regex against Gemini's actual tool names) → `onebrain qmd-reindex` (= Claude `PostToolUse` parity). Both wrapped as `{cmd} > /dev/null 2>&1; echo '{}'` to satisfy Gemini's JSON-on-stdout protocol. +- feat(.gemini/settings.json): `model.disableLoopDetection: true` so legitimate multi-file skill activations (e.g. `/onebrain:help` reading SKILL.md + plugin.json + skills folder) don't trip Gemini's repetitive-tool-call heuristic. +- feat(.gemini/commands/onebrain): 25 hand-curated `.toml` slash commands under the `onebrain:` namespace (`/onebrain:braindump`, `/onebrain:capture`, ...). Namespacing avoids collisions with Gemini built-ins (`/help`, `/tasks`) and mirrors the Claude plugin path. Tab-complete on the suffix works (`/dail` → `/onebrain:daily`). +- note: this release establishes the unified-plugin policy — anything inside `.claude/plugins/onebrain/` OR `.gemini/` (or future harness configs) bumps the plugin track. CLI track (`package.json`) stays independent for TS source changes only. +- note: distribution — `vault-sync` (CLI v2.2.0+) auto-deploys `.gemini/` to the vault root alongside `.claude/plugins/onebrain/`. No manual install step required. + +## v2.2.5 — fix: Windows skill + script compat (PowerShell / cmd / native Python) + +Audit pass over every skill snippet that assumed Bash / Unix-only tooling. Closes #128, #129, #130. + +- fix(open-in-obsidian.sh): use `cygpath -m` on MINGW/CYGWIN/MSYS to emit `C:/...` paths Obsidian accepts; percent-encode the URI so spaces and `#`/`&`/`?` in vault paths or filenames no longer truncate the launch (#130) +- fix(reading-notes): default filename template uses ` - ` instead of ` : ` so notes save on NTFS without truncation; gotcha note removed (#130) +- fix(import/markitdown-setup): drop the WSL-only gate on Windows; detect `python3` / `python` / `py -3` (and matching `pip` / `py -3 -m pip`) so native Windows installs can install markitdown (#128) +- fix(qmd setup): replace `openssl rand -hex 3` / `python3 -c …` with `node -e "…randomBytes(3)…"`; `basename` swapped for a Node one-liner — Node is portable and already required by the CLI (#128) +- fix(skills): cross-platform shell guidance — `which X || where X` for package detection; describe outcome (mkdir / mv / cp / rm / ls) so the model picks the shell-native form on PowerShell/cmd; drop `"$PWD"` from `onebrain vault-sync` (CLI defaults to cwd) (#129) +- fix(INSTRUCTIONS startup): replace `LC_ALL=en_US.UTF-8 grep -r …` with the Grep tool — UTF-8 handling is platform-correct and PowerShell can dispatch it (#129) +- fix(doctor SKILL): always strip trailing whitespace from vault.yml-derived paths (CRLF on Windows); normalize `installPath` separators before substring checks against the cache dir (#129) +- fix(skills/help, /onboarding, /learn): use `$HOME` / `$env:USERPROFILE` instead of the literal `~` for Glob/Read calls — the Glob tool does not expand tildes (#129) + +## v2.2.4 — feat(update): backfill vault-side config drift after migration + +- feat(/update SKILL): Step 8 now adds `update_channel: stable` to vault.yml when missing +- feat(/update SKILL): new Step 9 rewrites stale `extraKnownMarketplaces.onebrain.source.repo` (`kengio/onebrain` → `onebrain-ai/onebrain`) in vault `.claude/settings.json` + +## v2.2.3 — fix: session-log glob across /wrapup, /daily, /weekly, /distill, /reorganize, INSTRUCTIONS + +Same class of bug across multiple skills: globbing `[logs_folder]/.../*.md` matches checkpoint files (`*-checkpoint-*.md`) and `/update` migration logs (`*-update-*.md`) in addition to actual session logs. Tightened every affected pattern to `*-session-*.md` and added an inline note explaining why so it doesn't drift back. + +- fix(/wrapup SKILL): Step 6 recap-reminder glob narrowed from `07-logs/YYYY/MM/*.md` to `*-session-*.md`. The bare `*.md` pattern was inflating the displayed unrecapped count (reporting 10 unrecapped when only 2 actual session logs were unrecapped). +- fix(/daily SKILL): Phase 1 "find most recent session log" glob narrowed to `*-session-*.md`. Previously a more recent checkpoint or `/update` log could be picked as "most recent", causing the briefing to read the wrong file. +- fix(/weekly SKILL): Step 1 weekly file list narrowed to `*-session-*.md` so the review doesn't include checkpoint or update logs. +- fix(/distill SKILL): Step 2 session-log search narrowed to `*-session-*.md` so non-session files in the logs folder don't contribute distillation content. +- fix(/reorganize SKILL): flat-root logs glob narrowed from `[logs_folder]/*.md` to `*-session-*.md` so a flat checkpoint or update log isn't treated as a legacy session log to migrate. +- fix(INSTRUCTIONS Recalling Information): Step 3 grep hint now specifies `**/*-session-*.md` so the agent doesn't default to bare `*.md` when searching past decisions. + +## v2.2.2 — chore: migrate to onebrain-ai org + +- chore(/update SKILL): raw GitHub URL templates updated to `onebrain-ai/onebrain` for plugin file fetches +- chore(plugin.json): version bump aligned with CLI v2.1.7 org migration +- note: existing vaults still work via GitHub auto-redirect; `/update` will pick up new URLs going forward + +## v2.2.1 — fix: align with CLI v2.1.6 (Stop-hook-only) + +- fix(INSTRUCTIONS): drop entire PostCompact section (Path A/B + auto-wrapup routing). Single dispatch row — `NN since ` → write checkpoint. Note added explaining why PostCompact + PreCompact are not registered +- feat(/wrapup + AUTO-SUMMARY): explicit **preservation rule** — deduplicate, don't summarize. Every unique decision, action item, learning, and topic must appear in the session log. No length cap. Heuristic: combined Key Decisions + Action Items + Open Questions length ≥ sum across all checkpoints +- fix(/doctor SKILL): hook check rewritten to allowed-events sweep (Stop + PostToolUse only); sample report shows stale-entry warnings instead of PostCompact-specific failure +- fix(session-formats.md): drop "PostCompact Path A/B" frontmatter case; keep "Recovered from checkpoints" for /wrapup orphan recovery +- fix(/wrapup SKILL.md): state-file note updated to 3-field `0::00`; PostCompact follow-up signal wording removed +- fix(/update migration-steps + SKILL): clarify Stop-hook-only registration; session-end synthesis is via AUTO-SUMMARY or manual /wrapup + +## v2.2.0 — fix: PostCompact session log; simplify checkpoint cleanup; stronger qmd-first search + +- fix(INSTRUCTIONS PostCompact): inline writes replace background-agent dispatch — Path B silently failed because background agents don't see the main agent's compacted context. Path A still consolidates leftover checkpoints + deletes them, identical to /wrapup. +- fix(wrapup + AUTO-SUMMARY): drop Step 5 (mark `merged: true`) and Step 6 safety-net scan. Checkpoints deleted directly after session log write verified — the log is the recovery proof. +- fix(session-formats): remove `merged: false` from checkpoint frontmatter template. +- fix(doctor): orphan-checkpoint check no longer reads `merged:` frontmatter — any leftover checkpoint is unmerged by definition. +- feat(INSTRUCTIONS + QMD.md): stronger qmd-first guidance — qmd is the explicit default for vault content searches; Grep reserved for non-content lookups. +- chore(memory-health-checks): drop the `merged: true` straggler row; ignore the field on legacy files. + +## v2.1.0 + +- docs(onboarding): update install.sh reference → onebrain init; remove method/runtime.harness from vault.yml template +- docs(skills): remove method: onebrain from qmd and reorganize skill examples +- fix(doctor): --fix removes deprecated vault.yml keys (method, runtime.harness) in addition to onebrain_version + +## v2.0.10 — fix: background agent checkpoint writes; updated hook reason format in INSTRUCTIONS + +- fix(instructions): Auto Checkpoint routing now parses NN from hook reason; filename built from context session_token +- fix(instructions): stop hook and postcompact writes dispatched to background agent (mode: bypassPermissions) — main session no longer blocks on file writes +- fix(instructions): postcompact uses bare `auto-wrapup` reason; session_token sourced from context with session-init fallback +- fix(instructions): session-init failure explicitly aborts silently; routing table checks auto-wrapup reason first; Path A steps follow Path A dispatch (no longer split by Path B) + +## v2.0.9 — fix: startup grep locale, postcompact routing, wrapup score-0 fallback + +- fix(INSTRUCTIONS): startup task scan uses `LC_ALL=en_US.UTF-8` prefix on grep — prevents emoji pattern failures on macOS +- fix(INSTRUCTIONS): postcompact auto-wrapup Path A (step 9, after verify) and Path B now route action items to project notes — matches /wrapup Step 4b parity +- fix(wrapup): add session-context fallback in Step 4b-3b — score-0 tasks are routed to the project identified from `## What We Worked On` instead of being skipped; separate skipped_score0/skipped_ties lists +- fix(auto-summary): add session-context fallback for score-0 tasks in step 3 with explicit tokenization delimiters — matches /wrapup Step 4b-3b parity -- New hidden subcommand `onebrain run-skill --vault X --skill /name [--arg key=value ...]` spawns `claude -p "/onebrain:skill args" --add-dir ` with `cwd=`; resolves `claude` via `CLAUDE_BIN` env → known prefixes (`~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`) → PATH; the scheduler plist now invokes this instead of the never-implemented `--vault/--skill/--headless` flags -- `register-schedule` resolves command-mode binary names to absolute paths via `/usr/bin/which`, since launchd inherits a restricted PATH that excludes Homebrew/Bun/`~/.local/bin`; absolute paths now also `existsSync`-checked and relative paths resolve against the vault root (not `process.cwd()`); unresolved binaries throw at register time so failures don't hide until run time -- `labelForEntry` derives command-mode labels from the binary basename so `command: onebrain` and `command: /opt/homebrew/bin/onebrain` produce the same plist (and still collide correctly with skill `/onebrain`); `register-schedule` no longer mutates caller-supplied entries — the resolved path stays internal to plist generation -- `register-schedule --test ` drives `runSkillCommand` instead of spawning `claude` with non-existent flags, and propagates the child exit code (POSIX-conventional `128 + signal` for signal kills, `127` for spawn errors, `78`/`EX_CONFIG` for missing `vault.yml`) -- Hardening: `--arg` collector rejects empty keys; `buildPrompt` throws on empty skill names; `CLAUDE_BIN` typos surface as warnings instead of silently falling through to the probe list; one-shot plist's self-delete path now derives from the same label as the `launchctl bootout` target so they can never drift -- `process.argv[1]` dev-mode fallback: when running via `bun run src/index.ts`, argv[1] resolves to an unexecutable `.ts` file; `register-schedule` now detects that and falls back to `which onebrain` -- 23 new unit tests covering `buildPrompt`, `resolveCommandBinary` (4 branches incl. relative-path resolution), the spawn surface, signal/error/exit-code propagation, and the `CLAUDE_BIN` typo + override paths; existing scheduler tests rewritten for the new plist shape with explicit `not.toContain('--headless')` regression sentinels -- Plists generated by pre-v2.3.3 CLI silently exit 78 on every fire — run `onebrain register-schedule` once after upgrading to regenerate them; a `/doctor` check for stale-shape plists is filed as a follow-up +## v2.0.8 — refactor: extract shared session formats; remove backfill-recapped from /update -## v2.3.2 — fix(doctor): detect new Claude Code hook exec-form schema +- refactor(startup): add `skills/startup/references/session-formats.md` — canonical checkpoint + session log templates shared across all writers +- refactor(INSTRUCTIONS): replace inline checkpoint/session log format blocks with reference to session-formats.md +- refactor(wrapup): replace inline session log templates (Step 1b orphan recovery, Step 4) with reference to session-formats.md +- refactor(AUTO-SUMMARY): replace inline format description with reference to session-formats.md +- fix(update): remove migration Step 6 (backfill-recapped) — session logs without recapped: are naturally candidates for /recap, no backfill needed -- `checkSettingsHooks` now joins `command` + `args[]` into the effective command string before substring matching, so canonical exec-form hooks (`{command: "onebrain", args: ["checkpoint", "stop"]}`) are no longer false-flagged as missing -- New `detectHookForm` helper classifies each matching entry as `exec` (canonical), `legacy` (shell-form, wrapper, etc.), or `absent` — legacy entries now warn with "--fix will migrate to exec form" instead of staying invisible -- `detectHookForm` scans all matching entries per event: if any entry is in canonical exec form, the hook is reported as exec even when a legacy duplicate also matches (handles partial-migration state where a stale legacy entry was left behind alongside the new canonical one) -- `effectiveCommand` filters non-string `args[]` entries — hand-edited `settings.json` with stray `null`/numbers can't produce ghost substring matches -- Stale-hook sweep also uses the joined effective command, so a stale `onebrain` reference hidden in `args[]` of a wrapper entry is no longer missed -- 10 unit tests covering exec, legacy shell, bash-wrapper, absent, partial migration, mixed-state Stop+PostToolUse, stale exec-form events, defensive args filtering, and qmd-conditional skipping -- No behavior change for vaults already in canonical exec form (the common case post-v2.3.0) +## v2.0.7 — fix: postcompact Path B, remove PreCompact hook -## v2.3.1 — feat(scheduler): hook-style command mode for direct CLI scheduling +- fix(INSTRUCTIONS): postcompact auto-wrapup adds Path B — when no checkpoint files exist, synthesize session log from current context (was a no-op, causing auto-compact to write nothing) +- fix(INSTRUCTIONS): checkpoint trigger now matches reason prefix — `since start` / `since checkpoint-NN` suffix no longer prevents file creation +- fix(INSTRUCTIONS): PreCompact is now a no-op and no longer registered; PostCompact resets counter in all paths +- fix(INSTRUCTIONS): remove merged:true write step from postcompact; simplify delete step +- fix(INSTRUCTIONS): update session_token tooltip to include $TMUX_PANE and $TERM_SESSION_ID priority +- fix(doctor): replace PreCompact required-check with stale-hook warning (🟡 suggest /update to remove) +- fix(update): migration-steps.md and SKILL.md updated to reflect Stop/PostCompact-only hook registration +- fix(wrapup): update session token mismatch gotcha note to reflect CLI v2.0.12 fix -- `ScheduleEntry.command` field added: schedule any CLI binary using the same `command + args[]` shape as Claude Code hooks -- `args` is now `Record` (skill mode → `--key=value` flags) OR `string[]` (command mode → positional argv) -- `validateEntry` enforces exactly-one-of(skill, command) + matching args shape; type guards `isSkillMode` / `isCommandMode` exported -- One-shot command entries reject shell-special chars in args (`"`, `$`, backtick, `\`) — same guard as v2.3.0 -- `register-schedule --status` displays command entries as `cmd: ` and skill entries with inline `(key=value)` args -- Collision detection extended: skill and command entries derive plist labels independently; conflicts reported with mode-tagged names -- Zero breaking change to existing skill-mode entries — full v2.3.0 test suite passes without modification +## v2.0.6 — fix: replace bash scripts with CLI; fix SessionStart hook breaking vault after /update -## v2.3.0 — feat(scheduler): OneBrain scheduler — launchd-backed recurring + one-shot schedules (E9) +- fix(register-hooks): remove SessionStart hook registration — session-init is called by agent startup, not via hook +- fix(wrapup): reset-checkpoint-counter.sh → onebrain checkpoint reset +- fix(update): vault-sync.sh → onebrain vault-sync; backfill-recapped.sh → onebrain migrate backfill-recapped +- fix(update): pin-to-vault.sh + clean-plugin-cache.sh → onebrain vault-sync (doctor, onboarding) +- feat(qmd): register-hooks.sh --qmd/--remove-qmd → onebrain register-hooks --qmd/--remove-qmd +- chore: delete all replaced bash scripts (hooks/, update/scripts/, wrapup/scripts/) +- fix(update): bootstrap step downloads only SKILL.md — no bash scripts needed -- New subcommand `onebrain register-schedule` — registers scheduled skills with macOS launchd, reading the `schedule:` block from `vault.yml` -- Flags: `--dry-run`, `--remove`, `--refresh`, `--resume `, `--status`, `--test ` -- Recurring schedules via 5-field cron syntax in `cron:` field; validated before plist emission -- One-shot schedules via ISO `at: "YYYY-MM-DD HH:MM"` field; plist emits self-delete shell wrapper that auto-uninstalls after firing -- Schedulable validation: rejects entries pointing at skills without `schedulable:` or `schedulable_with_args:` frontmatter (or with missing `required_args`) -- Plist collision detection: two entries normalizing to the same `~/Library/LaunchAgents/com.onebrain.