本文へ移動
cccskills
無料GitHub で公開

graph

Rebuild the vault dependency graph (_graph.md) via the deterministic generator script. /graph forces a full rebuild; /graph last (run after every /sync) rebuilds only if the vault changed; /graph [N] is treated as last. The generator reads the vault and writes _graph.md directly, so the file never streams through a model response.

インストール方法を見る

含まれるファイル(3)

  • SKILL.md9.2 KB
  • generate_graph.py12.7 KB
  • RATIONALE.md18.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Rebuild _graph.md from vault state. Structural metadata only — no content files modified, no snapshots, no _hot.md changes.

Engine: .claude/skills/graph/generate_graph.py (deterministic). It reads every Thesis / Sector / Macro / Research file, validates wikilinks, and writes _graph.md directly. This replaced the legacy LLM-extraction + incremental-Edit procedure on 2026-06-04, after that approach hit a max-output-token wall: the full file is ~90 KB ≈ ~21 K output tokens, too large to emit in one model response — and both /graph (always full Write) and /graph last (escalation Write) funneled into that single oversized write. Generating the file from a script removes model output tokens from the path entirely, so the failure class (token ceiling, escalation traps, watermark edge cases, surgical-Edit anchor failures) cannot recur.

.last_sync is owned exclusively by /sync. /graph never touches it.

Design rationale for the (now-superseded) incremental design: .claude/skills/graph/RATIONALE.md. Legacy manual procedure: git history prior to 2026-06-04 + the Fallback section below.

Step 0: Pre-flight

0.1 Acquire vault lock

vault-wide scope per .claude/skills/_shared/preflight.md Procedure 1 (§1.3a) — /graph reads every thesis file, so a concurrent writer could produce inconsistent extraction. Capture the token; release in the final Bash block (ownership-checked).

Use the standard §1.3a block verbatim (with skill: /graph) — do NOT hand-roll a lock. The prior inline form omitted timeout_at:, the .vault-lock.* collision scan, and set -C noclobber, so (a) any preflight-conformant skill's collision loop read graph's lock as timeout_at:-empty → [[ "" > "$NOW" ]] false → classified a LIVE graph run STALE and invited a force-unlock, and (b) graph did not detect concurrent ticker locks at all.

LOCK_FILE=".vault-lock"
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
TOKEN="$(printf '%08x' $RANDOM$RANDOM)-$(date -u +%s)"
TIMEOUT_AT=$(date -u -v+10M +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '+10 minutes' +%Y-%m-%dT%H:%M:%SZ)
setopt NULL_GLOB 2>/dev/null || shopt -s nullglob 2>/dev/null || true

for existing in .vault-lock .vault-lock.* ; do
  [ -f "$existing" ] || continue
  EX_TIMEOUT=$(grep '^timeout_at:' "$existing" | sed 's/timeout_at: //')
  EX_SKILL=$(grep '^skill:' "$existing" | sed 's/skill: //')
  EX_TOKEN=$(grep '^token:' "$existing" | sed 's/token: //')
  if [[ "$EX_TIMEOUT" > "$NOW" ]]; then
    echo "LOCK_HELD|$existing|$EX_SKILL|$EX_TOKEN|$EX_TIMEOUT"; exit 1
  else
    echo "STALE_LOCK|$existing|$EX_SKILL|$EX_TOKEN|timeout_exceeded_at|$EX_TIMEOUT"; exit 2
  fi
done

set -C
if ! cat > "$LOCK_FILE" <<EOF
---
token: $TOKEN
skill: /graph
scope: vault-wide
started_at: $NOW
timeout_at: $TIMEOUT_AT
session_id: ${CLAUDE_SESSION_ID:-unknown}
---

# Vault lock

Held by /graph (token $TOKEN) since $NOW.
EOF
then
  set +C; echo "LOCK_RACE|$LOCK_FILE|created by a concurrent run between check and write — re-run"; exit 1
fi
set +C
trap "rm -f '$LOCK_FILE'" INT TERM
echo "ACQUIRED|$LOCK_FILE|$TOKEN"

Reclaim a stale lock (STALE_LOCK) only per §1.6 — never auto-steal. Release in the final Bash block with the ownership-verified form (grep '^token:' .vault-lock == $TOKEN before rm -f).

0.2 No rename-marker check

/graph is read-only for theses; the graph faithfully reflects current filenames + wikilinks. /lint #37 surfaces pending rename markers separately.

Step 1: Run the generator

Map the argument to a mode and invoke once:

InvocationArgBehavior
/graphfullAlways (re)writes _graph.md (disaster-recovery semantics).
/graph lastlastWrites only if the body changed OR a force-marker is present; else leaves the file untouched and reports up-to-date.
/graph [N]lastSame as last (N accepted for back-compat, treated as last).
python3 .claude/skills/graph/generate_graph.py full   # or: last

What the generator does (so the report is faithful):

  • Validates every wikilink against on-disk files; drops dangling refs (renamed sectors, legacy Macro/ prefix, typo'd thesis names) and the intentional-unresolved [[pinned]] / [[preserve]] markers (never flagged as broken).
  • Rebuilds adjacency, both reverse indexes, bidirectional clusters (union-find), and the orphan set from scratch every run — no drift.
  • Emits the T7.3 read-through cache (status: + log_tail: — last 3 Log entries, truncated at 100 chars + …) that /sync Pass 1 triage depends on.
  • Self-validates the written file (5 sections present; ### / status / log_tail counts all equal the thesis count). Exit 0 = written or up-to-date, 2 = validation failed, 1 = runtime error.
  • On a successful write, deletes the .sync_all_fresh and .graph_invalidations force-markers (their presence forces a write even when the body is unchanged, so closures/sync-all always reconcile).

If the generator exits non-zero: do NOT leave a half-written graph. Surface its stdout/stderr verbatim and use the Fallback section. Exit 2 means the file was written but failed structural checks — re-run full; if it persists, the schema contract or the vault is the problem.

Step 2: Validate & report

The generator already self-validated. Confirm structure and release the lock in one Bash block:

echo "=== frontmatter ==="; head -13 _graph.md
echo "=== sections (expect 5) ==="; grep -cE '^## ' _graph.md
echo "=== entries vs cache (three numbers must be equal) ==="
printf '### %s | status %s | log_tail %s\n' \
  "$(grep -cE '^### ' _graph.md)" "$(grep -c '\*\*status:\*\*' _graph.md)" "$(grep -c '\*\*log_tail:\*\*' _graph.md)"
# lock release — ownership-checked (substitute LOCK_TOKEN captured at Step 0.1)
EXPECTED="<LOCK_TOKEN>"
if [ -f .vault-lock ] && grep -q "token: $EXPECTED" .vault-lock; then rm -f .vault-lock && echo "LOCK RELEASED";
else echo "⚠️ lock token mismatch — not removing"; fi

Report to the user:

  • Mode + status (written / up-to-date) + reason (from generator stdout).
  • Nodes: theses + sectors + macro + research. Edges. Orphans (list).
  • Clusters: from generator stdout (note new/dissolved vs prior if recoverable).
  • Dangling links dropped: count — these are source-file link debt; a /lint pass or manual cleanup fixes the source, the graph just reflects current truth.
  • Markers cleared: from generator stdout.
  • No content files modified — graph metadata only.

Output schema contract (what the generator must emit)

Frozen interface — consumers depend on it: /sync Pass 1 triage (reads status: + log_tail: prefixes) and the graph-primer in /ingest, /compare, /thesis, /stress-test, /brief, /deepen. Any change to generate_graph.py must preserve:

  • Frontmatter: type: vault-graph, date, last_graph_write (ISO-8601 …Z), graph_mode, theses, sectors, macro, research, edges, orphans.
  • Five sections, in order: ## Thesis Adjacency Index, ## Reverse Index: Macro → Theses, ## Reverse Index: Sector → Theses, ## Cross-Thesis Clusters, ## Orphan Research Notes.
  • Adjacency entry: ### TICKER - Name then 2-space bullets sectors / macros / cross-thesis / research / status / log_tail (— for empty); log_tail sub-bullets 4-space indent, ≤3, each truncated at 100 chars + … (horizontal ellipsis — /lint #42 safe, never ...).

/lint #38 ages the graph state-markers (.sync_all_fresh / .graph_invalidations), NOT graph_mode:; /lint #43 enforces the lock contract. Validation false-positive note: unbalanced [[ ]] inside log_tail sub-bullets is EXPECTED (truncation can sever a quoted link) — only structural fields and table rows must balance.

Fallback (python3 unavailable, or generator exits 1/2)

Reproduce the schema above without ever single-Write-ing the whole file (that is the failure this skill exists to avoid — at vault scale one Write is ~21 K output tokens and aborts):

  1. Extract inventory + reverse indexes + per-thesis wikilinks/status/log_tail in bounded Bash blocks — batch theses ≤20 per block (the Bash tool truncates output ~20 KB).
  2. Categorize/validate wikilinks in memory using the same rules as the generator (prefix → sector/macro/cross-thesis/research; drop dangling, [[pinned]], legacy Macro/).
  3. Chunked emission: Write frontmatter + ## Thesis Adjacency Index + the first ≤20 entries; then cat >> _graph.md <<'GRAPHEOF' … GRAPHEOF (quoted delimiter, so [[, backticks, $, | are literal) for each remaining ≤20-entry batch and each later section. Keep every call ≤ ~6 KB.
  4. Validate (re-read: 5 sections, counts equal) and delete .sync_all_fresh + .graph_invalidations only after success.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Sweep addressed callouts older than a threshold (default 180 days) into the target note's

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

Extract a thesis's load-bearing assumptions and scan for internal contradictions — the falsifiable claims the bull case requires, what would falsify each, and where the thesis's own Risks / Bear Case / research already argue against it. Use when user says "assumptions", "what must be true", "load-bearing assumptions", or "does [TICKER] contradict itself".

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

brief

無料

Generate a concise 1-page investment brief from a thesis — the elevator pitch version. Use when user says "brief", "summarise thesis", "pitch me [TICKER]", "one-pager", or "investment memo".

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

catalyst

無料

Extract and maintain a cross-portfolio catalyst calendar from all thesis notes. Use when user says "catalyst", "calendar", "what's coming up", "upcoming events", or "what could move the portfolio".

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

clean

無料

Delete old snapshots from _Archive/Snapshots/. Accepts a day threshold (default 180). Also `daily-intel [days]` mode — prune auto-generated n8n scanning surfaces (news briefs, X dashboards) from Daily Intel/ older than 90 days. Use when user says "clean", "clean snapshots", "delete old snapshots", "clean daily intel", or when /lint flags stale snapshots.

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

clean

無料

Delete old snapshots from _Archive/Snapshots/. Accepts a day threshold (default 180). Also `daily-intel [days]` mode — prune auto-generated n8n scanning surfaces (news briefs, X dashboards) from Daily Intel/ older than 90 days. Use when user says "clean", "clean snapshots", "delete old snapshots", "clean daily intel", or when $lint flags stale snapshots.

日本語の概要は準備中です。原文の説明を表示しています。

jameswong2011/InvestmentVault32026年9月9日 更新

jameswong2011 のスキルをすべて見る

このスキルの問題を報告する