obsidian

package
v1.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package obsidian implements the Engram → Obsidian vault export engine. It reads observations from the store and writes structured markdown files with YAML frontmatter, wikilinks, and hub notes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ObservationToMarkdown

func ObservationToMarkdown(obs store.Observation) string

ObservationToMarkdown converts a store.Observation into an Obsidian-compatible markdown string with YAML frontmatter, an H1 title, the content body, and a wikilinks footer section.

func SessionHubMarkdown

func SessionHubMarkdown(sessionID string, obs []ObsRef) string

SessionHubMarkdown generates the markdown content for a session hub note. It lists all observations in the session as wikilinks.

Output path: {vault}/engram/_sessions/{sessionID}.md

func ShouldCreateTopicHub

func ShouldCreateTopicHub(count int) bool

ShouldCreateTopicHub reports whether a topic prefix has enough observations to warrant creating a hub note. The threshold is ≥2 (REQ-EXPORT-05).

func Slugify

func Slugify(title string, id int64) string

Slugify converts an observation title and ID into a filesystem-safe slug. The algorithm:

  1. Lowercase the title
  2. Replace non-alphanumeric characters with hyphens
  3. Trim leading/trailing hyphens
  4. Truncate to 60 chars (trimming trailing hyphens after truncation)
  5. Append the ID for collision safety

If the title is empty, the slug is "observation-{id}".

func TopicHubMarkdown

func TopicHubMarkdown(prefix string, obs []ObsRef) string

TopicHubMarkdown generates the markdown content for a topic cluster hub note. It lists all observations sharing the same topic prefix as wikilinks with type annotations.

Output path: {vault}/engram/_topics/{prefix}.md where prefix uses "--" instead of "/" for filesystem safety.

func WriteGraphConfig

func WriteGraphConfig(vaultPath string, mode GraphConfigMode) error

WriteGraphConfig writes the embedded graph.json default into {vaultPath}/.obsidian/graph.json according to the given mode.

  • preserve: creates the file only when it does not already exist.
  • force: always creates or overwrites the file with the embedded default.
  • skip: no-op; returns nil immediately.

The .obsidian/ directory is created with 0755 permissions if it does not exist (except in skip mode where nothing is written).

func WriteState

func WriteState(path string, s SyncState) error

WriteState persists the sync state as JSON to the given file path. The file is written atomically (overwrite) with 0644 permissions.

Types

type ExportConfig

type ExportConfig struct {
	VaultPath   string          // --vault (required): path to the Obsidian vault root
	Project     string          // --project (optional): filter export to a single project
	Limit       int             // --limit (0 = no limit)
	Since       time.Time       // --since (zero = use state file)
	Force       bool            // --force: ignore state, full re-export
	GraphConfig GraphConfigMode // --graph-config: preserve|force|skip (empty string = skip for backward compat)
}

ExportConfig holds all CLI flags for the obsidian-export command.

type ExportResult

type ExportResult struct {
	Created     int
	Updated     int
	Deleted     int
	Skipped     int
	HubsCreated int
	Errors      []error
}

ExportResult summarizes what happened during an export run.

type Exportable

type Exportable interface {
	// Export performs one export cycle and returns its result.
	Export() (*ExportResult, error)
	// SetGraphConfig overrides the GraphConfig mode for subsequent calls.
	SetGraphConfig(mode GraphConfigMode)
	// GraphConfig returns the current GraphConfig mode.
	GraphConfig() GraphConfigMode
}

Exportable is the interface the Watcher uses to run export cycles. *Exporter satisfies this interface. Fake implementations are used in tests.

type Exporter

type Exporter struct {
	// contains filtered or unexported fields
}

Exporter reads from the store and writes markdown files to a vault.

func NewExporter

func NewExporter(s StoreReader, cfg ExportConfig) *Exporter

NewExporter constructs an Exporter. Validation happens in Export().

func (*Exporter) Export

func (e *Exporter) Export() (*ExportResult, error)

Export performs a full or incremental export from the store to the vault. It returns an ExportResult summarizing what happened.

func (*Exporter) GraphConfig

func (e *Exporter) GraphConfig() GraphConfigMode

GraphConfig returns the current GraphConfig mode.

func (*Exporter) SetGraphConfig

func (e *Exporter) SetGraphConfig(mode GraphConfigMode)

SetGraphConfig sets the GraphConfig mode on this exporter's config. This is used by Watcher to force GraphConfigSkip on subsequent cycles (REQ-WATCH-06).

type GraphConfigMode

type GraphConfigMode string

GraphConfigMode controls how WriteGraphConfig handles an existing graph.json.

const (
	// GraphConfigPreserve writes the default template only if graph.json is absent (default).
	GraphConfigPreserve GraphConfigMode = "preserve"

	// GraphConfigForce always overwrites graph.json with the embedded default.
	GraphConfigForce GraphConfigMode = "force"

	// GraphConfigSkip never reads, writes, or creates graph.json.
	GraphConfigSkip GraphConfigMode = "skip"
)

func ParseGraphConfigMode

func ParseGraphConfigMode(s string) (GraphConfigMode, error)

ParseGraphConfigMode parses s into a GraphConfigMode. Returns an error for any value not in the accepted set {preserve, force, skip}. Parsing is case-sensitive.

type ObsRef

type ObsRef struct {
	Slug     string // filename slug (without .md extension), e.g. "fixed-auth-bug-1"
	Title    string // human-readable title
	TopicKey string // observation's topic_key (may be empty)
	Type     string // observation type (e.g. "bugfix", "architecture")
}

ObsRef is a lightweight reference to an observation for use in hub notes. It carries only the fields needed to build wikilinks and type annotations.

type StoreReader

type StoreReader interface {
	Export() (*store.ExportData, error)
	Stats() *store.Stats
}

StoreReader is the read-only interface the exporter needs. Keeps the dependency narrow — easy to mock in tests.

type SyncState

type SyncState struct {
	LastExportAt string            `json:"last_export_at"`
	Files        map[int64]string  `json:"files"`        // obs ID → relative vault path
	SessionHubs  map[string]string `json:"session_hubs"` // session ID → relative path
	TopicHubs    map[string]string `json:"topic_hubs"`   // topic prefix → relative path
	Version      int               `json:"version"`      // schema version (1)
}

SyncState tracks the state of a previous export run. It is persisted as JSON in {vault}/engram/.engram-sync-state.json.

func ReadState

func ReadState(path string) (SyncState, error)

ReadState reads the sync state from the given JSON file path. If the file does not exist, it returns an empty SyncState and no error.

type Watcher

type Watcher struct {
	// contains filtered or unexported fields
}

Watcher wraps an Exportable and runs it on a fixed interval in a loop.

func NewWatcher

func NewWatcher(cfg WatcherConfig) *Watcher

NewWatcher constructs a Watcher from the given config.

func (*Watcher) Run

func (w *Watcher) Run(ctx context.Context) error

Run executes the watch loop.

Behavior:

  • The first cycle runs immediately (REQ-WATCH-03).
  • Subsequent cycles run after each interval tick.
  • On cycle error: the error is logged and the loop continues (REQ-WATCH-04).
  • The first cycle uses the exporter's current GraphConfig; subsequent cycles force GraphConfigSkip (REQ-WATCH-06).
  • Returns ctx.Err() when the context is canceled or times out (REQ-WATCH-05).

type WatcherConfig

type WatcherConfig struct {
	// Exporter is the export driver. Required.
	Exporter Exportable
	// Interval between cycles. Required.
	Interval time.Duration
	// Logf is the log function. Defaults to log.Printf if nil.
	Logf func(format string, args ...any)
}

WatcherConfig holds constructor parameters for Watcher.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL