Skip to content

v0.7.0

Latest

Choose a tag to compare

@github-actions github-actions released this 20 Jul 19:48
· 10 commits to master since this release
fdefbb2

Concepts can now carry relations. An opt-in ingest pass extracts them, packs ship the
resulting graph, and queries follow it. Alongside that: synto find, three new trace
subcommands, and alias-level concept curation. Most of the smaller work here — alias
management, advisory acks, and the Unicode and code-fence fixes — came out of
@VibeSan7's report from a real-world setup (#94).

Existing vaults migrate to schema v29 automatically on first run.

Added

  • Concept relation extraction, opt-in (#109). A third fast-model pass during ingest
    extracts directed relations between known concepts ("Raft depends_on Consensus") into
    new relations/relation_evidence tables, each with a verbatim evidence
    quote. Endpoints are restricted to known concepts and their aliases — relations the
    model invents never enter the graph, though every raw candidate is kept in
    relation_candidates as an audit trail. Compiled articles surface their top 10
    relations in a relations: frontmatter block. Off by default, since it adds one LLM
    call per chunk; enable with relation_extraction = true under [pipeline]. Relations
    from a removed source are not garbage-collected yet.

  • Concept graph in packs, and graph-aware queries (#109). Packs now include
    graph/graph.json (nodes = concepts, edges = relations) and a graph capability in
    the manifest whenever relations exist; every edge endpoint resolves to a node, so
    consumers can assume a closed graph. synto query and the MCP answer_question tool
    pull in up to 2 related articles via 1-hop expansion (confidence ≥ 0.7) — a no-op on
    vaults without relations.

  • synto find <query> (#109). Reverse lookup over the wiki, ranked: concept
    name/alias match first, then title match, then first-paragraph body match.

  • synto trace term|relation|citation (#109). Trace where a term occurs, the
    verbatim evidence behind an extracted relation, or which articles consumed a source
    segment. Extends the existing trace article.

  • synto concept alias add|remove|move (#101). The fast model sometimes attaches a
    surface to the wrong entity (an npm package name landing as a project alias), with no
    CLI remedy short of a merge. remove detaches the alias and records a denial tombstone
    so the next ingest can't silently re-attach it; move re-points it to the right entity
    in one step. Both un-rewrite the [[Canonical|Alias]] links the wrong alias had
    produced, and denials survive a state.db rebuild via the .synto/INDEX.json seed.

  • synto maintain can acknowledge known advisories (#102). Long-running vaults carry
    advisories that are true by construction (e.g. graph_noise), which clutter the output
    and hide new issues. [maintain] ack = ["graph_noise"] in synto.toml collapses them
    into a one-line count; scope one to a single file with
    "graph_noise:wiki/Some Note.md". Acks are display-only — the health score and
    advisory count are unchanged.

Fixed

  • Article filenames are Windows-safe, with automatic drift repair (#107). A title
    like NUL or Foo. produced a file Windows cannot create or round-trip, breaking
    vault sync. sanitize_filename now de-reserves device names and strips trailing
    dots/control chars; files named by the old rules are reported as filename_drift
    and maintain --fix renames them and repoints inbound links.

  • CI now tests Python 3.14 (#107). Ubuntu runs the full suite on 3.11/3.12/3.14;
    the Windows job runs the path-portability subset — widened to cover these changes —
    on 3.11 and 3.14. The reporter's Windows + Python 3.14 environment was previously
    untested anywhere; making the full suite Windows-clean is tracked in #108.

  • missing_media, inline_tag, and orphan-mention scans skip code regions (#106).
    Example embeds, #include-style directives, and titles inside code fences or inline
    code were reported as advisories on code-heavy vaults. All three now mask code first
    (like the #96 scanners), and the inline-tag regex accepts any-script letters so real
    non-Latin tags are finally reported.

  • Tags in any script survive sanitization and maintain --fix (#105). Tag rules
    stripped every non-ASCII character, so on non-English vaults LLM-proposed tags were
    silently dropped and --fix deleted valid Unicode tags (каталог, 日本語, café)
    from frontmatter. Rules are now script-agnostic and idempotent (NFC + lowercase
    before filtering); ASCII tags behave exactly as before. Decomposed (NFD, macOS-style)
    tags are normalized to NFC — a one-time frontmatter rewrite under --fix that then
    converges.

  • Name matching folds non-ASCII case (#105). SQLite's lower() folds ASCII only, so
    the rename collision check and the concept-lookup substring fallback missed non-ASCII
    case variants (e.g. Привет vs привет). Both now compare via Python casefold();
    remaining legacy lower() sites are tracked in #104.

  • StateDB._tx() now opens a real transaction at depth 0 (#100). sqlite3's legacy
    isolation mode only implicit-BEGINs before DML, so a nested _tx()'s SAVEPOINT issued
    before any outer write silently became the outermost transaction and committed early —
    a failed query --synthesize file write could leave a phantom DB row that blocked
    re-synthesizing that question, and migration hooks documented as atomic were not.
    Depth-0 frames now BEGIN explicitly, making nesting and DDL frames atomic as documented.

Full Changelog: v0.6.3...v0.7.0