koshas 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kosha/SKILL.md ADDED
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: kosha
3
+ description: >
4
+ Surface repo code and installed package snippets before writing new code.
5
+ Run at the start of any task that touches existing patterns or packages.
6
+ ---
7
+
8
+ # kosha — repo + package memory for coding agents
9
+
10
+ FTS5 + vector search + call graph over your repo and installed packages. Results include
11
+ callers, callees, and PageRank. No LLMs required.
12
+
13
+ ## Setup
14
+
15
+ **One-time per project:**
16
+ ```python
17
+ from kosha import Kosha
18
+ Kosha(install_skill=True) # writes .agents/skills/kosha/SKILL.md
19
+ ```
20
+
21
+ **Once per session** (incremental — fast on repeat):
22
+ ```python
23
+ k = Kosha()
24
+ k.sync(pkgs=['fasthtml', 'fastcore']) # repo code + packages + call graph
25
+ ```
26
+
27
+ ## Orchestration patterns
28
+
29
+ ### Pattern 1 — Quick lookup
30
+ *Simple "how does X work?" questions about existing code or packages.*
31
+
32
+ ```python
33
+ results = k.context('how do I embed a query', limit=10)
34
+ for r in results:
35
+ print(r['metadata']['mod_name'], r['content'][:120])
36
+ ```
37
+
38
+ ### Pattern 2 — Before writing code
39
+ *Any task that adds or modifies behaviour. Run before touching files.*
40
+
41
+ ```python
42
+ # 1. Get relevant snippets enriched with call graph
43
+ results = k.context('your task description', limit=15, graph=True)
44
+
45
+ # 2. Read structural position of each result
46
+ for r in results:
47
+ print(r['metadata']['mod_name'],
48
+ '| pagerank:', r['pagerank'],
49
+ '| callers:', r['callers'],
50
+ '| callees:', r['callees'])
51
+
52
+ # 3. Write code that fits the existing patterns
53
+ ```
54
+
55
+ ### Pattern 3 — Full structural plan
56
+ *Complex tasks, unfamiliar codebases, anything touching multiple modules.*
57
+
58
+ ```python
59
+ from itertools import combinations
60
+
61
+ # Step 1: identify relevant packages + dependency tree
62
+ tc = k.task_context('your task description', depth=2)
63
+ # tc['packages'] — ranked packages relevant to the query
64
+ # tc['dep_layers'] — BFS dep layers ordered by coupling strength
65
+
66
+ # Step 2: find key functions, enriched with graph data
67
+ results = k.context('your task description', limit=20, graph=True)
68
+
69
+ # Step 3: map call chains between the top results
70
+ nodes = [r['metadata']['mod_name'] for r in results[:8]]
71
+ paths = [p for a, b in combinations(nodes, 2) if (p := k.short_path(a, b))]
72
+ paths.sort(key=len) # shortest = tightest coupling
73
+
74
+ # Step 4: drill into join points
75
+ for node in nodes[:5]:
76
+ info = k.ni(node)
77
+ # info['callers'] — who calls this → where to hook in upstream
78
+ # info['callees'] — what it calls → what you can reuse downstream
79
+ # info['co_dispatched'] — registered peers → pattern to follow for new routes/handlers
80
+
81
+ # Step 5: write a plan grounded in mod_name + lineno
82
+ for r in results[:5]:
83
+ m = r['metadata']
84
+ print(f"{m['mod_name']} line {m.get('lineno', '?')} pagerank={r.get('pagerank', 0):.5f}")
85
+ ```
86
+
87
+ > **`co_dispatched`** — functions assigned together in the same list/dict at module level (route
88
+ > groups, plugin registrations, handler tables). Tells you where to add a new handler without
89
+ > reading all the glue code.
90
+
91
+ ## What a graph-enriched result looks like
92
+
93
+ ```python
94
+ {
95
+ 'content': 'def merge(*ds):\n "Merge all dicts"\n return {k:v for d in ds ...}',
96
+ 'metadata': {
97
+ 'mod_name': 'fastcore.basics.merge', # fully-qualified — use for ni() / short_path()
98
+ 'path': '/path/to/fastcore/basics.py',
99
+ 'lineno': 655,
100
+ 'type': 'FunctionDef',
101
+ 'package': 'fastcore', # env results only
102
+ },
103
+ # structural position
104
+ 'pagerank': 0.00027, # centrality — higher = more load-bearing
105
+ 'in_degree': 8, # number of callers
106
+ 'out_degree': 12, # number of callees
107
+ 'callers': ['fastcore.script.call_parse._f', ...],
108
+ 'callees': ['fastcore.basics.NS.__iter__', ...],
109
+ 'co_dispatched': [],
110
+ }
111
+ ```
112
+
113
+ ## Filter syntax
114
+
115
+ | Token | Example | Effect |
116
+ |-------|---------|--------|
117
+ | `package:name` | `package:fasthtml` | Restrict env search to one package |
118
+ | `file:glob` | `file:routes*` | Restrict repo results by filename |
119
+ | `path:pattern` | `path:api/*` | Restrict repo results by path |
120
+ | `lang:ext` | `lang:py` | Filter by language |
121
+ | `type:node` | `type:FunctionDef` | Filter by AST node type |
122
+
123
+ Plural and comma-separated values work: `packages:fastcore,litesearch paths:basics,core`
124
+
125
+ ## Graph API
126
+
127
+ | Call | Returns |
128
+ |------|---------|
129
+ | `k.ni(node)` | Full node info: meta + callers + callees + co_dispatched |
130
+ | `k.short_path(a, b)` | Shortest call chain between two nodes |
131
+ | `k.neighbors(node, depth=2)` | All nodes within N hops |
132
+ | `k.graph.ranked(k=10, module='pkg')` | Top-k nodes by PageRank |
133
+ | `k.gn(where='node like "%X%"')` | Direct graph_nodes table query |
134
+ | `k.ge(where='caller like "%X%"')` | Direct graph_edges table query |
135
+
136
+ ## Full API
137
+
138
+ | Method | Purpose |
139
+ |--------|---------|
140
+ | `k.sync(pkgs, dir)` | One-shot sync: repo + packages + graph |
141
+ | `k.context(q, limit, graph)` | Fan-out search, graph-enriched |
142
+ | `k.repo_context(q, limit)` | Repo only |
143
+ | `k.env_context(q, limit)` | Packages only |
144
+ | `k.task_context(q, depth)` | Packages + dep stack |
145
+ | `k.watch_repo()` | Live incremental re-index on file changes |
146
+ | `k.nuke()` | Drop all databases |
147
+
148
+ ## Database locations
149
+
150
+ - `.kosha/code.db` — repo code chunks + embeddings (project-local)
151
+ - `.kosha/graph.db` — call graph (project-local)
152
+ - `$XDG_DATA_HOME/kosha/env.db` — installed packages (global, shared across repos)
153
+
154
+ ## Harness installation
155
+
156
+ **Project-local** (auto-discovered by most harnesses, commit alongside code):
157
+ ```python
158
+ Kosha(install_skill=True) # → .agents/skills/kosha/SKILL.md
159
+ ```
160
+
161
+ **Claude Code — global** (available in all projects):
162
+ ```bash
163
+ mkdir -p ~/.claude/skills/kosha
164
+ cp .agents/skills/kosha/SKILL.md ~/.claude/skills/kosha/SKILL.md
165
+ ```
166
+
167
+ **Other harnesses**: place SKILL.md wherever the harness discovers agent skills
168
+ (`.agents/skills/`, `.continue/skills/`, or configure path in harness settings).
kosha/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ __version__ = "0.0.2"
2
+ from .core import *
3
+ from .graph import *
kosha/_modidx.py ADDED
@@ -0,0 +1,96 @@
1
+ # Autogenerated by nbdev
2
+
3
+ d = { 'settings': { 'branch': 'main',
4
+ 'doc_baseurl': '/kosha',
5
+ 'doc_host': 'https://vedicreader.github.io',
6
+ 'git_url': 'https://github.com/vedicreader/kosha',
7
+ 'lib_path': 'kosha'},
8
+ 'syms': { 'kosha.core': { 'kosha.core.Kosha': ('core.html#kosha', 'kosha/core.py'),
9
+ 'kosha.core.Kosha.__init__': ('core.html#kosha.__init__', 'kosha/core.py'),
10
+ 'kosha.core.Kosha._is_pkg_ingested': ('core.html#kosha._is_pkg_ingested', 'kosha/core.py'),
11
+ 'kosha.core.Kosha.awatch_repo': ('core.html#kosha.awatch_repo', 'kosha/core.py'),
12
+ 'kosha.core.Kosha.env_context': ('core.html#kosha.env_context', 'kosha/core.py'),
13
+ 'kosha.core.Kosha.nuke': ('core.html#kosha.nuke', 'kosha/core.py'),
14
+ 'kosha.core.Kosha.pkg_context': ('core.html#kosha.pkg_context', 'kosha/core.py'),
15
+ 'kosha.core.Kosha.pkgs2consider': ('core.html#kosha.pkgs2consider', 'kosha/core.py'),
16
+ 'kosha.core.Kosha.pkgs_in_env': ('core.html#kosha.pkgs_in_env', 'kosha/core.py'),
17
+ 'kosha.core.Kosha.process_env': ('core.html#kosha.process_env', 'kosha/core.py'),
18
+ 'kosha.core.Kosha.process_repo': ('core.html#kosha.process_repo', 'kosha/core.py'),
19
+ 'kosha.core.Kosha.prune_old_pkgs': ('core.html#kosha.prune_old_pkgs', 'kosha/core.py'),
20
+ 'kosha.core.Kosha.prune_old_versions': ('core.html#kosha.prune_old_versions', 'kosha/core.py'),
21
+ 'kosha.core.Kosha.repo_context': ('core.html#kosha.repo_context', 'kosha/core.py'),
22
+ 'kosha.core.Kosha.rm_pkg': ('core.html#kosha.rm_pkg', 'kosha/core.py'),
23
+ 'kosha.core.Kosha.update_pkg': ('core.html#kosha.update_pkg', 'kosha/core.py'),
24
+ 'kosha.core.Kosha.update_pkgs': ('core.html#kosha.update_pkgs', 'kosha/core.py'),
25
+ 'kosha.core.Kosha.update_repo': ('core.html#kosha.update_repo', 'kosha/core.py'),
26
+ 'kosha.core.Kosha.watch_repo': ('core.html#kosha.watch_repo', 'kosha/core.py'),
27
+ 'kosha.core._content': ('core.html#_content', 'kosha/core.py'),
28
+ 'kosha.core._glob_to_like': ('core.html#_glob_to_like', 'kosha/core.py'),
29
+ 'kosha.core._slug': ('core.html#_slug', 'kosha/core.py'),
30
+ 'kosha.core.arun': ('core.html#arun', 'kosha/core.py'),
31
+ 'kosha.core.count_imp': ('core.html#count_imp', 'kosha/core.py'),
32
+ 'kosha.core.embed_chunk': ('core.html#embed_chunk', 'kosha/core.py'),
33
+ 'kosha.core.embedder': ('core.html#embedder', 'kosha/core.py'),
34
+ 'kosha.core.env_pkg_versions': ('core.html#env_pkg_versions', 'kosha/core.py'),
35
+ 'kosha.core.filt2wh': ('core.html#filt2wh', 'kosha/core.py'),
36
+ 'kosha.core.has_init': ('core.html#has_init', 'kosha/core.py'),
37
+ 'kosha.core.mv_skill_md': ('core.html#mv_skill_md', 'kosha/core.py'),
38
+ 'kosha.core.parse': ('core.html#parse', 'kosha/core.py'),
39
+ 'kosha.core.parseq': ('core.html#parseq', 'kosha/core.py'),
40
+ 'kosha.core.pkg_doc': ('core.html#pkg_doc', 'kosha/core.py'),
41
+ 'kosha.core.pkg_trans_deps': ('core.html#pkg_trans_deps', 'kosha/core.py'),
42
+ 'kosha.core.process_content': ('core.html#process_content', 'kosha/core.py'),
43
+ 'kosha.core.repo_root': ('core.html#repo_root', 'kosha/core.py'),
44
+ 'kosha.core.static_embedder': ('core.html#static_embedder', 'kosha/core.py')},
45
+ 'kosha.graph': { 'kosha.graph.CodeGraph': ('graph.html#codegraph', 'kosha/graph.py'),
46
+ 'kosha.graph.CodeGraph.__init__': ('graph.html#codegraph.__init__', 'kosha/graph.py'),
47
+ 'kosha.graph.CodeGraph._add_dyn': ('graph.html#codegraph._add_dyn', 'kosha/graph.py'),
48
+ 'kosha.graph.CodeGraph._add_static': ('graph.html#codegraph._add_static', 'kosha/graph.py'),
49
+ 'kosha.graph.CodeGraph._centrality': ('graph.html#codegraph._centrality', 'kosha/graph.py'),
50
+ 'kosha.graph.CodeGraph._drop_file': ('graph.html#codegraph._drop_file', 'kosha/graph.py'),
51
+ 'kosha.graph.CodeGraph._index_files': ('graph.html#codegraph._index_files', 'kosha/graph.py'),
52
+ 'kosha.graph.CodeGraph._stale': ('graph.html#codegraph._stale', 'kosha/graph.py'),
53
+ 'kosha.graph.CodeGraph.callees': ('graph.html#codegraph.callees', 'kosha/graph.py'),
54
+ 'kosha.graph.CodeGraph.callers': ('graph.html#codegraph.callers', 'kosha/graph.py'),
55
+ 'kosha.graph.CodeGraph.co_dispatched': ('graph.html#codegraph.co_dispatched', 'kosha/graph.py'),
56
+ 'kosha.graph.CodeGraph.edge_kinds': ('graph.html#codegraph.edge_kinds', 'kosha/graph.py'),
57
+ 'kosha.graph.CodeGraph.file2nodes': ('graph.html#codegraph.file2nodes', 'kosha/graph.py'),
58
+ 'kosha.graph.CodeGraph.from_dir': ('graph.html#codegraph.from_dir', 'kosha/graph.py'),
59
+ 'kosha.graph.CodeGraph.from_file': ('graph.html#codegraph.from_file', 'kosha/graph.py'),
60
+ 'kosha.graph.CodeGraph.from_pkg': ('graph.html#codegraph.from_pkg', 'kosha/graph.py'),
61
+ 'kosha.graph.CodeGraph.from_sources': ('graph.html#codegraph.from_sources', 'kosha/graph.py'),
62
+ 'kosha.graph.CodeGraph.neighbors': ('graph.html#codegraph.neighbors', 'kosha/graph.py'),
63
+ 'kosha.graph.CodeGraph.node_info': ('graph.html#codegraph.node_info', 'kosha/graph.py'),
64
+ 'kosha.graph.CodeGraph.process_files': ('graph.html#codegraph.process_files', 'kosha/graph.py'),
65
+ 'kosha.graph.CodeGraph.ranked': ('graph.html#codegraph.ranked', 'kosha/graph.py'),
66
+ 'kosha.graph.CodeGraph.short_path': ('graph.html#codegraph.short_path', 'kosha/graph.py'),
67
+ 'kosha.graph.CodeGraph.short_paths': ('graph.html#codegraph.short_paths', 'kosha/graph.py'),
68
+ 'kosha.graph.CodeGraph.sync': ('graph.html#codegraph.sync', 'kosha/graph.py'),
69
+ 'kosha.graph.CodeGraph.sync_dir': ('graph.html#codegraph.sync_dir', 'kosha/graph.py'),
70
+ 'kosha.graph.CodeGraph.sync_pkgs': ('graph.html#codegraph.sync_pkgs', 'kosha/graph.py'),
71
+ 'kosha.graph.Kosha.context': ('graph.html#kosha.context', 'kosha/graph.py'),
72
+ 'kosha.graph.Kosha.dep_stack': ('graph.html#kosha.dep_stack', 'kosha/graph.py'),
73
+ 'kosha.graph.Kosha.ge': ('graph.html#kosha.ge', 'kosha/graph.py'),
74
+ 'kosha.graph.Kosha.gn': ('graph.html#kosha.gn', 'kosha/graph.py'),
75
+ 'kosha.graph.Kosha.graph': ('graph.html#kosha.graph', 'kosha/graph.py'),
76
+ 'kosha.graph.Kosha.graphdb': ('graph.html#kosha.graphdb', 'kosha/graph.py'),
77
+ 'kosha.graph.Kosha.neighbors': ('graph.html#kosha.neighbors', 'kosha/graph.py'),
78
+ 'kosha.graph.Kosha.ni': ('graph.html#kosha.ni', 'kosha/graph.py'),
79
+ 'kosha.graph.Kosha.short_path': ('graph.html#kosha.short_path', 'kosha/graph.py'),
80
+ 'kosha.graph.Kosha.short_paths': ('graph.html#kosha.short_paths', 'kosha/graph.py'),
81
+ 'kosha.graph.Kosha.sync': ('graph.html#kosha.sync', 'kosha/graph.py'),
82
+ 'kosha.graph.Kosha.task_context': ('graph.html#kosha.task_context', 'kosha/graph.py'),
83
+ 'kosha.graph._co_edges': ('graph.html#_co_edges', 'kosha/graph.py'),
84
+ 'kosha.graph._conf': ('graph.html#_conf', 'kosha/graph.py'),
85
+ 'kosha.graph._conn_edges': ('graph.html#_conn_edges', 'kosha/graph.py'),
86
+ 'kosha.graph._dec_edges': ('graph.html#_dec_edges', 'kosha/graph.py'),
87
+ 'kosha.graph._delegates_edges': ('graph.html#_delegates_edges', 'kosha/graph.py'),
88
+ 'kosha.graph._e': ('graph.html#_e', 'kosha/graph.py'),
89
+ 'kosha.graph._lambda_nodes': ('graph.html#_lambda_nodes', 'kosha/graph.py'),
90
+ 'kosha.graph._nodes': ('graph.html#_nodes', 'kosha/graph.py'),
91
+ 'kosha.graph._pagerank': ('graph.html#_pagerank', 'kosha/graph.py'),
92
+ 'kosha.graph._patch_edges': ('graph.html#_patch_edges', 'kosha/graph.py'),
93
+ 'kosha.graph._reg_edges': ('graph.html#_reg_edges', 'kosha/graph.py'),
94
+ 'kosha.graph._root': ('graph.html#_root', 'kosha/graph.py'),
95
+ 'kosha.graph.dyn_edges': ('graph.html#dyn_edges', 'kosha/graph.py'),
96
+ 'kosha.graph.static_edges': ('graph.html#static_edges', 'kosha/graph.py')}}}