@grove-dev/core 0.2.21 → 0.3.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.
Files changed (102) hide show
  1. package/README.md +16 -142
  2. package/dist/build-data.d.ts.map +1 -1
  3. package/dist/build-data.js +40 -4
  4. package/dist/build-data.js.map +1 -1
  5. package/dist/config.d.ts +3 -3
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +1 -1
  8. package/dist/config.js.map +1 -1
  9. package/dist/contributors.d.ts +24 -0
  10. package/dist/contributors.d.ts.map +1 -0
  11. package/dist/contributors.js +90 -0
  12. package/dist/contributors.js.map +1 -0
  13. package/dist/directory-client.d.ts +11 -0
  14. package/dist/directory-client.d.ts.map +1 -0
  15. package/dist/directory-client.js +11 -0
  16. package/dist/directory-client.js.map +1 -0
  17. package/dist/directory-display.d.ts +27 -0
  18. package/dist/directory-display.d.ts.map +1 -0
  19. package/dist/directory-display.js +104 -0
  20. package/dist/directory-display.js.map +1 -0
  21. package/dist/directory-format.d.ts +29 -0
  22. package/dist/directory-format.d.ts.map +1 -0
  23. package/dist/directory-format.js +72 -0
  24. package/dist/directory-format.js.map +1 -0
  25. package/dist/directory-lenses.d.ts +59 -0
  26. package/dist/directory-lenses.d.ts.map +1 -0
  27. package/dist/directory-lenses.js +199 -0
  28. package/dist/directory-lenses.js.map +1 -0
  29. package/dist/directory-repo.d.ts +20 -0
  30. package/dist/directory-repo.d.ts.map +1 -0
  31. package/dist/directory-repo.js +31 -0
  32. package/dist/directory-repo.js.map +1 -0
  33. package/dist/directory-scores.d.ts +37 -0
  34. package/dist/directory-scores.d.ts.map +1 -0
  35. package/dist/directory-scores.js +76 -0
  36. package/dist/directory-scores.js.map +1 -0
  37. package/dist/directory-search.d.ts +119 -0
  38. package/dist/directory-search.d.ts.map +1 -0
  39. package/dist/directory-search.js +398 -0
  40. package/dist/directory-search.js.map +1 -0
  41. package/dist/directory-taxonomy.d.ts +11 -0
  42. package/dist/directory-taxonomy.d.ts.map +1 -0
  43. package/dist/directory-taxonomy.js +22 -0
  44. package/dist/directory-taxonomy.js.map +1 -0
  45. package/dist/index.d.ts +13 -2
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +20 -7
  48. package/dist/index.js.map +1 -1
  49. package/dist/llms.d.ts.map +1 -1
  50. package/dist/llms.js +11 -4
  51. package/dist/llms.js.map +1 -1
  52. package/dist/prepare.d.ts +18 -0
  53. package/dist/prepare.d.ts.map +1 -0
  54. package/dist/prepare.js +72 -0
  55. package/dist/prepare.js.map +1 -0
  56. package/dist/schema.d.ts +54 -0
  57. package/dist/schema.d.ts.map +1 -1
  58. package/dist/schema.js +30 -0
  59. package/dist/schema.js.map +1 -1
  60. package/dist/sitemap.d.ts.map +1 -1
  61. package/dist/sitemap.js +4 -1
  62. package/dist/sitemap.js.map +1 -1
  63. package/dist/validate.d.ts.map +1 -1
  64. package/dist/validate.js +41 -0
  65. package/dist/validate.js.map +1 -1
  66. package/package.json +9 -2
  67. package/dist/build-data.test.d.ts +0 -2
  68. package/dist/build-data.test.d.ts.map +0 -1
  69. package/dist/build-data.test.js +0 -171
  70. package/dist/build-data.test.js.map +0 -1
  71. package/dist/decisions.test.d.ts +0 -2
  72. package/dist/decisions.test.d.ts.map +0 -1
  73. package/dist/decisions.test.js +0 -205
  74. package/dist/decisions.test.js.map +0 -1
  75. package/dist/enrich.test.d.ts +0 -2
  76. package/dist/enrich.test.d.ts.map +0 -1
  77. package/dist/enrich.test.js +0 -105
  78. package/dist/enrich.test.js.map +0 -1
  79. package/dist/github-client.test.d.ts +0 -2
  80. package/dist/github-client.test.d.ts.map +0 -1
  81. package/dist/github-client.test.js +0 -176
  82. package/dist/github-client.test.js.map +0 -1
  83. package/dist/github.test.d.ts +0 -2
  84. package/dist/github.test.d.ts.map +0 -1
  85. package/dist/github.test.js +0 -73
  86. package/dist/github.test.js.map +0 -1
  87. package/dist/health.test.d.ts +0 -2
  88. package/dist/health.test.d.ts.map +0 -1
  89. package/dist/health.test.js +0 -183
  90. package/dist/health.test.js.map +0 -1
  91. package/dist/importer.test.d.ts +0 -2
  92. package/dist/importer.test.d.ts.map +0 -1
  93. package/dist/importer.test.js +0 -173
  94. package/dist/importer.test.js.map +0 -1
  95. package/dist/slug.test.d.ts +0 -2
  96. package/dist/slug.test.d.ts.map +0 -1
  97. package/dist/slug.test.js +0 -101
  98. package/dist/slug.test.js.map +0 -1
  99. package/dist/validate.test.d.ts +0 -2
  100. package/dist/validate.test.d.ts.map +0 -1
  101. package/dist/validate.test.js +0 -249
  102. package/dist/validate.test.js.map +0 -1
package/dist/validate.js CHANGED
@@ -13,6 +13,21 @@ async function exists(path) {
13
13
  return false;
14
14
  }
15
15
  }
16
+ async function taxonomyIds(path) {
17
+ try {
18
+ const raw = parseYaml(await readFile(path, "utf8"));
19
+ if (!Array.isArray(raw))
20
+ return new Set();
21
+ return new Set(raw
22
+ .map((entry) => entry && typeof entry === "object"
23
+ ? entry.id
24
+ : undefined)
25
+ .filter((id) => typeof id === "string"));
26
+ }
27
+ catch {
28
+ return new Set();
29
+ }
30
+ }
16
31
  /**
17
32
  * Validate a Grove project: read every record YAML under
18
33
  * `config.paths.recordsDir`, run full Zod parsing, and surface any
@@ -41,6 +56,21 @@ export async function validateProject(config, opts = {}) {
41
56
  const slugs = new Set();
42
57
  /** Slugs that have a github link and therefore need a health entry. */
43
58
  const slugsNeedingHealth = new Set();
59
+ const taxonomyDir = config.paths.taxonomyDir ?? "data/taxonomy";
60
+ const taxonomy = {
61
+ categories: await taxonomyIds(resolve(process.cwd(), taxonomyDir, "categories.yml")),
62
+ stacks: await taxonomyIds(resolve(process.cwd(), taxonomyDir, "stacks.yml")),
63
+ platforms: await taxonomyIds(resolve(process.cwd(), taxonomyDir, "platforms.yml")),
64
+ };
65
+ const warnUnknownTaxonomy = (fileSlug, field, value, ids, filename) => {
66
+ if (ids.size === 0 || ids.has(value))
67
+ return;
68
+ warnings.push({
69
+ code: "unknown_taxonomy_value",
70
+ message: `${fileSlug}: ${field} "${value}" is not defined in ${taxonomyDir}/${filename}`,
71
+ severity: "warning",
72
+ });
73
+ };
44
74
  for (const file of files) {
45
75
  const fileSlug = basename(file, ".yml");
46
76
  const text = await readFile(join(recordsDir, file), "utf8");
@@ -106,6 +136,17 @@ export async function validateProject(config, opts = {}) {
106
136
  severity: "warning",
107
137
  });
108
138
  }
139
+ warnUnknownTaxonomy(fileSlug, "category", parsed.category, taxonomy.categories, "categories.yml");
140
+ if (parsed.kind === "project") {
141
+ // `stack` is the canonical browse taxonomy. `stacks` contains
142
+ // supporting technologies and is intentionally open-ended.
143
+ if (parsed.stack) {
144
+ warnUnknownTaxonomy(fileSlug, "stack", parsed.stack, taxonomy.stacks, "stacks.yml");
145
+ }
146
+ for (const platform of parsed.platforms) {
147
+ warnUnknownTaxonomy(fileSlug, "platform", platform, taxonomy.platforms, "platforms.yml");
148
+ }
149
+ }
109
150
  // Records that link to a GitHub repo need a matching health entry
110
151
  // so list/detail UIs can render staleness signals. Track here and
111
152
  // cross-check against health.yml below.
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@grove-dev/core",
3
- "version": "0.2.21",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "description": "Headless engine for Grove: resource schema, config, importers, validators, taxonomy, sitemap, llms.txt, and the data build pipeline.",
6
6
  "license": "MIT",
7
+ "engines": {
8
+ "node": ">=22.12.0"
9
+ },
7
10
  "keywords": [
8
11
  "grove",
9
12
  "directory",
@@ -31,6 +34,10 @@
31
34
  ".": {
32
35
  "types": "./dist/index.d.ts",
33
36
  "import": "./dist/index.js"
37
+ },
38
+ "./directory": {
39
+ "types": "./dist/directory-client.d.ts",
40
+ "import": "./dist/directory-client.js"
34
41
  }
35
42
  },
36
43
  "files": [
@@ -43,7 +50,7 @@
43
50
  "zod": "^4.4.3"
44
51
  },
45
52
  "scripts": {
46
- "build": "tsc -p tsconfig.json",
53
+ "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
47
54
  "check": "tsc -p tsconfig.json --noEmit",
48
55
  "test": "cd ../.. && pnpm exec vitest run --project unit packages/core"
49
56
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=build-data.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-data.test.d.ts","sourceRoot":"","sources":["../src/build-data.test.ts"],"names":[],"mappings":""}
@@ -1,171 +0,0 @@
1
- /**
2
- * @grove-dev/core — build-data.ts unit tests.
3
- *
4
- * The brief calls out `applyDecision` as a load-bearing function:
5
- * - When a project record has no existing health block but a
6
- * decisions.yml override exists, the function fabricates an
7
- * "unknown" health block (via `classifyHealth(slug)`) and
8
- * writes the decision's visibility into it. This is the
9
- * preserved (vs. removed) decision from the audit, and the
10
- * test pins the chosen behavior.
11
- * - For resource-hub / ecosystem-map records (no `health`
12
- * block), the decision visibility goes onto the record's
13
- * top-level `visibility` field.
14
- *
15
- * `generate` itself is tested via filesystem round-trip with a
16
- * real tmpdir.
17
- */
18
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
19
- import { mkdtemp, mkdir, writeFile, readFile, rm } from "node:fs/promises";
20
- import { tmpdir } from "node:os";
21
- import { join } from "node:path";
22
- import { generate } from "./build-data.js";
23
- import { toIndexRecord } from "./schema.js";
24
- function makeProject(overrides = {}) {
25
- return {
26
- kind: "project",
27
- slug: "demo",
28
- name: "Demo",
29
- description: "A demo",
30
- category: "tools",
31
- tags: [],
32
- links: {},
33
- curation: { reviewed: false, labels: [], lenses: [] },
34
- scores: {},
35
- visibility: "keep",
36
- ...overrides,
37
- };
38
- }
39
- describe("toIndexRecord — fabrication behaviour (applyDecision shape)", () => {
40
- it("a project record with no health block + a decision.decision.visibility of 'hide' fabricates a health block carrying that visibility", async () => {
41
- // This test pins the PRESERVED audit decision: when a
42
- // project record has no health block but a decisions.yml
43
- // override exists, applyDecision (called inside generate)
44
- // fabricates a health block via classifyHealth(slug) (the
45
- // canonical unknown shape) and overwrites visibility.
46
- // The fabrication must keep the unknown status / maturity /
47
- // tier, and only visibility changes.
48
- //
49
- // We exercise the public `toIndexRecord` path, which is what
50
- // generate ultimately calls, with a record that has been
51
- // through the applyDecision path (simulate that here by
52
- // hand).
53
- const project = makeProject();
54
- // The "fabricated" record is what applyDecision produces:
55
- const fabricated = {
56
- ...project,
57
- health: {
58
- status: "unknown",
59
- maturity: "unknown",
60
- tier: "experimental",
61
- visibility: "hide",
62
- cleanupCandidate: false,
63
- staleReason: null,
64
- confidence: "low",
65
- reasons: ["No GitHub metadata available"],
66
- },
67
- };
68
- const idx = toIndexRecord(fabricated);
69
- // The index record's `visibility` (read by the index
70
- // filter) must reflect the decision override, not the
71
- // fabricated default of "keep".
72
- expect(idx.visibility).toBe("hide");
73
- });
74
- });
75
- describe("generate — filesystem round-trip", () => {
76
- let cwd;
77
- beforeEach(async () => {
78
- cwd = await mkdtemp(join(tmpdir(), "grove-build-test-"));
79
- await mkdir(join(cwd, "data", "records"), { recursive: true });
80
- await mkdir(join(cwd, "data", "generated"), { recursive: true });
81
- // grove.config.ts stub so loadConfig() doesn't throw.
82
- await writeFile(join(cwd, "grove.config.ts"), [
83
- "export default {",
84
- " site: { name: 'test', tagline: 'test' },",
85
- " paths: { recordsDir: 'data/records', generatedDir: 'data/generated', health: 'data/health.yml', decisions: 'data/decisions.yml' },",
86
- " blueprint: 'project-directory',",
87
- " nav: [],",
88
- " theme: {},",
89
- " integrations: {},",
90
- "};",
91
- ].join("\n"));
92
- });
93
- afterEach(async () => {
94
- await rm(cwd, { recursive: true, force: true });
95
- });
96
- it("generates records.full.json, records.index.json, and records.json (alias) from a real records dir", async () => {
97
- await writeFile(join(cwd, "data", "records", "demo.yml"), [
98
- "kind: project",
99
- "slug: demo",
100
- "name: Demo",
101
- "description: a demo",
102
- "category: tools",
103
- "links: {}",
104
- "curation: { reviewed: false, labels: [], lenses: [] }",
105
- "scores: {}",
106
- ].join("\n"));
107
- const r = await generate(cwd);
108
- expect(r.totalRecords).toBe(1);
109
- expect(r.visibleRecords).toBe(1);
110
- // The three files were all written.
111
- const full = JSON.parse(await readFile(r.fullPath, "utf8"));
112
- const idx = JSON.parse(await readFile(r.indexPath, "utf8"));
113
- const alias = JSON.parse(await readFile(r.aliasPath, "utf8"));
114
- expect(full.totalRecords).toBe(1);
115
- expect(idx.totalRecords).toBe(1);
116
- // Alias == full payload.
117
- expect(alias).toEqual(full);
118
- });
119
- it("applies a decisions.yml override of visibility='hide' to a project record without a health block", async () => {
120
- // The brief's load-bearing test: a project record that has
121
- // no health block, plus a decisions.yml that says
122
- // "hide" for that slug, must produce a hidden record in the
123
- // full payload AND exclude it from the index payload.
124
- await writeFile(join(cwd, "data", "records", "hidden.yml"), [
125
- "kind: project",
126
- "slug: hidden",
127
- "name: Hidden",
128
- "description: should be hidden by decisions.yml",
129
- "category: tools",
130
- "links: {}",
131
- "curation: { reviewed: false, labels: [], lenses: [] }",
132
- "scores: {}",
133
- ].join("\n"));
134
- await writeFile(join(cwd, "data", "decisions.yml"), [
135
- "decisions:",
136
- " - id: hidden",
137
- " decision:",
138
- " visibility: hide",
139
- " reason: tested override",
140
- ].join("\n"));
141
- const r = await generate(cwd);
142
- expect(r.totalRecords).toBe(1); // full payload still includes the record
143
- expect(r.visibleRecords).toBe(0); // but the index payload omits it
144
- const full = JSON.parse(await readFile(r.fullPath, "utf8"));
145
- const hidden = full.records.find((rec) => rec.slug === "hidden");
146
- expect(hidden).toBeDefined();
147
- // The fabrication: a health block exists, and its visibility
148
- // is "hide" (the decision override), not "keep" (the
149
- // fabricated default).
150
- expect(hidden?.health?.visibility).toBe("hide");
151
- });
152
- it("writes site-config.json with stats derived from the records", async () => {
153
- await writeFile(join(cwd, "data", "records", "coolify.yml"), [
154
- "kind: project",
155
- "slug: coolify",
156
- "name: Coolify",
157
- "description: self-hosting",
158
- "category: tools",
159
- "stacks: [typescript]",
160
- "links: {}",
161
- "curation: { reviewed: false, labels: [], lenses: [] }",
162
- "scores: {}",
163
- ].join("\n"));
164
- const r = await generate(cwd);
165
- const sitePath = join(cwd, "data", "generated", "site-config.json");
166
- const site = JSON.parse(await readFile(sitePath, "utf8"));
167
- expect(site.stats.totalRecords).toBe(1);
168
- expect(site.stats.totalApps).toBe(1);
169
- });
170
- });
171
- //# sourceMappingURL=build-data.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-data.test.js","sourceRoot":"","sources":["../src/build-data.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=decisions.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decisions.test.d.ts","sourceRoot":"","sources":["../src/decisions.test.ts"],"names":[],"mappings":""}
@@ -1,205 +0,0 @@
1
- /**
2
- * @grove-dev/core — decisions + cleanup-stale unit tests.
3
- *
4
- * `pickCleanupCandidates` is a pure predicate and trivially testable
5
- * without any I/O. `cleanupStale` reads from the filesystem and
6
- * writes `data/generated/cleanup-report.json` — the tests below use
7
- * `tmpdir()` (per the brief — no fs mocks) to spin up a real
8
- * project tree and exercise both the happy path and the missing-
9
- * files-dir / invalid-YAML silent-fallback paths.
10
- */
11
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
12
- import { mkdir, writeFile, readFile, rm, mkdtemp } from "node:fs/promises";
13
- import { tmpdir } from "node:os";
14
- import { join } from "node:path";
15
- import { pickCleanupCandidates, cleanupStale } from "./decisions.js";
16
- function makeProjectResource(overrides = {}) {
17
- return {
18
- kind: "project",
19
- slug: "demo",
20
- name: "Demo",
21
- description: "A demo project",
22
- category: "tools",
23
- tags: [],
24
- links: { github: "https://github.com/owner/repo" },
25
- curation: { reviewed: false, labels: [], lenses: [] },
26
- scores: {},
27
- visibility: "keep",
28
- ...overrides,
29
- };
30
- }
31
- describe("pickCleanupCandidates — pure predicate", () => {
32
- it("returns records whose health.cleanupCandidate is true", () => {
33
- const r = makeProjectResource({
34
- health: {
35
- status: "stale",
36
- maturity: "useful",
37
- tier: "listed",
38
- visibility: "keep",
39
- cleanupCandidate: true,
40
- staleReason: "no_commits_365_days",
41
- confidence: "high",
42
- reasons: [],
43
- },
44
- });
45
- expect(pickCleanupCandidates([r])).toEqual([r]);
46
- });
47
- it("returns records whose health.status is 'unknown' or 'needs_review'", () => {
48
- const a = makeProjectResource({ slug: "a", health: { status: "unknown", maturity: "unknown", tier: "experimental", visibility: "keep", cleanupCandidate: false, staleReason: null, confidence: "low", reasons: [] } });
49
- const b = makeProjectResource({ slug: "b", health: { status: "needs_review", maturity: "useful", tier: "listed", visibility: "keep", cleanupCandidate: false, staleReason: null, confidence: "medium", reasons: [] } });
50
- const c = makeProjectResource({ slug: "c", health: { status: "active", maturity: "mature", tier: "curated", visibility: "keep", cleanupCandidate: false, staleReason: null, confidence: "high", reasons: [] } });
51
- const out = pickCleanupCandidates([a, b, c]);
52
- expect(out.map((r) => r.slug).sort()).toEqual(["a", "b"]);
53
- });
54
- it("returns an empty array when no records need cleanup", () => {
55
- const a = makeProjectResource({ health: { status: "active", maturity: "mature", tier: "curated", visibility: "keep", cleanupCandidate: false, staleReason: null, confidence: "high", reasons: [] } });
56
- const b = makeProjectResource({ slug: "b", health: { status: "mature", maturity: "mature", tier: "curated", visibility: "keep", cleanupCandidate: false, staleReason: null, confidence: "high", reasons: [] } });
57
- expect(pickCleanupCandidates([a, b])).toEqual([]);
58
- });
59
- it("treats a record with no health block as not-a-candidate", () => {
60
- const r = makeProjectResource(); // no health
61
- expect(pickCleanupCandidates([r])).toEqual([]);
62
- });
63
- });
64
- describe("cleanupStale — filesystem integration (real tmpdir)", () => {
65
- let cwd;
66
- beforeEach(async () => {
67
- cwd = await mkdtemp(join(tmpdir(), "grove-cleanup-test-"));
68
- await mkdir(join(cwd, "data", "records"), { recursive: true });
69
- await mkdir(join(cwd, "data", "generated"), { recursive: true });
70
- // cleanupStale → loadConfig → jiti-resolves grove.config.ts.
71
- // Write a minimal valid stub so the config loader doesn't throw.
72
- await writeFile(join(cwd, "grove.config.ts"), [
73
- "export default {",
74
- " site: { name: 'test', tagline: 'test' },",
75
- " paths: { recordsDir: 'data/records', generatedDir: 'data/generated', health: 'data/health.yml', decisions: 'data/decisions.yml' },",
76
- " blueprint: 'project-directory',",
77
- " nav: [],",
78
- " theme: {},",
79
- " integrations: {},",
80
- "};",
81
- ].join("\n"));
82
- });
83
- afterEach(async () => {
84
- await rm(cwd, { recursive: true, force: true });
85
- });
86
- it("reads records, applies pickCleanupCandidates, writes cleanup-report.json", async () => {
87
- // One record whose health status is 'unknown' (cleanup candidate)
88
- // and one whose status is 'active' (not a candidate). The slug
89
- // field is in the YAML (matches the schema), and the file name
90
- // also carries it (cleanupStale overwrites normalized.slug
91
- // with the filename at line 88 — pinning that contract).
92
- await writeFile(join(cwd, "data", "records", "stale-one.yml"), [
93
- "kind: project",
94
- "slug: stale-one",
95
- "name: Stale One",
96
- "description: an old project",
97
- "category: tools",
98
- "links: { github: 'https://github.com/owner/repo' }",
99
- "curation: { reviewed: false, labels: [], lenses: [] }",
100
- "scores: {}",
101
- "health:",
102
- " status: unknown",
103
- " maturity: unknown",
104
- " tier: experimental",
105
- " visibility: keep",
106
- " cleanupCandidate: false",
107
- " staleReason: null",
108
- " confidence: low",
109
- " reasons: []",
110
- ].join("\n"));
111
- await writeFile(join(cwd, "data", "records", "fresh.yml"), [
112
- "kind: project",
113
- "slug: fresh",
114
- "name: Fresh",
115
- "description: an active project",
116
- "category: tools",
117
- "links: { github: 'https://github.com/owner/fresh' }",
118
- "curation: { reviewed: false, labels: [], lenses: [] }",
119
- "scores: {}",
120
- "health:",
121
- " status: active",
122
- " maturity: mature",
123
- " tier: curated",
124
- " visibility: keep",
125
- " cleanupCandidate: false",
126
- " staleReason: null",
127
- " confidence: high",
128
- " reasons: []",
129
- ].join("\n"));
130
- const { report, path } = await cleanupStale(cwd);
131
- expect(report.totalCandidates).toBe(1);
132
- expect(report.candidates[0]?.slug).toBe("stale-one");
133
- expect(report.candidates[0]?.status).toBe("unknown");
134
- expect(report.blueprint).toBe("project-directory");
135
- // Verify the file was actually written.
136
- const written = JSON.parse(await readFile(path, "utf8"));
137
- expect(written.totalCandidates).toBe(1);
138
- expect(written.candidates[0]?.slug).toBe("stale-one");
139
- });
140
- it("skips records whose parsed YAML fails Zod (try/catch on recordsFileSchema.parse)", async () => {
141
- // The brief calls out the silent try/catch around
142
- // `recordsFileSchema.parse(raw)` in decisions.ts as audit
143
- // concern #1. Pin the *current* behaviour (skip, do not
144
- // throw) so a future change to throw is visible.
145
- //
146
- // Note: `parseYaml` itself is NOT in a try/catch — a totally
147
- // malformed YAML would crash the loop. The silent path the
148
- // audit flagged is the Zod parse step, not the YAML parse
149
- // step. So this test uses a YAML file that *parses* but
150
- // produces a value the Zod schema rejects (e.g. an array
151
- // where an object is required).
152
- await writeFile(join(cwd, "data", "records", "broken.yml"),
153
- // YAML that parses to an array — fails Zod object validation.
154
- "- this\n- is\n- an\n- array\n");
155
- // A second, valid record that IS a cleanup candidate.
156
- await writeFile(join(cwd, "data", "records", "ok.yml"), [
157
- "kind: project",
158
- "slug: ok",
159
- "name: Ok",
160
- "description: candidate",
161
- "category: tools",
162
- "links: {}",
163
- "curation: { reviewed: false, labels: [], lenses: [] }",
164
- "scores: {}",
165
- "health:",
166
- " status: needs_review",
167
- " maturity: useful",
168
- " tier: listed",
169
- " visibility: keep",
170
- " cleanupCandidate: false",
171
- " staleReason: null",
172
- " confidence: medium",
173
- " reasons: []",
174
- ].join("\n"));
175
- const { report } = await cleanupStale(cwd);
176
- // The broken record is dropped; only "ok" is reported.
177
- expect(report.totalCandidates).toBe(1);
178
- expect(report.candidates[0]?.slug).toBe("ok");
179
- });
180
- it("returns an empty report when the records directory does not exist", async () => {
181
- // The readdir call at decisions.ts:77 uses .catch(() => []),
182
- // so a missing dir is silently treated as zero records. Pin
183
- // that behaviour — the function should NOT throw, the report
184
- // should be empty, and the JSON file should still be written
185
- // (so downstream tooling can rely on its presence). We test
186
- // by pointing config.paths.recordsDir at a path that doesn't
187
- // exist, rather than rm-ing the records dir after beforeEach
188
- // created the config (which would also remove the config).
189
- const noRecordsConfig = {
190
- site: { name: "test", tagline: "test" },
191
- paths: { recordsDir: "data/does-not-exist", generatedDir: "data/generated", health: "data/health.yml", decisions: "data/decisions.yml" },
192
- blueprint: "project-directory",
193
- nav: [],
194
- theme: {},
195
- integrations: {},
196
- };
197
- const { report, path } = await cleanupStale(cwd, noRecordsConfig);
198
- expect(report.totalCandidates).toBe(0);
199
- expect(report.candidates).toEqual([]);
200
- // The file should still exist for downstream consumers.
201
- const written = JSON.parse(await readFile(path, "utf8"));
202
- expect(written.totalCandidates).toBe(0);
203
- });
204
- });
205
- //# sourceMappingURL=decisions.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decisions.test.js","sourceRoot":"","sources":["../src/decisions.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=enrich.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"enrich.test.d.ts","sourceRoot":"","sources":["../src/enrich.test.ts"],"names":[],"mappings":""}