From cd937efc0140568f8e18a7dd3ee46b611c0b00a9 Mon Sep 17 00:00:00 2001 From: salvacybersec Date: Fri, 1 May 2026 13:26:36 +0300 Subject: [PATCH] docs: add Architecture section to README ASCII diagrams + prose covering: - Storage model: one parked source-of-truth fanned out to 3 lazy mirrors - Data flow for enable/disable (incremental INDEX updates, no global reindex) - INDEX.json schema with per-target active[] array - Interactive pick / disable-pick flows incl. target-picker UX - The fzf {} shell-escape gotcha and the correct quoting pattern --- README.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/README.md b/README.md index 7633684..fdd9feb 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,120 @@ opencode (≥1.14) auto-scans `~/.claude/skills/` as well as its own `~/.config/ For full agent / skill / persona generation across multiple AI platforms, see the upstream [`personas`](https://gitea.taygun.net.tr/salvacybersec/personas) repo. +## Architecture + +### Storage model — one source-of-truth, three lazy mirrors + +``` + ┌─────────────────────────────────────────┐ + │ ~/Documents/personas/skills-archive/ │ + │ (single source-of-truth, 1072+ skills) │ + │ │ + │ /SKILL.md ← frontmatter: │ + │ name, desc, │ + │ domain, sub, │ + │ tags │ + │ INDEX.json ← per-target active map │ + │ INDEX.md ← human-readable table │ + └─────────────────┬───────────────────────┘ + │ + │ cp -r (lazy, on demand, + │ per --target) + ▼ + ┌─────────────────────────┼─────────────────────────┐ + ▼ ▼ ▼ +┌───────────────┐ ┌───────────────┐ ┌───────────────┐ +│ opencode │ │ claude │ │ feynman │ +│ ~/.config/ │ │ ~/.claude/ │ │ ~/.feynman/ │ +│ opencode/ │ │ skills/ │ │ agent/ │ +│ skills/ │ │ │ │ skills/ │ +└───────────────┘ └───────────────┘ └───────────────┘ +``` + +The parked archive is the **only** dir that's authoritative. The three target dirs are mutable mirrors — `enable` copies in, `disable` removes from. No skill is ever deleted from parked by opc-skills. + +### Data flow — enable / disable + +``` + enable --target T1,T2,... + │ + ├──► for each target T: + │ cp -r PARKED/ → ACTIVE_T/ + │ sync shared refs (e.g. _platform-mapping.md) + │ INDEX.json: append T to record's `active[]` array + │ + └──► no global reindex required (incremental update) + + disable --target T1,T2,... + │ + ├──► for each target T: + │ rm -rf ACTIVE_T/ + │ INDEX.json: remove T from `active[]` + │ + └──► PARKED copy stays intact +``` + +### INDEX schema + +Each entry is a deduped record across all 3 targets: + +```json +{ + "folder": "performing-network-traffic-analysis-with-tshark", + "name": "performing-network-traffic-analysis-with-tshark", + "description": "Automate network traffic analysis using tshark…", + "domain": "cybersecurity", + "subdomain": "network-security", + "tags": ["network-analysis", "pcap", "tshark"], + "active": ["claude", "feynman"], // per-target presence + "status": "active" // "active" if any target, else "parked" +} +``` + +`reindex` rebuilds this from filesystem state across all 4 dirs (parked + 3 actives). `enable`/`disable` mutate `active[]` and `status` incrementally so bulk axis-ops (`enable-domain`, `enable-tag`) stay accurate without rescanning. + +### Interactive flows (`pick` / `disable-pick`) + +``` + pick: disable-pick: + ───── ──────────── + ① fzf: pick category ① fzf: pick category + (verb-prefix: performing, (from union-of-actives across + detecting, analyzing…) opencode + claude + feynman) + + ② fzf --multi: pick skills ② fzf --multi: pick skills + preview: PARKED//SKILL.md preview: same + [TAB toggles, ENTER confirms] rows annotated [oc,cl,fy] + + ③ fzf: pick target(s) ③ fzf: pick target(s) to remove from + ┌───────────────────────────┐ same picker + │ all (default) │ ENTER on highlighted "all" + │ opencode (N active) │ = remove from every target + │ claude (N active) │ where it's currently active + │ feynman (N active) │ + └───────────────────────────┘ + [TAB multi-select supported] + + ④ cp -r per-target ④ rm -rf per-target +``` + +The target picker leverages an fzf quirk: `--multi` returns the highlighted line as the sole selection if the user never pressed `TAB`. Putting `all` first means a default `ENTER` falls through to all three targets. + +### fzf `{}` quoting (gotcha) + +fzf shell-escapes `{}` substitutions automatically (wraps in single quotes). Wrapping `{}` again in outer quotes embeds those quote literals into the path: + +```bash +# ❌ becomes: sed -n '1,40p' ".../skills-archive/'name'/SKILL.md" +--preview="sed -n '1,40p' \"$PARKED/{}/SKILL.md\" 2>/dev/null" + +# ✅ becomes: sed -n '1,40p' ".../skills-archive"/'name'/SKILL.md +# (bash concatenates adjacent quoted/unquoted strings cleanly) +--preview="sed -n '1,40p' \"$PARKED\"/{}/SKILL.md 2>/dev/null" +``` + +All preview lines in `bin/opc-skills` follow the second pattern. + ## Install ```bash