@fxri/toolkit 1.10.1 → 1.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # 方弦工具集
2
2
 
3
+ ## 1.10.3
4
+
5
+ > 2026-09-21 发布
6
+
7
+ ### 🐛 问题修复
8
+
9
+ - 收紧 Node 引擎版本门槛至 `>=20.19.0`
10
+
11
+ - 此前 `engines.node` 标为 `>=20`,但 `changelog` 透传 changesets 的子命令依赖宿主默认开启 `require(esm)`(Node ≥ 20.19.0、22 线 ≥ 22.12.0),20.0–20.18 实际不可用
12
+ - 依据 14/16/18/20/22/24 六个主版本(含 20.19.0、22.11.0 等边界补丁号)实测结果收敛门槛,并同步 README、docs 站首页 / 指南 / FAQ / CLI 参考的环境要求与例外说明
13
+
14
+ ### 📝 文档更新
15
+
16
+ - 文档站更新日志页启用右侧「本页目录」——该页为全量历史镜像,此前整页关闭目录;现只列版本号(`outline: [2, 2]`),避免各版本的分组标题一并进目录后随版本持续膨胀
17
+
18
+ ## 1.10.2
19
+
20
+ > 2026-09-16 发布
21
+
22
+ ### ⚡ 优化改进
23
+
24
+ - 发版链路在发布动作前补门禁关卡——`fxri-release-changelog` 技能要求发布前跑一次项目验收命令(如 `pnpm verify`),本仓库「发版链路」第 2 步由纯构建升级为该门禁(版本 1.1.1)
25
+ - 关卡设在发布前而非推送前:发布到包仓库 / 制品库不可逆,推送失败重推即可
26
+ - 原第 2 步为纯 `pnpm build`,构建工具不做类型检查,发布前无任何验收关卡
27
+ - 任务收尾链路明确「归档与沉淀 → 验收 → 提交」顺序,验收须晚于归档——归档会改写 `.tasks/`(写归档文件、删 active 源文件、清理空月份目录)且自身不做阻断式校验,早于归档跑验收就覆盖不到终态、归档产物等于无人校验;配套约定归档块「完成情况」只记改动事实与所用验证命令,不逐条抄门禁结果(避免先写结论后验证)(`fxri-plan-to-task` 1.3.2、`fxri-session-recap` 1.2.2;`docs/faq.md` 同步该顺序约束的表述)
28
+ - 本仓库验收步骤清单单源化——新增 `pnpm verify` 聚合门禁(步骤定义在 `scripts/verify.mjs`),本地与全部 CI 流水线共用同一份清单,消除此前四份手写清单彼此漂移导致的「本地自检通过、CI 才报错」
29
+ - `fxri-plan-to-task` 技能补「验收与 CI 同源、不手写清单」纪律(版本 1.3.1)
30
+ - 本仓库验收门禁补 `pnpm typecheck`——`pnpm lint`(eslint)与 `pnpm build` 均不做类型检查,此前仅靠 CI 暴露类型错误
31
+
32
+ ### 🐛 问题修复
33
+
34
+ - 修复 `toolkit changelog` 帮助拦截与解析错误提示两处 TypeScript 类型错误(`noUncheckedIndexedAccess` 下索引与正则捕获组取值未兜底),改用解构判空与空串兜底;运行时行为与输出不变,本仓库 `pnpm typecheck` 恢复通过
35
+
3
36
  ## 1.10.1
4
37
 
5
38
  > 2026-09-16 发布
package/README.md CHANGED
@@ -91,7 +91,7 @@ npm / yarn / bun 用户与各方式对比见 [新手指南 · 安装](./docs/get
91
91
 
92
92
  ## ⚙️ 环境要求
93
93
 
94
- - Node.js >= 20(Node 18 可安装,changesets 相关子命令不可用,见 [FAQ](./docs/faq.md#node-18-能用吗))
94
+ - Node.js >= 20.19.0(更低版本可安装,changesets 相关子命令不可用,见 [FAQ](./docs/faq.md#node-18-能用吗))
95
95
 
96
96
  ## 📄 版权信息
97
97
 
package/TRADEMARK.md CHANGED
@@ -1,41 +1,41 @@
1
- # 商标声明
2
-
3
- ## 基本信息
4
-
5
- | 项目 | 内容 |
6
- |---|---|
7
- | 商标名称 | 方弦® |
8
- | 商标类型 | 文字商标 |
9
- | 商标说明 | 商标由文字"方弦"组成 |
10
- | 商标类别 | 第42类(共10项) |
11
- | 注册号 | 89648411 |
12
- | 申请人 | 唐启云 |
13
- | 递交商标局 | 2026-01-12 |
14
- | 版本 | 基础版 |
15
-
16
- ## 第42类服务项目
17
-
18
- 计算机出租;计算机软件设计;为他人研究和开发新产品;计算机软件维护;把有形的数据或文件转换成电子媒体;为他人创建和维护网站;网络服务器出租;提供互联网搜索引擎;托管计算机站(网站);云计算。
19
-
20
- ## 权利状态
21
-
22
- "方弦®"商标(注册号89648411)已获中国国家知识产权局商标局核准注册,核定使用于第42类上述服务项目,现为注册商标。
23
-
24
- ## 授权范围
25
-
26
- 本仓库的开源许可证(MIT License)仅授予代码的使用、修改和分发权利,**不构成对任何商标、服务标记或品牌名称的授权许可**。
27
-
28
- 任何派生作品、修改版本、商业产品均不得使用"方弦"名称、Logo 或相关标识,除非获得书面授权。
29
-
30
- ## 使用规范
31
-
32
- - 在开源社区讨论、文档引用中提及本项目时,可使用"方弦®"指代本项目名称
33
- - 未经书面授权,不得在任何商业产品、服务或宣传材料中使用"方弦"标识
34
-
35
- ## 获取授权
36
-
37
- 如需将"方弦"商标用于商业用途,请联系:唐启云 <tqy@fxri.net>
38
-
39
- ## 侵权处理
40
-
41
- 如发现未经授权使用"方弦®"商标的行为,请通过上述联系方式举报。
1
+ # 商标声明
2
+
3
+ ## 基本信息
4
+
5
+ | 项目 | 内容 |
6
+ |---|---|
7
+ | 商标名称 | 方弦® |
8
+ | 商标类型 | 文字商标 |
9
+ | 商标说明 | 商标由文字"方弦"组成 |
10
+ | 商标类别 | 第42类(共10项) |
11
+ | 注册号 | 89648411 |
12
+ | 申请人 | 唐启云 |
13
+ | 递交商标局 | 2026-01-12 |
14
+ | 版本 | 基础版 |
15
+
16
+ ## 第42类服务项目
17
+
18
+ 计算机出租;计算机软件设计;为他人研究和开发新产品;计算机软件维护;把有形的数据或文件转换成电子媒体;为他人创建和维护网站;网络服务器出租;提供互联网搜索引擎;托管计算机站(网站);云计算。
19
+
20
+ ## 权利状态
21
+
22
+ "方弦®"商标(注册号89648411)已获中国国家知识产权局商标局核准注册,核定使用于第42类上述服务项目,现为注册商标。
23
+
24
+ ## 授权范围
25
+
26
+ 本仓库的开源许可证(MIT License)仅授予代码的使用、修改和分发权利,**不构成对任何商标、服务标记或品牌名称的授权许可**。
27
+
28
+ 任何派生作品、修改版本、商业产品均不得使用"方弦"名称、Logo 或相关标识,除非获得书面授权。
29
+
30
+ ## 使用规范
31
+
32
+ - 在开源社区讨论、文档引用中提及本项目时,可使用"方弦®"指代本项目名称
33
+ - 未经书面授权,不得在任何商业产品、服务或宣传材料中使用"方弦"标识
34
+
35
+ ## 获取授权
36
+
37
+ 如需将"方弦"商标用于商业用途,请联系:唐启云 <tqy@fxri.net>
38
+
39
+ ## 侵权处理
40
+
41
+ 如发现未经授权使用"方弦®"商标的行为,请通过上述联系方式举报。
package/dist/cli.cjs CHANGED
@@ -95,7 +95,7 @@ ${n.deps}`,n.deps);for(;;){let h=l.replace(/^- (.+)\n- \1$/gm,"- $1");if(h===l)b
95
95
  `:`
96
96
  `,o=n.endsWith(`
97
97
  `)||n===""?n:n+r;$(t,o+vn.replace(/\n/g,r).replace(/^\r?\n/,""))}function wn(e){return JSON.stringify({schemaVersion:1,...e},null,2)}function ie(e){return e&&e!=="json"?(console.error(`\u26A0\uFE0F \u4E0D\u652F\u6301\u7684\u8F93\u51FA\u683C\u5F0F\u300C${e}\u300D\uFF0C\u4EC5\u652F\u6301 json`),process.exitCode=1,!1):!0}var y=require("fs"),k=require("path"),Tn=require("url");var xn="@fxri/toolkit",ut="SKILL.md",W=".agents/skills",Rn="canonical\uFF08\u591A\u5BB6 agent \u5171\u8BFB\uFF09",wo=".toolkit-skills.json",An=[{name:"aider-desk",label:"AiderDesk",dir:".aider-desk/skills"},{name:"amp",label:"Amp",dir:".config/agents/skills",detect:[".config/amp"]},{name:"antigravity",label:"Antigravity",dir:".gemini/antigravity/skills"},{name:"antigravity-cli",label:"Antigravity CLI",dir:".gemini/antigravity-cli/skills"},{name:"astrbot",label:"AstrBot",dir:".astrbot/data/skills",detect:[".astrbot"]},{name:"autohand-code",label:"Autohand Code CLI",dir:".autohand/skills"},{name:"augment",label:"Augment",dir:".augment/skills"},{name:"bob",label:"IBM Bob",dir:".bob/skills"},{name:"claude-code",label:"Claude Code",dir:".claude/skills"},{name:"openclaw",label:"OpenClaw",dir:".openclaw/skills",detect:[".openclaw",".clawdbot",".moltbot"]},{name:"cline",label:"Cline",dir:W,detect:[".cline"]},{name:"codearts-agent",label:"CodeArts Agent",dir:".codeartsdoer/skills"},{name:"codebuddy",label:"CodeBuddy",dir:".codebuddy/skills"},{name:"codemaker",label:"Codemaker",dir:".codemaker/skills"},{name:"codestudio",label:"Code Studio",dir:".codestudio/skills"},{name:"codex",label:"Codex",dir:".codex/skills",detect:[".codex","/etc/codex"]},{name:"command-code",label:"Command Code",dir:".commandcode/skills"},{name:"continue",label:"Continue",dir:".continue/skills"},{name:"cortex",label:"Cortex Code",dir:".snowflake/cortex/skills"},{name:"crush",label:"Crush",dir:".config/crush/skills"},{name:"cursor",label:"Cursor",dir:".cursor/skills"},{name:"deepagents",label:"Deep Agents",dir:".deepagents/agent/skills",detect:[".deepagents"]},{name:"devin",label:"Devin for Terminal",dir:".config/devin/skills"},{name:"dexto",label:"Dexto",dir:W,detect:[".dexto"]},{name:"droid",label:"Droid",dir:".factory/skills"},{name:"firebender",label:"Firebender",dir:".firebender/skills"},{name:"forgecode",label:"ForgeCode",dir:".forge/skills"},{name:"fx",label:"fx",dir:".fx/skills"},{name:"gemini-cli",label:"Gemini CLI",dir:".gemini/skills"},{name:"github-copilot",label:"GitHub Copilot",dir:".copilot/skills"},{name:"goose",label:"Goose",dir:".config/goose/skills"},{name:"grok",label:"Grok Build",dir:".grok/skills"},{name:"hermes-agent",label:"Hermes Agent",dir:".hermes/skills"},{name:"inference-sh",label:"inference.sh",dir:".inferencesh/skills"},{name:"jazz",label:"Jazz",dir:".jazz/skills"},{name:"junie",label:"Junie",dir:".junie/skills"},{name:"iflow-cli",label:"iFlow CLI",dir:".iflow/skills"},{name:"kilo",label:"Kilo Code",dir:".kilo/skills",detect:[".kilo",".kilocode"]},{name:"kimchi",label:"Kimchi",dir:".config/kimchi/harness/skills",detect:[".config/kimchi"]},{name:"kimi-code-cli",label:"Kimi Code CLI",dir:W,detect:[".kimi-code",".kimi"]},{name:"kiro-cli",label:"Kiro CLI",dir:".kiro/skills"},{name:"kode",label:"Kode",dir:".kode/skills"},{name:"lingma",label:"Lingma",dir:".lingma/skills"},{name:"loaf",label:"Loaf",dir:W,detect:[".loaf"]},{name:"mcpjam",label:"MCPJam",dir:".mcpjam/skills"},{name:"minimax-code",label:"MiniMax Code",dir:".minimax/skills",detect:[".minimax","/Applications/MiniMax Code.app"]},{name:"mistral-vibe",label:"Mistral Vibe",dir:".vibe/skills"},{name:"moxby",label:"Moxby",dir:".moxby/skills"},{name:"mux",label:"Mux",dir:".mux/skills"},{name:"opencode",label:"OpenCode",dir:".config/opencode/skills"},{name:"openhands",label:"OpenHands",dir:".openhands/skills"},{name:"ona",label:"Ona",dir:".ona/skills"},{name:"pi",label:"Pi",dir:".pi/agent/skills"},{name:"posit-assistant",label:"Posit Assistant",dir:".posit/assistant/skills",detect:[".posit/assistant",".positai"]},{name:"qoder",label:"Qoder",dir:".qoder/skills"},{name:"qoder-cn",label:"Qoder CN",dir:".qoder-cn/skills"},{name:"qwen-code",label:"Qwen Code",dir:".qwen/skills"},{name:"replit",label:"Replit",dir:".config/agents/skills"},{name:"reasonix",label:"Reasonix",dir:".reasonix/skills"},{name:"rovodev",label:"Rovo Dev",dir:".rovodev/skills"},{name:"roo",label:"Roo Code",dir:".roo/skills"},{name:"sarvam-code",label:"Sarvam Code",dir:W,detect:[".sarvam"]},{name:"tabnine-cli",label:"Tabnine CLI",dir:".tabnine/agent/skills",detect:[".tabnine"]},{name:"terramind",label:"Terramind",dir:".terramind/skills"},{name:"tinycloud",label:"Tinycloud",dir:".tinycloud/skills"},{name:"trae",label:"Trae",dir:".trae/skills"},{name:"trae-cn",label:"Trae CN",dir:".trae-cn/skills"},{name:"warp",label:"Warp",dir:W,detect:[".warp"]},{name:"windsurf",label:"Windsurf",dir:".codeium/windsurf/skills"},{name:"zed",label:"Zed",dir:W,detect:[".config/zed"]},{name:"zcode",label:"ZCode",dir:".zcode/skills",detect:[".zcode","/Applications/ZCode.app"]},{name:"zencoder",label:"Zencoder",dir:".zencoder/skills"},{name:"zenflow",label:"Zenflow",dir:".zencoder/skills"},{name:"neovate",label:"Neovate",dir:".neovate/skills"},{name:"pochi",label:"Pochi",dir:".pochi/skills"},{name:"adal",label:"AdaL",dir:".adal/skills"},{name:"universal",label:"Universal",dir:".config/agents/skills"}],dt;function Cn(){if(dt)return dt;let e=(0,k.dirname)((0,Tn.fileURLToPath)(v));for(;;){let t=(0,k.join)(e,"package.json");if((0,y.existsSync)(t))try{if(JSON.parse(R(t)).name===xn)return dt=e,e}catch{}let n=(0,k.dirname)(e);if(n===e)break;e=n}throw new Error(`\u672A\u80FD\u4ECE\u6A21\u5757\u4F4D\u7F6E\u5411\u4E0A\u5B9A\u4F4D ${xn} \u7684\u5305\u6839\u76EE\u5F55`)}function Z(){return(0,k.join)(Cn(),"skills")}function ft(){return Cn()}function xo(e){try{let n=R((0,k.join)(e,ut)).match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!n)return"";let r=(n[1]??"").match(/^[ \t]+version:[ \t]*"?([^"\r\n]+?)"?[ \t]*$/m);return r?(r[1]??"").trim():""}catch{return""}}function $o(e){try{let n=R((0,k.join)(e,ut)).match(/^>[ \t]*本技能版本[ \t]*([^ \t((]+)/m);return n?(n[1]??"").trim():""}catch{return""}}function To(e){let t=[];for(let n of e){if(!n.version)continue;let r=$o(n.dir);r!==n.version&&t.push({name:n.name,frontmatter:n.version,body:r})}return t}function $e(){let e=Z();if(!(0,y.existsSync)(e))return[];let t=[];for(let n of(0,y.readdirSync)(e).sort()){let r=(0,k.join)(e,n);try{if(!(0,y.lstatSync)(r).isDirectory())continue}catch{continue}(0,y.existsSync)((0,k.join)(r,ut))&&t.push({name:n,dir:r,version:xo(r)})}return t}function N(e){let t=(0,k.normalize)((0,k.resolve)(e));return process.platform==="win32"?t.toLowerCase():t}function Ro(e){let t=(0,k.normalize)(e);return/^[a-zA-Z]:[\\/]$/.test(t)?t:t.replace(/[\\/]+$/,"")||t}function Ye(e,t,n,r=!1){let o;if(n)o=n;else try{o=(0,y.lstatSync)(e)}catch{return"absent"}if(o.isSymbolicLink()){let s="";try{s=(0,y.readlinkSync)(e)}catch{return"dangling"}let i=Ro((0,k.isAbsolute)(s)?s:(0,k.resolve)((0,k.dirname)(e),s));return N(i)!==N(t)?"wrong":r||(0,y.existsSync)(e)?"link-ok":"dangling"}return o.isDirectory()?"dir":"file"}function We(e,t){let n,r;try{n=(0,y.readdirSync)(e).sort(),r=(0,y.readdirSync)(t).sort()}catch{return!1}if(n.length!==r.length||n.some((o,s)=>o!==r[s]))return!1;for(let o of n){let s=(0,k.join)(e,o),i=(0,k.join)(t,o),a,l;try{a=(0,y.statSync)(s),l=(0,y.statSync)(i)}catch{return!1}if(a.isDirectory()!==l.isDirectory())return!1;if(a.isDirectory()){if(!We(s,i))return!1}else try{if(!(0,y.readFileSync)(s).equals((0,y.readFileSync)(i)))return!1}catch{return!1}}return!0}function Te(){return(0,k.join)(ae(),".agents",wo)}function Ke(){let e=Te();if(!(0,y.existsSync)(e))return null;try{let t=JSON.parse(R(e));return!t||!Array.isArray(t.targets)?null:t}catch{return null}}function En(e){let t=Te();(0,y.mkdirSync)((0,k.dirname)(t),{recursive:!0});let n={version:1,updatedAt:new Date().toISOString(),targets:e};$(t,`${JSON.stringify(n,null,2)}
98
- `)}function Ln(e=[]){let t=ae(),n=[],r=new Set,o=(s,i,a,l)=>{let d=(0,k.resolve)(s),u=N(d);r.has(u)||(r.add(u),n.push({dir:d,label:i,kind:a,available:l,dirExists:(0,y.existsSync)(d)}))};o((0,k.join)(t,W),Rn,"primary",!0);for(let s of An){let i=(0,k.join)(t,(0,k.dirname)(s.dir)),a=(0,y.existsSync)(i)||(s.detect??[]).some(l=>(0,y.existsSync)((0,k.isAbsolute)(l)?l:(0,k.join)(t,l)));o((0,k.join)(t,s.dir),s.label,"agent",a)}for(let s of e)o(s,"\u81EA\u5B9A\u4E49 --dir","custom",!0);return n}function Ao(e){let t=N((0,k.resolve)(e));return t===N((0,k.join)(ae(),W))?Rn:An.find(r=>N((0,k.join)(ae(),r.dir))===t)?.label??null}function mt(e){(0,y.rmSync)(e,{recursive:!0,force:!0})}function $n(e,t){(0,y.mkdirSync)((0,k.dirname)(t),{recursive:!0}),(0,y.cpSync)(e,t,{recursive:!0})}function Co(e,t,n){if(n)return $n(e,t),{mode:"copy"};try{return(0,y.mkdirSync)((0,k.dirname)(t),{recursive:!0}),(0,y.symlinkSync)(e,t,process.platform==="win32"?"junction":"dir"),{mode:"link"}}catch(r){return $n(e,t),{mode:"copy",reason:r.message}}}function In(e={}){let t=$e(),n=Ln(e.dirs??[]),r=Ke(),o=new Map;for(let l of r?.targets??[])o.set(N(l.dir),l);let s=[],i=[],a=[];for(let l of n){if(!l.available){i.push({dir:l.dir,label:l.label});continue}let d={dir:l.dir,label:l.label,kind:l.kind,created:[],updated:[],skipped:[],conflicts:[],failed:[],degraded:[],links:[],copies:[]};for(let u of t){let m=(0,k.join)(l.dir,u.name),p=Ye(m,u.dir);if(p==="link-ok"){d.skipped.push(u.name),d.links.push(u.name);continue}if(p==="dir"&&!e.force){if(!(o.get(N(l.dir))?.copies.includes(u.name)??!1)){d.conflicts.push(u.name);continue}if(We(u.dir,m)){d.skipped.push(u.name),d.copies.push(u.name);continue}}if(p==="file"&&!e.force){d.conflicts.push(u.name);continue}if(e.dryRun){p==="absent"?d.created.push(u.name):d.updated.push(u.name),e.copy?d.copies.push(u.name):d.links.push(u.name);continue}try{p!=="absent"&&mt(m);let c=Co(u.dir,m,!!e.copy);p==="absent"?d.created.push(u.name):d.updated.push(u.name),c.mode==="link"?d.links.push(u.name):(d.copies.push(u.name),c.reason&&d.degraded.push({name:u.name,reason:c.reason}))}catch(c){d.failed.push({name:u.name,reason:c.message})}}s.push(d),e.dryRun||a.push({dir:l.dir,updatedAt:new Date().toISOString(),links:d.links,copies:d.copies})}if(!e.dryRun){let l=new Set(s.map(m=>N(m.dir))),d=(r?.targets??[]).filter(m=>!l.has(N(m.dir))),u=[...a,...d].filter(m=>m.links.length>0||m.copies.length>0);u.length>0&&En(u)}return{source:Z(),skills:t.map(l=>l.name),targets:s,skippedTargets:i,stateFile:Te()}}function Fn(e={}){let t=Ke(),n=Te();if(!t)return{stateFile:n,stateExists:!1,targets:[],stateRemoved:!1};let r=[],o=!1;for(let a of t.targets){let l={dir:a.dir,label:Ao(a.dir),removed:[],missing:[],skippedForeign:[]},d=[...new Set([...a.links,...a.copies])];for(let u of d){let m=(0,k.join)(a.dir,u),p=(0,k.join)(Z(),u),c=Ye(m,p);if(c==="absent"){l.missing.push(u);continue}if(c==="wrong"){l.skippedForeign.push(u);continue}if(c==="file"){l.skippedForeign.push(u);continue}if(c==="dir"&&!We(p,m)){l.skippedForeign.push(u);continue}if(e.dryRun){l.removed.push(u);continue}try{mt(m),l.removed.push(u)}catch{o=!0,l.skippedForeign.push(u)}}r.push(l)}let s=r.every(a=>a.skippedForeign.length===0),i=!e.dryRun&&!o&&s;return i&&(0,y.rmSync)(n,{force:!0}),{stateFile:n,stateExists:!0,targets:r,stateRemoved:i}}function On(){let e=$e(),t=Ln([]),n=Ke(),r=new Map;for(let i of n?.targets??[])r.set(N(i.dir),i);let o=[],s=[];for(let i of t){let a=r.get(N(i.dir));if(!i.available&&i.kind==="agent"){s.push({dir:i.dir,label:i.label});continue}if(i.kind!=="primary"&&!i.dirExists&&!a)continue;let l=[...new Set([...e.map(m=>m.name),...a?[...a.links,...a.copies]:[]])].sort(),d=new Map(e.map(m=>[m.name,m.version])),u=[];for(let m of l){let p=(0,k.join)(Z(),m),c=(0,k.join)(i.dir,m),f=Ye(c,p),g;f==="link-ok"?g="link":f==="dangling"?g="dangling":f==="wrong"?g="wrong":f==="file"?g="conflict":f==="dir"?(0,y.existsSync)(p)&&We(p,c)?g="copy":g=a?.copies.includes(m)?"copy-drift":"conflict":g="missing",u.push({name:m,state:g,version:d.get(m)??""})}o.push({dir:i.dir,label:i.label,kind:i.kind,available:i.available,dirExists:i.dirExists,recorded:!!a,items:u})}return{source:Z(),skills:e.map(i=>i.name),skillVersions:Object.fromEntries(e.map(i=>[i.name,i.version])),versionMismatches:To(e),stateFile:Te(),stateExists:!!n,targets:o,pendingAgents:s}}function jn(){let e=_("skills");if(e?.autoLink===!1||process.env.CI)return 0;let t=Ke();if(!t)return 0;let n=Z(),r;try{r=new Set((0,y.readdirSync)(n).filter(l=>(0,y.existsSync)((0,k.join)(n,l))))}catch{return 0}let o=e?.autoLinkReplaceForeign!==!1,s=process.platform==="win32"?"junction":"dir",i=0,a=[];for(let l of t.targets){let d;try{d=(0,y.readdirSync)(l.dir,{withFileTypes:!0})}catch{a.push(l);continue}let u=new Map(d.map(p=>[p.name,p])),m=l.links.filter(p=>{if(!r.has(p))return!1;let c=(0,k.join)(n,p),f=(0,k.join)(l.dir,p),g=u.get(p),h=g?Ye(f,c,g,!0):"absent";if(h==="link-ok"||!o&&(h==="dir"||h==="file"))return!0;try{return h!=="absent"&&mt(f),(0,y.symlinkSync)(c,f,s),i+=1,!0}catch{return!0}});a.push({...l,links:m,updatedAt:new Date().toISOString()})}return i>0&&En(a),i}var me=require("fs"),Dn=require("path"),pt=require("os"),Nn=require("child_process");var Eo="https://registry.npmjs.org/@fxri%2Ftoolkit/latest";async function Mn(){try{let e=await fetch(Eo,{signal:AbortSignal.timeout(1e3),headers:{accept:"application/vnd.npm.install-v1+json"}});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}catch{return null}}function _n(e,t){let n=i=>i.trim().replace(/^-/,"").split(/[.+-]/).map(a=>Number.parseInt(a,10)).map(a=>Number.isFinite(a)?a:0),r=n(e),o=n(t),s=Math.max(r.length,o.length);for(let i=0;i<s;i++){let a=r[i]??0,l=o[i]??0;if(a!==l)return a>l}return!1}var Lo=1440*60*1e3,Io=3600*1e3,Fo="FX_NO_UPDATE_CHECK",gt="--fxri-update-check-worker";function Bn(){return(0,Dn.join)((0,pt.tmpdir)(),".toolkit-update-check.json")}function Oo(){let e=Bn();try{if(!(0,me.existsSync)(e))return null;let t=JSON.parse(R(e)),n=typeof t.ts=="number"?t.ts:0,r=typeof t.latest=="string"?t.latest:"",o=t.ok===!0,s=o?Lo:Io;return Date.now()-n>=s?((0,me.rmSync)(e,{force:!0}),null):o&&!r?null:{ts:n,ok:o,latest:r}}catch{return null}}function jo(e,t){try{let n=Bn();(0,me.mkdirSync)((0,pt.tmpdir)(),{recursive:!0}),$(n,JSON.stringify({ts:Date.now(),ok:e,latest:t}))}catch{}}function Mo(){let e=process.env[Fo];if(e!==void 0&&e!=="")return!["0","false","off","no"].includes(e.trim().toLowerCase());let t=qe()?.updateCheck;return t&&typeof t=="object"?t.enabled===!1:!1}function Pn(e){if(Mo())return;let t=Oo();if(t){t.ok&&_n(t.latest,e)&&Do(t.latest,e);return}_o()}function _o(){let e=process.argv[1];if(e)try{(0,Nn.spawn)(process.execPath,[e,gt],{detached:!0,stdio:"ignore",windowsHide:!0}).unref()}catch{}}async function Un(){let e=await Mn().catch(()=>null);jo(e!==null,e??"")}function Do(e,t){console.error(`\u2B06\uFE0F \u53D1\u73B0\u65B0\u7248\u672C ${e}\uFF08\u5F53\u524D ${t}\uFF09\uFF1Apnpm add -g @fxri/toolkit \u5347\u7EA7\u540E\u8BF7\u5F00\u65B0\u4F1A\u8BDD\u52A0\u8F7D\u6700\u65B0 skills \u89C4\u5219\uFF1B\u672C\u5730\u6280\u80FD\u53EF\u7528 toolkit skills status \u68C0\u67E5\uFF08\u8F6F\u94FE\u81EA\u52A8\u8DDF\u968F\uFF0C\u526F\u672C\u5F62\u5F0F\u9700\u91CD\u8DD1 toolkit skills install\uFF09`)}var No="\u663E\u793A\u5E2E\u52A9",Bo=["version","format"];function ht(e){e.helpOption("-h, --help",No),e.configureHelp({subcommandTerm:t=>`${t.name()} ${t.usage()}`.replace(/\s+/g," ").trim()});for(let t of e.commands)ht(t)}function zn(e){return Bo.includes(e[0])?e.slice(1).some(t=>t==="-h"||t==="--help"):!1}var kt="\u8FD0\u884C toolkit --help \u67E5\u770B\u53EF\u7528\u547D\u4EE4";function Yn(e){let t=/\n\(Did you mean (one of )?([^)]*?)\?\)$/.exec(e);if(!t)return"";let n=t[2].split(", ").join("\u3001");return t[1]?`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n} \u4E4B\u4E00\uFF1F\uFF09`:`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n}\uFF1F\uFF09`}function Wn(e){switch(e.code){case"commander.unknownCommand":{let t=/unknown command '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u547D\u4EE4\u300C${t}\u300D\u3002${Yn(e.message)}
98
+ `)}function Ln(e=[]){let t=ae(),n=[],r=new Set,o=(s,i,a,l)=>{let d=(0,k.resolve)(s),u=N(d);r.has(u)||(r.add(u),n.push({dir:d,label:i,kind:a,available:l,dirExists:(0,y.existsSync)(d)}))};o((0,k.join)(t,W),Rn,"primary",!0);for(let s of An){let i=(0,k.join)(t,(0,k.dirname)(s.dir)),a=(0,y.existsSync)(i)||(s.detect??[]).some(l=>(0,y.existsSync)((0,k.isAbsolute)(l)?l:(0,k.join)(t,l)));o((0,k.join)(t,s.dir),s.label,"agent",a)}for(let s of e)o(s,"\u81EA\u5B9A\u4E49 --dir","custom",!0);return n}function Ao(e){let t=N((0,k.resolve)(e));return t===N((0,k.join)(ae(),W))?Rn:An.find(r=>N((0,k.join)(ae(),r.dir))===t)?.label??null}function mt(e){(0,y.rmSync)(e,{recursive:!0,force:!0})}function $n(e,t){(0,y.mkdirSync)((0,k.dirname)(t),{recursive:!0}),(0,y.cpSync)(e,t,{recursive:!0})}function Co(e,t,n){if(n)return $n(e,t),{mode:"copy"};try{return(0,y.mkdirSync)((0,k.dirname)(t),{recursive:!0}),(0,y.symlinkSync)(e,t,process.platform==="win32"?"junction":"dir"),{mode:"link"}}catch(r){return $n(e,t),{mode:"copy",reason:r.message}}}function In(e={}){let t=$e(),n=Ln(e.dirs??[]),r=Ke(),o=new Map;for(let l of r?.targets??[])o.set(N(l.dir),l);let s=[],i=[],a=[];for(let l of n){if(!l.available){i.push({dir:l.dir,label:l.label});continue}let d={dir:l.dir,label:l.label,kind:l.kind,created:[],updated:[],skipped:[],conflicts:[],failed:[],degraded:[],links:[],copies:[]};for(let u of t){let m=(0,k.join)(l.dir,u.name),p=Ye(m,u.dir);if(p==="link-ok"){d.skipped.push(u.name),d.links.push(u.name);continue}if(p==="dir"&&!e.force){if(!(o.get(N(l.dir))?.copies.includes(u.name)??!1)){d.conflicts.push(u.name);continue}if(We(u.dir,m)){d.skipped.push(u.name),d.copies.push(u.name);continue}}if(p==="file"&&!e.force){d.conflicts.push(u.name);continue}if(e.dryRun){p==="absent"?d.created.push(u.name):d.updated.push(u.name),e.copy?d.copies.push(u.name):d.links.push(u.name);continue}try{p!=="absent"&&mt(m);let c=Co(u.dir,m,!!e.copy);p==="absent"?d.created.push(u.name):d.updated.push(u.name),c.mode==="link"?d.links.push(u.name):(d.copies.push(u.name),c.reason&&d.degraded.push({name:u.name,reason:c.reason}))}catch(c){d.failed.push({name:u.name,reason:c.message})}}s.push(d),e.dryRun||a.push({dir:l.dir,updatedAt:new Date().toISOString(),links:d.links,copies:d.copies})}if(!e.dryRun){let l=new Set(s.map(m=>N(m.dir))),d=(r?.targets??[]).filter(m=>!l.has(N(m.dir))),u=[...a,...d].filter(m=>m.links.length>0||m.copies.length>0);u.length>0&&En(u)}return{source:Z(),skills:t.map(l=>l.name),targets:s,skippedTargets:i,stateFile:Te()}}function Fn(e={}){let t=Ke(),n=Te();if(!t)return{stateFile:n,stateExists:!1,targets:[],stateRemoved:!1};let r=[],o=!1;for(let a of t.targets){let l={dir:a.dir,label:Ao(a.dir),removed:[],missing:[],skippedForeign:[]},d=[...new Set([...a.links,...a.copies])];for(let u of d){let m=(0,k.join)(a.dir,u),p=(0,k.join)(Z(),u),c=Ye(m,p);if(c==="absent"){l.missing.push(u);continue}if(c==="wrong"){l.skippedForeign.push(u);continue}if(c==="file"){l.skippedForeign.push(u);continue}if(c==="dir"&&!We(p,m)){l.skippedForeign.push(u);continue}if(e.dryRun){l.removed.push(u);continue}try{mt(m),l.removed.push(u)}catch{o=!0,l.skippedForeign.push(u)}}r.push(l)}let s=r.every(a=>a.skippedForeign.length===0),i=!e.dryRun&&!o&&s;return i&&(0,y.rmSync)(n,{force:!0}),{stateFile:n,stateExists:!0,targets:r,stateRemoved:i}}function On(){let e=$e(),t=Ln([]),n=Ke(),r=new Map;for(let i of n?.targets??[])r.set(N(i.dir),i);let o=[],s=[];for(let i of t){let a=r.get(N(i.dir));if(!i.available&&i.kind==="agent"){s.push({dir:i.dir,label:i.label});continue}if(i.kind!=="primary"&&!i.dirExists&&!a)continue;let l=[...new Set([...e.map(m=>m.name),...a?[...a.links,...a.copies]:[]])].sort(),d=new Map(e.map(m=>[m.name,m.version])),u=[];for(let m of l){let p=(0,k.join)(Z(),m),c=(0,k.join)(i.dir,m),f=Ye(c,p),g;f==="link-ok"?g="link":f==="dangling"?g="dangling":f==="wrong"?g="wrong":f==="file"?g="conflict":f==="dir"?(0,y.existsSync)(p)&&We(p,c)?g="copy":g=a?.copies.includes(m)?"copy-drift":"conflict":g="missing",u.push({name:m,state:g,version:d.get(m)??""})}o.push({dir:i.dir,label:i.label,kind:i.kind,available:i.available,dirExists:i.dirExists,recorded:!!a,items:u})}return{source:Z(),skills:e.map(i=>i.name),skillVersions:Object.fromEntries(e.map(i=>[i.name,i.version])),versionMismatches:To(e),stateFile:Te(),stateExists:!!n,targets:o,pendingAgents:s}}function jn(){let e=_("skills");if(e?.autoLink===!1||process.env.CI)return 0;let t=Ke();if(!t)return 0;let n=Z(),r;try{r=new Set((0,y.readdirSync)(n).filter(l=>(0,y.existsSync)((0,k.join)(n,l))))}catch{return 0}let o=e?.autoLinkReplaceForeign!==!1,s=process.platform==="win32"?"junction":"dir",i=0,a=[];for(let l of t.targets){let d;try{d=(0,y.readdirSync)(l.dir,{withFileTypes:!0})}catch{a.push(l);continue}let u=new Map(d.map(p=>[p.name,p])),m=l.links.filter(p=>{if(!r.has(p))return!1;let c=(0,k.join)(n,p),f=(0,k.join)(l.dir,p),g=u.get(p),h=g?Ye(f,c,g,!0):"absent";if(h==="link-ok"||!o&&(h==="dir"||h==="file"))return!0;try{return h!=="absent"&&mt(f),(0,y.symlinkSync)(c,f,s),i+=1,!0}catch{return!0}});a.push({...l,links:m,updatedAt:new Date().toISOString()})}return i>0&&En(a),i}var me=require("fs"),Dn=require("path"),pt=require("os"),Nn=require("child_process");var Eo="https://registry.npmjs.org/@fxri%2Ftoolkit/latest";async function Mn(){try{let e=await fetch(Eo,{signal:AbortSignal.timeout(1e3),headers:{accept:"application/vnd.npm.install-v1+json"}});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}catch{return null}}function _n(e,t){let n=i=>i.trim().replace(/^-/,"").split(/[.+-]/).map(a=>Number.parseInt(a,10)).map(a=>Number.isFinite(a)?a:0),r=n(e),o=n(t),s=Math.max(r.length,o.length);for(let i=0;i<s;i++){let a=r[i]??0,l=o[i]??0;if(a!==l)return a>l}return!1}var Lo=1440*60*1e3,Io=3600*1e3,Fo="FX_NO_UPDATE_CHECK",gt="--fxri-update-check-worker";function Bn(){return(0,Dn.join)((0,pt.tmpdir)(),".toolkit-update-check.json")}function Oo(){let e=Bn();try{if(!(0,me.existsSync)(e))return null;let t=JSON.parse(R(e)),n=typeof t.ts=="number"?t.ts:0,r=typeof t.latest=="string"?t.latest:"",o=t.ok===!0,s=o?Lo:Io;return Date.now()-n>=s?((0,me.rmSync)(e,{force:!0}),null):o&&!r?null:{ts:n,ok:o,latest:r}}catch{return null}}function jo(e,t){try{let n=Bn();(0,me.mkdirSync)((0,pt.tmpdir)(),{recursive:!0}),$(n,JSON.stringify({ts:Date.now(),ok:e,latest:t}))}catch{}}function Mo(){let e=process.env[Fo];if(e!==void 0&&e!=="")return!["0","false","off","no"].includes(e.trim().toLowerCase());let t=qe()?.updateCheck;return t&&typeof t=="object"?t.enabled===!1:!1}function Pn(e){if(Mo())return;let t=Oo();if(t){t.ok&&_n(t.latest,e)&&Do(t.latest,e);return}_o()}function _o(){let e=process.argv[1];if(e)try{(0,Nn.spawn)(process.execPath,[e,gt],{detached:!0,stdio:"ignore",windowsHide:!0}).unref()}catch{}}async function Un(){let e=await Mn().catch(()=>null);jo(e!==null,e??"")}function Do(e,t){console.error(`\u2B06\uFE0F \u53D1\u73B0\u65B0\u7248\u672C ${e}\uFF08\u5F53\u524D ${t}\uFF09\uFF1Apnpm add -g @fxri/toolkit \u5347\u7EA7\u540E\u8BF7\u5F00\u65B0\u4F1A\u8BDD\u52A0\u8F7D\u6700\u65B0 skills \u89C4\u5219\uFF1B\u672C\u5730\u6280\u80FD\u53EF\u7528 toolkit skills status \u68C0\u67E5\uFF08\u8F6F\u94FE\u81EA\u52A8\u8DDF\u968F\uFF0C\u526F\u672C\u5F62\u5F0F\u9700\u91CD\u8DD1 toolkit skills install\uFF09`)}var No="\u663E\u793A\u5E2E\u52A9",Bo=["version","format"];function ht(e){e.helpOption("-h, --help",No),e.configureHelp({subcommandTerm:t=>`${t.name()} ${t.usage()}`.replace(/\s+/g," ").trim()});for(let t of e.commands)ht(t)}function zn(e){let[t]=e;return!t||!Bo.includes(t)?!1:e.slice(1).some(n=>n==="-h"||n==="--help")}var kt="\u8FD0\u884C toolkit --help \u67E5\u770B\u53EF\u7528\u547D\u4EE4";function Yn(e){let t=/\n\(Did you mean (one of )?([^)]*?)\?\)$/.exec(e);if(!t)return"";let n=(t[2]??"").split(", ").join("\u3001");return t[1]?`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n} \u4E4B\u4E00\uFF1F\uFF09`:`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n}\uFF1F\uFF09`}function Wn(e){switch(e.code){case"commander.unknownCommand":{let t=/unknown command '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u547D\u4EE4\u300C${t}\u300D\u3002${Yn(e.message)}
99
99
  ${kt}`:null}case"commander.unknownOption":{let t=/unknown option '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u9009\u9879\u300C${t}\u300D\u3002${Yn(e.message)}
100
100
  ${kt}`:null}case"commander.excessArguments":{let t=/too many arguments(?: for '([^']*)')?\. Expected (\d+) arguments? but got (\d+)\./.exec(e.message);return t?`\u26A0\uFE0F ${t[1]?`\u547D\u4EE4\u300C${t[1]}\u300D`:"\u547D\u4EE4"}\u671F\u671B ${t[2]} \u4E2A\u53C2\u6570\uFF0C\u5B9E\u9645\u6536\u5230 ${t[3]} \u4E2A\u3002
101
101
  ${kt}`:null}default:return null}}var Kn="\u4E13\u4E3A\u591A\u4EBA + AI \u8DE8\u9879\u76EE\u534F\u4F5C\u6253\u9020\uFF1A\u4EFB\u52A1\u7BA1\u7406 + \u591A\u8BED\u8A00 CHANGELOG\u3002";var qn=(0,Gn.createRequire)(v),Po=qn.resolve("@changesets/cli/bin.js"),{version:Zn}=qn("../package.json"),bt=e=>{let t=(0,Vn.spawnSync)(process.execPath,[Po,...e],{stdio:"inherit"});t.status!==0&&process.exit(t.status??1)};function Uo(){if(process.platform==="win32")try{process.stdout.setDefaultEncoding("utf8"),process.stderr.setDefaultEncoding("utf8")}catch{}}function Xn(){let e=_("check");return typeof e?.warnings=="boolean"?e.warnings:void 0}function zo(){let t=_("changelog")?.languages;if(!t||typeof t!="object")return ue;let n={...ue};for(let[r,o]of Object.entries(t))o&&typeof o=="object"&&(n[r]=o);return n}function Yo(e=".changeset"){if(!(0,Re.existsSync)(e))return!1;try{return(0,Re.readdirSync)(e).some(t=>t.endsWith(".md")&&t!=="README.md")}catch{return!1}}function Wo(e=".tasks"){return F((0,Jn.join)(e,"active")).length>0}function Hn(e){let t=fn(".",e);t>0&&console.warn(`\u26A0\uFE0F ${t} \u6761\u53D8\u66F4\u96C6\u6761\u76EE\u7F3A\u7C7B\u578B\u524D\u7F00\uFF0C\u5EFA\u8BAE\u6309\u300C\u7C7B\u578B\uFF1A\u63CF\u8FF0\u300D\u64B0\u5199`)}function He(e){if(e.length===0){console.log("\u672A\u53D1\u73B0\u95EE\u9898");return}for(let t of e)console.log(` ${t.file}${t.line?`:${t.line}`:""}: ${t.message}`)}function Ko(e,t){return[...t,e]}var Ho={link:"\u8F6F\u94FE\u6B63\u5E38",dangling:"\u8F6F\u94FE\u60AC\u7A7A\uFF08\u771F\u6E90\u7F3A\u5931\u6216\u5347\u7EA7\u540E\u65E7\u8DEF\u5F84\u5931\u6548\uFF09",wrong:"\u8F6F\u94FE\u6307\u5411\u522B\u5904",copy:"\u526F\u672C\u5DF2\u540C\u6B65","copy-drift":"\u526F\u672C\u5DF2\u6F02\u79FB\uFF08\u4E0E\u771F\u6E90\u4E0D\u4E00\u81F4\uFF09",missing:"\u7F3A\u5931",conflict:"\u540C\u540D\u51B2\u7A81\uFF08\u975E\u672C\u5305\u4EA7\u7269\uFF09"},Go=["dangling","wrong","copy-drift","missing","conflict"];function Ae(e){console.log(wn(e))}function Qn(e,t){return t?`${e}@${t}`:e}function Vo(e,t){let n=t?"[\u9884\u6F14] ":"",r=new Map($e().map(o=>[o.name,o.version]));console.log(`${n}\u6280\u80FD\u6E90\uFF1A${e.source}`),console.log(`${n}\u5305\u5185\u6280\u80FD\uFF08${e.skills.length}\uFF09\uFF1A${e.skills.map(o=>Qn(o,r.get(o)??"")).join("\u3001")||"\u65E0"}`);for(let o of e.targets){console.log(""),console.log(`${o.label}\uFF1A${o.dir}`),o.created.length>0&&console.log(` \u65B0\u5EFA\uFF1A${o.created.join("\u3001")}`),o.updated.length>0&&console.log(` \u91CD\u5EFA/\u66F4\u65B0\uFF1A${o.updated.join("\u3001")}`),o.skipped.length>0&&console.log(` \u8DF3\u8FC7\uFF08\u5DF2\u5C31\u7EEA\uFF09\uFF1A${o.skipped.join("\u3001")}`),o.conflicts.length>0&&console.log(` \u8DF3\u8FC7\uFF08\u540C\u540D\u975E\u672C\u5305\u4EA7\u7269\uFF0C\u5982\u9700\u8986\u76D6\u52A0 --force\uFF09\uFF1A${o.conflicts.join("\u3001")}`);for(let i of o.degraded)console.log(` \u26A0\uFE0F \u964D\u7EA7\u4E3A\u526F\u672C\uFF1A${i.name}\uFF08\u94FE\u63A5\u521B\u5EFA\u5931\u8D25\uFF1A${i.reason}\uFF09`);for(let i of o.failed)console.log(` \u26A0\uFE0F \u5931\u8D25\uFF1A${i.name}\uFF08${i.reason}\uFF09`);let s=[];o.links.length>0&&s.push(`\u8F6F\u94FE ${o.links.length} \u4E2A`),o.copies.length>0&&s.push(`\u526F\u672C ${o.copies.length} \u4E2A`),s.length>0&&console.log(` \u4EA7\u7269\u5F62\u6001\uFF1A${s.join(" / ")}`)}console.log(""),e.skippedTargets.length>0&&console.log(`\u672A\u5B89\u88C5\u7684 agent ${e.skippedTargets.length} \u4E2A\u5DF2\u8DF3\u8FC7\uFF08\u4E0D\u5728\u7528\u6237\u673A\u5668\u4E0A\u51ED\u7A7A\u9020\u76EE\u5F55\uFF09\uFF1B\u5982\u9700\u88C5\u5230\u672A\u8BC6\u522B\u7684 agent\uFF1Atoolkit skills install --dir <\u5176\u5168\u5C40\u6280\u80FD\u76EE\u5F55>`),console.log(`${n}\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}`),t&&console.log("[\u9884\u6F14] \u672A\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\uFF1B\u786E\u8BA4\u65E0\u8BEF\u540E\u53BB\u6389 --dry-run \u6267\u884C")}function Jo(e){console.log(`\u6280\u80FD\u6E90\uFF1A${e.source}`),console.log(`\u6280\u80FD\u7248\u672C\uFF1A${e.skills.map(n=>Qn(n,e.skillVersions[n]??"")).join("\u3001")||"\u65E0"}`);for(let n of e.versionMismatches)console.warn(`\u26A0\uFE0F \u6280\u80FD\u7248\u672C\u53CC\u5199\u4F4D\u4E0D\u4E00\u81F4\uFF1A${n.name}\uFF08frontmatter ${n.frontmatter} / \u6B63\u6587 ${n.body||"\u672A\u58F0\u660E"}\uFF09`);console.log(`\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}${e.stateExists?"":"\uFF08\u672A\u8BB0\u5F55\uFF0C\u5C1A\u672A\u6267\u884C\u8FC7 toolkit skills install\uFF09"}`);let t=0;for(let n of e.targets){console.log(""),console.log(`${n.label}\uFF1A${n.dir}${n.dirExists?"":"\uFF08\u76EE\u5F55\u672A\u521B\u5EFA\uFF09"}`);for(let r of n.items)Go.includes(r.state)&&(t+=1),console.log(` ${r.name}\uFF1A${Ho[r.state]}`)}e.pendingAgents.length>0&&(console.log(""),console.log(`\u672A\u5B89\u88C5\u7684 agent ${e.pendingAgents.length} \u4E2A\u672A\u7EB3\u5165\u5206\u53D1\uFF08\u9700\u8981\u65F6\u7528 toolkit skills install --dir <\u8DEF\u5F84> \u6307\u5B9A\uFF09`)),console.log(""),console.log(t>0?`\u5171 ${t} \u5904\u9700\u5904\u7406\uFF1A\u7F3A\u5931 / \u60AC\u7A7A / \u6307\u5411\u9519\u8BEF / \u526F\u672C\u6F02\u79FB\u7528 toolkit skills install \u8865\u9F50\uFF0C\u540C\u540D\u51B2\u7A81\u7528 toolkit skills install --force \u8986\u76D6`:"\u6240\u6709\u5DF2\u7EB3\u5165\u7684\u76EE\u6807\u5747\u6B63\u5E38")}function qo(e,t){let n=t?"[\u9884\u6F14] ":"";if(!e.stateExists){console.log("\u672A\u627E\u5230\u672C\u5305\u7684\u72B6\u6001\u6587\u4EF6\uFF0C\u6CA1\u6709\u7531\u672C\u5305\u5B89\u88C5\u7684\u4EA7\u7269\u9700\u8981\u6E05\u7406\uFF08\u5176\u4ED6\u65B9\u5F0F\u5B89\u88C5\u7684\u6280\u80FD\u4E0D\u53D7\u5F71\u54CD\uFF09");return}console.log(`${n}\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}`);for(let r of e.targets)console.log(""),console.log(r.label?`${r.label}\uFF1A${r.dir}`:r.dir),r.removed.length>0&&console.log(` ${t?"\u5C06\u79FB\u9664":"\u5DF2\u79FB\u9664"}\uFF1A${r.removed.join("\u3001")}`),r.missing.length>0&&console.log(` \u5DF2\u4E0D\u5B58\u5728\uFF1A${r.missing.join("\u3001")}`),r.skippedForeign.length>0&&console.log(` \u26A0\uFE0F \u8DF3\u8FC7\uFF08\u975E\u672C\u5305\u4EA7\u7269\u6216\u5185\u5BB9\u5DF2\u88AB\u6539\u52A8\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\uFF09\uFF1A${r.skippedForeign.join("\u3001")}`);console.log(""),t?console.log("[\u9884\u6F14] \u672A\u6267\u884C\u5220\u9664\uFF1B\u65E0\u9057\u7559\u6761\u76EE\u65F6\u5C06\u540C\u65F6\u5220\u9664\u72B6\u6001\u6587\u4EF6"):e.stateRemoved?console.log("\u72B6\u6001\u6587\u4EF6\u5DF2\u5220\u9664\uFF0C\u672C\u5305\u4EA7\u7269\u6E05\u7406\u5B8C\u6BD5"):console.log("\u72B6\u6001\u6587\u4EF6\u5DF2\u4FDD\u7559\uFF08\u5B58\u5728\u9700\u4EBA\u5DE5\u786E\u8BA4\u6216\u672A\u79FB\u9664\u7684\u6761\u76EE\uFF09")}var yt=["archive","check","normalize","stats"],K=new Ge.Command,er="";K.name("toolkit").description(Kn).version(Zn,"-v, --version","\u663E\u793A\u7248\u672C\u53F7").enablePositionalOptions(!0).exitOverride().configureOutput({writeErr:e=>{er+=e}});K.addHelpText("after",["","\u6587\u6863\u7AD9\uFF1A",` \u65B0\u624B\u6307\u5357 ${fe.gettingStarted}`,` \u5B8C\u6574\u653B\u7565 ${fe.guide}`,` \u5168\u90E8\u6587\u6863 ${fe.site}`].join(`
package/dist/cli.js CHANGED
@@ -95,7 +95,7 @@ ${n.deps}`,n.deps);for(;;){let h=l.replace(/^- (.+)\n- \1$/gm,"- $1");if(h===l)b
95
95
  `:`
96
96
  `,o=n.endsWith(`
97
97
  `)||n===""?n:n+r;$(t,o+vn.replace(/\n/g,r).replace(/^\r?\n/,""))}function Sn(e){return JSON.stringify({schemaVersion:1,...e},null,2)}function V(e){return e&&e!=="json"?(console.error(`\u26A0\uFE0F \u4E0D\u652F\u6301\u7684\u8F93\u51FA\u683C\u5F0F\u300C${e}\u300D\uFF0C\u4EC5\u652F\u6301 json`),process.exitCode=1,!1):!0}import{cpSync as as,existsSync as M,lstatSync as An,mkdirSync as st,readdirSync as he,readFileSync as xn,readlinkSync as ls,rmSync as Cn,statSync as $n,symlinkSync as En}from"fs";import{dirname as J,isAbsolute as Ln,join as S,normalize as Fn,resolve as _e}from"path";import{fileURLToPath as cs}from"url";var Tn="@fxri/toolkit",it="SKILL.md",_=".agents/skills",In="canonical\uFF08\u591A\u5BB6 agent \u5171\u8BFB\uFF09",ds=".toolkit-skills.json",On=[{name:"aider-desk",label:"AiderDesk",dir:".aider-desk/skills"},{name:"amp",label:"Amp",dir:".config/agents/skills",detect:[".config/amp"]},{name:"antigravity",label:"Antigravity",dir:".gemini/antigravity/skills"},{name:"antigravity-cli",label:"Antigravity CLI",dir:".gemini/antigravity-cli/skills"},{name:"astrbot",label:"AstrBot",dir:".astrbot/data/skills",detect:[".astrbot"]},{name:"autohand-code",label:"Autohand Code CLI",dir:".autohand/skills"},{name:"augment",label:"Augment",dir:".augment/skills"},{name:"bob",label:"IBM Bob",dir:".bob/skills"},{name:"claude-code",label:"Claude Code",dir:".claude/skills"},{name:"openclaw",label:"OpenClaw",dir:".openclaw/skills",detect:[".openclaw",".clawdbot",".moltbot"]},{name:"cline",label:"Cline",dir:_,detect:[".cline"]},{name:"codearts-agent",label:"CodeArts Agent",dir:".codeartsdoer/skills"},{name:"codebuddy",label:"CodeBuddy",dir:".codebuddy/skills"},{name:"codemaker",label:"Codemaker",dir:".codemaker/skills"},{name:"codestudio",label:"Code Studio",dir:".codestudio/skills"},{name:"codex",label:"Codex",dir:".codex/skills",detect:[".codex","/etc/codex"]},{name:"command-code",label:"Command Code",dir:".commandcode/skills"},{name:"continue",label:"Continue",dir:".continue/skills"},{name:"cortex",label:"Cortex Code",dir:".snowflake/cortex/skills"},{name:"crush",label:"Crush",dir:".config/crush/skills"},{name:"cursor",label:"Cursor",dir:".cursor/skills"},{name:"deepagents",label:"Deep Agents",dir:".deepagents/agent/skills",detect:[".deepagents"]},{name:"devin",label:"Devin for Terminal",dir:".config/devin/skills"},{name:"dexto",label:"Dexto",dir:_,detect:[".dexto"]},{name:"droid",label:"Droid",dir:".factory/skills"},{name:"firebender",label:"Firebender",dir:".firebender/skills"},{name:"forgecode",label:"ForgeCode",dir:".forge/skills"},{name:"fx",label:"fx",dir:".fx/skills"},{name:"gemini-cli",label:"Gemini CLI",dir:".gemini/skills"},{name:"github-copilot",label:"GitHub Copilot",dir:".copilot/skills"},{name:"goose",label:"Goose",dir:".config/goose/skills"},{name:"grok",label:"Grok Build",dir:".grok/skills"},{name:"hermes-agent",label:"Hermes Agent",dir:".hermes/skills"},{name:"inference-sh",label:"inference.sh",dir:".inferencesh/skills"},{name:"jazz",label:"Jazz",dir:".jazz/skills"},{name:"junie",label:"Junie",dir:".junie/skills"},{name:"iflow-cli",label:"iFlow CLI",dir:".iflow/skills"},{name:"kilo",label:"Kilo Code",dir:".kilo/skills",detect:[".kilo",".kilocode"]},{name:"kimchi",label:"Kimchi",dir:".config/kimchi/harness/skills",detect:[".config/kimchi"]},{name:"kimi-code-cli",label:"Kimi Code CLI",dir:_,detect:[".kimi-code",".kimi"]},{name:"kiro-cli",label:"Kiro CLI",dir:".kiro/skills"},{name:"kode",label:"Kode",dir:".kode/skills"},{name:"lingma",label:"Lingma",dir:".lingma/skills"},{name:"loaf",label:"Loaf",dir:_,detect:[".loaf"]},{name:"mcpjam",label:"MCPJam",dir:".mcpjam/skills"},{name:"minimax-code",label:"MiniMax Code",dir:".minimax/skills",detect:[".minimax","/Applications/MiniMax Code.app"]},{name:"mistral-vibe",label:"Mistral Vibe",dir:".vibe/skills"},{name:"moxby",label:"Moxby",dir:".moxby/skills"},{name:"mux",label:"Mux",dir:".mux/skills"},{name:"opencode",label:"OpenCode",dir:".config/opencode/skills"},{name:"openhands",label:"OpenHands",dir:".openhands/skills"},{name:"ona",label:"Ona",dir:".ona/skills"},{name:"pi",label:"Pi",dir:".pi/agent/skills"},{name:"posit-assistant",label:"Posit Assistant",dir:".posit/assistant/skills",detect:[".posit/assistant",".positai"]},{name:"qoder",label:"Qoder",dir:".qoder/skills"},{name:"qoder-cn",label:"Qoder CN",dir:".qoder-cn/skills"},{name:"qwen-code",label:"Qwen Code",dir:".qwen/skills"},{name:"replit",label:"Replit",dir:".config/agents/skills"},{name:"reasonix",label:"Reasonix",dir:".reasonix/skills"},{name:"rovodev",label:"Rovo Dev",dir:".rovodev/skills"},{name:"roo",label:"Roo Code",dir:".roo/skills"},{name:"sarvam-code",label:"Sarvam Code",dir:_,detect:[".sarvam"]},{name:"tabnine-cli",label:"Tabnine CLI",dir:".tabnine/agent/skills",detect:[".tabnine"]},{name:"terramind",label:"Terramind",dir:".terramind/skills"},{name:"tinycloud",label:"Tinycloud",dir:".tinycloud/skills"},{name:"trae",label:"Trae",dir:".trae/skills"},{name:"trae-cn",label:"Trae CN",dir:".trae-cn/skills"},{name:"warp",label:"Warp",dir:_,detect:[".warp"]},{name:"windsurf",label:"Windsurf",dir:".codeium/windsurf/skills"},{name:"zed",label:"Zed",dir:_,detect:[".config/zed"]},{name:"zcode",label:"ZCode",dir:".zcode/skills",detect:[".zcode","/Applications/ZCode.app"]},{name:"zencoder",label:"Zencoder",dir:".zencoder/skills"},{name:"zenflow",label:"Zenflow",dir:".zencoder/skills"},{name:"neovate",label:"Neovate",dir:".neovate/skills"},{name:"pochi",label:"Pochi",dir:".pochi/skills"},{name:"adal",label:"AdaL",dir:".adal/skills"},{name:"universal",label:"Universal",dir:".config/agents/skills"}],ot;function jn(){if(ot)return ot;let e=J(cs(import.meta.url));for(;;){let t=S(e,"package.json");if(M(t))try{if(JSON.parse(T(t)).name===Tn)return ot=e,e}catch{}let n=J(e);if(n===e)break;e=n}throw new Error(`\u672A\u80FD\u4ECE\u6A21\u5757\u4F4D\u7F6E\u5411\u4E0A\u5B9A\u4F4D ${Tn} \u7684\u5305\u6839\u76EE\u5F55`)}function Y(){return S(jn(),"skills")}function at(){return jn()}function us(e){try{let n=T(S(e,it)).match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!n)return"";let r=(n[1]??"").match(/^[ \t]+version:[ \t]*"?([^"\r\n]+?)"?[ \t]*$/m);return r?(r[1]??"").trim():""}catch{return""}}function fs(e){try{let n=T(S(e,it)).match(/^>[ \t]*本技能版本[ \t]*([^ \t((]+)/m);return n?(n[1]??"").trim():""}catch{return""}}function ms(e){let t=[];for(let n of e){if(!n.version)continue;let r=fs(n.dir);r!==n.version&&t.push({name:n.name,frontmatter:n.version,body:r})}return t}function ke(){let e=Y();if(!M(e))return[];let t=[];for(let n of he(e).sort()){let r=S(e,n);try{if(!An(r).isDirectory())continue}catch{continue}M(S(r,it))&&t.push({name:n,dir:r,version:us(r)})}return t}function I(e){let t=Fn(_e(e));return process.platform==="win32"?t.toLowerCase():t}function ps(e){let t=Fn(e);return/^[a-zA-Z]:[\\/]$/.test(t)?t:t.replace(/[\\/]+$/,"")||t}function De(e,t,n,r=!1){let o;if(n)o=n;else try{o=An(e)}catch{return"absent"}if(o.isSymbolicLink()){let s="";try{s=ls(e)}catch{return"dangling"}let i=ps(Ln(s)?s:_e(J(e),s));return I(i)!==I(t)?"wrong":r||M(e)?"link-ok":"dangling"}return o.isDirectory()?"dir":"file"}function Ne(e,t){let n,r;try{n=he(e).sort(),r=he(t).sort()}catch{return!1}if(n.length!==r.length||n.some((o,s)=>o!==r[s]))return!1;for(let o of n){let s=S(e,o),i=S(t,o),a,l;try{a=$n(s),l=$n(i)}catch{return!1}if(a.isDirectory()!==l.isDirectory())return!1;if(a.isDirectory()){if(!Ne(s,i))return!1}else try{if(!xn(s).equals(xn(i)))return!1}catch{return!1}}return!0}function be(){return S(q(),".agents",ds)}function Be(){let e=be();if(!M(e))return null;try{let t=JSON.parse(T(e));return!t||!Array.isArray(t.targets)?null:t}catch{return null}}function Mn(e){let t=be();st(J(t),{recursive:!0});let n={version:1,updatedAt:new Date().toISOString(),targets:e};$(t,`${JSON.stringify(n,null,2)}
98
- `)}function _n(e=[]){let t=q(),n=[],r=new Set,o=(s,i,a,l)=>{let d=_e(s),u=I(d);r.has(u)||(r.add(u),n.push({dir:d,label:i,kind:a,available:l,dirExists:M(d)}))};o(S(t,_),In,"primary",!0);for(let s of On){let i=S(t,J(s.dir)),a=M(i)||(s.detect??[]).some(l=>M(Ln(l)?l:S(t,l)));o(S(t,s.dir),s.label,"agent",a)}for(let s of e)o(s,"\u81EA\u5B9A\u4E49 --dir","custom",!0);return n}function gs(e){let t=I(_e(e));return t===I(S(q(),_))?In:On.find(r=>I(S(q(),r.dir))===t)?.label??null}function lt(e){Cn(e,{recursive:!0,force:!0})}function Rn(e,t){st(J(t),{recursive:!0}),as(e,t,{recursive:!0})}function hs(e,t,n){if(n)return Rn(e,t),{mode:"copy"};try{return st(J(t),{recursive:!0}),En(e,t,process.platform==="win32"?"junction":"dir"),{mode:"link"}}catch(r){return Rn(e,t),{mode:"copy",reason:r.message}}}function Dn(e={}){let t=ke(),n=_n(e.dirs??[]),r=Be(),o=new Map;for(let l of r?.targets??[])o.set(I(l.dir),l);let s=[],i=[],a=[];for(let l of n){if(!l.available){i.push({dir:l.dir,label:l.label});continue}let d={dir:l.dir,label:l.label,kind:l.kind,created:[],updated:[],skipped:[],conflicts:[],failed:[],degraded:[],links:[],copies:[]};for(let u of t){let m=S(l.dir,u.name),p=De(m,u.dir);if(p==="link-ok"){d.skipped.push(u.name),d.links.push(u.name);continue}if(p==="dir"&&!e.force){if(!(o.get(I(l.dir))?.copies.includes(u.name)??!1)){d.conflicts.push(u.name);continue}if(Ne(u.dir,m)){d.skipped.push(u.name),d.copies.push(u.name);continue}}if(p==="file"&&!e.force){d.conflicts.push(u.name);continue}if(e.dryRun){p==="absent"?d.created.push(u.name):d.updated.push(u.name),e.copy?d.copies.push(u.name):d.links.push(u.name);continue}try{p!=="absent"&&lt(m);let c=hs(u.dir,m,!!e.copy);p==="absent"?d.created.push(u.name):d.updated.push(u.name),c.mode==="link"?d.links.push(u.name):(d.copies.push(u.name),c.reason&&d.degraded.push({name:u.name,reason:c.reason}))}catch(c){d.failed.push({name:u.name,reason:c.message})}}s.push(d),e.dryRun||a.push({dir:l.dir,updatedAt:new Date().toISOString(),links:d.links,copies:d.copies})}if(!e.dryRun){let l=new Set(s.map(m=>I(m.dir))),d=(r?.targets??[]).filter(m=>!l.has(I(m.dir))),u=[...a,...d].filter(m=>m.links.length>0||m.copies.length>0);u.length>0&&Mn(u)}return{source:Y(),skills:t.map(l=>l.name),targets:s,skippedTargets:i,stateFile:be()}}function Nn(e={}){let t=Be(),n=be();if(!t)return{stateFile:n,stateExists:!1,targets:[],stateRemoved:!1};let r=[],o=!1;for(let a of t.targets){let l={dir:a.dir,label:gs(a.dir),removed:[],missing:[],skippedForeign:[]},d=[...new Set([...a.links,...a.copies])];for(let u of d){let m=S(a.dir,u),p=S(Y(),u),c=De(m,p);if(c==="absent"){l.missing.push(u);continue}if(c==="wrong"){l.skippedForeign.push(u);continue}if(c==="file"){l.skippedForeign.push(u);continue}if(c==="dir"&&!Ne(p,m)){l.skippedForeign.push(u);continue}if(e.dryRun){l.removed.push(u);continue}try{lt(m),l.removed.push(u)}catch{o=!0,l.skippedForeign.push(u)}}r.push(l)}let s=r.every(a=>a.skippedForeign.length===0),i=!e.dryRun&&!o&&s;return i&&Cn(n,{force:!0}),{stateFile:n,stateExists:!0,targets:r,stateRemoved:i}}function Bn(){let e=ke(),t=_n([]),n=Be(),r=new Map;for(let i of n?.targets??[])r.set(I(i.dir),i);let o=[],s=[];for(let i of t){let a=r.get(I(i.dir));if(!i.available&&i.kind==="agent"){s.push({dir:i.dir,label:i.label});continue}if(i.kind!=="primary"&&!i.dirExists&&!a)continue;let l=[...new Set([...e.map(m=>m.name),...a?[...a.links,...a.copies]:[]])].sort(),d=new Map(e.map(m=>[m.name,m.version])),u=[];for(let m of l){let p=S(Y(),m),c=S(i.dir,m),f=De(c,p),g;f==="link-ok"?g="link":f==="dangling"?g="dangling":f==="wrong"?g="wrong":f==="file"?g="conflict":f==="dir"?M(p)&&Ne(p,c)?g="copy":g=a?.copies.includes(m)?"copy-drift":"conflict":g="missing",u.push({name:m,state:g,version:d.get(m)??""})}o.push({dir:i.dir,label:i.label,kind:i.kind,available:i.available,dirExists:i.dirExists,recorded:!!a,items:u})}return{source:Y(),skills:e.map(i=>i.name),skillVersions:Object.fromEntries(e.map(i=>[i.name,i.version])),versionMismatches:ms(e),stateFile:be(),stateExists:!!n,targets:o,pendingAgents:s}}function Pn(){let e=L("skills");if(e?.autoLink===!1||process.env.CI)return 0;let t=Be();if(!t)return 0;let n=Y(),r;try{r=new Set(he(n).filter(l=>M(S(n,l))))}catch{return 0}let o=e?.autoLinkReplaceForeign!==!1,s=process.platform==="win32"?"junction":"dir",i=0,a=[];for(let l of t.targets){let d;try{d=he(l.dir,{withFileTypes:!0})}catch{a.push(l);continue}let u=new Map(d.map(p=>[p.name,p])),m=l.links.filter(p=>{if(!r.has(p))return!1;let c=S(n,p),f=S(l.dir,p),g=u.get(p),h=g?De(f,c,g,!0):"absent";if(h==="link-ok"||!o&&(h==="dir"||h==="file"))return!0;try{return h!=="absent"&&lt(f),En(c,f,s),i+=1,!0}catch{return!0}});a.push({...l,links:m,updatedAt:new Date().toISOString()})}return i>0&&Mn(a),i}import{existsSync as bs,mkdirSync as ys,rmSync as vs}from"fs";import{join as ws}from"path";import{tmpdir as Yn}from"os";import{spawn as Ss}from"child_process";var ks="https://registry.npmjs.org/@fxri%2Ftoolkit/latest";async function Un(){try{let e=await fetch(ks,{signal:AbortSignal.timeout(1e3),headers:{accept:"application/vnd.npm.install-v1+json"}});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}catch{return null}}function zn(e,t){let n=i=>i.trim().replace(/^-/,"").split(/[.+-]/).map(a=>Number.parseInt(a,10)).map(a=>Number.isFinite(a)?a:0),r=n(e),o=n(t),s=Math.max(r.length,o.length);for(let i=0;i<s;i++){let a=r[i]??0,l=o[i]??0;if(a!==l)return a>l}return!1}var xs=1440*60*1e3,$s=3600*1e3,Ts="FX_NO_UPDATE_CHECK",ct="--fxri-update-check-worker";function Wn(){return ws(Yn(),".toolkit-update-check.json")}function Rs(){let e=Wn();try{if(!bs(e))return null;let t=JSON.parse(T(e)),n=typeof t.ts=="number"?t.ts:0,r=typeof t.latest=="string"?t.latest:"",o=t.ok===!0,s=o?xs:$s;return Date.now()-n>=s?(vs(e,{force:!0}),null):o&&!r?null:{ts:n,ok:o,latest:r}}catch{return null}}function As(e,t){try{let n=Wn();ys(Yn(),{recursive:!0}),$(n,JSON.stringify({ts:Date.now(),ok:e,latest:t}))}catch{}}function Cs(){let e=process.env[Ts];if(e!==void 0&&e!=="")return!["0","false","off","no"].includes(e.trim().toLowerCase());let t=Ye()?.updateCheck;return t&&typeof t=="object"?t.enabled===!1:!1}function Kn(e){if(Cs())return;let t=Rs();if(t){t.ok&&zn(t.latest,e)&&Ls(t.latest,e);return}Es()}function Es(){let e=process.argv[1];if(e)try{Ss(process.execPath,[e,ct],{detached:!0,stdio:"ignore",windowsHide:!0}).unref()}catch{}}async function Hn(){let e=await Un().catch(()=>null);As(e!==null,e??"")}function Ls(e,t){console.error(`\u2B06\uFE0F \u53D1\u73B0\u65B0\u7248\u672C ${e}\uFF08\u5F53\u524D ${t}\uFF09\uFF1Apnpm add -g @fxri/toolkit \u5347\u7EA7\u540E\u8BF7\u5F00\u65B0\u4F1A\u8BDD\u52A0\u8F7D\u6700\u65B0 skills \u89C4\u5219\uFF1B\u672C\u5730\u6280\u80FD\u53EF\u7528 toolkit skills status \u68C0\u67E5\uFF08\u8F6F\u94FE\u81EA\u52A8\u8DDF\u968F\uFF0C\u526F\u672C\u5F62\u5F0F\u9700\u91CD\u8DD1 toolkit skills install\uFF09`)}var Fs="\u663E\u793A\u5E2E\u52A9",Is=["version","format"];function dt(e){e.helpOption("-h, --help",Fs),e.configureHelp({subcommandTerm:t=>`${t.name()} ${t.usage()}`.replace(/\s+/g," ").trim()});for(let t of e.commands)dt(t)}function Gn(e){return Is.includes(e[0])?e.slice(1).some(t=>t==="-h"||t==="--help"):!1}var ut="\u8FD0\u884C toolkit --help \u67E5\u770B\u53EF\u7528\u547D\u4EE4";function Vn(e){let t=/\n\(Did you mean (one of )?([^)]*?)\?\)$/.exec(e);if(!t)return"";let n=t[2].split(", ").join("\u3001");return t[1]?`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n} \u4E4B\u4E00\uFF1F\uFF09`:`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n}\uFF1F\uFF09`}function Jn(e){switch(e.code){case"commander.unknownCommand":{let t=/unknown command '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u547D\u4EE4\u300C${t}\u300D\u3002${Vn(e.message)}
98
+ `)}function _n(e=[]){let t=q(),n=[],r=new Set,o=(s,i,a,l)=>{let d=_e(s),u=I(d);r.has(u)||(r.add(u),n.push({dir:d,label:i,kind:a,available:l,dirExists:M(d)}))};o(S(t,_),In,"primary",!0);for(let s of On){let i=S(t,J(s.dir)),a=M(i)||(s.detect??[]).some(l=>M(Ln(l)?l:S(t,l)));o(S(t,s.dir),s.label,"agent",a)}for(let s of e)o(s,"\u81EA\u5B9A\u4E49 --dir","custom",!0);return n}function gs(e){let t=I(_e(e));return t===I(S(q(),_))?In:On.find(r=>I(S(q(),r.dir))===t)?.label??null}function lt(e){Cn(e,{recursive:!0,force:!0})}function Rn(e,t){st(J(t),{recursive:!0}),as(e,t,{recursive:!0})}function hs(e,t,n){if(n)return Rn(e,t),{mode:"copy"};try{return st(J(t),{recursive:!0}),En(e,t,process.platform==="win32"?"junction":"dir"),{mode:"link"}}catch(r){return Rn(e,t),{mode:"copy",reason:r.message}}}function Dn(e={}){let t=ke(),n=_n(e.dirs??[]),r=Be(),o=new Map;for(let l of r?.targets??[])o.set(I(l.dir),l);let s=[],i=[],a=[];for(let l of n){if(!l.available){i.push({dir:l.dir,label:l.label});continue}let d={dir:l.dir,label:l.label,kind:l.kind,created:[],updated:[],skipped:[],conflicts:[],failed:[],degraded:[],links:[],copies:[]};for(let u of t){let m=S(l.dir,u.name),p=De(m,u.dir);if(p==="link-ok"){d.skipped.push(u.name),d.links.push(u.name);continue}if(p==="dir"&&!e.force){if(!(o.get(I(l.dir))?.copies.includes(u.name)??!1)){d.conflicts.push(u.name);continue}if(Ne(u.dir,m)){d.skipped.push(u.name),d.copies.push(u.name);continue}}if(p==="file"&&!e.force){d.conflicts.push(u.name);continue}if(e.dryRun){p==="absent"?d.created.push(u.name):d.updated.push(u.name),e.copy?d.copies.push(u.name):d.links.push(u.name);continue}try{p!=="absent"&&lt(m);let c=hs(u.dir,m,!!e.copy);p==="absent"?d.created.push(u.name):d.updated.push(u.name),c.mode==="link"?d.links.push(u.name):(d.copies.push(u.name),c.reason&&d.degraded.push({name:u.name,reason:c.reason}))}catch(c){d.failed.push({name:u.name,reason:c.message})}}s.push(d),e.dryRun||a.push({dir:l.dir,updatedAt:new Date().toISOString(),links:d.links,copies:d.copies})}if(!e.dryRun){let l=new Set(s.map(m=>I(m.dir))),d=(r?.targets??[]).filter(m=>!l.has(I(m.dir))),u=[...a,...d].filter(m=>m.links.length>0||m.copies.length>0);u.length>0&&Mn(u)}return{source:Y(),skills:t.map(l=>l.name),targets:s,skippedTargets:i,stateFile:be()}}function Nn(e={}){let t=Be(),n=be();if(!t)return{stateFile:n,stateExists:!1,targets:[],stateRemoved:!1};let r=[],o=!1;for(let a of t.targets){let l={dir:a.dir,label:gs(a.dir),removed:[],missing:[],skippedForeign:[]},d=[...new Set([...a.links,...a.copies])];for(let u of d){let m=S(a.dir,u),p=S(Y(),u),c=De(m,p);if(c==="absent"){l.missing.push(u);continue}if(c==="wrong"){l.skippedForeign.push(u);continue}if(c==="file"){l.skippedForeign.push(u);continue}if(c==="dir"&&!Ne(p,m)){l.skippedForeign.push(u);continue}if(e.dryRun){l.removed.push(u);continue}try{lt(m),l.removed.push(u)}catch{o=!0,l.skippedForeign.push(u)}}r.push(l)}let s=r.every(a=>a.skippedForeign.length===0),i=!e.dryRun&&!o&&s;return i&&Cn(n,{force:!0}),{stateFile:n,stateExists:!0,targets:r,stateRemoved:i}}function Bn(){let e=ke(),t=_n([]),n=Be(),r=new Map;for(let i of n?.targets??[])r.set(I(i.dir),i);let o=[],s=[];for(let i of t){let a=r.get(I(i.dir));if(!i.available&&i.kind==="agent"){s.push({dir:i.dir,label:i.label});continue}if(i.kind!=="primary"&&!i.dirExists&&!a)continue;let l=[...new Set([...e.map(m=>m.name),...a?[...a.links,...a.copies]:[]])].sort(),d=new Map(e.map(m=>[m.name,m.version])),u=[];for(let m of l){let p=S(Y(),m),c=S(i.dir,m),f=De(c,p),g;f==="link-ok"?g="link":f==="dangling"?g="dangling":f==="wrong"?g="wrong":f==="file"?g="conflict":f==="dir"?M(p)&&Ne(p,c)?g="copy":g=a?.copies.includes(m)?"copy-drift":"conflict":g="missing",u.push({name:m,state:g,version:d.get(m)??""})}o.push({dir:i.dir,label:i.label,kind:i.kind,available:i.available,dirExists:i.dirExists,recorded:!!a,items:u})}return{source:Y(),skills:e.map(i=>i.name),skillVersions:Object.fromEntries(e.map(i=>[i.name,i.version])),versionMismatches:ms(e),stateFile:be(),stateExists:!!n,targets:o,pendingAgents:s}}function Pn(){let e=L("skills");if(e?.autoLink===!1||process.env.CI)return 0;let t=Be();if(!t)return 0;let n=Y(),r;try{r=new Set(he(n).filter(l=>M(S(n,l))))}catch{return 0}let o=e?.autoLinkReplaceForeign!==!1,s=process.platform==="win32"?"junction":"dir",i=0,a=[];for(let l of t.targets){let d;try{d=he(l.dir,{withFileTypes:!0})}catch{a.push(l);continue}let u=new Map(d.map(p=>[p.name,p])),m=l.links.filter(p=>{if(!r.has(p))return!1;let c=S(n,p),f=S(l.dir,p),g=u.get(p),h=g?De(f,c,g,!0):"absent";if(h==="link-ok"||!o&&(h==="dir"||h==="file"))return!0;try{return h!=="absent"&&lt(f),En(c,f,s),i+=1,!0}catch{return!0}});a.push({...l,links:m,updatedAt:new Date().toISOString()})}return i>0&&Mn(a),i}import{existsSync as bs,mkdirSync as ys,rmSync as vs}from"fs";import{join as ws}from"path";import{tmpdir as Yn}from"os";import{spawn as Ss}from"child_process";var ks="https://registry.npmjs.org/@fxri%2Ftoolkit/latest";async function Un(){try{let e=await fetch(ks,{signal:AbortSignal.timeout(1e3),headers:{accept:"application/vnd.npm.install-v1+json"}});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}catch{return null}}function zn(e,t){let n=i=>i.trim().replace(/^-/,"").split(/[.+-]/).map(a=>Number.parseInt(a,10)).map(a=>Number.isFinite(a)?a:0),r=n(e),o=n(t),s=Math.max(r.length,o.length);for(let i=0;i<s;i++){let a=r[i]??0,l=o[i]??0;if(a!==l)return a>l}return!1}var xs=1440*60*1e3,$s=3600*1e3,Ts="FX_NO_UPDATE_CHECK",ct="--fxri-update-check-worker";function Wn(){return ws(Yn(),".toolkit-update-check.json")}function Rs(){let e=Wn();try{if(!bs(e))return null;let t=JSON.parse(T(e)),n=typeof t.ts=="number"?t.ts:0,r=typeof t.latest=="string"?t.latest:"",o=t.ok===!0,s=o?xs:$s;return Date.now()-n>=s?(vs(e,{force:!0}),null):o&&!r?null:{ts:n,ok:o,latest:r}}catch{return null}}function As(e,t){try{let n=Wn();ys(Yn(),{recursive:!0}),$(n,JSON.stringify({ts:Date.now(),ok:e,latest:t}))}catch{}}function Cs(){let e=process.env[Ts];if(e!==void 0&&e!=="")return!["0","false","off","no"].includes(e.trim().toLowerCase());let t=Ye()?.updateCheck;return t&&typeof t=="object"?t.enabled===!1:!1}function Kn(e){if(Cs())return;let t=Rs();if(t){t.ok&&zn(t.latest,e)&&Ls(t.latest,e);return}Es()}function Es(){let e=process.argv[1];if(e)try{Ss(process.execPath,[e,ct],{detached:!0,stdio:"ignore",windowsHide:!0}).unref()}catch{}}async function Hn(){let e=await Un().catch(()=>null);As(e!==null,e??"")}function Ls(e,t){console.error(`\u2B06\uFE0F \u53D1\u73B0\u65B0\u7248\u672C ${e}\uFF08\u5F53\u524D ${t}\uFF09\uFF1Apnpm add -g @fxri/toolkit \u5347\u7EA7\u540E\u8BF7\u5F00\u65B0\u4F1A\u8BDD\u52A0\u8F7D\u6700\u65B0 skills \u89C4\u5219\uFF1B\u672C\u5730\u6280\u80FD\u53EF\u7528 toolkit skills status \u68C0\u67E5\uFF08\u8F6F\u94FE\u81EA\u52A8\u8DDF\u968F\uFF0C\u526F\u672C\u5F62\u5F0F\u9700\u91CD\u8DD1 toolkit skills install\uFF09`)}var Fs="\u663E\u793A\u5E2E\u52A9",Is=["version","format"];function dt(e){e.helpOption("-h, --help",Fs),e.configureHelp({subcommandTerm:t=>`${t.name()} ${t.usage()}`.replace(/\s+/g," ").trim()});for(let t of e.commands)dt(t)}function Gn(e){let[t]=e;return!t||!Is.includes(t)?!1:e.slice(1).some(n=>n==="-h"||n==="--help")}var ut="\u8FD0\u884C toolkit --help \u67E5\u770B\u53EF\u7528\u547D\u4EE4";function Vn(e){let t=/\n\(Did you mean (one of )?([^)]*?)\?\)$/.exec(e);if(!t)return"";let n=(t[2]??"").split(", ").join("\u3001");return t[1]?`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n} \u4E4B\u4E00\uFF1F\uFF09`:`\uFF08\u662F\u5426\u60F3\u8F93\u5165 ${n}\uFF1F\uFF09`}function Jn(e){switch(e.code){case"commander.unknownCommand":{let t=/unknown command '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u547D\u4EE4\u300C${t}\u300D\u3002${Vn(e.message)}
99
99
  ${ut}`:null}case"commander.unknownOption":{let t=/unknown option '([^']*)'/.exec(e.message)?.[1];return t?`\u26A0\uFE0F \u672A\u77E5\u9009\u9879\u300C${t}\u300D\u3002${Vn(e.message)}
100
100
  ${ut}`:null}case"commander.excessArguments":{let t=/too many arguments(?: for '([^']*)')?\. Expected (\d+) arguments? but got (\d+)\./.exec(e.message);return t?`\u26A0\uFE0F ${t[1]?`\u547D\u4EE4\u300C${t[1]}\u300D`:"\u547D\u4EE4"}\u671F\u671B ${t[2]} \u4E2A\u53C2\u6570\uFF0C\u5B9E\u9645\u6536\u5230 ${t[3]} \u4E2A\u3002
101
101
  ${ut}`:null}default:return null}}var qn="\u4E13\u4E3A\u591A\u4EBA + AI \u8DE8\u9879\u76EE\u534F\u4F5C\u6253\u9020\uFF1A\u4EFB\u52A1\u7BA1\u7406 + \u591A\u8BED\u8A00 CHANGELOG\u3002";var Qn=Ms(import.meta.url),Bs=Qn.resolve("@changesets/cli/bin.js"),{version:er}=Qn("../package.json"),ft=e=>{let t=_s(process.execPath,[Bs,...e],{stdio:"inherit"});t.status!==0&&process.exit(t.status??1)};function Ps(){if(process.platform==="win32")try{process.stdout.setDefaultEncoding("utf8"),process.stderr.setDefaultEncoding("utf8")}catch{}}function tr(){let e=L("check");return typeof e?.warnings=="boolean"?e.warnings:void 0}function Us(){let t=L("changelog")?.languages;if(!t||typeof t!="object")return oe;let n={...oe};for(let[r,o]of Object.entries(t))o&&typeof o=="object"&&(n[r]=o);return n}function zs(e=".changeset"){if(!Xn(e))return!1;try{return Ds(e).some(t=>t.endsWith(".md")&&t!=="README.md")}catch{return!1}}function Ys(e=".tasks"){return C(Ns(e,"active")).length>0}function Zn(e){let t=fn(".",e);t>0&&console.warn(`\u26A0\uFE0F ${t} \u6761\u53D8\u66F4\u96C6\u6761\u76EE\u7F3A\u7C7B\u578B\u524D\u7F00\uFF0C\u5EFA\u8BAE\u6309\u300C\u7C7B\u578B\uFF1A\u63CF\u8FF0\u300D\u64B0\u5199`)}function Pe(e){if(e.length===0){console.log("\u672A\u53D1\u73B0\u95EE\u9898");return}for(let t of e)console.log(` ${t.file}${t.line?`:${t.line}`:""}: ${t.message}`)}function Ws(e,t){return[...t,e]}var Ks={link:"\u8F6F\u94FE\u6B63\u5E38",dangling:"\u8F6F\u94FE\u60AC\u7A7A\uFF08\u771F\u6E90\u7F3A\u5931\u6216\u5347\u7EA7\u540E\u65E7\u8DEF\u5F84\u5931\u6548\uFF09",wrong:"\u8F6F\u94FE\u6307\u5411\u522B\u5904",copy:"\u526F\u672C\u5DF2\u540C\u6B65","copy-drift":"\u526F\u672C\u5DF2\u6F02\u79FB\uFF08\u4E0E\u771F\u6E90\u4E0D\u4E00\u81F4\uFF09",missing:"\u7F3A\u5931",conflict:"\u540C\u540D\u51B2\u7A81\uFF08\u975E\u672C\u5305\u4EA7\u7269\uFF09"},Hs=["dangling","wrong","copy-drift","missing","conflict"];function ye(e){console.log(Sn(e))}function nr(e,t){return t?`${e}@${t}`:e}function Gs(e,t){let n=t?"[\u9884\u6F14] ":"",r=new Map(ke().map(o=>[o.name,o.version]));console.log(`${n}\u6280\u80FD\u6E90\uFF1A${e.source}`),console.log(`${n}\u5305\u5185\u6280\u80FD\uFF08${e.skills.length}\uFF09\uFF1A${e.skills.map(o=>nr(o,r.get(o)??"")).join("\u3001")||"\u65E0"}`);for(let o of e.targets){console.log(""),console.log(`${o.label}\uFF1A${o.dir}`),o.created.length>0&&console.log(` \u65B0\u5EFA\uFF1A${o.created.join("\u3001")}`),o.updated.length>0&&console.log(` \u91CD\u5EFA/\u66F4\u65B0\uFF1A${o.updated.join("\u3001")}`),o.skipped.length>0&&console.log(` \u8DF3\u8FC7\uFF08\u5DF2\u5C31\u7EEA\uFF09\uFF1A${o.skipped.join("\u3001")}`),o.conflicts.length>0&&console.log(` \u8DF3\u8FC7\uFF08\u540C\u540D\u975E\u672C\u5305\u4EA7\u7269\uFF0C\u5982\u9700\u8986\u76D6\u52A0 --force\uFF09\uFF1A${o.conflicts.join("\u3001")}`);for(let i of o.degraded)console.log(` \u26A0\uFE0F \u964D\u7EA7\u4E3A\u526F\u672C\uFF1A${i.name}\uFF08\u94FE\u63A5\u521B\u5EFA\u5931\u8D25\uFF1A${i.reason}\uFF09`);for(let i of o.failed)console.log(` \u26A0\uFE0F \u5931\u8D25\uFF1A${i.name}\uFF08${i.reason}\uFF09`);let s=[];o.links.length>0&&s.push(`\u8F6F\u94FE ${o.links.length} \u4E2A`),o.copies.length>0&&s.push(`\u526F\u672C ${o.copies.length} \u4E2A`),s.length>0&&console.log(` \u4EA7\u7269\u5F62\u6001\uFF1A${s.join(" / ")}`)}console.log(""),e.skippedTargets.length>0&&console.log(`\u672A\u5B89\u88C5\u7684 agent ${e.skippedTargets.length} \u4E2A\u5DF2\u8DF3\u8FC7\uFF08\u4E0D\u5728\u7528\u6237\u673A\u5668\u4E0A\u51ED\u7A7A\u9020\u76EE\u5F55\uFF09\uFF1B\u5982\u9700\u88C5\u5230\u672A\u8BC6\u522B\u7684 agent\uFF1Atoolkit skills install --dir <\u5176\u5168\u5C40\u6280\u80FD\u76EE\u5F55>`),console.log(`${n}\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}`),t&&console.log("[\u9884\u6F14] \u672A\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\uFF1B\u786E\u8BA4\u65E0\u8BEF\u540E\u53BB\u6389 --dry-run \u6267\u884C")}function Vs(e){console.log(`\u6280\u80FD\u6E90\uFF1A${e.source}`),console.log(`\u6280\u80FD\u7248\u672C\uFF1A${e.skills.map(n=>nr(n,e.skillVersions[n]??"")).join("\u3001")||"\u65E0"}`);for(let n of e.versionMismatches)console.warn(`\u26A0\uFE0F \u6280\u80FD\u7248\u672C\u53CC\u5199\u4F4D\u4E0D\u4E00\u81F4\uFF1A${n.name}\uFF08frontmatter ${n.frontmatter} / \u6B63\u6587 ${n.body||"\u672A\u58F0\u660E"}\uFF09`);console.log(`\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}${e.stateExists?"":"\uFF08\u672A\u8BB0\u5F55\uFF0C\u5C1A\u672A\u6267\u884C\u8FC7 toolkit skills install\uFF09"}`);let t=0;for(let n of e.targets){console.log(""),console.log(`${n.label}\uFF1A${n.dir}${n.dirExists?"":"\uFF08\u76EE\u5F55\u672A\u521B\u5EFA\uFF09"}`);for(let r of n.items)Hs.includes(r.state)&&(t+=1),console.log(` ${r.name}\uFF1A${Ks[r.state]}`)}e.pendingAgents.length>0&&(console.log(""),console.log(`\u672A\u5B89\u88C5\u7684 agent ${e.pendingAgents.length} \u4E2A\u672A\u7EB3\u5165\u5206\u53D1\uFF08\u9700\u8981\u65F6\u7528 toolkit skills install --dir <\u8DEF\u5F84> \u6307\u5B9A\uFF09`)),console.log(""),console.log(t>0?`\u5171 ${t} \u5904\u9700\u5904\u7406\uFF1A\u7F3A\u5931 / \u60AC\u7A7A / \u6307\u5411\u9519\u8BEF / \u526F\u672C\u6F02\u79FB\u7528 toolkit skills install \u8865\u9F50\uFF0C\u540C\u540D\u51B2\u7A81\u7528 toolkit skills install --force \u8986\u76D6`:"\u6240\u6709\u5DF2\u7EB3\u5165\u7684\u76EE\u6807\u5747\u6B63\u5E38")}function Js(e,t){let n=t?"[\u9884\u6F14] ":"";if(!e.stateExists){console.log("\u672A\u627E\u5230\u672C\u5305\u7684\u72B6\u6001\u6587\u4EF6\uFF0C\u6CA1\u6709\u7531\u672C\u5305\u5B89\u88C5\u7684\u4EA7\u7269\u9700\u8981\u6E05\u7406\uFF08\u5176\u4ED6\u65B9\u5F0F\u5B89\u88C5\u7684\u6280\u80FD\u4E0D\u53D7\u5F71\u54CD\uFF09");return}console.log(`${n}\u72B6\u6001\u6587\u4EF6\uFF1A${e.stateFile}`);for(let r of e.targets)console.log(""),console.log(r.label?`${r.label}\uFF1A${r.dir}`:r.dir),r.removed.length>0&&console.log(` ${t?"\u5C06\u79FB\u9664":"\u5DF2\u79FB\u9664"}\uFF1A${r.removed.join("\u3001")}`),r.missing.length>0&&console.log(` \u5DF2\u4E0D\u5B58\u5728\uFF1A${r.missing.join("\u3001")}`),r.skippedForeign.length>0&&console.log(` \u26A0\uFE0F \u8DF3\u8FC7\uFF08\u975E\u672C\u5305\u4EA7\u7269\u6216\u5185\u5BB9\u5DF2\u88AB\u6539\u52A8\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\uFF09\uFF1A${r.skippedForeign.join("\u3001")}`);console.log(""),t?console.log("[\u9884\u6F14] \u672A\u6267\u884C\u5220\u9664\uFF1B\u65E0\u9057\u7559\u6761\u76EE\u65F6\u5C06\u540C\u65F6\u5220\u9664\u72B6\u6001\u6587\u4EF6"):e.stateRemoved?console.log("\u72B6\u6001\u6587\u4EF6\u5DF2\u5220\u9664\uFF0C\u672C\u5305\u4EA7\u7269\u6E05\u7406\u5B8C\u6BD5"):console.log("\u72B6\u6001\u6587\u4EF6\u5DF2\u4FDD\u7559\uFF08\u5B58\u5728\u9700\u4EBA\u5DE5\u786E\u8BA4\u6216\u672A\u79FB\u9664\u7684\u6761\u76EE\uFF09")}var mt=["archive","check","normalize","stats"],D=new Os,rr="";D.name("toolkit").description(qn).version(er,"-v, --version","\u663E\u793A\u7248\u672C\u53F7").enablePositionalOptions(!0).exitOverride().configureOutput({writeErr:e=>{rr+=e}});D.addHelpText("after",["","\u6587\u6863\u7AD9\uFF1A",` \u65B0\u624B\u6307\u5357 ${ie.gettingStarted}`,` \u5B8C\u6574\u653B\u7565 ${ie.guide}`,` \u5168\u90E8\u6587\u6863 ${ie.site}`].join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fxri/toolkit",
3
- "version": "1.10.1",
3
+ "version": "1.10.3",
4
4
  "description": "专为多人 + AI 跨项目协作打造:任务管理 + 多语言 CHANGELOG。",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -66,7 +66,7 @@
66
66
  "vitest": "^4.1.11"
67
67
  },
68
68
  "engines": {
69
- "node": ">=20"
69
+ "node": ">=20.19.0"
70
70
  },
71
71
  "publishConfig": {
72
72
  "registry": "https://registry.npmjs.org/",
@@ -82,6 +82,7 @@
82
82
  "test": "vitest run",
83
83
  "test:watch": "vitest",
84
84
  "test:coverage": "vitest run --coverage",
85
+ "verify": "node scripts/verify.mjs",
85
86
  "changeset": "changeset",
86
87
  "sync:changelog-doc": "node scripts/sync-changelog-doc.mjs",
87
88
  "docs:dev": "vitepress dev docs",
package/skills/README.md CHANGED
@@ -8,9 +8,9 @@
8
8
 
9
9
  | 技能 | 版本 | 用途 |
10
10
  | --- | --- | --- |
11
- | [fxri-plan-to-task](./fxri-plan-to-task/SKILL.md) | 1.2.0 | 方案落盘:建档评估(先查后写)→ 建档 → 校验 → 归档 → 任务级规范沉淀(能力终点);规范载体迁移 |
12
- | [fxri-release-changelog](./fxri-release-changelog/SKILL.md) | 1.0.12 | changesets 发版与多语言 CHANGELOG 维护 |
13
- | [fxri-session-recap](./fxri-session-recap/SKILL.md) | 1.2.0 | 会话收尾全量沉淀 + 规范沉淀 / 新会话三层恢复 / 历史任务时间批量修正 |
11
+ | [fxri-plan-to-task](./fxri-plan-to-task/SKILL.md) | 1.3.2 | 方案落盘:建档评估(先查后写)→ 建档 → 校验 → 归档 → 任务级规范沉淀(能力终点);规范载体迁移 |
12
+ | [fxri-release-changelog](./fxri-release-changelog/SKILL.md) | 1.1.1 | changesets 发版与多语言 CHANGELOG 维护 |
13
+ | [fxri-session-recap](./fxri-session-recap/SKILL.md) | 1.2.2 | 会话收尾全量沉淀 + 规范沉淀 / 新会话三层恢复 / 历史任务时间批量修正 |
14
14
 
15
15
  版本号取自各 SKILL.md 的 frontmatter `metadata.version`(`toolkit skills status` / `skills install` 打印的真源版本),与正文首部版本声明双写一致。
16
16
 
@@ -3,14 +3,14 @@ name: fxri-plan-to-task
3
3
  description: 将已确认的实施方案落盘为标准任务文件并跟踪至归档:动手前建档评估(查 active/archive 判同主题)、按模板建档、状态机更新、四级时间源取证、自查校验、任务级规范沉淀与手工归档。当用户确认方案后表达「开始落地/登记记录」的意图,或即将动手改仓库文件时使用——含建档、任务登记、落盘、归档、任务校验、规范载体迁移(conventions 单文件升目录形态)等说法及其口语近义表达(如按这个做吧、记一下、建个任务跟踪)均触发。不用于方案未确认的对话、会话收尾整场沉淀(fxri-session-recap 模式一)、与任务记录无关的普通 TODO、issue 管理或日常提交信息撰写。
4
4
  license: MIT
5
5
  metadata:
6
- version: "1.3.0"
6
+ version: "1.3.2"
7
7
  author: fxri
8
8
  source: https://github.com/fxri-net/toolkit
9
9
  ---
10
10
 
11
11
  # 方案落盘:任务建档与归档
12
12
 
13
- > 本技能版本 1.3.0(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
13
+ > 本技能版本 1.3.2(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
14
14
 
15
15
  ## 何时使用
16
16
 
@@ -92,7 +92,9 @@ metadata:
92
92
 
93
93
  ### 6. 收尾边界(硬约束到沉淀)
94
94
 
95
- **归档 + 规范沉淀即本技能流程终点**(先归档、后沉淀)。提交、发版、推送不是必经步骤,是否执行取决于用户的全局 / 个人 / 项目规则;若提交代码,先归档与沉淀、后提交,任务归档文件与规范载体变更、代码变更落在**同一个 git 提交**(顺序不可颠倒),避免任务完成却滞留 `active/` 未归档,或归档单独成一条提交。
95
+ **归档 + 规范沉淀即本技能流程终点**(先归档、后沉淀)。提交、发版、推送不是必经步骤,是否执行取决于用户的全局 / 个人 / 项目规则;若提交代码,按「归档与沉淀 → 跑项目验收命令 → 提交」的顺序执行,任务归档文件与规范载体变更、代码变更落在**同一个 git 提交**(顺序不可颠倒),避免任务完成却滞留 `active/` 未归档,或归档单独成一条提交。
96
+
97
+ ⚠️ **验收须晚于归档**:归档会改写 `.tasks/`(写归档文件、删 active 源文件、清理空月份目录),而归档本身不做阻断式校验——早于归档跑验收就覆盖不到终态,归档产物等于无人校验。同理,归档块「完成情况」只记改动事实与所用验证命令,不逐条抄写验收输出。
96
98
 
97
99
  ## 失败模式
98
100
 
@@ -1,13 +1,13 @@
1
- ---
2
- owner: <负责人 git 用户名>
3
- status: 待办
4
- created: <创建日 YYYYMMDD>
5
- updated: <创建日 YYYYMMDD,随每次修改同步>
6
- completed: ''
7
- depends_on: []
8
- scope: <影响范围>
9
- ---
10
-
11
- # 任务标题
12
-
13
- (方案正文:背景、实施方案、影响范围、验证方式)
1
+ ---
2
+ owner: <负责人 git 用户名>
3
+ status: 待办
4
+ created: <创建日 YYYYMMDD>
5
+ updated: <创建日 YYYYMMDD,随每次修改同步>
6
+ completed: ''
7
+ depends_on: []
8
+ scope: <影响范围>
9
+ ---
10
+
11
+ # 任务标题
12
+
13
+ (方案正文:背景、实施方案、影响范围、验证方式)
@@ -1,147 +1,147 @@
1
- # 规范载体规范(conventions)
2
-
3
- > 面向多人 + AI 协作,任何语言项目可直接使用,仅依赖文件读写能力。本文件为 SKILL.md 的配套规范,定义 `.tasks/conventions/` 的目录结构、归属分类、读写判定与存量迁移;任务文件本身的规范见 `task-spec.md`。
4
-
5
- ## 1. 载体结构
6
-
7
- ```
8
- .tasks/
9
- ├── active/ # 进行中的任务
10
- ├── archive/ # 已终结任务归档
11
- └── conventions/ # 项目协作规范载体
12
- ├── index.md # 唯一入口与唯一权威(常驻读)
13
- ├── common.md # 全端通用条文(按需创建)
14
- └── <端名>.md # 各端专有条文(按需创建)
15
- ```
16
-
17
- - `index.md` 是唯一入口:端清单在此声明、每条规范在此留一行指针,读取时只读它即可掌握规范全貌
18
- - 分册**按需创建**,判据是「该归属下有无需独立承载的条文」,不设条数阈值——溯源索引式项目可能始终只有 `index.md`
19
- - 目录与任务目录同在 `.tasks/` 根层,纯 Markdown 随 git 走;默认 `.tasks` 目录名可随任务区自定而变,内部结构不变
20
- - 非任务文件:`toolkit tasks` 各子命令不读其内容,`check` 不因内容告警;仅在**载体形态异常**时给软告警(旧单文件残留、缺 `index.md`)
21
-
22
- ## 2. index.md 结构
23
-
24
- 四节固定顺序:端清单 → 索引 → 演进记录 → 用法说明。
25
-
26
- ### 2.1 端清单(唯一权威)
27
-
28
- ```markdown
29
- ## 一、端清单
30
-
31
- > 端名与任务 frontmatter 的 `scope` 取值共用同一套词表;保留字 `index` / `common` 不得作端名。
32
-
33
- | 端名 | 说明 |
34
- | --- | --- |
35
- | web | 前端主站 |
36
- | server | 后端服务 |
37
- ```
38
-
39
- 单端项目写一行或留空表并注明「本项目单端,规范全归 common」。
40
-
41
- ### 2.2 索引表
42
-
43
- ```markdown
44
- | # | 规则 | 当前语义 | 归属 | 状态 | 确立来源任务 | 单一事实源 |
45
- | --- | --- | --- | --- | --- | --- | --- |
46
- | 1 | 四级时间源 | 时间取证优先级:当场打点 > 聊天记录时间戳 > git 提交时间 > 系统时间兜底 | common | 生效 | 20260906-会话收尾沉淀能力升级 | task-spec.md(口径随版本走) |
47
- ```
48
-
49
- - **归属**:取值必须 ∈ {`common`} ∪ 端清单,否则为悬空指针(需修正)
50
- - **状态**:`生效` / `已废弃`;废弃不删行,改状态即可(与「归档任务不可变」同哲学:留痕优于抹除)
51
- - **单一事实源**:条文正文去哪看。已指向项目现有规则层(AGENTS / 全局规则 / skills)时填指向;条文就在本载体分册内时填分册名(如 `common.md`)
52
-
53
- ### 2.3 演进记录(修订留痕)
54
-
55
- 规则语义变更不覆盖丢史:先在演进记录追加一行(规则 → 旧语义 → 变更为 → 修订来源任务),再更新索引表当前语义。
56
-
57
- ```markdown
58
- | 规则 | 修订内容 | 修订来源任务 |
59
- | --- | --- | --- |
60
- ```
61
-
62
- ### 2.4 用法说明
63
-
64
- 写明本项目采用哪种形态、读写判定要点、以及规则层源头变更时的同步纪律。
65
-
66
- ## 3. 分册结构
67
-
68
- ```markdown
69
- # 全端通用规范(common)
70
-
71
- > 归属:common(所有端适用)。条文全文见本节,索引见 index.md。
72
-
73
- ## 1. 四级时间源
74
-
75
- (条文全文)
76
- ```
77
-
78
- 端分册同构,首部 `# {端名} 规范`、`> 归属:{端名}`。
79
-
80
- ## 4. 端名规则
81
-
82
- - **与任务 frontmatter `scope` 取值逐字一致**:两者共用同一套词表,读取时才能机械匹配(任务写 `scope: web+server` → 加载 `web.md` + `server.md`)
83
- - **形态约束**:非空、不含空格、不含路径分隔符(`/ \ : * ? " < > |`)
84
- - **保留字**:`index`、`common` 不得作端名
85
- - **风格**:随项目 `scope` 既有写法(`web` / `server` / `admin` / `前端` 均成立),无全局词表——工具无法预知项目端构成,故不硬编码取值
86
-
87
- ## 5. 读取判定(分层)
88
-
89
- 1. **常驻**:只读 `index.md`(端清单 + 索引),成本与规范条数成线性、不随分册增大
90
- 2. **按需**:取当前任务 `scope` 的每个值 → 命中端清单的加载对应分册,再叠加 `common.md`
91
- 3. **非端值**:`scope` 中不在端清单的值视为分类标签,静默跳过,不报错
92
- 4. **空 scope**:只加载 `common.md`(保守,不臆测端归属)
93
-
94
- ## 6. 写入判定(沉淀归属)
95
-
96
- 1. 先问「这条是否**所有端都适用**」→ 是则归 `common`
97
- 2. 否则逐端确认「适用于哪些端」→ 写入命中的端分册
98
- 3. **禁止跨端合并归属**:不得出现「web+server 共识」这类跨端条目——真全端升 `common`,只适用几端则各端各记一条
99
- 4. `common` 语义锁死为「所有端都适用」,**不得用作「不确定归哪端」的暂存区**,否则会退化为垃圾桶
100
- 5. 写入前须经用户确认;一次性决策不升格为规范,留在任务正文
101
-
102
- ## 7. 两种形态
103
-
104
- 形态差异体现在分册是否存在与「单一事实源」列取值,**不是结构二选一**:
105
-
106
- | 形态 | 适用 | 表现 |
107
- | --- | --- | --- |
108
- | 溯源索引式 | 项目已有规则层(AGENTS / 全局规则 / skills) | 不复制条文,索引行「当前语义」写简版语义、「单一事实源」写指向;可能只有 `index.md` |
109
- | 条文式 | 无其他规则文件的项目 | 条文全文写入对应归属分册,本载体即项目唯一规范载体 |
110
-
111
- 同一项目内可混用:部分规则指向外部规则层、部分条文落在本载体。
112
-
113
- ## 8. 内容修订
114
-
115
- - 语义变更:先在「演进记录」留痕,再更新索引表当前语义;条文在分册内的同步改分册
116
- - 规则作废:索引行状态改 `已废弃`,不删行、不删分册条目
117
- - 规则层源头变更(AGENTS / 全局规则 / skills 条文改了):同步检查索引对应行当前语义是否需更新,随该变更同批落盘
118
-
119
- ## 9. 存量迁移(旧单文件 → 目录形态)
120
-
121
- 触发:`toolkit tasks check` 报旧 `conventions.md` 存在;或用户直接要求迁移。
122
-
123
- **三段式**(可中断,中途停下不丢内容):
124
-
125
- 1. **机器搬骨架**:建 `conventions/`,旧文件**整体**搬为 `index.md`(原文一字不丢),删除旧文件——此刻 `index.md` 是原文快照,功能上与旧文件等价
126
- 2. **AI 提归属建议**:读原有条目,逐条给出「`common` / 某端」建议与理由(旧文件无端信息,语义分流无法机械完成),形成待确认清单
127
- 3. **用户逐条确认**:确认后写索引行 + 把条文全文拆入对应分册;**未确认的条目保持原样留在 `index.md`**,不强推
128
-
129
- 补充要求:
130
-
131
- - 迁移与内容重排分开做:先完成形态迁移(结构到位),再谈条目归属调整,避免一次变更混合两种风险
132
- - 端清单在迁移时同步建立:从项目已有 `scope` 取值与实际子项目构成归纳,经用户确认写入端清单节
133
- - 旧文件已不存在时不重复迁移
134
-
135
- ## 10. 兼容读(迁移期)
136
-
137
- 读取时先找 `conventions/index.md`;不存在再看旧单文件 `conventions.md`,存在则按旧单文件内容读取并**在对话中提示可迁移**。两者并存时以目录形态为准,并提示旧文件待清理。
138
-
139
- ## 11. 自查清单
140
-
141
- - [ ] `conventions/` 存在时必有 `index.md`(缺则为形态异常)
142
- - [ ] 端清单非空且不含保留字 `index` / `common`
143
- - [ ] 索引表「归属」列取值 ∈ {`common`} ∪ 端清单(无悬空指针)
144
- - [ ] 「状态」列取值为 `生效` / `已废弃`
145
- - [ ] 分册文件与端清单 + `common` 对应,无孤立文件
146
- - [ ] 旧单文件 `conventions.md` 已迁移(不存在,或已提示待清理)
147
- - [ ] 规范写入均经用户确认,且带「确立来源任务」
1
+ # 规范载体规范(conventions)
2
+
3
+ > 面向多人 + AI 协作,任何语言项目可直接使用,仅依赖文件读写能力。本文件为 SKILL.md 的配套规范,定义 `.tasks/conventions/` 的目录结构、归属分类、读写判定与存量迁移;任务文件本身的规范见 `task-spec.md`。
4
+
5
+ ## 1. 载体结构
6
+
7
+ ```
8
+ .tasks/
9
+ ├── active/ # 进行中的任务
10
+ ├── archive/ # 已终结任务归档
11
+ └── conventions/ # 项目协作规范载体
12
+ ├── index.md # 唯一入口与唯一权威(常驻读)
13
+ ├── common.md # 全端通用条文(按需创建)
14
+ └── <端名>.md # 各端专有条文(按需创建)
15
+ ```
16
+
17
+ - `index.md` 是唯一入口:端清单在此声明、每条规范在此留一行指针,读取时只读它即可掌握规范全貌
18
+ - 分册**按需创建**,判据是「该归属下有无需独立承载的条文」,不设条数阈值——溯源索引式项目可能始终只有 `index.md`
19
+ - 目录与任务目录同在 `.tasks/` 根层,纯 Markdown 随 git 走;默认 `.tasks` 目录名可随任务区自定而变,内部结构不变
20
+ - 非任务文件:`toolkit tasks` 各子命令不读其内容,`check` 不因内容告警;仅在**载体形态异常**时给软告警(旧单文件残留、缺 `index.md`)
21
+
22
+ ## 2. index.md 结构
23
+
24
+ 四节固定顺序:端清单 → 索引 → 演进记录 → 用法说明。
25
+
26
+ ### 2.1 端清单(唯一权威)
27
+
28
+ ```markdown
29
+ ## 一、端清单
30
+
31
+ > 端名与任务 frontmatter 的 `scope` 取值共用同一套词表;保留字 `index` / `common` 不得作端名。
32
+
33
+ | 端名 | 说明 |
34
+ | --- | --- |
35
+ | web | 前端主站 |
36
+ | server | 后端服务 |
37
+ ```
38
+
39
+ 单端项目写一行或留空表并注明「本项目单端,规范全归 common」。
40
+
41
+ ### 2.2 索引表
42
+
43
+ ```markdown
44
+ | # | 规则 | 当前语义 | 归属 | 状态 | 确立来源任务 | 单一事实源 |
45
+ | --- | --- | --- | --- | --- | --- | --- |
46
+ | 1 | 四级时间源 | 时间取证优先级:当场打点 > 聊天记录时间戳 > git 提交时间 > 系统时间兜底 | common | 生效 | 20260906-会话收尾沉淀能力升级 | task-spec.md(口径随版本走) |
47
+ ```
48
+
49
+ - **归属**:取值必须 ∈ {`common`} ∪ 端清单,否则为悬空指针(需修正)
50
+ - **状态**:`生效` / `已废弃`;废弃不删行,改状态即可(与「归档任务不可变」同哲学:留痕优于抹除)
51
+ - **单一事实源**:条文正文去哪看。已指向项目现有规则层(AGENTS / 全局规则 / skills)时填指向;条文就在本载体分册内时填分册名(如 `common.md`)
52
+
53
+ ### 2.3 演进记录(修订留痕)
54
+
55
+ 规则语义变更不覆盖丢史:先在演进记录追加一行(规则 → 旧语义 → 变更为 → 修订来源任务),再更新索引表当前语义。
56
+
57
+ ```markdown
58
+ | 规则 | 修订内容 | 修订来源任务 |
59
+ | --- | --- | --- |
60
+ ```
61
+
62
+ ### 2.4 用法说明
63
+
64
+ 写明本项目采用哪种形态、读写判定要点、以及规则层源头变更时的同步纪律。
65
+
66
+ ## 3. 分册结构
67
+
68
+ ```markdown
69
+ # 全端通用规范(common)
70
+
71
+ > 归属:common(所有端适用)。条文全文见本节,索引见 index.md。
72
+
73
+ ## 1. 四级时间源
74
+
75
+ (条文全文)
76
+ ```
77
+
78
+ 端分册同构,首部 `# {端名} 规范`、`> 归属:{端名}`。
79
+
80
+ ## 4. 端名规则
81
+
82
+ - **与任务 frontmatter `scope` 取值逐字一致**:两者共用同一套词表,读取时才能机械匹配(任务写 `scope: web+server` → 加载 `web.md` + `server.md`)
83
+ - **形态约束**:非空、不含空格、不含路径分隔符(`/ \ : * ? " < > |`)
84
+ - **保留字**:`index`、`common` 不得作端名
85
+ - **风格**:随项目 `scope` 既有写法(`web` / `server` / `admin` / `前端` 均成立),无全局词表——工具无法预知项目端构成,故不硬编码取值
86
+
87
+ ## 5. 读取判定(分层)
88
+
89
+ 1. **常驻**:只读 `index.md`(端清单 + 索引),成本与规范条数成线性、不随分册增大
90
+ 2. **按需**:取当前任务 `scope` 的每个值 → 命中端清单的加载对应分册,再叠加 `common.md`
91
+ 3. **非端值**:`scope` 中不在端清单的值视为分类标签,静默跳过,不报错
92
+ 4. **空 scope**:只加载 `common.md`(保守,不臆测端归属)
93
+
94
+ ## 6. 写入判定(沉淀归属)
95
+
96
+ 1. 先问「这条是否**所有端都适用**」→ 是则归 `common`
97
+ 2. 否则逐端确认「适用于哪些端」→ 写入命中的端分册
98
+ 3. **禁止跨端合并归属**:不得出现「web+server 共识」这类跨端条目——真全端升 `common`,只适用几端则各端各记一条
99
+ 4. `common` 语义锁死为「所有端都适用」,**不得用作「不确定归哪端」的暂存区**,否则会退化为垃圾桶
100
+ 5. 写入前须经用户确认;一次性决策不升格为规范,留在任务正文
101
+
102
+ ## 7. 两种形态
103
+
104
+ 形态差异体现在分册是否存在与「单一事实源」列取值,**不是结构二选一**:
105
+
106
+ | 形态 | 适用 | 表现 |
107
+ | --- | --- | --- |
108
+ | 溯源索引式 | 项目已有规则层(AGENTS / 全局规则 / skills) | 不复制条文,索引行「当前语义」写简版语义、「单一事实源」写指向;可能只有 `index.md` |
109
+ | 条文式 | 无其他规则文件的项目 | 条文全文写入对应归属分册,本载体即项目唯一规范载体 |
110
+
111
+ 同一项目内可混用:部分规则指向外部规则层、部分条文落在本载体。
112
+
113
+ ## 8. 内容修订
114
+
115
+ - 语义变更:先在「演进记录」留痕,再更新索引表当前语义;条文在分册内的同步改分册
116
+ - 规则作废:索引行状态改 `已废弃`,不删行、不删分册条目
117
+ - 规则层源头变更(AGENTS / 全局规则 / skills 条文改了):同步检查索引对应行当前语义是否需更新,随该变更同批落盘
118
+
119
+ ## 9. 存量迁移(旧单文件 → 目录形态)
120
+
121
+ 触发:`toolkit tasks check` 报旧 `conventions.md` 存在;或用户直接要求迁移。
122
+
123
+ **三段式**(可中断,中途停下不丢内容):
124
+
125
+ 1. **机器搬骨架**:建 `conventions/`,旧文件**整体**搬为 `index.md`(原文一字不丢),删除旧文件——此刻 `index.md` 是原文快照,功能上与旧文件等价
126
+ 2. **AI 提归属建议**:读原有条目,逐条给出「`common` / 某端」建议与理由(旧文件无端信息,语义分流无法机械完成),形成待确认清单
127
+ 3. **用户逐条确认**:确认后写索引行 + 把条文全文拆入对应分册;**未确认的条目保持原样留在 `index.md`**,不强推
128
+
129
+ 补充要求:
130
+
131
+ - 迁移与内容重排分开做:先完成形态迁移(结构到位),再谈条目归属调整,避免一次变更混合两种风险
132
+ - 端清单在迁移时同步建立:从项目已有 `scope` 取值与实际子项目构成归纳,经用户确认写入端清单节
133
+ - 旧文件已不存在时不重复迁移
134
+
135
+ ## 10. 兼容读(迁移期)
136
+
137
+ 读取时先找 `conventions/index.md`;不存在再看旧单文件 `conventions.md`,存在则按旧单文件内容读取并**在对话中提示可迁移**。两者并存时以目录形态为准,并提示旧文件待清理。
138
+
139
+ ## 11. 自查清单
140
+
141
+ - [ ] `conventions/` 存在时必有 `index.md`(缺则为形态异常)
142
+ - [ ] 端清单非空且不含保留字 `index` / `common`
143
+ - [ ] 索引表「归属」列取值 ∈ {`common`} ∪ 端清单(无悬空指针)
144
+ - [ ] 「状态」列取值为 `生效` / `已废弃`
145
+ - [ ] 分册文件与端清单 + `common` 对应,无孤立文件
146
+ - [ ] 旧单文件 `conventions.md` 已迁移(不存在,或已提示待清理)
147
+ - [ ] 规范写入均经用户确认,且带「确立来源任务」
@@ -102,4 +102,6 @@ scope: app # 影响范围;多值以半角加号分隔(toolkit+lxg
102
102
  - **仓库文件改动口径**:需写入版本控制的工作区文件的增 / 改 / 删(源码、配置、文档、技能、任务区自身均计入);纯读取、纯执行、纯汇报不计入;拿不准时列出差异问用户,不猜
103
103
  - **动作不算,改动才算**:收尾动作(提交、发版、推送、部署)本身及其固有产物(版本号、更新日志、标签)不构成任务、不单独建档;这些动作过程中若出现需改仓库文件才能解决的缺陷(如打包配置错误、发布渠道错误),该修复按普通任务建档
104
104
  - **归档块不可变**:已归档块是终结记录(唯一键 + 完成时间已固定),不追加新的工作内容;延续 / 扩展需求走新任务并标注来源链。唯一例外是**事实更正**——后续核实推翻原块结论时,在其正文末尾追加「修订记录」(保留原结论、不动元数据行、附更正时刻与依据),与 conventions 载体「废弃不删行」同属留痕优于抹除
105
- - 强制约束到**沉淀**为止:归档 + 规范沉淀即流程终点;提交、发版、推送不是必经步骤,是否执行取决于用户的全局 / 个人 / 项目规则;若提交代码,先归档与沉淀、后 git commit,任务记录(归档文件 + conventions 载体)与代码变更落在同一提交
105
+ - **验收与 CI 同源,不手写清单**:项目的验收步骤清单只允许一份真源——一条聚合命令(如 `pnpm verify`)背后由脚本定义步骤,本地与全部 CI 流水线共用它;禁止在规则文件、CI 配置里另抄一份步骤枚举。多份手写清单必然漂移,征兆就是「本地自检通过、CI 才报错」,出现该征兆先查清单是否已经漂移
106
+ - 强制约束到**沉淀**为止:归档 + 规范沉淀即流程终点;提交、发版、推送不是必经步骤,是否执行取决于用户的全局 / 个人 / 项目规则;若提交代码,按「归档与沉淀 → 跑项目验收命令 → git commit」的顺序执行,任务记录(归档文件 + conventions 载体)与代码变更落在同一提交
107
+ - **验收须晚于归档**:归档会改写任务区(写归档文件、删 active 源文件、清理空月份目录),而归档本身不做阻断式校验——早于归档跑验收就覆盖不到终态,归档产物等于无人校验。同理,归档块「完成情况」只记改动事实与所用验证命令,不逐条抄写验收输出(归档在前、验收在后,抄结果就成了先写结论后验证)
@@ -3,14 +3,14 @@ name: fxri-release-changelog
3
3
  description: 基于 changesets 的发版与多语言 CHANGELOG 维护流程:创建变更集、消费发版、把分组标题与条目转为项目语言风格、清理变更集、打标签发布;无 changesets 的项目提供同格式手工模式。当用户表达发版或记录变更意图——含创建变更集、changeset、发版、version、CHANGELOG 格式化等说法及其口语近义表达(如发一版、出个版本、记一下这次改动、生成更新日志)时使用。⚠️ 注意区分:用户说「提交个版本 / 先提交一版 / commit」通常指 git 提交当前改动(走任务收尾后提交),**不是发版**。不用于日常 commit message 撰写、git 提交操作或与发版无关的文档修改。
4
4
  license: MIT
5
5
  metadata:
6
- version: "1.1.0"
6
+ version: "1.1.1"
7
7
  author: fxri
8
8
  source: https://github.com/fxri-net/toolkit
9
9
  ---
10
10
 
11
11
  # 发版与 CHANGELOG
12
12
 
13
- > 本技能版本 1.1.0(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
13
+ > 本技能版本 1.1.1(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
14
14
 
15
15
  ## 何时使用
16
16
 
@@ -33,10 +33,11 @@ metadata:
33
33
 
34
34
  1. 记录变更:`npx changeset`(或项目包管理器等价脚本)——**变更描述一律以 `类型:` 前缀开头**(如 `新增:` / `修复:` / `优化:`),并按类型选影响级别(重大→major、新增/修改→minor、优化/修复/清理/文档→patch,完整对照见 `references/changelog-format.md`)
35
35
  2. 消费发版:`npx changeset version`——自动写版本号与 CHANGELOG
36
- 3. 格式化:按 `references/changelog-format.md` 的语义分组规则归类条目、转换分组标题、润色为项目语言风格(中文示例:`### Patch Changes` 下的 `- 修复:xxx` → `### 🐛 问题修复` 下的 `- xxx`——归类后类型前缀被剥离,类型由分组标题承接);分组维度与 bump 维度正交,条目归组只看类型前缀
36
+ 3. 格式化:按 `references/changelog-format.md` 的语义分组规则归类条目、转换分组标题、润色为项目语言风格(中文示例:`### Patch Changes` 下的 `- 修复:xxx` → `### 🐛 问题修复` 下的 `- xxx`——归类后类型前缀被剥离,类型由分组标题承接);分组维度与 bump 维度正交,条目归组只看类型前缀
37
37
  4. 归一:润色后跑一次 `toolkit changelog --history format`——人工润色(含补写历史块明细)容易在条目之间留空行,该命令按「同组顶层条目逐行相邻」重排历史块;项目另有更新日志镜像页(如 `docs/changelog.md`)时再跑一次同步脚本,否则镜像一致性校验会失败
38
38
  5. 清理:删除已消费的 `.changeset/*.md`
39
- 6. 发布:提交版本与 CHANGELOG 改动 → 打 `vX.Y.Z` 标签 → 按项目渠道发布(如 `npm publish`)
39
+ 6. 门禁:发布前跑一次项目的验收命令(如 `pnpm verify`)——**关卡设在发布前而非推送前**:发布到包仓库 / 制品库不可逆,推送失败重推即可,故必须拦在不可逆动作之前;任一步失败即中止发版,不进入提交、打标签、发布
40
+ 7. 发布:提交版本与 CHANGELOG 改动 → 打 `vX.Y.Z` 标签 → 按项目渠道发布(如 `npm publish`)
40
41
 
41
42
  ⚠️ 自动生成的条目必须人工核对润色,与仓库既有 CHANGELOG 风格保持一致。
42
43
 
@@ -51,8 +52,8 @@ metadata:
51
52
  | version 后 CHANGELOG 分组标题仍是英文 | 按 references 的映射表补一次格式化 |
52
53
  | CHANGELOG 出现「- - 条目」双前缀伪影(变更集条目以 `- ` 开头) | `toolkit changelog version/format` 已自动还原为顶层条目;手工模式按 references 规则手动清理 |
53
54
  | 条目与仓库既有风格不一致 | 人工润色为项目语言与句式,勿保留机器直译 |
54
- | 变更集遗漏(发版后才发现功能未记录) | 补建变更集随下次发版;本次在发布说明中人工补充 |
55
- | 改动已发布却无归档记录(有提交、无任务档) | 先补归档(fxri-session-recap 模式一)再继续发布后续步骤;发版本身不补建档 |
55
+ | 变更集遗漏(发版后才发现功能未记录) | 补建变更集随下次发版;本次在发布说明中人工补充 |
56
+ | 改动已发布却无归档记录(有提交、无任务档) | 先补归档(fxri-session-recap 模式一)再继续发布后续步骤;发版本身不补建档 |
56
57
  | 发版后历史块内出现多余空行(`自举一致性` 类零改动用例失败) | 跑 `toolkit changelog --history format` 归一(**必须带 `--history`**,默认模式不动历史块),再补跑一次镜像页同步脚本 |
57
58
 
58
59
  ## 可选加速(不构成依赖)
@@ -61,7 +62,7 @@ metadata:
61
62
 
62
63
  - `toolkit changelog`:创建变更集(等价 changeset)
63
64
  - `toolkit changelog version`:发版并自动做中文分组标题格式化
64
- - `toolkit changelog format`:仅格式化既有 CHANGELOG
65
+ - `toolkit changelog format`:仅格式化既有 CHANGELOG
65
66
  - `toolkit changelog --history format`:连带追溯改写历史版本块(用户主动要求修正历史块时才加,默认不动)
66
67
  - `toolkit changelog --lang <语言> …`:切换输出语言(内置 zh / en,其余可配置扩展)
67
68
  - ⚠️ `changelog` 域开了选项透传,自有选项(`--lang` / `--history` / `--redact` / `--warn`)必须写在子命令**之前**:`toolkit changelog --history format` 生效,写成 `toolkit changelog format --history` 会被 changesets 静默忽略(表现为「无 CHANGELOG 需要更新」)
@@ -43,8 +43,8 @@
43
43
  | `依赖:` / 源文本 `- Updated dependencies` | `deps` | `### 🔗 依赖变更` | `### 🔗 Dependency Updates` |
44
44
  | 无前缀兜底 | `other` | `### 📦 其他变更` | `### 📦 Other` |
45
45
 
46
- **无前缀条目的兜底规则**:按条目**所属源组标题**声明的影响级别归组——`### Major Changes` → `breaking`、`### Minor Changes` → `added`、`### Patch Changes` → `other`;不从版本号推导。
47
-
46
+ **无前缀条目的兜底规则**:按条目**所属源组标题**声明的影响级别归组——`### Major Changes` → `breaking`、`### Minor Changes` → `added`、`### Patch Changes` → `other`;不从版本号推导。
47
+
48
48
  **追溯历史块的兜底规则**(`--history`):历史块没有英文源组标题,改按**所属既有组标题**查槽位——先查当前语言组标题,再查历史组标题表(如 `### 🐛 补丁修复` → `fixed`);两处都识别不出则整组连同标题原样保留。
49
49
 
50
50
  **依赖条目不走前缀解析**:源组标题 `### Dependent Changes` 整块,以及源文本 `- Updated dependencies`(含缩进子项)一律归入 `deps` 槽位。
@@ -3,14 +3,14 @@ name: fxri-session-recap
3
3
  description: 会话收尾的工作记忆沉淀 + 新会话开场恢复 + 历史任务时间修正:收尾时把整场会话的全部任务完整建档归档,按四级时间源还原真实完成时间,沉淀规范进 conventions 载体;新会话开场按三层恢复(全量索引 + active 精读 + 近窗归档)重建现场并核对规范;也可批量修正历史归档时间。当用户表达会话收尾意图(如今天先到这、收个尾、归档本次会话、把结论记下来)、接续意图(如恢复上下文、继续上次、上次做到哪)、或修正历史任务时间时使用。不用于会话中途的常规方案建档(那是 fxri-plan-to-task 的职责)、与工作交接无关的代码技术总结。
4
4
  license: MIT
5
5
  metadata:
6
- version: "1.2.1"
6
+ version: "1.2.2"
7
7
  author: fxri
8
8
  source: https://github.com/fxri-net/toolkit
9
9
  ---
10
10
 
11
11
  # 会话归档、上下文恢复与历史修正
12
12
 
13
- > 本技能版本 1.2.1(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
13
+ > 本技能版本 1.2.2(随 @fxri/toolkit 同批分发)。被问版本时即报此值——不读磁盘、不跑 CLI:报出的值就是本会话上下文里已加载内容的版本,可与 `toolkit skills status` 打印的磁盘基准值对照,不一致即说明会话上下文已过期,开新会话即可。
14
14
 
15
15
  ## 何时使用
16
16
 
@@ -48,12 +48,13 @@ metadata:
48
48
  ### R2 统一收尾链路(能力终点 = 沉淀)
49
49
 
50
50
  ```
51
- 任务终结 → 归档 → 规范沉淀(硬终点) → 提交/发版/推送(可选,需用户确认)
51
+ 任务终结 → 归档 → 规范沉淀(硬终点) → 验收 → 提交/发版/推送(可选,需用户确认)
52
52
  ```
53
53
 
54
54
  - 归档是中间步骤,**规范沉淀才是流程终点**
55
- - 沉淀时机固定:归档完成后、任何 git 操作前,规范与归档文件同批落盘
56
- - 提交、发版、推送**不是必经步骤**,是否执行取决于用户全局/个人/项目规则;若提交代码:先归档、后提交,归档文件与代码变更落在同一 git 提交
55
+ - 沉淀时机固定:归档完成后、任何收尾动作(验收 / 提交 / 发版 / 推送)前,规范与归档文件同批落盘
56
+ - ⚠️ **验收须晚于归档**:归档会改写 `.tasks/`,且归档本身不做阻断式校验——早于归档跑验收就覆盖不到终态,归档产物等于无人校验;归档块「完成情况」只记改动事实与所用验证命令,不逐条抄写验收输出
57
+ - 提交、发版、推送**不是必经步骤**,是否执行取决于用户全局/个人/项目规则;若提交代码:先归档、后跑项目验收命令、再提交,归档文件与代码变更落在同一 git 提交
57
58
  - **动作不算、改动才算**:收尾动作(提交、发版、推送、部署)本身及其固有产物(版本号、更新日志、标签)不构成任务、不单独建档;其所依据的改动须有归档记录,缺则补档
58
59
 
59
60
  ### R3 规范落点:`.tasks/conventions/` 载体(两级沉淀同一载体)
@@ -85,11 +86,11 @@ metadata:
85
86
  3. **逐条落盘**(先查后写;格式与目录规范见 `../fxri-plan-to-task/references/task-spec.md`;fxri-plan-to-task 未一并安装、该兄弟路径不存在时,改读包内真源——`toolkit skills status` 打印的「技能源」目录下 `fxri-plan-to-task/references/task-spec.md`):
86
87
  - 会话工作有对应任务 → 更新原文件:正文追加结论与决策,时间字段按 R1 校准
87
88
  - 无对应任务但有独立成果 → 按 fxri-plan-to-task 规范建档,created 取任务真实创建日
88
- - 未尽事项 → 拆独立任务文件(status: 待办),不在正文留游离待办
89
+ - 未尽事项 → 拆独立任务文件(status: 待办),不在正文留游离待办
89
90
  - 收尾动作(提交、发版、推送、部署)本身及其固有产物(版本号、更新日志、标签)不单独成档;其所依据的改动缺归档记录时须补档
90
91
  4. **归档**:终结态任务按 task-spec「手工归档步骤」执行(合并归档块 → 降序重排 → 写回 → 删源文件 → 清理空月份目录),或 `toolkit tasks archive` 自动化
91
92
  5. **规范沉淀(终点)**:按「规范提炼子流程」执行会话级提炼,写入 conventions 载体
92
- 6. **收尾边界**:沉淀即本技能流程终点。提交、发版、推送不是必经步骤,是否执行取决于用户规则;若提交代码,先归档、后提交,任务归档文件 + conventions 载体与本次代码变更落在**同一个 git 提交**;提交前向用户展示待提交内容供确认
93
+ 6. **收尾边界**:沉淀即本技能流程终点。提交、发版、推送不是必经步骤,是否执行取决于用户规则;⚠️ 验收须晚于归档——若提交代码,先归档、再跑项目验收命令、后提交,任务归档文件 + conventions 载体与本次代码变更落在**同一个 git 提交**;提交前向用户展示待提交内容供确认
93
94
  7. **回报**:向用户列出本次沉淀的任务清单、归档位置与规范变更,确认无遗漏后再结束
94
95
 
95
96
  ## 模式二:恢复上下文