UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

68 lines (67 loc) • 2.77 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /** * Deterministic frontmatter lint for `lesson` assets (v1 spec §13). * * The contract is fixed: * * - Required: `description` — a non-empty single-line string describing * what the lesson teaches. * - Required: `when_to_use` — a non-empty single-line string describing * the trigger that should make a caller apply the lesson. * * Lint produces structured findings rather than throwing so callers can * batch-validate (e.g. `akm proposal accept` over a queue) and surface every * violation in a single pass. * * The lint is intentionally side-effect free and does not import the indexer * or filesystem walker; it operates on a single file path + raw string. This * lets it run from any code path (CLI, proposal-accept, asset-spec tests) * without dragging in the rest of the runtime. */ import { parseFrontmatter } from "./asset/frontmatter.js"; function isNonEmptyString(value) { return typeof value === "string" && value.trim().length > 0; } /** * Lint a lesson given its raw markdown source. * * `pathForMessages` is woven into every finding's message so callers can * surface the offending file in CLI/proposal flows without having to map * findings back to paths separately. */ export function lintLessonContent(raw, pathForMessages) { const findings = []; const parsed = parseFrontmatter(raw); const fm = parsed.data; if (!("description" in fm)) { findings.push({ kind: "missing-description", field: "description", message: `Lesson at ${pathForMessages} is missing required frontmatter field \`description\`.`, }); } else if (!isNonEmptyString(fm.description)) { findings.push({ kind: "empty-description", field: "description", message: `Lesson at ${pathForMessages} has an empty \`description\` frontmatter field; it must be a non-empty single-line string.`, }); } if (!("when_to_use" in fm)) { findings.push({ kind: "missing-when_to_use", field: "when_to_use", message: `Lesson at ${pathForMessages} is missing required frontmatter field \`when_to_use\`.`, }); } else if (!isNonEmptyString(fm.when_to_use)) { findings.push({ kind: "empty-when_to_use", field: "when_to_use", message: `Lesson at ${pathForMessages} has an empty \`when_to_use\` frontmatter field; it must be a non-empty single-line string.`, }); } return { path: pathForMessages, findings }; }