Resync with graphify-py @ 92e682f (v0.9.0)#31
Conversation
Port the applicable feature, security, and bug-fix changes from
`graphify-py` v0.8.49 -> v0.9.0 (38 upstream commits) and bump the
workspace to `0.9.0`.
Ports:
- Node IDs are now the full repo-relative path with the extension
dropped and separators collapsed to `_`, so same-named files in
different directories stay distinct (#1504, #1509). Legacy graphs
read as-is with a one-line rebuild nudge.
- Cross-file type-reference stubs are sourceless and carry an
`origin_file` so same-label stubs from different files do not merge
(#1462, #1500).
- New C# cross-file type resolver plus `enum`/`struct`/`record` node
types (#1466).
- Java `enum`/annotation node types, generic-argument and field-type
references (#1512, #1510, #1485, #1487).
- Objective-C header routing, generic property types, class-method
selectors, and `@import` handling (#1475).
- New WPF/XAML extractor: `x:Class`, named controls, `{Binding}`
paths, and ViewModel / code-behind resolution (#1460, #1473).
- Vue single-file-component extraction and `.metal` routing through
the C++ extractor (#1468, #1480).
- Obsidian export only overwrites notes it owns via a manifest, the
Canvas uses a `ceil(sqrt(n))` grid, and note/canvas filenames are
de-duplicated case-insensitively (#1506, #1452, #1453).
- Wiki articles link with portable relative Markdown links instead of
`[[wikilinks]]`, with case-folded slug dedup (#1444, #1453).
- LLM requests send `stream: false`, and `kimi`/`gemini`/`deepseek`
honour a bare `*_BASE_URL` (#1223, #1458).
- CLI `--timing` on `extract`/`cluster-only`/`label`, and
`--missing-only` on `cluster-only`/`label` (#1490, #1481).
- `reflect --if-stale` also weighs the graph sidecars, the Read|Glob
hook matches a file's real trailing extension, and `affected` /
`explain` resolve a source-file path to its file-level node
(#1470, #1463, #1503).
Glory to the Omnissiah
Resolve the 24 findings from the first CodeRabbit pass on the resync.
Genuine divergences from graphify-py are fixed; findings that match
graphify-py are kept and the rationale recorded in an in-code comment
(CodeRabbit reads code, not commit messages).
Fixes:
- `extract()` now clears the thread-local XAML `ViewModel` class cache
per run (generation-gated across the rayon pool), matching graphify-py
`_XAML_CSHARP_CLASS_CACHE.clear()`; a repeated in-process run re-scans
`.cs` instead of serving stale members. Adds a regression test.
- Obsidian manifest write propagates IO errors instead of swallowing
them, like the sibling note writes and graphify-py `.write_text`.
- `ingest` C-family map includes `.cxx` (extracted as C++ and present in
`analyze`'s family map; graphify-py's build map omits it).
- Legacy-id alias registration is skipped unless the node id shares the
new stem, so a mismatched prefix no longer maps unrelated edges.
- `collect_cs_files` uses `entry.file_type()` so a symlinked directory
cannot loop forever.
- `is_objc_header` reads only the 256 KiB it inspects.
- Vue dynamic-import recovery scans the masked source, so an `import()`
in `<template>`/`<style>` is not edged.
Kept as graphify-py parity (documented in code):
- Sourceless stub `source_location` stays `Some("")` (graphify-py emits
`""`); wiki resolver keys by label and reserves `index` only in the
resolver; C# merges a file's namespaces into one scope; the direct
`<Binding Path>` element emits no generated-member edge; validation
runs once before the semantic re-key.
Also strengthens the affected test assertions (exact set/count checks,
`origin_file` and canonical-id checks, real absolute/relative paths, raw
event-edge count, loud directory-walk errors).
By the will of the Machine God
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (7)
📝 WalkthroughWalkthroughThis release bumps the workspace to 0.9.0, changes node IDs to full repo-relative stems, adds ChangesGraphify 0.9.0 release
Sequence Diagram(s)sequenceDiagram
participant extract_xaml
participant code_behind_resolver
participant viewmodel_resolver
participant cs_class_lookup
participant toolkit_extractor
participant XamlBuilder
extract_xaml->>code_behind_resolver: resolve x:Class and event handlers
extract_xaml->>viewmodel_resolver: detect DataContext / Prism / naming
viewmodel_resolver->>cs_class_lookup: scan *ViewModel classes
extract_xaml->>toolkit_extractor: emit ObservableProperty / RelayCommand members
extract_xaml->>XamlBuilder: deduplicate nodes and edges
Estimated code review effort🎯 5 (Critical) | ⏱️ ~150 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Resolve the findings from the second CodeRabbit pass. Genuine bugs and determinism gaps are fixed (several are bugs `graphify-py` shares, fixed per AGENTS.md); findings that faithfully mirror `graphify-py` are kept, with the parity reasoning recorded in code. Fixes: - `with_xaml_extract_root` restores the thread-local extract root through an RAII guard, so a panic can't leak it to a reused rayon worker (parity with graphify-py's `try`/`finally`). - `.xaml` joins the AST disk-cache bypass list: XAML resolution scans sibling `.cs` code-behind, so a content-keyed cache served stale `ViewModel` members across runs. - `origin_file` is relativized alongside `source_file` (extraction and build) so the #1462 stub field no longer leaks absolute machine paths into graph JSON. - objc and PowerShell `ensure_named_node` emit sourceless stubs (empty `source_file`, `origin_file` set) so cross-file references rewire onto real definitions instead of becoming phantom duplicates (#1402/#1462). - Obsidian `owned_write` refuses to follow a symlink at the target or a parent component, so a symlinked note can't escape the vault (#1506). - `find_node` matches a source path by its normalized full path rather than tokenized form, so distinct paths no longer collide. - `cluster-only --missing-only` preserves a malformed labels file instead of relabeling over it, matching the non-`--missing-only` path. - `#[must_use]` on the pure ID/stem helpers; corrected `extract` and `label` doc-comments. Kept as parity (documented in code): the objc compound-selector node-ID form, C# nested-namespace registration deferral, and the wiki/`index_md` god-node list all mirror `graphify-py` exactly. Test strengthening: `lessons_fresh` now covers both graph sidecars (matching the Python parametrization), the trailing-slash seed test exercises the re-keyed file node, and the affected test suites return `Result` with `?` per the repo convention. By the will of the Machine God
A `src\foo.rs` query reached the `source_exact` tier (its `query_path` normalizes `\` to `/`), but the L1 file-node preference never fired. `query_basename` came from `Path::file_name` on the raw label, and on Unix `\` is not a path separator, so the basename kept the whole backslash string instead of `foo.rs` — so the file node never floated ahead of its symbols. Derive both `query_basename` and `query_path` from one slash-normalized string so Windows-style path queries match the forward-slash behavior (#1503). The `#[must_use]` nitpick on `find_node` was already satisfied; no change there. Ave Deus Mechanicus
Three CodeRabbit findings (C# nested namespaces, ObjC selector colon collapse, wiki `index_md` god-node list) were re-raised. Verified each against `graphify-py @ 92e682f`: all faithfully mirror the reference, none is a still-valid bug, and "fixing" any would break byte-identical parity. No behavioral change — only inline parity notes: - ObjC (`objc.rs`): graphify-py joins selector identifiers colon-less (`extract.py:9623`/`:9657`), pinned by `objc_compound_selector_call_ resolves`. Firmed the comment to name the deliberate collision-risk trade-off (`setFoo:bar:`/`setFoobar:` collapse); preserving `:` would re-key every keyword selector and break parity. - Wiki (`generate.rs`): `index_md` intentionally gets the full `god_nodes_data` (`wiki.py:333`); a node absent from the graph is rendered as plain text by `md_link`, not a broken link, so filtering would diverge from byte-identical `index.md`. Documented at the call site. The C# site was already documented (`csharp.py:106-111`, flat `own_ns` with `# len > 1: skip`); left unchanged. By the will of the Machine God
`cluster-only --no-label --missing-only` with an existing `.graphify_labels.json` wiped every community to a `Community N` placeholder, clobbering hand-curated names. The `--no-label` branch fired before the `--missing-only` handling and never loaded the existing file. graphify-py preserves here: `__main__.py:3489` loads existing labels for any `exists && !force_relabel` case, with no `missing_only` exclusion. The Rust port had added `&& !opts.missing_only` to that branch, dropping `--no-label --missing-only` into the placeholder path. Fire the preserve branch whenever no LLM naming will happen (`!missing_only || no_label`), since `--no-label` forbids any LLM call. Curated labels survive; only true gaps fall back to placeholders. Adds a `cluster-only` regression test. By the will of the Machine God
Address the latest CodeRabbit findings (verified against `graphify-py @ 92e682f`): - `cluster-only` marked the `export` stage before the HTML render, so `--timing` excluded `to_html` time. graphify-py marks it after (`__main__.py:3555`); moved the mark past the render to match. - Strengthened the label-preservation tests to assert community 0 still maps to `Authentication` by key (parse + `["0"]`), not a bare substring; added a concrete per-stage line to the timing test. Adds `serde_json` as a dev-dependency for the structural assertion. Skipped (parity): the `--no-label` branch keeps `&& !force_relabel` — `label` does not accept `--no-label`, so the combination is unreachable, and the guard matches graphify-py `__main__.py:3494` (`elif no_label and not force_relabel`). By the will of the Machine God
7985376 to
6bf2f0d
Compare
Ports the applicable changes from
graphify-pyv0.8.49 → v0.9.0 (38 upstream commits) and bumps the workspace to0.9.0. Submodule pointer advanced to92e682f.Breaking change
_), e.g.src/auth/session.py→src_auth_session,validate()inside →src_auth_session_validate(#1504/#1509). Same-named files in different directories no longer collide. Abuild_from_jsonre-key migrates pre-#1504 graphs; read-only consumers (query/serve) print a one-line rebuild nudge instead of silently re-keying.Ported
origin_fileso same-label stubs from different files stay distinct (#1462/#1500).enum/struct/recordnode types (#1466).@import(#1475).x:Class, named controls,{Binding}paths, ViewModel / code-behind resolution (#1460/#1473)..metalrouted through the C++ extractor (#1468/#1480).ceil(sqrt(n))grid, case-fold filename dedup (#1506/#1452/#1453); wiki portable relative-Markdown links (#1444).stream: false;kimi/gemini/deepseekhonour a bare*_BASE_URL(#1223/#1458).--timingonextract/cluster-only/label;--missing-onlyoncluster-only/label(#1490/#1481).--if-staleweighs graph sidecars; the Read|Glob hook matches the real trailing extension;affected/explainresolve a source-file path to its file-level node (#1470/#1463/#1503).Docs (
README.md,USAGE.md) reconciled: new flags, formats, env vars, node-ID scheme, and export behaviours. Parity tests ported for every new upstream test case.Verification
cargo clippy --all-targets --all-features --workspace— cleancargo nextest run --workspace— 2283 passed, 2 skippedhk check— pass--type committed—findings: 0(24 first-pass findings resolved: genuine divergences fixed, graphify-py-matching ones kept with in-code// Parity dispute (CodeRabbit): …comments)Summary by CodeRabbit
--timingand--missing-only; expanded backend base-URL env overrides (KIMI/GEMINI/DEEPSEEK).