@mmerterden/multi-agent-pipeline 16.12.0 → 16.14.0

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 (49) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +4 -4
  3. package/README.tr.md +4 -4
  4. package/docs/adr/0010-own-code-graph.md +129 -0
  5. package/docs/adr/README.md +1 -0
  6. package/docs/architecture.md +2 -2
  7. package/docs/ecosystem.md +5 -5
  8. package/docs/features.md +8 -0
  9. package/package.json +1 -1
  10. package/pipeline/commands/multi-agent/graph/SKILL.md +105 -0
  11. package/pipeline/commands/multi-agent/help/SKILL.md +8 -8
  12. package/pipeline/commands/multi-agent/sync/SKILL.md +12 -12
  13. package/pipeline/commands/multi-agent/uninstall/SKILL.md +9 -7
  14. package/pipeline/multi-agent-refs/analysis/evidence.md +21 -0
  15. package/pipeline/multi-agent-refs/cross-cli-contract.md +10 -10
  16. package/pipeline/multi-agent-refs/features/code-graph.md +69 -0
  17. package/pipeline/multi-agent-refs/features/model-fallback.md +44 -2
  18. package/pipeline/multi-agent-refs/knowledge.md +6 -0
  19. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  20. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +5 -0
  21. package/pipeline/multi-agent-refs/phases/phase-4-review.md +3 -3
  22. package/pipeline/multi-agent-refs/phases/phase-7-report.md +2 -0
  23. package/pipeline/preferences-template.json +2 -0
  24. package/pipeline/schemas/code-graph.schema.json +91 -0
  25. package/pipeline/schemas/prefs.schema.json +45 -0
  26. package/pipeline/schemas/token-budget.json +2 -2
  27. package/pipeline/scripts/_code-graph.mjs +545 -0
  28. package/pipeline/scripts/_path-match.mjs +87 -0
  29. package/pipeline/scripts/code-graph-rules/android.json +130 -0
  30. package/pipeline/scripts/code-graph-rules/go.json +124 -0
  31. package/pipeline/scripts/code-graph-rules/ios.json +95 -0
  32. package/pipeline/scripts/code-graph-rules/node.json +151 -0
  33. package/pipeline/scripts/code-graph-rules/python.json +91 -0
  34. package/pipeline/scripts/graph-affected.mjs +161 -0
  35. package/pipeline/scripts/graph-build.mjs +157 -0
  36. package/pipeline/scripts/graph-query.mjs +191 -0
  37. package/pipeline/scripts/graph-report.mjs +237 -0
  38. package/pipeline/scripts/smoke-cross-cli-behavior.sh +7 -4
  39. package/pipeline/scripts/test-gap-rules/go.json +24 -0
  40. package/pipeline/scripts/test-gap-rules/ios.json +38 -10
  41. package/pipeline/scripts/test-gap-scan.mjs +2 -21
  42. package/pipeline/scripts/uninstall.mjs +11 -2
  43. package/pipeline/scripts/validate-code-graph.mjs +174 -0
  44. package/pipeline/skills/.skills-index.json +14 -3
  45. package/pipeline/skills/shared/README.md +6 -5
  46. package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +106 -0
  47. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +11 -11
  48. package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +4 -4
  49. package/pipeline/skills/skills-index.md +4 -3
@@ -0,0 +1,130 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "stack": "android",
4
+ "description": "Kotlin + Java code-graph rules. Adds what the graph needs on top of test-gap-rules/android.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants internal types too, because Phase 1 narrows scope on the whole module, not just its public surface.",
5
+ "comments": {
6
+ "line": [
7
+ "//"
8
+ ],
9
+ "block": [
10
+ [
11
+ "/*",
12
+ "*/"
13
+ ]
14
+ ],
15
+ "string": [
16
+ "\"\"\"",
17
+ "\""
18
+ ]
19
+ },
20
+ "definitionPatterns": [
21
+ {
22
+ "id": "enum",
23
+ "kind": "enum",
24
+ "regex": "\\benum\\s+(?:class\\s+)?([A-Z][A-Za-z0-9_]*)"
25
+ },
26
+ {
27
+ "id": "record",
28
+ "kind": "record",
29
+ "regex": "\\brecord\\s+([A-Z][A-Za-z0-9_]*)"
30
+ },
31
+ {
32
+ "id": "typealias",
33
+ "kind": "typealias",
34
+ "regex": "\\btypealias\\s+([A-Z][A-Za-z0-9_]*)"
35
+ },
36
+ {
37
+ "id": "object",
38
+ "kind": "object",
39
+ "regex": "\\bobject\\s+([A-Z][A-Za-z0-9_]*)"
40
+ },
41
+ {
42
+ "id": "interface",
43
+ "kind": "interface",
44
+ "regex": "\\binterface\\s+([A-Z][A-Za-z0-9_]*)"
45
+ },
46
+ {
47
+ "id": "class",
48
+ "kind": "class",
49
+ "regex": "\\bclass\\s+([A-Z][A-Za-z0-9_]*)"
50
+ },
51
+ {
52
+ "id": "fun",
53
+ "kind": "fun",
54
+ "regex": "\\bfun\\s+(?:<[^>]*>\\s*)?([a-zA-Z_][A-Za-z0-9_]*)"
55
+ }
56
+ ],
57
+ "importPatterns": [
58
+ {
59
+ "id": "import",
60
+ "regex": "^\\s*import\\s+(?:static\\s+)?(?:[A-Za-z_][A-Za-z0-9_]*\\.)+([A-Z][A-Za-z0-9_]*)"
61
+ }
62
+ ],
63
+ "referenceKinds": [
64
+ "class",
65
+ "interface",
66
+ "object",
67
+ "enum",
68
+ "record",
69
+ "typealias"
70
+ ],
71
+ "referenceKindsNote": "fun is deliberately absent, for the reason Swift's rules record for func: a bare lowercase name matched across files is almost never a call to that exact declaration, and on a large app the generic ones (invoke, build, create, get) take the top god-node slots purely because each happened to be declared once. Composables are the tempting exception - they are capitalised and behave like types - but they are declared with fun, so including them means including every other fun with them.",
72
+ "ignoredIdentifiers": [
73
+ "this",
74
+ "super",
75
+ "it",
76
+ "init",
77
+ "constructor",
78
+ "companion",
79
+ "class",
80
+ "interface",
81
+ "object",
82
+ "enum",
83
+ "record",
84
+ "fun",
85
+ "val",
86
+ "var",
87
+ "return",
88
+ "when",
89
+ "where",
90
+ "is",
91
+ "as",
92
+ "in",
93
+ "out",
94
+ "by",
95
+ "import",
96
+ "package",
97
+ "public",
98
+ "private",
99
+ "protected",
100
+ "internal",
101
+ "static",
102
+ "final",
103
+ "abstract",
104
+ "open",
105
+ "override",
106
+ "sealed",
107
+ "data",
108
+ "inline",
109
+ "suspend",
110
+ "lateinit",
111
+ "throws",
112
+ "try",
113
+ "catch",
114
+ "finally",
115
+ "null",
116
+ "true",
117
+ "false",
118
+ "void",
119
+ "int",
120
+ "long",
121
+ "boolean",
122
+ "String",
123
+ "Int",
124
+ "Long",
125
+ "Boolean",
126
+ "Unit",
127
+ "Any"
128
+ ],
129
+ "note": "Kotlin declaration modifiers are not separate patterns: `data class Foo`, `sealed class Foo` and `annotation class Foo` all still contain `class Foo`, so one pattern covers them. `enum` allows an optional `class` between keyword and name, which is the only shape that differs between Java (`enum Foo`) and Kotlin (`enum class Foo`). `object` matches the named form only - `companion object {` and the anonymous `object : Iface {` carry no name and correctly produce nothing. Imports are fully qualified on the JVM, so the pattern captures the final segment: `import com.example.ui.Button` resolves against the file named Button.kt, which is how the engine links a file-level import edge. A star import (`import com.example.ui.*`) captures nothing, deliberately - it names a package, and pointing every star import at an arbitrary file in that package would invent an edge nobody wrote. Pattern ORDER is load-bearing: `enum class Cabin` matches both the enum pattern and the class pattern, and the first match to register the name decides its kind, so the more specific patterns are listed first. With class first, every Kotlin enum was filed as a class and the report's symbol-kind census was wrong."
130
+ }
@@ -0,0 +1,124 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "stack": "go",
4
+ "description": "Go code-graph rules. Adds what the graph needs on top of test-gap-rules/go.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants unexported declarations too, because Phase 1 narrows scope on the whole package, not just its exported surface.",
5
+ "comments": {
6
+ "line": [
7
+ "//"
8
+ ],
9
+ "block": [
10
+ [
11
+ "/*",
12
+ "*/"
13
+ ]
14
+ ],
15
+ "string": [
16
+ "`",
17
+ "\"",
18
+ "'"
19
+ ]
20
+ },
21
+ "importSpecifiersAreStrings": true,
22
+ "definitionPatterns": [
23
+ {
24
+ "id": "struct",
25
+ "kind": "struct",
26
+ "regex": "\\btype\\s+([A-Za-z_][A-Za-z0-9_]*)\\s+struct\\b"
27
+ },
28
+ {
29
+ "id": "interface",
30
+ "kind": "interface",
31
+ "regex": "\\btype\\s+([A-Za-z_][A-Za-z0-9_]*)\\s+interface\\b"
32
+ },
33
+ {
34
+ "id": "type",
35
+ "kind": "type",
36
+ "regex": "\\btype\\s+([A-Za-z_][A-Za-z0-9_]*)\\s+(?!struct\\b|interface\\b)[A-Za-z_*\\[]"
37
+ },
38
+ {
39
+ "id": "func",
40
+ "kind": "func",
41
+ "regex": "^func\\s+(?:\\([^)]*\\)\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*[(\\[]"
42
+ }
43
+ ],
44
+ "importPatterns": [
45
+ {
46
+ "id": "specifier",
47
+ "regex": "^[ \\t]*(?:import[ \\t]+)?(?:[A-Za-z_.][A-Za-z0-9_]*[ \\t]+)?\"(?:[^\"]*/)?([A-Za-z_][A-Za-z0-9_.-]*)\"[ \\t]*$"
48
+ }
49
+ ],
50
+ "referenceKinds": [
51
+ "struct",
52
+ "interface",
53
+ "type"
54
+ ],
55
+ "referenceKindsNote": "func is deliberately absent, for the reason the Swift, Kotlin, Node and Python rules all record: a bare name matched across files is almost never a call to that exact declaration, and Go's short-name convention (New, Run, Get, Close, Error) makes it worse than most. Functions still reach the graph through their defines edge, so they stay findable by name.",
56
+ "ignoredIdentifiers": [
57
+ "package",
58
+ "import",
59
+ "func",
60
+ "type",
61
+ "struct",
62
+ "interface",
63
+ "map",
64
+ "chan",
65
+ "var",
66
+ "const",
67
+ "return",
68
+ "if",
69
+ "else",
70
+ "for",
71
+ "range",
72
+ "switch",
73
+ "case",
74
+ "default",
75
+ "select",
76
+ "go",
77
+ "defer",
78
+ "break",
79
+ "continue",
80
+ "fallthrough",
81
+ "goto",
82
+ "nil",
83
+ "true",
84
+ "false",
85
+ "iota",
86
+ "make",
87
+ "new",
88
+ "len",
89
+ "cap",
90
+ "append",
91
+ "copy",
92
+ "delete",
93
+ "panic",
94
+ "recover",
95
+ "print",
96
+ "println",
97
+ "error",
98
+ "string",
99
+ "bool",
100
+ "byte",
101
+ "rune",
102
+ "int",
103
+ "int8",
104
+ "int16",
105
+ "int32",
106
+ "int64",
107
+ "uint",
108
+ "uint8",
109
+ "uint16",
110
+ "uint32",
111
+ "uint64",
112
+ "float32",
113
+ "float64",
114
+ "complex64",
115
+ "complex128",
116
+ "uintptr",
117
+ "any",
118
+ "comparable",
119
+ "err",
120
+ "ctx",
121
+ "ok"
122
+ ],
123
+ "note": "A Go import path is a string literal, so `importSpecifiersAreStrings` applies exactly as it does for JavaScript: the import pass reads a text with comments stripped and strings intact, and the pattern captures the last path segment, which is the package name in the overwhelmingly common case where the two agree. The pattern is anchored to a whole line holding nothing but an optional `import`, an optional alias and the quoted path, because Go has no import keyword on the lines inside a parenthesized block. Without that anchor it matched EVERY double-quoted string in the file and turned each one into a module node. A named import (`sql \"database/sql\"`) and the handful of packages whose name differs from their directory both resolve to the directory name, which is what the engine matches against a file basename anyway. The three type patterns are ordered so `struct` and `interface` claim their shapes before the general `type` alias pattern, which excludes them by lookahead rather than by order alone - order and lookahead together, because a rule file that relies on order silently changes meaning when someone sorts it. `func` is anchored to column 0, which is where every Go function and method declaration lives; the engine's nesting rule then never has to fire for this stack.\n\nUNMEASURED: unlike ios, android, node and python, these rules were never run against a real Go codebase. There was no Go repo and no toolchain on the machine that wrote them. The smoke exercises them on a synthetic fixture, which proves they parse and produce a schema-valid graph, not that they produce a USEFUL one. Treat the first real build as the measurement, and check the hub list before trusting it."
124
+ }
@@ -0,0 +1,95 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "stack": "ios",
4
+ "description": "Swift code-graph rules. Adds what the graph needs on top of test-gap-rules/ios.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants internal types too, because Phase 1 narrows scope on the whole module, not just its public surface.",
5
+ "comments": {
6
+ "line": ["//"],
7
+ "block": [["/*", "*/"]],
8
+ "string": ["\"\"\"", "\""]
9
+ },
10
+ "definitionPatterns": [
11
+ {
12
+ "id": "class",
13
+ "kind": "class",
14
+ "regex": "\\b(?:final\\s+)?class\\s+([A-Z][A-Za-z0-9_]*)"
15
+ },
16
+ {
17
+ "id": "struct",
18
+ "kind": "struct",
19
+ "regex": "\\bstruct\\s+([A-Z][A-Za-z0-9_]*)"
20
+ },
21
+ {
22
+ "id": "enum",
23
+ "kind": "enum",
24
+ "regex": "\\benum\\s+([A-Z][A-Za-z0-9_]*)"
25
+ },
26
+ {
27
+ "id": "protocol",
28
+ "kind": "protocol",
29
+ "regex": "\\bprotocol\\s+([A-Z][A-Za-z0-9_]*)"
30
+ },
31
+ {
32
+ "id": "actor",
33
+ "kind": "actor",
34
+ "regex": "\\bactor\\s+([A-Z][A-Za-z0-9_]*)"
35
+ },
36
+ {
37
+ "id": "typealias",
38
+ "kind": "typealias",
39
+ "regex": "\\btypealias\\s+([A-Z][A-Za-z0-9_]*)"
40
+ },
41
+ {
42
+ "id": "func",
43
+ "kind": "func",
44
+ "regex": "\\bfunc\\s+([a-zA-Z_][A-Za-z0-9_]*)"
45
+ }
46
+ ],
47
+ "importPatterns": [
48
+ {
49
+ "id": "import",
50
+ "regex": "^\\s*import\\s+(?:class|struct|enum|protocol|func|var|let|typealias)\\s+([A-Za-z_][A-Za-z0-9_]*)|^\\s*import\\s+([A-Za-z_][A-Za-z0-9_]*)"
51
+ }
52
+ ],
53
+ "referenceKinds": ["class", "struct", "enum", "protocol", "actor", "typealias"],
54
+ "referenceKindsNote": "func is deliberately absent. A bare lowercase method name matched across files is almost never a call to that exact declaration: on a large Swift app `with`, `size`, `name`, `image` and `model` took the top god-node slots purely because each happened to be declared in exactly one file. Functions still reach the graph through their `defines` edge, so they stay findable by name.",
55
+ "ignoredIdentifiers": [
56
+ "self",
57
+ "Self",
58
+ "super",
59
+ "init",
60
+ "deinit",
61
+ "body",
62
+ "some",
63
+ "any",
64
+ "func",
65
+ "class",
66
+ "struct",
67
+ "enum",
68
+ "protocol",
69
+ "extension",
70
+ "var",
71
+ "let",
72
+ "return",
73
+ "guard",
74
+ "where",
75
+ "case",
76
+ "default",
77
+ "import",
78
+ "public",
79
+ "private",
80
+ "internal",
81
+ "fileprivate",
82
+ "open",
83
+ "static",
84
+ "final",
85
+ "override",
86
+ "throws",
87
+ "async",
88
+ "await",
89
+ "try",
90
+ "nil",
91
+ "true",
92
+ "false"
93
+ ],
94
+ "note": "extension is intentionally NOT a definition pattern. `extension Foo` would register a second symbol named Foo alongside its declaring file, the name would become ambiguous, and buildGraph drops ambiguous references - so every reference to an extended type would vanish. Extensions still reach the graph as reference edges through the identifier pass."
95
+ }
@@ -0,0 +1,151 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "stack": "node",
4
+ "description": "TypeScript + JavaScript code-graph rules. Adds what the graph needs on top of test-gap-rules/node.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants unexported declarations too, because Phase 1 narrows scope on the whole module, not just its public surface.",
5
+ "comments": {
6
+ "line": [
7
+ "//"
8
+ ],
9
+ "block": [
10
+ [
11
+ "/*",
12
+ "*/"
13
+ ]
14
+ ],
15
+ "string": [
16
+ "`",
17
+ "\"",
18
+ "'"
19
+ ]
20
+ },
21
+ "definitionPatterns": [
22
+ {
23
+ "id": "class",
24
+ "kind": "class",
25
+ "regex": "\\bclass\\s+([A-Za-z_$][A-Za-z0-9_$]*)"
26
+ },
27
+ {
28
+ "id": "interface",
29
+ "kind": "interface",
30
+ "regex": "\\binterface\\s+([A-Za-z_$][A-Za-z0-9_$]*)"
31
+ },
32
+ {
33
+ "id": "type",
34
+ "kind": "type",
35
+ "regex": "\\btype\\s+([A-Za-z_$][A-Za-z0-9_$]*)\\s*(?:<[^=>]*>\\s*)?="
36
+ },
37
+ {
38
+ "id": "enum",
39
+ "kind": "enum",
40
+ "regex": "\\benum\\s+([A-Za-z_$][A-Za-z0-9_$]*)"
41
+ },
42
+ {
43
+ "id": "const",
44
+ "kind": "const",
45
+ "regex": "^(?:export\\s+)?(?:declare\\s+)?const\\s+([A-Z][A-Za-z0-9_$]*)\\s*[:=]"
46
+ },
47
+ {
48
+ "id": "function",
49
+ "kind": "function",
50
+ "regex": "\\bfunction\\s*\\*?\\s+([A-Za-z_$][A-Za-z0-9_$]*)"
51
+ }
52
+ ],
53
+ "importPatterns": [
54
+ {
55
+ "id": "specifier",
56
+ "regex": "(?:\\bfrom|\\brequire\\s*\\(|\\bimport)\\s*\\(?\\s*[\"'](?:[^\"']*[\\/:])?([A-Za-z_$][A-Za-z0-9_$-]*)(?:\\.[A-Za-z0-9]+)*[\"']"
57
+ }
58
+ ],
59
+ "referenceKinds": [
60
+ "class",
61
+ "interface",
62
+ "type",
63
+ "enum",
64
+ "const"
65
+ ],
66
+ "referenceKindsNote": "function is deliberately absent, for the reason Swift's rules record for func: a bare name matched across files is almost never a call to that exact declaration, and the generic ones (run, main, get, parse, handler) would take the top god-node slots purely because each happened to be declared once. Functions still reach the graph through their defines edge, so they stay findable by name. const is present but narrowed to an uppercase-initial declaration at column 0, which is what a component, a singleton or an exported table looks like; a lowercase const is a local and is not a declaration anyone references across files. Measured on this repo (126 sources): including function put `ok` at degree 52, `f` at 38, `tokens` at 15 and `arg` at 12 - local helper names that happen to be declared exactly once, so the ambiguity rule does not catch them either. Excluding it leaves a thin symbol layer, and that is the honest shape of this stack: a JavaScript module's exported unit is usually a function, so the useful graph here is the import graph between files. `graph-affected \"<file>.mjs\"` answers who imports a module, which is the question this stack actually gets asked.",
67
+ "ignoredIdentifiers": [
68
+ "this",
69
+ "super",
70
+ "constructor",
71
+ "prototype",
72
+ "arguments",
73
+ "class",
74
+ "interface",
75
+ "type",
76
+ "enum",
77
+ "function",
78
+ "const",
79
+ "let",
80
+ "var",
81
+ "return",
82
+ "import",
83
+ "export",
84
+ "default",
85
+ "from",
86
+ "as",
87
+ "in",
88
+ "of",
89
+ "new",
90
+ "delete",
91
+ "typeof",
92
+ "instanceof",
93
+ "void",
94
+ "await",
95
+ "async",
96
+ "yield",
97
+ "if",
98
+ "else",
99
+ "switch",
100
+ "case",
101
+ "for",
102
+ "while",
103
+ "do",
104
+ "break",
105
+ "continue",
106
+ "try",
107
+ "catch",
108
+ "finally",
109
+ "throw",
110
+ "extends",
111
+ "implements",
112
+ "static",
113
+ "public",
114
+ "private",
115
+ "protected",
116
+ "readonly",
117
+ "declare",
118
+ "namespace",
119
+ "module",
120
+ "require",
121
+ "null",
122
+ "undefined",
123
+ "true",
124
+ "false",
125
+ "string",
126
+ "number",
127
+ "boolean",
128
+ "object",
129
+ "any",
130
+ "unknown",
131
+ "never",
132
+ "console",
133
+ "process",
134
+ "window",
135
+ "document",
136
+ "Promise",
137
+ "Array",
138
+ "Object",
139
+ "String",
140
+ "Number",
141
+ "Boolean",
142
+ "Error",
143
+ "JSON",
144
+ "Math",
145
+ "Date",
146
+ "Map",
147
+ "Set"
148
+ ],
149
+ "note": "A JavaScript module specifier IS a string literal, so `importSpecifiersAreStrings` tells the engine to run the import patterns over a text with comments stripped but strings intact. Without it every import edge in this stack would vanish silently, because the specifier is blanked before the pattern ever sees it. Only the import pass reads that text; definitions and the identifier set still come from the fully stripped body, so a name that appears only inside a string still produces no reference edge. Template literals are stripped whole, interpolations included: it is better to lose a real mention than to invent one from a string. The single specifier pattern captures the last path segment with any extension chain removed, which is what the engine resolves against a file basename: ./_retrieval.mjs and ../a/b/util and node:fs and @scope/pkg all reduce to one name.",
150
+ "importSpecifiersAreStrings": true
151
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "stack": "python",
4
+ "description": "Python code-graph rules. Adds what the graph needs on top of test-gap-rules/python.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants private declarations too, because Phase 1 narrows scope on the whole package, not just its public surface.",
5
+ "comments": {
6
+ "line": ["#"],
7
+ "block": [],
8
+ "string": ["\"\"\"", "'''", "\"", "'"]
9
+ },
10
+ "definitionPatterns": [
11
+ {
12
+ "id": "class",
13
+ "kind": "class",
14
+ "regex": "\\bclass\\s+([A-Za-z_][A-Za-z0-9_]*)"
15
+ },
16
+ {
17
+ "id": "def",
18
+ "kind": "def",
19
+ "regex": "\\bdef\\s+([A-Za-z_][A-Za-z0-9_]*)"
20
+ }
21
+ ],
22
+ "importPatterns": [
23
+ {
24
+ "id": "from-import",
25
+ "regex": "^\\s*from\\s+[.\\w]*?([A-Za-z_][A-Za-z0-9_]*)\\s+import\\b"
26
+ },
27
+ {
28
+ "id": "import",
29
+ "regex": "^\\s*import\\s+(?:[A-Za-z_][A-Za-z0-9_]*\\.)*([A-Za-z_][A-Za-z0-9_]*)"
30
+ }
31
+ ],
32
+ "referenceKinds": ["class"],
33
+ "referenceKindsNote": "def is deliberately absent, for the reason Swift's rules record for func and the node rules record with measurements: a bare lowercase name matched across files is almost never a call to that exact declaration, and Python's convention of short module-level helpers (main, run, load, parse, setup) makes it worse than most. Functions still reach the graph through their defines edge, so they stay findable by name.",
34
+ "ignoredIdentifiers": [
35
+ "self",
36
+ "cls",
37
+ "class",
38
+ "def",
39
+ "return",
40
+ "import",
41
+ "from",
42
+ "as",
43
+ "in",
44
+ "is",
45
+ "not",
46
+ "and",
47
+ "or",
48
+ "if",
49
+ "elif",
50
+ "else",
51
+ "for",
52
+ "while",
53
+ "break",
54
+ "continue",
55
+ "pass",
56
+ "try",
57
+ "except",
58
+ "finally",
59
+ "raise",
60
+ "with",
61
+ "yield",
62
+ "lambda",
63
+ "global",
64
+ "nonlocal",
65
+ "assert",
66
+ "del",
67
+ "async",
68
+ "await",
69
+ "None",
70
+ "True",
71
+ "False",
72
+ "print",
73
+ "len",
74
+ "str",
75
+ "int",
76
+ "float",
77
+ "bool",
78
+ "list",
79
+ "dict",
80
+ "set",
81
+ "tuple",
82
+ "type",
83
+ "range",
84
+ "open",
85
+ "super",
86
+ "property",
87
+ "staticmethod",
88
+ "classmethod"
89
+ ],
90
+ "note": "There is no block-comment token: a Python triple-quoted docstring is a string literal, and it is listed under `string` so the stripper removes it the same way it removes any other string. Longest tokens come first there, so \"\"\" and ''' are consumed whole before the single-quote forms get a chance to match their first character. Both import patterns capture the LAST dotted segment, which is what the engine resolves against a file basename: `from package.module import Thing` points at module.py, and `import package.module` does the same. `from . import x` and `from .. import x` capture nothing, deliberately - a bare relative package names a directory, and pointing it at an arbitrary file inside would invent an edge nobody wrote."
91
+ }