Frontmatter Model
Canonical contract lives in internal/model/document.go. Do not change without agreement — scan/parse/query/search/tui/output all depend on it.
type FormatKind string // FormatOKF, FormatPortent, FormatGeneric, FormatNonetype Document struct { Path, Title, DocType, Description, Resource, Role string // Role: ""|index|log Tags []string Body string CreatedAt, UpdatedAt *time.Time Status string Organized, Archived *bool BelongsTo, RelatedTo []string Sources []Source Generated, Verified *Attestation Format FormatKind Raw map[string]any SearchBlob string ParseError error}Family detection (internal/parse)
Section titled “Family detection (internal/parse)”- Portent/Tolaria
type:Task|Project|Operation|Responsibility|Event|Note|Topic|Person, or bareorganized/archivedkeys →portent. - Any other
type→okf(covers OKF v0.1type+timestampand v0.2generated.at,verified{by,at},sources[{id,resource,title,author}],description). - Frontmatter without
type→generic. No frontmatter →none.
Normalization
Section titled “Normalization”- Title:
title→ else first# H1→ else filename without extension. - Type: verbatim
type, matching folds case. - Tags: YAML list | single string | comma string;
[[wikilink]]markers stripped. - Dates:
CreatedAt← first ofcreated,date,timestamp,generated.at;UpdatedAt← first ofgenerated.at,timestamp,last_modified,updated,modified. Layouts: RFC3339,2006-01-02,2006-01,2006-01-02T15:04:05(+15:04:05space variant), unix timestamps. - Lifecycle:
statuslowercased;organized/archivedcoerced from bool/string/number.IsArchived()=archived:trueorstatus:archived. - Relationships:
belongs_to/belongs-to→BelongsTo,related_to/related-to→RelatedTo(string or list, wikilinks stripped);resource;sources[];generated/verified {by,at}.index.md/log.mdbasenames setRole: index|log(deprioritized in ranking, never dropped). - SearchBlob:
title + description + tags + flattened scalars of Raw + body(BuildSearchBlob,FlattenScalarssorted-key, recursion into nested maps/lists, keys/nils skipped). Stored as-is; lowercased at match time. - Resilience: only a leading
---block counts (SplitFrontmatter); malformed YAML never fails hard — recorded onDocument.ParseError, file stays searchable via filename/H1 + body (testdata/bad-yaml.md).
See also: Query Syntax for how these fields are filtered, and Search & Ranking for how SearchBlob is scored.