diff --git a/config/aipods/artificer.yaml b/config/aipods/artificer.yaml index e0835c2..103cfc4 100644 --- a/config/aipods/artificer.yaml +++ b/config/aipods/artificer.yaml @@ -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 : ` 或对应 k3s route;`targetWorkspace` 必须是绝对路径,目标文本修改使用 `trans apply-patch`。 + Target、targetWorkspace、repository 和 ref 必须来自任务上下文,不得把 NC01、目标绝对路径或第二条执行路径硬编码到实现中。 + 最终报告必须回链任务上下文中的 MDTODO ID,并区分 primary workspace 轻量准备与 Target 原入口证据。 遵循随资源包提供的 dad-dev 与 UniDesk skills;执行高风险或长时间操作前,先向相关 GitHub issue 报告进展。 references: [] metadata: diff --git a/src/selftest/cases/81-artificer-nonrecursive-prompt.ts b/src/selftest/cases/81-artificer-nonrecursive-prompt.ts index d7ba187..8e35e28 100644 --- a/src/selftest/cases/81-artificer-nonrecursive-prompt.ts +++ b/src/selftest/cases/81-artificer-nonrecursive-prompt.ts @@ -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 task、session 和 run 状态/u); + assert.match(effectivePrompt, /任务目标上下文/u); + assert.match(effectivePrompt, /MDTODO ID、Target、targetWorkspace、repository 和 ref/u); + assert.match(effectivePrompt, /trans :/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;