Skip to content

feat: vault metabolism Phase 2 (structural health metrics + dashboard) - #2

Merged
cizer merged 5 commits into
mainfrom
feat/vault-metabolism-phase2
Jun 15, 2026
Merged

feat: vault metabolism Phase 2 (structural health metrics + dashboard)#2
cizer merged 5 commits into
mainfrom
feat/vault-metabolism-phase2

Conversation

@cizer

@cizer cizer commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Phase 2 of the vault-metabolism plan in METABOLISM.md, stacked on the merged Phase 0-1 work. All structural, timestamp-free, and read-only: no scoring, no access signal, no decay (those stay gated behind the Phase 3 experiment).

2a — structural graph metrics (core/graph.go)

Over the Phase-0 resolved link graph (undirected projection, dangling links excluded, self-loops dropped, edges deduplicated):

  • connected components via union-find (count + giant-component ratio)
  • k-core coreness via Batagelj-Zaversnik peel (the durable-vs-transitory axis, exposed as data, not per-note noise)
  • orphan/leaf and island detectors folded into hebb health

Orphans/leaves are flagged only in connective folders (2-Areas, 3-Resources) once stale; fresh capture and archives are never flagged. Islands are small components (size 2 to island_max_size) that are not the mainland (the largest component is excluded) and not wholly archived, so they never duplicate orphan findings, flag the giant component, or flag fresh single notes. New [health] config block for the folder lists, stale-days, and island size.

2b — the dashboard (hebb serve)

New GET /api/health returns {findings, stats} (refreshing the index like /api/search, behind the same loopback bind and DNS-rebinding Host guard, with a test covering it). The embedded page gains a worklist-first Health tab: findings grouped by type with counts, each row deep-linking to the note via obsidian://, ordered by an honest per-type proxy (no invented access-frequency ranking, that signal is Phase 3). Structural metric tiles sit below. No composite "health score", per the Goodhart rule. Search view unchanged.

Refinement caught by smoke-testing

The first cut of the island detector flagged the giant hub-and-spoke component and double-reported orphans as size-1 islands. Tightened so islands are size 2 to N and never the largest component, then re-verified against the real binary. (Folded into the 2a commit.)

Verification

gofmt, vet, build, test ./... all clean (uncached) after each step, plus a live hebb serve smoke confirming the endpoint, the dashboard markup, and a 403 on a foreign Host.

Next

Phase 3: the access-log observer plus the two-week falsification experiment that decides whether the scoring/decay half of the plan is real.

🤖 Generated with Claude Code

cizer and others added 3 commits June 15, 2026 22:49
…, k-core)

Phase 2a of METABOLISM.md: the timestamp-free structural layer over the
Phase-0 resolved link graph (undirected projection, dangling links excluded,
self-loops dropped, edges deduplicated).

- core/graph.go: union-find connected components (count + giant-component
  ratio), Batagelj-Zaversnik k-core coreness peel (the durable-vs-transitory
  axis, exposed as data not per-note noise), and orphan/leaf/island detectors.
- orphans/leaves are flagged only in connective folders (2-Areas, 3-Resources)
  and only once stale; fresh capture and archives are never flagged. Islands
  are small components (size 2..island_max_size) that are not the mainland
  (largest component excluded) and not wholly archived, so they never
  duplicate orphan findings or flag the giant component or fresh single notes.
- GraphHealth exposes component/coreness stats as the substrate the dashboard
  and vault_stats will read. hebb health prints a one-line graph summary; the
  --json envelope is now {findings, stats}.
- [health] config gains connective_folders, expected_orphan_folders,
  orphan_stale_days, island_max_size with defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 2b of METABOLISM.md: extend the web app from search-only into a
health view. New GET /api/health runs RunHealthFull and returns the
{findings, stats} envelope, refreshing the index like /api/search and
sitting behind the same loopback bind and Host guard (covered by a test).

The embedded page gains a Health tab, worklist-first: findings grouped by
type with counts, each row deep-linking to the note via obsidian://, ordered
by an honest per-type proxy (oversized by tokens, orphans/leaves by age,
islands by size; no invented access-frequency ranking, that signal is
Phase 3). Structural metric tiles (notes, links, components, giant ratio,
max k-core) sit below the worklist. No single composite health score, per
the Goodhart rule. Search view is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0603e97876

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli/health.go Outdated
Comment thread web/index.html Outdated
Comment thread web/index.html Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements Phase 2 of the vault-metabolism plan by extending vault health from Phase-1 content detectors into Phase-2 structural graph metrics (components + k-core + orphan/leaf/island findings) and wiring a new health dashboard into hebb serve via a new /api/health endpoint.

Changes:

  • Add Phase 2a structural graph model + metrics and new detectors (orphans/leaves/islands) surfaced via core.RunHealthFull and CLI output.
  • Add /api/health endpoint and UI “Health” tab to display grouped findings and structural metric tiles.
  • Extend [health] config with thresholds/folder lists and update tests accordingly.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web/server.go Adds /api/health endpoint returning findings + graph stats envelope.
web/server_test.go Adds endpoint shape/host-guard tests and a fixture vault for health.
web/index.html Adds Health tab UI, rendering logic, and dashboard styling.
METABOLISM.md Marks Phase 2 checklist item complete.
core/vaultconfig.go Adds Phase 2a [health] config fields + defaulting accessors.
core/health.go Introduces HealthResult + RunHealthFull, runs Phase 2a detectors, computes graph stats.
core/health_test.go Adjusts “clean notes not flagged” test to only assert Phase 1 types.
core/graph.go New graph implementation: build graph, components, coreness, orphan/leaf/island detection, and GraphStats.
core/graph_test.go New tests covering graph construction, metrics, detectors, and config defaults.
cli/health.go Extends hebb health JSON output envelope and prints structural summary line in text mode.
cli/health_test.go Updates JSON/text tests for new envelope and structural summary line.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread web/index.html Outdated
Comment thread core/graph.go Outdated
Comment thread core/graph.go Outdated
cizer and others added 2 commits June 15, 2026 23:26
Addresses PR #2 review:
- Show the Search/Health tabs on initial load instead of only after a search
  or the #view=health hash, so the dashboard is reachable from the landing
  page (Search stays the default active tab).
- Remove the total note-count tile (the hoarding-incentive vanity metric
  METABOLISM Phase 2 forbids); keep components, giant ratio, max k-core.
- Merge the duplicate class attribute on the refresh-health link (invalid
  HTML that left the click handler unreachable).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… archives

Addresses PR #2 review:
- hebb health --json again emits a top-level []Finding array (its Phase 1
  contract now on main); the {findings, stats} envelope changed shape silently
  and broke array consumers. Graph stats remain on the text summary and the web
  /api/health endpoint, which is unchanged.
- Island suppression now uses a new [health] archive_folders config (default
  4-Archives) instead of the full expected_orphan_folders list, matching
  METABOLISM ("islands outside Archives") and the config comment; islands in
  Journal/Notes are reported again. Orphan/leaf detection still uses the full
  expected-orphan list.
- Correct the GraphHealth doc comment to describe the real call paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cizer

cizer commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

Thanks both. All six addressed in 8c8324a (web) and 05ce760 (core/cli):

  • hebb health --json reverted to a top-level []Finding array (its merged Phase 1 contract); graph stats stay on the text summary and the /api/health endpoint (05ce760).
  • Health dashboard tabs now show on initial load, so the view is reachable without a search or the hash (8c8324a).
  • Removed the total note-count tile (the vanity metric METABOLISM forbids); kept components, giant ratio, max k-core (8c8324a).
  • Merged the duplicate class attribute on the refresh-health link (8c8324a).
  • Island suppression now uses a new [health] archive_folders config (default 4-Archives) instead of the full expected-orphan list, matching the doc and the config comment; islands in Journal/Notes are reported again (05ce760).
  • Corrected the GraphHealth doc comment to describe the real call paths (05ce760).

Also flagged a separate, pre-existing bug found in passing (not in this PR's scope): automation/generate-vault-digest.py selects notes by st_mtime, so a bulk rewrite or sync both hides real edits and floods the next run. Tracked for a follow-up; it is the same mtime-unreliability the Phase 3 access log addresses.

Full suite green; web changes verified with a live serve smoke. Resolving these threads.

@cizer
cizer merged commit 7b65cc1 into main Jun 15, 2026
5 checks passed
@cizer
cizer deleted the feat/vault-metabolism-phase2 branch June 21, 2026 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants