Merge pull request #732 from pikasTech/fix/issue729-agentrun-prompt-planner

fix: route AgentRun prompt changes to cloud-api rollout
This commit is contained in:
Lyon
2026-06-03 07:26:32 +08:00
committed by GitHub
2 changed files with 58 additions and 0 deletions
+54
View File
@@ -161,6 +161,8 @@ test("component model uses built-in service paths", () => {
"cmd/hwlab-cloud-api/",
"cmd/hwlab-codex-api-responses-forwarder/",
"cmd/hwlab-deepseek-responses-bridge/",
"internal/agent/agentrun-dispatch.mjs",
"internal/agent/prompts/",
"internal/audit/",
"internal/cloud/",
"internal/db/",
@@ -169,6 +171,58 @@ test("component model uses built-in service paths", () => {
assert.deepEqual(matchingPaths(["cmd/hwlab-cloud-api/main.ts"], models[0].componentPaths), ["cmd/hwlab-cloud-api/main.ts"]);
});
test("v02 planner treats AgentRun runtime prompt changes as cloud-api inputs", async () => {
const repo = await createFixtureRepo({ includeDevicePod: true });
await mkdir(path.join(repo, "internal/agent/prompts"), { recursive: true });
await writeFile(path.join(repo, "internal/agent/agentrun-dispatch.mjs"), "export const prompt = true;\n");
await writeFile(path.join(repo, "internal/agent/prompts/hwlab-v02-runtime.md"), "prompt v1\n");
await git(repo, ["add", "."]);
await git(repo, ["commit", "-m", "seed agentrun prompt"]);
const initialSha = (await git(repo, ["rev-parse", "HEAD"])).stdout.trim();
const initialPlan = await createG14CiPlan({
repoRoot: repo,
lane: "v02",
baseRef: "HEAD",
targetRef: initialSha,
artifactCatalogPath: "deploy/artifact-catalog.v02.json",
services: ["hwlab-cloud-api", "hwlab-cloud-web", "hwlab-device-pod"]
});
const initialCloudWeb = initialPlan.services.find((service) => service.serviceId === "hwlab-cloud-web");
const initialDevicePod = initialPlan.services.find((service) => service.serviceId === "hwlab-device-pod");
const initialHashes = Object.fromEntries(initialPlan.services.map((service) => [service.serviceId, service.componentInputHash]));
await writeFile(path.join(repo, "deploy/artifact-catalog.v02.json"), JSON.stringify(createCatalogFixture("ready", {
sourceCommitId: initialPlan.sourceCommitId,
componentInputHashes: initialHashes,
cloudWebEnvironmentInputHash: initialCloudWeb.environmentInputHash,
cloudWebCodeInputHash: initialCloudWeb.codeInputHash,
cloudWebBootCommit: initialPlan.sourceCommitId,
devicePodEnvironmentInputHash: initialDevicePod.environmentInputHash,
devicePodCodeInputHash: initialDevicePod.codeInputHash,
devicePodBootCommit: initialPlan.sourceCommitId
}), null, 2));
await git(repo, ["add", "deploy/artifact-catalog.v02.json"]);
await git(repo, ["commit", "-m", "seed v02 catalog with agentrun prompt"]);
await writeFile(path.join(repo, "internal/agent/prompts/hwlab-v02-runtime.md"), "prompt v2\n");
await git(repo, ["add", "internal/agent/prompts/hwlab-v02-runtime.md"]);
await git(repo, ["commit", "-m", "change agentrun prompt"]);
const plan = await createG14CiPlan({
repoRoot: repo,
lane: "v02",
baseRef: "HEAD~1",
targetRef: "HEAD",
artifactCatalogPath: "deploy/artifact-catalog.v02.json",
services: ["hwlab-cloud-api", "hwlab-cloud-web", "hwlab-device-pod"]
});
assert.deepEqual(plan.affectedServices, ["hwlab-cloud-api"]);
assert.deepEqual(plan.buildServices, ["hwlab-cloud-api"]);
assert.deepEqual(plan.rolloutServices, ["hwlab-cloud-api"]);
const cloudApi = plan.services.find((service) => service.serviceId === "hwlab-cloud-api");
assert.deepEqual(cloudApi.changedPaths, ["internal/agent/prompts/hwlab-v02-runtime.md"]);
assert.deepEqual(cloudApi.reason, ["component-path-changed"]);
});
test("planner scopes cloud-web runtime changes to cloud-web", async () => {
const repo = await createFixtureRepo();
await writeFile(path.join(repo, "internal/dev-entrypoint/cloud-web-runtime.mjs"), "export const runtime = 2;\n");
+4
View File
@@ -71,6 +71,8 @@ const serviceSpecificPaths = Object.freeze({
"internal/cloud/",
"internal/db/",
"internal/audit/",
"internal/agent/agentrun-dispatch.mjs",
"internal/agent/prompts/",
"skills/hwlab-agent-runtime/"
],
"hwlab-cloud-web": [
@@ -438,6 +440,8 @@ export function isTestOnlyPath(filePath) {
export function isDocsOnlyPath(filePath) {
const normalized = normalizeRepoPath(filePath);
if (normalized.startsWith("internal/agent/prompts/")) return false;
if (normalized.startsWith("skills/")) return false;
return DEFAULT_DOCS_ONLY_PATHS.some((pattern) => pathMatches(pattern, normalized)) || normalized.endsWith(".md");
}