Repository navigation
Releases: lkhfrgc/enhanced-graph
Release list
Enhanced Graph 1.3.3
A documentation release: the entry page now points at the companion project.
Works better together with scholar-llm-wiki
scholar-llm-wiki builds the kind of vault this
plugin is for — AI agents compile papers, books and notes into a structured, densely
interlinked wiki. A dense link graph is what makes the association engine and the insights
panel worth having: the scoring has something to score, and the structural cards have
something to find.
The line sits directly under the title in both READMEs, each in its own language:
Works better together with scholar-llm-wiki in README.md — the one the directory renders
— and 结合 scholar-llm-wiki 使用更佳 in README.zh.md.
No plugin code changed in this release.
1.3.2 added this line to both files in Chinese, which put the wrong language on the directory's
entry page. This release is that correction, and nothing else.
Enhanced Graph 1.3.2
A documentation release: the entry page now points at the companion project.
结合 scholar-llm-wiki 使用更佳
scholar-llm-wiki builds the kind of vault this
plugin is for — AI agents compile papers, books and notes into a structured, densely
interlinked wiki. A dense link graph is what makes the association engine and the insights
panel worth having: the scoring has something to score, and the structural cards have
something to find.
The line sits directly under the title, in both README.md (which the directory renders) and
README.zh.md.
No plugin code changed in this release.
Enhanced Graph 1.3.1
A submission fix. 1.3.0 was rejected by the plugin directory's automated review, and the
cause was in the diagnostic added while chasing a layout bug.
What the review rejected, and why it was right
Unexpected undescribed directive comment. Include descriptions to explain why the
comment is necessary.
src/view/width-probe.ts:70
src/view/width-probe.ts:190
Disabling 'no-console' is not allowed.
src/view/width-probe.ts:70
src/view/width-probe.ts:190
The width probe printed its report with console.log, silenced by
// eslint-disable-next-line no-console. Both halves were wrong:
- The rule that was actually enabled is
obsidianmd/rule-custom-message, notno-console,
so the directive silenced nothing and was reported as unused — and an unexplained
directive is itself an error. - Explaining it would not have helped.
eslint-comments/require-descriptionwants a
description andeslint-comments/no-restricted-disablerefuses to let that rule be
disabled at all, so a console call in a submitted plugin cannot be silenced. Obsidian's
guideline is that a plugin should not log what it can show instead.
What the probe does now
The report is published on window as enhancedGraphWidthProbe(), and the same report is
offered as a Notice when the event fires. Nothing is logged. Calling the function in the
developer console returns the text; scripts/obsidian-probe*.mjs in the repository read it
over the DevTools protocol, which is how the panel-width bug was actually found and fixed.
It is a better interface than the log it replaces: the name autocompletes, and calling it is
the documentation.
command.probe-official-graph also had a console.info mirroring the report it already
shows as a Notice. Removed for the same reason — the report was in two places and one of
them was against the guidelines.
So this cannot happen again
npm run verify now includes npm run lint:obsidian, which runs the reviewer's own
eslint-plugin-obsidianmd recommended set over src. It is scoped to the three rules the
review actually enforces — the console rule and the two directive rules — because the sample
plugin's configuration is stricter than the reviewer and enabling the rest would fail the
build on warnings the directory accepts.
Verified both ways: restoring the rejected console.log and its directive reproduces the
review's messages exactly, and removing it passes.
Also fixed
The --fix pass used while cleaning this up removed a type assertion in official-graph.ts
that was load-bearing; 85 tests caught it and the change was reverted rather than kept.
Enhanced Graph 1.3.0
The insights panel is rebuilt around one idea: a card should say what it noticed and what it
costs you to act on it. The old panel offered one kind of card — a connection the vault did not
know about — and there are now nine, grouped into four tabs, ordered by severity and then by how
much work the card is.
The interface strings for this feature are Chinese. The English column below is a translation
for this document only.
The panel
Four tabs, each answering a different question:
| Tab | Cards |
|---|---|
| 建议新增 (suggested new links) | 正文提及 N 处但未链接 — a page's name written in prose without a link · 共享 N 个邻居 — two pages with many shared neighbours and no link between them · 疑似重复页 |
| 惊奇连接 (surprising links) | Links you already wrote, scored for crossing a community boundary, joining distant page types, and sharing sources. This is the previous release's list, given its own tab — it had been buried under newer cards |
| 结构风险 (structural risks) | 单点故障 (removing the page disconnects part of the graph) · 集群门户 (a whole area reachable through one page) · 连接不足的枢纽 (more structure than its link count suggests) · 中介节点 (sits between groups that do not talk to each other) |
| 知识空白 (knowledge gaps) | N 个孤立页面 · 稀疏知识领域 · 关键桥接 |
Every card carries an evidence badge (强证据 / 中等证据 / 弱证据) and a cost badge — 一键
(one click), 需编辑, or 需撰写 — and the ordering respects the cost: at the same severity,
the cards you can clear in one click come first.
Dismissals are applied live against your current settings, so a card you dismiss stays dismissed
across rebuilds. The tab labels count what is left.
Acting on a card, not just reading it
A card whose link can be inserted without writing anything gets an 插入链接 button. It shows
the exact line before and after, with the new link highlighted, and writes only when you confirm.
The insertion goes through Obsidian's vault API, so it lands in the editor's own undo history —
Ctrl/Cmd+Z takes it back.
The insertion keeps your words. If a note writes 偏好优化(DPO) and the page is called
RLHF 与 DPO, the result is 偏好优化(DPO)([[RLHF 与 DPO]]): the link is added beside what
you wrote, never substituted for it. The same holds when a page's name differs from the words in
the sentence, and when a note writes a name in a different case.
Other cards offer 并排打开 (both notes side by side), create an index note, or export.
Faster
The graph and the analysis are cached, and a rebuild no longer blocks the view: the panel keeps
showing the previous findings while a new pass runs, and vault changes mark the cache stale
rather than re-running the analysis on every keystroke.
Fixed
- The insight panel's width is fixed and no longer follows its pane, and its cards are one width
across every group. Cards used to change width between tabs because a group whose content
overflowed gave 14 px to the scrollbar while a short group gave none — measured in a real
vault, 266 px against 278 px. - The panel is no longer cut off in a narrow pane.
Built, but not reachable in this release
Said plainly rather than left for you to discover:
- The trends tab is empty, and correctly so. 长期孤立页面 and 久未更新的枢纽 need page ages;
on a three-day-old vault nothing has aged past the thresholds. 新兴主题 and 衰退主题 need a
history of when each link first appeared — the detection is written and tested, but nothing
calls it yet, so no history file is being written. Those two cards cannot fire until that
is wired up. - The exported report still covers the two original sections. The panel shows nine card
types; the report has not been extended to match. - Panel contents can reshuffle. Measured: dropping 2 % of a vault's links keeps about 2.5 of
the panel's 6 cards. Dismissals survive a rebuild intact, but a materially changed graph can
reorder a group.
Enhanced Graph 1.2.1
A fix release for types, colour and labels, all reported from a second vault.
The legend showed one colour and the graph drew another
A legend row's dot came from a hash of the type's name, while the node beside it was drawn
from the vault's per-type colour: concept appeared with a green dot next to blue nodes.
The built-in graph's legend was never given the colour table the canvas was using — one
missing argument. Both now read from the same source.
The same hash explains two types sharing a colour: it collides, and connection and
question collided in a real vault.
What is checked now, rather than assumed: every legend row's dot is compared against the
colour of a node of that type. The old checks compared a function's output with itself,
which is why both sides looked correct while the screen disagreed.
A type keeps its colour
A type's colour used to be recomputed from the sorted list of types, so the set changing
moved the colours: measured, adding one type repainted 13 of 13 existing types when it
sorted first, and 3 of 13 when it sorted last.
Each type is now given a free colour the first time it appears, stored in the vault's
settings, and keeps it. A type that disappears releases its colour; one that comes back is
treated as a new type, so the palette does not fill up with pages that no longer exist.
Deleting typeColorAssignments from the settings starts over.
The ramp itself is also ordered better. Assignment walks the ramp, so a vault uses a prefix
of it, and the first five entries used to be five reds — the closest pair within any prefix
was ΔE 19.0. Farthest-point ordering lifts the first five to ΔE 38.5 while leaving the
22-colour minimum at 19.0. Colours change once on upgrade, then stay put.
A type is shown the way the note writes it
Rows, the hover card, the right-click menu, the status line and the exported report all
showed the plugin's own word for a type: a note with type: synthesis was labelled 综述, and
paper was shown as paper · source. Every surface now shows the declared string, and the
22 translated type names are gone from the interface strings entirely, so nothing can
translate a type again. A note with no type at all still shows the type the plugin inferred.
npm run audit:colors
New, and it is what made the first bug findable. Against any vault it prints, per declared
type: the label, the legend swatch, the colour its nodes are drawn in, what an older build
would have drawn, and the analysis type. It reads the colours stored in the vault's own
data.json, so it reports what the plugin is using rather than a second opinion.
Also fixed
The test suite failed about one full run in four with four uncaught document is not defined
errors: an enhancer's safety-net timer outlived its test environment. Tests now record every
enhancer they start and stop it afterwards; five consecutive full runs are clean.
Enhanced Graph 1.2.0
Twelve releases of fixes, one feature that changes what the plugin reads, and a
round of work on colour. Everything below was measured on a real vault before it
shipped; where a number is quoted, npm run verify prints it.
Reading a folder instead of the whole vault
The filters panel now scopes the graph to a folder you type, with path suggestions
from your own vault and any number of excluded subfolders. Apply is what makes
it take effect.
This is a build scope, not a hide: notes outside it are not read, so clusters,
insights and the report cover only what is inside. Typed paths replaced a folder
tree, because a tree cannot express an exclusion that has not been created yet.
Three defects in a row came out of it, all fixed and pinned: applying did not tell
the built-in graph to refresh; the built-in graph never applied the scope at all;
and the rebuild refreshed the views against an emptied cache, which is why colours
and folder suggestions disappeared after applying. Measured acceptance, in
verify:vault: scoping to concepts/ gives 27 nodes of 79 with no strays, and the
analysis covers the workspace and nothing else.
Clustering settings
Node weights and the Louvain resolution now live together in a 聚类设置 panel,
in both the standalone view and the built-in graph, with an Apply button and a
reset. Resolution is clamped to 0.5–3. Cluster cores are picked by weighted degree
rather than link count, so a core is the note the cluster's weight actually centres
on.
Sparse communities, judged against the vault
A cluster is now flagged sparse when its cohesion is below 1.5 × the vault's own
density, not below a fixed 0.15. A fixed number cannot travel between vaults: in a
densely linked one it flags nothing, and in a thinly linked one it flags everything.
Measured on this vault: density 0.136, the flagged cluster sits at 1.05×, the rest
at 2.5–4.4×.
Two measurements, no behaviour change
npm run eval:stability— how far the partition moves when the input moves: node
order 0.718 ARI, 1 % of links dropped 0.857, 5 % 0.751, resolution ±0.1 0.847.
Only 47 % of clusters keep their core note under a reordering.npm run eval:weightsgained a tag signal: tags alone score AUC 0.635 on held-out
link prediction (the retired type-affinity signal scored 0.54), and 25.0 % of
held-out links share a tag against 7.6 % of random pairs. Adding tags to the
shipped model improves it by 0.0071 with a pooled sd of 0.0127 — not significant,
so the model was left alone.
Types, and colour
Type rows are the types your vault declares, not the eleven the plugin knows.
A note with type: 实验记录 gets its own row, its own count, its own filter and its
own colour, so twenty custom types are twenty rows rather than one other.
Colours are assigned per vault: each build sorts the declared types and hands each
one the next entry of a searched ramp, so two types cannot collide. Measured: 13
declared types, 13 colours; a per-name hash gave 5 distinct colours for 10 custom
names. The ramp is 22 colours, worst pair ΔE 19.0, every one clearing 3:1 on both
the dark and the light canvas.
There is no standard spelling. The plugin does not treat concept as the canonical
form of 概念, and reserves no colour for any type — an earlier release did, and the
result was that the same idea written two ways was painted two colours while two
unrelated custom types could collide.
A type row with nothing left on the graph is greyed, including when the reason is
another rule (the workspace, the structural switch, a tag, a cluster) rather than
its own.
Legend gestures
Left-click a legend row excludes or restores that type or cluster, as before.
Right-click marks every node of it with a dot at the node's centre, drawn on the
same overlay the focus and search marks use, so it follows pan and zoom. A mark is
not a filter — nothing is hidden — and the row is highlighted so it is clear which
group is marked. Right-clicking again clears it. Measured: right-clicking 概念 dots
38 of 38 pages with the drawn node count unchanged at 77, and the overlay canvas
goes from 0 to 5289 lit pixels and back to 0.
Where a switch is applied, and when
- The built-in graph now asks its engine for a payload when it attaches. It renders
before the plugin attaches, so the first frame used to show the unfiltered graph:
a switch that is on by default, 隐藏索引 / 概览 / 日志, looked broken until an
unrelated repaint. - A graph view closed and reopened comes back with the panel its toolbar button says
is open. The panel is created per view while the mode outlives it, so it used to
open on the insights under a highlighted 过滤器. - 隐藏孤立节点 judges a page by its links in the whole vault, not in the current
scope: a note whose links all point outside the workspace was being hidden as
isolated. Structural pages are left to the switch that names them.
Fixed for real, not papered over
The test suite failed roughly one full run in four with four uncaught
document is not defined errors: an enhancer's safety-net timer outlived its jsdom
environment. Tests now record every enhancer they start and stop it in afterEach.
Five consecutive full runs are clean.
Enhanced Graph 1.1.1
A submission-review fix release. The plugin behaves exactly as 1.1.0 does; what
changed is what the directory's automated review found.
The blocking error
The review failed 1.1.0 on one error:
Sets styles directly instead of using CSS classes,
setCssProps, or
setCssStyles—harness/official-filters.ts:122
The test harness positions the stand-in built-in graph with an inline
style.cssText. The harness is scanned like the rest of the repository, so a
static style assignment there is an error even though no user ever runs it. The
box now comes from the harness page's own stylesheet
(.harness-official-graph), and the script only sets the class name.
Recommendations cleared
- Release assets now carry build provenance. The release workflow attests
main.jsandstyles.csswithactions/attest-build-provenance, so anyone can
verify withgh attestation verifythat the files were built from this
repository by that workflow, rather than uploaded by hand. - No more unsupported extra asset.
THIRD-PARTY-NOTICES.mdwas published as a
fourth release asset; Obsidian never downloads it and the directory flags it.
The file stays in the repository, and the notices also travel in the bundle's own
footer, so nothing about attribution changed.
Dead code the review noticed
Four leftovers from 1.1.0's removals, each an import or binding nothing used any
more: renderWeights in the built-in graph's module, DEFAULT_RELEVANCE_WEIGHTS,
GraphNode and GraphSnapshot in the plugin entry point, and the unused result of
applyExternalLayout.
Not changed
The review's remaining items are recommendations and warnings that this plugin
cannot honestly clear: it enumerates the vault because a vault-wide graph is what
it draws, and it reads the clipboard because one command copies the relevance
report. Both are listed as recommendations, not errors, and the same entries were
present on 1.0.2, which the review completed.