fix: preserve auto-captured skill updates

This commit is contained in:
Shakker
2026-05-30 17:23:57 +01:00
committed by Shakker
parent 3a9e7dfa1a
commit 0b49710e8d
2 changed files with 71 additions and 2 deletions

View File

@@ -1,7 +1,13 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { captureEnv } from "../../test-utils/env.js";
import { createTrackedTempDirs } from "../../test-utils/tracked-temp-dirs.js";
import { inspectSkillProposal, listSkillProposals } from "../workshop/service.js";
import {
applySkillProposal,
inspectSkillProposal,
listSkillProposals,
} from "../workshop/service.js";
import { runSkillResearchAutoCapture } from "./autocapture.js";
const tempDirs = createTrackedTempDirs();
@@ -88,4 +94,61 @@ describe("skill research auto-capture", () => {
expect((await listSkillProposals({ workspaceDir })).proposals).toHaveLength(0);
});
it("preserves existing skill content when auto-capturing an update", async () => {
const workspaceDir = await makeWorkspace();
const skillFile = path.join(workspaceDir, "skills", "github-pr-workflow", "SKILL.md");
await fs.mkdir(path.dirname(skillFile), { recursive: true });
await fs.writeFile(
skillFile,
[
"---",
'name: "github-pr-workflow"',
'description: "Existing GitHub PR workflow."',
"---",
"",
"# GitHub PR Workflow",
"",
"- Preserve this original review checklist.",
"",
].join("\n"),
"utf8",
);
await runSkillResearchAutoCapture({
event: {
success: true,
messages: [
{
role: "user",
content:
"From now on, when working on GitHub PRs, always check CI before final response.",
},
],
},
ctx: { workspaceDir, agentId: "main" },
config: {
skills: {
workshop: {
autonomous: {
enabled: true,
},
},
},
},
});
const proposals = await listSkillProposals({ workspaceDir });
expect(proposals.proposals).toHaveLength(1);
expect(proposals.proposals[0]).toMatchObject({
kind: "update",
status: "pending",
skillKey: "github-pr-workflow",
});
await applySkillProposal({ workspaceDir, proposalId: proposals.proposals[0].id });
const updatedSkill = await fs.readFile(skillFile, "utf8");
expect(updatedSkill).toContain("Preserve this original review checklist.");
expect(updatedSkill).toContain("always check CI before final response");
});
});

View File

@@ -17,6 +17,12 @@ type SkillResearchAgentContext = {
const log = createSubsystemLogger("skills/research");
function buildAutoCaptureUpdateContent(existingSkill: string, capturedContent: string): string {
return [existingSkill.trimEnd(), "", "## Captured Update", "", capturedContent.trim(), ""].join(
"\n",
);
}
export async function runSkillResearchAutoCapture(params: {
event: SkillResearchAgentEndEvent;
ctx: SkillResearchAgentContext;
@@ -73,7 +79,7 @@ export async function runSkillResearchAutoCapture(params: {
config: params.config,
agentId: params.ctx.agentId,
skillName: proposal.skillName,
content: proposal.content,
content: buildAutoCaptureUpdateContent(existingSkill, proposal.content),
createdBy: "skill-workshop",
goal: proposal.goal,
evidence: proposal.evidence,