drafted 1.25.0 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli/drafted.mjs +31 -4
  2. package/package.json +1 -1
package/cli/drafted.mjs CHANGED
@@ -1679,8 +1679,9 @@ program
1679
1679
  // docs/contracts/drafted-skill-sync.md.
1680
1680
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1681
1681
 
1682
- // synthesizeSkillMd builds a self-describing SKILL.md. Drafted stores `content`
1683
- // as the body only (name/description/triggerPatterns are columns), so we prepend
1682
+ // synthesizeSkillMd builds a self-describing SKILL.md. name/description/
1683
+ // triggerPatterns are columns, and `content` may still carry the author's own
1684
+ // frontmatter (merged by splitStoredFrontmatter), so we prepend
1684
1685
  // YAML frontmatter — JSON scalars are valid YAML — for Causeway's projection and
1685
1686
  // Claude's native loader to read.
1686
1687
  // normalizeSetup mirrors the server (server/lib/skill-hash.mjs) — keep in lockstep.
@@ -1690,6 +1691,31 @@ function normalizeSetup(setup) {
1690
1691
  return arr.filter((s) => typeof s === 'string' && s.trim().length > 0);
1691
1692
  }
1692
1693
 
1694
+ // Keys synthesizeSkillMd writes from the skill row's columns. The row is the
1695
+ // authority for these, so a copy of one in the stored content is dropped.
1696
+ const COLUMN_KEYS = new Set(['name', 'description', 'triggerPatterns', 'setup', 'type', 'title', 'tags', 'timestamp']);
1697
+
1698
+ // Content written through fs/MCP keeps the author's frontmatter. Emitting it
1699
+ // as-is after the synthesized block gave every such SKILL.md TWO frontmatter
1700
+ // blocks (56 of 267 live skills on 2026-10-24), and loaders read only the
1701
+ // first, so author keys such as a Causeway `chain:` or `allowed-tools` were
1702
+ // lost on export. Split it: the author's other top-level keys, verbatim, join
1703
+ // the one block; the rest is the body. Line-based so the author's formatting
1704
+ // survives byte for byte; content with no frontmatter is returned unchanged.
1705
+ function splitStoredFrontmatter(content) {
1706
+ const text = content || '';
1707
+ const m = /^---\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/.exec(text);
1708
+ if (!m) return { extra: [], body: text };
1709
+ const extra = [];
1710
+ let keep = false;
1711
+ for (const line of m[1].split(/\r?\n/)) {
1712
+ const key = /^([A-Za-z_][\w.-]*)\s*:/.exec(line);
1713
+ if (key) keep = !COLUMN_KEYS.has(key[1]);
1714
+ if (keep) extra.push(line);
1715
+ }
1716
+ return { extra, body: text.slice(m[0].length) };
1717
+ }
1718
+
1693
1719
  function synthesizeSkillMd(skill) {
1694
1720
  const lines = ['---', `name: ${JSON.stringify(skill.name || skill.slug || '')}`];
1695
1721
  if (skill.description) lines.push(`description: ${JSON.stringify(skill.description)}`);
@@ -1719,8 +1745,9 @@ function synthesizeSkillMd(skill) {
1719
1745
  }
1720
1746
  const ts = skill.updatedAt ? new Date(skill.updatedAt) : null;
1721
1747
  if (ts && !Number.isNaN(ts.getTime())) lines.push(`timestamp: ${JSON.stringify(ts.toISOString())}`);
1722
- lines.push('---', '');
1723
- return lines.join('\n') + (skill.content || '');
1748
+ const { extra, body } = splitStoredFrontmatter(skill.content);
1749
+ lines.push(...extra, '---', '');
1750
+ return lines.join('\n') + body;
1724
1751
  }
1725
1752
 
1726
1753
  // bundleHash is a stable content hash over the bundle (sorted path\0content\0),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.25.0",
3
+ "version": "1.25.1",
4
4
  "description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
5
5
  "type": "module",
6
6
  "bin": {