swift-kg 0.2.0__tar.gz

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.
Files changed (35) hide show
  1. swift_kg-0.2.0/LICENSE +94 -0
  2. swift_kg-0.2.0/PKG-INFO +249 -0
  3. swift_kg-0.2.0/README.md +220 -0
  4. swift_kg-0.2.0/pyproject.toml +243 -0
  5. swift_kg-0.2.0/src/swift_kg/__init__.py +42 -0
  6. swift_kg-0.2.0/src/swift_kg/__main__.py +6 -0
  7. swift_kg-0.2.0/src/swift_kg/bridge.py +136 -0
  8. swift_kg-0.2.0/src/swift_kg/centrality.py +486 -0
  9. swift_kg-0.2.0/src/swift_kg/cli/__init__.py +1 -0
  10. swift_kg-0.2.0/src/swift_kg/cli/cmd_analyze.py +101 -0
  11. swift_kg-0.2.0/src/swift_kg/cli/cmd_bridges.py +38 -0
  12. swift_kg-0.2.0/src/swift_kg/cli/cmd_build.py +259 -0
  13. swift_kg-0.2.0/src/swift_kg/cli/cmd_centrality.py +140 -0
  14. swift_kg-0.2.0/src/swift_kg/cli/cmd_explain.py +58 -0
  15. swift_kg-0.2.0/src/swift_kg/cli/cmd_framework_nodes.py +43 -0
  16. swift_kg-0.2.0/src/swift_kg/cli/cmd_hooks.py +172 -0
  17. swift_kg-0.2.0/src/swift_kg/cli/cmd_init.py +236 -0
  18. swift_kg-0.2.0/src/swift_kg/cli/cmd_mcp.py +35 -0
  19. swift_kg-0.2.0/src/swift_kg/cli/cmd_model.py +52 -0
  20. swift_kg-0.2.0/src/swift_kg/cli/cmd_query.py +75 -0
  21. swift_kg-0.2.0/src/swift_kg/cli/cmd_snapshot.py +452 -0
  22. swift_kg-0.2.0/src/swift_kg/cli/cmd_viz.py +63 -0
  23. swift_kg-0.2.0/src/swift_kg/cli/main.py +59 -0
  24. swift_kg-0.2.0/src/swift_kg/cli/options.py +38 -0
  25. swift_kg-0.2.0/src/swift_kg/coderank.py +580 -0
  26. swift_kg-0.2.0/src/swift_kg/config.py +50 -0
  27. swift_kg-0.2.0/src/swift_kg/explain.py +316 -0
  28. swift_kg-0.2.0/src/swift_kg/extractor.py +1621 -0
  29. swift_kg-0.2.0/src/swift_kg/framework_detector.py +116 -0
  30. swift_kg-0.2.0/src/swift_kg/kg.py +366 -0
  31. swift_kg-0.2.0/src/swift_kg/mcp_server.py +1637 -0
  32. swift_kg-0.2.0/src/swift_kg/resolution.py +176 -0
  33. swift_kg-0.2.0/src/swift_kg/snapshots.py +103 -0
  34. swift_kg-0.2.0/src/swift_kg/swiftkg_thorough_analysis.py +2100 -0
  35. swift_kg-0.2.0/src/swift_kg/validation.py +121 -0
swift_kg-0.2.0/LICENSE ADDED
@@ -0,0 +1,94 @@
1
+ Elastic License 2.0
2
+
3
+ URL: https://www.elastic.co/licensing/elastic-license
4
+
5
+ ## Acceptance
6
+
7
+ By using the software, you agree to all of the terms and conditions below.
8
+
9
+ ## Copyright License
10
+
11
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
12
+ non-sublicensable, non-transferable license to use, copy, distribute, make
13
+ available, and prepare derivative works of the software, in each case subject to
14
+ the limitations and conditions below.
15
+
16
+ ## Limitations
17
+
18
+ **You may not provide the software to third parties as a hosted or managed
19
+ service, where the service provides users with access to any substantial set of
20
+ the features or functionality of the software.**
21
+
22
+ You may not move, change, disable, or circumvent the license key functionality
23
+ in the software, and you may not remove or obscure any functionality in the
24
+ software that is protected by the license key.
25
+
26
+ You may not alter, remove, or obscure any licensing, copyright, or other notices
27
+ of the licensor in the software. Any use of the licensor's trademarks is subject
28
+ to applicable law.
29
+
30
+ ## Patents
31
+
32
+ The licensor grants you a license, under any patent claims the licensor can
33
+ license, or becomes able to license, to make, have made, use, sell, offer for
34
+ sale, import and have imported the software, in each case subject to the
35
+ limitations and conditions in this license. This license does not cover any
36
+ patent claims that you cause to be infringed by modifications or additions to the
37
+ software. If you or your company make any written claim that the software
38
+ infringes or contributes to infringement of any patent, your patent license for
39
+ the software granted under these terms ends immediately. If your company makes
40
+ such a claim, your patent license ends immediately for work on behalf of your
41
+ company.
42
+
43
+ ## Notices
44
+
45
+ You must ensure that anyone who gets a copy of any part of the software from you
46
+ also gets a copy of these terms or the URL for them above, as well as copies of
47
+ any plain-text lines beginning with "Required Notice:" that the licensor provided
48
+ with the software. For example:
49
+
50
+ Required Notice: Copyright (c) 2026 Eric G. Suchanek, PhD
51
+
52
+ ## No Other Rights
53
+
54
+ These terms do not imply any other licenses not expressly granted in this
55
+ license.
56
+
57
+ ## Termination
58
+
59
+ If you use the software in violation of these terms, such use is not licensed,
60
+ and your licenses will automatically terminate. If the licensor provides you with
61
+ a notice of your violation, and you cease all violation of this license no later
62
+ than 30 days after you receive that notice, your licenses will be reinstated
63
+ retroactively. However, if you violate these terms after such reinstatement, any
64
+ additional violation of these terms will cause your licenses to terminate
65
+ automatically and permanently.
66
+
67
+ ## No Liability
68
+
69
+ *As far as the law allows, the software comes as is, without any warranty or
70
+ condition, and the licensor will not be liable to you for any damages arising out
71
+ of these terms or the use or nature of the software, under any kind of legal
72
+ claim.*
73
+
74
+ ## Definitions
75
+
76
+ The **licensor** is the entity offering these terms, and the **software** is the
77
+ software the licensor makes available under these terms, including any portion of
78
+ it.
79
+
80
+ **You** refers to the individual or entity agreeing to these terms.
81
+
82
+ **Your company** is any legal entity, sole proprietorship, or other kind of
83
+ organization that you work for, plus all organizations that have control over,
84
+ are under the control of, or are under common control with that organization.
85
+ Control means ownership of substantially all the assets of an entity, or the
86
+ power to direct its management and policies by vote, contract, or otherwise.
87
+ Control can be direct or indirect.
88
+
89
+ **Your licenses** are all the licenses granted to you for the software under
90
+ these terms.
91
+
92
+ **Use** means anything you do with the software requiring one of your licenses.
93
+
94
+ **Trademark** means trademarks, service marks, and similar rights.
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: swift-kg
3
+ Version: 0.2.0
4
+ Summary: Knowledge graph for Swift codebases -- AST extraction, hybrid semantic+structural search
5
+ License-Expression: Elastic-2.0
6
+ License-File: LICENSE
7
+ Keywords: knowledge-graph,swift,ios,ast,sqlite-vec,sqlite,semantic-search
8
+ Author: Eric G. Suchanek, PhD
9
+ Author-email: suchanek@mac.com
10
+ Requires-Python: >=3.12,<3.14
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Dist: click (>=8.1.0,<9)
19
+ Requires-Dist: kgmodule-utils[semantic,sqlite-vec] (>=0.21.0)
20
+ Requires-Dist: mcp (>=1.0.0,<2)
21
+ Requires-Dist: networkx (>=3.0)
22
+ Requires-Dist: rich (>=14.3.3,<15)
23
+ Requires-Dist: tree-sitter (>=0.25.0)
24
+ Requires-Dist: tree-sitter-swift (>=0.7.0)
25
+ Project-URL: Homepage, https://github.com/Flux-Frontiers/swift_kg
26
+ Project-URL: Repository, https://github.com/Flux-Frontiers/swift_kg
27
+ Description-Content-Type: text/markdown
28
+
29
+ # SwiftKG
30
+
31
+ [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
32
+ [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
33
+ [![PyPI](https://img.shields.io/pypi/v/swift-kg.svg)](https://pypi.org/project/swift-kg/)
34
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/Flux-Frontiers/swift_kg/releases)
35
+ [![CI](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/ci.yml)
36
+ [![Docs](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/docs.yml/badge.svg)](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/docs.yml)
37
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
38
+
39
+ Knowledge graph for Swift codebases -- deterministic AST extraction, hybrid semantic + structural search.
40
+
41
+ ## Overview
42
+
43
+ SwiftKG builds a queryable knowledge graph from Swift source using:
44
+
45
+ - **tree-sitter** for deterministic, parser-level AST extraction (no LLM inference during indexing)
46
+ - **SQLite** for the structural graph (nodes, edges, provenance)
47
+ - **sqlite-vec** for the semantic vector index (embeddings via `BAAI/bge-small-en-v1.5`)
48
+ - **Hybrid retrieval**: semantic seed → graph hop expansion → lexical re-ranking
49
+
50
+ It needs no Swift toolchain, no Xcode, and no buildable project. Point it at
51
+ any checkout, on macOS or on Linux CI, and it indexes.
52
+
53
+ ## What Swift makes different
54
+
55
+ Three things about Swift are not cosmetic differences from the Python and
56
+ TypeScript modules in this fleet, and they shape the whole graph.
57
+
58
+ **Inheritance and conformance are written identically.** `: Base, Proto` gives
59
+ no syntactic signal about which is which:
60
+
61
+ ```swift
62
+ final class DiskStorage: Storage<Data> {} // superclass
63
+ struct Point: Equatable, Hashable {} // two protocols
64
+ class Storage<T>: NSObject, Repository {} // superclass, then protocol
65
+ ```
66
+
67
+ SwiftKG runs two passes. The first builds a repository-wide table of every
68
+ declared type and its kind; the second resolves each specifier against it, so
69
+ a protocol target becomes `CONFORMS` and a class or actor target becomes
70
+ `INHERITS`. When the target is external — `NSObject`, `Codable`, anything from
71
+ a dependency — it falls back to the language's own rule: only a class or actor
72
+ may have a superclass, and it must be written first.
73
+
74
+ **There are no per-file imports within a module.** Every file in a target sees
75
+ every other file's declarations without an import statement. That makes the
76
+ repository the correct resolution scope rather than an approximation of one,
77
+ so calls and type references resolve across files. A name declared twice
78
+ resolves to nothing rather than to an arbitrary one of the two — an honest
79
+ `sym:` stub beats a confidently wrong edge.
80
+
81
+ **Extensions are a unit of authorship.** A type's conformances and much of its
82
+ behaviour routinely live in an extension in a different file. Each extension
83
+ gets its own node and an `EXTENDS` edge to the type, with members qualified
84
+ under the type (`Point.scaled`), so `swiftkg` can answer "where is the rest of
85
+ this type" without losing where the code actually is. Since it is idiomatic to
86
+ write one extension per conformance, an extension's own ID carries its
87
+ conformance list (`ext:…:Point+Codable`) rather than colliding on the type name.
88
+
89
+ Swift also states access level with a keyword, so `public` / `open` /
90
+ `internal` / `private` is recorded as a fact rather than guessed from a naming
91
+ convention. The public-API report, the centrality penalty for private symbols,
92
+ and `explain`'s reasoning about zero-caller declarations all read it directly.
93
+
94
+ ## Node types
95
+
96
+ | Kind | Description |
97
+ |------|-------------|
98
+ | `module` | Every indexed `.swift` file |
99
+ | `class` | Class declaration |
100
+ | `struct` | Struct declaration |
101
+ | `enum` | Enum declaration |
102
+ | `protocol` | Protocol declaration |
103
+ | `actor` | Actor declaration |
104
+ | `extension` | Extension declaration |
105
+ | `function` | Free function at file scope |
106
+ | `method` | Function, initializer, deinitializer or subscript inside a type |
107
+ | `property` | Stored or computed property, enum case, or file-scope `let`/`var` |
108
+ | `typealias` | Type alias, and `associatedtype` inside a protocol |
109
+ | `symbol` | Unresolved import or call stub |
110
+
111
+ ## Edge types
112
+
113
+ | Relation | Description |
114
+ |----------|-------------|
115
+ | `CONTAINS` | module → type/function, type → member |
116
+ | `IMPORTS` | module → `sym:<Module>` (a Swift import names a module, not a file) |
117
+ | `CALLS` | function/method → function, method, or type initializer |
118
+ | `INHERITS` | class or actor → superclass |
119
+ | `CONFORMS` | type or extension → protocol |
120
+ | `EXTENDS` | extension → the type it extends |
121
+
122
+ ## Quick start
123
+
124
+ ```bash
125
+ pip install swift-kg
126
+
127
+ # First-time setup (downloads model, builds graph, installs hooks, snapshots)
128
+ swiftkg init --repo /path/to/swift-repo
129
+
130
+ # Build the KG for a Swift repo
131
+ swiftkg build --repo /path/to/swift-repo
132
+
133
+ # Query
134
+ swiftkg query "networking layer"
135
+ swiftkg pack "request error handling" --hop 2
136
+
137
+ # Understand the repository
138
+ swiftkg analyze /path/to/swift-repo
139
+ swiftkg centrality --top 20
140
+ swiftkg explain "proto:Sources/Networking/Client.swift:HTTPClienting"
141
+ ```
142
+
143
+ `build` wipes and rebuilds; `update` upserts without wiping. The split is
144
+ deliberate — a rebuild is correct after renames or deletions, where an upsert
145
+ leaves phantom nodes behind, so the safe operation is the bare verb and the
146
+ surprising one has to be asked for by name.
147
+
148
+ ## MCP tools
149
+
150
+ `swiftkg mcp --repo /path/to/swift-repo` exposes 21 tools. Two exist only in
151
+ this module:
152
+
153
+ | Tool | Purpose |
154
+ |------|---------|
155
+ | `type_hierarchy(node_id)` | Conformers, subclasses, extensions and declared supertypes of one type, together — for a Swift type these are one question |
156
+ | `public_api(module_path, limit)` | The declared `public` / `open` surface, read from access levels |
157
+
158
+ The rest match the fleet: `graph_stats`, `query_codebase`, `pack_snippets`,
159
+ `callers`, `get_node`, `list_nodes`, `find_node`, `centrality`,
160
+ `bridge_centrality`, `framework_nodes`, `find_definition_at`, `analyze_repo`,
161
+ `explain`, `rank_nodes`, `query_ranked`, `explain_rank`, `snapshot_list`,
162
+ `snapshot_show`, `snapshot_diff`.
163
+
164
+ See [`docs/MCP.md`](docs/MCP.md) for client configuration.
165
+
166
+ ## Snapshots & git hook
167
+
168
+ `swiftkg snapshot save` records graph metrics under `.swiftkg/snapshots/`, and
169
+ `swiftkg install-hooks` installs a pre-commit hook that keeps them current.
170
+ Alongside the shared metrics, SwiftKG records what actually characterises a
171
+ Swift codebase: counts by type kind, conformance and inheritance counts, and
172
+ extensions-per-type — how much behaviour is declared away from the type it
173
+ belongs to.
174
+
175
+ Snapshots, not per-node timestamps, are how a code KG answers temporal
176
+ questions. Git already owns when the code changed.
177
+
178
+ ## Python API
179
+
180
+ ```python
181
+ from swift_kg import SwiftKG
182
+
183
+ with SwiftKG(repo_root="/path/to/swift-repo") as kg:
184
+ kg.build(wipe=True)
185
+
186
+ result = kg.query("networking layer", k=8)
187
+ pack = kg.pack("request error handling")
188
+ pack.save("context.md")
189
+
190
+ protocol_id = "proto:Sources/Networking/Client.swift:HTTPClienting"
191
+ kg.conformers(protocol_id) # every conforming type and extension
192
+ kg.subclasses(class_id) # direct subclasses
193
+ kg.extensions_of(type_id) # extensions, wherever they are declared
194
+ ```
195
+
196
+ ## Configuration
197
+
198
+ When the target repository has a `pyproject.toml`, SwiftKG reads
199
+ `[tool.swiftkg]`:
200
+
201
+ ```toml
202
+ [tool.swiftkg]
203
+ include = ["Sources"] # top-level dirs to index (unset = all)
204
+ exclude = ["Vendor"] # extra dirs to skip at every depth
205
+ ```
206
+
207
+ Most Swift repositories have no `pyproject.toml`, which is fine: with no
208
+ config, everything is indexed. `.build`, `.swiftpm`, `DerivedData`, `Pods`,
209
+ `Carthage`, `xcuserdata` and `*.xcodeproj` / `*.xcworkspace` bundles are always
210
+ skipped.
211
+
212
+ ## Architecture
213
+
214
+ ```
215
+ Swift source ─► tree-sitter ─► pass 1: symbol table
216
+ └► pass 2: NodeSpec / EdgeSpec
217
+
218
+ ├─► SQLite (authoritative graph)
219
+ └─► sqlite-vec (semantic index)
220
+
221
+ hybrid query ◄────┘
222
+
223
+ CLI · MCP server · Python API
224
+ ```
225
+
226
+ Everything below the extractor — persistence, indexing, hybrid retrieval,
227
+ snippet packing, snapshots — comes from
228
+ [`kgmodule-utils`](https://pypi.org/project/kgmodule-utils/). This package
229
+ implements the Swift-specific layer and nothing else.
230
+
231
+ ## Status
232
+
233
+ The visualizers (`swiftkg viz`, `viz3d`, `viz-timeline`) are registered and
234
+ report that they are not yet available; see the CHANGELOG's Unreleased
235
+ section. Everything else is complete.
236
+
237
+ ## Author
238
+
239
+ Eric G. Suchanek, PhD — [Flux-Frontiers](https://github.com/Flux-Frontiers)
240
+
241
+ ## Citation
242
+
243
+ See [`CITATION.cff`](CITATION.cff).
244
+
245
+ ## License
246
+
247
+ [Elastic License 2.0](https://www.elastic.co/licensing/elastic-license). See
248
+ [`LICENSE`](LICENSE).
249
+
@@ -0,0 +1,220 @@
1
+ # SwiftKG
2
+
3
+ [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
4
+ [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
5
+ [![PyPI](https://img.shields.io/pypi/v/swift-kg.svg)](https://pypi.org/project/swift-kg/)
6
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/Flux-Frontiers/swift_kg/releases)
7
+ [![CI](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/ci.yml)
8
+ [![Docs](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/docs.yml/badge.svg)](https://github.com/Flux-Frontiers/swift_kg/actions/workflows/docs.yml)
9
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
10
+
11
+ Knowledge graph for Swift codebases -- deterministic AST extraction, hybrid semantic + structural search.
12
+
13
+ ## Overview
14
+
15
+ SwiftKG builds a queryable knowledge graph from Swift source using:
16
+
17
+ - **tree-sitter** for deterministic, parser-level AST extraction (no LLM inference during indexing)
18
+ - **SQLite** for the structural graph (nodes, edges, provenance)
19
+ - **sqlite-vec** for the semantic vector index (embeddings via `BAAI/bge-small-en-v1.5`)
20
+ - **Hybrid retrieval**: semantic seed → graph hop expansion → lexical re-ranking
21
+
22
+ It needs no Swift toolchain, no Xcode, and no buildable project. Point it at
23
+ any checkout, on macOS or on Linux CI, and it indexes.
24
+
25
+ ## What Swift makes different
26
+
27
+ Three things about Swift are not cosmetic differences from the Python and
28
+ TypeScript modules in this fleet, and they shape the whole graph.
29
+
30
+ **Inheritance and conformance are written identically.** `: Base, Proto` gives
31
+ no syntactic signal about which is which:
32
+
33
+ ```swift
34
+ final class DiskStorage: Storage<Data> {} // superclass
35
+ struct Point: Equatable, Hashable {} // two protocols
36
+ class Storage<T>: NSObject, Repository {} // superclass, then protocol
37
+ ```
38
+
39
+ SwiftKG runs two passes. The first builds a repository-wide table of every
40
+ declared type and its kind; the second resolves each specifier against it, so
41
+ a protocol target becomes `CONFORMS` and a class or actor target becomes
42
+ `INHERITS`. When the target is external — `NSObject`, `Codable`, anything from
43
+ a dependency — it falls back to the language's own rule: only a class or actor
44
+ may have a superclass, and it must be written first.
45
+
46
+ **There are no per-file imports within a module.** Every file in a target sees
47
+ every other file's declarations without an import statement. That makes the
48
+ repository the correct resolution scope rather than an approximation of one,
49
+ so calls and type references resolve across files. A name declared twice
50
+ resolves to nothing rather than to an arbitrary one of the two — an honest
51
+ `sym:` stub beats a confidently wrong edge.
52
+
53
+ **Extensions are a unit of authorship.** A type's conformances and much of its
54
+ behaviour routinely live in an extension in a different file. Each extension
55
+ gets its own node and an `EXTENDS` edge to the type, with members qualified
56
+ under the type (`Point.scaled`), so `swiftkg` can answer "where is the rest of
57
+ this type" without losing where the code actually is. Since it is idiomatic to
58
+ write one extension per conformance, an extension's own ID carries its
59
+ conformance list (`ext:…:Point+Codable`) rather than colliding on the type name.
60
+
61
+ Swift also states access level with a keyword, so `public` / `open` /
62
+ `internal` / `private` is recorded as a fact rather than guessed from a naming
63
+ convention. The public-API report, the centrality penalty for private symbols,
64
+ and `explain`'s reasoning about zero-caller declarations all read it directly.
65
+
66
+ ## Node types
67
+
68
+ | Kind | Description |
69
+ |------|-------------|
70
+ | `module` | Every indexed `.swift` file |
71
+ | `class` | Class declaration |
72
+ | `struct` | Struct declaration |
73
+ | `enum` | Enum declaration |
74
+ | `protocol` | Protocol declaration |
75
+ | `actor` | Actor declaration |
76
+ | `extension` | Extension declaration |
77
+ | `function` | Free function at file scope |
78
+ | `method` | Function, initializer, deinitializer or subscript inside a type |
79
+ | `property` | Stored or computed property, enum case, or file-scope `let`/`var` |
80
+ | `typealias` | Type alias, and `associatedtype` inside a protocol |
81
+ | `symbol` | Unresolved import or call stub |
82
+
83
+ ## Edge types
84
+
85
+ | Relation | Description |
86
+ |----------|-------------|
87
+ | `CONTAINS` | module → type/function, type → member |
88
+ | `IMPORTS` | module → `sym:<Module>` (a Swift import names a module, not a file) |
89
+ | `CALLS` | function/method → function, method, or type initializer |
90
+ | `INHERITS` | class or actor → superclass |
91
+ | `CONFORMS` | type or extension → protocol |
92
+ | `EXTENDS` | extension → the type it extends |
93
+
94
+ ## Quick start
95
+
96
+ ```bash
97
+ pip install swift-kg
98
+
99
+ # First-time setup (downloads model, builds graph, installs hooks, snapshots)
100
+ swiftkg init --repo /path/to/swift-repo
101
+
102
+ # Build the KG for a Swift repo
103
+ swiftkg build --repo /path/to/swift-repo
104
+
105
+ # Query
106
+ swiftkg query "networking layer"
107
+ swiftkg pack "request error handling" --hop 2
108
+
109
+ # Understand the repository
110
+ swiftkg analyze /path/to/swift-repo
111
+ swiftkg centrality --top 20
112
+ swiftkg explain "proto:Sources/Networking/Client.swift:HTTPClienting"
113
+ ```
114
+
115
+ `build` wipes and rebuilds; `update` upserts without wiping. The split is
116
+ deliberate — a rebuild is correct after renames or deletions, where an upsert
117
+ leaves phantom nodes behind, so the safe operation is the bare verb and the
118
+ surprising one has to be asked for by name.
119
+
120
+ ## MCP tools
121
+
122
+ `swiftkg mcp --repo /path/to/swift-repo` exposes 21 tools. Two exist only in
123
+ this module:
124
+
125
+ | Tool | Purpose |
126
+ |------|---------|
127
+ | `type_hierarchy(node_id)` | Conformers, subclasses, extensions and declared supertypes of one type, together — for a Swift type these are one question |
128
+ | `public_api(module_path, limit)` | The declared `public` / `open` surface, read from access levels |
129
+
130
+ The rest match the fleet: `graph_stats`, `query_codebase`, `pack_snippets`,
131
+ `callers`, `get_node`, `list_nodes`, `find_node`, `centrality`,
132
+ `bridge_centrality`, `framework_nodes`, `find_definition_at`, `analyze_repo`,
133
+ `explain`, `rank_nodes`, `query_ranked`, `explain_rank`, `snapshot_list`,
134
+ `snapshot_show`, `snapshot_diff`.
135
+
136
+ See [`docs/MCP.md`](docs/MCP.md) for client configuration.
137
+
138
+ ## Snapshots & git hook
139
+
140
+ `swiftkg snapshot save` records graph metrics under `.swiftkg/snapshots/`, and
141
+ `swiftkg install-hooks` installs a pre-commit hook that keeps them current.
142
+ Alongside the shared metrics, SwiftKG records what actually characterises a
143
+ Swift codebase: counts by type kind, conformance and inheritance counts, and
144
+ extensions-per-type — how much behaviour is declared away from the type it
145
+ belongs to.
146
+
147
+ Snapshots, not per-node timestamps, are how a code KG answers temporal
148
+ questions. Git already owns when the code changed.
149
+
150
+ ## Python API
151
+
152
+ ```python
153
+ from swift_kg import SwiftKG
154
+
155
+ with SwiftKG(repo_root="/path/to/swift-repo") as kg:
156
+ kg.build(wipe=True)
157
+
158
+ result = kg.query("networking layer", k=8)
159
+ pack = kg.pack("request error handling")
160
+ pack.save("context.md")
161
+
162
+ protocol_id = "proto:Sources/Networking/Client.swift:HTTPClienting"
163
+ kg.conformers(protocol_id) # every conforming type and extension
164
+ kg.subclasses(class_id) # direct subclasses
165
+ kg.extensions_of(type_id) # extensions, wherever they are declared
166
+ ```
167
+
168
+ ## Configuration
169
+
170
+ When the target repository has a `pyproject.toml`, SwiftKG reads
171
+ `[tool.swiftkg]`:
172
+
173
+ ```toml
174
+ [tool.swiftkg]
175
+ include = ["Sources"] # top-level dirs to index (unset = all)
176
+ exclude = ["Vendor"] # extra dirs to skip at every depth
177
+ ```
178
+
179
+ Most Swift repositories have no `pyproject.toml`, which is fine: with no
180
+ config, everything is indexed. `.build`, `.swiftpm`, `DerivedData`, `Pods`,
181
+ `Carthage`, `xcuserdata` and `*.xcodeproj` / `*.xcworkspace` bundles are always
182
+ skipped.
183
+
184
+ ## Architecture
185
+
186
+ ```
187
+ Swift source ─► tree-sitter ─► pass 1: symbol table
188
+ └► pass 2: NodeSpec / EdgeSpec
189
+
190
+ ├─► SQLite (authoritative graph)
191
+ └─► sqlite-vec (semantic index)
192
+
193
+ hybrid query ◄────┘
194
+
195
+ CLI · MCP server · Python API
196
+ ```
197
+
198
+ Everything below the extractor — persistence, indexing, hybrid retrieval,
199
+ snippet packing, snapshots — comes from
200
+ [`kgmodule-utils`](https://pypi.org/project/kgmodule-utils/). This package
201
+ implements the Swift-specific layer and nothing else.
202
+
203
+ ## Status
204
+
205
+ The visualizers (`swiftkg viz`, `viz3d`, `viz-timeline`) are registered and
206
+ report that they are not yet available; see the CHANGELOG's Unreleased
207
+ section. Everything else is complete.
208
+
209
+ ## Author
210
+
211
+ Eric G. Suchanek, PhD — [Flux-Frontiers](https://github.com/Flux-Frontiers)
212
+
213
+ ## Citation
214
+
215
+ See [`CITATION.cff`](CITATION.cff).
216
+
217
+ ## License
218
+
219
+ [Elastic License 2.0](https://www.elastic.co/licensing/elastic-license). See
220
+ [`LICENSE`](LICENSE).