ralph-hero-knowledge-index 0.1.11 → 0.1.13

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-knowledge",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Knowledge graph for ralph-hero: semantic search, relationship traversal, and document indexing across thoughts/ documents. Optional companion to ralph-hero.",
5
5
  "author": {
6
6
  "name": "Chad Dubiel",
package/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "ralph-knowledge": {
4
4
  "command": "npx",
5
- "args": ["-y", "ralph-hero-knowledge-index@0.1.11"]
5
+ "args": ["-y", "ralph-hero-knowledge-index@0.1.13"]
6
6
  }
7
7
  }
8
8
  }
@@ -39,6 +39,7 @@ export function writeTypeIndex(outDir, type, heading, docs) {
39
39
  const TYPE_HEADINGS = {
40
40
  research: "Research",
41
41
  plan: "Plans",
42
+ spec: "Specs",
42
43
  idea: "Ideas",
43
44
  review: "Reviews",
44
45
  report: "Reports",
@@ -52,6 +53,18 @@ export function writeIssueHubs(outDir, allDocs) {
52
53
  byIssue.set(doc.githubIssue, list);
53
54
  }
54
55
  }
56
+ // Secondary pass: index into additional hubs from githubIssues array
57
+ for (const doc of allDocs) {
58
+ for (const issueNum of doc.githubIssues) {
59
+ if (issueNum === doc.githubIssue)
60
+ continue; // already added in primary pass
61
+ const list = byIssue.get(issueNum) ?? [];
62
+ if (!list.includes(doc)) {
63
+ list.push(doc);
64
+ byIssue.set(issueNum, list);
65
+ }
66
+ }
67
+ }
55
68
  const issuesDir = join(outDir, "_issues");
56
69
  mkdirSync(issuesDir, { recursive: true });
57
70
  for (const [issueNum, docs] of byIssue) {
@@ -112,6 +125,7 @@ export function writeMasterIndex(outDir, allDocs, hasUncategorized = false) {
112
125
  "## Browse by Type\n",
113
126
  "- [[_research]] — Research documents",
114
127
  "- [[_plans]] — Implementation plans",
128
+ "- [[_specs]] — Specifications",
115
129
  "- [[_ideas]] — Ideas and drafts",
116
130
  "- [[_reviews]] — Code and plan reviews",
117
131
  "- [[_reports]] — Status reports",
@@ -223,6 +237,7 @@ WHERE !contains(rows.type, "plan")
223
237
  const TYPE_INDEX_CONFIG = [
224
238
  { type: "research", filename: "research", heading: "Research Documents" },
225
239
  { type: "plan", filename: "plans", heading: "Implementation Plans" },
240
+ { type: "spec", filename: "specs", heading: "Specifications" },
226
241
  { type: "idea", filename: "ideas", heading: "Ideas & Drafts" },
227
242
  { type: "review", filename: "reviews", heading: "Reviews" },
228
243
  { type: "report", filename: "reports", heading: "Reports" },
@@ -1 +1 @@
1
- {"version":3,"file":"generate-indexes.js","sourceRoot":"","sources":["../src/generate-indexes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-indexes.js","sourceRoot":"","sources":["../src/generate-indexes.ts"],"names":[],"mappings":"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"}
package/dist/parser.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export interface Relationship {
2
2
  sourceId: string;
3
3
  targetId: string;
4
- type: "builds_on" | "tensions" | "superseded_by";
4
+ type: "builds_on" | "tensions" | "superseded_by" | "post_mortem";
5
5
  }
6
6
  export interface ParsedDocument {
7
7
  id: string;
@@ -11,8 +11,10 @@ export interface ParsedDocument {
11
11
  type: string | null;
12
12
  status: string | null;
13
13
  githubIssue: number | null;
14
+ githubIssues: number[];
14
15
  tags: string[];
15
16
  relationships: Relationship[];
16
17
  content: string;
17
18
  }
19
+ export declare function inferTypeFromPath(path: string): string | null;
18
20
  export declare function parseDocument(id: string, path: string, raw: string): ParsedDocument;
package/dist/parser.js CHANGED
@@ -1,8 +1,22 @@
1
1
  import { parse as parseYaml } from "yaml";
2
2
  const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
3
3
  const TITLE_RE = /^# (.+)$/m;
4
- const WIKILINK_REL_RE = /^- (builds_on|tensions):: \[\[(.+?)\]\]/gm;
4
+ const WIKILINK_REL_RE = /^- (builds_on|tensions|post_mortem):: \[\[(.+?)\]\]/gm;
5
5
  const SUPERSEDED_BY_RE = /\[\[(.+?)\]\]/;
6
+ const PATH_TYPE_MAP = [
7
+ { segment: "/research/", type: "research" },
8
+ { segment: "/plans/", type: "plan" },
9
+ { segment: "/ideas/", type: "idea" },
10
+ { segment: "/reviews/", type: "review" },
11
+ { segment: "/reports/", type: "report" },
12
+ ];
13
+ export function inferTypeFromPath(path) {
14
+ for (const { segment, type } of PATH_TYPE_MAP) {
15
+ if (path.includes(segment))
16
+ return type;
17
+ }
18
+ return null;
19
+ }
6
20
  export function parseDocument(id, path, raw) {
7
21
  const fmMatch = raw.match(FRONTMATTER_RE);
8
22
  const frontmatter = fmMatch ? parseYaml(fmMatch[1]) ?? {} : {};
@@ -16,6 +30,8 @@ export function parseDocument(id, path, raw) {
16
30
  relationships.push({
17
31
  sourceId: id,
18
32
  targetId: match[2],
33
+ // Cast is safe: WIKILINK_REL_RE alternation matches exactly these three types.
34
+ // "superseded_by" is intentionally absent — it is parsed from frontmatter, not body wikilinks.
19
35
  type: match[1],
20
36
  });
21
37
  }
@@ -30,7 +46,9 @@ export function parseDocument(id, path, raw) {
30
46
  return {
31
47
  id, path, title,
32
48
  date: frontmatter.date ? String(frontmatter.date) : null,
33
- type: frontmatter.type ?? null,
49
+ type: (typeof frontmatter.type === "string" && frontmatter.type.length > 0)
50
+ ? frontmatter.type
51
+ : inferTypeFromPath(path),
34
52
  status: frontmatter.status ?? null,
35
53
  githubIssue: typeof frontmatter.github_issue === "number"
36
54
  ? frontmatter.github_issue
@@ -39,6 +57,9 @@ export function parseDocument(id, path, raw) {
39
57
  : typeof frontmatter.primary_issue === "number"
40
58
  ? frontmatter.primary_issue
41
59
  : null,
60
+ githubIssues: Array.isArray(frontmatter.github_issues)
61
+ ? frontmatter.github_issues.filter((n) => typeof n === "number")
62
+ : [],
42
63
  tags, relationships, content: body,
43
64
  };
44
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-hero-knowledge-index",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -53,7 +53,9 @@ Check if `[thoughts-dir]/.obsidian/` exists.
53
53
  { "query": "path:_", "color": { "a": 1, "rgb": 8421504 } },
54
54
  { "query": "tag:#research OR type:research", "color": { "a": 1, "rgb": 4474111 } },
55
55
  { "query": "tag:#plan OR type:plan", "color": { "a": 1, "rgb": 4487360 } },
56
- { "query": "tag:#idea OR type:idea", "color": { "a": 1, "rgb": 16761095 } }
56
+ { "query": "tag:#idea OR type:idea", "color": { "a": 1, "rgb": 16761095 } },
57
+ { "query": "type:report", "color": { "a": 1, "rgb": 16744272 } },
58
+ { "query": "type:spec", "color": { "a": 1, "rgb": 12517631 } }
57
59
  ]
58
60
  }
59
61
  ```
@@ -15,6 +15,7 @@ function makeParsedDoc(overrides: Partial<ParsedDocument>): ParsedDocument {
15
15
  type: "research",
16
16
  status: "draft",
17
17
  githubIssue: null,
18
+ githubIssues: [],
18
19
  tags: [],
19
20
  relationships: [],
20
21
  content: "test content",
@@ -241,6 +242,70 @@ describe("generateIndexes", () => {
241
242
  const index = readFileSync(join(dir, "_index.md"), "utf-8");
242
243
  expect(index).not.toContain("[[_uncategorized]]");
243
244
  });
245
+
246
+ it("routes spec docs to _specs.md and not to uncategorized", () => {
247
+ const dir = mkdtempSync(join(tmpdir(), "gen-test-"));
248
+ const docs = [
249
+ makeParsedDoc({ id: "debug-spec", type: "spec", title: "Debug Mode Spec" }),
250
+ makeParsedDoc({ id: "r1", type: "research" }),
251
+ ];
252
+ generateIndexes(dir, docs);
253
+ expect(existsSync(join(dir, "_specs.md"))).toBe(true);
254
+ const specs = readFileSync(join(dir, "_specs.md"), "utf-8");
255
+ expect(specs).toContain("[[debug-spec]]");
256
+ expect(existsSync(join(dir, "_uncategorized.md"))).toBe(false);
257
+ const index = readFileSync(join(dir, "_index.md"), "utf-8");
258
+ expect(index).toContain("[[_specs]]");
259
+ expect(index).not.toContain("[[_uncategorized]]");
260
+ });
261
+ });
262
+
263
+ describe("writeIssueHubs — multi-hub indexing", () => {
264
+ it("indexes a document into all hubs listed in githubIssues", () => {
265
+ const dir = mkdtempSync(join(tmpdir(), "gen-test-"));
266
+ const doc = makeParsedDoc({
267
+ id: "2026-03-19-ralph-team-GH-611-session",
268
+ title: "Team Session Report",
269
+ type: "report",
270
+ githubIssue: 611,
271
+ githubIssues: [611, 612],
272
+ });
273
+ writeIssueHubs(dir, [doc]);
274
+ const hub611 = readFileSync(join(dir, "_issues", "GH-0611.md"), "utf-8");
275
+ const hub612 = readFileSync(join(dir, "_issues", "GH-0612.md"), "utf-8");
276
+ expect(hub611).toContain("[[2026-03-19-ralph-team-GH-611-session]]");
277
+ expect(hub612).toContain("[[2026-03-19-ralph-team-GH-611-session]]");
278
+ });
279
+
280
+ it("does not duplicate document in primary hub when githubIssues includes primary", () => {
281
+ const dir = mkdtempSync(join(tmpdir(), "gen-test-"));
282
+ const doc = makeParsedDoc({
283
+ id: "multi-issue-doc",
284
+ title: "Multi Issue Doc",
285
+ githubIssue: 100,
286
+ githubIssues: [100, 200],
287
+ });
288
+ writeIssueHubs(dir, [doc]);
289
+ const hub100 = readFileSync(join(dir, "_issues", "GH-0100.md"), "utf-8");
290
+ // Should appear exactly once, not twice
291
+ const matches = hub100.match(/\[\[multi-issue-doc\]\]/g) ?? [];
292
+ expect(matches).toHaveLength(1);
293
+ });
294
+
295
+ it("handles document with githubIssues but null githubIssue", () => {
296
+ const dir = mkdtempSync(join(tmpdir(), "gen-test-"));
297
+ const doc = makeParsedDoc({
298
+ id: "array-only-doc",
299
+ title: "Array Only",
300
+ githubIssue: null,
301
+ githubIssues: [300, 301],
302
+ });
303
+ writeIssueHubs(dir, [doc]);
304
+ const hub300 = readFileSync(join(dir, "_issues", "GH-0300.md"), "utf-8");
305
+ const hub301 = readFileSync(join(dir, "_issues", "GH-0301.md"), "utf-8");
306
+ expect(hub300).toContain("[[array-only-doc]]");
307
+ expect(hub301).toContain("[[array-only-doc]]");
308
+ });
244
309
  });
245
310
 
246
311
  describe("findMarkdownFiles", () => {
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { parseDocument } from "../parser.js";
2
+ import { parseDocument, inferTypeFromPath } from "../parser.js";
3
3
 
4
4
  const FULL_DOC = `---
5
5
  date: 2026-03-08
@@ -98,6 +98,41 @@ describe("parseDocument", () => {
98
98
  expect(doc.content).not.toContain("---");
99
99
  });
100
100
 
101
+ it("parses post_mortem relationship from Prior Work", () => {
102
+ const raw = `---
103
+ date: 2026-03-18
104
+ type: plan
105
+ github_issue: 600
106
+ ---
107
+
108
+ # My Plan
109
+
110
+ ## Prior Work
111
+
112
+ - post_mortem:: [[2026-03-19-ralph-team-GH-600-session]]
113
+ `;
114
+ const doc = parseDocument("my-plan", "thoughts/shared/plans/my-plan.md", raw);
115
+ const postMortem = doc.relationships.filter(r => r.type === "post_mortem");
116
+ expect(postMortem).toHaveLength(1);
117
+ expect(postMortem[0].targetId).toBe("2026-03-19-ralph-team-GH-600-session");
118
+ expect(postMortem[0].sourceId).toBe("my-plan");
119
+ });
120
+
121
+ it("does not parse post_mortem from frontmatter superseded_by path", () => {
122
+ // superseded_by is handled separately; post_mortem must come from body inline fields
123
+ const raw = `---
124
+ date: 2026-03-18
125
+ type: plan
126
+ superseded_by: "[[2026-03-19-ralph-team-GH-600-session]]"
127
+ ---
128
+
129
+ # My Plan
130
+ `;
131
+ const doc = parseDocument("my-plan", "thoughts/shared/plans/my-plan.md", raw);
132
+ const postMortem = doc.relationships.filter(r => r.type === "post_mortem");
133
+ expect(postMortem).toHaveLength(0);
134
+ });
135
+
101
136
  describe("githubIssue fallback chain", () => {
102
137
  function makeDoc(frontmatter: string, body = "# Test\n\nContent."): string {
103
138
  return `---\n${frontmatter}\n---\n\n${body}`;
@@ -180,4 +215,108 @@ describe("parseDocument", () => {
180
215
  expect(doc.githubIssue).toBe(550);
181
216
  });
182
217
  });
218
+
219
+ describe("githubIssues array", () => {
220
+ function makeDoc(frontmatter: string, body = "# Test\n\nContent."): string {
221
+ return `---\n${frontmatter}\n---\n\n${body}`;
222
+ }
223
+
224
+ it("populates githubIssues from github_issues array", () => {
225
+ const raw = makeDoc("github_issues: [100, 200, 300]");
226
+ const doc = parseDocument("test", "test.md", raw);
227
+ expect(doc.githubIssues).toEqual([100, 200, 300]);
228
+ });
229
+
230
+ it("filters non-number values from github_issues", () => {
231
+ const raw = makeDoc('github_issues: [100, "bad", 200]');
232
+ const doc = parseDocument("test", "test.md", raw);
233
+ expect(doc.githubIssues).toEqual([100, 200]);
234
+ });
235
+
236
+ it("returns empty array when github_issues is absent", () => {
237
+ const raw = makeDoc("github_issue: 42");
238
+ const doc = parseDocument("test", "test.md", raw);
239
+ expect(doc.githubIssues).toEqual([]);
240
+ });
241
+
242
+ it("returns empty array when github_issues is not an array", () => {
243
+ const raw = makeDoc("github_issues: 42");
244
+ const doc = parseDocument("test", "test.md", raw);
245
+ expect(doc.githubIssues).toEqual([]);
246
+ });
247
+
248
+ it("includes all issues in session post-mortem pattern", () => {
249
+ const raw = makeDoc([
250
+ "github_issue: 611",
251
+ "github_issues: [611, 612]",
252
+ ].join("\n"));
253
+ const doc = parseDocument("test", "test.md", raw);
254
+ expect(doc.githubIssues).toEqual([611, 612]);
255
+ expect(doc.githubIssue).toBe(611); // primary unchanged
256
+ });
257
+ });
258
+ });
259
+
260
+ describe("inferTypeFromPath", () => {
261
+ it("infers plan from /plans/ segment", () => {
262
+ expect(inferTypeFromPath("thoughts/shared/plans/foo.md")).toBe("plan");
263
+ });
264
+
265
+ it("infers research from /research/ segment", () => {
266
+ expect(inferTypeFromPath("thoughts/shared/research/foo.md")).toBe("research");
267
+ });
268
+
269
+ it("infers report from /reports/ segment", () => {
270
+ expect(inferTypeFromPath("thoughts/shared/reports/foo.md")).toBe("report");
271
+ });
272
+
273
+ it("infers idea from /ideas/ segment", () => {
274
+ expect(inferTypeFromPath("thoughts/ideas/foo.md")).toBe("idea");
275
+ });
276
+
277
+ it("returns null for unknown path", () => {
278
+ expect(inferTypeFromPath("thoughts/misc/foo.md")).toBeNull();
279
+ });
280
+ });
281
+
282
+ describe("parseDocument type inference", () => {
283
+ const NO_TYPE_DOC = `---
284
+ date: 2026-03-01
285
+ status: draft
286
+ ---
287
+
288
+ # My Plan
289
+ `;
290
+
291
+ const SPEC_DOC = `---
292
+ date: 2026-02-21
293
+ status: draft
294
+ type: spec
295
+ ---
296
+
297
+ # Debug Mode Spec
298
+ `;
299
+
300
+ it("infers type from path when frontmatter type is absent", () => {
301
+ const doc = parseDocument("my-plan", "thoughts/shared/plans/my-plan.md", NO_TYPE_DOC);
302
+ expect(doc.type).toBe("plan");
303
+ });
304
+
305
+ it("preserves frontmatter type: spec without aliasing", () => {
306
+ const doc = parseDocument("debug-spec", "thoughts/shared/plans/debug-spec.md", SPEC_DOC);
307
+ expect(doc.type).toBe("spec");
308
+ });
309
+
310
+ it("frontmatter type takes priority over path inference", () => {
311
+ // file is in /plans/ but has type: research in frontmatter
312
+ const raw = `---\ndate: 2026-03-01\ntype: research\n---\n\n# Research in plans dir\n`;
313
+ const doc = parseDocument("x", "thoughts/shared/plans/x.md", raw);
314
+ expect(doc.type).toBe("research");
315
+ });
316
+
317
+ it("returns null when path gives no hint and type is absent", () => {
318
+ const raw = `---\ndate: 2026-03-01\n---\n\n# Mystery\n`;
319
+ const doc = parseDocument("x", "thoughts/misc/x.md", raw);
320
+ expect(doc.type).toBeNull();
321
+ });
183
322
  });
@@ -55,6 +55,7 @@ export function writeTypeIndex(
55
55
  const TYPE_HEADINGS: Record<string, string> = {
56
56
  research: "Research",
57
57
  plan: "Plans",
58
+ spec: "Specs",
58
59
  idea: "Ideas",
59
60
  review: "Reviews",
60
61
  report: "Reports",
@@ -70,6 +71,18 @@ export function writeIssueHubs(outDir: string, allDocs: ParsedDocument[]): void
70
71
  }
71
72
  }
72
73
 
74
+ // Secondary pass: index into additional hubs from githubIssues array
75
+ for (const doc of allDocs) {
76
+ for (const issueNum of doc.githubIssues) {
77
+ if (issueNum === doc.githubIssue) continue; // already added in primary pass
78
+ const list = byIssue.get(issueNum) ?? [];
79
+ if (!list.includes(doc)) {
80
+ list.push(doc);
81
+ byIssue.set(issueNum, list);
82
+ }
83
+ }
84
+ }
85
+
73
86
  const issuesDir = join(outDir, "_issues");
74
87
  mkdirSync(issuesDir, { recursive: true });
75
88
 
@@ -138,6 +151,7 @@ export function writeMasterIndex(outDir: string, allDocs: ParsedDocument[], hasU
138
151
  "## Browse by Type\n",
139
152
  "- [[_research]] — Research documents",
140
153
  "- [[_plans]] — Implementation plans",
154
+ "- [[_specs]] — Specifications",
141
155
  "- [[_ideas]] — Ideas and drafts",
142
156
  "- [[_reviews]] — Code and plan reviews",
143
157
  "- [[_reports]] — Status reports",
@@ -254,6 +268,7 @@ WHERE !contains(rows.type, "plan")
254
268
  const TYPE_INDEX_CONFIG: Array<{ type: string; filename: string; heading: string }> = [
255
269
  { type: "research", filename: "research", heading: "Research Documents" },
256
270
  { type: "plan", filename: "plans", heading: "Implementation Plans" },
271
+ { type: "spec", filename: "specs", heading: "Specifications" },
257
272
  { type: "idea", filename: "ideas", heading: "Ideas & Drafts" },
258
273
  { type: "review", filename: "reviews", heading: "Reviews" },
259
274
  { type: "report", filename: "reports", heading: "Reports" },
package/src/parser.ts CHANGED
@@ -3,7 +3,7 @@ import { parse as parseYaml } from "yaml";
3
3
  export interface Relationship {
4
4
  sourceId: string;
5
5
  targetId: string;
6
- type: "builds_on" | "tensions" | "superseded_by";
6
+ type: "builds_on" | "tensions" | "superseded_by" | "post_mortem";
7
7
  }
8
8
 
9
9
  export interface ParsedDocument {
@@ -14,6 +14,7 @@ export interface ParsedDocument {
14
14
  type: string | null;
15
15
  status: string | null;
16
16
  githubIssue: number | null;
17
+ githubIssues: number[];
17
18
  tags: string[];
18
19
  relationships: Relationship[];
19
20
  content: string;
@@ -21,9 +22,24 @@ export interface ParsedDocument {
21
22
 
22
23
  const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
23
24
  const TITLE_RE = /^# (.+)$/m;
24
- const WIKILINK_REL_RE = /^- (builds_on|tensions):: \[\[(.+?)\]\]/gm;
25
+ const WIKILINK_REL_RE = /^- (builds_on|tensions|post_mortem):: \[\[(.+?)\]\]/gm;
25
26
  const SUPERSEDED_BY_RE = /\[\[(.+?)\]\]/;
26
27
 
28
+ const PATH_TYPE_MAP: Array<{ segment: string; type: string }> = [
29
+ { segment: "/research/", type: "research" },
30
+ { segment: "/plans/", type: "plan" },
31
+ { segment: "/ideas/", type: "idea" },
32
+ { segment: "/reviews/", type: "review" },
33
+ { segment: "/reports/", type: "report" },
34
+ ];
35
+
36
+ export function inferTypeFromPath(path: string): string | null {
37
+ for (const { segment, type } of PATH_TYPE_MAP) {
38
+ if (path.includes(segment)) return type;
39
+ }
40
+ return null;
41
+ }
42
+
27
43
  export function parseDocument(id: string, path: string, raw: string): ParsedDocument {
28
44
  const fmMatch = raw.match(FRONTMATTER_RE);
29
45
  const frontmatter = fmMatch ? parseYaml(fmMatch[1]) ?? {} : {};
@@ -38,7 +54,9 @@ export function parseDocument(id: string, path: string, raw: string): ParsedDocu
38
54
  relationships.push({
39
55
  sourceId: id,
40
56
  targetId: match[2],
41
- type: match[1] as "builds_on" | "tensions",
57
+ // Cast is safe: WIKILINK_REL_RE alternation matches exactly these three types.
58
+ // "superseded_by" is intentionally absent — it is parsed from frontmatter, not body wikilinks.
59
+ type: match[1] as "builds_on" | "tensions" | "post_mortem",
42
60
  });
43
61
  }
44
62
 
@@ -55,7 +73,9 @@ export function parseDocument(id: string, path: string, raw: string): ParsedDocu
55
73
  return {
56
74
  id, path, title,
57
75
  date: frontmatter.date ? String(frontmatter.date) : null,
58
- type: frontmatter.type ?? null,
76
+ type: (typeof frontmatter.type === "string" && frontmatter.type.length > 0)
77
+ ? frontmatter.type
78
+ : inferTypeFromPath(path),
59
79
  status: frontmatter.status ?? null,
60
80
  githubIssue: typeof frontmatter.github_issue === "number"
61
81
  ? frontmatter.github_issue
@@ -64,6 +84,9 @@ export function parseDocument(id: string, path: string, raw: string): ParsedDocu
64
84
  : typeof frontmatter.primary_issue === "number"
65
85
  ? frontmatter.primary_issue
66
86
  : null,
87
+ githubIssues: Array.isArray(frontmatter.github_issues)
88
+ ? frontmatter.github_issues.filter((n: unknown) => typeof n === "number")
89
+ : [],
67
90
  tags, relationships, content: body,
68
91
  };
69
92
  }