fix: 对齐NapCat自动化入口默认值

This commit is contained in:
sunlei 2026-06-25 01:52:13 +08:00
parent 6fc5e65986
commit fc750ddcf1
5 changed files with 194 additions and 64 deletions

View File

@ -44,6 +44,7 @@ pnpm run workstream-closeout -- --title "发布闭环" --verification "Jenkins S
pnpm run napcat-upstream-audit -- --artifact-root .kt-workspace/test-artifacts/napcat-upstream-sync
pnpm run napcat-sync-candidate-review
pnpm run napcat-runtime-release-readiness
pnpm run napcat-remote-dev-handoff
pnpm run nas-codex-bootstrap
pnpm run napcat-device-profile-check
pnpm run cleanup-history -- --dry-run
@ -126,6 +127,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
| `pnpm run napcat-upstream-audit` | 默认 dry-run 输出 NapCatQQ 上游 release 审计分类、只读 Git 命令和 artifact 路径;显式 `--execute --use-codex` 才运行 Codex。 |
| `pnpm run napcat-sync-candidate-review` | 输出 sync candidate review 的 prompt/context/只读命令骨架,不执行 Codex 或 Git 写操作。 |
| `pnpm run napcat-runtime-release-readiness` | 输出 runtime release readiness 的 prompt/context/只读检查骨架,不构建镜像、不调用 kubectl、不发布。 |
| `pnpm run napcat-remote-dev-handoff` | 输出远程开发 handoff 的 prompt/context 骨架,不创建线程、不同步仓库、不执行 Codex。 |
| `pnpm run nas-codex-bootstrap` | 输出可信 NAS Codex bootstrap dry-run plan真实安装、同步和 systemd 接入留给后续实现。 |
| `pnpm run napcat-device-profile-check` | 静态检查 API NapCat 设备身份护栏,防止回退到未知设备风险配置。 |
| `pnpm run deploy-observation` | 默认 dry-run 输出只读 NAS 观测命令;传 `--execute` 时执行 Jenkins/K8s/health/smoke 观测并写入 `.kt-workspace/test-artifacts/deploy-observation`。 |

View File

@ -10,6 +10,7 @@
"deploy-observation": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --deploy-observation",
"global-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --global-review",
"napcat-device-profile-check": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-device-profile-check",
"napcat-remote-dev-handoff": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-remote-dev-handoff",
"napcat-runtime-release-readiness": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-runtime-release-readiness",
"napcat-sync-candidate-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-sync-candidate-review",
"napcat-upstream-audit": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-upstream-audit",

View File

@ -28,6 +28,7 @@ import {
buildNapcatSyncCandidateReview,
buildNapcatUpstreamAudit,
buildNasCodexBootstrapPlan,
napcatAutomationDefaults,
} from './tools/napcatAutomation.js';
import { buildCommitPlan, buildComponentWorkflow, buildDbSyncPlan, buildFinishTask, buildPushPlan, buildRemoteHealthCheck } from './tools/workflow.js';
import { workstreamReusablePatternValues } from './core/constants.js';
@ -395,16 +396,18 @@ export function registerTools(server: McpServer): void {
createCandidateBranch: z.boolean().default(false),
dryMergeConflict: z.boolean().default(false),
execute: z.boolean().default(false),
forkBranch: z.string().default('HEAD'),
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
forkPatchFiles: z.array(z.string()).default([]),
forkRepo: z.string().default('KTeam/NapCatQQ'),
lastAcceptedUpstreamBase: z.string().default('origin/main'),
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
lastAcceptedUpstreamBase: z
.string()
.default(napcatAutomationDefaults.lastAcceptedUpstreamBase),
outputSchemaPath: z.string().optional(),
upstreamChangedFiles: z.array(z.string()).default([]),
upstreamReleaseTag: z.string().default('upstream/main'),
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
useCodex: z.boolean().default(false),
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
},
title: 'KT NapCat Upstream Audit',
},
@ -420,15 +423,17 @@ export function registerTools(server: McpServer): void {
artifactRoot: z
.string()
.default('.kt-workspace/test-artifacts/napcat-automation/sync-candidate-review'),
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
execute: z.boolean().default(false),
forkBranch: z.string().default('dev'),
forkRepo: z.string().default('KTeam/NapCatQQ'),
lastAcceptedUpstreamBase: z.string().default('origin/main'),
upstreamReleaseTag: z.string().default('upstream/main'),
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
lastAcceptedUpstreamBase: z
.string()
.default(napcatAutomationDefaults.lastAcceptedUpstreamBase),
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
useCodex: z.boolean().default(false),
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
},
title: 'KT NapCat Sync Candidate Review',
},
@ -441,20 +446,20 @@ export function registerTools(server: McpServer): void {
description:
'生成 NapCat runtime release readiness dry-run prompt、上下文和只读检查骨架不自动构建镜像、不调用 kubectl、不发布。',
inputSchema: {
apiImageTag: z.string().default('main-<jenkins-build>'),
apiImageTag: z.string().default(napcatAutomationDefaults.apiImageTag),
artifactRoot: z
.string()
.default('.kt-workspace/test-artifacts/napcat-automation/runtime-release-readiness'),
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
execute: z.boolean().default(false),
forkBranch: z.string().default('dev'),
forkRepo: z.string().default('KTeam/NapCatQQ'),
napcatImageTag: z.string().default('kt-napcat-desktop-cn:desktop-cn'),
profile: z.string().default('desktop-cn'),
upstreamReleaseTag: z.string().default('upstream/main'),
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
napcatImageTag: z.string().default(napcatAutomationDefaults.runtimeImageTag),
profile: z.string().default(napcatAutomationDefaults.runtimeProfile),
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
useCodex: z.boolean().default(false),
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
},
title: 'KT NapCat Runtime Release Readiness',
},
@ -470,15 +475,15 @@ export function registerTools(server: McpServer): void {
artifactRoot: z
.string()
.default('.kt-workspace/test-artifacts/napcat-automation/remote-dev-handoff'),
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
execute: z.boolean().default(false),
forkBranch: z.string().default('dev'),
forkRepo: z.string().default('KTeam/NapCatQQ'),
targetHost: z.string().default('nas'),
upstreamReleaseTag: z.string().default('upstream/main'),
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
targetHost: z.string().default(napcatAutomationDefaults.targetHost),
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
useCodex: z.boolean().default(false),
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
},
title: 'KT NapCat Remote Dev Handoff',
},
@ -494,10 +499,10 @@ export function registerTools(server: McpServer): void {
artifactRoot: z
.string()
.default('.kt-workspace/test-artifacts/napcat-automation/nas-codex-bootstrap'),
codexHome: z.string().default('/vol1/docker/kt-codex/home/.codex'),
codexHome: z.string().default(napcatAutomationDefaults.codexHome),
execute: z.boolean().default(false),
serviceName: z.string().default('kt-codex-automation'),
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
serviceName: z.string().default(napcatAutomationDefaults.bootstrapServiceName),
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
},
title: 'KT NAS Codex Bootstrap Plan',
},

View File

@ -5,6 +5,7 @@ import {
parseNasCodexBootstrapCliArgs,
parseDeployObservationCliArgs,
parseGlobalReviewCliArgs,
parseNapcatRemoteDevHandoffCliArgs,
parseNapcatRuntimeReleaseReadinessCliArgs,
parseNapcatSyncCandidateReviewCliArgs,
parseNapcatUpstreamAuditCliArgs,
@ -46,9 +47,15 @@ import {
} from "./tools/napcatAutomation.types.js";
import {
buildNapcatCodexExecCommand,
buildNapcatRemoteDevHandoff,
buildNapcatRuntimeReleaseReadiness,
buildNapcatSyncCandidateReview,
buildNapcatUpstreamAudit,
buildNasCodexBootstrapPlan,
classifyNapcatUpstreamAudit,
napcatAutomationDefaults,
} from "./tools/napcatAutomation.js";
import { registerTools } from "./registerTools.js";
import {
loadNapcatAutomationPrompt,
type NapcatAutomationPromptName,
@ -128,6 +135,11 @@ export async function runSelfTest(): Promise<void> {
"server",
"--napcat-runtime-release-readiness",
]);
const napcatRemoteHandoffCli = parseNapcatRemoteDevHandoffCliArgs([
"node",
"server",
"--napcat-remote-dev-handoff",
]);
const nasBootstrapCli = parseNasCodexBootstrapCliArgs([
"node",
"server",
@ -136,10 +148,85 @@ export async function runSelfTest(): Promise<void> {
if (
napcatCandidateCli.execute ||
napcatRuntimeCli.execute ||
napcatRemoteHandoffCli.execute ||
nasBootstrapCli.execute
) {
throw new Error("NapCat auxiliary CLI dry-run default self-check failed");
}
const napcatCandidateDefaults = buildNapcatSyncCandidateReview({}).context;
const napcatRuntimeDefaults = buildNapcatRuntimeReleaseReadiness({}).context;
const napcatRemoteDefaults = buildNapcatRemoteDevHandoff({}).context;
const nasBootstrapDefaults = buildNasCodexBootstrapPlan({}).context;
if (
napcatCandidateDefaults.candidateBranch !==
napcatAutomationDefaults.candidateBranch ||
napcatCandidateDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
napcatCandidateDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
napcatCandidateDefaults.lastAcceptedUpstreamBase !==
napcatAutomationDefaults.lastAcceptedUpstreamBase ||
napcatCandidateDefaults.upstreamReleaseTag !==
napcatAutomationDefaults.upstreamReleaseRef ||
napcatCandidateDefaults.upstreamRepo !== napcatAutomationDefaults.upstreamRepo ||
napcatCandidateDefaults.workspaceRoot !==
napcatAutomationDefaults.workspaceRoot
) {
throw new Error("NapCat candidate review default alignment self-check failed");
}
if (
napcatRuntimeDefaults.apiImageTag !==
napcatAutomationDefaults.apiImageTag ||
napcatRuntimeDefaults.candidateBranch !==
napcatAutomationDefaults.candidateBranch ||
napcatRuntimeDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
napcatRuntimeDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
napcatRuntimeDefaults.napcatImageTag !==
napcatAutomationDefaults.runtimeImageTag ||
napcatRuntimeDefaults.profile !== napcatAutomationDefaults.runtimeProfile ||
napcatRuntimeDefaults.upstreamReleaseTag !==
napcatAutomationDefaults.upstreamReleaseRef ||
napcatRuntimeDefaults.workspaceRoot !==
napcatAutomationDefaults.workspaceRoot
) {
throw new Error("NapCat runtime readiness default alignment self-check failed");
}
if (
napcatRemoteDefaults.candidateBranch !==
napcatAutomationDefaults.candidateBranch ||
napcatRemoteDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
napcatRemoteDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
napcatRemoteDefaults.targetHost !== napcatAutomationDefaults.targetHost ||
napcatRemoteDefaults.upstreamReleaseTag !==
napcatAutomationDefaults.upstreamReleaseRef ||
napcatRemoteDefaults.workspaceRoot !== napcatAutomationDefaults.workspaceRoot
) {
throw new Error("NapCat remote handoff default alignment self-check failed");
}
if (
nasBootstrapDefaults.codexHome !== napcatAutomationDefaults.codexHome ||
nasBootstrapDefaults.serviceName !==
napcatAutomationDefaults.bootstrapServiceName ||
nasBootstrapDefaults.workspaceRoot !== napcatAutomationDefaults.workspaceRoot
) {
throw new Error("NAS Codex bootstrap default alignment self-check failed");
}
const packageJson = JSON.parse(
readFileSync(resolveInsideRoot("mcp/ktWorkflow/package.json"), "utf8"),
) as { scripts?: Record<string, string> };
if (!packageJson.scripts?.["napcat-remote-dev-handoff"]) {
throw new Error("NapCat remote handoff npm script self-check failed");
}
const registeredByFakeServer: string[] = [];
const fakeMcpServer = {
/**
* Records registered MCP tool names so self-test proves the actual registerTools surface, not only the constants list.
* @param name - MCP tool name passed by `registerTools`.
* @returns Nothing; the name is appended to `registeredByFakeServer`.
*/
registerTool(name: string): void {
registeredByFakeServer.push(name);
},
};
registerTools(fakeMcpServer as never);
for (const toolName of [
"kt_napcat_upstream_audit",
"kt_napcat_sync_candidate_review",
@ -150,6 +237,9 @@ export async function runSelfTest(): Promise<void> {
if (!registeredToolNames.includes(toolName)) {
throw new Error(`NapCat MCP tool registry self-check failed: ${toolName}`);
}
if (!registeredByFakeServer.includes(toolName)) {
throw new Error(`NapCat MCP registerTools self-check failed: ${toolName}`);
}
}
if (parseNapcatAutomationClassification("manual-review") !== "manual-review") {
throw new Error("NapCat classification parser self-check failed");
@ -175,6 +265,24 @@ export async function runSelfTest(): Promise<void> {
"NapCat upstream audit dry-run artifact plan self-check failed",
);
}
const dryRunAuditDefaultCommands = dryRunAudit.commands.map(
(item) => item.command,
);
if (
dryRunAuditDefaultCommands.some((command) =>
command.includes("FORK_BRANCH:-HEAD"),
) ||
!dryRunAuditDefaultCommands.some((command) =>
command.includes(`FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}`),
) ||
!dryRunAuditDefaultCommands.some((command) =>
command.includes(
`UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}`,
),
)
) {
throw new Error("NapCat upstream audit command default alignment self-check failed");
}
const codexCommand = buildNapcatCodexExecCommand({
artifactRoot: "/vol1/docker/kt-codex/artifacts/smoke",
contextPacketPath:

View File

@ -100,10 +100,22 @@ const napcatNasCodexArtifactRoot = '/vol1/docker/kt-codex/artifacts';
const napcatLocalArtifactRoot = '.kt-workspace/test-artifacts';
const napcatAutomationSkeletonArtifactRoot =
'.kt-workspace/test-artifacts/napcat-automation';
const defaultNapcatForkRepo = 'KTeam/NapCatQQ';
const defaultNapcatUpstreamRepo = 'NapNeko/NapCatQQ';
const defaultNapcatCandidateBranch = 'napcat-upstream-sync/candidate';
const defaultNapcatWorkspaceRoot = '/vol1/docker/kt-codex/workspace/KT';
export const napcatAutomationDefaults = {
apiImageTag: 'main-<jenkins-build>',
bootstrapServiceName: 'kt-codex-automation',
candidateBranch: 'napcat-upstream-sync/candidate',
codexHome: '/vol1/docker/kt-codex/home/.codex',
forkBranch: 'dev',
forkRepo: 'KTeam/NapCatQQ',
lastAcceptedUpstreamBase: 'origin/main',
runtimeImageTag: 'kt-napcat-desktop-cn:desktop-cn',
runtimeProfile: 'desktop-cn',
targetHost: 'nas',
upstreamReleaseRef: 'upstream/main',
upstreamRepo: 'NapNeko/NapCatQQ',
workspaceRoot: '/vol1/docker/kt-codex/workspace/KT',
} as const;
interface NapcatPromptSkeletonConfig {
artifactSlug: string;
@ -189,14 +201,14 @@ export function buildNapcatSyncCandidateReview(
input: NapcatSyncCandidateReviewInput,
) {
const context = {
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
forkBranch: input.forkBranch ?? 'dev',
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
lastAcceptedUpstreamBase:
input.lastAcceptedUpstreamBase ?? 'LAST_ACCEPTED_UPSTREAM_BASE',
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
upstreamRepo: input.upstreamRepo ?? defaultNapcatUpstreamRepo,
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
input.lastAcceptedUpstreamBase ?? napcatAutomationDefaults.lastAcceptedUpstreamBase,
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
upstreamRepo: input.upstreamRepo ?? napcatAutomationDefaults.upstreamRepo,
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
};
return buildNapcatPromptSkeleton({
@ -209,13 +221,13 @@ export function buildNapcatSyncCandidateReview(
},
{
command:
'git log --oneline --decorate -n 20 "${CANDIDATE_BRANCH:-napcat-upstream-sync/candidate}"',
`git log --oneline --decorate -n 20 "\${CANDIDATE_BRANCH:-${napcatAutomationDefaults.candidateBranch}}"`,
description: 'Inspect recent candidate commits without changing refs.',
readOnly: true,
},
{
command:
'git diff --stat "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..${CANDIDATE_BRANCH:-napcat-upstream-sync/candidate}"',
`git diff --stat "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${CANDIDATE_BRANCH:-${napcatAutomationDefaults.candidateBranch}}"`,
description: 'Summarize candidate file churn for human review.',
readOnly: true,
},
@ -239,13 +251,14 @@ export function buildNapcatRuntimeReleaseReadiness(
input: NapcatRuntimeReleaseReadinessInput,
) {
const context = {
apiImageTag: input.apiImageTag ?? 'main-<jenkins-build>',
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
napcatImageTag: input.napcatImageTag ?? 'kt-napcat-desktop-cn:<profile>',
profile: input.profile ?? 'desktop-cn',
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
apiImageTag: input.apiImageTag ?? napcatAutomationDefaults.apiImageTag,
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
napcatImageTag: input.napcatImageTag ?? napcatAutomationDefaults.runtimeImageTag,
profile: input.profile ?? napcatAutomationDefaults.runtimeProfile,
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
};
return buildNapcatPromptSkeleton({
@ -288,11 +301,12 @@ export function buildNapcatRemoteDevHandoff(
input: NapcatRemoteDevHandoffInput,
) {
const context = {
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
targetHost: input.targetHost ?? 'nas',
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
targetHost: input.targetHost ?? napcatAutomationDefaults.targetHost,
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
};
return buildNapcatPromptSkeleton({
@ -329,9 +343,9 @@ export function buildNasCodexBootstrapPlan(input: NasCodexBootstrapPlanInput) {
input.artifactRoot?.trim() ||
`${napcatAutomationSkeletonArtifactRoot}/nas-codex-bootstrap`;
const context = {
codexHome: input.codexHome ?? '/vol1/docker/kt-codex/home/.codex',
serviceName: input.serviceName ?? 'kt-codex-automation',
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
codexHome: input.codexHome ?? napcatAutomationDefaults.codexHome,
serviceName: input.serviceName ?? napcatAutomationDefaults.bootstrapServiceName,
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
};
const requestedExecute = input.execute === true;
@ -532,7 +546,7 @@ function assertSafeNapcatCodexArtifactRoot(artifactRoot: string): void {
* @returns The configured workspace root or the stabilized NAS kt-codex workspace path.
*/
function resolveNapcatCodexWorkspaceRoot(workspaceRoot?: string): string {
return workspaceRoot?.trim() || '/vol1/docker/kt-codex/workspace/KT';
return workspaceRoot?.trim() || napcatAutomationDefaults.workspaceRoot;
}
/**
@ -1028,19 +1042,19 @@ export function buildNapcatUpstreamAudit(
},
{
command:
'git diff --name-only "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..${UPSTREAM_RELEASE_REF:-upstream/main}"',
`git diff --name-only "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}}"`,
description: 'List upstream release files changed since the last accepted base.',
readOnly: true,
},
{
command:
'git diff --name-only "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..HEAD"',
`git diff --name-only "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}}"`,
description: 'List KT fork patch files for deterministic overlap checks.',
readOnly: true,
},
{
command:
'git merge-tree "${FORK_BRANCH:-HEAD}" "${UPSTREAM_RELEASE_REF:-upstream/main}"',
`git merge-tree "\${FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}}" "\${UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}}"`,
description: 'Probe the dry merge shape without updating the worktree or refs.',
readOnly: true,
},