openalmanac 0.2.3 → 0.2.5

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.
@@ -5,6 +5,85 @@ import { stringify as yamlStringify } from "yaml";
5
5
  import { request, ARTICLES_DIR } from "../auth.js";
6
6
  import { validateArticle, parseFrontmatter } from "../validate.js";
7
7
  const SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
8
+ const WRITING_GUIDE = `
9
+ ## Article structure
10
+
11
+ \`\`\`yaml
12
+ ---
13
+ article_id: the-slug
14
+ title: Article Title
15
+ sources:
16
+ - url: https://example.com
17
+ title: Source Title
18
+ infobox:
19
+ header:
20
+ image_url: https://... # optional hero image
21
+ subtitle: Short tagline
22
+ details:
23
+ - key: Born
24
+ value: January 1, 1990
25
+ - key: Occupation
26
+ value: Scientist
27
+ links:
28
+ - label: Official site
29
+ url: https://...
30
+ sections:
31
+ - type: timeline # chronological events
32
+ title: Career Timeline
33
+ items:
34
+ - primary: "2010"
35
+ value: Started company
36
+ - type: list # bullet list
37
+ title: Known For
38
+ items:
39
+ - value: First achievement
40
+ - value: Second achievement
41
+ - type: tags # inline tags/chips
42
+ title: Genres
43
+ items:
44
+ - value: Rock
45
+ - value: Jazz
46
+ - type: grid # image grid
47
+ title: Gallery
48
+ items:
49
+ - image_url: https://...
50
+ value: Caption
51
+ - type: table # rows with label+value
52
+ title: Statistics
53
+ items:
54
+ - label: Height
55
+ value: "6'2\\""
56
+ - type: key_value # simple key-value pairs
57
+ title: Quick Facts
58
+ items:
59
+ - key: Population
60
+ value: "1.4 billion"
61
+ ---
62
+
63
+ Article body with [1] citation markers...
64
+ \`\`\`
65
+
66
+ ## Infobox
67
+
68
+ Include an infobox for any article about a person, place, organization, event, or concept. Pick the section types that fit — you don't need all six.
69
+
70
+ ## Citations
71
+
72
+ - Mark claims with [N] after punctuation: "The population is 1.4 billion.[1]"
73
+ - Number sequentially starting at [1]
74
+ - Every source in the sources list must be referenced at least once in the body
75
+ - Every [N] marker must have a matching source
76
+
77
+ ## Writing quality
78
+
79
+ - Every sentence should contain a specific fact the reader didn't know
80
+ - No filler phrases ("It is worth noting", "In today's world", "Throughout history")
81
+ - No promotional language ("revolutionary", "groundbreaking", "game-changing")
82
+ - No inflated significance ("one of the most important", "changed the world forever")
83
+ - No vague attribution ("many experts say", "it is widely regarded")
84
+ - No formulaic conclusions ("In conclusion", "continues to shape")
85
+ - Write like a concise encyclopedia, not a blog post
86
+ `.trim();
8
87
  function ensureArticlesDir() {
9
88
  mkdirSync(ARTICLES_DIR, { recursive: true });
10
89
  }
@@ -27,7 +106,8 @@ export function registerArticleTools(server) {
27
106
  server.addTool({
28
107
  name: "pull",
29
108
  description: "Download an article from OpenAlmanac to your local working directory (~/.openalmanac/articles/). " +
30
- "The file is saved as {slug}.md with YAML frontmatter. Edit the file locally, then use push to publish changes.",
109
+ "The file is saved as {slug}.md with YAML frontmatter. Returns a writing guide covering article structure, infobox format, citations, and quality rules. " +
110
+ "Edit the file locally, then use push to publish changes.",
31
111
  parameters: z.object({
32
112
  slug: z.string().describe("Article slug (e.g. 'machine-learning')"),
33
113
  }),
@@ -42,13 +122,14 @@ export function registerArticleTools(server) {
42
122
  const { frontmatter, content } = parseFrontmatter(markdown);
43
123
  const title = frontmatter.title || "(untitled)";
44
124
  const wordCount = content.trim().split(/\s+/).filter(Boolean).length;
45
- return `Pulled "${title}" to ${filePath}\n${wordCount} words, ${frontmatter.sources?.length ?? 0} sources.\nEdit the file, then use push to publish.`;
125
+ return `Pulled "${title}" to ${filePath}\n${wordCount} words, ${frontmatter.sources?.length ?? 0} sources.\n\n${WRITING_GUIDE}`;
46
126
  },
47
127
  });
48
128
  server.addTool({
49
129
  name: "new",
50
130
  description: "Create a new article scaffold in your local working directory (~/.openalmanac/articles/). " +
51
- "The file is created with YAML frontmatter and an empty body. Edit the file to add content and sources, then use push to publish.",
131
+ "The file is created with YAML frontmatter and an empty body. Returns a writing guide covering article structure, infobox format, citations, and quality rules. " +
132
+ "Edit the file to add content and sources, then use push to publish.",
52
133
  parameters: z.object({
53
134
  slug: z
54
135
  .string()
@@ -67,7 +148,7 @@ export function registerArticleTools(server) {
67
148
  const frontmatter = yamlStringify({ article_id: slug, title, sources: [] });
68
149
  const scaffold = `---\n${frontmatter}---\n\n`;
69
150
  writeFileSync(filePath, scaffold, "utf-8");
70
- return `Created ${filePath}\nEdit the file to add content and sources, then use push to publish.`;
151
+ return `Created ${filePath}\n\n${WRITING_GUIDE}`;
71
152
  },
72
153
  });
73
154
  server.addTool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openalmanac",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "OpenAlmanac — pull, edit, and push articles to the open knowledge base",
5
5
  "type": "module",
6
6
  "bin": {