kt-template-online-api/docs/superpowers/plans/2026-06-24-napcatqq-upstream-sync-runtime-release-pipeline-implementation-plan.md

1037 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# NapCatQQ Upstream Sync Runtime Release Pipeline Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build a ktWorkflow-owned automation path that audits upstream NapCatQQ releases, assists review with Codex CLI, builds verified KT NapCat runtime images, and promotes them to API through explicit deployment parameters.
**Architecture:** `mcp/ktWorkflow` owns collectors, prompts, schema validation, CLI wrappers, MCP tools, and scheduler entry points. `Node/kt-template-online-api` remains the runtime image and API deployment contract owner. Jenkins and NAS timers only call ktWorkflow scripts and never duplicate the audit algorithm.
**Tech Stack:** TypeScript ESM, MCP SDK, zod, Node `child_process`, Codex CLI `exec`, Jenkins Pipeline, Docker, K8s, NestJS API runtime config, Jest.
---
## File Structure
### `D:\MyFiles\KT\mcp\ktWorkflow`
- Create `prompts/napcat/upstream-audit.md`: Codex CLI prompt for upstream release risk classification.
- Create `prompts/napcat/sync-candidate-review.md`: Codex CLI prompt for candidate branch review.
- Create `prompts/napcat/runtime-release-readiness.md`: Codex CLI prompt for image promotion readiness.
- Create `prompts/napcat/remote-dev-handoff.md`: Codex CLI prompt for NAS remote-development handoff.
- Create `prompts/napcat/schemas/upstream-audit.schema.json`: JSON Schema used by `codex exec --output-schema`.
- Create `prompts/napcat/schemas/runtime-release-readiness.schema.json`: JSON Schema for release readiness reports.
- Create `src/tools/napcatAutomation.types.ts`: zod schemas, normalized input types, artifact result types, and constants.
- Create `src/tools/napcatAutomation.prompts.ts`: prompt path resolution and prompt loading helpers.
- Create `src/tools/napcatAutomation.ts`: deterministic collectors, Codex runner, artifact writer, and public builders for tools/scripts.
- Modify `src/types.ts`: exported MCP input/result interfaces.
- Modify `src/core/cli.ts`: CLI parsers for NapCat automation scripts.
- Modify `src/registerTools.ts`: MCP tool registration.
- Modify `src/server.ts`: CLI flag dispatch.
- Modify `src/core/constants.ts`: `registeredToolNames`.
- Modify `src/selfTest.ts`: deterministic self-tests for CLI parser, audit classification, prompt/schema presence, and safe command generation.
- Modify `package.json`: scripts `napcat-upstream-audit`, `napcat-sync-candidate-review`, `napcat-runtime-release-readiness`, and `nas-codex-bootstrap`.
- Modify `README.md`: public ktWorkflow usage docs and NAS command examples.
### `D:\MyFiles\KT\Node\kt-template-online-api`
- Modify `scripts/napcat-desktop-cn-stage-build.mjs`: include upstream release tag/commit, base image digest, Jenkins build URL, and fork artifact metadata.
- Modify `test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts`: assert richer marker and API deployment override contract.
- Create `test/modules/qqbot/napcat/napcat-runtime-promotion.spec.ts`: static tests for Jenkins/K8s runtime image/profile override behavior.
- Modify `Jenkinsfile`: add optional `QQBOT_NAPCAT_IMAGE_OVERRIDE` and `QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION_OVERRIDE` parameters and set K8s env during deploy.
- Modify `k8s/prod/api.yaml`: keep safe defaults while allowing Jenkins `kubectl set env` override.
- Modify `README.md` and `API.md`: document runtime promotion and rollback contract.
### `D:\MyFiles\KT\GitHub\NapCatQQ`
- Create `ci/kt-runtime-release.md`: repo-local release checklist used by Jenkins and human operators.
- No source login behavior changes are part of this plan. If upstream sync reveals login conflicts, create a separate NapCatQQ implementation plan.
### `D:\MyFiles\KT`
- Modify `TASKS.md`: record the completed planning state and verification evidence.
---
### Task 1: ktWorkflow NapCat Automation Contracts
**Files:**
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.types.ts`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\schemas\upstream-audit.schema.json`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\schemas\runtime-release-readiness.schema.json`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- [ ] **Step 1: Write the failing self-test**
Add a self-test block that imports the new schemas and verifies reason-code normalization.
```ts
import {
napcatAutomationReasonCodes,
parseNapcatAutomationClassification,
upstreamAuditOutputSchema,
} from './tools/napcatAutomation.types.js';
const napcatAuditSchemaSmoke = upstreamAuditOutputSchema.safeParse({
classification: 'manual-review',
reasonCodes: ['HOT_ZONE_CHANGED'],
recommendedAction: 'request-human-review',
summary: 'Login hot-zone changed.',
});
if (!napcatAuditSchemaSmoke.success) {
throw new Error('NapCat upstream audit schema self-check failed');
}
if (!napcatAutomationReasonCodes.includes('HOT_ZONE_CHANGED')) {
throw new Error('NapCat reason-code list self-check failed');
}
if (parseNapcatAutomationClassification('manual-review') !== 'manual-review') {
throw new Error('NapCat classification parser self-check failed');
}
```
- [ ] **Step 2: Run the self-test and confirm RED**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because `napcatAutomation.types.js` does not exist.
- [ ] **Step 3: Add zod types and constants**
Create `src/tools/napcatAutomation.types.ts`:
```ts
import { z } from 'zod';
export const napcatAutomationClassifications = [
'safe-candidate',
'manual-review',
'blocked',
] as const;
export const napcatAutomationReasonCodes = [
'NO_UPSTREAM_CHANGE',
'HOT_ZONE_CHANGED',
'FORK_PATCH_OVERLAP',
'DRY_MERGE_CONFLICT',
'BUILD_GRAPH_CHANGED',
'METADATA_UNAVAILABLE',
'CODEX_SCHEMA_INVALID',
] as const;
export const upstreamAuditOutputSchema = z.object({
classification: z.enum(napcatAutomationClassifications),
reasonCodes: z.array(z.enum(napcatAutomationReasonCodes)).min(1),
recommendedAction: z.enum([
'no-op',
'create-candidate-branch',
'request-human-review',
'block',
]),
summary: z.string().min(1),
});
export type NapcatAutomationClassification =
(typeof napcatAutomationClassifications)[number];
export interface NapcatUpstreamAuditInput {
artifactRoot?: string;
createCandidateBranch?: boolean;
execute?: boolean;
forkBranch?: string;
forkRepo?: string;
lastAcceptedUpstreamBase?: string;
upstreamReleaseTag?: string;
upstreamRepo?: string;
useCodex?: boolean;
}
export interface NapcatAutomationArtifact {
path: string;
type: 'context' | 'json' | 'jsonl' | 'markdown' | 'script';
}
export interface NapcatAutomationResult {
artifacts: NapcatAutomationArtifact[];
classification: NapcatAutomationClassification;
execute: boolean;
recommendedAction: string;
summary: string;
}
/**
* Parses the upstream audit classification emitted by deterministic collectors or Codex.
* @param value - Raw classification value from JSON output.
* @returns A supported classification value.
*/
export function parseNapcatAutomationClassification(
value: string,
): NapcatAutomationClassification {
const parsed = z.enum(napcatAutomationClassifications).safeParse(value);
if (!parsed.success) {
throw new Error(`Unsupported NapCat audit classification: ${value}`);
}
return parsed.data;
}
```
- [ ] **Step 4: Add JSON schemas for Codex CLI**
Create `prompts/napcat/schemas/upstream-audit.schema.json`:
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["classification", "reasonCodes", "recommendedAction", "summary"],
"properties": {
"classification": {
"enum": ["safe-candidate", "manual-review", "blocked"]
},
"reasonCodes": {
"type": "array",
"minItems": 1,
"items": {
"enum": [
"NO_UPSTREAM_CHANGE",
"HOT_ZONE_CHANGED",
"FORK_PATCH_OVERLAP",
"DRY_MERGE_CONFLICT",
"BUILD_GRAPH_CHANGED",
"METADATA_UNAVAILABLE",
"CODEX_SCHEMA_INVALID"
]
}
},
"recommendedAction": {
"enum": ["no-op", "create-candidate-branch", "request-human-review", "block"]
},
"summary": {
"type": "string",
"minLength": 1
}
}
}
```
Create `prompts/napcat/schemas/runtime-release-readiness.schema.json` with `sourceValidation`, `imageValidation`, `apiPromotionReadiness`, `onlineSmokeReadiness`, and `rollbackPointer` string fields.
- [ ] **Step 5: Run GREEN**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: both pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add prompts/napcat src/tools/napcatAutomation.types.ts src/selfTest.ts
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 定义NapCat自动化审计契约"
```
---
### Task 2: ktWorkflow Prompt Pack and Safe Prompt Loader
**Files:**
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\upstream-audit.md`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\sync-candidate-review.md`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\runtime-release-readiness.md`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\prompts\napcat\remote-dev-handoff.md`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.prompts.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- [ ] **Step 1: Write the failing self-test**
```ts
import {
loadNapcatAutomationPrompt,
napcatAutomationPromptNames,
} from './tools/napcatAutomation.prompts.js';
for (const promptName of napcatAutomationPromptNames) {
const promptText = loadNapcatAutomationPrompt(promptName);
if (!promptText.includes('Do not edit files')) {
throw new Error(`NapCat prompt safety contract missing: ${promptName}`);
}
}
```
- [ ] **Step 2: Run RED**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because prompt loader does not exist.
- [ ] **Step 3: Create prompt loader**
```ts
import { readFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
export const napcatAutomationPromptNames = [
'upstream-audit',
'sync-candidate-review',
'runtime-release-readiness',
'remote-dev-handoff',
] as const;
export type NapcatAutomationPromptName =
(typeof napcatAutomationPromptNames)[number];
const promptsRoot = path.resolve(
fileURLToPath(new URL('../../..', import.meta.url)),
'prompts',
'napcat',
);
/**
* Loads a source-controlled NapCat automation prompt by stable prompt name.
* @param name - Prompt identifier that maps to `prompts/napcat/${name}.md`.
* @returns UTF-8 prompt text used by Codex CLI automation.
*/
export function loadNapcatAutomationPrompt(
name: NapcatAutomationPromptName,
): string {
return readFileSync(path.join(promptsRoot, `${name}.md`), 'utf8');
}
```
- [ ] **Step 4: Create prompts**
Each prompt must include these exact safety lines:
```md
Do not edit files.
Do not run merge, commit, push, deploy, or Docker mutation commands.
Use only the supplied context packet.
Return JSON that matches the requested schema.
```
`upstream-audit.md` must also include the three classifications and the seven reason codes from Task 1.
- [ ] **Step 5: Run GREEN**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: both pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add prompts/napcat src/tools/napcatAutomation.prompts.ts src/selfTest.ts
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 增加NapCat自动化提示词包"
```
---
### Task 3: Deterministic Upstream Audit Collector
**Files:**
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.types.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- [ ] **Step 1: Write RED self-test for hot-zone classification**
```ts
import { classifyNapcatUpstreamAudit } from './tools/napcatAutomation.js';
const hotZoneAudit = classifyNapcatUpstreamAudit({
dryMergeConflict: false,
forkPatchFiles: ['packages/napcat-core/login/runtime.ts'],
upstreamChangedFiles: ['packages/napcat-core/login/runtime.ts'],
});
if (hotZoneAudit.classification !== 'manual-review') {
throw new Error('NapCat hot-zone audit classification self-check failed');
}
if (!hotZoneAudit.reasonCodes.includes('HOT_ZONE_CHANGED')) {
throw new Error('NapCat hot-zone reason-code self-check failed');
}
```
- [ ] **Step 2: Run RED**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because `classifyNapcatUpstreamAudit` does not exist.
- [ ] **Step 3: Implement classifier and context packet builder**
Add this public classifier:
```ts
const hotZonePatterns = [
/^packages\/napcat-core\/.*login/i,
/^packages\/napcat-core\/.*qrcode/i,
/^packages\/napcat-shell\//i,
/^packages\/napcat-framework\//i,
/^packages\/napcat-webui-backend\/.*QQLogin/i,
/^packages\/napcat-webui-backend\/.*Data/i,
/^packages\/napcat-webui-backend\/.*auth/i,
/^packages\/napcat-webui-frontend\//i,
/^packages\/napcat-adapter\//i,
/^packages\/napcat-onebot\//i,
/^packages\/napcat-vite\//i,
/^package\.json$/i,
/^pnpm-lock\.yaml$/i,
/^tsconfig.*\.json$/i,
/^vite.*\.ts$/i,
];
export interface NapcatAuditClassificationInput {
dryMergeConflict: boolean;
forkPatchFiles: string[];
upstreamChangedFiles: string[];
}
/**
* Classifies upstream release risk from already-collected file-level facts.
* @param input - Changed files, fork patch files, and dry-merge conflict status.
* @returns Schema-compatible classification used before optional Codex review.
*/
export function classifyNapcatUpstreamAudit(
input: NapcatAuditClassificationInput,
): {
classification: NapcatAutomationClassification;
reasonCodes: string[];
recommendedAction: string;
summary: string;
} {
const upstream = new Set(input.upstreamChangedFiles);
const overlapFiles = input.forkPatchFiles.filter((file) => upstream.has(file));
const hotZoneFiles = input.upstreamChangedFiles.filter((file) =>
hotZonePatterns.some((pattern) => pattern.test(file)),
);
if (input.dryMergeConflict) {
return {
classification: 'blocked',
reasonCodes: ['DRY_MERGE_CONFLICT'],
recommendedAction: 'block',
summary: 'Dry merge reported conflicts.',
};
}
if (hotZoneFiles.length > 0 || overlapFiles.length > 0) {
return {
classification: 'manual-review',
reasonCodes: [
...(hotZoneFiles.length > 0 ? ['HOT_ZONE_CHANGED'] : []),
...(overlapFiles.length > 0 ? ['FORK_PATCH_OVERLAP'] : []),
],
recommendedAction: 'request-human-review',
summary: 'Upstream changes require manual review before sync.',
};
}
return {
classification: 'safe-candidate',
reasonCodes: ['NO_UPSTREAM_CHANGE'],
recommendedAction: 'create-candidate-branch',
summary: 'No hot-zone or fork patch overlap was detected.',
};
}
```
- [ ] **Step 4: Add command builders without executing mutations**
Implement `buildNapcatUpstreamAudit(input)` so `execute=false` returns a script containing only bounded read-only commands:
```bash
git fetch upstream --tags --prune
git fetch origin --prune
git diff --name-only "$LAST_ACCEPTED_UPSTREAM_BASE..$UPSTREAM_RELEASE_COMMIT"
git merge-tree "$FORK_BRANCH" "$UPSTREAM_RELEASE_COMMIT"
```
Do not include `git merge`, `git push`, `docker build`, or `kubectl`.
- [ ] **Step 5: Run GREEN**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: both pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add src/tools/napcatAutomation.ts src/tools/napcatAutomation.types.ts src/selfTest.ts
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 增加NapCat上游审计采集器"
```
---
### Task 4: Codex CLI Runner and Artifact Capture
**Files:**
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- [ ] **Step 1: Write RED self-test for safe Codex command**
```ts
import { buildNapcatCodexExecCommand } from './tools/napcatAutomation.js';
const codexCommand = buildNapcatCodexExecCommand({
artifactRoot: '/vol1/docker/kt-codex/artifacts/smoke',
contextPacketPath: '/vol1/docker/kt-codex/artifacts/smoke/context-packet.md',
outputSchemaPath: '/vol1/docker/kt-codex/workspace/KT/mcp/ktWorkflow/prompts/napcat/schemas/upstream-audit.schema.json',
promptName: 'upstream-audit',
workspaceRoot: '/vol1/docker/kt-codex/workspace/KT',
});
if (!codexCommand.includes('--ask-for-approval never')) {
throw new Error('NapCat Codex runner approval policy self-check failed');
}
if (codexCommand.includes('git push') || codexCommand.includes('kubectl')) {
throw new Error('NapCat Codex runner mutation guard self-check failed');
}
```
- [ ] **Step 2: Run RED**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because `buildNapcatCodexExecCommand` does not exist.
- [ ] **Step 3: Implement command builder**
The command builder must shell-quote every path and include:
```bash
CODEX_HOME=/vol1/docker/kt-codex/home/.codex
codex exec
--cd /vol1/docker/kt-codex/workspace/KT
--profile automation
--sandbox workspace-write
--ask-for-approval never
--json
--ephemeral
--output-schema /vol1/docker/kt-codex/workspace/KT/mcp/ktWorkflow/prompts/napcat/schemas/upstream-audit.schema.json
--output-last-message /vol1/docker/kt-codex/artifacts/smoke/codex-upstream-audit.md
```
- [ ] **Step 4: Implement execution mode**
When `execute=true` and `useCodex=true`, `buildNapcatUpstreamAudit` must:
1. Write a context packet under the artifact root.
2. Run Codex CLI with a timeout of 10 minutes.
3. Capture JSONL stdout to `codex-upstream-audit.jsonl`.
4. Parse the final JSON payload with `upstreamAuditOutputSchema`.
5. Return `classification='blocked'` with `CODEX_SCHEMA_INVALID` if parsing fails.
- [ ] **Step 5: Run GREEN**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: both pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add src/tools/napcatAutomation.ts src/selfTest.ts
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 封装NapCat Codex审计执行器"
```
---
### Task 5: MCP Tools and CLI Scripts
**Files:**
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\types.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\core\cli.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\registerTools.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\server.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\core\constants.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\package.json`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\README.md`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- [ ] **Step 1: Write RED self-test for tool registration and CLI parser**
```ts
import { parseNapcatUpstreamAuditCliArgs } from './core/cli.js';
import { registeredToolNames } from './core/constants.js';
const napcatCli = parseNapcatUpstreamAuditCliArgs([
'node',
'server',
'--napcat-upstream-audit',
'--execute',
'--use-codex',
'--artifact-root',
'/vol1/docker/kt-codex/artifacts/napcat-upstream-sync',
]);
if (!napcatCli.execute || !napcatCli.useCodex) {
throw new Error('NapCat upstream audit CLI parser self-check failed');
}
if (!registeredToolNames.includes('kt_napcat_upstream_audit')) {
throw new Error('NapCat MCP tool registry self-check failed');
}
```
- [ ] **Step 2: Run RED**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because parser and tool names do not exist.
- [ ] **Step 3: Register MCP tools**
Add tools:
```ts
server.registerTool(
'kt_napcat_upstream_audit',
{
description: 'Generate or execute a NapCatQQ upstream release audit through ktWorkflow.',
inputSchema: {
artifactRoot: z.string().optional(),
createCandidateBranch: z.boolean().default(false),
execute: z.boolean().default(false),
forkBranch: z.string().default('kt/runtime-maintenance'),
forkRepo: z.string().default('D:/MyFiles/KT/GitHub/NapCatQQ'),
lastAcceptedUpstreamBase: z.string().optional(),
upstreamReleaseTag: z.string().optional(),
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
useCodex: z.boolean().default(false),
},
title: 'KT NapCat Upstream Audit',
},
async (input) => response(await buildNapcatUpstreamAudit(input)),
);
```
Also register `kt_napcat_sync_candidate_review`, `kt_napcat_runtime_release_readiness`, `kt_napcat_remote_dev_handoff`, and `kt_nas_codex_bootstrap_plan`.
- [ ] **Step 4: Add CLI flags and package scripts**
`package.json` scripts:
```json
{
"napcat-upstream-audit": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-upstream-audit",
"napcat-sync-candidate-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-sync-candidate-review",
"napcat-runtime-release-readiness": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-runtime-release-readiness",
"nas-codex-bootstrap": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --nas-codex-bootstrap"
}
```
- [ ] **Step 5: Run GREEN**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run napcat-upstream-audit -- --artifact-root .kt-workspace/test-artifacts/napcat-upstream-sync
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: dry-run prints commands/artifacts, self-test/typecheck pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add package.json README.md src
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 接入NapCat自动化MCP工具和CLI"
```
---
### Task 6: NAS Codex Bootstrap Plan Tool
**Files:**
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\tools\napcatAutomation.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\src\selfTest.ts`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\README.md`
- [ ] **Step 1: Write RED self-test for Linux-only bootstrap commands**
```ts
import { buildNasCodexBootstrapPlan } from './tools/napcatAutomation.js';
const bootstrap = buildNasCodexBootstrapPlan({ execute: false });
const commandText = bootstrap.commands.map((item) => item.command).join('\n');
if (!commandText.includes('/vol1/docker/kt-codex/home/.codex')) {
throw new Error('NAS Codex bootstrap CODEX_HOME self-check failed');
}
if (commandText.includes('C:\\Users')) {
throw new Error('NAS Codex bootstrap Windows path guard self-check failed');
}
```
- [ ] **Step 2: Run RED**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
```
Expected: fails because bootstrap builder does not exist.
- [ ] **Step 3: Implement dry-run bootstrap**
The dry-run must emit a bounded SSH here-string command that checks:
```bash
node --version
corepack --version
pnpm --version
git --version
docker --version
codex --version
test -d /vol1/docker/kt-codex/workspace/KT
test -d /vol1/docker/kt-codex/home/.codex
```
It must not copy secrets in dry-run mode.
- [ ] **Step 4: Add execute mode with explicit safe operations**
`execute=true` may create directories and install packages, but must not push, merge, deploy, or edit business repos.
- [ ] **Step 5: Run GREEN**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run nas-codex-bootstrap -- --dry-run
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
```
Expected: dry-run prints NAS setup checks, self-test/typecheck pass.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add README.md src
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "feat: 增加NAS Codex环境引导工具"
```
---
### Task 7: API Runtime Artifact Metadata
**Files:**
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\napcat-desktop-cn-stage-build.mjs`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\napcat-desktop-cn-image.spec.ts`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\README.md`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\API.md`
- [ ] **Step 1: Write RED test for richer fork artifact marker**
Add assertions:
```ts
expect(script).toContain('upstreamReleaseTag');
expect(script).toContain('upstreamReleaseCommit');
expect(script).toContain('napcatBaseImageDigest');
expect(script).toContain('jenkinsBuildUrl');
```
- [ ] **Step 2: Run RED**
```powershell
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts --runTestsByPath --runInBand
```
Expected: fails because the stage-build script only writes the older marker fields.
- [ ] **Step 3: Extend CLI args and marker**
Add `readArg` calls and marker fields:
```js
const upstreamReleaseTag = readArg('upstream-release-tag', 'unknown');
const upstreamReleaseCommit = readArg('upstream-release-commit', upstreamBaseCommit);
const napcatBaseImageDigest = readArg('napcat-base-image-digest', '');
const jenkinsBuildUrl = readArg('jenkins-build-url', '');
const marker = {
builtAt: new Date().toISOString(),
distSha256: sha256Directory(shellDist),
forkCommit: gitCommit(napcatRoot),
jenkinsBuildUrl,
napcatBaseImageDigest,
napcatMjsSha256: sha256File(napcatMjs),
upstreamBaseCommit,
upstreamReleaseCommit,
upstreamReleaseTag,
};
```
- [ ] **Step 4: Document command shape**
Add docs showing:
```powershell
node scripts/napcat-desktop-cn-stage-build.mjs `
--napcat-root D:\MyFiles\KT\GitHub\NapCatQQ `
--upstream-release-tag v4.8.0 `
--upstream-release-commit 0000000000000000000000000000000000000000 `
--napcat-base-image-digest mlikiowa/napcat-docker@sha256:0000000000000000000000000000000000000000000000000000000000000000 `
--jenkins-build-url https://jenkins.kwitsukasa.top/job/KT-NapCatQQ-Runtime-Release/1/
```
- [ ] **Step 5: Run GREEN**
```powershell
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts --runTestsByPath --runInBand
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
git -C D:\MyFiles\KT\Node\kt-template-online-api diff --check
```
Expected: tests/typecheck pass and diff has no whitespace errors.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add scripts/napcat-desktop-cn-stage-build.mjs test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts README.md API.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "feat: 扩展NapCat运行时构建元数据"
```
---
### Task 8: API Jenkins Runtime Promotion Override
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\napcat-runtime-promotion.spec.ts`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\Jenkinsfile`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\k8s\prod\api.yaml`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\README.md`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\API.md`
- [ ] **Step 1: Write RED static test**
```ts
import { readFileSync } from 'fs';
import { join } from 'path';
const repoRoot = join(__dirname, '../../../..');
const readSource = (relativePath: string) =>
readFileSync(join(repoRoot, relativePath), 'utf8');
describe('NapCat runtime promotion contract', () => {
it('exposes Jenkins parameters for runtime image and profile overrides', () => {
const jenkinsfile = readSource('Jenkinsfile');
expect(jenkinsfile).toContain("string(name: 'QQBOT_NAPCAT_IMAGE_OVERRIDE'");
expect(jenkinsfile).toContain("string(name: 'QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION_OVERRIDE'");
expect(jenkinsfile).toContain('kubectl ${kubeConfigArg} ${namespaceArg} set env');
expect(jenkinsfile).toContain('QQBOT_NAPCAT_IMAGE=${napcatImageOverride}');
expect(jenkinsfile).toContain('QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION=${napcatProfileOverride}');
});
it('keeps a safe default runtime profile in the K8s manifest', () => {
const manifest = readSource('k8s/prod/api.yaml');
expect(manifest).toContain('value: kt-napcat-desktop-cn:desktop-cn-v8');
expect(manifest).toContain('value: desktop-cn-v8');
});
});
```
- [ ] **Step 2: Run RED**
```powershell
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest test/modules/qqbot/napcat/napcat-runtime-promotion.spec.ts --runTestsByPath --runInBand
```
Expected: fails because Jenkins parameters do not exist.
- [ ] **Step 3: Add Jenkins parameters**
Add:
```groovy
string(name: 'QQBOT_NAPCAT_IMAGE_OVERRIDE', defaultValue: '', description: 'Verified NapCat runtime image to inject into API deployment; empty keeps manifest/default env')
string(name: 'QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION_OVERRIDE', defaultValue: '', description: 'Verified NapCat runtime profile version to inject into API deployment; empty keeps manifest/default env')
```
- [ ] **Step 4: Set K8s env only when override is present**
Inside `K8s Deploy`, after `set image`, add:
```groovy
def napcatImageOverride = params.QQBOT_NAPCAT_IMAGE_OVERRIDE?.trim()
def napcatProfileOverride = params.QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION_OVERRIDE?.trim()
if (napcatImageOverride) {
runCmd("kubectl ${kubeConfigArg} ${namespaceArg} set env ${shellQuote("deployment/${deploymentName}")} ${shellQuote("QQBOT_NAPCAT_IMAGE=${napcatImageOverride}")}")
}
if (napcatProfileOverride) {
runCmd("kubectl ${kubeConfigArg} ${namespaceArg} set env ${shellQuote("deployment/${deploymentName}")} ${shellQuote("QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION=${napcatProfileOverride}")}")
}
```
- [ ] **Step 5: Run GREEN**
```powershell
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest test/modules/qqbot/napcat/napcat-runtime-promotion.spec.ts test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts --runTestsByPath --runInBand
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
git -C D:\MyFiles\KT\Node\kt-template-online-api diff --check
```
Expected: tests/typecheck pass and diff has no whitespace errors.
- [ ] **Step 6: Commit**
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add Jenkinsfile k8s/prod/api.yaml README.md API.md test/modules/qqbot/napcat/napcat-runtime-promotion.spec.ts
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "feat: 支持NapCat运行时镜像参数推广"
```
---
### Task 9: NapCatQQ Release Checklist and Jenkins Entry Templates
**Files:**
- Create: `D:\MyFiles\KT\GitHub\NapCatQQ\ci\kt-runtime-release.md`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\ci\jenkins\KT-NapCatQQ-Upstream-Sync.Jenkinsfile`
- Create: `D:\MyFiles\KT\mcp\ktWorkflow\ci\jenkins\KT-NapCatQQ-Runtime-Release.Jenkinsfile`
- Modify: `D:\MyFiles\KT\mcp\ktWorkflow\README.md`
- [ ] **Step 1: Create release checklist**
The checklist must include:
```md
# KT NapCat Runtime Release Checklist
- Verify `origin` points to the KT writable fork or mirror.
- Verify `upstream` points to `https://github.com/NapNeko/NapCatQQ.git`.
- Run `pnpm install --frozen-lockfile`.
- Run focused login/runtime tests.
- Run `pnpm run typecheck`.
- Run `pnpm run build:webui`, `pnpm run build:shell`, and `pnpm run build:framework`.
- Build Docker runtime only through ktWorkflow/Jenkins.
- Do not merge upstream release branches without human review.
```
- [ ] **Step 2: Add upstream sync Jenkins template**
The upstream sync Jenkinsfile must call only:
```groovy
sh '''
set -e
pnpm --dir /vol1/docker/kt-codex/workspace/KT/mcp/ktWorkflow run napcat-upstream-audit -- \
--execute \
--use-codex \
--artifact-root /vol1/docker/kt-codex/artifacts/napcat-upstream-sync
'''
```
- [ ] **Step 3: Add runtime release Jenkins template**
The runtime release Jenkinsfile must call ktWorkflow readiness and API promotion commands, and must not inline the audit algorithm.
- [ ] **Step 4: Verify templates**
Run:
```powershell
rg -n "napcat-upstream-audit|napcat-runtime-release-readiness|git merge|git push" D:\MyFiles\KT\mcp\ktWorkflow\ci\jenkins
git -C D:\MyFiles\KT\mcp\ktWorkflow diff --check
git -C D:\MyFiles\KT\GitHub\NapCatQQ diff --check
```
Expected: templates contain ktWorkflow calls and do not contain automatic `git merge` or `git push`.
- [ ] **Step 5: Commit**
```powershell
git -C D:\MyFiles\KT\mcp\ktWorkflow add README.md ci/jenkins
git -C D:\MyFiles\KT\mcp\ktWorkflow commit -m "docs: 增加NapCatQQ自动化Jenkins入口"
git -C D:\MyFiles\KT\GitHub\NapCatQQ add ci/kt-runtime-release.md
git -C D:\MyFiles\KT\GitHub\NapCatQQ commit -m "docs: 增加KT运行时发布清单"
```
---
### Task 10: Local Verification, Review, and Planning Closeout
**Files:**
- Modify: `D:\MyFiles\KT\TASKS.md`
- [ ] **Step 1: Run local verification**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run napcat-upstream-audit -- --artifact-root .kt-workspace/test-artifacts/napcat-upstream-sync
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run nas-codex-bootstrap -- --dry-run
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run self-test
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run typecheck
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts test/modules/qqbot/napcat/napcat-runtime-promotion.spec.ts --runTestsByPath --runInBand
corepack pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
git -C D:\MyFiles\KT\mcp\ktWorkflow diff --check
git -C D:\MyFiles\KT\Node\kt-template-online-api diff --check
git -C D:\MyFiles\KT\GitHub\NapCatQQ diff --check
```
Expected: all commands pass.
- [ ] **Step 2: Run KT global review**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run global-review -- --content-scan-mode changed --max-findings-per-project 20
```
Expected: `findings=[]` or only documented false positives fixed in ktWorkflow review rules.
- [ ] **Step 3: Update TASKS**
Record scope, keywords, and verification evidence for:
```md
### 2026-06-24NapCatQQ 上游同步与运行时发布流水线实施
- 范围mcp/ktWorkflow、Node/kt-template-online-api、GitHub/NapCatQQ。
- 关键词ktWorkflow NapCat 自动化、Codex CLI exec、上游 release 审计、NAS bootstrap、API runtime image/profile override。
- 验证self-test/typecheck/Jest/global-review/diff-check 通过;线上 Jenkins/NAS dry-run 等待下一阶段。
```
- [ ] **Step 4: Run cleanup preview**
```powershell
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run cleanup-history -- --dry-run
```
Expected: report is reviewed. If it lists stale generated artifacts, run `--execute` and then rerun dry-run until `deleted=[]`.
- [ ] **Step 5: Commit remaining docs**
```powershell
git -C D:\MyFiles\KT add TASKS.md
git -C D:\MyFiles\KT commit -m "docs: 记录NapCatQQ自动化实施结果"
```
---
## Execution Handoff
Plan complete and saved to `docs/superpowers/plans/2026-06-24-napcatqq-upstream-sync-runtime-release-pipeline-implementation-plan.md`.
Two execution options:
1. **Subagent-Driven (recommended)** - Dispatch a fresh subagent per task, review between tasks, and keep ktWorkflow/API/NapCatQQ commits independent.
2. **Inline Execution** - Execute tasks in this session using `superpowers:executing-plans`, with review checkpoints after each repository boundary.
Recommended choice: **1**. This work touches three repositories and two runtime environments, so task-level subagents plus parent review will keep scope cleaner.