[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71JPZNB2V9W85NWGQN77F61":3,"skill-same:01M71JPZNB2V9W85NWGQN77F61":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":55,"commitSha":56,"skillDirectory":5,"forksCount":57,"repositoryHtmlUrl":58,"repositoryHomepageUrl":59,"ownerHtmlUrl":60,"ownerBlogUrl":61,"ownerDescription":62,"updatedAt":63,"install":64,"resources":77},"01M71JPZNB2V9W85NWGQN77F61","stats-sync",null,"Sync caezium\u002Fstats fork with upstream exelban\u002Fstats. Rebases henry\u002Fhistory-mcp onto upstream\u002Fmaster, stops on any conflict, runs the feature-presence audit + Swift tests + Debug build, then halts at a pre-install checkpoint and waits for the user to say \"install\". Use when the user says \"\u002Fstats-sync\", \"sync stats\", or asks to update the Stats fork.","caezium\u002Fskills","caezium","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F113233555?v=4","01M71JB77ZPBAWEK009Y2W8BP7","Henry Zhang","01M71JB792NVXCWSYD27HQ0964",3,"MIT","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fstats-sync\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"sync","stats","stats sync","feature","conflict","history","swift","master","install","edit","write","read","at","update","audit","Bash","when","presence","MCP","pre-install","2026-11-10 10:12:30",false,"---\nname: stats-sync\ndescription: Sync caezium\u002Fstats fork with upstream exelban\u002Fstats. Rebases henry\u002Fhistory-mcp onto upstream\u002Fmaster, stops on any conflict, runs the feature-presence audit + Swift tests + Debug build, then halts at a pre-install checkpoint and waits for the user to say \"install\". Use when the user says \"\u002Fstats-sync\", \"sync stats\", or asks to update the Stats fork.\nallowed-tools: Bash,Read,Edit,Write\n---\n\n# Stats Sync\n\nRoutine for keeping the `caezium\u002Fstats` fork up to date with\n`exelban\u002Fstats`. The fork's value is everything in `henry\u002Fhistory-mcp`:\na long-running history DB, an MCP query server, a SwiftUI History view,\nconfigurable retention\u002Ftier policy, reader energy gating, and the test\nscaffold. **None** of that exists upstream — every commit on\n`henry\u002Fhistory-mcp` is load-bearing and must survive every sync.\n\n## Conflict policy: stop on every conflict\n\nUnlike `dayflow-sync` there is no per-commit yaml and no auto-skip class.\nThe fork has only ~15 commits and they're all features — there's nothing\nsafe to drop. On any rebase conflict: stop with full context and ask the\nuser how to resolve.\n\n## Pre-install checkpoint\n\nAfter rebase + audit + tests + Debug build pass, the skill **always\nstops** with a glanceable summary and waits for the user to reply\n\"install\" (or \"abort\"). It never auto-touches `\u002FApplications\u002FStats.app`\nbecause the user's `~\u002FLibrary\u002FApplication Support\u002FStats\u002Flldb` is real\ndata — multiple gigabytes of their accumulated history — and a botched\ninstall loses it.\n\n## Context\n\n- Local clone: `~\u002FDesktop\u002Fstats`\n- Fork remote (`origin`): `https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fstats`\n- Upstream remote (`upstream`): `https:\u002F\u002Fgithub.com\u002Fexelban\u002Fstats`\n- Upstream's default branch is **`master`** (not `main` — it's an older\n  project)\n- Integration branch: `henry\u002Fhistory-mcp` — this is what the user\n  builds from. The fork has no equivalent of dayflow's \"main mirrors\n  upstream\" pattern; we only track upstream by SHA in state.\n- State directory: `~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002F`\n  - `last-synced-upstream.txt` — last upstream\u002Fmaster SHA processed\n  - `last-synced-date.txt`\n  - `last-skipped-commits.log` — empty in practice (we never skip)\n\n## Steps\n\n### 1. Sanity check\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit remote -v\ngit status --short\ngit branch --show-current\ndf -h ~ | tail -1\n```\n\nRequired state before proceeding:\n- `origin` points to `https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fstats.git`\n- `upstream` points to `https:\u002F\u002Fgithub.com\u002Fexelban\u002Fstats.git`\n- Working tree clean (no uncommitted changes, no untracked source files —\n  `.claude\u002F` worktrees are fine)\n- Current branch is `henry\u002Fhistory-mcp` (if not, ask the user before\n  switching — they may be mid-feature on something else)\n- Free space on `~` ≥ 4 GB (Stats's lldb can be 1–2 GB and Xcode needs\n  room for module cache + build_dist)\n\nIf the working tree is dirty, **stop and ask**.\nIf disk \u003C 4 GB, suggest the user clean their Spotify\u002Fswiftpm caches; do\nnot delete anything automatically. The Stats lldb is precious.\n\n### 2. Fetch upstream\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit fetch upstream --prune\ngit fetch origin --prune\n```\n\nCompare `git rev-parse upstream\u002Fmaster` against\n`~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt`.\nIf equal, **nothing changed upstream** — tell the user in one line and\nexit. No rebase, no audit, no checkpoint.\n\n### 3. Show what's new upstream\n\n```bash\nSINCE=$(cat ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt)\ngit log \"$SINCE..upstream\u002Fmaster\" --oneline --no-merges\ngit log \"$SINCE..upstream\u002Fmaster\" --no-merges --shortstat | tail -5\n```\n\nSummarize in plain English (\"Upstream added N commits since vX.Y.Z —\nmostly bug fixes for the GPU module\" \u002F similar). Also note any new tags\n(`git tag --contains upstream\u002Fmaster` minus the previous synced tag).\nDon't dump the full log into the user's reading view.\n\n### 4. Rebase `henry\u002Fhistory-mcp` onto `upstream\u002Fmaster`\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit checkout henry\u002Fhistory-mcp\ngit rebase upstream\u002Fmaster\n```\n\n**On any conflict:**\n\n1. Capture context:\n   ```bash\n   git status                                 # which files\n   CONFLICT_SUBJECT=$(git log -1 --format='%s' REBASE_HEAD)\n   echo \"Conflict during: $CONFLICT_SUBJECT\"\n   ```\n2. For each conflicted file, show:\n   - Our hunks (`\u003C\u003C\u003C\u003C\u003C\u003C\u003C` to `=======`)\n   - Their hunks (`=======` to `>>>>>>>`)\n   - Upstream's nearby intent: `git log upstream\u002Fmaster -p -1 -- \u003Cfile>`\n3. **Always stop and surface the conflict to the user.** Never\n   `git rebase --skip` — every commit on `henry\u002Fhistory-mcp` is a\n   feature that must survive.\n4. After the user dictates the resolution: `git add \u003Cfiles>`,\n   `git rebase --continue`. If the rebase chains into another conflict,\n   repeat from (1).\n\nCommon conflict files to flag with extra care (these are where the\nfork's most load-bearing patches live):\n- `Kit\u002Fmodule\u002Freader.swift` — base Reader class with `tick()`,\n  `selfPersists`, `lastReadAt`, `historyCadenceSeconds`,\n  `popupClosedIntervalMultiplier`. Upstream often re-edits this.\n- `Modules\u002FCPU\u002Freaders.swift` — FrequencyReader Task `defer` fix.\n- `Modules\u002FNet\u002Fmain.swift` + `Modules\u002FNet\u002Freaders.swift` — `selfPersists: true`\n  wiring on Net readers + setup() overrides for multiplier=1.\n- `Stats\u002FViews\u002FAppSettings.swift` — History storage UX.\n- `Kit\u002Fplugins\u002FDB.swift` (entirely fork-introduced, conflicts unlikely\n  unless upstream adds something at the same path).\n\nIf `git rebase --abort` becomes necessary, do it and **stop**. Don't try\nagain with `-Xours\u002F-Xtheirs` — wrong-default merges silently destroy\nfeatures.\n\nAfter a clean rebase:\n```bash\ngit push origin henry\u002Fhistory-mcp --force-with-lease\n```\n\n### 5. Feature-presence audit\n\nEvery grep below must match. If any FAILS, a patch got lost during the\nrebase — **stop and report** which one. Don't push, don't proceed.\n\n| Feature | Verify by |\n|---|---|\n| History DB exists | `[ -f Kit\u002Fplugins\u002FDB.swift ]` |\n| NetTierPolicy + tier configurability | `grep -q \"public struct NetTierPolicy\" Kit\u002Fplugins\u002FDB.swift` |\n| Drop sentinel for past-hour-tier rows | `grep -q \"dropSentinel\" Kit\u002Fplugins\u002FDB.swift` |\n| LLDB compactRange | `grep -q \"compactRange\" Kit\u002Flldb\u002Flldb.h && grep -q \"CompactRange\" Kit\u002Flldb\u002Flldb.m` |\n| Hourly maintenance calls compactRange | `grep -q \"compactRange()\" Kit\u002Fplugins\u002FDB.swift` |\n| ttlDaysOverride test hook | `grep -q \"ttlDaysOverride\" Kit\u002Fplugins\u002FDB.swift` |\n| QueryServer \u002F MCP | `[ -f Kit\u002Fplugins\u002FQueryServer.swift ] && grep -q \"case \\\"\u002Finfo\\\"\" Kit\u002Fplugins\u002FQueryServer.swift` |\n| QueryServer staleness | `grep -q \"age_seconds\" Kit\u002Fplugins\u002FQueryServer.swift` |\n| History view | `[ -f Stats\u002FViews\u002FHistoryView.swift ]` |\n| History view: 30 d \u002F 90 d range chips | `grep -q '\"30d\"' Stats\u002FViews\u002FHistoryView.swift && grep -q '\"90d\"' Stats\u002FViews\u002FHistoryView.swift` |\n| Stride-sampled top-N | `grep -q \"findTimeSeriesSampled\" Stats\u002FViews\u002FHistoryView.swift` |\n| Staleness warning chip | `grep -q \"staleReaderCount\" Stats\u002FViews\u002FHistoryView.swift` |\n| Reader tick gating | `grep -q \"popupClosedIntervalMultiplier\" Kit\u002Fmodule\u002Freader.swift && grep -q \"internal func tick\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader 60 s history cadence | `grep -q \"historyCadenceSeconds\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader selfPersists flag | `grep -q \"selfPersists\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader lastReadAt diagnostics | `grep -q \"lastReadAt\" Kit\u002Fmodule\u002Freader.swift` |\n| FrequencyReader defer fix | `grep -q \"defer { self.isReading = false }\" Modules\u002FCPU\u002Freaders.swift` |\n| Net selfPersists wiring | `grep -q \"selfPersists: true\" Modules\u002FNet\u002Fmain.swift` |\n| Net readers opt out of gate | `grep -q \"popupClosedIntervalMultiplier = 1\" Modules\u002FNet\u002Freaders.swift` |\n| History storage settings UX | `grep -q \"Keep detailed data for\" Stats\u002FViews\u002FAppSettings.swift && grep -q \"Keep summary data for\" Stats\u002FViews\u002FAppSettings.swift` |\n| Option lists | `grep -q \"HistoryDetailedDaysOptions\" Kit\u002Ftypes.swift && grep -q \"HistorySummaryDaysOptions\" Kit\u002Ftypes.swift` |\n| Test scaffold present | `[ -f Tests\u002FHistoryDB.swift ]` |\n| ReaderTickTests present | `grep -q \"final class ReaderTickTests\" Tests\u002FHistoryDB.swift` |\n\nRun these as a single bash block; collect failures into a list. Any\nnon-zero exit means a patch got lost in the rebase.\n\n### 6. Run the Swift tests\n\n```bash\ncd ~\u002FDesktop\u002Fstats\nxcodebuild -project Stats.xcodeproj -scheme Stats \\\n  -configuration Debug -destination 'platform=macOS' \\\n  -derivedDataPath \u002Ftmp\u002Fstats-sync-build \\\n  CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \\\n  test 2>&1 \\\n  | grep -E \"error:|Test Case.*(failed)|TEST (SUCCEEDED|FAILED)|Executed [0-9]+ test\" \\\n  | tail -15\n```\n\nExpected: `** TEST SUCCEEDED **` with all tests passing (currently 27\ntotal: 17 HistoryDBTests + 3 RAMTests + 7 ReaderTickTests; this number\nwill grow over time).\n\nNote the trailing `** TEST FAILED **` line that sometimes appears\n*after* a successful test run is from the test host binary trying to\nopen the live lldb while running Stats holds its LOCK. That's a\n**pre-existing nuisance, not a real failure** — verify by the\n`Executed N tests, with 0 failures` count just above it.\n\nIf real test failures appear: **stop, don't push, don't install**.\nShow the failure to the user.\n\n### 7. Debug build (final verification before the install checkpoint)\n\n```bash\ncd ~\u002FDesktop\u002Fstats\nxcodebuild -project Stats.xcodeproj -scheme Stats \\\n  -configuration Debug -destination 'generic\u002Fplatform=macOS' \\\n  -derivedDataPath \u002Ftmp\u002Fstats-sync-build \\\n  CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \\\n  build 2>&1 \\\n  | grep -E \"error:|BUILD (SUCCEEDED|FAILED)\" \\\n  | tail -10\n```\n\nExpected: `** BUILD SUCCEEDED **`. The test step (6) already builds\neverything but a separate `build` invocation catches errors that only\nsurface for the non-test target.\n\nIf the build fails:\n- Errors in files our patches touched → **patch needs updating**. Stop.\n- Errors in files only upstream touched → upstream regression in this\n  release. Tell the user; usually means waiting for the next upstream\n  patch or porting a workaround.\n\n### 8. Pre-install checkpoint\n\n**Always stop here.** Do NOT proceed to step 9 unless the user replies\n\"install\" or similar. This is the hard gate before\n`\u002FApplications\u002FStats.app` is touched.\n\nPresent a glanceable summary in this shape:\n\n```\nStats sync — ready to install? (\u003Cupstream version tag>, \u003CN> upstream commits)\n\nRebase: clean \u002F \u003CN> conflicts manually resolved\n  Conflicts on: \u003Cfile paths if any>\nAudit (~22 grep checks): all pass \u002F N failed\nTests: ** TEST SUCCEEDED ** — \u003CN> executed, 0 failures\nDebug build: ** BUILD SUCCEEDED **\n\nWhat changed upstream:\n  - \u003Cone bullet per upstream commit, summarized — e.g. \"GPU fan curve fix\">\n  - \u003Cif there's an upstream version tag in this range, name it>\n\nCurrently installed: \u003Cbundle version of \u002FApplications\u002FStats.app, if installed>\nWill be installed: Debug build from \u002Ftmp\u002Fstats-sync-build\n\nReply \"install\" to proceed with quit-Stats + install-to-\u002FApplications\n+ live-endpoint verify.\nReply \"abort\" to leave the rebased branch on the remote without\ntouching the live app.\n```\n\nIf anything looks off (audit failure, suspicious upstream commit\ntouching reader\u002FDB code), explicitly recommend \"abort\" or \"investigate\nfirst\" rather than \"install\".\n\n### 9. (On user \"install\") Quit + install + verify\n\nRun only after the user explicitly says \"install\".\n\n```bash\n# 1. Quit currently-running Stats\nosascript -e 'tell application \"Stats\" to quit' 2>\u002Fdev\u002Fnull\nsleep 3\npkill -9 -f Stats.app\u002FContents\u002FMacOS\u002FStats 2>\u002Fdev\u002Fnull || true\nsleep 1\n\n# 2. Replace \u002FApplications\u002FStats.app\nrm -rf \u002FApplications\u002FStats.app\ncp -R \u002Ftmp\u002Fstats-sync-build\u002FBuild\u002FProducts\u002FDebug\u002FStats.app \u002FApplications\u002FStats.app\nxattr -cr \u002FApplications\u002FStats.app\n\n# 3. Launch\nopen \u002FApplications\u002FStats.app\nsleep 6\nPID=$(pgrep -fl Stats.app\u002FContents\u002FMacOS\u002FStats | head -1 | awk '{print $1}')\necho \"Stats running: pid=$PID\"\n\n# 4. Free build cache\nrm -rf \u002Ftmp\u002Fstats-sync-build\n```\n\n**Note: no data backup is needed.** The lldb format is forward-compatible\nwithin this fork's schema — every commit on `henry\u002Fhistory-mcp` preserves\nthe on-disk layout. If a future commit ever changes that, add a backup\nstep here before it ships.\n\n**Verify the live endpoints** (gives confidence the install survived):\n\n```bash\nsleep 4    # let QueryServer come up\ncurl -s http:\u002F\u002F127.0.0.1:9276\u002Fhealth\ncurl -s http:\u002F\u002F127.0.0.1:9276\u002Finfo \\\n  | python3 -c \"\nimport sys, json\nd = json.load(sys.stdin)\nreaders = d.get('readers', [])\nstale = [r for r in readers if r.get('age_seconds') is not None and r['age_seconds'] > 300]\nprint(f'prefixes={len(d[\\\"prefixes\\\"])}, readers={len(readers)}, stale_at_startup={len(stale)}')\n\"\n```\n\nExpected:\n- `\u002Fhealth` returns `{\"ok\":true,\"app\":\"Stats\",\"port\":9276}`\n- `\u002Finfo` returns at least 10 prefixes; `stale_at_startup` may be a few\n  (some readers don't fire until a popup-open event), no warning yet.\n\nIf `\u002Fhealth` fails to respond after 8 seconds total, **stop and report** —\nthe QueryServer didn't come up. Probable causes: port collision, the\nbuild is missing the QueryServer file (which would have failed step 5),\nor auto-update tried to validate the install and bailed (the unsigned\nbuild doesn't carry a team ID — see the alert message from past\nsessions).\n\n### 10. Bump state markers\n\nAfter successful end-to-end run (install succeeded + endpoints\nverified):\n\n```bash\ngit -C ~\u002FDesktop\u002Fstats rev-parse upstream\u002Fmaster \\\n  > ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt\ndate +%Y-%m-%d > ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-date.txt\n```\n\nState marker advances ONLY after install succeeds AND endpoints respond.\nAborts, conflicts, audit failures, test failures, build failures, and\nQueryServer no-shows all leave the marker at the previous SHA so the\nnext run retries from the same base.\n\n### 11. Final report\n\nTell the user, under 200 words:\n- Upstream version + N commits merged\n- Conflicts: how many, which files (if any)\n- Audit: pass\u002Ffail\n- Tests: pass count\n- Build: succeeded\n- Install: bundle version, QueryServer responsive at the expected port\n- Anything notable in the upstream changes (e.g. \"GPU module gained a\n  new metric — visible in your charts next time the GPU module is\n  reloaded\")\n\n## Failure modes\n\n- **Working tree dirty** → ask the user before anything.\n- **Not on `henry\u002Fhistory-mcp`** → ask, don't auto-switch.\n- **Disk \u003C 4 GB** → stop, suggest cache cleanup, don't auto-delete.\n- **Rebase conflict** → stop with full context, never `--skip`.\n- **Feature-presence audit failure** → stop, name the missing patch.\n- **Test failures** → stop, don't push, surface the failure.\n- **Build failure** → stop, don't push, classify (our files vs upstream).\n- **No upstream changes** → exit early, one-line report.\n- **Pre-install checkpoint** → always stops here; not a failure.\n- **`\u002Fhealth` no-show after install** → stop, report; the install\n  binary may be broken or port-collided.\n","# Stats Sync\n\nRoutine for keeping the `caezium\u002Fstats` fork up to date with\n`exelban\u002Fstats`. The fork's value is everything in `henry\u002Fhistory-mcp`:\na long-running history DB, an MCP query server, a SwiftUI History view,\nconfigurable retention\u002Ftier policy, reader energy gating, and the test\nscaffold. **None** of that exists upstream — every commit on\n`henry\u002Fhistory-mcp` is load-bearing and must survive every sync.\n\n## Conflict policy: stop on every conflict\n\nUnlike `dayflow-sync` there is no per-commit yaml and no auto-skip class.\nThe fork has only ~15 commits and they're all features — there's nothing\nsafe to drop. On any rebase conflict: stop with full context and ask the\nuser how to resolve.\n\n## Pre-install checkpoint\n\nAfter rebase + audit + tests + Debug build pass, the skill **always\nstops** with a glanceable summary and waits for the user to reply\n\"install\" (or \"abort\"). It never auto-touches `\u002FApplications\u002FStats.app`\nbecause the user's `~\u002FLibrary\u002FApplication Support\u002FStats\u002Flldb` is real\ndata — multiple gigabytes of their accumulated history — and a botched\ninstall loses it.\n\n## Context\n\n- Local clone: `~\u002FDesktop\u002Fstats`\n- Fork remote (`origin`): `https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fstats`\n- Upstream remote (`upstream`): `https:\u002F\u002Fgithub.com\u002Fexelban\u002Fstats`\n- Upstream's default branch is **`master`** (not `main` — it's an older\n  project)\n- Integration branch: `henry\u002Fhistory-mcp` — this is what the user\n  builds from. The fork has no equivalent of dayflow's \"main mirrors\n  upstream\" pattern; we only track upstream by SHA in state.\n- State directory: `~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002F`\n  - `last-synced-upstream.txt` — last upstream\u002Fmaster SHA processed\n  - `last-synced-date.txt`\n  - `last-skipped-commits.log` — empty in practice (we never skip)\n\n## Steps\n\n### 1. Sanity check\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit remote -v\ngit status --short\ngit branch --show-current\ndf -h ~ | tail -1\n```\n\nRequired state before proceeding:\n- `origin` points to `https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fstats.git`\n- `upstream` points to `https:\u002F\u002Fgithub.com\u002Fexelban\u002Fstats.git`\n- Working tree clean (no uncommitted changes, no untracked source files —\n  `.claude\u002F` worktrees are fine)\n- Current branch is `henry\u002Fhistory-mcp` (if not, ask the user before\n  switching — they may be mid-feature on something else)\n- Free space on `~` ≥ 4 GB (Stats's lldb can be 1–2 GB and Xcode needs\n  room for module cache + build_dist)\n\nIf the working tree is dirty, **stop and ask**.\nIf disk \u003C 4 GB, suggest the user clean their Spotify\u002Fswiftpm caches; do\nnot delete anything automatically. The Stats lldb is precious.\n\n### 2. Fetch upstream\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit fetch upstream --prune\ngit fetch origin --prune\n```\n\nCompare `git rev-parse upstream\u002Fmaster` against\n`~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt`.\nIf equal, **nothing changed upstream** — tell the user in one line and\nexit. No rebase, no audit, no checkpoint.\n\n### 3. Show what's new upstream\n\n```bash\nSINCE=$(cat ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt)\ngit log \"$SINCE..upstream\u002Fmaster\" --oneline --no-merges\ngit log \"$SINCE..upstream\u002Fmaster\" --no-merges --shortstat | tail -5\n```\n\nSummarize in plain English (\"Upstream added N commits since vX.Y.Z —\nmostly bug fixes for the GPU module\" \u002F similar). Also note any new tags\n(`git tag --contains upstream\u002Fmaster` minus the previous synced tag).\nDon't dump the full log into the user's reading view.\n\n### 4. Rebase `henry\u002Fhistory-mcp` onto `upstream\u002Fmaster`\n\n```bash\ncd ~\u002FDesktop\u002Fstats\ngit checkout henry\u002Fhistory-mcp\ngit rebase upstream\u002Fmaster\n```\n\n**On any conflict:**\n\n1. Capture context:\n   ```bash\n   git status                                 # which files\n   CONFLICT_SUBJECT=$(git log -1 --format='%s' REBASE_HEAD)\n   echo \"Conflict during: $CONFLICT_SUBJECT\"\n   ```\n2. For each conflicted file, show:\n   - Our hunks (`\u003C\u003C\u003C\u003C\u003C\u003C\u003C` to `=======`)\n   - Their hunks (`=======` to `>>>>>>>`)\n   - Upstream's nearby intent: `git log upstream\u002Fmaster -p -1 -- \u003Cfile>`\n3. **Always stop and surface the conflict to the user.** Never\n   `git rebase --skip` — every commit on `henry\u002Fhistory-mcp` is a\n   feature that must survive.\n4. After the user dictates the resolution: `git add \u003Cfiles>`,\n   `git rebase --continue`. If the rebase chains into another conflict,\n   repeat from (1).\n\nCommon conflict files to flag with extra care (these are where the\nfork's most load-bearing patches live):\n- `Kit\u002Fmodule\u002Freader.swift` — base Reader class with `tick()`,\n  `selfPersists`, `lastReadAt`, `historyCadenceSeconds`,\n  `popupClosedIntervalMultiplier`. Upstream often re-edits this.\n- `Modules\u002FCPU\u002Freaders.swift` — FrequencyReader Task `defer` fix.\n- `Modules\u002FNet\u002Fmain.swift` + `Modules\u002FNet\u002Freaders.swift` — `selfPersists: true`\n  wiring on Net readers + setup() overrides for multiplier=1.\n- `Stats\u002FViews\u002FAppSettings.swift` — History storage UX.\n- `Kit\u002Fplugins\u002FDB.swift` (entirely fork-introduced, conflicts unlikely\n  unless upstream adds something at the same path).\n\nIf `git rebase --abort` becomes necessary, do it and **stop**. Don't try\nagain with `-Xours\u002F-Xtheirs` — wrong-default merges silently destroy\nfeatures.\n\nAfter a clean rebase:\n```bash\ngit push origin henry\u002Fhistory-mcp --force-with-lease\n```\n\n### 5. Feature-presence audit\n\nEvery grep below must match. If any FAILS, a patch got lost during the\nrebase — **stop and report** which one. Don't push, don't proceed.\n\n| Feature | Verify by |\n|---|---|\n| History DB exists | `[ -f Kit\u002Fplugins\u002FDB.swift ]` |\n| NetTierPolicy + tier configurability | `grep -q \"public struct NetTierPolicy\" Kit\u002Fplugins\u002FDB.swift` |\n| Drop sentinel for past-hour-tier rows | `grep -q \"dropSentinel\" Kit\u002Fplugins\u002FDB.swift` |\n| LLDB compactRange | `grep -q \"compactRange\" Kit\u002Flldb\u002Flldb.h && grep -q \"CompactRange\" Kit\u002Flldb\u002Flldb.m` |\n| Hourly maintenance calls compactRange | `grep -q \"compactRange()\" Kit\u002Fplugins\u002FDB.swift` |\n| ttlDaysOverride test hook | `grep -q \"ttlDaysOverride\" Kit\u002Fplugins\u002FDB.swift` |\n| QueryServer \u002F MCP | `[ -f Kit\u002Fplugins\u002FQueryServer.swift ] && grep -q \"case \\\"\u002Finfo\\\"\" Kit\u002Fplugins\u002FQueryServer.swift` |\n| QueryServer staleness | `grep -q \"age_seconds\" Kit\u002Fplugins\u002FQueryServer.swift` |\n| History view | `[ -f Stats\u002FViews\u002FHistoryView.swift ]` |\n| History view: 30 d \u002F 90 d range chips | `grep -q '\"30d\"' Stats\u002FViews\u002FHistoryView.swift && grep -q '\"90d\"' Stats\u002FViews\u002FHistoryView.swift` |\n| Stride-sampled top-N | `grep -q \"findTimeSeriesSampled\" Stats\u002FViews\u002FHistoryView.swift` |\n| Staleness warning chip | `grep -q \"staleReaderCount\" Stats\u002FViews\u002FHistoryView.swift` |\n| Reader tick gating | `grep -q \"popupClosedIntervalMultiplier\" Kit\u002Fmodule\u002Freader.swift && grep -q \"internal func tick\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader 60 s history cadence | `grep -q \"historyCadenceSeconds\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader selfPersists flag | `grep -q \"selfPersists\" Kit\u002Fmodule\u002Freader.swift` |\n| Reader lastReadAt diagnostics | `grep -q \"lastReadAt\" Kit\u002Fmodule\u002Freader.swift` |\n| FrequencyReader defer fix | `grep -q \"defer { self.isReading = false }\" Modules\u002FCPU\u002Freaders.swift` |\n| Net selfPersists wiring | `grep -q \"selfPersists: true\" Modules\u002FNet\u002Fmain.swift` |\n| Net readers opt out of gate | `grep -q \"popupClosedIntervalMultiplier = 1\" Modules\u002FNet\u002Freaders.swift` |\n| History storage settings UX | `grep -q \"Keep detailed data for\" Stats\u002FViews\u002FAppSettings.swift && grep -q \"Keep summary data for\" Stats\u002FViews\u002FAppSettings.swift` |\n| Option lists | `grep -q \"HistoryDetailedDaysOptions\" Kit\u002Ftypes.swift && grep -q \"HistorySummaryDaysOptions\" Kit\u002Ftypes.swift` |\n| Test scaffold present | `[ -f Tests\u002FHistoryDB.swift ]` |\n| ReaderTickTests present | `grep -q \"final class ReaderTickTests\" Tests\u002FHistoryDB.swift` |\n\nRun these as a single bash block; collect failures into a list. Any\nnon-zero exit means a patch got lost in the rebase.\n\n### 6. Run the Swift tests\n\n```bash\ncd ~\u002FDesktop\u002Fstats\nxcodebuild -project Stats.xcodeproj -scheme Stats \\\n  -configuration Debug -destination 'platform=macOS' \\\n  -derivedDataPath \u002Ftmp\u002Fstats-sync-build \\\n  CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \\\n  test 2>&1 \\\n  | grep -E \"error:|Test Case.*(failed)|TEST (SUCCEEDED|FAILED)|Executed [0-9]+ test\" \\\n  | tail -15\n```\n\nExpected: `** TEST SUCCEEDED **` with all tests passing (currently 27\ntotal: 17 HistoryDBTests + 3 RAMTests + 7 ReaderTickTests; this number\nwill grow over time).\n\nNote the trailing `** TEST FAILED **` line that sometimes appears\n*after* a successful test run is from the test host binary trying to\nopen the live lldb while running Stats holds its LOCK. That's a\n**pre-existing nuisance, not a real failure** — verify by the\n`Executed N tests, with 0 failures` count just above it.\n\nIf real test failures appear: **stop, don't push, don't install**.\nShow the failure to the user.\n\n### 7. Debug build (final verification before the install checkpoint)\n\n```bash\ncd ~\u002FDesktop\u002Fstats\nxcodebuild -project Stats.xcodeproj -scheme Stats \\\n  -configuration Debug -destination 'generic\u002Fplatform=macOS' \\\n  -derivedDataPath \u002Ftmp\u002Fstats-sync-build \\\n  CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \\\n  build 2>&1 \\\n  | grep -E \"error:|BUILD (SUCCEEDED|FAILED)\" \\\n  | tail -10\n```\n\nExpected: `** BUILD SUCCEEDED **`. The test step (6) already builds\neverything but a separate `build` invocation catches errors that only\nsurface for the non-test target.\n\nIf the build fails:\n- Errors in files our patches touched → **patch needs updating**. Stop.\n- Errors in files only upstream touched → upstream regression in this\n  release. Tell the user; usually means waiting for the next upstream\n  patch or porting a workaround.\n\n### 8. Pre-install checkpoint\n\n**Always stop here.** Do NOT proceed to step 9 unless the user replies\n\"install\" or similar. This is the hard gate before\n`\u002FApplications\u002FStats.app` is touched.\n\nPresent a glanceable summary in this shape:\n\n```\nStats sync — ready to install? (\u003Cupstream version tag>, \u003CN> upstream commits)\n\nRebase: clean \u002F \u003CN> conflicts manually resolved\n  Conflicts on: \u003Cfile paths if any>\nAudit (~22 grep checks): all pass \u002F N failed\nTests: ** TEST SUCCEEDED ** — \u003CN> executed, 0 failures\nDebug build: ** BUILD SUCCEEDED **\n\nWhat changed upstream:\n  - \u003Cone bullet per upstream commit, summarized — e.g. \"GPU fan curve fix\">\n  - \u003Cif there's an upstream version tag in this range, name it>\n\nCurrently installed: \u003Cbundle version of \u002FApplications\u002FStats.app, if installed>\nWill be installed: Debug build from \u002Ftmp\u002Fstats-sync-build\n\nReply \"install\" to proceed with quit-Stats + install-to-\u002FApplications\n+ live-endpoint verify.\nReply \"abort\" to leave the rebased branch on the remote without\ntouching the live app.\n```\n\nIf anything looks off (audit failure, suspicious upstream commit\ntouching reader\u002FDB code), explicitly recommend \"abort\" or \"investigate\nfirst\" rather than \"install\".\n\n### 9. (On user \"install\") Quit + install + verify\n\nRun only after the user explicitly says \"install\".\n\n```bash\n# 1. Quit currently-running Stats\nosascript -e 'tell application \"Stats\" to quit' 2>\u002Fdev\u002Fnull\nsleep 3\npkill -9 -f Stats.app\u002FContents\u002FMacOS\u002FStats 2>\u002Fdev\u002Fnull || true\nsleep 1\n\n# 2. Replace \u002FApplications\u002FStats.app\nrm -rf \u002FApplications\u002FStats.app\ncp -R \u002Ftmp\u002Fstats-sync-build\u002FBuild\u002FProducts\u002FDebug\u002FStats.app \u002FApplications\u002FStats.app\nxattr -cr \u002FApplications\u002FStats.app\n\n# 3. Launch\nopen \u002FApplications\u002FStats.app\nsleep 6\nPID=$(pgrep -fl Stats.app\u002FContents\u002FMacOS\u002FStats | head -1 | awk '{print $1}')\necho \"Stats running: pid=$PID\"\n\n# 4. Free build cache\nrm -rf \u002Ftmp\u002Fstats-sync-build\n```\n\n**Note: no data backup is needed.** The lldb format is forward-compatible\nwithin this fork's schema — every commit on `henry\u002Fhistory-mcp` preserves\nthe on-disk layout. If a future commit ever changes that, add a backup\nstep here before it ships.\n\n**Verify the live endpoints** (gives confidence the install survived):\n\n```bash\nsleep 4    # let QueryServer come up\ncurl -s http:\u002F\u002F127.0.0.1:9276\u002Fhealth\ncurl -s http:\u002F\u002F127.0.0.1:9276\u002Finfo \\\n  | python3 -c \"\nimport sys, json\nd = json.load(sys.stdin)\nreaders = d.get('readers', [])\nstale = [r for r in readers if r.get('age_seconds') is not None and r['age_seconds'] > 300]\nprint(f'prefixes={len(d[\\\"prefixes\\\"])}, readers={len(readers)}, stale_at_startup={len(stale)}')\n\"\n```\n\nExpected:\n- `\u002Fhealth` returns `{\"ok\":true,\"app\":\"Stats\",\"port\":9276}`\n- `\u002Finfo` returns at least 10 prefixes; `stale_at_startup` may be a few\n  (some readers don't fire until a popup-open event), no warning yet.\n\nIf `\u002Fhealth` fails to respond after 8 seconds total, **stop and report** —\nthe QueryServer didn't come up. Probable causes: port collision, the\nbuild is missing the QueryServer file (which would have failed step 5),\nor auto-update tried to validate the install and bailed (the unsigned\nbuild doesn't carry a team ID — see the alert message from past\nsessions).\n\n### 10. Bump state markers\n\nAfter successful end-to-end run (install succeeded + endpoints\nverified):\n\n```bash\ngit -C ~\u002FDesktop\u002Fstats rev-parse upstream\u002Fmaster \\\n  > ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-upstream.txt\ndate +%Y-%m-%d > ~\u002F.claude\u002Fskills\u002Fstats-sync\u002Fstate\u002Flast-synced-date.txt\n```\n\nState marker advances ONLY after install succeeds AND endpoints respond.\nAborts, conflicts, audit failures, test failures, build failures, and\nQueryServer no-shows all leave the marker at the previous SHA so the\nnext run retries from the same base.\n\n### 11. Final report\n\nTell the user, under 200 words:\n- Upstream version + N commits merged\n- Conflicts: how many, which files (if any)\n- Audit: pass\u002Ffail\n- Tests: pass count\n- Build: succeeded\n- Install: bundle version, QueryServer responsive at the expected port\n- Anything notable in the upstream changes (e.g. \"GPU module gained a\n  new metric — visible in your charts next time the GPU module is\n  reloaded\")\n\n## Failure modes\n\n- **Working tree dirty** → ask the user before anything.\n- **Not on `henry\u002Fhistory-mcp`** → ask, don't auto-switch.\n- **Disk \u003C 4 GB** → stop, suggest cache cleanup, don't auto-delete.\n- **Rebase conflict** → stop with full context, never `--skip`.\n- **Feature-presence audit failure** → stop, name the missing patch.\n- **Test failures** → stop, don't push, surface the failure.\n- **Build failure** → stop, don't push, classify (our files vs upstream).\n- **No upstream changes** → exit early, one-line report.\n- **Pre-install checkpoint** → always stops here; not a failure.\n- **`\u002Fhealth` no-show after install** → stop, report; the install\n  binary may be broken or port-collided.\n",{"name":5,"description":7,"allowed-tools":54},"Bash,Read,Edit,Write","main","6ef866230c1ba3459fd08fc65141dfd37fffd41a",0,"https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills","https:\u002F\u002Fskills.henryzh.dev","https:\u002F\u002Fgithub.com\u002Fcaezium","henryzh.dev","quant, data science, full-stack, robotics.\r\nbuilding cool stuff","2026-08-24 19:21:44",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add caezium\u002Fskills --skill stats-sync",{"tool":70,"command":71},"bunx","bunx skills add caezium\u002Fskills --skill stats-sync",{"tool":73,"command":74},"pnpm","pnpm dlx skills add caezium\u002Fskills --skill stats-sync","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fstats-sync\u002FSKILL.md",true,[],[79,98,126,144,164,185],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":91,"publishedAt":49},"01M71JT4RYCAS18RF6003YYR1D","writing-for-agents","Writing documents for agents. Use when creating or editing skills, or modifying AGENTS.md or CLAUDE.md.","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fwriting-for-agents\u002FSKILL.md",[85,88],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":89,"categoryName":90,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000036","内容创作者",[92,93,94,95,96,97,45],"writing for agents","for","writing","editing","use","documents",{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":107,"publishedAt":49},"01M71JT0GES4AZ5ADH8EADNN1Z","wrangler","Cloudflare Workers CLI for deploying, developing, and managing Workers, KV, R2, D1, Vectorize, Hyperdrive, Workers AI, Containers, Queues, Workflows, Pipelines, and Secrets Store. Load before running wrangler commands to ensure correct syntax and best practices. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fwrangler\u002FSKILL.md",[104],{"categoryNo":105,"categoryName":106,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[100,108,109,110,111,112,113,114,115,116,117,118,119,93,120,121,122,123,124,125],"cloudflare","d1","knowledge","workflows","cli","secrets","commands","syntax","cloudflare workers","r2","queues","running","containers","correct","load","workers","best practices","store",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":49},"01M71JSWX4R203M32K9A18AAW8","workers-best-practices","Reviews and authors Cloudflare Workers code against production best practices. Load when writing new Workers, reviewing Worker code, configuring wrangler.jsonc, or checking for common Workers anti-patterns (streaming, floating promises, global state, secrets, bindings, observability). Biases towards retrieval from Cloudflare docs over pre-trained knowledge.","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fworkers-best-practices\u002FSKILL.md",[],[133,123,124,134,135,136,93,108,137,110,138,100,94,122,45,139,140,141,142,143],"workers best practices","observability","reviews","promises","worker","new","code","common","streaming","state","anti-patterns",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":150,"publishedAt":49},"01M71JST6P88MXGT2MWDTPJGEG","wizard","Generate an interactive bash wizard that walks a human through steps only they can perform. Use when provisioning infrastructure, setting up credentials or CI secrets, walking an unfamiliar third-party dashboard, or running a one-off migration or cutover. Don't invoke this for steps the agent can perform itself.","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fwizard\u002FSKILL.md",[],[146,119,151,93,152,153,154,155,96,156,45,44,157,158,159,160,161,162,163,113],"setting","up","ci","provisioning infrastructure","only","invoke","one","interactive","can","credentials","dashboard","generate","human",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":171,"publishedAt":49},"01M71JSQ95S7BQ61DAPN95X2W4","why","Use for 'why does X work this way', 'why we picked Y', design rationale, regressions, postmortems, or data-backed thresholds. Discovers available evidence sources, searches each relevant category, and returns a cited read on decisions and tradeoffs. Use how for runtime behavior.","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fwhy\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fwhy\u002FSKILL.md",[],[166,172,173,174,175,93,176,177,96,178,179,180,181,40,182,183,184],"sources","thresholds","evidence","relevant","runtime","design","decisions","work","how","behavior","data","rationale","returns",{"skillNo":186,"name":187,"nameZh":6,"description":188,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":189,"categories":190,"keywords":192,"publishedAt":49},"01M71JSMHFVSH8HK8GXN6YAX6J","week-prep","Generate a briefing with calendar, tasks, and attention flags. Use for \"week prep\", \"briefing\", or \"what's on this week\".","https:\u002F\u002Fgithub.com\u002Fcaezium\u002Fskills\u002Fblob\u002Fmain\u002Fweek-prep\u002FSKILL.md",[191],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[193,194,195,196,197,93,198,199,200,47,96,44,201,202,203,162,204,40,205,206],"week prep","prep","deep","attention","get","search","messages","briefing","tasks","with","slack","calendar","flags","grep"]