Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: pensar
Type: Package
Title: LLM Wiki Engine
Version: 0.6.2
Version: 0.6.3
Date: 2026-05-19
Authors@R: c(
person("Troy", "Hernandez", role = c("aut", "cre"),
Expand Down
19 changes: 19 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# pensar 0.6.3

## Bug fixes

* `vault_graph()`'s control-file filter now works on Windows. The
previous implementation compared `dirname(file)` against
`normalizePath(vault)`, but `dirname()` on Windows uses forward
slashes in its output while `normalizePath()` defaults to
backslashes, so the comparison was always false on Windows. Control
files (`schema.md`, `index.md`, `log.md`) leaked into the graph,
and the "No pages in vault" guard never fired on an empty vault.
Now normalises `vault` with `winslash = "/"` so the comparison
matches `dirname()`'s output on both platforms.
* `inst/tinytest/test_vault_graph.R`'s empty-vault regression test
is now between the saber-installed and saber-`graph_svg` guards so
it runs on machines whose saber is still at the current CRAN
release (0.3.0). Without this, the win-builder farm was the only
place exercising the bug.

# pensar 0.6.2

## Bug fixes
Expand Down
7 changes: 6 additions & 1 deletion R/vault_graph.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ vault_graph <- function(vault = default_vault(), width = 1600L,
stop("Package 'saber' is required for vault_graph(). ",
"Install it before calling this function.", call. = FALSE)
}
vault <- normalizePath(vault, mustWork = TRUE)
# winslash = "/" so this matches dirname()'s output (which always
# uses forward slashes, even on Windows where normalizePath defaults
# to backslashes). Without it the control-file filter below never
# matches on Windows, control files leak into the graph, and the
# "No pages in vault" guard never fires on an empty vault.
vault <- normalizePath(vault, mustWork = TRUE, winslash = "/")

all_md <- list.files(vault, pattern = "\\.md$", recursive = TRUE,
full.names = TRUE)
Expand Down
21 changes: 13 additions & 8 deletions inst/tinytest/test_vault_graph.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ expect_equal(
if (!requireNamespace("saber", quietly = TRUE)) {
exit_file("saber not installed")
}

# Empty vault errors cleanly. This test doesn't need graph_svg
# (vault_graph errors before reaching the renderer); sits between
# the saber-installed gate and the graph_svg gate so it runs on
# every machine with saber, including ones whose saber is older
# than the one shipping graph_svg(). The bug it guards against is
# the path-separator mismatch on Windows that lets control files
# slip through the "No pages in vault" guard.
empty <- file.path(tempdir(), paste0("empty-vault-",
format(Sys.time(), "%H%M%S")))
init_vault(empty, agent_instructions = FALSE, rproj = FALSE)
expect_error(vault_graph(vault = empty), "No pages in vault")

if (!"graph_svg" %in% getNamespaceExports("saber")) {
exit_file("installed saber lacks graph_svg(); skipping")
}
Expand All @@ -51,11 +64,3 @@ expect_true(any(grepl("type: articles", svg, fixed = TRUE)))
expect_true(any(grepl("(broken wikilink)", svg, fixed = TRUE)))
expect_true(any(grepl("Missing", svg, fixed = TRUE)))

# Empty vault errors cleanly
empty <- file.path(tempdir(), paste0("empty-vault-",
format(Sys.time(), "%H%M%S")))
init_vault(empty, agent_instructions = FALSE, rproj = FALSE)
# Remove the only seeded content so there are no pages (schema/index/log
# are filtered as control files).
# init_vault leaves schema/index/log only, which the function filters out.
expect_error(vault_graph(vault = empty), "No pages in vault")