@grove-dev/core 0.2.16 → 0.2.20
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.
- package/README.md +2 -2
- package/dist/build-data.d.ts.map +1 -1
- package/dist/build-data.js +19 -12
- package/dist/build-data.js.map +1 -1
- package/dist/build-data.test.d.ts +2 -0
- package/dist/build-data.test.d.ts.map +1 -0
- package/dist/build-data.test.js +171 -0
- package/dist/build-data.test.js.map +1 -0
- package/dist/decisions.test.d.ts +2 -0
- package/dist/decisions.test.d.ts.map +1 -0
- package/dist/decisions.test.js +205 -0
- package/dist/decisions.test.js.map +1 -0
- package/dist/enrich.test.d.ts +2 -0
- package/dist/enrich.test.d.ts.map +1 -0
- package/dist/enrich.test.js +105 -0
- package/dist/enrich.test.js.map +1 -0
- package/dist/github-client.d.ts.map +1 -1
- package/dist/github-client.js +4 -1
- package/dist/github-client.js.map +1 -1
- package/dist/github-client.test.d.ts +2 -0
- package/dist/github-client.test.d.ts.map +1 -0
- package/dist/github-client.test.js +176 -0
- package/dist/github-client.test.js.map +1 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +6 -2
- package/dist/github.js.map +1 -1
- package/dist/github.test.d.ts +2 -0
- package/dist/github.test.d.ts.map +1 -0
- package/dist/github.test.js +73 -0
- package/dist/github.test.js.map +1 -0
- package/dist/health.test.d.ts +2 -0
- package/dist/health.test.d.ts.map +1 -0
- package/dist/health.test.js +183 -0
- package/dist/health.test.js.map +1 -0
- package/dist/importer.test.d.ts +2 -0
- package/dist/importer.test.d.ts.map +1 -0
- package/dist/importer.test.js +173 -0
- package/dist/importer.test.js.map +1 -0
- package/dist/index.d.ts +36 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -16
- package/dist/index.js.map +1 -1
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +6 -4
- package/dist/llms.js.map +1 -1
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +16 -10
- package/dist/markdown.js.map +1 -1
- package/dist/parseReadme.d.ts.map +1 -1
- package/dist/parseReadme.js +5 -1
- package/dist/parseReadme.js.map +1 -1
- package/dist/schema.d.ts +1 -14
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +14 -60
- package/dist/schema.js.map +1 -1
- package/dist/slug.d.ts +10 -0
- package/dist/slug.d.ts.map +1 -1
- package/dist/slug.js +10 -0
- package/dist/slug.js.map +1 -1
- package/dist/slug.test.d.ts +2 -0
- package/dist/slug.test.d.ts.map +1 -0
- package/dist/slug.test.js +101 -0
- package/dist/slug.test.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +249 -0
- package/dist/validate.test.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -96,7 +96,6 @@ import {
|
|
|
96
96
|
fetchGithubMetadata,
|
|
97
97
|
enrichFromGithubHtml,
|
|
98
98
|
classifyHealth,
|
|
99
|
-
healthFromSignals,
|
|
100
99
|
type GithubMetadata,
|
|
101
100
|
type HealthEntry,
|
|
102
101
|
type EnrichedFields,
|
|
@@ -144,7 +143,8 @@ The V0 published `@grove-dev/core` exposed several names that the V1 release rep
|
|
|
144
143
|
| `buildReviewReport` | removed (the cleanup report is a side effect of `pickCleanupCandidates`) |
|
|
145
144
|
| `parseAppYaml` | removed (V0 `apps` model is gone; use `readYamlFile` + Zod parse) |
|
|
146
145
|
| `normalizeAppRecord` / `toIndexApp` | internal to `build-data.ts`; not part of the V1 public surface |
|
|
147
|
-
| `
|
|
146
|
+
| `validateAppRecord` | removed (V0 `apps` model is gone) |
|
|
147
|
+
| `validateProject` | kept (V1 name — used by tests and CLI for the structured `ValidationIssue[]` output that `generate`'s throw path does not produce) |
|
|
148
148
|
|
|
149
149
|
## Development
|
|
150
150
|
|
package/dist/build-data.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-data.d.ts","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"build-data.d.ts","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAgErB;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAC5B,GAAG,SAAgB,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAmNzB"}
|
package/dist/build-data.js
CHANGED
|
@@ -2,6 +2,7 @@ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
import { blueprintKind, recordsFileSchema, toIndexRecord, unwrapDecisions, decisionsFileSchema, } from "./schema.js";
|
|
5
|
+
import { classifyHealth } from "./health.js";
|
|
5
6
|
import { loadConfig } from "./config.js";
|
|
6
7
|
/**
|
|
7
8
|
* Apply a minimal decisions.yml override to a normalized record. The
|
|
@@ -15,6 +16,15 @@ import { loadConfig } from "./config.js";
|
|
|
15
16
|
*
|
|
16
17
|
* The full override pipeline (with reasons surfaced in the index
|
|
17
18
|
* payload) is a V2 feature; V1 keeps the merge intentional and small.
|
|
19
|
+
*
|
|
20
|
+
* When a project record has no existing health block but a decisions
|
|
21
|
+
* override exists, we call `classifyHealth` (the V1 single source of
|
|
22
|
+
* truth) with no GitHub metadata to fabricate an "unknown" health
|
|
23
|
+
* block whose `visibility` we then overwrite with the decision. This
|
|
24
|
+
* fabrication is required by the index payload: `toIndexRecord` reads
|
|
25
|
+
* `record.health?.visibility` to populate the index, so the override
|
|
26
|
+
* cannot flow through without a health block. Without the fabrication
|
|
27
|
+
* the override would silently disappear from the rendered index.
|
|
18
28
|
*/
|
|
19
29
|
function applyDecision(record, visibilityById) {
|
|
20
30
|
const override = visibilityById.get(record.slug);
|
|
@@ -22,17 +32,12 @@ function applyDecision(record, visibilityById) {
|
|
|
22
32
|
return record;
|
|
23
33
|
if (record.kind === "project") {
|
|
24
34
|
const existing = record.health;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
staleReason: null,
|
|
32
|
-
confidence: "medium",
|
|
33
|
-
reasons: [],
|
|
34
|
-
};
|
|
35
|
-
const merged = { ...(existing ?? fallback), visibility: override };
|
|
35
|
+
// Fabricate a default "no signals" health block via the canonical
|
|
36
|
+
// classifier. Keeps the threshold/format in lockstep with the rest
|
|
37
|
+
// of the package — if `classifyHealth` ever changes its unknown
|
|
38
|
+
// shape, this fabrication updates automatically.
|
|
39
|
+
const fabricated = classifyHealth(record.slug).health;
|
|
40
|
+
const merged = { ...(existing ?? fabricated), visibility: override };
|
|
36
41
|
return { ...record, health: merged };
|
|
37
42
|
}
|
|
38
43
|
// Resource-hub / ecosystem-map: no `health` block; the top-level
|
|
@@ -123,7 +128,9 @@ export async function generate(cwd = process.cwd(), config) {
|
|
|
123
128
|
platforms.add(p);
|
|
124
129
|
const gh = r.github;
|
|
125
130
|
if (gh?.fullName && gh.fullName.includes("/")) {
|
|
126
|
-
|
|
131
|
+
const [owner] = gh.fullName.split("/");
|
|
132
|
+
if (owner)
|
|
133
|
+
owners.add(owner);
|
|
127
134
|
}
|
|
128
135
|
if (typeof gh?.stars === "number")
|
|
129
136
|
totalStars += gh.stars;
|
package/dist/build-data.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-data.js","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,mBAAmB,GAGpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC
|
|
1
|
+
{"version":3,"file":"build-data.js","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-data.test.d.ts","sourceRoot":"","sources":["../src/build-data.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,171 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-data.test.js","sourceRoot":"","sources":["../src/build-data.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decisions.test.d.ts","sourceRoot":"","sources":["../src/decisions.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,205 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decisions.test.js","sourceRoot":"","sources":["../src/decisions.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich.test.d.ts","sourceRoot":"","sources":["../src/enrich.test.ts"],"names":[],"mappings":""}
|