@warpgogol/forge 2.8.1 → 2.8.2

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 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../os/session/handlers/validate.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAML,KAAK,uBAAuB,EAE7B,MAAM,aAAa,CAAC;AAgBrB,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,CAAC,CAuKtD"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../os/session/handlers/validate.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAML,KAAK,uBAAuB,EAE7B,MAAM,aAAa,CAAC;AAgBrB,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,CAAC,CA8LtD"}
@@ -3,7 +3,8 @@
3
3
  <purpose>
4
4
  session.validate handler — checks session frontmatter schema (SES-01),
5
5
  id-filename match (SES-02), RFC-id existence (SES-03), raw file hygiene
6
- (SES-04), and non-markdown file detection (SES-05).
6
+ (SES-04), non-markdown file detection (SES-05), and missing checkpoint
7
+ fields in implementation/mission sessions (SES-06, RFC-0884).
7
8
  </purpose>
8
9
  <non-goals>
9
10
  <item>Does not move or modify files — that is session.archive.</item>
@@ -12,6 +13,7 @@ id-filename match (SES-02), RFC-id existence (SES-03), raw file hygiene
12
13
  </MODULE_CONTRACT>
13
14
  <CHANGE_SUMMARY>
14
15
  <item>RFC-0537: implement session.validate command handler.</item>
16
+ <item>RFC-0884: add SES-06 warning for missing checkpoint fields in implementation/mission sessions.</item>
15
17
  </CHANGE_SUMMARY>
16
18
  */
17
19
  import path from "node:path";
@@ -76,7 +78,9 @@ export async function runSessionValidate(input, context) {
76
78
  }
77
79
  }
78
80
  // SES-01: Check types is a valid array
81
+ // typesArray is also used by SES-06 below — hoisted here to make the coupling explicit.
79
82
  const typesValue = fm["types"];
83
+ const typesArray = Array.isArray(typesValue) ? typesValue : [];
80
84
  if (Array.isArray(typesValue)) {
81
85
  for (const t of typesValue) {
82
86
  if (!SESSION_TYPES.includes(t)) {
@@ -129,6 +133,24 @@ export async function runSessionValidate(input, context) {
129
133
  });
130
134
  }
131
135
  }
136
+ // SES-06: Missing checkpoint fields in implementation/mission sessions
137
+ // typesArray is extracted by SES-01 above.
138
+ const isImplOrMission = typesArray.includes("implementation") || typesArray.includes("mission");
139
+ if (isImplOrMission) {
140
+ const hasCheckpointFields = "systemDelta" in fm ||
141
+ "diagrams" in fm ||
142
+ "evidence" in fm ||
143
+ "remainingIssues" in fm ||
144
+ "checkpoint" in fm;
145
+ if (!hasCheckpointFields) {
146
+ violations.push({
147
+ rule: SES_RULES.SES_06,
148
+ file: relFile,
149
+ message: "Implementation/mission session missing checkpoint frontmatter fields (systemDelta, diagrams, evidence, remainingIssues, checkpoint). Agent should populate these during fo-session-save.",
150
+ severity: "warning",
151
+ });
152
+ }
153
+ }
132
154
  }
133
155
  // SES-04: Raw files in .raw/ that haven't been processed (warning)
134
156
  const rawFiles = await listRawFiles(sessionDirPath);
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../os/session/handlers/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../os/session/handlers/validate.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ export declare const SESSION_ID_PATTERN: RegExp;
5
5
  export declare const SESSION_FILE_PATTERN: RegExp;
6
6
  export declare const SESSION_TYPES: readonly ["mission", "grilling", "implementation", "review", "fix", "freeform"];
7
7
  export type SessionType = (typeof SESSION_TYPES)[number];
8
- export declare const SESSION_KNOWN_KEYS: readonly ["id", "date", "duration", "types", "summary", "relatedRfcs", "relatedArtifacts", "decisions", "commits", "files", "commands"];
8
+ export declare const SESSION_KNOWN_KEYS: readonly ["id", "date", "duration", "types", "summary", "relatedRfcs", "relatedArtifacts", "decisions", "commits", "files", "commands", "systemDelta", "diagrams", "evidence", "remainingIssues", "checkpoint"];
9
9
  export declare const SESSION_REQUIRED_KEYS: readonly ["id", "date", "types"];
10
10
  export declare const SESSION_REQUIRED_SECTIONS: readonly ["## Transcript"];
11
11
  export declare const SES_RULES: {
@@ -14,8 +14,33 @@ export declare const SES_RULES: {
14
14
  readonly SES_03: "SES-03";
15
15
  readonly SES_04: "SES-04";
16
16
  readonly SES_05: "SES-05";
17
+ readonly SES_06: "SES-06";
17
18
  };
18
19
  export type SesRule = (typeof SES_RULES)[keyof typeof SES_RULES];
20
+ export interface SessionCheckpoint {
21
+ before: string;
22
+ change: string;
23
+ after: string;
24
+ }
25
+ export interface SessionDiagram {
26
+ type: "flowchart" | "sequenceDiagram" | "stateDiagram-v2" | "erDiagram" | "none";
27
+ scope: "current-system" | "session-delta";
28
+ caption: string;
29
+ mermaid: string;
30
+ }
31
+ export interface SessionEvidenceEntry {
32
+ claim: string;
33
+ source?: string;
34
+ test?: string;
35
+ command?: string;
36
+ }
37
+ export interface SessionSystemDelta {
38
+ changedContracts: string[];
39
+ changedSchemas: string[];
40
+ changedStateMachines: string[];
41
+ changedInvariants: string[];
42
+ changedPersistence: string[];
43
+ }
19
44
  export interface SessionFrontmatter {
20
45
  id: string;
21
46
  date: string;
@@ -28,6 +53,11 @@ export interface SessionFrontmatter {
28
53
  commits: string[];
29
54
  files: string[];
30
55
  commands: string[];
56
+ systemDelta?: SessionSystemDelta;
57
+ diagrams?: SessionDiagram[];
58
+ evidence?: SessionEvidenceEntry[];
59
+ remainingIssues?: string[];
60
+ checkpoint?: SessionCheckpoint;
31
61
  }
32
62
  export interface SessionSaveResult {
33
63
  command: "session.save";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../os/session/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../os/session/types.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ validation rule identifiers.
11
11
  </MODULE_CONTRACT>
12
12
  <CHANGE_SUMMARY>
13
13
  <item>RFC-0537: initial session domain types, constants, and SES rule identifiers.</item>
14
+ <item>RFC-0884: add checkpoint interfaces, extend SessionFrontmatter with optional checkpoint fields, add SES-06 rule.</item>
14
15
  </CHANGE_SUMMARY>
15
16
  */
16
17
  export const SESSION_DIR = "docs/sessions";
@@ -38,6 +39,11 @@ export const SESSION_KNOWN_KEYS = [
38
39
  "commits",
39
40
  "files",
40
41
  "commands",
42
+ "systemDelta",
43
+ "diagrams",
44
+ "evidence",
45
+ "remainingIssues",
46
+ "checkpoint",
41
47
  ];
42
48
  export const SESSION_REQUIRED_KEYS = ["id", "date", "types"];
43
49
  export const SESSION_REQUIRED_SECTIONS = ["## Transcript"];
@@ -48,5 +54,6 @@ export const SES_RULES = {
48
54
  SES_03: "SES-03",
49
55
  SES_04: "SES-04",
50
56
  SES_05: "SES-05",
57
+ SES_06: "SES-06",
51
58
  };
52
59
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../os/session/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;EAcE;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,kBAAkB,GAAG,mDAAmD,CAAC;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,uDAAuD,CAAC;AAE5F,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS;IACT,UAAU;IACV,gBAAgB;IAChB,QAAQ;IACR,KAAK;IACL,UAAU;CACF,CAAC;AAIX,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI;IACJ,MAAM;IACN,UAAU;IACV,OAAO;IACP,SAAS;IACT,aAAa;IACb,kBAAkB;IAClB,WAAW;IACX,SAAS;IACT,OAAO;IACP,UAAU;CACF,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAEtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,eAAe,CAAU,CAAC;AAEpE,uBAAuB;AACvB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../os/session/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;EAeE;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,kBAAkB,GAAG,mDAAmD,CAAC;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,uDAAuD,CAAC;AAE5F,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS;IACT,UAAU;IACV,gBAAgB;IAChB,QAAQ;IACR,KAAK;IACL,UAAU;CACF,CAAC;AAIX,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI;IACJ,MAAM;IACN,UAAU;IACV,OAAO;IACP,SAAS;IACT,aAAa;IACb,kBAAkB;IAClB,WAAW;IACX,SAAS;IACT,OAAO;IACP,UAAU;IACV,aAAa;IACb,UAAU;IACV,UAAU;IACV,iBAAiB;IACjB,YAAY;CACJ,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAEtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,eAAe,CAAU,CAAC;AAEpE,uBAAuB;AACvB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warpgogol/forge",
3
- "version": "2.8.1",
3
+ "version": "2.8.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { resolveTerminology, defaultForgeConfig, type ForgeConfig } from "../forge-config.ts";
3
+ import { TERMINOLOGY_DEFAULTS } from "../../profiles/profile-schema.ts";
4
+
5
+ describe("resolveTerminology", () => {
6
+ function makeConfig(terminology?: Record<string, string>): ForgeConfig {
7
+ const config = defaultForgeConfig("test");
8
+ if (terminology && config.bindings) {
9
+ config.bindings.terminology = terminology;
10
+ }
11
+ return config;
12
+ }
13
+
14
+ it("returns universal default when no overrides exist", () => {
15
+ const config = makeConfig();
16
+ expect(resolveTerminology(config, undefined, "artifact")).toBe(TERMINOLOGY_DEFAULTS.artifact);
17
+ expect(resolveTerminology(config, undefined, "operator")).toBe(TERMINOLOGY_DEFAULTS.operator);
18
+ });
19
+
20
+ it("returns the key itself when not found in any tier", () => {
21
+ const config = makeConfig();
22
+ expect(resolveTerminology(config, undefined, "nonexistent")).toBe("nonexistent");
23
+ });
24
+
25
+ it("tier 1: per-project bindings.terminology overrides everything", () => {
26
+ const config = makeConfig({ artifact: "widget" });
27
+ expect(resolveTerminology(config, { artifact: "module" }, "artifact")).toBe("widget");
28
+ });
29
+
30
+ it("tier 2: caller-provided terminology overrides universal default", () => {
31
+ const config = makeConfig();
32
+ expect(resolveTerminology(config, { artifact: "custom" }, "artifact")).toBe("custom");
33
+ });
34
+
35
+ it("tier 3: universal default used when tiers 1 and 2 are absent", () => {
36
+ const config = makeConfig();
37
+ expect(resolveTerminology(config, undefined, "module")).toBe(TERMINOLOGY_DEFAULTS.module);
38
+ });
39
+
40
+ it("handles undefined bindings entirely", () => {
41
+ const config = defaultForgeConfig("test");
42
+ delete config.bindings;
43
+ expect(resolveTerminology(config, { artifact: "thing" }, "artifact")).toBe("thing");
44
+ });
45
+ });
@@ -0,0 +1,219 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { normalizeTitle, detectDuplicatePrinciples, planPromotion } from "../promote.ts";
3
+ import type {
4
+ ParsedKnowledgeFile,
5
+ KnowledgeEntry,
6
+ KnowledgeEntryMeta,
7
+ ParseIssue,
8
+ } from "../schema.ts";
9
+
10
+ function makeMeta(overrides: Partial<KnowledgeEntryMeta> = {}): KnowledgeEntryMeta {
11
+ return {
12
+ id: "K-0001",
13
+ layer: "L1",
14
+ created: "2026-01-01",
15
+ lastConfirmedAt: "2026-01-01",
16
+ confirmations: 1,
17
+ status: "active",
18
+ ...overrides,
19
+ };
20
+ }
21
+
22
+ function makeEntry(title: string, meta?: Partial<KnowledgeEntryMeta>): KnowledgeEntry {
23
+ return { meta: makeMeta(meta), title, body: "", lineStart: 0 };
24
+ }
25
+
26
+ function makeParsedFile(entries: KnowledgeEntry[], issues: ParseIssue[] = []): ParsedKnowledgeFile {
27
+ return {
28
+ path: "qa-log.md",
29
+ layer: "L1",
30
+ preamble: "",
31
+ entries,
32
+ legacySections: [],
33
+ isKnowledgeAdjacent: false,
34
+ parseIssues: issues,
35
+ };
36
+ }
37
+
38
+ describe("normalizeTitle", () => {
39
+ it("lowercases and removes punctuation", () => {
40
+ expect(normalizeTitle("Hello, World!")).toBe("hello world");
41
+ });
42
+
43
+ it("strips stop words", () => {
44
+ expect(normalizeTitle("The Quick Brown Fox")).toBe("quick brown fox");
45
+ expect(normalizeTitle("A Cat on a Mat")).toBe("cat on mat");
46
+ });
47
+
48
+ it("collapses whitespace", () => {
49
+ expect(normalizeTitle(" Multiple Spaces ")).toBe("multiple spaces");
50
+ });
51
+
52
+ it("handles unicode letters", () => {
53
+ expect(normalizeTitle("Übergröße Straße")).toBe("übergröße straße");
54
+ });
55
+
56
+ it("returns empty for all-stop-word input", () => {
57
+ expect(normalizeTitle("the a an")).toBe("");
58
+ });
59
+ });
60
+
61
+ describe("detectDuplicatePrinciples", () => {
62
+ it("detects exact title matches across skills", () => {
63
+ const files = [
64
+ { skill: "skill-a", parsed: makeParsedFile([makeEntry("Always Check Types")]) },
65
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Always Check Types")]) },
66
+ ];
67
+ const dupes = detectDuplicatePrinciples(files);
68
+ expect(dupes).toHaveLength(1);
69
+ expect(dupes[0].kind).toBe("exact");
70
+ });
71
+
72
+ it("skips stale and archived entries", () => {
73
+ const files = [
74
+ {
75
+ skill: "skill-a",
76
+ parsed: makeParsedFile([makeEntry("Same Title", { id: "K-0001", status: "stale" })]),
77
+ },
78
+ {
79
+ skill: "skill-b",
80
+ parsed: makeParsedFile([makeEntry("Same Title", { id: "K-0002", status: "archived" })]),
81
+ },
82
+ ];
83
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
84
+ });
85
+
86
+ it("skips already-promoted entries", () => {
87
+ const files = [
88
+ {
89
+ skill: "skill-a",
90
+ parsed: makeParsedFile([makeEntry("Title", { id: "K-0001", promotedTo: "shared/K-0002" })]),
91
+ },
92
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Title", { id: "K-0002" })]) },
93
+ ];
94
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
95
+ });
96
+
97
+ it("skips linked pairs via supersedes", () => {
98
+ const files = [
99
+ {
100
+ skill: "skill-a",
101
+ parsed: makeParsedFile([makeEntry("Same Title", { supersedes: ["K-0002"] })]),
102
+ },
103
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Same Title", { id: "K-0002" })]) },
104
+ ];
105
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
106
+ });
107
+
108
+ it("skips knowledge-adjacent files", () => {
109
+ const parsed = makeParsedFile([makeEntry("Title", { id: "K-0001" })]);
110
+ parsed.isKnowledgeAdjacent = true;
111
+ const files = [
112
+ { skill: "skill-a", parsed },
113
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Title", { id: "K-0002" })]) },
114
+ ];
115
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
116
+ });
117
+
118
+ it("skips files with parse issues", () => {
119
+ const files = [
120
+ {
121
+ skill: "skill-a",
122
+ parsed: makeParsedFile(
123
+ [makeEntry("Title", { id: "K-0001" })],
124
+ [{ line: 1, message: "bad" }],
125
+ ),
126
+ },
127
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Title", { id: "K-0002" })]) },
128
+ ];
129
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
130
+ });
131
+
132
+ it("detects containment when shorter title is substring of longer", () => {
133
+ const files = [
134
+ {
135
+ skill: "skill-a",
136
+ parsed: makeParsedFile([
137
+ makeEntry("Always validate input before processing", { id: "K-0001" }),
138
+ ]),
139
+ },
140
+ {
141
+ skill: "skill-b",
142
+ parsed: makeParsedFile([
143
+ makeEntry("Always validate input before processing and after", { id: "K-0002" }),
144
+ ]),
145
+ },
146
+ ];
147
+ const dupes = detectDuplicatePrinciples(files);
148
+ expect(dupes).toHaveLength(1);
149
+ expect(dupes[0].kind).toBe("containment");
150
+ });
151
+
152
+ it("does not detect containment for very short titles", () => {
153
+ const files = [
154
+ { skill: "skill-a", parsed: makeParsedFile([makeEntry("Check types", { id: "K-0001" })]) },
155
+ {
156
+ skill: "skill-b",
157
+ parsed: makeParsedFile([makeEntry("Check types and more", { id: "K-0002" })]),
158
+ },
159
+ ];
160
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
161
+ });
162
+
163
+ it("returns empty for no duplicates", () => {
164
+ const files = [
165
+ { skill: "skill-a", parsed: makeParsedFile([makeEntry("Unique Title A", { id: "K-0001" })]) },
166
+ { skill: "skill-b", parsed: makeParsedFile([makeEntry("Unique Title B", { id: "K-0002" })]) },
167
+ ];
168
+ expect(detectDuplicatePrinciples(files)).toHaveLength(0);
169
+ });
170
+ });
171
+
172
+ describe("planPromotion", () => {
173
+ it("creates shared entry with summed confirmations", () => {
174
+ const sources = [
175
+ {
176
+ skill: "skill-a",
177
+ file: "qa-log.md",
178
+ entry: makeEntry("Shared Principle", { id: "K-0001", confirmations: 3 }),
179
+ },
180
+ {
181
+ skill: "skill-b",
182
+ file: "qa-log.md",
183
+ entry: makeEntry("Shared Principle", { id: "K-0002", confirmations: 5 }),
184
+ },
185
+ ];
186
+ const plan = planPromotion(
187
+ sources,
188
+ { title: "Merged", body: "Combined body" },
189
+ "K-0099",
190
+ "2026-08-20",
191
+ );
192
+ expect(plan.sharedEntry.meta.id).toBe("K-0099");
193
+ expect(plan.sharedEntry.meta.layer).toBe("L2");
194
+ expect(plan.sharedEntry.meta.confirmations).toBe(8);
195
+ expect(plan.sharedEntry.meta.promotedFrom).toEqual(["skill-a/K-0001", "skill-b/K-0002"]);
196
+ expect(plan.sharedEntry.title).toBe("Merged");
197
+ expect(plan.sharedEntry.body).toBe("Combined body");
198
+ });
199
+
200
+ it("creates local pointers for each source", () => {
201
+ const sources = [
202
+ { skill: "skill-a", file: "qa-log.md", entry: makeEntry("Title", { id: "K-0001" }) },
203
+ { skill: "skill-b", file: "learned.md", entry: makeEntry("Title", { id: "K-0002" }) },
204
+ ];
205
+ const plan = planPromotion(sources, { title: "M", body: "B" }, "K-0099", "2026-01-01");
206
+ expect(plan.localPointers).toEqual([
207
+ { skill: "skill-a", file: "qa-log.md", entryId: "K-0001" },
208
+ { skill: "skill-b", file: "learned.md", entryId: "K-0002" },
209
+ ]);
210
+ });
211
+
212
+ it("handles undefined confirmations as zero", () => {
213
+ const sources = [
214
+ { skill: "s", file: "f.md", entry: makeEntry("T", { confirmations: undefined }) },
215
+ ];
216
+ const plan = planPromotion(sources, { title: "M", body: "B" }, "K-0099", "2026-01-01");
217
+ expect(plan.sharedEntry.meta.confirmations).toBe(0);
218
+ });
219
+ });
@@ -0,0 +1,192 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { serializeKnowledgeFile } from "../serialize.ts";
3
+ import type { ParsedKnowledgeFile, KnowledgeEntryMeta } from "../schema.ts";
4
+
5
+ function makeMeta(overrides: Partial<KnowledgeEntryMeta> = {}): KnowledgeEntryMeta {
6
+ return {
7
+ id: "entry-001",
8
+ layer: "L1",
9
+ created: "2026-01-01",
10
+ lastConfirmedAt: "2026-01-01",
11
+ confirmations: 1,
12
+ status: "active",
13
+ ...overrides,
14
+ };
15
+ }
16
+
17
+ describe("serializeKnowledgeFile", () => {
18
+ it("serializes empty parsed file to single newline", () => {
19
+ const parsed: ParsedKnowledgeFile = {
20
+ path: "test.md",
21
+ layer: "L1",
22
+ preamble: "",
23
+ entries: [],
24
+ legacySections: [],
25
+ isKnowledgeAdjacent: false,
26
+ parseIssues: [],
27
+ };
28
+ expect(serializeKnowledgeFile(parsed)).toBe("\n");
29
+ });
30
+
31
+ it("serializes preamble only", () => {
32
+ const parsed: ParsedKnowledgeFile = {
33
+ path: "test.md",
34
+ layer: "L1",
35
+ preamble: "# My Knowledge File",
36
+ entries: [],
37
+ legacySections: [],
38
+ isKnowledgeAdjacent: false,
39
+ parseIssues: [],
40
+ };
41
+ expect(serializeKnowledgeFile(parsed)).toBe("# My Knowledge File\n");
42
+ });
43
+
44
+ it("serializes a single entry with meta and body", () => {
45
+ const parsed: ParsedKnowledgeFile = {
46
+ path: "test.md",
47
+ layer: "L1",
48
+ preamble: "",
49
+ entries: [
50
+ {
51
+ meta: makeMeta(),
52
+ title: "First Principle",
53
+ body: "This is the body text.",
54
+ lineStart: 0,
55
+ },
56
+ ],
57
+ legacySections: [],
58
+ isKnowledgeAdjacent: false,
59
+ parseIssues: [],
60
+ };
61
+ const result = serializeKnowledgeFile(parsed);
62
+ expect(result).toContain("### entry-001: First Principle");
63
+ expect(result).toContain("```knowledge-entry");
64
+ expect(result).toContain("id: entry-001");
65
+ expect(result).toContain("layer: L1");
66
+ expect(result).toContain("status: active");
67
+ expect(result).toContain("This is the body text.");
68
+ expect(result).toContain("```");
69
+ });
70
+
71
+ it("omits undefined meta fields", () => {
72
+ const parsed: ParsedKnowledgeFile = {
73
+ path: "test.md",
74
+ layer: "L1",
75
+ preamble: "",
76
+ entries: [
77
+ {
78
+ meta: makeMeta({ supersedes: undefined, promotedTo: undefined, expiresAt: undefined }),
79
+ title: "Minimal",
80
+ body: "",
81
+ lineStart: 0,
82
+ },
83
+ ],
84
+ legacySections: [],
85
+ isKnowledgeAdjacent: false,
86
+ parseIssues: [],
87
+ };
88
+ const result = serializeKnowledgeFile(parsed);
89
+ expect(result).not.toContain("supersedes");
90
+ expect(result).not.toContain("promotedTo");
91
+ expect(result).not.toContain("expiresAt");
92
+ });
93
+
94
+ it("serializes array meta values as inline arrays", () => {
95
+ const parsed: ParsedKnowledgeFile = {
96
+ path: "test.md",
97
+ layer: "L1",
98
+ preamble: "",
99
+ entries: [
100
+ {
101
+ meta: makeMeta({ supersedes: ["old-001", "old-002"] }),
102
+ title: "Merged",
103
+ body: "",
104
+ lineStart: 0,
105
+ },
106
+ ],
107
+ legacySections: [],
108
+ isKnowledgeAdjacent: false,
109
+ parseIssues: [],
110
+ };
111
+ const result = serializeKnowledgeFile(parsed);
112
+ expect(result).toContain("supersedes: [old-001, old-002]");
113
+ });
114
+
115
+ it("serializes empty array as []", () => {
116
+ const parsed: ParsedKnowledgeFile = {
117
+ path: "test.md",
118
+ layer: "L1",
119
+ preamble: "",
120
+ entries: [
121
+ {
122
+ meta: makeMeta({ supersedes: [] }),
123
+ title: "Empty",
124
+ body: "",
125
+ lineStart: 0,
126
+ },
127
+ ],
128
+ legacySections: [],
129
+ isKnowledgeAdjacent: false,
130
+ parseIssues: [],
131
+ };
132
+ const result = serializeKnowledgeFile(parsed);
133
+ expect(result).toContain("supersedes: []");
134
+ });
135
+
136
+ it("serializes null meta value as null", () => {
137
+ const parsed: ParsedKnowledgeFile = {
138
+ path: "test.md",
139
+ layer: "L1",
140
+ preamble: "",
141
+ entries: [
142
+ {
143
+ meta: makeMeta({ promotedTo: null }),
144
+ title: "Null",
145
+ body: "",
146
+ lineStart: 0,
147
+ },
148
+ ],
149
+ legacySections: [],
150
+ isKnowledgeAdjacent: false,
151
+ parseIssues: [],
152
+ };
153
+ const result = serializeKnowledgeFile(parsed);
154
+ expect(result).toContain("promotedTo: null");
155
+ });
156
+
157
+ it("serializes legacy sections", () => {
158
+ const parsed: ParsedKnowledgeFile = {
159
+ path: "test.md",
160
+ layer: "L1",
161
+ preamble: "",
162
+ entries: [],
163
+ legacySections: [{ text: "## Old Section\n\nSome content", lineStart: 0 }],
164
+ isKnowledgeAdjacent: false,
165
+ parseIssues: [],
166
+ };
167
+ const result = serializeKnowledgeFile(parsed);
168
+ expect(result).toContain("## Old Section");
169
+ expect(result).toContain("Some content");
170
+ });
171
+
172
+ it("collapses excessive newlines to max two", () => {
173
+ const parsed: ParsedKnowledgeFile = {
174
+ path: "test.md",
175
+ layer: "L1",
176
+ preamble: "preamble",
177
+ entries: [
178
+ {
179
+ meta: makeMeta(),
180
+ title: "Title",
181
+ body: "body",
182
+ lineStart: 0,
183
+ },
184
+ ],
185
+ legacySections: [],
186
+ isKnowledgeAdjacent: false,
187
+ parseIssues: [],
188
+ };
189
+ const result = serializeKnowledgeFile(parsed);
190
+ expect(result).not.toMatch(/\n{3,}/);
191
+ });
192
+ });