Skip to content

Fix starter-pack templates showing their frontmatter as raw text in…#246

Merged
inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync
Jun 24, 2026
Merged

Fix starter-pack templates showing their frontmatter as raw text in…#246
inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync

Conversation

@inkeep-oss-sync

Copy link
Copy Markdown
Contributor

Fix starter-pack templates showing their frontmatter as raw text in the editor.

Template files stored two stacked frontmatter blocks: the template's own title and description, then the frontmatter a new document receives. Editors only recognize the first block, so the second one leaked into the document body and showed up as raw --- fences and key: value lines instead of editable properties.

Templates now use a single frontmatter block, with the template's identity under a reserved template: key and the new-document defaults as top-level keys. Creating a document from a template still produces the same frontmatter, with {{date}} and {{user}} substituted as before — including from an agent via write({ document: { template } }). Templates already on disk keep working and convert to the single-block shape the next time they are saved, so there is no migration step. This also fixes one starter template whose description contained an unquoted colon that broke YAML parsing, and adds a guard test so that class of bug cannot ship again.

The template edit dialog is reworked to match: the title field is labeled Title, a dedicated Type field carries the Open Knowledge Format type, and a Default properties editor exposes the rest of the new-document frontmatter as editable key/value rows — so the starter content is now plain markdown instead of a raw frontmatter block. Every document created from any starter template carries a semantic type plus a one-line description summarizing what that kind of document holds, which you then specialize per document.

* fix(open-knowledge): single-block template frontmatter

Template files stored two stacked frontmatter blocks (the template's own
title/description, then the frontmatter a new doc receives). Editors only
recognize the first block, so the second leaked into the rendered body as
raw fences and key/value text instead of editable properties.

Templates now use one frontmatter block: the identity lives under a reserved
template: key, the new-doc defaults are top-level keys, and the body is clean
markdown. A core helper does the compose/decompose in the apply, read, and
write paths; doc-frontmatter is handled as raw text so {{date}} and {{user}}
tokens survive. Legacy two-block templates still read correctly and convert
on the next save, so there is no migration.

Also quotes one starter description with an unquoted colon that broke YAML
parsing, and adds a guard test over every pack so that class of bug cannot
ship again.

* docs(open-knowledge): update OKF conformance comments for single-block templates

The cross-pack OKF rule-2 test already derives the instantiated doc via
instantiateDoc (consumerFrontmatterYaml), so it validates single-block
templates with no logic change. Refresh the now-stale "two-block / block 2"
comments and test name to describe the single-block format.

* fix(open-knowledge): address PR review on template format

- readTemplateMeta: restore an operator-facing diagnostic when a template has
  no title (heuristic for hand-edited malformed YAML), which the previous
  YAML-parse path emitted before delegating to the silent core parser.
- templates-write.test.ts: add a test for the reserved template: key rejection.
- template-format.ts: peelTemplateIdentity now treats a blank line as interior
  to the identity block only when a later line is still indented, matching the
  documented intent; add a test. Document why TemplateIdentity is open-shaped.
- api-extension move handler: use instantiateDoc for consistency with create-page.

* fix(open-knowledge): restore BOM stripping in parseTemplateFile

The deleted extractFrontmatterYaml stripped a leading UTF-8 BOM before
frontmatter detection. parseTemplateFile did not, so a BOM-prefixed template
(some Windows editors add one on re-save) failed FRONTMATTER_RE and silently
lost its identity in the picker. Strip the BOM at the top of parseTemplateFile
so all call sites benefit; add a test.

* feat(open-knowledge): add a Type field to the template dialog

The new-doc `type` (OKF §9 rule 2) was buried in the raw "Starter content"
frontmatter block. Surface it as a dedicated field next to Name/Description:
extracted from the starter-content frontmatter on load, re-injected as the
first frontmatter key on save. The lift/inject is text-level so {{date}} and
{{user}} tokens in sibling values survive. Editing an older template with no
type lets the author add one. Adds helper + round-trip tests.

* feat(open-knowledge): template dialog — Title label + Default properties editor

- Relabel the title field "Name" -> "Title" (it writes frontmatter `title`,
  and the dialog already has a separate Filename field).
- Lift the whole doc-frontmatter out of the raw "Starter content" block into
  editable key/value rows ("Default properties"); Type keeps its dedicated
  field; Starter content is now pure markdown. Parse/compose is text-level so
  value shapes ([], flow lists) and {{date}}/{{user}} tokens round-trip intact.
- Replace the type-only helpers with parseDocBody/composeDocBody + tests.

* docs(open-knowledge): update template docs to the single-block format

The Folders and templates page taught the old two-block template format (a
stacked second frontmatter block for the new doc's properties). Rewrite it for
the single-block format: identity under a reserved template: key, top-level
keys are the new-doc properties, and point at the dialog's Type + Default
properties fields. Note legacy two-block templates still read + self-migrate.

* docs(open-knowledge): clarify the write-verb template content description

Tighten TEMPLATE_CONTENT_DESCRIBE so agents understand the single-block model:
a leading frontmatter block in the starter content sets the new doc's starting
properties (type/status/tags), while the template's own picker identity is the
separate `frontmatter` field (stripped at instantiation). Notes that on disk it
composes to one block with identity under a reserved `template:` key.

* fix(open-knowledge): write_document(template) must instantiate single-block templates

The MCP write({ document: { template } }) path stripped the whole frontmatter
block (stripFrontmatter), which for a single-block template dropped the
doc-frontmatter (type/status/tags) from every created doc. Use instantiateDoc
like the create-page API, so the new doc keeps its starting properties. Legacy
two-block templates are unaffected; {{date}}/{{user}} still substitute.

* test(open-knowledge): regression for write_document(template) single-block instantiation

* docs(open-knowledge): fix stale two-block comment in starter.ts

* test(open-knowledge): fix md-audit tag-orphan (move prose above @Covers tags)

* fix(open-knowledge): guard composeDocBody against duplicate type key + add property-editor tests

- composeDocBody now skips a property row keyed `type` (the dedicated Type
  field owns it), preventing a duplicate `type:` YAML key.
- Add DOM interaction tests for the Default properties editor (seed rows,
  Add property, Remove property, value editing) and a unit test for the guard.

Addresses the two pending PR-review recommendations.

* docs(open-knowledge): expand changeset to cover the template dialog rework

* feat(open-knowledge): give every starter template a default description

All 35 templates across all 7 starter packs now carry a top-level
description in their created-doc frontmatter, a one-line summary of what
that kind of document holds. A template default is necessarily the same
for every doc of its type, so it reads as 'what this document is' and the
author specializes it per document. Values are double-quoted to stay
valid YAML where the summary contains a colon. Verified by the OKF
conformance and seed-frontmatter guard tests.

GitOrigin-RevId: ac00c6706db28d16366be5faf655f9e6e2778626

@inkeep-internal-ci inkeep-internal-ci Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval from agents-private public-mirror-sync (run: https://github.com/inkeep/agents-private/actions/runs/28077960432). Source of truth is the monorepo; direct edits on inkeep/open-knowledge are overwritten on next sync.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@inkeep-oss-sync inkeep-oss-sync Bot merged commit a21c46b into main Jun 24, 2026
2 checks passed
@inkeep-oss-sync inkeep-oss-sync Bot deleted the copybara/sync branch June 24, 2026 05:47
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