homeostat 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/src/daily.js +26 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Homeostat turns review feedback that led to a code change into short, scored rul
|
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
8
|
# In a repo for your team's knowledge base:
|
|
9
|
-
npx --yes homeostat@0.1.
|
|
9
|
+
npx --yes homeostat@0.1.5 init
|
|
10
10
|
|
|
11
11
|
# In Claude Code:
|
|
12
12
|
claude plugin marketplace add ysugarmen/homeostat
|
package/dist/src/daily.js
CHANGED
|
@@ -67,6 +67,14 @@ async function daily(opts, io) {
|
|
|
67
67
|
settled++;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
// Lessons still waiting in an open review PR: a new lesson that repeats one waits with it.
|
|
71
|
+
git(root, "fetch", "--quiet", "origin", "+refs/heads/homeostat/review-*:refs/remotes/origin/homeostat/review-*");
|
|
72
|
+
const inReview = [...decisions.values()].flatMap((d) => d.decided.flatMap((r) => {
|
|
73
|
+
if (r.decision !== "review" || !r.pr || !open.has(r.pr))
|
|
74
|
+
return [];
|
|
75
|
+
const entry = parseEntry(showFile(root, remote(r.pr), r.path) ?? "").entry;
|
|
76
|
+
return entry ? [entry] : [];
|
|
77
|
+
}));
|
|
70
78
|
const lessons = [];
|
|
71
79
|
const decidedHashes = (m) => new Set(decisions.get(m)?.decided.map((r) => r.hash));
|
|
72
80
|
const heartbeats = {};
|
|
@@ -182,6 +190,13 @@ async function daily(opts, io) {
|
|
|
182
190
|
}
|
|
183
191
|
for (const l of lessons)
|
|
184
192
|
decide(l, files, config, inForce, groups.get(l)?.length ?? 1);
|
|
193
|
+
for (const { l, entry } of fresh) {
|
|
194
|
+
const twin = inReview.find((r) => r.frontmatter.id === entry.frontmatter.id || sameLesson(r, entry));
|
|
195
|
+
if (!twin || l.decision === "declined")
|
|
196
|
+
continue;
|
|
197
|
+
l.decision = "review";
|
|
198
|
+
l.reason = `the same lesson as ${twin.frontmatter.id}, which is waiting in review: decide them together`;
|
|
199
|
+
}
|
|
185
200
|
for (const [l, group] of groups) {
|
|
186
201
|
if (group.length < 2)
|
|
187
202
|
continue;
|
|
@@ -263,8 +278,17 @@ async function daily(opts, io) {
|
|
|
263
278
|
if (pr.pr) {
|
|
264
279
|
row.reviewPr = pr.pr.url;
|
|
265
280
|
const logins = reviewerLogins(config, review, member);
|
|
266
|
-
if (logins.length)
|
|
267
|
-
|
|
281
|
+
if (logins.length && provider.requestReviewers) {
|
|
282
|
+
try {
|
|
283
|
+
await provider.requestReviewers(kbRepo, pr.pr.id, logins);
|
|
284
|
+
io.stdout(` asked ${logins.map((l) => `@${l}`).join(", ")} to review ${pr.pr.url}\n`);
|
|
285
|
+
}
|
|
286
|
+
catch (e) {
|
|
287
|
+
// Usually: they are not collaborators on the KB repo. The PR still waits in the queue.
|
|
288
|
+
row.reviewError = `could not request ${logins.map((l) => `@${l}`).join(", ")}: ${e.message}`;
|
|
289
|
+
io.stdout(` ${row.reviewError}; reviewers must be collaborators on ${sources.kbRepo}\n`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
268
292
|
}
|
|
269
293
|
for (const l of review)
|
|
270
294
|
Object.assign(l, { pr: pr.branch });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homeostat",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Turn your team's code-review lessons into rules every coding agent follows: Claude Code, MCP, Cursor, Copilot, AGENTS.md.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"commander": "^15.0.0",
|
|
42
|
-
"@homeostat/
|
|
43
|
-
"@homeostat/
|
|
44
|
-
"@homeostat/
|
|
42
|
+
"@homeostat/mcp": "0.1.5",
|
|
43
|
+
"@homeostat/dashboard": "0.1.5",
|
|
44
|
+
"@homeostat/core": "0.1.5"
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public",
|