@starterculture/devkeep-actions 0.3.1 → 0.4.1
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/dist/consolidate-release.js +25 -21
- package/dist/draft-log-entry.js +18 -14
- package/dist/draft-release-notes.js +5 -1
- package/dist/sync-onboarding.js +17 -13
- package/package.json +1 -1
|
@@ -72,10 +72,14 @@ function createClaudeClient(apiKey) {
|
|
|
72
72
|
// ../../modules/core/dist/claude/complete.js
|
|
73
73
|
var DEFAULT_MAX_CONTINUATIONS = 5;
|
|
74
74
|
var CONTINUATION_USER_MESSAGE = "Continue exactly where you left off. Do not repeat any text already written, and do not add any preamble or commentary \u2014 resume the previous response verbatim from the exact cutoff point.";
|
|
75
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 24e4;
|
|
75
76
|
async function createCompleteMessage(claude, params, { maxContinuations = DEFAULT_MAX_CONTINUATIONS, timeoutMs, signal } = {}) {
|
|
76
77
|
let fullText = "";
|
|
77
78
|
let usage = ZERO_USAGE;
|
|
78
|
-
const requestOptions =
|
|
79
|
+
const requestOptions = {
|
|
80
|
+
timeout: timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
81
|
+
...signal !== void 0 ? { signal } : {}
|
|
82
|
+
};
|
|
79
83
|
for (let attempt = 0; attempt <= maxContinuations; attempt++) {
|
|
80
84
|
const messages = fullText ? [
|
|
81
85
|
...params.messages,
|
|
@@ -186,22 +190,22 @@ function isNotFound(error) {
|
|
|
186
190
|
return typeof error === "object" && error !== null && "status" in error && error.status === 404;
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
// ../../modules/devlore/dist/
|
|
190
|
-
function
|
|
191
|
-
return `projects/${projectName}/
|
|
193
|
+
// ../../modules/devlore/dist/canonicalDocs.js
|
|
194
|
+
function canonicalDocsPath(projectName) {
|
|
195
|
+
return `projects/${projectName}/canonical/README.md`;
|
|
192
196
|
}
|
|
193
|
-
async function
|
|
194
|
-
return (await
|
|
197
|
+
async function getCanonicalDocs(octokit, params) {
|
|
198
|
+
return (await getCanonicalDocsFile(octokit, params)).content;
|
|
195
199
|
}
|
|
196
|
-
async function
|
|
197
|
-
return (await
|
|
200
|
+
async function getCanonicalDocsSha(octokit, params) {
|
|
201
|
+
return (await getCanonicalDocsFile(octokit, params)).sha;
|
|
198
202
|
}
|
|
199
|
-
async function
|
|
203
|
+
async function getCanonicalDocsFile(octokit, { owner, repo, projectName }) {
|
|
200
204
|
try {
|
|
201
205
|
const { data } = await octokit.rest.repos.getContent({
|
|
202
206
|
owner,
|
|
203
207
|
repo,
|
|
204
|
-
path:
|
|
208
|
+
path: canonicalDocsPath(projectName)
|
|
205
209
|
});
|
|
206
210
|
if (Array.isArray(data) || data.type !== "file") {
|
|
207
211
|
return { content: "" };
|
|
@@ -228,13 +232,13 @@ ${entry.content}`).join("\n\n");
|
|
|
228
232
|
`Previous release: ${input.previousTag ?? "(none \u2014 this is the first release)"}`,
|
|
229
233
|
`Date: ${input.date}`,
|
|
230
234
|
"",
|
|
231
|
-
"Current
|
|
232
|
-
input.
|
|
235
|
+
"Current canonical docs (may be empty if none exist yet):",
|
|
236
|
+
input.canonicalDocs || "(none yet)",
|
|
233
237
|
"",
|
|
234
238
|
"Log entries since the previous release:",
|
|
235
239
|
entriesText || "(none)",
|
|
236
240
|
"",
|
|
237
|
-
`Draft the updated
|
|
241
|
+
`Draft the updated canonical docs for ${input.projectName} as of ${input.tag}, folding in what changed across the log entries above into the current canonical docs. This is the official record, reviewed by a human before merging, so write it as durable reference documentation, not a changelog.`
|
|
238
242
|
].join("\n");
|
|
239
243
|
}
|
|
240
244
|
|
|
@@ -347,7 +351,7 @@ function releaseBranchName(projectName, tag) {
|
|
|
347
351
|
return `devkeep/${projectName}/${tag}`;
|
|
348
352
|
}
|
|
349
353
|
async function consolidateRelease({ projectOctokit, vaultOctokit, claude, projectOwner, projectRepoName, vaultOwner, vaultRepoName, projectName, tag }) {
|
|
350
|
-
const [{ logEntries, previousTag },
|
|
354
|
+
const [{ logEntries, previousTag }, canonicalDocs, canonicalDocsSha] = await Promise.all([
|
|
351
355
|
selectLogEntriesSincePreviousRelease({
|
|
352
356
|
vaultOctokit,
|
|
353
357
|
projectOctokit,
|
|
@@ -358,8 +362,8 @@ async function consolidateRelease({ projectOctokit, vaultOctokit, claude, projec
|
|
|
358
362
|
projectRepoName,
|
|
359
363
|
tag
|
|
360
364
|
}),
|
|
361
|
-
|
|
362
|
-
|
|
365
|
+
getCanonicalDocs(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName }),
|
|
366
|
+
getCanonicalDocsSha(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName })
|
|
363
367
|
]);
|
|
364
368
|
const prompt = buildConsolidationPrompt({
|
|
365
369
|
projectName,
|
|
@@ -367,7 +371,7 @@ async function consolidateRelease({ projectOctokit, vaultOctokit, claude, projec
|
|
|
367
371
|
previousTag,
|
|
368
372
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
369
373
|
logEntries,
|
|
370
|
-
|
|
374
|
+
canonicalDocs
|
|
371
375
|
});
|
|
372
376
|
const { text: draftedDocs, usage } = await createCompleteMessage(claude, {
|
|
373
377
|
model: defaultModelFor(MODEL_TIER),
|
|
@@ -395,13 +399,13 @@ async function consolidateRelease({ projectOctokit, vaultOctokit, claude, projec
|
|
|
395
399
|
await vaultOctokit.rest.repos.createOrUpdateFileContents({
|
|
396
400
|
owner: vaultOwner,
|
|
397
401
|
repo: vaultRepoName,
|
|
398
|
-
path:
|
|
402
|
+
path: canonicalDocsPath(projectName),
|
|
399
403
|
message: `Consolidate release: ${projectName}@${tag}`,
|
|
400
404
|
content: Buffer.from(draftedDocs, "utf-8").toString("base64"),
|
|
401
405
|
branch,
|
|
402
|
-
sha:
|
|
406
|
+
sha: canonicalDocsSha
|
|
403
407
|
});
|
|
404
|
-
await recordUsage(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName, branch }, "consolidateRelease", usage);
|
|
408
|
+
await recordUsage(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName, branch: VAULT_BASE_BRANCH }, "consolidateRelease", usage);
|
|
405
409
|
const openPrs = await vaultOctokit.rest.pulls.list({ owner: vaultOwner, repo: vaultRepoName, state: "open", head: `${vaultOwner}:${branch}` }).catch(() => ({ data: [] }));
|
|
406
410
|
if (openPrs.data.length > 0) {
|
|
407
411
|
return { branch, prNumber: openPrs.data[0].number, prUrl: openPrs.data[0].html_url, usage };
|
|
@@ -412,7 +416,7 @@ async function consolidateRelease({ projectOctokit, vaultOctokit, claude, projec
|
|
|
412
416
|
title: `Consolidate release: ${projectName}@${tag}`,
|
|
413
417
|
head: branch,
|
|
414
418
|
base: VAULT_BASE_BRANCH,
|
|
415
|
-
body: `Drafted
|
|
419
|
+
body: `Drafted canonical doc update for \`${projectName}\` at \`${tag}\`, generated from the log entries since the last release. Review before merging \u2014 this updates the official docs.`
|
|
416
420
|
});
|
|
417
421
|
return { branch, prNumber: pr.data.number, prUrl: pr.data.html_url, usage };
|
|
418
422
|
}
|
package/dist/draft-log-entry.js
CHANGED
|
@@ -72,10 +72,14 @@ function createClaudeClient(apiKey) {
|
|
|
72
72
|
// ../../modules/core/dist/claude/complete.js
|
|
73
73
|
var DEFAULT_MAX_CONTINUATIONS = 5;
|
|
74
74
|
var CONTINUATION_USER_MESSAGE = "Continue exactly where you left off. Do not repeat any text already written, and do not add any preamble or commentary \u2014 resume the previous response verbatim from the exact cutoff point.";
|
|
75
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 24e4;
|
|
75
76
|
async function createCompleteMessage(claude, params, { maxContinuations = DEFAULT_MAX_CONTINUATIONS, timeoutMs, signal } = {}) {
|
|
76
77
|
let fullText = "";
|
|
77
78
|
let usage = ZERO_USAGE;
|
|
78
|
-
const requestOptions =
|
|
79
|
+
const requestOptions = {
|
|
80
|
+
timeout: timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
81
|
+
...signal !== void 0 ? { signal } : {}
|
|
82
|
+
};
|
|
79
83
|
for (let attempt = 0; attempt <= maxContinuations; attempt++) {
|
|
80
84
|
const messages = fullText ? [
|
|
81
85
|
...params.messages,
|
|
@@ -233,19 +237,19 @@ async function getProjectDiff(octokit, { owner, repo, base, head }) {
|
|
|
233
237
|
}
|
|
234
238
|
}
|
|
235
239
|
|
|
236
|
-
// ../../modules/devlore/dist/
|
|
237
|
-
function
|
|
238
|
-
return `projects/${projectName}/
|
|
240
|
+
// ../../modules/devlore/dist/canonicalDocs.js
|
|
241
|
+
function canonicalDocsPath(projectName) {
|
|
242
|
+
return `projects/${projectName}/canonical/README.md`;
|
|
239
243
|
}
|
|
240
|
-
async function
|
|
241
|
-
return (await
|
|
244
|
+
async function getCanonicalDocs(octokit, params) {
|
|
245
|
+
return (await getCanonicalDocsFile(octokit, params)).content;
|
|
242
246
|
}
|
|
243
|
-
async function
|
|
247
|
+
async function getCanonicalDocsFile(octokit, { owner, repo, projectName }) {
|
|
244
248
|
try {
|
|
245
249
|
const { data } = await octokit.rest.repos.getContent({
|
|
246
250
|
owner,
|
|
247
251
|
repo,
|
|
248
|
-
path:
|
|
252
|
+
path: canonicalDocsPath(projectName)
|
|
249
253
|
});
|
|
250
254
|
if (Array.isArray(data) || data.type !== "file") {
|
|
251
255
|
return { content: "" };
|
|
@@ -363,8 +367,8 @@ ${file.patch}`).join("\n\n");
|
|
|
363
367
|
"Commit messages:",
|
|
364
368
|
input.commitMessages.map((message) => `- ${message}`).join("\n"),
|
|
365
369
|
"",
|
|
366
|
-
"Current
|
|
367
|
-
input.
|
|
370
|
+
"Current canonical docs (may be empty if none exist yet):",
|
|
371
|
+
input.canonicalDocs || "(none yet)",
|
|
368
372
|
"",
|
|
369
373
|
"Diff:",
|
|
370
374
|
diff,
|
|
@@ -568,13 +572,13 @@ async function syncProductDoc(projectOctokit, vaultOctokit, { projectOwner, proj
|
|
|
568
572
|
});
|
|
569
573
|
});
|
|
570
574
|
}
|
|
571
|
-
async function draftBucketLogEntry({ vaultOctokit, claude, vaultOwner, vaultRepoName, projectName, headSha, date, commitMessages, files,
|
|
575
|
+
async function draftBucketLogEntry({ vaultOctokit, claude, vaultOwner, vaultRepoName, projectName, headSha, date, commitMessages, files, canonicalDocs, moduleId, moduleName }) {
|
|
572
576
|
const prompt = buildLogEntryPrompt({
|
|
573
577
|
projectName,
|
|
574
578
|
date,
|
|
575
579
|
commitMessages,
|
|
576
580
|
files,
|
|
577
|
-
|
|
581
|
+
canonicalDocs,
|
|
578
582
|
moduleName: moduleName ?? void 0
|
|
579
583
|
});
|
|
580
584
|
const { text, usage } = await createCompleteMessage(claude, {
|
|
@@ -629,7 +633,7 @@ async function draftLogEntry({ projectOctokit, vaultOctokit, claude, projectOwne
|
|
|
629
633
|
ref: headSha
|
|
630
634
|
});
|
|
631
635
|
const buckets = routeDiffByModule(diff.files, manifest);
|
|
632
|
-
const
|
|
636
|
+
const canonicalDocs = await getCanonicalDocs(vaultOctokit, {
|
|
633
637
|
owner: vaultOwner,
|
|
634
638
|
repo: vaultRepoName,
|
|
635
639
|
projectName
|
|
@@ -647,7 +651,7 @@ async function draftLogEntry({ projectOctokit, vaultOctokit, claude, projectOwne
|
|
|
647
651
|
date,
|
|
648
652
|
commitMessages: diff.commitMessages,
|
|
649
653
|
files: bucket.files,
|
|
650
|
-
|
|
654
|
+
canonicalDocs,
|
|
651
655
|
moduleId: bucket.moduleId,
|
|
652
656
|
moduleName: bucket.moduleName
|
|
653
657
|
});
|
|
@@ -72,10 +72,14 @@ function createClaudeClient(apiKey) {
|
|
|
72
72
|
// ../../modules/core/dist/claude/complete.js
|
|
73
73
|
var DEFAULT_MAX_CONTINUATIONS = 5;
|
|
74
74
|
var CONTINUATION_USER_MESSAGE = "Continue exactly where you left off. Do not repeat any text already written, and do not add any preamble or commentary \u2014 resume the previous response verbatim from the exact cutoff point.";
|
|
75
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 24e4;
|
|
75
76
|
async function createCompleteMessage(claude, params, { maxContinuations = DEFAULT_MAX_CONTINUATIONS, timeoutMs, signal } = {}) {
|
|
76
77
|
let fullText = "";
|
|
77
78
|
let usage = ZERO_USAGE;
|
|
78
|
-
const requestOptions =
|
|
79
|
+
const requestOptions = {
|
|
80
|
+
timeout: timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
81
|
+
...signal !== void 0 ? { signal } : {}
|
|
82
|
+
};
|
|
79
83
|
for (let attempt = 0; attempt <= maxContinuations; attempt++) {
|
|
80
84
|
const messages = fullText ? [
|
|
81
85
|
...params.messages,
|
package/dist/sync-onboarding.js
CHANGED
|
@@ -72,10 +72,14 @@ function createClaudeClient(apiKey) {
|
|
|
72
72
|
// ../../modules/core/dist/claude/complete.js
|
|
73
73
|
var DEFAULT_MAX_CONTINUATIONS = 5;
|
|
74
74
|
var CONTINUATION_USER_MESSAGE = "Continue exactly where you left off. Do not repeat any text already written, and do not add any preamble or commentary \u2014 resume the previous response verbatim from the exact cutoff point.";
|
|
75
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 24e4;
|
|
75
76
|
async function createCompleteMessage(claude, params, { maxContinuations = DEFAULT_MAX_CONTINUATIONS, timeoutMs, signal } = {}) {
|
|
76
77
|
let fullText = "";
|
|
77
78
|
let usage = ZERO_USAGE;
|
|
78
|
-
const requestOptions =
|
|
79
|
+
const requestOptions = {
|
|
80
|
+
timeout: timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
81
|
+
...signal !== void 0 ? { signal } : {}
|
|
82
|
+
};
|
|
79
83
|
for (let attempt = 0; attempt <= maxContinuations; attempt++) {
|
|
80
84
|
const messages = fullText ? [
|
|
81
85
|
...params.messages,
|
|
@@ -164,8 +168,8 @@ function buildOnboardingGuidePrompt(input) {
|
|
|
164
168
|
"",
|
|
165
169
|
input.currentState ? `--- Current state ---
|
|
166
170
|
${input.currentState}` : "",
|
|
167
|
-
input.
|
|
168
|
-
${input.
|
|
171
|
+
input.canonicalDocs ? `--- Canonical docs ---
|
|
172
|
+
${input.canonicalDocs}` : "",
|
|
169
173
|
input.decisions.length > 0 ? `--- Decisions ---
|
|
170
174
|
${input.decisions.join("\n\n")}` : "",
|
|
171
175
|
"",
|
|
@@ -268,19 +272,19 @@ function isNotFound2(error) {
|
|
|
268
272
|
return typeof error === "object" && error !== null && "status" in error && error.status === 404;
|
|
269
273
|
}
|
|
270
274
|
|
|
271
|
-
// ../../modules/devlore/dist/
|
|
272
|
-
function
|
|
273
|
-
return `projects/${projectName}/
|
|
275
|
+
// ../../modules/devlore/dist/canonicalDocs.js
|
|
276
|
+
function canonicalDocsPath(projectName) {
|
|
277
|
+
return `projects/${projectName}/canonical/README.md`;
|
|
274
278
|
}
|
|
275
|
-
async function
|
|
276
|
-
return (await
|
|
279
|
+
async function getCanonicalDocs(octokit, params) {
|
|
280
|
+
return (await getCanonicalDocsFile(octokit, params)).content;
|
|
277
281
|
}
|
|
278
|
-
async function
|
|
282
|
+
async function getCanonicalDocsFile(octokit, { owner, repo, projectName }) {
|
|
279
283
|
try {
|
|
280
284
|
const { data } = await octokit.rest.repos.getContent({
|
|
281
285
|
owner,
|
|
282
286
|
repo,
|
|
283
|
-
path:
|
|
287
|
+
path: canonicalDocsPath(projectName)
|
|
284
288
|
});
|
|
285
289
|
if (Array.isArray(data) || data.type !== "file") {
|
|
286
290
|
return { content: "" };
|
|
@@ -360,15 +364,15 @@ async function readVaultFile(octokit, owner, repo, path) {
|
|
|
360
364
|
return data && !Array.isArray(data) && data.type === "file" ? Buffer.from(data.content, "base64").toString("utf-8") : "";
|
|
361
365
|
}
|
|
362
366
|
async function syncOnboarding({ projectOctokit, vaultOctokit, claude, projectOwner, projectRepoName, vaultOwner, vaultRepoName, projectName }) {
|
|
363
|
-
const [currentState,
|
|
367
|
+
const [currentState, canonicalDocs, entries] = await Promise.all([
|
|
364
368
|
readVaultFile(vaultOctokit, vaultOwner, vaultRepoName, currentStatePath(projectName)),
|
|
365
|
-
|
|
369
|
+
getCanonicalDocs(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName }).catch(() => ""),
|
|
366
370
|
listDecisionEntries(vaultOctokit, { owner: vaultOwner, repo: vaultRepoName, projectName }).catch(() => [])
|
|
367
371
|
]);
|
|
368
372
|
const prompt = buildOnboardingGuidePrompt({
|
|
369
373
|
projectName,
|
|
370
374
|
currentState: redactText(currentState),
|
|
371
|
-
|
|
375
|
+
canonicalDocs: redactText(canonicalDocs),
|
|
372
376
|
decisions: entries.map((entry) => redactText(entry.content))
|
|
373
377
|
});
|
|
374
378
|
const { text, usage } = await createCompleteMessage(claude, { model: defaultModelFor(MODEL_TIER), max_tokens: MAX_TOKENS, messages: [{ role: "user", content: prompt }] }, { maxContinuations: MAX_CONTINUATIONS });
|