Sfoglia il codice sorgente

release: publish fmode-qiwei 0.5.1

gangvy 1 mese fa
parent
commit
755c85dece

+ 1 - 1
claude-code/claude-code-qiwe-assistant/.claude-plugin/plugin.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "qiwei-assistant",
   "name": "qiwei-assistant",
   "description": "Enterprise WeChat intelligent office, goal management, customer service, CRM and API skills for Claude Code and Fmode Studio.",
   "description": "Enterprise WeChat intelligent office, goal management, customer service, CRM and API skills for Claude Code and Fmode Studio.",
-  "version": "0.5.0",
+  "version": "0.5.1",
   "author": {
   "author": {
     "name": "fmode"
     "name": "fmode"
   }
   }

+ 2 - 1
claude-code/claude-code-qiwe-assistant/README.md

@@ -419,9 +419,10 @@ node install.js workspace <客户项目目录> --smoke
 <客户项目>/.claude/plugins/qiwei-assistant
 <客户项目>/.claude/plugins/qiwei-assistant
 <客户项目>/.claude/skills/<qiwei-skill>
 <客户项目>/.claude/skills/<qiwei-skill>
 <客户项目>/.mcp.json
 <客户项目>/.mcp.json
+<客户项目>/.gitignore
 ```
 ```
 
 
-安装过程不会复制 `.env`、`.env.local`、`.npmrc`、真实运行输出、客户 Session、Playwright 会话、压缩包或源码目录中的 `node_modules`。当前公开版本为 `fmode-qiwei@0.5.0`;版本与验证记录见 `docs/RELEASE.md`。
+安装器会幂等补全项目根目录 `.gitignore`,保留项目已有规则,并忽略本地凭据、运行数据库、Session、日志和依赖目录。安装过程不会复制 `.env`、`.env.local`、`.npmrc`、真实运行输出、客户 Session、Playwright 会话、压缩包或源码目录中的 `node_modules`。当前公开版本为 `fmode-qiwei@0.5.1`;版本与验证记录见 `docs/RELEASE.md`。
 
 
 ## 子 Skill 索引
 ## 子 Skill 索引
 
 

+ 5 - 3
claude-code/claude-code-qiwe-assistant/docs/RELEASE.md

@@ -3,8 +3,8 @@
 ## 当前状态
 ## 当前状态
 
 
 - npm 包名:`fmode-qiwei`
 - npm 包名:`fmode-qiwei`
-- 当前版本:`0.5.0`
-- 状态:已发布到 npm,`latest=0.5.0`
+- 当前版本:`0.5.1`
+- 状态:已发布到 npm,`latest=0.5.1`
 - 运行要求:Node.js `22.5.0+`(使用内置 `node:sqlite`)
 - 运行要求:Node.js `22.5.0+`(使用内置 `node:sqlite`)
 - Dashboard:`http://127.0.0.1:4320/`
 - Dashboard:`http://127.0.0.1:4320/`
 
 
@@ -30,7 +30,7 @@ node install.js workspace <客户项目目录> --smoke
 本地 tgz:
 本地 tgz:
 
 
 ```powershell
 ```powershell
-npm install -g .\fmode-qiwei-0.5.0.tgz
+npm install -g .\fmode-qiwei-0.5.1.tgz
 fmode-qiwei workspace <客户项目目录> --smoke
 fmode-qiwei workspace <客户项目目录> --smoke
 ```
 ```
 
 
@@ -46,9 +46,11 @@ workspace 安装会生成:
 <客户项目>/.claude/plugins/qiwei-assistant
 <客户项目>/.claude/plugins/qiwei-assistant
 <客户项目>/.claude/skills/<skill-name>/SKILL.md
 <客户项目>/.claude/skills/<skill-name>/SKILL.md
 <客户项目>/.mcp.json
 <客户项目>/.mcp.json
+<客户项目>/.gitignore
 ```
 ```
 
 
 项目级 `.mcp.json` 使用安装目录内 `mcp/src/server.js` 的绝对路径,可从任意工作目录启动。
 项目级 `.mcp.json` 使用安装目录内 `mcp/src/server.js` 的绝对路径,可从任意工作目录启动。
+项目级 `.gitignore` 使用随 npm 包发布的模板幂等合并,保留客户已有规则并过滤本地凭据、运行状态和临时文件。
 
 
 ## 凭据与本地数据
 ## 凭据与本地数据
 
 

+ 1 - 1
claude-code/claude-code-qiwe-assistant/docs/guides/ACCOUNT-SWITCH-DEMO.md

@@ -41,7 +41,7 @@ node .claude\plugins\qiwei-assistant\install.js preview .
 http://127.0.0.1:4320/
 http://127.0.0.1:4320/
 ```
 ```
 
 
-> `0.5.0` 发布后可直接使用 `npx --yes fmode-qiwei@latest workspace --smoke`;上述本地源码命令继续用于开发分支验证。
+> `0.5.1` 发布后可直接使用 `npx --yes fmode-qiwei@latest workspace --smoke`;上述本地源码命令继续用于开发分支验证。
 
 
 ## 4. 页面操作步骤
 ## 4. 页面操作步骤
 
 

+ 23 - 1
claude-code/claude-code-qiwe-assistant/install.js

@@ -8,6 +8,9 @@ const { spawnSync } = require('child_process');
 const ROOT = __dirname;
 const ROOT = __dirname;
 const EXCLUDED_ROOTS = new Set(['.claude', '.git', '.github', '.playwright-cli', '.vscode', 'coverage', 'dist', 'node_modules', 'output', 'outputs']);
 const EXCLUDED_ROOTS = new Set(['.claude', '.git', '.github', '.playwright-cli', '.vscode', 'coverage', 'dist', 'node_modules', 'output', 'outputs']);
 const EXCLUDED_FILES = new Set(['.env', '.env.local', '.npmrc', 'poll_reply.log', 'poll_state.json']);
 const EXCLUDED_FILES = new Set(['.env', '.env.local', '.npmrc', 'poll_reply.log', 'poll_state.json']);
+const WORKSPACE_GITIGNORE_TEMPLATE = path.join(ROOT, 'templates', 'workspace.gitignore');
+const WORKSPACE_GITIGNORE_START = '# >>> qiwei-assistant managed ignores >>>';
+const WORKSPACE_GITIGNORE_END = '# <<< qiwei-assistant managed ignores <<<';
 
 
 function usage() {
 function usage() {
   return [
   return [
@@ -19,7 +22,7 @@ function usage() {
     '  fmode-qiwei workspace [客户项目目录] --smoke',
     '  fmode-qiwei workspace [客户项目目录] --smoke',
     '  fmode-qiwei preview [客户项目目录] [--no-open] [--port 4320]',
     '  fmode-qiwei preview [客户项目目录] [--no-open] [--port 4320]',
     '',
     '',
-    'workspace 模式会写入 .claude/plugins、.claude/skills 和项目级 .mcp.json。',
+    'workspace 模式会写入 .claude/plugins、.claude/skills、项目级 .mcp.json,并补全 .gitignore。',
     'preview 模式会启动工作台、检查当前状态并打开浏览器。',
     'preview 模式会启动工作台、检查当前状态并打开浏览器。',
   ].join('\n');
   ].join('\n');
 }
 }
@@ -42,6 +45,7 @@ function assertRequiredFiles() {
     'mcp/src/server.js',
     'mcp/src/server.js',
     'runtime/callback-service/src/index.mjs',
     'runtime/callback-service/src/index.mjs',
     'qiwei.runtime.config.example.mjs',
     'qiwei.runtime.config.example.mjs',
+    'templates/workspace.gitignore',
     'skills/qiwei-dashboard/SKILL.md',
     'skills/qiwei-dashboard/SKILL.md',
     'skills/qiwei-goal-management/SKILL.md',
     'skills/qiwei-goal-management/SKILL.md',
     'skills/qiwei-real-estate-auto-reply/SKILL.md',
     'skills/qiwei-real-estate-auto-reply/SKILL.md',
@@ -89,6 +93,23 @@ function copyTree(source, destination, filter = () => true) {
   fs.copyFileSync(source, destination);
   fs.copyFileSync(source, destination);
 }
 }
 
 
+function mergeWorkspaceGitignore(target) {
+  const gitignorePath = path.join(target, '.gitignore');
+  const managedBlock = fs.readFileSync(WORKSPACE_GITIGNORE_TEMPLATE, 'utf8').trim();
+  let current = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf8') : '';
+  const start = current.indexOf(WORKSPACE_GITIGNORE_START);
+  const end = current.indexOf(WORKSPACE_GITIGNORE_END, start + WORKSPACE_GITIGNORE_START.length);
+
+  if (start >= 0 && end >= start) {
+    current = `${current.slice(0, start)}${managedBlock}${current.slice(end + WORKSPACE_GITIGNORE_END.length)}`;
+  } else {
+    const prefix = current.trimEnd();
+    current = `${prefix}${prefix ? '\n\n' : ''}${managedBlock}\n`;
+  }
+  fs.writeFileSync(gitignorePath, current.replace(/\n*$/, '\n'), 'utf8');
+  return gitignorePath;
+}
+
 function run(command, args, cwd, options = {}) {
 function run(command, args, cwd, options = {}) {
   const useCmd = process.platform === 'win32' && command === 'npm';
   const useCmd = process.platform === 'win32' && command === 'npm';
   const result = spawnSync(useCmd ? 'cmd.exe' : command, useCmd ? ['/d', '/s', '/c', 'npm', ...args] : args, {
   const result = spawnSync(useCmd ? 'cmd.exe' : command, useCmd ? ['/d', '/s', '/c', 'npm', ...args] : args, {
@@ -104,6 +125,7 @@ function run(command, args, cwd, options = {}) {
 function installWorkspace(targetInput, options = {}) {
 function installWorkspace(targetInput, options = {}) {
   const target = path.resolve(targetInput || process.cwd());
   const target = path.resolve(targetInput || process.cwd());
   fs.mkdirSync(target, { recursive: true });
   fs.mkdirSync(target, { recursive: true });
+  mergeWorkspaceGitignore(target);
   const pluginsRoot = path.join(target, '.claude', 'plugins');
   const pluginsRoot = path.join(target, '.claude', 'plugins');
   const skillsRoot = path.join(target, '.claude', 'skills');
   const skillsRoot = path.join(target, '.claude', 'skills');
   const pluginDir = path.join(pluginsRoot, 'qiwei-assistant');
   const pluginDir = path.join(pluginsRoot, 'qiwei-assistant');

+ 1 - 1
claude-code/claude-code-qiwe-assistant/mcp/src/server.js

@@ -174,7 +174,7 @@ function wrap(handler) {
 function createServer() {
 function createServer() {
   const server = new McpServer({
   const server = new McpServer({
     name: 'enterprise-wechat-assistant',
     name: 'enterprise-wechat-assistant',
-    version: '0.5.0'
+    version: '0.5.1'
   });
   });
 
 
   server.registerTool(
   server.registerTool(

+ 11 - 7
claude-code/claude-code-qiwe-assistant/package-lock.json

@@ -1,12 +1,12 @@
 {
 {
   "name": "fmode-qiwei",
   "name": "fmode-qiwei",
-  "version": "0.5.0",
+  "version": "0.5.1",
   "lockfileVersion": 3,
   "lockfileVersion": 3,
   "requires": true,
   "requires": true,
   "packages": {
   "packages": {
     "": {
     "": {
       "name": "fmode-qiwei",
       "name": "fmode-qiwei",
-      "version": "0.5.0",
+      "version": "0.5.1",
       "dependencies": {
       "dependencies": {
         "@binsee/wx-voice": "^0.3.2",
         "@binsee/wx-voice": "^0.3.2",
         "@ffmpeg-installer/ffmpeg": "^1.1.0",
         "@ffmpeg-installer/ffmpeg": "^1.1.0",
@@ -791,9 +791,9 @@
       "license": "MIT"
       "license": "MIT"
     },
     },
     "node_modules/fast-uri": {
     "node_modules/fast-uri": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
-      "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+      "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
       "funding": [
       "funding": [
         {
         {
           "type": "github",
           "type": "github",
@@ -947,7 +947,9 @@
       }
       }
     },
     },
     "node_modules/hono": {
     "node_modules/hono": {
-      "version": "4.12.27",
+      "version": "4.13.0",
+      "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.0.tgz",
+      "integrity": "sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==",
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">=16.9.0"
         "node": ">=16.9.0"
@@ -990,7 +992,9 @@
       "license": "ISC"
       "license": "ISC"
     },
     },
     "node_modules/ip-address": {
     "node_modules/ip-address": {
-      "version": "10.2.0",
+      "version": "10.4.0",
+      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
+      "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
       "license": "MIT",
       "license": "MIT",
       "engines": {
       "engines": {
         "node": ">= 12"
         "node": ">= 12"

+ 2 - 1
claude-code/claude-code-qiwe-assistant/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "fmode-qiwei",
   "name": "fmode-qiwei",
-  "version": "0.5.0",
+  "version": "0.5.1",
   "description": "Fmode 企业微信智能办公技能包:客户运营、智能客服、Dashboard、Webhook/Relay、官方 CLI 与目标管理",
   "description": "Fmode 企业微信智能办公技能包:客户运营、智能客服、Dashboard、Webhook/Relay、官方 CLI 与目标管理",
   "author": "fmode",
   "author": "fmode",
   "main": "mcp/src/server.js",
   "main": "mcp/src/server.js",
@@ -24,6 +24,7 @@
     "scripts/*.mjs",
     "scripts/*.mjs",
     "skill-package-manifest.json",
     "skill-package-manifest.json",
     "skills/",
     "skills/",
+    "templates/",
     "runtime/",
     "runtime/",
     "THIRD_PARTY_NOTICES.md",
     "THIRD_PARTY_NOTICES.md",
     "wecom-cli-runtime.json"
     "wecom-cli-runtime.json"

+ 1 - 0
claude-code/claude-code-qiwe-assistant/scripts/package-smoke-test.js

@@ -99,6 +99,7 @@ function main() {
     'scripts/preview-dashboard.js',
     'scripts/preview-dashboard.js',
     'scripts/startup-preview-smoke-test.js',
     'scripts/startup-preview-smoke-test.js',
     'skill-package-manifest.json',
     'skill-package-manifest.json',
+    'templates/workspace.gitignore',
     'THIRD_PARTY_NOTICES.md',
     'THIRD_PARTY_NOTICES.md',
   ]) {
   ]) {
     assert(packedPaths.has(required), `npm 包缺少 ${required}`);
     assert(packedPaths.has(required), `npm 包缺少 ${required}`);

+ 17 - 0
claude-code/claude-code-qiwe-assistant/scripts/startup-preview-smoke-test.js

@@ -38,6 +38,7 @@ function testStartupSummary() {
 function testWorkspaceInstall(tempRoot) {
 function testWorkspaceInstall(tempRoot) {
   const target = path.join(tempRoot, 'customer-project');
   const target = path.join(tempRoot, 'customer-project');
   fs.mkdirSync(target, { recursive: true });
   fs.mkdirSync(target, { recursive: true });
+  fs.writeFileSync(path.join(target, '.gitignore'), '# Customer rules\ncustomer-cache/\n', 'utf8');
   const result = spawnSync(process.execPath, [path.join(ROOT, 'install.js'), 'workspace', target, '--skip-install'], {
   const result = spawnSync(process.execPath, [path.join(ROOT, 'install.js'), 'workspace', target, '--skip-install'], {
     cwd: ROOT,
     cwd: ROOT,
     encoding: 'utf8',
     encoding: 'utf8',
@@ -52,6 +53,22 @@ function testWorkspaceInstall(tempRoot) {
   assert.equal(config.env?.CLAUDE_CODE_WORKDIR, target);
   assert.equal(config.env?.CLAUDE_CODE_WORKDIR, target);
   assert(fs.existsSync(path.join(target, '.claude', 'plugins', 'qiwei-assistant', 'scripts', 'preview-dashboard.js')));
   assert(fs.existsSync(path.join(target, '.claude', 'plugins', 'qiwei-assistant', 'scripts', 'preview-dashboard.js')));
   assert(!fs.existsSync(path.join(target, '.claude', 'plugins', 'qiwei-assistant', '.env.local')));
   assert(!fs.existsSync(path.join(target, '.claude', 'plugins', 'qiwei-assistant', '.env.local')));
+  const gitignorePath = path.join(target, '.gitignore');
+  const firstGitignore = fs.readFileSync(gitignorePath, 'utf8');
+  assert.match(firstGitignore, /# Customer rules\ncustomer-cache\//);
+  assert.match(firstGitignore, /# >>> qiwei-assistant managed ignores >>>/);
+  assert.match(firstGitignore, /\*\*\/\.env\.local/);
+  assert.match(firstGitignore, /outputs\/messages\/\*\.db/);
+
+  const repeated = spawnSync(process.execPath, [path.join(ROOT, 'install.js'), 'workspace', target, '--skip-install'], {
+    cwd: ROOT,
+    encoding: 'utf8',
+    windowsHide: true,
+  });
+  assert.equal(repeated.status, 0, repeated.stderr || repeated.stdout);
+  const secondGitignore = fs.readFileSync(gitignorePath, 'utf8');
+  assert.equal((secondGitignore.match(/# >>> qiwei-assistant managed ignores >>>/g) || []).length, 1);
+  assert.match(secondGitignore, /# Customer rules\ncustomer-cache\//);
 }
 }
 
 
 function main() {
 function main() {

+ 2 - 1
claude-code/claude-code-qiwe-assistant/skill-package-manifest.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "fmode-qiwei",
   "name": "fmode-qiwei",
-  "version": "0.5.0",
+  "version": "0.5.1",
   "status": "published",
   "status": "published",
   "plugin": "qiwei-assistant",
   "plugin": "qiwei-assistant",
   "description": "企业微信智能办公技能包:日常办公、目标推进、智能客服、CRM 客户管理和底层 Skills/API。",
   "description": "企业微信智能办公技能包:日常办公、目标推进、智能客服、CRM 客户管理和底层 Skills/API。",
@@ -98,6 +98,7 @@
   "sessionReviewCommand": "npm run agent:session -- --customer <客户名称>",
   "sessionReviewCommand": "npm run agent:session -- --customer <客户名称>",
   "security": [
   "security": [
     "安装包不复制 .env.local、真实 outputs、Playwright 会话或 node_modules",
     "安装包不复制 .env.local、真实 outputs、Playwright 会话或 node_modules",
+    "workspace 初始化会幂等补全项目 .gitignore,保留客户已有规则并忽略本地凭据与运行数据",
     "客户 Session 原始 ID 不进入用户提示或 Dashboard",
     "客户 Session 原始 ID 不进入用户提示或 Dashboard",
     "默认 review 模式;群聊全自动模式必须按群明确开启并二次确认,发送失败保留草稿"
     "默认 review 模式;群聊全自动模式必须按群明确开启并二次确认,发送失败保留草稿"
   ]
   ]

+ 53 - 0
claude-code/claude-code-qiwe-assistant/templates/workspace.gitignore

@@ -0,0 +1,53 @@
+# >>> qiwei-assistant managed ignores >>>
+# Dependencies
+node_modules/
+**/node_modules/
+
+# Local credentials and environment overrides
+.env
+.env.local
+.env.*.local
+**/.env
+**/.env.local
+**/.env.*.local
+!.env.example
+!**/.env.example
+.npmrc
+**/.npmrc
+
+# Local runtime state and temporary data
+outputs/tmp/
+outputs/runtime/
+outputs/messages/*.db
+outputs/messages/*.db-*
+outputs/messages/claude-code-sessions*.json
+outputs/messages/rooms/
+outputs/group-operations/*.db
+outputs/group-operations/*.db-*
+outputs/customers/
+outputs/groups/
+outputs/portraits/
+outputs/dashboard/dashboard-state.json
+outputs/backups/
+outputs/voice/
+/messages/
+poll_state.json
+qwmsgs*.json
+qwrooms*.json
+qwsessions*.json
+*.log
+
+# Build, package, coverage and browser artifacts
+coverage/
+dist/
+*.tgz
+*.zip
+.playwright-cli/
+
+# Local editor and operating-system files
+.claude/settings.local.json
+.DS_Store
+Thumbs.db
+**/__MACOSX/
+~$*
+# <<< qiwei-assistant managed ignores <<<

+ 2 - 1
release/npm发布管理文档/NPM技能包发布管理.md

@@ -30,7 +30,7 @@
 | fmode 视觉分析 | `fmode-vision` | `0.1.1` | 已发布 | `claude-code/fmode-vision/`(如有) | https://www.npmjs.com/package/fmode-vision |
 | fmode 视觉分析 | `fmode-vision` | `0.1.1` | 已发布 | `claude-code/fmode-vision/`(如有) | https://www.npmjs.com/package/fmode-vision |
 | fmode 音视频处理 | `fmode-ffmpeg` | `0.1.1` | 已发布 | `claude-code/fmode-ffmpeg/` | https://www.npmjs.com/package/fmode-ffmpeg |
 | fmode 音视频处理 | `fmode-ffmpeg` | `0.1.1` | 已发布 | `claude-code/fmode-ffmpeg/` | https://www.npmjs.com/package/fmode-ffmpeg |
 | fmode 录音转写 | `fmode-listen` | `0.1.1` | 已发布 | `claude-code/fmode-listen/`(如有) | https://www.npmjs.com/package/fmode-listen |
 | fmode 录音转写 | `fmode-listen` | `0.1.1` | 已发布 | `claude-code/fmode-listen/`(如有) | https://www.npmjs.com/package/fmode-listen |
-| fmode 企业微信智能办公 | `fmode-qiwei` | `0.5.0` | 已发布 | `claude-code/claude-code-qiwe-assistant/` | https://www.npmjs.com/package/fmode-qiwei |
+| fmode 企业微信智能办公 | `fmode-qiwei` | `0.5.1` | 已发布 | `claude-code/claude-code-qiwe-assistant/` | https://www.npmjs.com/package/fmode-qiwei |
 | 装修量尺图缺标记检查 | `@gangvy/claude-code-measurement-marker-check` | `0.1.2` | 已发布 | `claude-code-measurement-marker-check/` | https://www.npmjs.com/package/@gangvy/claude-code-measurement-marker-check |
 | 装修量尺图缺标记检查 | `@gangvy/claude-code-measurement-marker-check` | `0.1.2` | 已发布 | `claude-code-measurement-marker-check/` | https://www.npmjs.com/package/@gangvy/claude-code-measurement-marker-check |
 
 
 ## 安装入口
 ## 安装入口
@@ -142,6 +142,7 @@ npm exec --yes --package fmode-qiwei@latest -- fmode-qiwei workspace . --smoke
 
 
 ```text
 ```text
 .\.mcp.json
 .\.mcp.json
+.\.gitignore
 .\.claude\plugins\qiwei-assistant
 .\.claude\plugins\qiwei-assistant
 .\.claude\skills\<qiwei-skill>\SKILL.md
 .\.claude\skills\<qiwei-skill>\SKILL.md
 ```
 ```

+ 8 - 0
release/npm发布管理文档/变更记录/fmode-qiwei.md

@@ -2,6 +2,14 @@
 
 
 > 当前版本号见 [`../NPM技能包发布管理.md`](../NPM技能包发布管理.md) 的「发布状态总览」。本文按版本号倒序记录 `fmode-qiwei` 的更新内容。
 > 当前版本号见 [`../NPM技能包发布管理.md`](../NPM技能包发布管理.md) 的「发布状态总览」。本文按版本号倒序记录 `fmode-qiwei` 的更新内容。
 
 
+## 0.5.1(2026-08-04)
+
+- workspace 初始化新增项目根目录 `.gitignore`:通过随包发布的 `templates/workspace.gitignore` 规避 npm 默认省略源码 `.gitignore` 的行为。
+- 初始化器会幂等更新托管规则区块并保留客户已有内容,覆盖 `.env*`、`.npmrc`、`node_modules`、运行数据库、Claude Session、消息流水、日志、构建包和浏览器缓存。
+- 增加重复初始化、客户规则保留、模板实际入包和真实 `git check-ignore` 验收;实际 tar 包共 190 项,违规文件为 0。
+- 更新 `fast-uri`、`hono`、`ip-address` 安全修复版本;18 组发布检查及生产依赖审计通过,0 vulnerabilities。
+- 已发布并验证 npm `latest=0.5.1`;registry 查询、实际 tar 安装和线上 `workspace --smoke` 均通过,发布包 shasum 为 `81508e2d…`。
+
 ## 0.5.0(2026-08-03)
 ## 0.5.0(2026-08-03)
 
 
 - 从业务项目选择性回迁通用能力;未加入 `qiwei-property-match`、房源 Provider、购房画像、房源推荐规则、小牛业务默认值或房源云函数。
 - 从业务项目选择性回迁通用能力;未加入 `qiwei-property-match`、房源 Provider、购房画像、房源推荐规则、小牛业务默认值或房源云函数。