Merge pull request #349 from pikasTech/fix/artificer-source-override
Pipelines as Code CI / agentrun-nc01-v02-ci-846e3c0ff3a18198360dcfeea4040441f1830e62 Success

fix: 强制 Artificer 使用 Target 透传执行边界
This commit is contained in:
Lyon
2026-07-13 15:33:21 +08:00
committed by GitHub
2 changed files with 25 additions and 1 deletions
+6
View File
@@ -117,6 +117,7 @@ spec:
- name: unidesk-gh
- name: unidesk-code-queue
- name: unidesk-cicd
- name: unidesk-subagent
- name: unidesk-decision
- name: unidesk-ops
- name: unidesk-sub2api
@@ -128,6 +129,11 @@ spec:
你就是当前已派发任务的 Artificer 执行者,必须按任务要求直接完成工作;仅在任务需要源码修改时,才在 primary workspace 完成修改、测试和 PR。
禁止通过 `agentrun create`、`agentrun apply`、`agentrun dispatch`、Code Queue 或任何等价入口创建或派发另一个 Artificer 来完成当前任务。
允许只读查询 AgentRun task、session 和 run 状态;只读查询不属于二次派单。
派单 prompt 必须提供“任务目标上下文”,其中包含 MDTODO ID、Target、targetWorkspace、repository 和 ref;这些字段是目标操作的唯一定位事实,缺失时必须在写入前返回可操作错误,禁止猜测运行位置。
primary workspace 只用于读取随资源包提供的工具与 skill,以及完成任务明确授权的本地轻量准备;不得把 runner 容器本地执行冒充 Target 原入口验证。
凡面向任务 Target 的现场探测、命令执行、验证、远端文本修改、Git 操作和运行面观察,都必须使用 `trans <Target>:<targetWorkspace> <operation>` 或对应 k3s route`targetWorkspace` 必须是绝对路径,目标文本修改使用 `trans <route> apply-patch`。
Target、targetWorkspace、repository 和 ref 必须来自任务上下文,不得把 NC01、目标绝对路径或第二条执行路径硬编码到实现中。
最终报告必须回链任务上下文中的 MDTODO ID,并区分 primary workspace 轻量准备与 Target 原入口证据。
遵循随资源包提供的 dad-dev 与 UniDesk skills;执行高风险或长时间操作前,先向相关 GitHub issue 报告进展。
references: []
metadata:
@@ -18,6 +18,12 @@ const selfTest: SelfTestCase = async (context) => {
updatedAt: "2026-01-01T00:00:00.000Z",
}, { prompt: userPrompt });
const effectivePrompt = String(((rendered.queueTask as JsonRecord).payload as JsonRecord).prompt);
const executionPolicy = (rendered.queueTask as JsonRecord).executionPolicy as JsonRecord;
const secretScope = executionPolicy.secretScope as JsonRecord;
const toolCredentials = secretScope.toolCredentials as JsonRecord[];
const resourceBundleRef = (rendered.queueTask as JsonRecord).resourceBundleRef as JsonRecord;
const requiredSkills = resourceBundleRef.requiredSkills as JsonRecord[];
const bundles = resourceBundleRef.bundles as JsonRecord[];
assert.match(effectivePrompt, / Artificer /u);
assert.match(effectivePrompt, //u);
@@ -28,10 +34,22 @@ const selfTest: SelfTestCase = async (context) => {
assert.match(effectivePrompt, /agentrun dispatch/u);
assert.match(effectivePrompt, /Code Queue/u);
assert.match(effectivePrompt, / AgentRun tasksession run /u);
assert.match(effectivePrompt, //u);
assert.match(effectivePrompt, /MDTODO IDTargettargetWorkspacerepository ref/u);
assert.match(effectivePrompt, /trans <Target>:<targetWorkspace>/u);
assert.match(effectivePrompt, /targetWorkspace` /u);
assert.match(effectivePrompt, /runner Target /u);
assert.match(effectivePrompt, / NC01/u);
assert.ok(requiredSkills.some((item) => item.name === "unidesk-trans"), "Artificer must require the unidesk-trans skill");
assert.ok(bundles.some((item) => item.name === "agentrun-runner-tools" && item.targetPath === "tools"), "Artificer must materialize the bundled trans executable");
const unideskSsh = toolCredentials.find((item) => item.tool === "unidesk-ssh" && item.purpose === "ssh-passthrough");
assert.ok(unideskSsh, "Artificer must bind the unidesk-ssh route credential");
assert.deepEqual((unideskSsh.secretRef as JsonRecord).keys, ["UNIDESK_SSH_CLIENT_TOKEN"]);
assert.equal((unideskSsh.projection as JsonRecord).envName, "UNIDESK_SSH_CLIENT_TOKEN");
assert.equal(effectivePrompt.endsWith(userPrompt), true, "rendered prompt must preserve the complete user business prompt");
assert.equal(effectivePrompt.split(userPrompt).length - 1, 1, "rendered prompt must include the user business prompt exactly once");
return { name: "artificer-nonrecursive-prompt", tests: ["artificer-yaml-nonrecursive-prompt-render", "artificer-user-prompt-preserved"] };
return { name: "artificer-nonrecursive-prompt", tests: ["artificer-yaml-nonrecursive-prompt-render", "artificer-target-trans-prompt-render", "artificer-trans-skill-tool-and-secretref-bound", "artificer-user-prompt-preserved"] };
};
export default selfTest;