Token导航 LogoToken导航TokenDH.com
研究检索只读clawhub未标认证来源可访问clear审计通过

narrative-topology叙事拓扑

Agent Skill

narrative-topology 用于查找、检索和筛选相关信息,适合在 OpenClaw 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

3,648

周安装

149

GitHub Stars

1

下载量

1,168
OpenClaw

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT-0

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:narrative-topology(叙事拓扑)
来源仓库:https://github.com/turinfohlen/narrative-topology
安装命令:
openclaw skills install narrative-topology
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install narrative-topology

简介

narrative-topology 从长篇叙述中提取语义关系,生成 RDF 三元组与邻接矩阵。

  • 适用于复杂架构讨论、知识图谱构建或文本结构分析场景。
  • 通过 clawhub 安装后可辅助 Agent 进行信息组织与可视化呈现。
  • 使用时需注意输入文本长度与语义密度,避免低效提取。
  • 适用宿主包括 OpenClaw,接入前应确认版本、权限和运行环境要求。

SKILL.md

name
narrative-topology
description
>

Narrative Topology

Core Concept

Problem: Long discussions (100+ messages, architectural debates, narrative analysis) lose structure. Easy to miss critical dependencies, causality chains, or bottlenecks.

Solution: Embed RDF-style triples in markdown. Scan with Python. Extract semantic adjacency matrix. See structure.


Triple Notation

Format


<<{Subject, Predicate, Object}.

Examples

Simple relations:


<<{Claude, outputs, analysis}.
<<{analysis, informs, decision}.

Parallel subjects (cartesian product):


<<{[A, B, C], implements, feature}.

Expands to:


{A, implements, feature}
{B, implements, feature}
{C, implements, feature}

Parallel objects:


<<{payment_system, affects, [latency, cost, security]}.

Expands to:


{payment_system, affects, latency}
{payment_system, affects, cost}
{payment_system, affects, security}

Both parallel:


<<{[Claude, User], collaborated_on, [design, implementation]}.

Full cartesian product: 2×2 = 4 edges.

Syntax Rules

  • <<{ starts the triple
  • }. (period-dot) terminates
  • Commas separate subject, predicate, object
  • Whitespace trimmed automatically
  • [...] denotes list; bare tokens are singletons
  • Lines in markdown, easily greppable

Why This Format

  1. RDF-like — Semantic web standard, well-understood
  2. Grep-friendlygrep '<<{' file.md finds all triples
  3. Unambiguous — Clear start/end, no nesting
  4. Markdown-native — Doesn't break rendering
  5. Compact — One line per relation

Example: Hamlet

Input markdown (partial):

## Act I

<<{Claudius, murders, old_king}.
<<{Claudius, usurps, Denmark_throne}.
<<{Claudius, marries, Gertrude}.

## Act II

<<{ghost, reveals, Hamlet}.
<<{ghost, demands, revenge}.
<<{Hamlet, feigns, madness}.
<<{Hamlet, kills, Polonius}.

## Consequences

<<{Polonius_death, causes, Ophelia_madness}.
<<{Ophelia, drowns, river}.

## Climax

<<{[Hamlet, Laertes], duel, each_other}.
<<{[poison_sword, poison_wine], kills, [Hamlet, Laertes, Claudius, Gertrude]}.
<<{Fortinbras, takes_over, Denmark}.

Output: Adjacency matrix showing all 14 nodes and their causal/narrative dependencies.


Python Scanner

Place scanner.py in your markdown directory. Run:

python scanner.py

Code

#!/usr/bin/env python3
"""
Narrative Topology Scanner
Usage: python scanner.py
Outputs adjacency matrix compressed with x::n notation
"""

import os
import sys

def list_files_recursive(directory, extensions=('.txt', '.def', '.erl', '.ex', '.md')):
    """Yield all files with given extensions under directory."""
    for root, _, files in os.walk(directory):
        for f in files:
            if f.endswith(extensions):
                yield os.path.join(root, f)

def parse_list(s):
    """Parse a token that may be a singleton or a bracketed list."""
    s = s.strip()
    if s.startswith('[') and s.endswith(']'):
        inner = s[1:-1].strip()
        if not inner:
            return []
        return [item.strip() for item in inner.split(',')]
    return [s]

def smart_split(content):
    """
    Split content by commas while respecting nested brackets.
    Returns list of three parts: subject, predicate, object.
    """
    parts = []
    current = []
    depth = 0
    for ch in content:
        if ch == ',' and depth == 0:
            parts.append(''.join(current).strip())
            current = []
        else:
            if ch == '[':
                depth += 1
            elif ch == ']':
                depth -= 1
            current.append(ch)
    if current:
        parts.append(''.join(current).strip())
    return parts if len(parts) == 3 else None

def process_line(line):
    """Extract triples from a single line."""
    line = line.strip()
    if not line.startswith('<<{'):
        return []
    if not line.endswith('}.'):
        return []
    # Extract content between <<{ and }.
    content = line[3:-2]
    parts = smart_split(content)
    if not parts:
        return []
    s, p, o = parts  # p is ignored (predicate)
    subjects = parse_list(s)
    objects = parse_list(o)
    edges = []
    for subj in subjects:
        for obj in objects:
            edges.append((subj, obj))
    return edges

def process_file(filepath):
    """Process a single file, returning list of (source, target) edges."""
    edges = []
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            for line in f:
                edges.extend(process_line(line))
    except Exception:
        pass
    return edges

def compress_row(row):
    """Convert list of ints to x::n compressed string."""
    if not row:
        return ''
    compressed = []
    current_val = row[0]
    count = 1
    for val in row[1:]:
        if val == current_val:
            count += 1
        else:
            compressed.append(f"{current_val}::{count}")
            current_val = val
            count = 1
    compressed.append(f"{current_val}::{count}")
    return ','.join(compressed)

def main():
    cwd = os.getcwd()
    edges = []
    for filepath in list_files_recursive(cwd):
        edges.extend(process_file(filepath))

    # Gather unique nodes
    nodes = set()
    for s, o in edges:
        nodes.add(s)
        nodes.add(o)
    nodes = sorted(nodes)
    n = len(nodes)

    # Build index map
    idx = {node: i for i, node in enumerate(nodes)}

    # Build adjacency matrix (list of lists)
    matrix = [[0] * n for _ in range(n)]
    for s, o in edges:
        i, j = idx[s], idx[o]
        matrix[i][j] = 1

    # Output
    print("Nodes: " + ", ".join(nodes))
    print()
    print("Adjacency Matrix (compressed x::n):")
    print("# x::n = n copies of value x")
    for row in matrix:
        print(compress_row(row))

    print()
    print("Stats:")
    print(f"Nodes: {n}")
    print(f"Edges: {len(edges)}")
    if n > 0:
        density = len(edges) / (n * n)
        print(f"Density: {density:.4f}")

if __name__ == "__main__":
    main()

Output

The scanner outputs an adjacency matrix compressed with x::n notation (n copies of value x):

Nodes: Claudius, Denmark_throne, Fortinbras, Gertrude, Hamlet, Laertes, Ophelia, Polonius, Polonius_death, ...

Adjacency Matrix (compressed x::n):
# x::n = n copies of value x
0::14
0::3,1::1,0::10
0::4,1::2,0::8
1::14
...

Stats:
Nodes: 14
Edges: 12
Density: 0.0612

Format rule: x::n means n consecutive occurrences of value x. Example: 0::2,1::3,0::1 expands to [0,0,1,1,1,0].

For AI analysis: The matrix rows = sources (in node list order), columns = targets. 1 = edge exists.


Interpreting the Matrix

Rows = Sources, Columns = Targets

Matrix M where M[i,j] = 1 means: Node_i → Node_j

Key Analyses

· In-degree (column sum): How many things cause this node? (Count 1s in each column) · Out-degree (row sum): How many things does this node cause? (Count 1s in each row) · Strongly connected components: Cycles (feedback loops, mutual causality) · Topological sort: Order events by causal dependency · Critical path: Chain with maximum bottleneck nodes


Extending the Scanner

Add Weighted Edges

Replace binary (0/1) with strength values:

# Instead of setting to 1, count occurrences
weight_matrix = [[0] * n for _ in range(n)]
for s, o in edges:
    i, j = idx[s], idx[o]
    weight_matrix[i][j] += 1

Output matrix has counts, not just binary.

Generate Mermaid Graph

Add to scanner:

print("graph LR")
for s, o in edges:
    print(f"  {s} --> {o}")

Pipe output to a .mmd file, render in claude.ai.

Generate GraphViz DOT

print("digraph {")
for s, o in edges:
    print(f'  "{s}" -> "{o}";')
print("}")

Render with dot, convert to PNG/SVG.


Use Cases

  1. Narrative Analysis

Extract plot dependency from novel/screenplay. · Identify critical turning points (high in-degree) · Find orphaned subplots (isolated nodes) · Spot circular dependencies (tragedy, irony)

  1. Architectural Discussions

Embed triples in design doc markdown:

   <<{microservice_A, calls, microservice_B}.
   <<{microservice_B, depends_on, database}.
   <<{database, shared_by, [service_C, service_D]}.

Scan → see service coupling graph → identify decoupling opportunities.

  1. Project Workflows

Task dependencies:

   <<{design_doc, blocks, implementation}.
   <<{implementation, requires, code_review}.
   <<{code_review, unblocks, deployment}.

Scan → topological sort → critical path analysis.

  1. Technical Debt Mapping
   <<{legacy_code, causes, technical_debt}.
   <<{technical_debt, blocks, new_feature}.
   <<{new_feature, required_by, [OKR_1, OKR_2]}.

Prioritize refactor based on downstream impact.


Integration with all-dialogue-to-markdown

Optional pairing:

  1. Claude writes analysis in markdown (using all-dialogue skill)
  2. You embed triples in the markdown as you read
  3. Run scanner on the output file → see structure
  4. Use matrix to:

· Ask follow-up questions · Spot gaps · Verify causality chains

Example workflow:

User: "Analyze scheduler design. Save as scheduler-analysis.md"
Claude: [saves full analysis to scheduler-analysis.md]

User: [reads md, embeds triples]
<<{async_dispatch, reduces, latency}.
<<{latency, affects, throughput}.

User: "Run scanner on scheduler-analysis.md"
Scanner: [adjacency matrix]

User: [examines matrix] "What about error propagation?"

No requirement to use all-dialogue — works standalone on any markdown.


Workflow

Standalone Use

  1. Write markdown with embedded triples
  2. Place scanner.py in same directory
  3. Run: python scanner.py
  4. Get compressed adjacency matrix
  5. Use for analysis or feed back to AI

With all-dialogue Pairing

  1. Ask Claude to save analysis to markdown (all-dialogue skill)
  2. Read markdown, mark critical relations with triples
  3. Run scanner
  4. Iterate: use matrix to ask more precise questions

Philosophy

· Why separate from all-dialogue? All-dialogue manages token flow (thinking + response → file). Narrative-topology manages semantic extraction (relations → matrix). Independent concerns. Both can upgrade separately. Narrative-topology applies to any markdown, not just Claude output. · Why triples instead of prose summaries? Prose is lossy. Easy to miss connections. Triples are canonical, computable, greppable. Matrix enables quantitative analysis (paths, cycles, centrality). Scales: 50 triples → clear structure. 500 triples → still manageable. · Why Python? Ubiquitous, no extra dependencies. Single file, runs anywhere. Clear, readable, and easily extensible.


Summary

Narrative Topology extracts relational structure from dense text.

· Input: Markdown with <<{S, P, O}. triples · Processing: Python scanner parses + expands cartesian products · Output: Adjacency matrix compressed with x::n notation (low token cost, AI‑friendly) · Power: See causal chains, bottlenecks, cycles in long discussions · Scope: Works standalone. Pairs naturally with all-dialogue.

Use it to maintain signal in long, complex narratives.

适合场景

01

OpenClaw 用户查找和安装 Skill 时

02

用户想查找某类 Agent Skill 时

03

需要根据任务场景推荐可安装能力包时

04

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

OpenClaw

77.22%
按下载量换算902

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills