@fxri/toolkit 1.5.5 → 1.6.0
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 +34 -0
- package/LICENSE +21 -21
- package/NOTICE +9 -9
- package/README.md +361 -330
- package/SPEC.md +118 -116
- package/TRADEMARK.md +47 -47
- package/dist/cli.cjs +35 -31
- package/dist/cli.js +32 -28
- package/dist/index.cjs +35 -31
- package/dist/index.js +33 -29
- package/package.json +17 -15
- package/skills/README.md +52 -0
- package/skills/fxri-plan-to-task/SKILL.md +72 -0
- package/skills/fxri-plan-to-task/assets/active-task-template.md +13 -0
- package/skills/fxri-plan-to-task/references/task-spec.md +85 -0
- package/skills/fxri-release-changelog/SKILL.md +54 -0
- package/skills/fxri-release-changelog/references/changelog-format.md +40 -0
package/dist/index.js
CHANGED
|
@@ -1,81 +1,85 @@
|
|
|
1
|
-
var
|
|
2
|
-
`).
|
|
1
|
+
var Z=["\u5F85\u529E","\u8FDB\u884C\u4E2D","\u5DF2\u5B8C\u6210","\u963B\u585E","\u5DF2\u653E\u5F03"],D=["\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03"];function L(e){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!t)return{};let n={};for(let o of(t[1]??"").split(/\r?\n/)){let r=o.indexOf(":");if(r===-1)continue;let s=o.slice(0,r).trim(),i=o.slice(r+1).trim();(i.startsWith("'")&&i.endsWith("'")||i.startsWith('"')&&i.endsWith('"'))&&(i=i.slice(1,-1)),s&&(n[s]=i)}return n}function E(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length):e}function Q(e){return e.split(/\r?\n/).find(t=>t.startsWith("# ")&&!t.startsWith("#!"))?.replace(/^#\s*/,"")??""}function ke(e){let t=e.split(/\r?\n/),n=t.findIndex(o=>/^# /.test(o));return n===-1?e:(t.splice(n,1),t.join(`
|
|
2
|
+
`))}import{existsSync as nt,readdirSync as be,statSync as rt}from"fs";import{join as we,basename as ot,extname as st}from"path";function S(e){if(!nt(e))return[];let t=[];for(let n of be(e)){let o=we(e,n);if(rt(o).isDirectory())for(let r of be(o))r.endsWith(".md")&&t.push(we(o,r));else n.endsWith(".md")&&t.push(o)}return t}function I(e){return ot(e,st(e)).match(/^(\d{8})/)?.[1]??""}import{readFileSync as vt}from"fs";import{join as $t,basename as De}from"path";import{existsSync as it,readFileSync as at}from"fs";import{join as ct,dirname as lt}from"path";var _;function ye(){if(_!==void 0)return _;_=null;let e=process.cwd();for(;;){let t=ct(e,".toolkitrc.json");if(it(t))try{_=JSON.parse(at(t,"utf8"));break}catch{}let n=lt(e);if(n===e)break;e=n}return _}function N(e){let t=ye();if(!t)return;let n=t[e];return typeof n=="object"&&n!==null?n:void 0}function dt(){_=void 0}function ve(e,t){let n=e.trim().toLowerCase();return["1","true","on","yes"].includes(n)?!0:["0","false","off","no"].includes(n)?!1:t}function $e(e,t,n,o){if(e!==void 0)return e;let r=process.env[t];return r!==void 0&&r!==""?ve(r,o):n!==void 0?n:o}var pt=[{name:"\u5185\u7F51URL",pattern:/(https?:\/\/)[a-zA-Z0-9.-]+(:\d{2,5})(?=\/|[\s]|$)/g,replacement:"$1***$2"},{name:"\u90AE\u7BB1",pattern:/([a-zA-Z0-9._%+-])[a-zA-Z0-9._%+-]*@(?:[a-zA-Z0-9-]+\.)+([a-zA-Z]{2,})/g,replacement:"$1***@***.$2"},{name:"JWT",pattern:/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,replacement:"eyJ***.***.***"},{name:"AWS\u5BC6\u94A5",pattern:/\b(AKIA|ASIA)[A-Z0-9]{16}\b/g,replacement:"$1****"},{name:"GitHub\u5BC6\u94A5",pattern:/\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}\b/g,replacement:"$1_****"},{name:"GitHub\u7EC6\u7C92\u5EA6\u5BC6\u94A5",pattern:/\bgithub_pat_[A-Za-z0-9_]{80,}\b/g,replacement:"github_pat_****"},{name:"OpenAI\u5BC6\u94A5",pattern:/\bsk-[A-Za-z0-9]{20,}\b/g,replacement:"sk-****"},{name:"OpenAI\u9879\u76EE\u5BC6\u94A5",pattern:/\bsk-proj-[A-Za-z0-9_-]{40,}\b/g,replacement:"sk-proj-****"},{name:"Slack\u5BC6\u94A5",pattern:/\b(xox[baprs])-[A-Za-z0-9-]{10,}\b/g,replacement:"$1-****"},{name:"Slack\u5E94\u7528\u4EE4\u724C",pattern:/\bxapp-\d+-[A-Za-z0-9-]{15,}\b/g,replacement:"xapp-****"},{name:"\u624B\u673A\u53F7",pattern:/(?<!\d)(1[3-9]\d)\d{4}(\d{4})(?!\d)/g,replacement:"$1****$2"},{name:"\u8EAB\u4EFD\u8BC1",pattern:/(?<!\d)(\d{6})\d{8}(\d{3}[\dXx])(?!\d)/g,replacement:"$1********$2"},{name:"IPv4",pattern:/(?<![\d.])(\d{1,3}\.\d{1,3})\.\d{1,3}\.\d{1,3}(?![\d.])/g,replacement:"$1.***.***"}];function mt(){let e=N("redact");return e?{enabled:typeof e.enabled=="boolean"?e.enabled:void 0,disable:Array.isArray(e.disable)?e.disable.filter(t=>typeof t=="string"):void 0,rules:Array.isArray(e.rules)?e.rules:void 0}:null}function ut(){let e=mt(),t=new Set(e?.disable??[]),n=[];for(let o of e?.rules??[])try{n.push({name:o.name,pattern:new RegExp(o.pattern,o.flags??""),replacement:o.replacement})}catch{}return[...n,...pt.filter(o=>!t.has(o.name))]}function C(e,t){if(!t||!e)return e;let n=e;for(let o of ut())n=n.replace(o.pattern,o.replacement);return n}import{readFileSync as Le}from"fs";import{join as je,basename as bt}from"path";function ee(e){let t={};if(!e)return t;for(let n of e.replace(/^>\s*/,"").split(/[ ]+/).map(o=>o.trim()).filter(Boolean)){let o=n.search(/[::]/);if(o<=0)continue;let r=n.slice(0,o).trim(),s=n.slice(o+1).trim();!r||!s||(r.includes("\u8D1F\u8D23\u4EBA")?t.owner=s:r.includes("\u72B6\u6001")?t.status=s:r.includes("\u8303\u56F4")?t.scope=s:r.includes("\u5B8C\u6210\u65F6\u95F4")&&(t.completed=s))}return t}function $(e){let t=e.trim(),n=t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})[T\s](\d{1,2}):(\d{2})(?::\d{2})?$/)??t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);if(!n)return t;let o=s=>s?.padStart(2,"0")??"",r=`${n[1]??""}-${o(n[2])}-${o(n[3])}`;return n.length===4?`${r} 00:00`:`${r} ${o(n[4])}:${o(n[5])}`}function xe(e){return e.match(/^\d{8}-(.+?)-/)?.[1]??""}function ft(e,t){return`> \u8D1F\u8D23\u4EBA\uFF1A${xe(e)||"\u672A\u6807\u6CE8"}\u3000\u72B6\u6001\uFF1A\u5DF2\u5B8C\u6210\u3000\u8303\u56F4\uFF1A-\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${$(t)}`}function Te(e,t,n){let o=ee(n),r=o.owner||xe(e)||"\u672A\u6807\u6CE8",s=o.status||"\u5DF2\u5B8C\u6210",i=o.scope||"-";return`> \u8D1F\u8D23\u4EBA\uFF1A${r}\u3000\u72B6\u6001\uFF1A${s}\u3000\u8303\u56F4\uFF1A${i}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${$(t)}`}function A(e){let t=e.split(/\r?\n/),n=[];for(let s=0;s<t.length;s++){let i=t[s];if(!i||!/^## .+/.test(i))continue;let a=s+1;for(;a<t.length&&(t[a]??"").trim()==="";)a++;let d=t[a]?.trim()??"";d.startsWith("> ")&&d.includes("\u5B8C\u6210\u65F6\u95F4")&&n.push(s)}if(n.length===0)return{header:e,blocks:[]};let o=t.slice(0,n[0]??0).join(`
|
|
3
|
+
`).trimEnd(),r=[];for(let s=0;s<n.length;s++){let i=n[s]??0,a=s+1<n.length?n[s+1]??t.length:t.length,d=t.slice(i,a).join(`
|
|
3
4
|
`).trim().split(`
|
|
4
|
-
`),l=d[0].replace(/^## /,""),
|
|
5
|
-
`).trim()}function
|
|
5
|
+
`),l=(d[0]??"").replace(/^## /,""),m=null,f="",u=1;for(let c=1;c<d.length;c++){let g=d[c]??"",p=g.trim();if(p.startsWith("> ")&&p.includes("\u5B8C\u6210\u65F6\u95F4")){m=g;let h=p.match(/完成时间:(.+)$/);h&&(f=(h[1]??"").trim()),u=c+1;break}}r.push({title:l,metaLine:m,completed:f,body:gt(d.slice(u))})}return{header:o,blocks:r}}function gt(e){let t=[...e];for(;;){for(;t.length>0&&(t[t.length-1]??"").trim()==="";)t.pop();let n=t[t.length-1]??"";if(t.length>0&&/^---+\s*$/.test(n.trim()))t.pop();else break}return t.join(`
|
|
6
|
+
`).trim()}function Se(e){let t=e.split(/\r?\n/),n=[];for(let o=0;o<t.length;o++){let r=t[o]?.match(/^## (\d{8}-[^-]+-.+)$/)?.[1];if(!r)continue;let s=o+1;for(;s<t.length&&(t[s]??"").trim()==="";)s++;let i=t[s]?.trim()??"";i.startsWith("> ")&&!i.includes("\u5B8C\u6210\u65F6\u95F4")&&n.push(r)}return n}function z(e){let t=e.metaLine??(e.completed?ft(e.title,e.completed):null);return t?`## ${e.title}
|
|
6
7
|
|
|
7
8
|
${t}
|
|
8
9
|
|
|
9
10
|
${e.body}`:`## ${e.title}
|
|
10
11
|
|
|
11
|
-
${e.body}`}function
|
|
12
|
-
`),r.length===0){let l=Object.values(n).some(
|
|
12
|
+
${e.body}`}function te(e){if(Array.isArray(e))return e.filter(r=>typeof r=="string");if(typeof e!="string")return[];let t=e.trim();if(!t||t==="[]")return[];try{let r=JSON.parse(t);if(Array.isArray(r))return r.map(String).filter(Boolean)}catch{}let n=[...t.matchAll(/'([^']*)'|"([^"]*)"/g)].map(r=>r[1]??r[2]).filter(r=>!!r);if(n.length>0)return n;let o=t.match(/^\[(.*)\]$/)?.[1];return o!=null?o.split(/[,,]/).map(r=>r.trim().replace(/^['"]|['"]$/g,"")).filter(Boolean):[]}import{relative as ht,sep as kt}from"path";function O(e,t){return ht(e,t).split(kt).join("/")}var Y=e=>String(e).padStart(2,"0");function Re(e){let t=e.trim().match(/^(\d{4})[-/]?(\d{1,2})[-/]?(\d{1,2})/);if(!t)return null;let[,n,o,r]=t;return!n||!o||!r?null:{y:n,m:Y(+o),d:Y(+r)}}function x(e){let t=Re(e);return t?`${t.y}-${t.m}-${t.d}`:""}function Ae(e){let t=Re(e);return t?`${t.y}${t.m}${t.d}`:e.trim().replace(/[-/]/g,"")}function Ce(){let e=new Date;return`${e.getFullYear()}-${Y(e.getMonth()+1)}-${Y(e.getDate())}`}function ae(){let e=new Date;return`${e.getFullYear()}${Y(e.getMonth()+1)}${Y(e.getDate())}`}var M=["\u5F85\u529E","\u8FDB\u884C\u4E2D","\u963B\u585E","\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03","\u672A\u6807\u6CE8"];function Oe(e=".tasks"){let t=je(e,"active");return S(t).map(n=>{let o=Le(n,"utf8"),r=L(o);return{view:"\u5F85\u5B8C\u6210",title:Q(o)||bt(n,".md"),status:r.status||"\u672A\u6807\u6CE8",owner:r.owner||"\u672A\u6807\u6CE8",scope:r.scope||"-",created:r.created||I(n),updated:r.updated||"",completed:r.completed||"",depends:te(r.depends_on),file:O(e,n)}})}function wt(e){let t=ee(e);return{owner:t.owner||"\u672A\u6807\u6CE8",status:t.status||"\u5DF2\u5B8C\u6210",scope:t.scope||"-"}}function Me(e=".tasks"){let t=je(e,"archive"),n=[];for(let o of S(t)){let r=Le(o,"utf8");for(let s of A(r).blocks){let i=wt(s.metaLine);n.push({view:"\u5DF2\u5F52\u6863",title:s.title,status:i.status,owner:i.owner,scope:i.scope,created:"",updated:"",completed:s.completed,depends:[],file:O(e,o)})}}return n}function ce(e,t){return e===void 0?!0:Array.isArray(e)?e.includes(t):e===t}function yt(e,t){if(!ce(t.owner,e.owner)||!ce(t.scope,e.scope)||!ce(t.status,e.status))return!1;if(t.date||t.since||t.until){let n=t.date?x(t.date):x(t.since||""),o=t.date?x(t.date):x(t.until||"");if(!n&&!o||!(e.view==="\u5DF2\u5F52\u6863"?[x(e.completed)]:[x(e.created),x(e.updated)].filter(Boolean)).some(i=>i&&(!n||i>=n)&&(!o||i<=o)))return!1}return!0}function Ee(e){return e.view==="\u5DF2\u5F52\u6863"?x(e.completed):x(e.created||e.updated||e.completed)}function Fe(e){let t=e.view==="\u5DF2\u5F52\u6863"?e.completed:e.completed||e.updated||e.created,n=x(t);if(!n)return"";let o=t.match(/(\d{1,2}):(\d{2})/),r=o?.[1]??"",s=o?.[2]??"";return n.replace(/-/g,"")+(o?`${r.padStart(2,"0")}${s}`:"0000")}function Ie(e){let t=new Map(M.map((n,o)=>[n,o]));return[...e].sort((n,o)=>{let r=t.get(n.status)??M.length,s=t.get(o.status)??M.length;return r!==s?r-s:Fe(o).localeCompare(Fe(n))})}function Be(e){let t={},n={};for(let o of e)t[o.status]=(t[o.status]||0)+1,n[o.owner]=(n[o.owner]||0)+1;return{total:e.length,byStatus:t,byOwner:n}}function le(e=".tasks",t="active",n={}){let o=[];(t==="active"||t==="all")&&o.push(...Oe(e)),(t==="archived"||t==="all")&&o.push(...Me(e)),o=o.filter(s=>yt(s,n));let r=Ie(o);return{rows:r,summary:Be(r)}}function xt(e=".tasks"){let t=$t(e,"active");return S(t).map(n=>{let o=vt(n,"utf8"),r=L(o),s=Q(o)||De(n,".md");return{file:n,name:De(n,".md"),date:I(n),title:s,frontmatter:r,body:E(o).trim()}})}function Tt(e=".tasks",t=!0){_e(e,"active",{},t)}function _e(e=".tasks",t="active",n={},o=!0){let{rows:r,summary:s}=le(e,t,n);if(console.log(`\u4EFB\u52A1\u603B\u89C8\uFF08${t==="active"?"\u5F85\u5B8C\u6210":t==="archived"?"\u5DF2\u5F52\u6863":"\u5F85\u5B8C\u6210 + \u5DF2\u5F52\u6863"}\uFF09\uFF1A
|
|
13
|
+
`),r.length===0){let l=Object.values(n).some(m=>Array.isArray(m)?m.length>0:!!m);console.log(l?"\u65E0\u5339\u914D\u4EFB\u52A1":t==="archived"?"\u5F53\u524D\u65E0\u5DF2\u5F52\u6863\u4EFB\u52A1":t==="all"?"\u5F53\u524D\u65E0\u4EFB\u52A1":"\u5F53\u524D\u65E0\u5F85\u5B8C\u6210\u4EFB\u52A1");return}let a={};for(let l of r)(a[l.status]||=[]).push(l);let d=Object.keys(a).filter(l=>!M.includes(l)).sort();for(let l of[...M,...d]){let m=a[l]||[];if(m.length!==0){console.log(`\u3010${l}\u3011${m.length} \u9879`);for(let f of m){let u=t==="all"?`${f.view} `:"";console.log(` ${Ee(f)} ${u}${(f.owner||"\u672A\u6807\u6CE8").padEnd(8)} ${C(f.title,o)}\uFF08${f.scope||"-"}\uFF09`)}console.log("")}}St(s)}function St(e){let t=M.filter(r=>e.byStatus[r]),n=Object.keys(e.byStatus).filter(r=>!M.includes(r)),o=Object.keys(e.byOwner).sort((r,s)=>(e.byOwner[s]??0)-(e.byOwner[r]??0));if(console.log(`\u5171 ${e.total} \u4E2A\u4EFB\u52A1`),t.length>0||n.length>0){let r=t.map(s=>`${s} ${e.byStatus[s]}`);n.length>0&&r.push(`\u5176\u4ED6 ${n.reduce((s,i)=>s+(e.byStatus[i]??0),0)}`),console.log(`\u6309\u72B6\u6001\uFF1A${r.join("\u3000")}`)}o.length>0&&console.log(`\u6309\u8D1F\u8D23\u4EBA\uFF1A${o.map(r=>`${r} ${e.byOwner[r]}`).join("\u3000")}`)}import{mkdirSync as Lt}from"fs";import{dirname as jt}from"path";import{createRequire as Ot}from"module";import{writeFileSync as Rt,renameSync as At}from"fs";import{dirname as Ct,join as Ft}from"path";function F(e,t){let n=Ft(Ct(e),`.tmp-${process.pid}-${Date.now().toString(36)}`);Rt(n,t),At(n,e)}var Mt=Ot(import.meta.url);function de(e){Lt(jt(e),{recursive:!0})}var ne=[{label:"\u89C6\u56FE",value:e=>e.view==="\u5DF2\u5F52\u6863"?"\u5DF2\u5F52\u6863":"\u5F85\u5B8C\u6210"},{label:"\u4EFB\u52A1\u540D",value:e=>e.title},{label:"\u72B6\u6001",value:e=>e.status},{label:"\u8D1F\u8D23\u4EBA",value:e=>e.owner},{label:"\u8303\u56F4",value:e=>e.scope},{label:"\u521B\u5EFA\u65E5\u671F",value:e=>e.created?x(e.created):""},{label:"\u66F4\u65B0\u65E5\u671F",value:e=>e.updated?x(e.updated):""},{label:"\u5B8C\u6210\u65F6\u95F4",value:e=>e.completed},{label:"\u4F9D\u8D56",value:e=>e.depends.join(", ")},{label:"\u6765\u6E90\u6587\u4EF6",value:e=>e.file}],Et=[{label:"\u4EFB\u52A1\u540D",value:e=>e.title},{label:"\u72B6\u6001",value:e=>e.status},{label:"\u8D1F\u8D23\u4EBA",value:e=>e.owner},{label:"\u8303\u56F4",value:e=>e.scope},{label:"\u521B\u5EFA\u65E5\u671F",value:e=>e.created?x(e.created):""},{label:"\u66F4\u65B0\u65E5\u671F",value:e=>e.updated?x(e.updated):""},{label:"\u5B8C\u6210\u65F6\u95F4",value:e=>e.completed},{label:"\u4F9D\u8D56",value:e=>e.depends.join(", ")},{label:"\u6765\u6E90\u6587\u4EF6",value:e=>e.file}],It=[{label:"\u4EFB\u52A1\u540D",value:e=>e.title},{label:"\u72B6\u6001",value:e=>e.status},{label:"\u8D1F\u8D23\u4EBA",value:e=>e.owner},{label:"\u8303\u56F4",value:e=>e.scope},{label:"\u5B8C\u6210\u65F6\u95F4",value:e=>e.completed},{label:"\u6765\u6E90\u6587\u4EF6",value:e=>e.file}];function Bt(e){return/[",\n\r]/.test(e)?`"${e.replace(/"/g,'""')}"`:e}function Ne(e,t=!0){let n=ne.map(r=>r.label).join(","),o=e.map(r=>ne.map(s=>{let i=s.label==="\u4EFB\u52A1\u540D"?C(s.value(r),t):s.value(r);return Bt(i)}).join(",")).join(`\r
|
|
13
14
|
`);return`\uFEFF${n}${o?`\r
|
|
14
|
-
${o}`:""}`}function
|
|
15
|
+
${o}`:""}`}function ze(e,t,n=!0){let o=e.map(r=>({view:r.view==="\u5DF2\u5F52\u6863"?"archived":"active",title:C(r.title,n),status:r.status,owner:r.owner,scope:r.scope,created:r.created,updated:r.updated,completed:r.completed,depends:r.depends,file:r.file}));return JSON.stringify({schemaVersion:1,summary:t,items:o},null,2)}async function Dt(e,t,n=!0){let o=Mt("exceljs"),r=new o.Workbook,s=e.filter(c=>c.view==="\u5F85\u5B8C\u6210"),i=e.filter(c=>c.view==="\u5DF2\u5F52\u6863"),a=(c,g,p)=>{c.columns=g.map(h=>({header:h.label,key:h.label,width:Math.max(h.label.length+4,14)})),c.getRow(1).font={bold:!0};for(let h of p)c.addRow(g.map(v=>v.label==="\u4EFB\u52A1\u540D"?C(v.value(h),n):v.value(h)))},d=r.addWorksheet("\u5F85\u5B8C\u6210");a(d,Et,s);let l=r.addWorksheet("\u5DF2\u5F52\u6863");a(l,It,i);let m=r.addWorksheet("\u6C47\u603B");m.columns=[{header:"\u7C7B\u522B",key:"k",width:10},{header:"\u6570\u503C",key:"v",width:12}];let f=(c,g)=>{m.addRow([c,""]).font={bold:!0};for(let[p,h]of Object.entries(g).sort((v,R)=>R[1]-v[1]))m.addRow([p,h])};m.addRow(["\u4EFB\u52A1\u603B\u6570",t.total]).font={bold:!0},f("\u6309\u72B6\u6001",t.byStatus),f("\u6309\u8D1F\u8D23\u4EBA",t.byOwner),m.addRow([]);let u=m.addRow(ne.map(c=>c.label));u.font={bold:!0};for(let c of e)m.addRow(ne.map(g=>g.label==="\u4EFB\u52A1\u540D"?C(g.value(c),n):g.value(c)));return Buffer.from(await r.xlsx.writeBuffer())}async function _t(e,t,n,o=!0){let r=e.split(".").pop()?.toLowerCase();if(r==="csv")de(e),F(e,Ne(t,o));else if(r==="json")de(e),F(e,ze(t,n,o));else if(r==="xlsx")de(e),F(e,await Dt(t,n,o));else throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u51FA\u683C\u5F0F\u300C${r||""}\u300D\uFF0C\u4EC5\u652F\u6301 .csv / .xlsx / .json`)}import{readFileSync as pe,existsSync as me,mkdirSync as Ue}from"fs";import{join as q}from"path";import{createRequire as Ut}from"module";import{openSync as Nt,unlinkSync as Ye,statSync as zt,closeSync as Yt}from"fs";import{join as We}from"path";var Wt=600*1e3;function W(e,t=Wt){let n=We(e,".archive.lock");for(let o=0;o<2;o++)try{return Nt(n,"wx")}catch{try{let r=zt(n);if(Date.now()-r.mtimeMs<=t)return null;Ye(n)}catch{return null}}return null}function U(e,t){Yt(t);try{Ye(We(e,".archive.lock"))}catch{}}var Pt=Ut(import.meta.url),Pe={\u4EFB\u52A1\u540D:"title",\u6807\u9898:"title",\u4E8B\u9879:"title",\u4EFB\u52A1:"title",\u4EFB\u52A1\u6807\u9898:"title",\u4E8B\u9879\u540D\u79F0:"title",title:"title",name:"title",task:"title",subject:"title",summary:"title",\u72B6\u6001:"status",status:"status",state:"status",\u8D1F\u8D23\u4EBA:"owner",\u7ECF\u529E\u4EBA:"owner",\u5904\u7406\u4EBA:"owner",\u6267\u884C\u4EBA:"owner",\u6307\u6D3E\u7ED9:"owner",owner:"owner",assignee:"owner",handler:"owner",\u8303\u56F4:"scope",\u9879\u76EE:"scope",\u6A21\u5757:"scope",scope:"scope",project:"scope",\u521B\u5EFA\u65E5\u671F:"created",\u521B\u5EFA\u65F6\u95F4:"created",created:"created",created_at:"created",createdat:"created",\u66F4\u65B0\u65E5\u671F:"updated",\u66F4\u65B0\u65F6\u95F4:"updated",updated:"updated",updated_at:"updated",updatedat:"updated",\u5B8C\u6210\u65F6\u95F4:"completed",\u5B8C\u6210\u65E5\u671F:"completed",\u622A\u6B62\u65F6\u95F4:"completed",\u622A\u6B62\u65E5\u671F:"completed",\u7ED3\u675F\u65F6\u95F4:"completed",completed:"completed",done:"completed",finished:"completed",completedat:"completed",due:"completed",\u4F9D\u8D56:"depends",\u4F9D\u8D56\u4EFB\u52A1:"depends",depends:"depends",depends_on:"depends",dependency:"depends",dependencies:"depends",\u5907\u6CE8:"body",\u63CF\u8FF0:"body",\u6B63\u6587:"body",\u8BF4\u660E:"body",description:"body",body:"body",note:"body",notes:"body",\u89C6\u56FE:"",\u6765\u6E90\u6587\u4EF6:"",\u6587\u4EF6:"",view:"",file:"",path:""};function Ve(e,t={}){let n=new Map;return e.forEach((o,r)=>{let s=String(o??"").trim().toLowerCase();if(!s)return;let i;t[s]!==void 0&&(i=t[s]),i===void 0&&(i=Pe[s]),i!==""&&i&&!n.has(i)&&n.set(i,r)}),n}function Vt(e){let t=[],n=e.replace(/^\uFEFF/,"").replace(/\r\n/g,`
|
|
15
16
|
`).replace(/\r/g,`
|
|
16
17
|
`),o=[],r="",s=!1;for(let i=0;i<n.length;i++){let a=n[i];s?a==='"'?n[i+1]==='"'?(r+='"',i++):s=!1:r+=a:a==='"'?s=!0:a===","?(o.push(r),r=""):a===`
|
|
17
|
-
`?(o.push(r),t.push(o),o=[],r=""):r+=a}return(r!==""||o.length>0)&&(o.push(r),t.push(o)),t.filter(i=>i.length>1||(i[0]||"").trim()!=="")}function
|
|
18
|
+
`?(o.push(r),t.push(o),o=[],r=""):r+=a}return(r!==""||o.length>0)&&(o.push(r),t.push(o)),t.filter(i=>i.length>1||(i[0]||"").trim()!=="")}function Jt(e,t){let n=Vt(e);if(n.length===0)return[];let o=Ve(n[0]??[],t),r=[];for(let s=1;s<n.length;s++){let i={},a=n[s]??[];for(let[d,l]of o)i[d]=(a[l]??"").trim();(i.title||Object.keys(i).length>0)&&r.push(i)}return r}function Zt(e,t){let n=[];for(let o=1;o<=(e.rowCount||0);o++){let r=e.getRow(o),s=[];for(let a=1;a<=(r.cellCount||0);a++)s.push(r.getCell(a).text??"");if(s.every(a=>a.trim()===""))continue;let i=Ve(s,t);if(i.has("title")){for(let a=o+1;a<=e.rowCount;a++){let d=e.getRow(a),l={},m=!0;for(let[f,u]of i){let c=(d.getCell(u+1).text??"").trim();c&&(m=!1),l[f]=c}!m&&(l.title||Object.keys(l).length>0)&&n.push(l)}break}}return n}async function qt(e,t){let n=Pt("exceljs"),o=new n.Workbook;await o.xlsx.readFile(e);let r=[];for(let s of o.worksheets)s.name.includes("\u6C47\u603B")||r.push(...Zt(s,t));return r}function Ht(e,t){let n=JSON.parse(e);if(!Array.isArray(n)&&typeof n.schemaVersion=="number"){let s=n.schemaVersion;s>1&&console.warn(`\u26A0\uFE0F \u5BFC\u5165 JSON \u6765\u81EA\u66F4\u9AD8 schema \u7248\u672C v${s}\uFF0C\u5B57\u6BB5\u89E3\u6790\u53EF\u80FD\u4E0D\u5B8C\u6574`)}let o=Array.isArray(n)?n:Array.isArray(n.items)?n.items:[],r=[];for(let s of o){if(!s||typeof s!="object")continue;let i={};for(let[a,d]of Object.entries(s)){let l=a.trim().toLowerCase(),m;t[l]!==void 0&&(m=t[l]),m===void 0&&(m=Pe[l]),m&&(Array.isArray(d)?i[m]=d.join(","):d!=null&&(i[m]=String(d)))}r.push(i)}return r}function Gt(e){let t=e.trim().replace(/[\\/:*?"<>|]/g," ").replace(/\s+/g," "),n=t.length>24;return{slug:t.slice(0,24).trim().replace(/\s+/g,"-")||"\u4EFB\u52A1",truncated:n}}function Xt(e,t,n){let o=(e.title||"").trim();if(!o)return n.push(`\u8DF3\u8FC7\u4E00\u884C\uFF1A\u7F3A\u5C11\u4EFB\u52A1\u540D\uFF08${Object.entries(e).slice(0,3).map(([l,m])=>`${l}=${m}`).join(" ")}\uFF09`),{ok:!1};let r=(e.status||"").trim()||"\u5F85\u529E";Z.includes(r)||(n.push(`\u4EFB\u52A1\u300C${o}\u300D\u72B6\u6001\u300C${r}\u300D\u975E\u6CD5\uFF0C\u5DF2\u5F52\u4E3A\u5F85\u529E`),r="\u5F85\u529E");let s=e.completed?.trim()?$(e.completed.trim()):"";s&&!D.includes(r)&&(n.push(`\u4EFB\u52A1\u300C${o}\u300D\u5E26\u5B8C\u6210\u65F6\u95F4\u4F46\u72B6\u6001\u4E3A\u300C${r}\u300D\uFF0C\u5DF2\u7F6E\u4E3A\u5DF2\u5B8C\u6210`),r="\u5DF2\u5B8C\u6210");let i=(e.owner||"").trim()||t.owner||"";i=i.replace(/\s+/g,"");let a=(e.scope||"").trim()||t.scope||"-",d=(e.depends||"").split(/[,,;;]/).map(l=>l.trim()).filter(Boolean);return{ok:!0,t:{title:o,status:r,owner:i||"\u672A\u6807\u6CE8",scope:a,created:Ae(e.created||""),completed:s,depends:d,body:e.body?.trim()||""}}}function Kt(e,t,n,o){let r=t.created||ae(),s=q(e,"active",r.slice(0,6)),{slug:i,truncated:a}=Gt(t.title);a&&o.push(`\u4EFB\u52A1\u300C${t.title}\u300D\u6807\u9898\u8FC7\u957F\uFF0C\u6587\u4EF6\u540D\u5DF2\u622A\u65AD`);let d=`${r}-${t.owner}-${i}`,l=1,m=q(s,`${d}.md`);for(;me(m);)m=q(s,`${d}-${l++}.md`);let u=["---",`owner: ${t.owner}`,`status: ${t.status}`,`created: ${r}`,`updated: ${ae()}`,`completed: ${t.completed?`'${t.completed}'`:"''"}`,`depends_on: ${JSON.stringify(t.depends)}`,`scope: ${t.scope}`,"---","",`# ${t.title}`].join(`
|
|
18
19
|
`)+(t.body?`
|
|
19
20
|
|
|
20
21
|
${t.body}
|
|
21
22
|
`:`
|
|
22
|
-
`);return n||(
|
|
23
|
+
`);return n||(Ue(s,{recursive:!0}),F(m,u)),m}function Qt(e,t,n,o){let r=t.completed||"",s=r?x(r):"";if(!s)return o.push(`\u4EFB\u52A1\u300C${t.title}\u300D\u7F3A\u5C11\u5B8C\u6210\u65F6\u95F4\uFF0C\u65E0\u6CD5\u76F4\u63A5\u5F52\u6863\uFF08\u53EF\u6539\u7528 active \u76EE\u6807\uFF09`),null;let i=s.replace(/-/g,""),a=q(e,"archive",i.slice(0,6)),d=q(a,`${i}.md`),l=`> \u8D1F\u8D23\u4EBA\uFF1A${t.owner}\u3000\u72B6\u6001\uFF1A\u5DF2\u5B8C\u6210\u3000\u8303\u56F4\uFF1A${t.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${r}`,m=`# ${t.title}${t.body?`
|
|
23
24
|
|
|
24
|
-
${t.body}`:""}`,
|
|
25
|
+
${t.body}`:""}`,f={title:t.title,metaLine:l,completed:r,body:m};if(n)return d;Ue(a,{recursive:!0});let u=`# ${i} \u5F52\u6863
|
|
25
26
|
|
|
26
27
|
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks import --target archive\` \u81EA\u52A8\u751F\u6210\u3002
|
|
27
|
-
`,c=[];if(
|
|
28
|
+
`,c=[];if(me(d)){let p=A(pe(d,"utf8"));p.header&&(u=p.header),c=p.blocks}c.push(f),c.sort((p,h)=>$(h.completed).localeCompare($(p.completed)));let g=c.map(p=>`## ${p.title}
|
|
28
29
|
|
|
29
|
-
${
|
|
30
|
+
${p.metaLine}
|
|
30
31
|
|
|
31
|
-
${
|
|
32
|
+
${p.body}`);return F(d,`${u}
|
|
32
33
|
|
|
33
34
|
${g.join(`
|
|
34
35
|
|
|
35
36
|
---
|
|
36
37
|
|
|
37
38
|
`)}
|
|
38
|
-
`),d}async function
|
|
39
|
+
`),d}async function en(e,t=".tasks",n={}){let o=!!n.dryRun,r=[],s=Object.fromEntries(Object.entries(n.importColumns??{}).map(([c,g])=>[String(c).trim().toLowerCase(),String(g)])),i=e.split(".").pop()?.toLowerCase(),a;if(i==="csv")a=Jt(pe(e,"utf8"),s);else if(i==="xlsx")a=await qt(e,s);else if(i==="json")a=Ht(pe(e,"utf8"),s);else throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u5165\u683C\u5F0F\u300C${i||""}\u300D\uFF0C\u4EC5\u652F\u6301 .csv / .xlsx / .json`);if(a.length===0)return console.log("\u672A\u8BC6\u522B\u5230\u53EF\u5BFC\u5165\u7684\u4EFB\u52A1\u884C\uFF08\u68C0\u67E5\u8868\u5934\u662F\u5426\u5305\u542B\u300C\u4EFB\u52A1\u540D/\u6807\u9898\u300D\u7B49\u5217\u540D\uFF09"),{created:0,skipped:0,warnings:r,dryRun:o};let d=0,l=0,m=n.target??"active",f=null;if(!o&&me(t)&&(f=W(t),f===null)){let c="\u68C0\u6D4B\u5230\u5199\u5165\u9501 .archive.lock\uFF0C\u53EF\u80FD\u6709\u5E76\u53D1\u5199\u5165\u6B63\u5728\u8FDB\u884C\uFF0C\u672C\u6B21\u5DF2\u8DF3\u8FC7";return console.warn(`\u26A0\uFE0F ${c}`),{created:0,skipped:a.length,warnings:[...r,c],dryRun:o}}try{for(let c of a){let g=Xt(c,n,r);if(!g.ok){l++;continue}let p=g.t;if(m==="archive"){let h=Qt(t,p,o,r);if(!h){l++;continue}console.log(`${o?"[\u9884\u6F14] \u5C06\u5199\u5165\u5F52\u6863":"\u5DF2\u5199\u5165\u5F52\u6863"} \u2192 ${O(t,h)}`)}else{let h=Kt(t,p,o,r);console.log(`${o?"[\u9884\u6F14] \u5C06\u521B\u5EFA":"\u5DF2\u521B\u5EFA"} \u2192 ${O(t,h)}`)}d++}}finally{if(f!==null)try{U(t,f)}catch{}}for(let c of r)console.warn(`\u26A0\uFE0F ${c}`);return console.log(`${o?"\u9884\u6F14\u53EF\u5BFC\u5165":"\u5DF2\u5BFC\u5165"} ${d} \u4E2A\u4EFB\u52A1\uFF0C\u8DF3\u8FC7 ${l} \u884C`),{created:d,skipped:l,warnings:r,dryRun:o}}import{readFileSync as fe,mkdirSync as tn,unlinkSync as nn,existsSync as rn,readdirSync as on,rmdirSync as sn}from"fs";import{join as re,basename as ue,dirname as Ze,resolve as Je,sep as an}from"path";function oe(e,t){let n=Je(e),o=Je(t);for(;n!==o&&n.startsWith(o+an);){try{if(on(n).length>0)break;sn(n)}catch{break}n=Ze(n)}}function cn(e){let t=fe(e,"utf8"),{blocks:n}=A(t);return n.map(o=>({block:z(o),completed:o.completed}))}function ln(e=".tasks",t=!0,n={}){let{dryRun:o=!1,warn:r=!0}=n,s=re(e,"active"),i=re(e,"archive"),a=[],d=S(s);if(d.length===0)return console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u65E0\u9700\u5F52\u6863"),{archived:0,skipped:[],warnings:a};let l=[],m=[];for(let c of d){let g=fe(c,"utf8"),p=L(g);if(!D.includes(p.status))continue;let h=$(p.completed||"");if(!h){m.push(ue(c,".md")),console.log(`\u8DF3\u8FC7 ${ue(c,".md")}\uFF1A\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`);continue}l.push({file:c,name:ue(c,".md"),owner:p.owner||"\u672A\u6807\u6CE8",status:p.status||"\u672A\u6807\u6CE8",scope:p.scope||"-",completed:h,body:E(g).trim()})}if(l.length===0)return console.log("\u672C\u6B21\u65E0\u53EF\u5F52\u6863\u4EFB\u52A1"),{archived:0,skipped:m,warnings:a};if(r)for(let c of l){let g=c.completed.replace(/-/g,"").slice(0,8),p=I(c.file);p&&g!==p&&a.push(`\u4EFB\u52A1\u300C${c.name}\u300D\u5B8C\u6210\u65F6\u95F4 ${c.completed} \u4E0E\u521B\u5EFA\u65E5 ${p} \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u786E\u8BA4 completed \u662F\u5426\u586B\u9519`)}let f={};for(let c of l){let g=c.completed.replace(/-/g,"").slice(0,8);(f[g]||=[]).push(c)}let u=null;if(!o&&(u=W(e),u===null)){let c="\u68C0\u6D4B\u5230\u5F52\u6863\u9501 .archive.lock\uFF0C\u53EF\u80FD\u6709\u5E76\u53D1\u5F52\u6863\u6B63\u5728\u8FDB\u884C\uFF0C\u672C\u6B21\u5DF2\u8DF3\u8FC7";return console.warn(`\u26A0\uFE0F ${c}`),{archived:0,skipped:m,warnings:[...a,c]}}try{let c=0,g=[];for(let[p,h]of Object.entries(f)){let v=re(i,p.slice(0,6)),R=re(v,`${p}.md`),B=rn(R)?fe(R,"utf8"):"",K=`# ${p} \u5F52\u6863
|
|
39
40
|
|
|
40
|
-
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002`,
|
|
41
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002`,j=[];if(B){let b=A(B);b.header&&(K=b.header);for(let T of b.blocks)j.push({block:z(T),completed:T.completed})}if(r){let b=new Set(j.map(T=>T.block.match(/^## (.+)/)?.[1]??""));for(let T of h)b.has(T.name)&&a.push(`\u5F52\u6863\u6587\u4EF6\u5DF2\u5B58\u5728\u540C\u540D\u4EFB\u52A1\u300C${T.name}\u300D\uFF0C\u7591\u4F3C\u91CD\u590D\u5F52\u6863`)}j.push(...h.map(b=>({block:`## ${b.name}
|
|
41
42
|
|
|
42
|
-
> \u8D1F\u8D23\u4EBA\uFF1A${
|
|
43
|
+
> \u8D1F\u8D23\u4EBA\uFF1A${b.owner}\u3000\u72B6\u6001\uFF1A${b.status}\u3000\u8303\u56F4\uFF1A${b.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${b.completed}
|
|
43
44
|
|
|
44
|
-
${
|
|
45
|
+
${C(b.body,t)}`,completed:b.completed})));for(let b of j)b.completed=$(b.completed);if(j.sort((b,T)=>T.completed.localeCompare(b.completed)),o){console.log(`[\u9884\u6F14] \u5C06\u5F52\u6863 ${h.length} \u4E2A\u4EFB\u52A1 \u2192 ${p}.md`);for(let b of h)console.log(`[\u9884\u6F14] - ${b.name}`);continue}try{tn(v,{recursive:!0});let b=B.includes(`\r
|
|
46
|
+
`)?`\r
|
|
47
|
+
`:`
|
|
48
|
+
`;F(R,`${K}
|
|
45
49
|
|
|
46
|
-
${
|
|
50
|
+
${j.map(V=>V.block).join(`
|
|
47
51
|
|
|
48
52
|
---
|
|
49
53
|
|
|
50
54
|
`)}
|
|
51
|
-
|
|
55
|
+
`.replace(/\n/g,b));for(let V of h)nn(V.file);let T=h[0];T&&oe(Ze(T.file),e),console.log(`\u5DF2\u5F52\u6863 ${h.length} \u4E2A\u4EFB\u52A1 \u2192 ${p}.md`),c+=h.length}catch(b){g.push(`${p}.md\uFF1A${b.message}`)}}for(let p of a)console.warn(`\u26A0\uFE0F ${p}`);if(g.length>0){console.error(`\u5F52\u6863\u5931\u8D25 ${g.length} \u4E2A\u65E5\u671F\u6587\u4EF6\uFF08active \u672A\u5220\u9664\uFF0C\u53EF\u91CD\u8BD5\uFF09\uFF1A`);for(let p of g)console.error(` - ${p}`)}return console.log(o?`[\u9884\u6F14] \u5171 ${l.length} \u4E2A\u4EFB\u52A1\u53EF\u5F52\u6863\uFF08\u672A\u843D\u76D8\uFF09`:`\u5171\u5F52\u6863 ${c} \u4E2A\u4EFB\u52A1${g.length>0?`\uFF0C\u5931\u8D25 ${g.length} \u4E2A`:""}`),{archived:o?l.length:c,skipped:m,warnings:a}}finally{if(u!==null)try{U(e,u)}catch{}}}import{readFileSync as ge,statSync as dn}from"fs";import{join as Ge,basename as H,dirname as pn}from"path";var mn=/待办|待实施|待核对|待确认|待开始|待评估|待排期|待做|TODO/,un=/^\d{4}-\d{1,2}-\d{1,2}(?:[T\s]\d{1,2}:\d{2}(?::\d{2})?)?$/,fn=/^\d{4}-\d{1,2}-\d{1,2}[T\s]\d{1,2}:\d{2}(?::\d{2})?$/,gn=/^\d{8}-[^-]+-.+\.md$/;function qe(e){let t=e.match(/^(\d{4})-?(\d{1,2})-?(\d{1,2})/);if(!t)return!1;let[,n,o,r]=t;if(!n||!o||!r)return!1;let s=+n,i=+o,a=+r;if(i<1||i>12||a<1||a>31)return!1;let d=new Date(Date.UTC(s,i-1,a));return d.getUTCFullYear()===s&&d.getUTCMonth()===i-1&&d.getUTCDate()===a}function Xe(e){let t=[],n=H(e),o=ge(e,"utf8");if(!/^---\r?\n[\s\S]*?\r?\n---/.test(o))return t.push({level:"error",file:n,message:"\u7F3A\u5C11 frontmatter"}),t;let s=L(o);if(s.status?Z.includes(s.status)||t.push({level:"error",file:n,message:`status \u975E\u6CD5\u503C\u300C${s.status}\u300D\uFF0C\u5E94\u4E3A ${Z.join(" / ")}`}):t.push({level:"error",file:n,message:"frontmatter \u7F3A\u5C11 status \u5B57\u6BB5"}),D.includes(s.status)&&!s.completed&&t.push({level:"error",file:n,message:`status \u4E3A\u300C${s.status}\u300D\u4F46\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`}),s.completed){let f=s.completed.trim();if(!un.test(f))t.push({level:"warn",file:n,message:`completed\u300C${s.completed}\u300D\u683C\u5F0F\u975E\u6CD5\uFF0C\u5E94\u4E3A YYYY-MM-DD HH:mm`});else{let u=f.match(/^\d{4}-\d{1,2}-\d{1,2}/)?.[0]??f;qe(u)?fn.test(f)||t.push({level:"warn",file:n,message:`completed\u300C${s.completed}\u300D\u5EFA\u8BAE\u8865\u5168\u4E3A\u5B8C\u6574\u65F6\u95F4 YYYY-MM-DD HH:mm`}):t.push({level:"warn",file:n,message:`completed\u300C${s.completed}\u300D\u65E5\u671F\u4E0D\u5B58\u5728\uFF0C\u8BF7\u6838\u5BF9`})}}s.owner||t.push({level:"warn",file:n,message:"\u7F3A\u5C11 owner \u8D1F\u8D23\u4EBA\u5B57\u6BB5"}),s.created?/^\d{8}$/.test(s.created.trim())?qe(s.created.trim())||t.push({level:"warn",file:n,message:`created\u300C${s.created}\u300D\u65E5\u671F\u4E0D\u5B58\u5728\uFF0C\u8BF7\u6838\u5BF9`}):t.push({level:"warn",file:n,message:`created\u300C${s.created}\u300D\u683C\u5F0F\u975E\u6CD5\uFF0C\u5E94\u4E3A YYYYMMDD`}):t.push({level:"warn",file:n,message:"\u7F3A\u5C11 created \u521B\u5EFA\u65E5\u671F\u5B57\u6BB5"});let i=n.match(/^(\d{8})-/);gn.test(n)?s.created&&/^\d{8}$/.test(s.created.trim())&&i&&s.created.trim()!==i[1]&&t.push({level:"warn",file:n,message:`\u6587\u4EF6\u540D\u65E5\u671F ${i[1]} \u4E0E created ${s.created.trim()} \u4E0D\u4E00\u81F4`}):t.push({level:"warn",file:n,message:"\u6587\u4EF6\u540D\u4E0D\u7B26\u5408\u89C4\u8303 {YYYYMMDD}-{\u8D1F\u8D23\u4EBA}-{\u7B80\u8FF0}.md"});let a=ke(E(o)),l=N("check")?.pendingMarkers!==!1?a.match(mn):null;return l&&t.push({level:"warn",file:n,message:`\u6B63\u6587\u542B\u672A\u95ED\u5408\u5F85\u529E\u6807\u8BB0\u300C${l[0]}\u300D\uFF0C\u5EFA\u8BAE\u62C6\u5206\u4E3A\u72EC\u7ACB active \u4EFB\u52A1\u6216\u660E\u786E\u95ED\u73AF`}),N("check")?.includeCheckbox!==!1&&/^[-*]\s*\[ \]\s/m.test(a)&&t.push({level:"warn",file:n,message:"\u6B63\u6587\u542B\u672A\u52FE\u9009\u5F85\u529E\u9879\u300C- [ ]\u300D\uFF0C\u5EFA\u8BAE\u62C6\u5206\u4E3A\u72EC\u7ACB active \u4EFB\u52A1\u6216\u52FE\u9009\u5B8C\u6210"}),t}function hn(e=".tasks"){let t=Ge(e,"active"),n=S(t),o=[];for(let a of n)o.push(...Xe(a)),pn(a)===t&&o.push({level:"warn",file:H(a),message:"active \u4EFB\u52A1\u5E94\u653E\u5165 {YYYYMM} \u6708\u4EFD\u5B50\u76EE\u5F55\uFF08\u5F53\u524D\u76F4\u653E active \u6839\u76EE\u5F55\uFF09"});let r=new Map;for(let a of n){let d=H(a,".md"),l=r.get(d);l?l.push(a):r.set(d,[a])}for(let[a,d]of r)d.length>1&&o.push({level:"warn",file:a,message:`\u5B58\u5728 ${d.length} \u4E2A\u540C\u540D\u4EFB\u52A1\u6587\u4EF6\uFF0C\u7591\u4F3C\u91CD\u590D\u5EFA\u6863`});o.push(...bn(n,e));let s=o.filter(a=>a.level==="error").length,i=o.length-s;return{issues:o,errorCount:s,warnCount:i}}var He=new Map;function kn(e){let t=dn(e),n=He.get(e);if(n&&n.mtimeMs===t.mtimeMs)return n.titles;let o=[];try{for(let r of A(ge(e,"utf8")).blocks)r.title&&!o.includes(r.title)&&o.push(r.title)}catch{}return He.set(e,{mtimeMs:t.mtimeMs,titles:o}),o}function bn(e,t){let n=[],o=new Set(e.map(u=>H(u,".md"))),r=new Map,s=u=>u.trim().replace(/\.md$/,"").trim(),i=new Map;for(let u of S(Ge(t,"archive")))for(let c of kn(u))i.has(c)||i.set(c,O(t,u));for(let u of e){let c=H(u,".md"),g=ge(u,"utf8"),p=L(g),h=te(p.depends_on).map(s);r.set(c,h);for(let v of h)if(!o.has(v)){let R=i.get(v);n.push({level:"warn",file:c,message:R?`\u4F9D\u8D56\u7684\u4EFB\u52A1\u300C${v}\u300D\u4E0D\u5728 active \u4E2D\uFF08\u5DF2\u5F52\u6863\u4E8E ${R}\uFF0C\u65E0\u9700\u518D\u4F9D\u8D56\uFF09`:`\u4F9D\u8D56\u7684\u4EFB\u52A1\u300C${v}\u300D\u4E0D\u5728 active \u4E2D\uFF08\u53EF\u80FD\u5DF2\u5F52\u6863\u6216\u6587\u4EF6\u540D\u62FC\u5199\u9519\u8BEF\uFF09`})}}let a=0,d=1,l=2,m=new Map,f=(u,c)=>{m.set(u,d);for(let g of r.get(u)??[]){if(!o.has(g))continue;let p=m.get(g)??a;if(p===d)return[...c,g];if(p===a){let h=f(g,[...c,g]);if(h)return h}}return m.set(u,l),null};for(let u of r.keys())if((m.get(u)??a)===a){let c=f(u,[u]);if(c){n.push({level:"warn",file:u,message:`depends_on \u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56\uFF1A${c.join(" \u2192 ")}`});break}}return n}import{readFileSync as se,unlinkSync as wn,existsSync as ie,mkdirSync as Ke,renameSync as yn}from"fs";import{join as P,basename as X,dirname as G}from"path";var vn=["\u8D1F\u8D23\u4EBA","\u72B6\u6001","\u8303\u56F4","\u5B8C\u6210\u65F6\u95F4"];function Qe(e){return vn.every(t=>e.includes(t))}function $n(e=".tasks"){let t=P(e,"archive"),n=S(t),o=[];for(let r of n){let s=X(r),i=s.replace(/\.md$/,""),a=se(r,"utf8"),{blocks:d}=A(a),l=X(G(r)),m=s.replace(/\.md$/,"");l&&m&&l!==m.slice(0,6)&&o.push({file:s,message:`\u5F52\u6863\u6587\u4EF6\u4F4D\u4E8E ${l} \u6708\u4EFD\u76EE\u5F55\uFF0C\u4E0E\u6587\u4EF6\u540D\u65E5\u671F ${m.slice(0,6)} \u4E0D\u4E00\u81F4`,fixable:!1});for(let f of Se(a))o.push({file:s,message:`\u7591\u4F3C\u4EFB\u52A1\u5757\u300C${f}\u300D\u5143\u6570\u636E\u7F3A\u300C\u5B8C\u6210\u65F6\u95F4\u300D\uFF0C\u5DF2\u88AB\u5F52\u5165\u524D\u4E00\u5757\u6B63\u6587\uFF08\u9700\u4EBA\u5DE5\u786E\u8BA4\uFF09`,fixable:!1});for(let f=1;f<d.length;f++){let u=d[f-1],c=d[f];if(!u||!c)continue;let g=$(u.completed),p=$(c.completed);if(g&&p&&g<p){o.push({file:s,message:"\u4EFB\u52A1\u5757\u672A\u6309\u5B8C\u6210\u65F6\u95F4\u964D\u5E8F\u6392\u5217",fixable:!0});break}}for(let f of d){f.metaLine?Qe(f.metaLine)||o.push({file:s,message:`\u5757\u300C${f.title}\u300D\u5143\u6570\u636E\u884C\u4E0D\u5B8C\u6574\uFF08\u7F3A\u8D1F\u8D23\u4EBA/\u72B6\u6001/\u8303\u56F4\u4E4B\u4E00\uFF09`,fixable:!!f.completed}):o.push({file:s,message:`\u5757\u300C${f.title}\u300D\u7F3A\u5C11\u5143\u6570\u636E\u884C\uFF08\u8D1F\u8D23\u4EBA/\u72B6\u6001/\u8303\u56F4/\u5B8C\u6210\u65F6\u95F4\uFF09`,fixable:!!f.completed});let u=$(f.completed),c=u.replace(/-/g,"").slice(0,8);c&&i&&c!==i&&o.push({file:s,message:`\u5757\u300C${f.title}\u300D\u5B8C\u6210\u65F6\u95F4 ${u} \u4E0E\u5F52\u6863\u6587\u4EF6\u65E5\u671F ${i} \u4E0D\u4E00\u81F4`,fixable:!1})}}return o}function xn(e,t,n){let o=P(e,"archive",n.slice(0,6)),r=P(o,`${n}.md`);Ke(o,{recursive:!0});let s=`# ${n} \u5F52\u6863
|
|
52
56
|
|
|
53
|
-
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002`,i=[];if(
|
|
57
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002`,i=[];if(ie(r)){let l=A(se(r,"utf8"));l.header&&(s=l.header),i.push(...l.blocks)}i.some(l=>l.title===t.title)&&console.warn(`\u26A0\uFE0F \u76EE\u6807 ${n}.md \u5DF2\u5B58\u5728\u540C\u540D\u5757\u300C${t.title}\u300D\uFF0C\u8FC1\u79FB\u5C06\u4EA7\u751F\u91CD\u590D`),i.push(t),i.sort((l,m)=>$(m.completed).localeCompare($(l.completed)));let a=ie(r)&&se(r,"utf8").includes(`\r
|
|
54
58
|
`)?`\r
|
|
55
59
|
`:`
|
|
56
60
|
`,d=`${s}
|
|
57
61
|
|
|
58
|
-
${i.map(
|
|
62
|
+
${i.map(z).join(`
|
|
59
63
|
|
|
60
64
|
---
|
|
61
65
|
|
|
62
66
|
`)}
|
|
63
|
-
`.replace(/\n/g,a);
|
|
67
|
+
`.replace(/\n/g,a);F(r,d),console.log(` \u5757\u300C${t.title}\u300D\u8FC1\u79FB \u2192 ${n}.md`)}function Tn(e=".tasks"){let t=P(e,"archive"),n=S(t),o=[],r=0,s=null;if(s=W(e),s===null)return console.warn("\u26A0\uFE0F \u68C0\u6D4B\u5230\u5F52\u6863\u9501\uFF0C\u53EF\u80FD\u6709\u5E76\u53D1\u5199\u64CD\u4F5C\u6B63\u5728\u8FDB\u884C\uFF0C\u672C\u6B21\u5DF2\u8DF3\u8FC7\u4FEE\u590D"),{issues:o,fixed:r};try{for(let i of n){let a=i,d=X(a),l=d.replace(/\.md$/,""),m=X(G(a)),f=/^\d{8}$/.test(l)?l.slice(0,6):"";if(f&&m!==f){let k=P(t,f,d);ie(k)?console.warn(`\u26A0\uFE0F ${d}\uFF1A\u76EE\u6807\u6708\u4EFD\u76EE\u5F55 ${f} \u5DF2\u5B58\u5728\u540C\u540D\u6587\u4EF6\uFF0C\u672A\u81EA\u52A8\u79FB\u52A8\uFF08\u9700\u4EBA\u5DE5\u5904\u7406\uFF09`):(Ke(P(t,f),{recursive:!0}),yn(a,k),a=k,oe(G(i),t))}let u=se(a,"utf8"),{header:c,blocks:g}=A(u),p=[],h=a!==i;a!==i&&(p.push(`\u79FB\u52A8\u81F3 ${X(G(a))} \u6708\u4EFD\u76EE\u5F55`),r++);for(let k of g)k.completed&&(!k.metaLine||!Qe(k.metaLine))&&(k.metaLine=Te(k.title,k.completed,k.metaLine),p.push(`\u8865\u5143\u6570\u636E\u300C${k.title}\u300D`),h=!0,r++);let v=[],R=0;for(let k of g){let J=k.completed?$(k.completed).replace(/-/g,"").slice(0,8):"";J&&J!==l?(xn(e,k,J),R++,h=!0):v.push(k)}R>0&&(p.push(`\u8FC1\u79FB ${R} \u4E2A\u6F02\u79FB\u5757`),r+=R);let B=v.filter(k=>k.completed),K=v.filter(k=>!k.completed),j=[...B].sort((k,J)=>$(J.completed).localeCompare($(k.completed)));JSON.stringify(j.map(k=>k.title))!==JSON.stringify(B.map(k=>k.title))&&(v.splice(0,v.length,...j,...K),p.push("\u964D\u5E8F\u91CD\u6392"),r++,h=!0);let T=/^---\s*\r?\n\r?\n---/m.test(u);T&&(p.push("\u6E05\u7406\u5197\u4F59\u5206\u9694\u7B26"),r++);let V=u.includes(`\r
|
|
64
68
|
`)?`\r
|
|
65
69
|
`:`
|
|
66
|
-
`;if(g.length>0&&
|
|
70
|
+
`;if(g.length>0&&v.length===0)ie(a)&&wn(a),oe(G(a),t),p.push("\u5220\u9664\u7A7A\u5F52\u6863\u6587\u4EF6"),h=!0;else if(h||T){let k=((c?c+`
|
|
67
71
|
|
|
68
|
-
`:"")+
|
|
72
|
+
`:"")+v.map(z).join(`
|
|
69
73
|
|
|
70
74
|
---
|
|
71
75
|
|
|
72
76
|
`)+`
|
|
73
|
-
`).replace(/\n/g,
|
|
77
|
+
`).replace(/\n/g,V);F(a,k)}p.length>0&&console.log(` ${d}: ${p.join("\u3001")}`)}return{issues:o,fixed:r}}finally{if(s!==null)try{U(e,s)}catch{}}}var jo={zh:{replacements:{"### Major Changes":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### \u91CD\u5927\u53D8\u66F4":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### Minor Changes":"### \u2728 \u65B0\u589E\u529F\u80FD","### \u65B0\u589E\u529F\u80FD":"### \u2728 \u65B0\u589E\u529F\u80FD","### Patch Changes":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### \u8865\u4E01\u4FEE\u590D":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### Dependent Changes":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","### \u4F9D\u8D56\u53D8\u66F4":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","- Updated dependencies":"- \u66F4\u65B0\u4F9D\u8D56"},deps:"- \u66F4\u65B0\u4F9D\u8D56",released:"\u53D1\u5E03"},en:{replacements:{"### Major Changes":"### \u{1F6A8} Major Changes","### Minor Changes":"### \u2728 Minor Changes","### Patch Changes":"### \u{1F41B} Patch Changes","### Dependent Changes":"### \u{1F517} Dependent Changes"},deps:"- Updated dependencies",released:"released"}},Oo="zh";import{readdirSync as Sn}from"fs";import{join as et}from"path";function he(e){let t=[],n=new Set(["node_modules",".git","dist","coverage"]),o=r=>{let s;try{s=Sn(r,{withFileTypes:!0})}catch{return}for(let i of s)if(i.isDirectory()){if(n.has(i.name))continue;o(et(r,i.name))}else i.name==="CHANGELOG.md"&&t.push(et(r,i.name))};return o(e),t}import{readFileSync as Rn,writeFileSync as An}from"fs";function Cn(){return Ce()}function tt(e,t,n,o=!0){let r=Rn(e,"utf8"),s=r.includes(`\r
|
|
74
78
|
`)?`\r
|
|
75
79
|
`:`
|
|
76
80
|
`,i=r.replace(/\r\n/g,`
|
|
77
|
-
`),a=i;for(let[
|
|
81
|
+
`),a=i;for(let[u,c]of Object.entries(n.replacements))a=a.replaceAll(u,c);for(a=a.replace(/^- [0-9a-f]{7}: /gm,"- ");a.includes(`${n.deps}
|
|
78
82
|
${n.deps}`);)a=a.replace(`${n.deps}
|
|
79
|
-
${n.deps}`,n.deps);for(;;){let
|
|
80
|
-
`),l=[];for(let
|
|
81
|
-
`),
|
|
83
|
+
${n.deps}`,n.deps);for(;;){let u=a.replace(/^- (.+)\n- \1$/gm,"- $1");if(u===a)break;a=u}let d=a.split(`
|
|
84
|
+
`),l=[];for(let u=0;u<d.length;u++){let c=d[u]??"";if(l.push(c),/^## \d+\.\d+\.\d+/.test(c)){let g=u+1;for(;g<d.length&&(d[g]??"").trim()==="";)g++;let p=d[g]??"";p.startsWith("> ")&&/^> \d{4}-\d{2}-\d{2} (?:发布|released)$/.test(p.trim())||l.push(`> ${t} ${n.released}`)}}let m=l.join(`
|
|
85
|
+
`),f=C(m,o);return f!==i?(An(e,f.replace(/\n/g,s),"utf8"),!0):!1}function Fn(e,t,n,o=!0){let r=[];for(let s of he(e))tt(s,t,n,o)&&r.push(s);if(r.length===0)console.log("\u65E0 CHANGELOG \u9700\u8981\u66F4\u65B0");else for(let s of r)console.log(`changelog \u5DF2\u66F4\u65B0\uFF1A${s}`);return r}export{Z as ALL_STATUSES,Oo as DEFAULT_LANG,D as DONE_STATUSES,ln as archiveTasks,Be as buildSummary,$n as checkArchive,he as collectChangelogs,I as dateFromFileName,_t as exportTasks,Tn as fixArchive,tt as formatChangelog,Fn as formatChangelogs,N as getConfigSection,en as importTasks,jo as languages,Oe as listActiveTasks,Me as listArchivedTasks,S as listTaskFiles,xt as listTasks,ye as loadToolkitConfig,Cn as localDate,$ as normalizeCompleted,Ie as orderRows,cn as parseArchiveTasks,ve as parseBool,L as parseFrontmatter,_e as printTaskBoard,Tt as printTasks,le as queryTasks,C as redactText,dt as resetToolkitConfigCache,$e as resolveEnabled,E as stripFrontmatter,Ne as toCSV,ze as toJSON,Xe as validateTaskFile,hn as validateTasks};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fxri/toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "专为多人 + AI 跨项目协作打造:任务管理 + 多语言 CHANGELOG。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
34
|
"dist",
|
|
35
|
+
"skills",
|
|
35
36
|
"README.md",
|
|
36
37
|
"SPEC.md",
|
|
37
38
|
"CHANGELOG.md",
|
|
@@ -40,6 +41,19 @@
|
|
|
40
41
|
"NOTICE",
|
|
41
42
|
"package.json"
|
|
42
43
|
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"dev": "pnpm build:debug && node ./dist/cli.js",
|
|
46
|
+
"build": "cross-env NODE_ENV=production tsup",
|
|
47
|
+
"build:debug": "cross-env NODE_ENV=development tsup --config tsup.dev.config.ts",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"lint": "eslint . --cache",
|
|
50
|
+
"lint:fix": "eslint . --fix",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"changeset": "changeset",
|
|
55
|
+
"release": "pnpm build && pnpm publish"
|
|
56
|
+
},
|
|
43
57
|
"keywords": [
|
|
44
58
|
"toolkit",
|
|
45
59
|
"task",
|
|
@@ -63,24 +77,12 @@
|
|
|
63
77
|
"typescript-eslint": "^8.69.0",
|
|
64
78
|
"vitest": "^4.1.11"
|
|
65
79
|
},
|
|
80
|
+
"packageManager": "pnpm@10.34.4",
|
|
66
81
|
"engines": {
|
|
67
82
|
"node": ">=20"
|
|
68
83
|
},
|
|
69
84
|
"publishConfig": {
|
|
70
85
|
"registry": "https://registry.npmjs.org/",
|
|
71
86
|
"access": "public"
|
|
72
|
-
},
|
|
73
|
-
"scripts": {
|
|
74
|
-
"dev": "pnpm build:debug && node ./dist/cli.js",
|
|
75
|
-
"build": "cross-env NODE_ENV=production tsup",
|
|
76
|
-
"build:debug": "cross-env NODE_ENV=development tsup --config tsup.dev.config.ts",
|
|
77
|
-
"typecheck": "tsc --noEmit",
|
|
78
|
-
"lint": "eslint . --cache",
|
|
79
|
-
"lint:fix": "eslint . --fix",
|
|
80
|
-
"test": "vitest run",
|
|
81
|
-
"test:watch": "vitest",
|
|
82
|
-
"test:coverage": "vitest run --coverage",
|
|
83
|
-
"changeset": "changeset",
|
|
84
|
-
"release": "pnpm build && pnpm publish"
|
|
85
87
|
}
|
|
86
|
-
}
|
|
88
|
+
}
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# fxri Skills
|
|
2
|
+
|
|
3
|
+
零依赖 AI 技能包:纯 Markdown 规范 + 流程指令,不绑定编程语言、框架或任何工具,AI 仅凭文件读写即可完整执行;`@fxri/toolkit` 仅作为可选加速器出现(各 SKILL.md 末尾「可选加速」节)。
|
|
4
|
+
|
|
5
|
+
遵循 [Agent Skills 开放标准](https://agentskills.io)(`SKILL.md` = YAML frontmatter + Markdown 正文),可被 Claude Code、Cursor、Codex、Gemini CLI 等兼容 agent 按需加载。
|
|
6
|
+
|
|
7
|
+
## 技能列表
|
|
8
|
+
|
|
9
|
+
| 技能 | 用途 |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| [fxri-plan-to-task](./fxri-plan-to-task/SKILL.md) | 方案落盘:先查后写 → 建档 → 校验 → 归档 → 归档提交同批 |
|
|
12
|
+
| [fxri-release-changelog](./fxri-release-changelog/SKILL.md) | changesets 发版与多语言 CHANGELOG 维护 |
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
### 方式一:`npx skills` 自动安装(推荐)
|
|
17
|
+
|
|
18
|
+
本仓库遵循 Agent Skills 开放标准,兼容 [vercel-labs/skills](https://github.com/vercel-labs/skills) 安装器(自动识别本机 agent、写锁定文件):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx skills add fxri-net/toolkit # 安装全部技能
|
|
22
|
+
npx skills add fxri-net/toolkit --skill fxri-plan-to-task # 只装单个技能
|
|
23
|
+
npx skills list / update / remove # 查看 / 升级 / 卸载
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- 项目级安装默认写 `.agents/skills/` 并对各 agent(Claude Code / Cursor / Codex 等 75+)目录建立符号链接;团队项目把生成的 `skills-lock.json` 提交进仓库以对齐版本,单人可加 `-g` 全局安装
|
|
27
|
+
- ⚠️ 已知上游行为(v1.5.x):项目级安装时若 `.claude/` 目录不存在,Claude Code 目标会被静默跳过——先创建 `.claude/skills/` 空目录或改用 `-g`
|
|
28
|
+
|
|
29
|
+
### 方式二:手工复制 / 软链
|
|
30
|
+
|
|
31
|
+
- 复制或软链技能目录到 agent 的 skills 目录(如 Claude Code 的 `.claude/skills/`)
|
|
32
|
+
- 支持自定义 rules 的工具(如 Trae):链接 SKILL.md 为规则
|
|
33
|
+
- 通用兜底:在项目根 `AGENTS.md` 中引用本目录路径
|
|
34
|
+
|
|
35
|
+
复制副本以 frontmatter `metadata.version` 判断是否需要同步上游(`metadata.source` 指向本仓库)。
|
|
36
|
+
|
|
37
|
+
## 与其他 skills 共存
|
|
38
|
+
|
|
39
|
+
每个技能是独立目录、独立激活单元:agent 按 `description` 匹配任务按需加载,不用到的技能零上下文占用。唯一约束是目录名(即 `name`)不重复;`description` 已含反向排除,与常见通用技能重叠概率低。
|
|
40
|
+
|
|
41
|
+
## 命名约定
|
|
42
|
+
|
|
43
|
+
- `fxri-` 前缀为组织级命名空间(对应 npm scope `@fxri/`),fxri 生态新技能沿用;不使用产品级 `toolkit-` 前缀,避免暗示工具依赖
|
|
44
|
+
- name 全小写 kebab-case,与目录名一致,≤64 字符
|
|
45
|
+
|
|
46
|
+
## 发布前核对清单
|
|
47
|
+
|
|
48
|
+
- [ ] name:kebab-case、与目录名一致、≤64 字符
|
|
49
|
+
- [ ] description:≤1024 字符,含做什么 + 何时用 + 正向触发词 + 反向排除
|
|
50
|
+
- [ ] metadata.version:内容变更即递增
|
|
51
|
+
- [ ] 主干 SKILL.md < 200 行,细节下沉 `references/`,可复制资产放 `assets/`
|
|
52
|
+
- [ ] 引用的 references / assets 相对路径有效
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fxri-plan-to-task
|
|
3
|
+
description: 将已确认的实施方案落盘为标准任务文件并跟踪至归档:先查后写防重复建档、按模板建档、状态机更新、自查校验、手工归档与归档提交同批。当用户确认方案后要求登记或落盘任务、提到建档、任务登记、归档、任务校验时使用。不用于与方案落盘无关的普通 TODO、issue 管理或日常提交信息撰写。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
author: fxri
|
|
8
|
+
source: https://github.com/fxri-net/toolkit
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 方案落盘:任务建档与归档
|
|
12
|
+
|
|
13
|
+
## 何时使用
|
|
14
|
+
|
|
15
|
+
- 用户确认实施方案后,需要把方案登记为任务文件持续跟踪
|
|
16
|
+
- 触发词:方案落盘 / 建档 / 任务登记 / 归档 / 任务校验
|
|
17
|
+
|
|
18
|
+
**何时不使用**:与方案落盘无关的普通 TODO、issue 管理、日历待办。
|
|
19
|
+
|
|
20
|
+
## 核心约定
|
|
21
|
+
|
|
22
|
+
任务文件规范(目录结构、命名、frontmatter 字段、归档格式、手工归档步骤、自查清单)全部以 `references/task-spec.md` 为准,本文件只写流程。执行任何写操作前先读它。
|
|
23
|
+
|
|
24
|
+
## 工作流
|
|
25
|
+
|
|
26
|
+
### 1. 先查后写(防重复建档)
|
|
27
|
+
|
|
28
|
+
- 列出任务目录 `active/` 下全部 `.md`(含一层 `{YYYYMM}/` 月份子目录),并核对 `archive/` 是否已有同主题任务
|
|
29
|
+
- 已有同主题任务:更新原文件,禁止新建
|
|
30
|
+
- 任务唯一键:`{年月日}-{用户名}-{任务简述}`;多人对同一需求共用一个文件
|
|
31
|
+
|
|
32
|
+
### 2. 建档
|
|
33
|
+
|
|
34
|
+
- 整段复制 `assets/active-task-template.md` 再填空,不要凭记忆组装 frontmatter
|
|
35
|
+
- 文件放入 `active/{YYYYMM}/`;目录不存在时按规范创建
|
|
36
|
+
- `created` 必须等于文件名日期前缀;`updated` 随每次修改同步
|
|
37
|
+
|
|
38
|
+
### 3. 过程更新
|
|
39
|
+
|
|
40
|
+
- status 五态流转:待办 → 进行中 → 阻塞 →(已完成 | 已放弃);后两者为终结态
|
|
41
|
+
- 进入终结态必须补 `completed: YYYY-MM-DD HH:mm`(真实收工时间)
|
|
42
|
+
- 方案正文出现「待实施 / 待核对 / 待评估」等游离子项时,拆分为独立任务文件,不在正文留游离待办
|
|
43
|
+
|
|
44
|
+
### 4. 校验
|
|
45
|
+
|
|
46
|
+
按 `references/task-spec.md` 的「自查清单」逐项核对,发现问题当场修复后再进入下一步。
|
|
47
|
+
|
|
48
|
+
### 5. 归档
|
|
49
|
+
|
|
50
|
+
按 `references/task-spec.md` 的「手工归档步骤」执行:合并归档块 → 降序重排 → 写回 → 删 active 源文件 → 清理空月份目录。
|
|
51
|
+
|
|
52
|
+
### 6. 归档提交同批(硬约束)
|
|
53
|
+
|
|
54
|
+
先归档、后提交:任务归档文件必须与本次代码变更落在**同一个 git 提交**,顺序不可颠倒。避免任务完成却滞留 `active/` 未归档,或归档单独成一条提交。
|
|
55
|
+
|
|
56
|
+
## 失败模式
|
|
57
|
+
|
|
58
|
+
| 症状 | 处置 |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| active 下出现同名任务文件 | 重复建档,合并为一个后删除多余 |
|
|
61
|
+
| completed 日期与文件名创建日不一致 | 核对是否填错;确为跨天完成则以 completed 日期归档 |
|
|
62
|
+
| depends_on 引用的任务已归档 | 正常,依赖随之解除;引用拼写错误则修正 |
|
|
63
|
+
| 并发写归档文件互相覆盖 | 归档前确认无其他写者同时操作;冲突时以重排后完整合并为准 |
|
|
64
|
+
|
|
65
|
+
## 可选加速(不构成依赖)
|
|
66
|
+
|
|
67
|
+
项目已安装 @fxri/toolkit 时,可用命令替代对应手工步骤,缺失不影响主流程:
|
|
68
|
+
|
|
69
|
+
- `toolkit tasks`:查 active 总览(替代第 1 步人工翻目录)
|
|
70
|
+
- `toolkit tasks check`:自动校验(替代第 4 步自查清单)
|
|
71
|
+
- `toolkit tasks archive`:自动归档(替代第 5 步,含排他锁防并发;可 `--dry-run` 预演)
|
|
72
|
+
- 任务目录非默认 `.tasks` 时加 `--dir <path>`
|