[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CAVBYASZECPR3AW1G5FY4M":3,"skill-same:01M6CAVBYASZECPR3AW1G5FY4M":95},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":52,"linkOnly":53,"markdownContent":54,"markdownBody":55,"frontMatter":56,"refName":74,"commitSha":75,"skillDirectory":76,"forksCount":77,"repositoryHtmlUrl":78,"repositoryHomepageUrl":6,"ownerHtmlUrl":79,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":80,"install":81,"resources":94},"01M6CAVBYASZECPR3AW1G5FY4M","wiki-vault-safeguards",null,"Safety patterns for working with a populated LLM-wiki \u002F personal knowledge vault (~\u002Fllm_wiki, ~\u002Fwiki, etc.) — preventing concept-page clobber, enforcing append-not-overwrite, the default-doing-now save location for research artifacts, AND the push-to-origin-main flow when the wiki is a git repo with concurrent agent activity. Activates when the user asks to save research \u002F a brief \u002F top-10 \u002F synthesis to the wiki, or asks to push the wiki to origin main. Loads alongside llm-wiki and obsidian skills.","jleechanorg\u002Fjleechan-skills","jleechanorg","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F221404966?v=4","01M6C1VJ99XG950X1DWPEBCBGX","01M6C1VJDK5YVDNT3362RT5WSB",6,"MIT","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fwiki-vault-safeguards\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51],"wiki vault safeguards","vault","wiki","fetch","2026","Research Artifacts","break","verified","re","worker","files","conflict resolution","html","karpathy","fix","directory","write","rebase","knowledge","Safety","flow","brief","git","status","obsidian","personal","2026-11-10 10:12:30",false,"---\nname: wiki-vault-safeguards\ndescription: \"Safety patterns for working with a populated LLM-wiki \u002F personal knowledge vault (~\u002Fllm_wiki, ~\u002Fwiki, etc.) — preventing concept-page clobber, enforcing append-not-overwrite, the default-doing-now save location for research artifacts, AND the push-to-origin-main flow when the wiki is a git repo with concurrent agent activity. Activates when the user asks to save research \u002F a brief \u002F top-10 \u002F synthesis to the wiki, or asks to push the wiki to origin main. Loads alongside llm-wiki and obsidian skills.\"\nversion: 1.2.0\nauthor: Hermes Agent\nlicense: MIT\nplatforms: [linux, macos]\nchangelog:\n  - \"1.2.0 (2026-07-28): Two new pitfalls. (a) 'sources\u002F' vs 'raw\u002F' directory trap — workers invent `sources\u002Farticles\u002F` because the frontmatter field is `sources:` and they confuse field-with-directory. The wiki's Layer 1 directory is ALWAYS `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F`, `raw\u002Ftranscripts\u002F`). A worker that wrote `sources: [\\\"sources\u002Farticles\u002Fmbti\u002FENFJ-per.html\\\"]` left 17 files with non-existent directory references; parent had to sed-fix all 17. (b) Concept pages without raw sources — workers that summarize N articles and write N concept pages but skip the curl-fetch into `raw\u002Farticles\u002F\u003Cfile>.\u003Cext>` step silently break re-ingest drift detection. Lint's source-drift check (item ⑧ in llm-wiki) becomes a no-op for the skipped sources. Both pitfalls verified on 16-MBTI ingest (2026-07-28, personalitypage.com).\"\n  - \"1.1.0 (2026-07-26): Add Failure Modes 3a-3e (cross-org push with wrong gh account, git ls-files truth over git status, stash-then-checkout pattern, journal-file rebase conflict resolution).\"\n  - \"1.0.0 (initial): Failure Modes 1-3 (overwrite trap, default-doing-now save, push-to-origin-main).\"\nmetadata:\n  hermes:\n    tags: [wiki, knowledge-base, safety, git, vault, llm-wiki, karpathy]\n    category: research\n    related_skills: [llm-wiki, obsidian]\n---\n\n# Wiki \u002F Vault Safeguards\n\nCompanion to the `llm-wiki` and `obsidian` skills. Those skills describe the Karpathy\npattern and Obsidian vault mechanics. This skill covers the **safety patterns** that\napply specifically when the vault is *populated* (multiple agents writing over time,\nmonths of accumulated concept pages) and **backed by a git repo** (`jleechanorg\u002Fllm-wiki.git`,\n`jleechanclaw` etc.) with concurrent activity.\n\n## When This Skill Activates\n\nLoad this skill when ANY of these are true:\n\n- The user asks to save, write, ingest, file, or commit a research artifact to a wiki\u002Fvault\n- The user asks to \"push the wiki to origin main\" \u002F \"commit the wiki\" \u002F \"push my notes\"\n- You're about to call `write_file` on a path inside `~\u002Fllm_wiki\u002F` or `~\u002Fwiki\u002F` or any\n  other markdown-vault directory\n- You see `wiki\u002F` or `notes\u002F` or `vault\u002F` referenced in the conversation and the wiki\n  is already populated (>20 markdown files)\n\n## Three Failure Modes This Skill Prevents\n\n### Failure Mode 1: Concept-page overwrite trap\n\n**Symptom:** You complete the orientation routine (read SCHEMA + index + scan log), see\nthat `concepts\u002FHarnessEngineering.md` exists with a 2026-04-14 last_updated date, and\ncorrectly decide \"the answer belongs in `concepts\u002FHarnessEngineering.md`.\" Then you\ncall `write_file(path='concepts\u002FHarnessEngineering.md', content=\u003Cnew content>)`. The\npre-existing 60+ lines of Meta-Harness paper + 4-layer architecture + OpenAI workshop\nnotes are silently gone. No error, no warning.\n\n**Why orientation didn't save you:** The orientation routine tells you a page exists.\nIt does not enforce the merge-with-existing rule on `write_file`. `write_file` is a\n*clobber-and-replace* primitive — that's its contract.\n\n**The three-step pattern before any write to a known-existing page:**\n\n1. **Re-read the target file** (`read_file path=\u003Cconcept>.md`) immediately before\n   `write_file`. Even if you saw the path in `index.md` 3 turns ago, re-read — the\n   page may have been updated by another agent in parallel.\n2. **Diff concepts, not just filenames.** If the existing page covers a *different\n   framing* of the same word (e.g. pre-existing HarnessEngineering is the\n   self-bootstrapping agent runtime harness; new research is the AIEWF 2026\n   human-org harness), the answer is **append a section, not overwrite**.\n   Append-only preserves the compounding nature of the wiki.\n3. **When in doubt, `patch` not `write_file`.** Read the existing page, find a stable\n   anchor (last bullet list, last heading, etc.), and `patch` to add a new section.\n   `write_file` is only safe for genuinely new pages or genuinely\n   contradicted-and-resolved content (mark with `contradictions:` frontmatter first).\n\n**Recovery if you clobbered:** If the vault is under git (which is the assumption for\nthis skill), `git checkout HEAD -- \u003Cpath>` restores the pre-write state, then re-do\nthe work as a `patch` append.\n\n**Verified session:** 2026-07-14, AIEWF 2026 brief. I clobbered `HarnessEngineering.md`\nthat had the Meta-Harness paper + 4-layer architecture. Recovered via `git checkout HEAD\n-- concepts\u002FHarnessEngineering.md`, then used `patch` to append a new AIEWF validation\nsection. Net result: +14 lines additive, zero content loss.\n\n### Failure Mode 2: Research artifact saved to \u002Ftmp, then pick-one-menu asked\n\n**Symptom:** User asks \"research the top 10 learnings from the conference.\" You write the\nbrief to `\u002Ftmp\u002Faiewf-2026-top-10.md` (volatile), post a Slack reply with the summary,\nand ask \"Pick one: (a) save to wiki (b) deeper AO pull (c) LinkedIn draft.\" User replies\n\"keep going save the brief and summarize it, why did you stop.\"\n\n**Why this is wrong twice over:** (1) `\u002Ftmp\u002Ffoo.md` is volatile — gone on next reboot.\n(2) The pick-one-menu violates SOUL.md `no-pick-one-menus` COMMIT explicitly.\n\n**The default-doing-now move:**\n\n1. Write the brief to `sources\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.md` (or `raw\u002Farticles\u002F`\n   per plain Karpathy-pattern vaults).\n2. Create the 2-3 concept pages the brief implies, each with cross-references via\n   `[[wikilinks]]`.\n3. Add entries to `index.md` linking them.\n4. Post a one-line summary back to the originating thread.\n\n**Do NOT ask \"where should I save this?\"** The vault is the answer. Default-doing-now\napplies. Volatile `\u002Ftmp` + ask-the-user is the failure mode. The user can always say\n\"move it elsewhere,\" but `\u002Ftmp` is wrong by default.\n\n### Failure Mode 3: Push to origin main with divergent history\n\n**Symptom:** User says \"push to origin main.\" You `git status` and see 3\n`[Auto] Pending changes` commits ahead of origin\u002Fmain, none of them yours. You try\n`git rebase origin\u002Fmain` and it aborts with conflicts in `raw\u002Fcampaigns\u002F*` that have\nnothing to do with your work.\n\n**The safe pattern:**\n\n1. `git fetch origin` first — see the actual remote state.\n2. `git status --short --branch` — local divergence from origin.\n3. `git log origin\u002Fmain..HEAD` and `git diff --stat origin\u002Fmain..HEAD` — identify\n   which local commits are yours vs pre-existing.\n4. **Decision tree:**\n   - **Unrelated pre-existing commits → `git reset --hard origin\u002Fmain`** then unstash\n     your work, commit, push. Cleaner linear history.\n   - **Your commits you want to preserve → rebase manually**, resolve conflicts\n     file-by-file with `git checkout --theirs\u002F--ours \u003Cpath>` for specific hunks.\n5. **Never `git checkout --theirs \u003Cindex.md>` wholesale** — you'll lose other agents'\n   recent entries. Resolve `index.md` conflicts manually by reading both versions and\n   merging the additions.\n6. **Stage only your files** with explicit paths, not `git add -A`. Untracked files\n   in `.beads\u002F`, `artifacts\u002F`, `raw\u002F` from other agents are not yours to commit.\n   (Verified: 50+ untracked `.beads\u002F.br_history\u002F*.jsonl` files in `~\u002Fllm_wiki` from\n   prior sessions — none related to AIEWF brief, all left alone.)\n7. Commit with a scoped message that names the source\u002Fsession\u002Ftask, then `git push origin main`.\n8. Verify: `git rev-parse origin\u002Fmain` matches local HEAD SHA.\n\nIf the vault is **not** under git, report that explicitly to the user and offer\n`git init` + first-commit. Don't `git push` to a non-existent remote.\n\n#### 3a. Cross-org push when `gh auth` is wrong for the vault's remote\n\n**Trigger:** `git push origin main` returns `Repository not found` against a remote\nURL like `https:\u002F\u002Fgithub.com\u002FAgnt-F\u002F\u003Crepo>.git` or `https:\u002F\u002Fgithub.com\u002F\u003Cother-org>\u002F\u003Crepo>.git`,\nwhile `gh auth status` shows the active account is `jleechan2015` (member of\n`jleechanorg` but NOT of the vault's org).\n\n**Why this fires:** `gh`'s HTTP-credential helper scopes the token to the active\naccount's accessible orgs. `jleechan2015` cannot push to `Agnt-F\u002F*` even if a `$USER-af`\naccount exists in 1Password\u002FKeychain — `gh` only knows about one active user at a time.\n\n**The fix — token override for one push, no global config pollution:**\n\n```bash\n# 1. Verify a non-gh token exists for the target org in the environment\nGH_TOKEN_AGENTF=\"$GH_TOKEN_AGENTF\" curl -sS -o \u002Fdev\u002Fnull -w \"HTTP %{http_code}\\n\" \\\n  -H \"Authorization: token $GH_TOKEN_AGENTF\" -H \"User-Agent: hermes-push\" \\\n  https:\u002F\u002Fapi.github.com\u002Frepos\u002FAgnt-F\u002F\u003Crepo>\n\n# Expect HTTP 200. If 401\u002F404 the token is wrong or has wrong scope.\n\n# 2. Push with that token via URL insteadOf + a credential helper that reads from env\ngit -c credential.helper='!f() { echo \"username=x-access-token\"; echo \"password=$1\"; }; f \"$@\"' \\\n    -c \"url.https:\u002F\u002Fx-access-token:$GH_TOKEN_AGENTF@github.com\u002FAgnt-F\u002F\u003Crepo>.git\u002F.insteadOf=https:\u002F\u002Fgithub.com\u002FAgnt-F\u002F\u003Crepo>.git\" \\\n    push origin main\n```\n\n**DOs \u002F DON'Ts:**\n- DO use `GH_TOKEN_AGENTF` (or whatever the org-scoped env var is) — DO NOT embed the\n  token in the remote URL with `git remote set-url origin ...`.\n- DO scope the `-c` flags to the one `push` invocation — DO NOT `git config --global`.\n- DO verify the token with the API probe before pushing (saves a round-trip on a wrong token).\n- DO NOT echo the token in shell history. Use `$GH_TOKEN_AGENTF` directly, never `echo $GH_TOKEN_AGENTF`.\n\n**Companion rule:** for `Agnt-F\u002F*` Agnt-F vault work, load `agentf` skill alongside\nthis one — it documents the `$USER-af` vs `jleechan2015` distinction and the\ncanonical token location.\n\n#### 3b. \"Is this file already committed?\" — `git status` lies, `git ls-files` is the truth\n\n**Trigger:** A path appears in `git status --short` as `?? foo\u002Fbar.md` (untracked)\non the first scan, but after `git add` of OTHER files it disappears from the\nuntracked list — and yet `git ls-files foo\u002Fbar.md` returns the path. If you\nincluded the path in your `git add` list, it was a no-op but you also didn't double-check.\n\n**Why this fires:** A race between your `git status` call and another agent \u002F cron\nrunning `git add foo\u002Fbar.md && git commit` mid-session. The untracked-list snippet\nyou snapshotted is stale by the time you stage other files.\n\n**The diagnostic:**\n```bash\n# Before adding ANY borderline path, verify it is currently untracked\ngit ls-files \u003Cpath>          # empty output → truly untracked, safe to add\ngit log --all --oneline -- \u003Cpath> | head -3   # see if it has commit history\n```\n\n**The rule:** when building an `git add \u003Clist>` command, run `git ls-files \u003Ceach-path>`\nin a parallel batch first. Paths that return a hit were already committed by another\nagent — drop them from the add list. Paths that return empty are still untracked.\n\n#### 3c. Landmine taxonomy — pre-push checklist for untracked file lists\n\n**Trigger:** `git status --short` lists 10+ untracked files and at least one has a\nborderline name (`*-recovery-*`, `nextsteps-*`, `*-audit-*`, numeric ID, etc.).\nThree classes of landmines recur across multi-repo pushes:\n\n1. **Multi-MB recovery artifact folders** — `dk2d-recovery-*\u002F`, `*\u002Fartifacts\u002F`, `ao-*-*\u002F`\n   containing `b3\u002F`, `native32\u002F`, `*.so`, raw ffprobe dumps. NEVER push.\n2. **`.beads\u002F.br_history\u002F*.jsonl`** — bead CLI history dumps that aren't in `.gitignore`\n   by default. ALWAYS skip; recommend adding `.beads\u002F.br_history\u002F` to `.gitignore` in\n   the next session.\n3. **Auto-export cron dumps under `cron\u002F` or `launchd\u002F`** — these are usually already\n   committed at their canonical paths, but the local working tree may have stale copies\n   that look untracked after a half-completed export run.\n\n**The pre-push checklist:**\n\n```bash\n# 1. Size audit — anything >5 MB untracked is suspicious\ngit status --short | grep \"^??\" | awk '{print $2}' | xargs -I {} sh -c 'du -sh \"{}\" 2>\u002Fdev\u002Fnull' | sort -h | tail -10\n\n# 2. First-line sniff of every borderline file (.md files, by 10-line head)\nfor f in $(git status --short | grep \"^??\" | awk '{print $2}' | grep '\\.md$'); do\n  echo \"=== $f ===\"; head -10 \"$f\"; echo\ndone\n\n# 3. Stale-branch probe — confirm you're on the branch you think you are\ngit branch --show-current\ngit rev-parse --abbrev-ref --symbolic-full-name @{u}    # upstream\n\n# 4. Auth probe — confirm gh-vs-target-org alignment\ngh auth status | grep -E \"account|Active\" | head -3\n```\n\nIf any check returns a landmine, STOP and ask the user or skip the file explicitly.\nDo not `git add -A` and hope.\n\n#### 3d. Stash-then-checkout to free a dirty worktree for branch switching\n\n**Trigger:** You need to `git checkout main` (or any branch) but the current branch\nhas `M` files that `git status` reports would be overwritten. The dirty files are\ncontent you DO want to push (they correspond to commits on the current branch you'll\nre-apply via cherry-pick), but `git checkout` refuses without `commit` or `stash`.\n\n**The pattern:**\n\n```bash\n# 1. Stash ONLY the explicitly-named files (not `git stash` blanket)\ngit stash push -m \"branch-rescue-stash\" -- README.md learnings-2026-07.md\n\n# 2. Now checkout succeeds\ngit checkout main\n\n# 3. Cherry-pick the commits that originally carried those file changes\ngit cherry-pick \u003Csha1> \u003Csha2> ...\n\n# 4. Resolve any post-cherry-pick conflicts (see 3e below)\n\n# 5. Drop the stash when the cherry-picks succeed\ngit stash list    # confirm it's still there\ngit stash drop stash@{0}\n```\n\n**DO NOT use `git stash pop` here** — if cherry-picking conflicted, `stash drop` is\ncleaner; `stash pop` would either fail or silently re-apply dirt that the merge\nalready covered.\n\n#### 3e. Rebase-onto-origin\u002Fmain conflict when BOTH local-main commits AND\ncherry-picked-feature-branch commits modified the same journal file\n\n**Trigger:** You `git rebase origin\u002Fmain` after fetching new remote commits, and the\nrebase aborts with a `\u003C\u003C\u003C\u003C\u003C\u003C\u003C HEAD` \u002F `=======` \u002F `>>>>>>> \u003Csha>` conflict in a file\nnamed `learnings-YYYY-MM.md`, `daily-log-YYYY-MM.md`, or any chronological journal\nwhere both sides added dated entries.\n\n**Why this fires:** the local feature branch was branched from origin\u002Fmain BEFORE\nthe auto-export cron added N more journal entries. After you cherry-pick the\nfeature-branch commits onto `main`, then `git fetch` shows origin\u002Fmain has 7 more\njournal entries ahead of `main` too. The rebase merges local-vs-remote BOTH having\nnew journal entries — most are unique-but-similar in shape, so `git` conflates them\ninto a hunk conflict.\n\n**The resolution rule:** **keep ALL dated entries from both sides, in chronological\norder.** Do NOT `git checkout --theirs` (loses your entries) or `--ours` (loses\nremote's entries). Open the conflict block, identify each `## YYYY-MM-DD` heading,\ninterleave them by date, drop the markers.\n\n```bash\n# After patch'ing the file with merged content:\ngrep -nE \"^(\u003C\u003C\u003C\u003C\u003C\u003C\u003C|=======|>>>>>>>)\" learnings-2026-07.md | head -5\n# MUST return zero matches before continuing\n\ngit add learnings-2026-07.md\ngit rebase --continue\n```\n\nIf the markers still exist after `patch`, the rebase will silently produce a\ncorrupted commit — gate on `grep` returning zero.\n\n## Integration with Existing Skills\n\n- **Load with `llm-wiki`** when the user is doing structured research ingest. The\n  llm-wiki skill covers the Karpathy pattern and orientation; this skill covers the\n  safety + git-push layer.\n- **Load with `obsidian`** when the user is doing personal-note work in Obsidian.\n  The obsidian skill covers vault mechanics (path resolution, read\u002Fwrite\u002Fappend,\n  wikilinks); this skill covers the \"populated vault + git push\" edge cases.\n- **Companion to `github-pr-workflow`**: this skill is for personal wikis, not\n  project repos. For project repos with branch protection and PR review, follow\n  the standard `always-pr-never-local-edit` + `github-pr-workflow` patterns instead.\n\n## Quick Reference: Decision Table\n\n| Situation | Action |\n|---|---|\n| Vault exists, target page exists, content is mine to write | `read_file` then `patch` (append) |\n| Vault exists, target page exists, content contradicts existing | `patch` + add `contradictions:` frontmatter |\n| Vault exists, target page is new | `write_file` (safe — no existing content to clobber) |\n| Vault exists, user asked for a \"research artifact\" \u002F \"brief\" | Default-doing-now: write to `sources\u002F`, create concepts, update index |\n| User asked \"where should I save this?\" | Don't ask back. Save to vault on this turn and tell them where. |\n| User asked \"push to origin main\" and local is divergent | `reset --hard origin\u002Fmain` → unstash → commit → push |\n| User asked \"push to origin main\" and local is clean | `git push origin main` directly |\n\n## Pitfalls (one-liners)\n\n- `write_file` clobbers — always `read_file` first.\n- Append-only by default; `write_file` only for genuinely new pages.\n- Default-doing-now: research artifacts go to vault, not `\u002Ftmp`.\n- Never `git add -A` in a vault repo with concurrent agent activity.\n- Never `git checkout --theirs` on `index.md` — merge manually.\n- `\u002Ftmp\u002Ffoo.md` is a bug, not a strategy.\n- `git status` snapshot is stale — confirm `git ls-files \u003Cpath>` before staging borderline files.\n- Pre-push audit: `du -sh` every untracked dir, head-sniff borderline `.md`s, verify branch + auth.\n- `git push` returning \"Repository not found\" against a non-`jleechanorg` org = wrong active `gh` account; use a token override pattern (see 3a).\n- `git rebase origin\u002Fmain` conflict on a journal file = both sides added dated entries; merge chronologically, never `--theirs` or `--ours`.\n- `git stash drop`, not `git stash pop`, after a successful cherry-pick that re-applies stashed content.\n\n### Failure Mode 4: `sources\u002F` vs `raw\u002F` directory trap (frontmatter field confused with Layer 1 directory)\n\n**Symptom:** A worker is told to ingest N source articles into the wiki. It writes N concept pages with correct frontmatter `sources: [\"mbti\u002FENFJ-per.html\"]` but the **directory** it points at is `sources\u002Farticles\u002Fmbti\u002FENFJ-per.html` — a path that does not exist in this wiki. The wiki's Layer 1 directory is `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F`, `raw\u002Ftranscripts\u002F`, `raw\u002Fassets\u002F`), not `sources\u002Farticles\u002F`. The wiki is missing the actual source files (the worker either never fetched them, or fetched them into the wrong directory, or just summarized without saving). The next lint pass's source-drift check (item ⑧ in `llm-wiki`) becomes a no-op for those sources.\n\n**Why this fires:** The frontmatter field is `sources:` (plural noun) and the URL-prefix convention is `raw\u002F`. The worker has both `sources:` (in frontmatter) and the source path string (in the value) and conflates them, inventing `sources\u002Farticles\u002F` as a directory because \"the value starts with `sources\u002F`\". This is a \"the model improvises formatting\" class of error — see `llm-narration-format-clarifier` for the broader pattern.\n\n**The rule:** the `sources:` frontmatter field's value is **always a path under `raw\u002F`**. Valid forms:\n- `raw\u002Farticles\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.md` (LLM-extracted text)\n- `raw\u002Farticles\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.html` (raw HTML when the original is HTML and the LLM hasn't reformatted it)\n- `raw\u002Fpapers\u002F\u003Carxiv-id>-\u003Cslug>.pdf` (arXiv PDFs)\n- `raw\u002Ftranscripts\u002F\u003Cmeeting-slug>-YYYY-MM-DD.md`\n- `raw\u002Fassets\u002F\u003Cimage>.png`\n\nNever `sources\u002F`, never `articles\u002F` (without `raw\u002F` prefix), never any path that doesn't start with `raw\u002F`.\n\n**Diagnostic (5 commands, ~3s):**\n\n```bash\n# 1. List every concept page's sources: frontmatter value\nfor f in $WIKI\u002Fconcepts\u002F*.md; do\n  grep -E '^sources:' \"$f\"\ndone | sort -u\n\n# 2. For every non-raw-prefixed source, flag it\ngrep -rEh '^sources:' $WIKI\u002F | grep -vE '\"raw\u002F' | head -20\n\n# 3. For every flagged source, check whether the file exists\n# (this is what `llm-wiki` lint item ⑧ does — if it can't find the file, it can't drift-check)\n```\n\n**Recovery recipe (sed fix across all flagged files):**\n\n```bash\n# Verify the substitution works for one file before bulk-applying\ngrep -nE '^sources:.*\"sources\u002F' \"$WIKI\u002Fconcepts\u002Fmbti\u002FENFJ.md\"\n\n# Bulk-fix: sources\u002Farticles\u002F\u003CTYPE>.html → raw\u002Farticles\u002F\u003CTYPE>.html\nfor f in $(grep -rlE '^sources:.*\"sources\u002F' $WIKI\u002F); do\n  sed -i '' 's|\"sources\u002Farticles\u002F|\"raw\u002Farticles\u002F|g' \"$f\"\ndone\n\n# Verify no flagged paths remain\ngrep -rEh '^sources:' $WIKI\u002F | grep -vE '\"raw\u002F' | head -5\n# Expect: zero output\n```\n\n**Verified session (2026-07-28):** 16-MBTI ingest. The wiki worker wrote 16 concept pages + 1 index page, each with `sources: [\"sources\u002Farticles\u002Fmbti\u002F{TYPE}-per.html\"]`. None of those source files existed. Parent session (1) ran the Python-script curl-fetch into the **correct** `raw\u002Farticles\u002Fmbti\u002F` directory, then (2) bulk-sed-fixed all 17 files to use `raw\u002Farticles\u002F` paths. ~10 lines of sed + a 90-second Python ingest script. The fix would have been 2 lines per file if the worker had used the right path the first time.\n\n**Anti-pattern:** re-running the worker with a bigger `--max-turns` budget. The worker will fix 1-2 files and re-time-out at the same place. The parent-session sed fix is faster (sub-second) and avoids losing the worker's well-formed concept pages.\n\n### Failure Mode 5: Concept pages without raw sources (skipped the `raw\u002F` ingest step)\n\n**Symptom:** A worker is told to ingest N articles (e.g. \"ingest 16 MBTI personality pages from personalitypage.com\"). It writes 16 concept pages summarizing each article, but it **skipped** the curl-fetch step into `raw\u002Farticles\u002F`. The `sources:` frontmatter on each concept page references a file that does not exist on disk. The wiki appears complete (17 markdown files for the MBTI topic) but is **un-re-ingestable**: when the source URL changes, the wiki can't detect drift because there's no source-of-truth hash to compare against.\n\n**Why this fires:** The worker treats \"summarize N articles into N concept pages\" as the deliverable and optimizes for \"concept pages exist\" rather than \"concept pages exist AND their raw sources exist\". This is a \"task boundary invisible\" error — see `claude-code-claudem` for the related worker-context boundary case.\n\n**The rule:** an ingest of N articles MUST produce N raw files in `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F` \u002F `raw\u002Ftranscripts\u002F`) AND N corresponding concept pages AND `index.md` references AND a `log.md` entry. Skipping any one of these four steps is incomplete. The lint check that catches this is **`raw\u002F` file-existence assertion during concept-page write**: when writing a concept page that references a `sources:` path, assert the file exists at write-time.\n\n**The write-time assertion recipe (run BEFORE `write_file` on the concept page):**\n\n```python\nimport os, re\nWIKI = \"$HOME\u002Fllm_wiki\u002Fwiki\"\nconcept_path = \"concepts\u002Fmbti\u002FENFJ.md\"\n# Extract the sources: line\nwith open(concept_path) as f:\n    sources_line = next((l for l in f if l.startswith(\"sources:\")), \"\")\nm = re.search(r'\"([^\"]+)\"', sources_line)\nif m:\n    raw_path = os.path.join(WIKI, m.group(1))\n    assert os.path.exists(raw_path), f\"Missing raw source: {raw_path}\"\n```\n\n**Diagnostic for \"did the worker skip the raw step?\":**\n\n```bash\n# 1. List all source paths referenced in concept pages\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u\n\n# 2. For each, check existence\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u | \\\n  tr -d '\"' | while read p; do\n    [ -f \"$WIKI\u002F$p\" ] && echo \"OK $p\" || echo \"MISSING $p\"\n  done\n\n# 3. Count missing\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u | \\\n  tr -d '\"' | while read p; do\n    [ ! -f \"$WIKI\u002F$p\" ] && echo \"$p\"\n  done | wc -l\n```\n\n**Recovery recipe (fetch the missing sources into `raw\u002F`):**\n\n```bash\nmkdir -p $WIKI\u002Fraw\u002Farticles\u002Fmbti\n# Use Python with proper request handling (curl loop with 0.5s sleep is acceptable\n# but watch for Ezoic\u002FCloudflare bot-detection that returns 200 with empty body).\n# The personalitypage.com 16-page MBTI ingest took 14s with a 0.4s sleep.\nfor t in ISTJ ISFJ INFJ INTJ ISTP ISFP INFP INTP ESTP ESFP ENFP ENTP ESTJ ESFJ ENFJ ENTJ; do\n  curl -fsS --max-time 30 -o $WIKI\u002Fraw\u002Farticles\u002Fmbti\u002F${t}-per.html \\\n    \"https:\u002F\u002Fpersonalitypage.com\u002Fhtml\u002F${t}-per.html\"\n  sleep 0.5\ndone\n```\n\n**Verified session (2026-07-28):** 16-MBTI ingest. Worker wrote 16 concept pages but skipped the raw step. Parent session ran a 90-second Python ingest script (with size-check + sleep) into the correct directory. The wiki now has 16 HTML files (79-97 KB each, sha256-hashed) AND 16 concept pages AND `index.md` references AND `log.md` entry — all 4 deliverable components intact.\n\n**Anti-pattern:** telling the worker \"you also need to write the raw files\" and re-dispatching. The worker will time out at the same place. Parent-session recovery is faster AND avoids losing the worker's well-formed concept pages.","# Wiki \u002F Vault Safeguards\n\nCompanion to the `llm-wiki` and `obsidian` skills. Those skills describe the Karpathy\npattern and Obsidian vault mechanics. This skill covers the **safety patterns** that\napply specifically when the vault is *populated* (multiple agents writing over time,\nmonths of accumulated concept pages) and **backed by a git repo** (`jleechanorg\u002Fllm-wiki.git`,\n`jleechanclaw` etc.) with concurrent activity.\n\n## When This Skill Activates\n\nLoad this skill when ANY of these are true:\n\n- The user asks to save, write, ingest, file, or commit a research artifact to a wiki\u002Fvault\n- The user asks to \"push the wiki to origin main\" \u002F \"commit the wiki\" \u002F \"push my notes\"\n- You're about to call `write_file` on a path inside `~\u002Fllm_wiki\u002F` or `~\u002Fwiki\u002F` or any\n  other markdown-vault directory\n- You see `wiki\u002F` or `notes\u002F` or `vault\u002F` referenced in the conversation and the wiki\n  is already populated (>20 markdown files)\n\n## Three Failure Modes This Skill Prevents\n\n### Failure Mode 1: Concept-page overwrite trap\n\n**Symptom:** You complete the orientation routine (read SCHEMA + index + scan log), see\nthat `concepts\u002FHarnessEngineering.md` exists with a 2026-04-14 last_updated date, and\ncorrectly decide \"the answer belongs in `concepts\u002FHarnessEngineering.md`.\" Then you\ncall `write_file(path='concepts\u002FHarnessEngineering.md', content=\u003Cnew content>)`. The\npre-existing 60+ lines of Meta-Harness paper + 4-layer architecture + OpenAI workshop\nnotes are silently gone. No error, no warning.\n\n**Why orientation didn't save you:** The orientation routine tells you a page exists.\nIt does not enforce the merge-with-existing rule on `write_file`. `write_file` is a\n*clobber-and-replace* primitive — that's its contract.\n\n**The three-step pattern before any write to a known-existing page:**\n\n1. **Re-read the target file** (`read_file path=\u003Cconcept>.md`) immediately before\n   `write_file`. Even if you saw the path in `index.md` 3 turns ago, re-read — the\n   page may have been updated by another agent in parallel.\n2. **Diff concepts, not just filenames.** If the existing page covers a *different\n   framing* of the same word (e.g. pre-existing HarnessEngineering is the\n   self-bootstrapping agent runtime harness; new research is the AIEWF 2026\n   human-org harness), the answer is **append a section, not overwrite**.\n   Append-only preserves the compounding nature of the wiki.\n3. **When in doubt, `patch` not `write_file`.** Read the existing page, find a stable\n   anchor (last bullet list, last heading, etc.), and `patch` to add a new section.\n   `write_file` is only safe for genuinely new pages or genuinely\n   contradicted-and-resolved content (mark with `contradictions:` frontmatter first).\n\n**Recovery if you clobbered:** If the vault is under git (which is the assumption for\nthis skill), `git checkout HEAD -- \u003Cpath>` restores the pre-write state, then re-do\nthe work as a `patch` append.\n\n**Verified session:** 2026-07-14, AIEWF 2026 brief. I clobbered `HarnessEngineering.md`\nthat had the Meta-Harness paper + 4-layer architecture. Recovered via `git checkout HEAD\n-- concepts\u002FHarnessEngineering.md`, then used `patch` to append a new AIEWF validation\nsection. Net result: +14 lines additive, zero content loss.\n\n### Failure Mode 2: Research artifact saved to \u002Ftmp, then pick-one-menu asked\n\n**Symptom:** User asks \"research the top 10 learnings from the conference.\" You write the\nbrief to `\u002Ftmp\u002Faiewf-2026-top-10.md` (volatile), post a Slack reply with the summary,\nand ask \"Pick one: (a) save to wiki (b) deeper AO pull (c) LinkedIn draft.\" User replies\n\"keep going save the brief and summarize it, why did you stop.\"\n\n**Why this is wrong twice over:** (1) `\u002Ftmp\u002Ffoo.md` is volatile — gone on next reboot.\n(2) The pick-one-menu violates SOUL.md `no-pick-one-menus` COMMIT explicitly.\n\n**The default-doing-now move:**\n\n1. Write the brief to `sources\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.md` (or `raw\u002Farticles\u002F`\n   per plain Karpathy-pattern vaults).\n2. Create the 2-3 concept pages the brief implies, each with cross-references via\n   `[[wikilinks]]`.\n3. Add entries to `index.md` linking them.\n4. Post a one-line summary back to the originating thread.\n\n**Do NOT ask \"where should I save this?\"** The vault is the answer. Default-doing-now\napplies. Volatile `\u002Ftmp` + ask-the-user is the failure mode. The user can always say\n\"move it elsewhere,\" but `\u002Ftmp` is wrong by default.\n\n### Failure Mode 3: Push to origin main with divergent history\n\n**Symptom:** User says \"push to origin main.\" You `git status` and see 3\n`[Auto] Pending changes` commits ahead of origin\u002Fmain, none of them yours. You try\n`git rebase origin\u002Fmain` and it aborts with conflicts in `raw\u002Fcampaigns\u002F*` that have\nnothing to do with your work.\n\n**The safe pattern:**\n\n1. `git fetch origin` first — see the actual remote state.\n2. `git status --short --branch` — local divergence from origin.\n3. `git log origin\u002Fmain..HEAD` and `git diff --stat origin\u002Fmain..HEAD` — identify\n   which local commits are yours vs pre-existing.\n4. **Decision tree:**\n   - **Unrelated pre-existing commits → `git reset --hard origin\u002Fmain`** then unstash\n     your work, commit, push. Cleaner linear history.\n   - **Your commits you want to preserve → rebase manually**, resolve conflicts\n     file-by-file with `git checkout --theirs\u002F--ours \u003Cpath>` for specific hunks.\n5. **Never `git checkout --theirs \u003Cindex.md>` wholesale** — you'll lose other agents'\n   recent entries. Resolve `index.md` conflicts manually by reading both versions and\n   merging the additions.\n6. **Stage only your files** with explicit paths, not `git add -A`. Untracked files\n   in `.beads\u002F`, `artifacts\u002F`, `raw\u002F` from other agents are not yours to commit.\n   (Verified: 50+ untracked `.beads\u002F.br_history\u002F*.jsonl` files in `~\u002Fllm_wiki` from\n   prior sessions — none related to AIEWF brief, all left alone.)\n7. Commit with a scoped message that names the source\u002Fsession\u002Ftask, then `git push origin main`.\n8. Verify: `git rev-parse origin\u002Fmain` matches local HEAD SHA.\n\nIf the vault is **not** under git, report that explicitly to the user and offer\n`git init` + first-commit. Don't `git push` to a non-existent remote.\n\n#### 3a. Cross-org push when `gh auth` is wrong for the vault's remote\n\n**Trigger:** `git push origin main` returns `Repository not found` against a remote\nURL like `https:\u002F\u002Fgithub.com\u002FAgnt-F\u002F\u003Crepo>.git` or `https:\u002F\u002Fgithub.com\u002F\u003Cother-org>\u002F\u003Crepo>.git`,\nwhile `gh auth status` shows the active account is `jleechan2015` (member of\n`jleechanorg` but NOT of the vault's org).\n\n**Why this fires:** `gh`'s HTTP-credential helper scopes the token to the active\naccount's accessible orgs. `jleechan2015` cannot push to `Agnt-F\u002F*` even if a `$USER-af`\naccount exists in 1Password\u002FKeychain — `gh` only knows about one active user at a time.\n\n**The fix — token override for one push, no global config pollution:**\n\n```bash\n# 1. Verify a non-gh token exists for the target org in the environment\nGH_TOKEN_AGENTF=\"$GH_TOKEN_AGENTF\" curl -sS -o \u002Fdev\u002Fnull -w \"HTTP %{http_code}\\n\" \\\n  -H \"Authorization: token $GH_TOKEN_AGENTF\" -H \"User-Agent: hermes-push\" \\\n  https:\u002F\u002Fapi.github.com\u002Frepos\u002FAgnt-F\u002F\u003Crepo>\n\n# Expect HTTP 200. If 401\u002F404 the token is wrong or has wrong scope.\n\n# 2. Push with that token via URL insteadOf + a credential helper that reads from env\ngit -c credential.helper='!f() { echo \"username=x-access-token\"; echo \"password=$1\"; }; f \"$@\"' \\\n    -c \"url.https:\u002F\u002Fx-access-token:$GH_TOKEN_AGENTF@github.com\u002FAgnt-F\u002F\u003Crepo>.git\u002F.insteadOf=https:\u002F\u002Fgithub.com\u002FAgnt-F\u002F\u003Crepo>.git\" \\\n    push origin main\n```\n\n**DOs \u002F DON'Ts:**\n- DO use `GH_TOKEN_AGENTF` (or whatever the org-scoped env var is) — DO NOT embed the\n  token in the remote URL with `git remote set-url origin ...`.\n- DO scope the `-c` flags to the one `push` invocation — DO NOT `git config --global`.\n- DO verify the token with the API probe before pushing (saves a round-trip on a wrong token).\n- DO NOT echo the token in shell history. Use `$GH_TOKEN_AGENTF` directly, never `echo $GH_TOKEN_AGENTF`.\n\n**Companion rule:** for `Agnt-F\u002F*` Agnt-F vault work, load `agentf` skill alongside\nthis one — it documents the `$USER-af` vs `jleechan2015` distinction and the\ncanonical token location.\n\n#### 3b. \"Is this file already committed?\" — `git status` lies, `git ls-files` is the truth\n\n**Trigger:** A path appears in `git status --short` as `?? foo\u002Fbar.md` (untracked)\non the first scan, but after `git add` of OTHER files it disappears from the\nuntracked list — and yet `git ls-files foo\u002Fbar.md` returns the path. If you\nincluded the path in your `git add` list, it was a no-op but you also didn't double-check.\n\n**Why this fires:** A race between your `git status` call and another agent \u002F cron\nrunning `git add foo\u002Fbar.md && git commit` mid-session. The untracked-list snippet\nyou snapshotted is stale by the time you stage other files.\n\n**The diagnostic:**\n```bash\n# Before adding ANY borderline path, verify it is currently untracked\ngit ls-files \u003Cpath>          # empty output → truly untracked, safe to add\ngit log --all --oneline -- \u003Cpath> | head -3   # see if it has commit history\n```\n\n**The rule:** when building an `git add \u003Clist>` command, run `git ls-files \u003Ceach-path>`\nin a parallel batch first. Paths that return a hit were already committed by another\nagent — drop them from the add list. Paths that return empty are still untracked.\n\n#### 3c. Landmine taxonomy — pre-push checklist for untracked file lists\n\n**Trigger:** `git status --short` lists 10+ untracked files and at least one has a\nborderline name (`*-recovery-*`, `nextsteps-*`, `*-audit-*`, numeric ID, etc.).\nThree classes of landmines recur across multi-repo pushes:\n\n1. **Multi-MB recovery artifact folders** — `dk2d-recovery-*\u002F`, `*\u002Fartifacts\u002F`, `ao-*-*\u002F`\n   containing `b3\u002F`, `native32\u002F`, `*.so`, raw ffprobe dumps. NEVER push.\n2. **`.beads\u002F.br_history\u002F*.jsonl`** — bead CLI history dumps that aren't in `.gitignore`\n   by default. ALWAYS skip; recommend adding `.beads\u002F.br_history\u002F` to `.gitignore` in\n   the next session.\n3. **Auto-export cron dumps under `cron\u002F` or `launchd\u002F`** — these are usually already\n   committed at their canonical paths, but the local working tree may have stale copies\n   that look untracked after a half-completed export run.\n\n**The pre-push checklist:**\n\n```bash\n# 1. Size audit — anything >5 MB untracked is suspicious\ngit status --short | grep \"^??\" | awk '{print $2}' | xargs -I {} sh -c 'du -sh \"{}\" 2>\u002Fdev\u002Fnull' | sort -h | tail -10\n\n# 2. First-line sniff of every borderline file (.md files, by 10-line head)\nfor f in $(git status --short | grep \"^??\" | awk '{print $2}' | grep '\\.md$'); do\n  echo \"=== $f ===\"; head -10 \"$f\"; echo\ndone\n\n# 3. Stale-branch probe — confirm you're on the branch you think you are\ngit branch --show-current\ngit rev-parse --abbrev-ref --symbolic-full-name @{u}    # upstream\n\n# 4. Auth probe — confirm gh-vs-target-org alignment\ngh auth status | grep -E \"account|Active\" | head -3\n```\n\nIf any check returns a landmine, STOP and ask the user or skip the file explicitly.\nDo not `git add -A` and hope.\n\n#### 3d. Stash-then-checkout to free a dirty worktree for branch switching\n\n**Trigger:** You need to `git checkout main` (or any branch) but the current branch\nhas `M` files that `git status` reports would be overwritten. The dirty files are\ncontent you DO want to push (they correspond to commits on the current branch you'll\nre-apply via cherry-pick), but `git checkout` refuses without `commit` or `stash`.\n\n**The pattern:**\n\n```bash\n# 1. Stash ONLY the explicitly-named files (not `git stash` blanket)\ngit stash push -m \"branch-rescue-stash\" -- README.md learnings-2026-07.md\n\n# 2. Now checkout succeeds\ngit checkout main\n\n# 3. Cherry-pick the commits that originally carried those file changes\ngit cherry-pick \u003Csha1> \u003Csha2> ...\n\n# 4. Resolve any post-cherry-pick conflicts (see 3e below)\n\n# 5. Drop the stash when the cherry-picks succeed\ngit stash list    # confirm it's still there\ngit stash drop stash@{0}\n```\n\n**DO NOT use `git stash pop` here** — if cherry-picking conflicted, `stash drop` is\ncleaner; `stash pop` would either fail or silently re-apply dirt that the merge\nalready covered.\n\n#### 3e. Rebase-onto-origin\u002Fmain conflict when BOTH local-main commits AND\ncherry-picked-feature-branch commits modified the same journal file\n\n**Trigger:** You `git rebase origin\u002Fmain` after fetching new remote commits, and the\nrebase aborts with a `\u003C\u003C\u003C\u003C\u003C\u003C\u003C HEAD` \u002F `=======` \u002F `>>>>>>> \u003Csha>` conflict in a file\nnamed `learnings-YYYY-MM.md`, `daily-log-YYYY-MM.md`, or any chronological journal\nwhere both sides added dated entries.\n\n**Why this fires:** the local feature branch was branched from origin\u002Fmain BEFORE\nthe auto-export cron added N more journal entries. After you cherry-pick the\nfeature-branch commits onto `main`, then `git fetch` shows origin\u002Fmain has 7 more\njournal entries ahead of `main` too. The rebase merges local-vs-remote BOTH having\nnew journal entries — most are unique-but-similar in shape, so `git` conflates them\ninto a hunk conflict.\n\n**The resolution rule:** **keep ALL dated entries from both sides, in chronological\norder.** Do NOT `git checkout --theirs` (loses your entries) or `--ours` (loses\nremote's entries). Open the conflict block, identify each `## YYYY-MM-DD` heading,\ninterleave them by date, drop the markers.\n\n```bash\n# After patch'ing the file with merged content:\ngrep -nE \"^(\u003C\u003C\u003C\u003C\u003C\u003C\u003C|=======|>>>>>>>)\" learnings-2026-07.md | head -5\n# MUST return zero matches before continuing\n\ngit add learnings-2026-07.md\ngit rebase --continue\n```\n\nIf the markers still exist after `patch`, the rebase will silently produce a\ncorrupted commit — gate on `grep` returning zero.\n\n## Integration with Existing Skills\n\n- **Load with `llm-wiki`** when the user is doing structured research ingest. The\n  llm-wiki skill covers the Karpathy pattern and orientation; this skill covers the\n  safety + git-push layer.\n- **Load with `obsidian`** when the user is doing personal-note work in Obsidian.\n  The obsidian skill covers vault mechanics (path resolution, read\u002Fwrite\u002Fappend,\n  wikilinks); this skill covers the \"populated vault + git push\" edge cases.\n- **Companion to `github-pr-workflow`**: this skill is for personal wikis, not\n  project repos. For project repos with branch protection and PR review, follow\n  the standard `always-pr-never-local-edit` + `github-pr-workflow` patterns instead.\n\n## Quick Reference: Decision Table\n\n| Situation | Action |\n|---|---|\n| Vault exists, target page exists, content is mine to write | `read_file` then `patch` (append) |\n| Vault exists, target page exists, content contradicts existing | `patch` + add `contradictions:` frontmatter |\n| Vault exists, target page is new | `write_file` (safe — no existing content to clobber) |\n| Vault exists, user asked for a \"research artifact\" \u002F \"brief\" | Default-doing-now: write to `sources\u002F`, create concepts, update index |\n| User asked \"where should I save this?\" | Don't ask back. Save to vault on this turn and tell them where. |\n| User asked \"push to origin main\" and local is divergent | `reset --hard origin\u002Fmain` → unstash → commit → push |\n| User asked \"push to origin main\" and local is clean | `git push origin main` directly |\n\n## Pitfalls (one-liners)\n\n- `write_file` clobbers — always `read_file` first.\n- Append-only by default; `write_file` only for genuinely new pages.\n- Default-doing-now: research artifacts go to vault, not `\u002Ftmp`.\n- Never `git add -A` in a vault repo with concurrent agent activity.\n- Never `git checkout --theirs` on `index.md` — merge manually.\n- `\u002Ftmp\u002Ffoo.md` is a bug, not a strategy.\n- `git status` snapshot is stale — confirm `git ls-files \u003Cpath>` before staging borderline files.\n- Pre-push audit: `du -sh` every untracked dir, head-sniff borderline `.md`s, verify branch + auth.\n- `git push` returning \"Repository not found\" against a non-`jleechanorg` org = wrong active `gh` account; use a token override pattern (see 3a).\n- `git rebase origin\u002Fmain` conflict on a journal file = both sides added dated entries; merge chronologically, never `--theirs` or `--ours`.\n- `git stash drop`, not `git stash pop`, after a successful cherry-pick that re-applies stashed content.\n\n### Failure Mode 4: `sources\u002F` vs `raw\u002F` directory trap (frontmatter field confused with Layer 1 directory)\n\n**Symptom:** A worker is told to ingest N source articles into the wiki. It writes N concept pages with correct frontmatter `sources: [\"mbti\u002FENFJ-per.html\"]` but the **directory** it points at is `sources\u002Farticles\u002Fmbti\u002FENFJ-per.html` — a path that does not exist in this wiki. The wiki's Layer 1 directory is `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F`, `raw\u002Ftranscripts\u002F`, `raw\u002Fassets\u002F`), not `sources\u002Farticles\u002F`. The wiki is missing the actual source files (the worker either never fetched them, or fetched them into the wrong directory, or just summarized without saving). The next lint pass's source-drift check (item ⑧ in `llm-wiki`) becomes a no-op for those sources.\n\n**Why this fires:** The frontmatter field is `sources:` (plural noun) and the URL-prefix convention is `raw\u002F`. The worker has both `sources:` (in frontmatter) and the source path string (in the value) and conflates them, inventing `sources\u002Farticles\u002F` as a directory because \"the value starts with `sources\u002F`\". This is a \"the model improvises formatting\" class of error — see `llm-narration-format-clarifier` for the broader pattern.\n\n**The rule:** the `sources:` frontmatter field's value is **always a path under `raw\u002F`**. Valid forms:\n- `raw\u002Farticles\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.md` (LLM-extracted text)\n- `raw\u002Farticles\u002F\u003Cdescriptive-slug>-YYYY-MM-DD.html` (raw HTML when the original is HTML and the LLM hasn't reformatted it)\n- `raw\u002Fpapers\u002F\u003Carxiv-id>-\u003Cslug>.pdf` (arXiv PDFs)\n- `raw\u002Ftranscripts\u002F\u003Cmeeting-slug>-YYYY-MM-DD.md`\n- `raw\u002Fassets\u002F\u003Cimage>.png`\n\nNever `sources\u002F`, never `articles\u002F` (without `raw\u002F` prefix), never any path that doesn't start with `raw\u002F`.\n\n**Diagnostic (5 commands, ~3s):**\n\n```bash\n# 1. List every concept page's sources: frontmatter value\nfor f in $WIKI\u002Fconcepts\u002F*.md; do\n  grep -E '^sources:' \"$f\"\ndone | sort -u\n\n# 2. For every non-raw-prefixed source, flag it\ngrep -rEh '^sources:' $WIKI\u002F | grep -vE '\"raw\u002F' | head -20\n\n# 3. For every flagged source, check whether the file exists\n# (this is what `llm-wiki` lint item ⑧ does — if it can't find the file, it can't drift-check)\n```\n\n**Recovery recipe (sed fix across all flagged files):**\n\n```bash\n# Verify the substitution works for one file before bulk-applying\ngrep -nE '^sources:.*\"sources\u002F' \"$WIKI\u002Fconcepts\u002Fmbti\u002FENFJ.md\"\n\n# Bulk-fix: sources\u002Farticles\u002F\u003CTYPE>.html → raw\u002Farticles\u002F\u003CTYPE>.html\nfor f in $(grep -rlE '^sources:.*\"sources\u002F' $WIKI\u002F); do\n  sed -i '' 's|\"sources\u002Farticles\u002F|\"raw\u002Farticles\u002F|g' \"$f\"\ndone\n\n# Verify no flagged paths remain\ngrep -rEh '^sources:' $WIKI\u002F | grep -vE '\"raw\u002F' | head -5\n# Expect: zero output\n```\n\n**Verified session (2026-07-28):** 16-MBTI ingest. The wiki worker wrote 16 concept pages + 1 index page, each with `sources: [\"sources\u002Farticles\u002Fmbti\u002F{TYPE}-per.html\"]`. None of those source files existed. Parent session (1) ran the Python-script curl-fetch into the **correct** `raw\u002Farticles\u002Fmbti\u002F` directory, then (2) bulk-sed-fixed all 17 files to use `raw\u002Farticles\u002F` paths. ~10 lines of sed + a 90-second Python ingest script. The fix would have been 2 lines per file if the worker had used the right path the first time.\n\n**Anti-pattern:** re-running the worker with a bigger `--max-turns` budget. The worker will fix 1-2 files and re-time-out at the same place. The parent-session sed fix is faster (sub-second) and avoids losing the worker's well-formed concept pages.\n\n### Failure Mode 5: Concept pages without raw sources (skipped the `raw\u002F` ingest step)\n\n**Symptom:** A worker is told to ingest N articles (e.g. \"ingest 16 MBTI personality pages from personalitypage.com\"). It writes 16 concept pages summarizing each article, but it **skipped** the curl-fetch step into `raw\u002Farticles\u002F`. The `sources:` frontmatter on each concept page references a file that does not exist on disk. The wiki appears complete (17 markdown files for the MBTI topic) but is **un-re-ingestable**: when the source URL changes, the wiki can't detect drift because there's no source-of-truth hash to compare against.\n\n**Why this fires:** The worker treats \"summarize N articles into N concept pages\" as the deliverable and optimizes for \"concept pages exist\" rather than \"concept pages exist AND their raw sources exist\". This is a \"task boundary invisible\" error — see `claude-code-claudem` for the related worker-context boundary case.\n\n**The rule:** an ingest of N articles MUST produce N raw files in `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F` \u002F `raw\u002Ftranscripts\u002F`) AND N corresponding concept pages AND `index.md` references AND a `log.md` entry. Skipping any one of these four steps is incomplete. The lint check that catches this is **`raw\u002F` file-existence assertion during concept-page write**: when writing a concept page that references a `sources:` path, assert the file exists at write-time.\n\n**The write-time assertion recipe (run BEFORE `write_file` on the concept page):**\n\n```python\nimport os, re\nWIKI = \"$HOME\u002Fllm_wiki\u002Fwiki\"\nconcept_path = \"concepts\u002Fmbti\u002FENFJ.md\"\n# Extract the sources: line\nwith open(concept_path) as f:\n    sources_line = next((l for l in f if l.startswith(\"sources:\")), \"\")\nm = re.search(r'\"([^\"]+)\"', sources_line)\nif m:\n    raw_path = os.path.join(WIKI, m.group(1))\n    assert os.path.exists(raw_path), f\"Missing raw source: {raw_path}\"\n```\n\n**Diagnostic for \"did the worker skip the raw step?\":**\n\n```bash\n# 1. List all source paths referenced in concept pages\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u\n\n# 2. For each, check existence\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u | \\\n  tr -d '\"' | while read p; do\n    [ -f \"$WIKI\u002F$p\" ] && echo \"OK $p\" || echo \"MISSING $p\"\n  done\n\n# 3. Count missing\ngrep -rhE '^sources:' $WIKI\u002Fconcepts\u002F | grep -oE '\"raw\u002F[^\"]+\"' | sort -u | \\\n  tr -d '\"' | while read p; do\n    [ ! -f \"$WIKI\u002F$p\" ] && echo \"$p\"\n  done | wc -l\n```\n\n**Recovery recipe (fetch the missing sources into `raw\u002F`):**\n\n```bash\nmkdir -p $WIKI\u002Fraw\u002Farticles\u002Fmbti\n# Use Python with proper request handling (curl loop with 0.5s sleep is acceptable\n# but watch for Ezoic\u002FCloudflare bot-detection that returns 200 with empty body).\n# The personalitypage.com 16-page MBTI ingest took 14s with a 0.4s sleep.\nfor t in ISTJ ISFJ INFJ INTJ ISTP ISFP INFP INTP ESTP ESFP ENFP ENTP ESTJ ESFJ ENFJ ENTJ; do\n  curl -fsS --max-time 30 -o $WIKI\u002Fraw\u002Farticles\u002Fmbti\u002F${t}-per.html \\\n    \"https:\u002F\u002Fpersonalitypage.com\u002Fhtml\u002F${t}-per.html\"\n  sleep 0.5\ndone\n```\n\n**Verified session (2026-07-28):** 16-MBTI ingest. Worker wrote 16 concept pages but skipped the raw step. Parent session ran a 90-second Python ingest script (with size-check + sleep) into the correct directory. The wiki now has 16 HTML files (79-97 KB each, sha256-hashed) AND 16 concept pages AND `index.md` references AND `log.md` entry — all 4 deliverable components intact.\n\n**Anti-pattern:** telling the worker \"you also need to write the raw files\" and re-dispatching. The worker will time out at the same place. Parent-session recovery is faster AND avoids losing the worker's well-formed concept pages.",{"name":5,"author":57,"license":14,"version":58,"metadata":59,"changelog":67,"platforms":71,"description":7},"Hermes Agent","1.2.0",{"hermes":60},{"tags":61,"category":65,"related_skills":66},[28,62,63,48,27,64,39],"knowledge-base","safety","llm-wiki","research",[64,50],[68,69,70],"1.2.0 (2026-07-28): Two new pitfalls. (a) 'sources\u002F' vs 'raw\u002F' directory trap — workers invent `sources\u002Farticles\u002F` because the frontmatter field is `sources:` and they confuse field-with-directory. The wiki's Layer 1 directory is ALWAYS `raw\u002Farticles\u002F` (or `raw\u002Fpapers\u002F`, `raw\u002Ftranscripts\u002F`). A worker that wrote `sources: [\"sources\u002Farticles\u002Fmbti\u002FENFJ-per.html\"]` left 17 files with non-existent directory references; parent had to sed-fix all 17. (b) Concept pages without raw sources — workers that summarize N articles and write N concept pages but skip the curl-fetch into `raw\u002Farticles\u002F\u003Cfile>.\u003Cext>` step silently break re-ingest drift detection. Lint's source-drift check (item ⑧ in llm-wiki) becomes a no-op for the skipped sources. Both pitfalls verified on 16-MBTI ingest (2026-07-28, personalitypage.com).","1.1.0 (2026-07-26): Add Failure Modes 3a-3e (cross-org push with wrong gh account, git ls-files truth over git status, stash-then-checkout pattern, journal-file rebase conflict resolution).","1.0.0 (initial): Failure Modes 1-3 (overwrite trap, default-doing-now save, push-to-origin-main).",[72,73],"linux","macos","main","05df7380981a2c4af868ce0fa57962ae0eea62a9","hermes\u002Fskills\u002Fwiki-vault-safeguards",0,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills","https:\u002F\u002Fgithub.com\u002Fjleechanorg","2026-11-12 14:45:07",{"source":8,"skillName":5,"commands":82,"prompt":92,"zipAvailable":93},[83,86,89],{"tool":84,"command":85},"npx","npx skills add jleechanorg\u002Fjleechan-skills --skill wiki-vault-safeguards",{"tool":87,"command":88},"bunx","bunx skills add jleechanorg\u002Fjleechan-skills --skill wiki-vault-safeguards",{"tool":90,"command":91},"pnpm","pnpm dlx skills add jleechanorg\u002Fjleechan-skills --skill wiki-vault-safeguards","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fwiki-vault-safeguards\u002FSKILL.md",true,[],[96,114,136,150,164,180],{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":102,"publishedAt":52},"01M716Y5MTJ6GYJZ2ATXCJK8G4","instinct","Use when the user invokes \u002Finstinct or \u002Fin, or asks to \"message Instinct\", \"ask Instinct\", \"tell Instinct\", \"check Instinct\", or read replies from the configured peer assistant. iMessage first, WhatsApp Web as fallback.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Finstinct\u002FSKILL.md",[],[98,103,104,105,106,107,108,109,110,111,112,113],"user","when","replies","check","use","identity","whatsapp","gmail","read","message","ask",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":125,"publishedAt":52},"01M716Y4HF7FVVMJSA2CCVN5VF","hr","Compatibility alias for history-resume; produce the same fresh-state, provenance-aware resume briefing.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fhr\u002FSKILL.md",[120],{"categoryNo":121,"categoryName":122,"taxonomyType":123,"taxonomyTypeDesc":124},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[116,126,127,128,129,130,131,132,133,134,135],"resume","compatibility","provenance","for","history","produce","alias","briefing","state","fresh",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":52},"01M716Y1FFNFKFJYYKF8HQA6T8","history-resume","Resume briefing for the current repository branch or worktree using fresh state and admitted history sources.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fhistory-resume\u002FSKILL.md",[142],{"categoryNo":121,"categoryName":122,"taxonomyType":123,"taxonomyTypeDesc":124},[130,126,144,145,103,146,133,147,129,148,149,134,135],"history resume","branch","analysis","repository","worktree","sources",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":52},"01M716XWXJ8EPHK4RH9T14TR85","grok","Alias for the canonical grokbot browser conversation workflow; \u002Fgrok talks to the Grok bot the same way \u002Fdot talks to Dot.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgrok\u002FSKILL.md",[],[152,157,158,159,129,160,132,161,162,163],"dot","bot","workflow","canonical","conversation","browser","grokbot",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":170,"publishedAt":52},"01M70N9Q07DTE0EW5KFXMMMSJ0","codexa-bench","Compare `codexa` and normal `codex` on a fair split of comparable work by default; use `--strict` for duplicate runs of the exact same task.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fcodexa-bench\u002FSKILL.md",[],[171,172,173,107,174,129,175,176,177,178,179],"codexa bench","work","split","default","duplicate","task","compare","normal","codex",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":184,"licenseFileUrl":185,"sourceHtmlUrl":186,"categories":187,"keywords":197,"publishedAt":52},"01M6C24S2X60SP8BBFGAEKPEGW","frontend-design","Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML\u002FCSS layouts, or when styling\u002Fbeautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ffrontend-design\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ffrontend-design\u002FSKILL.md",[188,191,194],{"categoryNo":189,"categoryName":190,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":192,"categoryName":193,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":195,"categoryName":196,"taxonomyType":123,"taxonomyTypeDesc":124},"01JBSEEDCAT000000000000032","设计师",[198,199,200,107,201,202,203,103,38,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,104,221],"frontend","design","frontend design","generic","ui design","react","components","code","artifacts","ui","aesthetics","Production","web components","landing","applications","quality","web","css","create","examples","with","react components","web ui","pages"]